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