blob: cdcf2e0c8fe02ca42e6d9af401a5c6034a292e06 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Andy Flemingad347bb2008-10-30 16:41:01 -05002/*
3 * Copyright 2008, Freescale Semiconductor, Inc
Yangbo Luf9049b22020-06-17 18:08:58 +08004 * Copyright 2020 NXP
Andy Flemingad347bb2008-10-30 16:41:01 -05005 * Andy Fleming
6 *
7 * Based vaguely on the Linux code
Andy Flemingad347bb2008-10-30 16:41:01 -05008 */
9
10#include <config.h>
Simon Glass655306c2020-05-10 11:39:58 -060011#include <blk.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050012#include <command.h>
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -060013#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060014#include <log.h>
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -060015#include <dm/device-internal.h>
Stephen Warrenbf0c7852014-05-23 12:47:06 -060016#include <errno.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050017#include <mmc.h>
18#include <part.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060019#include <time.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060020#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060021#include <linux/delay.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060022#include <linux/printk.h>
Peng Fan15305962016-10-11 15:08:43 +080023#include <power/regulator.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050024#include <malloc.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060025#include <memalign.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050026#include <linux/list.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060027#include <linux/printk.h>
Rabin Vincent69d4e2c2009-04-05 13:30:54 +053028#include <div64.h>
Paul Burton8d30cc92013-09-09 15:30:26 +010029#include "mmc_private.h"
Andy Flemingad347bb2008-10-30 16:41:01 -050030
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +020031#define DEFAULT_CMD6_TIMEOUT_MS 500
32
Tim Harvey728cbde2024-05-31 08:36:34 -070033/**
34 * names of emmc BOOT_PARTITION_ENABLE values
35 *
36 * Boot Area Partitions - name consistent with Linux
37 */
38const char *emmc_boot_part_names[] = {
39 "default", /* EMMC_BOOT_PART_DEFAULT */
40 "boot0", /* EMMC_BOOT_PART_BOOT1 */
41 "boot1", /* EMMC_BOOT_PART_BOOT2 */
42 "",
43 "",
44 "",
45 "",
46 "user", /* EMMC_BOOT_PART_USER */
47};
48
49/**
50 * names of emmc 'hardware partitions' consistent with:
51 * - value used in mmc_switch()
52 * - value used by PARTITION_CONFIG PARTITION_ACCESS field
53 *
54 * Boot Area Partitions - name consistent with Linux
55 * General Perpose Partitions - name consistent with 'mmc hwpartition' usage
56 */
57const char *emmc_hwpart_names[] = {
58 "user", /* EMMC_HWPART_DEFAULT */
59 "boot0", /* EMMC_HWPART_BOOT1 */
60 "boot1", /* EMMC_HWPART_BOOT2 */
61 "rpmb", /* EMMC_HWPART_RPMB */
62 "gp1", /* EMMC_HWPART_GP1 */
63 "gp2", /* EMMC_HWPART_GP2 */
64 "gp3", /* EMMC_HWPART_GP3 */
65 "gp4", /* EMMC_HWPART_GP4 */
66};
67
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +020068static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
Marek Vasutf537e392016-12-01 02:06:33 +010069
Simon Glasseba48f92017-07-29 11:35:31 -060070#if !CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020071
Sam Protsenkodb174c62019-08-14 22:52:51 +030072static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020073{
Loic Poulain9c32f4f2022-05-26 16:37:21 +020074 if (mmc->cfg->ops->wait_dat0)
75 return mmc->cfg->ops->wait_dat0(mmc, state, timeout_us);
76
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020077 return -ENOSYS;
78}
79
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +020080__weak int board_mmc_getwp(struct mmc *mmc)
Nikita Kiryanov020f2612012-12-03 02:19:46 +000081{
82 return -1;
83}
84
85int mmc_getwp(struct mmc *mmc)
86{
87 int wp;
88
89 wp = board_mmc_getwp(mmc);
90
Peter Korsgaardf7b15102013-03-21 04:00:03 +000091 if (wp < 0) {
Pantelis Antoniou2c850462014-03-11 19:34:20 +020092 if (mmc->cfg->ops->getwp)
93 wp = mmc->cfg->ops->getwp(mmc);
Peter Korsgaardf7b15102013-03-21 04:00:03 +000094 else
95 wp = 0;
96 }
Nikita Kiryanov020f2612012-12-03 02:19:46 +000097
98 return wp;
99}
100
Jeroen Hofstee47726302014-07-10 22:46:28 +0200101__weak int board_mmc_getcd(struct mmc *mmc)
102{
Stefano Babic6e00edf2010-02-05 15:04:43 +0100103 return -1;
104}
Simon Glass394dfc02016-06-12 23:30:22 -0600105#endif
Stefano Babic6e00edf2010-02-05 15:04:43 +0100106
Simon Glassb23d96e2016-06-12 23:30:20 -0600107#ifdef CONFIG_MMC_TRACE
108void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
Andy Flemingad347bb2008-10-30 16:41:01 -0500109{
Simon Glassb23d96e2016-06-12 23:30:20 -0600110 printf("CMD_SEND:%d\n", cmd->cmdidx);
Marek Vasut6eeee302019-03-23 18:54:45 +0100111 printf("\t\tARG\t\t\t 0x%08x\n", cmd->cmdarg);
Simon Glassb23d96e2016-06-12 23:30:20 -0600112}
Marek Vasutdccb6082012-03-15 18:41:35 +0000113
Simon Glassb23d96e2016-06-12 23:30:20 -0600114void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret)
115{
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000116 int i;
117 u8 *ptr;
118
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700119 if (ret) {
120 printf("\t\tRET\t\t\t %d\n", ret);
121 } else {
122 switch (cmd->resp_type) {
123 case MMC_RSP_NONE:
124 printf("\t\tMMC_RSP_NONE\n");
125 break;
126 case MMC_RSP_R1:
Marek Vasut6eeee302019-03-23 18:54:45 +0100127 printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700128 cmd->response[0]);
129 break;
130 case MMC_RSP_R1b:
Marek Vasut6eeee302019-03-23 18:54:45 +0100131 printf("\t\tMMC_RSP_R1b\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700132 cmd->response[0]);
133 break;
134 case MMC_RSP_R2:
Marek Vasut6eeee302019-03-23 18:54:45 +0100135 printf("\t\tMMC_RSP_R2\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700136 cmd->response[0]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100137 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700138 cmd->response[1]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100139 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700140 cmd->response[2]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100141 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700142 cmd->response[3]);
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000143 printf("\n");
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700144 printf("\t\t\t\t\tDUMPING DATA\n");
145 for (i = 0; i < 4; i++) {
146 int j;
147 printf("\t\t\t\t\t%03d - ", i*4);
148 ptr = (u8 *)&cmd->response[i];
149 ptr += 3;
150 for (j = 0; j < 4; j++)
Marek Vasut6eeee302019-03-23 18:54:45 +0100151 printf("%02x ", *ptr--);
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700152 printf("\n");
153 }
154 break;
155 case MMC_RSP_R3:
Marek Vasut6eeee302019-03-23 18:54:45 +0100156 printf("\t\tMMC_RSP_R3,4\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700157 cmd->response[0]);
158 break;
159 default:
160 printf("\t\tERROR MMC rsp not supported\n");
161 break;
Bin Meng4a4ef872016-03-17 21:53:13 -0700162 }
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000163 }
Simon Glassb23d96e2016-06-12 23:30:20 -0600164}
165
166void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
167{
168 int status;
169
170 status = (cmd->response[0] & MMC_STATUS_CURR_STATE) >> 9;
171 printf("CURR STATE:%d\n", status);
172}
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000173#endif
Simon Glassb23d96e2016-06-12 23:30:20 -0600174
Pali Rohár377ecee2022-04-03 00:20:10 +0200175#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG) || CONFIG_VAL(LOGLEVEL) >= LOGL_DEBUG
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200176const char *mmc_mode_name(enum bus_mode mode)
177{
178 static const char *const names[] = {
179 [MMC_LEGACY] = "MMC legacy",
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200180 [MMC_HS] = "MMC High Speed (26MHz)",
181 [SD_HS] = "SD High Speed (50MHz)",
182 [UHS_SDR12] = "UHS SDR12 (25MHz)",
183 [UHS_SDR25] = "UHS SDR25 (50MHz)",
184 [UHS_SDR50] = "UHS SDR50 (100MHz)",
185 [UHS_SDR104] = "UHS SDR104 (208MHz)",
186 [UHS_DDR50] = "UHS DDR50 (50MHz)",
187 [MMC_HS_52] = "MMC High Speed (52MHz)",
188 [MMC_DDR_52] = "MMC DDR52 (52MHz)",
189 [MMC_HS_200] = "HS200 (200MHz)",
Peng Fan46801252018-08-10 14:07:54 +0800190 [MMC_HS_400] = "HS400 (200MHz)",
Peng Faneede83b2019-07-10 14:43:07 +0800191 [MMC_HS_400_ES] = "HS400ES (200MHz)",
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200192 };
193
194 if (mode >= MMC_MODES_END)
195 return "Unknown mode";
196 else
197 return names[mode];
198}
199#endif
200
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200201static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
202{
203 static const int freqs[] = {
Jaehoon Chung7c5c7302018-01-30 14:10:16 +0900204 [MMC_LEGACY] = 25000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200205 [MMC_HS] = 26000000,
206 [SD_HS] = 50000000,
Jaehoon Chung7c5c7302018-01-30 14:10:16 +0900207 [MMC_HS_52] = 52000000,
208 [MMC_DDR_52] = 52000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200209 [UHS_SDR12] = 25000000,
210 [UHS_SDR25] = 50000000,
211 [UHS_SDR50] = 100000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200212 [UHS_DDR50] = 50000000,
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100213 [UHS_SDR104] = 208000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200214 [MMC_HS_200] = 200000000,
Peng Fan46801252018-08-10 14:07:54 +0800215 [MMC_HS_400] = 200000000,
Peng Faneede83b2019-07-10 14:43:07 +0800216 [MMC_HS_400_ES] = 200000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200217 };
218
219 if (mode == MMC_LEGACY)
220 return mmc->legacy_speed;
221 else if (mode >= MMC_MODES_END)
222 return 0;
223 else
224 return freqs[mode];
225}
226
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200227static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
228{
229 mmc->selected_mode = mode;
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200230 mmc->tran_speed = mmc_mode2freq(mmc, mode);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200231 mmc->ddr_mode = mmc_is_mode_ddr(mode);
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900232 pr_debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
233 mmc->tran_speed / 1000000);
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200234 return 0;
235}
236
Simon Glasseba48f92017-07-29 11:35:31 -0600237#if !CONFIG_IS_ENABLED(DM_MMC)
Simon Glassb23d96e2016-06-12 23:30:20 -0600238int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
239{
240 int ret;
241
242 mmmc_trace_before_send(mmc, cmd);
243 ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
244 mmmc_trace_after_send(mmc, cmd, ret);
245
Marek Vasutdccb6082012-03-15 18:41:35 +0000246 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -0500247}
Simon Glass394dfc02016-06-12 23:30:22 -0600248#endif
Andy Flemingad347bb2008-10-30 16:41:01 -0500249
Sean Anderson86325092020-10-17 08:36:27 -0400250/**
251 * mmc_send_cmd_retry() - send a command to the mmc device, retrying on error
252 *
253 * @dev: device to receive the command
254 * @cmd: command to send
255 * @data: additional data to send/receive
256 * @retries: how many times to retry; mmc_send_cmd is always called at least
257 * once
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100258 * Return: 0 if ok, -ve on error
Sean Anderson86325092020-10-17 08:36:27 -0400259 */
260static int mmc_send_cmd_retry(struct mmc *mmc, struct mmc_cmd *cmd,
261 struct mmc_data *data, uint retries)
262{
263 int ret;
264
265 do {
266 ret = mmc_send_cmd(mmc, cmd, data);
267 } while (ret && retries--);
268
269 return ret;
270}
271
272/**
273 * mmc_send_cmd_quirks() - send a command to the mmc device, retrying if a
274 * specific quirk is enabled
275 *
276 * @dev: device to receive the command
277 * @cmd: command to send
278 * @data: additional data to send/receive
279 * @quirk: retry only if this quirk is enabled
280 * @retries: how many times to retry; mmc_send_cmd is always called at least
281 * once
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100282 * Return: 0 if ok, -ve on error
Sean Anderson86325092020-10-17 08:36:27 -0400283 */
284static int mmc_send_cmd_quirks(struct mmc *mmc, struct mmc_cmd *cmd,
285 struct mmc_data *data, u32 quirk, uint retries)
286{
Simon Glass68f3ced2023-02-05 15:40:16 -0700287 if (IS_ENABLED(CONFIG_MMC_QUIRKS) && mmc->quirks & quirk)
Sean Anderson86325092020-10-17 08:36:27 -0400288 return mmc_send_cmd_retry(mmc, cmd, data, retries);
289 else
290 return mmc_send_cmd(mmc, cmd, data);
291}
292
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200293int mmc_send_status(struct mmc *mmc, unsigned int *status)
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000294{
295 struct mmc_cmd cmd;
Sean Anderson86325092020-10-17 08:36:27 -0400296 int ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000297
298 cmd.cmdidx = MMC_CMD_SEND_STATUS;
299 cmd.resp_type = MMC_RSP_R1;
Marek Vasutc4427392011-08-10 09:24:48 +0200300 if (!mmc_host_is_spi(mmc))
301 cmd.cmdarg = mmc->rca << 16;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000302
Sean Anderson86325092020-10-17 08:36:27 -0400303 ret = mmc_send_cmd_retry(mmc, &cmd, NULL, 4);
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200304 mmc_trace_state(mmc, &cmd);
Sean Anderson86325092020-10-17 08:36:27 -0400305 if (!ret)
306 *status = cmd.response[0];
307
308 return ret;
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200309}
310
Sam Protsenkodb174c62019-08-14 22:52:51 +0300311int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200312{
313 unsigned int status;
314 int err;
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +0200315
Sam Protsenkodb174c62019-08-14 22:52:51 +0300316 err = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
Jean-Jacques Hiblot4f04a322019-07-02 10:53:53 +0200317 if (err != -ENOSYS)
318 return err;
319
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200320 while (1) {
321 err = mmc_send_status(mmc, &status);
322 if (err)
323 return err;
324
325 if ((status & MMC_STATUS_RDY_FOR_DATA) &&
326 (status & MMC_STATUS_CURR_STATE) !=
327 MMC_STATE_PRG)
328 break;
329
330 if (status & MMC_STATUS_MASK) {
Simon Glass7ec24132024-09-29 19:49:48 -0600331#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -0600332 log_err("Status Error: %#08x\n", status);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100333#endif
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200334 return -ECOMM;
335 }
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000336
Sam Protsenkodb174c62019-08-14 22:52:51 +0300337 if (timeout_ms-- <= 0)
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500338 break;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000339
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500340 udelay(1000);
341 }
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000342
Sam Protsenkodb174c62019-08-14 22:52:51 +0300343 if (timeout_ms <= 0) {
Simon Glass7ec24132024-09-29 19:49:48 -0600344#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -0600345 log_err("Timeout waiting card ready\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100346#endif
Jaehoon Chung7825d202016-07-19 16:33:36 +0900347 return -ETIMEDOUT;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000348 }
349
350 return 0;
351}
352
Paul Burton8d30cc92013-09-09 15:30:26 +0100353int mmc_set_blocklen(struct mmc *mmc, int len)
Andy Flemingad347bb2008-10-30 16:41:01 -0500354{
355 struct mmc_cmd cmd;
356
Andrew Gabbasov9fc2a412014-12-01 06:59:09 -0600357 if (mmc->ddr_mode)
Jaehoon Chung38ce30b2014-05-16 13:59:54 +0900358 return 0;
359
Andy Flemingad347bb2008-10-30 16:41:01 -0500360 cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
361 cmd.resp_type = MMC_RSP_R1;
362 cmd.cmdarg = len;
Andy Flemingad347bb2008-10-30 16:41:01 -0500363
Sean Anderson86325092020-10-17 08:36:27 -0400364 return mmc_send_cmd_quirks(mmc, &cmd, NULL,
365 MMC_QUIRK_RETRY_SET_BLOCKLEN, 4);
Andy Flemingad347bb2008-10-30 16:41:01 -0500366}
367
Tom Rinidec7ea02024-05-20 13:35:03 -0600368#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200369static const u8 tuning_blk_pattern_4bit[] = {
370 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
371 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
372 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
373 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
374 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
375 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
376 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
377 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
378};
379
380static const u8 tuning_blk_pattern_8bit[] = {
381 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
382 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
383 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
384 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
385 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
386 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
387 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
388 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
389 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
390 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
391 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
392 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
393 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
394 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
395 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
396 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
397};
398
Marek Vasutdad81fb2024-02-20 09:36:23 +0100399int mmc_send_tuning(struct mmc *mmc, u32 opcode)
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200400{
401 struct mmc_cmd cmd;
402 struct mmc_data data;
403 const u8 *tuning_block_pattern;
404 int size, err;
405
406 if (mmc->bus_width == 8) {
407 tuning_block_pattern = tuning_blk_pattern_8bit;
408 size = sizeof(tuning_blk_pattern_8bit);
409 } else if (mmc->bus_width == 4) {
410 tuning_block_pattern = tuning_blk_pattern_4bit;
411 size = sizeof(tuning_blk_pattern_4bit);
412 } else {
413 return -EINVAL;
414 }
415
416 ALLOC_CACHE_ALIGN_BUFFER(u8, data_buf, size);
417
418 cmd.cmdidx = opcode;
419 cmd.cmdarg = 0;
420 cmd.resp_type = MMC_RSP_R1;
421
422 data.dest = (void *)data_buf;
423 data.blocks = 1;
424 data.blocksize = size;
425 data.flags = MMC_DATA_READ;
426
427 err = mmc_send_cmd(mmc, &cmd, &data);
428 if (err)
429 return err;
430
431 if (memcmp(data_buf, tuning_block_pattern, size))
432 return -EIO;
433
434 return 0;
435}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100436#endif
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200437
Hai Pham27abf9f2023-06-20 00:38:24 +0200438int mmc_send_stop_transmission(struct mmc *mmc, bool write)
439{
440 struct mmc_cmd cmd;
441
442 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
443 cmd.cmdarg = 0;
444 /*
445 * JEDEC Standard No. 84-B51 Page 126
446 * CMD12 STOP_TRANSMISSION R1/R1b[3]
447 * NOTE 3 R1 for read cases and R1b for write cases.
448 *
449 * Physical Layer Simplified Specification Version 9.00
450 * 7.3.1.3 Detailed Command Description
451 * CMD12 R1b
452 */
453 cmd.resp_type = (IS_SD(mmc) || write) ? MMC_RSP_R1b : MMC_RSP_R1;
454
455 return mmc_send_cmd(mmc, &cmd, NULL);
456}
457
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200458static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
Kim Phillips87ea3892012-10-29 13:34:43 +0000459 lbaint_t blkcnt)
Andy Flemingad347bb2008-10-30 16:41:01 -0500460{
461 struct mmc_cmd cmd;
462 struct mmc_data data;
463
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700464 if (blkcnt > 1)
465 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
466 else
467 cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
Andy Flemingad347bb2008-10-30 16:41:01 -0500468
469 if (mmc->high_capacity)
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700470 cmd.cmdarg = start;
Andy Flemingad347bb2008-10-30 16:41:01 -0500471 else
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700472 cmd.cmdarg = start * mmc->read_bl_len;
Andy Flemingad347bb2008-10-30 16:41:01 -0500473
474 cmd.resp_type = MMC_RSP_R1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500475
476 data.dest = dst;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700477 data.blocks = blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500478 data.blocksize = mmc->read_bl_len;
479 data.flags = MMC_DATA_READ;
480
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700481 if (mmc_send_cmd(mmc, &cmd, &data))
482 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500483
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700484 if (blkcnt > 1) {
Hai Pham27abf9f2023-06-20 00:38:24 +0200485 if (mmc_send_stop_transmission(mmc, false)) {
Simon Glass7ec24132024-09-29 19:49:48 -0600486#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -0600487 log_err("mmc fail to send stop cmd\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100488#endif
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700489 return 0;
490 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500491 }
492
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700493 return blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500494}
495
Marek Vasut31976d92020-04-04 12:45:05 +0200496#if !CONFIG_IS_ENABLED(DM_MMC)
497static int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
498{
499 if (mmc->cfg->ops->get_b_max)
500 return mmc->cfg->ops->get_b_max(mmc, dst, blkcnt);
501 else
502 return mmc->cfg->b_max;
503}
504#endif
505
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600506#if CONFIG_IS_ENABLED(BLK)
Simon Glass62e293a2016-06-12 23:30:15 -0600507ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
Simon Glass59bc6f22016-05-01 13:52:41 -0600508#else
Simon Glass62e293a2016-06-12 23:30:15 -0600509ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
510 void *dst)
Simon Glass59bc6f22016-05-01 13:52:41 -0600511#endif
Andy Flemingad347bb2008-10-30 16:41:01 -0500512{
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600513#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -0700514 struct blk_desc *block_dev = dev_get_uclass_plat(dev);
Simon Glass59bc6f22016-05-01 13:52:41 -0600515#endif
Simon Glass2f26fff2016-02-29 15:25:51 -0700516 int dev_num = block_dev->devnum;
Stephen Warren1e0f92a2015-12-07 11:38:49 -0700517 int err;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700518 lbaint_t cur, blocks_todo = blkcnt;
Marek Vasut31976d92020-04-04 12:45:05 +0200519 uint b_max;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700520
521 if (blkcnt == 0)
522 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500523
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700524 struct mmc *mmc = find_mmc_device(dev_num);
Andy Flemingad347bb2008-10-30 16:41:01 -0500525 if (!mmc)
526 return 0;
527
Marek Vasutf537e392016-12-01 02:06:33 +0100528 if (CONFIG_IS_ENABLED(MMC_TINY))
529 err = mmc_switch_part(mmc, block_dev->hwpart);
530 else
531 err = blk_dselect_hwpart(block_dev, block_dev->hwpart);
532
Stephen Warren1e0f92a2015-12-07 11:38:49 -0700533 if (err < 0)
534 return 0;
535
Simon Glasse5db1152016-05-01 13:52:35 -0600536 if ((start + blkcnt) > block_dev->lba) {
Simon Glass7ec24132024-09-29 19:49:48 -0600537#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -0600538 log_err("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
539 start + blkcnt, block_dev->lba);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100540#endif
Lei Wene1cc9c82010-09-13 22:07:27 +0800541 return 0;
542 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500543
Simon Glassa4343c42015-06-23 15:38:50 -0600544 if (mmc_set_blocklen(mmc, mmc->read_bl_len)) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900545 pr_debug("%s: Failed to set blocklen\n", __func__);
Andy Flemingad347bb2008-10-30 16:41:01 -0500546 return 0;
Simon Glassa4343c42015-06-23 15:38:50 -0600547 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500548
Marek Vasut31976d92020-04-04 12:45:05 +0200549 b_max = mmc_get_b_max(mmc, dst, blkcnt);
550
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700551 do {
Marek Vasut31976d92020-04-04 12:45:05 +0200552 cur = (blocks_todo > b_max) ? b_max : blocks_todo;
Simon Glassa4343c42015-06-23 15:38:50 -0600553 if (mmc_read_blocks(mmc, dst, start, cur) != cur) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900554 pr_debug("%s: Failed to read blocks\n", __func__);
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700555 return 0;
Simon Glassa4343c42015-06-23 15:38:50 -0600556 }
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700557 blocks_todo -= cur;
558 start += cur;
559 dst += cur * mmc->read_bl_len;
560 } while (blocks_todo > 0);
Andy Flemingad347bb2008-10-30 16:41:01 -0500561
562 return blkcnt;
563}
564
Kim Phillips87ea3892012-10-29 13:34:43 +0000565static int mmc_go_idle(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -0500566{
567 struct mmc_cmd cmd;
568 int err;
569
570 udelay(1000);
571
572 cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
573 cmd.cmdarg = 0;
574 cmd.resp_type = MMC_RSP_NONE;
Andy Flemingad347bb2008-10-30 16:41:01 -0500575
576 err = mmc_send_cmd(mmc, &cmd, NULL);
577
578 if (err)
579 return err;
580
581 udelay(2000);
582
583 return 0;
584}
585
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100586#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200587static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
588{
589 struct mmc_cmd cmd;
590 int err = 0;
591
592 /*
593 * Send CMD11 only if the request is to switch the card to
594 * 1.8V signalling.
595 */
596 if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
597 return mmc_set_signal_voltage(mmc, signal_voltage);
598
599 cmd.cmdidx = SD_CMD_SWITCH_UHS18V;
600 cmd.cmdarg = 0;
601 cmd.resp_type = MMC_RSP_R1;
602
603 err = mmc_send_cmd(mmc, &cmd, NULL);
604 if (err)
605 return err;
606
607 if (!mmc_host_is_spi(mmc) && (cmd.response[0] & MMC_STATUS_ERROR))
608 return -EIO;
609
610 /*
611 * The card should drive cmd and dat[0:3] low immediately
612 * after the response of cmd11, but wait 100 us to be sure
613 */
614 err = mmc_wait_dat0(mmc, 0, 100);
615 if (err == -ENOSYS)
616 udelay(100);
617 else if (err)
618 return -ETIMEDOUT;
619
620 /*
621 * During a signal voltage level switch, the clock must be gated
622 * for 5 ms according to the SD spec
623 */
Jaehoon Chung239cb2f2018-01-26 19:25:29 +0900624 mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200625
626 err = mmc_set_signal_voltage(mmc, signal_voltage);
627 if (err)
628 return err;
629
630 /* Keep clock gated for at least 10 ms, though spec only says 5 ms */
631 mdelay(10);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +0900632 mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200633
634 /*
635 * Failure to switch is indicated by the card holding
636 * dat[0:3] low. Wait for at least 1 ms according to spec
637 */
638 err = mmc_wait_dat0(mmc, 1, 1000);
639 if (err == -ENOSYS)
640 udelay(1000);
641 else if (err)
642 return -ETIMEDOUT;
643
644 return 0;
645}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100646#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200647
648static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
Andy Flemingad347bb2008-10-30 16:41:01 -0500649{
650 int timeout = 1000;
651 int err;
652 struct mmc_cmd cmd;
653
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500654 while (1) {
Andy Flemingad347bb2008-10-30 16:41:01 -0500655 cmd.cmdidx = MMC_CMD_APP_CMD;
656 cmd.resp_type = MMC_RSP_R1;
657 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500658
659 err = mmc_send_cmd(mmc, &cmd, NULL);
660
661 if (err)
662 return err;
663
664 cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
665 cmd.resp_type = MMC_RSP_R3;
Stefano Babicf8e9a212010-01-20 18:20:39 +0100666
667 /*
668 * Most cards do not answer if some reserved bits
669 * in the ocr are set. However, Some controller
670 * can set bit 7 (reserved for low voltages), but
671 * how to manage low voltages SD card is not yet
672 * specified.
673 */
Thomas Chou1254c3d2010-12-24 13:12:21 +0000674 cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200675 (mmc->cfg->voltages & 0xff8000);
Andy Flemingad347bb2008-10-30 16:41:01 -0500676
677 if (mmc->version == SD_VERSION_2)
678 cmd.cmdarg |= OCR_HCS;
679
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200680 if (uhs_en)
681 cmd.cmdarg |= OCR_S18R;
682
Andy Flemingad347bb2008-10-30 16:41:01 -0500683 err = mmc_send_cmd(mmc, &cmd, NULL);
684
685 if (err)
686 return err;
687
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500688 if (cmd.response[0] & OCR_BUSY)
689 break;
Andy Flemingad347bb2008-10-30 16:41:01 -0500690
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500691 if (timeout-- <= 0)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900692 return -EOPNOTSUPP;
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500693
694 udelay(1000);
695 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500696
697 if (mmc->version != SD_VERSION_2)
698 mmc->version = SD_VERSION_1_0;
699
Thomas Chou1254c3d2010-12-24 13:12:21 +0000700 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
701 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
702 cmd.resp_type = MMC_RSP_R3;
703 cmd.cmdarg = 0;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000704
705 err = mmc_send_cmd(mmc, &cmd, NULL);
706
707 if (err)
708 return err;
709 }
710
Rabin Vincentb6eed942009-04-05 13:30:56 +0530711 mmc->ocr = cmd.response[0];
Andy Flemingad347bb2008-10-30 16:41:01 -0500712
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100713#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200714 if (uhs_en && !(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)
715 == 0x41000000) {
716 err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
717 if (err)
718 return err;
719 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100720#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200721
Andy Flemingad347bb2008-10-30 16:41:01 -0500722 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
723 mmc->rca = 0;
724
725 return 0;
726}
727
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500728static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg)
Andy Flemingad347bb2008-10-30 16:41:01 -0500729{
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500730 struct mmc_cmd cmd;
Andy Flemingad347bb2008-10-30 16:41:01 -0500731 int err;
732
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500733 cmd.cmdidx = MMC_CMD_SEND_OP_COND;
734 cmd.resp_type = MMC_RSP_R3;
735 cmd.cmdarg = 0;
Rob Herring5fd3edd2015-03-23 17:56:59 -0500736 if (use_arg && !mmc_host_is_spi(mmc))
737 cmd.cmdarg = OCR_HCS |
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200738 (mmc->cfg->voltages &
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500739 (mmc->ocr & OCR_VOLTAGE_MASK)) |
740 (mmc->ocr & OCR_ACCESS_MODE);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000741
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500742 err = mmc_send_cmd(mmc, &cmd, NULL);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000743 if (err)
744 return err;
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500745 mmc->ocr = cmd.response[0];
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000746 return 0;
747}
748
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +0200749static int mmc_send_op_cond(struct mmc *mmc)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000750{
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000751 int err, i;
Haibo Chen71949512020-06-15 17:18:12 +0800752 int timeout = 1000;
Ronald Wahl5e4b3142024-12-11 21:52:00 +0100753 ulong start;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000754
Andy Flemingad347bb2008-10-30 16:41:01 -0500755 /* Some cards seem to need this */
756 mmc_go_idle(mmc);
757
Haibo Chen71949512020-06-15 17:18:12 +0800758 start = get_timer(0);
Wolfgang Denk62fb2b42021-09-27 17:42:39 +0200759 /* Asking to the card its capabilities */
Haibo Chen71949512020-06-15 17:18:12 +0800760 for (i = 0; ; i++) {
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500761 err = mmc_send_op_cond_iter(mmc, i != 0);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000762 if (err)
763 return err;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200764
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000765 /* exit if not busy (flag seems to be inverted) */
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500766 if (mmc->ocr & OCR_BUSY)
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -0500767 break;
Haibo Chen71949512020-06-15 17:18:12 +0800768
769 if (get_timer(start) > timeout)
770 return -ETIMEDOUT;
771 udelay(100);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000772 }
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -0500773 mmc->op_cond_pending = 1;
774 return 0;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000775}
Wolfgang Denk80f70212011-05-19 22:21:41 +0200776
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +0200777static int mmc_complete_op_cond(struct mmc *mmc)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000778{
779 struct mmc_cmd cmd;
780 int timeout = 1000;
Vipul Kumardbad7b42018-05-03 12:20:54 +0530781 ulong start;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000782 int err;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200783
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000784 mmc->op_cond_pending = 0;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500785 if (!(mmc->ocr & OCR_BUSY)) {
Yangbo Lu9c720612016-08-02 15:33:18 +0800786 /* Some cards seem to need this */
787 mmc_go_idle(mmc);
788
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500789 start = get_timer(0);
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500790 while (1) {
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500791 err = mmc_send_op_cond_iter(mmc, 1);
792 if (err)
793 return err;
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500794 if (mmc->ocr & OCR_BUSY)
795 break;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500796 if (get_timer(start) > timeout)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900797 return -EOPNOTSUPP;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500798 udelay(100);
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500799 }
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500800 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500801
Thomas Chou1254c3d2010-12-24 13:12:21 +0000802 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
803 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
804 cmd.resp_type = MMC_RSP_R3;
805 cmd.cmdarg = 0;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000806
807 err = mmc_send_cmd(mmc, &cmd, NULL);
808
809 if (err)
810 return err;
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500811
812 mmc->ocr = cmd.response[0];
Thomas Chou1254c3d2010-12-24 13:12:21 +0000813 }
814
Andy Flemingad347bb2008-10-30 16:41:01 -0500815 mmc->version = MMC_VERSION_UNKNOWN;
Andy Flemingad347bb2008-10-30 16:41:01 -0500816
817 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
Stephen Warrenf6545f12014-01-30 16:11:12 -0700818 mmc->rca = 1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500819
820 return 0;
821}
822
Heinrich Schuchardtbf230e12020-03-30 07:24:17 +0200823int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
Andy Flemingad347bb2008-10-30 16:41:01 -0500824{
825 struct mmc_cmd cmd;
826 struct mmc_data data;
827 int err;
828
829 /* Get the Card Status Register */
830 cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
831 cmd.resp_type = MMC_RSP_R1;
832 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500833
Yoshihiro Shimodaf6bec732012-06-07 19:09:11 +0000834 data.dest = (char *)ext_csd;
Andy Flemingad347bb2008-10-30 16:41:01 -0500835 data.blocks = 1;
Simon Glassa09c2b72013-04-03 08:54:30 +0000836 data.blocksize = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -0500837 data.flags = MMC_DATA_READ;
838
839 err = mmc_send_cmd(mmc, &cmd, &data);
840
841 return err;
842}
843
Marek Vasut8a966472019-02-06 11:34:27 +0100844static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
845 bool send_status)
Andy Flemingad347bb2008-10-30 16:41:01 -0500846{
Ronald Wahl5e4b3142024-12-11 21:52:00 +0100847 ulong start;
848 unsigned int status;
Andy Flemingad347bb2008-10-30 16:41:01 -0500849 struct mmc_cmd cmd;
Sam Protsenkodb174c62019-08-14 22:52:51 +0300850 int timeout_ms = DEFAULT_CMD6_TIMEOUT_MS;
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +0200851 bool is_part_switch = (set == EXT_CSD_CMD_SET_NORMAL) &&
852 (index == EXT_CSD_PART_CONF);
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000853 int ret;
Andy Flemingad347bb2008-10-30 16:41:01 -0500854
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +0200855 if (mmc->gen_cmd6_time)
Sam Protsenkodb174c62019-08-14 22:52:51 +0300856 timeout_ms = mmc->gen_cmd6_time * 10;
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +0200857
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +0200858 if (is_part_switch && mmc->part_switch_time)
Sam Protsenkodb174c62019-08-14 22:52:51 +0300859 timeout_ms = mmc->part_switch_time * 10;
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +0200860
Andy Flemingad347bb2008-10-30 16:41:01 -0500861 cmd.cmdidx = MMC_CMD_SWITCH;
862 cmd.resp_type = MMC_RSP_R1b;
863 cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000864 (index << 16) |
865 (value << 8);
Andy Flemingad347bb2008-10-30 16:41:01 -0500866
Sean Anderson86325092020-10-17 08:36:27 -0400867 ret = mmc_send_cmd_retry(mmc, &cmd, NULL, 3);
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200868 if (ret)
869 return ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000870
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200871 start = get_timer(0);
Marek Vasut8a966472019-02-06 11:34:27 +0100872
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200873 /* poll dat0 for rdy/buys status */
Sam Protsenkodb174c62019-08-14 22:52:51 +0300874 ret = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200875 if (ret && ret != -ENOSYS)
876 return ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000877
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200878 /*
Kirill Kapranovcd9ea642021-10-09 23:49:59 +0300879 * In cases when neiter allowed to poll by using CMD13 nor we are
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200880 * capable of polling by using mmc_wait_dat0, then rely on waiting the
881 * stated timeout to be sufficient.
882 */
Kirill Kapranovcd9ea642021-10-09 23:49:59 +0300883 if (ret == -ENOSYS && !send_status) {
Sam Protsenkodb174c62019-08-14 22:52:51 +0300884 mdelay(timeout_ms);
Haibo Chend8de5e42020-09-22 18:11:42 +0800885 return 0;
886 }
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200887
Marek Vasut946e06f2022-07-15 01:58:24 +0200888 if (!send_status)
889 return 0;
890
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200891 /* Finally wait until the card is ready or indicates a failure
892 * to switch. It doesn't hurt to use CMD13 here even if send_status
Sam Protsenkodb174c62019-08-14 22:52:51 +0300893 * is false, because by now (after 'timeout_ms' ms) the bus should be
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200894 * reliable.
895 */
896 do {
897 ret = mmc_send_status(mmc, &status);
898
899 if (!ret && (status & MMC_STATUS_SWITCH_ERROR)) {
900 pr_debug("switch failed %d/%d/0x%x !\n", set, index,
901 value);
902 return -EIO;
903 }
Stefan Boscha463bbe2021-01-23 13:37:41 +0100904 if (!ret && (status & MMC_STATUS_RDY_FOR_DATA) &&
905 (status & MMC_STATUS_CURR_STATE) == MMC_STATE_TRANS)
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200906 return 0;
907 udelay(100);
Sam Protsenkodb174c62019-08-14 22:52:51 +0300908 } while (get_timer(start) < timeout_ms);
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000909
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200910 return -ETIMEDOUT;
Andy Flemingad347bb2008-10-30 16:41:01 -0500911}
912
Marek Vasut8a966472019-02-06 11:34:27 +0100913int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
914{
915 return __mmc_switch(mmc, set, index, value, true);
916}
917
Heinrich Schuchardt75e5a642020-03-30 07:24:19 +0200918int mmc_boot_wp(struct mmc *mmc)
919{
920 return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, 1);
921}
922
Ying-Chun Liu (PaulLiu)4493cb52022-04-25 21:59:02 +0800923int mmc_boot_wp_single_partition(struct mmc *mmc, int partition)
924{
925 u8 value;
926 int ret;
927
928 value = EXT_CSD_BOOT_WP_B_PWR_WP_EN;
929
930 if (partition == 0) {
931 value |= EXT_CSD_BOOT_WP_B_SEC_WP_SEL;
932 ret = mmc_switch(mmc,
933 EXT_CSD_CMD_SET_NORMAL,
934 EXT_CSD_BOOT_WP,
935 value);
936 } else if (partition == 1) {
937 value |= EXT_CSD_BOOT_WP_B_SEC_WP_SEL;
938 value |= EXT_CSD_BOOT_WP_B_PWR_WP_SEC_SEL;
939 ret = mmc_switch(mmc,
940 EXT_CSD_CMD_SET_NORMAL,
941 EXT_CSD_BOOT_WP,
942 value);
943 } else {
944 ret = mmc_boot_wp(mmc);
945 }
946
947 return ret;
948}
949
Marek Vasuta318a7a2018-04-15 00:37:11 +0200950#if !CONFIG_IS_ENABLED(MMC_TINY)
Marek Vasut111572f2019-01-03 21:19:24 +0100951static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode,
952 bool hsdowngrade)
Andy Flemingad347bb2008-10-30 16:41:01 -0500953{
Andy Flemingad347bb2008-10-30 16:41:01 -0500954 int err;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200955 int speed_bits;
956
957 ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
958
959 switch (mode) {
960 case MMC_HS:
961 case MMC_HS_52:
962 case MMC_DDR_52:
963 speed_bits = EXT_CSD_TIMING_HS;
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +0200964 break;
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +0100965#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +0200966 case MMC_HS_200:
967 speed_bits = EXT_CSD_TIMING_HS200;
968 break;
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +0100969#endif
Peng Fan46801252018-08-10 14:07:54 +0800970#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
971 case MMC_HS_400:
972 speed_bits = EXT_CSD_TIMING_HS400;
973 break;
974#endif
Peng Faneede83b2019-07-10 14:43:07 +0800975#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
976 case MMC_HS_400_ES:
977 speed_bits = EXT_CSD_TIMING_HS400;
978 break;
979#endif
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200980 case MMC_LEGACY:
981 speed_bits = EXT_CSD_TIMING_LEGACY;
982 break;
983 default:
984 return -EINVAL;
985 }
Marek Vasut8a966472019-02-06 11:34:27 +0100986
987 err = __mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
988 speed_bits, !hsdowngrade);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200989 if (err)
990 return err;
991
Marek Vasut111572f2019-01-03 21:19:24 +0100992#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
993 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
994 /*
995 * In case the eMMC is in HS200/HS400 mode and we are downgrading
996 * to HS mode, the card clock are still running much faster than
997 * the supported HS mode clock, so we can not reliably read out
998 * Extended CSD. Reconfigure the controller to run at HS mode.
999 */
1000 if (hsdowngrade) {
Venkatesh Yadav Abbarapu10f9def2024-04-23 11:00:57 +05301001 mmc_select_mode(mmc, MMC_HS_52);
1002 mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS_52), false);
Marek Vasut111572f2019-01-03 21:19:24 +01001003 }
1004#endif
1005
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001006 if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
1007 /* Now check to see that it worked */
1008 err = mmc_send_ext_csd(mmc, test_csd);
1009 if (err)
1010 return err;
1011
1012 /* No high-speed support */
1013 if (!test_csd[EXT_CSD_HS_TIMING])
1014 return -ENOTSUPP;
1015 }
1016
1017 return 0;
1018}
1019
1020static int mmc_get_capabilities(struct mmc *mmc)
1021{
1022 u8 *ext_csd = mmc->ext_csd;
1023 char cardtype;
Andy Flemingad347bb2008-10-30 16:41:01 -05001024
Jean-Jacques Hiblot3f2ffc22017-11-30 17:43:56 +01001025 mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05001026
Thomas Chou1254c3d2010-12-24 13:12:21 +00001027 if (mmc_host_is_spi(mmc))
1028 return 0;
1029
Andy Flemingad347bb2008-10-30 16:41:01 -05001030 /* Only version 4 supports high-speed */
1031 if (mmc->version < MMC_VERSION_4)
1032 return 0;
1033
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001034 if (!ext_csd) {
Simon Glass367e3852024-08-22 07:54:55 -06001035 log_err("No ext_csd found!\n"); /* this should never happen */
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001036 return -ENOTSUPP;
1037 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001038
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001039 mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
Andy Flemingad347bb2008-10-30 16:41:01 -05001040
Peng Fan46801252018-08-10 14:07:54 +08001041 cardtype = ext_csd[EXT_CSD_CARD_TYPE];
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001042 mmc->cardtype = cardtype;
Andy Flemingad347bb2008-10-30 16:41:01 -05001043
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001044#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001045 if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
1046 EXT_CSD_CARD_TYPE_HS200_1_8V)) {
1047 mmc->card_caps |= MMC_MODE_HS200;
1048 }
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001049#endif
Peng Faneede83b2019-07-10 14:43:07 +08001050#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
1051 CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
Peng Fan46801252018-08-10 14:07:54 +08001052 if (cardtype & (EXT_CSD_CARD_TYPE_HS400_1_2V |
1053 EXT_CSD_CARD_TYPE_HS400_1_8V)) {
1054 mmc->card_caps |= MMC_MODE_HS400;
1055 }
1056#endif
Jaehoon Chung38ce30b2014-05-16 13:59:54 +09001057 if (cardtype & EXT_CSD_CARD_TYPE_52) {
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001058 if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
Jaehoon Chung38ce30b2014-05-16 13:59:54 +09001059 mmc->card_caps |= MMC_MODE_DDR_52MHz;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001060 mmc->card_caps |= MMC_MODE_HS_52MHz;
Jaehoon Chung38ce30b2014-05-16 13:59:54 +09001061 }
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001062 if (cardtype & EXT_CSD_CARD_TYPE_26)
1063 mmc->card_caps |= MMC_MODE_HS;
Andy Flemingad347bb2008-10-30 16:41:01 -05001064
Peng Faneede83b2019-07-10 14:43:07 +08001065#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
1066 if (ext_csd[EXT_CSD_STROBE_SUPPORT] &&
1067 (mmc->card_caps & MMC_MODE_HS400)) {
1068 mmc->card_caps |= MMC_MODE_HS400_ES;
1069 }
1070#endif
1071
Andy Flemingad347bb2008-10-30 16:41:01 -05001072 return 0;
1073}
Marek Vasuta318a7a2018-04-15 00:37:11 +02001074#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001075
Stephen Warrene315ae82013-06-11 15:14:01 -06001076static int mmc_set_capacity(struct mmc *mmc, int part_num)
1077{
1078 switch (part_num) {
1079 case 0:
1080 mmc->capacity = mmc->capacity_user;
1081 break;
1082 case 1:
1083 case 2:
1084 mmc->capacity = mmc->capacity_boot;
1085 break;
1086 case 3:
1087 mmc->capacity = mmc->capacity_rpmb;
1088 break;
1089 case 4:
1090 case 5:
1091 case 6:
1092 case 7:
1093 mmc->capacity = mmc->capacity_gp[part_num - 4];
1094 break;
1095 default:
1096 return -1;
1097 }
1098
Simon Glasse5db1152016-05-01 13:52:35 -06001099 mmc_get_blk_desc(mmc)->lba = lldiv(mmc->capacity, mmc->read_bl_len);
Stephen Warrene315ae82013-06-11 15:14:01 -06001100
1101 return 0;
1102}
1103
Simon Glass62e293a2016-06-12 23:30:15 -06001104int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
Lei Wen31b99802011-05-02 16:26:26 +00001105{
Stephen Warrene315ae82013-06-11 15:14:01 -06001106 int ret;
Jean-Jacques Hiblotfaf5c952019-07-02 10:53:58 +02001107 int retry = 3;
Lei Wen31b99802011-05-02 16:26:26 +00001108
Jean-Jacques Hiblotfaf5c952019-07-02 10:53:58 +02001109 do {
1110 ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1111 EXT_CSD_PART_CONF,
1112 (mmc->part_config & ~PART_ACCESS_MASK)
1113 | (part_num & PART_ACCESS_MASK));
1114 } while (ret && retry--);
Peter Bigot45fde892014-09-02 18:31:23 -05001115
1116 /*
1117 * Set the capacity if the switch succeeded or was intended
1118 * to return to representing the raw device.
1119 */
Stephen Warren1e0f92a2015-12-07 11:38:49 -07001120 if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) {
Peter Bigot45fde892014-09-02 18:31:23 -05001121 ret = mmc_set_capacity(mmc, part_num);
Simon Glass984db5d2016-05-01 13:52:37 -06001122 mmc_get_blk_desc(mmc)->hwpart = part_num;
Stephen Warren1e0f92a2015-12-07 11:38:49 -07001123 }
Stephen Warrene315ae82013-06-11 15:14:01 -06001124
Peter Bigot45fde892014-09-02 18:31:23 -05001125 return ret;
Lei Wen31b99802011-05-02 16:26:26 +00001126}
1127
Jean-Jacques Hiblot1d7769a2017-11-30 17:44:02 +01001128#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001129int mmc_hwpart_config(struct mmc *mmc,
1130 const struct mmc_hwpart_conf *conf,
1131 enum mmc_hwpart_conf_mode mode)
1132{
1133 u8 part_attrs = 0;
1134 u32 enh_size_mult;
1135 u32 enh_start_addr;
1136 u32 gp_size_mult[4];
1137 u32 max_enh_size_mult;
1138 u32 tot_enh_size_mult = 0;
Diego Santa Cruz80200272014-12-23 10:50:31 +01001139 u8 wr_rel_set;
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001140 int i, pidx, err;
1141 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
1142
1143 if (mode < MMC_HWPART_CONF_CHECK || mode > MMC_HWPART_CONF_COMPLETE)
1144 return -EINVAL;
1145
1146 if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4_41)) {
Simon Glass367e3852024-08-22 07:54:55 -06001147 log_err("eMMC >= 4.4 required for enhanced user data area\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001148 return -EMEDIUMTYPE;
1149 }
1150
1151 if (!(mmc->part_support & PART_SUPPORT)) {
Simon Glass367e3852024-08-22 07:54:55 -06001152 log_err("Card does not support partitioning\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001153 return -EMEDIUMTYPE;
1154 }
1155
1156 if (!mmc->hc_wp_grp_size) {
Simon Glass367e3852024-08-22 07:54:55 -06001157 log_err("Card does not define HC WP group size\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001158 return -EMEDIUMTYPE;
1159 }
1160
1161 /* check partition alignment and total enhanced size */
1162 if (conf->user.enh_size) {
1163 if (conf->user.enh_size % mmc->hc_wp_grp_size ||
1164 conf->user.enh_start % mmc->hc_wp_grp_size) {
Simon Glass367e3852024-08-22 07:54:55 -06001165 log_err("User data enhanced area not HC WP group size aligned\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001166 return -EINVAL;
1167 }
1168 part_attrs |= EXT_CSD_ENH_USR;
1169 enh_size_mult = conf->user.enh_size / mmc->hc_wp_grp_size;
1170 if (mmc->high_capacity) {
1171 enh_start_addr = conf->user.enh_start;
1172 } else {
1173 enh_start_addr = (conf->user.enh_start << 9);
1174 }
1175 } else {
1176 enh_size_mult = 0;
1177 enh_start_addr = 0;
1178 }
1179 tot_enh_size_mult += enh_size_mult;
1180
1181 for (pidx = 0; pidx < 4; pidx++) {
1182 if (conf->gp_part[pidx].size % mmc->hc_wp_grp_size) {
Simon Glass367e3852024-08-22 07:54:55 -06001183 log_err("GP%i partition not HC WP group-size aligned\n",
1184 pidx + 1);
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001185 return -EINVAL;
1186 }
1187 gp_size_mult[pidx] = conf->gp_part[pidx].size / mmc->hc_wp_grp_size;
1188 if (conf->gp_part[pidx].size && conf->gp_part[pidx].enhanced) {
1189 part_attrs |= EXT_CSD_ENH_GP(pidx);
1190 tot_enh_size_mult += gp_size_mult[pidx];
1191 }
1192 }
1193
1194 if (part_attrs && ! (mmc->part_support & ENHNCD_SUPPORT)) {
Simon Glass367e3852024-08-22 07:54:55 -06001195 log_err("Card does not support enhanced attribute\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001196 return -EMEDIUMTYPE;
1197 }
1198
1199 err = mmc_send_ext_csd(mmc, ext_csd);
1200 if (err)
1201 return err;
1202
1203 max_enh_size_mult =
1204 (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT+2] << 16) +
1205 (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT+1] << 8) +
1206 ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT];
1207 if (tot_enh_size_mult > max_enh_size_mult) {
Simon Glass367e3852024-08-22 07:54:55 -06001208 log_err("Total enhanced size exceeds maximum (%#x > %#x)\n",
1209 tot_enh_size_mult, max_enh_size_mult);
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001210 return -EMEDIUMTYPE;
1211 }
1212
Diego Santa Cruz80200272014-12-23 10:50:31 +01001213 /* The default value of EXT_CSD_WR_REL_SET is device
1214 * dependent, the values can only be changed if the
1215 * EXT_CSD_HS_CTRL_REL bit is set. The values can be
1216 * changed only once and before partitioning is completed. */
1217 wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
1218 if (conf->user.wr_rel_change) {
1219 if (conf->user.wr_rel_set)
1220 wr_rel_set |= EXT_CSD_WR_DATA_REL_USR;
1221 else
1222 wr_rel_set &= ~EXT_CSD_WR_DATA_REL_USR;
1223 }
1224 for (pidx = 0; pidx < 4; pidx++) {
1225 if (conf->gp_part[pidx].wr_rel_change) {
1226 if (conf->gp_part[pidx].wr_rel_set)
1227 wr_rel_set |= EXT_CSD_WR_DATA_REL_GP(pidx);
1228 else
1229 wr_rel_set &= ~EXT_CSD_WR_DATA_REL_GP(pidx);
1230 }
1231 }
1232
1233 if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET] &&
1234 !(ext_csd[EXT_CSD_WR_REL_PARAM] & EXT_CSD_HS_CTRL_REL)) {
1235 puts("Card does not support host controlled partition write "
1236 "reliability settings\n");
1237 return -EMEDIUMTYPE;
1238 }
1239
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001240 if (ext_csd[EXT_CSD_PARTITION_SETTING] &
1241 EXT_CSD_PARTITION_SETTING_COMPLETED) {
Simon Glass367e3852024-08-22 07:54:55 -06001242 log_err("Card already partitioned\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001243 return -EPERM;
1244 }
1245
1246 if (mode == MMC_HWPART_CONF_CHECK)
1247 return 0;
1248
1249 /* Partitioning requires high-capacity size definitions */
1250 if (!(ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01)) {
1251 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1252 EXT_CSD_ERASE_GROUP_DEF, 1);
1253
1254 if (err)
1255 return err;
1256
1257 ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
1258
Jaehoon Chung58b9eb82020-01-17 15:06:54 +09001259#if CONFIG_IS_ENABLED(MMC_WRITE)
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001260 /* update erase group size to be high-capacity */
1261 mmc->erase_grp_size =
1262 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
Jaehoon Chung58b9eb82020-01-17 15:06:54 +09001263#endif
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001264
1265 }
1266
1267 /* all OK, write the configuration */
1268 for (i = 0; i < 4; i++) {
1269 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1270 EXT_CSD_ENH_START_ADDR+i,
1271 (enh_start_addr >> (i*8)) & 0xFF);
1272 if (err)
1273 return err;
1274 }
1275 for (i = 0; i < 3; i++) {
1276 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1277 EXT_CSD_ENH_SIZE_MULT+i,
1278 (enh_size_mult >> (i*8)) & 0xFF);
1279 if (err)
1280 return err;
1281 }
1282 for (pidx = 0; pidx < 4; pidx++) {
1283 for (i = 0; i < 3; i++) {
1284 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1285 EXT_CSD_GP_SIZE_MULT+pidx*3+i,
1286 (gp_size_mult[pidx] >> (i*8)) & 0xFF);
1287 if (err)
1288 return err;
1289 }
1290 }
1291 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1292 EXT_CSD_PARTITIONS_ATTRIBUTE, part_attrs);
1293 if (err)
1294 return err;
1295
1296 if (mode == MMC_HWPART_CONF_SET)
1297 return 0;
1298
Diego Santa Cruz80200272014-12-23 10:50:31 +01001299 /* The WR_REL_SET is a write-once register but shall be
1300 * written before setting PART_SETTING_COMPLETED. As it is
1301 * write-once we can only write it when completing the
1302 * partitioning. */
1303 if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET]) {
1304 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1305 EXT_CSD_WR_REL_SET, wr_rel_set);
1306 if (err)
1307 return err;
1308 }
1309
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001310 /* Setting PART_SETTING_COMPLETED confirms the partition
1311 * configuration but it only becomes effective after power
1312 * cycle, so we do not adjust the partition related settings
1313 * in the mmc struct. */
1314
1315 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1316 EXT_CSD_PARTITION_SETTING,
1317 EXT_CSD_PARTITION_SETTING_COMPLETED);
1318 if (err)
1319 return err;
1320
1321 return 0;
1322}
Jean-Jacques Hiblot1d7769a2017-11-30 17:44:02 +01001323#endif
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001324
Simon Glasseba48f92017-07-29 11:35:31 -06001325#if !CONFIG_IS_ENABLED(DM_MMC)
Thierry Redingb9c8b772012-01-02 01:15:37 +00001326int mmc_getcd(struct mmc *mmc)
1327{
1328 int cd;
1329
1330 cd = board_mmc_getcd(mmc);
1331
Peter Korsgaardf7b15102013-03-21 04:00:03 +00001332 if (cd < 0) {
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001333 if (mmc->cfg->ops->getcd)
1334 cd = mmc->cfg->ops->getcd(mmc);
Peter Korsgaardf7b15102013-03-21 04:00:03 +00001335 else
1336 cd = 1;
1337 }
Thierry Redingb9c8b772012-01-02 01:15:37 +00001338
1339 return cd;
1340}
Simon Glass394dfc02016-06-12 23:30:22 -06001341#endif
Thierry Redingb9c8b772012-01-02 01:15:37 +00001342
Marek Vasuta318a7a2018-04-15 00:37:11 +02001343#if !CONFIG_IS_ENABLED(MMC_TINY)
Kim Phillips87ea3892012-10-29 13:34:43 +00001344static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
Andy Flemingad347bb2008-10-30 16:41:01 -05001345{
1346 struct mmc_cmd cmd;
1347 struct mmc_data data;
1348
1349 /* Switch the frequency */
1350 cmd.cmdidx = SD_CMD_SWITCH_FUNC;
1351 cmd.resp_type = MMC_RSP_R1;
1352 cmd.cmdarg = (mode << 31) | 0xffffff;
1353 cmd.cmdarg &= ~(0xf << (group * 4));
1354 cmd.cmdarg |= value << (group * 4);
Andy Flemingad347bb2008-10-30 16:41:01 -05001355
1356 data.dest = (char *)resp;
1357 data.blocksize = 64;
1358 data.blocks = 1;
1359 data.flags = MMC_DATA_READ;
1360
1361 return mmc_send_cmd(mmc, &cmd, &data);
1362}
1363
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001364static int sd_get_capabilities(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001365{
1366 int err;
1367 struct mmc_cmd cmd;
Suniel Mahesh2f423da2017-10-05 11:32:00 +05301368 ALLOC_CACHE_ALIGN_BUFFER(__be32, scr, 2);
1369 ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16);
Andy Flemingad347bb2008-10-30 16:41:01 -05001370 struct mmc_data data;
1371 int timeout;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001372#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001373 u32 sd3_bus_mode;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001374#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001375
Faiz Abbas01db77e2020-02-26 13:44:32 +05301376 mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05001377
Thomas Chou1254c3d2010-12-24 13:12:21 +00001378 if (mmc_host_is_spi(mmc))
1379 return 0;
1380
Andy Flemingad347bb2008-10-30 16:41:01 -05001381 /* Read the SCR to find out if this card supports higher speeds */
1382 cmd.cmdidx = MMC_CMD_APP_CMD;
1383 cmd.resp_type = MMC_RSP_R1;
1384 cmd.cmdarg = mmc->rca << 16;
Andy Flemingad347bb2008-10-30 16:41:01 -05001385
1386 err = mmc_send_cmd(mmc, &cmd, NULL);
1387
1388 if (err)
1389 return err;
1390
1391 cmd.cmdidx = SD_CMD_APP_SEND_SCR;
1392 cmd.resp_type = MMC_RSP_R1;
1393 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05001394
Anton staaf9b00f0d2011-10-03 13:54:59 +00001395 data.dest = (char *)scr;
Andy Flemingad347bb2008-10-30 16:41:01 -05001396 data.blocksize = 8;
1397 data.blocks = 1;
1398 data.flags = MMC_DATA_READ;
1399
Sean Anderson86325092020-10-17 08:36:27 -04001400 err = mmc_send_cmd_retry(mmc, &cmd, &data, 3);
Andy Flemingad347bb2008-10-30 16:41:01 -05001401
Sean Anderson86325092020-10-17 08:36:27 -04001402 if (err)
Andy Flemingad347bb2008-10-30 16:41:01 -05001403 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05001404
Yauhen Kharuzhy6e8edf42009-05-07 00:43:30 +03001405 mmc->scr[0] = __be32_to_cpu(scr[0]);
1406 mmc->scr[1] = __be32_to_cpu(scr[1]);
Andy Flemingad347bb2008-10-30 16:41:01 -05001407
1408 switch ((mmc->scr[0] >> 24) & 0xf) {
Bin Meng4a4ef872016-03-17 21:53:13 -07001409 case 0:
1410 mmc->version = SD_VERSION_1_0;
1411 break;
1412 case 1:
1413 mmc->version = SD_VERSION_1_10;
1414 break;
1415 case 2:
1416 mmc->version = SD_VERSION_2;
1417 if ((mmc->scr[0] >> 15) & 0x1)
1418 mmc->version = SD_VERSION_3;
1419 break;
1420 default:
1421 mmc->version = SD_VERSION_1_0;
1422 break;
Andy Flemingad347bb2008-10-30 16:41:01 -05001423 }
1424
Alagu Sankar24bb5ab2010-05-12 15:08:24 +05301425 if (mmc->scr[0] & SD_DATA_4BIT)
1426 mmc->card_caps |= MMC_MODE_4BIT;
1427
Andy Flemingad347bb2008-10-30 16:41:01 -05001428 /* Version 1.0 doesn't support switching */
1429 if (mmc->version == SD_VERSION_1_0)
1430 return 0;
1431
1432 timeout = 4;
1433 while (timeout--) {
1434 err = sd_switch(mmc, SD_SWITCH_CHECK, 0, 1,
Anton staaf9b00f0d2011-10-03 13:54:59 +00001435 (u8 *)switch_status);
Andy Flemingad347bb2008-10-30 16:41:01 -05001436
1437 if (err)
1438 return err;
1439
1440 /* The high-speed function is busy. Try again */
Yauhen Kharuzhy6e8edf42009-05-07 00:43:30 +03001441 if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
Andy Flemingad347bb2008-10-30 16:41:01 -05001442 break;
1443 }
1444
Andy Flemingad347bb2008-10-30 16:41:01 -05001445 /* If high-speed isn't supported, we return */
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001446 if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)
1447 mmc->card_caps |= MMC_CAP(SD_HS);
Andy Flemingad347bb2008-10-30 16:41:01 -05001448
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001449#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001450 /* Version before 3.0 don't support UHS modes */
1451 if (mmc->version < SD_VERSION_3)
1452 return 0;
1453
1454 sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;
1455 if (sd3_bus_mode & SD_MODE_UHS_SDR104)
1456 mmc->card_caps |= MMC_CAP(UHS_SDR104);
1457 if (sd3_bus_mode & SD_MODE_UHS_SDR50)
1458 mmc->card_caps |= MMC_CAP(UHS_SDR50);
1459 if (sd3_bus_mode & SD_MODE_UHS_SDR25)
1460 mmc->card_caps |= MMC_CAP(UHS_SDR25);
1461 if (sd3_bus_mode & SD_MODE_UHS_SDR12)
1462 mmc->card_caps |= MMC_CAP(UHS_SDR12);
1463 if (sd3_bus_mode & SD_MODE_UHS_DDR50)
1464 mmc->card_caps |= MMC_CAP(UHS_DDR50);
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001465#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001466
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001467 return 0;
1468}
1469
1470static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
1471{
1472 int err;
1473
1474 ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001475 int speed;
Macpaul Lin24e92ec2011-11-28 16:31:09 +00001476
Marek Vasut4105e972018-11-18 03:25:08 +01001477 /* SD version 1.00 and 1.01 does not support CMD 6 */
1478 if (mmc->version == SD_VERSION_1_0)
1479 return 0;
1480
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001481 switch (mode) {
Faiz Abbas01db77e2020-02-26 13:44:32 +05301482 case MMC_LEGACY:
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001483 speed = UHS_SDR12_BUS_SPEED;
1484 break;
1485 case SD_HS:
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001486 speed = HIGH_SPEED_BUS_SPEED;
1487 break;
1488#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
1489 case UHS_SDR12:
1490 speed = UHS_SDR12_BUS_SPEED;
1491 break;
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001492 case UHS_SDR25:
1493 speed = UHS_SDR25_BUS_SPEED;
1494 break;
1495 case UHS_SDR50:
1496 speed = UHS_SDR50_BUS_SPEED;
1497 break;
1498 case UHS_DDR50:
1499 speed = UHS_DDR50_BUS_SPEED;
1500 break;
1501 case UHS_SDR104:
1502 speed = UHS_SDR104_BUS_SPEED;
1503 break;
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001504#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001505 default:
1506 return -EINVAL;
1507 }
1508
1509 err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, speed, (u8 *)switch_status);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001510 if (err)
1511 return err;
1512
Jean-Jacques Hiblote7f664e2018-02-09 12:09:27 +01001513 if (((__be32_to_cpu(switch_status[4]) >> 24) & 0xF) != speed)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001514 return -ENOTSUPP;
1515
1516 return 0;
1517}
Andy Flemingad347bb2008-10-30 16:41:01 -05001518
Marek Vasut8ff55fb2018-04-15 00:36:45 +02001519static int sd_select_bus_width(struct mmc *mmc, int w)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001520{
1521 int err;
1522 struct mmc_cmd cmd;
1523
1524 if ((w != 4) && (w != 1))
1525 return -EINVAL;
1526
1527 cmd.cmdidx = MMC_CMD_APP_CMD;
1528 cmd.resp_type = MMC_RSP_R1;
1529 cmd.cmdarg = mmc->rca << 16;
1530
1531 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05001532 if (err)
1533 return err;
1534
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001535 cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
1536 cmd.resp_type = MMC_RSP_R1;
1537 if (w == 4)
1538 cmd.cmdarg = 2;
1539 else if (w == 1)
1540 cmd.cmdarg = 0;
1541 err = mmc_send_cmd(mmc, &cmd, NULL);
1542 if (err)
1543 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05001544
1545 return 0;
1546}
Marek Vasuta318a7a2018-04-15 00:37:11 +02001547#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001548
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001549#if CONFIG_IS_ENABLED(MMC_WRITE)
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001550static int sd_read_ssr(struct mmc *mmc)
1551{
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001552 static const unsigned int sd_au_size[] = {
1553 0, SZ_16K / 512, SZ_32K / 512,
1554 SZ_64K / 512, SZ_128K / 512, SZ_256K / 512,
1555 SZ_512K / 512, SZ_1M / 512, SZ_2M / 512,
1556 SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512,
1557 SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512,
1558 SZ_64M / 512,
1559 };
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001560 int err, i;
1561 struct mmc_cmd cmd;
1562 ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16);
1563 struct mmc_data data;
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001564 unsigned int au, eo, et, es;
1565
1566 cmd.cmdidx = MMC_CMD_APP_CMD;
1567 cmd.resp_type = MMC_RSP_R1;
1568 cmd.cmdarg = mmc->rca << 16;
1569
Sean Anderson86325092020-10-17 08:36:27 -04001570 err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_APP_CMD, 4);
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001571 if (err)
1572 return err;
1573
1574 cmd.cmdidx = SD_CMD_APP_SD_STATUS;
1575 cmd.resp_type = MMC_RSP_R1;
1576 cmd.cmdarg = 0;
1577
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001578 data.dest = (char *)ssr;
1579 data.blocksize = 64;
1580 data.blocks = 1;
1581 data.flags = MMC_DATA_READ;
1582
Sean Anderson86325092020-10-17 08:36:27 -04001583 err = mmc_send_cmd_retry(mmc, &cmd, &data, 3);
1584 if (err)
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001585 return err;
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001586
1587 for (i = 0; i < 16; i++)
1588 ssr[i] = be32_to_cpu(ssr[i]);
1589
1590 au = (ssr[2] >> 12) & 0xF;
1591 if ((au <= 9) || (mmc->version == SD_VERSION_3)) {
1592 mmc->ssr.au = sd_au_size[au];
1593 es = (ssr[3] >> 24) & 0xFF;
1594 es |= (ssr[2] & 0xFF) << 8;
1595 et = (ssr[3] >> 18) & 0x3F;
1596 if (es && et) {
1597 eo = (ssr[3] >> 16) & 0x3;
1598 mmc->ssr.erase_timeout = (et * 1000) / es;
1599 mmc->ssr.erase_offset = eo * 1000;
1600 }
1601 } else {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001602 pr_debug("Invalid Allocation Unit Size.\n");
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001603 }
1604
1605 return 0;
1606}
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001607#endif
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01001608/*
1609 * TRAN_SPEED bits 0:2 encode the frequency unit:
1610 * 0 = 100KHz, 1 = 1MHz, 2 = 10MHz, 3 = 100MHz, values 4 - 7 are reserved.
1611 * The values in fbase[] are divided by 10 to avoid floats in multiplier[].
1612 */
Mike Frysingerb588caf2010-10-20 01:15:53 +00001613static const int fbase[] = {
Andy Flemingad347bb2008-10-30 16:41:01 -05001614 10000,
1615 100000,
1616 1000000,
1617 10000000,
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01001618 0, /* reserved */
1619 0, /* reserved */
1620 0, /* reserved */
1621 0, /* reserved */
Andy Flemingad347bb2008-10-30 16:41:01 -05001622};
1623
1624/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
1625 * to platforms without floating point.
1626 */
Simon Glass03317cc2016-05-14 14:02:57 -06001627static const u8 multipliers[] = {
Andy Flemingad347bb2008-10-30 16:41:01 -05001628 0, /* reserved */
1629 10,
1630 12,
1631 13,
1632 15,
1633 20,
1634 25,
1635 30,
1636 35,
1637 40,
1638 45,
1639 50,
1640 55,
1641 60,
1642 70,
1643 80,
1644};
1645
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001646static inline int bus_width(uint cap)
1647{
1648 if (cap == MMC_MODE_8BIT)
1649 return 8;
1650 if (cap == MMC_MODE_4BIT)
1651 return 4;
1652 if (cap == MMC_MODE_1BIT)
1653 return 1;
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001654 pr_warn("invalid bus witdh capability 0x%x\n", cap);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001655 return 0;
1656}
1657
Simon Glasseba48f92017-07-29 11:35:31 -06001658#if !CONFIG_IS_ENABLED(DM_MMC)
Tom Rinidec7ea02024-05-20 13:35:03 -06001659#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Kishon Vijay Abraham Iae7174f2017-09-21 16:30:05 +02001660static int mmc_execute_tuning(struct mmc *mmc, uint opcode)
1661{
1662 return -ENOTSUPP;
1663}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001664#endif
Kishon Vijay Abraham Iae7174f2017-09-21 16:30:05 +02001665
Jean-Jacques Hiblot3f4da432025-04-10 11:00:20 +02001666static void mmc_send_init_stream(struct mmc *mmc)
1667{
1668}
1669
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001670static int mmc_set_ios(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001671{
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001672 int ret = 0;
1673
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001674 if (mmc->cfg->ops->set_ios)
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001675 ret = mmc->cfg->ops->set_ios(mmc);
1676
1677 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05001678}
Yann Gautier6f558332019-09-19 17:56:12 +02001679
1680static int mmc_host_power_cycle(struct mmc *mmc)
1681{
1682 int ret = 0;
1683
1684 if (mmc->cfg->ops->host_power_cycle)
1685 ret = mmc->cfg->ops->host_power_cycle(mmc);
1686
1687 return ret;
1688}
Simon Glass394dfc02016-06-12 23:30:22 -06001689#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001690
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001691int mmc_set_clock(struct mmc *mmc, uint clock, bool disable)
Andy Flemingad347bb2008-10-30 16:41:01 -05001692{
Jaehoon Chungab4d4052018-01-23 14:04:30 +09001693 if (!disable) {
Jaehoon Chung8a933292018-01-17 19:36:58 +09001694 if (clock > mmc->cfg->f_max)
1695 clock = mmc->cfg->f_max;
Andy Flemingad347bb2008-10-30 16:41:01 -05001696
Jaehoon Chung8a933292018-01-17 19:36:58 +09001697 if (clock < mmc->cfg->f_min)
1698 clock = mmc->cfg->f_min;
1699 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001700
1701 mmc->clock = clock;
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001702 mmc->clk_disable = disable;
Andy Flemingad347bb2008-10-30 16:41:01 -05001703
Jaehoon Chungc8477d62018-01-26 19:25:30 +09001704 debug("clock is %s (%dHz)\n", disable ? "disabled" : "enabled", clock);
1705
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001706 return mmc_set_ios(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001707}
1708
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001709static int mmc_set_bus_width(struct mmc *mmc, uint width)
Andy Flemingad347bb2008-10-30 16:41:01 -05001710{
1711 mmc->bus_width = width;
1712
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001713 return mmc_set_ios(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001714}
1715
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001716#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
1717/*
1718 * helper function to display the capabilities in a human
1719 * friendly manner. The capabilities include bus width and
1720 * supported modes.
1721 */
1722void mmc_dump_capabilities(const char *text, uint caps)
1723{
1724 enum bus_mode mode;
1725
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001726 pr_debug("%s: widths [", text);
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001727 if (caps & MMC_MODE_8BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001728 pr_debug("8, ");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001729 if (caps & MMC_MODE_4BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001730 pr_debug("4, ");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001731 if (caps & MMC_MODE_1BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001732 pr_debug("1, ");
1733 pr_debug("\b\b] modes [");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001734 for (mode = MMC_LEGACY; mode < MMC_MODES_END; mode++)
1735 if (MMC_CAP(mode) & caps)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001736 pr_debug("%s, ", mmc_mode_name(mode));
1737 pr_debug("\b\b]\n");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001738}
1739#endif
1740
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001741struct mode_width_tuning {
1742 enum bus_mode mode;
1743 uint widths;
Tom Rinidec7ea02024-05-20 13:35:03 -06001744#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001745 uint tuning;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001746#endif
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001747};
1748
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001749#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001750int mmc_voltage_to_mv(enum mmc_voltage voltage)
1751{
1752 switch (voltage) {
1753 case MMC_SIGNAL_VOLTAGE_000: return 0;
1754 case MMC_SIGNAL_VOLTAGE_330: return 3300;
1755 case MMC_SIGNAL_VOLTAGE_180: return 1800;
1756 case MMC_SIGNAL_VOLTAGE_120: return 1200;
1757 }
1758 return -EINVAL;
1759}
1760
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001761static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1762{
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001763 int err;
1764
1765 if (mmc->signal_voltage == signal_voltage)
1766 return 0;
1767
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001768 mmc->signal_voltage = signal_voltage;
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001769 err = mmc_set_ios(mmc);
1770 if (err)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001771 pr_debug("unable to set voltage (err %d)\n", err);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001772
1773 return err;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001774}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001775#else
1776static inline int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1777{
1778 return 0;
1779}
1780#endif
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001781
Marek Vasuta318a7a2018-04-15 00:37:11 +02001782#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001783static const struct mode_width_tuning sd_modes_by_pref[] = {
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001784#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Tom Rinidec7ea02024-05-20 13:35:03 -06001785#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001786 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001787 .mode = UHS_SDR104,
1788 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1789 .tuning = MMC_CMD_SEND_TUNING_BLOCK
1790 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001791#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001792 {
1793 .mode = UHS_SDR50,
1794 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1795 },
1796 {
1797 .mode = UHS_DDR50,
1798 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1799 },
1800 {
1801 .mode = UHS_SDR25,
1802 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1803 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001804#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001805 {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001806 .mode = SD_HS,
1807 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1808 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001809#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001810 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001811 .mode = UHS_SDR12,
1812 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1813 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001814#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001815 {
Faiz Abbas01db77e2020-02-26 13:44:32 +05301816 .mode = MMC_LEGACY,
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001817 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1818 }
1819};
1820
1821#define for_each_sd_mode_by_pref(caps, mwt) \
1822 for (mwt = sd_modes_by_pref;\
1823 mwt < sd_modes_by_pref + ARRAY_SIZE(sd_modes_by_pref);\
1824 mwt++) \
1825 if (caps & MMC_CAP(mwt->mode))
1826
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02001827static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001828{
1829 int err;
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001830 uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
1831 const struct mode_width_tuning *mwt;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001832#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001833 bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001834#else
1835 bool uhs_en = false;
1836#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001837 uint caps;
1838
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001839#ifdef DEBUG
1840 mmc_dump_capabilities("sd card", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001841 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001842#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001843
Anup Pateld9c92c72019-07-08 04:10:43 +00001844 if (mmc_host_is_spi(mmc)) {
1845 mmc_set_bus_width(mmc, 1);
Faiz Abbas01db77e2020-02-26 13:44:32 +05301846 mmc_select_mode(mmc, MMC_LEGACY);
Anup Pateld9c92c72019-07-08 04:10:43 +00001847 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
Pragnesh Patela01f57e2020-06-29 15:17:26 +05301848#if CONFIG_IS_ENABLED(MMC_WRITE)
1849 err = sd_read_ssr(mmc);
1850 if (err)
1851 pr_warn("unable to read ssr\n");
1852#endif
Anup Pateld9c92c72019-07-08 04:10:43 +00001853 return 0;
1854 }
1855
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001856 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001857 caps = card_caps & mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001858
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001859 if (!uhs_en)
1860 caps &= ~UHS_CAPS;
1861
1862 for_each_sd_mode_by_pref(caps, mwt) {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001863 uint *w;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001864
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001865 for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001866 if (*w & caps & mwt->widths) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001867 pr_debug("trying mode %s width %d (at %d MHz)\n",
1868 mmc_mode_name(mwt->mode),
1869 bus_width(*w),
1870 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001871
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001872 /* configure the bus width (card + host) */
1873 err = sd_select_bus_width(mmc, bus_width(*w));
1874 if (err)
1875 goto error;
1876 mmc_set_bus_width(mmc, bus_width(*w));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001877
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001878 /* configure the bus mode (card) */
1879 err = sd_set_card_speed(mmc, mwt->mode);
1880 if (err)
1881 goto error;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001882
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001883 /* configure the bus mode (host) */
1884 mmc_select_mode(mmc, mwt->mode);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001885 mmc_set_clock(mmc, mmc->tran_speed,
1886 MMC_CLK_ENABLE);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001887
Tom Rinidec7ea02024-05-20 13:35:03 -06001888#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001889 /* execute tuning if needed */
1890 if (mwt->tuning && !mmc_host_is_spi(mmc)) {
1891 err = mmc_execute_tuning(mmc,
1892 mwt->tuning);
1893 if (err) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001894 pr_debug("tuning failed\n");
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001895 goto error;
1896 }
1897 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001898#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001899
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001900#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001901 err = sd_read_ssr(mmc);
Peng Fan2d2fe8e2018-03-05 16:20:40 +08001902 if (err)
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001903 pr_warn("unable to read ssr\n");
1904#endif
1905 if (!err)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001906 return 0;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001907
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001908error:
1909 /* revert to a safer bus speed */
Faiz Abbas01db77e2020-02-26 13:44:32 +05301910 mmc_select_mode(mmc, MMC_LEGACY);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001911 mmc_set_clock(mmc, mmc->tran_speed,
1912 MMC_CLK_ENABLE);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001913 }
1914 }
1915 }
1916
Simon Glass367e3852024-08-22 07:54:55 -06001917 log_err("unable to select a mode\n");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001918 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001919}
1920
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001921/*
1922 * read the compare the part of ext csd that is constant.
1923 * This can be used to check that the transfer is working
1924 * as expected.
1925 */
1926static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001927{
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001928 int err;
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02001929 const u8 *ext_csd = mmc->ext_csd;
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001930 ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
1931
Jean-Jacques Hiblot7ab1b622017-11-30 17:43:58 +01001932 if (mmc->version < MMC_VERSION_4)
1933 return 0;
1934
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001935 err = mmc_send_ext_csd(mmc, test_csd);
1936 if (err)
1937 return err;
1938
1939 /* Only compare read only fields */
1940 if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
1941 == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
1942 ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
1943 == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
1944 ext_csd[EXT_CSD_REV]
1945 == test_csd[EXT_CSD_REV] &&
1946 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
1947 == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
1948 memcmp(&ext_csd[EXT_CSD_SEC_CNT],
1949 &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
1950 return 0;
1951
1952 return -EBADMSG;
1953}
1954
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001955#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001956static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1957 uint32_t allowed_mask)
1958{
1959 u32 card_mask = 0;
1960
1961 switch (mode) {
Peng Faneede83b2019-07-10 14:43:07 +08001962 case MMC_HS_400_ES:
Peng Fan46801252018-08-10 14:07:54 +08001963 case MMC_HS_400:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001964 case MMC_HS_200:
Peng Fan46801252018-08-10 14:07:54 +08001965 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V |
1966 EXT_CSD_CARD_TYPE_HS400_1_8V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001967 card_mask |= MMC_SIGNAL_VOLTAGE_180;
Peng Fan46801252018-08-10 14:07:54 +08001968 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
1969 EXT_CSD_CARD_TYPE_HS400_1_2V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001970 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1971 break;
1972 case MMC_DDR_52:
1973 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
1974 card_mask |= MMC_SIGNAL_VOLTAGE_330 |
1975 MMC_SIGNAL_VOLTAGE_180;
1976 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_2V)
1977 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1978 break;
1979 default:
1980 card_mask |= MMC_SIGNAL_VOLTAGE_330;
1981 break;
1982 }
1983
1984 while (card_mask & allowed_mask) {
1985 enum mmc_voltage best_match;
1986
1987 best_match = 1 << (ffs(card_mask & allowed_mask) - 1);
1988 if (!mmc_set_signal_voltage(mmc, best_match))
1989 return 0;
1990
1991 allowed_mask &= ~best_match;
1992 }
1993
1994 return -ENOTSUPP;
1995}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001996#else
1997static inline int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1998 uint32_t allowed_mask)
1999{
2000 return 0;
2001}
2002#endif
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002003
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002004static const struct mode_width_tuning mmc_modes_by_pref[] = {
Peng Faneede83b2019-07-10 14:43:07 +08002005#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
2006 {
2007 .mode = MMC_HS_400_ES,
2008 .widths = MMC_MODE_8BIT,
2009 },
2010#endif
Peng Fan46801252018-08-10 14:07:54 +08002011#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
2012 {
2013 .mode = MMC_HS_400,
2014 .widths = MMC_MODE_8BIT,
2015 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
2016 },
2017#endif
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002018#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002019 {
2020 .mode = MMC_HS_200,
2021 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002022 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002023 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002024#endif
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002025 {
2026 .mode = MMC_DDR_52,
2027 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
2028 },
2029 {
2030 .mode = MMC_HS_52,
2031 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2032 },
2033 {
2034 .mode = MMC_HS,
2035 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2036 },
2037 {
2038 .mode = MMC_LEGACY,
2039 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2040 }
2041};
2042
2043#define for_each_mmc_mode_by_pref(caps, mwt) \
2044 for (mwt = mmc_modes_by_pref;\
2045 mwt < mmc_modes_by_pref + ARRAY_SIZE(mmc_modes_by_pref);\
2046 mwt++) \
2047 if (caps & MMC_CAP(mwt->mode))
2048
2049static const struct ext_csd_bus_width {
2050 uint cap;
2051 bool is_ddr;
2052 uint ext_csd_bits;
2053} ext_csd_bus_width[] = {
2054 {MMC_MODE_8BIT, true, EXT_CSD_DDR_BUS_WIDTH_8},
2055 {MMC_MODE_4BIT, true, EXT_CSD_DDR_BUS_WIDTH_4},
2056 {MMC_MODE_8BIT, false, EXT_CSD_BUS_WIDTH_8},
2057 {MMC_MODE_4BIT, false, EXT_CSD_BUS_WIDTH_4},
2058 {MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
2059};
2060
Peng Fan46801252018-08-10 14:07:54 +08002061#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
2062static int mmc_select_hs400(struct mmc *mmc)
2063{
2064 int err;
2065
2066 /* Set timing to HS200 for tuning */
Marek Vasut111572f2019-01-03 21:19:24 +01002067 err = mmc_set_card_speed(mmc, MMC_HS_200, false);
Peng Fan46801252018-08-10 14:07:54 +08002068 if (err)
2069 return err;
2070
2071 /* configure the bus mode (host) */
2072 mmc_select_mode(mmc, MMC_HS_200);
2073 mmc_set_clock(mmc, mmc->tran_speed, false);
2074
2075 /* execute tuning if needed */
Marek Vasut259cc632024-02-24 23:32:09 +01002076 mmc->hs400_tuning = true;
Peng Fan46801252018-08-10 14:07:54 +08002077 err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200);
Marek Vasut259cc632024-02-24 23:32:09 +01002078 mmc->hs400_tuning = false;
Peng Fan46801252018-08-10 14:07:54 +08002079 if (err) {
2080 debug("tuning failed\n");
2081 return err;
2082 }
2083
2084 /* Set back to HS */
Venkatesh Yadav Abbarapu10f9def2024-04-23 11:00:57 +05302085 mmc_set_card_speed(mmc, MMC_HS_52, true);
Peng Fan46801252018-08-10 14:07:54 +08002086
Yangbo Lu5347aea2020-09-01 16:58:04 +08002087 err = mmc_hs400_prepare_ddr(mmc);
2088 if (err)
2089 return err;
2090
Peng Fan46801252018-08-10 14:07:54 +08002091 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2092 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
2093 if (err)
2094 return err;
2095
Marek Vasut111572f2019-01-03 21:19:24 +01002096 err = mmc_set_card_speed(mmc, MMC_HS_400, false);
Peng Fan46801252018-08-10 14:07:54 +08002097 if (err)
2098 return err;
2099
2100 mmc_select_mode(mmc, MMC_HS_400);
2101 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2102 if (err)
2103 return err;
2104
2105 return 0;
2106}
2107#else
2108static int mmc_select_hs400(struct mmc *mmc)
2109{
2110 return -ENOTSUPP;
2111}
2112#endif
2113
Peng Faneede83b2019-07-10 14:43:07 +08002114#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
2115#if !CONFIG_IS_ENABLED(DM_MMC)
2116static int mmc_set_enhanced_strobe(struct mmc *mmc)
2117{
2118 return -ENOTSUPP;
2119}
2120#endif
2121static int mmc_select_hs400es(struct mmc *mmc)
2122{
2123 int err;
2124
2125 err = mmc_set_card_speed(mmc, MMC_HS, true);
2126 if (err)
2127 return err;
2128
2129 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2130 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG |
2131 EXT_CSD_BUS_WIDTH_STROBE);
2132 if (err) {
2133 printf("switch to bus width for hs400 failed\n");
2134 return err;
2135 }
2136 /* TODO: driver strength */
2137 err = mmc_set_card_speed(mmc, MMC_HS_400_ES, false);
2138 if (err)
2139 return err;
2140
2141 mmc_select_mode(mmc, MMC_HS_400_ES);
2142 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2143 if (err)
2144 return err;
2145
2146 return mmc_set_enhanced_strobe(mmc);
2147}
2148#else
2149static int mmc_select_hs400es(struct mmc *mmc)
2150{
2151 return -ENOTSUPP;
2152}
2153#endif
2154
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002155#define for_each_supported_width(caps, ddr, ecbv) \
2156 for (ecbv = ext_csd_bus_width;\
2157 ecbv < ext_csd_bus_width + ARRAY_SIZE(ext_csd_bus_width);\
2158 ecbv++) \
2159 if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
2160
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002161static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02002162{
Jaehoon Chung6b3431c2020-12-04 06:36:00 +09002163 int err = 0;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002164 const struct mode_width_tuning *mwt;
2165 const struct ext_csd_bus_width *ecbw;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002166
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002167#ifdef DEBUG
2168 mmc_dump_capabilities("mmc", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002169 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002170#endif
2171
Anup Pateld9c92c72019-07-08 04:10:43 +00002172 if (mmc_host_is_spi(mmc)) {
2173 mmc_set_bus_width(mmc, 1);
2174 mmc_select_mode(mmc, MMC_LEGACY);
2175 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
2176 return 0;
2177 }
2178
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002179 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002180 card_caps &= mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002181
2182 /* Only version 4 of MMC supports wider bus widths */
2183 if (mmc->version < MMC_VERSION_4)
2184 return 0;
2185
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002186 if (!mmc->ext_csd) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002187 pr_debug("No ext_csd found!\n"); /* this should enver happen */
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002188 return -ENOTSUPP;
2189 }
2190
Marek Vasut111572f2019-01-03 21:19:24 +01002191#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
Ye Li3679e802021-08-17 17:20:34 +08002192 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
2193 CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
Marek Vasut111572f2019-01-03 21:19:24 +01002194 /*
2195 * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode
2196 * before doing anything else, since a transition from either of
2197 * the HS200/HS400 mode directly to legacy mode is not supported.
2198 */
2199 if (mmc->selected_mode == MMC_HS_200 ||
Ye Li3679e802021-08-17 17:20:34 +08002200 mmc->selected_mode == MMC_HS_400 ||
2201 mmc->selected_mode == MMC_HS_400_ES)
Marek Vasut111572f2019-01-03 21:19:24 +01002202 mmc_set_card_speed(mmc, MMC_HS, true);
2203 else
2204#endif
2205 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002206
2207 for_each_mmc_mode_by_pref(card_caps, mwt) {
2208 for_each_supported_width(card_caps & mwt->widths,
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002209 mmc_is_mode_ddr(mwt->mode), ecbw) {
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002210 enum mmc_voltage old_voltage;
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002211 pr_debug("trying mode %s width %d (at %d MHz)\n",
2212 mmc_mode_name(mwt->mode),
2213 bus_width(ecbw->cap),
2214 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002215 old_voltage = mmc->signal_voltage;
2216 err = mmc_set_lowest_voltage(mmc, mwt->mode,
2217 MMC_ALL_SIGNAL_VOLTAGE);
2218 if (err)
2219 continue;
2220
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002221 /* configure the bus width (card + host) */
2222 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2223 EXT_CSD_BUS_WIDTH,
2224 ecbw->ext_csd_bits & ~EXT_CSD_DDR_FLAG);
2225 if (err)
2226 goto error;
2227 mmc_set_bus_width(mmc, bus_width(ecbw->cap));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002228
Peng Fan46801252018-08-10 14:07:54 +08002229 if (mwt->mode == MMC_HS_400) {
2230 err = mmc_select_hs400(mmc);
2231 if (err) {
2232 printf("Select HS400 failed %d\n", err);
2233 goto error;
2234 }
Peng Faneede83b2019-07-10 14:43:07 +08002235 } else if (mwt->mode == MMC_HS_400_ES) {
2236 err = mmc_select_hs400es(mmc);
2237 if (err) {
2238 printf("Select HS400ES failed %d\n",
2239 err);
2240 goto error;
2241 }
Peng Fan46801252018-08-10 14:07:54 +08002242 } else {
2243 /* configure the bus speed (card) */
Marek Vasut111572f2019-01-03 21:19:24 +01002244 err = mmc_set_card_speed(mmc, mwt->mode, false);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002245 if (err)
2246 goto error;
Peng Fan46801252018-08-10 14:07:54 +08002247
2248 /*
2249 * configure the bus width AND the ddr mode
2250 * (card). The host side will be taken care
2251 * of in the next step
2252 */
2253 if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) {
2254 err = mmc_switch(mmc,
2255 EXT_CSD_CMD_SET_NORMAL,
2256 EXT_CSD_BUS_WIDTH,
2257 ecbw->ext_csd_bits);
2258 if (err)
2259 goto error;
2260 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002261
Peng Fan46801252018-08-10 14:07:54 +08002262 /* configure the bus mode (host) */
2263 mmc_select_mode(mmc, mwt->mode);
2264 mmc_set_clock(mmc, mmc->tran_speed,
2265 MMC_CLK_ENABLE);
Tom Rinidec7ea02024-05-20 13:35:03 -06002266#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002267
Peng Fan46801252018-08-10 14:07:54 +08002268 /* execute tuning if needed */
2269 if (mwt->tuning) {
2270 err = mmc_execute_tuning(mmc,
2271 mwt->tuning);
2272 if (err) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002273 pr_debug("tuning failed : %d\n", err);
Peng Fan46801252018-08-10 14:07:54 +08002274 goto error;
2275 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002276 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002277#endif
Peng Fan46801252018-08-10 14:07:54 +08002278 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002279
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002280 /* do a transfer to check the configuration */
2281 err = mmc_read_and_compare_ext_csd(mmc);
2282 if (!err)
2283 return 0;
2284error:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002285 mmc_set_signal_voltage(mmc, old_voltage);
Naoki Hayama3110dcb2020-10-12 18:35:22 +09002286 /* if an error occurred, revert to a safer bus mode */
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002287 mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2288 EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
2289 mmc_select_mode(mmc, MMC_LEGACY);
Valentine Barshak29f8d072023-06-10 13:22:33 +02002290 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002291 mmc_set_bus_width(mmc, 1);
2292 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002293 }
2294
Simon Glass367e3852024-08-22 07:54:55 -06002295 log_err("unable to select a mode: %d\n", err);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002296
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002297 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002298}
Marek Vasut67c77f92024-03-17 04:01:22 +01002299#else
2300static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
2301{
2302 return 0;
2303};
2304
2305static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
2306{
2307 return 0;
2308};
Marek Vasuta318a7a2018-04-15 00:37:11 +02002309#endif
2310
2311#if CONFIG_IS_ENABLED(MMC_TINY)
2312DEFINE_CACHE_ALIGN_BUFFER(u8, ext_csd_bkup, MMC_MAX_BLOCK_LEN);
2313#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002314
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002315static int mmc_startup_v4(struct mmc *mmc)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002316{
2317 int err, i;
2318 u64 capacity;
2319 bool has_parts = false;
2320 bool part_completed;
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002321 static const u32 mmc_versions[] = {
2322 MMC_VERSION_4,
2323 MMC_VERSION_4_1,
2324 MMC_VERSION_4_2,
2325 MMC_VERSION_4_3,
Jean-Jacques Hiblotc64862b2018-02-09 12:09:28 +01002326 MMC_VERSION_4_4,
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002327 MMC_VERSION_4_41,
2328 MMC_VERSION_4_5,
2329 MMC_VERSION_5_0,
2330 MMC_VERSION_5_1
2331 };
2332
Marek Vasuta318a7a2018-04-15 00:37:11 +02002333#if CONFIG_IS_ENABLED(MMC_TINY)
2334 u8 *ext_csd = ext_csd_bkup;
2335
2336 if (IS_SD(mmc) || mmc->version < MMC_VERSION_4)
2337 return 0;
2338
2339 if (!mmc->ext_csd)
Sam Edwardsed8339f2023-05-18 13:47:07 -06002340 memset(ext_csd_bkup, 0, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002341
2342 err = mmc_send_ext_csd(mmc, ext_csd);
2343 if (err)
2344 goto error;
2345
2346 /* store the ext csd for future reference */
2347 if (!mmc->ext_csd)
2348 mmc->ext_csd = ext_csd;
2349#else
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002350 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002351
2352 if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4))
2353 return 0;
2354
2355 /* check ext_csd version and capacity */
2356 err = mmc_send_ext_csd(mmc, ext_csd);
2357 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002358 goto error;
2359
2360 /* store the ext csd for future reference */
2361 if (!mmc->ext_csd)
2362 mmc->ext_csd = malloc(MMC_MAX_BLOCK_LEN);
2363 if (!mmc->ext_csd)
2364 return -ENOMEM;
2365 memcpy(mmc->ext_csd, ext_csd, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002366#endif
Alexander Kochetkovf1133c92018-02-20 14:35:55 +03002367 if (ext_csd[EXT_CSD_REV] >= ARRAY_SIZE(mmc_versions))
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002368 return -EINVAL;
2369
2370 mmc->version = mmc_versions[ext_csd[EXT_CSD_REV]];
2371
2372 if (mmc->version >= MMC_VERSION_4_2) {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002373 /*
2374 * According to the JEDEC Standard, the value of
2375 * ext_csd's capacity is valid if the value is more
2376 * than 2GB
2377 */
2378 capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
2379 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8
2380 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16
2381 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
2382 capacity *= MMC_MAX_BLOCK_LEN;
Marek Vasut1d8d1722025-01-29 12:15:54 +01002383 if (mmc->high_capacity)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002384 mmc->capacity_user = capacity;
2385 }
2386
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +02002387 if (mmc->version >= MMC_VERSION_4_5)
2388 mmc->gen_cmd6_time = ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
2389
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002390 /* The partition data may be non-zero but it is only
2391 * effective if PARTITION_SETTING_COMPLETED is set in
2392 * EXT_CSD, so ignore any data if this bit is not set,
2393 * except for enabling the high-capacity group size
2394 * definition (see below).
2395 */
2396 part_completed = !!(ext_csd[EXT_CSD_PARTITION_SETTING] &
2397 EXT_CSD_PARTITION_SETTING_COMPLETED);
2398
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +02002399 mmc->part_switch_time = ext_csd[EXT_CSD_PART_SWITCH_TIME];
2400 /* Some eMMC set the value too low so set a minimum */
2401 if (mmc->part_switch_time < MMC_MIN_PART_SWITCH_TIME && mmc->part_switch_time)
2402 mmc->part_switch_time = MMC_MIN_PART_SWITCH_TIME;
2403
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002404 /* store the partition info of emmc */
2405 mmc->part_support = ext_csd[EXT_CSD_PARTITIONING_SUPPORT];
2406 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
2407 ext_csd[EXT_CSD_BOOT_MULT])
2408 mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
2409 if (part_completed &&
2410 (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & ENHNCD_SUPPORT))
2411 mmc->part_attr = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE];
2412
2413 mmc->capacity_boot = ext_csd[EXT_CSD_BOOT_MULT] << 17;
2414
2415 mmc->capacity_rpmb = ext_csd[EXT_CSD_RPMB_MULT] << 17;
2416
2417 for (i = 0; i < 4; i++) {
2418 int idx = EXT_CSD_GP_SIZE_MULT + i * 3;
2419 uint mult = (ext_csd[idx + 2] << 16) +
2420 (ext_csd[idx + 1] << 8) + ext_csd[idx];
2421 if (mult)
2422 has_parts = true;
2423 if (!part_completed)
2424 continue;
2425 mmc->capacity_gp[i] = mult;
2426 mmc->capacity_gp[i] *=
2427 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2428 mmc->capacity_gp[i] *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2429 mmc->capacity_gp[i] <<= 19;
2430 }
2431
Simon Glass7ec24132024-09-29 19:49:48 -06002432#ifndef CONFIG_XPL_BUILD
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002433 if (part_completed) {
2434 mmc->enh_user_size =
2435 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 2] << 16) +
2436 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 1] << 8) +
2437 ext_csd[EXT_CSD_ENH_SIZE_MULT];
2438 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2439 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2440 mmc->enh_user_size <<= 19;
2441 mmc->enh_user_start =
2442 (ext_csd[EXT_CSD_ENH_START_ADDR + 3] << 24) +
2443 (ext_csd[EXT_CSD_ENH_START_ADDR + 2] << 16) +
2444 (ext_csd[EXT_CSD_ENH_START_ADDR + 1] << 8) +
2445 ext_csd[EXT_CSD_ENH_START_ADDR];
2446 if (mmc->high_capacity)
2447 mmc->enh_user_start <<= 9;
2448 }
Jean-Jacques Hiblotc94c5472018-01-04 15:23:35 +01002449#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002450
2451 /*
2452 * Host needs to enable ERASE_GRP_DEF bit if device is
2453 * partitioned. This bit will be lost every time after a reset
2454 * or power off. This will affect erase size.
2455 */
2456 if (part_completed)
2457 has_parts = true;
2458 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) &&
2459 (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB))
2460 has_parts = true;
2461 if (has_parts) {
2462 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2463 EXT_CSD_ERASE_GROUP_DEF, 1);
2464
2465 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002466 goto error;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002467
2468 ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
2469 }
2470
2471 if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01) {
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002472#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002473 /* Read out group size from ext_csd */
2474 mmc->erase_grp_size =
2475 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002476#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002477 /*
2478 * if high capacity and partition setting completed
2479 * SEC_COUNT is valid even if it is smaller than 2 GiB
2480 * JEDEC Standard JESD84-B45, 6.2.4
2481 */
2482 if (mmc->high_capacity && part_completed) {
2483 capacity = (ext_csd[EXT_CSD_SEC_CNT]) |
2484 (ext_csd[EXT_CSD_SEC_CNT + 1] << 8) |
2485 (ext_csd[EXT_CSD_SEC_CNT + 2] << 16) |
2486 (ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
2487 capacity *= MMC_MAX_BLOCK_LEN;
2488 mmc->capacity_user = capacity;
2489 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002490 }
2491#if CONFIG_IS_ENABLED(MMC_WRITE)
2492 else {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002493 /* Calculate the group size from the csd value. */
2494 int erase_gsz, erase_gmul;
2495
2496 erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
2497 erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
2498 mmc->erase_grp_size = (erase_gsz + 1)
2499 * (erase_gmul + 1);
2500 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002501#endif
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002502#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002503 mmc->hc_wp_grp_size = 1024
2504 * ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
2505 * ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002506#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002507
2508 mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
2509
Loic Poulainc0aadbb2023-01-26 10:24:17 +01002510 mmc->can_trim =
2511 !!(ext_csd[EXT_CSD_SEC_FEATURE] & EXT_CSD_SEC_FEATURE_TRIM_EN);
2512
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002513 return 0;
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002514error:
2515 if (mmc->ext_csd) {
Marek Vasuta318a7a2018-04-15 00:37:11 +02002516#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002517 free(mmc->ext_csd);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002518#endif
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002519 mmc->ext_csd = NULL;
2520 }
2521 return err;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002522}
2523
Kim Phillips87ea3892012-10-29 13:34:43 +00002524static int mmc_startup(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002525{
Stephen Warrene315ae82013-06-11 15:14:01 -06002526 int err, i;
Andy Flemingad347bb2008-10-30 16:41:01 -05002527 uint mult, freq;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002528 u64 cmult, csize;
Andy Flemingad347bb2008-10-30 16:41:01 -05002529 struct mmc_cmd cmd;
Simon Glasse5db1152016-05-01 13:52:35 -06002530 struct blk_desc *bdesc;
Andy Flemingad347bb2008-10-30 16:41:01 -05002531
Thomas Chou1254c3d2010-12-24 13:12:21 +00002532#ifdef CONFIG_MMC_SPI_CRC_ON
2533 if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
2534 cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
2535 cmd.resp_type = MMC_RSP_R1;
2536 cmd.cmdarg = 1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002537 err = mmc_send_cmd(mmc, &cmd, NULL);
Thomas Chou1254c3d2010-12-24 13:12:21 +00002538 if (err)
2539 return err;
2540 }
2541#endif
2542
Andy Flemingad347bb2008-10-30 16:41:01 -05002543 /* Put the Card in Identify Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002544 cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
2545 MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
Andy Flemingad347bb2008-10-30 16:41:01 -05002546 cmd.resp_type = MMC_RSP_R2;
2547 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002548
Sean Anderson86325092020-10-17 08:36:27 -04002549 err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_SEND_CID, 4);
Andy Flemingad347bb2008-10-30 16:41:01 -05002550 if (err)
2551 return err;
2552
2553 memcpy(mmc->cid, cmd.response, 16);
2554
2555 /*
2556 * For MMC cards, set the Relative Address.
Heinrich Schuchardta53d6bf2025-04-14 13:49:43 +02002557 * For SD cards, get the Relative Address.
Andy Flemingad347bb2008-10-30 16:41:01 -05002558 * This also puts the cards into Standby State
2559 */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002560 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2561 cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
2562 cmd.cmdarg = mmc->rca << 16;
2563 cmd.resp_type = MMC_RSP_R6;
Andy Flemingad347bb2008-10-30 16:41:01 -05002564
Thomas Chou1254c3d2010-12-24 13:12:21 +00002565 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002566
Thomas Chou1254c3d2010-12-24 13:12:21 +00002567 if (err)
2568 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002569
Thomas Chou1254c3d2010-12-24 13:12:21 +00002570 if (IS_SD(mmc))
2571 mmc->rca = (cmd.response[0] >> 16) & 0xffff;
2572 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002573
2574 /* Get the Card-Specific Data */
2575 cmd.cmdidx = MMC_CMD_SEND_CSD;
2576 cmd.resp_type = MMC_RSP_R2;
2577 cmd.cmdarg = mmc->rca << 16;
Andy Flemingad347bb2008-10-30 16:41:01 -05002578
2579 err = mmc_send_cmd(mmc, &cmd, NULL);
2580
2581 if (err)
2582 return err;
2583
Rabin Vincentb6eed942009-04-05 13:30:56 +05302584 mmc->csd[0] = cmd.response[0];
2585 mmc->csd[1] = cmd.response[1];
2586 mmc->csd[2] = cmd.response[2];
2587 mmc->csd[3] = cmd.response[3];
Andy Flemingad347bb2008-10-30 16:41:01 -05002588
2589 if (mmc->version == MMC_VERSION_UNKNOWN) {
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302590 int version = (cmd.response[0] >> 26) & 0xf;
Andy Flemingad347bb2008-10-30 16:41:01 -05002591
2592 switch (version) {
Bin Meng4a4ef872016-03-17 21:53:13 -07002593 case 0:
2594 mmc->version = MMC_VERSION_1_2;
2595 break;
2596 case 1:
2597 mmc->version = MMC_VERSION_1_4;
2598 break;
2599 case 2:
2600 mmc->version = MMC_VERSION_2_2;
2601 break;
2602 case 3:
2603 mmc->version = MMC_VERSION_3;
2604 break;
2605 case 4:
2606 mmc->version = MMC_VERSION_4;
2607 break;
2608 default:
2609 mmc->version = MMC_VERSION_1_2;
2610 break;
Andy Flemingad347bb2008-10-30 16:41:01 -05002611 }
2612 }
2613
2614 /* divide frequency by 10, since the mults are 10x bigger */
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302615 freq = fbase[(cmd.response[0] & 0x7)];
2616 mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
Andy Flemingad347bb2008-10-30 16:41:01 -05002617
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002618 mmc->legacy_speed = freq * mult;
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01002619 if (!mmc->legacy_speed)
2620 log_debug("TRAN_SPEED: reserved value");
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002621 mmc_select_mode(mmc, MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05002622
Markus Niebel03951412013-12-16 13:40:46 +01002623 mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
Rabin Vincentb6eed942009-04-05 13:30:56 +05302624 mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002625#if CONFIG_IS_ENABLED(MMC_WRITE)
Andy Flemingad347bb2008-10-30 16:41:01 -05002626
2627 if (IS_SD(mmc))
2628 mmc->write_bl_len = mmc->read_bl_len;
2629 else
Rabin Vincentb6eed942009-04-05 13:30:56 +05302630 mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002631#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002632
2633 if (mmc->high_capacity) {
2634 csize = (mmc->csd[1] & 0x3f) << 16
2635 | (mmc->csd[2] & 0xffff0000) >> 16;
2636 cmult = 8;
2637 } else {
2638 csize = (mmc->csd[1] & 0x3ff) << 2
2639 | (mmc->csd[2] & 0xc0000000) >> 30;
2640 cmult = (mmc->csd[2] & 0x00038000) >> 15;
2641 }
2642
Stephen Warrene315ae82013-06-11 15:14:01 -06002643 mmc->capacity_user = (csize + 1) << (cmult + 2);
2644 mmc->capacity_user *= mmc->read_bl_len;
2645 mmc->capacity_boot = 0;
2646 mmc->capacity_rpmb = 0;
2647 for (i = 0; i < 4; i++)
2648 mmc->capacity_gp[i] = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002649
Simon Glassa09c2b72013-04-03 08:54:30 +00002650 if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN)
2651 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -05002652
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002653#if CONFIG_IS_ENABLED(MMC_WRITE)
Simon Glassa09c2b72013-04-03 08:54:30 +00002654 if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
2655 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002656#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002657
Markus Niebel03951412013-12-16 13:40:46 +01002658 if ((mmc->dsr_imp) && (0xffffffff != mmc->dsr)) {
2659 cmd.cmdidx = MMC_CMD_SET_DSR;
2660 cmd.cmdarg = (mmc->dsr & 0xffff) << 16;
2661 cmd.resp_type = MMC_RSP_NONE;
2662 if (mmc_send_cmd(mmc, &cmd, NULL))
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002663 pr_warn("MMC: SET_DSR failed\n");
Markus Niebel03951412013-12-16 13:40:46 +01002664 }
2665
Andy Flemingad347bb2008-10-30 16:41:01 -05002666 /* Select the card, and put it into Transfer Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002667 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2668 cmd.cmdidx = MMC_CMD_SELECT_CARD;
Ajay Bhargav4a32fba2011-10-05 03:13:23 +00002669 cmd.resp_type = MMC_RSP_R1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002670 cmd.cmdarg = mmc->rca << 16;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002671 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002672
Thomas Chou1254c3d2010-12-24 13:12:21 +00002673 if (err)
2674 return err;
2675 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002676
Lei Wenea526762011-06-22 17:03:31 +00002677 /*
2678 * For SD, its erase group is always one sector
2679 */
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002680#if CONFIG_IS_ENABLED(MMC_WRITE)
Lei Wenea526762011-06-22 17:03:31 +00002681 mmc->erase_grp_size = 1;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002682#endif
Lei Wen31b99802011-05-02 16:26:26 +00002683 mmc->part_config = MMCPART_NOAVAILABLE;
Diego Santa Cruza7a75992014-12-23 10:50:27 +01002684
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002685 err = mmc_startup_v4(mmc);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002686 if (err)
2687 return err;
Sukumar Ghorai232293c2010-09-20 18:29:29 +05302688
Simon Glasse5db1152016-05-01 13:52:35 -06002689 err = mmc_set_capacity(mmc, mmc_get_blk_desc(mmc)->hwpart);
Stephen Warrene315ae82013-06-11 15:14:01 -06002690 if (err)
2691 return err;
2692
Marek Vasuta318a7a2018-04-15 00:37:11 +02002693#if CONFIG_IS_ENABLED(MMC_TINY)
2694 mmc_set_clock(mmc, mmc->legacy_speed, false);
Faiz Abbas01db77e2020-02-26 13:44:32 +05302695 mmc_select_mode(mmc, MMC_LEGACY);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002696 mmc_set_bus_width(mmc, 1);
2697#else
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002698 if (IS_SD(mmc)) {
2699 err = sd_get_capabilities(mmc);
2700 if (err)
2701 return err;
2702 err = sd_select_mode_and_width(mmc, mmc->card_caps);
2703 } else {
2704 err = mmc_get_capabilities(mmc);
2705 if (err)
2706 return err;
Masahiro Yamadabf1f25c2020-01-23 14:31:12 +09002707 err = mmc_select_mode_and_width(mmc, mmc->card_caps);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002708 }
Marek Vasuta318a7a2018-04-15 00:37:11 +02002709#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002710 if (err)
2711 return err;
2712
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002713 mmc->best_mode = mmc->selected_mode;
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00002714
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002715 /* Fix the block length for DDR mode */
2716 if (mmc->ddr_mode) {
2717 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002718#if CONFIG_IS_ENABLED(MMC_WRITE)
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002719 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002720#endif
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002721 }
2722
Andy Flemingad347bb2008-10-30 16:41:01 -05002723 /* fill in device description */
Simon Glasse5db1152016-05-01 13:52:35 -06002724 bdesc = mmc_get_blk_desc(mmc);
2725 bdesc->lun = 0;
2726 bdesc->hwpart = 0;
2727 bdesc->type = 0;
2728 bdesc->blksz = mmc->read_bl_len;
2729 bdesc->log2blksz = LOG2(bdesc->blksz);
2730 bdesc->lba = lldiv(mmc->capacity, mmc->read_bl_len);
Simon Glass7ec24132024-09-29 19:49:48 -06002731#if !defined(CONFIG_XPL_BUILD) || \
Sjoerd Simonsd67754f2015-12-04 23:27:40 +01002732 (defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \
Simon Glass7611ac62019-09-25 08:56:27 -06002733 !CONFIG_IS_ENABLED(USE_TINY_PRINTF))
Simon Glasse5db1152016-05-01 13:52:35 -06002734 sprintf(bdesc->vendor, "Man %06x Snr %04x%04x",
Taylor Hutt7367ec22012-10-20 17:15:59 +00002735 mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
2736 (mmc->cid[3] >> 16) & 0xffff);
Simon Glasse5db1152016-05-01 13:52:35 -06002737 sprintf(bdesc->product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002738 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
2739 (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
2740 (mmc->cid[2] >> 24) & 0xff);
Simon Glasse5db1152016-05-01 13:52:35 -06002741 sprintf(bdesc->revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002742 (mmc->cid[2] >> 16) & 0xf);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002743#else
Simon Glasse5db1152016-05-01 13:52:35 -06002744 bdesc->vendor[0] = 0;
2745 bdesc->product[0] = 0;
2746 bdesc->revision[0] = 0;
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002747#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002748
Simon Glass7ec24132024-09-29 19:49:48 -06002749#if !defined(CONFIG_DM_MMC) && (!defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT))
Andre Przywara17798042018-12-17 10:05:45 +00002750 part_init(bdesc);
2751#endif
2752
Andy Flemingad347bb2008-10-30 16:41:01 -05002753 return 0;
2754}
2755
Kim Phillips87ea3892012-10-29 13:34:43 +00002756static int mmc_send_if_cond(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002757{
2758 struct mmc_cmd cmd;
2759 int err;
2760
2761 cmd.cmdidx = SD_CMD_SEND_IF_COND;
2762 /* We set the bit if the host supports voltages between 2.7 and 3.6 V */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002763 cmd.cmdarg = ((mmc->cfg->voltages & 0xff8000) != 0) << 8 | 0xaa;
Andy Flemingad347bb2008-10-30 16:41:01 -05002764 cmd.resp_type = MMC_RSP_R7;
Andy Flemingad347bb2008-10-30 16:41:01 -05002765
2766 err = mmc_send_cmd(mmc, &cmd, NULL);
2767
2768 if (err)
2769 return err;
2770
Rabin Vincentb6eed942009-04-05 13:30:56 +05302771 if ((cmd.response[0] & 0xff) != 0xaa)
Jaehoon Chung7825d202016-07-19 16:33:36 +09002772 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002773 else
2774 mmc->version = SD_VERSION_2;
2775
2776 return 0;
2777}
2778
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002779#if !CONFIG_IS_ENABLED(DM_MMC)
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002780/* board-specific MMC power initializations. */
2781__weak void board_mmc_power_init(void)
2782{
2783}
Simon Glass833b80d2017-04-22 19:10:56 -06002784#endif
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002785
Peng Fan15305962016-10-11 15:08:43 +08002786static int mmc_power_init(struct mmc *mmc)
2787{
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002788#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002789#if CONFIG_IS_ENABLED(DM_REGULATOR)
Peng Fan15305962016-10-11 15:08:43 +08002790 int ret;
2791
2792 ret = device_get_supply_regulator(mmc->dev, "vmmc-supply",
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002793 &mmc->vmmc_supply);
2794 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002795 pr_debug("%s: No vmmc supply\n", mmc->dev->name);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002796
2797 ret = device_get_supply_regulator(mmc->dev, "vqmmc-supply",
2798 &mmc->vqmmc_supply);
2799 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002800 pr_debug("%s: No vqmmc supply\n", mmc->dev->name);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002801#endif
2802#else /* !CONFIG_DM_MMC */
2803 /*
2804 * Driver model should use a regulator, as above, rather than calling
2805 * out to board code.
2806 */
2807 board_mmc_power_init();
2808#endif
2809 return 0;
2810}
2811
2812/*
2813 * put the host in the initial state:
2814 * - turn on Vdd (card power supply)
2815 * - configure the bus width and clock to minimal values
2816 */
2817static void mmc_set_initial_state(struct mmc *mmc)
2818{
2819 int err;
2820
2821 /* First try to set 3.3V. If it fails set to 1.8V */
2822 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
2823 if (err != 0)
2824 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
2825 if (err != 0)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002826 pr_warn("mmc: failed to set signal voltage\n");
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002827
2828 mmc_select_mode(mmc, MMC_LEGACY);
2829 mmc_set_bus_width(mmc, 1);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002830 mmc_set_clock(mmc, 0, MMC_CLK_ENABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002831}
Peng Fan15305962016-10-11 15:08:43 +08002832
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002833static int mmc_power_on(struct mmc *mmc)
2834{
2835#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002836 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002837 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2838 true);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002839
Jonas Karlman0f28e182023-07-19 21:20:59 +00002840 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002841 printf("Error enabling VMMC supply : %d\n", ret);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002842 return ret;
2843 }
Peng Fan15305962016-10-11 15:08:43 +08002844 }
2845#endif
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002846 return 0;
2847}
2848
2849static int mmc_power_off(struct mmc *mmc)
2850{
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002851 mmc_set_clock(mmc, 0, MMC_CLK_DISABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002852#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
2853 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002854 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2855 false);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002856
Jonas Karlman0f28e182023-07-19 21:20:59 +00002857 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002858 pr_debug("Error disabling VMMC supply : %d\n", ret);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002859 return ret;
2860 }
2861 }
Simon Glass833b80d2017-04-22 19:10:56 -06002862#endif
Peng Fan15305962016-10-11 15:08:43 +08002863 return 0;
2864}
2865
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002866static int mmc_power_cycle(struct mmc *mmc)
2867{
2868 int ret;
2869
2870 ret = mmc_power_off(mmc);
2871 if (ret)
2872 return ret;
Yann Gautier6f558332019-09-19 17:56:12 +02002873
2874 ret = mmc_host_power_cycle(mmc);
2875 if (ret)
2876 return ret;
2877
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002878 /*
2879 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
2880 * to be on the safer side.
2881 */
2882 udelay(2000);
2883 return mmc_power_on(mmc);
2884}
2885
Pali Rohár7c639622021-07-14 16:37:29 +02002886int mmc_get_op_cond(struct mmc *mmc, bool quiet)
Andy Flemingad347bb2008-10-30 16:41:01 -05002887{
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002888 bool uhs_en = supports_uhs(mmc->cfg->host_caps);
Macpaul Lin028bde12011-11-14 23:35:39 +00002889 int err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002890
Lei Wen31b99802011-05-02 16:26:26 +00002891 if (mmc->has_init)
2892 return 0;
2893
Peng Fan15305962016-10-11 15:08:43 +08002894 err = mmc_power_init(mmc);
2895 if (err)
2896 return err;
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002897
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002898#ifdef CONFIG_MMC_QUIRKS
2899 mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN |
Joel Johnson5ea041b2020-01-11 09:08:14 -07002900 MMC_QUIRK_RETRY_SEND_CID |
2901 MMC_QUIRK_RETRY_APP_CMD;
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002902#endif
2903
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002904 err = mmc_power_cycle(mmc);
2905 if (err) {
2906 /*
2907 * if power cycling is not supported, we should not try
2908 * to use the UHS modes, because we wouldn't be able to
2909 * recover from an error during the UHS initialization.
2910 */
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002911 pr_debug("Unable to do a full power cycle. Disabling the UHS modes for safety\n");
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002912 uhs_en = false;
2913 mmc->host_caps &= ~UHS_CAPS;
2914 err = mmc_power_on(mmc);
2915 }
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002916 if (err)
2917 return err;
2918
Simon Glasseba48f92017-07-29 11:35:31 -06002919#if CONFIG_IS_ENABLED(DM_MMC)
Yangbo Luc46f5d72020-09-01 16:57:59 +08002920 /*
2921 * Re-initialization is needed to clear old configuration for
2922 * mmc rescan.
2923 */
2924 err = mmc_reinit(mmc);
Simon Glass394dfc02016-06-12 23:30:22 -06002925#else
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02002926 /* made sure it's not NULL earlier */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002927 err = mmc->cfg->ops->init(mmc);
Yangbo Luc46f5d72020-09-01 16:57:59 +08002928#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002929 if (err)
2930 return err;
Andrew Gabbasov9fc2a412014-12-01 06:59:09 -06002931 mmc->ddr_mode = 0;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02002932
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002933retry:
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002934 mmc_set_initial_state(mmc);
Jean-Jacques Hiblot5f23d872017-09-21 16:30:01 +02002935
Jean-Jacques Hiblot3f4da432025-04-10 11:00:20 +02002936 mmc_send_init_stream(mmc);
2937
Andy Flemingad347bb2008-10-30 16:41:01 -05002938 /* Reset the Card */
2939 err = mmc_go_idle(mmc);
2940
2941 if (err)
2942 return err;
2943
Marcel Ziswilerb2b7fc82019-05-20 02:44:53 +02002944 /* The internal partition reset to user partition(0) at every CMD0 */
Simon Glasse5db1152016-05-01 13:52:35 -06002945 mmc_get_blk_desc(mmc)->hwpart = 0;
Lei Wen31b99802011-05-02 16:26:26 +00002946
Andy Flemingad347bb2008-10-30 16:41:01 -05002947 /* Test for SD version 2 */
Macpaul Lin028bde12011-11-14 23:35:39 +00002948 err = mmc_send_if_cond(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05002949
Andy Flemingad347bb2008-10-30 16:41:01 -05002950 /* Now try to get the SD card's operating condition */
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002951 err = sd_send_op_cond(mmc, uhs_en);
2952 if (err && uhs_en) {
2953 uhs_en = false;
2954 mmc_power_cycle(mmc);
2955 goto retry;
2956 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002957
2958 /* If the command timed out, we check for an MMC card */
Jaehoon Chung7825d202016-07-19 16:33:36 +09002959 if (err == -ETIMEDOUT) {
Andy Flemingad347bb2008-10-30 16:41:01 -05002960 err = mmc_send_op_cond(mmc);
2961
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002962 if (err) {
Simon Glass7ec24132024-09-29 19:49:48 -06002963#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Pali Rohár7c639622021-07-14 16:37:29 +02002964 if (!quiet)
Simon Glass367e3852024-08-22 07:54:55 -06002965 log_err("Card did not respond to voltage select! : %d\n",
2966 err);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002967#endif
Jaehoon Chung7825d202016-07-19 16:33:36 +09002968 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002969 }
2970 }
2971
Jon Nettleton2663fe42018-06-11 15:26:19 +03002972 return err;
2973}
2974
2975int mmc_start_init(struct mmc *mmc)
2976{
2977 bool no_card;
2978 int err = 0;
2979
2980 /*
2981 * all hosts are capable of 1 bit bus-width and able to use the legacy
2982 * timings.
2983 */
Faiz Abbas01db77e2020-02-26 13:44:32 +05302984 mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) |
Aswath Govindrajubb5b9fe2021-08-13 23:04:41 +05302985 MMC_MODE_1BIT;
2986
2987 if (IS_ENABLED(CONFIG_MMC_SPEED_MODE_SET)) {
2988 if (mmc->user_speed_mode != MMC_MODES_END) {
2989 int i;
2990 /* set host caps */
2991 if (mmc->host_caps & MMC_CAP(mmc->user_speed_mode)) {
2992 /* Remove all existing speed capabilities */
2993 for (i = MMC_LEGACY; i < MMC_MODES_END; i++)
2994 mmc->host_caps &= ~MMC_CAP(i);
2995 mmc->host_caps |= (MMC_CAP(mmc->user_speed_mode)
2996 | MMC_CAP(MMC_LEGACY) |
2997 MMC_MODE_1BIT);
2998 } else {
Simon Glass367e3852024-08-22 07:54:55 -06002999 log_err("bus_mode requested is not supported\n");
Aswath Govindrajubb5b9fe2021-08-13 23:04:41 +05303000 return -EINVAL;
3001 }
3002 }
3003 }
Faiz Abbasf6fd4ec2020-02-26 13:44:30 +05303004#if CONFIG_IS_ENABLED(DM_MMC)
3005 mmc_deferred_probe(mmc);
3006#endif
Jon Nettleton2663fe42018-06-11 15:26:19 +03003007#if !defined(CONFIG_MMC_BROKEN_CD)
Jon Nettleton2663fe42018-06-11 15:26:19 +03003008 no_card = mmc_getcd(mmc) == 0;
3009#else
3010 no_card = 0;
3011#endif
3012#if !CONFIG_IS_ENABLED(DM_MMC)
Baruch Siach0448ce62019-07-22 15:52:12 +03003013 /* we pretend there's no card when init is NULL */
Jon Nettleton2663fe42018-06-11 15:26:19 +03003014 no_card = no_card || (mmc->cfg->ops->init == NULL);
3015#endif
3016 if (no_card) {
3017 mmc->has_init = 0;
Simon Glass7ec24132024-09-29 19:49:48 -06003018#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -06003019 log_err("MMC: no card present\n");
Jon Nettleton2663fe42018-06-11 15:26:19 +03003020#endif
3021 return -ENOMEDIUM;
3022 }
3023
Pali Rohár7c639622021-07-14 16:37:29 +02003024 err = mmc_get_op_cond(mmc, false);
Jon Nettleton2663fe42018-06-11 15:26:19 +03003025
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003026 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003027 mmc->init_in_progress = 1;
3028
3029 return err;
3030}
3031
3032static int mmc_complete_init(struct mmc *mmc)
3033{
3034 int err = 0;
3035
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003036 mmc->init_in_progress = 0;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003037 if (mmc->op_cond_pending)
3038 err = mmc_complete_op_cond(mmc);
3039
3040 if (!err)
3041 err = mmc_startup(mmc);
Lei Wen31b99802011-05-02 16:26:26 +00003042 if (err)
3043 mmc->has_init = 0;
3044 else
3045 mmc->has_init = 1;
3046 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05003047}
3048
Marek Vasut9b51ddc2025-01-18 04:09:53 +01003049static void mmc_cyclic_cd_poll(struct cyclic_info *c)
Marek Vasutb0967402024-09-06 19:10:42 +02003050{
Marek Vasut9b51ddc2025-01-18 04:09:53 +01003051 struct mmc *m = container_of(c, struct mmc, cyclic);
Marek Vasutb0967402024-09-06 19:10:42 +02003052
3053 if (!m->has_init)
3054 return;
3055
3056 if (mmc_getcd(m))
3057 return;
3058
3059 mmc_deinit(m);
3060 m->has_init = 0;
3061}
3062
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003063int mmc_init(struct mmc *mmc)
3064{
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003065 int err = 0;
Vipul Kumardbad7b42018-05-03 12:20:54 +05303066 __maybe_unused ulong start;
Simon Glass5f4bd8c2017-07-04 13:31:19 -06003067#if CONFIG_IS_ENABLED(DM_MMC)
Simon Glass59bc6f22016-05-01 13:52:41 -06003068 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003069
Simon Glass59bc6f22016-05-01 13:52:41 -06003070 upriv->mmc = mmc;
3071#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003072 if (mmc->has_init)
3073 return 0;
Mateusz Zalegada351782014-04-29 20:15:30 +02003074
3075 start = get_timer(0);
3076
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003077 if (!mmc->init_in_progress)
3078 err = mmc_start_init(mmc);
3079
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003080 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003081 err = mmc_complete_init(mmc);
Marek Vasut285de2c2025-01-18 04:27:34 +01003082 if (err) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09003083 pr_info("%s: %d, time %lu\n", __func__, err, get_timer(start));
Marek Vasut285de2c2025-01-18 04:27:34 +01003084 return err;
3085 }
Jagan Teki9bee2b52017-01-10 11:18:43 +01003086
Marek Vasutb0967402024-09-06 19:10:42 +02003087 if (CONFIG_IS_ENABLED(CYCLIC, (!mmc->cyclic.func), (NULL))) {
3088 /* Register cyclic function for card detect polling */
Marek Vasut9b51ddc2025-01-18 04:09:53 +01003089 cyclic_register(&mmc->cyclic, mmc_cyclic_cd_poll, 100 * 1000,
3090 mmc->cfg->name);
Marek Vasutb0967402024-09-06 19:10:42 +02003091 }
3092
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003093 return err;
3094}
3095
Marek Vasuta4773fc2019-01-29 04:45:51 +01003096int mmc_deinit(struct mmc *mmc)
3097{
3098 u32 caps_filtered;
3099
Marek Vasutb0967402024-09-06 19:10:42 +02003100 if (CONFIG_IS_ENABLED(CYCLIC, (mmc->cyclic.func), (NULL)))
Marek Vasut9b51ddc2025-01-18 04:09:53 +01003101 cyclic_unregister(&mmc->cyclic);
Marek Vasutb0967402024-09-06 19:10:42 +02003102
Marek Vasut67c77f92024-03-17 04:01:22 +01003103 if (!CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) &&
3104 !CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) &&
3105 !CONFIG_IS_ENABLED(MMC_HS400_SUPPORT))
3106 return 0;
3107
Marek Vasuta4773fc2019-01-29 04:45:51 +01003108 if (!mmc->has_init)
3109 return 0;
3110
3111 if (IS_SD(mmc)) {
3112 caps_filtered = mmc->card_caps &
3113 ~(MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) |
3114 MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
3115 MMC_CAP(UHS_SDR104));
3116
3117 return sd_select_mode_and_width(mmc, caps_filtered);
3118 } else {
3119 caps_filtered = mmc->card_caps &
Ye Li3679e802021-08-17 17:20:34 +08003120 ~(MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_HS_400) | MMC_CAP(MMC_HS_400_ES));
Marek Vasuta4773fc2019-01-29 04:45:51 +01003121
3122 return mmc_select_mode_and_width(mmc, caps_filtered);
3123 }
3124}
Marek Vasuta4773fc2019-01-29 04:45:51 +01003125
Markus Niebel03951412013-12-16 13:40:46 +01003126int mmc_set_dsr(struct mmc *mmc, u16 val)
3127{
3128 mmc->dsr = val;
3129 return 0;
3130}
3131
Jeroen Hofstee47726302014-07-10 22:46:28 +02003132/* CPU-specific MMC initializations */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003133__weak int cpu_mmc_init(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003134{
3135 return -1;
3136}
3137
Jeroen Hofstee47726302014-07-10 22:46:28 +02003138/* board-specific MMC initializations. */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003139__weak int board_mmc_init(struct bd_info *bis)
Jeroen Hofstee47726302014-07-10 22:46:28 +02003140{
3141 return -1;
3142}
Andy Flemingad347bb2008-10-30 16:41:01 -05003143
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003144void mmc_set_preinit(struct mmc *mmc, int preinit)
3145{
3146 mmc->preinit = preinit;
3147}
3148
Faiz Abbasb3857fd2018-02-12 19:35:24 +05303149#if CONFIG_IS_ENABLED(DM_MMC)
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003150static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003151{
Simon Glass547cb342015-12-29 05:22:49 -07003152 int ret, i;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003153 struct uclass *uc;
Simon Glass547cb342015-12-29 05:22:49 -07003154 struct udevice *dev;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003155
3156 ret = uclass_get(UCLASS_MMC, &uc);
3157 if (ret)
3158 return ret;
3159
Simon Glass547cb342015-12-29 05:22:49 -07003160 /*
3161 * Try to add them in sequence order. Really with driver model we
3162 * should allow holes, but the current MMC list does not allow that.
3163 * So if we request 0, 1, 3 we will get 0, 1, 2.
3164 */
3165 for (i = 0; ; i++) {
3166 ret = uclass_get_device_by_seq(UCLASS_MMC, i, &dev);
3167 if (ret == -ENODEV)
3168 break;
3169 }
3170 uclass_foreach_dev(dev, uc) {
3171 ret = device_probe(dev);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003172 if (ret)
Simon Glass367e3852024-08-22 07:54:55 -06003173 log_err("%s - probe failed: %d\n", dev->name, ret);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003174 }
3175
3176 return 0;
3177}
3178#else
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003179static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003180{
3181 if (board_mmc_init(bis) < 0)
3182 cpu_mmc_init(bis);
3183
3184 return 0;
3185}
3186#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003187
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003188int mmc_initialize(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003189{
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003190 static int initialized = 0;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003191 int ret;
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003192 if (initialized) /* Avoid initializing mmc multiple times */
3193 return 0;
3194 initialized = 1;
3195
Simon Glass5f4bd8c2017-07-04 13:31:19 -06003196#if !CONFIG_IS_ENABLED(BLK)
Marek Vasutf537e392016-12-01 02:06:33 +01003197#if !CONFIG_IS_ENABLED(MMC_TINY)
Simon Glasse5db1152016-05-01 13:52:35 -06003198 mmc_list_init();
3199#endif
Marek Vasutf537e392016-12-01 02:06:33 +01003200#endif
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003201 ret = mmc_probe(bis);
3202 if (ret)
3203 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05003204
Simon Glass7ec24132024-09-29 19:49:48 -06003205#ifndef CONFIG_XPL_BUILD
Andy Flemingad347bb2008-10-30 16:41:01 -05003206 print_mmc_devices(',');
Ying Zhang9ff70262013-08-16 15:16:11 +08003207#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05003208
Simon Glasse5db1152016-05-01 13:52:35 -06003209 mmc_do_preinit();
Andy Flemingad347bb2008-10-30 16:41:01 -05003210 return 0;
3211}
Tomas Melinc17dae52016-11-25 11:01:03 +02003212
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303213#if CONFIG_IS_ENABLED(DM_MMC)
3214int mmc_init_device(int num)
3215{
3216 struct udevice *dev;
3217 struct mmc *m;
3218 int ret;
3219
Aswath Govindraju57e2ccb2021-03-25 12:48:47 +05303220 if (uclass_get_device_by_seq(UCLASS_MMC, num, &dev)) {
3221 ret = uclass_get_device(UCLASS_MMC, num, &dev);
3222 if (ret)
Simon Glass9c3e9262024-09-20 09:24:38 +02003223 return log_msg_ret("ini", ret);
Aswath Govindraju57e2ccb2021-03-25 12:48:47 +05303224 }
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303225
3226 m = mmc_get_mmc_dev(dev);
3227 if (!m)
3228 return 0;
Venkatesh Yadav Abbarapu6738fcb2022-09-29 10:22:49 +05303229
3230 /* Initialising user set speed mode */
3231 m->user_speed_mode = MMC_MODES_END;
3232
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303233 if (m->preinit)
3234 mmc_start_init(m);
3235
3236 return 0;
3237}
3238#endif
3239
Tomas Melinc17dae52016-11-25 11:01:03 +02003240#ifdef CONFIG_CMD_BKOPS_ENABLE
Marek Vasutefdeed62023-01-05 15:19:08 +01003241int mmc_set_bkops_enable(struct mmc *mmc, bool autobkops, bool enable)
Tomas Melinc17dae52016-11-25 11:01:03 +02003242{
3243 int err;
Marek Vasutefdeed62023-01-05 15:19:08 +01003244 u32 bit = autobkops ? BIT(1) : BIT(0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003245 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
3246
3247 err = mmc_send_ext_csd(mmc, ext_csd);
3248 if (err) {
3249 puts("Could not get ext_csd register values\n");
3250 return err;
3251 }
3252
3253 if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) {
3254 puts("Background operations not supported on device\n");
3255 return -EMEDIUMTYPE;
3256 }
3257
Marek Vasutefdeed62023-01-05 15:19:08 +01003258 if (enable && (ext_csd[EXT_CSD_BKOPS_EN] & bit)) {
Tomas Melinc17dae52016-11-25 11:01:03 +02003259 puts("Background operations already enabled\n");
3260 return 0;
3261 }
3262
Marek Vasutefdeed62023-01-05 15:19:08 +01003263 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN,
3264 enable ? bit : 0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003265 if (err) {
Marek Vasutefdeed62023-01-05 15:19:08 +01003266 printf("Failed to %sable manual background operations\n",
3267 enable ? "en" : "dis");
Tomas Melinc17dae52016-11-25 11:01:03 +02003268 return err;
3269 }
3270
Marek Vasutefdeed62023-01-05 15:19:08 +01003271 printf("%sabled %s background operations\n",
3272 enable ? "En" : "Dis", autobkops ? "auto" : "manual");
Tomas Melinc17dae52016-11-25 11:01:03 +02003273
3274 return 0;
3275}
3276#endif
David Woodhouse49fee032020-08-04 10:05:46 +01003277
3278__weak int mmc_get_env_dev(void)
3279{
3280#ifdef CONFIG_SYS_MMC_ENV_DEV
3281 return CONFIG_SYS_MMC_ENV_DEV;
3282#else
3283 return 0;
3284#endif
3285}