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