Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add support for TI TPS65219 PMIC.

Merge series from Jerome Neanne <jneanne@baylibre.com>:

This driver supports
- 3 Buck regulators and 4 LDOs
- low-power standby mode
- warm/soft reset
- basic fault handling (via interrupts).
- power button

Not implemented
- DVS

1-Regulators:
Full implementation and test
Visual check: cat /sys/kernel/debug/regulator/regulator_summary
Full validation requires userspace-consumer and virtual-regulator
LDO1 is not used and output can be probbed on TP84.

+600
+173
Documentation/devicetree/bindings/regulator/ti,tps65219.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/regulator/ti,tps65219.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: TI tps65219 Power Management Integrated Circuit regulators 8 + 9 + maintainers: 10 + - Jerome Neanne <jerome.neanne@baylibre.com> 11 + 12 + description: | 13 + Regulator nodes should be named to buck<number> and ldo<number>. 14 + 15 + properties: 16 + compatible: 17 + enum: 18 + - ti,tps65219 19 + 20 + reg: 21 + maxItems: 1 22 + 23 + system-power-controller: 24 + type: boolean 25 + description: Optional property that indicates that this device is 26 + controlling system power. 27 + 28 + interrupts: 29 + description: Short-circuit, over-current, under-voltage for regulators, PB interrupts. 30 + maxItems: 1 31 + 32 + interrupt-controller: true 33 + 34 + '#interrupt-cells': 35 + description: Specifies the PIN numbers and Flags, as defined in 36 + include/dt-bindings/interrupt-controller/irq.h 37 + const: 1 38 + 39 + ti,power-button: 40 + type: boolean 41 + description: | 42 + Optional property that sets the EN/PB/VSENSE pin to be a 43 + power-button. 44 + TPS65219 has a multipurpose pin called EN/PB/VSENSE that can be either 45 + 1. EN in which case it functions as an enable pin. 46 + 2. VSENSE which compares the voltages and triggers an automatic 47 + on/off request. 48 + 3. PB in which case it can be configured to trigger an interrupt 49 + to the SoC. 50 + ti,power-button reflects the last one of those options 51 + where the board has a button wired to the pin and triggers 52 + an interrupt on pressing it. 53 + 54 + patternProperties: 55 + "^buck[1-3]-supply$": 56 + description: Input supply phandle of one regulator. 57 + 58 + "^ldo[1-4]-supply$": 59 + description: Input supply phandle of one regulator. 60 + 61 + regulators: 62 + type: object 63 + description: | 64 + list of regulators provided by this controller 65 + 66 + patternProperties: 67 + "^ldo[1-4]$": 68 + type: object 69 + $ref: regulator.yaml# 70 + description: 71 + Properties for single LDO regulator. 72 + 73 + unevaluatedProperties: false 74 + 75 + "^buck[1-3]$": 76 + type: object 77 + $ref: regulator.yaml# 78 + description: 79 + Properties for single BUCK regulator. 80 + 81 + unevaluatedProperties: false 82 + 83 + additionalProperties: false 84 + 85 + required: 86 + - compatible 87 + - reg 88 + - interrupts 89 + - regulators 90 + 91 + additionalProperties: false 92 + 93 + examples: 94 + - | 95 + #include <dt-bindings/interrupt-controller/arm-gic.h> 96 + i2c { 97 + #address-cells = <1>; 98 + #size-cells = <0>; 99 + 100 + tps65219: pmic@30 { 101 + compatible = "ti,tps65219"; 102 + reg = <0x30>; 103 + buck1-supply = <&vcc_3v3_sys>; 104 + buck2-supply = <&vcc_3v3_sys>; 105 + buck3-supply = <&vcc_3v3_sys>; 106 + ldo1-supply = <&vcc_3v3_sys>; 107 + ldo2-supply = <&buck2_reg>; 108 + ldo3-supply = <&vcc_3v3_sys>; 109 + ldo4-supply = <&vcc_3v3_sys>; 110 + 111 + pinctrl-0 = <&pmic_irq_pins_default>; 112 + 113 + interrupt-parent = <&gic500>; 114 + interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>; 115 + ti,power-button; 116 + 117 + regulators { 118 + buck1_reg: buck1 { 119 + regulator-name = "VDD_CORE"; 120 + regulator-min-microvolt = <750000>; 121 + regulator-max-microvolt = <750000>; 122 + regulator-boot-on; 123 + regulator-always-on; 124 + }; 125 + 126 + buck2_reg: buck2 { 127 + regulator-name = "VCC1V8"; 128 + regulator-min-microvolt = <1800000>; 129 + regulator-max-microvolt = <1800000>; 130 + regulator-boot-on; 131 + regulator-always-on; 132 + }; 133 + 134 + buck3_reg: buck3 { 135 + regulator-name = "VDD_LPDDR4"; 136 + regulator-min-microvolt = <1100000>; 137 + regulator-max-microvolt = <1100000>; 138 + regulator-boot-on; 139 + regulator-always-on; 140 + }; 141 + 142 + ldo1_reg: ldo1 { 143 + regulator-name = "VDDSHV_SD_IO_PMIC"; 144 + regulator-min-microvolt = <33000000>; 145 + regulator-max-microvolt = <33000000>; 146 + }; 147 + 148 + ldo2_reg: ldo2 { 149 + regulator-name = "VDDAR_CORE"; 150 + regulator-min-microvolt = <850000>; 151 + regulator-max-microvolt = <850000>; 152 + regulator-boot-on; 153 + regulator-always-on; 154 + }; 155 + 156 + ldo3_reg: ldo3 { 157 + regulator-name = "VDDA_1V8"; 158 + regulator-min-microvolt = <18000000>; 159 + regulator-max-microvolt = <18000000>; 160 + regulator-boot-on; 161 + regulator-always-on; 162 + }; 163 + 164 + ldo4_reg: ldo4 { 165 + regulator-name = "VDD_PHY_2V5"; 166 + regulator-min-microvolt = <25000000>; 167 + regulator-max-microvolt = <25000000>; 168 + regulator-boot-on; 169 + regulator-always-on; 170 + }; 171 + }; 172 + }; 173 + };
+1
MAINTAINERS
··· 14935 14935 F: drivers/regulator/pbias-regulator.c 14936 14936 F: drivers/regulator/tps65217-regulator.c 14937 14937 F: drivers/regulator/tps65218-regulator.c 14938 + F: drivers/regulator/tps65219-regulator.c 14938 14939 F: drivers/regulator/tps65910-regulator.c 14939 14940 F: drivers/regulator/twl-regulator.c 14940 14941 F: drivers/regulator/twl6030-regulator.c
+9
drivers/regulator/Kconfig
··· 1384 1384 voltage regulators. It supports software based voltage control 1385 1385 for different voltage domains 1386 1386 1387 + config REGULATOR_TPS65219 1388 + tristate "TI TPS65219 Power regulators" 1389 + depends on MFD_TPS65219 && OF 1390 + help 1391 + This driver supports TPS65219 voltage regulator chips. 1392 + TPS65219 series of PMICs have 3 single phase BUCKs & 4 LDOs 1393 + voltage regulators. It supports software based voltage control 1394 + for different voltage domains. 1395 + 1387 1396 config REGULATOR_TPS6524X 1388 1397 tristate "TI TPS6524X Power regulators" 1389 1398 depends on SPI
+1
drivers/regulator/Makefile
··· 162 162 obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o 163 163 obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o 164 164 obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o 165 + obj-$(CONFIG_REGULATOR_TPS65219) += tps65219-regulator.o 165 166 obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o 166 167 obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o 167 168 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
+416
drivers/regulator/tps65219-regulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // tps65219-regulator.c 4 + // 5 + // Regulator driver for TPS65219 PMIC 6 + // 7 + // Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/ 8 + // 9 + // This implementation derived from tps65218 authored by 10 + // "J Keerthy <j-keerthy@ti.com>" 11 + // 12 + 13 + #include <linux/kernel.h> 14 + #include <linux/module.h> 15 + #include <linux/device.h> 16 + #include <linux/init.h> 17 + #include <linux/err.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/of_device.h> 20 + #include <linux/regmap.h> 21 + #include <linux/regulator/of_regulator.h> 22 + #include <linux/regulator/driver.h> 23 + #include <linux/regulator/machine.h> 24 + #include <linux/mfd/tps65219.h> 25 + 26 + struct tps65219_regulator_irq_type { 27 + const char *irq_name; 28 + const char *regulator_name; 29 + const char *event_name; 30 + unsigned long event; 31 + }; 32 + 33 + struct tps65219_regulator_irq_type tps65219_regulator_irq_types[] = { 34 + { "LDO3_SCG", "LDO3", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, 35 + { "LDO3_OC", "LDO3", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 36 + { "LDO3_UV", "LDO3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 37 + { "LDO4_SCG", "LDO4", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, 38 + { "LDO4_OC", "LDO4", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 39 + { "LDO4_UV", "LDO4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 40 + { "LDO1_SCG", "LDO1", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, 41 + { "LDO1_OC", "LDO1", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 42 + { "LDO1_UV", "LDO1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 43 + { "LDO2_SCG", "LDO2", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, 44 + { "LDO2_OC", "LDO2", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 45 + { "LDO2_UV", "LDO2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 46 + { "BUCK3_SCG", "BUCK3", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, 47 + { "BUCK3_OC", "BUCK3", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 48 + { "BUCK3_NEG_OC", "BUCK3", "negative overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 49 + { "BUCK3_UV", "BUCK3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 50 + { "BUCK1_SCG", "BUCK1", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, 51 + { "BUCK1_OC", "BUCK1", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 52 + { "BUCK1_NEG_OC", "BUCK1", "negative overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 53 + { "BUCK1_UV", "BUCK1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 54 + { "BUCK2_SCG", "BUCK2", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, 55 + { "BUCK2_OC", "BUCK2", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 56 + { "BUCK2_NEG_OC", "BUCK2", "negative overcurrent", REGULATOR_EVENT_OVER_CURRENT }, 57 + { "BUCK2_UV", "BUCK2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 58 + { "BUCK1_RV", "BUCK1", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 59 + { "BUCK2_RV", "BUCK2", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 60 + { "BUCK3_RV", "BUCK3", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 61 + { "LDO1_RV", "LDO1", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 62 + { "LDO2_RV", "LDO2", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 63 + { "LDO3_RV", "LDO3", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 64 + { "LDO4_RV", "LDO4", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 65 + { "BUCK1_RV_SD", "BUCK1", "residual voltage on shutdown", 66 + REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 67 + { "BUCK2_RV_SD", "BUCK2", "residual voltage on shutdown", 68 + REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 69 + { "BUCK3_RV_SD", "BUCK3", "residual voltage on shutdown", 70 + REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 71 + { "LDO1_RV_SD", "LDO1", "residual voltage on shutdown", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 72 + { "LDO2_RV_SD", "LDO2", "residual voltage on shutdown", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 73 + { "LDO3_RV_SD", "LDO3", "residual voltage on shutdown", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 74 + { "LDO4_RV_SD", "LDO4", "residual voltage on shutdown", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 75 + { "SENSOR_3_WARM", "SENSOR3", "warm temperature", REGULATOR_EVENT_OVER_TEMP_WARN}, 76 + { "SENSOR_2_WARM", "SENSOR2", "warm temperature", REGULATOR_EVENT_OVER_TEMP_WARN }, 77 + { "SENSOR_1_WARM", "SENSOR1", "warm temperature", REGULATOR_EVENT_OVER_TEMP_WARN }, 78 + { "SENSOR_0_WARM", "SENSOR0", "warm temperature", REGULATOR_EVENT_OVER_TEMP_WARN }, 79 + { "SENSOR_3_HOT", "SENSOR3", "hot temperature", REGULATOR_EVENT_OVER_TEMP}, 80 + { "SENSOR_2_HOT", "SENSOR2", "hot temperature", REGULATOR_EVENT_OVER_TEMP }, 81 + { "SENSOR_1_HOT", "SENSOR1", "hot temperature", REGULATOR_EVENT_OVER_TEMP }, 82 + { "SENSOR_0_HOT", "SENSOR0", "hot temperature", REGULATOR_EVENT_OVER_TEMP }, 83 + { "TIMEOUT", "", "", REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE }, 84 + }; 85 + 86 + struct tps65219_regulator_irq_data { 87 + struct device *dev; 88 + struct tps65219_regulator_irq_type *type; 89 + struct regulator_dev *rdev; 90 + }; 91 + 92 + #define TPS65219_REGULATOR(_name, _of, _id, _type, _ops, _n, _vr, _vm, _er, \ 93 + _em, _cr, _cm, _lr, _nlr, _delay, _fuv, \ 94 + _ct, _ncl, _bpm) \ 95 + { \ 96 + .name = _name, \ 97 + .of_match = _of, \ 98 + .regulators_node = of_match_ptr("regulators"), \ 99 + .supply_name = _of, \ 100 + .id = _id, \ 101 + .ops = &(_ops), \ 102 + .n_voltages = _n, \ 103 + .type = _type, \ 104 + .owner = THIS_MODULE, \ 105 + .vsel_reg = _vr, \ 106 + .vsel_mask = _vm, \ 107 + .csel_reg = _cr, \ 108 + .csel_mask = _cm, \ 109 + .curr_table = _ct, \ 110 + .n_current_limits = _ncl, \ 111 + .enable_reg = _er, \ 112 + .enable_mask = _em, \ 113 + .volt_table = NULL, \ 114 + .linear_ranges = _lr, \ 115 + .n_linear_ranges = _nlr, \ 116 + .ramp_delay = _delay, \ 117 + .fixed_uV = _fuv, \ 118 + .bypass_reg = _vr, \ 119 + .bypass_mask = _bpm, \ 120 + .bypass_val_on = 1, \ 121 + } \ 122 + 123 + static const struct linear_range bucks_ranges[] = { 124 + REGULATOR_LINEAR_RANGE(600000, 0x0, 0x1f, 25000), 125 + REGULATOR_LINEAR_RANGE(1400000, 0x20, 0x33, 100000), 126 + REGULATOR_LINEAR_RANGE(3400000, 0x34, 0x3f, 0), 127 + }; 128 + 129 + static const struct linear_range ldos_1_2_ranges[] = { 130 + REGULATOR_LINEAR_RANGE(600000, 0x0, 0x37, 50000), 131 + REGULATOR_LINEAR_RANGE(3400000, 0x38, 0x3f, 0), 132 + }; 133 + 134 + static const struct linear_range ldos_3_4_ranges[] = { 135 + REGULATOR_LINEAR_RANGE(1200000, 0x0, 0xC, 0), 136 + REGULATOR_LINEAR_RANGE(1250000, 0xD, 0x35, 50000), 137 + REGULATOR_LINEAR_RANGE(3300000, 0x36, 0x3F, 0), 138 + }; 139 + 140 + static int tps65219_set_mode(struct regulator_dev *dev, unsigned int mode) 141 + { 142 + struct tps65219 *tps = rdev_get_drvdata(dev); 143 + 144 + switch (mode) { 145 + case REGULATOR_MODE_NORMAL: 146 + return regmap_set_bits(tps->regmap, TPS65219_REG_STBY_1_CONFIG, 147 + dev->desc->enable_mask); 148 + 149 + case REGULATOR_MODE_STANDBY: 150 + return regmap_clear_bits(tps->regmap, 151 + TPS65219_REG_STBY_1_CONFIG, 152 + dev->desc->enable_mask); 153 + default: 154 + return -EINVAL; 155 + } 156 + } 157 + 158 + static unsigned int tps65219_get_mode(struct regulator_dev *dev) 159 + { 160 + struct tps65219 *tps = rdev_get_drvdata(dev); 161 + unsigned int rid = rdev_get_id(dev); 162 + int ret, value = 0; 163 + 164 + ret = regmap_read(tps->regmap, TPS65219_REG_STBY_1_CONFIG, &value); 165 + if (ret) { 166 + dev_dbg(tps->dev, "%s failed for regulator %s: %d ", 167 + __func__, dev->desc->name, ret); 168 + return ret; 169 + } 170 + value = (value & BIT(rid)) >> rid; 171 + if (value) 172 + return REGULATOR_MODE_STANDBY; 173 + else 174 + return REGULATOR_MODE_NORMAL; 175 + } 176 + 177 + /* 178 + * generic regulator_set_bypass_regmap does not fully match requirements 179 + * TPS65219 Requires explicitly that regulator is disabled before switch 180 + */ 181 + static int tps65219_set_bypass(struct regulator_dev *dev, bool enable) 182 + { 183 + struct tps65219 *tps = rdev_get_drvdata(dev); 184 + unsigned int rid = rdev_get_id(dev); 185 + int ret = 0; 186 + 187 + if (dev->desc->ops->enable) { 188 + dev_err(tps->dev, 189 + "%s LDO%d enabled, must be shut down to set bypass ", 190 + __func__, rid); 191 + return -EBUSY; 192 + } 193 + ret = regulator_set_bypass_regmap(dev, enable); 194 + return ret; 195 + } 196 + 197 + /* Operations permitted on BUCK1/2/3 */ 198 + static const struct regulator_ops tps65219_bucks_ops = { 199 + .is_enabled = regulator_is_enabled_regmap, 200 + .enable = regulator_enable_regmap, 201 + .disable = regulator_disable_regmap, 202 + .set_mode = tps65219_set_mode, 203 + .get_mode = tps65219_get_mode, 204 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 205 + .set_voltage_sel = regulator_set_voltage_sel_regmap, 206 + .list_voltage = regulator_list_voltage_linear_range, 207 + .map_voltage = regulator_map_voltage_linear_range, 208 + .set_voltage_time_sel = regulator_set_voltage_time_sel, 209 + 210 + }; 211 + 212 + /* Operations permitted on LDO1/2 */ 213 + static const struct regulator_ops tps65219_ldos_1_2_ops = { 214 + .is_enabled = regulator_is_enabled_regmap, 215 + .enable = regulator_enable_regmap, 216 + .disable = regulator_disable_regmap, 217 + .set_mode = tps65219_set_mode, 218 + .get_mode = tps65219_get_mode, 219 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 220 + .set_voltage_sel = regulator_set_voltage_sel_regmap, 221 + .list_voltage = regulator_list_voltage_linear_range, 222 + .map_voltage = regulator_map_voltage_linear_range, 223 + .set_bypass = tps65219_set_bypass, 224 + .get_bypass = regulator_get_bypass_regmap, 225 + }; 226 + 227 + /* Operations permitted on LDO3/4 */ 228 + static const struct regulator_ops tps65219_ldos_3_4_ops = { 229 + .is_enabled = regulator_is_enabled_regmap, 230 + .enable = regulator_enable_regmap, 231 + .disable = regulator_disable_regmap, 232 + .set_mode = tps65219_set_mode, 233 + .get_mode = tps65219_get_mode, 234 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 235 + .set_voltage_sel = regulator_set_voltage_sel_regmap, 236 + .list_voltage = regulator_list_voltage_linear_range, 237 + .map_voltage = regulator_map_voltage_linear_range, 238 + }; 239 + 240 + static const struct regulator_desc regulators[] = { 241 + TPS65219_REGULATOR("BUCK1", "buck1", TPS65219_BUCK_1, 242 + REGULATOR_VOLTAGE, tps65219_bucks_ops, 64, 243 + TPS65219_REG_BUCK1_VOUT, 244 + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, 245 + TPS65219_REG_ENABLE_CTRL, 246 + TPS65219_ENABLE_BUCK1_EN_MASK, 0, 0, bucks_ranges, 247 + 3, 4000, 0, NULL, 0, 0), 248 + TPS65219_REGULATOR("BUCK2", "buck2", TPS65219_BUCK_2, 249 + REGULATOR_VOLTAGE, tps65219_bucks_ops, 64, 250 + TPS65219_REG_BUCK2_VOUT, 251 + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, 252 + TPS65219_REG_ENABLE_CTRL, 253 + TPS65219_ENABLE_BUCK2_EN_MASK, 0, 0, bucks_ranges, 254 + 3, 4000, 0, NULL, 0, 0), 255 + TPS65219_REGULATOR("BUCK3", "buck3", TPS65219_BUCK_3, 256 + REGULATOR_VOLTAGE, tps65219_bucks_ops, 64, 257 + TPS65219_REG_BUCK3_VOUT, 258 + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, 259 + TPS65219_REG_ENABLE_CTRL, 260 + TPS65219_ENABLE_BUCK3_EN_MASK, 0, 0, bucks_ranges, 261 + 3, 0, 0, NULL, 0, 0), 262 + TPS65219_REGULATOR("LDO1", "ldo1", TPS65219_LDO_1, 263 + REGULATOR_VOLTAGE, tps65219_ldos_1_2_ops, 64, 264 + TPS65219_REG_LDO1_VOUT, 265 + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, 266 + TPS65219_REG_ENABLE_CTRL, 267 + TPS65219_ENABLE_LDO1_EN_MASK, 0, 0, ldos_1_2_ranges, 268 + 2, 0, 0, NULL, 0, TPS65219_LDOS_BYP_CONFIG_MASK), 269 + TPS65219_REGULATOR("LDO2", "ldo2", TPS65219_LDO_2, 270 + REGULATOR_VOLTAGE, tps65219_ldos_1_2_ops, 64, 271 + TPS65219_REG_LDO2_VOUT, 272 + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, 273 + TPS65219_REG_ENABLE_CTRL, 274 + TPS65219_ENABLE_LDO2_EN_MASK, 0, 0, ldos_1_2_ranges, 275 + 2, 0, 0, NULL, 0, TPS65219_LDOS_BYP_CONFIG_MASK), 276 + TPS65219_REGULATOR("LDO3", "ldo3", TPS65219_LDO_3, 277 + REGULATOR_VOLTAGE, tps65219_ldos_3_4_ops, 64, 278 + TPS65219_REG_LDO3_VOUT, 279 + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, 280 + TPS65219_REG_ENABLE_CTRL, 281 + TPS65219_ENABLE_LDO3_EN_MASK, 0, 0, ldos_3_4_ranges, 282 + 3, 0, 0, NULL, 0, 0), 283 + TPS65219_REGULATOR("LDO4", "ldo4", TPS65219_LDO_4, 284 + REGULATOR_VOLTAGE, tps65219_ldos_3_4_ops, 64, 285 + TPS65219_REG_LDO4_VOUT, 286 + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, 287 + TPS65219_REG_ENABLE_CTRL, 288 + TPS65219_ENABLE_LDO4_EN_MASK, 0, 0, ldos_3_4_ranges, 289 + 3, 0, 0, NULL, 0, 0), 290 + }; 291 + 292 + static irqreturn_t tps65219_regulator_irq_handler(int irq, void *data) 293 + { 294 + struct tps65219_regulator_irq_data *irq_data = data; 295 + 296 + if (irq_data->type->event_name[0] == '\0') { 297 + /* This is the timeout interrupt no specific regulator */ 298 + dev_err(irq_data->dev, 299 + "System was put in shutdown due to timeout during an active or standby transition.\n"); 300 + return IRQ_HANDLED; 301 + } 302 + 303 + regulator_notifier_call_chain(irq_data->rdev, 304 + irq_data->type->event, NULL); 305 + 306 + dev_err(irq_data->dev, "Error IRQ trap %s for %s\n", 307 + irq_data->type->event_name, irq_data->type->regulator_name); 308 + return IRQ_HANDLED; 309 + } 310 + 311 + static int tps65219_get_rdev_by_name(const char *regulator_name, 312 + struct regulator_dev *rdevtbl[7], 313 + struct regulator_dev *dev) 314 + { 315 + int i; 316 + 317 + for (i = 0; i < ARRAY_SIZE(regulators); i++) { 318 + if (strcmp(regulator_name, regulators[i].name) == 0) { 319 + dev = rdevtbl[i]; 320 + return 0; 321 + } 322 + } 323 + return -EINVAL; 324 + } 325 + 326 + static int tps65219_regulator_probe(struct platform_device *pdev) 327 + { 328 + struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent); 329 + struct regulator_dev *rdev; 330 + struct regulator_config config = { }; 331 + int i; 332 + int error; 333 + int irq; 334 + struct tps65219_regulator_irq_data *irq_data; 335 + struct tps65219_regulator_irq_type *irq_type; 336 + struct regulator_dev *rdevtbl[7]; 337 + 338 + config.dev = tps->dev; 339 + config.driver_data = tps; 340 + config.regmap = tps->regmap; 341 + 342 + for (i = 0; i < ARRAY_SIZE(regulators); i++) { 343 + dev_dbg(tps->dev, "%s regul i= %d START", __func__, i); 344 + rdev = devm_regulator_register(&pdev->dev, &regulators[i], 345 + &config); 346 + if (IS_ERR(rdev)) { 347 + dev_err(tps->dev, "failed to register %s regulator\n", 348 + pdev->name); 349 + return PTR_ERR(rdev); 350 + } 351 + rdevtbl[i] = rdev; 352 + dev_dbg(tps->dev, "%s regul i= %d COMPLETED", __func__, i); 353 + } 354 + 355 + irq_data = devm_kmalloc(tps->dev, 356 + ARRAY_SIZE(tps65219_regulator_irq_types) * 357 + sizeof(struct tps65219_regulator_irq_data), 358 + GFP_KERNEL); 359 + if (!irq_data) 360 + return -ENOMEM; 361 + 362 + for (i = 0; i < ARRAY_SIZE(tps65219_regulator_irq_types); ++i) { 363 + irq_type = &tps65219_regulator_irq_types[i]; 364 + 365 + irq = platform_get_irq_byname(pdev, irq_type->irq_name); 366 + if (irq < 0) { 367 + dev_err(tps->dev, "Failed to get IRQ %s: %d\n", 368 + irq_type->irq_name, irq); 369 + return -EINVAL; 370 + } 371 + irq_data[i].dev = tps->dev; 372 + irq_data[i].type = irq_type; 373 + 374 + tps65219_get_rdev_by_name(irq_type->regulator_name, rdevtbl, rdev); 375 + if (rdev < 0) { 376 + dev_err(tps->dev, "Failed to get rdev for %s\n", 377 + irq_type->regulator_name); 378 + return -EINVAL; 379 + } 380 + irq_data[i].rdev = rdev; 381 + 382 + error = devm_request_threaded_irq(tps->dev, irq, NULL, 383 + tps65219_regulator_irq_handler, 384 + IRQF_ONESHOT, 385 + irq_type->irq_name, 386 + &irq_data[i]); 387 + if (error) { 388 + dev_err(tps->dev, "failed to request %s IRQ %d: %d\n", 389 + irq_type->irq_name, irq, error); 390 + return error; 391 + } 392 + } 393 + 394 + return 0; 395 + } 396 + 397 + static const struct platform_device_id tps65219_regulator_id_table[] = { 398 + { "tps65219-regulator", }, 399 + { /* sentinel */ } 400 + }; 401 + MODULE_DEVICE_TABLE(platform, tps65219_regulator_id_table); 402 + 403 + static struct platform_driver tps65219_regulator_driver = { 404 + .driver = { 405 + .name = "tps65219-pmic", 406 + }, 407 + .probe = tps65219_regulator_probe, 408 + .id_table = tps65219_regulator_id_table, 409 + }; 410 + 411 + module_platform_driver(tps65219_regulator_driver); 412 + 413 + MODULE_AUTHOR("Jerome Neanne <j-neanne@baylibre.com>"); 414 + MODULE_DESCRIPTION("TPS65219 voltage regulator driver"); 415 + MODULE_ALIAS("platform:tps65219-pmic"); 416 + MODULE_LICENSE("GPL");