aboutsummaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c108
-rw-r--r--drivers/regulator/s2mps11.c28
-rw-r--r--drivers/regulator/s5m8767.c13
3 files changed, 87 insertions, 62 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index d92612c51657..872e53f15590 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -110,6 +110,11 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
struct device *dev,
const char *supply_name);
+static struct regulator_dev *dev_to_rdev(struct device *dev)
+{
+ return container_of(dev, struct regulator_dev, dev);
+}
+
static const char *rdev_get_name(struct regulator_dev *rdev)
{
if (rdev->constraints && rdev->constraints->name)
@@ -774,7 +779,7 @@ static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state)
static void print_constraints(struct regulator_dev *rdev)
{
struct regulation_constraints *constraints = rdev->constraints;
- char buf[80] = "";
+ char buf[160] = "";
int count = 0;
int ret;
@@ -3994,13 +3999,57 @@ static int __init regulator_init(void)
/* init early to allow our consumers to complete system booting */
core_initcall(regulator_init);
-static int __init regulator_init_complete(void)
+static int __init regulator_late_cleanup(struct device *dev, void *data)
{
- struct regulator_dev *rdev;
- const struct regulator_ops *ops;
- struct regulation_constraints *c;
+ struct regulator_dev *rdev = dev_to_rdev(dev);
+ const struct regulator_ops *ops = rdev->desc->ops;
+ struct regulation_constraints *c = rdev->constraints;
int enabled, ret;
+ if (c && c->always_on)
+ return 0;
+
+ if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS))
+ return 0;
+
+ mutex_lock(&rdev->mutex);
+
+ if (rdev->use_count)
+ goto unlock;
+
+ /* If we can't read the status assume it's on. */
+ if (ops->is_enabled)
+ enabled = ops->is_enabled(rdev);
+ else
+ enabled = 1;
+
+ if (!enabled)
+ goto unlock;
+
+ if (have_full_constraints()) {
+ /* We log since this may kill the system if it goes
+ * wrong. */
+ rdev_info(rdev, "disabling\n");
+ ret = _regulator_do_disable(rdev);
+ if (ret != 0)
+ rdev_err(rdev, "couldn't disable: %d\n", ret);
+ } else {
+ /* The intention is that in future we will
+ * assume that full constraints are provided
+ * so warn even if we aren't going to do
+ * anything here.
+ */
+ rdev_warn(rdev, "incomplete constraints, leaving on\n");
+ }
+
+unlock:
+ mutex_unlock(&rdev->mutex);
+
+ return 0;
+}
+
+static int __init regulator_init_complete(void)
+{
/*
* Since DT doesn't provide an idiomatic mechanism for
* enabling full constraints and since it's much more natural
@@ -4010,58 +4059,13 @@ static int __init regulator_init_complete(void)
if (of_have_populated_dt())
has_full_constraints = true;
- mutex_lock(&regulator_list_mutex);
-
/* If we have a full configuration then disable any regulators
* we have permission to change the status for and which are
* not in use or always_on. This is effectively the default
* for DT and ACPI as they have full constraints.
*/
- list_for_each_entry(rdev, &regulator_list, list) {
- ops = rdev->desc->ops;
- c = rdev->constraints;
-
- if (c && c->always_on)
- continue;
-
- if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS))
- continue;
-
- mutex_lock(&rdev->mutex);
-
- if (rdev->use_count)
- goto unlock;
-
- /* If we can't read the status assume it's on. */
- if (ops->is_enabled)
- enabled = ops->is_enabled(rdev);
- else
- enabled = 1;
-
- if (!enabled)
- goto unlock;
-
- if (have_full_constraints()) {
- /* We log since this may kill the system if it
- * goes wrong. */
- rdev_info(rdev, "disabling\n");
- ret = _regulator_do_disable(rdev);
- if (ret != 0)
- rdev_err(rdev, "couldn't disable: %d\n", ret);
- } else {
- /* The intention is that in future we will
- * assume that full constraints are provided
- * so warn even if we aren't going to do
- * anything here.
- */
- rdev_warn(rdev, "incomplete constraints, leaving on\n");
- }
-
-unlock:
- mutex_unlock(&rdev->mutex);
- }
-
- mutex_unlock(&regulator_list_mutex);
+ class_for_each_device(&regulator_class, NULL, NULL,
+ regulator_late_cleanup);
return 0;
}
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 697be114e21a..ad9920c3dda7 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -302,7 +302,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \
}
-#define regulator_desc_s2mps11_buck6_10(num, min, step) { \
+#define regulator_desc_s2mps11_buck67810(num, min, step) { \
.name = "BUCK"#num, \
.id = S2MPS11_BUCK##num, \
.ops = &s2mps11_buck_ops, \
@@ -318,6 +318,22 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \
}
+#define regulator_desc_s2mps11_buck9 { \
+ .name = "BUCK9", \
+ .id = S2MPS11_BUCK9, \
+ .ops = &s2mps11_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = MIN_3000_MV, \
+ .uV_step = STEP_25_MV, \
+ .n_voltages = S2MPS11_BUCK9_N_VOLTAGES, \
+ .ramp_delay = S2MPS11_RAMP_DELAY, \
+ .vsel_reg = S2MPS11_REG_B9CTRL2, \
+ .vsel_mask = S2MPS11_BUCK9_VSEL_MASK, \
+ .enable_reg = S2MPS11_REG_B9CTRL1, \
+ .enable_mask = S2MPS11_ENABLE_MASK \
+}
+
static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_ldo(1, STEP_25_MV),
regulator_desc_s2mps11_ldo(2, STEP_50_MV),
@@ -362,11 +378,11 @@ static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_buck1_4(3),
regulator_desc_s2mps11_buck1_4(4),
regulator_desc_s2mps11_buck5,
- regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV),
- regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV),
+ regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck9,
+ regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV),
};
static int s2mps14_regulator_enable(struct regulator_dev *rdev)
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 0ab5cbeeb797..c53fe2645548 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -202,9 +202,10 @@ static int s5m8767_get_register(struct s5m8767_info *s5m8767, int reg_id,
}
}
- if (i < s5m8767->num_regulators)
- *enable_ctrl =
- s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
+ if (i >= s5m8767->num_regulators)
+ return -EINVAL;
+
+ *enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
return 0;
}
@@ -936,8 +937,12 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
else
regulators[id].vsel_mask = 0xff;
- s5m8767_get_register(s5m8767, id, &enable_reg,
+ ret = s5m8767_get_register(s5m8767, id, &enable_reg,
&enable_val);
+ if (ret) {
+ dev_err(s5m8767->dev, "error reading registers\n");
+ return ret;
+ }
regulators[id].enable_reg = enable_reg;
regulators[id].enable_mask = S5M8767_ENCTRL_MASK;
regulators[id].enable_val = enable_val;