1 /*
2  * Copyright (c) 2006-2024, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024/04/05     flyingcys    first version
9  */
10 #include <rthw.h>
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <mmu.h>
14 #include <stdbool.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 
18 #include "board.h"
19 #include "cache.h"
20 
21 #define DBG_TAG     "drv.sdio"
22 #define DBG_LEVEL   DBG_INFO
23 #include <rtdbg.h>
24 
25 #include <drivers/dev_mmcsd_core.h>
26 #include <drivers/dev_sdio.h>
27 
28 #include "drv_sdhci.h"
29 
30 #define SDMMC_DMA_ALIGN_CACHE 64
31 
32 struct rthw_sdhci
33 {
34     struct rt_mmcsd_host *host;
35     rt_ubase_t base;
36     rt_uint32_t irq;
37     volatile rt_err_t cmd_error;
38     volatile rt_err_t data_error;
39     rt_uint32_t response_type;
40     volatile rt_uint32_t response[4];
41     char name[RT_NAME_MAX];
42     rt_sem_t sem_cmd;
43     rt_sem_t sem_data;
44 };
45 
sdhci_set_card_clock(rt_ubase_t base,uint32_t srcClock_Hz,uint32_t target_HZ)46 static uint32_t sdhci_set_card_clock(rt_ubase_t base, uint32_t srcClock_Hz, uint32_t target_HZ)
47 {
48     uintptr_t BASE = (uintptr_t)base;
49     uint32_t divider = 1U;
50     uint32_t i;
51 
52     RT_ASSERT(target_HZ > 0);
53 
54     if (srcClock_Hz <= target_HZ )
55     {
56         divider = 0;
57     }
58     else
59     {
60         for (divider = 0x1; divider < 0x3FF; divider++)
61         {
62             if(srcClock_Hz / (2*divider) <= target_HZ)
63                 break;
64         }
65 
66         if(divider == 0x3FF)
67         {
68             LOG_D("Warning: Can't set the freq to %d, divider is filled!!!", target_HZ);
69         }
70     }
71 
72     RT_ASSERT(divider <= 0x3FF);
73 
74     if (mmio_read_16(BASE + SDIF_HOST_CONTROL2) & 1<<15)
75     {
76         LOG_D("Use SDCLK Preset Value.");
77     }
78     else
79     {
80         mmio_write_16(BASE + SDIF_CLK_CTRL,
81                 mmio_read_16(BASE + SDIF_CLK_CTRL) & ~0x9); // disable INTERNAL_CLK_EN and PLL_ENABLE
82         mmio_write_16(BASE + SDIF_CLK_CTRL,
83                 (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x3F) | ((divider & 0xff) << 8) | ((divider & 0x300) >> 2)); // set clk div
84 
85         mmio_write_16(BASE + SDIF_CLK_CTRL,
86                 mmio_read_16(BASE + SDIF_CLK_CTRL) | 0x1); // set INTERNAL_CLK_EN
87 
88         for (i = 0; i <= 150000; i += 100)
89         {
90             if (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x2)
91             {
92                 break;
93             }
94 
95             rt_hw_us_delay(100);
96         }
97 
98         if (i > 150000)
99         {
100             LOG_D("SD INTERNAL_CLK_EN seting FAILED!");
101             RT_ASSERT(0);
102         }
103 
104         mmio_write_16(BASE + SDIF_CLK_CTRL,
105                 mmio_read_16(BASE + SDIF_CLK_CTRL) | 0x8); // set PLL_ENABLE
106 
107         for (i = 0; i <= 150000; i += 100)
108         {
109             if (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x2)
110             {
111                 return target_HZ;
112             }
113 
114             rt_hw_us_delay(100);
115         }
116     }
117 
118     LOG_E("SD PLL seting FAILED!\n");
119     return -1;
120 }
121 
SDIF_ChangeCardClock(rt_ubase_t base,uint32_t srcClock_Hz,uint32_t target_HZ)122 static uint32_t SDIF_ChangeCardClock(rt_ubase_t base, uint32_t srcClock_Hz, uint32_t target_HZ)
123 {
124     uintptr_t BASE = (uintptr_t)base;
125     uint32_t divider = 1U;
126     uint32_t i;
127 
128     if (target_HZ <= 0)
129     {
130         mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_32(BASE + SDIF_CLK_CTRL) & ~(0x1<<2)); // stop SD clock
131 //      mmio_write_16(BASE + 0x31e, 0x00);
132         return -1;
133     }
134 
135     if (srcClock_Hz <= target_HZ )
136     {
137         divider = 0;
138     }
139     else
140     {
141         for (divider = 0x1; divider < 0x3FF; divider++)
142         {
143             if(srcClock_Hz / (2*divider) <= target_HZ)
144                 break;
145         }
146 
147         if(divider == 0x3FF)
148         {
149             LOG_D("Warning: Can't set the freq to %d, divider is filled!!!", target_HZ);
150         }
151     }
152 
153     RT_ASSERT(divider <= 0x3FF);
154 
155     mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) & ~(0x1<<2)); // stop SD clock
156 
157 //  mmio_write_16(BASE + 0x31e, 0x10);
158     mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) & ~0x8); // disable  PLL_ENABLE
159 
160     if (mmio_read_16(BASE + SDIF_HOST_CONTROL2) & 1<<15)
161     {
162         LOG_D("Use SDCLK Preset Value.");
163         // 4 need recheck?
164         mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) & ~0x7); // clr UHS_MODE_SEL
165     }
166     else
167     {
168         mmio_write_16(BASE + SDIF_CLK_CTRL, (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x3F) | ((divider & 0xff) << 8) | ((divider & 0x300) >> 2)); // set clk div
169         mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) & ~(0x1 << 5)); // CLK_GEN_SELECT
170     }
171 
172     mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) | 0xc); // enable  PLL_ENABLE
173 
174     //LOG_D("mmio_read_16(BASE + SDIF_CLK_CTRL) = 0x%x", mmio_read_16(BASE + SDIF_CLK_CTRL));
175 
176     for (i = 0; i <= 150000; i += 100)
177     {
178         if (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x2)
179         {
180             return target_HZ;
181         }
182 
183         rt_hw_us_delay(100);
184     }
185 
186     LOG_E("SD PLL seting FAILED!\n");
187 
188     return -1;
189 }
190 
sdhci_wait_cmd_complete(struct rthw_sdhci * sdhci)191 static void sdhci_wait_cmd_complete(struct rthw_sdhci *sdhci)
192 {
193     rt_err_t ret = RT_EOK;
194     rt_uint32_t intmask;
195     uintptr_t BASE = (uintptr_t)sdhci->base;
196 
197     ret = rt_sem_take(sdhci->sem_cmd, rt_tick_from_millisecond(3000));
198     if (ret != RT_EOK)
199     {
200         LOG_E("wait cmd complete timeout ...");
201         sdhci->cmd_error = -RT_ETIMEOUT;
202         return;
203     }
204 }
205 
sdhci_wait_data_complete(struct rthw_sdhci * sdhci)206 static void sdhci_wait_data_complete(struct rthw_sdhci *sdhci)
207 {
208     rt_err_t ret = RT_EOK;
209     rt_uint32_t intmask;
210     uintptr_t BASE = (uintptr_t)sdhci->base;
211 
212     ret = rt_sem_take(sdhci->sem_data, rt_tick_from_millisecond(3000));
213     if (ret != RT_EOK)
214     {
215         LOG_E("wait data complete timeout ...");
216         sdhci->data_error = -RT_ETIMEOUT;
217         return;
218     }
219 }
220 
sdhci_prepare_data(struct rthw_sdhci * sdhci,struct rt_mmcsd_cmd * cmd,struct rt_mmcsd_data * data,rt_ubase_t start_addr,rt_uint32_t load_len)221 static uint32_t sdhci_prepare_data(struct rthw_sdhci *sdhci, struct rt_mmcsd_cmd *cmd, struct rt_mmcsd_data *data, rt_ubase_t start_addr, rt_uint32_t load_len)
222 {
223     uintptr_t BASE = (uintptr_t)sdhci->base;
224 
225     uint32_t block_cnt, blksz;
226     uint8_t tmp;
227     rt_ubase_t dma_addr;
228 
229     blksz = data->blksize;
230     block_cnt = data->blks;
231 
232     rt_hw_cpu_dcache_clean((void *)start_addr, load_len);
233 #ifdef RT_USING_SMART
234         dma_addr = (rt_ubase_t)rt_kmem_v2p((void *)start_addr);
235 #else
236         dma_addr = start_addr;
237 #endif
238 
239     mmio_write_32(BASE + SDIF_ADMA_SA_LOW, dma_addr);
240     mmio_write_32(BASE + SDIF_ADMA_SA_HIGH, (dma_addr >> 32));
241 
242     mmio_write_32(BASE + SDIF_DMA_ADDRESS, block_cnt);
243     mmio_write_16(BASE + SDIF_BLOCK_COUNT, 0);
244 
245     mmio_write_16(BASE + SDIF_BLOCK_SIZE, SDIF_MAKE_BLKSZ(7, blksz));
246 
247     // select SDMA
248     tmp = mmio_read_8(BASE + SDIF_HOST_CONTROL);
249     tmp &= ~SDIF_CTRL_DMA_MASK;
250     tmp |= SDIF_CTRL_SDMA;
251 
252     mmio_write_8(BASE + SDIF_HOST_CONTROL, tmp);
253 
254     return 0;
255 }
256 
align_alloc(uint64_t align,uint32_t size,void ** mem_unalign)257 static inline void *align_alloc(uint64_t align, uint32_t size, void **mem_unalign)
258 {
259     void *mem;
260     uint64_t offset;
261     size+=2*align;
262 
263     *mem_unalign = (void *)rt_malloc(size);
264 
265     if (!*mem_unalign)
266     {
267         LOG_E("sdio memalign error!\n");
268         return NULL;
269     }
270 
271     offset = (uint64_t)*mem_unalign % align;
272 
273     if (offset == 0)
274         mem = (void *)*mem_unalign;
275     else
276         mem = (void *)(*mem_unalign + (align - offset));
277 
278     return mem;
279 }
280 
sdhci_send_data_cmd(struct rthw_sdhci * sdhci,struct rt_mmcsd_cmd * cmd,struct rt_mmcsd_data * data)281 static rt_err_t sdhci_send_data_cmd(struct rthw_sdhci *sdhci, struct rt_mmcsd_cmd *cmd, struct rt_mmcsd_data *data)
282 {
283     uintptr_t BASE = (uintptr_t)sdhci->base;
284     uint32_t mode = 0;
285     uint32_t flags = 0;
286     int end_time = 0;
287     int start_time = rt_tick_get_millisecond();
288     sdhci_dma_config_t dma_config;
289 
290     while(1)
291     {
292         if (!(mmio_read_32(BASE + SDIF_PRESENT_STATE) & SDIF_CMD_INHIBIT))
293             break;
294         end_time = rt_tick_get_millisecond();
295         if (end_time - start_time >= 2000)
296             return -RT_ETIMEOUT;
297     }
298 
299     rt_ubase_t start_addr;
300     void *src_unalign = NULL;
301 
302     if (data)
303     {
304         dma_config.dma_des_buffer_len = data->blksize * data->blks;
305         if (data->flags & DATA_DIR_READ)
306         {
307             if ((uint64_t)data->buf & (SDMMC_DMA_ALIGN_CACHE - 1))
308             {
309                 start_addr = (rt_ubase_t)align_alloc(SDMMC_DMA_ALIGN_CACHE, dma_config.dma_des_buffer_len, (void **)&src_unalign);
310             }
311             else
312             {
313                 start_addr = (rt_ubase_t)data->buf;
314             }
315         }
316         else
317         {
318             start_addr = (rt_ubase_t)data->buf;
319         }
320 
321         sdhci_prepare_data(sdhci, cmd, data, start_addr, dma_config.dma_des_buffer_len);
322 
323         mode = SDIF_TRNS_DMA;
324         if (mmc_op_multi(cmd->cmd_code) || data->blks > 1)
325             mode |= SDIF_TRNS_MULTI | SDIF_TRNS_BLK_CNT_EN;
326 
327         if (data->flags & DATA_DIR_READ)
328             mode |= SDIF_TRNS_READ;
329         else
330             mode &= ~SDIF_TRNS_READ;
331 
332         mmio_write_16(BASE + SDIF_TRANSFER_MODE, mode);
333     }
334 
335     // set cmd flags
336     if (resp_type(cmd) == RESP_NONE)
337             flags |= SDIF_CMD_RESP_NONE;
338     else if (resp_type(cmd) == RESP_R2)
339         flags |= SDIF_CMD_RESP_LONG;
340     else if (resp_type(cmd) == RESP_R1B)
341         flags |= SDIF_CMD_RESP_SHORT_BUSY;
342    else
343         flags |= SDIF_CMD_RESP_SHORT;
344 
345     if (data)
346     {
347         flags |= SDIF_CMD_CRC;
348         flags |= SDIF_CMD_INDEX;
349         flags |= SDIF_CMD_DATA;
350     }
351 
352     mmio_write_32(BASE + SDIF_ARGUMENT, cmd->arg);
353     // issue the cmd
354     mmio_write_16(BASE + SDIF_COMMAND, SDIF_MAKE_CMD(cmd->cmd_code, flags));
355 
356     sdhci_wait_cmd_complete(sdhci);
357     if (sdhci->cmd_error != RT_EOK)
358     {
359         LOG_E("cmd error: %d\n", sdhci->cmd_error);
360         return sdhci->cmd_error;
361     }
362 
363     memcpy((void *)cmd->resp, (void *)sdhci->response, sizeof(sdhci->response));
364 
365     if (data)
366     {
367         sdhci_wait_data_complete(sdhci);
368         if (sdhci->data_error != RT_EOK)
369         {
370             LOG_E("sdio data error!\n");
371             return sdhci->data_error;
372         }
373 
374         if (data->flags & DATA_DIR_READ)
375         {
376             rt_hw_cpu_dcache_invalidate((void *)start_addr, dma_config.dma_des_buffer_len);
377             if (src_unalign)
378             {
379                 memcpy((void *)data->buf, (void *)start_addr, dma_config.dma_des_buffer_len);
380                 rt_free(src_unalign);
381                 src_unalign = NULL;
382             }
383         }
384     }
385 
386     return RT_EOK;
387 }
388 
sdhci_cmd_irq(struct rthw_sdhci * sdhci,uint32_t intmask)389 static void sdhci_cmd_irq(struct rthw_sdhci *sdhci, uint32_t intmask)
390 {
391     int i;
392     uintptr_t BASE = (uintptr_t)sdhci->base;
393 
394     if (intmask & (SDIF_INT_TIMEOUT | SDIF_INT_CRC |
395                SDIF_INT_END_BIT | SDIF_INT_INDEX))
396     {
397         if (intmask & SDIF_INT_TIMEOUT)
398         {
399             sdhci->cmd_error = -RT_ETIMEOUT;
400             LOG_E("SDIF_INT_TIMEOUT");
401         }
402 
403         return;
404     }
405 
406     if (intmask & SDIF_INT_RESPONSE)
407     {
408         if (sdhci->response_type == RESP_R2)
409         {
410             /* CRC is stripped so we need to do some shifting. */
411             for (i = 0; i < 4; i++) {
412                 sdhci->response[i] = mmio_read_32(BASE + SDIF_RESPONSE_01 + (3-i)*4) << 8;
413                 if (i != 3)
414                     sdhci->response[i] |= mmio_read_8(BASE + SDIF_RESPONSE_01 + (3-i)*4-1);
415             }
416             LOG_D("sdhci->response: [%08x %08x %08x %08x]", sdhci->response[0], sdhci->response[1], sdhci->response[2], sdhci->response[3]);
417         }
418         else
419         {
420             sdhci->response[0] = mmio_read_32(BASE + SDIF_RESPONSE_01);
421             LOG_D("sdhci->response: [%08x]", sdhci->response[0]);
422         }
423 
424         rt_sem_release(sdhci->sem_cmd);
425     }
426 }
427 
sdhci_data_irq(struct rthw_sdhci * sdhci,uint32_t intmask)428 static void sdhci_data_irq(struct rthw_sdhci *sdhci, uint32_t intmask)
429 {
430     uintptr_t BASE = (uintptr_t)sdhci->base;
431     uint32_t command;
432 
433     /* CMD19 generates _only_ Buffer Read Ready interrupt */
434     if (intmask & SDIF_INT_DATA_AVAIL)
435     {
436         command = SDIF_GET_CMD(mmio_read_16(BASE + SDIF_COMMAND));
437         if (command == MMC_CMD19 ||
438             command == MMC_CMD21) {
439             //host->tuning_done = 1;
440             return;
441         }
442     }
443 
444     if ((intmask & SDIF_INT_DATA_TIMEOUT) || (intmask & SDIF_INT_DATA_END_BIT) || (intmask & SDIF_INT_DATA_CRC) || (intmask & SDIF_INT_ADMA_ERROR))
445     {
446         sdhci->data_error = -RT_ERROR;
447         return;
448     }
449 
450     if (intmask & SDIF_INT_DATA_END)
451     {
452         sdhci->data_error = RT_EOK;
453         return;
454     }
455 
456     if (intmask & SDIF_INT_DMA_END)
457     {
458         uint64_t dma_addr;
459         dma_addr = mmio_read_32(BASE + SDIF_ADMA_SA_LOW);
460         mmio_write_32(BASE + SDIF_ADMA_SA_LOW, dma_addr);
461         mmio_write_32(BASE + SDIF_ADMA_SA_HIGH, 0);
462     }
463 
464     return;
465 }
466 
sdhci_transfer_handle_irq(int irqno,void * param)467 static void sdhci_transfer_handle_irq(int irqno, void *param)
468 {
469     struct rthw_sdhci *sdhci = (struct rthw_sdhci *)param;
470     uintptr_t BASE = (uintptr_t)sdhci->base;
471     int max_loop = 16;
472     uint32_t intmask;
473     uint32_t mask;
474     uint32_t unexpected;
475 
476     intmask = mmio_read_32(BASE + SDIF_INT_STATUS);
477 
478     if (!intmask || intmask == 0xffffffff)
479     {
480         LOG_E("never be here!\n");
481         return;
482     }
483 
484     do
485     {
486         mask = intmask & (SDIF_INT_CMD_MASK | SDIF_INT_DATA_MASK | SDIF_INT_BUS_POWER);
487         mmio_write_32(BASE + SDIF_INT_STATUS, mask);
488 
489         if (intmask & SDIF_INT_CMD_MASK)
490         {
491             sdhci_cmd_irq(sdhci, intmask & SDIF_INT_CMD_MASK);
492         }
493 
494         if (intmask & SDIF_INT_DMA_END)
495         {
496             uint64_t dma_addr;
497             dma_addr = mmio_read_32(BASE + SDIF_ADMA_SA_LOW);
498             mmio_write_32(BASE + SDIF_ADMA_SA_LOW, dma_addr);
499             mmio_write_32(BASE + SDIF_ADMA_SA_HIGH, 0);
500             return;
501         }
502 
503         if (intmask & SDIF_INT_DATA_MASK)
504         {
505             sdhci_data_irq(sdhci, intmask & SDIF_INT_DATA_MASK);
506             rt_sem_release(sdhci->sem_data);
507         }
508 
509         if (intmask & SDIF_INT_CARD_INT)
510         {
511             LOG_D("init_card_init");
512         }
513 
514         intmask &= ~(SDIF_INT_CARD_INSERT | SDIF_INT_CARD_REMOVE |
515                 SDIF_INT_CMD_MASK | SDIF_INT_DATA_MASK |
516                 SDIF_INT_ERROR | SDIF_INT_BUS_POWER |
517                 SDIF_INT_RETUNE | SDIF_INT_CARD_INT);
518 
519         if (intmask)
520         {
521             unexpected = intmask;
522             mmio_write_32(BASE + SDIF_INT_STATUS, intmask);
523             LOG_D("unexpected interrupt: 0x%08x.", unexpected);
524         }
525 
526         intmask = mmio_read_32(BASE + SDIF_INT_STATUS);
527     } while (intmask && --max_loop);
528 }
529 
sdhci_set_clock(rt_ubase_t base,uint32_t target_hz)530 static uint32_t sdhci_set_clock(rt_ubase_t base, uint32_t target_hz)
531 {
532     uint32_t source_clock_hz;
533     uint32_t ret;
534 
535     source_clock_hz = 375 * 1000 * 1000;
536     if (target_hz <= 400000)
537         ret = sdhci_set_card_clock(base, source_clock_hz, target_hz);
538     else
539         ret = SDIF_ChangeCardClock(base, source_clock_hz, target_hz);
540 
541     return ret;
542 }
543 
sdhci_set_bus_width(rt_ubase_t base,uint8_t bus_width)544 static void sdhci_set_bus_width(rt_ubase_t base, uint8_t bus_width)
545 {
546     uintptr_t BASE = (uintptr_t)base;
547     uint32_t ctrl;
548     uint16_t ctrl_2;
549 
550     ctrl = mmio_read_8(BASE + SDIF_HOST_CONTROL);
551     if (bus_width == MMCSD_BUS_WIDTH_1)
552         ctrl &= ~SDIF_DAT_XFER_WIDTH;
553     else if (bus_width == MMCSD_BUS_WIDTH_4)
554         ctrl |= SDIF_DAT_XFER_WIDTH;
555     ctrl |= SDIF_CTRL_HISPD;
556 
557     ctrl_2 = mmio_read_16(BASE + SDIF_HOST_CONTROL2);
558     ctrl_2 &= ~SDIF_CTRL_UHS_MASK;
559     ctrl_2 |= SDIF_CTRL_UHS_SDR25;
560     mmio_write_16(BASE + SDIF_HOST_CONTROL2, ctrl_2);
561 
562     rt_thread_mdelay(1);
563 
564     mmio_write_8(BASE + SDIF_HOST_CONTROL, ctrl);
565 }
566 
sdhci_enable_card_power(rt_ubase_t base,bool enable)567 static void sdhci_enable_card_power(rt_ubase_t base, bool enable)
568 {
569     uintptr_t BASE = (uintptr_t)base;
570 
571     if (enable)
572     {
573         mmio_write_8(BASE + SDIF_PWR_CONTROL,mmio_read_8(BASE + SDIF_PWR_CONTROL) | 0x1);
574     }
575     else
576     {
577         mmio_write_8(BASE + SDIF_PWR_CONTROL,mmio_read_8(BASE+ SDIF_PWR_CONTROL) & ~0x1);
578     }
579 }
580 
sdhci_detect_card_insert(rt_ubase_t base,bool data3)581 static uint32_t sdhci_detect_card_insert(rt_ubase_t base, bool data3)
582 {
583     uintptr_t BASE = (uintptr_t)base;
584     if (data3)
585     {
586         return (mmio_read_32(BASE+SDIF_PRESENT_STATE) & SDIF_CARD_STABLE) == SDIF_CARD_STABLE ? 0U : 1U;
587     }
588     else
589     {
590         return (mmio_read_32(BASE+SDIF_PRESENT_STATE) & SDIF_CARD_INSERTED) == SDIF_CARD_INSERTED ? 1U : 0U;
591     }
592 }
593 
sdhci_enable_card_clock(rt_ubase_t base,bool enable)594 static void sdhci_enable_card_clock(rt_ubase_t base, bool enable)
595 {
596     uintptr_t BASE = (uintptr_t)base;
597     if (enable)
598     {
599          mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_32(BASE + SDIF_CLK_CTRL) | (0x1<<2)); // stop SD clock
600     }
601     else
602     {
603         mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_32(BASE + SDIF_CLK_CTRL) & ~(0x1<<2)); // stop SD clock
604     }
605 }
606 
sdhci_hw_reset(rt_ubase_t base)607 static void sdhci_hw_reset(rt_ubase_t base)
608 {
609     uintptr_t BASE = (uintptr_t)base;
610 
611     mmio_write_16(BASE + SDIF_CLK_CTRL, (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x3F) | DEFAULT_DIV_SD_INIT_CLOCK << 8);
612 
613     rt_thread_mdelay(1);
614 
615     mmio_write_8(BASE + SDIF_SOFTWARE_RESET, 0x7);
616     while (mmio_read_8(BASE + SDIF_SOFTWARE_RESET));
617 }
618 
619 #define REG_TOP_SD_PWRSW_CTRL       (0x1F4)
620 
sdhci_pad_setting(rt_ubase_t base)621 static void sdhci_pad_setting(rt_ubase_t base)
622 {
623     uintptr_t BASE = (uintptr_t)base;
624 
625     if (BASE == (rt_ubase_t)SDIO0_BASE)
626     {
627         //set power for sd0
628         mmio_write_32(TOP_BASE + REG_TOP_SD_PWRSW_CTRL, 0x9);
629         rt_thread_mdelay(1);
630 
631         //set pu/down
632         mmio_write_32(REG_SDIO0_CD_PAD_REG, (mmio_read_32(REG_SDIO0_CD_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_CD_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
633         mmio_write_32(REG_SDIO0_PWR_EN_PAD_REG, (mmio_read_32(REG_SDIO0_PWR_EN_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_PWR_EN_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
634         mmio_write_32(REG_SDIO0_CLK_PAD_REG, (mmio_read_32(REG_SDIO0_CLK_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_CLK_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
635         mmio_write_32(REG_SDIO0_CMD_PAD_REG, (mmio_read_32(REG_SDIO0_CMD_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_CMD_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
636         mmio_write_32(REG_SDIO0_DAT1_PAD_REG, (mmio_read_32(REG_SDIO0_DAT1_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_DAT1_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
637         mmio_write_32(REG_SDIO0_DAT0_PAD_REG, (mmio_read_32(REG_SDIO0_DAT0_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_DAT0_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
638         mmio_write_32(REG_SDIO0_DAT2_PAD_REG, (mmio_read_32(REG_SDIO0_DAT2_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_DAT2_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
639         mmio_write_32(REG_SDIO0_DAT3_PAD_REG, (mmio_read_32(REG_SDIO0_DAT3_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_DAT3_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
640 
641         //set pinmux
642         mmio_write_8(REG_SDIO0_CD_PIO_REG, REG_SDIO0_CD_PIO_VALUE);
643         mmio_write_8(REG_SDIO0_PWR_EN_PIO_REG, REG_SDIO0_PWR_EN_PIO_VALUE);
644         mmio_write_8(REG_SDIO0_CLK_PIO_REG, REG_SDIO0_CLK_PIO_VALUE);
645         mmio_write_8(REG_SDIO0_CMD_PIO_REG, REG_SDIO0_CMD_PIO_VALUE);
646         mmio_write_8(REG_SDIO0_DAT0_PIO_REG, REG_SDIO0_DAT0_PIO_VALUE);
647         mmio_write_8(REG_SDIO0_DAT1_PIO_REG, REG_SDIO0_DAT1_PIO_VALUE);
648         mmio_write_8(REG_SDIO0_DAT2_PIO_REG, REG_SDIO0_DAT2_PIO_VALUE);
649         mmio_write_8(REG_SDIO0_DAT3_PIO_REG, REG_SDIO0_DAT3_PIO_VALUE);
650     }
651     else if(BASE == (rt_ubase_t)SDIO1_BASE)
652     {
653         // set rtc sdio1 related register
654         mmio_write_32(RTCSYS_CTRL, 0x1);
655         mmio_write_32(RTCSYS_CLKMUX, 0x10);
656         mmio_write_32(RTCSYS_CLKBYP, 0xfffffffc);
657         //mmio_write_32(RTCSYS_MCU51_ICTRL1, 0x0);
658 
659         mmio_write_32(REG_SDIO1_CLK_PAD_REG, (mmio_read_32(REG_SDIO1_CLK_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_CLK_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
660         mmio_write_32(REG_SDIO1_CMD_PAD_REG, (mmio_read_32(REG_SDIO1_CMD_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_CMD_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
661         mmio_write_32(REG_SDIO1_DAT1_PAD_REG, (mmio_read_32(REG_SDIO1_DAT1_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_DAT1_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
662         mmio_write_32(REG_SDIO1_DAT0_PAD_REG, (mmio_read_32(REG_SDIO1_DAT0_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_DAT0_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
663         mmio_write_32(REG_SDIO1_DAT2_PAD_REG, (mmio_read_32(REG_SDIO1_DAT2_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_DAT2_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
664         mmio_write_32(REG_SDIO1_DAT3_PAD_REG, (mmio_read_32(REG_SDIO1_DAT3_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_DAT3_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
665         mmio_write_32(RTCSYS_CTRL, 0x1);                                    // enable rtc2ap_ahb;
666 
667         //set pinmux
668         mmio_write_32(TOP_BASE + 0x294, (mmio_read_32(TOP_BASE + 0x294) & 0xFFFFFBFF));
669         mmio_write_8(REG_SDIO1_CLK_PIO_REG, REG_SDIO1_CLK_PIO_VALUE);
670         mmio_write_8(REG_SDIO1_CMD_PIO_REG, REG_SDIO1_CMD_PIO_VALUE);
671         mmio_write_8(REG_SDIO1_DAT0_PIO_REG, REG_SDIO1_DAT0_PIO_VALUE);
672         mmio_write_8(REG_SDIO1_DAT1_PIO_REG, REG_SDIO1_DAT1_PIO_VALUE);
673         mmio_write_8(REG_SDIO1_DAT2_PIO_REG, REG_SDIO1_DAT2_PIO_VALUE);
674         mmio_write_8(REG_SDIO1_DAT3_PIO_REG, REG_SDIO1_DAT3_PIO_VALUE);
675     }
676     else if(BASE == (rt_ubase_t)SDIO2_BASE)
677     {
678         //set pu/down
679         mmio_write_32(REG_SDIO2_RSTN_PAD_REG, (mmio_read_32(REG_SDIO2_RSTN_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_RSTN_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
680         mmio_write_32(REG_SDIO2_CLK_PAD_REG, (mmio_read_32(REG_SDIO2_CLK_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_CLK_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
681         mmio_write_32(REG_SDIO2_CMD_PAD_REG, (mmio_read_32(REG_SDIO2_CMD_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_CMD_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
682         mmio_write_32(REG_SDIO2_DAT0_PAD_REG, (mmio_read_32(REG_SDIO2_DAT0_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_DAT0_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
683         mmio_write_32(REG_SDIO2_DAT1_PAD_REG, (mmio_read_32(REG_SDIO2_DAT1_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_DAT1_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
684         mmio_write_32(REG_SDIO2_DAT2_PAD_REG, (mmio_read_32(REG_SDIO2_DAT2_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_DAT2_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
685         mmio_write_32(REG_SDIO2_DAT3_PAD_REG, (mmio_read_32(REG_SDIO2_DAT3_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_DAT3_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
686 
687         //set pinmux
688         mmio_write_8(REG_SDIO2_RSTN_PIO_REG, REG_SDIO2_RSTN_PIO_VALUE);
689         mmio_write_8(REG_SDIO2_CLK_PIO_REG, REG_SDIO2_CLK_PIO_VALUE);
690         mmio_write_8(REG_SDIO2_CMD_PIO_REG, REG_SDIO2_CMD_PIO_VALUE);
691         mmio_write_8(REG_SDIO2_DAT0_PIO_REG, REG_SDIO2_DAT0_PIO_VALUE);
692         mmio_write_8(REG_SDIO2_DAT1_PIO_REG, REG_SDIO2_DAT1_PIO_VALUE);
693         mmio_write_8(REG_SDIO2_DAT2_PIO_REG, REG_SDIO2_DAT2_PIO_VALUE);
694         mmio_write_8(REG_SDIO2_DAT3_PIO_REG, REG_SDIO2_DAT3_PIO_VALUE);
695     }
696 }
697 
sdhci_phy_init(rt_ubase_t base)698 static void sdhci_phy_init(rt_ubase_t base)
699 {
700     uintptr_t BASE = (uintptr_t)base;
701 
702     uintptr_t vendor_base = BASE + (mmio_read_16(BASE + P_VENDOR_SPECIFIC_AREA) & ((1<<12)-1));
703 
704     sdhci_hw_reset(base);
705 
706     rt_thread_mdelay(3);
707 
708     sdhci_pad_setting(base);
709 
710     if (BASE == (rt_ubase_t)SDIO2_BASE)
711     {
712         //reg_0x200[0] = 1 for sd2
713         mmio_write_32(vendor_base, mmio_read_32(vendor_base) | BIT(0));
714     }
715 
716     //reg_0x200[1] = 1
717     mmio_write_32(vendor_base, mmio_read_32(vendor_base) | BIT(1));
718 
719     if (BASE == (rt_ubase_t)SDIO1_BASE)
720     {
721         //reg_0x200[16] = 1 for sd1
722         mmio_write_32(vendor_base, mmio_read_32(vendor_base) | BIT(16));
723     }
724 
725     mmio_write_32(vendor_base + SDIF_PHY_CONFIG, mmio_read_32(vendor_base + SDIF_PHY_CONFIG) | BIT(0));
726 
727     mmio_write_32(vendor_base + SDIF_PHY_TX_RX_DLY, 0x1000100);
728 }
729 
sdhci_init(rt_ubase_t base)730 static void sdhci_init(rt_ubase_t base)
731 {
732     uintptr_t BASE = (uintptr_t)base;
733 
734     mmio_write_8(BASE + SDIF_SOFTWARE_RESET, 0x6);
735 
736     mmio_write_8(BASE + SDIF_PWR_CONTROL, (0x7 << 1));
737     mmio_write_8(BASE + SDIF_TOUT_CTRL, 0xe);
738     mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) | 1<<11);
739     mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) & ~(0x1 << 5));
740     mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) | SDIF_HOST_VER4_ENABLE);
741 
742     mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) | 0x1<<13);
743 
744     if (mmio_read_32(BASE + SDIF_CAPABILITIES1) & (0x1<<29))
745     {
746         mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) | (0x1<<14)); // enable async int
747     }
748 
749     rt_thread_mdelay(20);
750 
751     mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) & ~(0x1<<8)); // clr UHS2_IF_ENABLE
752     mmio_write_8(BASE + SDIF_PWR_CONTROL, mmio_read_8(BASE + SDIF_PWR_CONTROL) | 0x1); // set SD_BUS_PWR_VDD1
753     mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) & ~0x7); // clr UHS_MODE_SEL
754 
755     rt_thread_mdelay(50);
756 
757     mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) | (0x1<<2)); // supply SD clock
758 
759     rt_hw_us_delay(400); // wait for voltage ramp up time at least 74 cycle, 400us is 80 cycles for 200Khz
760 
761     mmio_write_16(BASE + SDIF_INT_STATUS, mmio_read_16(BASE + SDIF_INT_STATUS) | (0x1 << 6));
762 
763     mmio_write_16(BASE + SDIF_INT_STATUS_EN, mmio_read_16(BASE + SDIF_INT_STATUS_EN) | 0xFFFF);
764     mmio_write_16(BASE + SDIF_ERR_INT_STATUS_EN, mmio_read_16(BASE + SDIF_ERR_INT_STATUS_EN) | 0xFFFF);
765 
766 }
767 
rthw_sdhci_set_config(struct rthw_sdhci * sdhci)768 void rthw_sdhci_set_config(struct rthw_sdhci *sdhci)
769 {
770     uint32_t pio_irqs = SDIF_INT_DATA_AVAIL | SDIF_INT_SPACE_AVAIL;
771     uint32_t dma_irqs = SDIF_INT_DMA_END | SDIF_INT_ADMA_ERROR;
772     uint32_t int_status;
773     uintptr_t BASE = (uintptr_t)sdhci->base;
774 
775     static bool sd0_clock_state = false;
776     static bool sd1_clock_state = false;
777     static bool sd2_clock_state = false;
778 
779     if (BASE == (rt_ubase_t)SDIO0_BASE)
780     {
781         LOG_D("MMC_FLAG_SDCARD.");
782         if (sd0_clock_state == false)
783         {
784             mmio_write_32(MMC_SDIO0_PLL_REGISTER, MMC_MAX_CLOCK_DIV_VALUE);
785             mmio_clrbits_32(CLOCK_BYPASS_SELECT_REGISTER, BIT(6));
786             sd0_clock_state = true;
787         }
788     }
789     else if (BASE == (rt_ubase_t)SDIO1_BASE)
790     {
791         LOG_D("MMC_FLAG_SDIO.");
792         if (sd1_clock_state == false)
793         {
794             mmio_write_32(MMC_SDIO1_PLL_REGISTER, MMC_MAX_CLOCK_DIV_VALUE);
795             mmio_clrbits_32(CLOCK_BYPASS_SELECT_REGISTER, BIT(7));
796             sd1_clock_state = true;
797         }
798     }
799     else if (BASE == (rt_ubase_t)SDIO2_BASE)
800     {
801         LOG_D("MMC_FLAG_EMMC.");
802         if (sd2_clock_state == false)
803         {
804             mmio_write_32(MMC_SDIO2_PLL_REGISTER, MMC_MAX_CLOCK_DIV_VALUE);
805             mmio_clrbits_32(CLOCK_BYPASS_SELECT_REGISTER, BIT(5));
806             sd2_clock_state = true;
807         }
808     }
809 
810     sdhci_phy_init(sdhci->base);
811     sdhci_init(sdhci->base);
812 
813     int_status = SDIF_INT_BUS_POWER | SDIF_INT_DATA_END_BIT |
814         SDIF_INT_DATA_CRC | SDIF_INT_DATA_TIMEOUT |
815         SDIF_INT_INDEX | SDIF_INT_END_BIT | SDIF_INT_CRC |
816         SDIF_INT_TIMEOUT | SDIF_INT_DATA_END | SDIF_INT_RESPONSE;
817 
818     int_status = (int_status & ~pio_irqs) | dma_irqs;
819 
820     if (int_status)
821     {
822         rt_hw_interrupt_install(sdhci->irq, sdhci_transfer_handle_irq, sdhci, sdhci->name);
823         rt_hw_interrupt_umask(sdhci->irq);
824 
825         mmio_write_32(BASE + SDIF_SIGNAL_ENABLE, int_status);
826     }
827     else
828     {
829         mmio_write_32(BASE + SDIF_SIGNAL_ENABLE, 0);
830     }
831 
832 }
833 
rthw_sdhci_request(struct rt_mmcsd_host * host,struct rt_mmcsd_req * req)834 static void rthw_sdhci_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
835 {
836     RT_ASSERT(host != RT_NULL);
837     RT_ASSERT(req != RT_NULL);
838 
839     rt_err_t ret = RT_EOK;
840     struct rthw_sdhci *sdhci = (struct rthw_sdhci *)host->private_data;
841 
842     if (req->cmd != RT_NULL)
843     {
844         struct rt_mmcsd_cmd *cmd = req->cmd;
845         struct rt_mmcsd_data *data = req->data;
846 
847         LOG_D("[%s%s%s%s%s]REQ: CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c addr:%p, blks:%d, blksize:%d datalen:%d",
848                 (host->card == RT_NULL) ? "Unknown" : "",
849                 (host->card) && (host->card->card_type == CARD_TYPE_MMC) ? "MMC" : "",
850                 (host->card) && (host->card->card_type == CARD_TYPE_SD) ? "SD" : "",
851                 (host->card) && (host->card->card_type == CARD_TYPE_SDIO) ? "SDIO" : "",
852                 (host->card) && (host->card->card_type == CARD_TYPE_SDIO_COMBO) ? "SDIO_COMBO" : "",
853                 cmd->cmd_code,
854                 cmd->arg,
855                 resp_type(cmd) == RESP_NONE ? "NONE"  : "",
856                 resp_type(cmd) == RESP_R1  ? "R1"  : "",
857                 resp_type(cmd) == RESP_R1B ? "R1B"  : "",
858                 resp_type(cmd) == RESP_R2  ? "R2"  : "",
859                 resp_type(cmd) == RESP_R3  ? "R3"  : "",
860                 resp_type(cmd) == RESP_R4  ? "R4"  : "",
861                 resp_type(cmd) == RESP_R5  ? "R5"  : "",
862                 resp_type(cmd) == RESP_R6  ? "R6"  : "",
863                 resp_type(cmd) == RESP_R7  ? "R7"  : "",
864                 data ? (data->flags & DATA_DIR_WRITE ?  'w' : 'r') : '-',
865                 data ? data->buf : 0,
866                 data ? data->blks : 0,
867                 data ? data->blksize : 0,
868                 data ? data->blks * data->blksize : 0);
869 
870         if (cmd->cmd_code == SD_IO_SEND_OP_COND)
871         {
872             cmd->err = -RT_ERROR;
873 
874             mmcsd_req_complete(host);
875             return;
876         }
877 
878         sdhci->response_type = resp_type(cmd);
879         sdhci->cmd_error = RT_EOK;
880         sdhci->data_error = RT_EOK;
881         memset((void *)sdhci->response, 0, sizeof(sdhci->response));
882         memset(cmd->resp, 0, sizeof(cmd->resp));
883 
884         ret = sdhci_send_data_cmd(sdhci, cmd, data);
885         if (ret != RT_EOK)
886         {
887             memset(cmd->resp, 0, sizeof(cmd->resp));
888         }
889         cmd->err = ret;
890     }
891 
892     if (req->stop != RT_NULL)
893     {
894         struct rt_mmcsd_cmd *stop = req->stop;
895 
896         stop->err = sdhci_send_data_cmd(sdhci, stop, RT_NULL);
897     }
898 
899     mmcsd_req_complete(host);
900 }
901 
rthw_sdhci_iocfg(struct rt_mmcsd_host * host,struct rt_mmcsd_io_cfg * io_cfg)902 static void rthw_sdhci_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
903 {
904     RT_ASSERT(host != RT_NULL);
905     RT_ASSERT(io_cfg != RT_NULL);
906 
907     struct rthw_sdhci *sdhci = (struct rthw_sdhci *)host->private_data;
908     rt_uint32_t clk = io_cfg->clock;
909 
910     LOG_D("clk:%d width:%s%s%s power:%s%s%s",
911           clk,
912           io_cfg->bus_width == MMCSD_BUS_WIDTH_8 ? "8" : "",
913           io_cfg->bus_width == MMCSD_BUS_WIDTH_4 ? "4" : "",
914           io_cfg->bus_width == MMCSD_BUS_WIDTH_1 ? "1" : "",
915           io_cfg->power_mode == MMCSD_POWER_OFF ? "OFF" : "",
916           io_cfg->power_mode == MMCSD_POWER_UP ? "UP" : "",
917           io_cfg->power_mode == MMCSD_POWER_ON ? "ON" : ""
918          );
919 
920     if (clk > host->freq_max)
921         clk = host->freq_max;
922 
923     if (clk < host->freq_min)
924         clk = host->freq_min;
925 
926     sdhci_set_clock(sdhci->base, clk);
927 
928     /* power mode */
929     switch (io_cfg->power_mode)
930     {
931         case MMCSD_POWER_UP:
932         case MMCSD_POWER_ON:
933             sdhci_enable_card_power(sdhci->base, true);
934             break;
935 
936         case MMCSD_POWER_OFF:
937             sdhci_enable_card_power(sdhci->base, false);
938             break;
939 
940         default:
941             break;
942     }
943 
944     /* bus width */
945     switch (io_cfg->bus_width)
946     {
947         case MMCSD_BUS_WIDTH_1:
948         case MMCSD_BUS_WIDTH_4:
949             sdhci_set_bus_width(sdhci->base, io_cfg->bus_width);
950             break;
951 
952         case MMCSD_BUS_WIDTH_8:
953         default:
954             LOG_E("invalid bus_width: %d", io_cfg->bus_width);
955             break;
956     }
957 }
958 
959 
960 static const struct rt_mmcsd_host_ops ops = {
961     rthw_sdhci_request,
962     rthw_sdhci_iocfg,
963     RT_NULL,
964     RT_NULL,
965 };
966 
rthw_sdhci_init(void)967 static int rthw_sdhci_init(void)
968 {
969     rt_err_t ret = RT_EOK;
970 
971     struct rt_mmcsd_host *host;
972     struct rthw_sdhci *sdhci = RT_NULL;
973 
974     sdhci = rt_malloc(sizeof(struct rthw_sdhci));
975     if (sdhci == RT_NULL)
976     {
977         LOG_E("malloc rthw_sdhci faile...");
978     }
979     rt_memset(sdhci, 0, sizeof(struct rthw_sdhci));
980 
981     sdhci->sem_cmd = rt_sem_create("sem_cmd", 0, RT_IPC_FLAG_FIFO);
982     if (sdhci->sem_cmd == RT_NULL)
983     {
984         LOG_E("rt_sem_create sdhci event failed...");
985         rt_free(sdhci);
986         sdhci = RT_NULL;
987         return ret;
988     }
989 
990     sdhci->sem_data = rt_sem_create("sem_data", 0, RT_IPC_FLAG_FIFO);
991     if (sdhci->sem_data == RT_NULL)
992     {
993         LOG_E("rt_sem_create sdhci event failed...");
994         rt_sem_delete(sdhci->sem_cmd);
995         rt_free(sdhci);
996         sdhci = RT_NULL;
997         return ret;
998     }
999 
1000     sdhci->base = (rt_ubase_t)SDIO0_BASE;
1001     sdhci->irq = SDIO0_IRQ;
1002     strcpy(sdhci->name, "sdio0");
1003     rthw_sdhci_set_config(sdhci);
1004 
1005     host = mmcsd_alloc_host();
1006     RT_ASSERT(host != RT_NULL);
1007 
1008     /* set host default attributes */
1009     host->ops = &ops;
1010     host->freq_min = 400000;
1011     host->freq_max = 50 * 1000 * 1000;
1012     host->valid_ocr = VDD_31_32 | VDD_32_33 | VDD_33_34;
1013     host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED;
1014     host->max_seg_size = 512;
1015     host->max_dma_segs = 1;
1016     host->max_blk_size= 512;
1017     host->max_blk_count = 512;
1018 
1019     sdhci->host = host;
1020     host->private_data = sdhci;
1021 
1022     /* ready to change */
1023     mmcsd_change(host);
1024 
1025     return RT_EOK;
1026 }
1027 INIT_DEVICE_EXPORT(rthw_sdhci_init);
1028 
sdhci_reg_dump(uint8_t argc,char ** argv)1029 void sdhci_reg_dump(uint8_t argc, char **argv)
1030 {
1031     rt_ubase_t base;
1032     if (argc < 2)
1033     {
1034         rt_kprintf("Usage: sdhci_reg_dump 0/1/2\n");
1035         return;
1036     }
1037 
1038     if (0 == atoi(argv[1]))
1039         base = (rt_ubase_t)SDIO0_BASE;
1040     else if (1 == atoi(argv[1]))
1041         base = (rt_ubase_t)SDIO1_BASE;
1042     else
1043         base = (rt_ubase_t)SDIO2_BASE;
1044 
1045     uintptr_t BASE = (uintptr_t)base;
1046 
1047     rt_kprintf("============ SDHCI REGISTER DUMP ===========\n");
1048 
1049     rt_kprintf("Sys addr:  0x%08x | Version:  0x%08x\n",
1050            mmio_read_32(BASE + SDIF_DMA_ADDRESS),
1051            mmio_read_16(BASE + SDIF_HOST_VERSION));
1052     rt_kprintf("Blk size:  0x%08x | Blk cnt:  0x%08x\n",
1053            mmio_read_16(BASE + SDIF_BLOCK_SIZE),
1054            mmio_read_16(BASE + SDIF_BLOCK_COUNT));
1055     rt_kprintf("Argument:  0x%08x | Trn mode: 0x%08x\n",
1056            mmio_read_32(BASE + SDIF_ARGUMENT),
1057            mmio_read_16(BASE + SDIF_TRANSFER_MODE));
1058     rt_kprintf("Present:   0x%08x | Host ctl: 0x%08x\n",
1059            mmio_read_32(BASE + SDIF_PRESENT_STATE),
1060            mmio_read_8(BASE + SDIF_HOST_CONTROL));
1061     rt_kprintf("Power:     0x%08x | Blk gap:  0x%08x\n",
1062            mmio_read_8(BASE + SDIF_PWR_CONTROL),
1063            mmio_read_8(BASE + SDIF_BLOCK_GAP_CONTROL));
1064     rt_kprintf("Wake-up:   0x%08x | Clock:    0x%08x\n",
1065            mmio_read_8(BASE + SDIF_WAKE_UP_CONTROL),
1066            mmio_read_16(BASE + SDIF_CLK_CTRL));
1067     rt_kprintf("Timeout:   0x%08x | Int stat: 0x%08x\n",
1068            mmio_read_8(BASE + SDIF_TOUT_CTRL),
1069            mmio_read_32(BASE + SDIF_INT_STATUS));
1070     rt_kprintf("Int enab:  0x%08x | Sig enab: 0x%08x\n",
1071            mmio_read_32(BASE + SDIF_INT_ENABLE),
1072            mmio_read_32(BASE + SDIF_SIGNAL_ENABLE));
1073     rt_kprintf("ACmd stat: 0x%08x | Slot int: 0x%08x\n",
1074            mmio_read_16(BASE + SDIF_AUTO_CMD_STATUS),
1075            mmio_read_16(BASE + SDIF_SLOT_INT_STATUS));
1076     rt_kprintf("Caps:      0x%08x | Caps_1:   0x%08x\n",
1077            mmio_read_32(BASE + SDIF_CAPABILITIES),
1078            mmio_read_32(BASE + SDIF_CAPABILITIES_1));
1079     rt_kprintf("Cmd:       0x%08x | Max curr: 0x%08x\n",
1080            mmio_read_16(BASE + SDIF_COMMAND),
1081            mmio_read_32(BASE + SDIF_MAX_CURRENT));
1082     rt_kprintf("Resp[0]:   0x%08x | Resp[1]:  0x%08x\n",
1083            mmio_read_32(BASE + SDIF_RESPONSE),
1084            mmio_read_32(BASE + SDIF_RESPONSE + 4));
1085     rt_kprintf("Resp[2]:   0x%08x | Resp[3]:  0x%08x\n",
1086            mmio_read_32(BASE + SDIF_RESPONSE + 8),
1087            mmio_read_32(BASE + SDIF_RESPONSE + 12));
1088     rt_kprintf("Host ctl2: 0x%08x\n",
1089            mmio_read_16(BASE + SDIF_HOST_CONTROL2));
1090     rt_kprintf("ADMA Err:  0x%08x | ADMA Ptr: 0x%08x%08x\n",
1091            mmio_read_32(BASE + SDIF_ADMA_ERROR),
1092            mmio_read_32(BASE + SDIF_ADMA_ADDRESS_HI),
1093            mmio_read_32(BASE + SDIF_ADMA_ADDRESS));
1094     rt_kprintf("============================================\n");
1095 }
1096 MSH_CMD_EXPORT(sdhci_reg_dump, dump sdhci register);
1097