1 /*
2 * Copyright (c) 2023, Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "flash_cadence_nand_ll.h"
7
8 LOG_MODULE_REGISTER(flash_cdns_nand_ll, CONFIG_FLASH_LOG_LEVEL);
9
10 /**
11 * Wait for the Cadence NAND controller to become idle.
12 *
13 * @param base_address The base address of the Cadence NAND controller.
14 * @retval 0 on success or -ETIMEDOUT error value on failure.
15 */
cdns_nand_wait_idle(uintptr_t base_address)16 static inline int32_t cdns_nand_wait_idle(uintptr_t base_address)
17 {
18 /* Wait status command response ready */
19 if (!WAIT_FOR(CNF_GET_CTRL_BUSY(sys_read32(CNF_CMDREG(base_address, CTRL_STATUS))) == 0U,
20 IDLE_TIME_OUT, k_msleep(1))) {
21 LOG_ERR("Timed out waiting for wait idle response");
22 return -ETIMEDOUT;
23 }
24 return 0;
25 }
26
27 /**
28 * Set the row address for a NAND flash memory device using the Cadence NAND controller.
29 *
30 * @param params The Cadence NAND parameters structure.
31 * @param local_row_address The row address.
32 * @param page_set The page set number.
33 */
row_address_set(struct cadence_nand_params * params,uint32_t * local_row_address,uint32_t page_set)34 static void row_address_set(struct cadence_nand_params *params, uint32_t *local_row_address,
35 uint32_t page_set)
36 {
37 uint32_t block_number = 0;
38
39 block_number = ((page_set) / (params->npages_per_block));
40 *local_row_address = 0;
41 *local_row_address |= ROW_VAL_SET((params->page_size_bit) - 1, 0,
42 ((page_set) % (params->npages_per_block)));
43 *local_row_address |=
44 ROW_VAL_SET((params->block_size_bit) - 1, (params->page_size_bit), block_number);
45 *local_row_address |= ROW_VAL_SET((params->lun_size_bit) - 1, (params->block_size_bit),
46 (block_number / params->nblocks_per_lun));
47 }
48
49 /**
50 * Retrieve information about the NAND flash device using the Cadence NAND controller.
51 *
52 * @param params The Cadence NAND parameters structure.
53 * @retval 0 on success or -ENXIO error value on failure.
54 */
cdns_nand_device_info(struct cadence_nand_params * params)55 static int cdns_nand_device_info(struct cadence_nand_params *params)
56 {
57 struct nf_ctrl_version *nf_ver;
58 uintptr_t base_address;
59 uint32_t reg_value = 0;
60 uint8_t type;
61
62 base_address = params->nand_base;
63
64 /* Read flash device version information */
65 reg_value = sys_read32(CNF_CTRLPARAM(base_address, VERSION));
66 nf_ver = (struct nf_ctrl_version *)®_value;
67
68 LOG_INF("NAND Flash Version Information");
69 LOG_INF("HPNFC Magic Number 0x%x", nf_ver->hpnfc_magic_number);
70 LOG_INF("Fixed number 0x%x", nf_ver->ctrl_fix);
71 LOG_INF("Controller Revision Number 0x%x", nf_ver->ctrl_rev);
72
73 /* Interface Type */
74 reg_value = sys_read32(CNF_CTRLPARAM(base_address, DEV_PARAMS0));
75 type = CNF_GET_DEV_TYPE(reg_value);
76 if (type == CNF_DT_UNKNOWN) {
77 LOG_ERR("%s: device type unknown", __func__);
78 return -ENXIO;
79 }
80
81 params->nluns = CNF_GET_NLUNS(reg_value);
82 LOG_INF("Number of LUMs %hhx", params->nluns);
83
84 /* Pages per block */
85 reg_value = sys_read32(CNF_CTRLCFG(base_address, DEV_LAYOUT));
86 params->npages_per_block = GET_PAGES_PER_BLOCK(reg_value);
87
88 /* Page size and spare size */
89 reg_value = sys_read32(CNF_CTRLPARAM(base_address, DEV_AREA));
90 params->page_size = GET_PAGE_SIZE(reg_value);
91 params->spare_size = GET_SPARE_SIZE(reg_value);
92
93 /* Device blocks per LUN */
94 params->nblocks_per_lun = sys_read32(CNF_CTRLPARAM(base_address, DEV_BLOCKS_PLUN));
95
96 /* Calculate block size and total device size */
97 params->block_size = (params->npages_per_block * params->page_size);
98 params->device_size = ((long long)params->block_size *
99 (long long)(params->nblocks_per_lun * params->nluns));
100 LOG_INF("block size %x total device size %llx", params->block_size, params->device_size);
101
102 /* Calculate bit size of page, block and lun*/
103 params->page_size_bit = find_msb_set((params->npages_per_block) - 1);
104 params->block_size_bit = find_msb_set((params->nblocks_per_lun) - 1);
105 params->lun_size_bit = find_msb_set((params->nluns) - 1);
106 return 0;
107 }
108
109 /**
110 * Retrieve the status of a specific thread in the Cadence NAND controller.
111 *
112 * @param base_address The base address of the Cadence NAND controller.
113 * @param thread The thread identifier.
114 * @retval The status of the thread.
115 */
cdns_nand_get_thrd_status(uintptr_t base_address,uint8_t thread)116 static uint32_t cdns_nand_get_thrd_status(uintptr_t base_address, uint8_t thread)
117 {
118 uint32_t status;
119
120 sys_write32(THREAD_VAL(thread), (base_address + CMD_STATUS_PTR_ADDR));
121 status = sys_read32((base_address + CMD_STAT_CMD_STATUS));
122 return status;
123 }
124
125 /**
126 * Wait for a specific thread in the Cadence controller to complete.
127 *
128 * @param base_address The base address of the Cadence controller.
129 * @param thread The thread identifier to wait for.
130 * @retval 0 on success or -ETIMEDOUT error value on failure.
131 */
cdns_wait_for_thread(uintptr_t base_address,uint8_t thread)132 static int cdns_wait_for_thread(uintptr_t base_address, uint8_t thread)
133 {
134
135 if (!WAIT_FOR((sys_read32((base_address) + THR_STATUS) & BIT(thread)) == 0U,
136 THREAD_IDLE_TIME_OUT, k_msleep(1))) {
137 LOG_ERR("Timed out waiting for thread response");
138 return -ETIMEDOUT;
139 }
140
141 return 0;
142 }
143
144 /**
145 * Set features in the Cadence NAND controller using PIO operations.
146 *
147 * @param base_address The base address of the Cadence NAND controller.
148 * @param feat_addr The address of the feature to be set.
149 * @param feat_val The value of the feature to be set.
150 * @param thread The thread identifier for the PIO operation.
151 * @param vol_id The volume identifier for the feature set operation.
152 * @param use_intr Flag indicating whether to use interrupts during the operation.
153 * @retval 0 on success or -ETIMEDOUT error value on failure.
154 */
cdns_nand_pio_set_features(uintptr_t base_address,uint8_t feat_addr,uint8_t feat_val,uint8_t thread,uint8_t vol_id)155 static int cdns_nand_pio_set_features(uintptr_t base_address, uint8_t feat_addr, uint8_t feat_val,
156 uint8_t thread, uint8_t vol_id)
157 {
158 uint32_t status = 0;
159 int ret = 0;
160
161 ret = cdns_wait_for_thread(base_address, thread);
162
163 if (ret != 0) {
164 return ret;
165 }
166
167 sys_write32(SET_FEAT_ADDR(feat_addr), (base_address + CDNS_CMD_REG1));
168 sys_write32(feat_val, (base_address + CDNS_CMD_REG2));
169 status = CMD_0_THREAD_POS_SET(thread);
170 status |= CMD_0_C_MODE_SET(CT_PIO_MODE);
171 status |= PIO_CMD0_CT_SET(PIO_SET_FEA_MODE);
172 status |= CMD_0_VOL_ID_SET(vol_id);
173 sys_write32(status, (base_address + CDNS_CMD_REG0));
174 return 0;
175 }
176
177 /**
178 * Check whether a transfer complete for PIO operation in the Cadence controller has finished.
179 *
180 * @param base_address The base address of the Cadence controller.
181 * @param thread The thread identifier for the PIO operation.
182 * @retval 0 on success or negative error value on failure.
183 */
cdns_pio_transfer_complete(uintptr_t base_address,uint8_t thread)184 static int cdns_pio_transfer_complete(uintptr_t base_address, uint8_t thread)
185 {
186 uint32_t status;
187
188 status = WAIT_FOR(((cdns_nand_get_thrd_status(base_address, thread)) != 0), IDLE_TIME_OUT,
189 k_msleep(1));
190
191 if (status == 0) {
192 LOG_ERR("Timed out waiting for thread status response");
193 return -ETIMEDOUT;
194 }
195
196 if ((status & (BIT(F_CSTAT_COMP)))) {
197 if ((status & (BIT(F_CSTAT_FAIL)))) {
198 LOG_ERR("Cadence status operation failed %s", __func__);
199 return -EIO;
200 }
201 } else {
202 LOG_ERR("Cadence status complete failed %s", __func__);
203 return -EIO;
204 }
205 return 0;
206 }
207
208 /**
209 * Set the operational mode for the Cadence NAND controller.
210 *
211 * @param base_address The base address of the Cadence NAND controller.
212 * @param opr_mode The operational mode SDR / NVDDR to set.
213 * @retval 0 on success or negative error value on failure.
214 */
cdns_nand_set_opr_mode(uintptr_t base_address,uint8_t opr_mode)215 static int cdns_nand_set_opr_mode(uintptr_t base_address, uint8_t opr_mode)
216 {
217 uint8_t device_type;
218 uint32_t timing_mode = 0;
219 uint32_t status;
220 int ret;
221
222 if (opr_mode == CNF_OPR_WORK_MODE_SDR) {
223
224 status = ONFI_TIMING_MODE_SDR(
225 sys_read32(CNF_CTRLPARAM(base_address, ONFI_TIMING_0)));
226 timing_mode = find_lsb_set(status) - 1;
227
228 /* PHY Register Timing setting*/
229 sys_write32(PHY_CTRL_REG_SDR, (base_address + PHY_CTRL_REG_OFFSET));
230 sys_write32(PHY_TSEL_REG_SDR, (base_address + PHY_TSEL_REG_OFFSET));
231 sys_write32(PHY_DQ_TIMING_REG_SDR, (base_address + PHY_DQ_TIMING_REG_OFFSET));
232 sys_write32(PHY_DQS_TIMING_REG_SDR, (base_address + PHY_DQS_TIMING_REG_OFFSET));
233 sys_write32(PHY_GATE_LPBK_CTRL_REG_SDR, (base_address + PHY_GATE_LPBK_OFFSET));
234 sys_write32(PHY_DLL_MASTER_CTRL_REG_SDR, (base_address + PHY_DLL_MASTER_OFFSET));
235
236 /* Async mode timing settings */
237 sys_write32((CNF_ASYNC_TIMINGS_TRH) | (CNF_ASYNC_TIMINGS_TRP) |
238 (CNF_ASYNC_TIMINGS_TWH) | (CNF_ASYNC_TIMINGS_TWP),
239 CNF_MINICTRL(base_address, ASYNC_TOGGLE_TIMINGS));
240
241 /* Set operation work mode in common settings */
242 sys_clear_bits(CNF_MINICTRL(base_address, CMN_SETTINGS),
243 CNF_OPR_WORK_MODE_SDR_MASK);
244
245 } else {
246 /* NVDDR MODE */
247 status = ONFI_TIMING_MODE_NVDDR(
248 sys_read32(CNF_CTRLPARAM(base_address, ONFI_TIMING_0)));
249 timing_mode = find_lsb_set(status) - 1;
250 /* PHY Register Timing setting*/
251 sys_write32(PHY_CTRL_REG_DDR, (base_address + PHY_CTRL_REG_OFFSET));
252 sys_write32(PHY_TSEL_REG_DDR, (base_address + PHY_TSEL_REG_OFFSET));
253 sys_write32(PHY_DQ_TIMING_REG_DDR, (base_address + PHY_DQ_TIMING_REG_OFFSET));
254 sys_write32(PHY_DQS_TIMING_REG_DDR, (base_address + PHY_DQS_TIMING_REG_OFFSET));
255 sys_write32(PHY_GATE_LPBK_CTRL_REG_DDR, (base_address + PHY_GATE_LPBK_OFFSET));
256 sys_write32(PHY_DLL_MASTER_CTRL_REG_DDR, (base_address + PHY_DLL_MASTER_OFFSET));
257 /* Set operation work mode in common settings */
258 sys_set_bits(CNF_MINICTRL(base_address, CMN_SETTINGS),
259 CNF_OPR_WORK_MODE_NVDDR_MASK);
260 }
261
262 /* Wait for controller to be in idle state */
263 ret = cdns_nand_wait_idle(base_address);
264 if (ret != 0) {
265 LOG_ERR("Wait for controller to be in idle state Failed");
266 return ret;
267 }
268
269 /* Check device type */
270 device_type = CNF_GET_DEV_TYPE(sys_read32(CNF_CTRLPARAM(base_address, DEV_PARAMS0)));
271
272 if (device_type != ONFI_INTERFACE) {
273 LOG_ERR("Driver does not support this interface");
274 return -ENOTSUP;
275 }
276 /* Reset DLL PHY */
277 sys_clear_bit(CNF_MINICTRL(base_address, DLL_PHY_CTRL), CNF_DLL_PHY_RST_N);
278
279 /* Wait for controller to be in idle state */
280 ret = cdns_nand_wait_idle(base_address);
281 if (ret != 0) {
282 LOG_ERR("Wait for controller to be in idle state Failed");
283 return ret;
284 }
285
286 ret = cdns_nand_pio_set_features(base_address, SET_FEAT_TIMING_MODE_ADDRESS, timing_mode,
287 NF_TDEF_TRD_NUM, VOL_ID);
288 if (ret != 0) {
289 return ret;
290 }
291
292 ret = cdns_pio_transfer_complete(base_address, NF_TDEF_TRD_NUM);
293 if (ret != 0) {
294 LOG_ERR("cdns pio check failed");
295 return ret;
296 }
297
298 ret = cdns_nand_wait_idle(base_address);
299 if (ret != 0) {
300 LOG_ERR("Wait for controller to be in idle state Failed");
301 return ret;
302 }
303
304 /* set dll_rst_n in dll_phy_ctrl to 1 */
305 sys_set_bit(CNF_MINICTRL(base_address, DLL_PHY_CTRL), CNF_DLL_PHY_RST_N);
306
307 ret = cdns_nand_wait_idle(base_address);
308 if (ret != 0) {
309 LOG_ERR("Wait for controller to be in idle state Failed");
310 return ret;
311 }
312
313 return 0;
314 }
315
316 /**
317 * Configure the transfer settings of the Cadence NAND controller.
318 *
319 * @param base_address The base address of the Cadence NAND controller.
320 * @retval 0 on success or -ETIMEDOUT error value on failure.
321 */
cdns_nand_transfer_config(uintptr_t base_address)322 static int cdns_nand_transfer_config(uintptr_t base_address)
323 {
324 int ret = 0;
325 /* Wait for controller to be in idle state */
326 ret = cdns_nand_wait_idle(base_address);
327
328 if (ret != 0) {
329 LOG_ERR("Wait for controller to be in idle state Failed");
330 return ret;
331 }
332
333 /* Configure data transfer parameters */
334 sys_write32(ENABLE, CNF_CTRLCFG(base_address, TRANS_CFG0));
335
336 /* Disable cache and multiplane. */
337 sys_write32(DISABLE, CNF_CTRLCFG(base_address, MULTIPLANE_CFG));
338 sys_write32(DISABLE, CNF_CTRLCFG(base_address, CACHE_CFG));
339
340 /* Clear all interrupts. */
341 sys_write32(CLEAR_ALL_INTERRUPT, (base_address + INTR_STATUS));
342 return 0;
343 }
344
345 /**
346 * Initialize the Cadence NAND controller.
347 *
348 * @param params The Cadence NAND parameters structure.
349 * @retval 0 on success or negative error value on failure.
350 */
cdns_nand_init(struct cadence_nand_params * params)351 int cdns_nand_init(struct cadence_nand_params *params)
352 {
353 uint32_t reg_value_read = 0;
354 uintptr_t base_address = params->nand_base;
355 uint8_t datarate_mode = params->datarate_mode;
356 int ret;
357
358 if (!WAIT_FOR(CNF_GET_INIT_COMP(sys_read32(CNF_CMDREG(base_address, CTRL_STATUS))) != 0U,
359 IDLE_TIME_OUT, k_msleep(1))) {
360 LOG_ERR("Timed out waiting for NAND Controller Init complete status response");
361 return -ETIMEDOUT;
362 }
363
364 if (CNF_GET_INIT_FAIL(sys_read32(CNF_CMDREG(base_address, CTRL_STATUS))) != 0) {
365 LOG_ERR("NAND Controller Init complete Failed!!!");
366 return -ENODEV;
367 }
368
369 ret = cdns_nand_device_info(params);
370 if (ret != 0) {
371 return ret;
372 }
373
374 /* Hardware Support Features */
375 reg_value_read = sys_read32(CNF_CTRLPARAM(base_address, FEATURE));
376 /* Enable data integrity parity check if the data integrity parity mechanism is */
377 /* supported by the device */
378 if (CNF_HW_DI_PR_SUPPORT(reg_value_read) != 0) {
379 sys_set_bit(CNF_DI(base_address, CONTROL), CNF_DI_PAR_EN);
380 }
381
382 /* Enable data integrity CRC check if the data integrity CRC mechanism is */
383 /* supported by the device */
384 if (CNF_HW_DI_CRC_SUPPORT(reg_value_read) != 0) {
385 sys_set_bit(CNF_DI(base_address, CONTROL), CNF_DI_CRC_EN);
386 }
387 /* Status polling mode, device control and status register */
388 ret = cdns_nand_wait_idle(base_address);
389
390 if (ret != 0) {
391 LOG_ERR("Wait for controller to be in idle state Failed");
392 return ret;
393 }
394 sys_write32(DEV_STAT_DEF_VALUE, CNF_CTRLCFG(base_address, DEV_STAT));
395
396 /* Set operation work mode */
397 ret = cdns_nand_set_opr_mode(base_address, datarate_mode);
398 if (ret != 0) {
399 return ret;
400 }
401
402 /* Set data transfer configuration parameters */
403 ret = cdns_nand_transfer_config(base_address);
404 if (ret != 0) {
405 return ret;
406 }
407
408 /* Wait for controller to be in idle state */
409 ret = cdns_nand_wait_idle(base_address);
410 if (ret != 0) {
411 LOG_ERR("Wait for controller to be in idle state Failed");
412 return ret;
413 }
414
415 /* DMA Setting */
416 sys_write32((F_BURST_SEL_SET(NF_TDEF_BURST_SEL)) | (BIT(F_OTE)),
417 (base_address + NF_DMA_SETTING));
418
419 /* Pre fetch */
420 sys_write32(((NF_FIFO_TRIGG_LVL_SET(PRE_FETCH_VALUE)) |
421 (NF_DMA_PACKAGE_SIZE_SET(PRE_FETCH_VALUE))),
422 (base_address + NF_PRE_FETCH));
423 /* Total bits in row addressing*/
424 params->total_bit_row = find_msb_set(((params->npages_per_block) - 1)) +
425 find_msb_set((params->nblocks_per_lun) - 1);
426
427 if (ret != 0) {
428 LOG_ERR("Failed to establish device access width!");
429 return -EINVAL;
430 }
431 /* Enable Global Interrupt for NAND*/
432 #ifdef CONFIG_CDNS_NAND_INTERRUPT_SUPPORT
433 sys_set_bit((base_address + INTERRUPT_STATUS_REG), GINTR_ENABLE);
434 #endif
435 return 0;
436 }
437
438 #if CONFIG_CDNS_NAND_CDMA_MODE
439 /**
440 *
441 * This function performs Command descriptor structure prepareation.
442 *
443 * @param nf_mem determine which NF memory bank will be selected
444 * @param flash_ptr start ROW address in NF memory
445 * @param mem_ptr system memory pointer
446 * @param ctype Command type (read/write/erase)
447 * @param cmd_cnt counter for commands
448 * @param dma_sel select DMA engine (0 - slave DMA, 1 - master DMA)
449 * @param vol_id specify target volume ID
450 *
451 */
cdns_nand_cdma_prepare(char nf_mem,uint32_t flash_ptr,char * mem_ptr,uint16_t ctype,int32_t cmd_cnt,uint8_t dma_sel,uint8_t vol_id,struct cdns_cdma_command_descriptor * desc)452 void cdns_nand_cdma_prepare(char nf_mem, uint32_t flash_ptr, char *mem_ptr, uint16_t ctype,
453 int32_t cmd_cnt, uint8_t dma_sel, uint8_t vol_id,
454 struct cdns_cdma_command_descriptor *desc)
455 {
456 struct cdns_cdma_command_descriptor *cdma_desc;
457
458 cdma_desc = desc;
459 /* set fields for one descriptor */
460 cdma_desc->flash_pointer = flash_ptr;
461 cdma_desc->bank_number = nf_mem;
462 cdma_desc->command_flags |= CDMA_CF_DMA_MASTER_SET(dma_sel) | F_CFLAGS_VOL_ID_SET(vol_id);
463 cdma_desc->memory_pointer = (uintptr_t)mem_ptr;
464 cdma_desc->status = 0;
465 cdma_desc->sync_flag_pointer = 0;
466 cdma_desc->sync_arguments = 0;
467 cdma_desc->ctrl_data_ptr = 0x40;
468 cdma_desc->command_type = ctype;
469 if (cmd_cnt > 1) {
470 cdma_desc->next_pointer = (uintptr_t)(desc + 1);
471 cdma_desc->command_flags |= CFLAGS_MPTRPC_SET | CFLAGS_MPTRPC_SET;
472 cdma_desc->command_flags |= CFLAGS_CONT_SET;
473 } else {
474 cdma_desc->next_pointer = 0;
475 #ifdef CONFIG_CDNS_NAND_INTERRUPT_SUPPORT
476 cdma_desc->command_flags |= CDMA_CF_INT_SET;
477 #endif
478 }
479 }
480
481 /**
482 * Check a command descriptor transfer complete status in the Cadence NAND controller.
483 *
484 * @param desc_ptr The pointer to the command descriptor structure.
485 * @param params The Cadence NAND parameters structure.
486 * @retval 0 on success or negative error value on failure.
487 */
cdns_transfer_complete(struct cdns_cdma_command_descriptor * desc_ptr,struct cadence_nand_params * params)488 static int cdns_transfer_complete(struct cdns_cdma_command_descriptor *desc_ptr,
489 struct cadence_nand_params *params)
490 {
491 #ifdef CONFIG_CDNS_NAND_INTERRUPT_SUPPORT
492 uint32_t status = 0;
493
494 NAND_INT_SEM_TAKE(params);
495 sys_write32(NF_TDEF_TRD_NUM, (params->nand_base + CMD_STATUS_PTR_ADDR));
496 status = sys_read32((params->nand_base + CMD_STAT_CMD_STATUS));
497 if ((status & (BIT(F_CSTAT_COMP)))) {
498 if ((status & (BIT(F_CSTAT_FAIL)))) {
499 LOG_ERR("Cadence status operation failed %s", __func__);
500 return -EIO;
501 }
502 } else {
503 LOG_ERR("Cadence status complete failed %s", __func__);
504 return -EIO;
505 }
506 #else
507 ARG_UNUSED(params);
508
509 if (!WAIT_FOR(((desc_ptr->status & (BIT(F_CSTAT_COMP))) != 0), IDLE_TIME_OUT,
510 k_msleep(1))) {
511 LOG_ERR("Timed out waiting for thread status response");
512 return -ETIMEDOUT;
513 }
514 if ((desc_ptr->status & (BIT(F_CSTAT_FAIL))) != 0) {
515 LOG_ERR("Cadence status operation failed %s", __func__);
516 return -EIO;
517 }
518 #endif
519 return 0;
520 }
521
522 /**
523 * Send a command descriptor to the Cadence NAND controller for execution.
524 *
525 * @param base_address The base address of the Cadence NAND controller.
526 * @param desc_ptr The pointer to the command descriptor.
527 * @param thread The thread number for the execution.
528 * @retval 0 on success or -ETIMEDOUT error value on failure.
529 */
cdns_nand_send(uintptr_t base_address,char * desc_ptr,uint8_t thread)530 static int cdns_nand_send(uintptr_t base_address, char *desc_ptr, uint8_t thread)
531 {
532 uint64_t desc_address;
533 uint32_t status;
534 int ret;
535
536 desc_address = (uint64_t)desc_ptr;
537
538 ret = cdns_wait_for_thread(base_address, thread);
539
540 if (ret != 0) {
541 return ret;
542 }
543 /* desc_ptr address passing */
544 sys_write32(desc_address & U32_MASK_VAL, (base_address + CDNS_CMD_REG2));
545 sys_write32((desc_address >> 32) & U32_MASK_VAL, (base_address + CDNS_CMD_REG3));
546 /* Thread selection */
547 status = CMD_0_THREAD_POS_SET(thread);
548 /* CDMA Mode selection */
549 status |= CMD_0_C_MODE_SET(CT_CDMA_MODE);
550 /* CMD 0 Reg write*/
551 sys_write32(status, (base_address + CDNS_CMD_REG0));
552 return 0;
553 }
554
cdns_cdma_desc_transfer_finish(struct cadence_nand_params * params,uint32_t page_count,uint32_t max_page_desc,uint32_t ctype,uint32_t cond_start,char * buffer)555 static int cdns_cdma_desc_transfer_finish(struct cadence_nand_params *params, uint32_t page_count,
556 uint32_t max_page_desc, uint32_t ctype,
557 uint32_t cond_start, char *buffer)
558 {
559 uint32_t page_count_pass = 0;
560 uint32_t row_address = 0;
561 uint32_t base_address;
562 uint32_t page_buffer_size;
563 struct cdns_cdma_command_descriptor *cdma_desc;
564 int ret;
565
566 page_buffer_size = (page_count > max_page_desc) ? max_page_desc : page_count;
567
568 cdma_desc = k_malloc(sizeof(struct cdns_cdma_command_descriptor) * page_buffer_size);
569
570 if (cdma_desc == NULL) {
571 LOG_ERR("Memory allocation error occurred %s", __func__);
572 return -ENOSR;
573 }
574
575 base_address = params->nand_base;
576
577 while (page_count > 0) {
578 row_address_set(params, &row_address, cond_start);
579
580 if (page_count > max_page_desc) {
581 page_count_pass = max_page_desc;
582 page_count = page_count - max_page_desc;
583 cond_start = cond_start + page_count_pass;
584 } else {
585 page_count_pass = page_count;
586 page_count = page_count - page_count_pass;
587 }
588 for (int index = 0; index < page_count_pass; index++) {
589 cdns_nand_cdma_prepare(NF_TDEF_DEV_NUM, row_address, buffer,
590 (ctype + index), (page_count_pass - index),
591 DMA_MS_SEL, VOL_ID, (cdma_desc + index));
592 }
593 ret = cdns_nand_send(base_address, (char *)cdma_desc, NF_TDEF_TRD_NUM);
594
595 if (ret != 0) {
596 k_free(cdma_desc);
597 return ret;
598 }
599
600 if (ctype != CNF_CMD_ERASE) {
601 buffer = buffer + (max_page_desc * params->page_size);
602 }
603
604 ret = cdns_transfer_complete(cdma_desc, params);
605
606 if (ret != 0) {
607 k_free(cdma_desc);
608 return ret;
609 }
610 }
611
612 k_free(cdma_desc);
613
614 return 0;
615 }
616 /**
617 * Perform a CDMA write operation for the Cadence NAND controller.
618 *
619 * @param params The Cadence NAND parameters structure.
620 * @param start_page_number The starting page number for the write operation.
621 * @param buffer The buffer containing the data to be written.
622 * @param page_count The number of pages to be written.
623 * @retval 0 on success or negative error value on failure.
624 */
cdns_nand_cdma_write(struct cadence_nand_params * params,uint32_t start_page_number,char * buffer,uint32_t page_count)625 static int cdns_nand_cdma_write(struct cadence_nand_params *params, uint32_t start_page_number,
626 char *buffer, uint32_t page_count)
627 {
628 int ret;
629
630 ret = cdns_cdma_desc_transfer_finish(params, page_count, CONFIG_FLASH_CDNS_CDMA_PAGE_COUNT,
631 CNF_CMD_WR, start_page_number, buffer);
632
633 return ret;
634 }
635
636 /**
637 * Perform a CDMA read operation for the Cadence NAND controller.
638 *
639 * @param params The Cadence NAND parameters structure.
640 * @param start_page_number The starting page number for the read operation.
641 * @param buffer The buffer to store the read data.
642 * @param page_count The number of pages to be read.
643 * @retval 0 on success or negative error value on failure.
644 */
cdns_nand_cdma_read(struct cadence_nand_params * params,uint32_t start_page_number,char * buffer,uint32_t page_count)645 static int cdns_nand_cdma_read(struct cadence_nand_params *params, uint32_t start_page_number,
646 char *buffer, uint32_t page_count)
647 {
648 int ret;
649
650 ret = cdns_cdma_desc_transfer_finish(params, page_count, CONFIG_FLASH_CDNS_CDMA_PAGE_COUNT,
651 CNF_CMD_RD, start_page_number, buffer);
652
653 return ret;
654 }
655
656 /**
657 * Perform a CDMA erase operation for the Cadence NAND controller.
658 *
659 * @param params The Cadence NAND parameters structure.
660 * @param start_block_number The starting block number for the erase operation.
661 * @param block_count The number of blocks to be erased.
662 * @retval 0 on success or negative error value on failure.
663 */
cdns_nand_cdma_erase(struct cadence_nand_params * params,uint32_t start_block_number,uint32_t block_count)664 static int cdns_nand_cdma_erase(struct cadence_nand_params *params, uint32_t start_block_number,
665 uint32_t block_count)
666 {
667 int ret;
668
669 ret = cdns_cdma_desc_transfer_finish(params, block_count,
670 CONFIG_FLASH_CDNS_CDMA_BLOCK_COUNT, CNF_CMD_ERASE,
671 start_block_number, NULL);
672
673 return ret;
674 }
675 #endif
676
677 #if CONFIG_CDNS_NAND_PIO_MODE
678
679 /**
680 * Perform an erase operation on the Cadence NAND controller using PIO.
681 *
682 * @param params The Cadence NAND parameters structure.
683 * @param thread The thread identifier for the PIO operation.
684 * @param bank The bank identifier for the erase operation.
685 * @param start_block The starting block number for the erase operation.
686 * @param ctype The command type for the erase operation.
687 * @param block_count The number of blocks to be erased.
688 * @retval 0 on success or negative error value on failure.
689 */
cdns_nand_pio_erase(struct cadence_nand_params * params,uint8_t thread,uint8_t bank,uint32_t start_block,uint16_t ctype,uint32_t block_count)690 static int cdns_nand_pio_erase(struct cadence_nand_params *params, uint8_t thread, uint8_t bank,
691 uint32_t start_block, uint16_t ctype, uint32_t block_count)
692 {
693 uint32_t status;
694 uintptr_t base_address;
695 uint32_t row_address = 0;
696 uint32_t index = 0;
697 int ret;
698
699 base_address = params->nand_base;
700 for (index = 0; index < block_count; index++) {
701
702 ret = cdns_wait_for_thread(base_address, thread);
703
704 if (ret != 0) {
705 return ret;
706 }
707 row_address_set(params, &row_address, (start_block * params->npages_per_block));
708 sys_write32(row_address, (base_address + CDNS_CMD_REG1));
709 start_block++;
710 sys_write32((NF_CMD4_BANK_SET(bank)), (base_address + CDNS_CMD_REG4));
711 status = CMD_0_THREAD_POS_SET(thread);
712 #ifdef CONFIG_CDNS_NAND_INTERRUPT_SUPPORT
713 status |= BIT(PIO_CF_INT);
714 #endif
715 status |= CMD_0_C_MODE_SET(CT_PIO_MODE);
716 status |= PIO_CMD0_CT_SET(ctype);
717 sys_write32(status, (base_address + CDNS_CMD_REG0));
718 NAND_INT_SEM_TAKE(params);
719 ret = cdns_pio_transfer_complete(base_address, thread);
720 if (ret != 0) {
721 return ret;
722 }
723 }
724
725 return 0;
726 }
727
728 /**
729 * Prepare for a PIO operation in the Cadence NAND controller.
730 *
731 * @param base_address The base address of the Cadence NAND controller.
732 * @param thread The thread ID associated with the operation.
733 * @param bank The bank ID for the operation.
734 * @param row_address The row address for the operation.
735 * @param buf The buffer containing the data for the operation.
736 * @param ctype The command type for the operation.
737 * @param dma_sel The DMA selection flag for the operation.
738 * @param vol_id The volume ID for the operation.
739 * @retval 0 on success or -ETIMEDOUT error value on failure.
740 */
cdns_nand_pio_prepare(uintptr_t base_address,uint8_t thread,uint8_t bank,uint32_t row_address,char * buf,uint16_t ctype,uint8_t dma_sel,uint8_t vol_id)741 static int cdns_nand_pio_prepare(uintptr_t base_address, uint8_t thread, uint8_t bank,
742 uint32_t row_address, char *buf, uint16_t ctype, uint8_t dma_sel,
743 uint8_t vol_id)
744 {
745 uint64_t buf_addr = (uintptr_t)buf;
746 uint32_t status;
747 int ret;
748
749 ret = cdns_wait_for_thread(base_address, thread);
750
751 if (ret != 0) {
752 return ret;
753 }
754
755 sys_write32(row_address, (base_address + CDNS_CMD_REG1));
756 sys_write32(NF_CMD4_BANK_SET(bank), (base_address + CDNS_CMD_REG4));
757 sys_write32(buf_addr & U32_MASK_VAL, (base_address + CDNS_CMD_REG2));
758 sys_write32((buf_addr >> 32) & U32_MASK_VAL, (base_address + CDNS_CMD_REG3));
759 status = CMD_0_THREAD_POS_SET(thread);
760 #ifdef CONFIG_CDNS_NAND_INTERRUPT_SUPPORT
761 status |= PIO_CF_INT_SET;
762 #endif
763 status |= PIO_CF_DMA_MASTER_SET(dma_sel);
764 status |= CMD_0_C_MODE_SET(CT_PIO_MODE);
765 status |= PIO_CMD0_CT_SET(ctype);
766 status |= CMD_0_VOL_ID_SET(vol_id);
767 sys_write32(status, (base_address + CDNS_CMD_REG0));
768 return 0;
769 }
770
771 /**
772 * Perform a PIO write operation for the Cadence NAND controller.
773 *
774 * @param params The Cadence NAND parameters structure.
775 * @param row_address The row address for the write operation.
776 * @param buffer The buffer containing the data to be written.
777 * @retval 0 on success or negative error value on failure.
778 */
cdns_nand_pio_write(struct cadence_nand_params * params,uint32_t row_address,char * buffer)779 static int cdns_nand_pio_write(struct cadence_nand_params *params, uint32_t row_address,
780 char *buffer)
781 {
782 uintptr_t base_address;
783 int ret;
784
785 base_address = params->nand_base;
786
787 ret = cdns_nand_pio_prepare(base_address, NF_TDEF_TRD_NUM, NF_TDEF_DEV_NUM, row_address,
788 buffer, CNF_CMD_WR, DMA_MS_SEL, VOL_ID);
789
790 if (ret != 0) {
791 return ret;
792 }
793 NAND_INT_SEM_TAKE(params);
794 ret = cdns_pio_transfer_complete(base_address, NF_TDEF_TRD_NUM);
795 if (ret != 0) {
796 return ret;
797 }
798
799 return 0;
800 }
801
802 /**
803 * Perform a PIO read operation for the Cadence NAND controller.
804 *
805 * @param params The Cadence NAND parameters structure.
806 * @param row_address The row address for the read operation.
807 * @param buffer The buffer to store the read data.
808 * @retval 0 on success or negative error value on failure.
809 */
cdns_nand_pio_read(struct cadence_nand_params * params,uint32_t row_address,char * buffer)810 static int cdns_nand_pio_read(struct cadence_nand_params *params, uint32_t row_address,
811 char *buffer)
812 {
813 uintptr_t base_address;
814 int ret;
815
816 base_address = params->nand_base;
817
818 ret = cdns_nand_pio_prepare(base_address, NF_TDEF_TRD_NUM, NF_TDEF_DEV_NUM, row_address,
819 buffer, CNF_CMD_RD, DMA_MS_SEL, VOL_ID);
820
821 if (ret != 0) {
822 return ret;
823 }
824
825 NAND_INT_SEM_TAKE(params);
826 ret = cdns_pio_transfer_complete(base_address, NF_TDEF_TRD_NUM);
827 if (ret != 0) {
828 return ret;
829 }
830
831 return 0;
832 }
833
834 /**
835 * Perform a combined PIO read and write operation for the Cadence NAND controller.
836 *
837 * @param params The Cadence NAND parameters structure.
838 * @param start_page_number The starting page number for the read/write operation.
839 * @param buffer The buffer containing the data to be written or to store the read data.
840 * @param page_count The number of pages to be read or written.
841 * @param mode The mode of operation (read, write).
842 * @retval 0 on success or negative error value on failure.
843 */
cdns_nand_pio_read_write(struct cadence_nand_params * params,uint32_t start_page_number,char * buffer,uint32_t page_count,uint8_t mode)844 static int cdns_nand_pio_read_write(struct cadence_nand_params *params, uint32_t start_page_number,
845 char *buffer, uint32_t page_count, uint8_t mode)
846 {
847 uint32_t index;
848 uint32_t pio_row_address = 0;
849 int ret = 0;
850
851 for (index = 0; index < page_count; index++) {
852 row_address_set(params, &pio_row_address, start_page_number++);
853 if (mode == CDNS_READ) {
854 ret = cdns_nand_pio_read(params, pio_row_address,
855 buffer + (index * (params->page_size)));
856 } else {
857 ret = cdns_nand_pio_write(params, pio_row_address,
858 buffer + (index * (params->page_size)));
859 }
860 }
861 return ret;
862 }
863 #endif
864
865 #if CONFIG_CDNS_NAND_GENERIC_MODE
866 /**
867 * Send a generic command to the Cadence NAND controller.
868 *
869 * @param params The Cadence NAND parameters structure.
870 * @param mini_ctrl_cmd The command to be sent.
871 * @retval 0 on success or -ETIMEDOUT error value on failure.
872 */
cdns_generic_send_cmd(struct cadence_nand_params * params,uint64_t mini_ctrl_cmd)873 static int cdns_generic_send_cmd(struct cadence_nand_params *params, uint64_t mini_ctrl_cmd)
874 {
875
876 uint32_t mini_ctrl_cmd_l, mini_ctrl_cmd_h, status;
877 uintptr_t base_address;
878 int ret = 0;
879
880 base_address = params->nand_base;
881 mini_ctrl_cmd_l = mini_ctrl_cmd & U32_MASK_VAL;
882 mini_ctrl_cmd_h = mini_ctrl_cmd >> 32;
883 ret = cdns_nand_wait_idle(base_address);
884
885 if (ret != 0) {
886 LOG_ERR("Wait for controller to be in idle state Failed");
887 return ret;
888 }
889 sys_write32(mini_ctrl_cmd_l, (base_address + CDNS_CMD_REG2));
890 sys_write32(mini_ctrl_cmd_h, (base_address + CDNS_CMD_REG3));
891 /* Select generic command. */
892 status = CMD_0_THREAD_POS_SET(NF_TDEF_TRD_NUM);
893 #ifdef CONFIG_CDNS_NAND_INTERRUPT_SUPPORT
894 status |= GEN_CF_INT_SET(GEN_CF_INT_ENABLE);
895 #endif
896 status |= CMD_0_C_MODE_SET(CT_GENERIC_MODE);
897 sys_write32(status, (base_address + CDNS_CMD_REG0));
898 return 0;
899 }
900
901 /**
902 * Send a generic command data to the Cadence NAND controller.
903 *
904 * @param params The Cadence NAND parameters structure.
905 * @param mode The mode of operation (read, write).
906 * @param data_length The length of the associated data.
907 * @retval 0 on success or -ETIMEDOUT error value on failure.
908 */
cdns_generic_cmd_data(struct cadence_nand_params * params,uint8_t mode,uint32_t data_length)909 static int cdns_generic_cmd_data(struct cadence_nand_params *params, uint8_t mode,
910 uint32_t data_length)
911 {
912 uint64_t mini_ctrl_cmd = 0;
913 int ret = 0;
914
915 mini_ctrl_cmd |= GCMD_TWB_VALUE;
916 mini_ctrl_cmd |= GCMCD_DATA_SEQ;
917 mini_ctrl_cmd |= GEN_SECTOR_COUNT_SET;
918 mini_ctrl_cmd |= GEN_LAST_SECTOR_SIZE_SET((uint64_t)data_length);
919 mini_ctrl_cmd |= GEN_DIR_SET((uint64_t)mode);
920 mini_ctrl_cmd |= GEN_SECTOR_SET((uint64_t)data_length);
921 ret = cdns_generic_send_cmd(params, mini_ctrl_cmd);
922 return ret;
923 }
924
925 /**
926 * Wait for the completion of an SDMA operation in the Cadence NAND controller.
927 *
928 * @param base_address The base address of the Cadence NAND controller.
929 * @retval 0 on success or -ETIMEDOUT error value on failure.
930 */
cdns_wait_sdma(uintptr_t base_address)931 static int cdns_wait_sdma(uintptr_t base_address)
932 {
933
934 if (!WAIT_FOR(((sys_read32(base_address + INTR_STATUS) & BIT(SDMA_TRIGG)) != 0),
935 IDLE_TIME_OUT, k_msleep(1))) {
936 LOG_ERR("Timed out waiting for sdma response");
937 return -ETIMEDOUT;
938 }
939 sys_set_bit((base_address + INTR_STATUS), SDMA_TRIGG);
940 return 0;
941 }
942
943 /**
944 * Perform buffer copying to SDMA regs in the Cadence NAND controller.
945 *
946 * @param sdma_base_address The base address of the SDMA in the Cadence NAND controller.
947 * @param buffer The source or destination buffer for the copy operation.
948 * @param data_length The length of the data to be copied.
949 */
sdma_buffer_copy_in(uint32_t sdma_base_address,uint8_t * buffer,uint32_t data_length)950 static void sdma_buffer_copy_in(uint32_t sdma_base_address, uint8_t *buffer, uint32_t data_length)
951 {
952 uint32_t index;
953
954 for (index = 0; index < data_length; index++) {
955 sys_write8(*(buffer + index), sdma_base_address + index);
956 }
957 }
958
959 /**
960 * Perform buffer copying from SDMA regs in the Cadence NAND controller.
961 *
962 * @param sdma_base_address The base address of the SDMA in the Cadence NAND controller.
963 * @param buffer The source or destination buffer for the copy operation.
964 * @param data_length The length of the data to be copied.
965 */
sdma_buffer_copy_out(uint32_t sdma_base_address,uint8_t * buffer,uint32_t data_length)966 static void sdma_buffer_copy_out(uint32_t sdma_base_address, uint8_t *buffer, uint32_t data_length)
967 {
968 uint32_t index;
969
970 for (index = 0; index < data_length; index++) {
971 *(buffer + index) = sys_read8(sdma_base_address + index);
972 }
973 }
974
975 /**
976 * Perform a generic page read operation in the Cadence NAND controller.
977 *
978 * @param params The Cadence NAND parameters structure.
979 * @param read_address The address from which to read the page.
980 * @param data_buffer The buffer to store the read data.
981 * @retval 0 on success or negative error value on failure.
982 */
cdns_generic_page_read(struct cadence_nand_params * params,uint64_t read_address,void * data_buffer)983 static int cdns_generic_page_read(struct cadence_nand_params *params, uint64_t read_address,
984 void *data_buffer)
985 {
986 uint64_t mini_ctrl_cmd = 0;
987 uintptr_t base_address = params->nand_base;
988 int ret;
989
990 mini_ctrl_cmd = PAGE_READ_CMD;
991 mini_ctrl_cmd |= GCMD_TWB_VALUE;
992 if ((params->nluns > 1) || (params->total_bit_row > 16)) {
993 mini_ctrl_cmd |= PAGE_MAX_BYTES(PAGE_MAX_SIZE);
994 } else {
995 mini_ctrl_cmd |= PAGE_MAX_BYTES(PAGE_MAX_SIZE - 1);
996 }
997 mini_ctrl_cmd |= read_address << 32;
998 ret = cdns_generic_send_cmd(params, mini_ctrl_cmd);
999 if (ret != 0) {
1000 return ret;
1001 }
1002 NAND_INT_SEM_TAKE(params);
1003 ret = cdns_generic_cmd_data(params, CDNS_READ, params->page_size);
1004 if (ret != 0) {
1005 return ret;
1006 }
1007 NAND_INT_SEM_TAKE(params);
1008 ret = cdns_wait_sdma(base_address);
1009 if (ret != 0) {
1010 return ret;
1011 }
1012 sdma_buffer_copy_out(params->sdma_base, data_buffer, params->page_size);
1013 return 0;
1014 }
1015
1016 /**
1017 * Perform a generic page write operation in the Cadence NAND controller.
1018 *
1019 * @param params The Cadence NAND parameters structure.
1020 * @param write_address The address to which the page will be written.
1021 * @param data_buffer The buffer containing the data to be written.
1022 * @retval 0 on success or negative error value on failure.
1023 */
cdns_generic_page_write(struct cadence_nand_params * params,uint64_t write_address,void * data_buffer)1024 static int cdns_generic_page_write(struct cadence_nand_params *params, uint64_t write_address,
1025 void *data_buffer)
1026 {
1027 uint64_t mini_ctrl_cmd = 0;
1028 int ret;
1029
1030 uintptr_t base_address = params->nand_base;
1031
1032 mini_ctrl_cmd |= GCMD_TWB_VALUE;
1033 mini_ctrl_cmd |= GEN_ADDR_WRITE_DATA((uint32_t)write_address);
1034 if ((params->nluns > 1) || (params->total_bit_row > BIT16_CHECK)) {
1035 mini_ctrl_cmd |= PAGE_MAX_BYTES(PAGE_MAX_SIZE);
1036 } else {
1037 mini_ctrl_cmd |= PAGE_MAX_BYTES(PAGE_MAX_SIZE - 1);
1038 }
1039 mini_ctrl_cmd |= PAGE_WRITE_CMD;
1040 ret = cdns_generic_send_cmd(params, mini_ctrl_cmd);
1041 if (ret != 0) {
1042 return ret;
1043 }
1044 NAND_INT_SEM_TAKE(params);
1045 ret = cdns_generic_cmd_data(params, CDNS_WRITE, params->page_size);
1046 if (ret != 0) {
1047 return ret;
1048 }
1049 sdma_buffer_copy_in(params->sdma_base, data_buffer, params->page_size);
1050 NAND_INT_SEM_TAKE(params);
1051 mini_ctrl_cmd = 0;
1052 mini_ctrl_cmd |= PAGE_WRITE_10H_CMD;
1053 mini_ctrl_cmd |= GCMD_TWB_VALUE;
1054 mini_ctrl_cmd |= PAGE_CMOD_CMD;
1055 ret = cdns_generic_send_cmd(params, mini_ctrl_cmd);
1056 if (ret != 0) {
1057 return ret;
1058 }
1059 NAND_INT_SEM_TAKE(params);
1060 ret = cdns_wait_sdma(base_address);
1061 return ret;
1062 }
1063
1064 /**
1065 * Perform a generic read or write operation for a range of pages in the Cadence NAND controller.
1066 *
1067 * @param params The Cadence NAND parameters structure.
1068 * @param start_page_number The starting page number for the read or write operation.
1069 * @param buffer The buffer containing the data to be written or to store the read data.
1070 * @param page_count The number of pages to be read or written.
1071 * @param mode The mode of operation (read, write).
1072 * @retval 0 on success or negative error value on failure.
1073 */
cdns_nand_gen_read_write(struct cadence_nand_params * params,uint32_t start_page_number,char * buffer,uint32_t page_count,uint8_t mode)1074 static int cdns_nand_gen_read_write(struct cadence_nand_params *params, uint32_t start_page_number,
1075 char *buffer, uint32_t page_count, uint8_t mode)
1076 {
1077 uint64_t address = 0;
1078 uint32_t index = 0;
1079 uint32_t gen_row_address = 0;
1080 int ret = 0;
1081
1082 for (index = 0; index < page_count; index++) {
1083 row_address_set(params, &gen_row_address, start_page_number++);
1084 address = ((uint64_t)gen_row_address);
1085 if (mode == CDNS_READ) {
1086 ret = cdns_generic_page_read(params, address,
1087 buffer + (index * (params->page_size)));
1088 if (ret != 0) {
1089 LOG_ERR("Cadence NAND Generic Page Read Error!!");
1090 return ret;
1091 }
1092 } else {
1093 ret = cdns_generic_page_write(params, address,
1094 buffer + (index * (params->page_size)));
1095 if (ret != 0) {
1096 LOG_ERR("Cadence NAND Generic Page write Error!!");
1097 return ret;
1098 }
1099 }
1100 }
1101 return 0;
1102 }
1103
1104 /**
1105 * Perform a generic erase operation for a range of blocks in the Cadence NAND controller.
1106 *
1107 * @param params The Cadence NAND parameters structure.
1108 * @param start_block The starting block number for the erase operation.
1109 * @param block_count The number of blocks to be erased.
1110 * @retval 0 on success or -ETIMEDOUT error value on failure.
1111 */
cdns_nand_gen_erase(struct cadence_nand_params * params,uint32_t start_block,uint32_t block_count)1112 static int cdns_nand_gen_erase(struct cadence_nand_params *params, uint32_t start_block,
1113 uint32_t block_count)
1114 {
1115 uint64_t mini_ctrl_cmd = 0;
1116 uintptr_t base_address = 0;
1117 uint32_t gen_row_address = 0;
1118 uint32_t index = 0;
1119 int ret = 0;
1120
1121 for (index = 0; index < block_count; index++) {
1122 row_address_set(params, &gen_row_address, (start_block * params->npages_per_block));
1123 start_block++;
1124 base_address = params->nand_base;
1125 mini_ctrl_cmd |= GCMD_TWB_VALUE;
1126 mini_ctrl_cmd |= ERASE_ADDR_SIZE;
1127 mini_ctrl_cmd |= ((gen_row_address) & (U32_MASK_VAL));
1128 mini_ctrl_cmd |= PAGE_ERASE_CMD;
1129 ret = cdns_generic_send_cmd(params, mini_ctrl_cmd);
1130 if (ret != 0) {
1131 return ret;
1132 }
1133 NAND_INT_SEM_TAKE(params);
1134 }
1135 return 0;
1136 }
1137 #endif
1138
1139 /**
1140 * Read data from the Cadence NAND controller into a buffer.
1141 */
cdns_read_data(struct cadence_nand_params * params,uint32_t start_page_number,const void * buffer,uint32_t page_count)1142 static inline int cdns_read_data(struct cadence_nand_params *params, uint32_t start_page_number,
1143 const void *buffer, uint32_t page_count)
1144 {
1145 int ret;
1146
1147 #if CONFIG_CDNS_NAND_CDMA_MODE
1148 ret = cdns_nand_cdma_read(params, start_page_number, (char *)buffer, page_count);
1149 #elif CONFIG_CDNS_NAND_PIO_MODE
1150 ret = cdns_nand_pio_read_write(params, start_page_number, (char *)buffer, page_count,
1151 CDNS_READ);
1152 #elif CONFIG_CDNS_NAND_GENERIC_MODE
1153 ret = cdns_nand_gen_read_write(params, start_page_number, (char *)buffer, page_count,
1154 CDNS_READ);
1155 #endif
1156 return ret;
1157 }
1158
1159 /**
1160 * Read data from the Cadence NAND controller into a buffer.
1161 *
1162 * @param params The Cadence NAND parameters structure.
1163 * @param buffer The buffer to store the read data.
1164 * @param offset The offset within the NAND to start reading from.
1165 * @param size The size of the data to read.
1166 * @retval 0 on success or negative error value on failure.
1167 */
cdns_nand_read(struct cadence_nand_params * params,const void * buffer,uint32_t offset,uint32_t size)1168 int cdns_nand_read(struct cadence_nand_params *params, const void *buffer, uint32_t offset,
1169 uint32_t size)
1170 {
1171 uint32_t start_page_number;
1172 uint32_t end_page_number;
1173 uint32_t page_count;
1174 int ret = 0;
1175 uint16_t r_bytes;
1176 uint16_t bytes_dif;
1177 uint16_t lp_bytes_dif;
1178 uint8_t check_page_first = 0;
1179 uint8_t check_page_last = 0;
1180 uint8_t *first_end_page;
1181 uint8_t *last_end_page;
1182
1183 if (params == NULL) {
1184 LOG_ERR("Wrong parameter passed!!");
1185 return -EINVAL;
1186 }
1187
1188 if (size == 0) {
1189 return 0;
1190 }
1191
1192 if ((offset >= params->device_size) || (size > (params->device_size - offset))) {
1193 LOG_ERR("Wrong offset or size value passed!!");
1194 return -EINVAL;
1195 }
1196
1197 start_page_number = offset / (params->page_size);
1198 end_page_number = ((offset + size) - 1) / ((params->page_size));
1199
1200 if ((offset % params->page_size) == 0) {
1201 check_page_first = 1;
1202 }
1203 if (((offset + size) % params->page_size) == 0) {
1204 check_page_last = 1;
1205 }
1206 page_count = end_page_number - start_page_number;
1207 page_count++;
1208 if ((check_page_last == 1) && (check_page_first == 1)) {
1209 ret = cdns_read_data(params, start_page_number, (char *)buffer, page_count);
1210 if (ret != 0) {
1211 return ret;
1212 }
1213
1214 } else if (((check_page_last == 0) && (check_page_first == 1) && (page_count == 1)) ||
1215 ((check_page_last == 0) && (check_page_first == 0) && (page_count == 1)) ||
1216 ((check_page_last == 1) && (check_page_first == 0) && (page_count == 1))) {
1217 first_end_page = (char *)k_malloc(sizeof(char) * (params->page_size));
1218 if (first_end_page != NULL) {
1219 memset(first_end_page, 0xFF, sizeof(char) * (params->page_size));
1220 } else {
1221 LOG_ERR("Memory allocation error occurred %s", __func__);
1222 return -ENOSR;
1223 }
1224 ret = cdns_read_data(params, start_page_number, first_end_page, page_count);
1225 if (ret != 0) {
1226 k_free(first_end_page);
1227 return ret;
1228 }
1229 memcpy((char *)buffer, first_end_page + (offset % (params->page_size)), size);
1230 k_free(first_end_page);
1231 } else if (((check_page_last == 0) && (check_page_first == 1) && (page_count == 2)) ||
1232 ((check_page_last == 0) && (check_page_first == 0) && (page_count == 2)) ||
1233 ((check_page_last == 1) && (check_page_first == 0) && (page_count == 2))) {
1234 first_end_page = (char *)k_malloc(sizeof(char) * (params->page_size * 2));
1235 if (first_end_page != NULL) {
1236 memset(first_end_page, 0xFF, sizeof(char) * (params->page_size * 2));
1237 } else {
1238 LOG_ERR("Memory allocation error occurred %s", __func__);
1239 return -ENOSR;
1240 }
1241 ret = cdns_read_data(params, start_page_number, first_end_page, page_count);
1242 if (ret < 0) {
1243 k_free(first_end_page);
1244 return ret;
1245 }
1246 memcpy((char *)buffer, first_end_page + (offset % (params->page_size)), size);
1247 k_free(first_end_page);
1248
1249 } else if ((check_page_last == 0) && (check_page_first == 1) && (page_count > 2)) {
1250 first_end_page = (char *)k_malloc(sizeof(char) * (params->page_size));
1251 if (first_end_page != NULL) {
1252 memset(first_end_page, 0xFF, sizeof(char) * (params->page_size));
1253 } else {
1254 LOG_ERR("Memory allocation error occurred %s", __func__);
1255 return -ENOSR;
1256 }
1257 ret = cdns_read_data(params, end_page_number, first_end_page, 1);
1258 if (ret < 0) {
1259 k_free(first_end_page);
1260 return ret;
1261 }
1262 r_bytes = (offset + size) % (params->page_size);
1263 ret = cdns_read_data(params, start_page_number, (char *)buffer, (--page_count));
1264 if (ret != 0) {
1265 k_free(first_end_page);
1266 return ret;
1267 }
1268
1269 memcpy((char *)buffer + ((page_count - 1) * params->page_size), first_end_page,
1270 r_bytes);
1271 k_free(first_end_page);
1272
1273 } else if ((check_page_last == 1) && (check_page_first == 0) && (page_count > 2)) {
1274 first_end_page = (char *)k_malloc(sizeof(char) * (params->page_size));
1275 if (first_end_page != NULL) {
1276 memset(first_end_page, 0xFF, sizeof(char) * (params->page_size));
1277 } else {
1278 LOG_ERR("Memory allocation error occurred %s", __func__);
1279 return -ENOSR;
1280 }
1281 ret = cdns_read_data(params, start_page_number, first_end_page, 1);
1282 if (ret < 0) {
1283 k_free(first_end_page);
1284 return ret;
1285 }
1286 r_bytes = (offset) % (params->page_size);
1287 bytes_dif = (((start_page_number + 1) * params->page_size) - r_bytes);
1288 r_bytes = (offset + size) % (params->page_size);
1289 ret = cdns_read_data(params, (++start_page_number), ((char *)buffer + bytes_dif),
1290 (--page_count));
1291 if (ret != 0) {
1292 k_free(first_end_page);
1293 return ret;
1294 }
1295 memcpy((char *)buffer, first_end_page + r_bytes, bytes_dif);
1296 k_free(first_end_page);
1297 } else if ((check_page_last == 0) && (check_page_first == 0) && (page_count > 2)) {
1298 first_end_page = (char *)k_malloc(sizeof(char) * (params->page_size));
1299 last_end_page = (char *)k_malloc(sizeof(char) * (params->page_size));
1300 if ((first_end_page != NULL) && (last_end_page != NULL)) {
1301 memset(first_end_page, 0xFF, sizeof(char) * (params->page_size));
1302 memset(last_end_page, 0xFF, sizeof(char) * (params->page_size));
1303 } else {
1304 LOG_ERR("Memory allocation error occurred %s", __func__);
1305 return -ENOSR;
1306 }
1307 ret = cdns_read_data(params, start_page_number, first_end_page, 1);
1308 if (ret != 0) {
1309 k_free(first_end_page);
1310 k_free(last_end_page);
1311 return ret;
1312 }
1313 r_bytes = (offset) % (params->page_size);
1314 bytes_dif = (((start_page_number + 1) * params->page_size) - r_bytes);
1315 lp_bytes_dif = (offset + size) % (params->page_size);
1316 ret = cdns_read_data(params, end_page_number, last_end_page, 1);
1317 if (ret != 0) {
1318 k_free(last_end_page);
1319 k_free(first_end_page);
1320 return ret;
1321 }
1322 r_bytes = (offset + size) % (params->page_size);
1323 ret = cdns_read_data(params, (++start_page_number), ((char *)buffer + bytes_dif),
1324 (page_count - 2));
1325 if (ret != 0) {
1326 k_free(last_end_page);
1327 k_free(first_end_page);
1328 return ret;
1329 }
1330 memcpy((char *)buffer, first_end_page + r_bytes, bytes_dif);
1331 memcpy(((char *)buffer + bytes_dif +
1332 ((page_count - 2) * (params->npages_per_block))),
1333 last_end_page, lp_bytes_dif);
1334 }
1335
1336 return 0;
1337 }
1338
1339 /**
1340 * Write data from a buffer to the Cadence NAND controller.
1341 *
1342 * @param params The Cadence NAND parameters structure.
1343 * @param buffer The buffer containing the data to be written.
1344 * @param offset The offset within the NAND to start writing to.
1345 * @param len The length of the data to write.
1346 * @retval 0 on success or negative error value on failure.
1347 */
cdns_nand_write(struct cadence_nand_params * params,const void * buffer,uint32_t offset,uint32_t len)1348 int cdns_nand_write(struct cadence_nand_params *params, const void *buffer, uint32_t offset,
1349 uint32_t len)
1350 {
1351 uint32_t start_page_number;
1352 uint32_t end_page_number;
1353 uint32_t page_count;
1354 int ret = 0;
1355
1356 if (params == NULL) {
1357 LOG_ERR("Wrong parameter passed!!");
1358 return -EINVAL;
1359 }
1360
1361 if (len == 0) {
1362 return 0;
1363 }
1364
1365 if ((offset >= params->device_size) || (len > (params->device_size - offset))) {
1366 LOG_ERR("Wrong offset or len value passed!!");
1367 return -EINVAL;
1368 }
1369
1370 if ((offset % params->page_size) != 0) {
1371 LOG_ERR("offset not page aligned!!! Page size = 0x%x", params->page_size);
1372 return -EINVAL;
1373 }
1374
1375 if ((len % params->page_size) != 0) {
1376 LOG_ERR("length not page aligned!!! Page size = 0x%x", params->page_size);
1377 return -EINVAL;
1378 }
1379
1380 start_page_number = offset / (params->page_size);
1381 end_page_number = ((offset + len) - 1) / ((params->page_size));
1382 page_count = end_page_number - start_page_number;
1383
1384 #if CONFIG_CDNS_NAND_CDMA_MODE
1385 ret = cdns_nand_cdma_write(params, start_page_number, (char *)buffer, ++page_count);
1386 #elif CONFIG_CDNS_NAND_PIO_MODE
1387 ret = cdns_nand_pio_read_write(params, start_page_number, (char *)buffer, ++page_count,
1388 CDNS_WRITE);
1389 #elif CONFIG_CDNS_NAND_GENERIC_MODE
1390 ret = cdns_nand_gen_read_write(params, start_page_number, (char *)buffer, ++page_count,
1391 CDNS_WRITE);
1392 #endif
1393 if (ret != 0) {
1394 LOG_ERR("Cadence driver write Failed!!!");
1395 }
1396
1397 return ret;
1398 }
1399
1400 /**
1401 * Perform an erase operation on the Cadence NAND controller.
1402 *
1403 * @param params The Cadence NAND parameters structure.
1404 * @param offset The offset within the NAND to start erasing.
1405 * @param size The size of the data to erase.
1406 * @retval 0 on success or negative error value on failure.
1407 */
cdns_nand_erase(struct cadence_nand_params * params,uint32_t offset,uint32_t size)1408 int cdns_nand_erase(struct cadence_nand_params *params, uint32_t offset, uint32_t size)
1409 {
1410 uint32_t start_block_number;
1411 uint32_t end_block_number;
1412 uint32_t block_count;
1413 int ret;
1414
1415 if (params == NULL) {
1416 LOG_ERR("Wrong parameter passed!!");
1417 return -EINVAL;
1418 }
1419
1420 if (size == 0) {
1421 return 0;
1422 }
1423
1424 if ((offset >= params->device_size) || (size > (params->device_size - offset))) {
1425 LOG_ERR("Wrong offset or size value passed!!");
1426 return -EINVAL;
1427 }
1428 if ((offset % (params->block_size)) != 0) {
1429 LOG_ERR("Offset value not aligned with block size!! Erase block size = %x",
1430 params->block_size);
1431 return -EINVAL;
1432 }
1433 if ((size % (params->block_size)) != 0) {
1434 LOG_ERR("Length value not aligned with block size!! Erase block size = %x",
1435 params->block_size);
1436 return -EINVAL;
1437 }
1438
1439 start_block_number = (offset / ((params->page_size))) / (params->npages_per_block);
1440 end_block_number =
1441 (((offset + size) - 1) / ((params->page_size))) / (params->npages_per_block);
1442 block_count = end_block_number - start_block_number;
1443 #if CONFIG_CDNS_NAND_CDMA_MODE
1444 ret = cdns_nand_cdma_erase(params, start_block_number, ++block_count);
1445 #elif CONFIG_CDNS_NAND_PIO_MODE
1446 ret = cdns_nand_pio_erase(params, NF_TDEF_TRD_NUM, NF_TDEF_DEV_NUM, start_block_number,
1447 CNF_CMD_ERASE, ++block_count);
1448 #elif CONFIG_CDNS_NAND_GENERIC_MODE
1449 ret = cdns_nand_gen_erase(params, start_block_number, ++block_count);
1450 #endif
1451 if (ret != 0) {
1452 LOG_ERR("Cadence driver Erase Failed!!!");
1453 }
1454
1455 return ret;
1456 }
1457
1458 #if CONFIG_CDNS_NAND_INTERRUPT_SUPPORT
cdns_nand_irq_handler_ll(struct cadence_nand_params * params)1459 void cdns_nand_irq_handler_ll(struct cadence_nand_params *params)
1460 {
1461 uint32_t status = 0;
1462 uint8_t thread_num = 0;
1463
1464 status = sys_read32(params->nand_base + THREAD_INTERRUPT_STATUS);
1465 thread_num = find_lsb_set(status);
1466
1467 if (GET_INIT_SET_CHECK(status, (thread_num - 1)) != 0) {
1468 /* Clear the interrupt*/
1469 sys_write32(BIT((thread_num - 1)), params->nand_base + THREAD_INTERRUPT_STATUS);
1470 }
1471 }
1472 #endif
1473