blob: c6f77abc5c74fdf117861a301e4c47eafac2bb43 [file] [log] [blame]
Wenbin Meidf062042021-03-25 14:37:35 +08001/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * MTK MSDC Host Controller interface specific code
4 */
5#include <assert.h>
6#include <cbmem.h>
7#include <commonlib/bsd/helpers.h>
8#include <commonlib/storage/sd_mmc.h>
Elyes HAOUAS879d04b2022-01-12 17:45:29 +01009#include <console/console.h>
Wenbin Meidf062042021-03-25 14:37:35 +080010#include <delay.h>
11#include <device/mmio.h>
12#include <lib.h>
13#include <soc/msdc.h>
14#include <string.h>
15#include <timer.h>
16
17static inline void msdc_set_field(void *reg, u32 field, u32 val)
18{
19 clrsetbits32(reg, field, val << __ffs(field));
20}
21
22/*
23 * Periodically poll an address until a condition is met or a timeout occurs
24 * @addr: Address to poll
25 * @mask: mask condition
26 * @timeout: Timeout in us, 0 means never timeout
27 *
28 * Returns 0 on success and -MSDC_NOT_READY upon a timeout.
29 */
30static int msdc_poll_timeout(void *addr, u32 mask)
31{
32 struct stopwatch timer;
33 stopwatch_init_usecs_expire(&timer, MSDC_TIMEOUT_US);
34 u32 reg;
35
36 do {
37 reg = read32(addr);
38 if (stopwatch_expired(&timer))
39 return -MSDC_NOT_READY;
40 udelay(1);
41 } while (reg & mask);
42
43 return MSDC_SUCCESS;
44}
45
46/*
47 * Wait for a bit mask in a given register. To avoid endless loops, a
48 * time-out is implemented here.
49 */
50static int msdc_wait_done(void *addr, u32 mask, u32 *status)
51{
52 struct stopwatch timer;
53 stopwatch_init_usecs_expire(&timer, CMD_TIMEOUT_MS);
54 u32 reg;
55
56 do {
57 reg = read32(addr);
58 if (stopwatch_expired(&timer)) {
59 if (status)
60 *status = reg;
61 return -MSDC_NOT_READY;
62 }
63 udelay(1);
64 } while (!(reg & mask));
65
66 if (status)
67 *status = reg;
68
69 return MSDC_SUCCESS;
70}
71
72static void msdc_reset_hw(struct msdc_ctrlr *host)
73{
74 u32 val;
75
76 setbits32(host->base + MSDC_CFG, MSDC_CFG_RST);
77 if (msdc_poll_timeout(host->base + MSDC_CFG, MSDC_CFG_RST) != MSDC_SUCCESS)
78 msdc_error("Softwave reset timeout!\n");
79
80 setbits32(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
81 if (msdc_poll_timeout(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR) != MSDC_SUCCESS)
82 msdc_error("Clear FIFO timeout!\n");
83
84 val = read32(host->base + MSDC_INT);
85 write32(host->base + MSDC_INT, val);
86}
87
88static void msdc_init_hw(struct msdc_ctrlr *host)
89{
90 /* Configure to MMC/SD mode */
91 setbits32(host->base + MSDC_CFG, MSDC_CFG_MODE);
92
93 /* Reset */
94 msdc_reset_hw(host);
95
96 /* Set PIO mode */
97 setbits32(host->base + MSDC_CFG, MSDC_CFG_PIO);
98
99 write32(host->top_base + EMMC_TOP_CONTROL, 0);
100 write32(host->top_base + EMMC_TOP_CMD, 0);
101
102 write32(host->base + MSDC_IOCON, 0);
103 clrbits32(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL);
104 write32(host->base + MSDC_PATCH_BIT, 0x403c0046);
105 msdc_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1);
106 write32(host->base + MSDC_PATCH_BIT1, 0xffff4089);
107 setbits32(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL);
108
109 msdc_set_field(host->base + MSDC_PATCH_BIT1,
110 MSDC_PATCH_BIT1_STOP_DLY, 3);
111 clrbits32(host->base + SDC_FIFO_CFG, SDC_FIFO_CFG_WRVALIDSEL);
112 clrbits32(host->base + SDC_FIFO_CFG, SDC_FIFO_CFG_RDVALIDSEL);
113
114 clrbits32(host->base + MSDC_PATCH_BIT1, (1 << 7));
115
116 msdc_set_field(host->base + MSDC_PATCH_BIT2, MSDC_PB2_RESPWAIT, 3);
117 if (host->top_base)
118 setbits32(host->top_base + EMMC_TOP_CONTROL, SDC_RX_ENH_EN);
119 else
120 setbits32(host->base + SDC_ADV_CFG0, SDC_RX_ENHANCE_EN);
121 /* Use async fifo, then no need to tune internal delay */
122 clrbits32(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGRESP);
123 setbits32(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS);
124
125 if (host->top_base) {
126 setbits32(host->top_base + EMMC_TOP_CONTROL,
127 PAD_DAT_RD_RXDLY_SEL);
128 clrbits32(host->top_base + EMMC_TOP_CONTROL, DATA_K_VALUE_SEL);
129 setbits32(host->top_base + EMMC_TOP_CMD, PAD_CMD_RD_RXDLY_SEL);
130 } else {
131 setbits32(host->base + MSDC_PAD_TUNE,
132 MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL);
133 }
134
135 /* Configure to enable SDIO mode. Otherwise, sdio cmd5 will fail. */
136 setbits32(host->base + SDC_CFG, SDC_CFG_SDIO);
137
138 /* Config SDIO device detect interrupt function */
139 clrbits32(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
140 setbits32(host->base + SDC_ADV_CFG0, SDC_DAT1_IRQ_TRIGGER);
141
142 /* Configure to default data timeout */
143 msdc_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3);
144
145 msdc_debug("init hardware done!\n");
146}
147
148static void msdc_fifo_clr(struct msdc_ctrlr *host)
149{
150 setbits32(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
151
152 if (msdc_poll_timeout(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR) != MSDC_SUCCESS)
153 msdc_error("Clear FIFO timeout!\n");
154}
155
156static u32 msdc_cmd_find_resp(struct msdc_ctrlr *host, struct mmc_command *cmd)
157{
158 switch (cmd->resp_type) {
159 case CARD_RSP_R1:
160 return 0x1;
161 case CARD_RSP_R1b:
162 return 0x7;
163 case CARD_RSP_R2:
164 return 0x2;
165 case CARD_RSP_R3:
166 return 0x3;
167 case CARD_RSP_NONE:
168 default:
169 return 0x0;
170 }
171}
172
173static bool msdc_cmd_is_ready(struct msdc_ctrlr *host)
174{
175 int ret;
176
177 ret = msdc_poll_timeout(host->base + SDC_STS, SDC_STS_CMDBUSY);
178 if (ret != MSDC_SUCCESS) {
179 msdc_error("CMD bus busy detected, SDC_STS: %#x\n",
180 read32(host->base + SDC_STS));
181 msdc_reset_hw(host);
182 return false;
183 }
184
185 ret = msdc_poll_timeout(host->base + SDC_STS, SDC_STS_SDCBUSY);
186 if (ret != MSDC_SUCCESS) {
187 msdc_error("SD controller busy detected, SDC_STS: %#x\n",
188 read32(host->base + SDC_STS));
189 msdc_reset_hw(host);
190 return false;
191 }
192
193 return true;
194}
195
196static u32 msdc_cmd_prepare_raw_cmd(struct msdc_ctrlr *host,
197 struct mmc_command *cmd,
198 struct mmc_data *data)
199{
200 u32 opcode = cmd->cmdidx;
201 u32 resp_type = msdc_cmd_find_resp(host, cmd);
202 u32 blocksize = 0;
203 u32 dtype = 0;
204 u32 rawcmd = 0;
205
206 switch (opcode) {
207 case MMC_CMD_WRITE_MULTIPLE_BLOCK:
208 case MMC_CMD_READ_MULTIPLE_BLOCK:
209 dtype = 2;
210 break;
211 case MMC_CMD_WRITE_SINGLE_BLOCK:
212 case MMC_CMD_READ_SINGLE_BLOCK:
213 case MMC_CMD_AUTO_TUNING_SEQUENCE:
214 dtype = 1;
215 break;
216 case MMC_CMD_SEND_STATUS:
217 if (data)
218 dtype = 1;
219 }
220
221 if (data) {
222 if (data->flags == DATA_FLAG_READ)
223 rawcmd |= SDC_CMD_WR;
224
225 if (data->blocks > 1)
226 dtype = 2;
227
228 blocksize = data->blocksize;
229 }
230
231 rawcmd |= (opcode << SDC_CMD_CMD_S) & SDC_CMD_CMD_M;
232 rawcmd |= (resp_type << SDC_CMD_RSPTYP_S) & SDC_CMD_RSPTYP_M;
233 rawcmd |= (blocksize << SDC_CMD_BLK_LEN_S) & SDC_CMD_BLK_LEN_M;
234 rawcmd |= (dtype << SDC_CMD_DTYPE_S) & SDC_CMD_DTYPE_M;
235
236 if (opcode == MMC_CMD_STOP_TRANSMISSION)
237 rawcmd |= SDC_CMD_STOP;
238
239 return rawcmd;
240}
241
242static int msdc_cmd_done(struct msdc_ctrlr *host, int events,
243 struct mmc_command *cmd)
244{
245 u32 *rsp = cmd->response;
246 int ret = 0;
247
248 if (cmd->resp_type & CARD_RSP_PRESENT) {
249 if (cmd->resp_type & CARD_RSP_136) {
250 rsp[0] = read32(host->base + SDC_RESP3);
251 rsp[1] = read32(host->base + SDC_RESP2);
252 rsp[2] = read32(host->base + SDC_RESP1);
253 rsp[3] = read32(host->base + SDC_RESP0);
254 } else {
255 rsp[0] = read32(host->base + SDC_RESP0);
256 }
257 }
258
259 if (!(events & MSDC_INT_CMDRDY)) {
260 if (cmd->cmdidx != MMC_CMD_AUTO_TUNING_SEQUENCE) {
261 /*
262 * should not clear fifo/interrupt as the tune data
263 * may have already come.
264 */
265 msdc_reset_hw(host);
266 }
267 if (events & MSDC_INT_CMDTMO)
268 ret = -ETIMEDOUT;
269 else
270 ret = -EIO;
271 }
272
273 return ret;
274}
275
276static int msdc_start_command(struct msdc_ctrlr *host, struct mmc_command *cmd,
277 struct mmc_data *data)
278{
279 u32 rawcmd, status;
280 u32 blocks = 0;
281 int ret;
282
283 if (!msdc_cmd_is_ready(host))
284 return -EIO;
285
286 if (read32(host->base + MSDC_FIFOCS) &
287 (MSDC_FIFOCS_TXCNT | MSDC_FIFOCS_RXCNT)) {
288 msdc_error("TX/RX FIFO non-empty before start of IO. Reset\n");
289 msdc_reset_hw(host);
290 }
291
292 msdc_fifo_clr(host);
293
294 rawcmd = msdc_cmd_prepare_raw_cmd(host, cmd, data);
295
296 if (data)
297 blocks = data->blocks;
298
299 write32(host->base + MSDC_INT, CMD_INTS_MASK);
300 write32(host->base + SDC_BLK_NUM, blocks);
301 write32(host->base + SDC_ARG, cmd->cmdarg);
302 write32(host->base + SDC_CMD, rawcmd);
303
304 ret = msdc_wait_done(host->base + MSDC_INT, CMD_INTS_MASK, &status);
305 if (ret != MSDC_SUCCESS)
306 status = MSDC_INT_CMDTMO;
307
308 return msdc_cmd_done(host, status, cmd);
309}
310
311static int msdc_send_command(struct sd_mmc_ctrlr *ctrlr,
312 struct mmc_command *cmd, struct mmc_data *data)
313{
314 struct msdc_ctrlr *host;
315
316 host = container_of(ctrlr, struct msdc_ctrlr, sd_mmc_ctrlr);
317
318 return msdc_start_command(host, cmd, data);
319}
320
321static void msdc_set_clock(struct msdc_ctrlr *host, u32 clock)
322{
323 u32 mode, mode_shift;
324 u32 div, div_mask;
325 const u32 div_width = 12;
326 u32 sclk;
327 u32 hclk = host->src_hz;
328 struct sd_mmc_ctrlr *ctrlr = &host->sd_mmc_ctrlr;
329
330 if (clock >= hclk) {
331 mode = 0x1; /* no divisor */
332 div = 0;
333 sclk = hclk;
334 } else {
335 mode = 0x0; /* use divisor */
336 if (clock >= (hclk / 2)) {
337 div = 0; /* mean div = 1/2 */
338 sclk = hclk / 2; /* sclk = clk / 2 */
339 } else {
340 div = DIV_ROUND_UP(hclk, clock * 4);
341 sclk = (hclk >> 2) / div;
342 }
343 }
344
345 div_mask = (1 << div_width) - 1;
346 mode_shift = 8 + div_width;
347 assert(div <= div_mask);
348
349 clrsetbits_le32(host->base + MSDC_CFG, (0x3 << mode_shift) | (div_mask << 8),
350 (mode << mode_shift) | (div << 8));
351 if (msdc_wait_done(host->base + MSDC_CFG, MSDC_CFG_CKSTB, NULL) != MSDC_SUCCESS)
352 msdc_error("Failed while wait clock stable!\n");
353
354 ctrlr->bus_hz = sclk;
355 msdc_debug("sclk: %d\n", sclk);
356}
357
358static void msdc_set_buswidth(struct msdc_ctrlr *host, u32 width)
359{
360 u32 val = read32(host->base + SDC_CFG);
361
362 val &= ~SDC_CFG_BUSWIDTH;
363
364 switch (width) {
365 default:
366 case 1:
367 val |= (MSDC_BUS_1BITS << 16);
368 break;
369 case 4:
370 val |= (MSDC_BUS_4BITS << 16);
371 break;
372 case 8:
373 val |= (MSDC_BUS_8BITS << 16);
374 break;
375 }
376
377 write32(host->base + SDC_CFG, val);
378 msdc_trace("Bus Width = %d\n", width);
379}
380
381static void msdc_set_ios(struct sd_mmc_ctrlr *ctrlr)
382{
383 struct msdc_ctrlr *host;
384
385 host = container_of(ctrlr, struct msdc_ctrlr, sd_mmc_ctrlr);
386
387 /* Set the clock frequency */
388 if (ctrlr->bus_hz != ctrlr->request_hz)
389 msdc_set_clock(host, ctrlr->request_hz);
390
391 msdc_set_buswidth(host, ctrlr->bus_width);
392
393}
394
395static void msdc_update_pointers(struct msdc_ctrlr *host)
396{
397 struct sd_mmc_ctrlr *ctrlr = &host->sd_mmc_ctrlr;
398
399 /* Update the routine pointers */
400 ctrlr->send_cmd = &msdc_send_command;
401 ctrlr->set_ios = &msdc_set_ios;
402
403 ctrlr->f_min = 400 * 1000;
404 ctrlr->f_max = 52 * 1000 * 1000;
405 ctrlr->bus_width = 1;
406 ctrlr->caps |= DRVR_CAP_HS | DRVR_CAP_HC;
407 ctrlr->voltages = 0x40ff8080;
408}
409
410static void add_msdc(struct msdc_ctrlr *host)
411{
412 struct sd_mmc_ctrlr *ctrlr = &host->sd_mmc_ctrlr;
413
414 msdc_update_pointers(host);
415
416 /* Initialize the MTK MSDC controller */
417 msdc_init_hw(host);
418
419 /* Display the results */
420 msdc_trace("%#010x: ctrlr->caps\n", ctrlr->caps);
421 msdc_trace("%d.%03d MHz: ctrlr->f_max\n",
422 ctrlr->f_max / 1000000,
423 (ctrlr->f_max / 1000) % 1000);
424 msdc_trace("%d.%03d MHz: ctrlr->f_min\n",
425 ctrlr->f_min / 1000000,
426 (ctrlr->f_min / 1000) % 1000);
427 msdc_trace("%#010x: ctrlr->voltages\n", ctrlr->voltages);
428}
429
430static void msdc_controller_init(struct msdc_ctrlr *host, void *base, void *top_base)
431{
432 memset(host, 0, sizeof(*host));
433 host->base = base;
434 host->top_base = top_base;
435 host->src_hz = 50 * 1000 * 1000;
436
437 add_msdc(host);
438}
439
440static void set_early_mmc_wake_status(int32_t status)
441{
442 int32_t *ms_cbmem;
443
444 ms_cbmem = cbmem_add(CBMEM_ID_MMC_STATUS, sizeof(status));
445
Elyes Haouas0f1fb8a2022-09-13 09:57:30 +0200446 if (!ms_cbmem) {
Wenbin Meidf062042021-03-25 14:37:35 +0800447 printk(BIOS_ERR,
448 "%s: Failed to add early mmc wake status to cbmem!\n",
449 __func__);
450 return;
451 }
452
453 printk(BIOS_DEBUG, "Early init status = %d\n", status);
454 *ms_cbmem = status;
455}
456
457int mtk_emmc_early_init(void *base, void *top_base)
458{
459 struct storage_media media = { 0 };
460 int err;
461 struct msdc_ctrlr msdc_host;
462 struct sd_mmc_ctrlr *mmc_ctrlr = &msdc_host.sd_mmc_ctrlr;
463
464 /* Init mtk mmc ctrlr */
465 msdc_controller_init(&msdc_host, base, top_base);
466
467 media.ctrlr = mmc_ctrlr;
468 SET_CLOCK(mmc_ctrlr, 400 * 1000);
469 SET_BUS_WIDTH(mmc_ctrlr, 1);
470
471 /* Reset emmc, send CMD0 */
472 if (sd_mmc_go_idle(&media))
473 goto out_err;
474
475 /* Send CMD1 */
476 err = mmc_send_op_cond(&media);
Wenbin Meia49460c2022-06-08 16:37:00 +0800477 if (err == 0) {
478 if (media.op_cond_response & OCR_HCS)
479 set_early_mmc_wake_status(MMC_STATUS_CMD1_READY_HCS);
480 else
481 set_early_mmc_wake_status(MMC_STATUS_CMD1_READY);
482 } else if (err == CARD_IN_PROGRESS) {
Wenbin Meidf062042021-03-25 14:37:35 +0800483 set_early_mmc_wake_status(MMC_STATUS_CMD1_IN_PROGRESS);
Wenbin Meia49460c2022-06-08 16:37:00 +0800484 } else {
Wenbin Meidf062042021-03-25 14:37:35 +0800485 goto out_err;
Wenbin Meia49460c2022-06-08 16:37:00 +0800486 }
Wenbin Meidf062042021-03-25 14:37:35 +0800487
488 return 0;
489
490out_err:
491 set_early_mmc_wake_status(MMC_STATUS_NEED_RESET);
492 return -1;
493}