blob: c4b6fcafeca87093fe0a90eae335203f1ad3a9b1 [file] [log] [blame]
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +08001/*
2 * Copyright (c) 2019, Linaro Limited
3 * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include <arch.h>
9#include <arch_helpers.h>
10#include <assert.h>
11#include <common/debug.h>
12#include <lib/mmio.h>
13#include <drivers/delay_timer.h>
14#include <drivers/rpi3/sdhost/rpi3_sdhost.h>
15#include <drivers/mmc.h>
16#include <drivers/rpi3/gpio/rpi3_gpio.h>
17#include <errno.h>
18#include <string.h>
19
20static void rpi3_sdhost_initialize(void);
21static int rpi3_sdhost_send_cmd(struct mmc_cmd *cmd);
22static int rpi3_sdhost_set_ios(unsigned int clk, unsigned int width);
23static int rpi3_sdhost_prepare(int lba, uintptr_t buf, size_t size);
24static int rpi3_sdhost_read(int lba, uintptr_t buf, size_t size);
25static int rpi3_sdhost_write(int lba, uintptr_t buf, size_t size);
26
27static const struct mmc_ops rpi3_sdhost_ops = {
28 .init = rpi3_sdhost_initialize,
29 .send_cmd = rpi3_sdhost_send_cmd,
30 .set_ios = rpi3_sdhost_set_ios,
31 .prepare = rpi3_sdhost_prepare,
32 .read = rpi3_sdhost_read,
33 .write = rpi3_sdhost_write,
34};
35
36static struct rpi3_sdhost_params rpi3_sdhost_params;
37
38/**
39 * Wait for command being processed.
40 *
41 * This function waits the command being processed. It compares
42 * the ENABLE flag of the HC_COMMAND register. When ENABLE flag disappeared
43 * it means the command is processed by the SDHOST.
44 * The timeout is currently 1000*100 us = 100 ms.
45 *
46 * @return 0: command finished. 1: command timed out.
47 */
48static int rpi3_sdhost_waitcommand(void)
49{
50 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
51
52 volatile int timeout = 1000;
53
54 while ((mmio_read_32(reg_base + HC_COMMAND) & HC_CMD_ENABLE)
55 && (--timeout > 0)) {
56 udelay(100);
57 }
58
59 return ((timeout > 0) ? 0 : (-(ETIMEDOUT)));
60}
61
62/**
63 * Send the command and argument to the SDHOST
64 *
65 * This function will wait for the previous command finished. And then
66 * clear any error status of previous command. And then
67 * send out the command and args. The command will be turned on the ENABLE
68 * flag before sending out.
69 */
70static void send_command_raw(unsigned int cmd, unsigned int arg)
71{
72 unsigned int status;
73 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
74
75 /* wait for previous command finish */
76 rpi3_sdhost_waitcommand();
77
78 /* clean error status */
79 status = mmio_read_32(reg_base + HC_HOSTSTATUS);
80 if (status & HC_HSTST_MASK_ERROR_ALL)
81 mmio_write_32(reg_base + HC_HOSTSTATUS, status);
82
83 /* recording the command */
84 rpi3_sdhost_params.current_cmd = cmd & HC_CMD_COMMAND_MASK;
85
86 /* send the argument and command */
87 mmio_write_32(reg_base + HC_ARGUMENT, arg);
88 mmio_write_32(reg_base + HC_COMMAND, cmd | HC_CMD_ENABLE);
89}
90
91/**
92 * Send the command and argument to the SDHOST, decorated with control
93 * flags.
94 *
95 * This function will use send_command_raw to send the commands to SDHOST.
96 * But before sending it will decorate the command with control flags specific
97 * to SDHOST.
98 */
99static void send_command_decorated(unsigned int cmd, unsigned int arg)
100{
101 unsigned int cmd_flags = 0;
102
103 switch (cmd & HC_CMD_COMMAND_MASK) {
104 case MMC_CMD(0):
105 cmd_flags |= HC_CMD_RESPONSE_NONE;
106 break;
107 case MMC_ACMD(51):
108 cmd_flags |= HC_CMD_READ;
109 break;
110 case MMC_CMD(8):
111 case MMC_CMD(11):
112 case MMC_CMD(17):
113 case MMC_CMD(18):
114 cmd_flags |= HC_CMD_READ;
115 break;
116 case MMC_CMD(20):
117 case MMC_CMD(24):
118 case MMC_CMD(25):
119 cmd_flags |= HC_CMD_WRITE;
120 break;
121 case MMC_CMD(12):
122 cmd_flags |= HC_CMD_BUSY;
123 break;
124 default:
125 break;
126 }
127 send_command_raw(cmd | cmd_flags, arg);
128}
129
130/**
131 * drains the FIFO on DATA port
132 *
133 * This function drains any data left in the DATA port.
134 */
135static void rpi3_drain_fifo(void)
136{
137 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
138 volatile int timeout = 100000;
139
140 rpi3_sdhost_waitcommand();
141
142 while (mmio_read_32(reg_base + HC_HOSTSTATUS) & HC_HSTST_HAVEDATA) {
143 mmio_read_32(reg_base + HC_DATAPORT);
144 udelay(100);
145 }
146
147 while (1) {
148 uint32_t edm, fsm;
149
150 edm = mmio_read_32(reg_base + HC_DEBUG);
151 fsm = edm & HC_DBG_FSM_MASK;
152
153 if ((fsm == HC_DBG_FSM_IDENTMODE) ||
154 (fsm == HC_DBG_FSM_DATAMODE))
155 break;
156
157 if ((fsm == HC_DBG_FSM_READWAIT) ||
158 (fsm == HC_DBG_FSM_WRITESTART1) ||
159 (fsm == HC_DBG_FSM_READDATA)) {
160 mmio_write_32(reg_base + HC_DEBUG,
161 edm | HC_DBG_FORCE_DATA_MODE);
162 break;
163 }
164
165 if (--timeout <= 0) {
166 ERROR("rpi3_sdhost: %s cannot recover stat\n",
167 __func__);
168 return;
169 }
170 }
171}
172
173/**
174 * Dump SDHOST registers
175 */
176static void rpi3_sdhost_print_regs(void)
177{
178 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
179
180 INFO("rpi3_sdhost: HC_COMMAND: 0x%08x\n",
181 mmio_read_32(reg_base + HC_COMMAND));
182 INFO("rpi3_sdhost: HC_ARGUMENT: 0x%08x\n",
183 mmio_read_32(reg_base + HC_ARGUMENT));
184 INFO("rpi3_sdhost: HC_TIMEOUTCOUNTER: 0x%08x\n",
185 mmio_read_32(reg_base + HC_TIMEOUTCOUNTER));
186 INFO("rpi3_sdhost: HC_CLOCKDIVISOR: 0x%08x\n",
187 mmio_read_32(reg_base + HC_CLOCKDIVISOR));
188 INFO("rpi3_sdhost: HC_RESPONSE_0: 0x%08x\n",
189 mmio_read_32(reg_base + HC_RESPONSE_0));
190 INFO("rpi3_sdhost: HC_RESPONSE_1: 0x%08x\n",
191 mmio_read_32(reg_base + HC_RESPONSE_1));
192 INFO("rpi3_sdhost: HC_RESPONSE_2: 0x%08x\n",
193 mmio_read_32(reg_base + HC_RESPONSE_2));
194 INFO("rpi3_sdhost: HC_RESPONSE_3: 0x%08x\n",
195 mmio_read_32(reg_base + HC_RESPONSE_3));
196 INFO("rpi3_sdhost: HC_HOSTSTATUS: 0x%08x\n",
197 mmio_read_32(reg_base + HC_HOSTSTATUS));
198 INFO("rpi3_sdhost: HC_POWER: 0x%08x\n",
199 mmio_read_32(reg_base + HC_POWER));
200 INFO("rpi3_sdhost: HC_DEBUG: 0x%08x\n",
201 mmio_read_32(reg_base + HC_DEBUG));
202 INFO("rpi3_sdhost: HC_HOSTCONFIG: 0x%08x\n",
203 mmio_read_32(reg_base + HC_HOSTCONFIG));
204 INFO("rpi3_sdhost: HC_BLOCKSIZE: 0x%08x\n",
205 mmio_read_32(reg_base + HC_BLOCKSIZE));
206 INFO("rpi3_sdhost: HC_BLOCKCOUNT: 0x%08x\n",
207 mmio_read_32(reg_base + HC_BLOCKCOUNT));
208}
209
210/**
211 * Reset SDHOST
212 */
213static void rpi3_sdhost_reset(void)
214{
215 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
216 unsigned int dbg;
217 uint32_t tmp1;
218
219 mmio_write_32(reg_base + HC_POWER, 0);
220 mmio_write_32(reg_base + HC_COMMAND, 0);
221 mmio_write_32(reg_base + HC_ARGUMENT, 0);
222
223 mmio_write_32(reg_base + HC_TIMEOUTCOUNTER, HC_TIMEOUT_DEFAULT);
224 mmio_write_32(reg_base + HC_CLOCKDIVISOR, 0);
225 mmio_write_32(reg_base + HC_HOSTSTATUS, HC_HSTST_RESET);
226 mmio_write_32(reg_base + HC_HOSTCONFIG, 0);
227 mmio_write_32(reg_base + HC_BLOCKSIZE, 0);
228 mmio_write_32(reg_base + HC_BLOCKCOUNT, 0);
229
230 dbg = mmio_read_32(reg_base + HC_DEBUG);
231 dbg &= ~((HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_READ_SHIFT) |
232 (HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_WRITE_SHIFT));
233 dbg |= (HC_FIFO_THRESH_READ << HC_DBG_FIFO_THRESH_READ_SHIFT) |
234 (HC_FIFO_THRESH_WRITE << HC_DBG_FIFO_THRESH_WRITE_SHIFT);
235 mmio_write_32(reg_base + HC_DEBUG, dbg);
236 mdelay(250);
237 mmio_write_32(reg_base + HC_POWER, 1);
238 mdelay(250);
239 rpi3_sdhost_params.clk_rate = 0;
240
241 mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_MAXVAL);
242 tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG);
243 mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1 | HC_HSTCF_INT_BUSY);
244}
245
246static void rpi3_sdhost_initialize(void)
247{
248 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
249
250 assert((rpi3_sdhost_params.reg_base & MMC_BLOCK_MASK) == 0);
251
252 rpi3_sdhost_reset();
253
254 mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_PREFERVAL);
255 udelay(300);
256}
257
258static int rpi3_sdhost_send_cmd(struct mmc_cmd *cmd)
259{
260 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
261 int err = 0;
262 uint32_t cmd_idx;
263 uint32_t cmd_arg;
264 uint32_t cmd_flags = 0;
265 uint32_t intmask;
266
267 /* Wait for the command done */
268 err = rpi3_sdhost_waitcommand();
269 if (err != 0) {
270 WARN("previous command not done yet\n");
271 return err;
272 }
273
274 cmd_idx = cmd->cmd_idx & HC_CMD_COMMAND_MASK;
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800275
276 cmd_arg = cmd->cmd_arg;
277 if (cmd_idx == MMC_ACMD(51)) {
278 /* if previous cmd send to SDHOST is not MMC_CMD(55).
279 * It means this MMC_ACMD(51) is a resend.
280 * And we must also resend MMC_CMD(55) in this case
281 */
282 if (rpi3_sdhost_params.current_cmd != MMC_CMD(55)) {
283 send_command_decorated(
284 MMC_CMD(55),
285 rpi3_sdhost_params.sdcard_rca <<
286 RCA_SHIFT_OFFSET);
287 rpi3_sdhost_params.mmc_app_cmd = 1;
288 rpi3_sdhost_waitcommand();
289
290 /* Also we need to call prepare to clean the buffer */
291 rpi3_sdhost_prepare(0, (uintptr_t)NULL, 8);
292 }
293 }
294
295 /* We ignore MMC_CMD(12) sending from the TF-A's MMC driver
296 * because we send MMC_CMD(12) by ourselves.
297 */
298 if (cmd_idx == MMC_CMD(12))
299 return 0;
300
301 if ((cmd->resp_type & MMC_RSP_136) &&
302 (cmd->resp_type & MMC_RSP_BUSY)) {
303 ERROR("rpi3_sdhost: unsupported response type!\n");
304 return -(EOPNOTSUPP);
305 }
306
307 if (cmd->resp_type & MMC_RSP_48 && cmd->resp_type != MMC_RESPONSE_R2) {
308 /* 48-bit command
309 * We don't need to set any flags here because it is default.
310 */
311 } else if (cmd->resp_type & MMC_RSP_136) {
312 /* 136-bit command */
313 cmd_flags |= HC_CMD_RESPONSE_LONG;
314 } else {
315 /* no respond command */
316 cmd_flags |= HC_CMD_RESPONSE_NONE;
317 }
318
319 rpi3_sdhost_params.cmdbusy = 0;
320 if (cmd->resp_type & MMC_RSP_BUSY) {
321 cmd_flags |= HC_CMD_BUSY;
322 rpi3_sdhost_params.cmdbusy = 1;
323 }
324
325 if (rpi3_sdhost_params.mmc_app_cmd) {
326 switch (cmd_idx) {
327 case MMC_ACMD(41):
328 if (cmd_arg == OCR_HCS)
329 cmd_arg |= OCR_3_3_3_4;
330 break;
331 default:
332 break;
333 }
334 rpi3_sdhost_params.mmc_app_cmd = 0;
335 }
336
337 if (cmd_idx == MMC_CMD(55))
338 rpi3_sdhost_params.mmc_app_cmd = 1;
339
340 send_command_decorated(cmd_idx | cmd_flags, cmd_arg);
341
342 intmask = mmio_read_32(reg_base + HC_HOSTSTATUS);
343 if (rpi3_sdhost_params.cmdbusy && (intmask & HC_HSTST_INT_BUSY)) {
344 mmio_write_32(reg_base + HC_HOSTSTATUS, HC_HSTST_INT_BUSY);
345 rpi3_sdhost_params.cmdbusy = 0;
346 }
347
348 if (!(cmd_flags & HC_CMD_RESPONSE_NONE)) {
349 err = rpi3_sdhost_waitcommand();
350 if (err != 0)
351 ERROR("rpi3_sdhost: cmd cannot be finished\n");
352 }
353
354 cmd->resp_data[0] = mmio_read_32(reg_base + HC_RESPONSE_0);
355 cmd->resp_data[1] = mmio_read_32(reg_base + HC_RESPONSE_1);
356 cmd->resp_data[2] = mmio_read_32(reg_base + HC_RESPONSE_2);
357 cmd->resp_data[3] = mmio_read_32(reg_base + HC_RESPONSE_3);
358
359 if (mmio_read_32(reg_base + HC_COMMAND) & HC_CMD_FAILED) {
360 uint32_t sdhsts = mmio_read_32(reg_base + HC_HOSTSTATUS);
361
362 mmio_write_32(reg_base + HC_HOSTSTATUS,
363 HC_HSTST_MASK_ERROR_ALL);
364
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800365 /*
366 * If the command SEND_OP_COND returns with CRC7 error,
367 * it can be considered as having completed successfully.
368 */
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800369 if (!(sdhsts & HC_HSTST_ERROR_CRC7)
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800370 || (cmd_idx != MMC_CMD(1))) {
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800371 if (sdhsts & HC_HSTST_TIMEOUT_CMD) {
372 ERROR("rpi3_sdhost: timeout status 0x%x\n",
373 sdhsts);
374 err = -(ETIMEDOUT);
375 } else {
376 ERROR("rpi3_sdhost: unknown err, cmd = 0x%x\n",
377 mmio_read_32(reg_base + HC_COMMAND));
378 ERROR("rpi3_sdhost status: 0x%x\n", sdhsts);
379 err = -(EILSEQ);
380 }
381 }
382 }
383
384 if ((!err) && (cmd_idx == MMC_CMD(3))) {
385 /* we keep the RCA in case to send MMC_CMD(55) ourselves */
386 rpi3_sdhost_params.sdcard_rca = (cmd->resp_data[0]
387 & 0xFFFF0000U) >> 16;
388 }
389
390 return err;
391}
392
393static int rpi3_sdhost_set_clock(unsigned int clk)
394{
395 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
396 uint32_t max_clk = 250000000;
397 uint32_t div;
398
399 if (clk < 100000) {
400 mmio_write_32(reg_base + HC_CLOCKDIVISOR,
401 HC_CLOCKDIVISOR_MAXVAL);
402 return 0;
403 }
404
405 div = max_clk / clk;
406 if (div < 2)
407 div = 2;
408
409 if ((max_clk / div) > clk)
410 div++;
411
412 div -= 2;
413 if (div > HC_CLOCKDIVISOR_MAXVAL)
414 div = HC_CLOCKDIVISOR_MAXVAL;
415
416 rpi3_sdhost_params.clk_rate = max_clk / (div + 2);
417 rpi3_sdhost_params.ns_per_fifo_word = (1000000000 /
418 rpi3_sdhost_params.clk_rate)
419 * 8;
420
421 mmio_write_32(reg_base + HC_CLOCKDIVISOR, div);
422 return 0;
423}
424
425static int rpi3_sdhost_set_ios(unsigned int clk, unsigned int width)
426{
427 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
428 uint32_t tmp1;
429
430 rpi3_sdhost_set_clock(clk);
431 VERBOSE("rpi3_sdhost: Changing clock to %dHz for data mode\n", clk);
432
433 if (width != MMC_BUS_WIDTH_4 && width != MMC_BUS_WIDTH_1) {
434 ERROR("rpi3_sdhost: width %d not supported\n", width);
435 return -(EOPNOTSUPP);
436 }
437 rpi3_sdhost_params.bus_width = width;
438
439 tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG);
440 tmp1 &= ~(HC_HSTCF_EXTBUS_4BIT);
441 if (rpi3_sdhost_params.bus_width == MMC_BUS_WIDTH_4)
442 tmp1 |= HC_HSTCF_EXTBUS_4BIT;
443
444 mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1);
445 tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG);
446 mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1 |
447 HC_HSTCF_SLOW_CARD | HC_HSTCF_INTBUS_WIDE);
448
449 return 0;
450}
451
452static int rpi3_sdhost_prepare(int lba, uintptr_t buf, size_t size)
453{
454 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
455 size_t blocks;
456 size_t blocksize;
457
458 if (size < 512) {
459 blocksize = size;
460 blocks = 1;
461 } else {
462 blocksize = 512;
463 blocks = size / blocksize;
464 if (size % blocksize != 0)
465 blocks++;
466 }
467
468 rpi3_drain_fifo();
469
470 mmio_write_32(reg_base + HC_BLOCKSIZE, blocksize);
471 mmio_write_32(reg_base + HC_BLOCKCOUNT, blocks);
472 udelay(100);
473 return 0;
474}
475
476static int rpi3_sdhost_read(int lba, uintptr_t buf, size_t size)
477{
478 int err = 0;
479 uint32_t *buf1 = ((uint32_t *) buf);
480 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
481 int timeout = 100000;
482 int remaining_words = 0;
483
484 for (int i = 0; i < size / 4; i++) {
485 volatile int t = timeout;
486 uint32_t hsts_err;
487
488 while ((mmio_read_32(reg_base + HC_HOSTSTATUS)
489 & HC_HSTST_HAVEDATA) == 0) {
490 if (t == 0) {
491 ERROR("rpi3_sdhost: fifo timeout after %dus\n",
492 timeout);
493 err = -(ETIMEDOUT);
494 break;
495 }
496 t--;
497 udelay(10);
498 }
499 if (t == 0)
500 break;
501
502 uint32_t data = mmio_read_32(reg_base + HC_DATAPORT);
503
504 hsts_err = mmio_read_32(reg_base + HC_HOSTSTATUS)
505 & HC_HSTST_MASK_ERROR_ALL;
506 if (hsts_err) {
507 ERROR("rpi3_sdhost: transfer FIFO word %d: 0x%x\n",
508 i,
509 mmio_read_32(reg_base + HC_HOSTSTATUS));
510 rpi3_sdhost_print_regs();
511
512 err = -(EILSEQ);
513
514 /* clean the error status */
515 mmio_write_32(reg_base + HC_HOSTSTATUS, hsts_err);
516 }
517
518 if (buf1)
519 buf1[i] = data;
520
521 /* speeding up if the remaining words are still a lot */
522 remaining_words = (mmio_read_32(reg_base + HC_DEBUG) >> 4)
523 & HC_DBG_FIFO_THRESH_MASK;
524 if (remaining_words >= 7)
525 continue;
526
527 /* delay. slowing down the read process */
528 udelay(100);
529 }
530
531 /* We decide to stop by ourselves.
532 * It is because MMC_CMD(18) -> MMC_CMD(13) -> MMC_CMD(12)
533 * doesn't work for RPi3 SDHost.
534 */
535 if (rpi3_sdhost_params.current_cmd == MMC_CMD(18))
536 send_command_decorated(MMC_CMD(12), 0);
537
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800538 return err;
539}
540
541static int rpi3_sdhost_write(int lba, uintptr_t buf, size_t size)
542{
543 uint32_t *buf1 = ((uint32_t *) buf);
544 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
545 int err = 0;
546 int remaining_words = 0;
547
548 for (int i = 0; i < size / 4; i++) {
549 uint32_t hsts_err;
550 uint32_t data = buf1[i];
551 uint32_t dbg;
552 uint32_t fsm_state;
553
554 mmio_write_32(reg_base + HC_DATAPORT, data);
555
556 dbg = mmio_read_32(reg_base + HC_DEBUG);
557 fsm_state = dbg & HC_DBG_FSM_MASK;
558 if (fsm_state != HC_DBG_FSM_WRITEDATA
559 && fsm_state != HC_DBG_FSM_WRITESTART1
560 && fsm_state != HC_DBG_FSM_WRITESTART2
561 && fsm_state != HC_DBG_FSM_WRITECRC
562 && fsm_state != HC_DBG_FSM_WRITEWAIT1
563 && fsm_state != HC_DBG_FSM_WRITEWAIT2) {
564 hsts_err = mmio_read_32(reg_base + HC_HOSTSTATUS)
565 & HC_HSTST_MASK_ERROR_ALL;
566 if (hsts_err)
567 err = -(EILSEQ);
568 }
569
570 /* speeding up if the remaining words are not many */
571 remaining_words = (mmio_read_32(reg_base + HC_DEBUG) >> 4)
572 & HC_DBG_FIFO_THRESH_MASK;
573 if (remaining_words <= 4)
574 continue;
575
576 udelay(100);
577 }
578
579 /* We decide to stop by ourselves.
580 * It is because MMC_CMD(25) -> MMC_CMD(13) -> MMC_CMD(12)
581 * doesn't work for RPi3 SDHost.
582 */
583 if (rpi3_sdhost_params.current_cmd == MMC_CMD(25))
584 send_command_decorated(MMC_CMD(12), 0);
585
586 return err;
587}
588
589void rpi3_sdhost_init(struct rpi3_sdhost_params *params,
590 struct mmc_device_info *mmc_dev_info)
591{
592 assert((params != 0) &&
593 ((params->reg_base & MMC_BLOCK_MASK) == 0));
594
595 memcpy(&rpi3_sdhost_params, params, sizeof(struct rpi3_sdhost_params));
596
597 /* backup GPIO 48 to 53 configurations */
598 for (int i = 48; i <= 53; i++) {
599 rpi3_sdhost_params.gpio48_pinselect[i - 48]
600 = rpi3_gpio_get_select(i);
601 VERBOSE("rpi3_sdhost: Original GPIO state %d: %d\n",
602 i,
603 rpi3_sdhost_params.gpio48_pinselect[i - 48]);
604 }
605
606 /* setting pull resistors for 48 to 53.
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800607 * It is debatable to set SD_CLK to UP or NONE. We massively
608 * tested different brands of SD Cards and found NONE works
609 * most stable.
610 *
611 * GPIO 48 (SD_CLK) to GPIO_PULL_NONE
612 * GPIO 49 (SD_CMD) to GPIO_PULL_UP
613 * GPIO 50 (SD_D0) to GPIO_PULL_UP
614 * GPIO 51 (SD_D1) to GPIO_PULL_UP
615 * GPIO 52 (SD_D2) to GPIO_PULL_UP
616 * GPIO 53 (SD_D3) to GPIO_PULL_UP
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800617 */
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800618 gpio_set_pull(48, GPIO_PULL_NONE);
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800619 for (int i = 49; i <= 53; i++)
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800620 gpio_set_pull(i, GPIO_PULL_UP);
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800621
622 /* Set pin 48-53 to alt-0. It means route SDHOST to card slot */
623 for (int i = 48; i <= 53; i++)
624 rpi3_gpio_set_select(i, RPI3_GPIO_FUNC_ALT0);
625
626 mmc_init(&rpi3_sdhost_ops, params->clk_rate, params->bus_width,
627 params->flags, mmc_dev_info);
628}
629
630void rpi3_sdhost_stop(void)
631{
632 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
633
634 VERBOSE("rpi3_sdhost: Shutting down: drain FIFO out\n");
635 rpi3_drain_fifo();
636
637 VERBOSE("rpi3_sdhost: Shutting down: slowing down the clock\n");
638 mmio_write_32(reg_base+HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_SLOWVAL);
639 udelay(500);
640
641 VERBOSE("rpi3_sdhost: Shutting down: put SDHost into idle state\n");
642 send_command_decorated(MMC_CMD(0), 0);
643 udelay(500);
644
645 mmio_write_32(reg_base + HC_COMMAND, 0);
646 mmio_write_32(reg_base + HC_ARGUMENT, 0);
647 mmio_write_32(reg_base + HC_TIMEOUTCOUNTER, HC_TIMEOUT_IDLE);
648 mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_STOPVAL);
649
650 udelay(100);
651
652 mmio_write_32(reg_base + HC_POWER, 0);
653 mmio_write_32(reg_base + HC_HOSTCONFIG, 0);
654 mmio_write_32(reg_base + HC_BLOCKSIZE, 0x400);
655 mmio_write_32(reg_base + HC_BLOCKCOUNT, 0);
656 mmio_write_32(reg_base + HC_HOSTSTATUS, 0x7f8);
657
658 mmio_write_32(reg_base + HC_COMMAND, 0);
659 mmio_write_32(reg_base + HC_ARGUMENT, 0);
660
661 udelay(100);
662
663 /* Restore the pinmux to original state */
664 for (int i = 48; i <= 53; i++) {
665 rpi3_gpio_set_select(i,
666 rpi3_sdhost_params.gpio48_pinselect[i-48]);
667 }
668
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800669 /* Reset the pull resistors before entering BL33.
670 * GPIO 48 (SD_CLK) to GPIO_PULL_UP
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800671 * GPIO 49 (SD_CMD) to GPIO_PULL_UP
672 * GPIO 50 (SD_D0) to GPIO_PULL_UP
673 * GPIO 51 (SD_D1) to GPIO_PULL_UP
674 * GPIO 52 (SD_D2) to GPIO_PULL_UP
675 * GPIO 53 (SD_D3) to GPIO_PULL_UP
676 */
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800677 for (int i = 48; i <= 53; i++)
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800678 gpio_set_pull(i, GPIO_PULL_UP);
679}