blob: 2c1f4f9c336bfed6c075a7bc47f373e8f8effa86 [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>
Tom Rini546e96b2025-05-21 16:51:20 -060023#include <linux/sizes.h>
Peng Fan15305962016-10-11 15:08:43 +080024#include <power/regulator.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050025#include <malloc.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060026#include <memalign.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050027#include <linux/list.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060028#include <linux/printk.h>
Rabin Vincent69d4e2c2009-04-05 13:30:54 +053029#include <div64.h>
Paul Burton8d30cc92013-09-09 15:30:26 +010030#include "mmc_private.h"
Andy Flemingad347bb2008-10-30 16:41:01 -050031
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +020032#define DEFAULT_CMD6_TIMEOUT_MS 500
33
Tim Harvey728cbde2024-05-31 08:36:34 -070034/**
35 * names of emmc BOOT_PARTITION_ENABLE values
36 *
37 * Boot Area Partitions - name consistent with Linux
38 */
39const char *emmc_boot_part_names[] = {
40 "default", /* EMMC_BOOT_PART_DEFAULT */
41 "boot0", /* EMMC_BOOT_PART_BOOT1 */
42 "boot1", /* EMMC_BOOT_PART_BOOT2 */
43 "",
44 "",
45 "",
46 "",
47 "user", /* EMMC_BOOT_PART_USER */
48};
49
50/**
51 * names of emmc 'hardware partitions' consistent with:
52 * - value used in mmc_switch()
53 * - value used by PARTITION_CONFIG PARTITION_ACCESS field
54 *
55 * Boot Area Partitions - name consistent with Linux
56 * General Perpose Partitions - name consistent with 'mmc hwpartition' usage
57 */
58const char *emmc_hwpart_names[] = {
59 "user", /* EMMC_HWPART_DEFAULT */
60 "boot0", /* EMMC_HWPART_BOOT1 */
61 "boot1", /* EMMC_HWPART_BOOT2 */
62 "rpmb", /* EMMC_HWPART_RPMB */
63 "gp1", /* EMMC_HWPART_GP1 */
64 "gp2", /* EMMC_HWPART_GP2 */
65 "gp3", /* EMMC_HWPART_GP3 */
66 "gp4", /* EMMC_HWPART_GP4 */
67};
68
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +020069static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
Marek Vasutf537e392016-12-01 02:06:33 +010070
Simon Glasseba48f92017-07-29 11:35:31 -060071#if !CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020072
Sam Protsenkodb174c62019-08-14 22:52:51 +030073static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020074{
Loic Poulain9c32f4f2022-05-26 16:37:21 +020075 if (mmc->cfg->ops->wait_dat0)
76 return mmc->cfg->ops->wait_dat0(mmc, state, timeout_us);
77
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020078 return -ENOSYS;
79}
80
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +020081__weak int board_mmc_getwp(struct mmc *mmc)
Nikita Kiryanov020f2612012-12-03 02:19:46 +000082{
83 return -1;
84}
85
86int mmc_getwp(struct mmc *mmc)
87{
88 int wp;
89
90 wp = board_mmc_getwp(mmc);
91
Peter Korsgaardf7b15102013-03-21 04:00:03 +000092 if (wp < 0) {
Pantelis Antoniou2c850462014-03-11 19:34:20 +020093 if (mmc->cfg->ops->getwp)
94 wp = mmc->cfg->ops->getwp(mmc);
Peter Korsgaardf7b15102013-03-21 04:00:03 +000095 else
96 wp = 0;
97 }
Nikita Kiryanov020f2612012-12-03 02:19:46 +000098
99 return wp;
100}
101
Jeroen Hofstee47726302014-07-10 22:46:28 +0200102__weak int board_mmc_getcd(struct mmc *mmc)
103{
Stefano Babic6e00edf2010-02-05 15:04:43 +0100104 return -1;
105}
Simon Glass394dfc02016-06-12 23:30:22 -0600106#endif
Stefano Babic6e00edf2010-02-05 15:04:43 +0100107
Simon Glassb23d96e2016-06-12 23:30:20 -0600108#ifdef CONFIG_MMC_TRACE
109void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
Andy Flemingad347bb2008-10-30 16:41:01 -0500110{
Simon Glassb23d96e2016-06-12 23:30:20 -0600111 printf("CMD_SEND:%d\n", cmd->cmdidx);
Marek Vasut6eeee302019-03-23 18:54:45 +0100112 printf("\t\tARG\t\t\t 0x%08x\n", cmd->cmdarg);
Simon Glassb23d96e2016-06-12 23:30:20 -0600113}
Marek Vasutdccb6082012-03-15 18:41:35 +0000114
Simon Glassb23d96e2016-06-12 23:30:20 -0600115void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret)
116{
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000117 int i;
118 u8 *ptr;
119
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700120 if (ret) {
121 printf("\t\tRET\t\t\t %d\n", ret);
122 } else {
123 switch (cmd->resp_type) {
124 case MMC_RSP_NONE:
125 printf("\t\tMMC_RSP_NONE\n");
126 break;
127 case MMC_RSP_R1:
Marek Vasut6eeee302019-03-23 18:54:45 +0100128 printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700129 cmd->response[0]);
130 break;
131 case MMC_RSP_R1b:
Marek Vasut6eeee302019-03-23 18:54:45 +0100132 printf("\t\tMMC_RSP_R1b\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700133 cmd->response[0]);
134 break;
135 case MMC_RSP_R2:
Marek Vasut6eeee302019-03-23 18:54:45 +0100136 printf("\t\tMMC_RSP_R2\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700137 cmd->response[0]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100138 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700139 cmd->response[1]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100140 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700141 cmd->response[2]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100142 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700143 cmd->response[3]);
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000144 printf("\n");
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700145 printf("\t\t\t\t\tDUMPING DATA\n");
146 for (i = 0; i < 4; i++) {
147 int j;
148 printf("\t\t\t\t\t%03d - ", i*4);
149 ptr = (u8 *)&cmd->response[i];
150 ptr += 3;
151 for (j = 0; j < 4; j++)
Marek Vasut6eeee302019-03-23 18:54:45 +0100152 printf("%02x ", *ptr--);
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700153 printf("\n");
154 }
155 break;
156 case MMC_RSP_R3:
Marek Vasut6eeee302019-03-23 18:54:45 +0100157 printf("\t\tMMC_RSP_R3,4\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700158 cmd->response[0]);
159 break;
160 default:
161 printf("\t\tERROR MMC rsp not supported\n");
162 break;
Bin Meng4a4ef872016-03-17 21:53:13 -0700163 }
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000164 }
Simon Glassb23d96e2016-06-12 23:30:20 -0600165}
166
167void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
168{
169 int status;
170
171 status = (cmd->response[0] & MMC_STATUS_CURR_STATE) >> 9;
172 printf("CURR STATE:%d\n", status);
173}
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000174#endif
Simon Glassb23d96e2016-06-12 23:30:20 -0600175
Pali Rohár377ecee2022-04-03 00:20:10 +0200176#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG) || CONFIG_VAL(LOGLEVEL) >= LOGL_DEBUG
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200177const char *mmc_mode_name(enum bus_mode mode)
178{
179 static const char *const names[] = {
180 [MMC_LEGACY] = "MMC legacy",
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200181 [MMC_HS] = "MMC High Speed (26MHz)",
182 [SD_HS] = "SD High Speed (50MHz)",
183 [UHS_SDR12] = "UHS SDR12 (25MHz)",
184 [UHS_SDR25] = "UHS SDR25 (50MHz)",
185 [UHS_SDR50] = "UHS SDR50 (100MHz)",
186 [UHS_SDR104] = "UHS SDR104 (208MHz)",
187 [UHS_DDR50] = "UHS DDR50 (50MHz)",
188 [MMC_HS_52] = "MMC High Speed (52MHz)",
189 [MMC_DDR_52] = "MMC DDR52 (52MHz)",
190 [MMC_HS_200] = "HS200 (200MHz)",
Peng Fan46801252018-08-10 14:07:54 +0800191 [MMC_HS_400] = "HS400 (200MHz)",
Peng Faneede83b2019-07-10 14:43:07 +0800192 [MMC_HS_400_ES] = "HS400ES (200MHz)",
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200193 };
194
195 if (mode >= MMC_MODES_END)
196 return "Unknown mode";
197 else
198 return names[mode];
199}
200#endif
201
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200202static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
203{
204 static const int freqs[] = {
Jaehoon Chung7c5c7302018-01-30 14:10:16 +0900205 [MMC_LEGACY] = 25000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200206 [MMC_HS] = 26000000,
207 [SD_HS] = 50000000,
Jaehoon Chung7c5c7302018-01-30 14:10:16 +0900208 [MMC_HS_52] = 52000000,
209 [MMC_DDR_52] = 52000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200210 [UHS_SDR12] = 25000000,
211 [UHS_SDR25] = 50000000,
212 [UHS_SDR50] = 100000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200213 [UHS_DDR50] = 50000000,
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100214 [UHS_SDR104] = 208000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200215 [MMC_HS_200] = 200000000,
Peng Fan46801252018-08-10 14:07:54 +0800216 [MMC_HS_400] = 200000000,
Peng Faneede83b2019-07-10 14:43:07 +0800217 [MMC_HS_400_ES] = 200000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200218 };
219
220 if (mode == MMC_LEGACY)
221 return mmc->legacy_speed;
222 else if (mode >= MMC_MODES_END)
223 return 0;
224 else
225 return freqs[mode];
226}
227
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200228static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
229{
230 mmc->selected_mode = mode;
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200231 mmc->tran_speed = mmc_mode2freq(mmc, mode);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200232 mmc->ddr_mode = mmc_is_mode_ddr(mode);
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900233 pr_debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
234 mmc->tran_speed / 1000000);
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200235 return 0;
236}
237
Simon Glasseba48f92017-07-29 11:35:31 -0600238#if !CONFIG_IS_ENABLED(DM_MMC)
Simon Glassb23d96e2016-06-12 23:30:20 -0600239int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
240{
241 int ret;
242
243 mmmc_trace_before_send(mmc, cmd);
244 ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
245 mmmc_trace_after_send(mmc, cmd, ret);
246
Marek Vasutdccb6082012-03-15 18:41:35 +0000247 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -0500248}
Simon Glass394dfc02016-06-12 23:30:22 -0600249#endif
Andy Flemingad347bb2008-10-30 16:41:01 -0500250
Sean Anderson86325092020-10-17 08:36:27 -0400251/**
252 * mmc_send_cmd_retry() - send a command to the mmc device, retrying on error
253 *
254 * @dev: device to receive the command
255 * @cmd: command to send
256 * @data: additional data to send/receive
257 * @retries: how many times to retry; mmc_send_cmd is always called at least
258 * once
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100259 * Return: 0 if ok, -ve on error
Sean Anderson86325092020-10-17 08:36:27 -0400260 */
261static int mmc_send_cmd_retry(struct mmc *mmc, struct mmc_cmd *cmd,
262 struct mmc_data *data, uint retries)
263{
264 int ret;
265
266 do {
267 ret = mmc_send_cmd(mmc, cmd, data);
268 } while (ret && retries--);
269
270 return ret;
271}
272
273/**
274 * mmc_send_cmd_quirks() - send a command to the mmc device, retrying if a
275 * specific quirk is enabled
276 *
277 * @dev: device to receive the command
278 * @cmd: command to send
279 * @data: additional data to send/receive
280 * @quirk: retry only if this quirk is enabled
281 * @retries: how many times to retry; mmc_send_cmd is always called at least
282 * once
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100283 * Return: 0 if ok, -ve on error
Sean Anderson86325092020-10-17 08:36:27 -0400284 */
285static int mmc_send_cmd_quirks(struct mmc *mmc, struct mmc_cmd *cmd,
286 struct mmc_data *data, u32 quirk, uint retries)
287{
Simon Glass68f3ced2023-02-05 15:40:16 -0700288 if (IS_ENABLED(CONFIG_MMC_QUIRKS) && mmc->quirks & quirk)
Sean Anderson86325092020-10-17 08:36:27 -0400289 return mmc_send_cmd_retry(mmc, cmd, data, retries);
290 else
291 return mmc_send_cmd(mmc, cmd, data);
292}
293
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200294int mmc_send_status(struct mmc *mmc, unsigned int *status)
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000295{
296 struct mmc_cmd cmd;
Sean Anderson86325092020-10-17 08:36:27 -0400297 int ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000298
299 cmd.cmdidx = MMC_CMD_SEND_STATUS;
300 cmd.resp_type = MMC_RSP_R1;
Marek Vasutc4427392011-08-10 09:24:48 +0200301 if (!mmc_host_is_spi(mmc))
302 cmd.cmdarg = mmc->rca << 16;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000303
Sean Anderson86325092020-10-17 08:36:27 -0400304 ret = mmc_send_cmd_retry(mmc, &cmd, NULL, 4);
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200305 mmc_trace_state(mmc, &cmd);
Sean Anderson86325092020-10-17 08:36:27 -0400306 if (!ret)
307 *status = cmd.response[0];
308
309 return ret;
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200310}
311
Sam Protsenkodb174c62019-08-14 22:52:51 +0300312int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200313{
314 unsigned int status;
315 int err;
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +0200316
Sam Protsenkodb174c62019-08-14 22:52:51 +0300317 err = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
Jean-Jacques Hiblot4f04a322019-07-02 10:53:53 +0200318 if (err != -ENOSYS)
319 return err;
320
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200321 while (1) {
322 err = mmc_send_status(mmc, &status);
323 if (err)
324 return err;
325
326 if ((status & MMC_STATUS_RDY_FOR_DATA) &&
327 (status & MMC_STATUS_CURR_STATE) !=
328 MMC_STATE_PRG)
329 break;
330
331 if (status & MMC_STATUS_MASK) {
Simon Glass7ec24132024-09-29 19:49:48 -0600332#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -0600333 log_err("Status Error: %#08x\n", status);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100334#endif
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200335 return -ECOMM;
336 }
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000337
Sam Protsenkodb174c62019-08-14 22:52:51 +0300338 if (timeout_ms-- <= 0)
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500339 break;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000340
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500341 udelay(1000);
342 }
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000343
Sam Protsenkodb174c62019-08-14 22:52:51 +0300344 if (timeout_ms <= 0) {
Simon Glass7ec24132024-09-29 19:49:48 -0600345#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -0600346 log_err("Timeout waiting card ready\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100347#endif
Jaehoon Chung7825d202016-07-19 16:33:36 +0900348 return -ETIMEDOUT;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000349 }
350
351 return 0;
352}
353
Paul Burton8d30cc92013-09-09 15:30:26 +0100354int mmc_set_blocklen(struct mmc *mmc, int len)
Andy Flemingad347bb2008-10-30 16:41:01 -0500355{
356 struct mmc_cmd cmd;
357
Andrew Gabbasov9fc2a412014-12-01 06:59:09 -0600358 if (mmc->ddr_mode)
Jaehoon Chung38ce30b2014-05-16 13:59:54 +0900359 return 0;
360
Andy Flemingad347bb2008-10-30 16:41:01 -0500361 cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
362 cmd.resp_type = MMC_RSP_R1;
363 cmd.cmdarg = len;
Andy Flemingad347bb2008-10-30 16:41:01 -0500364
Sean Anderson86325092020-10-17 08:36:27 -0400365 return mmc_send_cmd_quirks(mmc, &cmd, NULL,
366 MMC_QUIRK_RETRY_SET_BLOCKLEN, 4);
Andy Flemingad347bb2008-10-30 16:41:01 -0500367}
368
Tom Rinidec7ea02024-05-20 13:35:03 -0600369#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200370static const u8 tuning_blk_pattern_4bit[] = {
371 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
372 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
373 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
374 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
375 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
376 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
377 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
378 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
379};
380
381static const u8 tuning_blk_pattern_8bit[] = {
382 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
383 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
384 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
385 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
386 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
387 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
388 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
389 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
390 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
391 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
392 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
393 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
394 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
395 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
396 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
397 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
398};
399
Marek Vasutdad81fb2024-02-20 09:36:23 +0100400int mmc_send_tuning(struct mmc *mmc, u32 opcode)
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200401{
402 struct mmc_cmd cmd;
403 struct mmc_data data;
404 const u8 *tuning_block_pattern;
405 int size, err;
406
407 if (mmc->bus_width == 8) {
408 tuning_block_pattern = tuning_blk_pattern_8bit;
409 size = sizeof(tuning_blk_pattern_8bit);
410 } else if (mmc->bus_width == 4) {
411 tuning_block_pattern = tuning_blk_pattern_4bit;
412 size = sizeof(tuning_blk_pattern_4bit);
413 } else {
414 return -EINVAL;
415 }
416
417 ALLOC_CACHE_ALIGN_BUFFER(u8, data_buf, size);
418
419 cmd.cmdidx = opcode;
420 cmd.cmdarg = 0;
421 cmd.resp_type = MMC_RSP_R1;
422
423 data.dest = (void *)data_buf;
424 data.blocks = 1;
425 data.blocksize = size;
426 data.flags = MMC_DATA_READ;
427
428 err = mmc_send_cmd(mmc, &cmd, &data);
429 if (err)
430 return err;
431
432 if (memcmp(data_buf, tuning_block_pattern, size))
433 return -EIO;
434
435 return 0;
436}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100437#endif
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200438
Hai Pham27abf9f2023-06-20 00:38:24 +0200439int mmc_send_stop_transmission(struct mmc *mmc, bool write)
440{
441 struct mmc_cmd cmd;
442
443 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
444 cmd.cmdarg = 0;
445 /*
446 * JEDEC Standard No. 84-B51 Page 126
447 * CMD12 STOP_TRANSMISSION R1/R1b[3]
448 * NOTE 3 R1 for read cases and R1b for write cases.
449 *
450 * Physical Layer Simplified Specification Version 9.00
451 * 7.3.1.3 Detailed Command Description
452 * CMD12 R1b
453 */
454 cmd.resp_type = (IS_SD(mmc) || write) ? MMC_RSP_R1b : MMC_RSP_R1;
455
456 return mmc_send_cmd(mmc, &cmd, NULL);
457}
458
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200459static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
Kim Phillips87ea3892012-10-29 13:34:43 +0000460 lbaint_t blkcnt)
Andy Flemingad347bb2008-10-30 16:41:01 -0500461{
462 struct mmc_cmd cmd;
463 struct mmc_data data;
464
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700465 if (blkcnt > 1)
466 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
467 else
468 cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
Andy Flemingad347bb2008-10-30 16:41:01 -0500469
470 if (mmc->high_capacity)
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700471 cmd.cmdarg = start;
Andy Flemingad347bb2008-10-30 16:41:01 -0500472 else
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700473 cmd.cmdarg = start * mmc->read_bl_len;
Andy Flemingad347bb2008-10-30 16:41:01 -0500474
475 cmd.resp_type = MMC_RSP_R1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500476
477 data.dest = dst;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700478 data.blocks = blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500479 data.blocksize = mmc->read_bl_len;
480 data.flags = MMC_DATA_READ;
481
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700482 if (mmc_send_cmd(mmc, &cmd, &data))
483 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500484
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700485 if (blkcnt > 1) {
Hai Pham27abf9f2023-06-20 00:38:24 +0200486 if (mmc_send_stop_transmission(mmc, false)) {
Simon Glass7ec24132024-09-29 19:49:48 -0600487#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -0600488 log_err("mmc fail to send stop cmd\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100489#endif
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700490 return 0;
491 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500492 }
493
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700494 return blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500495}
496
Marek Vasut31976d92020-04-04 12:45:05 +0200497#if !CONFIG_IS_ENABLED(DM_MMC)
498static int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
499{
500 if (mmc->cfg->ops->get_b_max)
501 return mmc->cfg->ops->get_b_max(mmc, dst, blkcnt);
502 else
503 return mmc->cfg->b_max;
504}
505#endif
506
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600507#if CONFIG_IS_ENABLED(BLK)
Simon Glass62e293a2016-06-12 23:30:15 -0600508ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
Simon Glass59bc6f22016-05-01 13:52:41 -0600509#else
Simon Glass62e293a2016-06-12 23:30:15 -0600510ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
511 void *dst)
Simon Glass59bc6f22016-05-01 13:52:41 -0600512#endif
Andy Flemingad347bb2008-10-30 16:41:01 -0500513{
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600514#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -0700515 struct blk_desc *block_dev = dev_get_uclass_plat(dev);
Simon Glass59bc6f22016-05-01 13:52:41 -0600516#endif
Simon Glass2f26fff2016-02-29 15:25:51 -0700517 int dev_num = block_dev->devnum;
Stephen Warren1e0f92a2015-12-07 11:38:49 -0700518 int err;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700519 lbaint_t cur, blocks_todo = blkcnt;
Marek Vasut31976d92020-04-04 12:45:05 +0200520 uint b_max;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700521
522 if (blkcnt == 0)
523 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500524
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700525 struct mmc *mmc = find_mmc_device(dev_num);
Andy Flemingad347bb2008-10-30 16:41:01 -0500526 if (!mmc)
527 return 0;
528
Marek Vasutf537e392016-12-01 02:06:33 +0100529 if (CONFIG_IS_ENABLED(MMC_TINY))
530 err = mmc_switch_part(mmc, block_dev->hwpart);
531 else
532 err = blk_dselect_hwpart(block_dev, block_dev->hwpart);
533
Stephen Warren1e0f92a2015-12-07 11:38:49 -0700534 if (err < 0)
535 return 0;
536
Simon Glasse5db1152016-05-01 13:52:35 -0600537 if ((start + blkcnt) > block_dev->lba) {
Simon Glass7ec24132024-09-29 19:49:48 -0600538#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -0600539 log_err("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
540 start + blkcnt, block_dev->lba);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100541#endif
Lei Wene1cc9c82010-09-13 22:07:27 +0800542 return 0;
543 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500544
Simon Glassa4343c42015-06-23 15:38:50 -0600545 if (mmc_set_blocklen(mmc, mmc->read_bl_len)) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900546 pr_debug("%s: Failed to set blocklen\n", __func__);
Andy Flemingad347bb2008-10-30 16:41:01 -0500547 return 0;
Simon Glassa4343c42015-06-23 15:38:50 -0600548 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500549
Marek Vasut31976d92020-04-04 12:45:05 +0200550 b_max = mmc_get_b_max(mmc, dst, blkcnt);
551
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700552 do {
Marek Vasut31976d92020-04-04 12:45:05 +0200553 cur = (blocks_todo > b_max) ? b_max : blocks_todo;
Simon Glassa4343c42015-06-23 15:38:50 -0600554 if (mmc_read_blocks(mmc, dst, start, cur) != cur) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900555 pr_debug("%s: Failed to read blocks\n", __func__);
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700556 return 0;
Simon Glassa4343c42015-06-23 15:38:50 -0600557 }
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700558 blocks_todo -= cur;
559 start += cur;
560 dst += cur * mmc->read_bl_len;
561 } while (blocks_todo > 0);
Andy Flemingad347bb2008-10-30 16:41:01 -0500562
563 return blkcnt;
564}
565
Kim Phillips87ea3892012-10-29 13:34:43 +0000566static int mmc_go_idle(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -0500567{
568 struct mmc_cmd cmd;
569 int err;
570
571 udelay(1000);
572
573 cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
574 cmd.cmdarg = 0;
575 cmd.resp_type = MMC_RSP_NONE;
Andy Flemingad347bb2008-10-30 16:41:01 -0500576
577 err = mmc_send_cmd(mmc, &cmd, NULL);
578
579 if (err)
580 return err;
581
582 udelay(2000);
583
584 return 0;
585}
586
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100587#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200588static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
589{
590 struct mmc_cmd cmd;
591 int err = 0;
592
593 /*
594 * Send CMD11 only if the request is to switch the card to
595 * 1.8V signalling.
596 */
597 if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
598 return mmc_set_signal_voltage(mmc, signal_voltage);
599
600 cmd.cmdidx = SD_CMD_SWITCH_UHS18V;
601 cmd.cmdarg = 0;
602 cmd.resp_type = MMC_RSP_R1;
603
604 err = mmc_send_cmd(mmc, &cmd, NULL);
605 if (err)
606 return err;
607
608 if (!mmc_host_is_spi(mmc) && (cmd.response[0] & MMC_STATUS_ERROR))
609 return -EIO;
610
611 /*
612 * The card should drive cmd and dat[0:3] low immediately
613 * after the response of cmd11, but wait 100 us to be sure
614 */
615 err = mmc_wait_dat0(mmc, 0, 100);
616 if (err == -ENOSYS)
617 udelay(100);
618 else if (err)
619 return -ETIMEDOUT;
620
621 /*
622 * During a signal voltage level switch, the clock must be gated
623 * for 5 ms according to the SD spec
624 */
Jaehoon Chung239cb2f2018-01-26 19:25:29 +0900625 mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200626
627 err = mmc_set_signal_voltage(mmc, signal_voltage);
628 if (err)
629 return err;
630
631 /* Keep clock gated for at least 10 ms, though spec only says 5 ms */
632 mdelay(10);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +0900633 mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200634
635 /*
636 * Failure to switch is indicated by the card holding
637 * dat[0:3] low. Wait for at least 1 ms according to spec
638 */
639 err = mmc_wait_dat0(mmc, 1, 1000);
640 if (err == -ENOSYS)
641 udelay(1000);
642 else if (err)
643 return -ETIMEDOUT;
644
645 return 0;
646}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100647#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200648
649static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
Andy Flemingad347bb2008-10-30 16:41:01 -0500650{
651 int timeout = 1000;
652 int err;
653 struct mmc_cmd cmd;
654
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500655 while (1) {
Andy Flemingad347bb2008-10-30 16:41:01 -0500656 cmd.cmdidx = MMC_CMD_APP_CMD;
657 cmd.resp_type = MMC_RSP_R1;
658 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500659
660 err = mmc_send_cmd(mmc, &cmd, NULL);
661
662 if (err)
663 return err;
664
665 cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
666 cmd.resp_type = MMC_RSP_R3;
Stefano Babicf8e9a212010-01-20 18:20:39 +0100667
668 /*
669 * Most cards do not answer if some reserved bits
670 * in the ocr are set. However, Some controller
671 * can set bit 7 (reserved for low voltages), but
672 * how to manage low voltages SD card is not yet
673 * specified.
674 */
Thomas Chou1254c3d2010-12-24 13:12:21 +0000675 cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200676 (mmc->cfg->voltages & 0xff8000);
Andy Flemingad347bb2008-10-30 16:41:01 -0500677
678 if (mmc->version == SD_VERSION_2)
679 cmd.cmdarg |= OCR_HCS;
680
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200681 if (uhs_en)
682 cmd.cmdarg |= OCR_S18R;
683
Andy Flemingad347bb2008-10-30 16:41:01 -0500684 err = mmc_send_cmd(mmc, &cmd, NULL);
685
686 if (err)
687 return err;
688
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500689 if (cmd.response[0] & OCR_BUSY)
690 break;
Andy Flemingad347bb2008-10-30 16:41:01 -0500691
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500692 if (timeout-- <= 0)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900693 return -EOPNOTSUPP;
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500694
695 udelay(1000);
696 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500697
698 if (mmc->version != SD_VERSION_2)
699 mmc->version = SD_VERSION_1_0;
700
Thomas Chou1254c3d2010-12-24 13:12:21 +0000701 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
702 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
703 cmd.resp_type = MMC_RSP_R3;
704 cmd.cmdarg = 0;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000705
706 err = mmc_send_cmd(mmc, &cmd, NULL);
707
708 if (err)
709 return err;
710 }
711
Rabin Vincentb6eed942009-04-05 13:30:56 +0530712 mmc->ocr = cmd.response[0];
Andy Flemingad347bb2008-10-30 16:41:01 -0500713
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100714#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200715 if (uhs_en && !(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)
716 == 0x41000000) {
717 err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
718 if (err)
719 return err;
720 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100721#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200722
Andy Flemingad347bb2008-10-30 16:41:01 -0500723 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
724 mmc->rca = 0;
725
726 return 0;
727}
728
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500729static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg)
Andy Flemingad347bb2008-10-30 16:41:01 -0500730{
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500731 struct mmc_cmd cmd;
Andy Flemingad347bb2008-10-30 16:41:01 -0500732 int err;
733
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500734 cmd.cmdidx = MMC_CMD_SEND_OP_COND;
735 cmd.resp_type = MMC_RSP_R3;
736 cmd.cmdarg = 0;
Rob Herring5fd3edd2015-03-23 17:56:59 -0500737 if (use_arg && !mmc_host_is_spi(mmc))
738 cmd.cmdarg = OCR_HCS |
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200739 (mmc->cfg->voltages &
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500740 (mmc->ocr & OCR_VOLTAGE_MASK)) |
741 (mmc->ocr & OCR_ACCESS_MODE);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000742
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500743 err = mmc_send_cmd(mmc, &cmd, NULL);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000744 if (err)
745 return err;
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500746 mmc->ocr = cmd.response[0];
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000747 return 0;
748}
749
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +0200750static int mmc_send_op_cond(struct mmc *mmc)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000751{
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000752 int err, i;
Haibo Chen71949512020-06-15 17:18:12 +0800753 int timeout = 1000;
Ronald Wahl5e4b3142024-12-11 21:52:00 +0100754 ulong start;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000755
Andy Flemingad347bb2008-10-30 16:41:01 -0500756 /* Some cards seem to need this */
757 mmc_go_idle(mmc);
758
Haibo Chen71949512020-06-15 17:18:12 +0800759 start = get_timer(0);
Wolfgang Denk62fb2b42021-09-27 17:42:39 +0200760 /* Asking to the card its capabilities */
Haibo Chen71949512020-06-15 17:18:12 +0800761 for (i = 0; ; i++) {
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500762 err = mmc_send_op_cond_iter(mmc, i != 0);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000763 if (err)
764 return err;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200765
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000766 /* exit if not busy (flag seems to be inverted) */
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500767 if (mmc->ocr & OCR_BUSY)
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -0500768 break;
Haibo Chen71949512020-06-15 17:18:12 +0800769
770 if (get_timer(start) > timeout)
771 return -ETIMEDOUT;
772 udelay(100);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000773 }
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -0500774 mmc->op_cond_pending = 1;
775 return 0;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000776}
Wolfgang Denk80f70212011-05-19 22:21:41 +0200777
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +0200778static int mmc_complete_op_cond(struct mmc *mmc)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000779{
780 struct mmc_cmd cmd;
781 int timeout = 1000;
Vipul Kumardbad7b42018-05-03 12:20:54 +0530782 ulong start;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000783 int err;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200784
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000785 mmc->op_cond_pending = 0;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500786 if (!(mmc->ocr & OCR_BUSY)) {
Yangbo Lu9c720612016-08-02 15:33:18 +0800787 /* Some cards seem to need this */
788 mmc_go_idle(mmc);
789
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500790 start = get_timer(0);
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500791 while (1) {
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500792 err = mmc_send_op_cond_iter(mmc, 1);
793 if (err)
794 return err;
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500795 if (mmc->ocr & OCR_BUSY)
796 break;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500797 if (get_timer(start) > timeout)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900798 return -EOPNOTSUPP;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500799 udelay(100);
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500800 }
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500801 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500802
Thomas Chou1254c3d2010-12-24 13:12:21 +0000803 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
804 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
805 cmd.resp_type = MMC_RSP_R3;
806 cmd.cmdarg = 0;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000807
808 err = mmc_send_cmd(mmc, &cmd, NULL);
809
810 if (err)
811 return err;
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500812
813 mmc->ocr = cmd.response[0];
Thomas Chou1254c3d2010-12-24 13:12:21 +0000814 }
815
Andy Flemingad347bb2008-10-30 16:41:01 -0500816 mmc->version = MMC_VERSION_UNKNOWN;
Andy Flemingad347bb2008-10-30 16:41:01 -0500817
818 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
Stephen Warrenf6545f12014-01-30 16:11:12 -0700819 mmc->rca = 1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500820
821 return 0;
822}
823
Heinrich Schuchardtbf230e12020-03-30 07:24:17 +0200824int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
Andy Flemingad347bb2008-10-30 16:41:01 -0500825{
826 struct mmc_cmd cmd;
827 struct mmc_data data;
828 int err;
829
830 /* Get the Card Status Register */
831 cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
832 cmd.resp_type = MMC_RSP_R1;
833 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500834
Yoshihiro Shimodaf6bec732012-06-07 19:09:11 +0000835 data.dest = (char *)ext_csd;
Andy Flemingad347bb2008-10-30 16:41:01 -0500836 data.blocks = 1;
Simon Glassa09c2b72013-04-03 08:54:30 +0000837 data.blocksize = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -0500838 data.flags = MMC_DATA_READ;
839
840 err = mmc_send_cmd(mmc, &cmd, &data);
841
842 return err;
843}
844
Marek Vasut8a966472019-02-06 11:34:27 +0100845static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
846 bool send_status)
Andy Flemingad347bb2008-10-30 16:41:01 -0500847{
Ronald Wahl5e4b3142024-12-11 21:52:00 +0100848 ulong start;
849 unsigned int status;
Andy Flemingad347bb2008-10-30 16:41:01 -0500850 struct mmc_cmd cmd;
Sam Protsenkodb174c62019-08-14 22:52:51 +0300851 int timeout_ms = DEFAULT_CMD6_TIMEOUT_MS;
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +0200852 bool is_part_switch = (set == EXT_CSD_CMD_SET_NORMAL) &&
853 (index == EXT_CSD_PART_CONF);
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000854 int ret;
Andy Flemingad347bb2008-10-30 16:41:01 -0500855
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +0200856 if (mmc->gen_cmd6_time)
Sam Protsenkodb174c62019-08-14 22:52:51 +0300857 timeout_ms = mmc->gen_cmd6_time * 10;
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +0200858
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +0200859 if (is_part_switch && mmc->part_switch_time)
Sam Protsenkodb174c62019-08-14 22:52:51 +0300860 timeout_ms = mmc->part_switch_time * 10;
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +0200861
Andy Flemingad347bb2008-10-30 16:41:01 -0500862 cmd.cmdidx = MMC_CMD_SWITCH;
863 cmd.resp_type = MMC_RSP_R1b;
864 cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000865 (index << 16) |
866 (value << 8);
Andy Flemingad347bb2008-10-30 16:41:01 -0500867
Sean Anderson86325092020-10-17 08:36:27 -0400868 ret = mmc_send_cmd_retry(mmc, &cmd, NULL, 3);
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200869 if (ret)
870 return ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000871
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200872 start = get_timer(0);
Marek Vasut8a966472019-02-06 11:34:27 +0100873
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200874 /* poll dat0 for rdy/buys status */
Sam Protsenkodb174c62019-08-14 22:52:51 +0300875 ret = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200876 if (ret && ret != -ENOSYS)
877 return ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000878
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200879 /*
Kirill Kapranovcd9ea642021-10-09 23:49:59 +0300880 * In cases when neiter allowed to poll by using CMD13 nor we are
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200881 * capable of polling by using mmc_wait_dat0, then rely on waiting the
882 * stated timeout to be sufficient.
883 */
Kirill Kapranovcd9ea642021-10-09 23:49:59 +0300884 if (ret == -ENOSYS && !send_status) {
Sam Protsenkodb174c62019-08-14 22:52:51 +0300885 mdelay(timeout_ms);
Haibo Chend8de5e42020-09-22 18:11:42 +0800886 return 0;
887 }
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200888
Marek Vasut946e06f2022-07-15 01:58:24 +0200889 if (!send_status)
890 return 0;
891
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200892 /* Finally wait until the card is ready or indicates a failure
893 * to switch. It doesn't hurt to use CMD13 here even if send_status
Sam Protsenkodb174c62019-08-14 22:52:51 +0300894 * is false, because by now (after 'timeout_ms' ms) the bus should be
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200895 * reliable.
896 */
897 do {
898 ret = mmc_send_status(mmc, &status);
899
900 if (!ret && (status & MMC_STATUS_SWITCH_ERROR)) {
901 pr_debug("switch failed %d/%d/0x%x !\n", set, index,
902 value);
903 return -EIO;
904 }
Stefan Boscha463bbe2021-01-23 13:37:41 +0100905 if (!ret && (status & MMC_STATUS_RDY_FOR_DATA) &&
906 (status & MMC_STATUS_CURR_STATE) == MMC_STATE_TRANS)
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200907 return 0;
908 udelay(100);
Sam Protsenkodb174c62019-08-14 22:52:51 +0300909 } while (get_timer(start) < timeout_ms);
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000910
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200911 return -ETIMEDOUT;
Andy Flemingad347bb2008-10-30 16:41:01 -0500912}
913
Marek Vasut8a966472019-02-06 11:34:27 +0100914int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
915{
916 return __mmc_switch(mmc, set, index, value, true);
917}
918
Heinrich Schuchardt75e5a642020-03-30 07:24:19 +0200919int mmc_boot_wp(struct mmc *mmc)
920{
921 return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, 1);
922}
923
Ying-Chun Liu (PaulLiu)4493cb52022-04-25 21:59:02 +0800924int mmc_boot_wp_single_partition(struct mmc *mmc, int partition)
925{
926 u8 value;
927 int ret;
928
929 value = EXT_CSD_BOOT_WP_B_PWR_WP_EN;
930
931 if (partition == 0) {
932 value |= EXT_CSD_BOOT_WP_B_SEC_WP_SEL;
933 ret = mmc_switch(mmc,
934 EXT_CSD_CMD_SET_NORMAL,
935 EXT_CSD_BOOT_WP,
936 value);
937 } else if (partition == 1) {
938 value |= EXT_CSD_BOOT_WP_B_SEC_WP_SEL;
939 value |= EXT_CSD_BOOT_WP_B_PWR_WP_SEC_SEL;
940 ret = mmc_switch(mmc,
941 EXT_CSD_CMD_SET_NORMAL,
942 EXT_CSD_BOOT_WP,
943 value);
944 } else {
945 ret = mmc_boot_wp(mmc);
946 }
947
948 return ret;
949}
950
Marek Vasuta318a7a2018-04-15 00:37:11 +0200951#if !CONFIG_IS_ENABLED(MMC_TINY)
Marek Vasut111572f2019-01-03 21:19:24 +0100952static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode,
953 bool hsdowngrade)
Andy Flemingad347bb2008-10-30 16:41:01 -0500954{
Andy Flemingad347bb2008-10-30 16:41:01 -0500955 int err;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200956 int speed_bits;
957
958 ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
959
960 switch (mode) {
961 case MMC_HS:
962 case MMC_HS_52:
963 case MMC_DDR_52:
964 speed_bits = EXT_CSD_TIMING_HS;
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +0200965 break;
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +0100966#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +0200967 case MMC_HS_200:
968 speed_bits = EXT_CSD_TIMING_HS200;
969 break;
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +0100970#endif
Peng Fan46801252018-08-10 14:07:54 +0800971#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
972 case MMC_HS_400:
973 speed_bits = EXT_CSD_TIMING_HS400;
974 break;
975#endif
Peng Faneede83b2019-07-10 14:43:07 +0800976#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
977 case MMC_HS_400_ES:
978 speed_bits = EXT_CSD_TIMING_HS400;
979 break;
980#endif
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200981 case MMC_LEGACY:
982 speed_bits = EXT_CSD_TIMING_LEGACY;
983 break;
984 default:
985 return -EINVAL;
986 }
Marek Vasut8a966472019-02-06 11:34:27 +0100987
988 err = __mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
989 speed_bits, !hsdowngrade);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200990 if (err)
991 return err;
992
Marek Vasut111572f2019-01-03 21:19:24 +0100993#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
994 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
995 /*
996 * In case the eMMC is in HS200/HS400 mode and we are downgrading
997 * to HS mode, the card clock are still running much faster than
998 * the supported HS mode clock, so we can not reliably read out
999 * Extended CSD. Reconfigure the controller to run at HS mode.
1000 */
1001 if (hsdowngrade) {
Venkatesh Yadav Abbarapu10f9def2024-04-23 11:00:57 +05301002 mmc_select_mode(mmc, MMC_HS_52);
1003 mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS_52), false);
Marek Vasut111572f2019-01-03 21:19:24 +01001004 }
1005#endif
1006
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001007 if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
1008 /* Now check to see that it worked */
1009 err = mmc_send_ext_csd(mmc, test_csd);
1010 if (err)
1011 return err;
1012
1013 /* No high-speed support */
1014 if (!test_csd[EXT_CSD_HS_TIMING])
1015 return -ENOTSUPP;
1016 }
1017
1018 return 0;
1019}
1020
1021static int mmc_get_capabilities(struct mmc *mmc)
1022{
1023 u8 *ext_csd = mmc->ext_csd;
1024 char cardtype;
Andy Flemingad347bb2008-10-30 16:41:01 -05001025
Jean-Jacques Hiblot3f2ffc22017-11-30 17:43:56 +01001026 mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05001027
Thomas Chou1254c3d2010-12-24 13:12:21 +00001028 if (mmc_host_is_spi(mmc))
1029 return 0;
1030
Andy Flemingad347bb2008-10-30 16:41:01 -05001031 /* Only version 4 supports high-speed */
1032 if (mmc->version < MMC_VERSION_4)
1033 return 0;
1034
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001035 if (!ext_csd) {
Simon Glass367e3852024-08-22 07:54:55 -06001036 log_err("No ext_csd found!\n"); /* this should never happen */
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001037 return -ENOTSUPP;
1038 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001039
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001040 mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
Andy Flemingad347bb2008-10-30 16:41:01 -05001041
Peng Fan46801252018-08-10 14:07:54 +08001042 cardtype = ext_csd[EXT_CSD_CARD_TYPE];
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001043 mmc->cardtype = cardtype;
Andy Flemingad347bb2008-10-30 16:41:01 -05001044
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001045#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001046 if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
1047 EXT_CSD_CARD_TYPE_HS200_1_8V)) {
1048 mmc->card_caps |= MMC_MODE_HS200;
1049 }
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001050#endif
Peng Faneede83b2019-07-10 14:43:07 +08001051#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
1052 CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
Peng Fan46801252018-08-10 14:07:54 +08001053 if (cardtype & (EXT_CSD_CARD_TYPE_HS400_1_2V |
1054 EXT_CSD_CARD_TYPE_HS400_1_8V)) {
1055 mmc->card_caps |= MMC_MODE_HS400;
1056 }
1057#endif
Jaehoon Chung38ce30b2014-05-16 13:59:54 +09001058 if (cardtype & EXT_CSD_CARD_TYPE_52) {
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001059 if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
Jaehoon Chung38ce30b2014-05-16 13:59:54 +09001060 mmc->card_caps |= MMC_MODE_DDR_52MHz;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001061 mmc->card_caps |= MMC_MODE_HS_52MHz;
Jaehoon Chung38ce30b2014-05-16 13:59:54 +09001062 }
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001063 if (cardtype & EXT_CSD_CARD_TYPE_26)
1064 mmc->card_caps |= MMC_MODE_HS;
Andy Flemingad347bb2008-10-30 16:41:01 -05001065
Peng Faneede83b2019-07-10 14:43:07 +08001066#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
1067 if (ext_csd[EXT_CSD_STROBE_SUPPORT] &&
1068 (mmc->card_caps & MMC_MODE_HS400)) {
1069 mmc->card_caps |= MMC_MODE_HS400_ES;
1070 }
1071#endif
1072
Andy Flemingad347bb2008-10-30 16:41:01 -05001073 return 0;
1074}
Marek Vasuta318a7a2018-04-15 00:37:11 +02001075#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001076
Stephen Warrene315ae82013-06-11 15:14:01 -06001077static int mmc_set_capacity(struct mmc *mmc, int part_num)
1078{
1079 switch (part_num) {
1080 case 0:
1081 mmc->capacity = mmc->capacity_user;
1082 break;
1083 case 1:
1084 case 2:
1085 mmc->capacity = mmc->capacity_boot;
1086 break;
1087 case 3:
1088 mmc->capacity = mmc->capacity_rpmb;
1089 break;
1090 case 4:
1091 case 5:
1092 case 6:
1093 case 7:
1094 mmc->capacity = mmc->capacity_gp[part_num - 4];
1095 break;
1096 default:
1097 return -1;
1098 }
1099
Simon Glasse5db1152016-05-01 13:52:35 -06001100 mmc_get_blk_desc(mmc)->lba = lldiv(mmc->capacity, mmc->read_bl_len);
Stephen Warrene315ae82013-06-11 15:14:01 -06001101
1102 return 0;
1103}
1104
Simon Glass62e293a2016-06-12 23:30:15 -06001105int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
Lei Wen31b99802011-05-02 16:26:26 +00001106{
Stephen Warrene315ae82013-06-11 15:14:01 -06001107 int ret;
Jean-Jacques Hiblotfaf5c952019-07-02 10:53:58 +02001108 int retry = 3;
Lei Wen31b99802011-05-02 16:26:26 +00001109
Jean-Jacques Hiblotfaf5c952019-07-02 10:53:58 +02001110 do {
1111 ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1112 EXT_CSD_PART_CONF,
1113 (mmc->part_config & ~PART_ACCESS_MASK)
1114 | (part_num & PART_ACCESS_MASK));
1115 } while (ret && retry--);
Peter Bigot45fde892014-09-02 18:31:23 -05001116
1117 /*
1118 * Set the capacity if the switch succeeded or was intended
1119 * to return to representing the raw device.
1120 */
Stephen Warren1e0f92a2015-12-07 11:38:49 -07001121 if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) {
Peter Bigot45fde892014-09-02 18:31:23 -05001122 ret = mmc_set_capacity(mmc, part_num);
Simon Glass984db5d2016-05-01 13:52:37 -06001123 mmc_get_blk_desc(mmc)->hwpart = part_num;
Stephen Warren1e0f92a2015-12-07 11:38:49 -07001124 }
Stephen Warrene315ae82013-06-11 15:14:01 -06001125
Peter Bigot45fde892014-09-02 18:31:23 -05001126 return ret;
Lei Wen31b99802011-05-02 16:26:26 +00001127}
1128
Jean-Jacques Hiblot1d7769a2017-11-30 17:44:02 +01001129#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001130int mmc_hwpart_config(struct mmc *mmc,
1131 const struct mmc_hwpart_conf *conf,
1132 enum mmc_hwpart_conf_mode mode)
1133{
1134 u8 part_attrs = 0;
1135 u32 enh_size_mult;
1136 u32 enh_start_addr;
1137 u32 gp_size_mult[4];
1138 u32 max_enh_size_mult;
1139 u32 tot_enh_size_mult = 0;
Diego Santa Cruz80200272014-12-23 10:50:31 +01001140 u8 wr_rel_set;
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001141 int i, pidx, err;
1142 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
1143
1144 if (mode < MMC_HWPART_CONF_CHECK || mode > MMC_HWPART_CONF_COMPLETE)
1145 return -EINVAL;
1146
1147 if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4_41)) {
Simon Glass367e3852024-08-22 07:54:55 -06001148 log_err("eMMC >= 4.4 required for enhanced user data area\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001149 return -EMEDIUMTYPE;
1150 }
1151
1152 if (!(mmc->part_support & PART_SUPPORT)) {
Simon Glass367e3852024-08-22 07:54:55 -06001153 log_err("Card does not support partitioning\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001154 return -EMEDIUMTYPE;
1155 }
1156
1157 if (!mmc->hc_wp_grp_size) {
Simon Glass367e3852024-08-22 07:54:55 -06001158 log_err("Card does not define HC WP group size\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001159 return -EMEDIUMTYPE;
1160 }
1161
1162 /* check partition alignment and total enhanced size */
1163 if (conf->user.enh_size) {
1164 if (conf->user.enh_size % mmc->hc_wp_grp_size ||
1165 conf->user.enh_start % mmc->hc_wp_grp_size) {
Simon Glass367e3852024-08-22 07:54:55 -06001166 log_err("User data enhanced area not HC WP group size aligned\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001167 return -EINVAL;
1168 }
1169 part_attrs |= EXT_CSD_ENH_USR;
1170 enh_size_mult = conf->user.enh_size / mmc->hc_wp_grp_size;
1171 if (mmc->high_capacity) {
1172 enh_start_addr = conf->user.enh_start;
1173 } else {
1174 enh_start_addr = (conf->user.enh_start << 9);
1175 }
1176 } else {
1177 enh_size_mult = 0;
1178 enh_start_addr = 0;
1179 }
1180 tot_enh_size_mult += enh_size_mult;
1181
1182 for (pidx = 0; pidx < 4; pidx++) {
1183 if (conf->gp_part[pidx].size % mmc->hc_wp_grp_size) {
Simon Glass367e3852024-08-22 07:54:55 -06001184 log_err("GP%i partition not HC WP group-size aligned\n",
1185 pidx + 1);
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001186 return -EINVAL;
1187 }
1188 gp_size_mult[pidx] = conf->gp_part[pidx].size / mmc->hc_wp_grp_size;
1189 if (conf->gp_part[pidx].size && conf->gp_part[pidx].enhanced) {
1190 part_attrs |= EXT_CSD_ENH_GP(pidx);
1191 tot_enh_size_mult += gp_size_mult[pidx];
1192 }
1193 }
1194
1195 if (part_attrs && ! (mmc->part_support & ENHNCD_SUPPORT)) {
Simon Glass367e3852024-08-22 07:54:55 -06001196 log_err("Card does not support enhanced attribute\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001197 return -EMEDIUMTYPE;
1198 }
1199
1200 err = mmc_send_ext_csd(mmc, ext_csd);
1201 if (err)
1202 return err;
1203
1204 max_enh_size_mult =
1205 (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT+2] << 16) +
1206 (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT+1] << 8) +
1207 ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT];
1208 if (tot_enh_size_mult > max_enh_size_mult) {
Simon Glass367e3852024-08-22 07:54:55 -06001209 log_err("Total enhanced size exceeds maximum (%#x > %#x)\n",
1210 tot_enh_size_mult, max_enh_size_mult);
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001211 return -EMEDIUMTYPE;
1212 }
1213
Diego Santa Cruz80200272014-12-23 10:50:31 +01001214 /* The default value of EXT_CSD_WR_REL_SET is device
1215 * dependent, the values can only be changed if the
1216 * EXT_CSD_HS_CTRL_REL bit is set. The values can be
1217 * changed only once and before partitioning is completed. */
1218 wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
1219 if (conf->user.wr_rel_change) {
1220 if (conf->user.wr_rel_set)
1221 wr_rel_set |= EXT_CSD_WR_DATA_REL_USR;
1222 else
1223 wr_rel_set &= ~EXT_CSD_WR_DATA_REL_USR;
1224 }
1225 for (pidx = 0; pidx < 4; pidx++) {
1226 if (conf->gp_part[pidx].wr_rel_change) {
1227 if (conf->gp_part[pidx].wr_rel_set)
1228 wr_rel_set |= EXT_CSD_WR_DATA_REL_GP(pidx);
1229 else
1230 wr_rel_set &= ~EXT_CSD_WR_DATA_REL_GP(pidx);
1231 }
1232 }
1233
1234 if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET] &&
1235 !(ext_csd[EXT_CSD_WR_REL_PARAM] & EXT_CSD_HS_CTRL_REL)) {
1236 puts("Card does not support host controlled partition write "
1237 "reliability settings\n");
1238 return -EMEDIUMTYPE;
1239 }
1240
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001241 if (ext_csd[EXT_CSD_PARTITION_SETTING] &
1242 EXT_CSD_PARTITION_SETTING_COMPLETED) {
Simon Glass367e3852024-08-22 07:54:55 -06001243 log_err("Card already partitioned\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001244 return -EPERM;
1245 }
1246
1247 if (mode == MMC_HWPART_CONF_CHECK)
1248 return 0;
1249
1250 /* Partitioning requires high-capacity size definitions */
1251 if (!(ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01)) {
1252 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1253 EXT_CSD_ERASE_GROUP_DEF, 1);
1254
1255 if (err)
1256 return err;
1257
1258 ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
1259
Jaehoon Chung58b9eb82020-01-17 15:06:54 +09001260#if CONFIG_IS_ENABLED(MMC_WRITE)
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001261 /* update erase group size to be high-capacity */
1262 mmc->erase_grp_size =
1263 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
Jaehoon Chung58b9eb82020-01-17 15:06:54 +09001264#endif
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001265
1266 }
1267
1268 /* all OK, write the configuration */
1269 for (i = 0; i < 4; i++) {
1270 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1271 EXT_CSD_ENH_START_ADDR+i,
1272 (enh_start_addr >> (i*8)) & 0xFF);
1273 if (err)
1274 return err;
1275 }
1276 for (i = 0; i < 3; i++) {
1277 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1278 EXT_CSD_ENH_SIZE_MULT+i,
1279 (enh_size_mult >> (i*8)) & 0xFF);
1280 if (err)
1281 return err;
1282 }
1283 for (pidx = 0; pidx < 4; pidx++) {
1284 for (i = 0; i < 3; i++) {
1285 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1286 EXT_CSD_GP_SIZE_MULT+pidx*3+i,
1287 (gp_size_mult[pidx] >> (i*8)) & 0xFF);
1288 if (err)
1289 return err;
1290 }
1291 }
1292 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1293 EXT_CSD_PARTITIONS_ATTRIBUTE, part_attrs);
1294 if (err)
1295 return err;
1296
1297 if (mode == MMC_HWPART_CONF_SET)
1298 return 0;
1299
Diego Santa Cruz80200272014-12-23 10:50:31 +01001300 /* The WR_REL_SET is a write-once register but shall be
1301 * written before setting PART_SETTING_COMPLETED. As it is
1302 * write-once we can only write it when completing the
1303 * partitioning. */
1304 if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET]) {
1305 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1306 EXT_CSD_WR_REL_SET, wr_rel_set);
1307 if (err)
1308 return err;
1309 }
1310
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001311 /* Setting PART_SETTING_COMPLETED confirms the partition
1312 * configuration but it only becomes effective after power
1313 * cycle, so we do not adjust the partition related settings
1314 * in the mmc struct. */
1315
1316 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1317 EXT_CSD_PARTITION_SETTING,
1318 EXT_CSD_PARTITION_SETTING_COMPLETED);
1319 if (err)
1320 return err;
1321
1322 return 0;
1323}
Jean-Jacques Hiblot1d7769a2017-11-30 17:44:02 +01001324#endif
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001325
Simon Glasseba48f92017-07-29 11:35:31 -06001326#if !CONFIG_IS_ENABLED(DM_MMC)
Thierry Redingb9c8b772012-01-02 01:15:37 +00001327int mmc_getcd(struct mmc *mmc)
1328{
1329 int cd;
1330
1331 cd = board_mmc_getcd(mmc);
1332
Peter Korsgaardf7b15102013-03-21 04:00:03 +00001333 if (cd < 0) {
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001334 if (mmc->cfg->ops->getcd)
1335 cd = mmc->cfg->ops->getcd(mmc);
Peter Korsgaardf7b15102013-03-21 04:00:03 +00001336 else
1337 cd = 1;
1338 }
Thierry Redingb9c8b772012-01-02 01:15:37 +00001339
1340 return cd;
1341}
Simon Glass394dfc02016-06-12 23:30:22 -06001342#endif
Thierry Redingb9c8b772012-01-02 01:15:37 +00001343
Marek Vasuta318a7a2018-04-15 00:37:11 +02001344#if !CONFIG_IS_ENABLED(MMC_TINY)
Kim Phillips87ea3892012-10-29 13:34:43 +00001345static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
Andy Flemingad347bb2008-10-30 16:41:01 -05001346{
1347 struct mmc_cmd cmd;
1348 struct mmc_data data;
1349
1350 /* Switch the frequency */
1351 cmd.cmdidx = SD_CMD_SWITCH_FUNC;
1352 cmd.resp_type = MMC_RSP_R1;
1353 cmd.cmdarg = (mode << 31) | 0xffffff;
1354 cmd.cmdarg &= ~(0xf << (group * 4));
1355 cmd.cmdarg |= value << (group * 4);
Andy Flemingad347bb2008-10-30 16:41:01 -05001356
1357 data.dest = (char *)resp;
1358 data.blocksize = 64;
1359 data.blocks = 1;
1360 data.flags = MMC_DATA_READ;
1361
1362 return mmc_send_cmd(mmc, &cmd, &data);
1363}
1364
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001365static int sd_get_capabilities(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001366{
1367 int err;
1368 struct mmc_cmd cmd;
Suniel Mahesh2f423da2017-10-05 11:32:00 +05301369 ALLOC_CACHE_ALIGN_BUFFER(__be32, scr, 2);
1370 ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16);
Andy Flemingad347bb2008-10-30 16:41:01 -05001371 struct mmc_data data;
1372 int timeout;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001373#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001374 u32 sd3_bus_mode;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001375#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001376
Faiz Abbas01db77e2020-02-26 13:44:32 +05301377 mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05001378
Thomas Chou1254c3d2010-12-24 13:12:21 +00001379 if (mmc_host_is_spi(mmc))
1380 return 0;
1381
Andy Flemingad347bb2008-10-30 16:41:01 -05001382 /* Read the SCR to find out if this card supports higher speeds */
1383 cmd.cmdidx = MMC_CMD_APP_CMD;
1384 cmd.resp_type = MMC_RSP_R1;
1385 cmd.cmdarg = mmc->rca << 16;
Andy Flemingad347bb2008-10-30 16:41:01 -05001386
1387 err = mmc_send_cmd(mmc, &cmd, NULL);
1388
1389 if (err)
1390 return err;
1391
1392 cmd.cmdidx = SD_CMD_APP_SEND_SCR;
1393 cmd.resp_type = MMC_RSP_R1;
1394 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05001395
Anton staaf9b00f0d2011-10-03 13:54:59 +00001396 data.dest = (char *)scr;
Andy Flemingad347bb2008-10-30 16:41:01 -05001397 data.blocksize = 8;
1398 data.blocks = 1;
1399 data.flags = MMC_DATA_READ;
1400
Sean Anderson86325092020-10-17 08:36:27 -04001401 err = mmc_send_cmd_retry(mmc, &cmd, &data, 3);
Andy Flemingad347bb2008-10-30 16:41:01 -05001402
Sean Anderson86325092020-10-17 08:36:27 -04001403 if (err)
Andy Flemingad347bb2008-10-30 16:41:01 -05001404 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05001405
Yauhen Kharuzhy6e8edf42009-05-07 00:43:30 +03001406 mmc->scr[0] = __be32_to_cpu(scr[0]);
1407 mmc->scr[1] = __be32_to_cpu(scr[1]);
Andy Flemingad347bb2008-10-30 16:41:01 -05001408
1409 switch ((mmc->scr[0] >> 24) & 0xf) {
Bin Meng4a4ef872016-03-17 21:53:13 -07001410 case 0:
1411 mmc->version = SD_VERSION_1_0;
1412 break;
1413 case 1:
1414 mmc->version = SD_VERSION_1_10;
1415 break;
1416 case 2:
1417 mmc->version = SD_VERSION_2;
1418 if ((mmc->scr[0] >> 15) & 0x1)
1419 mmc->version = SD_VERSION_3;
1420 break;
1421 default:
1422 mmc->version = SD_VERSION_1_0;
1423 break;
Andy Flemingad347bb2008-10-30 16:41:01 -05001424 }
1425
Alagu Sankar24bb5ab2010-05-12 15:08:24 +05301426 if (mmc->scr[0] & SD_DATA_4BIT)
1427 mmc->card_caps |= MMC_MODE_4BIT;
1428
Andy Flemingad347bb2008-10-30 16:41:01 -05001429 /* Version 1.0 doesn't support switching */
1430 if (mmc->version == SD_VERSION_1_0)
1431 return 0;
1432
1433 timeout = 4;
1434 while (timeout--) {
1435 err = sd_switch(mmc, SD_SWITCH_CHECK, 0, 1,
Anton staaf9b00f0d2011-10-03 13:54:59 +00001436 (u8 *)switch_status);
Andy Flemingad347bb2008-10-30 16:41:01 -05001437
1438 if (err)
1439 return err;
1440
1441 /* The high-speed function is busy. Try again */
Yauhen Kharuzhy6e8edf42009-05-07 00:43:30 +03001442 if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
Andy Flemingad347bb2008-10-30 16:41:01 -05001443 break;
1444 }
1445
Andy Flemingad347bb2008-10-30 16:41:01 -05001446 /* If high-speed isn't supported, we return */
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001447 if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)
1448 mmc->card_caps |= MMC_CAP(SD_HS);
Andy Flemingad347bb2008-10-30 16:41:01 -05001449
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001450#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001451 /* Version before 3.0 don't support UHS modes */
1452 if (mmc->version < SD_VERSION_3)
1453 return 0;
1454
1455 sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;
1456 if (sd3_bus_mode & SD_MODE_UHS_SDR104)
1457 mmc->card_caps |= MMC_CAP(UHS_SDR104);
1458 if (sd3_bus_mode & SD_MODE_UHS_SDR50)
1459 mmc->card_caps |= MMC_CAP(UHS_SDR50);
1460 if (sd3_bus_mode & SD_MODE_UHS_SDR25)
1461 mmc->card_caps |= MMC_CAP(UHS_SDR25);
1462 if (sd3_bus_mode & SD_MODE_UHS_SDR12)
1463 mmc->card_caps |= MMC_CAP(UHS_SDR12);
1464 if (sd3_bus_mode & SD_MODE_UHS_DDR50)
1465 mmc->card_caps |= MMC_CAP(UHS_DDR50);
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001466#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001467
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001468 return 0;
1469}
1470
1471static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
1472{
1473 int err;
1474
1475 ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001476 int speed;
Macpaul Lin24e92ec2011-11-28 16:31:09 +00001477
Marek Vasut4105e972018-11-18 03:25:08 +01001478 /* SD version 1.00 and 1.01 does not support CMD 6 */
1479 if (mmc->version == SD_VERSION_1_0)
1480 return 0;
1481
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001482 switch (mode) {
Faiz Abbas01db77e2020-02-26 13:44:32 +05301483 case MMC_LEGACY:
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001484 speed = UHS_SDR12_BUS_SPEED;
1485 break;
1486 case SD_HS:
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001487 speed = HIGH_SPEED_BUS_SPEED;
1488 break;
1489#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
1490 case UHS_SDR12:
1491 speed = UHS_SDR12_BUS_SPEED;
1492 break;
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001493 case UHS_SDR25:
1494 speed = UHS_SDR25_BUS_SPEED;
1495 break;
1496 case UHS_SDR50:
1497 speed = UHS_SDR50_BUS_SPEED;
1498 break;
1499 case UHS_DDR50:
1500 speed = UHS_DDR50_BUS_SPEED;
1501 break;
1502 case UHS_SDR104:
1503 speed = UHS_SDR104_BUS_SPEED;
1504 break;
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001505#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001506 default:
1507 return -EINVAL;
1508 }
1509
1510 err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, speed, (u8 *)switch_status);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001511 if (err)
1512 return err;
1513
Jean-Jacques Hiblote7f664e2018-02-09 12:09:27 +01001514 if (((__be32_to_cpu(switch_status[4]) >> 24) & 0xF) != speed)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001515 return -ENOTSUPP;
1516
1517 return 0;
1518}
Andy Flemingad347bb2008-10-30 16:41:01 -05001519
Marek Vasut8ff55fb2018-04-15 00:36:45 +02001520static int sd_select_bus_width(struct mmc *mmc, int w)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001521{
1522 int err;
1523 struct mmc_cmd cmd;
1524
1525 if ((w != 4) && (w != 1))
1526 return -EINVAL;
1527
1528 cmd.cmdidx = MMC_CMD_APP_CMD;
1529 cmd.resp_type = MMC_RSP_R1;
1530 cmd.cmdarg = mmc->rca << 16;
1531
1532 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05001533 if (err)
1534 return err;
1535
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001536 cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
1537 cmd.resp_type = MMC_RSP_R1;
1538 if (w == 4)
1539 cmd.cmdarg = 2;
1540 else if (w == 1)
1541 cmd.cmdarg = 0;
1542 err = mmc_send_cmd(mmc, &cmd, NULL);
1543 if (err)
1544 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05001545
1546 return 0;
1547}
Marek Vasuta318a7a2018-04-15 00:37:11 +02001548#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001549
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001550#if CONFIG_IS_ENABLED(MMC_WRITE)
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001551static int sd_read_ssr(struct mmc *mmc)
1552{
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001553 static const unsigned int sd_au_size[] = {
1554 0, SZ_16K / 512, SZ_32K / 512,
1555 SZ_64K / 512, SZ_128K / 512, SZ_256K / 512,
1556 SZ_512K / 512, SZ_1M / 512, SZ_2M / 512,
1557 SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512,
1558 SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512,
1559 SZ_64M / 512,
1560 };
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001561 int err, i;
1562 struct mmc_cmd cmd;
1563 ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16);
1564 struct mmc_data data;
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001565 unsigned int au, eo, et, es;
1566
1567 cmd.cmdidx = MMC_CMD_APP_CMD;
1568 cmd.resp_type = MMC_RSP_R1;
1569 cmd.cmdarg = mmc->rca << 16;
1570
Sean Anderson86325092020-10-17 08:36:27 -04001571 err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_APP_CMD, 4);
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001572 if (err)
1573 return err;
1574
1575 cmd.cmdidx = SD_CMD_APP_SD_STATUS;
1576 cmd.resp_type = MMC_RSP_R1;
1577 cmd.cmdarg = 0;
1578
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001579 data.dest = (char *)ssr;
1580 data.blocksize = 64;
1581 data.blocks = 1;
1582 data.flags = MMC_DATA_READ;
1583
Sean Anderson86325092020-10-17 08:36:27 -04001584 err = mmc_send_cmd_retry(mmc, &cmd, &data, 3);
1585 if (err)
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001586 return err;
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001587
1588 for (i = 0; i < 16; i++)
1589 ssr[i] = be32_to_cpu(ssr[i]);
1590
1591 au = (ssr[2] >> 12) & 0xF;
1592 if ((au <= 9) || (mmc->version == SD_VERSION_3)) {
1593 mmc->ssr.au = sd_au_size[au];
1594 es = (ssr[3] >> 24) & 0xFF;
1595 es |= (ssr[2] & 0xFF) << 8;
1596 et = (ssr[3] >> 18) & 0x3F;
1597 if (es && et) {
1598 eo = (ssr[3] >> 16) & 0x3;
1599 mmc->ssr.erase_timeout = (et * 1000) / es;
1600 mmc->ssr.erase_offset = eo * 1000;
1601 }
1602 } else {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001603 pr_debug("Invalid Allocation Unit Size.\n");
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001604 }
1605
1606 return 0;
1607}
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001608#endif
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01001609/*
1610 * TRAN_SPEED bits 0:2 encode the frequency unit:
1611 * 0 = 100KHz, 1 = 1MHz, 2 = 10MHz, 3 = 100MHz, values 4 - 7 are reserved.
1612 * The values in fbase[] are divided by 10 to avoid floats in multiplier[].
1613 */
Mike Frysingerb588caf2010-10-20 01:15:53 +00001614static const int fbase[] = {
Andy Flemingad347bb2008-10-30 16:41:01 -05001615 10000,
1616 100000,
1617 1000000,
1618 10000000,
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01001619 0, /* reserved */
1620 0, /* reserved */
1621 0, /* reserved */
1622 0, /* reserved */
Andy Flemingad347bb2008-10-30 16:41:01 -05001623};
1624
1625/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
1626 * to platforms without floating point.
1627 */
Simon Glass03317cc2016-05-14 14:02:57 -06001628static const u8 multipliers[] = {
Andy Flemingad347bb2008-10-30 16:41:01 -05001629 0, /* reserved */
1630 10,
1631 12,
1632 13,
1633 15,
1634 20,
1635 25,
1636 30,
1637 35,
1638 40,
1639 45,
1640 50,
1641 55,
1642 60,
1643 70,
1644 80,
1645};
1646
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001647static inline int bus_width(uint cap)
1648{
1649 if (cap == MMC_MODE_8BIT)
1650 return 8;
1651 if (cap == MMC_MODE_4BIT)
1652 return 4;
1653 if (cap == MMC_MODE_1BIT)
1654 return 1;
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001655 pr_warn("invalid bus witdh capability 0x%x\n", cap);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001656 return 0;
1657}
1658
Simon Glasseba48f92017-07-29 11:35:31 -06001659#if !CONFIG_IS_ENABLED(DM_MMC)
Tom Rinidec7ea02024-05-20 13:35:03 -06001660#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Kishon Vijay Abraham Iae7174f2017-09-21 16:30:05 +02001661static int mmc_execute_tuning(struct mmc *mmc, uint opcode)
1662{
1663 return -ENOTSUPP;
1664}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001665#endif
Kishon Vijay Abraham Iae7174f2017-09-21 16:30:05 +02001666
Jean-Jacques Hiblot3f4da432025-04-10 11:00:20 +02001667static void mmc_send_init_stream(struct mmc *mmc)
1668{
1669}
1670
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001671static int mmc_set_ios(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001672{
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001673 int ret = 0;
1674
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001675 if (mmc->cfg->ops->set_ios)
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001676 ret = mmc->cfg->ops->set_ios(mmc);
1677
1678 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05001679}
Yann Gautier6f558332019-09-19 17:56:12 +02001680
1681static int mmc_host_power_cycle(struct mmc *mmc)
1682{
1683 int ret = 0;
1684
1685 if (mmc->cfg->ops->host_power_cycle)
1686 ret = mmc->cfg->ops->host_power_cycle(mmc);
1687
1688 return ret;
1689}
Simon Glass394dfc02016-06-12 23:30:22 -06001690#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001691
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001692int mmc_set_clock(struct mmc *mmc, uint clock, bool disable)
Andy Flemingad347bb2008-10-30 16:41:01 -05001693{
Jaehoon Chungab4d4052018-01-23 14:04:30 +09001694 if (!disable) {
Jaehoon Chung8a933292018-01-17 19:36:58 +09001695 if (clock > mmc->cfg->f_max)
1696 clock = mmc->cfg->f_max;
Andy Flemingad347bb2008-10-30 16:41:01 -05001697
Jaehoon Chung8a933292018-01-17 19:36:58 +09001698 if (clock < mmc->cfg->f_min)
1699 clock = mmc->cfg->f_min;
1700 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001701
1702 mmc->clock = clock;
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001703 mmc->clk_disable = disable;
Andy Flemingad347bb2008-10-30 16:41:01 -05001704
Jaehoon Chungc8477d62018-01-26 19:25:30 +09001705 debug("clock is %s (%dHz)\n", disable ? "disabled" : "enabled", clock);
1706
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001707 return mmc_set_ios(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001708}
1709
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001710static int mmc_set_bus_width(struct mmc *mmc, uint width)
Andy Flemingad347bb2008-10-30 16:41:01 -05001711{
1712 mmc->bus_width = width;
1713
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001714 return mmc_set_ios(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001715}
1716
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001717#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
1718/*
1719 * helper function to display the capabilities in a human
1720 * friendly manner. The capabilities include bus width and
1721 * supported modes.
1722 */
1723void mmc_dump_capabilities(const char *text, uint caps)
1724{
1725 enum bus_mode mode;
1726
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001727 pr_debug("%s: widths [", text);
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001728 if (caps & MMC_MODE_8BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001729 pr_debug("8, ");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001730 if (caps & MMC_MODE_4BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001731 pr_debug("4, ");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001732 if (caps & MMC_MODE_1BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001733 pr_debug("1, ");
1734 pr_debug("\b\b] modes [");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001735 for (mode = MMC_LEGACY; mode < MMC_MODES_END; mode++)
1736 if (MMC_CAP(mode) & caps)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001737 pr_debug("%s, ", mmc_mode_name(mode));
1738 pr_debug("\b\b]\n");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001739}
1740#endif
1741
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001742struct mode_width_tuning {
1743 enum bus_mode mode;
1744 uint widths;
Tom Rinidec7ea02024-05-20 13:35:03 -06001745#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001746 uint tuning;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001747#endif
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001748};
1749
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001750#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001751int mmc_voltage_to_mv(enum mmc_voltage voltage)
1752{
1753 switch (voltage) {
1754 case MMC_SIGNAL_VOLTAGE_000: return 0;
1755 case MMC_SIGNAL_VOLTAGE_330: return 3300;
1756 case MMC_SIGNAL_VOLTAGE_180: return 1800;
1757 case MMC_SIGNAL_VOLTAGE_120: return 1200;
1758 }
1759 return -EINVAL;
1760}
1761
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001762static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1763{
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001764 int err;
1765
1766 if (mmc->signal_voltage == signal_voltage)
1767 return 0;
1768
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001769 mmc->signal_voltage = signal_voltage;
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001770 err = mmc_set_ios(mmc);
1771 if (err)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001772 pr_debug("unable to set voltage (err %d)\n", err);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001773
1774 return err;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001775}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001776#else
1777static inline int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1778{
1779 return 0;
1780}
1781#endif
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001782
Marek Vasuta318a7a2018-04-15 00:37:11 +02001783#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001784static const struct mode_width_tuning sd_modes_by_pref[] = {
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001785#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Tom Rinidec7ea02024-05-20 13:35:03 -06001786#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001787 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001788 .mode = UHS_SDR104,
1789 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1790 .tuning = MMC_CMD_SEND_TUNING_BLOCK
1791 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001792#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001793 {
1794 .mode = UHS_SDR50,
1795 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1796 },
1797 {
1798 .mode = UHS_DDR50,
1799 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1800 },
1801 {
1802 .mode = UHS_SDR25,
1803 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1804 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001805#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001806 {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001807 .mode = SD_HS,
1808 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1809 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001810#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001811 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001812 .mode = UHS_SDR12,
1813 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1814 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001815#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001816 {
Faiz Abbas01db77e2020-02-26 13:44:32 +05301817 .mode = MMC_LEGACY,
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001818 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1819 }
1820};
1821
1822#define for_each_sd_mode_by_pref(caps, mwt) \
1823 for (mwt = sd_modes_by_pref;\
1824 mwt < sd_modes_by_pref + ARRAY_SIZE(sd_modes_by_pref);\
1825 mwt++) \
1826 if (caps & MMC_CAP(mwt->mode))
1827
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02001828static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001829{
1830 int err;
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001831 uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
1832 const struct mode_width_tuning *mwt;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001833#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001834 bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001835#else
1836 bool uhs_en = false;
1837#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001838 uint caps;
1839
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001840#ifdef DEBUG
1841 mmc_dump_capabilities("sd card", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001842 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001843#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001844
Anup Pateld9c92c72019-07-08 04:10:43 +00001845 if (mmc_host_is_spi(mmc)) {
1846 mmc_set_bus_width(mmc, 1);
Faiz Abbas01db77e2020-02-26 13:44:32 +05301847 mmc_select_mode(mmc, MMC_LEGACY);
Anup Pateld9c92c72019-07-08 04:10:43 +00001848 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
Pragnesh Patela01f57e2020-06-29 15:17:26 +05301849#if CONFIG_IS_ENABLED(MMC_WRITE)
1850 err = sd_read_ssr(mmc);
1851 if (err)
1852 pr_warn("unable to read ssr\n");
1853#endif
Anup Pateld9c92c72019-07-08 04:10:43 +00001854 return 0;
1855 }
1856
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001857 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001858 caps = card_caps & mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001859
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001860 if (!uhs_en)
1861 caps &= ~UHS_CAPS;
1862
1863 for_each_sd_mode_by_pref(caps, mwt) {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001864 uint *w;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001865
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001866 for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001867 if (*w & caps & mwt->widths) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001868 pr_debug("trying mode %s width %d (at %d MHz)\n",
1869 mmc_mode_name(mwt->mode),
1870 bus_width(*w),
1871 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001872
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001873 /* configure the bus width (card + host) */
1874 err = sd_select_bus_width(mmc, bus_width(*w));
1875 if (err)
1876 goto error;
1877 mmc_set_bus_width(mmc, bus_width(*w));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001878
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001879 /* configure the bus mode (card) */
1880 err = sd_set_card_speed(mmc, mwt->mode);
1881 if (err)
1882 goto error;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001883
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001884 /* configure the bus mode (host) */
1885 mmc_select_mode(mmc, mwt->mode);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001886 mmc_set_clock(mmc, mmc->tran_speed,
1887 MMC_CLK_ENABLE);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001888
Tom Rinidec7ea02024-05-20 13:35:03 -06001889#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001890 /* execute tuning if needed */
1891 if (mwt->tuning && !mmc_host_is_spi(mmc)) {
1892 err = mmc_execute_tuning(mmc,
1893 mwt->tuning);
1894 if (err) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001895 pr_debug("tuning failed\n");
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001896 goto error;
1897 }
1898 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001899#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001900
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001901#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001902 err = sd_read_ssr(mmc);
Peng Fan2d2fe8e2018-03-05 16:20:40 +08001903 if (err)
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001904 pr_warn("unable to read ssr\n");
1905#endif
1906 if (!err)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001907 return 0;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001908
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001909error:
1910 /* revert to a safer bus speed */
Faiz Abbas01db77e2020-02-26 13:44:32 +05301911 mmc_select_mode(mmc, MMC_LEGACY);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001912 mmc_set_clock(mmc, mmc->tran_speed,
1913 MMC_CLK_ENABLE);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001914 }
1915 }
1916 }
1917
Simon Glass367e3852024-08-22 07:54:55 -06001918 log_err("unable to select a mode\n");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001919 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001920}
1921
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001922/*
1923 * read the compare the part of ext csd that is constant.
1924 * This can be used to check that the transfer is working
1925 * as expected.
1926 */
1927static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001928{
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001929 int err;
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02001930 const u8 *ext_csd = mmc->ext_csd;
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001931 ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
1932
Jean-Jacques Hiblot7ab1b622017-11-30 17:43:58 +01001933 if (mmc->version < MMC_VERSION_4)
1934 return 0;
1935
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001936 err = mmc_send_ext_csd(mmc, test_csd);
1937 if (err)
1938 return err;
1939
1940 /* Only compare read only fields */
1941 if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
1942 == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
1943 ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
1944 == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
1945 ext_csd[EXT_CSD_REV]
1946 == test_csd[EXT_CSD_REV] &&
1947 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
1948 == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
1949 memcmp(&ext_csd[EXT_CSD_SEC_CNT],
1950 &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
1951 return 0;
1952
1953 return -EBADMSG;
1954}
1955
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001956#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001957static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1958 uint32_t allowed_mask)
1959{
1960 u32 card_mask = 0;
1961
1962 switch (mode) {
Peng Faneede83b2019-07-10 14:43:07 +08001963 case MMC_HS_400_ES:
Peng Fan46801252018-08-10 14:07:54 +08001964 case MMC_HS_400:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001965 case MMC_HS_200:
Peng Fan46801252018-08-10 14:07:54 +08001966 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V |
1967 EXT_CSD_CARD_TYPE_HS400_1_8V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001968 card_mask |= MMC_SIGNAL_VOLTAGE_180;
Peng Fan46801252018-08-10 14:07:54 +08001969 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
1970 EXT_CSD_CARD_TYPE_HS400_1_2V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001971 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1972 break;
1973 case MMC_DDR_52:
1974 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
1975 card_mask |= MMC_SIGNAL_VOLTAGE_330 |
1976 MMC_SIGNAL_VOLTAGE_180;
1977 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_2V)
1978 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1979 break;
1980 default:
1981 card_mask |= MMC_SIGNAL_VOLTAGE_330;
1982 break;
1983 }
1984
1985 while (card_mask & allowed_mask) {
1986 enum mmc_voltage best_match;
1987
1988 best_match = 1 << (ffs(card_mask & allowed_mask) - 1);
1989 if (!mmc_set_signal_voltage(mmc, best_match))
1990 return 0;
1991
1992 allowed_mask &= ~best_match;
1993 }
1994
1995 return -ENOTSUPP;
1996}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001997#else
1998static inline int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1999 uint32_t allowed_mask)
2000{
2001 return 0;
2002}
2003#endif
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002004
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002005static const struct mode_width_tuning mmc_modes_by_pref[] = {
Peng Faneede83b2019-07-10 14:43:07 +08002006#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
2007 {
2008 .mode = MMC_HS_400_ES,
2009 .widths = MMC_MODE_8BIT,
2010 },
2011#endif
Peng Fan46801252018-08-10 14:07:54 +08002012#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
2013 {
2014 .mode = MMC_HS_400,
2015 .widths = MMC_MODE_8BIT,
2016 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
2017 },
2018#endif
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002019#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002020 {
2021 .mode = MMC_HS_200,
2022 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002023 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002024 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002025#endif
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002026 {
2027 .mode = MMC_DDR_52,
2028 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
2029 },
2030 {
2031 .mode = MMC_HS_52,
2032 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2033 },
2034 {
2035 .mode = MMC_HS,
2036 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2037 },
2038 {
2039 .mode = MMC_LEGACY,
2040 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2041 }
2042};
2043
2044#define for_each_mmc_mode_by_pref(caps, mwt) \
2045 for (mwt = mmc_modes_by_pref;\
2046 mwt < mmc_modes_by_pref + ARRAY_SIZE(mmc_modes_by_pref);\
2047 mwt++) \
2048 if (caps & MMC_CAP(mwt->mode))
2049
2050static const struct ext_csd_bus_width {
2051 uint cap;
2052 bool is_ddr;
2053 uint ext_csd_bits;
2054} ext_csd_bus_width[] = {
2055 {MMC_MODE_8BIT, true, EXT_CSD_DDR_BUS_WIDTH_8},
2056 {MMC_MODE_4BIT, true, EXT_CSD_DDR_BUS_WIDTH_4},
2057 {MMC_MODE_8BIT, false, EXT_CSD_BUS_WIDTH_8},
2058 {MMC_MODE_4BIT, false, EXT_CSD_BUS_WIDTH_4},
2059 {MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
2060};
2061
Peng Fan46801252018-08-10 14:07:54 +08002062#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
2063static int mmc_select_hs400(struct mmc *mmc)
2064{
2065 int err;
2066
2067 /* Set timing to HS200 for tuning */
Marek Vasut111572f2019-01-03 21:19:24 +01002068 err = mmc_set_card_speed(mmc, MMC_HS_200, false);
Peng Fan46801252018-08-10 14:07:54 +08002069 if (err)
2070 return err;
2071
2072 /* configure the bus mode (host) */
2073 mmc_select_mode(mmc, MMC_HS_200);
2074 mmc_set_clock(mmc, mmc->tran_speed, false);
2075
2076 /* execute tuning if needed */
Marek Vasut259cc632024-02-24 23:32:09 +01002077 mmc->hs400_tuning = true;
Peng Fan46801252018-08-10 14:07:54 +08002078 err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200);
Marek Vasut259cc632024-02-24 23:32:09 +01002079 mmc->hs400_tuning = false;
Peng Fan46801252018-08-10 14:07:54 +08002080 if (err) {
2081 debug("tuning failed\n");
2082 return err;
2083 }
2084
2085 /* Set back to HS */
Venkatesh Yadav Abbarapu10f9def2024-04-23 11:00:57 +05302086 mmc_set_card_speed(mmc, MMC_HS_52, true);
Peng Fan46801252018-08-10 14:07:54 +08002087
Yangbo Lu5347aea2020-09-01 16:58:04 +08002088 err = mmc_hs400_prepare_ddr(mmc);
2089 if (err)
2090 return err;
2091
Peng Fan46801252018-08-10 14:07:54 +08002092 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2093 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
2094 if (err)
2095 return err;
2096
Marek Vasut111572f2019-01-03 21:19:24 +01002097 err = mmc_set_card_speed(mmc, MMC_HS_400, false);
Peng Fan46801252018-08-10 14:07:54 +08002098 if (err)
2099 return err;
2100
2101 mmc_select_mode(mmc, MMC_HS_400);
2102 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2103 if (err)
2104 return err;
2105
2106 return 0;
2107}
2108#else
2109static int mmc_select_hs400(struct mmc *mmc)
2110{
2111 return -ENOTSUPP;
2112}
2113#endif
2114
Peng Faneede83b2019-07-10 14:43:07 +08002115#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
2116#if !CONFIG_IS_ENABLED(DM_MMC)
2117static int mmc_set_enhanced_strobe(struct mmc *mmc)
2118{
2119 return -ENOTSUPP;
2120}
2121#endif
2122static int mmc_select_hs400es(struct mmc *mmc)
2123{
2124 int err;
2125
2126 err = mmc_set_card_speed(mmc, MMC_HS, true);
2127 if (err)
2128 return err;
2129
2130 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2131 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG |
2132 EXT_CSD_BUS_WIDTH_STROBE);
2133 if (err) {
2134 printf("switch to bus width for hs400 failed\n");
2135 return err;
2136 }
2137 /* TODO: driver strength */
2138 err = mmc_set_card_speed(mmc, MMC_HS_400_ES, false);
2139 if (err)
2140 return err;
2141
2142 mmc_select_mode(mmc, MMC_HS_400_ES);
2143 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2144 if (err)
2145 return err;
2146
2147 return mmc_set_enhanced_strobe(mmc);
2148}
2149#else
2150static int mmc_select_hs400es(struct mmc *mmc)
2151{
2152 return -ENOTSUPP;
2153}
2154#endif
2155
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002156#define for_each_supported_width(caps, ddr, ecbv) \
2157 for (ecbv = ext_csd_bus_width;\
2158 ecbv < ext_csd_bus_width + ARRAY_SIZE(ext_csd_bus_width);\
2159 ecbv++) \
2160 if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
2161
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002162static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02002163{
Jaehoon Chung6b3431c2020-12-04 06:36:00 +09002164 int err = 0;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002165 const struct mode_width_tuning *mwt;
2166 const struct ext_csd_bus_width *ecbw;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002167
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002168#ifdef DEBUG
2169 mmc_dump_capabilities("mmc", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002170 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002171#endif
2172
Anup Pateld9c92c72019-07-08 04:10:43 +00002173 if (mmc_host_is_spi(mmc)) {
2174 mmc_set_bus_width(mmc, 1);
2175 mmc_select_mode(mmc, MMC_LEGACY);
2176 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
2177 return 0;
2178 }
2179
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002180 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002181 card_caps &= mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002182
2183 /* Only version 4 of MMC supports wider bus widths */
2184 if (mmc->version < MMC_VERSION_4)
2185 return 0;
2186
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002187 if (!mmc->ext_csd) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002188 pr_debug("No ext_csd found!\n"); /* this should enver happen */
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002189 return -ENOTSUPP;
2190 }
2191
Marek Vasut111572f2019-01-03 21:19:24 +01002192#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
Ye Li3679e802021-08-17 17:20:34 +08002193 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
2194 CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
Marek Vasut111572f2019-01-03 21:19:24 +01002195 /*
2196 * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode
2197 * before doing anything else, since a transition from either of
2198 * the HS200/HS400 mode directly to legacy mode is not supported.
2199 */
2200 if (mmc->selected_mode == MMC_HS_200 ||
Ye Li3679e802021-08-17 17:20:34 +08002201 mmc->selected_mode == MMC_HS_400 ||
2202 mmc->selected_mode == MMC_HS_400_ES)
Marek Vasut111572f2019-01-03 21:19:24 +01002203 mmc_set_card_speed(mmc, MMC_HS, true);
2204 else
2205#endif
2206 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002207
2208 for_each_mmc_mode_by_pref(card_caps, mwt) {
2209 for_each_supported_width(card_caps & mwt->widths,
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002210 mmc_is_mode_ddr(mwt->mode), ecbw) {
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002211 enum mmc_voltage old_voltage;
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002212 pr_debug("trying mode %s width %d (at %d MHz)\n",
2213 mmc_mode_name(mwt->mode),
2214 bus_width(ecbw->cap),
2215 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002216 old_voltage = mmc->signal_voltage;
2217 err = mmc_set_lowest_voltage(mmc, mwt->mode,
2218 MMC_ALL_SIGNAL_VOLTAGE);
2219 if (err)
2220 continue;
2221
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002222 /* configure the bus width (card + host) */
2223 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2224 EXT_CSD_BUS_WIDTH,
2225 ecbw->ext_csd_bits & ~EXT_CSD_DDR_FLAG);
2226 if (err)
2227 goto error;
2228 mmc_set_bus_width(mmc, bus_width(ecbw->cap));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002229
Peng Fan46801252018-08-10 14:07:54 +08002230 if (mwt->mode == MMC_HS_400) {
2231 err = mmc_select_hs400(mmc);
2232 if (err) {
2233 printf("Select HS400 failed %d\n", err);
2234 goto error;
2235 }
Peng Faneede83b2019-07-10 14:43:07 +08002236 } else if (mwt->mode == MMC_HS_400_ES) {
2237 err = mmc_select_hs400es(mmc);
2238 if (err) {
2239 printf("Select HS400ES failed %d\n",
2240 err);
2241 goto error;
2242 }
Peng Fan46801252018-08-10 14:07:54 +08002243 } else {
2244 /* configure the bus speed (card) */
Marek Vasut111572f2019-01-03 21:19:24 +01002245 err = mmc_set_card_speed(mmc, mwt->mode, false);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002246 if (err)
2247 goto error;
Peng Fan46801252018-08-10 14:07:54 +08002248
2249 /*
2250 * configure the bus width AND the ddr mode
2251 * (card). The host side will be taken care
2252 * of in the next step
2253 */
2254 if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) {
2255 err = mmc_switch(mmc,
2256 EXT_CSD_CMD_SET_NORMAL,
2257 EXT_CSD_BUS_WIDTH,
2258 ecbw->ext_csd_bits);
2259 if (err)
2260 goto error;
2261 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002262
Peng Fan46801252018-08-10 14:07:54 +08002263 /* configure the bus mode (host) */
2264 mmc_select_mode(mmc, mwt->mode);
2265 mmc_set_clock(mmc, mmc->tran_speed,
2266 MMC_CLK_ENABLE);
Tom Rinidec7ea02024-05-20 13:35:03 -06002267#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002268
Peng Fan46801252018-08-10 14:07:54 +08002269 /* execute tuning if needed */
2270 if (mwt->tuning) {
2271 err = mmc_execute_tuning(mmc,
2272 mwt->tuning);
2273 if (err) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002274 pr_debug("tuning failed : %d\n", err);
Peng Fan46801252018-08-10 14:07:54 +08002275 goto error;
2276 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002277 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002278#endif
Peng Fan46801252018-08-10 14:07:54 +08002279 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002280
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002281 /* do a transfer to check the configuration */
2282 err = mmc_read_and_compare_ext_csd(mmc);
2283 if (!err)
2284 return 0;
2285error:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002286 mmc_set_signal_voltage(mmc, old_voltage);
Naoki Hayama3110dcb2020-10-12 18:35:22 +09002287 /* if an error occurred, revert to a safer bus mode */
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002288 mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2289 EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
2290 mmc_select_mode(mmc, MMC_LEGACY);
Valentine Barshak29f8d072023-06-10 13:22:33 +02002291 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002292 mmc_set_bus_width(mmc, 1);
2293 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002294 }
2295
Simon Glass367e3852024-08-22 07:54:55 -06002296 log_err("unable to select a mode: %d\n", err);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002297
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002298 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002299}
Marek Vasut67c77f92024-03-17 04:01:22 +01002300#else
2301static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
2302{
2303 return 0;
2304};
2305
2306static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
2307{
2308 return 0;
2309};
Marek Vasuta318a7a2018-04-15 00:37:11 +02002310#endif
2311
2312#if CONFIG_IS_ENABLED(MMC_TINY)
2313DEFINE_CACHE_ALIGN_BUFFER(u8, ext_csd_bkup, MMC_MAX_BLOCK_LEN);
2314#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002315
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002316static int mmc_startup_v4(struct mmc *mmc)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002317{
2318 int err, i;
2319 u64 capacity;
2320 bool has_parts = false;
2321 bool part_completed;
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002322 static const u32 mmc_versions[] = {
2323 MMC_VERSION_4,
2324 MMC_VERSION_4_1,
2325 MMC_VERSION_4_2,
2326 MMC_VERSION_4_3,
Jean-Jacques Hiblotc64862b2018-02-09 12:09:28 +01002327 MMC_VERSION_4_4,
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002328 MMC_VERSION_4_41,
2329 MMC_VERSION_4_5,
2330 MMC_VERSION_5_0,
2331 MMC_VERSION_5_1
2332 };
2333
Marek Vasuta318a7a2018-04-15 00:37:11 +02002334#if CONFIG_IS_ENABLED(MMC_TINY)
2335 u8 *ext_csd = ext_csd_bkup;
2336
2337 if (IS_SD(mmc) || mmc->version < MMC_VERSION_4)
2338 return 0;
2339
2340 if (!mmc->ext_csd)
Sam Edwardsed8339f2023-05-18 13:47:07 -06002341 memset(ext_csd_bkup, 0, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002342
2343 err = mmc_send_ext_csd(mmc, ext_csd);
2344 if (err)
2345 goto error;
2346
2347 /* store the ext csd for future reference */
2348 if (!mmc->ext_csd)
2349 mmc->ext_csd = ext_csd;
2350#else
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002351 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002352
2353 if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4))
2354 return 0;
2355
2356 /* check ext_csd version and capacity */
2357 err = mmc_send_ext_csd(mmc, ext_csd);
2358 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002359 goto error;
2360
2361 /* store the ext csd for future reference */
2362 if (!mmc->ext_csd)
2363 mmc->ext_csd = malloc(MMC_MAX_BLOCK_LEN);
2364 if (!mmc->ext_csd)
2365 return -ENOMEM;
2366 memcpy(mmc->ext_csd, ext_csd, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002367#endif
Alexander Kochetkovf1133c92018-02-20 14:35:55 +03002368 if (ext_csd[EXT_CSD_REV] >= ARRAY_SIZE(mmc_versions))
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002369 return -EINVAL;
2370
2371 mmc->version = mmc_versions[ext_csd[EXT_CSD_REV]];
2372
2373 if (mmc->version >= MMC_VERSION_4_2) {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002374 /*
2375 * According to the JEDEC Standard, the value of
2376 * ext_csd's capacity is valid if the value is more
2377 * than 2GB
2378 */
2379 capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
2380 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8
2381 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16
2382 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
2383 capacity *= MMC_MAX_BLOCK_LEN;
Marek Vasut1d8d1722025-01-29 12:15:54 +01002384 if (mmc->high_capacity)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002385 mmc->capacity_user = capacity;
2386 }
2387
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +02002388 if (mmc->version >= MMC_VERSION_4_5)
2389 mmc->gen_cmd6_time = ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
2390
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002391 /* The partition data may be non-zero but it is only
2392 * effective if PARTITION_SETTING_COMPLETED is set in
2393 * EXT_CSD, so ignore any data if this bit is not set,
2394 * except for enabling the high-capacity group size
2395 * definition (see below).
2396 */
2397 part_completed = !!(ext_csd[EXT_CSD_PARTITION_SETTING] &
2398 EXT_CSD_PARTITION_SETTING_COMPLETED);
2399
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +02002400 mmc->part_switch_time = ext_csd[EXT_CSD_PART_SWITCH_TIME];
2401 /* Some eMMC set the value too low so set a minimum */
2402 if (mmc->part_switch_time < MMC_MIN_PART_SWITCH_TIME && mmc->part_switch_time)
2403 mmc->part_switch_time = MMC_MIN_PART_SWITCH_TIME;
2404
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002405 /* store the partition info of emmc */
2406 mmc->part_support = ext_csd[EXT_CSD_PARTITIONING_SUPPORT];
2407 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
2408 ext_csd[EXT_CSD_BOOT_MULT])
2409 mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
2410 if (part_completed &&
2411 (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & ENHNCD_SUPPORT))
2412 mmc->part_attr = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE];
2413
2414 mmc->capacity_boot = ext_csd[EXT_CSD_BOOT_MULT] << 17;
2415
2416 mmc->capacity_rpmb = ext_csd[EXT_CSD_RPMB_MULT] << 17;
2417
2418 for (i = 0; i < 4; i++) {
2419 int idx = EXT_CSD_GP_SIZE_MULT + i * 3;
2420 uint mult = (ext_csd[idx + 2] << 16) +
2421 (ext_csd[idx + 1] << 8) + ext_csd[idx];
2422 if (mult)
2423 has_parts = true;
2424 if (!part_completed)
2425 continue;
2426 mmc->capacity_gp[i] = mult;
2427 mmc->capacity_gp[i] *=
2428 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2429 mmc->capacity_gp[i] *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2430 mmc->capacity_gp[i] <<= 19;
2431 }
2432
Simon Glass7ec24132024-09-29 19:49:48 -06002433#ifndef CONFIG_XPL_BUILD
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002434 if (part_completed) {
2435 mmc->enh_user_size =
2436 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 2] << 16) +
2437 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 1] << 8) +
2438 ext_csd[EXT_CSD_ENH_SIZE_MULT];
2439 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2440 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2441 mmc->enh_user_size <<= 19;
2442 mmc->enh_user_start =
2443 (ext_csd[EXT_CSD_ENH_START_ADDR + 3] << 24) +
2444 (ext_csd[EXT_CSD_ENH_START_ADDR + 2] << 16) +
2445 (ext_csd[EXT_CSD_ENH_START_ADDR + 1] << 8) +
2446 ext_csd[EXT_CSD_ENH_START_ADDR];
2447 if (mmc->high_capacity)
2448 mmc->enh_user_start <<= 9;
2449 }
Jean-Jacques Hiblotc94c5472018-01-04 15:23:35 +01002450#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002451
2452 /*
2453 * Host needs to enable ERASE_GRP_DEF bit if device is
2454 * partitioned. This bit will be lost every time after a reset
2455 * or power off. This will affect erase size.
2456 */
2457 if (part_completed)
2458 has_parts = true;
2459 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) &&
2460 (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB))
2461 has_parts = true;
2462 if (has_parts) {
2463 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2464 EXT_CSD_ERASE_GROUP_DEF, 1);
2465
2466 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002467 goto error;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002468
2469 ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
2470 }
2471
2472 if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01) {
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002473#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002474 /* Read out group size from ext_csd */
2475 mmc->erase_grp_size =
2476 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002477#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002478 /*
2479 * if high capacity and partition setting completed
2480 * SEC_COUNT is valid even if it is smaller than 2 GiB
2481 * JEDEC Standard JESD84-B45, 6.2.4
2482 */
2483 if (mmc->high_capacity && part_completed) {
2484 capacity = (ext_csd[EXT_CSD_SEC_CNT]) |
2485 (ext_csd[EXT_CSD_SEC_CNT + 1] << 8) |
2486 (ext_csd[EXT_CSD_SEC_CNT + 2] << 16) |
2487 (ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
2488 capacity *= MMC_MAX_BLOCK_LEN;
2489 mmc->capacity_user = capacity;
2490 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002491 }
2492#if CONFIG_IS_ENABLED(MMC_WRITE)
2493 else {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002494 /* Calculate the group size from the csd value. */
2495 int erase_gsz, erase_gmul;
2496
2497 erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
2498 erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
2499 mmc->erase_grp_size = (erase_gsz + 1)
2500 * (erase_gmul + 1);
2501 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002502#endif
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002503#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002504 mmc->hc_wp_grp_size = 1024
2505 * ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
2506 * ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002507#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002508
2509 mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
2510
Loic Poulainc0aadbb2023-01-26 10:24:17 +01002511 mmc->can_trim =
2512 !!(ext_csd[EXT_CSD_SEC_FEATURE] & EXT_CSD_SEC_FEATURE_TRIM_EN);
2513
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002514 return 0;
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002515error:
2516 if (mmc->ext_csd) {
Marek Vasuta318a7a2018-04-15 00:37:11 +02002517#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002518 free(mmc->ext_csd);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002519#endif
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002520 mmc->ext_csd = NULL;
2521 }
2522 return err;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002523}
2524
Kim Phillips87ea3892012-10-29 13:34:43 +00002525static int mmc_startup(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002526{
Stephen Warrene315ae82013-06-11 15:14:01 -06002527 int err, i;
Andy Flemingad347bb2008-10-30 16:41:01 -05002528 uint mult, freq;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002529 u64 cmult, csize;
Andy Flemingad347bb2008-10-30 16:41:01 -05002530 struct mmc_cmd cmd;
Simon Glasse5db1152016-05-01 13:52:35 -06002531 struct blk_desc *bdesc;
Andy Flemingad347bb2008-10-30 16:41:01 -05002532
Thomas Chou1254c3d2010-12-24 13:12:21 +00002533#ifdef CONFIG_MMC_SPI_CRC_ON
2534 if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
2535 cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
2536 cmd.resp_type = MMC_RSP_R1;
2537 cmd.cmdarg = 1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002538 err = mmc_send_cmd(mmc, &cmd, NULL);
Thomas Chou1254c3d2010-12-24 13:12:21 +00002539 if (err)
2540 return err;
2541 }
2542#endif
2543
Andy Flemingad347bb2008-10-30 16:41:01 -05002544 /* Put the Card in Identify Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002545 cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
2546 MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
Andy Flemingad347bb2008-10-30 16:41:01 -05002547 cmd.resp_type = MMC_RSP_R2;
2548 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002549
Sean Anderson86325092020-10-17 08:36:27 -04002550 err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_SEND_CID, 4);
Andy Flemingad347bb2008-10-30 16:41:01 -05002551 if (err)
2552 return err;
2553
2554 memcpy(mmc->cid, cmd.response, 16);
2555
2556 /*
2557 * For MMC cards, set the Relative Address.
Heinrich Schuchardta53d6bf2025-04-14 13:49:43 +02002558 * For SD cards, get the Relative Address.
Andy Flemingad347bb2008-10-30 16:41:01 -05002559 * This also puts the cards into Standby State
2560 */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002561 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2562 cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
2563 cmd.cmdarg = mmc->rca << 16;
2564 cmd.resp_type = MMC_RSP_R6;
Andy Flemingad347bb2008-10-30 16:41:01 -05002565
Thomas Chou1254c3d2010-12-24 13:12:21 +00002566 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002567
Thomas Chou1254c3d2010-12-24 13:12:21 +00002568 if (err)
2569 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002570
Thomas Chou1254c3d2010-12-24 13:12:21 +00002571 if (IS_SD(mmc))
2572 mmc->rca = (cmd.response[0] >> 16) & 0xffff;
2573 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002574
2575 /* Get the Card-Specific Data */
2576 cmd.cmdidx = MMC_CMD_SEND_CSD;
2577 cmd.resp_type = MMC_RSP_R2;
2578 cmd.cmdarg = mmc->rca << 16;
Andy Flemingad347bb2008-10-30 16:41:01 -05002579
2580 err = mmc_send_cmd(mmc, &cmd, NULL);
2581
2582 if (err)
2583 return err;
2584
Rabin Vincentb6eed942009-04-05 13:30:56 +05302585 mmc->csd[0] = cmd.response[0];
2586 mmc->csd[1] = cmd.response[1];
2587 mmc->csd[2] = cmd.response[2];
2588 mmc->csd[3] = cmd.response[3];
Andy Flemingad347bb2008-10-30 16:41:01 -05002589
2590 if (mmc->version == MMC_VERSION_UNKNOWN) {
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302591 int version = (cmd.response[0] >> 26) & 0xf;
Andy Flemingad347bb2008-10-30 16:41:01 -05002592
2593 switch (version) {
Bin Meng4a4ef872016-03-17 21:53:13 -07002594 case 0:
2595 mmc->version = MMC_VERSION_1_2;
2596 break;
2597 case 1:
2598 mmc->version = MMC_VERSION_1_4;
2599 break;
2600 case 2:
2601 mmc->version = MMC_VERSION_2_2;
2602 break;
2603 case 3:
2604 mmc->version = MMC_VERSION_3;
2605 break;
2606 case 4:
2607 mmc->version = MMC_VERSION_4;
2608 break;
2609 default:
2610 mmc->version = MMC_VERSION_1_2;
2611 break;
Andy Flemingad347bb2008-10-30 16:41:01 -05002612 }
2613 }
2614
2615 /* divide frequency by 10, since the mults are 10x bigger */
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302616 freq = fbase[(cmd.response[0] & 0x7)];
2617 mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
Andy Flemingad347bb2008-10-30 16:41:01 -05002618
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002619 mmc->legacy_speed = freq * mult;
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01002620 if (!mmc->legacy_speed)
2621 log_debug("TRAN_SPEED: reserved value");
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002622 mmc_select_mode(mmc, MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05002623
Markus Niebel03951412013-12-16 13:40:46 +01002624 mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
Rabin Vincentb6eed942009-04-05 13:30:56 +05302625 mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002626#if CONFIG_IS_ENABLED(MMC_WRITE)
Andy Flemingad347bb2008-10-30 16:41:01 -05002627
2628 if (IS_SD(mmc))
2629 mmc->write_bl_len = mmc->read_bl_len;
2630 else
Rabin Vincentb6eed942009-04-05 13:30:56 +05302631 mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002632#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002633
2634 if (mmc->high_capacity) {
2635 csize = (mmc->csd[1] & 0x3f) << 16
2636 | (mmc->csd[2] & 0xffff0000) >> 16;
2637 cmult = 8;
2638 } else {
2639 csize = (mmc->csd[1] & 0x3ff) << 2
2640 | (mmc->csd[2] & 0xc0000000) >> 30;
2641 cmult = (mmc->csd[2] & 0x00038000) >> 15;
2642 }
2643
Stephen Warrene315ae82013-06-11 15:14:01 -06002644 mmc->capacity_user = (csize + 1) << (cmult + 2);
2645 mmc->capacity_user *= mmc->read_bl_len;
2646 mmc->capacity_boot = 0;
2647 mmc->capacity_rpmb = 0;
2648 for (i = 0; i < 4; i++)
2649 mmc->capacity_gp[i] = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002650
Simon Glassa09c2b72013-04-03 08:54:30 +00002651 if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN)
2652 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -05002653
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002654#if CONFIG_IS_ENABLED(MMC_WRITE)
Simon Glassa09c2b72013-04-03 08:54:30 +00002655 if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
2656 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002657#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002658
Markus Niebel03951412013-12-16 13:40:46 +01002659 if ((mmc->dsr_imp) && (0xffffffff != mmc->dsr)) {
2660 cmd.cmdidx = MMC_CMD_SET_DSR;
2661 cmd.cmdarg = (mmc->dsr & 0xffff) << 16;
2662 cmd.resp_type = MMC_RSP_NONE;
2663 if (mmc_send_cmd(mmc, &cmd, NULL))
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002664 pr_warn("MMC: SET_DSR failed\n");
Markus Niebel03951412013-12-16 13:40:46 +01002665 }
2666
Andy Flemingad347bb2008-10-30 16:41:01 -05002667 /* Select the card, and put it into Transfer Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002668 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2669 cmd.cmdidx = MMC_CMD_SELECT_CARD;
Ajay Bhargav4a32fba2011-10-05 03:13:23 +00002670 cmd.resp_type = MMC_RSP_R1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002671 cmd.cmdarg = mmc->rca << 16;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002672 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002673
Thomas Chou1254c3d2010-12-24 13:12:21 +00002674 if (err)
2675 return err;
2676 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002677
Lei Wenea526762011-06-22 17:03:31 +00002678 /*
2679 * For SD, its erase group is always one sector
2680 */
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002681#if CONFIG_IS_ENABLED(MMC_WRITE)
Lei Wenea526762011-06-22 17:03:31 +00002682 mmc->erase_grp_size = 1;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002683#endif
Lei Wen31b99802011-05-02 16:26:26 +00002684 mmc->part_config = MMCPART_NOAVAILABLE;
Diego Santa Cruza7a75992014-12-23 10:50:27 +01002685
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002686 err = mmc_startup_v4(mmc);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002687 if (err)
2688 return err;
Sukumar Ghorai232293c2010-09-20 18:29:29 +05302689
Simon Glasse5db1152016-05-01 13:52:35 -06002690 err = mmc_set_capacity(mmc, mmc_get_blk_desc(mmc)->hwpart);
Stephen Warrene315ae82013-06-11 15:14:01 -06002691 if (err)
2692 return err;
2693
Marek Vasuta318a7a2018-04-15 00:37:11 +02002694#if CONFIG_IS_ENABLED(MMC_TINY)
2695 mmc_set_clock(mmc, mmc->legacy_speed, false);
Faiz Abbas01db77e2020-02-26 13:44:32 +05302696 mmc_select_mode(mmc, MMC_LEGACY);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002697 mmc_set_bus_width(mmc, 1);
2698#else
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002699 if (IS_SD(mmc)) {
2700 err = sd_get_capabilities(mmc);
2701 if (err)
2702 return err;
2703 err = sd_select_mode_and_width(mmc, mmc->card_caps);
2704 } else {
2705 err = mmc_get_capabilities(mmc);
2706 if (err)
2707 return err;
Masahiro Yamadabf1f25c2020-01-23 14:31:12 +09002708 err = mmc_select_mode_and_width(mmc, mmc->card_caps);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002709 }
Marek Vasuta318a7a2018-04-15 00:37:11 +02002710#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002711 if (err)
2712 return err;
2713
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002714 mmc->best_mode = mmc->selected_mode;
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00002715
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002716 /* Fix the block length for DDR mode */
2717 if (mmc->ddr_mode) {
2718 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002719#if CONFIG_IS_ENABLED(MMC_WRITE)
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002720 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002721#endif
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002722 }
2723
Andy Flemingad347bb2008-10-30 16:41:01 -05002724 /* fill in device description */
Simon Glasse5db1152016-05-01 13:52:35 -06002725 bdesc = mmc_get_blk_desc(mmc);
2726 bdesc->lun = 0;
2727 bdesc->hwpart = 0;
2728 bdesc->type = 0;
2729 bdesc->blksz = mmc->read_bl_len;
2730 bdesc->log2blksz = LOG2(bdesc->blksz);
2731 bdesc->lba = lldiv(mmc->capacity, mmc->read_bl_len);
Simon Glass7ec24132024-09-29 19:49:48 -06002732#if !defined(CONFIG_XPL_BUILD) || \
Sjoerd Simonsd67754f2015-12-04 23:27:40 +01002733 (defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \
Simon Glass7611ac62019-09-25 08:56:27 -06002734 !CONFIG_IS_ENABLED(USE_TINY_PRINTF))
Simon Glasse5db1152016-05-01 13:52:35 -06002735 sprintf(bdesc->vendor, "Man %06x Snr %04x%04x",
Taylor Hutt7367ec22012-10-20 17:15:59 +00002736 mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
2737 (mmc->cid[3] >> 16) & 0xffff);
Simon Glasse5db1152016-05-01 13:52:35 -06002738 sprintf(bdesc->product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002739 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
2740 (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
2741 (mmc->cid[2] >> 24) & 0xff);
Simon Glasse5db1152016-05-01 13:52:35 -06002742 sprintf(bdesc->revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002743 (mmc->cid[2] >> 16) & 0xf);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002744#else
Simon Glasse5db1152016-05-01 13:52:35 -06002745 bdesc->vendor[0] = 0;
2746 bdesc->product[0] = 0;
2747 bdesc->revision[0] = 0;
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002748#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002749
Simon Glass7ec24132024-09-29 19:49:48 -06002750#if !defined(CONFIG_DM_MMC) && (!defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT))
Andre Przywara17798042018-12-17 10:05:45 +00002751 part_init(bdesc);
2752#endif
2753
Andy Flemingad347bb2008-10-30 16:41:01 -05002754 return 0;
2755}
2756
Kim Phillips87ea3892012-10-29 13:34:43 +00002757static int mmc_send_if_cond(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002758{
2759 struct mmc_cmd cmd;
2760 int err;
2761
2762 cmd.cmdidx = SD_CMD_SEND_IF_COND;
2763 /* We set the bit if the host supports voltages between 2.7 and 3.6 V */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002764 cmd.cmdarg = ((mmc->cfg->voltages & 0xff8000) != 0) << 8 | 0xaa;
Andy Flemingad347bb2008-10-30 16:41:01 -05002765 cmd.resp_type = MMC_RSP_R7;
Andy Flemingad347bb2008-10-30 16:41:01 -05002766
2767 err = mmc_send_cmd(mmc, &cmd, NULL);
2768
2769 if (err)
2770 return err;
2771
Rabin Vincentb6eed942009-04-05 13:30:56 +05302772 if ((cmd.response[0] & 0xff) != 0xaa)
Jaehoon Chung7825d202016-07-19 16:33:36 +09002773 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002774 else
2775 mmc->version = SD_VERSION_2;
2776
2777 return 0;
2778}
2779
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002780#if !CONFIG_IS_ENABLED(DM_MMC)
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002781/* board-specific MMC power initializations. */
2782__weak void board_mmc_power_init(void)
2783{
2784}
Simon Glass833b80d2017-04-22 19:10:56 -06002785#endif
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002786
Peng Fan15305962016-10-11 15:08:43 +08002787static int mmc_power_init(struct mmc *mmc)
2788{
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002789#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002790#if CONFIG_IS_ENABLED(DM_REGULATOR)
Peng Fan15305962016-10-11 15:08:43 +08002791 int ret;
2792
2793 ret = device_get_supply_regulator(mmc->dev, "vmmc-supply",
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002794 &mmc->vmmc_supply);
2795 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002796 pr_debug("%s: No vmmc supply\n", mmc->dev->name);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002797
2798 ret = device_get_supply_regulator(mmc->dev, "vqmmc-supply",
2799 &mmc->vqmmc_supply);
2800 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002801 pr_debug("%s: No vqmmc supply\n", mmc->dev->name);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002802#endif
2803#else /* !CONFIG_DM_MMC */
2804 /*
2805 * Driver model should use a regulator, as above, rather than calling
2806 * out to board code.
2807 */
2808 board_mmc_power_init();
2809#endif
2810 return 0;
2811}
2812
2813/*
2814 * put the host in the initial state:
2815 * - turn on Vdd (card power supply)
2816 * - configure the bus width and clock to minimal values
2817 */
2818static void mmc_set_initial_state(struct mmc *mmc)
2819{
2820 int err;
2821
2822 /* First try to set 3.3V. If it fails set to 1.8V */
2823 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
2824 if (err != 0)
2825 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
2826 if (err != 0)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002827 pr_warn("mmc: failed to set signal voltage\n");
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002828
2829 mmc_select_mode(mmc, MMC_LEGACY);
2830 mmc_set_bus_width(mmc, 1);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002831 mmc_set_clock(mmc, 0, MMC_CLK_ENABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002832}
Peng Fan15305962016-10-11 15:08:43 +08002833
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002834static int mmc_power_on(struct mmc *mmc)
2835{
2836#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002837 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002838 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2839 true);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002840
Jonas Karlman0f28e182023-07-19 21:20:59 +00002841 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002842 printf("Error enabling VMMC supply : %d\n", ret);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002843 return ret;
2844 }
Peng Fan15305962016-10-11 15:08:43 +08002845 }
2846#endif
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002847 return 0;
2848}
2849
2850static int mmc_power_off(struct mmc *mmc)
2851{
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002852 mmc_set_clock(mmc, 0, MMC_CLK_DISABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002853#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
2854 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002855 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2856 false);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002857
Jonas Karlman0f28e182023-07-19 21:20:59 +00002858 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002859 pr_debug("Error disabling VMMC supply : %d\n", ret);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002860 return ret;
2861 }
2862 }
Simon Glass833b80d2017-04-22 19:10:56 -06002863#endif
Peng Fan15305962016-10-11 15:08:43 +08002864 return 0;
2865}
2866
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002867static int mmc_power_cycle(struct mmc *mmc)
2868{
2869 int ret;
2870
2871 ret = mmc_power_off(mmc);
2872 if (ret)
2873 return ret;
Yann Gautier6f558332019-09-19 17:56:12 +02002874
2875 ret = mmc_host_power_cycle(mmc);
2876 if (ret)
2877 return ret;
2878
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002879 /*
2880 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
2881 * to be on the safer side.
2882 */
2883 udelay(2000);
2884 return mmc_power_on(mmc);
2885}
2886
Pali Rohár7c639622021-07-14 16:37:29 +02002887int mmc_get_op_cond(struct mmc *mmc, bool quiet)
Andy Flemingad347bb2008-10-30 16:41:01 -05002888{
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002889 bool uhs_en = supports_uhs(mmc->cfg->host_caps);
Macpaul Lin028bde12011-11-14 23:35:39 +00002890 int err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002891
Lei Wen31b99802011-05-02 16:26:26 +00002892 if (mmc->has_init)
2893 return 0;
2894
Peng Fan15305962016-10-11 15:08:43 +08002895 err = mmc_power_init(mmc);
2896 if (err)
2897 return err;
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002898
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002899#ifdef CONFIG_MMC_QUIRKS
2900 mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN |
Joel Johnson5ea041b2020-01-11 09:08:14 -07002901 MMC_QUIRK_RETRY_SEND_CID |
2902 MMC_QUIRK_RETRY_APP_CMD;
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002903#endif
2904
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002905 err = mmc_power_cycle(mmc);
2906 if (err) {
2907 /*
2908 * if power cycling is not supported, we should not try
2909 * to use the UHS modes, because we wouldn't be able to
2910 * recover from an error during the UHS initialization.
2911 */
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002912 pr_debug("Unable to do a full power cycle. Disabling the UHS modes for safety\n");
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002913 uhs_en = false;
2914 mmc->host_caps &= ~UHS_CAPS;
2915 err = mmc_power_on(mmc);
2916 }
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002917 if (err)
2918 return err;
2919
Simon Glasseba48f92017-07-29 11:35:31 -06002920#if CONFIG_IS_ENABLED(DM_MMC)
Yangbo Luc46f5d72020-09-01 16:57:59 +08002921 /*
2922 * Re-initialization is needed to clear old configuration for
2923 * mmc rescan.
2924 */
2925 err = mmc_reinit(mmc);
Simon Glass394dfc02016-06-12 23:30:22 -06002926#else
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02002927 /* made sure it's not NULL earlier */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002928 err = mmc->cfg->ops->init(mmc);
Yangbo Luc46f5d72020-09-01 16:57:59 +08002929#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002930 if (err)
2931 return err;
Andrew Gabbasov9fc2a412014-12-01 06:59:09 -06002932 mmc->ddr_mode = 0;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02002933
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002934retry:
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002935 mmc_set_initial_state(mmc);
Jean-Jacques Hiblot5f23d872017-09-21 16:30:01 +02002936
Jean-Jacques Hiblot3f4da432025-04-10 11:00:20 +02002937 mmc_send_init_stream(mmc);
2938
Andy Flemingad347bb2008-10-30 16:41:01 -05002939 /* Reset the Card */
2940 err = mmc_go_idle(mmc);
2941
2942 if (err)
2943 return err;
2944
Marcel Ziswilerb2b7fc82019-05-20 02:44:53 +02002945 /* The internal partition reset to user partition(0) at every CMD0 */
Simon Glasse5db1152016-05-01 13:52:35 -06002946 mmc_get_blk_desc(mmc)->hwpart = 0;
Lei Wen31b99802011-05-02 16:26:26 +00002947
Andy Flemingad347bb2008-10-30 16:41:01 -05002948 /* Test for SD version 2 */
Macpaul Lin028bde12011-11-14 23:35:39 +00002949 err = mmc_send_if_cond(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05002950
Andy Flemingad347bb2008-10-30 16:41:01 -05002951 /* Now try to get the SD card's operating condition */
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002952 err = sd_send_op_cond(mmc, uhs_en);
2953 if (err && uhs_en) {
2954 uhs_en = false;
2955 mmc_power_cycle(mmc);
2956 goto retry;
2957 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002958
2959 /* If the command timed out, we check for an MMC card */
Jaehoon Chung7825d202016-07-19 16:33:36 +09002960 if (err == -ETIMEDOUT) {
Andy Flemingad347bb2008-10-30 16:41:01 -05002961 err = mmc_send_op_cond(mmc);
2962
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002963 if (err) {
Simon Glass7ec24132024-09-29 19:49:48 -06002964#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Pali Rohár7c639622021-07-14 16:37:29 +02002965 if (!quiet)
Simon Glass367e3852024-08-22 07:54:55 -06002966 log_err("Card did not respond to voltage select! : %d\n",
2967 err);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002968#endif
Jaehoon Chung7825d202016-07-19 16:33:36 +09002969 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002970 }
2971 }
2972
Jon Nettleton2663fe42018-06-11 15:26:19 +03002973 return err;
2974}
2975
2976int mmc_start_init(struct mmc *mmc)
2977{
2978 bool no_card;
2979 int err = 0;
2980
2981 /*
2982 * all hosts are capable of 1 bit bus-width and able to use the legacy
2983 * timings.
2984 */
Faiz Abbas01db77e2020-02-26 13:44:32 +05302985 mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) |
Aswath Govindrajubb5b9fe2021-08-13 23:04:41 +05302986 MMC_MODE_1BIT;
2987
2988 if (IS_ENABLED(CONFIG_MMC_SPEED_MODE_SET)) {
2989 if (mmc->user_speed_mode != MMC_MODES_END) {
2990 int i;
2991 /* set host caps */
2992 if (mmc->host_caps & MMC_CAP(mmc->user_speed_mode)) {
2993 /* Remove all existing speed capabilities */
2994 for (i = MMC_LEGACY; i < MMC_MODES_END; i++)
2995 mmc->host_caps &= ~MMC_CAP(i);
2996 mmc->host_caps |= (MMC_CAP(mmc->user_speed_mode)
2997 | MMC_CAP(MMC_LEGACY) |
2998 MMC_MODE_1BIT);
2999 } else {
Simon Glass367e3852024-08-22 07:54:55 -06003000 log_err("bus_mode requested is not supported\n");
Aswath Govindrajubb5b9fe2021-08-13 23:04:41 +05303001 return -EINVAL;
3002 }
3003 }
3004 }
Faiz Abbasf6fd4ec2020-02-26 13:44:30 +05303005#if CONFIG_IS_ENABLED(DM_MMC)
3006 mmc_deferred_probe(mmc);
3007#endif
Jon Nettleton2663fe42018-06-11 15:26:19 +03003008#if !defined(CONFIG_MMC_BROKEN_CD)
Jon Nettleton2663fe42018-06-11 15:26:19 +03003009 no_card = mmc_getcd(mmc) == 0;
3010#else
3011 no_card = 0;
3012#endif
3013#if !CONFIG_IS_ENABLED(DM_MMC)
Baruch Siach0448ce62019-07-22 15:52:12 +03003014 /* we pretend there's no card when init is NULL */
Jon Nettleton2663fe42018-06-11 15:26:19 +03003015 no_card = no_card || (mmc->cfg->ops->init == NULL);
3016#endif
3017 if (no_card) {
3018 mmc->has_init = 0;
Simon Glass7ec24132024-09-29 19:49:48 -06003019#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Simon Glass367e3852024-08-22 07:54:55 -06003020 log_err("MMC: no card present\n");
Jon Nettleton2663fe42018-06-11 15:26:19 +03003021#endif
3022 return -ENOMEDIUM;
3023 }
3024
Pali Rohár7c639622021-07-14 16:37:29 +02003025 err = mmc_get_op_cond(mmc, false);
Jon Nettleton2663fe42018-06-11 15:26:19 +03003026
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003027 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003028 mmc->init_in_progress = 1;
3029
3030 return err;
3031}
3032
3033static int mmc_complete_init(struct mmc *mmc)
3034{
3035 int err = 0;
3036
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003037 mmc->init_in_progress = 0;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003038 if (mmc->op_cond_pending)
3039 err = mmc_complete_op_cond(mmc);
3040
3041 if (!err)
3042 err = mmc_startup(mmc);
Lei Wen31b99802011-05-02 16:26:26 +00003043 if (err)
3044 mmc->has_init = 0;
3045 else
3046 mmc->has_init = 1;
3047 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05003048}
3049
Marek Vasut9b51ddc2025-01-18 04:09:53 +01003050static void mmc_cyclic_cd_poll(struct cyclic_info *c)
Marek Vasutb0967402024-09-06 19:10:42 +02003051{
Marek Vasut9b51ddc2025-01-18 04:09:53 +01003052 struct mmc *m = container_of(c, struct mmc, cyclic);
Marek Vasutb0967402024-09-06 19:10:42 +02003053
3054 if (!m->has_init)
3055 return;
3056
3057 if (mmc_getcd(m))
3058 return;
3059
3060 mmc_deinit(m);
3061 m->has_init = 0;
3062}
3063
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003064int mmc_init(struct mmc *mmc)
3065{
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003066 int err = 0;
Vipul Kumardbad7b42018-05-03 12:20:54 +05303067 __maybe_unused ulong start;
Simon Glass5f4bd8c2017-07-04 13:31:19 -06003068#if CONFIG_IS_ENABLED(DM_MMC)
Simon Glass59bc6f22016-05-01 13:52:41 -06003069 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003070
Simon Glass59bc6f22016-05-01 13:52:41 -06003071 upriv->mmc = mmc;
3072#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003073 if (mmc->has_init)
3074 return 0;
Mateusz Zalegada351782014-04-29 20:15:30 +02003075
3076 start = get_timer(0);
3077
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003078 if (!mmc->init_in_progress)
3079 err = mmc_start_init(mmc);
3080
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003081 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003082 err = mmc_complete_init(mmc);
Marek Vasut285de2c2025-01-18 04:27:34 +01003083 if (err) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09003084 pr_info("%s: %d, time %lu\n", __func__, err, get_timer(start));
Marek Vasut285de2c2025-01-18 04:27:34 +01003085 return err;
3086 }
Jagan Teki9bee2b52017-01-10 11:18:43 +01003087
Marek Vasutb0967402024-09-06 19:10:42 +02003088 if (CONFIG_IS_ENABLED(CYCLIC, (!mmc->cyclic.func), (NULL))) {
3089 /* Register cyclic function for card detect polling */
Marek Vasut9b51ddc2025-01-18 04:09:53 +01003090 cyclic_register(&mmc->cyclic, mmc_cyclic_cd_poll, 100 * 1000,
3091 mmc->cfg->name);
Marek Vasutb0967402024-09-06 19:10:42 +02003092 }
3093
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003094 return err;
3095}
3096
Marek Vasuta4773fc2019-01-29 04:45:51 +01003097int mmc_deinit(struct mmc *mmc)
3098{
3099 u32 caps_filtered;
3100
Marek Vasutb0967402024-09-06 19:10:42 +02003101 if (CONFIG_IS_ENABLED(CYCLIC, (mmc->cyclic.func), (NULL)))
Marek Vasut9b51ddc2025-01-18 04:09:53 +01003102 cyclic_unregister(&mmc->cyclic);
Marek Vasutb0967402024-09-06 19:10:42 +02003103
Marek Vasut67c77f92024-03-17 04:01:22 +01003104 if (!CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) &&
3105 !CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) &&
3106 !CONFIG_IS_ENABLED(MMC_HS400_SUPPORT))
3107 return 0;
3108
Marek Vasuta4773fc2019-01-29 04:45:51 +01003109 if (!mmc->has_init)
3110 return 0;
3111
3112 if (IS_SD(mmc)) {
3113 caps_filtered = mmc->card_caps &
3114 ~(MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) |
3115 MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
3116 MMC_CAP(UHS_SDR104));
3117
3118 return sd_select_mode_and_width(mmc, caps_filtered);
3119 } else {
3120 caps_filtered = mmc->card_caps &
Ye Li3679e802021-08-17 17:20:34 +08003121 ~(MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_HS_400) | MMC_CAP(MMC_HS_400_ES));
Marek Vasuta4773fc2019-01-29 04:45:51 +01003122
3123 return mmc_select_mode_and_width(mmc, caps_filtered);
3124 }
3125}
Marek Vasuta4773fc2019-01-29 04:45:51 +01003126
Markus Niebel03951412013-12-16 13:40:46 +01003127int mmc_set_dsr(struct mmc *mmc, u16 val)
3128{
3129 mmc->dsr = val;
3130 return 0;
3131}
3132
Jeroen Hofstee47726302014-07-10 22:46:28 +02003133/* CPU-specific MMC initializations */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003134__weak int cpu_mmc_init(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003135{
3136 return -1;
3137}
3138
Jeroen Hofstee47726302014-07-10 22:46:28 +02003139/* board-specific MMC initializations. */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003140__weak int board_mmc_init(struct bd_info *bis)
Jeroen Hofstee47726302014-07-10 22:46:28 +02003141{
3142 return -1;
3143}
Andy Flemingad347bb2008-10-30 16:41:01 -05003144
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003145void mmc_set_preinit(struct mmc *mmc, int preinit)
3146{
3147 mmc->preinit = preinit;
3148}
3149
Faiz Abbasb3857fd2018-02-12 19:35:24 +05303150#if CONFIG_IS_ENABLED(DM_MMC)
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003151static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003152{
Simon Glass547cb342015-12-29 05:22:49 -07003153 int ret, i;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003154 struct uclass *uc;
Simon Glass547cb342015-12-29 05:22:49 -07003155 struct udevice *dev;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003156
3157 ret = uclass_get(UCLASS_MMC, &uc);
3158 if (ret)
3159 return ret;
3160
Simon Glass547cb342015-12-29 05:22:49 -07003161 /*
3162 * Try to add them in sequence order. Really with driver model we
3163 * should allow holes, but the current MMC list does not allow that.
3164 * So if we request 0, 1, 3 we will get 0, 1, 2.
3165 */
3166 for (i = 0; ; i++) {
3167 ret = uclass_get_device_by_seq(UCLASS_MMC, i, &dev);
3168 if (ret == -ENODEV)
3169 break;
3170 }
3171 uclass_foreach_dev(dev, uc) {
3172 ret = device_probe(dev);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003173 if (ret)
Simon Glass367e3852024-08-22 07:54:55 -06003174 log_err("%s - probe failed: %d\n", dev->name, ret);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003175 }
3176
3177 return 0;
3178}
3179#else
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003180static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003181{
3182 if (board_mmc_init(bis) < 0)
3183 cpu_mmc_init(bis);
3184
3185 return 0;
3186}
3187#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003188
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003189int mmc_initialize(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003190{
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003191 static int initialized = 0;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003192 int ret;
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003193 if (initialized) /* Avoid initializing mmc multiple times */
3194 return 0;
3195 initialized = 1;
3196
Simon Glass5f4bd8c2017-07-04 13:31:19 -06003197#if !CONFIG_IS_ENABLED(BLK)
Marek Vasutf537e392016-12-01 02:06:33 +01003198#if !CONFIG_IS_ENABLED(MMC_TINY)
Simon Glasse5db1152016-05-01 13:52:35 -06003199 mmc_list_init();
3200#endif
Marek Vasutf537e392016-12-01 02:06:33 +01003201#endif
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003202 ret = mmc_probe(bis);
3203 if (ret)
3204 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05003205
Simon Glass7ec24132024-09-29 19:49:48 -06003206#ifndef CONFIG_XPL_BUILD
Andy Flemingad347bb2008-10-30 16:41:01 -05003207 print_mmc_devices(',');
Ying Zhang9ff70262013-08-16 15:16:11 +08003208#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05003209
Simon Glasse5db1152016-05-01 13:52:35 -06003210 mmc_do_preinit();
Andy Flemingad347bb2008-10-30 16:41:01 -05003211 return 0;
3212}
Tomas Melinc17dae52016-11-25 11:01:03 +02003213
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303214#if CONFIG_IS_ENABLED(DM_MMC)
3215int mmc_init_device(int num)
3216{
3217 struct udevice *dev;
3218 struct mmc *m;
3219 int ret;
3220
Aswath Govindraju57e2ccb2021-03-25 12:48:47 +05303221 if (uclass_get_device_by_seq(UCLASS_MMC, num, &dev)) {
3222 ret = uclass_get_device(UCLASS_MMC, num, &dev);
3223 if (ret)
Simon Glass9c3e9262024-09-20 09:24:38 +02003224 return log_msg_ret("ini", ret);
Aswath Govindraju57e2ccb2021-03-25 12:48:47 +05303225 }
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303226
3227 m = mmc_get_mmc_dev(dev);
3228 if (!m)
3229 return 0;
Venkatesh Yadav Abbarapu6738fcb2022-09-29 10:22:49 +05303230
3231 /* Initialising user set speed mode */
3232 m->user_speed_mode = MMC_MODES_END;
3233
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303234 if (m->preinit)
3235 mmc_start_init(m);
3236
3237 return 0;
3238}
3239#endif
3240
Tomas Melinc17dae52016-11-25 11:01:03 +02003241#ifdef CONFIG_CMD_BKOPS_ENABLE
Marek Vasutefdeed62023-01-05 15:19:08 +01003242int mmc_set_bkops_enable(struct mmc *mmc, bool autobkops, bool enable)
Tomas Melinc17dae52016-11-25 11:01:03 +02003243{
3244 int err;
Marek Vasutefdeed62023-01-05 15:19:08 +01003245 u32 bit = autobkops ? BIT(1) : BIT(0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003246 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
3247
3248 err = mmc_send_ext_csd(mmc, ext_csd);
3249 if (err) {
3250 puts("Could not get ext_csd register values\n");
3251 return err;
3252 }
3253
3254 if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) {
3255 puts("Background operations not supported on device\n");
3256 return -EMEDIUMTYPE;
3257 }
3258
Marek Vasutefdeed62023-01-05 15:19:08 +01003259 if (enable && (ext_csd[EXT_CSD_BKOPS_EN] & bit)) {
Tomas Melinc17dae52016-11-25 11:01:03 +02003260 puts("Background operations already enabled\n");
3261 return 0;
3262 }
3263
Marek Vasutefdeed62023-01-05 15:19:08 +01003264 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN,
3265 enable ? bit : 0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003266 if (err) {
Marek Vasutefdeed62023-01-05 15:19:08 +01003267 printf("Failed to %sable manual background operations\n",
3268 enable ? "en" : "dis");
Tomas Melinc17dae52016-11-25 11:01:03 +02003269 return err;
3270 }
3271
Marek Vasutefdeed62023-01-05 15:19:08 +01003272 printf("%sabled %s background operations\n",
3273 enable ? "En" : "Dis", autobkops ? "auto" : "manual");
Tomas Melinc17dae52016-11-25 11:01:03 +02003274
3275 return 0;
3276}
3277#endif
David Woodhouse49fee032020-08-04 10:05:46 +01003278
3279__weak int mmc_get_env_dev(void)
3280{
Marek Vasut30cf71d2025-06-09 21:26:39 +02003281#ifdef CONFIG_ENV_MMC_DEVICE_INDEX
3282 return CONFIG_ENV_MMC_DEVICE_INDEX;
David Woodhouse49fee032020-08-04 10:05:46 +01003283#else
3284 return 0;
3285#endif
3286}