Loading Documentation/devicetree/bindings/regulator/da9210.txt +4 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,10 @@ Required properties: - compatible: must be "dlg,da9210" - reg: the i2c slave address of the regulator. It should be 0x68. Optional properties: - interrupts: a reference to the DA9210 interrupt, if available. Any standard regulator properties can be used to configure the single da9210 DCDC. Loading Documentation/devicetree/bindings/regulator/da9211.txt +30 −2 Original line number Diff line number Diff line * Dialog Semiconductor DA9211/DA9213 Voltage Regulator * Dialog Semiconductor DA9211/DA9213/DA9215 Voltage Regulator Required properties: - compatible: "dlg,da9211" or "dlg,da9213". - compatible: "dlg,da9211" or "dlg,da9213" or "dlg,da9215" - reg: I2C slave address, usually 0x68. - interrupts: the interrupt outputs of the controller - regulators: A node that houses a sub-node for each regulator within the Loading Loading @@ -66,3 +66,31 @@ Example 2) DA9213 }; }; }; Example 3) DA9215 pmic: da9215@68 { compatible = "dlg,da9215"; reg = <0x68>; interrupts = <3 27>; regulators { BUCKA { regulator-name = "VBUCKA"; regulator-min-microvolt = < 300000>; regulator-max-microvolt = <1570000>; regulator-min-microamp = <4000000>; regulator-max-microamp = <7000000>; enable-gpios = <&gpio 27 0>; }; BUCKB { regulator-name = "VBUCKB"; regulator-min-microvolt = < 300000>; regulator-max-microvolt = <1570000>; regulator-min-microamp = <4000000>; regulator-max-microamp = <7000000>; enable-gpios = <&gpio 17 0>; }; }; }; drivers/regulator/Kconfig +3 −3 Original line number Diff line number Diff line Loading @@ -209,13 +209,13 @@ config REGULATOR_DA9210 interface. config REGULATOR_DA9211 tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9214 regulator" tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9214/DA9215 regulator" depends on I2C select REGMAP_I2C help Say y here to support for the Dialog Semiconductor DA9211/DA9212 /DA9213/DA9214. The DA9211/DA9212/DA9213/DA9214 is a multi-phase synchronous /DA9213/DA9214/DA9215. The DA9211/DA9212/DA9213/DA9214/DA9215 is a multi-phase synchronous step down converter 12A or 16A DC-DC Buck controlled through an I2C interface. Loading drivers/regulator/core.c +61 −55 Original line number Diff line number Diff line Loading @@ -111,6 +111,11 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, const char *supply_name); static void _regulator_put(struct regulator *regulator); 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) Loading Loading @@ -1612,14 +1617,15 @@ static void _regulator_put(struct regulator *regulator) if (regulator->dev) sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); mutex_lock(&rdev->mutex); kfree(regulator->supply_name); list_del(®ulator->list); kfree(regulator); rdev->open_count--; rdev->exclusive = 0; mutex_unlock(&rdev->mutex); kfree(regulator->supply_name); kfree(regulator); module_put(rdev->owner); } Loading Loading @@ -3608,6 +3614,9 @@ static const struct attribute_group *regulator_dev_groups[] = { static void regulator_dev_release(struct device *dev) { struct regulator_dev *rdev = dev_get_drvdata(dev); kfree(rdev->constraints); of_node_put(rdev->dev.of_node); kfree(rdev); } Loading Loading @@ -3839,9 +3848,7 @@ void regulator_unregister(struct regulator_dev *rdev) unset_regulator_supplies(rdev); list_del(&rdev->list); mutex_unlock(®ulator_list_mutex); kfree(rdev->constraints); regulator_ena_gpio_free(rdev); of_node_put(rdev->dev.of_node); device_unregister(&rdev->dev); } EXPORT_SYMBOL_GPL(regulator_unregister); Loading Loading @@ -4161,38 +4168,18 @@ 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; /* * Since DT doesn't provide an idiomatic mechanism for * enabling full constraints and since it's much more natural * with DT to provide them just assume that a DT enabled * system has full constraints. */ if (of_have_populated_dt()) has_full_constraints = true; mutex_lock(®ulator_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, ®ulator_list, list) { ops = rdev->desc->ops; c = rdev->constraints; if (c && c->always_on) continue; return 0; if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) continue; return 0; mutex_lock(&rdev->mutex); Loading @@ -4209,8 +4196,8 @@ static int __init regulator_init_complete(void) goto unlock; if (have_full_constraints()) { /* We log since this may kill the system if it * goes wrong. */ /* 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) Loading @@ -4226,9 +4213,28 @@ static int __init regulator_init_complete(void) unlock: mutex_unlock(&rdev->mutex); return 0; } mutex_unlock(®ulator_list_mutex); 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 * with DT to provide them just assume that a DT enabled * system has full constraints. */ if (of_have_populated_dt()) has_full_constraints = true; /* 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. */ class_for_each_device(®ulator_class, NULL, NULL, regulator_late_cleanup); return 0; } Loading drivers/regulator/da9210-regulator.c +75 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ #include <linux/i2c.h> #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/slab.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> Loading Loading @@ -120,6 +122,55 @@ static int da9210_get_current_limit(struct regulator_dev *rdev) return da9210_buck_limits[sel]; } static irqreturn_t da9210_irq_handler(int irq, void *data) { struct da9210 *chip = data; unsigned int val, handled = 0; int error, ret = IRQ_NONE; error = regmap_read(chip->regmap, DA9210_REG_EVENT_B, &val); if (error < 0) goto error_i2c; if (val & DA9210_E_OVCURR) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); handled |= DA9210_E_OVCURR; } if (val & DA9210_E_NPWRGOOD) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_UNDER_VOLTAGE, NULL); handled |= DA9210_E_NPWRGOOD; } if (val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT)) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_OVER_TEMP, NULL); handled |= val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT); } if (val & DA9210_E_VMAX) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_REGULATION_OUT, NULL); handled |= DA9210_E_VMAX; } if (handled) { /* Clear handled events */ error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled); if (error < 0) goto error_i2c; ret = IRQ_HANDLED; } return ret; error_i2c: dev_err(regmap_get_device(chip->regmap), "I2C error : %d\n", error); return ret; } /* * I2C driver interface functions */ Loading Loading @@ -168,6 +219,30 @@ static int da9210_i2c_probe(struct i2c_client *i2c, } chip->rdev = rdev; if (i2c->irq) { error = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, da9210_irq_handler, IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, "da9210", chip); if (error) { dev_err(&i2c->dev, "Failed to request IRQ%u: %d\n", i2c->irq, error); return error; } error = regmap_update_bits(chip->regmap, DA9210_REG_MASK_B, DA9210_M_OVCURR | DA9210_M_NPWRGOOD | DA9210_M_TEMP_WARN | DA9210_M_TEMP_CRIT | DA9210_M_VMAX, 0); if (error < 0) { dev_err(&i2c->dev, "Failed to update mask reg: %d\n", error); return error; } } else { dev_warn(&i2c->dev, "No IRQ configured\n"); } i2c_set_clientdata(i2c, chip); Loading Loading
Documentation/devicetree/bindings/regulator/da9210.txt +4 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,10 @@ Required properties: - compatible: must be "dlg,da9210" - reg: the i2c slave address of the regulator. It should be 0x68. Optional properties: - interrupts: a reference to the DA9210 interrupt, if available. Any standard regulator properties can be used to configure the single da9210 DCDC. Loading
Documentation/devicetree/bindings/regulator/da9211.txt +30 −2 Original line number Diff line number Diff line * Dialog Semiconductor DA9211/DA9213 Voltage Regulator * Dialog Semiconductor DA9211/DA9213/DA9215 Voltage Regulator Required properties: - compatible: "dlg,da9211" or "dlg,da9213". - compatible: "dlg,da9211" or "dlg,da9213" or "dlg,da9215" - reg: I2C slave address, usually 0x68. - interrupts: the interrupt outputs of the controller - regulators: A node that houses a sub-node for each regulator within the Loading Loading @@ -66,3 +66,31 @@ Example 2) DA9213 }; }; }; Example 3) DA9215 pmic: da9215@68 { compatible = "dlg,da9215"; reg = <0x68>; interrupts = <3 27>; regulators { BUCKA { regulator-name = "VBUCKA"; regulator-min-microvolt = < 300000>; regulator-max-microvolt = <1570000>; regulator-min-microamp = <4000000>; regulator-max-microamp = <7000000>; enable-gpios = <&gpio 27 0>; }; BUCKB { regulator-name = "VBUCKB"; regulator-min-microvolt = < 300000>; regulator-max-microvolt = <1570000>; regulator-min-microamp = <4000000>; regulator-max-microamp = <7000000>; enable-gpios = <&gpio 17 0>; }; }; };
drivers/regulator/Kconfig +3 −3 Original line number Diff line number Diff line Loading @@ -209,13 +209,13 @@ config REGULATOR_DA9210 interface. config REGULATOR_DA9211 tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9214 regulator" tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9214/DA9215 regulator" depends on I2C select REGMAP_I2C help Say y here to support for the Dialog Semiconductor DA9211/DA9212 /DA9213/DA9214. The DA9211/DA9212/DA9213/DA9214 is a multi-phase synchronous /DA9213/DA9214/DA9215. The DA9211/DA9212/DA9213/DA9214/DA9215 is a multi-phase synchronous step down converter 12A or 16A DC-DC Buck controlled through an I2C interface. Loading
drivers/regulator/core.c +61 −55 Original line number Diff line number Diff line Loading @@ -111,6 +111,11 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, const char *supply_name); static void _regulator_put(struct regulator *regulator); 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) Loading Loading @@ -1612,14 +1617,15 @@ static void _regulator_put(struct regulator *regulator) if (regulator->dev) sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); mutex_lock(&rdev->mutex); kfree(regulator->supply_name); list_del(®ulator->list); kfree(regulator); rdev->open_count--; rdev->exclusive = 0; mutex_unlock(&rdev->mutex); kfree(regulator->supply_name); kfree(regulator); module_put(rdev->owner); } Loading Loading @@ -3608,6 +3614,9 @@ static const struct attribute_group *regulator_dev_groups[] = { static void regulator_dev_release(struct device *dev) { struct regulator_dev *rdev = dev_get_drvdata(dev); kfree(rdev->constraints); of_node_put(rdev->dev.of_node); kfree(rdev); } Loading Loading @@ -3839,9 +3848,7 @@ void regulator_unregister(struct regulator_dev *rdev) unset_regulator_supplies(rdev); list_del(&rdev->list); mutex_unlock(®ulator_list_mutex); kfree(rdev->constraints); regulator_ena_gpio_free(rdev); of_node_put(rdev->dev.of_node); device_unregister(&rdev->dev); } EXPORT_SYMBOL_GPL(regulator_unregister); Loading Loading @@ -4161,38 +4168,18 @@ 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; /* * Since DT doesn't provide an idiomatic mechanism for * enabling full constraints and since it's much more natural * with DT to provide them just assume that a DT enabled * system has full constraints. */ if (of_have_populated_dt()) has_full_constraints = true; mutex_lock(®ulator_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, ®ulator_list, list) { ops = rdev->desc->ops; c = rdev->constraints; if (c && c->always_on) continue; return 0; if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) continue; return 0; mutex_lock(&rdev->mutex); Loading @@ -4209,8 +4196,8 @@ static int __init regulator_init_complete(void) goto unlock; if (have_full_constraints()) { /* We log since this may kill the system if it * goes wrong. */ /* 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) Loading @@ -4226,9 +4213,28 @@ static int __init regulator_init_complete(void) unlock: mutex_unlock(&rdev->mutex); return 0; } mutex_unlock(®ulator_list_mutex); 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 * with DT to provide them just assume that a DT enabled * system has full constraints. */ if (of_have_populated_dt()) has_full_constraints = true; /* 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. */ class_for_each_device(®ulator_class, NULL, NULL, regulator_late_cleanup); return 0; } Loading
drivers/regulator/da9210-regulator.c +75 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ #include <linux/i2c.h> #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/slab.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> Loading Loading @@ -120,6 +122,55 @@ static int da9210_get_current_limit(struct regulator_dev *rdev) return da9210_buck_limits[sel]; } static irqreturn_t da9210_irq_handler(int irq, void *data) { struct da9210 *chip = data; unsigned int val, handled = 0; int error, ret = IRQ_NONE; error = regmap_read(chip->regmap, DA9210_REG_EVENT_B, &val); if (error < 0) goto error_i2c; if (val & DA9210_E_OVCURR) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); handled |= DA9210_E_OVCURR; } if (val & DA9210_E_NPWRGOOD) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_UNDER_VOLTAGE, NULL); handled |= DA9210_E_NPWRGOOD; } if (val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT)) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_OVER_TEMP, NULL); handled |= val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT); } if (val & DA9210_E_VMAX) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_REGULATION_OUT, NULL); handled |= DA9210_E_VMAX; } if (handled) { /* Clear handled events */ error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled); if (error < 0) goto error_i2c; ret = IRQ_HANDLED; } return ret; error_i2c: dev_err(regmap_get_device(chip->regmap), "I2C error : %d\n", error); return ret; } /* * I2C driver interface functions */ Loading Loading @@ -168,6 +219,30 @@ static int da9210_i2c_probe(struct i2c_client *i2c, } chip->rdev = rdev; if (i2c->irq) { error = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, da9210_irq_handler, IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, "da9210", chip); if (error) { dev_err(&i2c->dev, "Failed to request IRQ%u: %d\n", i2c->irq, error); return error; } error = regmap_update_bits(chip->regmap, DA9210_REG_MASK_B, DA9210_M_OVCURR | DA9210_M_NPWRGOOD | DA9210_M_TEMP_WARN | DA9210_M_TEMP_CRIT | DA9210_M_VMAX, 0); if (error < 0) { dev_err(&i2c->dev, "Failed to update mask reg: %d\n", error); return error; } } else { dev_warn(&i2c->dev, "No IRQ configured\n"); } i2c_set_clientdata(i2c, chip); Loading