blob: d96db7a0f836732ccea15bdd9b36df92c7e2b703 [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>
11#include <common.h>
Simon Glass655306c2020-05-10 11:39:58 -060012#include <blk.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050013#include <command.h>
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -060014#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060015#include <log.h>
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -060016#include <dm/device-internal.h>
Stephen Warrenbf0c7852014-05-23 12:47:06 -060017#include <errno.h>
Andy Flemingad347bb2008-10-30 16:41:01 -050018#include <mmc.h>
19#include <part.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>
Rabin Vincent69d4e2c2009-04-05 13:30:54 +053027#include <div64.h>
Paul Burton8d30cc92013-09-09 15:30:26 +010028#include "mmc_private.h"
Andy Flemingad347bb2008-10-30 16:41:01 -050029
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +020030#define DEFAULT_CMD6_TIMEOUT_MS 500
31
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +020032static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
Marek Vasutf537e392016-12-01 02:06:33 +010033
Simon Glasseba48f92017-07-29 11:35:31 -060034#if !CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020035
Sam Protsenkodb174c62019-08-14 22:52:51 +030036static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020037{
Loic Poulain9c32f4f2022-05-26 16:37:21 +020038 if (mmc->cfg->ops->wait_dat0)
39 return mmc->cfg->ops->wait_dat0(mmc, state, timeout_us);
40
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +020041 return -ENOSYS;
42}
43
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +020044__weak int board_mmc_getwp(struct mmc *mmc)
Nikita Kiryanov020f2612012-12-03 02:19:46 +000045{
46 return -1;
47}
48
49int mmc_getwp(struct mmc *mmc)
50{
51 int wp;
52
53 wp = board_mmc_getwp(mmc);
54
Peter Korsgaardf7b15102013-03-21 04:00:03 +000055 if (wp < 0) {
Pantelis Antoniou2c850462014-03-11 19:34:20 +020056 if (mmc->cfg->ops->getwp)
57 wp = mmc->cfg->ops->getwp(mmc);
Peter Korsgaardf7b15102013-03-21 04:00:03 +000058 else
59 wp = 0;
60 }
Nikita Kiryanov020f2612012-12-03 02:19:46 +000061
62 return wp;
63}
64
Jeroen Hofstee47726302014-07-10 22:46:28 +020065__weak int board_mmc_getcd(struct mmc *mmc)
66{
Stefano Babic6e00edf2010-02-05 15:04:43 +010067 return -1;
68}
Simon Glass394dfc02016-06-12 23:30:22 -060069#endif
Stefano Babic6e00edf2010-02-05 15:04:43 +010070
Simon Glassb23d96e2016-06-12 23:30:20 -060071#ifdef CONFIG_MMC_TRACE
72void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
Andy Flemingad347bb2008-10-30 16:41:01 -050073{
Simon Glassb23d96e2016-06-12 23:30:20 -060074 printf("CMD_SEND:%d\n", cmd->cmdidx);
Marek Vasut6eeee302019-03-23 18:54:45 +010075 printf("\t\tARG\t\t\t 0x%08x\n", cmd->cmdarg);
Simon Glassb23d96e2016-06-12 23:30:20 -060076}
Marek Vasutdccb6082012-03-15 18:41:35 +000077
Simon Glassb23d96e2016-06-12 23:30:20 -060078void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret)
79{
Raffaele Recalcati894b1e22011-03-11 02:01:14 +000080 int i;
81 u8 *ptr;
82
Bin Meng8d1ad1e2016-03-17 21:53:14 -070083 if (ret) {
84 printf("\t\tRET\t\t\t %d\n", ret);
85 } else {
86 switch (cmd->resp_type) {
87 case MMC_RSP_NONE:
88 printf("\t\tMMC_RSP_NONE\n");
89 break;
90 case MMC_RSP_R1:
Marek Vasut6eeee302019-03-23 18:54:45 +010091 printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -070092 cmd->response[0]);
93 break;
94 case MMC_RSP_R1b:
Marek Vasut6eeee302019-03-23 18:54:45 +010095 printf("\t\tMMC_RSP_R1b\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -070096 cmd->response[0]);
97 break;
98 case MMC_RSP_R2:
Marek Vasut6eeee302019-03-23 18:54:45 +010099 printf("\t\tMMC_RSP_R2\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700100 cmd->response[0]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100101 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700102 cmd->response[1]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100103 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700104 cmd->response[2]);
Marek Vasut6eeee302019-03-23 18:54:45 +0100105 printf("\t\t \t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700106 cmd->response[3]);
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000107 printf("\n");
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700108 printf("\t\t\t\t\tDUMPING DATA\n");
109 for (i = 0; i < 4; i++) {
110 int j;
111 printf("\t\t\t\t\t%03d - ", i*4);
112 ptr = (u8 *)&cmd->response[i];
113 ptr += 3;
114 for (j = 0; j < 4; j++)
Marek Vasut6eeee302019-03-23 18:54:45 +0100115 printf("%02x ", *ptr--);
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700116 printf("\n");
117 }
118 break;
119 case MMC_RSP_R3:
Marek Vasut6eeee302019-03-23 18:54:45 +0100120 printf("\t\tMMC_RSP_R3,4\t\t 0x%08x \n",
Bin Meng8d1ad1e2016-03-17 21:53:14 -0700121 cmd->response[0]);
122 break;
123 default:
124 printf("\t\tERROR MMC rsp not supported\n");
125 break;
Bin Meng4a4ef872016-03-17 21:53:13 -0700126 }
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000127 }
Simon Glassb23d96e2016-06-12 23:30:20 -0600128}
129
130void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
131{
132 int status;
133
134 status = (cmd->response[0] & MMC_STATUS_CURR_STATE) >> 9;
135 printf("CURR STATE:%d\n", status);
136}
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000137#endif
Simon Glassb23d96e2016-06-12 23:30:20 -0600138
Pali Rohár377ecee2022-04-03 00:20:10 +0200139#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG) || CONFIG_VAL(LOGLEVEL) >= LOGL_DEBUG
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200140const char *mmc_mode_name(enum bus_mode mode)
141{
142 static const char *const names[] = {
143 [MMC_LEGACY] = "MMC legacy",
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200144 [MMC_HS] = "MMC High Speed (26MHz)",
145 [SD_HS] = "SD High Speed (50MHz)",
146 [UHS_SDR12] = "UHS SDR12 (25MHz)",
147 [UHS_SDR25] = "UHS SDR25 (50MHz)",
148 [UHS_SDR50] = "UHS SDR50 (100MHz)",
149 [UHS_SDR104] = "UHS SDR104 (208MHz)",
150 [UHS_DDR50] = "UHS DDR50 (50MHz)",
151 [MMC_HS_52] = "MMC High Speed (52MHz)",
152 [MMC_DDR_52] = "MMC DDR52 (52MHz)",
153 [MMC_HS_200] = "HS200 (200MHz)",
Peng Fan46801252018-08-10 14:07:54 +0800154 [MMC_HS_400] = "HS400 (200MHz)",
Peng Faneede83b2019-07-10 14:43:07 +0800155 [MMC_HS_400_ES] = "HS400ES (200MHz)",
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200156 };
157
158 if (mode >= MMC_MODES_END)
159 return "Unknown mode";
160 else
161 return names[mode];
162}
163#endif
164
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200165static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
166{
167 static const int freqs[] = {
Jaehoon Chung7c5c7302018-01-30 14:10:16 +0900168 [MMC_LEGACY] = 25000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200169 [MMC_HS] = 26000000,
170 [SD_HS] = 50000000,
Jaehoon Chung7c5c7302018-01-30 14:10:16 +0900171 [MMC_HS_52] = 52000000,
172 [MMC_DDR_52] = 52000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200173 [UHS_SDR12] = 25000000,
174 [UHS_SDR25] = 50000000,
175 [UHS_SDR50] = 100000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200176 [UHS_DDR50] = 50000000,
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100177 [UHS_SDR104] = 208000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200178 [MMC_HS_200] = 200000000,
Peng Fan46801252018-08-10 14:07:54 +0800179 [MMC_HS_400] = 200000000,
Peng Faneede83b2019-07-10 14:43:07 +0800180 [MMC_HS_400_ES] = 200000000,
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200181 };
182
183 if (mode == MMC_LEGACY)
184 return mmc->legacy_speed;
185 else if (mode >= MMC_MODES_END)
186 return 0;
187 else
188 return freqs[mode];
189}
190
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200191static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
192{
193 mmc->selected_mode = mode;
Jean-Jacques Hiblot78422312017-09-21 16:29:55 +0200194 mmc->tran_speed = mmc_mode2freq(mmc, mode);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +0200195 mmc->ddr_mode = mmc_is_mode_ddr(mode);
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900196 pr_debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
197 mmc->tran_speed / 1000000);
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +0200198 return 0;
199}
200
Simon Glasseba48f92017-07-29 11:35:31 -0600201#if !CONFIG_IS_ENABLED(DM_MMC)
Simon Glassb23d96e2016-06-12 23:30:20 -0600202int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
203{
204 int ret;
205
206 mmmc_trace_before_send(mmc, cmd);
207 ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
208 mmmc_trace_after_send(mmc, cmd, ret);
209
Marek Vasutdccb6082012-03-15 18:41:35 +0000210 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -0500211}
Simon Glass394dfc02016-06-12 23:30:22 -0600212#endif
Andy Flemingad347bb2008-10-30 16:41:01 -0500213
Sean Anderson86325092020-10-17 08:36:27 -0400214/**
215 * mmc_send_cmd_retry() - send a command to the mmc device, retrying on error
216 *
217 * @dev: device to receive the command
218 * @cmd: command to send
219 * @data: additional data to send/receive
220 * @retries: how many times to retry; mmc_send_cmd is always called at least
221 * once
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100222 * Return: 0 if ok, -ve on error
Sean Anderson86325092020-10-17 08:36:27 -0400223 */
224static int mmc_send_cmd_retry(struct mmc *mmc, struct mmc_cmd *cmd,
225 struct mmc_data *data, uint retries)
226{
227 int ret;
228
229 do {
230 ret = mmc_send_cmd(mmc, cmd, data);
231 } while (ret && retries--);
232
233 return ret;
234}
235
236/**
237 * mmc_send_cmd_quirks() - send a command to the mmc device, retrying if a
238 * specific quirk is enabled
239 *
240 * @dev: device to receive the command
241 * @cmd: command to send
242 * @data: additional data to send/receive
243 * @quirk: retry only if this quirk is enabled
244 * @retries: how many times to retry; mmc_send_cmd is always called at least
245 * once
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100246 * Return: 0 if ok, -ve on error
Sean Anderson86325092020-10-17 08:36:27 -0400247 */
248static int mmc_send_cmd_quirks(struct mmc *mmc, struct mmc_cmd *cmd,
249 struct mmc_data *data, u32 quirk, uint retries)
250{
Simon Glass68f3ced2023-02-05 15:40:16 -0700251 if (IS_ENABLED(CONFIG_MMC_QUIRKS) && mmc->quirks & quirk)
Sean Anderson86325092020-10-17 08:36:27 -0400252 return mmc_send_cmd_retry(mmc, cmd, data, retries);
253 else
254 return mmc_send_cmd(mmc, cmd, data);
255}
256
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200257int mmc_send_status(struct mmc *mmc, unsigned int *status)
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000258{
259 struct mmc_cmd cmd;
Sean Anderson86325092020-10-17 08:36:27 -0400260 int ret;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000261
262 cmd.cmdidx = MMC_CMD_SEND_STATUS;
263 cmd.resp_type = MMC_RSP_R1;
Marek Vasutc4427392011-08-10 09:24:48 +0200264 if (!mmc_host_is_spi(mmc))
265 cmd.cmdarg = mmc->rca << 16;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000266
Sean Anderson86325092020-10-17 08:36:27 -0400267 ret = mmc_send_cmd_retry(mmc, &cmd, NULL, 4);
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200268 mmc_trace_state(mmc, &cmd);
Sean Anderson86325092020-10-17 08:36:27 -0400269 if (!ret)
270 *status = cmd.response[0];
271
272 return ret;
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200273}
274
Sam Protsenkodb174c62019-08-14 22:52:51 +0300275int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200276{
277 unsigned int status;
278 int err;
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +0200279
Sam Protsenkodb174c62019-08-14 22:52:51 +0300280 err = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
Jean-Jacques Hiblot4f04a322019-07-02 10:53:53 +0200281 if (err != -ENOSYS)
282 return err;
283
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200284 while (1) {
285 err = mmc_send_status(mmc, &status);
286 if (err)
287 return err;
288
289 if ((status & MMC_STATUS_RDY_FOR_DATA) &&
290 (status & MMC_STATUS_CURR_STATE) !=
291 MMC_STATE_PRG)
292 break;
293
294 if (status & MMC_STATUS_MASK) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100295#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200296 pr_err("Status Error: 0x%08x\n", status);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100297#endif
Jean-Jacques Hiblot443edbe2019-07-02 10:53:52 +0200298 return -ECOMM;
299 }
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000300
Sam Protsenkodb174c62019-08-14 22:52:51 +0300301 if (timeout_ms-- <= 0)
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500302 break;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000303
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500304 udelay(1000);
305 }
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000306
Sam Protsenkodb174c62019-08-14 22:52:51 +0300307 if (timeout_ms <= 0) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100308#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +0100309 pr_err("Timeout waiting card ready\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100310#endif
Jaehoon Chung7825d202016-07-19 16:33:36 +0900311 return -ETIMEDOUT;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000312 }
313
314 return 0;
315}
316
Paul Burton8d30cc92013-09-09 15:30:26 +0100317int mmc_set_blocklen(struct mmc *mmc, int len)
Andy Flemingad347bb2008-10-30 16:41:01 -0500318{
319 struct mmc_cmd cmd;
320
Andrew Gabbasov9fc2a412014-12-01 06:59:09 -0600321 if (mmc->ddr_mode)
Jaehoon Chung38ce30b2014-05-16 13:59:54 +0900322 return 0;
323
Andy Flemingad347bb2008-10-30 16:41:01 -0500324 cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
325 cmd.resp_type = MMC_RSP_R1;
326 cmd.cmdarg = len;
Andy Flemingad347bb2008-10-30 16:41:01 -0500327
Sean Anderson86325092020-10-17 08:36:27 -0400328 return mmc_send_cmd_quirks(mmc, &cmd, NULL,
329 MMC_QUIRK_RETRY_SET_BLOCKLEN, 4);
Andy Flemingad347bb2008-10-30 16:41:01 -0500330}
331
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100332#ifdef MMC_SUPPORTS_TUNING
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200333static const u8 tuning_blk_pattern_4bit[] = {
334 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
335 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
336 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
337 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
338 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
339 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
340 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
341 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
342};
343
344static const u8 tuning_blk_pattern_8bit[] = {
345 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
346 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
347 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
348 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
349 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
350 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
351 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
352 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
353 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
354 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
355 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
356 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
357 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
358 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
359 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
360 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
361};
362
363int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error)
364{
365 struct mmc_cmd cmd;
366 struct mmc_data data;
367 const u8 *tuning_block_pattern;
368 int size, err;
369
370 if (mmc->bus_width == 8) {
371 tuning_block_pattern = tuning_blk_pattern_8bit;
372 size = sizeof(tuning_blk_pattern_8bit);
373 } else if (mmc->bus_width == 4) {
374 tuning_block_pattern = tuning_blk_pattern_4bit;
375 size = sizeof(tuning_blk_pattern_4bit);
376 } else {
377 return -EINVAL;
378 }
379
380 ALLOC_CACHE_ALIGN_BUFFER(u8, data_buf, size);
381
382 cmd.cmdidx = opcode;
383 cmd.cmdarg = 0;
384 cmd.resp_type = MMC_RSP_R1;
385
386 data.dest = (void *)data_buf;
387 data.blocks = 1;
388 data.blocksize = size;
389 data.flags = MMC_DATA_READ;
390
391 err = mmc_send_cmd(mmc, &cmd, &data);
392 if (err)
393 return err;
394
395 if (memcmp(data_buf, tuning_block_pattern, size))
396 return -EIO;
397
398 return 0;
399}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100400#endif
Jean-Jacques Hiblot71264bb2017-09-21 16:30:12 +0200401
Hai Pham27abf9f2023-06-20 00:38:24 +0200402int mmc_send_stop_transmission(struct mmc *mmc, bool write)
403{
404 struct mmc_cmd cmd;
405
406 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
407 cmd.cmdarg = 0;
408 /*
409 * JEDEC Standard No. 84-B51 Page 126
410 * CMD12 STOP_TRANSMISSION R1/R1b[3]
411 * NOTE 3 R1 for read cases and R1b for write cases.
412 *
413 * Physical Layer Simplified Specification Version 9.00
414 * 7.3.1.3 Detailed Command Description
415 * CMD12 R1b
416 */
417 cmd.resp_type = (IS_SD(mmc) || write) ? MMC_RSP_R1b : MMC_RSP_R1;
418
419 return mmc_send_cmd(mmc, &cmd, NULL);
420}
421
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200422static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
Kim Phillips87ea3892012-10-29 13:34:43 +0000423 lbaint_t blkcnt)
Andy Flemingad347bb2008-10-30 16:41:01 -0500424{
425 struct mmc_cmd cmd;
426 struct mmc_data data;
427
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700428 if (blkcnt > 1)
429 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
430 else
431 cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
Andy Flemingad347bb2008-10-30 16:41:01 -0500432
433 if (mmc->high_capacity)
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700434 cmd.cmdarg = start;
Andy Flemingad347bb2008-10-30 16:41:01 -0500435 else
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700436 cmd.cmdarg = start * mmc->read_bl_len;
Andy Flemingad347bb2008-10-30 16:41:01 -0500437
438 cmd.resp_type = MMC_RSP_R1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500439
440 data.dest = dst;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700441 data.blocks = blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500442 data.blocksize = mmc->read_bl_len;
443 data.flags = MMC_DATA_READ;
444
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700445 if (mmc_send_cmd(mmc, &cmd, &data))
446 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500447
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700448 if (blkcnt > 1) {
Hai Pham27abf9f2023-06-20 00:38:24 +0200449 if (mmc_send_stop_transmission(mmc, false)) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100450#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +0100451 pr_err("mmc fail to send stop cmd\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100452#endif
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700453 return 0;
454 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500455 }
456
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700457 return blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500458}
459
Marek Vasut31976d92020-04-04 12:45:05 +0200460#if !CONFIG_IS_ENABLED(DM_MMC)
461static int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
462{
463 if (mmc->cfg->ops->get_b_max)
464 return mmc->cfg->ops->get_b_max(mmc, dst, blkcnt);
465 else
466 return mmc->cfg->b_max;
467}
468#endif
469
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600470#if CONFIG_IS_ENABLED(BLK)
Simon Glass62e293a2016-06-12 23:30:15 -0600471ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
Simon Glass59bc6f22016-05-01 13:52:41 -0600472#else
Simon Glass62e293a2016-06-12 23:30:15 -0600473ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
474 void *dst)
Simon Glass59bc6f22016-05-01 13:52:41 -0600475#endif
Andy Flemingad347bb2008-10-30 16:41:01 -0500476{
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600477#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -0700478 struct blk_desc *block_dev = dev_get_uclass_plat(dev);
Simon Glass59bc6f22016-05-01 13:52:41 -0600479#endif
Simon Glass2f26fff2016-02-29 15:25:51 -0700480 int dev_num = block_dev->devnum;
Stephen Warren1e0f92a2015-12-07 11:38:49 -0700481 int err;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700482 lbaint_t cur, blocks_todo = blkcnt;
Marek Vasut31976d92020-04-04 12:45:05 +0200483 uint b_max;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700484
485 if (blkcnt == 0)
486 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500487
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700488 struct mmc *mmc = find_mmc_device(dev_num);
Andy Flemingad347bb2008-10-30 16:41:01 -0500489 if (!mmc)
490 return 0;
491
Marek Vasutf537e392016-12-01 02:06:33 +0100492 if (CONFIG_IS_ENABLED(MMC_TINY))
493 err = mmc_switch_part(mmc, block_dev->hwpart);
494 else
495 err = blk_dselect_hwpart(block_dev, block_dev->hwpart);
496
Stephen Warren1e0f92a2015-12-07 11:38:49 -0700497 if (err < 0)
498 return 0;
499
Simon Glasse5db1152016-05-01 13:52:35 -0600500 if ((start + blkcnt) > block_dev->lba) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100501#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +0100502 pr_err("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
503 start + blkcnt, block_dev->lba);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100504#endif
Lei Wene1cc9c82010-09-13 22:07:27 +0800505 return 0;
506 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500507
Simon Glassa4343c42015-06-23 15:38:50 -0600508 if (mmc_set_blocklen(mmc, mmc->read_bl_len)) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900509 pr_debug("%s: Failed to set blocklen\n", __func__);
Andy Flemingad347bb2008-10-30 16:41:01 -0500510 return 0;
Simon Glassa4343c42015-06-23 15:38:50 -0600511 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500512
Marek Vasut31976d92020-04-04 12:45:05 +0200513 b_max = mmc_get_b_max(mmc, dst, blkcnt);
514
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700515 do {
Marek Vasut31976d92020-04-04 12:45:05 +0200516 cur = (blocks_todo > b_max) ? b_max : blocks_todo;
Simon Glassa4343c42015-06-23 15:38:50 -0600517 if (mmc_read_blocks(mmc, dst, start, cur) != cur) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +0900518 pr_debug("%s: Failed to read blocks\n", __func__);
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700519 return 0;
Simon Glassa4343c42015-06-23 15:38:50 -0600520 }
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700521 blocks_todo -= cur;
522 start += cur;
523 dst += cur * mmc->read_bl_len;
524 } while (blocks_todo > 0);
Andy Flemingad347bb2008-10-30 16:41:01 -0500525
526 return blkcnt;
527}
528
Kim Phillips87ea3892012-10-29 13:34:43 +0000529static int mmc_go_idle(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -0500530{
531 struct mmc_cmd cmd;
532 int err;
533
534 udelay(1000);
535
536 cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
537 cmd.cmdarg = 0;
538 cmd.resp_type = MMC_RSP_NONE;
Andy Flemingad347bb2008-10-30 16:41:01 -0500539
540 err = mmc_send_cmd(mmc, &cmd, NULL);
541
542 if (err)
543 return err;
544
545 udelay(2000);
546
547 return 0;
548}
549
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100550#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200551static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
552{
553 struct mmc_cmd cmd;
554 int err = 0;
555
556 /*
557 * Send CMD11 only if the request is to switch the card to
558 * 1.8V signalling.
559 */
560 if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
561 return mmc_set_signal_voltage(mmc, signal_voltage);
562
563 cmd.cmdidx = SD_CMD_SWITCH_UHS18V;
564 cmd.cmdarg = 0;
565 cmd.resp_type = MMC_RSP_R1;
566
567 err = mmc_send_cmd(mmc, &cmd, NULL);
568 if (err)
569 return err;
570
571 if (!mmc_host_is_spi(mmc) && (cmd.response[0] & MMC_STATUS_ERROR))
572 return -EIO;
573
574 /*
575 * The card should drive cmd and dat[0:3] low immediately
576 * after the response of cmd11, but wait 100 us to be sure
577 */
578 err = mmc_wait_dat0(mmc, 0, 100);
579 if (err == -ENOSYS)
580 udelay(100);
581 else if (err)
582 return -ETIMEDOUT;
583
584 /*
585 * During a signal voltage level switch, the clock must be gated
586 * for 5 ms according to the SD spec
587 */
Jaehoon Chung239cb2f2018-01-26 19:25:29 +0900588 mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200589
590 err = mmc_set_signal_voltage(mmc, signal_voltage);
591 if (err)
592 return err;
593
594 /* Keep clock gated for at least 10 ms, though spec only says 5 ms */
595 mdelay(10);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +0900596 mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE);
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200597
598 /*
599 * Failure to switch is indicated by the card holding
600 * dat[0:3] low. Wait for at least 1 ms according to spec
601 */
602 err = mmc_wait_dat0(mmc, 1, 1000);
603 if (err == -ENOSYS)
604 udelay(1000);
605 else if (err)
606 return -ETIMEDOUT;
607
608 return 0;
609}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100610#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200611
612static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
Andy Flemingad347bb2008-10-30 16:41:01 -0500613{
614 int timeout = 1000;
615 int err;
616 struct mmc_cmd cmd;
617
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500618 while (1) {
Andy Flemingad347bb2008-10-30 16:41:01 -0500619 cmd.cmdidx = MMC_CMD_APP_CMD;
620 cmd.resp_type = MMC_RSP_R1;
621 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500622
623 err = mmc_send_cmd(mmc, &cmd, NULL);
624
625 if (err)
626 return err;
627
628 cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
629 cmd.resp_type = MMC_RSP_R3;
Stefano Babicf8e9a212010-01-20 18:20:39 +0100630
631 /*
632 * Most cards do not answer if some reserved bits
633 * in the ocr are set. However, Some controller
634 * can set bit 7 (reserved for low voltages), but
635 * how to manage low voltages SD card is not yet
636 * specified.
637 */
Thomas Chou1254c3d2010-12-24 13:12:21 +0000638 cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200639 (mmc->cfg->voltages & 0xff8000);
Andy Flemingad347bb2008-10-30 16:41:01 -0500640
641 if (mmc->version == SD_VERSION_2)
642 cmd.cmdarg |= OCR_HCS;
643
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200644 if (uhs_en)
645 cmd.cmdarg |= OCR_S18R;
646
Andy Flemingad347bb2008-10-30 16:41:01 -0500647 err = mmc_send_cmd(mmc, &cmd, NULL);
648
649 if (err)
650 return err;
651
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500652 if (cmd.response[0] & OCR_BUSY)
653 break;
Andy Flemingad347bb2008-10-30 16:41:01 -0500654
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500655 if (timeout-- <= 0)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900656 return -EOPNOTSUPP;
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500657
658 udelay(1000);
659 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500660
661 if (mmc->version != SD_VERSION_2)
662 mmc->version = SD_VERSION_1_0;
663
Thomas Chou1254c3d2010-12-24 13:12:21 +0000664 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
665 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
666 cmd.resp_type = MMC_RSP_R3;
667 cmd.cmdarg = 0;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000668
669 err = mmc_send_cmd(mmc, &cmd, NULL);
670
671 if (err)
672 return err;
673 }
674
Rabin Vincentb6eed942009-04-05 13:30:56 +0530675 mmc->ocr = cmd.response[0];
Andy Flemingad347bb2008-10-30 16:41:01 -0500676
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100677#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200678 if (uhs_en && !(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)
679 == 0x41000000) {
680 err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
681 if (err)
682 return err;
683 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +0100684#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +0200685
Andy Flemingad347bb2008-10-30 16:41:01 -0500686 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
687 mmc->rca = 0;
688
689 return 0;
690}
691
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500692static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg)
Andy Flemingad347bb2008-10-30 16:41:01 -0500693{
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500694 struct mmc_cmd cmd;
Andy Flemingad347bb2008-10-30 16:41:01 -0500695 int err;
696
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500697 cmd.cmdidx = MMC_CMD_SEND_OP_COND;
698 cmd.resp_type = MMC_RSP_R3;
699 cmd.cmdarg = 0;
Rob Herring5fd3edd2015-03-23 17:56:59 -0500700 if (use_arg && !mmc_host_is_spi(mmc))
701 cmd.cmdarg = OCR_HCS |
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200702 (mmc->cfg->voltages &
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500703 (mmc->ocr & OCR_VOLTAGE_MASK)) |
704 (mmc->ocr & OCR_ACCESS_MODE);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000705
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500706 err = mmc_send_cmd(mmc, &cmd, NULL);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000707 if (err)
708 return err;
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500709 mmc->ocr = cmd.response[0];
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000710 return 0;
711}
712
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +0200713static int mmc_send_op_cond(struct mmc *mmc)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000714{
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000715 int err, i;
Haibo Chen71949512020-06-15 17:18:12 +0800716 int timeout = 1000;
717 uint start;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000718
Andy Flemingad347bb2008-10-30 16:41:01 -0500719 /* Some cards seem to need this */
720 mmc_go_idle(mmc);
721
Haibo Chen71949512020-06-15 17:18:12 +0800722 start = get_timer(0);
Wolfgang Denk62fb2b42021-09-27 17:42:39 +0200723 /* Asking to the card its capabilities */
Haibo Chen71949512020-06-15 17:18:12 +0800724 for (i = 0; ; i++) {
Andrew Gabbasovfafa6a02015-03-19 07:44:04 -0500725 err = mmc_send_op_cond_iter(mmc, i != 0);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000726 if (err)
727 return err;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200728
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000729 /* exit if not busy (flag seems to be inverted) */
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500730 if (mmc->ocr & OCR_BUSY)
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -0500731 break;
Haibo Chen71949512020-06-15 17:18:12 +0800732
733 if (get_timer(start) > timeout)
734 return -ETIMEDOUT;
735 udelay(100);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000736 }
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -0500737 mmc->op_cond_pending = 1;
738 return 0;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000739}
Wolfgang Denk80f70212011-05-19 22:21:41 +0200740
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +0200741static int mmc_complete_op_cond(struct mmc *mmc)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000742{
743 struct mmc_cmd cmd;
744 int timeout = 1000;
Vipul Kumardbad7b42018-05-03 12:20:54 +0530745 ulong start;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000746 int err;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200747
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000748 mmc->op_cond_pending = 0;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500749 if (!(mmc->ocr & OCR_BUSY)) {
Yangbo Lu9c720612016-08-02 15:33:18 +0800750 /* Some cards seem to need this */
751 mmc_go_idle(mmc);
752
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500753 start = get_timer(0);
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500754 while (1) {
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500755 err = mmc_send_op_cond_iter(mmc, 1);
756 if (err)
757 return err;
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500758 if (mmc->ocr & OCR_BUSY)
759 break;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500760 if (get_timer(start) > timeout)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900761 return -EOPNOTSUPP;
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500762 udelay(100);
Andrew Gabbasov034857c2015-03-19 07:44:06 -0500763 }
Andrew Gabbasov5a513ca2015-03-19 07:44:05 -0500764 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500765
Thomas Chou1254c3d2010-12-24 13:12:21 +0000766 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
767 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
768 cmd.resp_type = MMC_RSP_R3;
769 cmd.cmdarg = 0;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000770
771 err = mmc_send_cmd(mmc, &cmd, NULL);
772
773 if (err)
774 return err;
Andrew Gabbasovec600d12015-03-19 07:44:03 -0500775
776 mmc->ocr = cmd.response[0];
Thomas Chou1254c3d2010-12-24 13:12:21 +0000777 }
778
Andy Flemingad347bb2008-10-30 16:41:01 -0500779 mmc->version = MMC_VERSION_UNKNOWN;
Andy Flemingad347bb2008-10-30 16:41:01 -0500780
781 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
Stephen Warrenf6545f12014-01-30 16:11:12 -0700782 mmc->rca = 1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500783
784 return 0;
785}
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
Andy Flemingad347bb2008-10-30 16:41:01 -05001573/* frequency bases */
1574/* divided by 10 to be nice to platforms without floating point */
Mike Frysingerb588caf2010-10-20 01:15:53 +00001575static const int fbase[] = {
Andy Flemingad347bb2008-10-30 16:41:01 -05001576 10000,
1577 100000,
1578 1000000,
1579 10000000,
1580};
1581
1582/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
1583 * to platforms without floating point.
1584 */
Simon Glass03317cc2016-05-14 14:02:57 -06001585static const u8 multipliers[] = {
Andy Flemingad347bb2008-10-30 16:41:01 -05001586 0, /* reserved */
1587 10,
1588 12,
1589 13,
1590 15,
1591 20,
1592 25,
1593 30,
1594 35,
1595 40,
1596 45,
1597 50,
1598 55,
1599 60,
1600 70,
1601 80,
1602};
1603
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001604static inline int bus_width(uint cap)
1605{
1606 if (cap == MMC_MODE_8BIT)
1607 return 8;
1608 if (cap == MMC_MODE_4BIT)
1609 return 4;
1610 if (cap == MMC_MODE_1BIT)
1611 return 1;
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01001612 pr_warn("invalid bus witdh capability 0x%x\n", cap);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001613 return 0;
1614}
1615
Simon Glasseba48f92017-07-29 11:35:31 -06001616#if !CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001617#ifdef MMC_SUPPORTS_TUNING
Kishon Vijay Abraham Iae7174f2017-09-21 16:30:05 +02001618static int mmc_execute_tuning(struct mmc *mmc, uint opcode)
1619{
1620 return -ENOTSUPP;
1621}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001622#endif
Kishon Vijay Abraham Iae7174f2017-09-21 16:30:05 +02001623
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001624static int mmc_set_ios(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001625{
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001626 int ret = 0;
1627
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001628 if (mmc->cfg->ops->set_ios)
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001629 ret = mmc->cfg->ops->set_ios(mmc);
1630
1631 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05001632}
Yann Gautier6f558332019-09-19 17:56:12 +02001633
1634static int mmc_host_power_cycle(struct mmc *mmc)
1635{
1636 int ret = 0;
1637
1638 if (mmc->cfg->ops->host_power_cycle)
1639 ret = mmc->cfg->ops->host_power_cycle(mmc);
1640
1641 return ret;
1642}
Simon Glass394dfc02016-06-12 23:30:22 -06001643#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001644
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001645int mmc_set_clock(struct mmc *mmc, uint clock, bool disable)
Andy Flemingad347bb2008-10-30 16:41:01 -05001646{
Jaehoon Chungab4d4052018-01-23 14:04:30 +09001647 if (!disable) {
Jaehoon Chung8a933292018-01-17 19:36:58 +09001648 if (clock > mmc->cfg->f_max)
1649 clock = mmc->cfg->f_max;
Andy Flemingad347bb2008-10-30 16:41:01 -05001650
Jaehoon Chung8a933292018-01-17 19:36:58 +09001651 if (clock < mmc->cfg->f_min)
1652 clock = mmc->cfg->f_min;
1653 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001654
1655 mmc->clock = clock;
Kishon Vijay Abraham Id6246bf2017-09-21 16:30:03 +02001656 mmc->clk_disable = disable;
Andy Flemingad347bb2008-10-30 16:41:01 -05001657
Jaehoon Chungc8477d62018-01-26 19:25:30 +09001658 debug("clock is %s (%dHz)\n", disable ? "disabled" : "enabled", clock);
1659
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001660 return mmc_set_ios(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001661}
1662
Kishon Vijay Abraham Ie178c112017-09-21 16:29:59 +02001663static int mmc_set_bus_width(struct mmc *mmc, uint width)
Andy Flemingad347bb2008-10-30 16:41:01 -05001664{
1665 mmc->bus_width = width;
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
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001670#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
1671/*
1672 * helper function to display the capabilities in a human
1673 * friendly manner. The capabilities include bus width and
1674 * supported modes.
1675 */
1676void mmc_dump_capabilities(const char *text, uint caps)
1677{
1678 enum bus_mode mode;
1679
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001680 pr_debug("%s: widths [", text);
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001681 if (caps & MMC_MODE_8BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001682 pr_debug("8, ");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001683 if (caps & MMC_MODE_4BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001684 pr_debug("4, ");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001685 if (caps & MMC_MODE_1BIT)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001686 pr_debug("1, ");
1687 pr_debug("\b\b] modes [");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001688 for (mode = MMC_LEGACY; mode < MMC_MODES_END; mode++)
1689 if (MMC_CAP(mode) & caps)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001690 pr_debug("%s, ", mmc_mode_name(mode));
1691 pr_debug("\b\b]\n");
Jean-Jacques Hiblot00de5042017-09-21 16:29:54 +02001692}
1693#endif
1694
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001695struct mode_width_tuning {
1696 enum bus_mode mode;
1697 uint widths;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001698#ifdef MMC_SUPPORTS_TUNING
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001699 uint tuning;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001700#endif
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001701};
1702
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001703#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001704int mmc_voltage_to_mv(enum mmc_voltage voltage)
1705{
1706 switch (voltage) {
1707 case MMC_SIGNAL_VOLTAGE_000: return 0;
1708 case MMC_SIGNAL_VOLTAGE_330: return 3300;
1709 case MMC_SIGNAL_VOLTAGE_180: return 1800;
1710 case MMC_SIGNAL_VOLTAGE_120: return 1200;
1711 }
1712 return -EINVAL;
1713}
1714
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001715static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1716{
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001717 int err;
1718
1719 if (mmc->signal_voltage == signal_voltage)
1720 return 0;
1721
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001722 mmc->signal_voltage = signal_voltage;
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001723 err = mmc_set_ios(mmc);
1724 if (err)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001725 pr_debug("unable to set voltage (err %d)\n", err);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001726
1727 return err;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001728}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001729#else
1730static inline int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
1731{
1732 return 0;
1733}
1734#endif
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02001735
Marek Vasuta318a7a2018-04-15 00:37:11 +02001736#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001737static const struct mode_width_tuning sd_modes_by_pref[] = {
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001738#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
1739#ifdef MMC_SUPPORTS_TUNING
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001740 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001741 .mode = UHS_SDR104,
1742 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1743 .tuning = MMC_CMD_SEND_TUNING_BLOCK
1744 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001745#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001746 {
1747 .mode = UHS_SDR50,
1748 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1749 },
1750 {
1751 .mode = UHS_DDR50,
1752 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1753 },
1754 {
1755 .mode = UHS_SDR25,
1756 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1757 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001758#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001759 {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001760 .mode = SD_HS,
1761 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1762 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001763#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001764 {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001765 .mode = UHS_SDR12,
1766 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1767 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001768#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001769 {
Faiz Abbas01db77e2020-02-26 13:44:32 +05301770 .mode = MMC_LEGACY,
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001771 .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
1772 }
1773};
1774
1775#define for_each_sd_mode_by_pref(caps, mwt) \
1776 for (mwt = sd_modes_by_pref;\
1777 mwt < sd_modes_by_pref + ARRAY_SIZE(sd_modes_by_pref);\
1778 mwt++) \
1779 if (caps & MMC_CAP(mwt->mode))
1780
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02001781static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001782{
1783 int err;
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001784 uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
1785 const struct mode_width_tuning *mwt;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001786#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001787 bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001788#else
1789 bool uhs_en = false;
1790#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001791 uint caps;
1792
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001793#ifdef DEBUG
1794 mmc_dump_capabilities("sd card", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001795 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01001796#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001797
Anup Pateld9c92c72019-07-08 04:10:43 +00001798 if (mmc_host_is_spi(mmc)) {
1799 mmc_set_bus_width(mmc, 1);
Faiz Abbas01db77e2020-02-26 13:44:32 +05301800 mmc_select_mode(mmc, MMC_LEGACY);
Anup Pateld9c92c72019-07-08 04:10:43 +00001801 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
Pragnesh Patela01f57e2020-06-29 15:17:26 +05301802#if CONFIG_IS_ENABLED(MMC_WRITE)
1803 err = sd_read_ssr(mmc);
1804 if (err)
1805 pr_warn("unable to read ssr\n");
1806#endif
Anup Pateld9c92c72019-07-08 04:10:43 +00001807 return 0;
1808 }
1809
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001810 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01001811 caps = card_caps & mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001812
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001813 if (!uhs_en)
1814 caps &= ~UHS_CAPS;
1815
1816 for_each_sd_mode_by_pref(caps, mwt) {
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001817 uint *w;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001818
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001819 for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001820 if (*w & caps & mwt->widths) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001821 pr_debug("trying mode %s width %d (at %d MHz)\n",
1822 mmc_mode_name(mwt->mode),
1823 bus_width(*w),
1824 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001825
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001826 /* configure the bus width (card + host) */
1827 err = sd_select_bus_width(mmc, bus_width(*w));
1828 if (err)
1829 goto error;
1830 mmc_set_bus_width(mmc, bus_width(*w));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001831
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001832 /* configure the bus mode (card) */
1833 err = sd_set_card_speed(mmc, mwt->mode);
1834 if (err)
1835 goto error;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001836
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001837 /* configure the bus mode (host) */
1838 mmc_select_mode(mmc, mwt->mode);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001839 mmc_set_clock(mmc, mmc->tran_speed,
1840 MMC_CLK_ENABLE);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001841
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001842#ifdef MMC_SUPPORTS_TUNING
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001843 /* execute tuning if needed */
1844 if (mwt->tuning && !mmc_host_is_spi(mmc)) {
1845 err = mmc_execute_tuning(mmc,
1846 mwt->tuning);
1847 if (err) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001848 pr_debug("tuning failed\n");
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001849 goto error;
1850 }
1851 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001852#endif
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02001853
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001854#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001855 err = sd_read_ssr(mmc);
Peng Fan2d2fe8e2018-03-05 16:20:40 +08001856 if (err)
Jean-Jacques Hiblotcb534f02018-01-04 15:23:33 +01001857 pr_warn("unable to read ssr\n");
1858#endif
1859 if (!err)
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001860 return 0;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001861
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001862error:
1863 /* revert to a safer bus speed */
Faiz Abbas01db77e2020-02-26 13:44:32 +05301864 mmc_select_mode(mmc, MMC_LEGACY);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09001865 mmc_set_clock(mmc, mmc->tran_speed,
1866 MMC_CLK_ENABLE);
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001867 }
1868 }
1869 }
1870
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09001871 pr_err("unable to select a mode\n");
Jean-Jacques Hiblot5b1a4d92017-09-21 16:29:57 +02001872 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001873}
1874
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001875/*
1876 * read the compare the part of ext csd that is constant.
1877 * This can be used to check that the transfer is working
1878 * as expected.
1879 */
1880static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02001881{
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001882 int err;
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02001883 const u8 *ext_csd = mmc->ext_csd;
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001884 ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
1885
Jean-Jacques Hiblot7ab1b622017-11-30 17:43:58 +01001886 if (mmc->version < MMC_VERSION_4)
1887 return 0;
1888
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02001889 err = mmc_send_ext_csd(mmc, test_csd);
1890 if (err)
1891 return err;
1892
1893 /* Only compare read only fields */
1894 if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
1895 == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
1896 ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
1897 == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
1898 ext_csd[EXT_CSD_REV]
1899 == test_csd[EXT_CSD_REV] &&
1900 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
1901 == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
1902 memcmp(&ext_csd[EXT_CSD_SEC_CNT],
1903 &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
1904 return 0;
1905
1906 return -EBADMSG;
1907}
1908
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001909#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001910static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1911 uint32_t allowed_mask)
1912{
1913 u32 card_mask = 0;
1914
1915 switch (mode) {
Peng Faneede83b2019-07-10 14:43:07 +08001916 case MMC_HS_400_ES:
Peng Fan46801252018-08-10 14:07:54 +08001917 case MMC_HS_400:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001918 case MMC_HS_200:
Peng Fan46801252018-08-10 14:07:54 +08001919 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V |
1920 EXT_CSD_CARD_TYPE_HS400_1_8V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001921 card_mask |= MMC_SIGNAL_VOLTAGE_180;
Peng Fan46801252018-08-10 14:07:54 +08001922 if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
1923 EXT_CSD_CARD_TYPE_HS400_1_2V))
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001924 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1925 break;
1926 case MMC_DDR_52:
1927 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
1928 card_mask |= MMC_SIGNAL_VOLTAGE_330 |
1929 MMC_SIGNAL_VOLTAGE_180;
1930 if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_2V)
1931 card_mask |= MMC_SIGNAL_VOLTAGE_120;
1932 break;
1933 default:
1934 card_mask |= MMC_SIGNAL_VOLTAGE_330;
1935 break;
1936 }
1937
1938 while (card_mask & allowed_mask) {
1939 enum mmc_voltage best_match;
1940
1941 best_match = 1 << (ffs(card_mask & allowed_mask) - 1);
1942 if (!mmc_set_signal_voltage(mmc, best_match))
1943 return 0;
1944
1945 allowed_mask &= ~best_match;
1946 }
1947
1948 return -ENOTSUPP;
1949}
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001950#else
1951static inline int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
1952 uint32_t allowed_mask)
1953{
1954 return 0;
1955}
1956#endif
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02001957
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001958static const struct mode_width_tuning mmc_modes_by_pref[] = {
Peng Faneede83b2019-07-10 14:43:07 +08001959#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
1960 {
1961 .mode = MMC_HS_400_ES,
1962 .widths = MMC_MODE_8BIT,
1963 },
1964#endif
Peng Fan46801252018-08-10 14:07:54 +08001965#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
1966 {
1967 .mode = MMC_HS_400,
1968 .widths = MMC_MODE_8BIT,
1969 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
1970 },
1971#endif
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001972#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001973 {
1974 .mode = MMC_HS_200,
1975 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02001976 .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001977 },
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01001978#endif
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02001979 {
1980 .mode = MMC_DDR_52,
1981 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
1982 },
1983 {
1984 .mode = MMC_HS_52,
1985 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
1986 },
1987 {
1988 .mode = MMC_HS,
1989 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
1990 },
1991 {
1992 .mode = MMC_LEGACY,
1993 .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
1994 }
1995};
1996
1997#define for_each_mmc_mode_by_pref(caps, mwt) \
1998 for (mwt = mmc_modes_by_pref;\
1999 mwt < mmc_modes_by_pref + ARRAY_SIZE(mmc_modes_by_pref);\
2000 mwt++) \
2001 if (caps & MMC_CAP(mwt->mode))
2002
2003static const struct ext_csd_bus_width {
2004 uint cap;
2005 bool is_ddr;
2006 uint ext_csd_bits;
2007} ext_csd_bus_width[] = {
2008 {MMC_MODE_8BIT, true, EXT_CSD_DDR_BUS_WIDTH_8},
2009 {MMC_MODE_4BIT, true, EXT_CSD_DDR_BUS_WIDTH_4},
2010 {MMC_MODE_8BIT, false, EXT_CSD_BUS_WIDTH_8},
2011 {MMC_MODE_4BIT, false, EXT_CSD_BUS_WIDTH_4},
2012 {MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
2013};
2014
Peng Fan46801252018-08-10 14:07:54 +08002015#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
2016static int mmc_select_hs400(struct mmc *mmc)
2017{
2018 int err;
2019
2020 /* Set timing to HS200 for tuning */
Marek Vasut111572f2019-01-03 21:19:24 +01002021 err = mmc_set_card_speed(mmc, MMC_HS_200, false);
Peng Fan46801252018-08-10 14:07:54 +08002022 if (err)
2023 return err;
2024
2025 /* configure the bus mode (host) */
2026 mmc_select_mode(mmc, MMC_HS_200);
2027 mmc_set_clock(mmc, mmc->tran_speed, false);
2028
2029 /* execute tuning if needed */
Yangbo Lu3ed53ac2020-09-01 16:58:03 +08002030 mmc->hs400_tuning = 1;
Peng Fan46801252018-08-10 14:07:54 +08002031 err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200);
Yangbo Lu3ed53ac2020-09-01 16:58:03 +08002032 mmc->hs400_tuning = 0;
Peng Fan46801252018-08-10 14:07:54 +08002033 if (err) {
2034 debug("tuning failed\n");
2035 return err;
2036 }
2037
2038 /* Set back to HS */
BOUGH CHEN8702bbc2019-03-26 06:24:17 +00002039 mmc_set_card_speed(mmc, MMC_HS, true);
Peng Fan46801252018-08-10 14:07:54 +08002040
Yangbo Lu5347aea2020-09-01 16:58:04 +08002041 err = mmc_hs400_prepare_ddr(mmc);
2042 if (err)
2043 return err;
2044
Peng Fan46801252018-08-10 14:07:54 +08002045 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2046 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
2047 if (err)
2048 return err;
2049
Marek Vasut111572f2019-01-03 21:19:24 +01002050 err = mmc_set_card_speed(mmc, MMC_HS_400, false);
Peng Fan46801252018-08-10 14:07:54 +08002051 if (err)
2052 return err;
2053
2054 mmc_select_mode(mmc, MMC_HS_400);
2055 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2056 if (err)
2057 return err;
2058
2059 return 0;
2060}
2061#else
2062static int mmc_select_hs400(struct mmc *mmc)
2063{
2064 return -ENOTSUPP;
2065}
2066#endif
2067
Peng Faneede83b2019-07-10 14:43:07 +08002068#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
2069#if !CONFIG_IS_ENABLED(DM_MMC)
2070static int mmc_set_enhanced_strobe(struct mmc *mmc)
2071{
2072 return -ENOTSUPP;
2073}
2074#endif
2075static int mmc_select_hs400es(struct mmc *mmc)
2076{
2077 int err;
2078
2079 err = mmc_set_card_speed(mmc, MMC_HS, true);
2080 if (err)
2081 return err;
2082
2083 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
2084 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG |
2085 EXT_CSD_BUS_WIDTH_STROBE);
2086 if (err) {
2087 printf("switch to bus width for hs400 failed\n");
2088 return err;
2089 }
2090 /* TODO: driver strength */
2091 err = mmc_set_card_speed(mmc, MMC_HS_400_ES, false);
2092 if (err)
2093 return err;
2094
2095 mmc_select_mode(mmc, MMC_HS_400_ES);
2096 err = mmc_set_clock(mmc, mmc->tran_speed, false);
2097 if (err)
2098 return err;
2099
2100 return mmc_set_enhanced_strobe(mmc);
2101}
2102#else
2103static int mmc_select_hs400es(struct mmc *mmc)
2104{
2105 return -ENOTSUPP;
2106}
2107#endif
2108
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002109#define for_each_supported_width(caps, ddr, ecbv) \
2110 for (ecbv = ext_csd_bus_width;\
2111 ecbv < ext_csd_bus_width + ARRAY_SIZE(ext_csd_bus_width);\
2112 ecbv++) \
2113 if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
2114
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002115static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
Jean-Jacques Hiblot933d1262017-09-21 16:29:52 +02002116{
Jaehoon Chung6b3431c2020-12-04 06:36:00 +09002117 int err = 0;
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002118 const struct mode_width_tuning *mwt;
2119 const struct ext_csd_bus_width *ecbw;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002120
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002121#ifdef DEBUG
2122 mmc_dump_capabilities("mmc", card_caps);
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002123 mmc_dump_capabilities("host", mmc->host_caps);
Jean-Jacques Hiblot93c31d12017-11-30 17:43:54 +01002124#endif
2125
Anup Pateld9c92c72019-07-08 04:10:43 +00002126 if (mmc_host_is_spi(mmc)) {
2127 mmc_set_bus_width(mmc, 1);
2128 mmc_select_mode(mmc, MMC_LEGACY);
2129 mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
2130 return 0;
2131 }
2132
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002133 /* Restrict card's capabilities by what the host can do */
Jean-Jacques Hiblotd7e5e032017-11-30 17:43:57 +01002134 card_caps &= mmc->host_caps;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002135
2136 /* Only version 4 of MMC supports wider bus widths */
2137 if (mmc->version < MMC_VERSION_4)
2138 return 0;
2139
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002140 if (!mmc->ext_csd) {
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002141 pr_debug("No ext_csd found!\n"); /* this should enver happen */
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002142 return -ENOTSUPP;
2143 }
2144
Marek Vasut111572f2019-01-03 21:19:24 +01002145#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
Ye Li3679e802021-08-17 17:20:34 +08002146 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
2147 CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
Marek Vasut111572f2019-01-03 21:19:24 +01002148 /*
2149 * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode
2150 * before doing anything else, since a transition from either of
2151 * the HS200/HS400 mode directly to legacy mode is not supported.
2152 */
2153 if (mmc->selected_mode == MMC_HS_200 ||
Ye Li3679e802021-08-17 17:20:34 +08002154 mmc->selected_mode == MMC_HS_400 ||
2155 mmc->selected_mode == MMC_HS_400_ES)
Marek Vasut111572f2019-01-03 21:19:24 +01002156 mmc_set_card_speed(mmc, MMC_HS, true);
2157 else
2158#endif
2159 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002160
2161 for_each_mmc_mode_by_pref(card_caps, mwt) {
2162 for_each_supported_width(card_caps & mwt->widths,
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002163 mmc_is_mode_ddr(mwt->mode), ecbw) {
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002164 enum mmc_voltage old_voltage;
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002165 pr_debug("trying mode %s width %d (at %d MHz)\n",
2166 mmc_mode_name(mwt->mode),
2167 bus_width(ecbw->cap),
2168 mmc_mode2freq(mmc, mwt->mode) / 1000000);
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002169 old_voltage = mmc->signal_voltage;
2170 err = mmc_set_lowest_voltage(mmc, mwt->mode,
2171 MMC_ALL_SIGNAL_VOLTAGE);
2172 if (err)
2173 continue;
2174
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002175 /* configure the bus width (card + host) */
2176 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2177 EXT_CSD_BUS_WIDTH,
2178 ecbw->ext_csd_bits & ~EXT_CSD_DDR_FLAG);
2179 if (err)
2180 goto error;
2181 mmc_set_bus_width(mmc, bus_width(ecbw->cap));
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002182
Peng Fan46801252018-08-10 14:07:54 +08002183 if (mwt->mode == MMC_HS_400) {
2184 err = mmc_select_hs400(mmc);
2185 if (err) {
2186 printf("Select HS400 failed %d\n", err);
2187 goto error;
2188 }
Peng Faneede83b2019-07-10 14:43:07 +08002189 } else if (mwt->mode == MMC_HS_400_ES) {
2190 err = mmc_select_hs400es(mmc);
2191 if (err) {
2192 printf("Select HS400ES failed %d\n",
2193 err);
2194 goto error;
2195 }
Peng Fan46801252018-08-10 14:07:54 +08002196 } else {
2197 /* configure the bus speed (card) */
Marek Vasut111572f2019-01-03 21:19:24 +01002198 err = mmc_set_card_speed(mmc, mwt->mode, false);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002199 if (err)
2200 goto error;
Peng Fan46801252018-08-10 14:07:54 +08002201
2202 /*
2203 * configure the bus width AND the ddr mode
2204 * (card). The host side will be taken care
2205 * of in the next step
2206 */
2207 if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) {
2208 err = mmc_switch(mmc,
2209 EXT_CSD_CMD_SET_NORMAL,
2210 EXT_CSD_BUS_WIDTH,
2211 ecbw->ext_csd_bits);
2212 if (err)
2213 goto error;
2214 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002215
Peng Fan46801252018-08-10 14:07:54 +08002216 /* configure the bus mode (host) */
2217 mmc_select_mode(mmc, mwt->mode);
2218 mmc_set_clock(mmc, mmc->tran_speed,
2219 MMC_CLK_ENABLE);
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002220#ifdef MMC_SUPPORTS_TUNING
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002221
Peng Fan46801252018-08-10 14:07:54 +08002222 /* execute tuning if needed */
2223 if (mwt->tuning) {
2224 err = mmc_execute_tuning(mmc,
2225 mwt->tuning);
2226 if (err) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002227 pr_debug("tuning failed : %d\n", err);
Peng Fan46801252018-08-10 14:07:54 +08002228 goto error;
2229 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002230 }
Jean-Jacques Hiblot6051e782017-11-30 17:44:01 +01002231#endif
Peng Fan46801252018-08-10 14:07:54 +08002232 }
Kishon Vijay Abraham I210369f2017-09-21 16:30:06 +02002233
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002234 /* do a transfer to check the configuration */
2235 err = mmc_read_and_compare_ext_csd(mmc);
2236 if (!err)
2237 return 0;
2238error:
Jean-Jacques Hiblotb6937d62017-09-21 16:30:11 +02002239 mmc_set_signal_voltage(mmc, old_voltage);
Naoki Hayama3110dcb2020-10-12 18:35:22 +09002240 /* if an error occurred, revert to a safer bus mode */
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002241 mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2242 EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
2243 mmc_select_mode(mmc, MMC_LEGACY);
Valentine Barshak29f8d072023-06-10 13:22:33 +02002244 mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002245 mmc_set_bus_width(mmc, 1);
2246 }
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002247 }
2248
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002249 pr_err("unable to select a mode : %d\n", err);
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002250
Jean-Jacques Hiblotec346832017-09-21 16:29:58 +02002251 return -ENOTSUPP;
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002252}
Marek Vasuta318a7a2018-04-15 00:37:11 +02002253#endif
2254
2255#if CONFIG_IS_ENABLED(MMC_TINY)
2256DEFINE_CACHE_ALIGN_BUFFER(u8, ext_csd_bkup, MMC_MAX_BLOCK_LEN);
2257#endif
Jean-Jacques Hiblot31e7cf32017-09-21 16:29:49 +02002258
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002259static int mmc_startup_v4(struct mmc *mmc)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002260{
2261 int err, i;
2262 u64 capacity;
2263 bool has_parts = false;
2264 bool part_completed;
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002265 static const u32 mmc_versions[] = {
2266 MMC_VERSION_4,
2267 MMC_VERSION_4_1,
2268 MMC_VERSION_4_2,
2269 MMC_VERSION_4_3,
Jean-Jacques Hiblotc64862b2018-02-09 12:09:28 +01002270 MMC_VERSION_4_4,
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002271 MMC_VERSION_4_41,
2272 MMC_VERSION_4_5,
2273 MMC_VERSION_5_0,
2274 MMC_VERSION_5_1
2275 };
2276
Marek Vasuta318a7a2018-04-15 00:37:11 +02002277#if CONFIG_IS_ENABLED(MMC_TINY)
2278 u8 *ext_csd = ext_csd_bkup;
2279
2280 if (IS_SD(mmc) || mmc->version < MMC_VERSION_4)
2281 return 0;
2282
2283 if (!mmc->ext_csd)
Sam Edwardsed8339f2023-05-18 13:47:07 -06002284 memset(ext_csd_bkup, 0, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002285
2286 err = mmc_send_ext_csd(mmc, ext_csd);
2287 if (err)
2288 goto error;
2289
2290 /* store the ext csd for future reference */
2291 if (!mmc->ext_csd)
2292 mmc->ext_csd = ext_csd;
2293#else
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002294 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002295
2296 if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4))
2297 return 0;
2298
2299 /* check ext_csd version and capacity */
2300 err = mmc_send_ext_csd(mmc, ext_csd);
2301 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002302 goto error;
2303
2304 /* store the ext csd for future reference */
2305 if (!mmc->ext_csd)
2306 mmc->ext_csd = malloc(MMC_MAX_BLOCK_LEN);
2307 if (!mmc->ext_csd)
2308 return -ENOMEM;
2309 memcpy(mmc->ext_csd, ext_csd, MMC_MAX_BLOCK_LEN);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002310#endif
Alexander Kochetkovf1133c92018-02-20 14:35:55 +03002311 if (ext_csd[EXT_CSD_REV] >= ARRAY_SIZE(mmc_versions))
Jean-Jacques Hiblotfa6c5772018-01-04 15:23:31 +01002312 return -EINVAL;
2313
2314 mmc->version = mmc_versions[ext_csd[EXT_CSD_REV]];
2315
2316 if (mmc->version >= MMC_VERSION_4_2) {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002317 /*
2318 * According to the JEDEC Standard, the value of
2319 * ext_csd's capacity is valid if the value is more
2320 * than 2GB
2321 */
2322 capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
2323 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8
2324 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16
2325 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
2326 capacity *= MMC_MAX_BLOCK_LEN;
2327 if ((capacity >> 20) > 2 * 1024)
2328 mmc->capacity_user = capacity;
2329 }
2330
Jean-Jacques Hiblot201559c2019-07-02 10:53:54 +02002331 if (mmc->version >= MMC_VERSION_4_5)
2332 mmc->gen_cmd6_time = ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
2333
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002334 /* The partition data may be non-zero but it is only
2335 * effective if PARTITION_SETTING_COMPLETED is set in
2336 * EXT_CSD, so ignore any data if this bit is not set,
2337 * except for enabling the high-capacity group size
2338 * definition (see below).
2339 */
2340 part_completed = !!(ext_csd[EXT_CSD_PARTITION_SETTING] &
2341 EXT_CSD_PARTITION_SETTING_COMPLETED);
2342
Jean-Jacques Hiblot7f5b1692019-07-02 10:53:55 +02002343 mmc->part_switch_time = ext_csd[EXT_CSD_PART_SWITCH_TIME];
2344 /* Some eMMC set the value too low so set a minimum */
2345 if (mmc->part_switch_time < MMC_MIN_PART_SWITCH_TIME && mmc->part_switch_time)
2346 mmc->part_switch_time = MMC_MIN_PART_SWITCH_TIME;
2347
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002348 /* store the partition info of emmc */
2349 mmc->part_support = ext_csd[EXT_CSD_PARTITIONING_SUPPORT];
2350 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
2351 ext_csd[EXT_CSD_BOOT_MULT])
2352 mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
2353 if (part_completed &&
2354 (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & ENHNCD_SUPPORT))
2355 mmc->part_attr = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE];
2356
2357 mmc->capacity_boot = ext_csd[EXT_CSD_BOOT_MULT] << 17;
2358
2359 mmc->capacity_rpmb = ext_csd[EXT_CSD_RPMB_MULT] << 17;
2360
2361 for (i = 0; i < 4; i++) {
2362 int idx = EXT_CSD_GP_SIZE_MULT + i * 3;
2363 uint mult = (ext_csd[idx + 2] << 16) +
2364 (ext_csd[idx + 1] << 8) + ext_csd[idx];
2365 if (mult)
2366 has_parts = true;
2367 if (!part_completed)
2368 continue;
2369 mmc->capacity_gp[i] = mult;
2370 mmc->capacity_gp[i] *=
2371 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2372 mmc->capacity_gp[i] *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2373 mmc->capacity_gp[i] <<= 19;
2374 }
2375
Jean-Jacques Hiblotc94c5472018-01-04 15:23:35 +01002376#ifndef CONFIG_SPL_BUILD
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002377 if (part_completed) {
2378 mmc->enh_user_size =
2379 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 2] << 16) +
2380 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 1] << 8) +
2381 ext_csd[EXT_CSD_ENH_SIZE_MULT];
2382 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
2383 mmc->enh_user_size *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
2384 mmc->enh_user_size <<= 19;
2385 mmc->enh_user_start =
2386 (ext_csd[EXT_CSD_ENH_START_ADDR + 3] << 24) +
2387 (ext_csd[EXT_CSD_ENH_START_ADDR + 2] << 16) +
2388 (ext_csd[EXT_CSD_ENH_START_ADDR + 1] << 8) +
2389 ext_csd[EXT_CSD_ENH_START_ADDR];
2390 if (mmc->high_capacity)
2391 mmc->enh_user_start <<= 9;
2392 }
Jean-Jacques Hiblotc94c5472018-01-04 15:23:35 +01002393#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002394
2395 /*
2396 * Host needs to enable ERASE_GRP_DEF bit if device is
2397 * partitioned. This bit will be lost every time after a reset
2398 * or power off. This will affect erase size.
2399 */
2400 if (part_completed)
2401 has_parts = true;
2402 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) &&
2403 (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB))
2404 has_parts = true;
2405 if (has_parts) {
2406 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
2407 EXT_CSD_ERASE_GROUP_DEF, 1);
2408
2409 if (err)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002410 goto error;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002411
2412 ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
2413 }
2414
2415 if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01) {
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002416#if CONFIG_IS_ENABLED(MMC_WRITE)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002417 /* Read out group size from ext_csd */
2418 mmc->erase_grp_size =
2419 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002420#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002421 /*
2422 * if high capacity and partition setting completed
2423 * SEC_COUNT is valid even if it is smaller than 2 GiB
2424 * JEDEC Standard JESD84-B45, 6.2.4
2425 */
2426 if (mmc->high_capacity && part_completed) {
2427 capacity = (ext_csd[EXT_CSD_SEC_CNT]) |
2428 (ext_csd[EXT_CSD_SEC_CNT + 1] << 8) |
2429 (ext_csd[EXT_CSD_SEC_CNT + 2] << 16) |
2430 (ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
2431 capacity *= MMC_MAX_BLOCK_LEN;
2432 mmc->capacity_user = capacity;
2433 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002434 }
2435#if CONFIG_IS_ENABLED(MMC_WRITE)
2436 else {
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002437 /* Calculate the group size from the csd value. */
2438 int erase_gsz, erase_gmul;
2439
2440 erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
2441 erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
2442 mmc->erase_grp_size = (erase_gsz + 1)
2443 * (erase_gmul + 1);
2444 }
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002445#endif
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002446#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002447 mmc->hc_wp_grp_size = 1024
2448 * ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
2449 * ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
Jean-Jacques Hiblotba54ab82018-01-04 15:23:36 +01002450#endif
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002451
2452 mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
2453
Loic Poulainc0aadbb2023-01-26 10:24:17 +01002454 mmc->can_trim =
2455 !!(ext_csd[EXT_CSD_SEC_FEATURE] & EXT_CSD_SEC_FEATURE_TRIM_EN);
2456
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002457 return 0;
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002458error:
2459 if (mmc->ext_csd) {
Marek Vasuta318a7a2018-04-15 00:37:11 +02002460#if !CONFIG_IS_ENABLED(MMC_TINY)
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002461 free(mmc->ext_csd);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002462#endif
Jean-Jacques Hiblot06976eb2017-11-30 17:43:59 +01002463 mmc->ext_csd = NULL;
2464 }
2465 return err;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002466}
2467
Kim Phillips87ea3892012-10-29 13:34:43 +00002468static int mmc_startup(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002469{
Stephen Warrene315ae82013-06-11 15:14:01 -06002470 int err, i;
Andy Flemingad347bb2008-10-30 16:41:01 -05002471 uint mult, freq;
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002472 u64 cmult, csize;
Andy Flemingad347bb2008-10-30 16:41:01 -05002473 struct mmc_cmd cmd;
Simon Glasse5db1152016-05-01 13:52:35 -06002474 struct blk_desc *bdesc;
Andy Flemingad347bb2008-10-30 16:41:01 -05002475
Thomas Chou1254c3d2010-12-24 13:12:21 +00002476#ifdef CONFIG_MMC_SPI_CRC_ON
2477 if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
2478 cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
2479 cmd.resp_type = MMC_RSP_R1;
2480 cmd.cmdarg = 1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002481 err = mmc_send_cmd(mmc, &cmd, NULL);
Thomas Chou1254c3d2010-12-24 13:12:21 +00002482 if (err)
2483 return err;
2484 }
2485#endif
2486
Andy Flemingad347bb2008-10-30 16:41:01 -05002487 /* Put the Card in Identify Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002488 cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
2489 MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
Andy Flemingad347bb2008-10-30 16:41:01 -05002490 cmd.resp_type = MMC_RSP_R2;
2491 cmd.cmdarg = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002492
Sean Anderson86325092020-10-17 08:36:27 -04002493 err = mmc_send_cmd_quirks(mmc, &cmd, NULL, MMC_QUIRK_RETRY_SEND_CID, 4);
Andy Flemingad347bb2008-10-30 16:41:01 -05002494 if (err)
2495 return err;
2496
2497 memcpy(mmc->cid, cmd.response, 16);
2498
2499 /*
2500 * For MMC cards, set the Relative Address.
2501 * For SD cards, get the Relatvie Address.
2502 * This also puts the cards into Standby State
2503 */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002504 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2505 cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
2506 cmd.cmdarg = mmc->rca << 16;
2507 cmd.resp_type = MMC_RSP_R6;
Andy Flemingad347bb2008-10-30 16:41:01 -05002508
Thomas Chou1254c3d2010-12-24 13:12:21 +00002509 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002510
Thomas Chou1254c3d2010-12-24 13:12:21 +00002511 if (err)
2512 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002513
Thomas Chou1254c3d2010-12-24 13:12:21 +00002514 if (IS_SD(mmc))
2515 mmc->rca = (cmd.response[0] >> 16) & 0xffff;
2516 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002517
2518 /* Get the Card-Specific Data */
2519 cmd.cmdidx = MMC_CMD_SEND_CSD;
2520 cmd.resp_type = MMC_RSP_R2;
2521 cmd.cmdarg = mmc->rca << 16;
Andy Flemingad347bb2008-10-30 16:41:01 -05002522
2523 err = mmc_send_cmd(mmc, &cmd, NULL);
2524
2525 if (err)
2526 return err;
2527
Rabin Vincentb6eed942009-04-05 13:30:56 +05302528 mmc->csd[0] = cmd.response[0];
2529 mmc->csd[1] = cmd.response[1];
2530 mmc->csd[2] = cmd.response[2];
2531 mmc->csd[3] = cmd.response[3];
Andy Flemingad347bb2008-10-30 16:41:01 -05002532
2533 if (mmc->version == MMC_VERSION_UNKNOWN) {
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302534 int version = (cmd.response[0] >> 26) & 0xf;
Andy Flemingad347bb2008-10-30 16:41:01 -05002535
2536 switch (version) {
Bin Meng4a4ef872016-03-17 21:53:13 -07002537 case 0:
2538 mmc->version = MMC_VERSION_1_2;
2539 break;
2540 case 1:
2541 mmc->version = MMC_VERSION_1_4;
2542 break;
2543 case 2:
2544 mmc->version = MMC_VERSION_2_2;
2545 break;
2546 case 3:
2547 mmc->version = MMC_VERSION_3;
2548 break;
2549 case 4:
2550 mmc->version = MMC_VERSION_4;
2551 break;
2552 default:
2553 mmc->version = MMC_VERSION_1_2;
2554 break;
Andy Flemingad347bb2008-10-30 16:41:01 -05002555 }
2556 }
2557
2558 /* divide frequency by 10, since the mults are 10x bigger */
Rabin Vincentbdf7a682009-04-05 13:30:55 +05302559 freq = fbase[(cmd.response[0] & 0x7)];
2560 mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
Andy Flemingad347bb2008-10-30 16:41:01 -05002561
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002562 mmc->legacy_speed = freq * mult;
Jean-Jacques Hiblota94fb412017-09-21 16:29:53 +02002563 mmc_select_mode(mmc, MMC_LEGACY);
Andy Flemingad347bb2008-10-30 16:41:01 -05002564
Markus Niebel03951412013-12-16 13:40:46 +01002565 mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
Rabin Vincentb6eed942009-04-05 13:30:56 +05302566 mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002567#if CONFIG_IS_ENABLED(MMC_WRITE)
Andy Flemingad347bb2008-10-30 16:41:01 -05002568
2569 if (IS_SD(mmc))
2570 mmc->write_bl_len = mmc->read_bl_len;
2571 else
Rabin Vincentb6eed942009-04-05 13:30:56 +05302572 mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002573#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002574
2575 if (mmc->high_capacity) {
2576 csize = (mmc->csd[1] & 0x3f) << 16
2577 | (mmc->csd[2] & 0xffff0000) >> 16;
2578 cmult = 8;
2579 } else {
2580 csize = (mmc->csd[1] & 0x3ff) << 2
2581 | (mmc->csd[2] & 0xc0000000) >> 30;
2582 cmult = (mmc->csd[2] & 0x00038000) >> 15;
2583 }
2584
Stephen Warrene315ae82013-06-11 15:14:01 -06002585 mmc->capacity_user = (csize + 1) << (cmult + 2);
2586 mmc->capacity_user *= mmc->read_bl_len;
2587 mmc->capacity_boot = 0;
2588 mmc->capacity_rpmb = 0;
2589 for (i = 0; i < 4; i++)
2590 mmc->capacity_gp[i] = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -05002591
Simon Glassa09c2b72013-04-03 08:54:30 +00002592 if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN)
2593 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -05002594
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002595#if CONFIG_IS_ENABLED(MMC_WRITE)
Simon Glassa09c2b72013-04-03 08:54:30 +00002596 if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
2597 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002598#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002599
Markus Niebel03951412013-12-16 13:40:46 +01002600 if ((mmc->dsr_imp) && (0xffffffff != mmc->dsr)) {
2601 cmd.cmdidx = MMC_CMD_SET_DSR;
2602 cmd.cmdarg = (mmc->dsr & 0xffff) << 16;
2603 cmd.resp_type = MMC_RSP_NONE;
2604 if (mmc_send_cmd(mmc, &cmd, NULL))
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002605 pr_warn("MMC: SET_DSR failed\n");
Markus Niebel03951412013-12-16 13:40:46 +01002606 }
2607
Andy Flemingad347bb2008-10-30 16:41:01 -05002608 /* Select the card, and put it into Transfer Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +00002609 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
2610 cmd.cmdidx = MMC_CMD_SELECT_CARD;
Ajay Bhargav4a32fba2011-10-05 03:13:23 +00002611 cmd.resp_type = MMC_RSP_R1;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002612 cmd.cmdarg = mmc->rca << 16;
Thomas Chou1254c3d2010-12-24 13:12:21 +00002613 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -05002614
Thomas Chou1254c3d2010-12-24 13:12:21 +00002615 if (err)
2616 return err;
2617 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002618
Lei Wenea526762011-06-22 17:03:31 +00002619 /*
2620 * For SD, its erase group is always one sector
2621 */
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002622#if CONFIG_IS_ENABLED(MMC_WRITE)
Lei Wenea526762011-06-22 17:03:31 +00002623 mmc->erase_grp_size = 1;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002624#endif
Lei Wen31b99802011-05-02 16:26:26 +00002625 mmc->part_config = MMCPART_NOAVAILABLE;
Diego Santa Cruza7a75992014-12-23 10:50:27 +01002626
Jean-Jacques Hibloted9506b2017-09-21 16:29:51 +02002627 err = mmc_startup_v4(mmc);
Jean-Jacques Hiblote84459c2017-09-21 16:29:50 +02002628 if (err)
2629 return err;
Sukumar Ghorai232293c2010-09-20 18:29:29 +05302630
Simon Glasse5db1152016-05-01 13:52:35 -06002631 err = mmc_set_capacity(mmc, mmc_get_blk_desc(mmc)->hwpart);
Stephen Warrene315ae82013-06-11 15:14:01 -06002632 if (err)
2633 return err;
2634
Marek Vasuta318a7a2018-04-15 00:37:11 +02002635#if CONFIG_IS_ENABLED(MMC_TINY)
2636 mmc_set_clock(mmc, mmc->legacy_speed, false);
Faiz Abbas01db77e2020-02-26 13:44:32 +05302637 mmc_select_mode(mmc, MMC_LEGACY);
Marek Vasuta318a7a2018-04-15 00:37:11 +02002638 mmc_set_bus_width(mmc, 1);
2639#else
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002640 if (IS_SD(mmc)) {
2641 err = sd_get_capabilities(mmc);
2642 if (err)
2643 return err;
2644 err = sd_select_mode_and_width(mmc, mmc->card_caps);
2645 } else {
2646 err = mmc_get_capabilities(mmc);
2647 if (err)
2648 return err;
Masahiro Yamadabf1f25c2020-01-23 14:31:12 +09002649 err = mmc_select_mode_and_width(mmc, mmc->card_caps);
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002650 }
Marek Vasuta318a7a2018-04-15 00:37:11 +02002651#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002652 if (err)
2653 return err;
2654
Jean-Jacques Hiblot3d30972b2017-09-21 16:30:09 +02002655 mmc->best_mode = mmc->selected_mode;
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00002656
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002657 /* Fix the block length for DDR mode */
2658 if (mmc->ddr_mode) {
2659 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002660#if CONFIG_IS_ENABLED(MMC_WRITE)
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002661 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Jean-Jacques Hiblot27edffe2018-01-04 15:23:34 +01002662#endif
Andrew Gabbasov532663b2014-12-01 06:59:11 -06002663 }
2664
Andy Flemingad347bb2008-10-30 16:41:01 -05002665 /* fill in device description */
Simon Glasse5db1152016-05-01 13:52:35 -06002666 bdesc = mmc_get_blk_desc(mmc);
2667 bdesc->lun = 0;
2668 bdesc->hwpart = 0;
2669 bdesc->type = 0;
2670 bdesc->blksz = mmc->read_bl_len;
2671 bdesc->log2blksz = LOG2(bdesc->blksz);
2672 bdesc->lba = lldiv(mmc->capacity, mmc->read_bl_len);
Sjoerd Simonsd67754f2015-12-04 23:27:40 +01002673#if !defined(CONFIG_SPL_BUILD) || \
2674 (defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \
Simon Glass7611ac62019-09-25 08:56:27 -06002675 !CONFIG_IS_ENABLED(USE_TINY_PRINTF))
Simon Glasse5db1152016-05-01 13:52:35 -06002676 sprintf(bdesc->vendor, "Man %06x Snr %04x%04x",
Taylor Hutt7367ec22012-10-20 17:15:59 +00002677 mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
2678 (mmc->cid[3] >> 16) & 0xffff);
Simon Glasse5db1152016-05-01 13:52:35 -06002679 sprintf(bdesc->product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002680 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
2681 (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
2682 (mmc->cid[2] >> 24) & 0xff);
Simon Glasse5db1152016-05-01 13:52:35 -06002683 sprintf(bdesc->revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
Taylor Hutt7367ec22012-10-20 17:15:59 +00002684 (mmc->cid[2] >> 16) & 0xf);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002685#else
Simon Glasse5db1152016-05-01 13:52:35 -06002686 bdesc->vendor[0] = 0;
2687 bdesc->product[0] = 0;
2688 bdesc->revision[0] = 0;
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002689#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002690
Andre Przywara17798042018-12-17 10:05:45 +00002691#if !defined(CONFIG_DM_MMC) && (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT))
2692 part_init(bdesc);
2693#endif
2694
Andy Flemingad347bb2008-10-30 16:41:01 -05002695 return 0;
2696}
2697
Kim Phillips87ea3892012-10-29 13:34:43 +00002698static int mmc_send_if_cond(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05002699{
2700 struct mmc_cmd cmd;
2701 int err;
2702
2703 cmd.cmdidx = SD_CMD_SEND_IF_COND;
2704 /* We set the bit if the host supports voltages between 2.7 and 3.6 V */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002705 cmd.cmdarg = ((mmc->cfg->voltages & 0xff8000) != 0) << 8 | 0xaa;
Andy Flemingad347bb2008-10-30 16:41:01 -05002706 cmd.resp_type = MMC_RSP_R7;
Andy Flemingad347bb2008-10-30 16:41:01 -05002707
2708 err = mmc_send_cmd(mmc, &cmd, NULL);
2709
2710 if (err)
2711 return err;
2712
Rabin Vincentb6eed942009-04-05 13:30:56 +05302713 if ((cmd.response[0] & 0xff) != 0xaa)
Jaehoon Chung7825d202016-07-19 16:33:36 +09002714 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002715 else
2716 mmc->version = SD_VERSION_2;
2717
2718 return 0;
2719}
2720
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002721#if !CONFIG_IS_ENABLED(DM_MMC)
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002722/* board-specific MMC power initializations. */
2723__weak void board_mmc_power_init(void)
2724{
2725}
Simon Glass833b80d2017-04-22 19:10:56 -06002726#endif
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002727
Peng Fan15305962016-10-11 15:08:43 +08002728static int mmc_power_init(struct mmc *mmc)
2729{
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002730#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002731#if CONFIG_IS_ENABLED(DM_REGULATOR)
Peng Fan15305962016-10-11 15:08:43 +08002732 int ret;
2733
2734 ret = device_get_supply_regulator(mmc->dev, "vmmc-supply",
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002735 &mmc->vmmc_supply);
2736 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002737 pr_debug("%s: No vmmc supply\n", mmc->dev->name);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002738
2739 ret = device_get_supply_regulator(mmc->dev, "vqmmc-supply",
2740 &mmc->vqmmc_supply);
2741 if (ret)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002742 pr_debug("%s: No vqmmc supply\n", mmc->dev->name);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002743#endif
2744#else /* !CONFIG_DM_MMC */
2745 /*
2746 * Driver model should use a regulator, as above, rather than calling
2747 * out to board code.
2748 */
2749 board_mmc_power_init();
2750#endif
2751 return 0;
2752}
2753
2754/*
2755 * put the host in the initial state:
2756 * - turn on Vdd (card power supply)
2757 * - configure the bus width and clock to minimal values
2758 */
2759static void mmc_set_initial_state(struct mmc *mmc)
2760{
2761 int err;
2762
2763 /* First try to set 3.3V. If it fails set to 1.8V */
2764 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
2765 if (err != 0)
2766 err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
2767 if (err != 0)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01002768 pr_warn("mmc: failed to set signal voltage\n");
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002769
2770 mmc_select_mode(mmc, MMC_LEGACY);
2771 mmc_set_bus_width(mmc, 1);
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002772 mmc_set_clock(mmc, 0, MMC_CLK_ENABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002773}
Peng Fan15305962016-10-11 15:08:43 +08002774
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002775static int mmc_power_on(struct mmc *mmc)
2776{
2777#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002778 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002779 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2780 true);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002781
Jonas Karlman0f28e182023-07-19 21:20:59 +00002782 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002783 printf("Error enabling VMMC supply : %d\n", ret);
Jean-Jacques Hiblota49ffa12017-09-21 16:29:48 +02002784 return ret;
2785 }
Peng Fan15305962016-10-11 15:08:43 +08002786 }
2787#endif
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002788 return 0;
2789}
2790
2791static int mmc_power_off(struct mmc *mmc)
2792{
Jaehoon Chung239cb2f2018-01-26 19:25:29 +09002793 mmc_set_clock(mmc, 0, MMC_CLK_DISABLE);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002794#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
2795 if (mmc->vmmc_supply) {
Jonas Karlman0f28e182023-07-19 21:20:59 +00002796 int ret = regulator_set_enable_if_allowed(mmc->vmmc_supply,
2797 false);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002798
Jonas Karlman0f28e182023-07-19 21:20:59 +00002799 if (ret && ret != -ENOSYS) {
Jaehoon Chungad9f7ce2020-11-17 07:04:59 +09002800 pr_debug("Error disabling VMMC supply : %d\n", ret);
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002801 return ret;
2802 }
2803 }
Simon Glass833b80d2017-04-22 19:10:56 -06002804#endif
Peng Fan15305962016-10-11 15:08:43 +08002805 return 0;
2806}
2807
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002808static int mmc_power_cycle(struct mmc *mmc)
2809{
2810 int ret;
2811
2812 ret = mmc_power_off(mmc);
2813 if (ret)
2814 return ret;
Yann Gautier6f558332019-09-19 17:56:12 +02002815
2816 ret = mmc_host_power_cycle(mmc);
2817 if (ret)
2818 return ret;
2819
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002820 /*
2821 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
2822 * to be on the safer side.
2823 */
2824 udelay(2000);
2825 return mmc_power_on(mmc);
2826}
2827
Pali Rohár7c639622021-07-14 16:37:29 +02002828int mmc_get_op_cond(struct mmc *mmc, bool quiet)
Andy Flemingad347bb2008-10-30 16:41:01 -05002829{
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002830 bool uhs_en = supports_uhs(mmc->cfg->host_caps);
Macpaul Lin028bde12011-11-14 23:35:39 +00002831 int err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002832
Lei Wen31b99802011-05-02 16:26:26 +00002833 if (mmc->has_init)
2834 return 0;
2835
Peng Fan15305962016-10-11 15:08:43 +08002836 err = mmc_power_init(mmc);
2837 if (err)
2838 return err;
Paul Kocialkowski2439fe92014-11-08 20:55:45 +01002839
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002840#ifdef CONFIG_MMC_QUIRKS
2841 mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN |
Joel Johnson5ea041b2020-01-11 09:08:14 -07002842 MMC_QUIRK_RETRY_SEND_CID |
2843 MMC_QUIRK_RETRY_APP_CMD;
Kishon Vijay Abraham I07baaa62017-09-21 16:30:10 +02002844#endif
2845
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002846 err = mmc_power_cycle(mmc);
2847 if (err) {
2848 /*
2849 * if power cycling is not supported, we should not try
2850 * to use the UHS modes, because we wouldn't be able to
2851 * recover from an error during the UHS initialization.
2852 */
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09002853 pr_debug("Unable to do a full power cycle. Disabling the UHS modes for safety\n");
Jean-Jacques Hiblotdc030fb2017-09-21 16:30:08 +02002854 uhs_en = false;
2855 mmc->host_caps &= ~UHS_CAPS;
2856 err = mmc_power_on(mmc);
2857 }
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002858 if (err)
2859 return err;
2860
Simon Glasseba48f92017-07-29 11:35:31 -06002861#if CONFIG_IS_ENABLED(DM_MMC)
Yangbo Luc46f5d72020-09-01 16:57:59 +08002862 /*
2863 * Re-initialization is needed to clear old configuration for
2864 * mmc rescan.
2865 */
2866 err = mmc_reinit(mmc);
Simon Glass394dfc02016-06-12 23:30:22 -06002867#else
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02002868 /* made sure it's not NULL earlier */
Pantelis Antoniou2c850462014-03-11 19:34:20 +02002869 err = mmc->cfg->ops->init(mmc);
Yangbo Luc46f5d72020-09-01 16:57:59 +08002870#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05002871 if (err)
2872 return err;
Andrew Gabbasov9fc2a412014-12-01 06:59:09 -06002873 mmc->ddr_mode = 0;
Kishon Vijay Abraham I4afb12b2017-09-21 16:30:00 +02002874
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002875retry:
Kishon Vijay Abraham I80b87e12017-09-21 16:30:02 +02002876 mmc_set_initial_state(mmc);
Jean-Jacques Hiblot5f23d872017-09-21 16:30:01 +02002877
Andy Flemingad347bb2008-10-30 16:41:01 -05002878 /* Reset the Card */
2879 err = mmc_go_idle(mmc);
2880
2881 if (err)
2882 return err;
2883
Marcel Ziswilerb2b7fc82019-05-20 02:44:53 +02002884 /* The internal partition reset to user partition(0) at every CMD0 */
Simon Glasse5db1152016-05-01 13:52:35 -06002885 mmc_get_blk_desc(mmc)->hwpart = 0;
Lei Wen31b99802011-05-02 16:26:26 +00002886
Andy Flemingad347bb2008-10-30 16:41:01 -05002887 /* Test for SD version 2 */
Macpaul Lin028bde12011-11-14 23:35:39 +00002888 err = mmc_send_if_cond(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05002889
Andy Flemingad347bb2008-10-30 16:41:01 -05002890 /* Now try to get the SD card's operating condition */
Jean-Jacques Hiblotf4d5b3e2017-09-21 16:30:07 +02002891 err = sd_send_op_cond(mmc, uhs_en);
2892 if (err && uhs_en) {
2893 uhs_en = false;
2894 mmc_power_cycle(mmc);
2895 goto retry;
2896 }
Andy Flemingad347bb2008-10-30 16:41:01 -05002897
2898 /* If the command timed out, we check for an MMC card */
Jaehoon Chung7825d202016-07-19 16:33:36 +09002899 if (err == -ETIMEDOUT) {
Andy Flemingad347bb2008-10-30 16:41:01 -05002900 err = mmc_send_op_cond(mmc);
2901
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002902 if (err) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002903#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Pali Rohár7c639622021-07-14 16:37:29 +02002904 if (!quiet)
2905 pr_err("Card did not respond to voltage select! : %d\n", err);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01002906#endif
Jaehoon Chung7825d202016-07-19 16:33:36 +09002907 return -EOPNOTSUPP;
Andy Flemingad347bb2008-10-30 16:41:01 -05002908 }
2909 }
2910
Jon Nettleton2663fe42018-06-11 15:26:19 +03002911 return err;
2912}
2913
2914int mmc_start_init(struct mmc *mmc)
2915{
2916 bool no_card;
2917 int err = 0;
2918
2919 /*
2920 * all hosts are capable of 1 bit bus-width and able to use the legacy
2921 * timings.
2922 */
Faiz Abbas01db77e2020-02-26 13:44:32 +05302923 mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) |
Aswath Govindrajubb5b9fe2021-08-13 23:04:41 +05302924 MMC_MODE_1BIT;
2925
2926 if (IS_ENABLED(CONFIG_MMC_SPEED_MODE_SET)) {
2927 if (mmc->user_speed_mode != MMC_MODES_END) {
2928 int i;
2929 /* set host caps */
2930 if (mmc->host_caps & MMC_CAP(mmc->user_speed_mode)) {
2931 /* Remove all existing speed capabilities */
2932 for (i = MMC_LEGACY; i < MMC_MODES_END; i++)
2933 mmc->host_caps &= ~MMC_CAP(i);
2934 mmc->host_caps |= (MMC_CAP(mmc->user_speed_mode)
2935 | MMC_CAP(MMC_LEGACY) |
2936 MMC_MODE_1BIT);
2937 } else {
2938 pr_err("bus_mode requested is not supported\n");
2939 return -EINVAL;
2940 }
2941 }
2942 }
Faiz Abbasf6fd4ec2020-02-26 13:44:30 +05302943#if CONFIG_IS_ENABLED(DM_MMC)
2944 mmc_deferred_probe(mmc);
2945#endif
Jon Nettleton2663fe42018-06-11 15:26:19 +03002946#if !defined(CONFIG_MMC_BROKEN_CD)
Jon Nettleton2663fe42018-06-11 15:26:19 +03002947 no_card = mmc_getcd(mmc) == 0;
2948#else
2949 no_card = 0;
2950#endif
2951#if !CONFIG_IS_ENABLED(DM_MMC)
Baruch Siach0448ce62019-07-22 15:52:12 +03002952 /* we pretend there's no card when init is NULL */
Jon Nettleton2663fe42018-06-11 15:26:19 +03002953 no_card = no_card || (mmc->cfg->ops->init == NULL);
2954#endif
2955 if (no_card) {
2956 mmc->has_init = 0;
2957#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
2958 pr_err("MMC: no card present\n");
2959#endif
2960 return -ENOMEDIUM;
2961 }
2962
Pali Rohár7c639622021-07-14 16:37:29 +02002963 err = mmc_get_op_cond(mmc, false);
Jon Nettleton2663fe42018-06-11 15:26:19 +03002964
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002965 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00002966 mmc->init_in_progress = 1;
2967
2968 return err;
2969}
2970
2971static int mmc_complete_init(struct mmc *mmc)
2972{
2973 int err = 0;
2974
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002975 mmc->init_in_progress = 0;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00002976 if (mmc->op_cond_pending)
2977 err = mmc_complete_op_cond(mmc);
2978
2979 if (!err)
2980 err = mmc_startup(mmc);
Lei Wen31b99802011-05-02 16:26:26 +00002981 if (err)
2982 mmc->has_init = 0;
2983 else
2984 mmc->has_init = 1;
2985 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05002986}
2987
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00002988int mmc_init(struct mmc *mmc)
2989{
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05002990 int err = 0;
Vipul Kumardbad7b42018-05-03 12:20:54 +05302991 __maybe_unused ulong start;
Simon Glass5f4bd8c2017-07-04 13:31:19 -06002992#if CONFIG_IS_ENABLED(DM_MMC)
Simon Glass59bc6f22016-05-01 13:52:41 -06002993 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00002994
Simon Glass59bc6f22016-05-01 13:52:41 -06002995 upriv->mmc = mmc;
2996#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00002997 if (mmc->has_init)
2998 return 0;
Mateusz Zalegada351782014-04-29 20:15:30 +02002999
3000 start = get_timer(0);
3001
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003002 if (!mmc->init_in_progress)
3003 err = mmc_start_init(mmc);
3004
Andrew Gabbasov3a669bc2015-03-19 07:44:07 -05003005 if (!err)
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003006 err = mmc_complete_init(mmc);
Jagan Teki9bee2b52017-01-10 11:18:43 +01003007 if (err)
Masahiro Yamadaf97b1482018-01-28 19:11:42 +09003008 pr_info("%s: %d, time %lu\n", __func__, err, get_timer(start));
Jagan Teki9bee2b52017-01-10 11:18:43 +01003009
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003010 return err;
3011}
3012
Marek Vasuta4773fc2019-01-29 04:45:51 +01003013#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
3014 CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
3015 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
3016int mmc_deinit(struct mmc *mmc)
3017{
3018 u32 caps_filtered;
3019
3020 if (!mmc->has_init)
3021 return 0;
3022
3023 if (IS_SD(mmc)) {
3024 caps_filtered = mmc->card_caps &
3025 ~(MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) |
3026 MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
3027 MMC_CAP(UHS_SDR104));
3028
3029 return sd_select_mode_and_width(mmc, caps_filtered);
3030 } else {
3031 caps_filtered = mmc->card_caps &
Ye Li3679e802021-08-17 17:20:34 +08003032 ~(MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_HS_400) | MMC_CAP(MMC_HS_400_ES));
Marek Vasuta4773fc2019-01-29 04:45:51 +01003033
3034 return mmc_select_mode_and_width(mmc, caps_filtered);
3035 }
3036}
3037#endif
3038
Markus Niebel03951412013-12-16 13:40:46 +01003039int mmc_set_dsr(struct mmc *mmc, u16 val)
3040{
3041 mmc->dsr = val;
3042 return 0;
3043}
3044
Jeroen Hofstee47726302014-07-10 22:46:28 +02003045/* CPU-specific MMC initializations */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003046__weak int cpu_mmc_init(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003047{
3048 return -1;
3049}
3050
Jeroen Hofstee47726302014-07-10 22:46:28 +02003051/* board-specific MMC initializations. */
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003052__weak int board_mmc_init(struct bd_info *bis)
Jeroen Hofstee47726302014-07-10 22:46:28 +02003053{
3054 return -1;
3055}
Andy Flemingad347bb2008-10-30 16:41:01 -05003056
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003057void mmc_set_preinit(struct mmc *mmc, int preinit)
3058{
3059 mmc->preinit = preinit;
3060}
3061
Faiz Abbasb3857fd2018-02-12 19:35:24 +05303062#if CONFIG_IS_ENABLED(DM_MMC)
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003063static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003064{
Simon Glass547cb342015-12-29 05:22:49 -07003065 int ret, i;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003066 struct uclass *uc;
Simon Glass547cb342015-12-29 05:22:49 -07003067 struct udevice *dev;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003068
3069 ret = uclass_get(UCLASS_MMC, &uc);
3070 if (ret)
3071 return ret;
3072
Simon Glass547cb342015-12-29 05:22:49 -07003073 /*
3074 * Try to add them in sequence order. Really with driver model we
3075 * should allow holes, but the current MMC list does not allow that.
3076 * So if we request 0, 1, 3 we will get 0, 1, 2.
3077 */
3078 for (i = 0; ; i++) {
3079 ret = uclass_get_device_by_seq(UCLASS_MMC, i, &dev);
3080 if (ret == -ENODEV)
3081 break;
3082 }
3083 uclass_foreach_dev(dev, uc) {
3084 ret = device_probe(dev);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003085 if (ret)
Jean-Jacques Hiblot678b6082017-11-30 17:44:00 +01003086 pr_err("%s - probe failed: %d\n", dev->name, ret);
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003087 }
3088
3089 return 0;
3090}
3091#else
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003092static int mmc_probe(struct bd_info *bis)
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003093{
3094 if (board_mmc_init(bis) < 0)
3095 cpu_mmc_init(bis);
3096
3097 return 0;
3098}
3099#endif
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00003100
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09003101int mmc_initialize(struct bd_info *bis)
Andy Flemingad347bb2008-10-30 16:41:01 -05003102{
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003103 static int initialized = 0;
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003104 int ret;
Daniel Kochmański13df57b2015-05-29 16:55:43 +02003105 if (initialized) /* Avoid initializing mmc multiple times */
3106 return 0;
3107 initialized = 1;
3108
Simon Glass5f4bd8c2017-07-04 13:31:19 -06003109#if !CONFIG_IS_ENABLED(BLK)
Marek Vasutf537e392016-12-01 02:06:33 +01003110#if !CONFIG_IS_ENABLED(MMC_TINY)
Simon Glasse5db1152016-05-01 13:52:35 -06003111 mmc_list_init();
3112#endif
Marek Vasutf537e392016-12-01 02:06:33 +01003113#endif
Sjoerd Simonsdf8aa522015-08-30 16:55:45 -06003114 ret = mmc_probe(bis);
3115 if (ret)
3116 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -05003117
Ying Zhang9ff70262013-08-16 15:16:11 +08003118#ifndef CONFIG_SPL_BUILD
Andy Flemingad347bb2008-10-30 16:41:01 -05003119 print_mmc_devices(',');
Ying Zhang9ff70262013-08-16 15:16:11 +08003120#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05003121
Simon Glasse5db1152016-05-01 13:52:35 -06003122 mmc_do_preinit();
Andy Flemingad347bb2008-10-30 16:41:01 -05003123 return 0;
3124}
Tomas Melinc17dae52016-11-25 11:01:03 +02003125
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303126#if CONFIG_IS_ENABLED(DM_MMC)
3127int mmc_init_device(int num)
3128{
3129 struct udevice *dev;
3130 struct mmc *m;
3131 int ret;
3132
Aswath Govindraju57e2ccb2021-03-25 12:48:47 +05303133 if (uclass_get_device_by_seq(UCLASS_MMC, num, &dev)) {
3134 ret = uclass_get_device(UCLASS_MMC, num, &dev);
3135 if (ret)
3136 return ret;
3137 }
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303138
3139 m = mmc_get_mmc_dev(dev);
3140 if (!m)
3141 return 0;
Venkatesh Yadav Abbarapu6738fcb2022-09-29 10:22:49 +05303142
3143 /* Initialising user set speed mode */
3144 m->user_speed_mode = MMC_MODES_END;
3145
Lokesh Vutlac59b41c2019-09-09 14:40:36 +05303146 if (m->preinit)
3147 mmc_start_init(m);
3148
3149 return 0;
3150}
3151#endif
3152
Tomas Melinc17dae52016-11-25 11:01:03 +02003153#ifdef CONFIG_CMD_BKOPS_ENABLE
Marek Vasutefdeed62023-01-05 15:19:08 +01003154int mmc_set_bkops_enable(struct mmc *mmc, bool autobkops, bool enable)
Tomas Melinc17dae52016-11-25 11:01:03 +02003155{
3156 int err;
Marek Vasutefdeed62023-01-05 15:19:08 +01003157 u32 bit = autobkops ? BIT(1) : BIT(0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003158 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
3159
3160 err = mmc_send_ext_csd(mmc, ext_csd);
3161 if (err) {
3162 puts("Could not get ext_csd register values\n");
3163 return err;
3164 }
3165
3166 if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) {
3167 puts("Background operations not supported on device\n");
3168 return -EMEDIUMTYPE;
3169 }
3170
Marek Vasutefdeed62023-01-05 15:19:08 +01003171 if (enable && (ext_csd[EXT_CSD_BKOPS_EN] & bit)) {
Tomas Melinc17dae52016-11-25 11:01:03 +02003172 puts("Background operations already enabled\n");
3173 return 0;
3174 }
3175
Marek Vasutefdeed62023-01-05 15:19:08 +01003176 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN,
3177 enable ? bit : 0);
Tomas Melinc17dae52016-11-25 11:01:03 +02003178 if (err) {
Marek Vasutefdeed62023-01-05 15:19:08 +01003179 printf("Failed to %sable manual background operations\n",
3180 enable ? "en" : "dis");
Tomas Melinc17dae52016-11-25 11:01:03 +02003181 return err;
3182 }
3183
Marek Vasutefdeed62023-01-05 15:19:08 +01003184 printf("%sabled %s background operations\n",
3185 enable ? "En" : "Dis", autobkops ? "auto" : "manual");
Tomas Melinc17dae52016-11-25 11:01:03 +02003186
3187 return 0;
3188}
3189#endif
David Woodhouse49fee032020-08-04 10:05:46 +01003190
3191__weak int mmc_get_env_dev(void)
3192{
3193#ifdef CONFIG_SYS_MMC_ENV_DEV
3194 return CONFIG_SYS_MMC_ENV_DEV;
3195#else
3196 return 0;
3197#endif
3198}