Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: core: Prepare to support SD UHS-II cards

The SD UHS-II interface was introduced to the SD spec v4.00 several years
ago. The interface is fundamentally different from an electrical and a
protocol point of view, comparing to the legacy SD interface.

However, the legacy SD protocol is supported through a specific transport
layer (SD-TRAN) defined in the UHS-II addendum of the spec. This allows the
SD card to be managed in a very similar way as a legacy SD card, hence a
lot of code can be re-used to support these new types of cards through the
mmc subsystem.

Moreover, an SD card that supports the UHS-II interface shall also be
backwards compatible with the legacy SD interface, which allows a UHS-II
card to be inserted into a legacy slot. As a matter of fact, this is
already supported by mmc subsystem as of today.

To prepare to add support for UHS-II, this change puts the basic foundation
in the mmc core in place, allowing it to be more easily reviewed before
subsequent changes implements the actual support.

Basically, the approach here adds a new UHS-II bus_ops type and adds a
separate initialization path for the UHS-II card. The intent is to avoid us
from sprinkling the legacy initialization path, but also to simplify
implementation of the UHS-II specific bits.

At this point, there is only one new host ops added to manage the various
ios settings needed for UHS-II. Additional host ops that are needed, are
being added from subsequent changes.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20240913102836.6144-3-victorshihgli@gmail.com

