blob: 799586891aff16381ddd40888af868142b50b0d0 [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
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001666static int mmc_set_ios(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001667{
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001668 int ret = 0;
1669
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001670 if (mmc->cfg->ops->set_ios)
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001671 ret = mmc->cfg->ops->set_ios(mmc);
1672
1673 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05001674}
Yann Gautier6f558332019-09-19 17:56:12 +02001675
1676static int mmc_host_power_cycle(struct mmc *mmc)
1677{
1678 int ret = 0;
1679
1680 if (mmc->cfg->ops->host_power_cycle)
1681 ret = mmc->cfg->ops->host_power_cycle(mmc);
1682
1683 return ret;
1684}
Simon Glass394dfc02016-06-12 23:30:22 -06001685#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001686
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001687int mmc_set_clock(struct mmc *mmc, uint clock, bool disable)
Andy Flemingad347bb2008-10-30 16:41:01 -05001688{
Jaehoon Chungab4d4052018-01-23 14:04:30 +09001689 if (!disable) {
Jaehoon Chung8a933292018-01-17 19:36:58 +09001690 if (clock > mmc->cfg->f_max)
1691 clock = mmc->cfg->f_max;
Andy Flemingad347bb2008-10-30 16:41:01 -05001692
Jaehoon Chung8a933292018-01-17 19:36:58 +09001693 if (clock < mmc->cfg->f_min)
1694 clock = mmc->cfg->f_min;
1695 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001696
1697 mmc->clock = clock;
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001698 mmc->clk_disable = disable;
Andy Flemingad347bb2008-10-30 16:41:01 -05001699
Jaehoon Chungc8477d62018-01-26 19:25:30 +09001700 debug("clock is %s (%dHz)\n", disable ? "disabled" : "enabled", clock);
1701
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001702 return mmc_set_ios(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001703}
1704
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001705static int mmc_set_bus_width(struct mmc *mmc, uint width)
Andy Flemingad347bb2008-10-30 16:41:01 -05001706{
1707 mmc->bus_width = width;
1708
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001709 return mmc_set_ios(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001710}
1711
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001712#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
1713/*
1714 * helper function to display the capabilities in a human
1715 * friendly manner. The capabilities include bus width and
1716 * supported modes.
1717 */
1718void mmc_dump_capabilities(const char *text, uint caps)
1719{
1720 enum bus_mode mode;
1721
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001722 pr_debug("%s: widths [", text);
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001723 if (caps & MMC_MODE_8BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001724 pr_debug("8, ");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001725 if (caps & MMC_MODE_4BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001726 pr_debug("4, ");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001727 if (caps & MMC_MODE_1BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001728 pr_debug("1, ");
1729 pr_debug("\b\b] modes [");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001730 for (mode = MMC_LEGACY; mode < MMC_MODES_END; mode++)
1731 if (MMC_CAP(mode) & caps)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001732 pr_debug("%s, ", mmc_mode_name(mode));
1733 pr_debug("\b\b]\n");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001734}
1735#endif
1736
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001737struct mode_width_tuning {
1738 enum bus_mode mode;
1739 uint widths;
Tom Rinidec7ea02024-05-20 13:35:03 -06001740#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001741 uint tuning;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001742#endif
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001743};
1744
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001745#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001746int mmc_voltage_to_mv(enum mmc_voltage voltage)
1747{
1748 switch (voltage) {
1749 case MMC_SIGNAL_VOLTAGE_000: return 0;
1750 case MMC_SIGNAL_VOLTAGE_330: return 3300;
1751 case MMC_SIGNAL_VOLTAGE_180: return 1800;
1752 case MMC_SIGNAL_VOLTAGE_120: return 1200;
1753 }
1754 return -EINVAL;
1755}
1756
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001757static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1758{
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001759 int err;
1760
1761 if (mmc->signal_voltage == signal_voltage)
1762 return 0;
1763
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001764 mmc->signal_voltage = signal_voltage;
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001765 err = mmc_set_ios(mmc);
1766 if (err)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001767 pr_debug("unable to set voltage (err %d)\n", err);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001768
1769 return err;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001770}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001771#else
1772static inline int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1773{
1774 return 0;
1775}
1776#endif
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001777
Marek Vasuta318a7a2018-04-15 00:37:11 +02001778#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001779static const struct mode_width_tuning sd_modes_by_pref[] = {
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001780#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Tom Rinidec7ea02024-05-20 13:35:03 -06001781#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001782 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001783 .mode = UHS_SDR104,
1784 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1785 .tuning = MMC_CMD_SEND_TUNING_BLOCK
1786 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001787#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001788 {
1789 .mode = UHS_SDR50,
1790 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1791 },
1792 {
1793 .mode = UHS_DDR50,
1794 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1795 },
1796 {
1797 .mode = UHS_SDR25,
1798 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1799 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001800#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001801 {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001802 .mode = SD_HS,
1803 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1804 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001805#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001806 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001807 .mode = UHS_SDR12,
1808 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1809 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001810#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001811 {
Faiz Abbas01db77e2020-02-26 13:44:32 +05301812 .mode = MMC_LEGACY,
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001813 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1814 }
1815};
1816
1817#define for_each_sd_mode_by_pref(caps, mwt) \
1818 for (mwt = sd_modes_by_pref;\
1819 mwt < sd_modes_by_pref + ARRAY_SIZE(sd_modes_by_pref);\
1820 mwt++) \
1821 if (caps & MMC_CAP(mwt->mode))
1822
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02001823static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001824{
1825 int err;
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001826 uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
1827 const struct mode_width_tuning *mwt;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001828#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001829 bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001830#else
1831 bool uhs_en = false;
1832#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001833 uint caps;
1834
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001835#ifdef DEBUG
1836 mmc_dump_capabilities("sd card", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001837 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001838#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001839
Anup Pateld9c92c72019-07-08 04:10:43 +00001840 if (mmc_host_is_spi(mmc)) {
1841 mmc_set_bus_width(mmc, 1);
Faiz Abbas01db77e2020-02-26 13:44:32 +05301842 mmc_select_mode(mmc, MMC_LEGACY);
Anup Pateld9c92c72019-07-08 04:10:43 +00001843 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
Pragnesh Patela01f57e2020-06-29 15:17:26 +05301844#if CONFIG_IS_ENABLED(MMC_WRITE)
1845 err = sd_read_ssr(mmc);
1846 if (err)
1847 pr_warn("unable to read ssr\n");
1848#endif
Anup Pateld9c92c72019-07-08 04:10:43 +00001849 return 0;
1850 }
1851
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001852 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001853 caps = card_caps & mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001854
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001855 if (!uhs_en)
1856 caps &= ~UHS_CAPS;
1857
1858 for_each_sd_mode_by_pref(caps, mwt) {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001859 uint *w;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001860
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001861 for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001862 if (*w & caps & mwt->widths) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001863 pr_debug("trying mode %s width %d (at %d MHz)\n",
1864 mmc_mode_name(mwt->mode),
1865 bus_width(*w),
1866 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001867
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001868 /* configure the bus width (card + host) */
1869 err = sd_select_bus_width(mmc, bus_width(*w));
1870 if (err)
1871 goto error;
1872 mmc_set_bus_width(mmc, bus_width(*w));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001873
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001874 /* configure the bus mode (card) */
1875 err = sd_set_card_speed(mmc, mwt->mode);
1876 if (err)
1877 goto error;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001878
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001879 /* configure the bus mode (host) */
1880 mmc_select_mode(mmc, mwt->mode);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001881 mmc_set_clock(mmc, mmc->tran_speed,
1882 MMC_CLK_ENABLE);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001883
Tom Rinidec7ea02024-05-20 13:35:03 -06001884#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001885 /* execute tuning if needed */
1886 if (mwt->tuning && !mmc_host_is_spi(mmc)) {
1887 err = mmc_execute_tuning(mmc,
1888 mwt->tuning);
1889 if (err) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001890 pr_debug("tuning failed\n");
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001891 goto error;
1892 }
1893 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001894#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001895
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001896#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001897 err = sd_read_ssr(mmc);
Peng Fan2d2fe8e2018-03-05 16:20:40 +08001898 if (err)
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001899 pr_warn("unable to read ssr\n");
1900#endif
1901 if (!err)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001902 return 0;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001903
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001904error:
1905 /* revert to a safer bus speed */
Faiz Abbas01db77e2020-02-26 13:44:32 +05301906 mmc_select_mode(mmc, MMC_LEGACY);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001907 mmc_set_clock(mmc, mmc->tran_speed,
1908 MMC_CLK_ENABLE);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001909 }
1910 }
1911 }
1912
Simon Glass367e3852024-08-22 07:54:55 -06001913 log_err("unable to select a mode\n");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001914 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001915}
1916
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001917/*
1918 * read the compare the part of ext csd that is constant.
1919 * This can be used to check that the transfer is working
1920 * as expected.
1921 */
1922static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001923{
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001924 int err;
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02001925 const u8 *ext_csd = mmc->ext_csd;
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001926 ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
1927
Jean-Jacques Hiblot7ab1b622017-11-30 17:43:58 +01001928 if (mmc->version < MMC_VERSION_4)
1929 return 0;
1930
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001931 err = mmc_send_ext_csd(mmc, test_csd);
1932 if (err)
1933 return err;
1934
1935 /* Only compare read only fields */
1936 if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
1937 == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
1938 ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
1939 == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
1940 ext_csd[EXT_CSD_REV]
1941 == test_csd[EXT_CSD_REV] &&
1942 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
1943 == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
1944 memcmp(&ext_csd[EXT_CSD_SEC_CNT],
1945 &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
1946 return 0;
1947
1948 return -EBADMSG;
1949}
1950
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001951#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001952static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1953 uint32_t allowed_mask)
1954{
1955 u32 card_mask = 0;
1956
1957 switch (mode) {
Peng Faneede83b2019-07-10 14:43:07 +08001958 case MMC_HS_400_ES:
Peng Fan46801252018-08-10 14:07:54 +08001959 case MMC_HS_400:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001960 case MMC_HS_200:
Peng Fan46801252018-08-10 14:07:54 +08001961 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V |
1962 EXT_CSD_CARD_TYPE_HS400_1_8V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001963 card_mask |= MMC_SIGNAL_VOLTAGE_180;
Peng Fan46801252018-08-10 14:07:54 +08001964 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
1965 EXT_CSD_CARD_TYPE_HS400_1_2V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001966 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1967 break;
1968 case MMC_DDR_52:
1969 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
1970 card_mask |= MMC_SIGNAL_VOLTAGE_330 |
1971 MMC_SIGNAL_VOLTAGE_180;
1972 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_2V)
1973 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1974 break;
1975 default:
1976 card_mask |= MMC_SIGNAL_VOLTAGE_330;
1977 break;
1978 }
1979
1980 while (card_mask & allowed_mask) {
1981 enum mmc_voltage best_match;
1982
1983 best_match = 1 << (ffs(card_mask & allowed_mask) - 1);
1984 if (!mmc_set_signal_voltage(mmc, best_match))
1985 return 0;
1986
1987 allowed_mask &= ~best_match;
1988 }
1989
1990 return -ENOTSUPP;
1991}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001992#else
1993static inline int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1994 uint32_t allowed_mask)
1995{
1996 return 0;
1997}
1998#endif
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001999
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002000static const struct mode_width_tuning mmc_modes_by_pref[] = {
Peng Faneede83b2019-07-10 14:43:07 +08002001#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
2002 {
2003 .mode = MMC_HS_400_ES,
2004 .widths = MMC_MODE_8BIT,
2005 },
2006#endif
Peng Fan46801252018-08-10 14:07:54 +08002007#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
2008 {
2009 .mode = MMC_HS_400,
2010 .widths = MMC_MODE_8BIT,
2011 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
2012 },
2013#endif
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002014#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002015 {
2016 .mode = MMC_HS_200,
2017 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002018 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002019 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002020#endif
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002021 {
2022 .mode = MMC_DDR_52,
2023 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
2024 },
2025 {
2026 .mode = MMC_HS_52,
2027 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2028 },
2029 {
2030 .mode = MMC_HS,
2031 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2032 },
2033 {
2034 .mode = MMC_LEGACY,
2035 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2036 }
2037};
2038
2039#define for_each_mmc_mode_by_pref(caps, mwt) \
2040 for (mwt = mmc_modes_by_pref;\
2041 mwt < mmc_modes_by_pref + ARRAY_SIZE(mmc_modes_by_pref);\
2042 mwt++) \
2043 if (caps & MMC_CAP(mwt->mode))
2044
2045static const struct ext_csd_bus_width {
2046 uint cap;
2047 bool is_ddr;
2048 uint ext_csd_bits;
2049} ext_csd_bus_width[] = {
2050 {MMC_MODE_8BIT, true, EXT_CSD_DDR_BUS_WIDTH_8},
2051 {MMC_MODE_4BIT, true, EXT_CSD_DDR_BUS_WIDTH_4},
2052 {MMC_MODE_8BIT, false, EXT_CSD_BUS_WIDTH_8},
2053 {MMC_MODE_4BIT, false, EXT_CSD_BUS_WIDTH_4},
2054 {MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
2055};
2056
Peng Fan46801252018-08-10 14:07:54 +08002057#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
2058static int mmc_select_hs400(struct mmc *mmc)
2059{
2060 int err;
2061
2062 /* Set timing to HS200 for tuning */
Marek Vasut111572f2019-01-03 21:19:24 +01002063 err = mmc_set_card_speed(mmc, MMC_HS_200, false);
Peng Fan46801252018-08-10 14:07:54 +08002064 if (err)
2065 return err;
2066
2067 /* configure the bus mode (host) */
2068 mmc_select_mode(mmc, MMC_HS_200);
2069 mmc_set_clock(mmc, mmc->tran_speed, false);
2070
2071 /* execute tuning if needed */
Marek Vasut259cc632024-02-24 23:32:09 +01002072 mmc->hs400_tuning = true;
Peng Fan46801252018-08-10 14:07:54 +08002073 err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200);
Marek Vasut259cc632024-02-24 23:32:09 +01002074 mmc->hs400_tuning = false;
Peng Fan46801252018-08-10 14:07:54 +08002075 if (err) {
2076 debug("tuning failed\n");
2077 return err;
2078 }
2079
2080 /* Set back to HS */
Venkatesh Yadav Abbarapu10f9def2024-04-23 11:00:57 +05302081 mmc_set_card_speed(mmc, MMC_HS_52, true);
Peng Fan46801252018-08-10 14:07:54 +08002082
Yangbo Lu5347aea2020-09-01 16:58:04 +08002083 err = mmc_hs400_prepare_ddr(mmc);
2084 if (err)
2085 return err;
2086
Peng Fan46801252018-08-10 14:07:54 +08002087 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2088 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
2089 if (err)
2090 return err;
2091
Marek Vasut111572f2019-01-03 21:19:24 +01002092 err = mmc_set_card_speed(mmc, MMC_HS_400, false);
Peng Fan46801252018-08-10 14:07:54 +08002093 if (err)
2094 return err;
2095
2096 mmc_select_mode(mmc, MMC_HS_400);
2097 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2098 if (err)
2099 return err;
2100
2101 return 0;
2102}
2103#else
2104static int mmc_select_hs400(struct mmc *mmc)
2105{
2106 return -ENOTSUPP;
2107}
2108#endif
2109
Peng Faneede83b2019-07-10 14:43:07 +08002110#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
2111#if !CONFIG_IS_ENABLED(DM_MMC)
2112static int mmc_set_enhanced_strobe(struct mmc *mmc)
2113{
2114 return -ENOTSUPP;
2115}
2116#endif
2117static int mmc_select_hs400es(struct mmc *mmc)
2118{
2119 int err;
2120
2121 err = mmc_set_card_speed(mmc, MMC_HS, true);
2122 if (err)
2123 return err;
2124
2125 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2126 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG |
2127 EXT_CSD_BUS_WIDTH_STROBE);
2128 if (err) {
2129 printf("switch to bus width for hs400 failed\n");
2130 return err;
2131 }
2132 /* TODO: driver strength */
2133 err = mmc_set_card_speed(mmc, MMC_HS_400_ES, false);
2134 if (err)
2135 return err;
2136
2137 mmc_select_mode(mmc, MMC_HS_400_ES);
2138 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2139 if (err)
2140 return err;
2141
2142 return mmc_set_enhanced_strobe(mmc);
2143}
2144#else
2145static int mmc_select_hs400es(struct mmc *mmc)
2146{
2147 return -ENOTSUPP;
2148}
2149#endif
2150
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002151#define for_each_supported_width(caps, ddr, ecbv) \
2152 for (ecbv = ext_csd_bus_width;\
2153 ecbv < ext_csd_bus_width + ARRAY_SIZE(ext_csd_bus_width);\
2154 ecbv++) \
2155 if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
2156
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002157static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02002158{
Jaehoon Chung6b3431c2020-12-04 06:36:00 +09002159 int err = 0;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002160 const struct mode_width_tuning *mwt;
2161 const struct ext_csd_bus_width *ecbw;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002162
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002163#ifdef DEBUG
2164 mmc_dump_capabilities("mmc", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002165 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002166#endif
2167
Anup Pateld9c92c72019-07-08 04:10:43 +00002168 if (mmc_host_is_spi(mmc)) {
2169 mmc_set_bus_width(mmc, 1);
2170 mmc_select_mode(mmc, MMC_LEGACY);
2171 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
2172 return 0;
2173 }
2174
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002175 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002176 card_caps &= mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002177
2178 /* Only version 4 of MMC supports wider bus widths */
2179 if (mmc->version < MMC_VERSION_4)
2180 return 0;
2181
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002182 if (!mmc->ext_csd) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002183 pr_debug("No ext_csd found!\n"); /* this should enver happen */
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002184 return -ENOTSUPP;
2185 }
2186
Marek Vasut111572f2019-01-03 21:19:24 +01002187#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
Ye Li3679e802021-08-17 17:20:34 +08002188 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
2189 CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
Marek Vasut111572f2019-01-03 21:19:24 +01002190 /*
2191 * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode
2192 * before doing anything else, since a transition from either of
2193 * the HS200/HS400 mode directly to legacy mode is not supported.
2194 */
2195 if (mmc->selected_mode == MMC_HS_200 ||
Ye Li3679e802021-08-17 17:20:34 +08002196 mmc->selected_mode == MMC_HS_400 ||
2197 mmc->selected_mode == MMC_HS_400_ES)
Marek Vasut111572f2019-01-03 21:19:24 +01002198 mmc_set_card_speed(mmc, MMC_HS, true);
2199 else
2200#endif
2201 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002202
2203 for_each_mmc_mode_by_pref(card_caps, mwt) {
2204 for_each_supported_width(card_caps & mwt->widths,
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002205 mmc_is_mode_ddr(mwt->mode), ecbw) {
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002206 enum mmc_voltage old_voltage;
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002207 pr_debug("trying mode %s width %d (at %d MHz)\n",
2208 mmc_mode_name(mwt->mode),
2209 bus_width(ecbw->cap),
2210 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002211 old_voltage = mmc->signal_voltage;
2212 err = mmc_set_lowest_voltage(mmc, mwt->mode,
2213 MMC_ALL_SIGNAL_VOLTAGE);
2214 if (err)
2215 continue;
2216
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002217 /* configure the bus width (card + host) */
2218 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2219 EXT_CSD_BUS_WIDTH,
2220 ecbw->ext_csd_bits & ~EXT_CSD_DDR_FLAG);
2221 if (err)
2222 goto error;
2223 mmc_set_bus_width(mmc, bus_width(ecbw->cap));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002224
Peng Fan46801252018-08-10 14:07:54 +08002225 if (mwt->mode == MMC_HS_400) {
2226 err = mmc_select_hs400(mmc);
2227 if (err) {
2228 printf("Select HS400 failed %d\n", err);
2229 goto error;
2230 }
Peng Faneede83b2019-07-10 14:43:07 +08002231 } else if (mwt->mode == MMC_HS_400_ES) {
2232 err = mmc_select_hs400es(mmc);
2233 if (err) {
2234 printf("Select HS400ES failed %d\n",
2235 err);
2236 goto error;
2237 }
Peng Fan46801252018-08-10 14:07:54 +08002238 } else {
2239 /* configure the bus speed (card) */
Marek Vasut111572f2019-01-03 21:19:24 +01002240 err = mmc_set_card_speed(mmc, mwt->mode, false);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002241 if (err)
2242 goto error;
Peng Fan46801252018-08-10 14:07:54 +08002243
2244 /*
2245 * configure the bus width AND the ddr mode
2246 * (card). The host side will be taken care
2247 * of in the next step
2248 */
2249 if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) {
2250 err = mmc_switch(mmc,
2251 EXT_CSD_CMD_SET_NORMAL,
2252 EXT_CSD_BUS_WIDTH,
2253 ecbw->ext_csd_bits);
2254 if (err)
2255 goto error;
2256 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002257
Peng Fan46801252018-08-10 14:07:54 +08002258 /* configure the bus mode (host) */
2259 mmc_select_mode(mmc, mwt->mode);
2260 mmc_set_clock(mmc, mmc->tran_speed,
2261 MMC_CLK_ENABLE);
Tom Rinidec7ea02024-05-20 13:35:03 -06002262#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002263
Peng Fan46801252018-08-10 14:07:54 +08002264 /* execute tuning if needed */
2265 if (mwt->tuning) {
2266 err = mmc_execute_tuning(mmc,
2267 mwt->tuning);
2268 if (err) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002269 pr_debug("tuning failed : %d\n", err);
Peng Fan46801252018-08-10 14:07:54 +08002270 goto error;
2271 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002272 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002273#endif
Peng Fan46801252018-08-10 14:07:54 +08002274 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002275
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002276 /* do a transfer to check the configuration */
2277 err = mmc_read_and_compare_ext_csd(mmc);
2278 if (!err)
2279 return 0;
2280error:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002281 mmc_set_signal_voltage(mmc, old_voltage);
Naoki Hayama3110dcb2020-10-12 18:35:22 +09002282 /* if an error occurred, revert to a safer bus mode */
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002283 mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2284 EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
2285 mmc_select_mode(mmc, MMC_LEGACY);
Valentine Barshak29f8d072023-06-10 13:22:33 +02002286 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002287 mmc_set_bus_width(mmc, 1);
2288 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002289 }
2290
Simon Glass367e3852024-08-22 07:54:55 -06002291 log_err("unable to select a mode: %d\n", err);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002292
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002293 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002294}
Marek Vasut67c77f92024-03-17 04:01:22 +01002295#else
2296static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
2297{
2298 return 0;
2299};
2300
2301static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
2302{
2303 return 0;
2304};
Marek Vasuta318a7a2018-04-15 00:37:11 +02002305#endif
2306
2307#if CONFIG_IS_ENABLED(MMC_TINY)
2308DEFINE_CACHE_ALIGN_BUFFER(u8, ext_csd_bkup, MMC_MAX_BLOCK_LEN);
2309#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002310
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002311static int mmc_startup_v4(struct mmc *mmc)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002312{
2313 int err, i;
2314 u64 capacity;
2315 bool has_parts = false;
2316 bool part_completed;
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002317 static const u32 mmc_versions[] = {
2318 MMC_VERSION_4,
2319 MMC_VERSION_4_1,
2320 MMC_VERSION_4_2,
2321 MMC_VERSION_4_3,
Jean-Jacques Hiblotc64862b2018-02-09 12:09:28 +01002322 MMC_VERSION_4_4,
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002323 MMC_VERSION_4_41,
2324 MMC_VERSION_4_5,
2325 MMC_VERSION_5_0,
2326 MMC_VERSION_5_1
2327 };
2328
Marek Vasuta318a7a2018-04-15 00:37:11 +02002329#if CONFIG_IS_ENABLED(MMC_TINY)
2330 u8 *ext_csd = ext_csd_bkup;
2331
2332 if (IS_SD(mmc) || mmc->version < MMC_VERSION_4)
2333 return 0;
2334
2335 if (!mmc->ext_csd)
Sam Edwardsed8339f2023-05-18 13:47:07 -06002336 memset(ext_csd_bkup, 0, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002337
2338 err = mmc_send_ext_csd(mmc, ext_csd);
2339 if (err)
2340 goto error;
2341
2342 /* store the ext csd for future reference */
2343 if (!mmc->ext_csd)
2344 mmc->ext_csd = ext_csd;
2345#else
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002346 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002347
2348 if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4))
2349 return 0;
2350
2351 /* check ext_csd version and capacity */
2352 err = mmc_send_ext_csd(mmc, ext_csd);
2353 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002354 goto error;
2355
2356 /* store the ext csd for future reference */
2357 if (!mmc->ext_csd)
2358 mmc->ext_csd = malloc(MMC_MAX_BLOCK_LEN);
2359 if (!mmc->ext_csd)
2360 return -ENOMEM;
2361 memcpy(mmc->ext_csd, ext_csd, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002362#endif
Alexander Kochetkovf1133c92018-02-20 14:35:55 +03002363 if (ext_csd[EXT_CSD_REV] >= ARRAY_SIZE(mmc_versions))
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002364 return -EINVAL;
2365
2366 mmc->version = mmc_versions[ext_csd[EXT_CSD_REV]];
2367
2368 if (mmc->version >= MMC_VERSION_4_2) {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002369 /*
2370 * According to the JEDEC Standard, the value of
2371 * ext_csd's capacity is valid if the value is more
2372 * than 2GB
2373 */
2374 capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
2375 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8
2376 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16
2377 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
2378 capacity *= MMC_MAX_BLOCK_LEN;
2379 if ((capacity >> 20) > 2 * 1024)
2380 mmc->capacity_user = capacity;
2381 }
2382
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +02002383 if (mmc->version >= MMC_VERSION_4_5)
2384 mmc->gen_cmd6_time = ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
2385
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002386 /* The partition data may be non-zero but it is only
2387 * effective if PARTITION_SETTING_COMPLETED is set in
2388 * EXT_CSD, so ignore any data if this bit is not set,
2389 * except for enabling the high-capacity group size
2390 * definition (see below).
2391 */
2392 part_completed = !!(ext_csd[EXT_CSD_PARTITION_SETTING] &
2393 EXT_CSD_PARTITION_SETTING_COMPLETED);
2394
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +02002395 mmc->part_switch_time = ext_csd[EXT_CSD_PART_SWITCH_TIME];
2396 /* Some eMMC set the value too low so set a minimum */
2397 if (mmc->part_switch_time < MMC_MIN_PART_SWITCH_TIME && mmc->part_switch_time)
2398 mmc->part_switch_time = MMC_MIN_PART_SWITCH_TIME;
2399
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002400 /* store the partition info of emmc */
2401 mmc->part_support = ext_csd[EXT_CSD_PARTITIONING_SUPPORT];
2402 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
2403 ext_csd[EXT_CSD_BOOT_MULT])
2404 mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
2405 if (part_completed &&
2406 (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & ENHNCD_SUPPORT))
2407 mmc->part_attr = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE];
2408
2409 mmc->capacity_boot = ext_csd[EXT_CSD_BOOT_MULT] << 17;
2410
2411 mmc->capacity_rpmb = ext_csd[EXT_CSD_RPMB_MULT] << 17;
2412
2413 for (i = 0; i < 4; i++) {
2414 int idx = EXT_CSD_GP_SIZE_MULT + i * 3;
2415 uint mult = (ext_csd[idx + 2] << 16) +
2416 (ext_csd[idx + 1] << 8) + ext_csd[idx];
2417 if (mult)
2418 has_parts = true;
2419 if (!part_completed)
2420 continue;
2421 mmc->capacity_gp[i] = mult;
2422 mmc->capacity_gp[i] *=
2423 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2424 mmc->capacity_gp[i] *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2425 mmc->capacity_gp[i] <<= 19;
2426 }
2427
Simon Glass7ec24132024-09-29 19:49:48 -06002428#ifndef CONFIG_XPL_BUILD
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002429 if (part_completed) {
2430 mmc->enh_user_size =
2431 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 2] << 16) +
2432 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 1] << 8) +
2433 ext_csd[EXT_CSD_ENH_SIZE_MULT];
2434 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2435 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2436 mmc->enh_user_size <<= 19;
2437 mmc->enh_user_start =
2438 (ext_csd[EXT_CSD_ENH_START_ADDR + 3] << 24) +
2439 (ext_csd[EXT_CSD_ENH_START_ADDR + 2] << 16) +
2440 (ext_csd[EXT_CSD_ENH_START_ADDR + 1] << 8) +
2441 ext_csd[EXT_CSD_ENH_START_ADDR];
2442 if (mmc->high_capacity)
2443 mmc->enh_user_start <<= 9;
2444 }
Jean-Jacques Hiblotc94c5472018-01-04 15:23:35 +01002445#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002446
2447 /*
2448 * Host needs to enable ERASE_GRP_DEF bit if device is
2449 * partitioned. This bit will be lost every time after a reset
2450 * or power off. This will affect erase size.
2451 */
2452 if (part_completed)
2453 has_parts = true;
2454 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) &&
2455 (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB))
2456 has_parts = true;
2457 if (has_parts) {
2458 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2459 EXT_CSD_ERASE_GROUP_DEF, 1);
2460
2461 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002462 goto error;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002463
2464 ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
2465 }
2466
2467 if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01) {
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002468#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002469 /* Read out group size from ext_csd */
2470 mmc->erase_grp_size =
2471 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002472#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002473 /*
2474 * if high capacity and partition setting completed
2475 * SEC_COUNT is valid even if it is smaller than 2 GiB
2476 * JEDEC Standard JESD84-B45, 6.2.4
2477 */
2478 if (mmc->high_capacity && part_completed) {
2479 capacity = (ext_csd[EXT_CSD_SEC_CNT]) |
2480 (ext_csd[EXT_CSD_SEC_CNT + 1] << 8) |
2481 (ext_csd[EXT_CSD_SEC_CNT + 2] << 16) |
2482 (ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
2483 capacity *= MMC_MAX_BLOCK_LEN;
2484 mmc->capacity_user = capacity;
2485 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002486 }
2487#if CONFIG_IS_ENABLED(MMC_WRITE)
2488 else {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002489 /* Calculate the group size from the csd value. */
2490 int erase_gsz, erase_gmul;
2491
2492 erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
2493 erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
2494 mmc->erase_grp_size = (erase_gsz + 1)
2495 * (erase_gmul + 1);
2496 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002497#endif
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002498#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002499 mmc->hc_wp_grp_size = 1024
2500 * ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
2501 * ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002502#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002503
2504 mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
2505
Loic Poulainc0aadbb2023-01-26 10:24:17 +01002506 mmc->can_trim =
2507 !!(ext_csd[EXT_CSD_SEC_FEATURE] & EXT_CSD_SEC_FEATURE_TRIM_EN);
2508
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002509 return 0;
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002510error:
2511 if (mmc->ext_csd) {
Marek Vasuta318a7a2018-04-15 00:37:11 +02002512#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002513 free(mmc->ext_csd);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002514#endif
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002515 mmc->ext_csd = NULL;
2516 }
2517 return err;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002518}
2519
Kim Phillips87ea3892012-10-29 13:34:43 +00002520static int mmc_startup(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002521{
Stephen Warrene315ae82013-06-11 15:14:01 -06002522 int err, i;
Andy Flemingad347bb2008-10-30 16:41:01 -05002523 uint mult, freq;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002524 u64 cmult, csize;
Andy Flemingad347bb2008-10-30 16:41:01 -05002525 struct mmc_cmd cmd;
Simon Glasse5db1152016-05-01 13:52:35 -06002526 struct blk_desc *bdesc;
Andy Flemingad347bb2008-10-30 16:41:01 -05002527
Thomas Chou1254c3d2010-12-24 13:12:21 +00002528#ifdef CONFIG_MMC_SPI_CRC_ON
2529 if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
2530 cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
2531 cmd.resp_type = MMC_RSP_R1;
2532 cmd.cmdarg = 1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002533 err = mmc_send_cmd(mmc, &cmd, NULL);
Thomas Chou1254c3d2010-12-24 13:12:21 +00002534 if (err)
2535 return err;
2536 }
2537#endif
2538
Andy Flemingad347bb2008-10-30 16:41:01 -05002539 /* Put the Card in Identify Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002540 cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
2541 MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
Andy Flemingad347bb2008-10-30 16:41:01 -05002542 cmd.resp_type = MMC_RSP_R2;
2543 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002544
Sean Anderson86325092020-10-17 08:36:27 -04002545 err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_SEND_CID, 4);
Andy Flemingad347bb2008-10-30 16:41:01 -05002546 if (err)
2547 return err;
2548
2549 memcpy(mmc->cid, cmd.response, 16);
2550
2551 /*
2552 * For MMC cards, set the Relative Address.
2553 * For SD cards, get the Relatvie Address.
2554 * This also puts the cards into Standby State
2555 */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002556 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2557 cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
2558 cmd.cmdarg = mmc->rca << 16;
2559 cmd.resp_type = MMC_RSP_R6;
Andy Flemingad347bb2008-10-30 16:41:01 -05002560
Thomas Chou1254c3d2010-12-24 13:12:21 +00002561 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002562
Thomas Chou1254c3d2010-12-24 13:12:21 +00002563 if (err)
2564 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002565
Thomas Chou1254c3d2010-12-24 13:12:21 +00002566 if (IS_SD(mmc))
2567 mmc->rca = (cmd.response[0] >> 16) & 0xffff;
2568 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002569
2570 /* Get the Card-Specific Data */
2571 cmd.cmdidx = MMC_CMD_SEND_CSD;
2572 cmd.resp_type = MMC_RSP_R2;
2573 cmd.cmdarg = mmc->rca << 16;
Andy Flemingad347bb2008-10-30 16:41:01 -05002574
2575 err = mmc_send_cmd(mmc, &cmd, NULL);
2576
2577 if (err)
2578 return err;
2579
Rabin Vincentb6eed942009-04-05 13:30:56 +05302580 mmc->csd[0] = cmd.response[0];
2581 mmc->csd[1] = cmd.response[1];
2582 mmc->csd[2] = cmd.response[2];
2583 mmc->csd[3] = cmd.response[3];
Andy Flemingad347bb2008-10-30 16:41:01 -05002584
2585 if (mmc->version == MMC_VERSION_UNKNOWN) {
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302586 int version = (cmd.response[0] >> 26) & 0xf;
Andy Flemingad347bb2008-10-30 16:41:01 -05002587
2588 switch (version) {
Bin Meng4a4ef872016-03-17 21:53:13 -07002589 case 0:
2590 mmc->version = MMC_VERSION_1_2;
2591 break;
2592 case 1:
2593 mmc->version = MMC_VERSION_1_4;
2594 break;
2595 case 2:
2596 mmc->version = MMC_VERSION_2_2;
2597 break;
2598 case 3:
2599 mmc->version = MMC_VERSION_3;
2600 break;
2601 case 4:
2602 mmc->version = MMC_VERSION_4;
2603 break;
2604 default:
2605 mmc->version = MMC_VERSION_1_2;
2606 break;
Andy Flemingad347bb2008-10-30 16:41:01 -05002607 }
2608 }
2609
2610 /* divide frequency by 10, since the mults are 10x bigger */
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302611 freq = fbase[(cmd.response[0] & 0x7)];
2612 mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
Andy Flemingad347bb2008-10-30 16:41:01 -05002613
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002614 mmc->legacy_speed = freq * mult;
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01002615 if (!mmc->legacy_speed)
2616 log_debug("TRAN_SPEED: reserved value");
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002617 mmc_select_mode(mmc, MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05002618
Markus Niebel03951412013-12-16 13:40:46 +01002619 mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
Rabin Vincentb6eed942009-04-05 13:30:56 +05302620 mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002621#if CONFIG_IS_ENABLED(MMC_WRITE)
Andy Flemingad347bb2008-10-30 16:41:01 -05002622
2623 if (IS_SD(mmc))
2624 mmc->write_bl_len = mmc->read_bl_len;
2625 else
Rabin Vincentb6eed942009-04-05 13:30:56 +05302626 mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002627#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002628
2629 if (mmc->high_capacity) {
2630 csize = (mmc->csd[1] & 0x3f) << 16
2631 | (mmc->csd[2] & 0xffff0000) >> 16;
2632 cmult = 8;
2633 } else {
2634 csize = (mmc->csd[1] & 0x3ff) << 2
2635 | (mmc->csd[2] & 0xc0000000) >> 30;
2636 cmult = (mmc->csd[2] & 0x00038000) >> 15;
2637 }
2638
Stephen Warrene315ae82013-06-11 15:14:01 -06002639 mmc->capacity_user = (csize + 1) << (cmult + 2);
2640 mmc->capacity_user *= mmc->read_bl_len;
2641 mmc->capacity_boot = 0;
2642 mmc->capacity_rpmb = 0;
2643 for (i = 0; i < 4; i++)
2644 mmc->capacity_gp[i] = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002645
Simon Glassa09c2b72013-04-03 08:54:30 +00002646 if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN)
2647 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -05002648
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002649#if CONFIG_IS_ENABLED(MMC_WRITE)
Simon Glassa09c2b72013-04-03 08:54:30 +00002650 if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
2651 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002652#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002653
Markus Niebel03951412013-12-16 13:40:46 +01002654 if ((mmc->dsr_imp) && (0xffffffff != mmc->dsr)) {
2655 cmd.cmdidx = MMC_CMD_SET_DSR;
2656 cmd.cmdarg = (mmc->dsr & 0xffff) << 16;
2657 cmd.resp_type = MMC_RSP_NONE;
2658 if (mmc_send_cmd(mmc, &cmd, NULL))
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002659 pr_warn("MMC: SET_DSR failed\n");
Markus Niebel03951412013-12-16 13:40:46 +01002660 }
2661
Andy Flemingad347bb2008-10-30 16:41:01 -05002662 /* Select the card, and put it into Transfer Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002663 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2664 cmd.cmdidx = MMC_CMD_SELECT_CARD;
Ajay Bhargav4a32fba2011-10-05 03:13:23 +00002665 cmd.resp_type = MMC_RSP_R1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002666 cmd.cmdarg = mmc->rca << 16;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002667 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002668
Thomas Chou1254c3d2010-12-24 13:12:21 +00002669 if (err)
2670 return err;
2671 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002672
Lei Wenea526762011-06-22 17:03:31 +00002673 /*
2674 * For SD, its erase group is always one sector
2675 */
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002676#if CONFIG_IS_ENABLED(MMC_WRITE)
Lei Wenea526762011-06-22 17:03:31 +00002677 mmc->erase_grp_size = 1;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002678#endif
Lei Wen31b99802011-05-02 16:26:26 +00002679 mmc->part_config = MMCPART_NOAVAILABLE;
Diego Santa Cruza7a75992014-12-23 10:50:27 +01002680
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002681 err = mmc_startup_v4(mmc);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002682 if (err)
2683 return err;
Sukumar Ghorai232293c2010-09-20 18:29:29 +05302684
Simon Glasse5db1152016-05-01 13:52:35 -06002685 err = mmc_set_capacity(mmc, mmc_get_blk_desc(mmc)->hwpart);
Stephen Warrene315ae82013-06-11 15:14:01 -06002686 if (err)
2687 return err;
2688
Marek Vasuta318a7a2018-04-15 00:37:11 +02002689#if CONFIG_IS_ENABLED(MMC_TINY)
2690 mmc_set_clock(mmc, mmc->legacy_speed, false);
Faiz Abbas01db77e2020-02-26 13:44:32 +05302691 mmc_select_mode(mmc, MMC_LEGACY);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002692 mmc_set_bus_width(mmc, 1);
2693#else
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002694 if (IS_SD(mmc)) {
2695 err = sd_get_capabilities(mmc);
2696 if (err)
2697 return err;
2698 err = sd_select_mode_and_width(mmc, mmc->card_caps);
2699 } else {
2700 err = mmc_get_capabilities(mmc);
2701 if (err)
2702 return err;
Masahiro Yamadabf1f25c2020-01-23 14:31:12 +09002703 err = mmc_select_mode_and_width(mmc, mmc->card_caps);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002704 }
Marek Vasuta318a7a2018-04-15 00:37:11 +02002705#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002706 if (err)
2707 return err;
2708
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002709 mmc->best_mode = mmc->selected_mode;
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00002710
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002711 /* Fix the block length for DDR mode */
2712 if (mmc->ddr_mode) {
2713 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002714#if CONFIG_IS_ENABLED(MMC_WRITE)
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002715 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002716#endif
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002717 }
2718
Andy Flemingad347bb2008-10-30 16:41:01 -05002719 /* fill in device description */
Simon Glasse5db1152016-05-01 13:52:35 -06002720 bdesc = mmc_get_blk_desc(mmc);
2721 bdesc->lun = 0;
2722 bdesc->hwpart = 0;
2723 bdesc->type = 0;
2724 bdesc->blksz = mmc->read_bl_len;
2725 bdesc->log2blksz = LOG2(bdesc->blksz);
2726 bdesc->lba = lldiv(mmc->capacity, mmc->read_bl_len);
Simon Glass7ec24132024-09-29 19:49:48 -06002727#if !defined(CONFIG_XPL_BUILD) || \
Sjoerd Simonsd67754f2015-12-04 23:27:40 +01002728 (defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \
Simon Glass7611ac62019-09-25 08:56:27 -06002729 !CONFIG_IS_ENABLED(USE_TINY_PRINTF))
Simon Glasse5db1152016-05-01 13:52:35 -06002730 sprintf(bdesc->vendor, "Man %06x Snr %04x%04x",
Taylor Hutt7367ec22012-10-20 17:15:59 +00002731 mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
2732 (mmc->cid[3] >> 16) & 0xffff);
Simon Glasse5db1152016-05-01 13:52:35 -06002733 sprintf(bdesc->product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002734 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
2735 (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
2736 (mmc->cid[2] >> 24) & 0xff);
Simon Glasse5db1152016-05-01 13:52:35 -06002737 sprintf(bdesc->revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002738 (mmc->cid[2] >> 16) & 0xf);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002739#else
Simon Glasse5db1152016-05-01 13:52:35 -06002740 bdesc->vendor[0] = 0;
2741 bdesc->product[0] = 0;
2742 bdesc->revision[0] = 0;
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002743#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002744
Simon Glass7ec24132024-09-29 19:49:48 -06002745#if !defined(CONFIG_DM_MMC) && (!defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT))
Andre Przywara17798042018-12-17 10:05:45 +00002746 part_init(bdesc);
2747#endif
2748
Andy Flemingad347bb2008-10-30 16:41:01 -05002749 return 0;
2750}
2751
Kim Phillips87ea3892012-10-29 13:34:43 +00002752static int mmc_send_if_cond(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002753{
2754 struct mmc_cmd cmd;
2755 int err;
2756
2757 cmd.cmdidx = SD_CMD_SEND_IF_COND;
2758 /* We set the bit if the host supports voltages between 2.7 and 3.6 V */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002759 cmd.cmdarg = ((mmc->cfg->voltages & 0xff8000) != 0) << 8 | 0xaa;
Andy Flemingad347bb2008-10-30 16:41:01 -05002760 cmd.resp_type = MMC_RSP_R7;
Andy Flemingad347bb2008-10-30 16:41:01 -05002761
2762 err = mmc_send_cmd(mmc, &cmd, NULL);
2763
2764 if (err)
2765 return err;
2766
Rabin Vincentb6eed942009-04-05 13:30:56 +05302767 if ((cmd.response[0] & 0xff) != 0xaa)
Jaehoon Chung7825d202016-07-19 16:33:36 +09002768 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002769 else
2770 mmc->version = SD_VERSION_2;
2771
2772 return 0;
2773}
2774
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002775#if !CONFIG_IS_ENABLED(DM_MMC)
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002776/* board-specific MMC power initializations. */
2777__weak void board_mmc_power_init(void)
2778{
2779}
Simon Glass833b80d2017-04-22 19:10:56 -06002780#endif
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002781
Peng Fan15305962016-10-11 15:08:43 +08002782static int mmc_power_init(struct mmc *mmc)
2783{
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002784#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002785#if CONFIG_IS_ENABLED(DM_REGULATOR)
Peng Fan15305962016-10-11 15:08:43 +08002786 int ret;
2787
2788 ret = device_get_supply_regulator(mmc->dev, "vmmc-supply",
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002789 &mmc->vmmc_supply);
2790 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002791 pr_debug("%s: No vmmc supply\n", mmc->dev->name);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002792
2793 ret = device_get_supply_regulator(mmc->dev, "vqmmc-supply",
2794 &mmc->vqmmc_supply);
2795 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002796 pr_debug("%s: No vqmmc supply\n", mmc->dev->name);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002797#endif
2798#else /* !CONFIG_DM_MMC */
2799 /*
2800 * Driver model should use a regulator, as above, rather than calling
2801 * out to board code.
2802 */
2803 board_mmc_power_init();
2804#endif
2805 return 0;
2806}
2807
2808/*
2809 * put the host in the initial state:
2810 * - turn on Vdd (card power supply)
2811 * - configure the bus width and clock to minimal values
2812 */
2813static void mmc_set_initial_state(struct mmc *mmc)
2814{
2815 int err;
2816
2817 /* First try to set 3.3V. If it fails set to 1.8V */
2818 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
2819 if (err != 0)
2820 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
2821 if (err != 0)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002822 pr_warn("mmc: failed to set signal voltage\n");
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002823
2824 mmc_select_mode(mmc, MMC_LEGACY);
2825 mmc_set_bus_width(mmc, 1);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002826 mmc_set_clock(mmc, 0, MMC_CLK_ENABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002827}
Peng Fan15305962016-10-11 15:08:43 +08002828
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002829static int mmc_power_on(struct mmc *mmc)
2830{
2831#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002832 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002833 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2834 true);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002835
Jonas Karlman0f28e182023-07-19 21:20:59 +00002836 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002837 printf("Error enabling VMMC supply : %d\n", ret);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002838 return ret;
2839 }
Peng Fan15305962016-10-11 15:08:43 +08002840 }
2841#endif
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002842 return 0;
2843}
2844
2845static int mmc_power_off(struct mmc *mmc)
2846{
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002847 mmc_set_clock(mmc, 0, MMC_CLK_DISABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002848#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
2849 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002850 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2851 false);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002852
Jonas Karlman0f28e182023-07-19 21:20:59 +00002853 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002854 pr_debug("Error disabling VMMC supply : %d\n", ret);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002855 return ret;
2856 }
2857 }
Simon Glass833b80d2017-04-22 19:10:56 -06002858#endif
Peng Fan15305962016-10-11 15:08:43 +08002859 return 0;
2860}
2861
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002862static int mmc_power_cycle(struct mmc *mmc)
2863{
2864 int ret;
2865
2866 ret = mmc_power_off(mmc);
2867 if (ret)
2868 return ret;
Yann Gautier6f558332019-09-19 17:56:12 +02002869
2870 ret = mmc_host_power_cycle(mmc);
2871 if (ret)
2872 return ret;
2873
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002874 /*
2875 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
2876 * to be on the safer side.
2877 */
2878 udelay(2000);
2879 return mmc_power_on(mmc);
2880}
2881
Pali Rohár7c639622021-07-14 16:37:29 +02002882int mmc_get_op_cond(struct mmc *mmc, bool quiet)
Andy Flemingad347bb2008-10-30 16:41:01 -05002883{
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002884 bool uhs_en = supports_uhs(mmc->cfg->host_caps);
Macpaul Lin028bde12011-11-14 23:35:39 +00002885 int err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002886
Lei Wen31b99802011-05-02 16:26:26 +00002887 if (mmc->has_init)
2888 return 0;
2889
Peng Fan15305962016-10-11 15:08:43 +08002890 err = mmc_power_init(mmc);
2891 if (err)
2892 return err;
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002893
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002894#ifdef CONFIG_MMC_QUIRKS
2895 mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN |
Joel Johnson5ea041b2020-01-11 09:08:14 -07002896 MMC_QUIRK_RETRY_SEND_CID |
2897 MMC_QUIRK_RETRY_APP_CMD;
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002898#endif
2899
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002900 err = mmc_power_cycle(mmc);
2901 if (err) {
2902 /*
2903 * if power cycling is not supported, we should not try
2904 * to use the UHS modes, because we wouldn't be able to
2905 * recover from an error during the UHS initialization.
2906 */
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002907 pr_debug("Unable to do a full power cycle. Disabling the UHS modes for safety\n");
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002908 uhs_en = false;
2909 mmc->host_caps &= ~UHS_CAPS;
2910 err = mmc_power_on(mmc);
2911 }
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002912 if (err)
2913 return err;
2914
Simon Glasseba48f92017-07-29 11:35:31 -06002915#if CONFIG_IS_ENABLED(DM_MMC)
Yangbo Luc46f5d72020-09-01 16:57:59 +08002916 /*
2917 * Re-initialization is needed to clear old configuration for
2918 * mmc rescan.
2919 */
2920 err = mmc_reinit(mmc);
Simon Glass394dfc02016-06-12 23:30:22 -06002921#else
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02002922 /* made sure it's not NULL earlier */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002923 err = mmc->cfg->ops->init(mmc);
Yangbo Luc46f5d72020-09-01 16:57:59 +08002924#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002925 if (err)
2926 return err;
Andrew Gabbasov9fc2a412014-12-01 06:59:09 -06002927 mmc->ddr_mode = 0;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02002928
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002929retry:
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002930 mmc_set_initial_state(mmc);
Jean-Jacques Hiblot5f23d872017-09-21 16:30:01 +02002931
Andy Flemingad347bb2008-10-30 16:41:01 -05002932 /* Reset the Card */
2933 err = mmc_go_idle(mmc);
2934
2935 if (err)
2936 return err;
2937
Marcel Ziswilerb2b7fc82019-05-20 02:44:53 +02002938 /* The internal partition reset to user partition(0) at every CMD0 */
Simon Glasse5db1152016-05-01 13:52:35 -06002939 mmc_get_blk_desc(mmc)->hwpart = 0;
Lei Wen31b99802011-05-02 16:26:26 +00002940
Andy Flemingad347bb2008-10-30 16:41:01 -05002941 /* Test for SD version 2 */
Macpaul Lin028bde12011-11-14 23:35:39 +00002942 err = mmc_send_if_cond(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05002943
Andy Flemingad347bb2008-10-30 16:41:01 -05002944 /* Now try to get the SD card's operating condition */
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002945 err = sd_send_op_cond(mmc, uhs_en);
2946 if (err && uhs_en) {
2947 uhs_en = false;
2948 mmc_power_cycle(mmc);
2949 goto retry;
2950 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002951
2952 /* If the command timed out, we check for an MMC card */
Jaehoon Chung7825d202016-07-19 16:33:36 +09002953 if (err == -ETIMEDOUT) {
Andy Flemingad347bb2008-10-30 16:41:01 -05002954 err = mmc_send_op_cond(mmc);
2955
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002956 if (err) {
Simon Glass7ec24132024-09-29 19:49:48 -06002957#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Pali Rohár7c639622021-07-14 16:37:29 +02002958 if (!quiet)
Simon Glass367e3852024-08-22 07:54:55 -06002959 log_err("Card did not respond to voltage select! : %d\n",
2960 err);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002961#endif
Jaehoon Chung7825d202016-07-19 16:33:36 +09002962 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002963 }
2964 }
2965
Jon Nettleton2663fe42018-06-11 15:26:19 +03002966 return err;
2967}
2968
2969int mmc_start_init(struct mmc *mmc)
2970{
2971 bool no_card;
2972 int err = 0;
2973
2974 /*
2975 * all hosts are capable of 1 bit bus-width and able to use the legacy
2976 * timings.
2977 */
Faiz Abbas01db77e2020-02-26 13:44:32 +05302978 mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) |
Aswath Govindrajubb5b9fe2021-08-13 23:04:41 +05302979 MMC_MODE_1BIT;
2980
2981 if (IS_ENABLED(CONFIG_MMC_SPEED_MODE_SET)) {
2982 if (mmc->user_speed_mode != MMC_MODES_END) {
2983 int i;
2984 /* set host caps */
2985 if (mmc->host_caps & MMC_CAP(mmc->user_speed_mode)) {
2986 /* Remove all existing speed capabilities */
2987 for (i = MMC_LEGACY; i < MMC_MODES_END; i++)
2988 mmc->host_caps &= ~MMC_CAP(i);
2989 mmc->host_caps |= (MMC_CAP(mmc->user_speed_mode)
2990 | MMC_CAP(MMC_LEGACY) |
2991 MMC_MODE_1BIT);
2992 } else {
Simon Glass367e3852024-08-22 07:54:55 -06002993 log_err("bus_mode requested is not supported\n");
Aswath Govindrajubb5b9fe2021-08-13 23:04:41 +05302994 return -EINVAL;
2995 }
2996 }
2997 }
Faiz Abbasf6fd4ec2020-02-26 13:44:30 +05302998#if CONFIG_IS_ENABLED(DM_MMC)
2999 mmc_deferred_probe(mmc);
3000#endif
Jon Nettleton2663fe42018-06-11 15:26:19 +03003001#if !defined(CONFIG_MMC_BROKEN_CD)
Jon Nettleton2663fe42018-06-11 15:26:19 +03003002 no_card = mmc_getcd(mmc) == 0;
3003#else
3004 no_card = 0;
3005#endif
3006#if !CONFIG_IS_ENABLED(DM_MMC)
Baruch Siach0448ce62019-07-22 15:52:12 +03003007 /* we pretend there's no card when init is NULL */
Jon Nettleton2663fe42018-06-11 15:26:19 +03003008 no_card = no_card || (mmc->cfg->ops->init == NULL);
3009#endif
3010 if (no_card) {
3011 mmc->has_init = 0;
Simon Glass7ec24132024-09-29 19:49:48 -06003012#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -06003013 log_err("MMC: no card present\n");
Jon Nettleton2663fe42018-06-11 15:26:19 +03003014#endif
3015 return -ENOMEDIUM;
3016 }
3017
Pali Rohár7c639622021-07-14 16:37:29 +02003018 err = mmc_get_op_cond(mmc, false);
Jon Nettleton2663fe42018-06-11 15:26:19 +03003019
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003020 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003021 mmc->init_in_progress = 1;
3022
3023 return err;
3024}
3025
3026static int mmc_complete_init(struct mmc *mmc)
3027{
3028 int err = 0;
3029
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003030 mmc->init_in_progress = 0;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003031 if (mmc->op_cond_pending)
3032 err = mmc_complete_op_cond(mmc);
3033
3034 if (!err)
3035 err = mmc_startup(mmc);
Lei Wen31b99802011-05-02 16:26:26 +00003036 if (err)
3037 mmc->has_init = 0;
3038 else
3039 mmc->has_init = 1;
3040 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05003041}
3042
Marek Vasutb0967402024-09-06 19:10:42 +02003043static void __maybe_unused mmc_cyclic_cd_poll(struct cyclic_info *c)
3044{
3045 struct mmc *m = CONFIG_IS_ENABLED(CYCLIC, (container_of(c, struct mmc, cyclic)), (NULL));
3046
3047 if (!m->has_init)
3048 return;
3049
3050 if (mmc_getcd(m))
3051 return;
3052
3053 mmc_deinit(m);
3054 m->has_init = 0;
3055}
3056
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003057int mmc_init(struct mmc *mmc)
3058{
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003059 int err = 0;
Vipul Kumardbad7b42018-05-03 12:20:54 +05303060 __maybe_unused ulong start;
Simon Glass5f4bd8c2017-07-04 13:31:19 -06003061#if CONFIG_IS_ENABLED(DM_MMC)
Simon Glass59bc6f22016-05-01 13:52:41 -06003062 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003063
Simon Glass59bc6f22016-05-01 13:52:41 -06003064 upriv->mmc = mmc;
3065#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003066 if (mmc->has_init)
3067 return 0;
Mateusz Zalegada351782014-04-29 20:15:30 +02003068
3069 start = get_timer(0);
3070
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003071 if (!mmc->init_in_progress)
3072 err = mmc_start_init(mmc);
3073
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003074 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003075 err = mmc_complete_init(mmc);
Jagan Teki9bee2b52017-01-10 11:18:43 +01003076 if (err)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09003077 pr_info("%s: %d, time %lu\n", __func__, err, get_timer(start));
Jagan Teki9bee2b52017-01-10 11:18:43 +01003078
Marek Vasutb0967402024-09-06 19:10:42 +02003079 if (CONFIG_IS_ENABLED(CYCLIC, (!mmc->cyclic.func), (NULL))) {
3080 /* Register cyclic function for card detect polling */
3081 CONFIG_IS_ENABLED(CYCLIC, (cyclic_register(&mmc->cyclic,
3082 mmc_cyclic_cd_poll,
3083 100 * 1000,
3084 mmc->cfg->name)));
3085 }
3086
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003087 return err;
3088}
3089
Marek Vasuta4773fc2019-01-29 04:45:51 +01003090int mmc_deinit(struct mmc *mmc)
3091{
3092 u32 caps_filtered;
3093
Marek Vasutb0967402024-09-06 19:10:42 +02003094 if (CONFIG_IS_ENABLED(CYCLIC, (mmc->cyclic.func), (NULL)))
3095 CONFIG_IS_ENABLED(CYCLIC, (cyclic_unregister(&mmc->cyclic)));
3096
Marek Vasut67c77f92024-03-17 04:01:22 +01003097 if (!CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) &&
3098 !CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) &&
3099 !CONFIG_IS_ENABLED(MMC_HS400_SUPPORT))
3100 return 0;
3101
Marek Vasuta4773fc2019-01-29 04:45:51 +01003102 if (!mmc->has_init)
3103 return 0;
3104
3105 if (IS_SD(mmc)) {
3106 caps_filtered = mmc->card_caps &
3107 ~(MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) |
3108 MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
3109 MMC_CAP(UHS_SDR104));
3110
3111 return sd_select_mode_and_width(mmc, caps_filtered);
3112 } else {
3113 caps_filtered = mmc->card_caps &
Ye Li3679e802021-08-17 17:20:34 +08003114 ~(MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_HS_400) | MMC_CAP(MMC_HS_400_ES));
Marek Vasuta4773fc2019-01-29 04:45:51 +01003115
3116 return mmc_select_mode_and_width(mmc, caps_filtered);
3117 }
3118}
Marek Vasuta4773fc2019-01-29 04:45:51 +01003119
Markus Niebel03951412013-12-16 13:40:46 +01003120int mmc_set_dsr(struct mmc *mmc, u16 val)
3121{
3122 mmc->dsr = val;
3123 return 0;
3124}
3125
Jeroen Hofstee47726302014-07-10 22:46:28 +02003126/* CPU-specific MMC initializations */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003127__weak int cpu_mmc_init(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003128{
3129 return -1;
3130}
3131
Jeroen Hofstee47726302014-07-10 22:46:28 +02003132/* board-specific MMC initializations. */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003133__weak int board_mmc_init(struct bd_info *bis)
Jeroen Hofstee47726302014-07-10 22:46:28 +02003134{
3135 return -1;
3136}
Andy Flemingad347bb2008-10-30 16:41:01 -05003137
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003138void mmc_set_preinit(struct mmc *mmc, int preinit)
3139{
3140 mmc->preinit = preinit;
3141}
3142
Faiz Abbasb3857fd2018-02-12 19:35:24 +05303143#if CONFIG_IS_ENABLED(DM_MMC)
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003144static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003145{
Simon Glass547cb342015-12-29 05:22:49 -07003146 int ret, i;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003147 struct uclass *uc;
Simon Glass547cb342015-12-29 05:22:49 -07003148 struct udevice *dev;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003149
3150 ret = uclass_get(UCLASS_MMC, &uc);
3151 if (ret)
3152 return ret;
3153
Simon Glass547cb342015-12-29 05:22:49 -07003154 /*
3155 * Try to add them in sequence order. Really with driver model we
3156 * should allow holes, but the current MMC list does not allow that.
3157 * So if we request 0, 1, 3 we will get 0, 1, 2.
3158 */
3159 for (i = 0; ; i++) {
3160 ret = uclass_get_device_by_seq(UCLASS_MMC, i, &dev);
3161 if (ret == -ENODEV)
3162 break;
3163 }
3164 uclass_foreach_dev(dev, uc) {
3165 ret = device_probe(dev);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003166 if (ret)
Simon Glass367e3852024-08-22 07:54:55 -06003167 log_err("%s - probe failed: %d\n", dev->name, ret);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003168 }
3169
3170 return 0;
3171}
3172#else
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003173static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003174{
3175 if (board_mmc_init(bis) < 0)
3176 cpu_mmc_init(bis);
3177
3178 return 0;
3179}
3180#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003181
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003182int mmc_initialize(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003183{
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003184 static int initialized = 0;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003185 int ret;
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003186 if (initialized) /* Avoid initializing mmc multiple times */
3187 return 0;
3188 initialized = 1;
3189
Simon Glass5f4bd8c2017-07-04 13:31:19 -06003190#if !CONFIG_IS_ENABLED(BLK)
Marek Vasutf537e392016-12-01 02:06:33 +01003191#if !CONFIG_IS_ENABLED(MMC_TINY)
Simon Glasse5db1152016-05-01 13:52:35 -06003192 mmc_list_init();
3193#endif
Marek Vasutf537e392016-12-01 02:06:33 +01003194#endif
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003195 ret = mmc_probe(bis);
3196 if (ret)
3197 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05003198
Simon Glass7ec24132024-09-29 19:49:48 -06003199#ifndef CONFIG_XPL_BUILD
Andy Flemingad347bb2008-10-30 16:41:01 -05003200 print_mmc_devices(',');
Ying Zhang9ff70262013-08-16 15:16:11 +08003201#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05003202
Simon Glasse5db1152016-05-01 13:52:35 -06003203 mmc_do_preinit();
Andy Flemingad347bb2008-10-30 16:41:01 -05003204 return 0;
3205}
Tomas Melinc17dae52016-11-25 11:01:03 +02003206
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303207#if CONFIG_IS_ENABLED(DM_MMC)
3208int mmc_init_device(int num)
3209{
3210 struct udevice *dev;
3211 struct mmc *m;
3212 int ret;
3213
Aswath Govindraju57e2ccb2021-03-25 12:48:47 +05303214 if (uclass_get_device_by_seq(UCLASS_MMC, num, &dev)) {
3215 ret = uclass_get_device(UCLASS_MMC, num, &dev);
3216 if (ret)
Simon Glass9c3e9262024-09-20 09:24:38 +02003217 return log_msg_ret("ini", ret);
Aswath Govindraju57e2ccb2021-03-25 12:48:47 +05303218 }
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303219
3220 m = mmc_get_mmc_dev(dev);
3221 if (!m)
3222 return 0;
Venkatesh Yadav Abbarapu6738fcb2022-09-29 10:22:49 +05303223
3224 /* Initialising user set speed mode */
3225 m->user_speed_mode = MMC_MODES_END;
3226
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303227 if (m->preinit)
3228 mmc_start_init(m);
3229
3230 return 0;
3231}
3232#endif
3233
Tomas Melinc17dae52016-11-25 11:01:03 +02003234#ifdef CONFIG_CMD_BKOPS_ENABLE
Marek Vasutefdeed62023-01-05 15:19:08 +01003235int mmc_set_bkops_enable(struct mmc *mmc, bool autobkops, bool enable)
Tomas Melinc17dae52016-11-25 11:01:03 +02003236{
3237 int err;
Marek Vasutefdeed62023-01-05 15:19:08 +01003238 u32 bit = autobkops ? BIT(1) : BIT(0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003239 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
3240
3241 err = mmc_send_ext_csd(mmc, ext_csd);
3242 if (err) {
3243 puts("Could not get ext_csd register values\n");
3244 return err;
3245 }
3246
3247 if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) {
3248 puts("Background operations not supported on device\n");
3249 return -EMEDIUMTYPE;
3250 }
3251
Marek Vasutefdeed62023-01-05 15:19:08 +01003252 if (enable && (ext_csd[EXT_CSD_BKOPS_EN] & bit)) {
Tomas Melinc17dae52016-11-25 11:01:03 +02003253 puts("Background operations already enabled\n");
3254 return 0;
3255 }
3256
Marek Vasutefdeed62023-01-05 15:19:08 +01003257 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN,
3258 enable ? bit : 0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003259 if (err) {
Marek Vasutefdeed62023-01-05 15:19:08 +01003260 printf("Failed to %sable manual background operations\n",
3261 enable ? "en" : "dis");
Tomas Melinc17dae52016-11-25 11:01:03 +02003262 return err;
3263 }
3264
Marek Vasutefdeed62023-01-05 15:19:08 +01003265 printf("%sabled %s background operations\n",
3266 enable ? "En" : "Dis", autobkops ? "auto" : "manual");
Tomas Melinc17dae52016-11-25 11:01:03 +02003267
3268 return 0;
3269}
3270#endif
David Woodhouse49fee032020-08-04 10:05:46 +01003271
3272__weak int mmc_get_env_dev(void)
3273{
3274#ifdef CONFIG_SYS_MMC_ENV_DEV
3275 return CONFIG_SYS_MMC_ENV_DEV;
3276#else
3277 return 0;
3278#endif
3279}