blob: 2102782add9118d3e04298a9d86b477d77285cf0 [file] [log] [blame]
Yann Gautier5380b0d2018-10-15 09:36:04 +02001/*
Yann Gautierc14205d2019-05-10 16:01:34 +02002 * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved
Yann Gautier5380b0d2018-10-15 09:36:04 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00007#include <assert.h>
8#include <errno.h>
9#include <string.h>
10
Yann Gautier5380b0d2018-10-15 09:36:04 +020011#include <arch.h>
12#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013#include <common/debug.h>
14#include <drivers/delay_timer.h>
15#include <drivers/mmc.h>
Yann Gautier038bff22019-01-17 19:17:47 +010016#include <drivers/st/stm32_gpio.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000017#include <drivers/st/stm32_sdmmc2.h>
Yann Gautiera2e2a302019-02-14 11:13:39 +010018#include <drivers/st/stm32mp_reset.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000019#include <lib/mmio.h>
20#include <lib/utils.h>
Yann Gautierc14205d2019-05-10 16:01:34 +020021#include <libfdt.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000022#include <plat/common/platform.h>
23
Yann Gautierc14205d2019-05-10 16:01:34 +020024#include <platform_def.h>
25
Yann Gautier5380b0d2018-10-15 09:36:04 +020026/* Registers offsets */
27#define SDMMC_POWER 0x00U
28#define SDMMC_CLKCR 0x04U
29#define SDMMC_ARGR 0x08U
30#define SDMMC_CMDR 0x0CU
31#define SDMMC_RESPCMDR 0x10U
32#define SDMMC_RESP1R 0x14U
33#define SDMMC_RESP2R 0x18U
34#define SDMMC_RESP3R 0x1CU
35#define SDMMC_RESP4R 0x20U
36#define SDMMC_DTIMER 0x24U
37#define SDMMC_DLENR 0x28U
38#define SDMMC_DCTRLR 0x2CU
39#define SDMMC_DCNTR 0x30U
40#define SDMMC_STAR 0x34U
41#define SDMMC_ICR 0x38U
42#define SDMMC_MASKR 0x3CU
43#define SDMMC_ACKTIMER 0x40U
44#define SDMMC_IDMACTRLR 0x50U
45#define SDMMC_IDMABSIZER 0x54U
46#define SDMMC_IDMABASE0R 0x58U
47#define SDMMC_IDMABASE1R 0x5CU
48#define SDMMC_FIFOR 0x80U
49
50/* SDMMC power control register */
51#define SDMMC_POWER_PWRCTRL GENMASK(1, 0)
Yann Gautierc14205d2019-05-10 16:01:34 +020052#define SDMMC_POWER_PWRCTRL_PWR_CYCLE BIT(1)
Yann Gautier5380b0d2018-10-15 09:36:04 +020053#define SDMMC_POWER_DIRPOL BIT(4)
54
55/* SDMMC clock control register */
56#define SDMMC_CLKCR_WIDBUS_4 BIT(14)
57#define SDMMC_CLKCR_WIDBUS_8 BIT(15)
58#define SDMMC_CLKCR_NEGEDGE BIT(16)
59#define SDMMC_CLKCR_HWFC_EN BIT(17)
60#define SDMMC_CLKCR_SELCLKRX_0 BIT(20)
61
62/* SDMMC command register */
63#define SDMMC_CMDR_CMDTRANS BIT(6)
64#define SDMMC_CMDR_CMDSTOP BIT(7)
65#define SDMMC_CMDR_WAITRESP GENMASK(9, 8)
66#define SDMMC_CMDR_WAITRESP_SHORT BIT(8)
67#define SDMMC_CMDR_WAITRESP_SHORT_NOCRC BIT(9)
68#define SDMMC_CMDR_CPSMEN BIT(12)
69
70/* SDMMC data control register */
71#define SDMMC_DCTRLR_DTEN BIT(0)
72#define SDMMC_DCTRLR_DTDIR BIT(1)
73#define SDMMC_DCTRLR_DTMODE GENMASK(3, 2)
Yann Gautier5380b0d2018-10-15 09:36:04 +020074#define SDMMC_DCTRLR_DBLOCKSIZE GENMASK(7, 4)
Yann Gautier6d9e6a02019-06-11 20:03:07 +020075#define SDMMC_DCTRLR_DBLOCKSIZE_SHIFT 4
Yann Gautier5380b0d2018-10-15 09:36:04 +020076#define SDMMC_DCTRLR_FIFORST BIT(13)
77
78#define SDMMC_DCTRLR_CLEAR_MASK (SDMMC_DCTRLR_DTEN | \
79 SDMMC_DCTRLR_DTDIR | \
80 SDMMC_DCTRLR_DTMODE | \
81 SDMMC_DCTRLR_DBLOCKSIZE)
Yann Gautier5380b0d2018-10-15 09:36:04 +020082
83/* SDMMC status register */
84#define SDMMC_STAR_CCRCFAIL BIT(0)
85#define SDMMC_STAR_DCRCFAIL BIT(1)
86#define SDMMC_STAR_CTIMEOUT BIT(2)
87#define SDMMC_STAR_DTIMEOUT BIT(3)
88#define SDMMC_STAR_TXUNDERR BIT(4)
89#define SDMMC_STAR_RXOVERR BIT(5)
90#define SDMMC_STAR_CMDREND BIT(6)
91#define SDMMC_STAR_CMDSENT BIT(7)
92#define SDMMC_STAR_DATAEND BIT(8)
93#define SDMMC_STAR_DBCKEND BIT(10)
Yann Gautiere88fdd72018-11-30 15:22:11 +010094#define SDMMC_STAR_DPSMACT BIT(12)
Yann Gautier5380b0d2018-10-15 09:36:04 +020095#define SDMMC_STAR_RXFIFOHF BIT(15)
96#define SDMMC_STAR_RXFIFOE BIT(19)
97#define SDMMC_STAR_IDMATE BIT(27)
98#define SDMMC_STAR_IDMABTC BIT(28)
99
100/* SDMMC DMA control register */
101#define SDMMC_IDMACTRLR_IDMAEN BIT(0)
102
103#define SDMMC_STATIC_FLAGS (SDMMC_STAR_CCRCFAIL | \
104 SDMMC_STAR_DCRCFAIL | \
105 SDMMC_STAR_CTIMEOUT | \
106 SDMMC_STAR_DTIMEOUT | \
107 SDMMC_STAR_TXUNDERR | \
108 SDMMC_STAR_RXOVERR | \
109 SDMMC_STAR_CMDREND | \
110 SDMMC_STAR_CMDSENT | \
111 SDMMC_STAR_DATAEND | \
112 SDMMC_STAR_DBCKEND | \
113 SDMMC_STAR_IDMATE | \
114 SDMMC_STAR_IDMABTC)
115
Etienne Carrieref02647a2019-12-08 08:14:40 +0100116#define TIMEOUT_US_1_MS 1000U
Yann Gautier2299d572019-02-14 11:14:39 +0100117#define TIMEOUT_US_10_MS 10000U
118#define TIMEOUT_US_1_S 1000000U
Yann Gautier5380b0d2018-10-15 09:36:04 +0200119
Yann Gautierc14205d2019-05-10 16:01:34 +0200120/* Power cycle delays in ms */
121#define VCC_POWER_OFF_DELAY 2
122#define VCC_POWER_ON_DELAY 2
123#define POWER_CYCLE_DELAY 2
124#define POWER_OFF_DELAY 2
125#define POWER_ON_DELAY 1
126
Yann Gautier5380b0d2018-10-15 09:36:04 +0200127#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2"
128
129static void stm32_sdmmc2_init(void);
130static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd);
131static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd);
132static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width);
133static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size);
134static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size);
135static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size);
136
137static const struct mmc_ops stm32_sdmmc2_ops = {
138 .init = stm32_sdmmc2_init,
139 .send_cmd = stm32_sdmmc2_send_cmd,
140 .set_ios = stm32_sdmmc2_set_ios,
141 .prepare = stm32_sdmmc2_prepare,
142 .read = stm32_sdmmc2_read,
143 .write = stm32_sdmmc2_write,
144};
145
146static struct stm32_sdmmc2_params sdmmc2_params;
147
148#pragma weak plat_sdmmc2_use_dma
149bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory)
150{
151 return false;
152}
153
154static void stm32_sdmmc2_init(void)
155{
156 uint32_t clock_div;
Yann Gautier3194afe2019-05-28 11:54:50 +0200157 uint32_t freq = STM32MP_MMC_INIT_FREQ;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200158 uintptr_t base = sdmmc2_params.reg_base;
159
Yann Gautier3194afe2019-05-28 11:54:50 +0200160 if (sdmmc2_params.max_freq != 0U) {
161 freq = MIN(sdmmc2_params.max_freq, freq);
162 }
163
Yann Gautierc14205d2019-05-10 16:01:34 +0200164 if (sdmmc2_params.vmmc_regu != NULL) {
165 regulator_disable(sdmmc2_params.vmmc_regu);
166 }
167
168 mdelay(VCC_POWER_OFF_DELAY);
169
170 mmio_write_32(base + SDMMC_POWER,
171 SDMMC_POWER_PWRCTRL_PWR_CYCLE | sdmmc2_params.dirpol);
172 mdelay(POWER_CYCLE_DELAY);
173
174 if (sdmmc2_params.vmmc_regu != NULL) {
175 regulator_enable(sdmmc2_params.vmmc_regu);
176 }
177
178 mdelay(VCC_POWER_ON_DELAY);
179
180 mmio_write_32(base + SDMMC_POWER, sdmmc2_params.dirpol);
181 mdelay(POWER_OFF_DELAY);
182
Yann Gautier3194afe2019-05-28 11:54:50 +0200183 clock_div = div_round_up(sdmmc2_params.clk_rate, freq * 2U);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200184
185 mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div |
186 sdmmc2_params.negedge |
187 sdmmc2_params.pin_ckin);
188
189 mmio_write_32(base + SDMMC_POWER,
190 SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol);
191
Yann Gautierc14205d2019-05-10 16:01:34 +0200192 mdelay(POWER_ON_DELAY);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200193}
194
195static int stm32_sdmmc2_stop_transfer(void)
196{
197 struct mmc_cmd cmd_stop;
198
199 zeromem(&cmd_stop, sizeof(struct mmc_cmd));
200
201 cmd_stop.cmd_idx = MMC_CMD(12);
202 cmd_stop.resp_type = MMC_RESPONSE_R1B;
203
204 return stm32_sdmmc2_send_cmd(&cmd_stop);
205}
206
207static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd)
208{
Yann Gautier2299d572019-02-14 11:14:39 +0100209 uint64_t timeout;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200210 uint32_t flags_cmd, status;
211 uint32_t flags_data = 0;
212 int err = 0;
213 uintptr_t base = sdmmc2_params.reg_base;
Yann Gautier2299d572019-02-14 11:14:39 +0100214 unsigned int cmd_reg, arg_reg;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200215
216 if (cmd == NULL) {
217 return -EINVAL;
218 }
219
220 flags_cmd = SDMMC_STAR_CTIMEOUT;
221 arg_reg = cmd->cmd_arg;
222
223 if ((mmio_read_32(base + SDMMC_CMDR) & SDMMC_CMDR_CPSMEN) != 0U) {
224 mmio_write_32(base + SDMMC_CMDR, 0);
225 }
226
227 cmd_reg = cmd->cmd_idx | SDMMC_CMDR_CPSMEN;
228
229 if (cmd->resp_type == 0U) {
230 flags_cmd |= SDMMC_STAR_CMDSENT;
231 }
232
233 if ((cmd->resp_type & MMC_RSP_48) != 0U) {
234 if ((cmd->resp_type & MMC_RSP_136) != 0U) {
235 flags_cmd |= SDMMC_STAR_CMDREND;
236 cmd_reg |= SDMMC_CMDR_WAITRESP;
237 } else if ((cmd->resp_type & MMC_RSP_CRC) != 0U) {
238 flags_cmd |= SDMMC_STAR_CMDREND | SDMMC_STAR_CCRCFAIL;
239 cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT;
240 } else {
241 flags_cmd |= SDMMC_STAR_CMDREND;
242 cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT_NOCRC;
243 }
244 }
245
246 switch (cmd->cmd_idx) {
247 case MMC_CMD(1):
248 arg_reg |= OCR_POWERUP;
249 break;
250 case MMC_CMD(8):
251 if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) {
252 cmd_reg |= SDMMC_CMDR_CMDTRANS;
253 }
254 break;
255 case MMC_CMD(12):
256 cmd_reg |= SDMMC_CMDR_CMDSTOP;
257 break;
258 case MMC_CMD(17):
259 case MMC_CMD(18):
260 cmd_reg |= SDMMC_CMDR_CMDTRANS;
261 if (sdmmc2_params.use_dma) {
262 flags_data |= SDMMC_STAR_DCRCFAIL |
263 SDMMC_STAR_DTIMEOUT |
264 SDMMC_STAR_DATAEND |
265 SDMMC_STAR_RXOVERR |
266 SDMMC_STAR_IDMATE;
267 }
268 break;
269 case MMC_ACMD(41):
270 arg_reg |= OCR_3_2_3_3 | OCR_3_3_3_4;
271 break;
272 case MMC_ACMD(51):
273 cmd_reg |= SDMMC_CMDR_CMDTRANS;
274 if (sdmmc2_params.use_dma) {
275 flags_data |= SDMMC_STAR_DCRCFAIL |
276 SDMMC_STAR_DTIMEOUT |
277 SDMMC_STAR_DATAEND |
278 SDMMC_STAR_RXOVERR |
279 SDMMC_STAR_IDMATE |
280 SDMMC_STAR_DBCKEND;
281 }
282 break;
283 default:
284 break;
285 }
286
Yann Gautier10454222020-06-12 14:14:26 +0200287 mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
288
289 /*
290 * Clear the SDMMC_DCTRLR if the command does not await data.
291 * Skip CMD55 as the next command could be data related, and
292 * the register could have been set in prepare function.
293 */
294 if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) &&
295 (cmd->cmd_idx != MMC_CMD(55))) {
296 mmio_write_32(base + SDMMC_DCTRLR, 0U);
297 }
298
Yann Gautier5380b0d2018-10-15 09:36:04 +0200299 if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) {
300 mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
301 }
302
303 mmio_write_32(base + SDMMC_ARGR, arg_reg);
304
305 mmio_write_32(base + SDMMC_CMDR, cmd_reg);
306
Yann Gautiere88fdd72018-11-30 15:22:11 +0100307 status = mmio_read_32(base + SDMMC_STAR);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200308
Yann Gautier2299d572019-02-14 11:14:39 +0100309 timeout = timeout_init_us(TIMEOUT_US_10_MS);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200310
Yann Gautiere88fdd72018-11-30 15:22:11 +0100311 while ((status & flags_cmd) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +0100312 if (timeout_elapsed(timeout)) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200313 err = -ETIMEDOUT;
314 ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n",
315 __func__, cmd->cmd_idx, status);
Yann Gautiere88fdd72018-11-30 15:22:11 +0100316 goto err_exit;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200317 }
Yann Gautier5380b0d2018-10-15 09:36:04 +0200318
Yann Gautiere88fdd72018-11-30 15:22:11 +0100319 status = mmio_read_32(base + SDMMC_STAR);
320 }
321
322 if ((status & (SDMMC_STAR_CTIMEOUT | SDMMC_STAR_CCRCFAIL)) != 0U) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200323 if ((status & SDMMC_STAR_CTIMEOUT) != 0U) {
324 err = -ETIMEDOUT;
325 /*
326 * Those timeouts can occur, and framework will handle
327 * the retries. CMD8 is expected to return this timeout
328 * for eMMC
329 */
330 if (!((cmd->cmd_idx == MMC_CMD(1)) ||
331 (cmd->cmd_idx == MMC_CMD(13)) ||
332 ((cmd->cmd_idx == MMC_CMD(8)) &&
333 (cmd->resp_type == MMC_RESPONSE_R7)))) {
334 ERROR("%s: CTIMEOUT (cmd = %d,status = %x)\n",
335 __func__, cmd->cmd_idx, status);
336 }
337 } else {
338 err = -EIO;
339 ERROR("%s: CRCFAIL (cmd = %d,status = %x)\n",
340 __func__, cmd->cmd_idx, status);
341 }
Yann Gautiere88fdd72018-11-30 15:22:11 +0100342
343 goto err_exit;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200344 }
345
Yann Gautiere88fdd72018-11-30 15:22:11 +0100346 if ((cmd_reg & SDMMC_CMDR_WAITRESP) != 0U) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200347 if ((cmd->cmd_idx == MMC_CMD(9)) &&
348 ((cmd_reg & SDMMC_CMDR_WAITRESP) == SDMMC_CMDR_WAITRESP)) {
349 /* Need to invert response to match CSD structure */
350 cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP4R);
351 cmd->resp_data[1] = mmio_read_32(base + SDMMC_RESP3R);
352 cmd->resp_data[2] = mmio_read_32(base + SDMMC_RESP2R);
353 cmd->resp_data[3] = mmio_read_32(base + SDMMC_RESP1R);
354 } else {
355 cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP1R);
356 if ((cmd_reg & SDMMC_CMDR_WAITRESP) ==
357 SDMMC_CMDR_WAITRESP) {
358 cmd->resp_data[1] = mmio_read_32(base +
359 SDMMC_RESP2R);
360 cmd->resp_data[2] = mmio_read_32(base +
361 SDMMC_RESP3R);
362 cmd->resp_data[3] = mmio_read_32(base +
363 SDMMC_RESP4R);
364 }
365 }
366 }
367
Yann Gautiere88fdd72018-11-30 15:22:11 +0100368 if (flags_data == 0U) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200369 mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
370
Yann Gautiere88fdd72018-11-30 15:22:11 +0100371 return 0;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200372 }
373
Yann Gautiere88fdd72018-11-30 15:22:11 +0100374 status = mmio_read_32(base + SDMMC_STAR);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200375
Yann Gautier2299d572019-02-14 11:14:39 +0100376 timeout = timeout_init_us(TIMEOUT_US_10_MS);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200377
Yann Gautiere88fdd72018-11-30 15:22:11 +0100378 while ((status & flags_data) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +0100379 if (timeout_elapsed(timeout)) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200380 ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n",
381 __func__, cmd->cmd_idx, status);
382 err = -ETIMEDOUT;
Yann Gautiere88fdd72018-11-30 15:22:11 +0100383 goto err_exit;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200384 }
Yann Gautiere88fdd72018-11-30 15:22:11 +0100385
386 status = mmio_read_32(base + SDMMC_STAR);
387 };
Yann Gautier5380b0d2018-10-15 09:36:04 +0200388
389 if ((status & (SDMMC_STAR_DTIMEOUT | SDMMC_STAR_DCRCFAIL |
390 SDMMC_STAR_TXUNDERR | SDMMC_STAR_RXOVERR |
391 SDMMC_STAR_IDMATE)) != 0U) {
392 ERROR("%s: Error flag (cmd = %d,status = %x)\n", __func__,
393 cmd->cmd_idx, status);
394 err = -EIO;
395 }
396
Yann Gautiere88fdd72018-11-30 15:22:11 +0100397err_exit:
Yann Gautier5380b0d2018-10-15 09:36:04 +0200398 mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
399 mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS);
400
Yann Gautier2299d572019-02-14 11:14:39 +0100401 if ((err != 0) && ((status & SDMMC_STAR_DPSMACT) != 0U)) {
Yann Gautiere88fdd72018-11-30 15:22:11 +0100402 int ret_stop = stm32_sdmmc2_stop_transfer();
403
404 if (ret_stop != 0) {
405 return ret_stop;
406 }
Yann Gautier5380b0d2018-10-15 09:36:04 +0200407 }
408
409 return err;
410}
411
412static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd)
413{
Yann Gautierdbb9f572020-06-12 12:17:17 +0200414 uint8_t retry;
415 int err;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200416
417 assert(cmd != NULL);
418
Yann Gautierdbb9f572020-06-12 12:17:17 +0200419 for (retry = 0U; retry < 3U; retry++) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200420 err = stm32_sdmmc2_send_cmd_req(cmd);
421 if (err == 0) {
Yann Gautierdbb9f572020-06-12 12:17:17 +0200422 return 0;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200423 }
424
425 if ((cmd->cmd_idx == MMC_CMD(1)) ||
426 (cmd->cmd_idx == MMC_CMD(13))) {
427 return 0; /* Retry managed by framework */
428 }
429
430 /* Command 8 is expected to fail for eMMC */
Yann Gautierdbb9f572020-06-12 12:17:17 +0200431 if (cmd->cmd_idx != MMC_CMD(8)) {
432 WARN(" CMD%u, Retry: %u, Error: %d\n",
433 cmd->cmd_idx, retry + 1U, err);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200434 }
435
Yann Gautierdbb9f572020-06-12 12:17:17 +0200436 udelay(10U);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200437 }
438
439 return err;
440}
441
442static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width)
443{
444 uintptr_t base = sdmmc2_params.reg_base;
445 uint32_t bus_cfg = 0;
Yann Gautier3194afe2019-05-28 11:54:50 +0200446 uint32_t clock_div, max_freq, freq;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200447 uint32_t clk_rate = sdmmc2_params.clk_rate;
448 uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq;
449
450 switch (width) {
451 case MMC_BUS_WIDTH_1:
452 break;
453 case MMC_BUS_WIDTH_4:
454 bus_cfg |= SDMMC_CLKCR_WIDBUS_4;
455 break;
456 case MMC_BUS_WIDTH_8:
457 bus_cfg |= SDMMC_CLKCR_WIDBUS_8;
458 break;
459 default:
460 panic();
461 break;
462 }
463
464 if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) {
465 if (max_bus_freq >= 52000000U) {
Yann Gautiera2e2a302019-02-14 11:13:39 +0100466 max_freq = STM32MP_EMMC_HIGH_SPEED_MAX_FREQ;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200467 } else {
Yann Gautiera2e2a302019-02-14 11:13:39 +0100468 max_freq = STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200469 }
470 } else {
471 if (max_bus_freq >= 50000000U) {
Yann Gautiera2e2a302019-02-14 11:13:39 +0100472 max_freq = STM32MP_SD_HIGH_SPEED_MAX_FREQ;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200473 } else {
Yann Gautiera2e2a302019-02-14 11:13:39 +0100474 max_freq = STM32MP_SD_NORMAL_SPEED_MAX_FREQ;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200475 }
476 }
477
Yann Gautier3194afe2019-05-28 11:54:50 +0200478 if (sdmmc2_params.max_freq != 0U) {
479 freq = MIN(sdmmc2_params.max_freq, max_freq);
480 } else {
481 freq = max_freq;
482 }
483
484 clock_div = div_round_up(clk_rate, freq * 2U);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200485
486 mmio_write_32(base + SDMMC_CLKCR,
487 SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg |
488 sdmmc2_params.negedge |
489 sdmmc2_params.pin_ckin);
490
491 return 0;
492}
493
494static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size)
495{
496 struct mmc_cmd cmd;
497 int ret;
498 uintptr_t base = sdmmc2_params.reg_base;
499 uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR;
Yann Gautier6d9e6a02019-06-11 20:03:07 +0200500 uint32_t arg_size;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200501
Yann Gautier6d9e6a02019-06-11 20:03:07 +0200502 assert(size != 0U);
503
504 if (size > MMC_BLOCK_SIZE) {
505 arg_size = MMC_BLOCK_SIZE;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200506 } else {
Yann Gautier6d9e6a02019-06-11 20:03:07 +0200507 arg_size = size;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200508 }
509
510 sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf);
511
512 if (sdmmc2_params.use_dma) {
513 inv_dcache_range(buf, size);
514 }
515
516 /* Prepare CMD 16*/
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100517 mmio_write_32(base + SDMMC_DTIMER, 0);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200518
519 mmio_write_32(base + SDMMC_DLENR, 0);
520
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100521 mmio_write_32(base + SDMMC_DCTRLR, 0);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200522
523 zeromem(&cmd, sizeof(struct mmc_cmd));
524
525 cmd.cmd_idx = MMC_CMD(16);
Yann Gautier6d9e6a02019-06-11 20:03:07 +0200526 cmd.cmd_arg = arg_size;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200527 cmd.resp_type = MMC_RESPONSE_R1;
528
529 ret = stm32_sdmmc2_send_cmd(&cmd);
530 if (ret != 0) {
531 ERROR("CMD16 failed\n");
532 return ret;
533 }
534
535 /* Prepare data command */
536 mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
537
538 mmio_write_32(base + SDMMC_DLENR, size);
539
540 if (sdmmc2_params.use_dma) {
541 mmio_write_32(base + SDMMC_IDMACTRLR,
542 SDMMC_IDMACTRLR_IDMAEN);
543 mmio_write_32(base + SDMMC_IDMABASE0R, buf);
544
545 flush_dcache_range(buf, size);
546 }
547
Yann Gautier6d9e6a02019-06-11 20:03:07 +0200548 data_ctrl |= __builtin_ctz(arg_size) << SDMMC_DCTRLR_DBLOCKSIZE_SHIFT;
549
Yann Gautier5380b0d2018-10-15 09:36:04 +0200550 mmio_clrsetbits_32(base + SDMMC_DCTRLR,
551 SDMMC_DCTRLR_CLEAR_MASK,
552 data_ctrl);
553
554 return 0;
555}
556
557static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size)
558{
559 uint32_t error_flags = SDMMC_STAR_RXOVERR | SDMMC_STAR_DCRCFAIL |
560 SDMMC_STAR_DTIMEOUT;
561 uint32_t flags = error_flags | SDMMC_STAR_DATAEND;
562 uint32_t status;
563 uint32_t *buffer;
564 uintptr_t base = sdmmc2_params.reg_base;
565 uintptr_t fifo_reg = base + SDMMC_FIFOR;
Yann Gautier2299d572019-02-14 11:14:39 +0100566 uint64_t timeout;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200567 int ret;
568
569 /* Assert buf is 4 bytes aligned */
570 assert((buf & GENMASK(1, 0)) == 0U);
571
572 buffer = (uint32_t *)buf;
573
574 if (sdmmc2_params.use_dma) {
575 inv_dcache_range(buf, size);
576
577 return 0;
578 }
579
580 if (size <= MMC_BLOCK_SIZE) {
581 flags |= SDMMC_STAR_DBCKEND;
582 }
583
Yann Gautier2299d572019-02-14 11:14:39 +0100584 timeout = timeout_init_us(TIMEOUT_US_1_S);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200585
586 do {
587 status = mmio_read_32(base + SDMMC_STAR);
588
589 if ((status & error_flags) != 0U) {
590 ERROR("%s: Read error (status = %x)\n", __func__,
591 status);
592 mmio_write_32(base + SDMMC_DCTRLR,
593 SDMMC_DCTRLR_FIFORST);
594
595 mmio_write_32(base + SDMMC_ICR,
596 SDMMC_STATIC_FLAGS);
597
598 ret = stm32_sdmmc2_stop_transfer();
599 if (ret != 0) {
600 return ret;
601 }
602
603 return -EIO;
604 }
605
Yann Gautier2299d572019-02-14 11:14:39 +0100606 if (timeout_elapsed(timeout)) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200607 ERROR("%s: timeout 1s (status = %x)\n",
608 __func__, status);
609 mmio_write_32(base + SDMMC_ICR,
610 SDMMC_STATIC_FLAGS);
611
612 ret = stm32_sdmmc2_stop_transfer();
613 if (ret != 0) {
614 return ret;
615 }
616
617 return -ETIMEDOUT;
618 }
619
620 if (size < (8U * sizeof(uint32_t))) {
621 if ((mmio_read_32(base + SDMMC_DCNTR) > 0U) &&
622 ((status & SDMMC_STAR_RXFIFOE) == 0U)) {
623 *buffer = mmio_read_32(fifo_reg);
624 buffer++;
625 }
626 } else if ((status & SDMMC_STAR_RXFIFOHF) != 0U) {
627 uint32_t count;
628
629 /* Read data from SDMMC Rx FIFO */
630 for (count = 0; count < 8U; count++) {
631 *buffer = mmio_read_32(fifo_reg);
632 buffer++;
633 }
634 }
635 } while ((status & flags) == 0U);
636
637 mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
638
639 if ((status & SDMMC_STAR_DPSMACT) != 0U) {
640 WARN("%s: DPSMACT=1, send stop\n", __func__);
641 return stm32_sdmmc2_stop_transfer();
642 }
643
644 return 0;
645}
646
647static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size)
648{
649 return 0;
650}
651
652static int stm32_sdmmc2_dt_get_config(void)
653{
654 int sdmmc_node;
655 void *fdt = NULL;
656 const fdt32_t *cuint;
Yann Gautiere289cb02019-11-04 14:27:23 +0100657 struct dt_node_info dt_info;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200658
659 if (fdt_get_address(&fdt) == 0) {
660 return -FDT_ERR_NOTFOUND;
661 }
662
663 if (fdt == NULL) {
664 return -FDT_ERR_NOTFOUND;
665 }
666
Yann Gautiere289cb02019-11-04 14:27:23 +0100667 sdmmc_node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT,
668 sdmmc2_params.reg_base);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200669 if (sdmmc_node == -FDT_ERR_NOTFOUND) {
670 return -FDT_ERR_NOTFOUND;
671 }
672
Yann Gautiere289cb02019-11-04 14:27:23 +0100673 dt_fill_device_info(&dt_info, sdmmc_node);
674 if (dt_info.status == DT_DISABLED) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200675 return -FDT_ERR_NOTFOUND;
676 }
677
678 if (dt_set_pinctrl_config(sdmmc_node) != 0) {
679 return -FDT_ERR_BADVALUE;
680 }
681
Yann Gautiere289cb02019-11-04 14:27:23 +0100682 sdmmc2_params.clock_id = dt_info.clock;
683 sdmmc2_params.reset_id = dt_info.reset;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200684
Yann Gautier7b7e4bf2019-01-17 19:16:03 +0100685 if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200686 sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0;
687 }
688
Yann Gautier7b7e4bf2019-01-17 19:16:03 +0100689 if ((fdt_getprop(fdt, sdmmc_node, "st,sig-dir", NULL)) != NULL) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200690 sdmmc2_params.dirpol = SDMMC_POWER_DIRPOL;
691 }
692
Yann Gautier7b7e4bf2019-01-17 19:16:03 +0100693 if ((fdt_getprop(fdt, sdmmc_node, "st,neg-edge", NULL)) != NULL) {
Yann Gautier5380b0d2018-10-15 09:36:04 +0200694 sdmmc2_params.negedge = SDMMC_CLKCR_NEGEDGE;
695 }
696
697 cuint = fdt_getprop(fdt, sdmmc_node, "bus-width", NULL);
698 if (cuint != NULL) {
699 switch (fdt32_to_cpu(*cuint)) {
700 case 4:
701 sdmmc2_params.bus_width = MMC_BUS_WIDTH_4;
702 break;
703
704 case 8:
705 sdmmc2_params.bus_width = MMC_BUS_WIDTH_8;
706 break;
707
708 default:
709 break;
710 }
711 }
712
Yann Gautier3194afe2019-05-28 11:54:50 +0200713 cuint = fdt_getprop(fdt, sdmmc_node, "max-frequency", NULL);
714 if (cuint != NULL) {
715 sdmmc2_params.max_freq = fdt32_to_cpu(*cuint);
716 }
717
Yann Gautierc14205d2019-05-10 16:01:34 +0200718 sdmmc2_params.vmmc_regu = regulator_get_by_supply_name(fdt, sdmmc_node, "vmmc");
719
Yann Gautier5380b0d2018-10-15 09:36:04 +0200720 return 0;
721}
722
723unsigned long long stm32_sdmmc2_mmc_get_device_size(void)
724{
725 return sdmmc2_params.device_info->device_size;
726}
727
728int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params)
729{
Etienne Carrieref02647a2019-12-08 08:14:40 +0100730 int rc;
731
Yann Gautier5380b0d2018-10-15 09:36:04 +0200732 assert((params != NULL) &&
733 ((params->reg_base & MMC_BLOCK_MASK) == 0U) &&
734 ((params->bus_width == MMC_BUS_WIDTH_1) ||
735 (params->bus_width == MMC_BUS_WIDTH_4) ||
736 (params->bus_width == MMC_BUS_WIDTH_8)));
737
738 memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params));
739
Yann Gautierc14205d2019-05-10 16:01:34 +0200740 sdmmc2_params.vmmc_regu = NULL;
741
Yann Gautier5380b0d2018-10-15 09:36:04 +0200742 if (stm32_sdmmc2_dt_get_config() != 0) {
743 ERROR("%s: DT error\n", __func__);
744 return -ENOMEM;
745 }
746
Yann Gautiere4a3c352019-02-14 10:53:33 +0100747 stm32mp_clk_enable(sdmmc2_params.clock_id);
Yann Gautier5380b0d2018-10-15 09:36:04 +0200748
Etienne Carrieref02647a2019-12-08 08:14:40 +0100749 rc = stm32mp_reset_assert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS);
750 if (rc != 0) {
751 panic();
752 }
Yann Gautier5380b0d2018-10-15 09:36:04 +0200753 udelay(2);
Etienne Carrieref02647a2019-12-08 08:14:40 +0100754 rc = stm32mp_reset_deassert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS);
755 if (rc != 0) {
756 panic();
757 }
Yann Gautier5380b0d2018-10-15 09:36:04 +0200758 mdelay(1);
759
Yann Gautiera2e2a302019-02-14 11:13:39 +0100760 sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id);
Yann Gautierc8fa1aa2019-03-08 10:59:00 +0100761 sdmmc2_params.device_info->ocr_voltage = OCR_3_2_3_3 | OCR_3_3_3_4;
Yann Gautier5380b0d2018-10-15 09:36:04 +0200762
763 return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate,
764 sdmmc2_params.bus_width, sdmmc2_params.flags,
765 sdmmc2_params.device_info);
766}