drivers/mmc/core/regulator.c
Source file repositories/reference/linux-study-clean/drivers/mmc/core/regulator.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/mmc/core/regulator.c- Extension
.c- Size
- 11904 bytes
- Lines
- 433
- Domain
- Driver Families
- Bucket
- drivers/mmc
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/device.hlinux/err.hlinux/log2.hlinux/regulator/consumer.hlinux/workqueue.hlinux/mmc/host.hcore.hhost.h
Detected Declarations
function mmc_ocrbitnum_to_vddfunction mmc_regulator_get_ocrmaskfunction set_iosfunction mmc_regulator_set_voltage_if_supportedfunction start_signal_voltage_switchfunction mmc_regulator_set_vqmmc2function mmc_regulator_get_ocrmaskfunction mmc_undervoltage_workfnfunction mmc_handle_regulator_eventfunction mmc_regulator_register_undervoltage_notifierfunction mmc_regulator_unregister_undervoltage_notifierfunction mmc_regulator_get_supplyfunction mmc_regulator_enable_vqmmcfunction mmc_regulator_disable_vqmmcexport mmc_regulator_set_ocrexport mmc_regulator_set_vqmmcexport mmc_regulator_set_vqmmc2export mmc_regulator_get_supplyexport mmc_regulator_enable_vqmmcexport mmc_regulator_disable_vqmmc
Annotated Snippet
if (result == 0 && !mmc->regulator_enabled) {
result = regulator_enable(supply);
if (!result)
mmc->regulator_enabled = true;
}
} else if (mmc->regulator_enabled) {
result = regulator_disable(supply);
if (result == 0)
mmc->regulator_enabled = false;
}
if (result)
dev_err(mmc_dev(mmc),
"could not set regulator OCR (%d)\n", result);
return result;
}
EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr);
static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator,
int min_uV, int target_uV,
int max_uV)
{
int current_uV;
/*
* Check if supported first to avoid errors since we may try several
* signal levels during power up and don't want to show errors.
*/
if (!regulator_is_supported_voltage(regulator, min_uV, max_uV))
return -EINVAL;
/*
* The voltage is already set, no need to switch.
* Return 1 to indicate that no switch happened.
*/
current_uV = regulator_get_voltage(regulator);
if (current_uV == target_uV)
return 1;
return regulator_set_voltage_triplet(regulator, min_uV, target_uV,
max_uV);
}
/**
* mmc_regulator_set_vqmmc - Set VQMMC as per the ios
* @mmc: the host to regulate
* @ios: io bus settings
*
* For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible.
* That will match the behavior of old boards where VQMMC and VMMC were supplied
* by the same supply. The Bus Operating conditions for 3.3V signaling in the
* SD card spec also define VQMMC in terms of VMMC.
* If this is not possible we'll try the full 2.7-3.6V of the spec.
*
* For 1.2V and 1.8V signaling we'll try to get as close as possible to the
* requested voltage. This is definitely a good idea for UHS where there's a
* separate regulator on the card that's trying to make 1.8V and it's best if
* we match.
*
* This function is expected to be used by a controller's
* start_signal_voltage_switch() function.
*/
int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct device *dev = mmc_dev(mmc);
int ret, volt, min_uV, max_uV;
/* If no vqmmc supply then we can't change the voltage */
if (IS_ERR(mmc->supply.vqmmc))
return -EINVAL;
switch (ios->signal_voltage) {
case MMC_SIGNAL_VOLTAGE_120:
return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
1100000, 1200000, 1300000);
case MMC_SIGNAL_VOLTAGE_180:
return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
1700000, 1800000, 1950000);
case MMC_SIGNAL_VOLTAGE_330:
ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV);
if (ret < 0)
return ret;
dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n",
__func__, volt, max_uV);
min_uV = max(volt - 300000, 2700000);
max_uV = min(max_uV + 200000, 3600000);
/*
Annotation
- Immediate include surface: `linux/device.h`, `linux/err.h`, `linux/log2.h`, `linux/regulator/consumer.h`, `linux/workqueue.h`, `linux/mmc/host.h`, `core.h`, `host.h`.
- Detected declarations: `function mmc_ocrbitnum_to_vdd`, `function mmc_regulator_get_ocrmask`, `function set_ios`, `function mmc_regulator_set_voltage_if_supported`, `function start_signal_voltage_switch`, `function mmc_regulator_set_vqmmc2`, `function mmc_regulator_get_ocrmask`, `function mmc_undervoltage_workfn`, `function mmc_handle_regulator_event`, `function mmc_regulator_register_undervoltage_notifier`.
- Atlas domain: Driver Families / drivers/mmc.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.