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
This commit is contained in:
Ulf Hansson 2024-09-13 18:28:18 +08:00
parent 153196d550
commit a56ffd3a83
2 changed files with 45 additions and 0 deletions

View File

@ -226,6 +226,33 @@ int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
}
EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc);
/**
* mmc_regulator_set_vqmmc2 - Set vqmmc2 as per the ios->vqmmc2_voltage
* @mmc: The mmc host to regulate
* @ios: The io bus settings
*
* Sets a new voltage level for the vqmmc2 regulator, which may correspond to
* the vdd2 regulator for an SD UHS-II interface. This function is expected to
* be called by mmc host drivers.
*
* Returns a negative error code on failure, zero if the voltage level was
* changed successfully or a positive value if the level didn't need to change.
*/
int mmc_regulator_set_vqmmc2(struct mmc_host *mmc, struct mmc_ios *ios)
{
if (IS_ERR(mmc->supply.vqmmc2))
return -EINVAL;
switch (ios->vqmmc2_voltage) {
case MMC_VQMMC2_VOLTAGE_180:
return mmc_regulator_set_voltage_if_supported(
mmc->supply.vqmmc2, 1700000, 1800000, 1950000);
default:
return -EINVAL;
}
}
EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc2);
#else
static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
@ -252,6 +279,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc)
mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc");
mmc->supply.vqmmc2 = devm_regulator_get_optional(dev, "vqmmc2");
if (IS_ERR(mmc->supply.vmmc)) {
if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
@ -275,6 +303,12 @@ int mmc_regulator_get_supply(struct mmc_host *mmc)
dev_dbg(dev, "No vqmmc regulator found\n");
}
if (IS_ERR(mmc->supply.vqmmc2)) {
if (PTR_ERR(mmc->supply.vqmmc2) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_dbg(dev, "No vqmmc2 regulator found\n");
}
return 0;
}
EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);

View File

@ -75,6 +75,9 @@ struct mmc_ios {
#define MMC_SIGNAL_VOLTAGE_180 1
#define MMC_SIGNAL_VOLTAGE_120 2
unsigned char vqmmc2_voltage;
#define MMC_VQMMC2_VOLTAGE_180 0
unsigned char drv_type; /* driver type (A, B, C, D) */
#define MMC_SET_DRIVER_TYPE_B 0
@ -308,6 +311,7 @@ struct mmc_pwrseq;
struct mmc_supply {
struct regulator *vmmc; /* Card power supply */
struct regulator *vqmmc; /* Optional Vccq supply */
struct regulator *vqmmc2; /* Optional supply for phy */
};
struct mmc_ctx {
@ -590,6 +594,7 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit);
int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios);
int mmc_regulator_set_vqmmc2(struct mmc_host *mmc, struct mmc_ios *ios);
#else
static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
@ -603,6 +608,12 @@ static inline int mmc_regulator_set_vqmmc(struct mmc_host *mmc,
{
return -EINVAL;
}
static inline int mmc_regulator_set_vqmmc2(struct mmc_host *mmc,
struct mmc_ios *ios)
{
return -EINVAL;
}
#endif
int mmc_regulator_get_supply(struct mmc_host *mmc);