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 *)&reg_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