1 /*
2  * Copyright (C) 2023 Intel Corporation
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <stddef.h>
7 #include "sdhc_cdns_ll.h"
8 #include <zephyr/logging/log.h>
9 
10 LOG_MODULE_REGISTER(sdhc_cdns_ll, CONFIG_SDHC_LOG_LEVEL);
11 
12 /* card busy and present */
13 #define CARD_BUSY			1
14 #define CARD_NOT_BUSY			0
15 #define CARD_PRESENT			1
16 
17 /* SRS12 error mask */
18 #define CDNS_SRS12_ERR_MASK			0xFFFF8000U
19 #define CDNS_CSD_BYTE_MASK			0x000000FFU
20 
21 /* General define */
22 #define SDHC_REG_MASK				0xFFFFFFFFU
23 #define SD_HOST_BLOCK_SIZE			0x200
24 
25 #define SDMMC_DMA_MAX_BUFFER_SIZE		(64 * 1024)
26 #define CDNSMMC_ADDRESS_MASK			(CONFIG_SDHC_BUFFER_ALIGNMENT - 1)
27 
28 #define SRS10_VAL_READ	(ADMA2_32 | HS_EN | DT_WIDTH)
29 #define SRS10_VAL_SW	(ADMA2_32 | DT_WIDTH)
30 #define SRS11_VAL_GEN	(READ_CLK | CDNS_SRS11_ICE | CDNS_SRS11_ICS | CDNS_SRS11_SDCE)
31 #define SRS11_VAL_CID	(CDNS_SRS11_ICE | CDNS_SRS11_ICS | CDNS_SRS11_SDCE)
32 #define SRS15_VAL_GEN	(CDNS_SRS15_BIT_AD_64 | CDNS_SRS15_HV4E | CDNS_SRS15_V18SE)
33 #define SRS15_VAL_RD_WR	(SRS15_VAL_GEN | CDNS_SRS15_SDR104 | CDNS_SRS15_PVE)
34 #define SRS15_VAL_CID	(CDNS_SRS15_HV4E | CDNS_SRS15_V18SE)
35 
36 #define CARD_REG_TIME_DELAY_US			100000
37 #define WAIT_ICS_TIME_DELAY_US			5000
38 #define RESET_SRS14				0x00000000
39 
40 static struct sdhc_cdns_params cdns_params;
41 static struct sdhc_cdns_combo_phy sdhc_cdns_combo_phy_reg_info;
42 static struct sdhc_cdns_sdmmc sdhc_cdns_sdmmc_reg_info;
43 
44 /* Function to write general phy registers */
sdhc_cdns_write_phy_reg(uint32_t phy_reg_addr,uint32_t phy_reg_addr_value,uint32_t phy_reg_data,uint32_t phy_reg_data_value)45 static int sdhc_cdns_write_phy_reg(uint32_t phy_reg_addr, uint32_t phy_reg_addr_value,
46 			uint32_t phy_reg_data, uint32_t phy_reg_data_value)
47 {
48 	uint32_t data = 0;
49 
50 	/* Set PHY register address, write HRS04*/
51 	sys_write32(phy_reg_addr_value, phy_reg_addr);
52 
53 	/* Set PHY register data, write HRS05 */
54 	sys_write32(phy_reg_data_value, phy_reg_data);
55 	data = sys_read32(phy_reg_data);
56 
57 	if (data != phy_reg_data_value) {
58 		LOG_ERR("PHY_REG_DATA is not set properly");
59 		return -ENXIO;
60 	}
61 
62 	return 0;
63 }
64 
sdhc_cdns_wait_ics(uint16_t timeout,uint32_t cdn_srs_res)65 int sdhc_cdns_wait_ics(uint16_t timeout, uint32_t cdn_srs_res)
66 {
67 	/* Wait status command response ready */
68 	if (!WAIT_FOR(((sys_read32(cdn_srs_res) & CDNS_SRS11_ICS)
69 		== CDNS_SRS11_ICS), timeout, k_msleep(1))) {
70 		LOG_ERR("Timed out waiting for ICS response");
71 		return -ETIMEDOUT;
72 	}
73 
74 	return 0;
75 }
76 
sdhc_cdns_busy(void)77 static int sdhc_cdns_busy(void)
78 {
79 	unsigned int data;
80 
81 	data = sys_read32(cdns_params.reg_base + SDHC_CDNS_SRS09);
82 	return (data & CDNS_SRS09_STAT_DAT_BUSY) ? CARD_BUSY : CARD_NOT_BUSY;
83 }
84 
sdhc_cdns_card_present(void)85 static int sdhc_cdns_card_present(void)
86 {
87 	uint32_t timeout = CARD_REG_TIME_DELAY_US;
88 
89 	if (!WAIT_FOR((((sys_read32(cdns_params.reg_base + SDHC_CDNS_SRS09))
90 			& CDNS_SRS09_CI) == CDNS_SRS09_CI),
91 			timeout, k_msleep(1))) {
92 		LOG_ERR("Card detection timeout");
93 		return -ETIMEDOUT;
94 	}
95 
96 	return CARD_PRESENT;
97 }
98 
sdhc_cdns_vol_reset(void)99 static int sdhc_cdns_vol_reset(void)
100 {
101 	/* Reset embedded card, turn off supply voltage */
102 	sys_write32(BUS_VOLTAGE_3_3_V,
103 		(cdns_params.reg_base + SDHC_CDNS_SRS10));
104 
105 	/*
106 	 * Turn on supply voltage
107 	 * CDNS_SRS10_BVS = 7, CDNS_SRS10_BP = 1, BP2 only in UHS2 mode
108 	 */
109 	sys_write32(BUS_VOLTAGE_3_3_V | CDNS_SRS10_BP,
110 		(cdns_params.reg_base + SDHC_CDNS_SRS10));
111 
112 	return 0;
113 }
114 
115 /*
116  * Values are taken from IP documents and calc_setting.py script
117  * with input value- mode sd_ds,
118  * sdmclk 5000,
119  * sdclk 10000,
120  * iocell_input_delay 2500,
121  * iocell_output_delay 2500 and
122  * delay_element 24
123  */
cdns_sdhc_set_sdmmc_params(struct sdhc_cdns_combo_phy * sdhc_cdns_combo_phy_reg,struct sdhc_cdns_sdmmc * sdhc_cdns_sdmmc_reg)124 void cdns_sdhc_set_sdmmc_params(struct sdhc_cdns_combo_phy *sdhc_cdns_combo_phy_reg,
125 	struct sdhc_cdns_sdmmc *sdhc_cdns_sdmmc_reg)
126 {
127 	/* Values are taken by the reference of cadence IP documents */
128 	sdhc_cdns_combo_phy_reg->cp_clk_wr_delay = 0;
129 	sdhc_cdns_combo_phy_reg->cp_clk_wrdqs_delay = 0;
130 	sdhc_cdns_combo_phy_reg->cp_data_select_oe_end = 1;
131 	sdhc_cdns_combo_phy_reg->cp_dll_bypass_mode = 1;
132 	sdhc_cdns_combo_phy_reg->cp_dll_locked_mode = 3;
133 	sdhc_cdns_combo_phy_reg->cp_dll_start_point = 4;
134 	sdhc_cdns_combo_phy_reg->cp_gate_cfg_always_on = 1;
135 	sdhc_cdns_combo_phy_reg->cp_io_mask_always_on = 0;
136 	sdhc_cdns_combo_phy_reg->cp_io_mask_end = 2;
137 	sdhc_cdns_combo_phy_reg->cp_io_mask_start = 0;
138 	sdhc_cdns_combo_phy_reg->cp_rd_del_sel = 52;
139 	sdhc_cdns_combo_phy_reg->cp_read_dqs_cmd_delay = 0;
140 	sdhc_cdns_combo_phy_reg->cp_read_dqs_delay = 0;
141 	sdhc_cdns_combo_phy_reg->cp_sw_half_cycle_shift = 0;
142 	sdhc_cdns_combo_phy_reg->cp_sync_method = 1;
143 	sdhc_cdns_combo_phy_reg->cp_underrun_suppress = 1;
144 	sdhc_cdns_combo_phy_reg->cp_use_ext_lpbk_dqs = 1;
145 	sdhc_cdns_combo_phy_reg->cp_use_lpbk_dqs = 1;
146 	sdhc_cdns_combo_phy_reg->cp_use_phony_dqs = 1;
147 	sdhc_cdns_combo_phy_reg->cp_use_phony_dqs_cmd = 1;
148 
149 	sdhc_cdns_sdmmc_reg->sdhc_extended_rd_mode = 1;
150 	sdhc_cdns_sdmmc_reg->sdhc_extended_wr_mode = 1;
151 	sdhc_cdns_sdmmc_reg->sdhc_hcsdclkadj = 6;
152 	sdhc_cdns_sdmmc_reg->sdhc_idelay_val = 1;
153 	sdhc_cdns_sdmmc_reg->sdhc_rdcmd_en = 1;
154 	sdhc_cdns_sdmmc_reg->sdhc_rddata_en = 1;
155 	sdhc_cdns_sdmmc_reg->sdhc_rw_compensate = 10;
156 	sdhc_cdns_sdmmc_reg->sdhc_sdcfsh = 0;
157 	sdhc_cdns_sdmmc_reg->sdhc_sdcfsl = 1;
158 	sdhc_cdns_sdmmc_reg->sdhc_wrcmd0_dly = 1;
159 	sdhc_cdns_sdmmc_reg->sdhc_wrcmd0_sdclk_dly = 0;
160 	sdhc_cdns_sdmmc_reg->sdhc_wrcmd1_dly = 0;
161 	sdhc_cdns_sdmmc_reg->sdhc_wrcmd1_sdclk_dly = 0;
162 	sdhc_cdns_sdmmc_reg->sdhc_wrdata0_dly = 1;
163 	sdhc_cdns_sdmmc_reg->sdhc_wrdata0_sdclk_dly = 0;
164 	sdhc_cdns_sdmmc_reg->sdhc_wrdata1_dly = 0;
165 	sdhc_cdns_sdmmc_reg->sdhc_wrdata1_sdclk_dly = 0;
166 }
167 
168 /* Phy register programing for phy init */
sdhc_cdns_program_phy_reg(struct sdhc_cdns_combo_phy * sdhc_cdns_combo_phy_reg,struct sdhc_cdns_sdmmc * sdhc_cdns_sdmmc_reg)169 static int sdhc_cdns_program_phy_reg(struct sdhc_cdns_combo_phy *sdhc_cdns_combo_phy_reg,
170 	struct sdhc_cdns_sdmmc *sdhc_cdns_sdmmc_reg)
171 {
172 	uint32_t value = 0;
173 	int ret = 0;
174 
175 	/*
176 	 * program PHY_DQS_TIMING_REG
177 	 * This register controls the DQS related timing
178 	 */
179 	value = (CP_USE_EXT_LPBK_DQS(sdhc_cdns_combo_phy_reg->cp_use_ext_lpbk_dqs))
180 		| (CP_USE_LPBK_DQS(sdhc_cdns_combo_phy_reg->cp_use_lpbk_dqs))
181 		| (CP_USE_PHONY_DQS(sdhc_cdns_combo_phy_reg->cp_use_phony_dqs))
182 		| (CP_USE_PHONY_DQS_CMD(sdhc_cdns_combo_phy_reg->cp_use_phony_dqs_cmd));
183 	ret = sdhc_cdns_write_phy_reg(cdns_params.reg_base + SDHC_CDNS_HRS04,
184 			cdns_params.combophy + PHY_DQS_TIMING_REG, cdns_params.reg_base
185 			+ SDHC_CDNS_HRS05, value);
186 	if (ret != 0U) {
187 		LOG_ERR("Error in PHY_DQS_TIMING_REG programming");
188 		return ret;
189 	}
190 
191 	/*
192 	 * program PHY_GATE_LPBK_CTRL_REG
193 	 * This register controls the gate and loopback control related timing.
194 	 */
195 	value = (CP_SYNC_METHOD(sdhc_cdns_combo_phy_reg->cp_sync_method))
196 		| (CP_SW_HALF_CYCLE_SHIFT(sdhc_cdns_combo_phy_reg->cp_sw_half_cycle_shift))
197 		| (CP_RD_DEL_SEL(sdhc_cdns_combo_phy_reg->cp_rd_del_sel))
198 		| (CP_UNDERRUN_SUPPRESS(sdhc_cdns_combo_phy_reg->cp_underrun_suppress))
199 		| (CP_GATE_CFG_ALWAYS_ON(sdhc_cdns_combo_phy_reg->cp_gate_cfg_always_on));
200 	ret = sdhc_cdns_write_phy_reg(cdns_params.reg_base + SDHC_CDNS_HRS04,
201 			cdns_params.combophy + PHY_GATE_LPBK_CTRL_REG, cdns_params.reg_base
202 			+ SDHC_CDNS_HRS05, value);
203 	if (ret != 0U) {
204 		LOG_ERR("Error in PHY_GATE_LPBK_CTRL_REG programming");
205 		return -ret;
206 	}
207 
208 	/*
209 	 * program PHY_DLL_MASTER_CTRL_REG
210 	 * This register holds the control for the Master DLL logic.
211 	 */
212 	value = (CP_DLL_BYPASS_MODE(sdhc_cdns_combo_phy_reg->cp_dll_bypass_mode))
213 			| (CP_DLL_START_POINT(sdhc_cdns_combo_phy_reg->cp_dll_start_point));
214 	ret = sdhc_cdns_write_phy_reg(cdns_params.reg_base + SDHC_CDNS_HRS04,
215 			cdns_params.combophy + PHY_DLL_MASTER_CTRL_REG, cdns_params.reg_base
216 			+ SDHC_CDNS_HRS05, value);
217 	if (ret != 0U) {
218 		LOG_ERR("Error in PHY_DLL_MASTER_CTRL_REG programming");
219 		return ret;
220 	}
221 
222 	/*
223 	 * program PHY_DLL_SLAVE_CTRL_REG
224 	 * This register holds the control for the slave DLL logic.
225 	 */
226 	value = (CP_READ_DQS_CMD_DELAY(sdhc_cdns_combo_phy_reg->cp_read_dqs_cmd_delay))
227 		| (CP_CLK_WRDQS_DELAY(sdhc_cdns_combo_phy_reg->cp_clk_wrdqs_delay))
228 		| (CP_CLK_WR_DELAY(sdhc_cdns_combo_phy_reg->cp_clk_wr_delay))
229 		| (CP_READ_DQS_DELAY(sdhc_cdns_combo_phy_reg->cp_read_dqs_delay));
230 	ret = sdhc_cdns_write_phy_reg(cdns_params.reg_base + SDHC_CDNS_HRS04,
231 			cdns_params.combophy + PHY_DLL_SLAVE_CTRL_REG, cdns_params.reg_base
232 			+ SDHC_CDNS_HRS05, value);
233 	if (ret != 0U) {
234 		LOG_ERR("Error in PHY_DLL_SLAVE_CTRL_REG programming");
235 		return ret;
236 	}
237 
238 	/*
239 	 * program PHY_CTRL_REG
240 	 * This register handles the global control settings for the PHY.
241 	 */
242 	sys_write32(cdns_params.combophy + PHY_CTRL_REG, cdns_params.reg_base
243 		+ SDHC_CDNS_HRS04);
244 	value = sys_read32(cdns_params.reg_base + SDHC_CDNS_HRS05);
245 
246 	/* phony_dqs_timing=0 */
247 	value &= ~(CP_PHONY_DQS_TIMING_MASK << CP_PHONY_DQS_TIMING_SHIFT);
248 	sys_write32(value, cdns_params.reg_base + SDHC_CDNS_HRS05);
249 
250 	/* switch off DLL_RESET */
251 	do {
252 		value = sys_read32(cdns_params.reg_base + SDHC_CDNS_HRS09);
253 		value |= CDNS_HRS09_PHY_SW_RESET;
254 		sys_write32(value, cdns_params.reg_base + SDHC_CDNS_HRS09);
255 		value = sys_read32(cdns_params.reg_base + SDHC_CDNS_HRS09);
256 	/* polling PHY_INIT_COMPLETE */
257 	} while ((value & CDNS_HRS09_PHY_INIT_COMP) != CDNS_HRS09_PHY_INIT_COMP);
258 
259 	/*
260 	 * program PHY_DQ_TIMING_REG
261 	 * This register controls the DQ related timing.
262 	 */
263 	sdhc_cdns_combo_phy_reg->cp_io_mask_end = 0U;
264 	value = (CP_IO_MASK_ALWAYS_ON(sdhc_cdns_combo_phy_reg->cp_io_mask_always_on))
265 		| (CP_IO_MASK_END(sdhc_cdns_combo_phy_reg->cp_io_mask_end))
266 		| (CP_IO_MASK_START(sdhc_cdns_combo_phy_reg->cp_io_mask_start))
267 		| (CP_DATA_SELECT_OE_END(sdhc_cdns_combo_phy_reg->cp_data_select_oe_end));
268 
269 	ret = sdhc_cdns_write_phy_reg(cdns_params.reg_base + SDHC_CDNS_HRS04,
270 			cdns_params.combophy + PHY_DQ_TIMING_REG, cdns_params.reg_base
271 			+ SDHC_CDNS_HRS05, value);
272 	if (ret != 0U) {
273 		LOG_ERR("Error in PHY_DQ_TIMING_REG programming");
274 		return ret;
275 	}
276 	return 0;
277 }
278 
sdhc_cdns_cache_invd(int lba,uintptr_t buf,size_t size)279 static int sdhc_cdns_cache_invd(int lba, uintptr_t buf, size_t size)
280 {
281 	int ret = 0;
282 
283 	ret = arch_dcache_invd_range((void *)buf, size);
284 	if (ret != 0) {
285 		LOG_ERR("%s: error in invalidate dcache with ret %d", __func__, ret);
286 		return ret;
287 	}
288 
289 	return 0;
290 }
291 
292 /* DMA preparation for the read and write operation */
sdhc_cdns_prepare(uint32_t dma_start_addr,uintptr_t dma_buff,struct sdhc_data * data)293 static int sdhc_cdns_prepare(uint32_t dma_start_addr, uintptr_t dma_buff,
294 	struct sdhc_data *data)
295 {
296 	struct sdhc_cdns_desc *desc;
297 	uint32_t desc_cnt, i;
298 	uintptr_t base;
299 	uint64_t desc_base;
300 	uint32_t size = data->blocks * data->block_size;
301 
302 	__ASSERT_NO_MSG(((dma_buff & CDNSMMC_ADDRESS_MASK) == 0) &&
303 			(cdns_params.desc_size > 0) &&
304 			((cdns_params.desc_size & MMC_BLOCK_MASK) == 0));
305 
306 	arch_dcache_flush_range((void *)dma_buff, size);
307 
308 	desc_cnt = (size + (SDMMC_DMA_MAX_BUFFER_SIZE) - 1) /
309 		(SDMMC_DMA_MAX_BUFFER_SIZE);
310 	__ASSERT_NO_MSG(desc_cnt * sizeof(struct sdhc_cdns_desc) <
311 		cdns_params.desc_size);
312 
313 	if (desc_cnt > CONFIG_CDNS_DESC_COUNT) {
314 		LOG_ERR("Requested data transfer length %u greater than configured length %u",
315 			size, (CONFIG_CDNS_DESC_COUNT * SDMMC_DMA_MAX_BUFFER_SIZE));
316 		return -EINVAL;
317 	}
318 
319 	/*
320 	 * Creating descriptor as per the desc_count and linked list of
321 	 * descriptor for contiguous desc alignment
322 	 */
323 	base = cdns_params.reg_base;
324 	desc = (struct sdhc_cdns_desc *)cdns_params.desc_base;
325 	desc_base = (uint64_t)desc;
326 	i = 0;
327 
328 	while ((i+1) < desc_cnt) {
329 		desc->attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA;
330 		desc->reserved = 0;
331 		desc->len = MAX_64KB_PAGE;
332 		desc->addr_lo = (dma_buff & 0xffffffff) + (SDMMC_DMA_MAX_BUFFER_SIZE * i);
333 		desc->addr_hi = (dma_buff >> 32) & 0xffffffff;
334 		size -= SDMMC_DMA_MAX_BUFFER_SIZE;
335 		desc++;
336 		i++;
337 	}
338 
339 	desc->attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA |
340 			ADMA_DESC_ATTR_END;
341 	desc->reserved = 0;
342 	desc->len = size;
343 	desc->addr_lo = (dma_buff & 0xffffffff) + (SDMMC_DMA_MAX_BUFFER_SIZE * i);
344 	desc->addr_hi = (dma_buff >> 32) & 0xffffffff;
345 
346 	sys_write32((uint32_t)desc_base, cdns_params.reg_base + SDHC_CDNS_SRS22);
347 	sys_write32((uint32_t)(desc_base >> 32), cdns_params.reg_base + SDHC_CDNS_SRS23);
348 	arch_dcache_flush_range((void *)cdns_params.desc_base,
349 				desc_cnt * sizeof(struct sdhc_cdns_desc));
350 
351 	sys_write32((data->block_size << CDNS_SRS01_BLK_SIZE |
352 				data->blocks << CDNS_SRS01_BLK_COUNT_CT |
353 				BUFFER_BOUNDARY_512K << CDNS_SRS01_SDMA_BUF),
354 				cdns_params.reg_base + SDHC_CDNS_SRS01);
355 
356 	return 0;
357 }
358 
sdhc_cdns_host_set_clk(int clk)359 static int sdhc_cdns_host_set_clk(int clk)
360 {
361 	uint32_t sdclkfsval = 0;
362 	uint32_t dtcvval = 0xe;
363 	int ret = 0;
364 
365 	sdclkfsval = (cdns_params.clk_rate / 2000) / clk;
366 	sys_write32(0, cdns_params.reg_base + SDHC_CDNS_SRS11);
367 	sys_write32(((dtcvval << CDNS_SRS11_DTCV) | (sdclkfsval << CDNS_SRS11_SDCLKFS) |
368 		CDNS_SRS11_ICE), cdns_params.reg_base + SDHC_CDNS_SRS11);
369 
370 	ret = sdhc_cdns_wait_ics(WAIT_ICS_TIME_DELAY_US, cdns_params.reg_base + SDHC_CDNS_SRS11);
371 	if (ret != 0) {
372 		return ret;
373 	}
374 
375 	/* Enable DLL reset */
376 	sys_clear_bit(cdns_params.reg_base + SDHC_CDNS_HRS09, 0);
377 	/* Set extended_wr_mode */
378 	sys_write32(((sys_read32(cdns_params.reg_base + SDHC_CDNS_HRS09)
379 		& 0xFFFFFFF7) | CDNS_HRS09_EXT_WR_MODE), (cdns_params.reg_base
380 		+ SDHC_CDNS_HRS09));
381 	/* Release DLL reset */
382 	sys_set_bits(cdns_params.reg_base + SDHC_CDNS_HRS09, CDNS_HRS09_RDCMD_EN_BIT |
383 					CDNS_HRS09_RDDATA_EN_BIT);
384 
385 	sys_write32(((dtcvval << CDNS_SRS11_DTCV) | (sdclkfsval << CDNS_SRS11_SDCLKFS)
386 			| CDNS_SRS11_ICE | CDNS_SRS11_SDCE),
387 			cdns_params.reg_base + SDHC_CDNS_SRS11);
388 
389 	sys_write32(0xFFFFFFFF, cdns_params.reg_base + SDHC_CDNS_SRS13);
390 
391 	return 0;
392 }
393 
sdhc_cdns_set_ios(unsigned int clk,unsigned int width)394 static int sdhc_cdns_set_ios(unsigned int clk, unsigned int width)
395 {
396 	int ret = 0;
397 
398 	switch (width) {
399 	case SDHC_BUS_WIDTH1BIT:
400 		sys_clear_bit(cdns_params.reg_base + SDHC_CDNS_SRS10, WIDTH_BIT1);
401 		break;
402 	case SDHC_BUS_WIDTH4BIT:
403 		sys_set_bit(cdns_params.reg_base + SDHC_CDNS_SRS10, WIDTH_BIT4);
404 		break;
405 	case SDHC_BUS_WIDTH8BIT:
406 		sys_set_bit(cdns_params.reg_base + SDHC_CDNS_SRS10, WIDTH_BIT8);
407 		break;
408 	default:
409 		__ASSERT_NO_MSG(0);
410 		break;
411 	}
412 
413 	/* Perform clock configuration when SD clock is not gated */
414 	if (clk != 0) {
415 		ret = sdhc_cdns_host_set_clk(clk);
416 		if (ret != 0) {
417 			LOG_ERR("%s: Clock configuration failed", __func__);
418 			return ret;
419 		}
420 	}
421 
422 	return 0;
423 }
424 
425 /* Programming HRS register for initialisation */
sdhc_cdns_init_hrs_io(struct sdhc_cdns_combo_phy * sdhc_cdns_combo_phy_reg,struct sdhc_cdns_sdmmc * sdhc_cdns_sdmmc_reg)426 static int sdhc_cdns_init_hrs_io(struct sdhc_cdns_combo_phy *sdhc_cdns_combo_phy_reg,
427 	struct sdhc_cdns_sdmmc *sdhc_cdns_sdmmc_reg)
428 {
429 	uint32_t value = 0;
430 	int ret = 0;
431 
432 	/*
433 	 * program HRS09, register 42
434 	 * PHY Control and Status Register
435 	 */
436 	value = (CDNS_HRS09_RDDATA_EN(sdhc_cdns_sdmmc_reg->sdhc_rddata_en))
437 		| (CDNS_HRS09_RDCMD_EN(sdhc_cdns_sdmmc_reg->sdhc_rdcmd_en))
438 		| (CDNS_HRS09_EXTENDED_WR(sdhc_cdns_sdmmc_reg->sdhc_extended_wr_mode))
439 		| (CDNS_HRS09_EXT_RD_MODE(sdhc_cdns_sdmmc_reg->sdhc_extended_rd_mode));
440 	sys_write32(value, cdns_params.reg_base + SDHC_CDNS_HRS09);
441 
442 	/*
443 	 * program HRS10, register 43
444 	 * Host Controller SDCLK start point adjustment
445 	 */
446 	value = (SDHC_HRS10_HCSDCLKADJ(sdhc_cdns_sdmmc_reg->sdhc_hcsdclkadj));
447 	sys_write32(value, cdns_params.reg_base + SDHC_CDNS_HRS10);
448 
449 	/*
450 	 * program HRS16, register 48
451 	 * CMD/DAT output delay
452 	 */
453 	value = (CDNS_HRS16_WRDATA1_SDCLK_DLY(sdhc_cdns_sdmmc_reg->sdhc_wrdata1_sdclk_dly))
454 		| (CDNS_HRS16_WRDATA0_SDCLK_DLY(sdhc_cdns_sdmmc_reg->sdhc_wrdata0_sdclk_dly))
455 		| (CDNS_HRS16_WRCMD1_SDCLK_DLY(sdhc_cdns_sdmmc_reg->sdhc_wrcmd1_sdclk_dly))
456 		| (CDNS_HRS16_WRCMD0_SDCLK_DLY(sdhc_cdns_sdmmc_reg->sdhc_wrcmd0_sdclk_dly))
457 		| (CDNS_HRS16_WRDATA1_DLY(sdhc_cdns_sdmmc_reg->sdhc_wrdata1_dly))
458 		| (CDNS_HRS16_WRDATA0_DLY(sdhc_cdns_sdmmc_reg->sdhc_wrdata0_dly))
459 		| (CDNS_HRS16_WRCMD1_DLY(sdhc_cdns_sdmmc_reg->sdhc_wrcmd1_dly))
460 		| (CDNS_HRS16_WRCMD0_DLY(sdhc_cdns_sdmmc_reg->sdhc_wrcmd0_dly));
461 	sys_write32(value, cdns_params.reg_base + SDHC_CDNS_HRS16);
462 
463 	/*
464 	 * program HRS07, register 40
465 	 * IO Delay Information Register
466 	 */
467 	value = (CDNS_HRS07_RW_COMPENSATE(sdhc_cdns_sdmmc_reg->sdhc_rw_compensate))
468 		| (CDNS_HRS07_IDELAY_VAL(sdhc_cdns_sdmmc_reg->sdhc_idelay_val));
469 	sys_write32(value, cdns_params.reg_base + SDHC_CDNS_HRS07);
470 
471 	return ret;
472 }
473 
sdhc_cdns_set_clk(struct sdhc_cdns_params * cdn_sdmmc_dev_type_params)474 static int sdhc_cdns_set_clk(struct sdhc_cdns_params *cdn_sdmmc_dev_type_params)
475 {
476 	uint32_t dtcvval, sdclkfsval;
477 	int ret = 0;
478 
479 	dtcvval = DTC_VAL;
480 	sdclkfsval = 0;
481 
482 	/* Condition for Default speed mode and SDR12 and SDR_BC */
483 	if ((cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == SD_DS) ||
484 		(cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == SD_UHS_SDR12) ||
485 		(cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == EMMC_SDR_BC)) {
486 		sdclkfsval = 4;
487 	} else if ((cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == SD_HS) ||
488 		(cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == SD_UHS_SDR25) ||
489 		(cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == SD_UHS_DDR50) ||
490 		(cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == EMMC_SDR)) {
491 		sdclkfsval = 2;
492 	} else if ((cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == SD_UHS_SDR50) ||
493 		(cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == EMMC_DDR) ||
494 		(cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == EMMC_HS400) ||
495 		(cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == EMMC_HS400ES)) {
496 		sdclkfsval = 1;
497 	} else if ((cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == SD_UHS_SDR104) ||
498 		(cdn_sdmmc_dev_type_params->cdn_sdmmc_dev_type == EMMC_HS200)) {
499 		sdclkfsval = 0;
500 	}
501 
502 	/* Disabling SD clock enable */
503 	sys_write32(0, cdns_params.reg_base + SDHC_CDNS_SRS11);
504 	sys_write32((dtcvval << CDNS_SRS11_DTCV) |
505 		(sdclkfsval << CDNS_SRS11_SDCLKFS) | CDNS_SRS11_ICE,
506 			cdns_params.reg_base + SDHC_CDNS_SRS11);
507 	ret = sdhc_cdns_wait_ics(WAIT_ICS_TIME_DELAY_US, cdns_params.reg_base + SDHC_CDNS_SRS11);
508 	if (ret != 0) {
509 		return ret;
510 	}
511 
512 	/* Enable DLL reset */
513 	sys_clear_bit(cdns_params.reg_base + SDHC_CDNS_HRS09, 0);
514 	/* Set extended_wr_mode */
515 	sys_write32(((sys_read32(cdns_params.reg_base + SDHC_CDNS_HRS09) &
516 			0xFFFFFFF7) | CDNS_HRS09_EXT_WR_MODE), (cdns_params.reg_base
517 			+ SDHC_CDNS_HRS09));
518 	/* Release DLL reset */
519 	sys_set_bits(cdns_params.reg_base + SDHC_CDNS_HRS09, CDNS_HRS09_RDCMD_EN_BIT |
520 					CDNS_HRS09_RDDATA_EN_BIT);
521 
522 	sys_write32((dtcvval << CDNS_SRS11_DTCV) | (sdclkfsval << CDNS_SRS11_SDCLKFS) |
523 		CDNS_SRS11_ICE | CDNS_SRS11_SDCE, cdns_params.reg_base
524 		+ SDHC_CDNS_SRS11);
525 
526 	sys_write32(0xFFFFFFFF, cdns_params.reg_base + SDHC_CDNS_SRS13);
527 	return 0;
528 }
529 
sdhc_cdns_reset(void)530 static int sdhc_cdns_reset(void)
531 {
532 	int32_t timeout;
533 
534 	sys_clear_bits(cdns_params.reg_base + SDHC_CDNS_SRS11, 0xFFFF);
535 
536 	/* Software reset */
537 	sys_set_bit(cdns_params.reg_base + SDHC_CDNS_HRS00, CDNS_HRS00_SWR);
538 
539 	/* Wait status command response ready */
540 	timeout = CARD_REG_TIME_DELAY_US;
541 	if (!WAIT_FOR(((sys_read32(cdns_params.reg_base + SDHC_CDNS_HRS00) &
542 		CDNS_HRS00_SWR) == 0), timeout, k_msleep(1))) {
543 		LOG_ERR("Software reset is not completed...timedout");
544 		return -ETIMEDOUT;
545 	}
546 
547 	/* Step 1, switch on DLL_RESET */
548 	sys_clear_bit(cdns_params.reg_base + SDHC_CDNS_HRS09, CDNS_HRS09_PHY_SW_RESET);
549 
550 	return 0;
551 }
552 
sdhc_cdns_init(void)553 static int sdhc_cdns_init(void)
554 {
555 	int ret = 0;
556 
557 	ret = sdhc_cdns_program_phy_reg(&sdhc_cdns_combo_phy_reg_info, &sdhc_cdns_sdmmc_reg_info);
558 	if (ret != 0U) {
559 		LOG_ERR("SoftPhy register configuration failed");
560 		return ret;
561 	}
562 
563 	ret = sdhc_cdns_init_hrs_io(&sdhc_cdns_combo_phy_reg_info, &sdhc_cdns_sdmmc_reg_info);
564 	if (ret != 0U) {
565 		LOG_ERR("Configuration for HRS IO reg failed");
566 		return ret;
567 	}
568 
569 	ret = sdhc_cdns_card_present();
570 	if (ret != CARD_PRESENT) {
571 		LOG_ERR("SD card does not detect");
572 		return -ETIMEDOUT;
573 	}
574 
575 	ret = sdhc_cdns_vol_reset();
576 	if (ret != 0U) {
577 		LOG_ERR("SD/MMC card reset failed");
578 		return ret;
579 	}
580 
581 	ret = sdhc_cdns_set_clk(&cdns_params);
582 	if (ret != 0U) {
583 		LOG_ERR("Host controller set clk failed");
584 		return ret;
585 	}
586 
587 	return 0;
588 }
589 
sdhc_cdns_send_cmd(struct sdmmc_cmd * cmd,struct sdhc_data * data)590 static int sdhc_cdns_send_cmd(struct sdmmc_cmd *cmd, struct sdhc_data *data)
591 {
592 	uint32_t op = 0;
593 	uint32_t value;
594 	uintptr_t base;
595 	int32_t timeout;
596 	uint32_t cmd_indx;
597 	uint32_t status_check = 0;
598 
599 	__ASSERT(cmd, "Assert %s function call", __func__);
600 	base = cdns_params.reg_base;
601 	cmd_indx = (cmd->cmd_idx) << CDNS_SRS03_COM_IDX;
602 
603 	if (data) {
604 		switch (cmd->cmd_idx) {
605 		case SD_SWITCH:
606 			op = CDNS_SRS03_DATA_PRSNT;
607 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS10, SRS10_VAL_SW);
608 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS11, SRS11_VAL_GEN);
609 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS15, SRS15_VAL_GEN);
610 			break;
611 
612 		case SD_WRITE_SINGLE_BLOCK:
613 		case SD_READ_SINGLE_BLOCK:
614 			op = CDNS_SRS03_DATA_PRSNT;
615 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS10, SRS10_VAL_READ);
616 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS11, SRS11_VAL_GEN);
617 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS15, SRS15_VAL_RD_WR);
618 			sys_write32(CDNS_SRS00_SAAR, cdns_params.reg_base + SDHC_CDNS_SRS00);
619 			break;
620 
621 		case SD_WRITE_MULTIPLE_BLOCK:
622 		case SD_READ_MULTIPLE_BLOCK:
623 			op = CDNS_SRS03_DATA_PRSNT | AUTO_CMD23 | CDNS_SRS03_MULTI_BLK_READ;
624 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS10, SRS10_VAL_READ);
625 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS11, SRS11_VAL_GEN);
626 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS15, SRS15_VAL_RD_WR);
627 			sys_write32(CDNS_SRS00_SAAR, cdns_params.reg_base + SDHC_CDNS_SRS00);
628 			break;
629 
630 		case SD_APP_SEND_SCR:
631 			op = CDNS_SRS03_DATA_PRSNT;
632 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS10, ADMA2_32);
633 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS11, SRS11_VAL_GEN);
634 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS15, SRS15_VAL_GEN);
635 			break;
636 
637 		default:
638 			op = 0;
639 			break;
640 		}
641 	} else {
642 		switch (cmd->cmd_idx) {
643 		case SD_GO_IDLE_STATE:
644 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS11, SRS11_VAL_CID);
645 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS15, CDNS_SRS15_HV4E);
646 			break;
647 
648 		case SD_ALL_SEND_CID:
649 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS11, SRS11_VAL_CID);
650 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS15, SRS15_VAL_CID);
651 			break;
652 
653 		case SD_SEND_IF_COND:
654 			op = CDNS_SRS03_CMD_IDX_CHK_EN;
655 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS11, SRS11_VAL_GEN);
656 			sys_set_bits(cdns_params.reg_base + SDHC_CDNS_SRS15, CDNS_SRS15_HV4E);
657 			break;
658 
659 		case SD_STOP_TRANSMISSION:
660 			op = CMD_STOP_ABORT_CMD;
661 			break;
662 
663 		case SD_SEND_STATUS:
664 			break;
665 
666 		case SD_SELECT_CARD:
667 			op = CDNS_SRS03_MULTI_BLK_READ;
668 			break;
669 
670 		default:
671 			op = 0;
672 			break;
673 		}
674 	}
675 
676 	switch (cmd->resp_type) {
677 	case SD_RSP_TYPE_NONE:
678 		op |= (CDNS_SRS03_CMD_READ | CDNS_SRS03_MULTI_BLK_READ |
679 			CDNS_SRS03_DMA_EN | CDNS_SRS03_BLK_CNT_EN);
680 		break;
681 
682 	case SD_RSP_TYPE_R2:
683 		op |= (CDNS_SRS03_CMD_READ | CDNS_SRS03_MULTI_BLK_READ |
684 			CDNS_SRS03_DMA_EN | CDNS_SRS03_BLK_CNT_EN |
685 			RES_TYPE_SEL_136 | CDNS_SRS03_RESP_CRCCE);
686 		break;
687 
688 	case SD_RSP_TYPE_R3:
689 		op |= (CDNS_SRS03_CMD_READ | CDNS_SRS03_MULTI_BLK_READ |
690 			CDNS_SRS03_DMA_EN | CDNS_SRS03_BLK_CNT_EN | RES_TYPE_SEL_48);
691 		break;
692 
693 	case SD_RSP_TYPE_R1:
694 		if ((cmd->cmd_idx == SD_WRITE_SINGLE_BLOCK) || (cmd->cmd_idx
695 			== SD_WRITE_MULTIPLE_BLOCK)) {
696 			op |= (CDNS_SRS03_DMA_EN | CDNS_SRS03_BLK_CNT_EN | RES_TYPE_SEL_48
697 			| CDNS_SRS03_RESP_CRCCE | CDNS_SRS03_CMD_IDX_CHK_EN);
698 		} else {
699 			op |= (CDNS_SRS03_DMA_EN | CDNS_SRS03_BLK_CNT_EN | CDNS_SRS03_CMD_READ
700 			| RES_TYPE_SEL_48 | CDNS_SRS03_RESP_CRCCE | CDNS_SRS03_CMD_IDX_CHK_EN);
701 		}
702 		break;
703 
704 	default:
705 		op |= (CDNS_SRS03_DMA_EN | CDNS_SRS03_BLK_CNT_EN | CDNS_SRS03_CMD_READ |
706 			CDNS_SRS03_MULTI_BLK_READ | RES_TYPE_SEL_48 | CDNS_SRS03_RESP_CRCCE |
707 			CDNS_SRS03_CMD_IDX_CHK_EN);
708 		break;
709 	}
710 
711 	timeout = CARD_REG_TIME_DELAY_US;
712 	if (!WAIT_FOR((sdhc_cdns_busy() == 0), timeout, k_msleep(1))) {
713 		k_panic();
714 	}
715 
716 	sys_write32(~0, cdns_params.reg_base + SDHC_CDNS_SRS12);
717 
718 	sys_write32(cmd->cmd_arg, cdns_params.reg_base + SDHC_CDNS_SRS02);
719 	sys_write32(RESET_SRS14, cdns_params.reg_base + SDHC_CDNS_SRS14);
720 	sys_write32(op | cmd_indx, cdns_params.reg_base + SDHC_CDNS_SRS03);
721 
722 	timeout = CARD_REG_TIME_DELAY_US;
723 	if (!WAIT_FOR(((((sys_read32(cdns_params.reg_base + SDHC_CDNS_SRS12)) &
724 			CDNS_SRS12_CC) == CDNS_SRS12_CC) | (((sys_read32(cdns_params.reg_base +
725 			SDHC_CDNS_SRS12)) & CDNS_SRS12_EINT) == CDNS_SRS12_EINT)),
726 			timeout, k_msleep(1))) {
727 		LOG_ERR("Response timeout SRS12");
728 		return -ETIMEDOUT;
729 	}
730 
731 	value = sys_read32(cdns_params.reg_base + SDHC_CDNS_SRS12);
732 	status_check = value & CDNS_SRS12_ERR_MASK;
733 	if (status_check != 0U) {
734 		LOG_ERR("SD host controller send command failed, SRS12 = %X", status_check);
735 		return -EIO;
736 	}
737 
738 	if ((op & RES_TYPE_SEL_48) || (op & RES_TYPE_SEL_136)) {
739 		cmd->resp_data[0] = sys_read32(cdns_params.reg_base + SDHC_CDNS_SRS04);
740 		if (op & RES_TYPE_SEL_136) {
741 			cmd->resp_data[1] = sys_read32(cdns_params.reg_base + SDHC_CDNS_SRS05);
742 			cmd->resp_data[2] = sys_read32(cdns_params.reg_base + SDHC_CDNS_SRS06);
743 			cmd->resp_data[3] = sys_read32(cdns_params.reg_base + SDHC_CDNS_SRS07);
744 
745 			/* 136-bit: RTS=01b, Response field R[127:8] - RESP3[23:0],
746 			 * RESP2[31:0], RESP1[31:0], RESP0[31:0]
747 			 * Subsystem expects 128 bits response but cadence SDHC sends
748 			 * 120 bits response from R[127:8]. Bits manupulation to address
749 			 * the correct responses for the 136 bit response type.
750 			 */
751 			cmd->resp_data[3] = ((cmd->resp_data[3] << 8) | ((cmd->resp_data[2] >> 24)
752 				& CDNS_CSD_BYTE_MASK));
753 			cmd->resp_data[2] = ((cmd->resp_data[2] << 8) | ((cmd->resp_data[1] >> 24)
754 				& CDNS_CSD_BYTE_MASK));
755 			cmd->resp_data[1] = ((cmd->resp_data[1] << 8) | ((cmd->resp_data[0] >> 24)
756 				& CDNS_CSD_BYTE_MASK));
757 			cmd->resp_data[0] = (cmd->resp_data[0] << 8);
758 		}
759 	}
760 
761 	return 0;
762 }
763 
764 static const struct sdhc_cdns_ops cdns_sdmmc_ops = {
765 	.init			= sdhc_cdns_init,
766 	.send_cmd		= sdhc_cdns_send_cmd,
767 	.card_present		= sdhc_cdns_card_present,
768 	.set_ios		= sdhc_cdns_set_ios,
769 	.prepare		= sdhc_cdns_prepare,
770 	.cache_invd		= sdhc_cdns_cache_invd,
771 	.busy			= sdhc_cdns_busy,
772 	.reset			= sdhc_cdns_reset,
773 };
774 
sdhc_cdns_sdmmc_init(struct sdhc_cdns_params * params,struct sdmmc_device_info * info,const struct sdhc_cdns_ops ** cb_sdmmc_ops)775 void sdhc_cdns_sdmmc_init(struct sdhc_cdns_params *params, struct sdmmc_device_info *info,
776 	const struct sdhc_cdns_ops  **cb_sdmmc_ops)
777 {
778 	__ASSERT_NO_MSG((params != NULL) &&
779 		((params->reg_base & MMC_BLOCK_MASK) == 0) &&
780 		((params->desc_size & MMC_BLOCK_MASK) == 0) &&
781 		((params->reg_phy & MMC_BLOCK_MASK) == 0) &&
782 		(params->desc_size > 0) &&
783 		(params->clk_rate > 0) &&
784 		((params->bus_width == MMC_BUS_WIDTH_1) ||
785 		(params->bus_width == MMC_BUS_WIDTH_4) ||
786 		(params->bus_width == MMC_BUS_WIDTH_8)));
787 
788 	memcpy(&cdns_params, params, sizeof(struct sdhc_cdns_params));
789 	cdns_params.cdn_sdmmc_dev_type = info->cdn_sdmmc_dev_type;
790 	*cb_sdmmc_ops = &cdns_sdmmc_ops;
791 
792 	cdns_sdhc_set_sdmmc_params(&sdhc_cdns_combo_phy_reg_info, &sdhc_cdns_sdmmc_reg_info);
793 }
794