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