+342 -2
+1 -1
drivers/mmc/core/Makefile
··· 7 7 mmc_core-y := core.o bus.o host.o \ 8 8 mmc.o mmc_ops.o sd.o sd_ops.o \ 9 9 sdio.o sdio_ops.o sdio_bus.o \ 10 - sdio_cis.o sdio_io.o sdio_irq.o \ 10 + sdio_cis.o sdio_io.o sdio_irq.o sd_uhs2.o\ 11 11 slot-gpio.o regulator.o 12 12 mmc_core-$(CONFIG_OF) += pwrseq.o 13 13 obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o
+16 -1
drivers/mmc/core/core.c
··· 2267 2267 goto out; 2268 2268 } 2269 2269 2270 + /* 2271 + * Ideally we should favor initialization of legacy SD cards and defer 2272 + * UHS-II enumeration. However, it seems like cards doesn't reliably 2273 + * announce their support for UHS-II in the response to the ACMD41, 2274 + * while initializing the legacy SD interface. Therefore, let's start 2275 + * with UHS-II for now. 2276 + */ 2277 + if (!mmc_attach_sd_uhs2(host)) { 2278 + mmc_release_host(host); 2279 + goto out; 2280 + } 2281 + 2270 2282 for (i = 0; i < ARRAY_SIZE(freqs); i++) { 2271 2283 unsigned int freq = freqs[i]; 2272 2284 if (freq > host->f_max) { ··· 2311 2299 2312 2300 void mmc_start_host(struct mmc_host *host) 2313 2301 { 2302 + bool power_up = !(host->caps2 & 2303 + (MMC_CAP2_NO_PRESCAN_POWERUP | MMC_CAP2_SD_UHS2)); 2304 + 2314 2305 host->f_init = max(min(freqs[0], host->f_max), host->f_min); 2315 2306 host->rescan_disable = 0; 2316 2307 2317 - if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) { 2308 + if (power_up) { 2318 2309 mmc_claim_host(host); 2319 2310 mmc_power_up(host, host->ocr_avail); 2320 2311 mmc_release_host(host);
+1
drivers/mmc/core/core.h
··· 81 81 int mmc_attach_mmc(struct mmc_host *host); 82 82 int mmc_attach_sd(struct mmc_host *host); 83 83 int mmc_attach_sdio(struct mmc_host *host); 84 + int mmc_attach_sd_uhs2(struct mmc_host *host); 84 85 85 86 /* Module parameters */ 86 87 extern bool use_spi_crc;
+294
drivers/mmc/core/sd_uhs2.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2021 Linaro Ltd 4 + * 5 + * Author: Ulf Hansson <ulf.hansson@linaro.org> 6 + * 7 + * Support for SD UHS-II cards 8 + */ 9 + #include <linux/err.h> 10 + 11 + #include <linux/mmc/host.h> 12 + #include <linux/mmc/card.h> 13 + 14 + #include "core.h" 15 + #include "bus.h" 16 + #include "sd.h" 17 + #include "mmc_ops.h" 18 + 19 + static const unsigned int sd_uhs2_freqs[] = { 52000000, 26000000 }; 20 + 21 + static int sd_uhs2_power_up(struct mmc_host *host) 22 + { 23 + int err; 24 + 25 + if (host->ios.power_mode == MMC_POWER_ON) 26 + return 0; 27 + 28 + host->ios.vdd = fls(host->ocr_avail) - 1; 29 + host->ios.clock = host->f_init; 30 + host->ios.timing = MMC_TIMING_UHS2_SPEED_A; 31 + host->ios.power_mode = MMC_POWER_ON; 32 + 33 + err = host->ops->uhs2_control(host, UHS2_SET_IOS); 34 + 35 + return err; 36 + } 37 + 38 + static int sd_uhs2_power_off(struct mmc_host *host) 39 + { 40 + if (host->ios.power_mode == MMC_POWER_OFF) 41 + return 0; 42 + 43 + host->ios.vdd = 0; 44 + host->ios.clock = 0; 45 + host->ios.timing = MMC_TIMING_LEGACY; 46 + host->ios.power_mode = MMC_POWER_OFF; 47 + 48 + return host->ops->uhs2_control(host, UHS2_SET_IOS); 49 + } 50 + 51 + /* 52 + * Run the phy initialization sequence, which mainly relies on the UHS-II host 53 + * to check that we reach the expected electrical state, between the host and 54 + * the card. 55 + */ 56 + static int sd_uhs2_phy_init(struct mmc_host *host) 57 + { 58 + return 0; 59 + } 60 + 61 + /* 62 + * Do the early initialization of the card, by sending the device init broadcast 63 + * command and wait for the process to be completed. 64 + */ 65 + static int sd_uhs2_dev_init(struct mmc_host *host) 66 + { 67 + return 0; 68 + } 69 + 70 + /* 71 + * Run the enumeration process by sending the enumerate command to the card. 72 + * Note that, we currently support only the point to point connection, which 73 + * means only one card can be attached per host/slot. 74 + */ 75 + static int sd_uhs2_enum(struct mmc_host *host, u32 *node_id) 76 + { 77 + return 0; 78 + } 79 + 80 + /* 81 + * Read the UHS-II configuration registers (CFG_REG) of the card, by sending it 82 + * commands and by parsing the responses. Store a copy of the relevant data in 83 + * card->uhs2_config. 84 + */ 85 + static int sd_uhs2_config_read(struct mmc_host *host, struct mmc_card *card) 86 + { 87 + return 0; 88 + } 89 + 90 + /* 91 + * Based on the card's and host's UHS-II capabilities, let's update the 92 + * configuration of the card and the host. This may also include to move to a 93 + * greater speed range/mode. Depending on the updated configuration, we may need 94 + * to do a soft reset of the card via sending it a GO_DORMANT_STATE command. 95 + * 96 + * In the final step, let's check if the card signals "config completion", which 97 + * indicates that the card has moved from config state into active state. 98 + */ 99 + static int sd_uhs2_config_write(struct mmc_host *host, struct mmc_card *card) 100 + { 101 + return 0; 102 + } 103 + 104 + /* 105 + * Initialize the UHS-II card through the SD-TRAN transport layer. This enables 106 + * commands/requests to be backwards compatible through the legacy SD protocol. 107 + * UHS-II cards has a specific power limit specified for VDD1/VDD2, that should 108 + * be set through a legacy CMD6. Note that, the power limit that becomes set, 109 + * survives a soft reset through the GO_DORMANT_STATE command. 110 + */ 111 + static int sd_uhs2_legacy_init(struct mmc_host *host, struct mmc_card *card) 112 + { 113 + return 0; 114 + } 115 + 116 + /* 117 + * Allocate the data structure for the mmc_card and run the UHS-II specific 118 + * initialization sequence. 119 + */ 120 + static int sd_uhs2_init_card(struct mmc_host *host) 121 + { 122 + struct mmc_card *card; 123 + u32 node_id = 0; 124 + int err; 125 + 126 + err = sd_uhs2_dev_init(host); 127 + if (err) 128 + return err; 129 + 130 + err = sd_uhs2_enum(host, &node_id); 131 + if (err) 132 + return err; 133 + 134 + card = mmc_alloc_card(host, &sd_type); 135 + if (IS_ERR(card)) 136 + return PTR_ERR(card); 137 + 138 + card->uhs2_config.node_id = node_id; 139 + card->type = MMC_TYPE_SD; 140 + 141 + err = sd_uhs2_config_read(host, card); 142 + if (err) 143 + goto err; 144 + 145 + err = sd_uhs2_config_write(host, card); 146 + if (err) 147 + goto err; 148 + 149 + host->card = card; 150 + return 0; 151 + 152 + err: 153 + mmc_remove_card(card); 154 + return err; 155 + } 156 + 157 + static void sd_uhs2_remove(struct mmc_host *host) 158 + { 159 + mmc_remove_card(host->card); 160 + host->card = NULL; 161 + } 162 + 163 + static int sd_uhs2_alive(struct mmc_host *host) 164 + { 165 + return mmc_send_status(host->card, NULL); 166 + } 167 + 168 + static void sd_uhs2_detect(struct mmc_host *host) 169 + { 170 + int err; 171 + 172 + mmc_get_card(host->card, NULL); 173 + err = _mmc_detect_card_removed(host); 174 + mmc_put_card(host->card, NULL); 175 + 176 + if (err) { 177 + sd_uhs2_remove(host); 178 + 179 + mmc_claim_host(host); 180 + mmc_detach_bus(host); 181 + sd_uhs2_power_off(host); 182 + mmc_release_host(host); 183 + } 184 + } 185 + 186 + static int sd_uhs2_suspend(struct mmc_host *host) 187 + { 188 + return 0; 189 + } 190 + 191 + static int sd_uhs2_resume(struct mmc_host *host) 192 + { 193 + return 0; 194 + } 195 + 196 + static int sd_uhs2_runtime_suspend(struct mmc_host *host) 197 + { 198 + return 0; 199 + } 200 + 201 + static int sd_uhs2_runtime_resume(struct mmc_host *host) 202 + { 203 + return 0; 204 + } 205 + 206 + static int sd_uhs2_shutdown(struct mmc_host *host) 207 + { 208 + return 0; 209 + } 210 + 211 + static int sd_uhs2_hw_reset(struct mmc_host *host) 212 + { 213 + return 0; 214 + } 215 + 216 + static const struct mmc_bus_ops sd_uhs2_ops = { 217 + .remove = sd_uhs2_remove, 218 + .alive = sd_uhs2_alive, 219 + .detect = sd_uhs2_detect, 220 + .suspend = sd_uhs2_suspend, 221 + .resume = sd_uhs2_resume, 222 + .runtime_suspend = sd_uhs2_runtime_suspend, 223 + .runtime_resume = sd_uhs2_runtime_resume, 224 + .shutdown = sd_uhs2_shutdown, 225 + .hw_reset = sd_uhs2_hw_reset, 226 + }; 227 + 228 + static int sd_uhs2_attach(struct mmc_host *host) 229 + { 230 + int err; 231 + 232 + err = sd_uhs2_power_up(host); 233 + if (err) 234 + goto err; 235 + 236 + err = sd_uhs2_phy_init(host); 237 + if (err) 238 + goto err; 239 + 240 + err = sd_uhs2_init_card(host); 241 + if (err) 242 + goto err; 243 + 244 + err = sd_uhs2_legacy_init(host, host->card); 245 + if (err) 246 + goto err; 247 + 248 + mmc_attach_bus(host, &sd_uhs2_ops); 249 + 250 + mmc_release_host(host); 251 + 252 + err = mmc_add_card(host->card); 253 + if (err) 254 + goto remove_card; 255 + 256 + mmc_claim_host(host); 257 + return 0; 258 + 259 + remove_card: 260 + mmc_remove_card(host->card); 261 + host->card = NULL; 262 + mmc_claim_host(host); 263 + mmc_detach_bus(host); 264 + err: 265 + sd_uhs2_power_off(host); 266 + return err; 267 + } 268 + 269 + int mmc_attach_sd_uhs2(struct mmc_host *host) 270 + { 271 + int i, err = 0; 272 + 273 + if (!(host->caps2 & MMC_CAP2_SD_UHS2)) 274 + return -EOPNOTSUPP; 275 + 276 + /* Turn off the legacy SD interface before trying with UHS-II. */ 277 + mmc_power_off(host); 278 + 279 + /* 280 + * Start UHS-II initialization at 52MHz and possibly make a retry at 281 + * 26MHz according to the spec. It's required that the host driver 282 + * validates ios->clock, to set a rate within the correct range. 283 + */ 284 + for (i = 0; i < ARRAY_SIZE(sd_uhs2_freqs); i++) { 285 + host->f_init = sd_uhs2_freqs[i]; 286 + pr_debug("%s: %s: trying to init UHS-II card at %u Hz\n", 287 + mmc_hostname(host), __func__, host->f_init); 288 + err = sd_uhs2_attach(host); 289 + if (!err) 290 + break; 291 + } 292 + 293 + return err; 294 + }
+7
include/linux/mmc/card.h
··· 209 209 #define SD_EXT_PERF_CMD_QUEUE (1<<4) 210 210 }; 211 211 212 + struct sd_uhs2_config { 213 + u32 node_id; 214 + /* TODO: Extend with more register configs. */ 215 + }; 216 + 212 217 struct sdio_cccr { 213 218 unsigned int sdio_vsn; 214 219 unsigned int sd_vsn; ··· 324 319 struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ 325 320 struct sd_ext_reg ext_power; /* SD extension reg for PM */ 326 321 struct sd_ext_reg ext_perf; /* SD extension reg for PERF */ 322 + 323 + struct sd_uhs2_config uhs2_config; /* SD UHS-II config */ 327 324 328 325 unsigned int sdio_funcs; /* number of SDIO functions */ 329 326 atomic_t sdio_funcs_probed; /* number of probed SDIO funcs */
+23
include/linux/mmc/host.h
··· 64 64 #define MMC_TIMING_MMC_HS400 10 65 65 #define MMC_TIMING_SD_EXP 11 66 66 #define MMC_TIMING_SD_EXP_1_2V 12 67 + #define MMC_TIMING_UHS2_SPEED_A 13 68 + #define MMC_TIMING_UHS2_SPEED_A_HD 14 69 + #define MMC_TIMING_UHS2_SPEED_B 15 70 + #define MMC_TIMING_UHS2_SPEED_B_HD 16 67 71 68 72 unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */ 69 73 ··· 94 90 #define MMC_NUM_CLK_PHASES (MMC_TIMING_MMC_HS400 + 1) 95 91 struct mmc_clk_phase_map { 96 92 struct mmc_clk_phase phase[MMC_NUM_CLK_PHASES]; 93 + }; 94 + 95 + struct sd_uhs2_caps { 96 + /* TODO: Add UHS-II capabilities for the host. */ 97 + }; 98 + 99 + enum sd_uhs2_operation { 100 + UHS2_SET_IOS, 97 101 }; 98 102 99 103 struct mmc_host; ··· 231 219 232 220 /* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP. */ 233 221 int (*init_sd_express)(struct mmc_host *host, struct mmc_ios *ios); 222 + 223 + /* 224 + * The uhs2_control callback is used to execute SD UHS-II specific 225 + * operations. It's mandatory to implement for hosts that supports the 226 + * SD UHS-II interface (MMC_CAP2_SD_UHS2). Expected return values are a 227 + * negative errno in case of a failure or zero for success. 228 + */ 229 + int (*uhs2_control)(struct mmc_host *host, enum sd_uhs2_operation op); 234 230 }; 235 231 236 232 struct mmc_cqe_ops { ··· 399 379 MMC_CAP2_HS200_1_2V_SDR) 400 380 #define MMC_CAP2_SD_EXP (1 << 7) /* SD express via PCIe */ 401 381 #define MMC_CAP2_SD_EXP_1_2V (1 << 8) /* SD express 1.2V */ 382 + #define MMC_CAP2_SD_UHS2 (1 << 9) /* SD UHS-II support */ 402 383 #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ 403 384 #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ 404 385 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ ··· 425 404 #define MMC_CAP2_CRYPTO 0 426 405 #endif 427 406 #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28) /* Host with eMMC that has GPT entry at a non-standard location */ 407 + 408 + struct sd_uhs2_caps uhs2_caps; /* Host UHS-II capabilities */ 428 409 429 410 int fixed_drv_type; /* fixed driver type for non-removable media */ 430 411