mirror of https://gitee.com/openkylin/linux.git
Merge series "regulator_sync_state() support" from Saravana Kannan <saravanak@google.com>:
Consider the following example: - regulator-X is provided by device-X. - regulator-X is a supplier to device-A, device-B and device-C. - device-A is off/inactive from boot. - device-B and device-C are left on/active by the bootloader - regulator-X is left on boot by the bootloader at 2000 mV to supply device-B and device-C. Example boot sequence 1: 1. device-X is probed successfully. 2. device-A is probed by driver-A a. driver-A gets regulator-X b. driver-A votes on regulator-X c. driver-A initializes device-A d. driver-A votes off regulator-X e. regulator-X is turned off. 3. System crashes or device-B and device-C become unreliable because regulator-X was turned off without following the proper quiescing steps for device-B and device-C. Example boot sequence 2: 1. device-X is probed successfully. 2. device-B is probed by driver-B a. driver-B gets regulator-X b. driver-B votes on regulator-X c. driver-B lowers device-B performance point. d. driver-B lowers voltage vote to 1000 mV. e. regulator-X voltage is lowered to 1000 mV. 3. System crashes or device-C becomes unreliable because regulator-X voltage was lowered to 1000 mV when device-C still needed it at 2000 mV This patch series makes sure these examples are handled correctly and system crash or device instability is avoided and the system remains usable. More details provided in the commit texts. v2->v3: Patch 2/4 - No functional change. Simple refactor. Patch 3/4 - Was Patch 2/2 in v2. - Rewrote commit text to hopefully address all previous points. - Renamed variable/functions. Hope it's clearer. - Added more comments. - Added logging - Fixed timeout functionality. - Handle exclusive consumers properly - Handle coupled regulators properly Patch 4/4 - Prevents voltage from going too low during boot. v1->v2: Patch 1/2 - New patch Patch 2/2 - This was the only patch in v1 - Made the late_initcall_sync timeout a commandline param - If timeout is set, we also give up waiting for all consumers after the timeout expires. - Made every regulator driver add sync_state() support Saravana Kannan (4): driver core: Add dev_set_drv_sync_state() regulator: core: Add destroy_regulator() regulator: core: Add basic enable/disable support for sync_state() callbacks regulator: core: Add voltage support for sync_state() callbacks drivers/regulator/core.c | 200 ++++++++++++++++++++++++++++--- include/linux/device.h | 12 ++ include/linux/regulator/driver.h | 2 + 3 files changed, 198 insertions(+), 16 deletions(-) -- 2.28.0.rc0.105.gf9edc3c819-goog
This commit is contained in:
commit
f70e472d69
|
@ -105,6 +105,7 @@ static int regulator_balance_voltage(struct regulator_dev *rdev,
|
||||||
static struct regulator *create_regulator(struct regulator_dev *rdev,
|
static struct regulator *create_regulator(struct regulator_dev *rdev,
|
||||||
struct device *dev,
|
struct device *dev,
|
||||||
const char *supply_name);
|
const char *supply_name);
|
||||||
|
static void destroy_regulator(struct regulator *regulator);
|
||||||
static void _regulator_put(struct regulator *regulator);
|
static void _regulator_put(struct regulator *regulator);
|
||||||
|
|
||||||
const char *rdev_get_name(struct regulator_dev *rdev)
|
const char *rdev_get_name(struct regulator_dev *rdev)
|
||||||
|
@ -2034,20 +2035,9 @@ struct regulator *regulator_get_optional(struct device *dev, const char *id)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regulator_get_optional);
|
EXPORT_SYMBOL_GPL(regulator_get_optional);
|
||||||
|
|
||||||
/* regulator_list_mutex lock held by regulator_put() */
|
static void destroy_regulator(struct regulator *regulator)
|
||||||
static void _regulator_put(struct regulator *regulator)
|
|
||||||
{
|
{
|
||||||
struct regulator_dev *rdev;
|
struct regulator_dev *rdev = regulator->rdev;
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(regulator))
|
|
||||||
return;
|
|
||||||
|
|
||||||
lockdep_assert_held_once(®ulator_list_mutex);
|
|
||||||
|
|
||||||
/* Docs say you must disable before calling regulator_put() */
|
|
||||||
WARN_ON(regulator->enable_count);
|
|
||||||
|
|
||||||
rdev = regulator->rdev;
|
|
||||||
|
|
||||||
debugfs_remove_recursive(regulator->debugfs);
|
debugfs_remove_recursive(regulator->debugfs);
|
||||||
|
|
||||||
|
@ -2068,6 +2058,24 @@ static void _regulator_put(struct regulator *regulator)
|
||||||
|
|
||||||
kfree_const(regulator->supply_name);
|
kfree_const(regulator->supply_name);
|
||||||
kfree(regulator);
|
kfree(regulator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* regulator_list_mutex lock held by regulator_put() */
|
||||||
|
static void _regulator_put(struct regulator *regulator)
|
||||||
|
{
|
||||||
|
struct regulator_dev *rdev;
|
||||||
|
|
||||||
|
if (IS_ERR_OR_NULL(regulator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
lockdep_assert_held_once(®ulator_list_mutex);
|
||||||
|
|
||||||
|
/* Docs say you must disable before calling regulator_put() */
|
||||||
|
WARN_ON(regulator->enable_count);
|
||||||
|
|
||||||
|
rdev = regulator->rdev;
|
||||||
|
|
||||||
|
destroy_regulator(regulator);
|
||||||
|
|
||||||
module_put(rdev->owner);
|
module_put(rdev->owner);
|
||||||
put_device(&rdev->dev);
|
put_device(&rdev->dev);
|
||||||
|
|
Loading…
Reference in New Issue