blob: cf8277cbed863ef3882f7abf10aa6bd66662074f [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Andy Flemingad347bb2008-10-30 16:41:01 -05002/*
3 * Copyright 2008, Freescale Semiconductor, Inc
Yangbo Luf9049b22020-06-17 18:08:58 +08004 * Copyright 2020 NXP
Andy Flemingad347bb2008-10-30 16:41:01 -05005 * Andy Fleming
6 *
7 * Based vaguely on the Linux code
Andy Flemingad347bb2008-10-30 16:41:01 -05008 */
9
10#include <config.h>
Simon Glass655306c2020-05-10 11:39:58 -060011#include <blk.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050012#include <command.h>
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -060013#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060014#include <log.h>
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -060015#include <dm/device-internal.h>
Stephen Warrenbf0c7852014-05-23 12:47:06 -060016#include <errno.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050017#include <mmc.h>
18#include <part.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060019#include <time.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060020#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060021#include <linux/delay.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060022#include <linux/printk.h>
Peng Fan15305962016-10-11 15:08:43 +080023#include <power/regulator.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050024#include <malloc.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060025#include <memalign.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050026#include <linux/list.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060027#include <linux/printk.h>
Rabin Vincent69d4e2c2009-04-05 13:30:54 +053028#include <div64.h>
Paul Burton8d30cc92013-09-09 15:30:26 +010029#include "mmc_private.h"
Andy Flemingad347bb2008-10-30 16:41:01 -050030
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +020031#define DEFAULT_CMD6_TIMEOUT_MS 500
32
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +020033static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
Marek Vasutf537e392016-12-01 02:06:33 +010034
Simon Glasseba48f92017-07-29 11:35:31 -060035#if !CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020036
Sam Protsenkodb174c62019-08-14 22:52:51 +030037static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020038{
Loic Poulain9c32f4f2022-05-26 16:37:21 +020039 if (mmc->cfg->ops->wait_dat0)
40 return mmc->cfg->ops->wait_dat0(mmc, state, timeout_us);
41
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020042 return -ENOSYS;
43}
44
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +020045__weak int board_mmc_getwp(struct mmc *mmc)
Nikita Kiryanov020f2612012-12-03 02:19:46 +000046{
47 return -1;
48}
49
50int mmc_getwp(struct mmc *mmc)
51{
52 int wp;
53
54 wp = board_mmc_getwp(mmc);
55
Peter Korsgaardf7b15102013-03-21 04:00:03 +000056 if (wp < 0) {
Pantelis Antoniou2c850462014-03-11 19:34:20 +020057 if (mmc->cfg->ops->getwp)
58 wp = mmc->cfg->ops->getwp(mmc);
Peter Korsgaardf7b15102013-03-21 04:00:03 +000059 else
60 wp = 0;
61 }
Nikita Kiryanov020f2612012-12-03 02:19:46 +000062
63 return wp;
64}
65
Jeroen Hofstee47726302014-07-10 22:46:28 +020066__weak int board_mmc_getcd(struct mmc *mmc)
67{
Stefano Babic6e00edf2010-02-05 15:04:43 +010068 return -1;
69}
Simon Glass394dfc02016-06-12 23:30:22 -060070#endif
Stefano Babic6e00edf2010-02-05 15:04:43 +010071
Simon Glassb23d96e2016-06-12 23:30:20 -060072#ifdef CONFIG_MMC_TRACE
73void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
Andy Flemingad347bb2008-10-30 16:41:01 -050074{
Simon Glassb23d96e2016-06-12 23:30:20 -060075 printf("CMD_SEND:%d\n", cmd->cmdidx);
Marek Vasut6eeee302019-03-23 18:54:45 +010076 printf("\t\tARG\t\t\t 0x%08x\n", cmd->cmdarg);
Simon Glassb23d96e2016-06-12 23:30:20 -060077}
Marek Vasutdccb6082012-03-15 18:41:35 +000078
Simon Glassb23d96e2016-06-12 23:30:20 -060079void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret)
80{
Raffaele Recalcati894b1e22011-03-11 02:01:14 +000081 int i;
82 u8 *ptr;
83
Bin Meng8d1ad1e2016-03-17 21:53:14 -070084 if (ret) {
85 printf("\t\tRET\t\t\t %d\n", ret);
86 } else {
87 switch (cmd->resp_type) {
88 case MMC_RSP_NONE:
89 printf("\t\tMMC_RSP_NONE\n");
90 break;
91 case MMC_RSP_R1:
Marek Vasut6eeee302019-03-23 18:54:45 +010092 printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -070093 cmd->response[0]);
94 break;
95 case MMC_RSP_R1b:
Marek Vasut6eeee302019-03-23 18:54:45 +010096 printf("\t\tMMC_RSP_R1b\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -070097 cmd->response[0]);
98 break;
99 case MMC_RSP_R2:
Marek Vasut6eeee302019-03-23 18:54:45 +0100100 printf("\t\tMMC_RSP_R2\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700101 cmd->response[0]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100102 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700103 cmd->response[1]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100104 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700105 cmd->response[2]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100106 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700107 cmd->response[3]);
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000108 printf("\n");
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700109 printf("\t\t\t\t\tDUMPING DATA\n");
110 for (i = 0; i < 4; i++) {
111 int j;
112 printf("\t\t\t\t\t%03d - ", i*4);
113 ptr = (u8 *)&cmd->response[i];
114 ptr += 3;
115 for (j = 0; j < 4; j++)
Marek Vasut6eeee302019-03-23 18:54:45 +0100116 printf("%02x ", *ptr--);
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700117 printf("\n");
118 }
119 break;
120 case MMC_RSP_R3:
Marek Vasut6eeee302019-03-23 18:54:45 +0100121 printf("\t\tMMC_RSP_R3,4\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700122 cmd->response[0]);
123 break;
124 default:
125 printf("\t\tERROR MMC rsp not supported\n");
126 break;
Bin Meng4a4ef872016-03-17 21:53:13 -0700127 }
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000128 }
Simon Glassb23d96e2016-06-12 23:30:20 -0600129}
130
131void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
132{
133 int status;
134
135 status = (cmd->response[0] & MMC_STATUS_CURR_STATE) >> 9;
136 printf("CURR STATE:%d\n", status);
137}
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000138#endif
Simon Glassb23d96e2016-06-12 23:30:20 -0600139
Pali Rohár377ecee2022-04-03 00:20:10 +0200140#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG) || CONFIG_VAL(LOGLEVEL) >= LOGL_DEBUG
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200141const char *mmc_mode_name(enum bus_mode mode)
142{
143 static const char *const names[] = {
144 [MMC_LEGACY] = "MMC legacy",
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200145 [MMC_HS] = "MMC High Speed (26MHz)",
146 [SD_HS] = "SD High Speed (50MHz)",
147 [UHS_SDR12] = "UHS SDR12 (25MHz)",
148 [UHS_SDR25] = "UHS SDR25 (50MHz)",
149 [UHS_SDR50] = "UHS SDR50 (100MHz)",
150 [UHS_SDR104] = "UHS SDR104 (208MHz)",
151 [UHS_DDR50] = "UHS DDR50 (50MHz)",
152 [MMC_HS_52] = "MMC High Speed (52MHz)",
153 [MMC_DDR_52] = "MMC DDR52 (52MHz)",
154 [MMC_HS_200] = "HS200 (200MHz)",
Peng Fan46801252018-08-10 14:07:54 +0800155 [MMC_HS_400] = "HS400 (200MHz)",
Peng Faneede83b2019-07-10 14:43:07 +0800156 [MMC_HS_400_ES] = "HS400ES (200MHz)",
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200157 };
158
159 if (mode >= MMC_MODES_END)
160 return "Unknown mode";
161 else
162 return names[mode];
163}
164#endif
165
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200166static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
167{
168 static const int freqs[] = {
Jaehoon Chung7c5c7302018-01-30 14:10:16 +0900169 [MMC_LEGACY] = 25000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200170 [MMC_HS] = 26000000,
171 [SD_HS] = 50000000,
Jaehoon Chung7c5c7302018-01-30 14:10:16 +0900172 [MMC_HS_52] = 52000000,
173 [MMC_DDR_52] = 52000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200174 [UHS_SDR12] = 25000000,
175 [UHS_SDR25] = 50000000,
176 [UHS_SDR50] = 100000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200177 [UHS_DDR50] = 50000000,
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100178 [UHS_SDR104] = 208000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200179 [MMC_HS_200] = 200000000,
Peng Fan46801252018-08-10 14:07:54 +0800180 [MMC_HS_400] = 200000000,
Peng Faneede83b2019-07-10 14:43:07 +0800181 [MMC_HS_400_ES] = 200000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200182 };
183
184 if (mode == MMC_LEGACY)
185 return mmc->legacy_speed;
186 else if (mode >= MMC_MODES_END)
187 return 0;
188 else
189 return freqs[mode];
190}
191
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200192static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
193{
194 mmc->selected_mode = mode;
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200195 mmc->tran_speed = mmc_mode2freq(mmc, mode);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200196 mmc->ddr_mode = mmc_is_mode_ddr(mode);
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900197 pr_debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
198 mmc->tran_speed / 1000000);
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200199 return 0;
200}
201
Simon Glasseba48f92017-07-29 11:35:31 -0600202#if !CONFIG_IS_ENABLED(DM_MMC)
Simon Glassb23d96e2016-06-12 23:30:20 -0600203int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
204{
205 int ret;
206
207 mmmc_trace_before_send(mmc, cmd);
208 ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
209 mmmc_trace_after_send(mmc, cmd, ret);
210
Marek Vasutdccb6082012-03-15 18:41:35 +0000211 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -0500212}
Simon Glass394dfc02016-06-12 23:30:22 -0600213#endif
Andy Flemingad347bb2008-10-30 16:41:01 -0500214
Sean Anderson86325092020-10-17 08:36:27 -0400215/**
216 * mmc_send_cmd_retry() - send a command to the mmc device, retrying on error
217 *
218 * @dev: device to receive the command
219 * @cmd: command to send
220 * @data: additional data to send/receive
221 * @retries: how many times to retry; mmc_send_cmd is always called at least
222 * once
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100223 * Return: 0 if ok, -ve on error
Sean Anderson86325092020-10-17 08:36:27 -0400224 */
225static int mmc_send_cmd_retry(struct mmc *mmc, struct mmc_cmd *cmd,
226 struct mmc_data *data, uint retries)
227{
228 int ret;
229
230 do {
231 ret = mmc_send_cmd(mmc, cmd, data);
232 } while (ret && retries--);
233
234 return ret;
235}
236
237/**
238 * mmc_send_cmd_quirks() - send a command to the mmc device, retrying if a
239 * specific quirk is enabled
240 *
241 * @dev: device to receive the command
242 * @cmd: command to send
243 * @data: additional data to send/receive
244 * @quirk: retry only if this quirk is enabled
245 * @retries: how many times to retry; mmc_send_cmd is always called at least
246 * once
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100247 * Return: 0 if ok, -ve on error
Sean Anderson86325092020-10-17 08:36:27 -0400248 */
249static int mmc_send_cmd_quirks(struct mmc *mmc, struct mmc_cmd *cmd,
250 struct mmc_data *data, u32 quirk, uint retries)
251{
Simon Glass68f3ced2023-02-05 15:40:16 -0700252 if (IS_ENABLED(CONFIG_MMC_QUIRKS) && mmc->quirks & quirk)
Sean Anderson86325092020-10-17 08:36:27 -0400253 return mmc_send_cmd_retry(mmc, cmd, data, retries);
254 else
255 return mmc_send_cmd(mmc, cmd, data);
256}
257
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200258int mmc_send_status(struct mmc *mmc, unsigned int *status)
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000259{
260 struct mmc_cmd cmd;
Sean Anderson86325092020-10-17 08:36:27 -0400261 int ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000262
263 cmd.cmdidx = MMC_CMD_SEND_STATUS;
264 cmd.resp_type = MMC_RSP_R1;
Marek Vasutc4427392011-08-10 09:24:48 +0200265 if (!mmc_host_is_spi(mmc))
266 cmd.cmdarg = mmc->rca << 16;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000267
Sean Anderson86325092020-10-17 08:36:27 -0400268 ret = mmc_send_cmd_retry(mmc, &cmd, NULL, 4);
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200269 mmc_trace_state(mmc, &cmd);
Sean Anderson86325092020-10-17 08:36:27 -0400270 if (!ret)
271 *status = cmd.response[0];
272
273 return ret;
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200274}
275
Sam Protsenkodb174c62019-08-14 22:52:51 +0300276int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200277{
278 unsigned int status;
279 int err;
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +0200280
Sam Protsenkodb174c62019-08-14 22:52:51 +0300281 err = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
Jean-Jacques Hiblot4f04a322019-07-02 10:53:53 +0200282 if (err != -ENOSYS)
283 return err;
284
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200285 while (1) {
286 err = mmc_send_status(mmc, &status);
287 if (err)
288 return err;
289
290 if ((status & MMC_STATUS_RDY_FOR_DATA) &&
291 (status & MMC_STATUS_CURR_STATE) !=
292 MMC_STATE_PRG)
293 break;
294
295 if (status & MMC_STATUS_MASK) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100296#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200297 pr_err("Status Error: 0x%08x\n", status);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100298#endif
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200299 return -ECOMM;
300 }
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000301
Sam Protsenkodb174c62019-08-14 22:52:51 +0300302 if (timeout_ms-- <= 0)
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500303 break;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000304
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500305 udelay(1000);
306 }
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000307
Sam Protsenkodb174c62019-08-14 22:52:51 +0300308 if (timeout_ms <= 0) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100309#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +0100310 pr_err("Timeout waiting card ready\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100311#endif
Jaehoon Chung7825d202016-07-19 16:33:36 +0900312 return -ETIMEDOUT;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000313 }
314
315 return 0;
316}
317
Paul Burton8d30cc92013-09-09 15:30:26 +0100318int mmc_set_blocklen(struct mmc *mmc, int len)
Andy Flemingad347bb2008-10-30 16:41:01 -0500319{
320 struct mmc_cmd cmd;
321
Andrew Gabbasov9fc2a412014-12-01 06:59:09 -0600322 if (mmc->ddr_mode)
Jaehoon Chung38ce30b2014-05-16 13:59:54 +0900323 return 0;
324
Andy Flemingad347bb2008-10-30 16:41:01 -0500325 cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
326 cmd.resp_type = MMC_RSP_R1;
327 cmd.cmdarg = len;
Andy Flemingad347bb2008-10-30 16:41:01 -0500328
Sean Anderson86325092020-10-17 08:36:27 -0400329 return mmc_send_cmd_quirks(mmc, &cmd, NULL,
330 MMC_QUIRK_RETRY_SET_BLOCKLEN, 4);
Andy Flemingad347bb2008-10-30 16:41:01 -0500331}
332
Tom Rinidec7ea02024-05-20 13:35:03 -0600333#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200334static const u8 tuning_blk_pattern_4bit[] = {
335 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
336 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
337 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
338 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
339 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
340 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
341 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
342 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
343};
344
345static const u8 tuning_blk_pattern_8bit[] = {
346 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
347 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
348 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
349 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
350 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
351 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
352 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
353 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
354 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
355 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
356 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
357 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
358 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
359 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
360 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
361 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
362};
363
Marek Vasutdad81fb2024-02-20 09:36:23 +0100364int mmc_send_tuning(struct mmc *mmc, u32 opcode)
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200365{
366 struct mmc_cmd cmd;
367 struct mmc_data data;
368 const u8 *tuning_block_pattern;
369 int size, err;
370
371 if (mmc->bus_width == 8) {
372 tuning_block_pattern = tuning_blk_pattern_8bit;
373 size = sizeof(tuning_blk_pattern_8bit);
374 } else if (mmc->bus_width == 4) {
375 tuning_block_pattern = tuning_blk_pattern_4bit;
376 size = sizeof(tuning_blk_pattern_4bit);
377 } else {
378 return -EINVAL;
379 }
380
381 ALLOC_CACHE_ALIGN_BUFFER(u8, data_buf, size);
382
383 cmd.cmdidx = opcode;
384 cmd.cmdarg = 0;
385 cmd.resp_type = MMC_RSP_R1;
386
387 data.dest = (void *)data_buf;
388 data.blocks = 1;
389 data.blocksize = size;
390 data.flags = MMC_DATA_READ;
391
392 err = mmc_send_cmd(mmc, &cmd, &data);
393 if (err)
394 return err;
395
396 if (memcmp(data_buf, tuning_block_pattern, size))
397 return -EIO;
398
399 return 0;
400}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100401#endif
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200402
Hai Pham27abf9f2023-06-20 00:38:24 +0200403int mmc_send_stop_transmission(struct mmc *mmc, bool write)
404{
405 struct mmc_cmd cmd;
406
407 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
408 cmd.cmdarg = 0;
409 /*
410 * JEDEC Standard No. 84-B51 Page 126
411 * CMD12 STOP_TRANSMISSION R1/R1b[3]
412 * NOTE 3 R1 for read cases and R1b for write cases.
413 *
414 * Physical Layer Simplified Specification Version 9.00
415 * 7.3.1.3 Detailed Command Description
416 * CMD12 R1b
417 */
418 cmd.resp_type = (IS_SD(mmc) || write) ? MMC_RSP_R1b : MMC_RSP_R1;
419
420 return mmc_send_cmd(mmc, &cmd, NULL);
421}
422
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200423static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
Kim Phillips87ea3892012-10-29 13:34:43 +0000424 lbaint_t blkcnt)
Andy Flemingad347bb2008-10-30 16:41:01 -0500425{
426 struct mmc_cmd cmd;
427 struct mmc_data data;
428
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700429 if (blkcnt > 1)
430 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
431 else
432 cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
Andy Flemingad347bb2008-10-30 16:41:01 -0500433
434 if (mmc->high_capacity)
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700435 cmd.cmdarg = start;
Andy Flemingad347bb2008-10-30 16:41:01 -0500436 else
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700437 cmd.cmdarg = start * mmc->read_bl_len;
Andy Flemingad347bb2008-10-30 16:41:01 -0500438
439 cmd.resp_type = MMC_RSP_R1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500440
441 data.dest = dst;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700442 data.blocks = blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500443 data.blocksize = mmc->read_bl_len;
444 data.flags = MMC_DATA_READ;
445
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700446 if (mmc_send_cmd(mmc, &cmd, &data))
447 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500448
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700449 if (blkcnt > 1) {
Hai Pham27abf9f2023-06-20 00:38:24 +0200450 if (mmc_send_stop_transmission(mmc, false)) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100451#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +0100452 pr_err("mmc fail to send stop cmd\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100453#endif
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700454 return 0;
455 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500456 }
457
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700458 return blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500459}
460
Marek Vasut31976d92020-04-04 12:45:05 +0200461#if !CONFIG_IS_ENABLED(DM_MMC)
462static int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
463{
464 if (mmc->cfg->ops->get_b_max)
465 return mmc->cfg->ops->get_b_max(mmc, dst, blkcnt);
466 else
467 return mmc->cfg->b_max;
468}
469#endif
470
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600471#if CONFIG_IS_ENABLED(BLK)
Simon Glass62e293a2016-06-12 23:30:15 -0600472ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
Simon Glass59bc6f22016-05-01 13:52:41 -0600473#else
Simon Glass62e293a2016-06-12 23:30:15 -0600474ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
475 void *dst)
Simon Glass59bc6f22016-05-01 13:52:41 -0600476#endif
Andy Flemingad347bb2008-10-30 16:41:01 -0500477{
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600478#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -0700479 struct blk_desc *block_dev = dev_get_uclass_plat(dev);
Simon Glass59bc6f22016-05-01 13:52:41 -0600480#endif
Simon Glass2f26fff2016-02-29 15:25:51 -0700481 int dev_num = block_dev->devnum;
Stephen Warren1e0f92a2015-12-07 11:38:49 -0700482 int err;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700483 lbaint_t cur, blocks_todo = blkcnt;
Marek Vasut31976d92020-04-04 12:45:05 +0200484 uint b_max;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700485
486 if (blkcnt == 0)
487 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500488
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700489 struct mmc *mmc = find_mmc_device(dev_num);
Andy Flemingad347bb2008-10-30 16:41:01 -0500490 if (!mmc)
491 return 0;
492
Marek Vasutf537e392016-12-01 02:06:33 +0100493 if (CONFIG_IS_ENABLED(MMC_TINY))
494 err = mmc_switch_part(mmc, block_dev->hwpart);
495 else
496 err = blk_dselect_hwpart(block_dev, block_dev->hwpart);
497
Stephen Warren1e0f92a2015-12-07 11:38:49 -0700498 if (err < 0)
499 return 0;
500
Simon Glasse5db1152016-05-01 13:52:35 -0600501 if ((start + blkcnt) > block_dev->lba) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100502#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +0100503 pr_err("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
504 start + blkcnt, block_dev->lba);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100505#endif
Lei Wene1cc9c82010-09-13 22:07:27 +0800506 return 0;
507 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500508
Simon Glassa4343c42015-06-23 15:38:50 -0600509 if (mmc_set_blocklen(mmc, mmc->read_bl_len)) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900510 pr_debug("%s: Failed to set blocklen\n", __func__);
Andy Flemingad347bb2008-10-30 16:41:01 -0500511 return 0;
Simon Glassa4343c42015-06-23 15:38:50 -0600512 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500513
Marek Vasut31976d92020-04-04 12:45:05 +0200514 b_max = mmc_get_b_max(mmc, dst, blkcnt);
515
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700516 do {
Marek Vasut31976d92020-04-04 12:45:05 +0200517 cur = (blocks_todo > b_max) ? b_max : blocks_todo;
Simon Glassa4343c42015-06-23 15:38:50 -0600518 if (mmc_read_blocks(mmc, dst, start, cur) != cur) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900519 pr_debug("%s: Failed to read blocks\n", __func__);
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700520 return 0;
Simon Glassa4343c42015-06-23 15:38:50 -0600521 }
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700522 blocks_todo -= cur;
523 start += cur;
524 dst += cur * mmc->read_bl_len;
525 } while (blocks_todo > 0);
Andy Flemingad347bb2008-10-30 16:41:01 -0500526
527 return blkcnt;
528}
529
Kim Phillips87ea3892012-10-29 13:34:43 +0000530static int mmc_go_idle(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -0500531{
532 struct mmc_cmd cmd;
533 int err;
534
535 udelay(1000);
536
537 cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
538 cmd.cmdarg = 0;
539 cmd.resp_type = MMC_RSP_NONE;
Andy Flemingad347bb2008-10-30 16:41:01 -0500540
541 err = mmc_send_cmd(mmc, &cmd, NULL);
542
543 if (err)
544 return err;
545
546 udelay(2000);
547
548 return 0;
549}
550
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100551#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200552static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
553{
554 struct mmc_cmd cmd;
555 int err = 0;
556
557 /*
558 * Send CMD11 only if the request is to switch the card to
559 * 1.8V signalling.
560 */
561 if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
562 return mmc_set_signal_voltage(mmc, signal_voltage);
563
564 cmd.cmdidx = SD_CMD_SWITCH_UHS18V;
565 cmd.cmdarg = 0;
566 cmd.resp_type = MMC_RSP_R1;
567
568 err = mmc_send_cmd(mmc, &cmd, NULL);
569 if (err)
570 return err;
571
572 if (!mmc_host_is_spi(mmc) && (cmd.response[0] & MMC_STATUS_ERROR))
573 return -EIO;
574
575 /*
576 * The card should drive cmd and dat[0:3] low immediately
577 * after the response of cmd11, but wait 100 us to be sure
578 */
579 err = mmc_wait_dat0(mmc, 0, 100);
580 if (err == -ENOSYS)
581 udelay(100);
582 else if (err)
583 return -ETIMEDOUT;
584
585 /*
586 * During a signal voltage level switch, the clock must be gated
587 * for 5 ms according to the SD spec
588 */
Jaehoon Chung239cb2f2018-01-26 19:25:29 +0900589 mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200590
591 err = mmc_set_signal_voltage(mmc, signal_voltage);
592 if (err)
593 return err;
594
595 /* Keep clock gated for at least 10 ms, though spec only says 5 ms */
596 mdelay(10);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +0900597 mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200598
599 /*
600 * Failure to switch is indicated by the card holding
601 * dat[0:3] low. Wait for at least 1 ms according to spec
602 */
603 err = mmc_wait_dat0(mmc, 1, 1000);
604 if (err == -ENOSYS)
605 udelay(1000);
606 else if (err)
607 return -ETIMEDOUT;
608
609 return 0;
610}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100611#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200612
613static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
Andy Flemingad347bb2008-10-30 16:41:01 -0500614{
615 int timeout = 1000;
616 int err;
617 struct mmc_cmd cmd;
618
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500619 while (1) {
Andy Flemingad347bb2008-10-30 16:41:01 -0500620 cmd.cmdidx = MMC_CMD_APP_CMD;
621 cmd.resp_type = MMC_RSP_R1;
622 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500623
624 err = mmc_send_cmd(mmc, &cmd, NULL);
625
626 if (err)
627 return err;
628
629 cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
630 cmd.resp_type = MMC_RSP_R3;
Stefano Babicf8e9a212010-01-20 18:20:39 +0100631
632 /*
633 * Most cards do not answer if some reserved bits
634 * in the ocr are set. However, Some controller
635 * can set bit 7 (reserved for low voltages), but
636 * how to manage low voltages SD card is not yet
637 * specified.
638 */
Thomas Chou1254c3d2010-12-24 13:12:21 +0000639 cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200640 (mmc->cfg->voltages & 0xff8000);
Andy Flemingad347bb2008-10-30 16:41:01 -0500641
642 if (mmc->version == SD_VERSION_2)
643 cmd.cmdarg |= OCR_HCS;
644
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200645 if (uhs_en)
646 cmd.cmdarg |= OCR_S18R;
647
Andy Flemingad347bb2008-10-30 16:41:01 -0500648 err = mmc_send_cmd(mmc, &cmd, NULL);
649
650 if (err)
651 return err;
652
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500653 if (cmd.response[0] & OCR_BUSY)
654 break;
Andy Flemingad347bb2008-10-30 16:41:01 -0500655
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500656 if (timeout-- <= 0)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900657 return -EOPNOTSUPP;
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500658
659 udelay(1000);
660 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500661
662 if (mmc->version != SD_VERSION_2)
663 mmc->version = SD_VERSION_1_0;
664
Thomas Chou1254c3d2010-12-24 13:12:21 +0000665 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
666 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
667 cmd.resp_type = MMC_RSP_R3;
668 cmd.cmdarg = 0;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000669
670 err = mmc_send_cmd(mmc, &cmd, NULL);
671
672 if (err)
673 return err;
674 }
675
Rabin Vincentb6eed942009-04-05 13:30:56 +0530676 mmc->ocr = cmd.response[0];
Andy Flemingad347bb2008-10-30 16:41:01 -0500677
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100678#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200679 if (uhs_en && !(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)
680 == 0x41000000) {
681 err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
682 if (err)
683 return err;
684 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100685#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200686
Andy Flemingad347bb2008-10-30 16:41:01 -0500687 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
688 mmc->rca = 0;
689
690 return 0;
691}
692
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500693static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg)
Andy Flemingad347bb2008-10-30 16:41:01 -0500694{
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500695 struct mmc_cmd cmd;
Andy Flemingad347bb2008-10-30 16:41:01 -0500696 int err;
697
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500698 cmd.cmdidx = MMC_CMD_SEND_OP_COND;
699 cmd.resp_type = MMC_RSP_R3;
700 cmd.cmdarg = 0;
Rob Herring5fd3edd2015-03-23 17:56:59 -0500701 if (use_arg && !mmc_host_is_spi(mmc))
702 cmd.cmdarg = OCR_HCS |
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200703 (mmc->cfg->voltages &
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500704 (mmc->ocr & OCR_VOLTAGE_MASK)) |
705 (mmc->ocr & OCR_ACCESS_MODE);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000706
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500707 err = mmc_send_cmd(mmc, &cmd, NULL);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000708 if (err)
709 return err;
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500710 mmc->ocr = cmd.response[0];
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000711 return 0;
712}
713
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +0200714static int mmc_send_op_cond(struct mmc *mmc)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000715{
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000716 int err, i;
Haibo Chen71949512020-06-15 17:18:12 +0800717 int timeout = 1000;
718 uint start;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000719
Andy Flemingad347bb2008-10-30 16:41:01 -0500720 /* Some cards seem to need this */
721 mmc_go_idle(mmc);
722
Haibo Chen71949512020-06-15 17:18:12 +0800723 start = get_timer(0);
Wolfgang Denk62fb2b42021-09-27 17:42:39 +0200724 /* Asking to the card its capabilities */
Haibo Chen71949512020-06-15 17:18:12 +0800725 for (i = 0; ; i++) {
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500726 err = mmc_send_op_cond_iter(mmc, i != 0);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000727 if (err)
728 return err;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200729
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000730 /* exit if not busy (flag seems to be inverted) */
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500731 if (mmc->ocr & OCR_BUSY)
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -0500732 break;
Haibo Chen71949512020-06-15 17:18:12 +0800733
734 if (get_timer(start) > timeout)
735 return -ETIMEDOUT;
736 udelay(100);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000737 }
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -0500738 mmc->op_cond_pending = 1;
739 return 0;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000740}
Wolfgang Denk80f70212011-05-19 22:21:41 +0200741
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +0200742static int mmc_complete_op_cond(struct mmc *mmc)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000743{
744 struct mmc_cmd cmd;
745 int timeout = 1000;
Vipul Kumardbad7b42018-05-03 12:20:54 +0530746 ulong start;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000747 int err;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200748
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000749 mmc->op_cond_pending = 0;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500750 if (!(mmc->ocr & OCR_BUSY)) {
Yangbo Lu9c720612016-08-02 15:33:18 +0800751 /* Some cards seem to need this */
752 mmc_go_idle(mmc);
753
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500754 start = get_timer(0);
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500755 while (1) {
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500756 err = mmc_send_op_cond_iter(mmc, 1);
757 if (err)
758 return err;
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500759 if (mmc->ocr & OCR_BUSY)
760 break;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500761 if (get_timer(start) > timeout)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900762 return -EOPNOTSUPP;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500763 udelay(100);
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500764 }
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500765 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500766
Thomas Chou1254c3d2010-12-24 13:12:21 +0000767 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
768 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
769 cmd.resp_type = MMC_RSP_R3;
770 cmd.cmdarg = 0;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000771
772 err = mmc_send_cmd(mmc, &cmd, NULL);
773
774 if (err)
775 return err;
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500776
777 mmc->ocr = cmd.response[0];
Thomas Chou1254c3d2010-12-24 13:12:21 +0000778 }
779
Andy Flemingad347bb2008-10-30 16:41:01 -0500780 mmc->version = MMC_VERSION_UNKNOWN;
Andy Flemingad347bb2008-10-30 16:41:01 -0500781
782 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
Stephen Warrenf6545f12014-01-30 16:11:12 -0700783 mmc->rca = 1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500784
785 return 0;
786}
787
Heinrich Schuchardtbf230e12020-03-30 07:24:17 +0200788int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
Andy Flemingad347bb2008-10-30 16:41:01 -0500789{
790 struct mmc_cmd cmd;
791 struct mmc_data data;
792 int err;
793
794 /* Get the Card Status Register */
795 cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
796 cmd.resp_type = MMC_RSP_R1;
797 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500798
Yoshihiro Shimodaf6bec732012-06-07 19:09:11 +0000799 data.dest = (char *)ext_csd;
Andy Flemingad347bb2008-10-30 16:41:01 -0500800 data.blocks = 1;
Simon Glassa09c2b72013-04-03 08:54:30 +0000801 data.blocksize = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -0500802 data.flags = MMC_DATA_READ;
803
804 err = mmc_send_cmd(mmc, &cmd, &data);
805
806 return err;
807}
808
Marek Vasut8a966472019-02-06 11:34:27 +0100809static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
810 bool send_status)
Andy Flemingad347bb2008-10-30 16:41:01 -0500811{
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200812 unsigned int status, start;
Andy Flemingad347bb2008-10-30 16:41:01 -0500813 struct mmc_cmd cmd;
Sam Protsenkodb174c62019-08-14 22:52:51 +0300814 int timeout_ms = DEFAULT_CMD6_TIMEOUT_MS;
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +0200815 bool is_part_switch = (set == EXT_CSD_CMD_SET_NORMAL) &&
816 (index == EXT_CSD_PART_CONF);
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000817 int ret;
Andy Flemingad347bb2008-10-30 16:41:01 -0500818
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +0200819 if (mmc->gen_cmd6_time)
Sam Protsenkodb174c62019-08-14 22:52:51 +0300820 timeout_ms = mmc->gen_cmd6_time * 10;
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +0200821
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +0200822 if (is_part_switch && mmc->part_switch_time)
Sam Protsenkodb174c62019-08-14 22:52:51 +0300823 timeout_ms = mmc->part_switch_time * 10;
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +0200824
Andy Flemingad347bb2008-10-30 16:41:01 -0500825 cmd.cmdidx = MMC_CMD_SWITCH;
826 cmd.resp_type = MMC_RSP_R1b;
827 cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000828 (index << 16) |
829 (value << 8);
Andy Flemingad347bb2008-10-30 16:41:01 -0500830
Sean Anderson86325092020-10-17 08:36:27 -0400831 ret = mmc_send_cmd_retry(mmc, &cmd, NULL, 3);
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200832 if (ret)
833 return ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000834
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200835 start = get_timer(0);
Marek Vasut8a966472019-02-06 11:34:27 +0100836
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200837 /* poll dat0 for rdy/buys status */
Sam Protsenkodb174c62019-08-14 22:52:51 +0300838 ret = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200839 if (ret && ret != -ENOSYS)
840 return ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000841
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200842 /*
Kirill Kapranovcd9ea642021-10-09 23:49:59 +0300843 * In cases when neiter allowed to poll by using CMD13 nor we are
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200844 * capable of polling by using mmc_wait_dat0, then rely on waiting the
845 * stated timeout to be sufficient.
846 */
Kirill Kapranovcd9ea642021-10-09 23:49:59 +0300847 if (ret == -ENOSYS && !send_status) {
Sam Protsenkodb174c62019-08-14 22:52:51 +0300848 mdelay(timeout_ms);
Haibo Chend8de5e42020-09-22 18:11:42 +0800849 return 0;
850 }
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200851
Marek Vasut946e06f2022-07-15 01:58:24 +0200852 if (!send_status)
853 return 0;
854
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200855 /* Finally wait until the card is ready or indicates a failure
856 * to switch. It doesn't hurt to use CMD13 here even if send_status
Sam Protsenkodb174c62019-08-14 22:52:51 +0300857 * is false, because by now (after 'timeout_ms' ms) the bus should be
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200858 * reliable.
859 */
860 do {
861 ret = mmc_send_status(mmc, &status);
862
863 if (!ret && (status & MMC_STATUS_SWITCH_ERROR)) {
864 pr_debug("switch failed %d/%d/0x%x !\n", set, index,
865 value);
866 return -EIO;
867 }
Stefan Boscha463bbe2021-01-23 13:37:41 +0100868 if (!ret && (status & MMC_STATUS_RDY_FOR_DATA) &&
869 (status & MMC_STATUS_CURR_STATE) == MMC_STATE_TRANS)
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200870 return 0;
871 udelay(100);
Sam Protsenkodb174c62019-08-14 22:52:51 +0300872 } while (get_timer(start) < timeout_ms);
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000873
Jean-Jacques Hiblot5a7cf402019-07-02 10:53:56 +0200874 return -ETIMEDOUT;
Andy Flemingad347bb2008-10-30 16:41:01 -0500875}
876
Marek Vasut8a966472019-02-06 11:34:27 +0100877int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
878{
879 return __mmc_switch(mmc, set, index, value, true);
880}
881
Heinrich Schuchardt75e5a642020-03-30 07:24:19 +0200882int mmc_boot_wp(struct mmc *mmc)
883{
884 return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, 1);
885}
886
Ying-Chun Liu (PaulLiu)4493cb52022-04-25 21:59:02 +0800887int mmc_boot_wp_single_partition(struct mmc *mmc, int partition)
888{
889 u8 value;
890 int ret;
891
892 value = EXT_CSD_BOOT_WP_B_PWR_WP_EN;
893
894 if (partition == 0) {
895 value |= EXT_CSD_BOOT_WP_B_SEC_WP_SEL;
896 ret = mmc_switch(mmc,
897 EXT_CSD_CMD_SET_NORMAL,
898 EXT_CSD_BOOT_WP,
899 value);
900 } else if (partition == 1) {
901 value |= EXT_CSD_BOOT_WP_B_SEC_WP_SEL;
902 value |= EXT_CSD_BOOT_WP_B_PWR_WP_SEC_SEL;
903 ret = mmc_switch(mmc,
904 EXT_CSD_CMD_SET_NORMAL,
905 EXT_CSD_BOOT_WP,
906 value);
907 } else {
908 ret = mmc_boot_wp(mmc);
909 }
910
911 return ret;
912}
913
Marek Vasuta318a7a2018-04-15 00:37:11 +0200914#if !CONFIG_IS_ENABLED(MMC_TINY)
Marek Vasut111572f2019-01-03 21:19:24 +0100915static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode,
916 bool hsdowngrade)
Andy Flemingad347bb2008-10-30 16:41:01 -0500917{
Andy Flemingad347bb2008-10-30 16:41:01 -0500918 int err;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200919 int speed_bits;
920
921 ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
922
923 switch (mode) {
924 case MMC_HS:
925 case MMC_HS_52:
926 case MMC_DDR_52:
927 speed_bits = EXT_CSD_TIMING_HS;
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +0200928 break;
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +0100929#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +0200930 case MMC_HS_200:
931 speed_bits = EXT_CSD_TIMING_HS200;
932 break;
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +0100933#endif
Peng Fan46801252018-08-10 14:07:54 +0800934#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
935 case MMC_HS_400:
936 speed_bits = EXT_CSD_TIMING_HS400;
937 break;
938#endif
Peng Faneede83b2019-07-10 14:43:07 +0800939#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
940 case MMC_HS_400_ES:
941 speed_bits = EXT_CSD_TIMING_HS400;
942 break;
943#endif
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200944 case MMC_LEGACY:
945 speed_bits = EXT_CSD_TIMING_LEGACY;
946 break;
947 default:
948 return -EINVAL;
949 }
Marek Vasut8a966472019-02-06 11:34:27 +0100950
951 err = __mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
952 speed_bits, !hsdowngrade);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200953 if (err)
954 return err;
955
Marek Vasut111572f2019-01-03 21:19:24 +0100956#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
957 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
958 /*
959 * In case the eMMC is in HS200/HS400 mode and we are downgrading
960 * to HS mode, the card clock are still running much faster than
961 * the supported HS mode clock, so we can not reliably read out
962 * Extended CSD. Reconfigure the controller to run at HS mode.
963 */
964 if (hsdowngrade) {
965 mmc_select_mode(mmc, MMC_HS);
966 mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
967 }
968#endif
969
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200970 if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
971 /* Now check to see that it worked */
972 err = mmc_send_ext_csd(mmc, test_csd);
973 if (err)
974 return err;
975
976 /* No high-speed support */
977 if (!test_csd[EXT_CSD_HS_TIMING])
978 return -ENOTSUPP;
979 }
980
981 return 0;
982}
983
984static int mmc_get_capabilities(struct mmc *mmc)
985{
986 u8 *ext_csd = mmc->ext_csd;
987 char cardtype;
Andy Flemingad347bb2008-10-30 16:41:01 -0500988
Jean-Jacques Hiblot3f2ffc22017-11-30 17:43:56 +0100989 mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -0500990
Thomas Chou1254c3d2010-12-24 13:12:21 +0000991 if (mmc_host_is_spi(mmc))
992 return 0;
993
Andy Flemingad347bb2008-10-30 16:41:01 -0500994 /* Only version 4 supports high-speed */
995 if (mmc->version < MMC_VERSION_4)
996 return 0;
997
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200998 if (!ext_csd) {
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +0100999 pr_err("No ext_csd found!\n"); /* this should enver happen */
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001000 return -ENOTSUPP;
1001 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001002
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001003 mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
Andy Flemingad347bb2008-10-30 16:41:01 -05001004
Peng Fan46801252018-08-10 14:07:54 +08001005 cardtype = ext_csd[EXT_CSD_CARD_TYPE];
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001006 mmc->cardtype = cardtype;
Andy Flemingad347bb2008-10-30 16:41:01 -05001007
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001008#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001009 if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
1010 EXT_CSD_CARD_TYPE_HS200_1_8V)) {
1011 mmc->card_caps |= MMC_MODE_HS200;
1012 }
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001013#endif
Peng Faneede83b2019-07-10 14:43:07 +08001014#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
1015 CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
Peng Fan46801252018-08-10 14:07:54 +08001016 if (cardtype & (EXT_CSD_CARD_TYPE_HS400_1_2V |
1017 EXT_CSD_CARD_TYPE_HS400_1_8V)) {
1018 mmc->card_caps |= MMC_MODE_HS400;
1019 }
1020#endif
Jaehoon Chung38ce30b2014-05-16 13:59:54 +09001021 if (cardtype & EXT_CSD_CARD_TYPE_52) {
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001022 if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
Jaehoon Chung38ce30b2014-05-16 13:59:54 +09001023 mmc->card_caps |= MMC_MODE_DDR_52MHz;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001024 mmc->card_caps |= MMC_MODE_HS_52MHz;
Jaehoon Chung38ce30b2014-05-16 13:59:54 +09001025 }
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001026 if (cardtype & EXT_CSD_CARD_TYPE_26)
1027 mmc->card_caps |= MMC_MODE_HS;
Andy Flemingad347bb2008-10-30 16:41:01 -05001028
Peng Faneede83b2019-07-10 14:43:07 +08001029#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
1030 if (ext_csd[EXT_CSD_STROBE_SUPPORT] &&
1031 (mmc->card_caps & MMC_MODE_HS400)) {
1032 mmc->card_caps |= MMC_MODE_HS400_ES;
1033 }
1034#endif
1035
Andy Flemingad347bb2008-10-30 16:41:01 -05001036 return 0;
1037}
Marek Vasuta318a7a2018-04-15 00:37:11 +02001038#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001039
Stephen Warrene315ae82013-06-11 15:14:01 -06001040static int mmc_set_capacity(struct mmc *mmc, int part_num)
1041{
1042 switch (part_num) {
1043 case 0:
1044 mmc->capacity = mmc->capacity_user;
1045 break;
1046 case 1:
1047 case 2:
1048 mmc->capacity = mmc->capacity_boot;
1049 break;
1050 case 3:
1051 mmc->capacity = mmc->capacity_rpmb;
1052 break;
1053 case 4:
1054 case 5:
1055 case 6:
1056 case 7:
1057 mmc->capacity = mmc->capacity_gp[part_num - 4];
1058 break;
1059 default:
1060 return -1;
1061 }
1062
Simon Glasse5db1152016-05-01 13:52:35 -06001063 mmc_get_blk_desc(mmc)->lba = lldiv(mmc->capacity, mmc->read_bl_len);
Stephen Warrene315ae82013-06-11 15:14:01 -06001064
1065 return 0;
1066}
1067
Simon Glass62e293a2016-06-12 23:30:15 -06001068int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
Lei Wen31b99802011-05-02 16:26:26 +00001069{
Stephen Warrene315ae82013-06-11 15:14:01 -06001070 int ret;
Jean-Jacques Hiblotfaf5c952019-07-02 10:53:58 +02001071 int retry = 3;
Lei Wen31b99802011-05-02 16:26:26 +00001072
Jean-Jacques Hiblotfaf5c952019-07-02 10:53:58 +02001073 do {
1074 ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1075 EXT_CSD_PART_CONF,
1076 (mmc->part_config & ~PART_ACCESS_MASK)
1077 | (part_num & PART_ACCESS_MASK));
1078 } while (ret && retry--);
Peter Bigot45fde892014-09-02 18:31:23 -05001079
1080 /*
1081 * Set the capacity if the switch succeeded or was intended
1082 * to return to representing the raw device.
1083 */
Stephen Warren1e0f92a2015-12-07 11:38:49 -07001084 if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) {
Peter Bigot45fde892014-09-02 18:31:23 -05001085 ret = mmc_set_capacity(mmc, part_num);
Simon Glass984db5d2016-05-01 13:52:37 -06001086 mmc_get_blk_desc(mmc)->hwpart = part_num;
Stephen Warren1e0f92a2015-12-07 11:38:49 -07001087 }
Stephen Warrene315ae82013-06-11 15:14:01 -06001088
Peter Bigot45fde892014-09-02 18:31:23 -05001089 return ret;
Lei Wen31b99802011-05-02 16:26:26 +00001090}
1091
Jean-Jacques Hiblot1d7769a2017-11-30 17:44:02 +01001092#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001093int mmc_hwpart_config(struct mmc *mmc,
1094 const struct mmc_hwpart_conf *conf,
1095 enum mmc_hwpart_conf_mode mode)
1096{
1097 u8 part_attrs = 0;
1098 u32 enh_size_mult;
1099 u32 enh_start_addr;
1100 u32 gp_size_mult[4];
1101 u32 max_enh_size_mult;
1102 u32 tot_enh_size_mult = 0;
Diego Santa Cruz80200272014-12-23 10:50:31 +01001103 u8 wr_rel_set;
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001104 int i, pidx, err;
1105 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
1106
1107 if (mode < MMC_HWPART_CONF_CHECK || mode > MMC_HWPART_CONF_COMPLETE)
1108 return -EINVAL;
1109
1110 if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4_41)) {
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001111 pr_err("eMMC >= 4.4 required for enhanced user data area\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001112 return -EMEDIUMTYPE;
1113 }
1114
1115 if (!(mmc->part_support & PART_SUPPORT)) {
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001116 pr_err("Card does not support partitioning\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001117 return -EMEDIUMTYPE;
1118 }
1119
1120 if (!mmc->hc_wp_grp_size) {
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001121 pr_err("Card does not define HC WP group size\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001122 return -EMEDIUMTYPE;
1123 }
1124
1125 /* check partition alignment and total enhanced size */
1126 if (conf->user.enh_size) {
1127 if (conf->user.enh_size % mmc->hc_wp_grp_size ||
1128 conf->user.enh_start % mmc->hc_wp_grp_size) {
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001129 pr_err("User data enhanced area not HC WP group "
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001130 "size aligned\n");
1131 return -EINVAL;
1132 }
1133 part_attrs |= EXT_CSD_ENH_USR;
1134 enh_size_mult = conf->user.enh_size / mmc->hc_wp_grp_size;
1135 if (mmc->high_capacity) {
1136 enh_start_addr = conf->user.enh_start;
1137 } else {
1138 enh_start_addr = (conf->user.enh_start << 9);
1139 }
1140 } else {
1141 enh_size_mult = 0;
1142 enh_start_addr = 0;
1143 }
1144 tot_enh_size_mult += enh_size_mult;
1145
1146 for (pidx = 0; pidx < 4; pidx++) {
1147 if (conf->gp_part[pidx].size % mmc->hc_wp_grp_size) {
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001148 pr_err("GP%i partition not HC WP group size "
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001149 "aligned\n", pidx+1);
1150 return -EINVAL;
1151 }
1152 gp_size_mult[pidx] = conf->gp_part[pidx].size / mmc->hc_wp_grp_size;
1153 if (conf->gp_part[pidx].size && conf->gp_part[pidx].enhanced) {
1154 part_attrs |= EXT_CSD_ENH_GP(pidx);
1155 tot_enh_size_mult += gp_size_mult[pidx];
1156 }
1157 }
1158
1159 if (part_attrs && ! (mmc->part_support & ENHNCD_SUPPORT)) {
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001160 pr_err("Card does not support enhanced attribute\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001161 return -EMEDIUMTYPE;
1162 }
1163
1164 err = mmc_send_ext_csd(mmc, ext_csd);
1165 if (err)
1166 return err;
1167
1168 max_enh_size_mult =
1169 (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT+2] << 16) +
1170 (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT+1] << 8) +
1171 ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT];
1172 if (tot_enh_size_mult > max_enh_size_mult) {
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001173 pr_err("Total enhanced size exceeds maximum (%u > %u)\n",
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001174 tot_enh_size_mult, max_enh_size_mult);
1175 return -EMEDIUMTYPE;
1176 }
1177
Diego Santa Cruz80200272014-12-23 10:50:31 +01001178 /* The default value of EXT_CSD_WR_REL_SET is device
1179 * dependent, the values can only be changed if the
1180 * EXT_CSD_HS_CTRL_REL bit is set. The values can be
1181 * changed only once and before partitioning is completed. */
1182 wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
1183 if (conf->user.wr_rel_change) {
1184 if (conf->user.wr_rel_set)
1185 wr_rel_set |= EXT_CSD_WR_DATA_REL_USR;
1186 else
1187 wr_rel_set &= ~EXT_CSD_WR_DATA_REL_USR;
1188 }
1189 for (pidx = 0; pidx < 4; pidx++) {
1190 if (conf->gp_part[pidx].wr_rel_change) {
1191 if (conf->gp_part[pidx].wr_rel_set)
1192 wr_rel_set |= EXT_CSD_WR_DATA_REL_GP(pidx);
1193 else
1194 wr_rel_set &= ~EXT_CSD_WR_DATA_REL_GP(pidx);
1195 }
1196 }
1197
1198 if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET] &&
1199 !(ext_csd[EXT_CSD_WR_REL_PARAM] & EXT_CSD_HS_CTRL_REL)) {
1200 puts("Card does not support host controlled partition write "
1201 "reliability settings\n");
1202 return -EMEDIUMTYPE;
1203 }
1204
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001205 if (ext_csd[EXT_CSD_PARTITION_SETTING] &
1206 EXT_CSD_PARTITION_SETTING_COMPLETED) {
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001207 pr_err("Card already partitioned\n");
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001208 return -EPERM;
1209 }
1210
1211 if (mode == MMC_HWPART_CONF_CHECK)
1212 return 0;
1213
1214 /* Partitioning requires high-capacity size definitions */
1215 if (!(ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01)) {
1216 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1217 EXT_CSD_ERASE_GROUP_DEF, 1);
1218
1219 if (err)
1220 return err;
1221
1222 ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
1223
Jaehoon Chung58b9eb82020-01-17 15:06:54 +09001224#if CONFIG_IS_ENABLED(MMC_WRITE)
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001225 /* update erase group size to be high-capacity */
1226 mmc->erase_grp_size =
1227 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
Jaehoon Chung58b9eb82020-01-17 15:06:54 +09001228#endif
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001229
1230 }
1231
1232 /* all OK, write the configuration */
1233 for (i = 0; i < 4; i++) {
1234 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1235 EXT_CSD_ENH_START_ADDR+i,
1236 (enh_start_addr >> (i*8)) & 0xFF);
1237 if (err)
1238 return err;
1239 }
1240 for (i = 0; i < 3; i++) {
1241 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1242 EXT_CSD_ENH_SIZE_MULT+i,
1243 (enh_size_mult >> (i*8)) & 0xFF);
1244 if (err)
1245 return err;
1246 }
1247 for (pidx = 0; pidx < 4; pidx++) {
1248 for (i = 0; i < 3; i++) {
1249 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1250 EXT_CSD_GP_SIZE_MULT+pidx*3+i,
1251 (gp_size_mult[pidx] >> (i*8)) & 0xFF);
1252 if (err)
1253 return err;
1254 }
1255 }
1256 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1257 EXT_CSD_PARTITIONS_ATTRIBUTE, part_attrs);
1258 if (err)
1259 return err;
1260
1261 if (mode == MMC_HWPART_CONF_SET)
1262 return 0;
1263
Diego Santa Cruz80200272014-12-23 10:50:31 +01001264 /* The WR_REL_SET is a write-once register but shall be
1265 * written before setting PART_SETTING_COMPLETED. As it is
1266 * write-once we can only write it when completing the
1267 * partitioning. */
1268 if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET]) {
1269 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1270 EXT_CSD_WR_REL_SET, wr_rel_set);
1271 if (err)
1272 return err;
1273 }
1274
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001275 /* Setting PART_SETTING_COMPLETED confirms the partition
1276 * configuration but it only becomes effective after power
1277 * cycle, so we do not adjust the partition related settings
1278 * in the mmc struct. */
1279
1280 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1281 EXT_CSD_PARTITION_SETTING,
1282 EXT_CSD_PARTITION_SETTING_COMPLETED);
1283 if (err)
1284 return err;
1285
1286 return 0;
1287}
Jean-Jacques Hiblot1d7769a2017-11-30 17:44:02 +01001288#endif
Diego Santa Cruz69eb71a02014-12-23 10:50:29 +01001289
Simon Glasseba48f92017-07-29 11:35:31 -06001290#if !CONFIG_IS_ENABLED(DM_MMC)
Thierry Redingb9c8b772012-01-02 01:15:37 +00001291int mmc_getcd(struct mmc *mmc)
1292{
1293 int cd;
1294
1295 cd = board_mmc_getcd(mmc);
1296
Peter Korsgaardf7b15102013-03-21 04:00:03 +00001297 if (cd < 0) {
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001298 if (mmc->cfg->ops->getcd)
1299 cd = mmc->cfg->ops->getcd(mmc);
Peter Korsgaardf7b15102013-03-21 04:00:03 +00001300 else
1301 cd = 1;
1302 }
Thierry Redingb9c8b772012-01-02 01:15:37 +00001303
1304 return cd;
1305}
Simon Glass394dfc02016-06-12 23:30:22 -06001306#endif
Thierry Redingb9c8b772012-01-02 01:15:37 +00001307
Marek Vasuta318a7a2018-04-15 00:37:11 +02001308#if !CONFIG_IS_ENABLED(MMC_TINY)
Kim Phillips87ea3892012-10-29 13:34:43 +00001309static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
Andy Flemingad347bb2008-10-30 16:41:01 -05001310{
1311 struct mmc_cmd cmd;
1312 struct mmc_data data;
1313
1314 /* Switch the frequency */
1315 cmd.cmdidx = SD_CMD_SWITCH_FUNC;
1316 cmd.resp_type = MMC_RSP_R1;
1317 cmd.cmdarg = (mode << 31) | 0xffffff;
1318 cmd.cmdarg &= ~(0xf << (group * 4));
1319 cmd.cmdarg |= value << (group * 4);
Andy Flemingad347bb2008-10-30 16:41:01 -05001320
1321 data.dest = (char *)resp;
1322 data.blocksize = 64;
1323 data.blocks = 1;
1324 data.flags = MMC_DATA_READ;
1325
1326 return mmc_send_cmd(mmc, &cmd, &data);
1327}
1328
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001329static int sd_get_capabilities(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001330{
1331 int err;
1332 struct mmc_cmd cmd;
Suniel Mahesh2f423da2017-10-05 11:32:00 +05301333 ALLOC_CACHE_ALIGN_BUFFER(__be32, scr, 2);
1334 ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16);
Andy Flemingad347bb2008-10-30 16:41:01 -05001335 struct mmc_data data;
1336 int timeout;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001337#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001338 u32 sd3_bus_mode;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001339#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001340
Faiz Abbas01db77e2020-02-26 13:44:32 +05301341 mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05001342
Thomas Chou1254c3d2010-12-24 13:12:21 +00001343 if (mmc_host_is_spi(mmc))
1344 return 0;
1345
Andy Flemingad347bb2008-10-30 16:41:01 -05001346 /* Read the SCR to find out if this card supports higher speeds */
1347 cmd.cmdidx = MMC_CMD_APP_CMD;
1348 cmd.resp_type = MMC_RSP_R1;
1349 cmd.cmdarg = mmc->rca << 16;
Andy Flemingad347bb2008-10-30 16:41:01 -05001350
1351 err = mmc_send_cmd(mmc, &cmd, NULL);
1352
1353 if (err)
1354 return err;
1355
1356 cmd.cmdidx = SD_CMD_APP_SEND_SCR;
1357 cmd.resp_type = MMC_RSP_R1;
1358 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05001359
Anton staaf9b00f0d2011-10-03 13:54:59 +00001360 data.dest = (char *)scr;
Andy Flemingad347bb2008-10-30 16:41:01 -05001361 data.blocksize = 8;
1362 data.blocks = 1;
1363 data.flags = MMC_DATA_READ;
1364
Sean Anderson86325092020-10-17 08:36:27 -04001365 err = mmc_send_cmd_retry(mmc, &cmd, &data, 3);
Andy Flemingad347bb2008-10-30 16:41:01 -05001366
Sean Anderson86325092020-10-17 08:36:27 -04001367 if (err)
Andy Flemingad347bb2008-10-30 16:41:01 -05001368 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05001369
Yauhen Kharuzhy6e8edf42009-05-07 00:43:30 +03001370 mmc->scr[0] = __be32_to_cpu(scr[0]);
1371 mmc->scr[1] = __be32_to_cpu(scr[1]);
Andy Flemingad347bb2008-10-30 16:41:01 -05001372
1373 switch ((mmc->scr[0] >> 24) & 0xf) {
Bin Meng4a4ef872016-03-17 21:53:13 -07001374 case 0:
1375 mmc->version = SD_VERSION_1_0;
1376 break;
1377 case 1:
1378 mmc->version = SD_VERSION_1_10;
1379 break;
1380 case 2:
1381 mmc->version = SD_VERSION_2;
1382 if ((mmc->scr[0] >> 15) & 0x1)
1383 mmc->version = SD_VERSION_3;
1384 break;
1385 default:
1386 mmc->version = SD_VERSION_1_0;
1387 break;
Andy Flemingad347bb2008-10-30 16:41:01 -05001388 }
1389
Alagu Sankar24bb5ab2010-05-12 15:08:24 +05301390 if (mmc->scr[0] & SD_DATA_4BIT)
1391 mmc->card_caps |= MMC_MODE_4BIT;
1392
Andy Flemingad347bb2008-10-30 16:41:01 -05001393 /* Version 1.0 doesn't support switching */
1394 if (mmc->version == SD_VERSION_1_0)
1395 return 0;
1396
1397 timeout = 4;
1398 while (timeout--) {
1399 err = sd_switch(mmc, SD_SWITCH_CHECK, 0, 1,
Anton staaf9b00f0d2011-10-03 13:54:59 +00001400 (u8 *)switch_status);
Andy Flemingad347bb2008-10-30 16:41:01 -05001401
1402 if (err)
1403 return err;
1404
1405 /* The high-speed function is busy. Try again */
Yauhen Kharuzhy6e8edf42009-05-07 00:43:30 +03001406 if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
Andy Flemingad347bb2008-10-30 16:41:01 -05001407 break;
1408 }
1409
Andy Flemingad347bb2008-10-30 16:41:01 -05001410 /* If high-speed isn't supported, we return */
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001411 if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)
1412 mmc->card_caps |= MMC_CAP(SD_HS);
Andy Flemingad347bb2008-10-30 16:41:01 -05001413
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001414#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001415 /* Version before 3.0 don't support UHS modes */
1416 if (mmc->version < SD_VERSION_3)
1417 return 0;
1418
1419 sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;
1420 if (sd3_bus_mode & SD_MODE_UHS_SDR104)
1421 mmc->card_caps |= MMC_CAP(UHS_SDR104);
1422 if (sd3_bus_mode & SD_MODE_UHS_SDR50)
1423 mmc->card_caps |= MMC_CAP(UHS_SDR50);
1424 if (sd3_bus_mode & SD_MODE_UHS_SDR25)
1425 mmc->card_caps |= MMC_CAP(UHS_SDR25);
1426 if (sd3_bus_mode & SD_MODE_UHS_SDR12)
1427 mmc->card_caps |= MMC_CAP(UHS_SDR12);
1428 if (sd3_bus_mode & SD_MODE_UHS_DDR50)
1429 mmc->card_caps |= MMC_CAP(UHS_DDR50);
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001430#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001431
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001432 return 0;
1433}
1434
1435static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
1436{
1437 int err;
1438
1439 ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001440 int speed;
Macpaul Lin24e92ec2011-11-28 16:31:09 +00001441
Marek Vasut4105e972018-11-18 03:25:08 +01001442 /* SD version 1.00 and 1.01 does not support CMD 6 */
1443 if (mmc->version == SD_VERSION_1_0)
1444 return 0;
1445
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001446 switch (mode) {
Faiz Abbas01db77e2020-02-26 13:44:32 +05301447 case MMC_LEGACY:
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001448 speed = UHS_SDR12_BUS_SPEED;
1449 break;
1450 case SD_HS:
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001451 speed = HIGH_SPEED_BUS_SPEED;
1452 break;
1453#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
1454 case UHS_SDR12:
1455 speed = UHS_SDR12_BUS_SPEED;
1456 break;
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001457 case UHS_SDR25:
1458 speed = UHS_SDR25_BUS_SPEED;
1459 break;
1460 case UHS_SDR50:
1461 speed = UHS_SDR50_BUS_SPEED;
1462 break;
1463 case UHS_DDR50:
1464 speed = UHS_DDR50_BUS_SPEED;
1465 break;
1466 case UHS_SDR104:
1467 speed = UHS_SDR104_BUS_SPEED;
1468 break;
Jean-Jacques Hiblot74c98b22018-01-04 15:23:30 +01001469#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001470 default:
1471 return -EINVAL;
1472 }
1473
1474 err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, speed, (u8 *)switch_status);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001475 if (err)
1476 return err;
1477
Jean-Jacques Hiblote7f664e2018-02-09 12:09:27 +01001478 if (((__be32_to_cpu(switch_status[4]) >> 24) & 0xF) != speed)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001479 return -ENOTSUPP;
1480
1481 return 0;
1482}
Andy Flemingad347bb2008-10-30 16:41:01 -05001483
Marek Vasut8ff55fb2018-04-15 00:36:45 +02001484static int sd_select_bus_width(struct mmc *mmc, int w)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001485{
1486 int err;
1487 struct mmc_cmd cmd;
1488
1489 if ((w != 4) && (w != 1))
1490 return -EINVAL;
1491
1492 cmd.cmdidx = MMC_CMD_APP_CMD;
1493 cmd.resp_type = MMC_RSP_R1;
1494 cmd.cmdarg = mmc->rca << 16;
1495
1496 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05001497 if (err)
1498 return err;
1499
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001500 cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
1501 cmd.resp_type = MMC_RSP_R1;
1502 if (w == 4)
1503 cmd.cmdarg = 2;
1504 else if (w == 1)
1505 cmd.cmdarg = 0;
1506 err = mmc_send_cmd(mmc, &cmd, NULL);
1507 if (err)
1508 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05001509
1510 return 0;
1511}
Marek Vasuta318a7a2018-04-15 00:37:11 +02001512#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001513
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001514#if CONFIG_IS_ENABLED(MMC_WRITE)
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001515static int sd_read_ssr(struct mmc *mmc)
1516{
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001517 static const unsigned int sd_au_size[] = {
1518 0, SZ_16K / 512, SZ_32K / 512,
1519 SZ_64K / 512, SZ_128K / 512, SZ_256K / 512,
1520 SZ_512K / 512, SZ_1M / 512, SZ_2M / 512,
1521 SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512,
1522 SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512,
1523 SZ_64M / 512,
1524 };
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001525 int err, i;
1526 struct mmc_cmd cmd;
1527 ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16);
1528 struct mmc_data data;
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001529 unsigned int au, eo, et, es;
1530
1531 cmd.cmdidx = MMC_CMD_APP_CMD;
1532 cmd.resp_type = MMC_RSP_R1;
1533 cmd.cmdarg = mmc->rca << 16;
1534
Sean Anderson86325092020-10-17 08:36:27 -04001535 err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_APP_CMD, 4);
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001536 if (err)
1537 return err;
1538
1539 cmd.cmdidx = SD_CMD_APP_SD_STATUS;
1540 cmd.resp_type = MMC_RSP_R1;
1541 cmd.cmdarg = 0;
1542
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001543 data.dest = (char *)ssr;
1544 data.blocksize = 64;
1545 data.blocks = 1;
1546 data.flags = MMC_DATA_READ;
1547
Sean Anderson86325092020-10-17 08:36:27 -04001548 err = mmc_send_cmd_retry(mmc, &cmd, &data, 3);
1549 if (err)
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001550 return err;
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001551
1552 for (i = 0; i < 16; i++)
1553 ssr[i] = be32_to_cpu(ssr[i]);
1554
1555 au = (ssr[2] >> 12) & 0xF;
1556 if ((au <= 9) || (mmc->version == SD_VERSION_3)) {
1557 mmc->ssr.au = sd_au_size[au];
1558 es = (ssr[3] >> 24) & 0xFF;
1559 es |= (ssr[2] & 0xFF) << 8;
1560 et = (ssr[3] >> 18) & 0x3F;
1561 if (es && et) {
1562 eo = (ssr[3] >> 16) & 0x3;
1563 mmc->ssr.erase_timeout = (et * 1000) / es;
1564 mmc->ssr.erase_offset = eo * 1000;
1565 }
1566 } else {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001567 pr_debug("Invalid Allocation Unit Size.\n");
Peng Fanb3fcf1e2016-09-01 11:13:38 +08001568 }
1569
1570 return 0;
1571}
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001572#endif
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01001573/*
1574 * TRAN_SPEED bits 0:2 encode the frequency unit:
1575 * 0 = 100KHz, 1 = 1MHz, 2 = 10MHz, 3 = 100MHz, values 4 - 7 are reserved.
1576 * The values in fbase[] are divided by 10 to avoid floats in multiplier[].
1577 */
Mike Frysingerb588caf2010-10-20 01:15:53 +00001578static const int fbase[] = {
Andy Flemingad347bb2008-10-30 16:41:01 -05001579 10000,
1580 100000,
1581 1000000,
1582 10000000,
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01001583 0, /* reserved */
1584 0, /* reserved */
1585 0, /* reserved */
1586 0, /* reserved */
Andy Flemingad347bb2008-10-30 16:41:01 -05001587};
1588
1589/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
1590 * to platforms without floating point.
1591 */
Simon Glass03317cc2016-05-14 14:02:57 -06001592static const u8 multipliers[] = {
Andy Flemingad347bb2008-10-30 16:41:01 -05001593 0, /* reserved */
1594 10,
1595 12,
1596 13,
1597 15,
1598 20,
1599 25,
1600 30,
1601 35,
1602 40,
1603 45,
1604 50,
1605 55,
1606 60,
1607 70,
1608 80,
1609};
1610
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001611static inline int bus_width(uint cap)
1612{
1613 if (cap == MMC_MODE_8BIT)
1614 return 8;
1615 if (cap == MMC_MODE_4BIT)
1616 return 4;
1617 if (cap == MMC_MODE_1BIT)
1618 return 1;
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001619 pr_warn("invalid bus witdh capability 0x%x\n", cap);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001620 return 0;
1621}
1622
Simon Glasseba48f92017-07-29 11:35:31 -06001623#if !CONFIG_IS_ENABLED(DM_MMC)
Tom Rinidec7ea02024-05-20 13:35:03 -06001624#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Kishon Vijay Abraham Iae7174f2017-09-21 16:30:05 +02001625static int mmc_execute_tuning(struct mmc *mmc, uint opcode)
1626{
1627 return -ENOTSUPP;
1628}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001629#endif
Kishon Vijay Abraham Iae7174f2017-09-21 16:30:05 +02001630
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001631static int mmc_set_ios(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001632{
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001633 int ret = 0;
1634
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001635 if (mmc->cfg->ops->set_ios)
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001636 ret = mmc->cfg->ops->set_ios(mmc);
1637
1638 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05001639}
Yann Gautier6f558332019-09-19 17:56:12 +02001640
1641static int mmc_host_power_cycle(struct mmc *mmc)
1642{
1643 int ret = 0;
1644
1645 if (mmc->cfg->ops->host_power_cycle)
1646 ret = mmc->cfg->ops->host_power_cycle(mmc);
1647
1648 return ret;
1649}
Simon Glass394dfc02016-06-12 23:30:22 -06001650#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001651
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001652int mmc_set_clock(struct mmc *mmc, uint clock, bool disable)
Andy Flemingad347bb2008-10-30 16:41:01 -05001653{
Jaehoon Chungab4d4052018-01-23 14:04:30 +09001654 if (!disable) {
Jaehoon Chung8a933292018-01-17 19:36:58 +09001655 if (clock > mmc->cfg->f_max)
1656 clock = mmc->cfg->f_max;
Andy Flemingad347bb2008-10-30 16:41:01 -05001657
Jaehoon Chung8a933292018-01-17 19:36:58 +09001658 if (clock < mmc->cfg->f_min)
1659 clock = mmc->cfg->f_min;
1660 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001661
1662 mmc->clock = clock;
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001663 mmc->clk_disable = disable;
Andy Flemingad347bb2008-10-30 16:41:01 -05001664
Jaehoon Chungc8477d62018-01-26 19:25:30 +09001665 debug("clock is %s (%dHz)\n", disable ? "disabled" : "enabled", clock);
1666
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001667 return mmc_set_ios(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001668}
1669
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001670static int mmc_set_bus_width(struct mmc *mmc, uint width)
Andy Flemingad347bb2008-10-30 16:41:01 -05001671{
1672 mmc->bus_width = width;
1673
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001674 return mmc_set_ios(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001675}
1676
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001677#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
1678/*
1679 * helper function to display the capabilities in a human
1680 * friendly manner. The capabilities include bus width and
1681 * supported modes.
1682 */
1683void mmc_dump_capabilities(const char *text, uint caps)
1684{
1685 enum bus_mode mode;
1686
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001687 pr_debug("%s: widths [", text);
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001688 if (caps & MMC_MODE_8BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001689 pr_debug("8, ");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001690 if (caps & MMC_MODE_4BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001691 pr_debug("4, ");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001692 if (caps & MMC_MODE_1BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001693 pr_debug("1, ");
1694 pr_debug("\b\b] modes [");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001695 for (mode = MMC_LEGACY; mode < MMC_MODES_END; mode++)
1696 if (MMC_CAP(mode) & caps)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001697 pr_debug("%s, ", mmc_mode_name(mode));
1698 pr_debug("\b\b]\n");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001699}
1700#endif
1701
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001702struct mode_width_tuning {
1703 enum bus_mode mode;
1704 uint widths;
Tom Rinidec7ea02024-05-20 13:35:03 -06001705#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001706 uint tuning;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001707#endif
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001708};
1709
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001710#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001711int mmc_voltage_to_mv(enum mmc_voltage voltage)
1712{
1713 switch (voltage) {
1714 case MMC_SIGNAL_VOLTAGE_000: return 0;
1715 case MMC_SIGNAL_VOLTAGE_330: return 3300;
1716 case MMC_SIGNAL_VOLTAGE_180: return 1800;
1717 case MMC_SIGNAL_VOLTAGE_120: return 1200;
1718 }
1719 return -EINVAL;
1720}
1721
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001722static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1723{
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001724 int err;
1725
1726 if (mmc->signal_voltage == signal_voltage)
1727 return 0;
1728
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001729 mmc->signal_voltage = signal_voltage;
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001730 err = mmc_set_ios(mmc);
1731 if (err)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001732 pr_debug("unable to set voltage (err %d)\n", err);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001733
1734 return err;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001735}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001736#else
1737static inline int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1738{
1739 return 0;
1740}
1741#endif
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001742
Marek Vasuta318a7a2018-04-15 00:37:11 +02001743#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001744static const struct mode_width_tuning sd_modes_by_pref[] = {
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001745#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Tom Rinidec7ea02024-05-20 13:35:03 -06001746#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001747 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001748 .mode = UHS_SDR104,
1749 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1750 .tuning = MMC_CMD_SEND_TUNING_BLOCK
1751 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001752#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001753 {
1754 .mode = UHS_SDR50,
1755 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1756 },
1757 {
1758 .mode = UHS_DDR50,
1759 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1760 },
1761 {
1762 .mode = UHS_SDR25,
1763 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1764 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001765#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001766 {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001767 .mode = SD_HS,
1768 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1769 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001770#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001771 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001772 .mode = UHS_SDR12,
1773 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1774 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001775#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001776 {
Faiz Abbas01db77e2020-02-26 13:44:32 +05301777 .mode = MMC_LEGACY,
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001778 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1779 }
1780};
1781
1782#define for_each_sd_mode_by_pref(caps, mwt) \
1783 for (mwt = sd_modes_by_pref;\
1784 mwt < sd_modes_by_pref + ARRAY_SIZE(sd_modes_by_pref);\
1785 mwt++) \
1786 if (caps & MMC_CAP(mwt->mode))
1787
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02001788static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001789{
1790 int err;
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001791 uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
1792 const struct mode_width_tuning *mwt;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001793#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001794 bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001795#else
1796 bool uhs_en = false;
1797#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001798 uint caps;
1799
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001800#ifdef DEBUG
1801 mmc_dump_capabilities("sd card", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001802 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001803#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001804
Anup Pateld9c92c72019-07-08 04:10:43 +00001805 if (mmc_host_is_spi(mmc)) {
1806 mmc_set_bus_width(mmc, 1);
Faiz Abbas01db77e2020-02-26 13:44:32 +05301807 mmc_select_mode(mmc, MMC_LEGACY);
Anup Pateld9c92c72019-07-08 04:10:43 +00001808 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
Pragnesh Patela01f57e2020-06-29 15:17:26 +05301809#if CONFIG_IS_ENABLED(MMC_WRITE)
1810 err = sd_read_ssr(mmc);
1811 if (err)
1812 pr_warn("unable to read ssr\n");
1813#endif
Anup Pateld9c92c72019-07-08 04:10:43 +00001814 return 0;
1815 }
1816
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001817 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001818 caps = card_caps & mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001819
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001820 if (!uhs_en)
1821 caps &= ~UHS_CAPS;
1822
1823 for_each_sd_mode_by_pref(caps, mwt) {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001824 uint *w;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001825
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001826 for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001827 if (*w & caps & mwt->widths) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001828 pr_debug("trying mode %s width %d (at %d MHz)\n",
1829 mmc_mode_name(mwt->mode),
1830 bus_width(*w),
1831 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001832
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001833 /* configure the bus width (card + host) */
1834 err = sd_select_bus_width(mmc, bus_width(*w));
1835 if (err)
1836 goto error;
1837 mmc_set_bus_width(mmc, bus_width(*w));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001838
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001839 /* configure the bus mode (card) */
1840 err = sd_set_card_speed(mmc, mwt->mode);
1841 if (err)
1842 goto error;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001843
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001844 /* configure the bus mode (host) */
1845 mmc_select_mode(mmc, mwt->mode);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001846 mmc_set_clock(mmc, mmc->tran_speed,
1847 MMC_CLK_ENABLE);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001848
Tom Rinidec7ea02024-05-20 13:35:03 -06001849#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001850 /* execute tuning if needed */
1851 if (mwt->tuning && !mmc_host_is_spi(mmc)) {
1852 err = mmc_execute_tuning(mmc,
1853 mwt->tuning);
1854 if (err) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001855 pr_debug("tuning failed\n");
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001856 goto error;
1857 }
1858 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001859#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001860
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001861#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001862 err = sd_read_ssr(mmc);
Peng Fan2d2fe8e2018-03-05 16:20:40 +08001863 if (err)
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001864 pr_warn("unable to read ssr\n");
1865#endif
1866 if (!err)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001867 return 0;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001868
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001869error:
1870 /* revert to a safer bus speed */
Faiz Abbas01db77e2020-02-26 13:44:32 +05301871 mmc_select_mode(mmc, MMC_LEGACY);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001872 mmc_set_clock(mmc, mmc->tran_speed,
1873 MMC_CLK_ENABLE);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001874 }
1875 }
1876 }
1877
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001878 pr_err("unable to select a mode\n");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001879 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001880}
1881
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001882/*
1883 * read the compare the part of ext csd that is constant.
1884 * This can be used to check that the transfer is working
1885 * as expected.
1886 */
1887static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001888{
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001889 int err;
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02001890 const u8 *ext_csd = mmc->ext_csd;
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001891 ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
1892
Jean-Jacques Hiblot7ab1b622017-11-30 17:43:58 +01001893 if (mmc->version < MMC_VERSION_4)
1894 return 0;
1895
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001896 err = mmc_send_ext_csd(mmc, test_csd);
1897 if (err)
1898 return err;
1899
1900 /* Only compare read only fields */
1901 if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
1902 == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
1903 ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
1904 == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
1905 ext_csd[EXT_CSD_REV]
1906 == test_csd[EXT_CSD_REV] &&
1907 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
1908 == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
1909 memcmp(&ext_csd[EXT_CSD_SEC_CNT],
1910 &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
1911 return 0;
1912
1913 return -EBADMSG;
1914}
1915
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001916#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001917static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1918 uint32_t allowed_mask)
1919{
1920 u32 card_mask = 0;
1921
1922 switch (mode) {
Peng Faneede83b2019-07-10 14:43:07 +08001923 case MMC_HS_400_ES:
Peng Fan46801252018-08-10 14:07:54 +08001924 case MMC_HS_400:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001925 case MMC_HS_200:
Peng Fan46801252018-08-10 14:07:54 +08001926 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V |
1927 EXT_CSD_CARD_TYPE_HS400_1_8V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001928 card_mask |= MMC_SIGNAL_VOLTAGE_180;
Peng Fan46801252018-08-10 14:07:54 +08001929 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
1930 EXT_CSD_CARD_TYPE_HS400_1_2V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001931 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1932 break;
1933 case MMC_DDR_52:
1934 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
1935 card_mask |= MMC_SIGNAL_VOLTAGE_330 |
1936 MMC_SIGNAL_VOLTAGE_180;
1937 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_2V)
1938 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1939 break;
1940 default:
1941 card_mask |= MMC_SIGNAL_VOLTAGE_330;
1942 break;
1943 }
1944
1945 while (card_mask & allowed_mask) {
1946 enum mmc_voltage best_match;
1947
1948 best_match = 1 << (ffs(card_mask & allowed_mask) - 1);
1949 if (!mmc_set_signal_voltage(mmc, best_match))
1950 return 0;
1951
1952 allowed_mask &= ~best_match;
1953 }
1954
1955 return -ENOTSUPP;
1956}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001957#else
1958static inline int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1959 uint32_t allowed_mask)
1960{
1961 return 0;
1962}
1963#endif
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001964
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001965static const struct mode_width_tuning mmc_modes_by_pref[] = {
Peng Faneede83b2019-07-10 14:43:07 +08001966#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
1967 {
1968 .mode = MMC_HS_400_ES,
1969 .widths = MMC_MODE_8BIT,
1970 },
1971#endif
Peng Fan46801252018-08-10 14:07:54 +08001972#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
1973 {
1974 .mode = MMC_HS_400,
1975 .widths = MMC_MODE_8BIT,
1976 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
1977 },
1978#endif
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001979#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001980 {
1981 .mode = MMC_HS_200,
1982 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001983 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001984 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001985#endif
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001986 {
1987 .mode = MMC_DDR_52,
1988 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
1989 },
1990 {
1991 .mode = MMC_HS_52,
1992 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
1993 },
1994 {
1995 .mode = MMC_HS,
1996 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
1997 },
1998 {
1999 .mode = MMC_LEGACY,
2000 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
2001 }
2002};
2003
2004#define for_each_mmc_mode_by_pref(caps, mwt) \
2005 for (mwt = mmc_modes_by_pref;\
2006 mwt < mmc_modes_by_pref + ARRAY_SIZE(mmc_modes_by_pref);\
2007 mwt++) \
2008 if (caps & MMC_CAP(mwt->mode))
2009
2010static const struct ext_csd_bus_width {
2011 uint cap;
2012 bool is_ddr;
2013 uint ext_csd_bits;
2014} ext_csd_bus_width[] = {
2015 {MMC_MODE_8BIT, true, EXT_CSD_DDR_BUS_WIDTH_8},
2016 {MMC_MODE_4BIT, true, EXT_CSD_DDR_BUS_WIDTH_4},
2017 {MMC_MODE_8BIT, false, EXT_CSD_BUS_WIDTH_8},
2018 {MMC_MODE_4BIT, false, EXT_CSD_BUS_WIDTH_4},
2019 {MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
2020};
2021
Peng Fan46801252018-08-10 14:07:54 +08002022#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
2023static int mmc_select_hs400(struct mmc *mmc)
2024{
2025 int err;
2026
2027 /* Set timing to HS200 for tuning */
Marek Vasut111572f2019-01-03 21:19:24 +01002028 err = mmc_set_card_speed(mmc, MMC_HS_200, false);
Peng Fan46801252018-08-10 14:07:54 +08002029 if (err)
2030 return err;
2031
2032 /* configure the bus mode (host) */
2033 mmc_select_mode(mmc, MMC_HS_200);
2034 mmc_set_clock(mmc, mmc->tran_speed, false);
2035
2036 /* execute tuning if needed */
Marek Vasut259cc632024-02-24 23:32:09 +01002037 mmc->hs400_tuning = true;
Peng Fan46801252018-08-10 14:07:54 +08002038 err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200);
Marek Vasut259cc632024-02-24 23:32:09 +01002039 mmc->hs400_tuning = false;
Peng Fan46801252018-08-10 14:07:54 +08002040 if (err) {
2041 debug("tuning failed\n");
2042 return err;
2043 }
2044
2045 /* Set back to HS */
BOUGH CHEN8702bbc2019-03-26 06:24:17 +00002046 mmc_set_card_speed(mmc, MMC_HS, true);
Peng Fan46801252018-08-10 14:07:54 +08002047
Yangbo Lu5347aea2020-09-01 16:58:04 +08002048 err = mmc_hs400_prepare_ddr(mmc);
2049 if (err)
2050 return err;
2051
Peng Fan46801252018-08-10 14:07:54 +08002052 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2053 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
2054 if (err)
2055 return err;
2056
Marek Vasut111572f2019-01-03 21:19:24 +01002057 err = mmc_set_card_speed(mmc, MMC_HS_400, false);
Peng Fan46801252018-08-10 14:07:54 +08002058 if (err)
2059 return err;
2060
2061 mmc_select_mode(mmc, MMC_HS_400);
2062 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2063 if (err)
2064 return err;
2065
2066 return 0;
2067}
2068#else
2069static int mmc_select_hs400(struct mmc *mmc)
2070{
2071 return -ENOTSUPP;
2072}
2073#endif
2074
Peng Faneede83b2019-07-10 14:43:07 +08002075#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
2076#if !CONFIG_IS_ENABLED(DM_MMC)
2077static int mmc_set_enhanced_strobe(struct mmc *mmc)
2078{
2079 return -ENOTSUPP;
2080}
2081#endif
2082static int mmc_select_hs400es(struct mmc *mmc)
2083{
2084 int err;
2085
2086 err = mmc_set_card_speed(mmc, MMC_HS, true);
2087 if (err)
2088 return err;
2089
2090 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2091 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG |
2092 EXT_CSD_BUS_WIDTH_STROBE);
2093 if (err) {
2094 printf("switch to bus width for hs400 failed\n");
2095 return err;
2096 }
2097 /* TODO: driver strength */
2098 err = mmc_set_card_speed(mmc, MMC_HS_400_ES, false);
2099 if (err)
2100 return err;
2101
2102 mmc_select_mode(mmc, MMC_HS_400_ES);
2103 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2104 if (err)
2105 return err;
2106
2107 return mmc_set_enhanced_strobe(mmc);
2108}
2109#else
2110static int mmc_select_hs400es(struct mmc *mmc)
2111{
2112 return -ENOTSUPP;
2113}
2114#endif
2115
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002116#define for_each_supported_width(caps, ddr, ecbv) \
2117 for (ecbv = ext_csd_bus_width;\
2118 ecbv < ext_csd_bus_width + ARRAY_SIZE(ext_csd_bus_width);\
2119 ecbv++) \
2120 if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
2121
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002122static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02002123{
Jaehoon Chung6b3431c2020-12-04 06:36:00 +09002124 int err = 0;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002125 const struct mode_width_tuning *mwt;
2126 const struct ext_csd_bus_width *ecbw;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002127
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002128#ifdef DEBUG
2129 mmc_dump_capabilities("mmc", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002130 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002131#endif
2132
Anup Pateld9c92c72019-07-08 04:10:43 +00002133 if (mmc_host_is_spi(mmc)) {
2134 mmc_set_bus_width(mmc, 1);
2135 mmc_select_mode(mmc, MMC_LEGACY);
2136 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
2137 return 0;
2138 }
2139
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002140 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002141 card_caps &= mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002142
2143 /* Only version 4 of MMC supports wider bus widths */
2144 if (mmc->version < MMC_VERSION_4)
2145 return 0;
2146
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002147 if (!mmc->ext_csd) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002148 pr_debug("No ext_csd found!\n"); /* this should enver happen */
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002149 return -ENOTSUPP;
2150 }
2151
Marek Vasut111572f2019-01-03 21:19:24 +01002152#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
Ye Li3679e802021-08-17 17:20:34 +08002153 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
2154 CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
Marek Vasut111572f2019-01-03 21:19:24 +01002155 /*
2156 * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode
2157 * before doing anything else, since a transition from either of
2158 * the HS200/HS400 mode directly to legacy mode is not supported.
2159 */
2160 if (mmc->selected_mode == MMC_HS_200 ||
Ye Li3679e802021-08-17 17:20:34 +08002161 mmc->selected_mode == MMC_HS_400 ||
2162 mmc->selected_mode == MMC_HS_400_ES)
Marek Vasut111572f2019-01-03 21:19:24 +01002163 mmc_set_card_speed(mmc, MMC_HS, true);
2164 else
2165#endif
2166 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002167
2168 for_each_mmc_mode_by_pref(card_caps, mwt) {
2169 for_each_supported_width(card_caps & mwt->widths,
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002170 mmc_is_mode_ddr(mwt->mode), ecbw) {
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002171 enum mmc_voltage old_voltage;
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002172 pr_debug("trying mode %s width %d (at %d MHz)\n",
2173 mmc_mode_name(mwt->mode),
2174 bus_width(ecbw->cap),
2175 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002176 old_voltage = mmc->signal_voltage;
2177 err = mmc_set_lowest_voltage(mmc, mwt->mode,
2178 MMC_ALL_SIGNAL_VOLTAGE);
2179 if (err)
2180 continue;
2181
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002182 /* configure the bus width (card + host) */
2183 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2184 EXT_CSD_BUS_WIDTH,
2185 ecbw->ext_csd_bits & ~EXT_CSD_DDR_FLAG);
2186 if (err)
2187 goto error;
2188 mmc_set_bus_width(mmc, bus_width(ecbw->cap));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002189
Peng Fan46801252018-08-10 14:07:54 +08002190 if (mwt->mode == MMC_HS_400) {
2191 err = mmc_select_hs400(mmc);
2192 if (err) {
2193 printf("Select HS400 failed %d\n", err);
2194 goto error;
2195 }
Peng Faneede83b2019-07-10 14:43:07 +08002196 } else if (mwt->mode == MMC_HS_400_ES) {
2197 err = mmc_select_hs400es(mmc);
2198 if (err) {
2199 printf("Select HS400ES failed %d\n",
2200 err);
2201 goto error;
2202 }
Peng Fan46801252018-08-10 14:07:54 +08002203 } else {
2204 /* configure the bus speed (card) */
Marek Vasut111572f2019-01-03 21:19:24 +01002205 err = mmc_set_card_speed(mmc, mwt->mode, false);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002206 if (err)
2207 goto error;
Peng Fan46801252018-08-10 14:07:54 +08002208
2209 /*
2210 * configure the bus width AND the ddr mode
2211 * (card). The host side will be taken care
2212 * of in the next step
2213 */
2214 if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) {
2215 err = mmc_switch(mmc,
2216 EXT_CSD_CMD_SET_NORMAL,
2217 EXT_CSD_BUS_WIDTH,
2218 ecbw->ext_csd_bits);
2219 if (err)
2220 goto error;
2221 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002222
Peng Fan46801252018-08-10 14:07:54 +08002223 /* configure the bus mode (host) */
2224 mmc_select_mode(mmc, mwt->mode);
2225 mmc_set_clock(mmc, mmc->tran_speed,
2226 MMC_CLK_ENABLE);
Tom Rinidec7ea02024-05-20 13:35:03 -06002227#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002228
Peng Fan46801252018-08-10 14:07:54 +08002229 /* execute tuning if needed */
2230 if (mwt->tuning) {
2231 err = mmc_execute_tuning(mmc,
2232 mwt->tuning);
2233 if (err) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002234 pr_debug("tuning failed : %d\n", err);
Peng Fan46801252018-08-10 14:07:54 +08002235 goto error;
2236 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002237 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002238#endif
Peng Fan46801252018-08-10 14:07:54 +08002239 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002240
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002241 /* do a transfer to check the configuration */
2242 err = mmc_read_and_compare_ext_csd(mmc);
2243 if (!err)
2244 return 0;
2245error:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002246 mmc_set_signal_voltage(mmc, old_voltage);
Naoki Hayama3110dcb2020-10-12 18:35:22 +09002247 /* if an error occurred, revert to a safer bus mode */
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002248 mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2249 EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
2250 mmc_select_mode(mmc, MMC_LEGACY);
Valentine Barshak29f8d072023-06-10 13:22:33 +02002251 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002252 mmc_set_bus_width(mmc, 1);
2253 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002254 }
2255
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002256 pr_err("unable to select a mode : %d\n", err);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002257
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002258 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002259}
Marek Vasut67c77f92024-03-17 04:01:22 +01002260#else
2261static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
2262{
2263 return 0;
2264};
2265
2266static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
2267{
2268 return 0;
2269};
Marek Vasuta318a7a2018-04-15 00:37:11 +02002270#endif
2271
2272#if CONFIG_IS_ENABLED(MMC_TINY)
2273DEFINE_CACHE_ALIGN_BUFFER(u8, ext_csd_bkup, MMC_MAX_BLOCK_LEN);
2274#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002275
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002276static int mmc_startup_v4(struct mmc *mmc)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002277{
2278 int err, i;
2279 u64 capacity;
2280 bool has_parts = false;
2281 bool part_completed;
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002282 static const u32 mmc_versions[] = {
2283 MMC_VERSION_4,
2284 MMC_VERSION_4_1,
2285 MMC_VERSION_4_2,
2286 MMC_VERSION_4_3,
Jean-Jacques Hiblotc64862b2018-02-09 12:09:28 +01002287 MMC_VERSION_4_4,
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002288 MMC_VERSION_4_41,
2289 MMC_VERSION_4_5,
2290 MMC_VERSION_5_0,
2291 MMC_VERSION_5_1
2292 };
2293
Marek Vasuta318a7a2018-04-15 00:37:11 +02002294#if CONFIG_IS_ENABLED(MMC_TINY)
2295 u8 *ext_csd = ext_csd_bkup;
2296
2297 if (IS_SD(mmc) || mmc->version < MMC_VERSION_4)
2298 return 0;
2299
2300 if (!mmc->ext_csd)
Sam Edwardsed8339f2023-05-18 13:47:07 -06002301 memset(ext_csd_bkup, 0, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002302
2303 err = mmc_send_ext_csd(mmc, ext_csd);
2304 if (err)
2305 goto error;
2306
2307 /* store the ext csd for future reference */
2308 if (!mmc->ext_csd)
2309 mmc->ext_csd = ext_csd;
2310#else
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002311 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002312
2313 if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4))
2314 return 0;
2315
2316 /* check ext_csd version and capacity */
2317 err = mmc_send_ext_csd(mmc, ext_csd);
2318 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002319 goto error;
2320
2321 /* store the ext csd for future reference */
2322 if (!mmc->ext_csd)
2323 mmc->ext_csd = malloc(MMC_MAX_BLOCK_LEN);
2324 if (!mmc->ext_csd)
2325 return -ENOMEM;
2326 memcpy(mmc->ext_csd, ext_csd, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002327#endif
Alexander Kochetkovf1133c92018-02-20 14:35:55 +03002328 if (ext_csd[EXT_CSD_REV] >= ARRAY_SIZE(mmc_versions))
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002329 return -EINVAL;
2330
2331 mmc->version = mmc_versions[ext_csd[EXT_CSD_REV]];
2332
2333 if (mmc->version >= MMC_VERSION_4_2) {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002334 /*
2335 * According to the JEDEC Standard, the value of
2336 * ext_csd's capacity is valid if the value is more
2337 * than 2GB
2338 */
2339 capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
2340 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8
2341 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16
2342 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
2343 capacity *= MMC_MAX_BLOCK_LEN;
2344 if ((capacity >> 20) > 2 * 1024)
2345 mmc->capacity_user = capacity;
2346 }
2347
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +02002348 if (mmc->version >= MMC_VERSION_4_5)
2349 mmc->gen_cmd6_time = ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
2350
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002351 /* The partition data may be non-zero but it is only
2352 * effective if PARTITION_SETTING_COMPLETED is set in
2353 * EXT_CSD, so ignore any data if this bit is not set,
2354 * except for enabling the high-capacity group size
2355 * definition (see below).
2356 */
2357 part_completed = !!(ext_csd[EXT_CSD_PARTITION_SETTING] &
2358 EXT_CSD_PARTITION_SETTING_COMPLETED);
2359
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +02002360 mmc->part_switch_time = ext_csd[EXT_CSD_PART_SWITCH_TIME];
2361 /* Some eMMC set the value too low so set a minimum */
2362 if (mmc->part_switch_time < MMC_MIN_PART_SWITCH_TIME && mmc->part_switch_time)
2363 mmc->part_switch_time = MMC_MIN_PART_SWITCH_TIME;
2364
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002365 /* store the partition info of emmc */
2366 mmc->part_support = ext_csd[EXT_CSD_PARTITIONING_SUPPORT];
2367 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
2368 ext_csd[EXT_CSD_BOOT_MULT])
2369 mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
2370 if (part_completed &&
2371 (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & ENHNCD_SUPPORT))
2372 mmc->part_attr = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE];
2373
2374 mmc->capacity_boot = ext_csd[EXT_CSD_BOOT_MULT] << 17;
2375
2376 mmc->capacity_rpmb = ext_csd[EXT_CSD_RPMB_MULT] << 17;
2377
2378 for (i = 0; i < 4; i++) {
2379 int idx = EXT_CSD_GP_SIZE_MULT + i * 3;
2380 uint mult = (ext_csd[idx + 2] << 16) +
2381 (ext_csd[idx + 1] << 8) + ext_csd[idx];
2382 if (mult)
2383 has_parts = true;
2384 if (!part_completed)
2385 continue;
2386 mmc->capacity_gp[i] = mult;
2387 mmc->capacity_gp[i] *=
2388 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2389 mmc->capacity_gp[i] *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2390 mmc->capacity_gp[i] <<= 19;
2391 }
2392
Jean-Jacques Hiblotc94c5472018-01-04 15:23:35 +01002393#ifndef CONFIG_SPL_BUILD
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002394 if (part_completed) {
2395 mmc->enh_user_size =
2396 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 2] << 16) +
2397 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 1] << 8) +
2398 ext_csd[EXT_CSD_ENH_SIZE_MULT];
2399 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2400 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2401 mmc->enh_user_size <<= 19;
2402 mmc->enh_user_start =
2403 (ext_csd[EXT_CSD_ENH_START_ADDR + 3] << 24) +
2404 (ext_csd[EXT_CSD_ENH_START_ADDR + 2] << 16) +
2405 (ext_csd[EXT_CSD_ENH_START_ADDR + 1] << 8) +
2406 ext_csd[EXT_CSD_ENH_START_ADDR];
2407 if (mmc->high_capacity)
2408 mmc->enh_user_start <<= 9;
2409 }
Jean-Jacques Hiblotc94c5472018-01-04 15:23:35 +01002410#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002411
2412 /*
2413 * Host needs to enable ERASE_GRP_DEF bit if device is
2414 * partitioned. This bit will be lost every time after a reset
2415 * or power off. This will affect erase size.
2416 */
2417 if (part_completed)
2418 has_parts = true;
2419 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) &&
2420 (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB))
2421 has_parts = true;
2422 if (has_parts) {
2423 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2424 EXT_CSD_ERASE_GROUP_DEF, 1);
2425
2426 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002427 goto error;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002428
2429 ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
2430 }
2431
2432 if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01) {
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002433#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002434 /* Read out group size from ext_csd */
2435 mmc->erase_grp_size =
2436 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002437#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002438 /*
2439 * if high capacity and partition setting completed
2440 * SEC_COUNT is valid even if it is smaller than 2 GiB
2441 * JEDEC Standard JESD84-B45, 6.2.4
2442 */
2443 if (mmc->high_capacity && part_completed) {
2444 capacity = (ext_csd[EXT_CSD_SEC_CNT]) |
2445 (ext_csd[EXT_CSD_SEC_CNT + 1] << 8) |
2446 (ext_csd[EXT_CSD_SEC_CNT + 2] << 16) |
2447 (ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
2448 capacity *= MMC_MAX_BLOCK_LEN;
2449 mmc->capacity_user = capacity;
2450 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002451 }
2452#if CONFIG_IS_ENABLED(MMC_WRITE)
2453 else {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002454 /* Calculate the group size from the csd value. */
2455 int erase_gsz, erase_gmul;
2456
2457 erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
2458 erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
2459 mmc->erase_grp_size = (erase_gsz + 1)
2460 * (erase_gmul + 1);
2461 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002462#endif
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002463#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002464 mmc->hc_wp_grp_size = 1024
2465 * ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
2466 * ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002467#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002468
2469 mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
2470
Loic Poulainc0aadbb2023-01-26 10:24:17 +01002471 mmc->can_trim =
2472 !!(ext_csd[EXT_CSD_SEC_FEATURE] & EXT_CSD_SEC_FEATURE_TRIM_EN);
2473
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002474 return 0;
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002475error:
2476 if (mmc->ext_csd) {
Marek Vasuta318a7a2018-04-15 00:37:11 +02002477#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002478 free(mmc->ext_csd);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002479#endif
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002480 mmc->ext_csd = NULL;
2481 }
2482 return err;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002483}
2484
Kim Phillips87ea3892012-10-29 13:34:43 +00002485static int mmc_startup(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002486{
Stephen Warrene315ae82013-06-11 15:14:01 -06002487 int err, i;
Andy Flemingad347bb2008-10-30 16:41:01 -05002488 uint mult, freq;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002489 u64 cmult, csize;
Andy Flemingad347bb2008-10-30 16:41:01 -05002490 struct mmc_cmd cmd;
Simon Glasse5db1152016-05-01 13:52:35 -06002491 struct blk_desc *bdesc;
Andy Flemingad347bb2008-10-30 16:41:01 -05002492
Thomas Chou1254c3d2010-12-24 13:12:21 +00002493#ifdef CONFIG_MMC_SPI_CRC_ON
2494 if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
2495 cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
2496 cmd.resp_type = MMC_RSP_R1;
2497 cmd.cmdarg = 1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002498 err = mmc_send_cmd(mmc, &cmd, NULL);
Thomas Chou1254c3d2010-12-24 13:12:21 +00002499 if (err)
2500 return err;
2501 }
2502#endif
2503
Andy Flemingad347bb2008-10-30 16:41:01 -05002504 /* Put the Card in Identify Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002505 cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
2506 MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
Andy Flemingad347bb2008-10-30 16:41:01 -05002507 cmd.resp_type = MMC_RSP_R2;
2508 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002509
Sean Anderson86325092020-10-17 08:36:27 -04002510 err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_SEND_CID, 4);
Andy Flemingad347bb2008-10-30 16:41:01 -05002511 if (err)
2512 return err;
2513
2514 memcpy(mmc->cid, cmd.response, 16);
2515
2516 /*
2517 * For MMC cards, set the Relative Address.
2518 * For SD cards, get the Relatvie Address.
2519 * This also puts the cards into Standby State
2520 */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002521 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2522 cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
2523 cmd.cmdarg = mmc->rca << 16;
2524 cmd.resp_type = MMC_RSP_R6;
Andy Flemingad347bb2008-10-30 16:41:01 -05002525
Thomas Chou1254c3d2010-12-24 13:12:21 +00002526 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002527
Thomas Chou1254c3d2010-12-24 13:12:21 +00002528 if (err)
2529 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002530
Thomas Chou1254c3d2010-12-24 13:12:21 +00002531 if (IS_SD(mmc))
2532 mmc->rca = (cmd.response[0] >> 16) & 0xffff;
2533 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002534
2535 /* Get the Card-Specific Data */
2536 cmd.cmdidx = MMC_CMD_SEND_CSD;
2537 cmd.resp_type = MMC_RSP_R2;
2538 cmd.cmdarg = mmc->rca << 16;
Andy Flemingad347bb2008-10-30 16:41:01 -05002539
2540 err = mmc_send_cmd(mmc, &cmd, NULL);
2541
2542 if (err)
2543 return err;
2544
Rabin Vincentb6eed942009-04-05 13:30:56 +05302545 mmc->csd[0] = cmd.response[0];
2546 mmc->csd[1] = cmd.response[1];
2547 mmc->csd[2] = cmd.response[2];
2548 mmc->csd[3] = cmd.response[3];
Andy Flemingad347bb2008-10-30 16:41:01 -05002549
2550 if (mmc->version == MMC_VERSION_UNKNOWN) {
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302551 int version = (cmd.response[0] >> 26) & 0xf;
Andy Flemingad347bb2008-10-30 16:41:01 -05002552
2553 switch (version) {
Bin Meng4a4ef872016-03-17 21:53:13 -07002554 case 0:
2555 mmc->version = MMC_VERSION_1_2;
2556 break;
2557 case 1:
2558 mmc->version = MMC_VERSION_1_4;
2559 break;
2560 case 2:
2561 mmc->version = MMC_VERSION_2_2;
2562 break;
2563 case 3:
2564 mmc->version = MMC_VERSION_3;
2565 break;
2566 case 4:
2567 mmc->version = MMC_VERSION_4;
2568 break;
2569 default:
2570 mmc->version = MMC_VERSION_1_2;
2571 break;
Andy Flemingad347bb2008-10-30 16:41:01 -05002572 }
2573 }
2574
2575 /* divide frequency by 10, since the mults are 10x bigger */
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302576 freq = fbase[(cmd.response[0] & 0x7)];
2577 mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
Andy Flemingad347bb2008-10-30 16:41:01 -05002578
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002579 mmc->legacy_speed = freq * mult;
Heinrich Schuchardt82479d42024-01-04 04:49:42 +01002580 if (!mmc->legacy_speed)
2581 log_debug("TRAN_SPEED: reserved value");
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002582 mmc_select_mode(mmc, MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05002583
Markus Niebel03951412013-12-16 13:40:46 +01002584 mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
Rabin Vincentb6eed942009-04-05 13:30:56 +05302585 mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002586#if CONFIG_IS_ENABLED(MMC_WRITE)
Andy Flemingad347bb2008-10-30 16:41:01 -05002587
2588 if (IS_SD(mmc))
2589 mmc->write_bl_len = mmc->read_bl_len;
2590 else
Rabin Vincentb6eed942009-04-05 13:30:56 +05302591 mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002592#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002593
2594 if (mmc->high_capacity) {
2595 csize = (mmc->csd[1] & 0x3f) << 16
2596 | (mmc->csd[2] & 0xffff0000) >> 16;
2597 cmult = 8;
2598 } else {
2599 csize = (mmc->csd[1] & 0x3ff) << 2
2600 | (mmc->csd[2] & 0xc0000000) >> 30;
2601 cmult = (mmc->csd[2] & 0x00038000) >> 15;
2602 }
2603
Stephen Warrene315ae82013-06-11 15:14:01 -06002604 mmc->capacity_user = (csize + 1) << (cmult + 2);
2605 mmc->capacity_user *= mmc->read_bl_len;
2606 mmc->capacity_boot = 0;
2607 mmc->capacity_rpmb = 0;
2608 for (i = 0; i < 4; i++)
2609 mmc->capacity_gp[i] = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002610
Simon Glassa09c2b72013-04-03 08:54:30 +00002611 if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN)
2612 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -05002613
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002614#if CONFIG_IS_ENABLED(MMC_WRITE)
Simon Glassa09c2b72013-04-03 08:54:30 +00002615 if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
2616 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002617#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002618
Markus Niebel03951412013-12-16 13:40:46 +01002619 if ((mmc->dsr_imp) && (0xffffffff != mmc->dsr)) {
2620 cmd.cmdidx = MMC_CMD_SET_DSR;
2621 cmd.cmdarg = (mmc->dsr & 0xffff) << 16;
2622 cmd.resp_type = MMC_RSP_NONE;
2623 if (mmc_send_cmd(mmc, &cmd, NULL))
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002624 pr_warn("MMC: SET_DSR failed\n");
Markus Niebel03951412013-12-16 13:40:46 +01002625 }
2626
Andy Flemingad347bb2008-10-30 16:41:01 -05002627 /* Select the card, and put it into Transfer Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002628 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2629 cmd.cmdidx = MMC_CMD_SELECT_CARD;
Ajay Bhargav4a32fba2011-10-05 03:13:23 +00002630 cmd.resp_type = MMC_RSP_R1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002631 cmd.cmdarg = mmc->rca << 16;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002632 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002633
Thomas Chou1254c3d2010-12-24 13:12:21 +00002634 if (err)
2635 return err;
2636 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002637
Lei Wenea526762011-06-22 17:03:31 +00002638 /*
2639 * For SD, its erase group is always one sector
2640 */
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002641#if CONFIG_IS_ENABLED(MMC_WRITE)
Lei Wenea526762011-06-22 17:03:31 +00002642 mmc->erase_grp_size = 1;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002643#endif
Lei Wen31b99802011-05-02 16:26:26 +00002644 mmc->part_config = MMCPART_NOAVAILABLE;
Diego Santa Cruza7a75992014-12-23 10:50:27 +01002645
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002646 err = mmc_startup_v4(mmc);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002647 if (err)
2648 return err;
Sukumar Ghorai232293c2010-09-20 18:29:29 +05302649
Simon Glasse5db1152016-05-01 13:52:35 -06002650 err = mmc_set_capacity(mmc, mmc_get_blk_desc(mmc)->hwpart);
Stephen Warrene315ae82013-06-11 15:14:01 -06002651 if (err)
2652 return err;
2653
Marek Vasuta318a7a2018-04-15 00:37:11 +02002654#if CONFIG_IS_ENABLED(MMC_TINY)
2655 mmc_set_clock(mmc, mmc->legacy_speed, false);
Faiz Abbas01db77e2020-02-26 13:44:32 +05302656 mmc_select_mode(mmc, MMC_LEGACY);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002657 mmc_set_bus_width(mmc, 1);
2658#else
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002659 if (IS_SD(mmc)) {
2660 err = sd_get_capabilities(mmc);
2661 if (err)
2662 return err;
2663 err = sd_select_mode_and_width(mmc, mmc->card_caps);
2664 } else {
2665 err = mmc_get_capabilities(mmc);
2666 if (err)
2667 return err;
Masahiro Yamadabf1f25c2020-01-23 14:31:12 +09002668 err = mmc_select_mode_and_width(mmc, mmc->card_caps);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002669 }
Marek Vasuta318a7a2018-04-15 00:37:11 +02002670#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002671 if (err)
2672 return err;
2673
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002674 mmc->best_mode = mmc->selected_mode;
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00002675
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002676 /* Fix the block length for DDR mode */
2677 if (mmc->ddr_mode) {
2678 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002679#if CONFIG_IS_ENABLED(MMC_WRITE)
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002680 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002681#endif
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002682 }
2683
Andy Flemingad347bb2008-10-30 16:41:01 -05002684 /* fill in device description */
Simon Glasse5db1152016-05-01 13:52:35 -06002685 bdesc = mmc_get_blk_desc(mmc);
2686 bdesc->lun = 0;
2687 bdesc->hwpart = 0;
2688 bdesc->type = 0;
2689 bdesc->blksz = mmc->read_bl_len;
2690 bdesc->log2blksz = LOG2(bdesc->blksz);
2691 bdesc->lba = lldiv(mmc->capacity, mmc->read_bl_len);
Sjoerd Simonsd67754f2015-12-04 23:27:40 +01002692#if !defined(CONFIG_SPL_BUILD) || \
2693 (defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \
Simon Glass7611ac62019-09-25 08:56:27 -06002694 !CONFIG_IS_ENABLED(USE_TINY_PRINTF))
Simon Glasse5db1152016-05-01 13:52:35 -06002695 sprintf(bdesc->vendor, "Man %06x Snr %04x%04x",
Taylor Hutt7367ec22012-10-20 17:15:59 +00002696 mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
2697 (mmc->cid[3] >> 16) & 0xffff);
Simon Glasse5db1152016-05-01 13:52:35 -06002698 sprintf(bdesc->product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002699 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
2700 (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
2701 (mmc->cid[2] >> 24) & 0xff);
Simon Glasse5db1152016-05-01 13:52:35 -06002702 sprintf(bdesc->revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002703 (mmc->cid[2] >> 16) & 0xf);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002704#else
Simon Glasse5db1152016-05-01 13:52:35 -06002705 bdesc->vendor[0] = 0;
2706 bdesc->product[0] = 0;
2707 bdesc->revision[0] = 0;
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002708#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002709
Andre Przywara17798042018-12-17 10:05:45 +00002710#if !defined(CONFIG_DM_MMC) && (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT))
2711 part_init(bdesc);
2712#endif
2713
Andy Flemingad347bb2008-10-30 16:41:01 -05002714 return 0;
2715}
2716
Kim Phillips87ea3892012-10-29 13:34:43 +00002717static int mmc_send_if_cond(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002718{
2719 struct mmc_cmd cmd;
2720 int err;
2721
2722 cmd.cmdidx = SD_CMD_SEND_IF_COND;
2723 /* We set the bit if the host supports voltages between 2.7 and 3.6 V */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002724 cmd.cmdarg = ((mmc->cfg->voltages & 0xff8000) != 0) << 8 | 0xaa;
Andy Flemingad347bb2008-10-30 16:41:01 -05002725 cmd.resp_type = MMC_RSP_R7;
Andy Flemingad347bb2008-10-30 16:41:01 -05002726
2727 err = mmc_send_cmd(mmc, &cmd, NULL);
2728
2729 if (err)
2730 return err;
2731
Rabin Vincentb6eed942009-04-05 13:30:56 +05302732 if ((cmd.response[0] & 0xff) != 0xaa)
Jaehoon Chung7825d202016-07-19 16:33:36 +09002733 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002734 else
2735 mmc->version = SD_VERSION_2;
2736
2737 return 0;
2738}
2739
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002740#if !CONFIG_IS_ENABLED(DM_MMC)
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002741/* board-specific MMC power initializations. */
2742__weak void board_mmc_power_init(void)
2743{
2744}
Simon Glass833b80d2017-04-22 19:10:56 -06002745#endif
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002746
Peng Fan15305962016-10-11 15:08:43 +08002747static int mmc_power_init(struct mmc *mmc)
2748{
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002749#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002750#if CONFIG_IS_ENABLED(DM_REGULATOR)
Peng Fan15305962016-10-11 15:08:43 +08002751 int ret;
2752
2753 ret = device_get_supply_regulator(mmc->dev, "vmmc-supply",
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002754 &mmc->vmmc_supply);
2755 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002756 pr_debug("%s: No vmmc supply\n", mmc->dev->name);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002757
2758 ret = device_get_supply_regulator(mmc->dev, "vqmmc-supply",
2759 &mmc->vqmmc_supply);
2760 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002761 pr_debug("%s: No vqmmc supply\n", mmc->dev->name);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002762#endif
2763#else /* !CONFIG_DM_MMC */
2764 /*
2765 * Driver model should use a regulator, as above, rather than calling
2766 * out to board code.
2767 */
2768 board_mmc_power_init();
2769#endif
2770 return 0;
2771}
2772
2773/*
2774 * put the host in the initial state:
2775 * - turn on Vdd (card power supply)
2776 * - configure the bus width and clock to minimal values
2777 */
2778static void mmc_set_initial_state(struct mmc *mmc)
2779{
2780 int err;
2781
2782 /* First try to set 3.3V. If it fails set to 1.8V */
2783 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
2784 if (err != 0)
2785 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
2786 if (err != 0)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002787 pr_warn("mmc: failed to set signal voltage\n");
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002788
2789 mmc_select_mode(mmc, MMC_LEGACY);
2790 mmc_set_bus_width(mmc, 1);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002791 mmc_set_clock(mmc, 0, MMC_CLK_ENABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002792}
Peng Fan15305962016-10-11 15:08:43 +08002793
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002794static int mmc_power_on(struct mmc *mmc)
2795{
2796#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002797 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002798 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2799 true);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002800
Jonas Karlman0f28e182023-07-19 21:20:59 +00002801 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002802 printf("Error enabling VMMC supply : %d\n", ret);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002803 return ret;
2804 }
Peng Fan15305962016-10-11 15:08:43 +08002805 }
2806#endif
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002807 return 0;
2808}
2809
2810static int mmc_power_off(struct mmc *mmc)
2811{
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002812 mmc_set_clock(mmc, 0, MMC_CLK_DISABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002813#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
2814 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002815 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2816 false);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002817
Jonas Karlman0f28e182023-07-19 21:20:59 +00002818 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002819 pr_debug("Error disabling VMMC supply : %d\n", ret);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002820 return ret;
2821 }
2822 }
Simon Glass833b80d2017-04-22 19:10:56 -06002823#endif
Peng Fan15305962016-10-11 15:08:43 +08002824 return 0;
2825}
2826
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002827static int mmc_power_cycle(struct mmc *mmc)
2828{
2829 int ret;
2830
2831 ret = mmc_power_off(mmc);
2832 if (ret)
2833 return ret;
Yann Gautier6f558332019-09-19 17:56:12 +02002834
2835 ret = mmc_host_power_cycle(mmc);
2836 if (ret)
2837 return ret;
2838
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002839 /*
2840 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
2841 * to be on the safer side.
2842 */
2843 udelay(2000);
2844 return mmc_power_on(mmc);
2845}
2846
Pali Rohár7c639622021-07-14 16:37:29 +02002847int mmc_get_op_cond(struct mmc *mmc, bool quiet)
Andy Flemingad347bb2008-10-30 16:41:01 -05002848{
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002849 bool uhs_en = supports_uhs(mmc->cfg->host_caps);
Macpaul Lin028bde12011-11-14 23:35:39 +00002850 int err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002851
Lei Wen31b99802011-05-02 16:26:26 +00002852 if (mmc->has_init)
2853 return 0;
2854
Peng Fan15305962016-10-11 15:08:43 +08002855 err = mmc_power_init(mmc);
2856 if (err)
2857 return err;
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002858
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002859#ifdef CONFIG_MMC_QUIRKS
2860 mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN |
Joel Johnson5ea041b2020-01-11 09:08:14 -07002861 MMC_QUIRK_RETRY_SEND_CID |
2862 MMC_QUIRK_RETRY_APP_CMD;
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002863#endif
2864
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002865 err = mmc_power_cycle(mmc);
2866 if (err) {
2867 /*
2868 * if power cycling is not supported, we should not try
2869 * to use the UHS modes, because we wouldn't be able to
2870 * recover from an error during the UHS initialization.
2871 */
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002872 pr_debug("Unable to do a full power cycle. Disabling the UHS modes for safety\n");
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002873 uhs_en = false;
2874 mmc->host_caps &= ~UHS_CAPS;
2875 err = mmc_power_on(mmc);
2876 }
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002877 if (err)
2878 return err;
2879
Simon Glasseba48f92017-07-29 11:35:31 -06002880#if CONFIG_IS_ENABLED(DM_MMC)
Yangbo Luc46f5d72020-09-01 16:57:59 +08002881 /*
2882 * Re-initialization is needed to clear old configuration for
2883 * mmc rescan.
2884 */
2885 err = mmc_reinit(mmc);
Simon Glass394dfc02016-06-12 23:30:22 -06002886#else
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02002887 /* made sure it's not NULL earlier */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002888 err = mmc->cfg->ops->init(mmc);
Yangbo Luc46f5d72020-09-01 16:57:59 +08002889#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002890 if (err)
2891 return err;
Andrew Gabbasov9fc2a412014-12-01 06:59:09 -06002892 mmc->ddr_mode = 0;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02002893
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002894retry:
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002895 mmc_set_initial_state(mmc);
Jean-Jacques Hiblot5f23d872017-09-21 16:30:01 +02002896
Andy Flemingad347bb2008-10-30 16:41:01 -05002897 /* Reset the Card */
2898 err = mmc_go_idle(mmc);
2899
2900 if (err)
2901 return err;
2902
Marcel Ziswilerb2b7fc82019-05-20 02:44:53 +02002903 /* The internal partition reset to user partition(0) at every CMD0 */
Simon Glasse5db1152016-05-01 13:52:35 -06002904 mmc_get_blk_desc(mmc)->hwpart = 0;
Lei Wen31b99802011-05-02 16:26:26 +00002905
Andy Flemingad347bb2008-10-30 16:41:01 -05002906 /* Test for SD version 2 */
Macpaul Lin028bde12011-11-14 23:35:39 +00002907 err = mmc_send_if_cond(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05002908
Andy Flemingad347bb2008-10-30 16:41:01 -05002909 /* Now try to get the SD card's operating condition */
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002910 err = sd_send_op_cond(mmc, uhs_en);
2911 if (err && uhs_en) {
2912 uhs_en = false;
2913 mmc_power_cycle(mmc);
2914 goto retry;
2915 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002916
2917 /* If the command timed out, we check for an MMC card */
Jaehoon Chung7825d202016-07-19 16:33:36 +09002918 if (err == -ETIMEDOUT) {
Andy Flemingad347bb2008-10-30 16:41:01 -05002919 err = mmc_send_op_cond(mmc);
2920
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002921 if (err) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002922#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Pali Rohár7c639622021-07-14 16:37:29 +02002923 if (!quiet)
2924 pr_err("Card did not respond to voltage select! : %d\n", err);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002925#endif
Jaehoon Chung7825d202016-07-19 16:33:36 +09002926 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002927 }
2928 }
2929
Jon Nettleton2663fe42018-06-11 15:26:19 +03002930 return err;
2931}
2932
2933int mmc_start_init(struct mmc *mmc)
2934{
2935 bool no_card;
2936 int err = 0;
2937
2938 /*
2939 * all hosts are capable of 1 bit bus-width and able to use the legacy
2940 * timings.
2941 */
Faiz Abbas01db77e2020-02-26 13:44:32 +05302942 mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) |
Aswath Govindrajubb5b9fe2021-08-13 23:04:41 +05302943 MMC_MODE_1BIT;
2944
2945 if (IS_ENABLED(CONFIG_MMC_SPEED_MODE_SET)) {
2946 if (mmc->user_speed_mode != MMC_MODES_END) {
2947 int i;
2948 /* set host caps */
2949 if (mmc->host_caps & MMC_CAP(mmc->user_speed_mode)) {
2950 /* Remove all existing speed capabilities */
2951 for (i = MMC_LEGACY; i < MMC_MODES_END; i++)
2952 mmc->host_caps &= ~MMC_CAP(i);
2953 mmc->host_caps |= (MMC_CAP(mmc->user_speed_mode)
2954 | MMC_CAP(MMC_LEGACY) |
2955 MMC_MODE_1BIT);
2956 } else {
2957 pr_err("bus_mode requested is not supported\n");
2958 return -EINVAL;
2959 }
2960 }
2961 }
Faiz Abbasf6fd4ec2020-02-26 13:44:30 +05302962#if CONFIG_IS_ENABLED(DM_MMC)
2963 mmc_deferred_probe(mmc);
2964#endif
Jon Nettleton2663fe42018-06-11 15:26:19 +03002965#if !defined(CONFIG_MMC_BROKEN_CD)
Jon Nettleton2663fe42018-06-11 15:26:19 +03002966 no_card = mmc_getcd(mmc) == 0;
2967#else
2968 no_card = 0;
2969#endif
2970#if !CONFIG_IS_ENABLED(DM_MMC)
Baruch Siach0448ce62019-07-22 15:52:12 +03002971 /* we pretend there's no card when init is NULL */
Jon Nettleton2663fe42018-06-11 15:26:19 +03002972 no_card = no_card || (mmc->cfg->ops->init == NULL);
2973#endif
2974 if (no_card) {
2975 mmc->has_init = 0;
2976#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
2977 pr_err("MMC: no card present\n");
2978#endif
2979 return -ENOMEDIUM;
2980 }
2981
Pali Rohár7c639622021-07-14 16:37:29 +02002982 err = mmc_get_op_cond(mmc, false);
Jon Nettleton2663fe42018-06-11 15:26:19 +03002983
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002984 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00002985 mmc->init_in_progress = 1;
2986
2987 return err;
2988}
2989
2990static int mmc_complete_init(struct mmc *mmc)
2991{
2992 int err = 0;
2993
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002994 mmc->init_in_progress = 0;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00002995 if (mmc->op_cond_pending)
2996 err = mmc_complete_op_cond(mmc);
2997
2998 if (!err)
2999 err = mmc_startup(mmc);
Lei Wen31b99802011-05-02 16:26:26 +00003000 if (err)
3001 mmc->has_init = 0;
3002 else
3003 mmc->has_init = 1;
3004 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05003005}
3006
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003007int mmc_init(struct mmc *mmc)
3008{
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003009 int err = 0;
Vipul Kumardbad7b42018-05-03 12:20:54 +05303010 __maybe_unused ulong start;
Simon Glass5f4bd8c2017-07-04 13:31:19 -06003011#if CONFIG_IS_ENABLED(DM_MMC)
Simon Glass59bc6f22016-05-01 13:52:41 -06003012 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003013
Simon Glass59bc6f22016-05-01 13:52:41 -06003014 upriv->mmc = mmc;
3015#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003016 if (mmc->has_init)
3017 return 0;
Mateusz Zalegada351782014-04-29 20:15:30 +02003018
3019 start = get_timer(0);
3020
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003021 if (!mmc->init_in_progress)
3022 err = mmc_start_init(mmc);
3023
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003024 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003025 err = mmc_complete_init(mmc);
Jagan Teki9bee2b52017-01-10 11:18:43 +01003026 if (err)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09003027 pr_info("%s: %d, time %lu\n", __func__, err, get_timer(start));
Jagan Teki9bee2b52017-01-10 11:18:43 +01003028
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003029 return err;
3030}
3031
Marek Vasuta4773fc2019-01-29 04:45:51 +01003032int mmc_deinit(struct mmc *mmc)
3033{
3034 u32 caps_filtered;
3035
Marek Vasut67c77f92024-03-17 04:01:22 +01003036 if (!CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) &&
3037 !CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) &&
3038 !CONFIG_IS_ENABLED(MMC_HS400_SUPPORT))
3039 return 0;
3040
Marek Vasuta4773fc2019-01-29 04:45:51 +01003041 if (!mmc->has_init)
3042 return 0;
3043
3044 if (IS_SD(mmc)) {
3045 caps_filtered = mmc->card_caps &
3046 ~(MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) |
3047 MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
3048 MMC_CAP(UHS_SDR104));
3049
3050 return sd_select_mode_and_width(mmc, caps_filtered);
3051 } else {
3052 caps_filtered = mmc->card_caps &
Ye Li3679e802021-08-17 17:20:34 +08003053 ~(MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_HS_400) | MMC_CAP(MMC_HS_400_ES));
Marek Vasuta4773fc2019-01-29 04:45:51 +01003054
3055 return mmc_select_mode_and_width(mmc, caps_filtered);
3056 }
3057}
Marek Vasuta4773fc2019-01-29 04:45:51 +01003058
Markus Niebel03951412013-12-16 13:40:46 +01003059int mmc_set_dsr(struct mmc *mmc, u16 val)
3060{
3061 mmc->dsr = val;
3062 return 0;
3063}
3064
Jeroen Hofstee47726302014-07-10 22:46:28 +02003065/* CPU-specific MMC initializations */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003066__weak int cpu_mmc_init(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003067{
3068 return -1;
3069}
3070
Jeroen Hofstee47726302014-07-10 22:46:28 +02003071/* board-specific MMC initializations. */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003072__weak int board_mmc_init(struct bd_info *bis)
Jeroen Hofstee47726302014-07-10 22:46:28 +02003073{
3074 return -1;
3075}
Andy Flemingad347bb2008-10-30 16:41:01 -05003076
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003077void mmc_set_preinit(struct mmc *mmc, int preinit)
3078{
3079 mmc->preinit = preinit;
3080}
3081
Faiz Abbasb3857fd2018-02-12 19:35:24 +05303082#if CONFIG_IS_ENABLED(DM_MMC)
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003083static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003084{
Simon Glass547cb342015-12-29 05:22:49 -07003085 int ret, i;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003086 struct uclass *uc;
Simon Glass547cb342015-12-29 05:22:49 -07003087 struct udevice *dev;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003088
3089 ret = uclass_get(UCLASS_MMC, &uc);
3090 if (ret)
3091 return ret;
3092
Simon Glass547cb342015-12-29 05:22:49 -07003093 /*
3094 * Try to add them in sequence order. Really with driver model we
3095 * should allow holes, but the current MMC list does not allow that.
3096 * So if we request 0, 1, 3 we will get 0, 1, 2.
3097 */
3098 for (i = 0; ; i++) {
3099 ret = uclass_get_device_by_seq(UCLASS_MMC, i, &dev);
3100 if (ret == -ENODEV)
3101 break;
3102 }
3103 uclass_foreach_dev(dev, uc) {
3104 ret = device_probe(dev);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003105 if (ret)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01003106 pr_err("%s - probe failed: %d\n", dev->name, ret);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003107 }
3108
3109 return 0;
3110}
3111#else
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003112static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003113{
3114 if (board_mmc_init(bis) < 0)
3115 cpu_mmc_init(bis);
3116
3117 return 0;
3118}
3119#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003120
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003121int mmc_initialize(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003122{
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003123 static int initialized = 0;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003124 int ret;
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003125 if (initialized) /* Avoid initializing mmc multiple times */
3126 return 0;
3127 initialized = 1;
3128
Simon Glass5f4bd8c2017-07-04 13:31:19 -06003129#if !CONFIG_IS_ENABLED(BLK)
Marek Vasutf537e392016-12-01 02:06:33 +01003130#if !CONFIG_IS_ENABLED(MMC_TINY)
Simon Glasse5db1152016-05-01 13:52:35 -06003131 mmc_list_init();
3132#endif
Marek Vasutf537e392016-12-01 02:06:33 +01003133#endif
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003134 ret = mmc_probe(bis);
3135 if (ret)
3136 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05003137
Ying Zhang9ff70262013-08-16 15:16:11 +08003138#ifndef CONFIG_SPL_BUILD
Andy Flemingad347bb2008-10-30 16:41:01 -05003139 print_mmc_devices(',');
Ying Zhang9ff70262013-08-16 15:16:11 +08003140#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05003141
Simon Glasse5db1152016-05-01 13:52:35 -06003142 mmc_do_preinit();
Andy Flemingad347bb2008-10-30 16:41:01 -05003143 return 0;
3144}
Tomas Melinc17dae52016-11-25 11:01:03 +02003145
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303146#if CONFIG_IS_ENABLED(DM_MMC)
3147int mmc_init_device(int num)
3148{
3149 struct udevice *dev;
3150 struct mmc *m;
3151 int ret;
3152
Aswath Govindraju57e2ccb2021-03-25 12:48:47 +05303153 if (uclass_get_device_by_seq(UCLASS_MMC, num, &dev)) {
3154 ret = uclass_get_device(UCLASS_MMC, num, &dev);
3155 if (ret)
3156 return ret;
3157 }
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303158
3159 m = mmc_get_mmc_dev(dev);
3160 if (!m)
3161 return 0;
Venkatesh Yadav Abbarapu6738fcb2022-09-29 10:22:49 +05303162
3163 /* Initialising user set speed mode */
3164 m->user_speed_mode = MMC_MODES_END;
3165
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303166 if (m->preinit)
3167 mmc_start_init(m);
3168
3169 return 0;
3170}
3171#endif
3172
Tomas Melinc17dae52016-11-25 11:01:03 +02003173#ifdef CONFIG_CMD_BKOPS_ENABLE
Marek Vasutefdeed62023-01-05 15:19:08 +01003174int mmc_set_bkops_enable(struct mmc *mmc, bool autobkops, bool enable)
Tomas Melinc17dae52016-11-25 11:01:03 +02003175{
3176 int err;
Marek Vasutefdeed62023-01-05 15:19:08 +01003177 u32 bit = autobkops ? BIT(1) : BIT(0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003178 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
3179
3180 err = mmc_send_ext_csd(mmc, ext_csd);
3181 if (err) {
3182 puts("Could not get ext_csd register values\n");
3183 return err;
3184 }
3185
3186 if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) {
3187 puts("Background operations not supported on device\n");
3188 return -EMEDIUMTYPE;
3189 }
3190
Marek Vasutefdeed62023-01-05 15:19:08 +01003191 if (enable && (ext_csd[EXT_CSD_BKOPS_EN] & bit)) {
Tomas Melinc17dae52016-11-25 11:01:03 +02003192 puts("Background operations already enabled\n");
3193 return 0;
3194 }
3195
Marek Vasutefdeed62023-01-05 15:19:08 +01003196 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN,
3197 enable ? bit : 0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003198 if (err) {
Marek Vasutefdeed62023-01-05 15:19:08 +01003199 printf("Failed to %sable manual background operations\n",
3200 enable ? "en" : "dis");
Tomas Melinc17dae52016-11-25 11:01:03 +02003201 return err;
3202 }
3203
Marek Vasutefdeed62023-01-05 15:19:08 +01003204 printf("%sabled %s background operations\n",
3205 enable ? "En" : "Dis", autobkops ? "auto" : "manual");
Tomas Melinc17dae52016-11-25 11:01:03 +02003206
3207 return 0;
3208}
3209#endif
David Woodhouse49fee032020-08-04 10:05:46 +01003210
3211__weak int mmc_get_env_dev(void)
3212{
3213#ifdef CONFIG_SYS_MMC_ENV_DEV
3214 return CONFIG_SYS_MMC_ENV_DEV;
3215#else
3216 return 0;
3217#endif
3218}