blob: 90c850947baaf17cd8e9ff719b1226dfe887b0e6 [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{
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800248 assert((rpi3_sdhost_params.reg_base & MMC_BLOCK_MASK) == 0);
249
250 rpi3_sdhost_reset();
251
Rob Newberry5db30082023-03-30 10:43:21 -0700252 rpi3_sdhost_set_ios(rpi3_sdhost_params.clk_rate_initial,
253 rpi3_sdhost_params.bus_width);
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800254 udelay(300);
255}
256
257static int rpi3_sdhost_send_cmd(struct mmc_cmd *cmd)
258{
259 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
260 int err = 0;
261 uint32_t cmd_idx;
262 uint32_t cmd_arg;
263 uint32_t cmd_flags = 0;
264 uint32_t intmask;
265
266 /* Wait for the command done */
267 err = rpi3_sdhost_waitcommand();
268 if (err != 0) {
269 WARN("previous command not done yet\n");
270 return err;
271 }
272
273 cmd_idx = cmd->cmd_idx & HC_CMD_COMMAND_MASK;
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800274
275 cmd_arg = cmd->cmd_arg;
276 if (cmd_idx == MMC_ACMD(51)) {
277 /* if previous cmd send to SDHOST is not MMC_CMD(55).
278 * It means this MMC_ACMD(51) is a resend.
279 * And we must also resend MMC_CMD(55) in this case
280 */
281 if (rpi3_sdhost_params.current_cmd != MMC_CMD(55)) {
282 send_command_decorated(
283 MMC_CMD(55),
284 rpi3_sdhost_params.sdcard_rca <<
285 RCA_SHIFT_OFFSET);
286 rpi3_sdhost_params.mmc_app_cmd = 1;
287 rpi3_sdhost_waitcommand();
288
289 /* Also we need to call prepare to clean the buffer */
290 rpi3_sdhost_prepare(0, (uintptr_t)NULL, 8);
291 }
292 }
293
294 /* We ignore MMC_CMD(12) sending from the TF-A's MMC driver
295 * because we send MMC_CMD(12) by ourselves.
296 */
297 if (cmd_idx == MMC_CMD(12))
298 return 0;
299
300 if ((cmd->resp_type & MMC_RSP_136) &&
301 (cmd->resp_type & MMC_RSP_BUSY)) {
302 ERROR("rpi3_sdhost: unsupported response type!\n");
303 return -(EOPNOTSUPP);
304 }
305
306 if (cmd->resp_type & MMC_RSP_48 && cmd->resp_type != MMC_RESPONSE_R2) {
307 /* 48-bit command
308 * We don't need to set any flags here because it is default.
309 */
310 } else if (cmd->resp_type & MMC_RSP_136) {
311 /* 136-bit command */
312 cmd_flags |= HC_CMD_RESPONSE_LONG;
313 } else {
314 /* no respond command */
315 cmd_flags |= HC_CMD_RESPONSE_NONE;
316 }
317
318 rpi3_sdhost_params.cmdbusy = 0;
319 if (cmd->resp_type & MMC_RSP_BUSY) {
320 cmd_flags |= HC_CMD_BUSY;
321 rpi3_sdhost_params.cmdbusy = 1;
322 }
323
324 if (rpi3_sdhost_params.mmc_app_cmd) {
325 switch (cmd_idx) {
326 case MMC_ACMD(41):
327 if (cmd_arg == OCR_HCS)
328 cmd_arg |= OCR_3_3_3_4;
329 break;
330 default:
331 break;
332 }
333 rpi3_sdhost_params.mmc_app_cmd = 0;
334 }
335
336 if (cmd_idx == MMC_CMD(55))
337 rpi3_sdhost_params.mmc_app_cmd = 1;
338
339 send_command_decorated(cmd_idx | cmd_flags, cmd_arg);
340
341 intmask = mmio_read_32(reg_base + HC_HOSTSTATUS);
342 if (rpi3_sdhost_params.cmdbusy && (intmask & HC_HSTST_INT_BUSY)) {
343 mmio_write_32(reg_base + HC_HOSTSTATUS, HC_HSTST_INT_BUSY);
344 rpi3_sdhost_params.cmdbusy = 0;
345 }
346
347 if (!(cmd_flags & HC_CMD_RESPONSE_NONE)) {
348 err = rpi3_sdhost_waitcommand();
349 if (err != 0)
350 ERROR("rpi3_sdhost: cmd cannot be finished\n");
351 }
352
353 cmd->resp_data[0] = mmio_read_32(reg_base + HC_RESPONSE_0);
354 cmd->resp_data[1] = mmio_read_32(reg_base + HC_RESPONSE_1);
355 cmd->resp_data[2] = mmio_read_32(reg_base + HC_RESPONSE_2);
356 cmd->resp_data[3] = mmio_read_32(reg_base + HC_RESPONSE_3);
357
358 if (mmio_read_32(reg_base + HC_COMMAND) & HC_CMD_FAILED) {
359 uint32_t sdhsts = mmio_read_32(reg_base + HC_HOSTSTATUS);
360
361 mmio_write_32(reg_base + HC_HOSTSTATUS,
362 HC_HSTST_MASK_ERROR_ALL);
363
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800364 /*
365 * If the command SEND_OP_COND returns with CRC7 error,
366 * it can be considered as having completed successfully.
367 */
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800368 if (!(sdhsts & HC_HSTST_ERROR_CRC7)
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800369 || (cmd_idx != MMC_CMD(1))) {
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800370 if (sdhsts & HC_HSTST_TIMEOUT_CMD) {
371 ERROR("rpi3_sdhost: timeout status 0x%x\n",
372 sdhsts);
373 err = -(ETIMEDOUT);
374 } else {
375 ERROR("rpi3_sdhost: unknown err, cmd = 0x%x\n",
376 mmio_read_32(reg_base + HC_COMMAND));
377 ERROR("rpi3_sdhost status: 0x%x\n", sdhsts);
378 err = -(EILSEQ);
379 }
380 }
381 }
382
383 if ((!err) && (cmd_idx == MMC_CMD(3))) {
384 /* we keep the RCA in case to send MMC_CMD(55) ourselves */
385 rpi3_sdhost_params.sdcard_rca = (cmd->resp_data[0]
386 & 0xFFFF0000U) >> 16;
387 }
388
389 return err;
390}
391
392static int rpi3_sdhost_set_clock(unsigned int clk)
393{
394 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
395 uint32_t max_clk = 250000000;
396 uint32_t div;
397
398 if (clk < 100000) {
399 mmio_write_32(reg_base + HC_CLOCKDIVISOR,
400 HC_CLOCKDIVISOR_MAXVAL);
401 return 0;
402 }
403
404 div = max_clk / clk;
405 if (div < 2)
406 div = 2;
407
408 if ((max_clk / div) > clk)
409 div++;
410
411 div -= 2;
412 if (div > HC_CLOCKDIVISOR_MAXVAL)
413 div = HC_CLOCKDIVISOR_MAXVAL;
414
415 rpi3_sdhost_params.clk_rate = max_clk / (div + 2);
416 rpi3_sdhost_params.ns_per_fifo_word = (1000000000 /
417 rpi3_sdhost_params.clk_rate)
418 * 8;
419
420 mmio_write_32(reg_base + HC_CLOCKDIVISOR, div);
421 return 0;
422}
423
424static int rpi3_sdhost_set_ios(unsigned int clk, unsigned int width)
425{
426 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
427 uint32_t tmp1;
428
429 rpi3_sdhost_set_clock(clk);
430 VERBOSE("rpi3_sdhost: Changing clock to %dHz for data mode\n", clk);
431
432 if (width != MMC_BUS_WIDTH_4 && width != MMC_BUS_WIDTH_1) {
433 ERROR("rpi3_sdhost: width %d not supported\n", width);
434 return -(EOPNOTSUPP);
435 }
436 rpi3_sdhost_params.bus_width = width;
437
438 tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG);
439 tmp1 &= ~(HC_HSTCF_EXTBUS_4BIT);
440 if (rpi3_sdhost_params.bus_width == MMC_BUS_WIDTH_4)
441 tmp1 |= HC_HSTCF_EXTBUS_4BIT;
442
443 mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1);
444 tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG);
445 mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1 |
446 HC_HSTCF_SLOW_CARD | HC_HSTCF_INTBUS_WIDE);
447
448 return 0;
449}
450
451static int rpi3_sdhost_prepare(int lba, uintptr_t buf, size_t size)
452{
453 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
454 size_t blocks;
455 size_t blocksize;
456
457 if (size < 512) {
458 blocksize = size;
459 blocks = 1;
460 } else {
461 blocksize = 512;
462 blocks = size / blocksize;
463 if (size % blocksize != 0)
464 blocks++;
465 }
466
467 rpi3_drain_fifo();
468
469 mmio_write_32(reg_base + HC_BLOCKSIZE, blocksize);
470 mmio_write_32(reg_base + HC_BLOCKCOUNT, blocks);
471 udelay(100);
472 return 0;
473}
474
475static int rpi3_sdhost_read(int lba, uintptr_t buf, size_t size)
476{
477 int err = 0;
478 uint32_t *buf1 = ((uint32_t *) buf);
479 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
480 int timeout = 100000;
481 int remaining_words = 0;
482
483 for (int i = 0; i < size / 4; i++) {
484 volatile int t = timeout;
485 uint32_t hsts_err;
486
487 while ((mmio_read_32(reg_base + HC_HOSTSTATUS)
488 & HC_HSTST_HAVEDATA) == 0) {
489 if (t == 0) {
490 ERROR("rpi3_sdhost: fifo timeout after %dus\n",
491 timeout);
492 err = -(ETIMEDOUT);
493 break;
494 }
495 t--;
496 udelay(10);
497 }
498 if (t == 0)
499 break;
500
501 uint32_t data = mmio_read_32(reg_base + HC_DATAPORT);
502
503 hsts_err = mmio_read_32(reg_base + HC_HOSTSTATUS)
504 & HC_HSTST_MASK_ERROR_ALL;
505 if (hsts_err) {
506 ERROR("rpi3_sdhost: transfer FIFO word %d: 0x%x\n",
507 i,
508 mmio_read_32(reg_base + HC_HOSTSTATUS));
509 rpi3_sdhost_print_regs();
510
511 err = -(EILSEQ);
512
513 /* clean the error status */
514 mmio_write_32(reg_base + HC_HOSTSTATUS, hsts_err);
515 }
516
517 if (buf1)
518 buf1[i] = data;
519
520 /* speeding up if the remaining words are still a lot */
521 remaining_words = (mmio_read_32(reg_base + HC_DEBUG) >> 4)
522 & HC_DBG_FIFO_THRESH_MASK;
523 if (remaining_words >= 7)
524 continue;
525
526 /* delay. slowing down the read process */
527 udelay(100);
528 }
529
530 /* We decide to stop by ourselves.
531 * It is because MMC_CMD(18) -> MMC_CMD(13) -> MMC_CMD(12)
532 * doesn't work for RPi3 SDHost.
533 */
534 if (rpi3_sdhost_params.current_cmd == MMC_CMD(18))
535 send_command_decorated(MMC_CMD(12), 0);
536
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800537 return err;
538}
539
540static int rpi3_sdhost_write(int lba, uintptr_t buf, size_t size)
541{
542 uint32_t *buf1 = ((uint32_t *) buf);
543 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
544 int err = 0;
545 int remaining_words = 0;
546
547 for (int i = 0; i < size / 4; i++) {
548 uint32_t hsts_err;
549 uint32_t data = buf1[i];
550 uint32_t dbg;
551 uint32_t fsm_state;
552
553 mmio_write_32(reg_base + HC_DATAPORT, data);
554
555 dbg = mmio_read_32(reg_base + HC_DEBUG);
556 fsm_state = dbg & HC_DBG_FSM_MASK;
557 if (fsm_state != HC_DBG_FSM_WRITEDATA
558 && fsm_state != HC_DBG_FSM_WRITESTART1
559 && fsm_state != HC_DBG_FSM_WRITESTART2
560 && fsm_state != HC_DBG_FSM_WRITECRC
561 && fsm_state != HC_DBG_FSM_WRITEWAIT1
562 && fsm_state != HC_DBG_FSM_WRITEWAIT2) {
563 hsts_err = mmio_read_32(reg_base + HC_HOSTSTATUS)
564 & HC_HSTST_MASK_ERROR_ALL;
565 if (hsts_err)
566 err = -(EILSEQ);
567 }
568
569 /* speeding up if the remaining words are not many */
570 remaining_words = (mmio_read_32(reg_base + HC_DEBUG) >> 4)
571 & HC_DBG_FIFO_THRESH_MASK;
572 if (remaining_words <= 4)
573 continue;
574
575 udelay(100);
576 }
577
578 /* We decide to stop by ourselves.
579 * It is because MMC_CMD(25) -> MMC_CMD(13) -> MMC_CMD(12)
580 * doesn't work for RPi3 SDHost.
581 */
582 if (rpi3_sdhost_params.current_cmd == MMC_CMD(25))
583 send_command_decorated(MMC_CMD(12), 0);
584
585 return err;
586}
587
588void rpi3_sdhost_init(struct rpi3_sdhost_params *params,
589 struct mmc_device_info *mmc_dev_info)
590{
591 assert((params != 0) &&
592 ((params->reg_base & MMC_BLOCK_MASK) == 0));
593
594 memcpy(&rpi3_sdhost_params, params, sizeof(struct rpi3_sdhost_params));
595
596 /* backup GPIO 48 to 53 configurations */
597 for (int i = 48; i <= 53; i++) {
598 rpi3_sdhost_params.gpio48_pinselect[i - 48]
599 = rpi3_gpio_get_select(i);
600 VERBOSE("rpi3_sdhost: Original GPIO state %d: %d\n",
601 i,
602 rpi3_sdhost_params.gpio48_pinselect[i - 48]);
603 }
604
605 /* setting pull resistors for 48 to 53.
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800606 * It is debatable to set SD_CLK to UP or NONE. We massively
607 * tested different brands of SD Cards and found NONE works
608 * most stable.
609 *
610 * GPIO 48 (SD_CLK) to GPIO_PULL_NONE
611 * GPIO 49 (SD_CMD) to GPIO_PULL_UP
612 * GPIO 50 (SD_D0) to GPIO_PULL_UP
613 * GPIO 51 (SD_D1) to GPIO_PULL_UP
614 * GPIO 52 (SD_D2) to GPIO_PULL_UP
615 * GPIO 53 (SD_D3) to GPIO_PULL_UP
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800616 */
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800617 gpio_set_pull(48, GPIO_PULL_NONE);
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800618 for (int i = 49; i <= 53; i++)
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800619 gpio_set_pull(i, GPIO_PULL_UP);
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800620
621 /* Set pin 48-53 to alt-0. It means route SDHOST to card slot */
622 for (int i = 48; i <= 53; i++)
623 rpi3_gpio_set_select(i, RPI3_GPIO_FUNC_ALT0);
624
625 mmc_init(&rpi3_sdhost_ops, params->clk_rate, params->bus_width,
626 params->flags, mmc_dev_info);
627}
628
629void rpi3_sdhost_stop(void)
630{
631 uintptr_t reg_base = rpi3_sdhost_params.reg_base;
632
633 VERBOSE("rpi3_sdhost: Shutting down: drain FIFO out\n");
634 rpi3_drain_fifo();
635
636 VERBOSE("rpi3_sdhost: Shutting down: slowing down the clock\n");
637 mmio_write_32(reg_base+HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_SLOWVAL);
638 udelay(500);
639
640 VERBOSE("rpi3_sdhost: Shutting down: put SDHost into idle state\n");
641 send_command_decorated(MMC_CMD(0), 0);
642 udelay(500);
643
644 mmio_write_32(reg_base + HC_COMMAND, 0);
645 mmio_write_32(reg_base + HC_ARGUMENT, 0);
646 mmio_write_32(reg_base + HC_TIMEOUTCOUNTER, HC_TIMEOUT_IDLE);
647 mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_STOPVAL);
648
649 udelay(100);
650
651 mmio_write_32(reg_base + HC_POWER, 0);
652 mmio_write_32(reg_base + HC_HOSTCONFIG, 0);
653 mmio_write_32(reg_base + HC_BLOCKSIZE, 0x400);
654 mmio_write_32(reg_base + HC_BLOCKCOUNT, 0);
655 mmio_write_32(reg_base + HC_HOSTSTATUS, 0x7f8);
656
657 mmio_write_32(reg_base + HC_COMMAND, 0);
658 mmio_write_32(reg_base + HC_ARGUMENT, 0);
659
660 udelay(100);
661
662 /* Restore the pinmux to original state */
663 for (int i = 48; i <= 53; i++) {
664 rpi3_gpio_set_select(i,
665 rpi3_sdhost_params.gpio48_pinselect[i-48]);
666 }
667
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800668 /* Reset the pull resistors before entering BL33.
669 * GPIO 48 (SD_CLK) to GPIO_PULL_UP
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800670 * GPIO 49 (SD_CMD) to GPIO_PULL_UP
671 * GPIO 50 (SD_D0) to GPIO_PULL_UP
672 * GPIO 51 (SD_D1) to GPIO_PULL_UP
673 * GPIO 52 (SD_D2) to GPIO_PULL_UP
674 * GPIO 53 (SD_D3) to GPIO_PULL_UP
675 */
Ying-Chun Liu (PaulLiu)a5cdc082019-02-12 22:41:06 +0800676 for (int i = 48; i <= 53; i++)
Ying-Chun Liu (PaulLiu)7eee8ef2019-01-30 04:17:32 +0800677 gpio_set_pull(i, GPIO_PULL_UP);
678}