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

Configure Feed

Select the types of activity you want to include in your feed.

mmc: core: Extend support for mmc regulators with a vqmmc2

To allow an additional external regulator to be controlled by an mmc host
driver, let's add support for a vqmmc2 regulator to the mmc core.

For an SD UHS-II interface the vqmmc2 regulator may correspond to the so
called vdd2 supply, as described by the SD spec. Initially, only 1.8V is
needed, hence limit the new helper function, mmc_regulator_set_vqmmc2() to
this too.

Note that, to allow for flexibility mmc host drivers need to manage the
enable/disable of the vqmmc2 regulator themselves, while the regulator is
looked up through the common mmc_regulator_get_supply().

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

+45
+34
drivers/mmc/core/regulator.c
··· 226 226 } 227 227 EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc); 228 228 229 + /** 230 + * mmc_regulator_set_vqmmc2 - Set vqmmc2 as per the ios->vqmmc2_voltage 231 + * @mmc: The mmc host to regulate 232 + * @ios: The io bus settings 233 + * 234 + * Sets a new voltage level for the vqmmc2 regulator, which may correspond to 235 + * the vdd2 regulator for an SD UHS-II interface. This function is expected to 236 + * be called by mmc host drivers. 237 + * 238 + * Returns a negative error code on failure, zero if the voltage level was 239 + * changed successfully or a positive value if the level didn't need to change. 240 + */ 241 + int mmc_regulator_set_vqmmc2(struct mmc_host *mmc, struct mmc_ios *ios) 242 + { 243 + if (IS_ERR(mmc->supply.vqmmc2)) 244 + return -EINVAL; 245 + 246 + switch (ios->vqmmc2_voltage) { 247 + case MMC_VQMMC2_VOLTAGE_180: 248 + return mmc_regulator_set_voltage_if_supported( 249 + mmc->supply.vqmmc2, 1700000, 1800000, 1950000); 250 + default: 251 + return -EINVAL; 252 + } 253 + } 254 + EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc2); 255 + 229 256 #else 230 257 231 258 static inline int mmc_regulator_get_ocrmask(struct regulator *supply) ··· 279 252 280 253 mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc"); 281 254 mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); 255 + mmc->supply.vqmmc2 = devm_regulator_get_optional(dev, "vqmmc2"); 282 256 283 257 if (IS_ERR(mmc->supply.vmmc)) { 284 258 if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) ··· 301 273 "vqmmc regulator not available\n"); 302 274 303 275 dev_dbg(dev, "No vqmmc regulator found\n"); 276 + } 277 + 278 + if (IS_ERR(mmc->supply.vqmmc2)) { 279 + if (PTR_ERR(mmc->supply.vqmmc2) == -EPROBE_DEFER) 280 + return -EPROBE_DEFER; 281 + dev_dbg(dev, "No vqmmc2 regulator found\n"); 304 282 } 305 283 306 284 return 0;
+11
include/linux/mmc/host.h
··· 75 75 #define MMC_SIGNAL_VOLTAGE_180 1 76 76 #define MMC_SIGNAL_VOLTAGE_120 2 77 77 78 + unsigned char vqmmc2_voltage; 79 + #define MMC_VQMMC2_VOLTAGE_180 0 80 + 78 81 unsigned char drv_type; /* driver type (A, B, C, D) */ 79 82 80 83 #define MMC_SET_DRIVER_TYPE_B 0 ··· 311 308 struct mmc_supply { 312 309 struct regulator *vmmc; /* Card power supply */ 313 310 struct regulator *vqmmc; /* Optional Vccq supply */ 311 + struct regulator *vqmmc2; /* Optional supply for phy */ 314 312 }; 315 313 316 314 struct mmc_ctx { ··· 594 590 struct regulator *supply, 595 591 unsigned short vdd_bit); 596 592 int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios); 593 + int mmc_regulator_set_vqmmc2(struct mmc_host *mmc, struct mmc_ios *ios); 597 594 #else 598 595 static inline int mmc_regulator_set_ocr(struct mmc_host *mmc, 599 596 struct regulator *supply, ··· 605 600 606 601 static inline int mmc_regulator_set_vqmmc(struct mmc_host *mmc, 607 602 struct mmc_ios *ios) 603 + { 604 + return -EINVAL; 605 + } 606 + 607 + static inline int mmc_regulator_set_vqmmc2(struct mmc_host *mmc, 608 + struct mmc_ios *ios) 608 609 { 609 610 return -EINVAL; 610 611 }