diff options
| -rw-r--r-- | Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt | 29 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/regulator/lp872x.txt | 1 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/regulator/regulator.txt | 5 | ||||
| -rw-r--r-- | drivers/regulator/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
| -rw-r--r-- | drivers/regulator/core.c | 11 | ||||
| -rw-r--r-- | drivers/regulator/fan53555.c | 18 | ||||
| -rw-r--r-- | drivers/regulator/gpio-regulator.c | 6 | ||||
| -rw-r--r-- | drivers/regulator/helpers.c | 23 | ||||
| -rw-r--r-- | drivers/regulator/hi655x-regulator.c | 227 | ||||
| -rw-r--r-- | drivers/regulator/lp872x.c | 38 | ||||
| -rw-r--r-- | drivers/regulator/of_regulator.c | 6 | ||||
| -rw-r--r-- | include/linux/regulator/driver.h | 17 | ||||
| -rw-r--r-- | include/linux/regulator/lp872x.h | 5 | ||||
| -rw-r--r-- | include/linux/regulator/machine.h | 12 |
15 files changed, 402 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt b/Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt new file mode 100644 index 000000000000..14cfdc564159 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | Hisilicon Hi655x Voltage regulators | ||
| 2 | |||
| 3 | Note: | ||
| 4 | The Hi655x regulator control is managed by Hi655x PMIC. | ||
| 5 | So the node of this regulator must be child node of Hi655x | ||
| 6 | PMIC node. | ||
| 7 | |||
| 8 | The driver uses the regulator core framework, so please also | ||
| 9 | take the bindings of regulator.txt for reference. | ||
| 10 | |||
| 11 | The valid names for regulators are: | ||
| 12 | |||
| 13 | LDO2_2V8 LDO7_SDIO LDO10_2V85 LDO13_1V8 LDO14_2V8 | ||
| 14 | LDO15_1V8 LDO17_2V5 LDO19_3V0 LDO21_1V8 LDO22_1V2 | ||
| 15 | |||
| 16 | Example: | ||
| 17 | pmic: pmic@f8000000 { | ||
| 18 | compatible = "hisilicon,hi655x-pmic"; | ||
| 19 | ... | ||
| 20 | regulators { | ||
| 21 | ldo2: LDO2@a21 { | ||
| 22 | regulator-name = "LDO2_2V8"; | ||
| 23 | regulator-min-microvolt = <2500000>; | ||
| 24 | regulator-max-microvolt = <3200000>; | ||
| 25 | regulator-enable-ramp-delay = <120>; | ||
| 26 | }; | ||
| 27 | ... | ||
| 28 | } | ||
| 29 | } | ||
diff --git a/Documentation/devicetree/bindings/regulator/lp872x.txt b/Documentation/devicetree/bindings/regulator/lp872x.txt index 78183182dad9..ca58a68ffdf1 100644 --- a/Documentation/devicetree/bindings/regulator/lp872x.txt +++ b/Documentation/devicetree/bindings/regulator/lp872x.txt | |||
| @@ -28,6 +28,7 @@ Optional properties: | |||
| 28 | - ti,dvs-gpio: GPIO specifier for external DVS pin control of LP872x devices. | 28 | - ti,dvs-gpio: GPIO specifier for external DVS pin control of LP872x devices. |
| 29 | - ti,dvs-vsel: DVS selector. 0 = SEL_V1, 1 = SEL_V2. | 29 | - ti,dvs-vsel: DVS selector. 0 = SEL_V1, 1 = SEL_V2. |
| 30 | - ti,dvs-state: initial DVS pin state. 0 = DVS_LOW, 1 = DVS_HIGH. | 30 | - ti,dvs-state: initial DVS pin state. 0 = DVS_LOW, 1 = DVS_HIGH. |
| 31 | - enable-gpios: GPIO specifier for EN pin control of LP872x devices. | ||
| 31 | 32 | ||
| 32 | Sub nodes for regulator_init_data | 33 | Sub nodes for regulator_init_data |
| 33 | LP8720 has maximum 6 nodes. (child name: ldo1 ~ 5 and buck) | 34 | LP8720 has maximum 6 nodes. (child name: ldo1 ~ 5 and buck) |
diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 1d112fc456aa..ecfc593cac15 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt | |||
| @@ -44,6 +44,11 @@ Optional properties: | |||
| 44 | any consumer request. | 44 | any consumer request. |
| 45 | - regulator-pull-down: Enable pull down resistor when the regulator is disabled. | 45 | - regulator-pull-down: Enable pull down resistor when the regulator is disabled. |
| 46 | - regulator-over-current-protection: Enable over current protection. | 46 | - regulator-over-current-protection: Enable over current protection. |
| 47 | - regulator-active-discharge: tristate, enable/disable active discharge of | ||
| 48 | regulators. The values are: | ||
| 49 | 0: Disable active discharge. | ||
| 50 | 1: Enable active discharge. | ||
| 51 | Absence of this property will leave configuration to default. | ||
| 47 | 52 | ||
| 48 | Deprecated properties: | 53 | Deprecated properties: |
| 49 | - regulator-compatible: If a regulator chip contains multiple | 54 | - regulator-compatible: If a regulator chip contains multiple |
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 74a6354eaefa..39b422b97ec0 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
| @@ -270,6 +270,14 @@ config REGULATOR_HI6421 | |||
| 270 | 21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All | 270 | 21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All |
| 271 | of them come with support to either ECO (idle) or sleep mode. | 271 | of them come with support to either ECO (idle) or sleep mode. |
| 272 | 272 | ||
| 273 | config REGULATOR_HI655X | ||
| 274 | tristate "Hisilicon HI655X PMIC regulators support" | ||
| 275 | depends on ARCH_HISI || COMPILE_TEST | ||
| 276 | depends on MFD_HI655X_PMIC && OF | ||
| 277 | help | ||
| 278 | This driver provides support for the voltage regulators of the | ||
| 279 | Hisilicon Hi655x PMIC device. | ||
| 280 | |||
| 273 | config REGULATOR_ISL9305 | 281 | config REGULATOR_ISL9305 |
| 274 | tristate "Intersil ISL9305 regulator" | 282 | tristate "Intersil ISL9305 regulator" |
| 275 | depends on I2C | 283 | depends on I2C |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 348cfd727350..bba7b7093bac 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
| @@ -35,6 +35,7 @@ obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o | |||
| 35 | obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o | 35 | obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o |
| 36 | obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o | 36 | obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o |
| 37 | obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o | 37 | obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o |
| 38 | obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o | ||
| 38 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o | 39 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o |
| 39 | obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o | 40 | obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o |
| 40 | obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o | 41 | obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 055f8c1a83a8..1cff11205642 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
| @@ -1139,6 +1139,17 @@ static int set_machine_constraints(struct regulator_dev *rdev, | |||
| 1139 | } | 1139 | } |
| 1140 | } | 1140 | } |
| 1141 | 1141 | ||
| 1142 | if (rdev->constraints->active_discharge && ops->set_active_discharge) { | ||
| 1143 | bool ad_state = (rdev->constraints->active_discharge == | ||
| 1144 | REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; | ||
| 1145 | |||
| 1146 | ret = ops->set_active_discharge(rdev, ad_state); | ||
| 1147 | if (ret < 0) { | ||
| 1148 | rdev_err(rdev, "failed to set active discharge\n"); | ||
| 1149 | return ret; | ||
| 1150 | } | ||
| 1151 | } | ||
| 1152 | |||
| 1142 | print_constraints(rdev); | 1153 | print_constraints(rdev); |
| 1143 | return 0; | 1154 | return 0; |
| 1144 | } | 1155 | } |
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 4940e8287df6..2cb5cc311610 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c | |||
| @@ -114,6 +114,22 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) | |||
| 114 | return 0; | 114 | return 0; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | static int fan53555_set_suspend_enable(struct regulator_dev *rdev) | ||
| 118 | { | ||
| 119 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); | ||
| 120 | |||
| 121 | return regmap_update_bits(di->regmap, di->sleep_reg, | ||
| 122 | VSEL_BUCK_EN, VSEL_BUCK_EN); | ||
| 123 | } | ||
| 124 | |||
| 125 | static int fan53555_set_suspend_disable(struct regulator_dev *rdev) | ||
| 126 | { | ||
| 127 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); | ||
| 128 | |||
| 129 | return regmap_update_bits(di->regmap, di->sleep_reg, | ||
| 130 | VSEL_BUCK_EN, 0); | ||
| 131 | } | ||
| 132 | |||
| 117 | static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode) | 133 | static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode) |
| 118 | { | 134 | { |
| 119 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); | 135 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); |
| @@ -192,6 +208,8 @@ static struct regulator_ops fan53555_regulator_ops = { | |||
| 192 | .set_mode = fan53555_set_mode, | 208 | .set_mode = fan53555_set_mode, |
| 193 | .get_mode = fan53555_get_mode, | 209 | .get_mode = fan53555_get_mode, |
| 194 | .set_ramp_delay = fan53555_set_ramp, | 210 | .set_ramp_delay = fan53555_set_ramp, |
| 211 | .set_suspend_enable = fan53555_set_suspend_enable, | ||
| 212 | .set_suspend_disable = fan53555_set_suspend_disable, | ||
| 195 | }; | 213 | }; |
| 196 | 214 | ||
| 197 | static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) | 215 | static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) |
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 7bba8b747f30..a8718e98674a 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c | |||
| @@ -283,8 +283,10 @@ static int gpio_regulator_probe(struct platform_device *pdev) | |||
| 283 | drvdata->nr_gpios = config->nr_gpios; | 283 | drvdata->nr_gpios = config->nr_gpios; |
| 284 | ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios); | 284 | ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios); |
| 285 | if (ret) { | 285 | if (ret) { |
| 286 | dev_err(&pdev->dev, | 286 | if (ret != -EPROBE_DEFER) |
| 287 | "Could not obtain regulator setting GPIOs: %d\n", ret); | 287 | dev_err(&pdev->dev, |
| 288 | "Could not obtain regulator setting GPIOs: %d\n", | ||
| 289 | ret); | ||
| 288 | goto err_memstate; | 290 | goto err_memstate; |
| 289 | } | 291 | } |
| 290 | } | 292 | } |
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index 3bbb32680a94..b1e32e7482e9 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c | |||
| @@ -465,3 +465,26 @@ int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) | |||
| 465 | return 0; | 465 | return 0; |
| 466 | } | 466 | } |
| 467 | EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); | 467 | EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); |
| 468 | |||
| 469 | /** | ||
| 470 | * regulator_set_active_discharge_regmap - Default set_active_discharge() | ||
| 471 | * using regmap | ||
| 472 | * | ||
| 473 | * @rdev: device to operate on. | ||
| 474 | * @enable: state to set, 0 to disable and 1 to enable. | ||
| 475 | */ | ||
| 476 | int regulator_set_active_discharge_regmap(struct regulator_dev *rdev, | ||
| 477 | bool enable) | ||
| 478 | { | ||
| 479 | unsigned int val; | ||
| 480 | |||
| 481 | if (enable) | ||
| 482 | val = rdev->desc->active_discharge_on; | ||
| 483 | else | ||
| 484 | val = rdev->desc->active_discharge_off; | ||
| 485 | |||
| 486 | return regmap_update_bits(rdev->regmap, | ||
| 487 | rdev->desc->active_discharge_reg, | ||
| 488 | rdev->desc->active_discharge_mask, val); | ||
| 489 | } | ||
| 490 | EXPORT_SYMBOL_GPL(regulator_set_active_discharge_regmap); | ||
diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c new file mode 100644 index 000000000000..aca18466f522 --- /dev/null +++ b/drivers/regulator/hi655x-regulator.c | |||
| @@ -0,0 +1,227 @@ | |||
| 1 | /* | ||
| 2 | * Device driver for regulators in Hi655x IC | ||
| 3 | * | ||
| 4 | * Copyright (c) 2016 Hisilicon. | ||
| 5 | * | ||
| 6 | * Authors: | ||
| 7 | * Chen Feng <puck.chen@hisilicon.com> | ||
| 8 | * Fei Wang <w.f@huawei.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/bitops.h> | ||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/err.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/io.h> | ||
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/regmap.h> | ||
| 23 | #include <linux/regulator/driver.h> | ||
| 24 | #include <linux/regulator/machine.h> | ||
| 25 | #include <linux/regulator/of_regulator.h> | ||
| 26 | #include <linux/mfd/hi655x-pmic.h> | ||
| 27 | |||
| 28 | struct hi655x_regulator { | ||
| 29 | unsigned int disable_reg; | ||
| 30 | unsigned int status_reg; | ||
| 31 | unsigned int ctrl_regs; | ||
| 32 | unsigned int ctrl_mask; | ||
| 33 | struct regulator_desc rdesc; | ||
| 34 | }; | ||
| 35 | |||
| 36 | /* LDO7 & LDO10 */ | ||
| 37 | static const unsigned int ldo7_voltages[] = { | ||
| 38 | 1800000, 1850000, 2850000, 2900000, | ||
| 39 | 3000000, 3100000, 3200000, 3300000, | ||
| 40 | }; | ||
| 41 | |||
| 42 | static const unsigned int ldo19_voltages[] = { | ||
| 43 | 1800000, 1850000, 1900000, 1750000, | ||
| 44 | 2800000, 2850000, 2900000, 3000000, | ||
| 45 | }; | ||
| 46 | |||
| 47 | static const unsigned int ldo22_voltages[] = { | ||
| 48 | 900000, 1000000, 1050000, 1100000, | ||
| 49 | 1150000, 1175000, 1185000, 1200000, | ||
| 50 | }; | ||
| 51 | |||
| 52 | enum hi655x_regulator_id { | ||
| 53 | HI655X_LDO0, | ||
| 54 | HI655X_LDO1, | ||
| 55 | HI655X_LDO2, | ||
| 56 | HI655X_LDO3, | ||
| 57 | HI655X_LDO4, | ||
| 58 | HI655X_LDO5, | ||
| 59 | HI655X_LDO6, | ||
| 60 | HI655X_LDO7, | ||
| 61 | HI655X_LDO8, | ||
| 62 | HI655X_LDO9, | ||
| 63 | HI655X_LDO10, | ||
| 64 | HI655X_LDO11, | ||
| 65 | HI655X_LDO12, | ||
| 66 | HI655X_LDO13, | ||
| 67 | HI655X_LDO14, | ||
| 68 | HI655X_LDO15, | ||
| 69 | HI655X_LDO16, | ||
| 70 | HI655X_LDO17, | ||
| 71 | HI655X_LDO18, | ||
| 72 | HI655X_LDO19, | ||
| 73 | HI655X_LDO20, | ||
| 74 | HI655X_LDO21, | ||
| 75 | HI655X_LDO22, | ||
| 76 | }; | ||
| 77 | |||
| 78 | static int hi655x_is_enabled(struct regulator_dev *rdev) | ||
| 79 | { | ||
| 80 | unsigned int value = 0; | ||
| 81 | |||
| 82 | struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); | ||
| 83 | |||
| 84 | regmap_read(rdev->regmap, regulator->status_reg, &value); | ||
| 85 | return (value & BIT(regulator->ctrl_mask)); | ||
| 86 | } | ||
| 87 | |||
| 88 | static int hi655x_disable(struct regulator_dev *rdev) | ||
| 89 | { | ||
| 90 | int ret = 0; | ||
| 91 | |||
| 92 | struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); | ||
| 93 | |||
| 94 | ret = regmap_write(rdev->regmap, regulator->disable_reg, | ||
| 95 | BIT(regulator->ctrl_mask)); | ||
| 96 | return ret; | ||
| 97 | } | ||
| 98 | |||
| 99 | static struct regulator_ops hi655x_regulator_ops = { | ||
| 100 | .enable = regulator_enable_regmap, | ||
| 101 | .disable = hi655x_disable, | ||
| 102 | .is_enabled = hi655x_is_enabled, | ||
| 103 | .list_voltage = regulator_list_voltage_table, | ||
| 104 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
| 105 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
| 106 | }; | ||
| 107 | |||
| 108 | static struct regulator_ops hi655x_ldo_linear_ops = { | ||
| 109 | .enable = regulator_enable_regmap, | ||
| 110 | .disable = hi655x_disable, | ||
| 111 | .is_enabled = hi655x_is_enabled, | ||
| 112 | .list_voltage = regulator_list_voltage_linear, | ||
| 113 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
| 114 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
| 115 | }; | ||
| 116 | |||
| 117 | #define HI655X_LDO(_ID, vreg, vmask, ereg, dreg, \ | ||
| 118 | sreg, cmask, vtable) { \ | ||
| 119 | .rdesc = { \ | ||
| 120 | .name = #_ID, \ | ||
| 121 | .of_match = of_match_ptr(#_ID), \ | ||
| 122 | .ops = &hi655x_regulator_ops, \ | ||
| 123 | .regulators_node = of_match_ptr("regulators"), \ | ||
| 124 | .type = REGULATOR_VOLTAGE, \ | ||
| 125 | .id = HI655X_##_ID, \ | ||
| 126 | .owner = THIS_MODULE, \ | ||
| 127 | .n_voltages = ARRAY_SIZE(vtable), \ | ||
| 128 | .volt_table = vtable, \ | ||
| 129 | .vsel_reg = HI655X_BUS_ADDR(vreg), \ | ||
| 130 | .vsel_mask = vmask, \ | ||
| 131 | .enable_reg = HI655X_BUS_ADDR(ereg), \ | ||
| 132 | .enable_mask = BIT(cmask), \ | ||
| 133 | }, \ | ||
| 134 | .disable_reg = HI655X_BUS_ADDR(dreg), \ | ||
| 135 | .status_reg = HI655X_BUS_ADDR(sreg), \ | ||
| 136 | .ctrl_mask = cmask, \ | ||
| 137 | } | ||
| 138 | |||
| 139 | #define HI655X_LDO_LINEAR(_ID, vreg, vmask, ereg, dreg, \ | ||
| 140 | sreg, cmask, minv, nvolt, vstep) { \ | ||
| 141 | .rdesc = { \ | ||
| 142 | .name = #_ID, \ | ||
| 143 | .of_match = of_match_ptr(#_ID), \ | ||
| 144 | .ops = &hi655x_ldo_linear_ops, \ | ||
| 145 | .regulators_node = of_match_ptr("regulators"), \ | ||
| 146 | .type = REGULATOR_VOLTAGE, \ | ||
| 147 | .id = HI655X_##_ID, \ | ||
| 148 | .owner = THIS_MODULE, \ | ||
| 149 | .min_uV = minv, \ | ||
| 150 | .n_voltages = nvolt, \ | ||
| 151 | .uV_step = vstep, \ | ||
| 152 | .vsel_reg = HI655X_BUS_ADDR(vreg), \ | ||
| 153 | .vsel_mask = vmask, \ | ||
| 154 | .enable_reg = HI655X_BUS_ADDR(ereg), \ | ||
| 155 | .enable_mask = BIT(cmask), \ | ||
| 156 | }, \ | ||
| 157 | .disable_reg = HI655X_BUS_ADDR(dreg), \ | ||
| 158 | .status_reg = HI655X_BUS_ADDR(sreg), \ | ||
| 159 | .ctrl_mask = cmask, \ | ||
| 160 | } | ||
| 161 | |||
| 162 | static struct hi655x_regulator regulators[] = { | ||
| 163 | HI655X_LDO_LINEAR(LDO2, 0x72, 0x07, 0x29, 0x2a, 0x2b, 0x01, | ||
| 164 | 2500000, 8, 100000), | ||
| 165 | HI655X_LDO(LDO7, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x06, ldo7_voltages), | ||
| 166 | HI655X_LDO(LDO10, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x01, ldo7_voltages), | ||
| 167 | HI655X_LDO_LINEAR(LDO13, 0x7e, 0x07, 0x2c, 0x2d, 0x2e, 0x04, | ||
| 168 | 1600000, 8, 50000), | ||
| 169 | HI655X_LDO_LINEAR(LDO14, 0x7f, 0x07, 0x2c, 0x2d, 0x2e, 0x05, | ||
| 170 | 2500000, 8, 100000), | ||
| 171 | HI655X_LDO_LINEAR(LDO15, 0x80, 0x07, 0x2c, 0x2d, 0x2e, 0x06, | ||
| 172 | 1600000, 8, 50000), | ||
| 173 | HI655X_LDO_LINEAR(LDO17, 0x82, 0x07, 0x2f, 0x30, 0x31, 0x00, | ||
| 174 | 2500000, 8, 100000), | ||
| 175 | HI655X_LDO(LDO19, 0x84, 0x07, 0x2f, 0x30, 0x31, 0x02, ldo19_voltages), | ||
| 176 | HI655X_LDO_LINEAR(LDO21, 0x86, 0x07, 0x2f, 0x30, 0x31, 0x04, | ||
| 177 | 1650000, 8, 50000), | ||
| 178 | HI655X_LDO(LDO22, 0x87, 0x07, 0x2f, 0x30, 0x31, 0x05, ldo22_voltages), | ||
| 179 | }; | ||
| 180 | |||
| 181 | static int hi655x_regulator_probe(struct platform_device *pdev) | ||
| 182 | { | ||
| 183 | unsigned int i; | ||
| 184 | struct hi655x_regulator *regulator; | ||
| 185 | struct hi655x_pmic *pmic; | ||
| 186 | struct regulator_config config = { }; | ||
| 187 | struct regulator_dev *rdev; | ||
| 188 | |||
| 189 | pmic = dev_get_drvdata(pdev->dev.parent); | ||
| 190 | if (!pmic) { | ||
| 191 | dev_err(&pdev->dev, "no pmic in the regulator parent node\n"); | ||
| 192 | return -ENODEV; | ||
| 193 | } | ||
| 194 | |||
| 195 | regulator = devm_kzalloc(&pdev->dev, sizeof(*regulator), GFP_KERNEL); | ||
| 196 | if (!regulator) | ||
| 197 | return -ENOMEM; | ||
| 198 | |||
| 199 | platform_set_drvdata(pdev, regulator); | ||
| 200 | |||
| 201 | config.dev = pdev->dev.parent; | ||
| 202 | config.regmap = pmic->regmap; | ||
| 203 | config.driver_data = regulator; | ||
| 204 | for (i = 0; i < ARRAY_SIZE(regulators); i++) { | ||
| 205 | rdev = devm_regulator_register(&pdev->dev, | ||
| 206 | ®ulators[i].rdesc, | ||
| 207 | &config); | ||
| 208 | if (IS_ERR(rdev)) { | ||
| 209 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
| 210 | regulator->rdesc.name); | ||
| 211 | return PTR_ERR(rdev); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | static struct platform_driver hi655x_regulator_driver = { | ||
| 218 | .driver = { | ||
| 219 | .name = "hi655x-regulator", | ||
| 220 | }, | ||
| 221 | .probe = hi655x_regulator_probe, | ||
| 222 | }; | ||
| 223 | module_platform_driver(hi655x_regulator_driver); | ||
| 224 | |||
| 225 | MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>"); | ||
| 226 | MODULE_DESCRIPTION("Hisilicon Hi655x regulator driver"); | ||
| 227 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 19d758486553..38992112fd6e 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/regmap.h> | 15 | #include <linux/regmap.h> |
| 16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
| 17 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
| 18 | #include <linux/delay.h> | ||
| 18 | #include <linux/regulator/lp872x.h> | 19 | #include <linux/regulator/lp872x.h> |
| 19 | #include <linux/regulator/driver.h> | 20 | #include <linux/regulator/driver.h> |
| 20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| @@ -738,10 +739,8 @@ static int lp872x_init_dvs(struct lp872x *lp) | |||
| 738 | goto set_default_dvs_mode; | 739 | goto set_default_dvs_mode; |
| 739 | 740 | ||
| 740 | gpio = dvs->gpio; | 741 | gpio = dvs->gpio; |
| 741 | if (!gpio_is_valid(gpio)) { | 742 | if (!gpio_is_valid(gpio)) |
| 742 | dev_warn(lp->dev, "invalid gpio: %d\n", gpio); | ||
| 743 | goto set_default_dvs_mode; | 743 | goto set_default_dvs_mode; |
| 744 | } | ||
| 745 | 744 | ||
| 746 | pinstate = dvs->init_state; | 745 | pinstate = dvs->init_state; |
| 747 | ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS"); | 746 | ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS"); |
| @@ -759,6 +758,33 @@ set_default_dvs_mode: | |||
| 759 | default_dvs_mode[lp->chipid]); | 758 | default_dvs_mode[lp->chipid]); |
| 760 | } | 759 | } |
| 761 | 760 | ||
| 761 | static int lp872x_hw_enable(struct lp872x *lp) | ||
| 762 | { | ||
| 763 | int ret, gpio; | ||
| 764 | |||
| 765 | if (!lp->pdata) | ||
| 766 | return -EINVAL; | ||
| 767 | |||
| 768 | gpio = lp->pdata->enable_gpio; | ||
| 769 | if (!gpio_is_valid(gpio)) | ||
| 770 | return 0; | ||
| 771 | |||
| 772 | /* Always set enable GPIO high. */ | ||
| 773 | ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X EN"); | ||
| 774 | if (ret) { | ||
| 775 | dev_err(lp->dev, "gpio request err: %d\n", ret); | ||
| 776 | return ret; | ||
| 777 | } | ||
| 778 | |||
| 779 | /* Each chip has a different enable delay. */ | ||
| 780 | if (lp->chipid == LP8720) | ||
| 781 | usleep_range(LP8720_ENABLE_DELAY, 1.5 * LP8720_ENABLE_DELAY); | ||
| 782 | else | ||
| 783 | usleep_range(LP8725_ENABLE_DELAY, 1.5 * LP8725_ENABLE_DELAY); | ||
| 784 | |||
| 785 | return 0; | ||
| 786 | } | ||
| 787 | |||
| 762 | static int lp872x_config(struct lp872x *lp) | 788 | static int lp872x_config(struct lp872x *lp) |
| 763 | { | 789 | { |
| 764 | struct lp872x_platform_data *pdata = lp->pdata; | 790 | struct lp872x_platform_data *pdata = lp->pdata; |
| @@ -877,6 +903,8 @@ static struct lp872x_platform_data | |||
| 877 | of_property_read_u8(np, "ti,dvs-state", &dvs_state); | 903 | of_property_read_u8(np, "ti,dvs-state", &dvs_state); |
| 878 | pdata->dvs->init_state = dvs_state ? DVS_HIGH : DVS_LOW; | 904 | pdata->dvs->init_state = dvs_state ? DVS_HIGH : DVS_LOW; |
| 879 | 905 | ||
| 906 | pdata->enable_gpio = of_get_named_gpio(np, "enable-gpios", 0); | ||
| 907 | |||
| 880 | if (of_get_child_count(np) == 0) | 908 | if (of_get_child_count(np) == 0) |
| 881 | goto out; | 909 | goto out; |
| 882 | 910 | ||
| @@ -950,6 +978,10 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) | |||
| 950 | lp->chipid = id->driver_data; | 978 | lp->chipid = id->driver_data; |
| 951 | i2c_set_clientdata(cl, lp); | 979 | i2c_set_clientdata(cl, lp); |
| 952 | 980 | ||
| 981 | ret = lp872x_hw_enable(lp); | ||
| 982 | if (ret) | ||
| 983 | return ret; | ||
| 984 | |||
| 953 | ret = lp872x_config(lp); | 985 | ret = lp872x_config(lp); |
| 954 | if (ret) | 986 | if (ret) |
| 955 | return ret; | 987 | return ret; |
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 499e437c7e91..fe2e33441dae 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c | |||
| @@ -93,6 +93,12 @@ static void of_get_regulation_constraints(struct device_node *np, | |||
| 93 | 93 | ||
| 94 | constraints->soft_start = of_property_read_bool(np, | 94 | constraints->soft_start = of_property_read_bool(np, |
| 95 | "regulator-soft-start"); | 95 | "regulator-soft-start"); |
| 96 | ret = of_property_read_u32(np, "regulator-active-discharge", &pval); | ||
| 97 | if (!ret) { | ||
| 98 | constraints->active_discharge = | ||
| 99 | (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE : | ||
| 100 | REGULATOR_ACTIVE_DISCHARGE_DISABLE; | ||
| 101 | } | ||
| 96 | 102 | ||
| 97 | if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) { | 103 | if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) { |
| 98 | if (desc && desc->of_map_mode) { | 104 | if (desc && desc->of_map_mode) { |
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 16ac9e108806..cd271e89a7e6 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h | |||
| @@ -93,6 +93,8 @@ struct regulator_linear_range { | |||
| 93 | * @get_current_limit: Get the configured limit for a current-limited regulator. | 93 | * @get_current_limit: Get the configured limit for a current-limited regulator. |
| 94 | * @set_input_current_limit: Configure an input limit. | 94 | * @set_input_current_limit: Configure an input limit. |
| 95 | * | 95 | * |
| 96 | * @set_active_discharge: Set active discharge enable/disable of regulators. | ||
| 97 | * | ||
| 96 | * @set_mode: Set the configured operating mode for the regulator. | 98 | * @set_mode: Set the configured operating mode for the regulator. |
| 97 | * @get_mode: Get the configured operating mode for the regulator. | 99 | * @get_mode: Get the configured operating mode for the regulator. |
| 98 | * @get_status: Return actual (not as-configured) status of regulator, as a | 100 | * @get_status: Return actual (not as-configured) status of regulator, as a |
| @@ -149,6 +151,7 @@ struct regulator_ops { | |||
| 149 | 151 | ||
| 150 | int (*set_input_current_limit) (struct regulator_dev *, int lim_uA); | 152 | int (*set_input_current_limit) (struct regulator_dev *, int lim_uA); |
| 151 | int (*set_over_current_protection) (struct regulator_dev *); | 153 | int (*set_over_current_protection) (struct regulator_dev *); |
| 154 | int (*set_active_discharge) (struct regulator_dev *, bool enable); | ||
| 152 | 155 | ||
| 153 | /* enable/disable regulator */ | 156 | /* enable/disable regulator */ |
| 154 | int (*enable) (struct regulator_dev *); | 157 | int (*enable) (struct regulator_dev *); |
| @@ -266,6 +269,14 @@ enum regulator_type { | |||
| 266 | * @bypass_mask: Mask for control when using regmap set_bypass | 269 | * @bypass_mask: Mask for control when using regmap set_bypass |
| 267 | * @bypass_val_on: Enabling value for control when using regmap set_bypass | 270 | * @bypass_val_on: Enabling value for control when using regmap set_bypass |
| 268 | * @bypass_val_off: Disabling value for control when using regmap set_bypass | 271 | * @bypass_val_off: Disabling value for control when using regmap set_bypass |
| 272 | * @active_discharge_off: Enabling value for control when using regmap | ||
| 273 | * set_active_discharge | ||
| 274 | * @active_discharge_on: Disabling value for control when using regmap | ||
| 275 | * set_active_discharge | ||
| 276 | * @active_discharge_mask: Mask for control when using regmap | ||
| 277 | * set_active_discharge | ||
| 278 | * @active_discharge_reg: Register for control when using regmap | ||
| 279 | * set_active_discharge | ||
| 269 | * | 280 | * |
| 270 | * @enable_time: Time taken for initial enable of regulator (in uS). | 281 | * @enable_time: Time taken for initial enable of regulator (in uS). |
| 271 | * @off_on_delay: guard time (in uS), before re-enabling a regulator | 282 | * @off_on_delay: guard time (in uS), before re-enabling a regulator |
| @@ -315,6 +326,10 @@ struct regulator_desc { | |||
| 315 | unsigned int bypass_mask; | 326 | unsigned int bypass_mask; |
| 316 | unsigned int bypass_val_on; | 327 | unsigned int bypass_val_on; |
| 317 | unsigned int bypass_val_off; | 328 | unsigned int bypass_val_off; |
| 329 | unsigned int active_discharge_on; | ||
| 330 | unsigned int active_discharge_off; | ||
| 331 | unsigned int active_discharge_mask; | ||
| 332 | unsigned int active_discharge_reg; | ||
| 318 | 333 | ||
| 319 | unsigned int enable_time; | 334 | unsigned int enable_time; |
| 320 | 335 | ||
| @@ -447,6 +462,8 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, | |||
| 447 | int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable); | 462 | int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable); |
| 448 | int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable); | 463 | int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable); |
| 449 | 464 | ||
| 465 | int regulator_set_active_discharge_regmap(struct regulator_dev *rdev, | ||
| 466 | bool enable); | ||
| 450 | void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); | 467 | void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); |
| 451 | 468 | ||
| 452 | #endif | 469 | #endif |
diff --git a/include/linux/regulator/lp872x.h b/include/linux/regulator/lp872x.h index 132e05c46661..6029279f4eed 100644 --- a/include/linux/regulator/lp872x.h +++ b/include/linux/regulator/lp872x.h | |||
| @@ -18,6 +18,9 @@ | |||
| 18 | 18 | ||
| 19 | #define LP872X_MAX_REGULATORS 9 | 19 | #define LP872X_MAX_REGULATORS 9 |
| 20 | 20 | ||
| 21 | #define LP8720_ENABLE_DELAY 200 | ||
| 22 | #define LP8725_ENABLE_DELAY 30000 | ||
| 23 | |||
| 21 | enum lp872x_regulator_id { | 24 | enum lp872x_regulator_id { |
| 22 | LP8720_ID_BASE, | 25 | LP8720_ID_BASE, |
| 23 | LP8720_ID_LDO1 = LP8720_ID_BASE, | 26 | LP8720_ID_LDO1 = LP8720_ID_BASE, |
| @@ -79,12 +82,14 @@ struct lp872x_regulator_data { | |||
| 79 | * @update_config : if LP872X_GENERAL_CFG register is updated, set true | 82 | * @update_config : if LP872X_GENERAL_CFG register is updated, set true |
| 80 | * @regulator_data : platform regulator id and init data | 83 | * @regulator_data : platform regulator id and init data |
| 81 | * @dvs : dvs data for buck voltage control | 84 | * @dvs : dvs data for buck voltage control |
| 85 | * @enable_gpio : gpio pin number for enable control | ||
| 82 | */ | 86 | */ |
| 83 | struct lp872x_platform_data { | 87 | struct lp872x_platform_data { |
| 84 | u8 general_config; | 88 | u8 general_config; |
| 85 | bool update_config; | 89 | bool update_config; |
| 86 | struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS]; | 90 | struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS]; |
| 87 | struct lp872x_dvs *dvs; | 91 | struct lp872x_dvs *dvs; |
| 92 | int enable_gpio; | ||
| 88 | }; | 93 | }; |
| 89 | 94 | ||
| 90 | #endif | 95 | #endif |
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index a1067d0b3991..5d627c83a630 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h | |||
| @@ -42,6 +42,13 @@ struct regulator; | |||
| 42 | #define REGULATOR_CHANGE_DRMS 0x10 | 42 | #define REGULATOR_CHANGE_DRMS 0x10 |
| 43 | #define REGULATOR_CHANGE_BYPASS 0x20 | 43 | #define REGULATOR_CHANGE_BYPASS 0x20 |
| 44 | 44 | ||
| 45 | /* Regulator active discharge flags */ | ||
| 46 | enum regulator_active_discharge { | ||
| 47 | REGULATOR_ACTIVE_DISCHARGE_DEFAULT, | ||
| 48 | REGULATOR_ACTIVE_DISCHARGE_DISABLE, | ||
| 49 | REGULATOR_ACTIVE_DISCHARGE_ENABLE, | ||
| 50 | }; | ||
| 51 | |||
| 45 | /** | 52 | /** |
| 46 | * struct regulator_state - regulator state during low power system states | 53 | * struct regulator_state - regulator state during low power system states |
| 47 | * | 54 | * |
| @@ -100,6 +107,9 @@ struct regulator_state { | |||
| 100 | * @initial_state: Suspend state to set by default. | 107 | * @initial_state: Suspend state to set by default. |
| 101 | * @initial_mode: Mode to set at startup. | 108 | * @initial_mode: Mode to set at startup. |
| 102 | * @ramp_delay: Time to settle down after voltage change (unit: uV/us) | 109 | * @ramp_delay: Time to settle down after voltage change (unit: uV/us) |
| 110 | * @active_discharge: Enable/disable active discharge. The enum | ||
| 111 | * regulator_active_discharge values are used for | ||
| 112 | * initialisation. | ||
| 103 | * @enable_time: Turn-on time of the rails (unit: microseconds) | 113 | * @enable_time: Turn-on time of the rails (unit: microseconds) |
| 104 | */ | 114 | */ |
| 105 | struct regulation_constraints { | 115 | struct regulation_constraints { |
| @@ -140,6 +150,8 @@ struct regulation_constraints { | |||
| 140 | unsigned int ramp_delay; | 150 | unsigned int ramp_delay; |
| 141 | unsigned int enable_time; | 151 | unsigned int enable_time; |
| 142 | 152 | ||
| 153 | unsigned int active_discharge; | ||
| 154 | |||
| 143 | /* constraint flags */ | 155 | /* constraint flags */ |
| 144 | unsigned always_on:1; /* regulator never off when system is on */ | 156 | unsigned always_on:1; /* regulator never off when system is on */ |
| 145 | unsigned boot_on:1; /* bootloader/firmware enabled regulator */ | 157 | unsigned boot_on:1; /* bootloader/firmware enabled regulator */ |
