1 /*
2 * File : drv_sdio.c
3 * Copyright (c) 2006-2021, RT-Thread Development Team
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date Author Notes
9 * 2019-07-29 zdzn first version
10 */
11
12 #include "drv_sdio.h"
13
14 static rt_uint32_t sdCommandTable[] = {
15 SD_CMD_INDEX(0),
16 SD_CMD_RESERVED(1),
17 SD_CMD_INDEX(2) | SD_RESP_R2,
18 SD_CMD_INDEX(3) | SD_RESP_R1,
19 SD_CMD_INDEX(4),
20 SD_CMD_RESERVED(5), //SD_CMD_INDEX(5) | SD_RESP_R4,
21 SD_CMD_INDEX(6) | SD_RESP_R1,
22 SD_CMD_INDEX(7) | SD_RESP_R1b,
23 SD_CMD_INDEX(8) | SD_RESP_R1,
24 SD_CMD_INDEX(9) | SD_RESP_R2,
25 SD_CMD_INDEX(10) | SD_RESP_R2,
26 SD_CMD_INDEX(11) | SD_RESP_R1,
27 SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT,
28 SD_CMD_INDEX(13) | SD_RESP_R1,
29 SD_CMD_RESERVED(14),
30 SD_CMD_INDEX(15),
31 SD_CMD_INDEX(16) | SD_RESP_R1,
32 SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ,
33 SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
34 SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ,
35 SD_CMD_INDEX(20) | SD_RESP_R1b,
36 SD_CMD_RESERVED(21),
37 SD_CMD_RESERVED(22),
38 SD_CMD_INDEX(23) | SD_RESP_R1,
39 SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE,
40 SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
41 SD_CMD_INDEX(26) | SD_RESP_R1 | SD_DATA_WRITE, //add
42 SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE,
43 SD_CMD_INDEX(28) | SD_RESP_R1b,
44 SD_CMD_INDEX(29) | SD_RESP_R1b,
45 SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ,
46 SD_CMD_RESERVED(31),
47 SD_CMD_INDEX(32) | SD_RESP_R1,
48 SD_CMD_INDEX(33) | SD_RESP_R1,
49 SD_CMD_RESERVED(34),
50 SD_CMD_INDEX(35) | SD_RESP_R1, //add
51 SD_CMD_INDEX(36) | SD_RESP_R1, //add
52 SD_CMD_RESERVED(37),
53 SD_CMD_INDEX(38) | SD_RESP_R1b,
54 SD_CMD_INDEX(39) | SD_RESP_R4, //add
55 SD_CMD_INDEX(40) | SD_RESP_R5, //add
56 SD_CMD_INDEX(41) | SD_RESP_R3, //add, mov from harbote
57 SD_CMD_RESERVED(42) | SD_RESP_R1,
58 SD_CMD_RESERVED(43),
59 SD_CMD_RESERVED(44),
60 SD_CMD_RESERVED(45),
61 SD_CMD_RESERVED(46),
62 SD_CMD_RESERVED(47),
63 SD_CMD_RESERVED(48),
64 SD_CMD_RESERVED(49),
65 SD_CMD_RESERVED(50),
66 SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ,
67 SD_CMD_RESERVED(52),
68 SD_CMD_RESERVED(53),
69 SD_CMD_RESERVED(54),
70 SD_CMD_INDEX(55) | SD_RESP_R3,
71 SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA,
72 SD_CMD_RESERVED(57),
73 SD_CMD_RESERVED(58),
74 SD_CMD_RESERVED(59),
75 SD_CMD_RESERVED(60),
76 SD_CMD_RESERVED(61),
77 SD_CMD_RESERVED(62),
78 SD_CMD_RESERVED(63)
79 };
80
read32(rt_uint32_t addr)81 static inline rt_uint32_t read32(rt_uint32_t addr)
82 {
83 return (*((volatile rt_uint32_t *)(addr)));
84 }
85
write32(rt_uint32_t addr,rt_uint32_t value)86 static inline void write32(rt_uint32_t addr, rt_uint32_t value)
87 {
88 *((volatile rt_uint32_t *)(addr)) = value;
89 }
90
sd_int(struct sdhci_pdata_t * pdat,unsigned int mask)91 rt_err_t sd_int(struct sdhci_pdata_t * pdat, unsigned int mask)
92 {
93 unsigned int r;
94 unsigned int m = mask | INT_ERROR_MASK;
95 int cnt = 1000000;
96 while (!(read32(pdat->virt + EMMC_INTERRUPT) & (m | INT_ERROR_MASK)) && cnt--)
97 DELAY_MICROS(1);
98 r = read32(pdat->virt + EMMC_INTERRUPT);
99 if (cnt <= 0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT))
100 {
101 write32(pdat->virt + EMMC_INTERRUPT, r);
102 //qemu maybe can not use sdcard
103 //rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n",mask, r, read32(pdat->virt + EMMC_STATUS));
104 //return -RT_ETIMEOUT;
105 }
106 else if (r & INT_ERROR_MASK)
107 {
108 write32(pdat->virt + EMMC_INTERRUPT, r);
109 rt_kprintf("send cmd/data error %x -> %x\n",r, read32(pdat->virt + EMMC_INTERRUPT));
110 return -RT_ERROR;
111 }
112 write32(pdat->virt + EMMC_INTERRUPT, mask);
113 return RT_EOK;
114 }
115
sd_status(struct sdhci_pdata_t * pdat,unsigned int mask)116 rt_err_t sd_status(struct sdhci_pdata_t * pdat, unsigned int mask)
117 {
118 int cnt = 500000;
119 while ((read32(pdat->virt + EMMC_STATUS) & mask) && !(read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK) && cnt--)
120 DELAY_MICROS(1);
121 if (cnt <= 0)
122 {
123 return -RT_ETIMEOUT;
124 }
125 else if (read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK)
126 {
127 return -RT_ERROR;
128 }
129 return RT_EOK;
130 }
131
raspi_transfer_command(struct sdhci_pdata_t * pdat,struct sdhci_cmd_t * cmd)132 static rt_err_t raspi_transfer_command(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd)
133 {
134
135 rt_uint32_t cmdidx;
136 rt_err_t ret = RT_EOK;
137 ret = sd_status(pdat, SR_CMD_INHIBIT);
138 if (ret)
139 {
140 rt_kprintf("ERROR: EMMC busy %d\n", ret);
141 return ret;
142 }
143
144 cmdidx = sdCommandTable[cmd->cmdidx];
145 if (cmdidx == 0xFFFFFFFF)
146 return -RT_EINVAL;
147 if (cmd->datarw == DATA_READ)
148 cmdidx |= SD_DATA_READ;
149 if (cmd->datarw == DATA_WRITE)
150 cmdidx |= SD_DATA_WRITE;
151 mmcsd_dbg("transfer cmd %x(%d) %x %x\n", cmdidx, cmd->cmdidx, cmd->cmdarg, read32(pdat->virt + EMMC_INTERRUPT));
152 write32(pdat->virt + EMMC_INTERRUPT,read32(pdat->virt + EMMC_INTERRUPT));
153 write32(pdat->virt + EMMC_ARG1, cmd->cmdarg);
154 write32(pdat->virt + EMMC_CMDTM, cmdidx);
155 if (cmd->cmdidx == SD_APP_OP_COND)
156 DELAY_MICROS(1000);
157 else if ((cmd->cmdidx == SD_SEND_IF_COND) || (cmd->cmdidx == APP_CMD))
158 DELAY_MICROS(100);
159 ret = sd_int(pdat, INT_CMD_DONE);
160 if (ret)
161 {
162 return ret;
163 }
164 if (cmd->resptype & RESP_MASK)
165 {
166
167 if (cmd->resptype & RESP_R2)
168 {
169 rt_uint32_t resp[4];
170 resp[0] = read32(pdat->virt + EMMC_RESP0);
171 resp[1] = read32(pdat->virt + EMMC_RESP1);
172 resp[2] = read32(pdat->virt + EMMC_RESP2);
173 resp[3] = read32(pdat->virt + EMMC_RESP3);
174 if (cmd->resptype == RESP_R2)
175 {
176 cmd->response[0] = resp[3]<<8 |((resp[2]>>24)&0xff);
177 cmd->response[1] = resp[2]<<8 |((resp[1]>>24)&0xff);
178 cmd->response[2] = resp[1]<<8 |((resp[0]>>24)&0xff);
179 cmd->response[3] = resp[0]<<8 ;
180 }
181 else
182 {
183 cmd->response[0] = resp[0];
184 cmd->response[1] = resp[1];
185 cmd->response[2] = resp[2];
186 cmd->response[3] = resp[3];
187 }
188 }
189 else
190 cmd->response[0] = read32(pdat->virt + EMMC_RESP0);
191 }
192 mmcsd_dbg("response: %x: %x %x %x %x (%x, %x)\n", cmd->resptype, cmd->response[0], cmd->response[1], cmd->response[2], cmd->response[3], read32(pdat->virt + EMMC_STATUS),read32(pdat->virt + EMMC_INTERRUPT));
193 return ret;
194 }
195
read_bytes(struct sdhci_pdata_t * pdat,rt_uint32_t * buf,rt_uint32_t blkcount,rt_uint32_t blksize)196 static rt_err_t read_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
197 {
198 int c = 0;
199 rt_err_t ret;
200 int d;
201 while (c < blkcount)
202 {
203 if ((ret = sd_int(pdat, INT_READ_RDY)))
204 {
205 rt_kprintf("timeout happens when reading block %d\n",c);
206 return ret;
207 }
208 for (d=0; d < blksize / 4; d++)
209 if (read32(pdat->virt + EMMC_STATUS) & SR_READ_AVAILABLE)
210 buf[d] = read32(pdat->virt + EMMC_DATA);
211 c++;
212 buf += blksize / 4;
213 }
214 return RT_EOK;
215 }
216
write_bytes(struct sdhci_pdata_t * pdat,rt_uint32_t * buf,rt_uint32_t blkcount,rt_uint32_t blksize)217 static rt_err_t write_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
218 {
219 int c = 0;
220 rt_err_t ret;
221 int d;
222 while (c < blkcount)
223 {
224 if ((ret = sd_int(pdat, INT_WRITE_RDY)))
225 {
226 return ret;
227 }
228 for (d=0; d < blksize / 4; d++)
229 write32(pdat->virt + EMMC_DATA, buf[d]);
230 c++;
231 buf += blksize / 4;
232 }
233 if ((ret = sd_int(pdat, INT_DATA_DONE)))
234 {
235 return ret;
236 }
237 return RT_EOK;
238 }
239
raspi_transfer_data(struct sdhci_pdata_t * pdat,struct sdhci_cmd_t * cmd,struct sdhci_data_t * dat)240 static rt_err_t raspi_transfer_data(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
241 {
242 rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz);
243 rt_err_t ret = sd_status(pdat, SR_DAT_INHIBIT);
244 if (ret)
245 {
246 rt_kprintf("ERROR: EMMC busy\n");
247 return ret;
248 }
249 if (dat->blkcnt > 1)
250 {
251 struct sdhci_cmd_t newcmd;
252 newcmd.cmdidx = SET_BLOCK_COUNT;
253 newcmd.cmdarg = dat->blkcnt;
254 newcmd.resptype = RESP_R1;
255 ret = raspi_transfer_command(pdat, &newcmd);
256 if (ret) return ret;
257 }
258
259 if(dlen < 512)
260 {
261 write32(pdat->virt + EMMC_BLKSIZECNT, dlen | 1 << 16);
262 }
263 else
264 {
265 write32(pdat->virt + EMMC_BLKSIZECNT, 512 | (dat->blkcnt) << 16);
266 }
267 if (dat->flag & DATA_DIR_READ)
268 {
269 cmd->datarw = DATA_READ;
270 ret = raspi_transfer_command(pdat, cmd);
271 if (ret) return ret;
272 mmcsd_dbg("read_block %d, %d\n", dat->blkcnt, dat->blksz );
273 ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
274 }
275 else if (dat->flag & DATA_DIR_WRITE)
276 {
277 cmd->datarw = DATA_WRITE;
278 ret = raspi_transfer_command(pdat, cmd);
279 if (ret) return ret;
280 mmcsd_dbg("write_block %d, %d", dat->blkcnt, dat->blksz );
281 ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
282 }
283 return ret;
284 }
285
sdhci_transfer(struct sdhci_t * sdhci,struct sdhci_cmd_t * cmd,struct sdhci_data_t * dat)286 static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
287 {
288 struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
289
290 if (!dat)
291 return raspi_transfer_command(pdat, cmd);
292
293 return raspi_transfer_data(pdat, cmd, dat);
294 }
295
mmc_request_send(struct rt_mmcsd_host * host,struct rt_mmcsd_req * req)296 static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
297 {
298 struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
299 struct sdhci_cmd_t cmd;
300 struct sdhci_cmd_t stop;
301 struct sdhci_data_t dat;
302
303 rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t));
304 rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t));
305 rt_memset(&dat, 0, sizeof(struct sdhci_data_t));
306
307 cmd.cmdidx = req->cmd->cmd_code;
308 cmd.cmdarg = req->cmd->arg;
309 cmd.resptype =resp_type(req->cmd);
310 if (req->data)
311 {
312 dat.buf = (rt_uint8_t *)req->data->buf;
313 dat.flag = req->data->flags;
314 dat.blksz = req->data->blksize;
315 dat.blkcnt = req->data->blks;
316
317 req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat);
318 }
319 else
320 {
321 req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL);
322 }
323
324 req->cmd->resp[3] = cmd.response[3];
325 req->cmd->resp[2] = cmd.response[2];
326 req->cmd->resp[1] = cmd.response[1];
327 req->cmd->resp[0] = cmd.response[0];
328
329 if (req->stop)
330 {
331 stop.cmdidx = req->stop->cmd_code;
332 stop.cmdarg = req->stop->arg;
333 cmd.resptype =resp_type(req->stop);
334 req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL);
335 }
336
337 mmcsd_req_complete(host);
338 }
339
mmc_card_status(struct rt_mmcsd_host * host)340 rt_int32_t mmc_card_status(struct rt_mmcsd_host *host)
341 {
342 return 0;
343 }
344
mmc_enable_irq(struct rt_mmcsd_host * host,rt_int32_t en)345 void mmc_enable_irq(struct rt_mmcsd_host *host, rt_int32_t en)
346 {
347
348 }
349
sdhci_detect(struct sdhci_t * sdhci)350 static rt_err_t sdhci_detect(struct sdhci_t * sdhci)
351 {
352 return RT_EOK;
353 }
354
sdhci_setwidth(struct sdhci_t * sdhci,rt_uint32_t width)355 static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width)
356 {
357 rt_uint32_t temp = 0;
358 struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
359 if (width == MMCSD_BUS_WIDTH_4)
360 {
361 temp = read32((pdat->virt + EMMC_CONTROL0));
362 temp |= C0_HCTL_HS_EN;
363 temp |= C0_HCTL_DWITDH; // always use 4 data lines:
364 write32((pdat->virt + EMMC_CONTROL0), temp);
365 }
366 return RT_EOK;
367 }
368
sdhci_getdivider(rt_uint32_t sdHostVer,rt_uint32_t freq)369 static rt_uint32_t sdhci_getdivider(rt_uint32_t sdHostVer, rt_uint32_t freq)
370 {
371 rt_uint32_t divisor;
372 rt_uint32_t closest = 41666666 / freq;
373 rt_uint32_t shiftcount = __rt_fls(closest - 1);
374
375
376 if (shiftcount > 0) shiftcount--;
377 if (shiftcount > 7) shiftcount = 7;
378 if (sdHostVer > HOST_SPEC_V2)
379 divisor = closest;
380 else
381 divisor = (1 << shiftcount);
382
383 if (divisor <= 2)
384 {
385 divisor = 2;
386 shiftcount = 0;
387 }
388
389 rt_uint32_t hi = 0;
390 if (sdHostVer > HOST_SPEC_V2)
391 hi = (divisor & 0x300) >> 2;
392 rt_uint32_t lo = (divisor & 0x0ff);
393 rt_uint32_t cdiv = (lo << 8) + hi;
394 return cdiv;
395 }
396
sdhci_setclock(struct sdhci_t * sdhci,rt_uint32_t clock)397 static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock)
398 {
399 rt_uint32_t temp = 0;
400 rt_uint32_t sdHostVer = 0;
401 int count = 100000;
402 struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)(sdhci->priv);
403
404 while ((read32(pdat->virt + EMMC_STATUS) & (SR_CMD_INHIBIT | SR_DAT_INHIBIT)) && (--count))
405 DELAY_MICROS(1);
406 if (count <= 0)
407 {
408 rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n",read32(pdat->virt + EMMC_STATUS));
409 return -RT_ERROR;
410 }
411
412 // Switch clock off.
413 temp = read32((pdat->virt + EMMC_CONTROL1));
414 temp &= ~C1_CLK_EN;
415 write32((pdat->virt + EMMC_CONTROL1),temp);
416 DELAY_MICROS(10);
417 // Request the new clock setting and enable the clock
418 temp = read32(pdat->virt + EMMC_SLOTISR_VER);
419 sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT;
420 int cdiv = sdhci_getdivider(sdHostVer, clock);
421 temp = read32((pdat->virt + EMMC_CONTROL1));
422 temp = (temp & 0xffff003f) | cdiv;
423 write32((pdat->virt + EMMC_CONTROL1),temp);
424 DELAY_MICROS(10);
425
426 // Enable the clock.
427 temp = read32(pdat->virt + EMMC_CONTROL1);
428 temp |= C1_CLK_EN;
429 write32((pdat->virt + EMMC_CONTROL1),temp);
430 DELAY_MICROS(10);
431 // Wait for clock to be stable.
432 count = 10000;
433 while (!(read32(pdat->virt + EMMC_CONTROL1) & C1_CLK_STABLE) && count--)
434 DELAY_MICROS(10);
435 if (count <= 0)
436 {
437 rt_kprintf("EMMC: ERROR: failed to get stable clock %d.\n", clock);
438 return -RT_ERROR;
439 }
440 mmcsd_dbg("set stable clock %d.\n", clock);
441 return RT_EOK;
442 }
443
mmc_set_iocfg(struct rt_mmcsd_host * host,struct rt_mmcsd_io_cfg * io_cfg)444 static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
445 {
446 struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data;
447 sdhci_setclock(sdhci, io_cfg->clock);
448 sdhci_setwidth(sdhci, io_cfg->bus_width);
449 }
450
451 static const struct rt_mmcsd_host_ops ops =
452 {
453 mmc_request_send,
454 mmc_set_iocfg,
455 RT_NULL,
456 RT_NULL,
457 };
458
sdmmc_gpio_init()459 static void sdmmc_gpio_init()
460 {
461 // int pin;
462 // bcm283x_gpio_fsel(47,BCM283X_GPIO_FSEL_INPT);
463 // bcm283x_gpio_set_pud(47, BCM283X_GPIO_PUD_UP);
464 // bcm283x_peri_set_bits(BCM283X_GPIO_BASE + BCM283X_GPIO_GPHEN1, 1<<15, 1<<15);
465 // for (pin = 53; pin >= 48; pin--)
466 // {
467 // bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_ALT3);
468 // bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_UP);
469 // }
470 }
471
reset_emmc(struct sdhci_pdata_t * pdat)472 static rt_err_t reset_emmc(struct sdhci_pdata_t * pdat){
473 rt_uint32_t temp;
474 int cnt;
475 write32((pdat->virt + EMMC_CONTROL0),0);
476 temp = read32((pdat->virt + EMMC_CONTROL1));
477 temp |= C1_SRST_HC;
478 write32((pdat->virt + EMMC_CONTROL1),temp);
479 cnt = 10000;
480 do
481 {
482 DELAY_MICROS(10);
483 }
484 while ((read32((pdat->virt + EMMC_CONTROL1)) & C1_SRST_HC) && cnt--);
485
486 if (cnt <= 0)
487 {
488 rt_kprintf("ERROR: failed to reset EMMC\n");
489 return -RT_ERROR;
490 }
491 temp = read32((pdat->virt + EMMC_CONTROL1));
492 temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX;
493 write32((pdat->virt + EMMC_CONTROL1),temp);
494 DELAY_MICROS(10);
495 return RT_EOK;
496 }
497
498 #ifdef RT_MMCSD_DBG
dump_registers(struct sdhci_pdata_t * pdat)499 void dump_registers(struct sdhci_pdata_t * pdat){
500 rt_kprintf("EMMC registers:");
501 int i = EMMC_ARG2;
502 for (; i <= EMMC_CONTROL2; i += 4)
503 rt_kprintf("\t%x:%x\n", i, read32(pdat->virt + i));
504 rt_kprintf("\t%x:%x\n", 0x50, read32(pdat->virt + 0x50));
505 rt_kprintf("\t%x:%x\n", 0x70, read32(pdat->virt + 0x70));
506 rt_kprintf("\t%x:%x\n", 0x74, read32(pdat->virt + 0x74));
507 rt_kprintf("\t%x:%x\n", 0x80, read32(pdat->virt + 0x80));
508 rt_kprintf("\t%x:%x\n", 0x84, read32(pdat->virt + 0x84));
509 rt_kprintf("\t%x:%x\n", 0x88, read32(pdat->virt + 0x88));
510 rt_kprintf("\t%x:%x\n", 0x8c, read32(pdat->virt + 0x8c));
511 rt_kprintf("\t%x:%x\n", 0x90, read32(pdat->virt + 0x90));
512 rt_kprintf("\t%x:%x\n", 0xf0, read32(pdat->virt + 0xf0));
513 rt_kprintf("\t%x:%x\n", 0xfc, read32(pdat->virt + 0xfc));
514 }
515 #endif
516
raspi_sdmmc_init(void)517 int raspi_sdmmc_init(void)
518 {
519 rt_uint32_t virt;
520 struct rt_mmcsd_host * host = RT_NULL;
521 struct sdhci_pdata_t * pdat = RT_NULL;
522 struct sdhci_t * sdhci = RT_NULL;
523
524 #ifdef BSP_USING_SDIO0
525 host = mmcsd_alloc_host();
526 if (!host)
527 {
528 rt_kprintf("alloc host failed");
529 goto err;
530 }
531
532 sdhci = rt_malloc(sizeof(struct sdhci_t));
533 if (!sdhci)
534 {
535 rt_kprintf("alloc sdhci failed");
536 goto err;
537 }
538 rt_memset(sdhci, 0, sizeof(struct sdhci_t));
539
540 sdmmc_gpio_init();
541
542 virt = MMC0_BASE_ADDR;
543
544 pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t));
545 RT_ASSERT(pdat != RT_NULL);
546
547 pdat->virt = (rt_uint32_t)virt;
548 reset_emmc(pdat);
549
550 sdhci->name = "sd0";
551 sdhci->voltages = VDD_33_34;
552 sdhci->width = MMCSD_BUSWIDTH_4;
553 sdhci->clock = 200 * 1000 * 1000;
554 sdhci->removeable = RT_TRUE;
555
556 sdhci->detect = sdhci_detect;
557 sdhci->setwidth = sdhci_setwidth;
558 sdhci->setclock = sdhci_setclock;
559 sdhci->transfer = sdhci_transfer;
560 sdhci->priv = pdat;
561
562 host->ops = &ops;
563 host->freq_min = 400000;
564 host->freq_max = 50000000;
565 host->valid_ocr = VDD_32_33 | VDD_33_34;
566 host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4;
567 host->max_seg_size = 2048;
568 host->max_dma_segs = 10;
569 host->max_blk_size = 512;
570 host->max_blk_count = 4096;
571
572 host->private_data = sdhci;
573
574 write32((pdat->virt + EMMC_IRPT_EN),0xffffffff);
575 write32((pdat->virt + EMMC_IRPT_MASK),0xffffffff);
576 #ifdef RT_MMCSD_DBG
577 dump_registers(pdat);
578 #endif
579 mmcsd_change(host);
580 #endif
581 return RT_EOK;
582
583 err:
584 if (host) rt_free(host);
585 if (sdhci) rt_free(sdhci);
586
587 return -RT_EIO;
588 }
589
590 INIT_DEVICE_EXPORT(raspi_sdmmc_init);
591