1 #include "ab32vg1_hal.h"
2
3 #ifdef HAL_SD_MODULE_ENABLED
4
5 #define HAL_LOG(...) hal_printf(__VA_ARGS__)
6
7 /************************* LL ************************************/
8
9 #define CK8E BIT(11) //在命令/数据包后加上8CLK
10 #define CBUSY BIT(10) //Busy Check
11 #define CLRSP BIT(9) //17Byte Long Rsp
12 #define CRSP BIT(8) //Need Rsp
13
14 //0x40是CMD中的 01 开头。
15 #define RSP_NO (0x40 | CK8E)
16 #define RSP_1 (0x40 | CRSP | CK8E) //接收6BYTE
17 #define RSP_1B (0x40 | CBUSY | CRSP | CK8E) //接收6BYTE,并等待BUSY
18 #define RSP_2 (0x40 | CLRSP | CRSP | CK8E) //接收17BYTE
19 #define RSP_3 (0x40 | CRSP | CK8E) //接收6BYTE
20 #define RSP_6 (0x40 | CRSP | CK8E) //接收6BYTE
21 #define RSP_7 (0x40 | CRSP | CK8E) //接收6BYTE
22 #define REQ_MULTREAD (18 | 0x40 | CRSP) //多块读时,不需要增加8CLK。其实,多块读先KICK DATA,这个是无所谓的
23
24 #define RSP_BUSY_TIMEOUT 2400000 //大约2s
25 #define RSP_TIMEOUT 6000 //大约5ms
26
27 uint8_t sysclk_update_baud(uint8_t baud);
28
sdio_setbaud(hal_sfr_t sdiox,uint8_t baud)29 void sdio_setbaud(hal_sfr_t sdiox, uint8_t baud)
30 {
31 sdiox[SDxBAUD] = sysclk_update_baud(baud);
32 }
33
sdio_init(hal_sfr_t sdiox,sdio_init_t init)34 void sdio_init(hal_sfr_t sdiox, sdio_init_t init)
35 {
36 sdiox[SDxCON] = 0;
37
38 hal_udelay(20);
39 sdiox[SDxCON] |= BIT(0); /* SD control enable */
40 sdio_setbaud(sdiox, init->clock_div); /* Set clock */
41 if (init->clock_power_save == SDMMC_CLOCK_POWER_SAVE_DISABLE) {
42 sdiox[SDxCON] |= BIT(3); /* Keep clock output */
43 } else {
44 sdiox[SDxCON] &= ~BIT(3); /* Keep clock output */
45 }
46 sdiox[SDxCON] |= BIT(5); /* Data interrupt enable */
47
48 hal_mdelay(40);
49 }
50
51 /**
52 * @brief Check if SDIO command is finished.
53 *
54 * @param sdiox
55 * @return true is finished
56 * @return false
57 */
sdio_check_finish(hal_sfr_t sdiox)58 bool sdio_check_finish(hal_sfr_t sdiox)
59 {
60 if (sdiox[SDxCON] & BIT(12)) {
61 sdiox[SDxCPND] = BIT(12);
62 return true;
63 }
64 return false;
65 }
66
67 /**
68 * @brief Check if SDIO has a response.
69 *
70 * @param sdiox
71 * @return true Have a response.
72 * @return false No response.
73 */
sdio_check_rsp(hal_sfr_t sdiox)74 bool sdio_check_rsp(hal_sfr_t sdiox)
75 {
76 return !(sdiox[SDxCON] & BIT(15));
77 }
78
sdio_send_cmd(hal_sfr_t sdiox,uint32_t cmd,uint32_t arg,uint8_t * abend)79 bool sdio_send_cmd(hal_sfr_t sdiox, uint32_t cmd, uint32_t arg, uint8_t *abend)
80 {
81 uint32_t time_out = (cmd & CBUSY) ? RSP_BUSY_TIMEOUT : RSP_TIMEOUT;
82 sdiox[SDxARG3] = arg;
83 sdiox[SDxCMD] = cmd;
84
85 while (sdio_check_finish(sdiox) == false) {
86 if (--time_out == 0) {
87 HAL_LOG("cmd time out\n");
88 if (abend != HAL_NULL) {
89 *abend = 1;
90 }
91 return false;
92 }
93 }
94
95 return sdio_check_rsp(sdiox);
96 }
97
sdio_get_cmd_rsp(hal_sfr_t sdiox)98 uint8_t sdio_get_cmd_rsp(hal_sfr_t sdiox)
99 {
100 return sdiox[SDxCMD];
101 }
102
sdio_get_rsp(hal_sfr_t sdiox,uint32_t rsp_reg)103 uint32_t sdio_get_rsp(hal_sfr_t sdiox, uint32_t rsp_reg)
104 {
105 return sdiox[rsp_reg];
106 }
107
sdio_read_kick(hal_sfr_t sdiox,void * buf)108 void sdio_read_kick(hal_sfr_t sdiox, void* buf)
109 {
110 sdiox[SDxDMAADR] = DMA_ADR(buf);
111 sdiox[SDxDMACNT] = 512;
112 }
113
sdio_write_kick(hal_sfr_t sdiox,void * buf)114 void sdio_write_kick(hal_sfr_t sdiox, void* buf)
115 {
116 sdiox[SDxDMAADR] = DMA_ADR(buf);
117 sdiox[SDxDMACNT] = BIT(18) | BIT(17) | BIT(16) | 512;
118 }
119
sdio_isbusy(hal_sfr_t sdiox)120 bool sdio_isbusy(hal_sfr_t sdiox)
121 {
122 return false;
123 }
124
sdmmc_cmd_go_idle_state(sd_handle_t hsd)125 bool sdmmc_cmd_go_idle_state(sd_handle_t hsd)
126 {
127 return sdio_send_cmd(hsd->instance, 0 | RSP_NO, hsd->sdcard.rca, &(hsd->sdcard.abend));
128 }
129
sdmmc_cmd_send_if_cond(sd_handle_t hsd)130 bool sdmmc_cmd_send_if_cond(sd_handle_t hsd)
131 {
132 return sdio_send_cmd(hsd->instance, 8 | RSP_7, SDMMC_CHECK_PATTERM, &(hsd->sdcard.abend));
133 }
134
sdmmc_cmd_all_send_cid(sd_handle_t hsd)135 bool sdmmc_cmd_all_send_cid(sd_handle_t hsd)
136 {
137 return sdio_send_cmd(hsd->instance, 2 | RSP_2, 0, &(hsd->sdcard.abend));
138 }
139
sdmmc_cmd_set_rel_addr(sd_handle_t hsd)140 void sdmmc_cmd_set_rel_addr(sd_handle_t hsd)
141 {
142 hal_sfr_t sdiox = hsd->instance;
143
144 if (hsd->sdcard.type == CARD_MMC) {
145 hsd->sdcard.rca = 0x00010000;
146 sdio_send_cmd(sdiox, 3 | RSP_1, hsd->sdcard.rca, &(hsd->sdcard.abend));
147 } else {
148 sdio_send_cmd(sdiox, 3 | RSP_6, 0, &(hsd->sdcard.abend));
149 hsd->sdcard.rca = sdio_get_rsp(sdiox, SDxARG3) & 0xffff0000;
150 }
151 }
152
sdmmc_cmd_send_csd(sd_handle_t hsd)153 void sdmmc_cmd_send_csd(sd_handle_t hsd)
154 {
155 hal_sfr_t sdiox = hsd->instance;
156
157 sdio_send_cmd(sdiox, 9 | RSP_2, hsd->sdcard.rca, &(hsd->sdcard.abend));
158 if (hsd->sdcard.type == CARD_MMC) {
159 //
160 } else {
161 if (hsd->sdcard.flag_sdhc == 1) {
162 hsd->sdcard.capacity = (sdio_get_rsp(sdiox, SDxARG2) << 24) & 0x00ff0000; /* rspbuf[8] */
163 hsd->sdcard.capacity |= ((sdio_get_rsp(sdiox, SDxARG1) >> 16) & 0x0000ffff); /* rspbuf[9] rspbuf[10] */
164 hsd->sdcard.capacity += 1;
165 hsd->sdcard.capacity <<= 10;
166 }
167 }
168 HAL_LOG("sd capacity=%d\n", hsd->sdcard.capacity);
169 }
170
sdmmc_cmd_select_card(sd_handle_t hsd)171 void sdmmc_cmd_select_card(sd_handle_t hsd)
172 {
173 sdio_send_cmd(hsd->instance, 7 | RSP_1B, hsd->sdcard.rca, &(hsd->sdcard.abend));
174 }
175
sdmmc_cmd_read_multiblock(sd_handle_t hsd)176 bool sdmmc_cmd_read_multiblock(sd_handle_t hsd)
177 {
178 return sdio_send_cmd(hsd->instance, REQ_MULTREAD, hsd->sdcard.rca, &(hsd->sdcard.abend));
179 }
180
sdmmc_cmd_app(sd_handle_t hsd)181 bool sdmmc_cmd_app(sd_handle_t hsd)
182 {
183 return sdio_send_cmd(hsd->instance, 55 | RSP_1, hsd->sdcard.rca, &(hsd->sdcard.abend));
184 }
185
sdmmc_acmd_op_cond(sd_handle_t hsd,uint32_t voltage)186 bool sdmmc_acmd_op_cond(sd_handle_t hsd, uint32_t voltage)
187 {
188 /* SEND CMD55 APP_CMD with RCA */
189 if (sdmmc_cmd_app(hsd)) {
190 /* Send CMD41 */
191 if (sdio_send_cmd(hsd->instance, 41 | RSP_3, voltage, &(hsd->sdcard.abend))) {
192 return true;
193 }
194 }
195 return false;
196 }
197
198 /************************* HAL ************************************/
199
sd_type_identification(sd_handle_t hsd)200 static bool sd_type_identification(sd_handle_t hsd)
201 {
202 uint8_t retry = hsd->cfg.identification_retry;
203 while (retry-- > 0)
204 {
205 /* CMD0: GO_IDLE_STATE */
206 sdmmc_cmd_go_idle_state(hsd);
207
208 /* CMD8: SEND_IF_COND: Command available only on V2.0 cards */
209 if (sdmmc_cmd_send_if_cond(hsd)) {
210 if (sdio_get_cmd_rsp(hsd->instance) == 0x08) {
211 hsd->sdcard.type = CARD_V2;
212 HAL_LOG("SD 2.0\n");
213 return true;
214 }
215 continue;
216 }
217 if (sdmmc_acmd_op_cond(hsd, 0x00ff8000)) {
218 hsd->sdcard.type = CARD_V1;
219 HAL_LOG("SD 1.0\n");
220 return true;
221 }
222 hal_mdelay(20);
223 }
224 return false;
225 }
226
sd_go_ready_try(sd_handle_t hsd)227 static bool sd_go_ready_try(sd_handle_t hsd)
228 {
229 uint32_t tmp = 0;
230 switch (hsd->sdcard.type)
231 {
232 case CARD_V1:
233 sdmmc_acmd_op_cond(hsd, 0x00ff8000);
234 break;
235
236 case CARD_V2:
237 sdmmc_acmd_op_cond(hsd, 0x40ff8000);
238 break;
239 default:
240 break;
241 }
242
243 if (0 == (hsd->instance[SDxARG3] & BIT(31))) {
244 return false; // no ready
245 }
246
247 if ((hsd->sdcard.type == CARD_V2) && (hsd->instance[SDxARG3] & BIT(30))) {
248 HAL_LOG("SDHC\n");
249 hsd->sdcard.flag_sdhc = 1;
250 }
251
252 return true;
253 }
254
sd_go_ready(sd_handle_t hsd)255 static bool sd_go_ready(sd_handle_t hsd)
256 {
257 if (hsd->sdcard.type == CARD_INVAL) {
258 return false;
259 }
260
261 uint8_t retry = hsd->cfg.go_ready_retry;
262 while (retry-- > 0)
263 {
264 if (sd_go_ready_try(hsd) == true) {
265 return true;
266 }
267 hal_mdelay(20);
268 }
269
270 return false;
271 }
272
sd_poweron(sd_handle_t hsd)273 static bool sd_poweron(sd_handle_t hsd)
274 {
275 if (sd_type_identification(hsd) == false) {
276 HAL_LOG("card invalid\n");
277 return false;
278 }
279
280 if (sd_go_ready(hsd) == false) {
281 HAL_LOG("no ready\n");
282 return false;
283 }
284
285 return true;
286 }
287
sd_init_card(sd_handle_t hsd)288 static void sd_init_card(sd_handle_t hsd)
289 {
290 /* Send CMD2 ALL_SEND_CID */
291 sdmmc_cmd_all_send_cid(hsd);
292 /* Send CMD3 SET_REL_ADDR */
293 sdmmc_cmd_set_rel_addr(hsd);
294 /* Send CMD9 SEND_CSD */
295 sdmmc_cmd_send_csd(hsd);
296 /* Select the Card */
297 sdmmc_cmd_select_card(hsd);
298
299 hsd->init.clock_div = 3;
300 hsd->init.clock_power_save = SDMMC_CLOCK_POWER_SAVE_ENABLE;
301
302 sdio_init(hsd->instance, &(hsd->init));
303 }
304
sd_read_wait(sd_handle_t hsd)305 static bool sd_read_wait(sd_handle_t hsd)
306 {
307 bool ret = false;
308 hal_sfr_t sdiox = hsd->instance;
309
310
311
312 return ret;
313 }
314
sd_read_start(sd_handle_t hsd,void * buf,uint32_t lba)315 static void sd_read_start(sd_handle_t hsd, void *buf, uint32_t lba)
316 {
317 if (hsd->sdcard.rw_state == HAL_SD_RW_STATE_READ) {
318
319 } else {
320 if (hsd->sdcard.rw_state == HAL_SD_RW_STATE_WRITE) {
321
322 }
323 sdio_read_kick(hsd->instance, buf);
324 sdmmc_cmd_read_multiblock(hsd);
325 }
326
327 hsd->sdcard.rw_state = HAL_SD_RW_STATE_READ;
328 // hsd->sdcard.rw_lba
329 }
330
sd_read_try(sd_handle_t hsd,void * buf,uint32_t lba)331 static bool sd_read_try(sd_handle_t hsd, void *buf, uint32_t lba)
332 {
333 HAL_LOG("read: %08x\n", lba);
334
335 if (hsd->sdcard.capacity < lba) {
336 lba = hsd->sdcard.capacity - 1;
337 }
338 sd_read_start(hsd, buf, lba);
339 return 0;
340 }
341
hal_sd_initcard(sd_handle_t hsd)342 void hal_sd_initcard(sd_handle_t hsd)
343 {
344 hal_sfr_t sdiox = hsd->instance;
345
346 hsd->init.clock_div = 119; /* SD clk 240KHz when system clk is 48MHz */
347 hsd->init.clock_power_save = SDMMC_CLOCK_POWER_SAVE_DISABLE;
348
349 sdio_init(sdiox, &(hsd->init));
350 sd_poweron(hsd);
351 sd_init_card(hsd);
352 }
353
hal_sd_mspinit(sd_handle_t hsd)354 WEAK void hal_sd_mspinit(sd_handle_t hsd)
355 {
356 }
357
hal_sd_init(sd_handle_t hsd)358 hal_error_t hal_sd_init(sd_handle_t hsd)
359 {
360 if (hsd == HAL_NULL) {
361 return -HAL_ERROR;
362 }
363
364 hsd->cfg.go_ready_retry = 200;
365 hsd->cfg.identification_retry = 5;
366 hsd->cfg.rw_init_retry = 3;
367 hsd->cfg.rw_retry = 3;
368
369 hal_sd_mspinit(hsd);
370 hal_sd_initcard(hsd);
371
372 return -HAL_ERROR;
373 }
374
hal_sd_deinit(uint32_t sdx)375 void hal_sd_deinit(uint32_t sdx)
376 {
377 }
378
hal_sd_read(sd_handle_t hsd,void * buf,uint32_t lba)379 bool hal_sd_read(sd_handle_t hsd, void *buf, uint32_t lba)
380 {
381 uint8_t init_retry = hsd->cfg.rw_init_retry;
382
383 while (init_retry-- > 0)
384 {
385 uint8_t retry = hsd->cfg.rw_retry;
386 while (retry-- > 0)
387 {
388 if (sd_read_try(hsd, buf, lba)) {
389 return true;
390 }
391 }
392 hsd->sdcard.state = HAL_SD_STATE_INVAL;
393
394 hal_mdelay(20);
395 }
396
397 return false;
398 }
399
400 #endif
401