diff options
-rw-r--r-- | Documentation/devicetree/bindings/regulator/dlg,da9121.yaml | 76 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/regulator/maxim,max8973.yaml | 3 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml | 3 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/regulator/regulator.yaml | 2 | ||||
-rw-r--r-- | drivers/regulator/bd718x7-regulator.c | 29 | ||||
-rw-r--r-- | drivers/regulator/da9121-regulator.c | 117 | ||||
-rw-r--r-- | drivers/regulator/da9121-regulator.h | 21 | ||||
-rw-r--r-- | drivers/regulator/irq_helpers.c | 41 | ||||
-rw-r--r-- | drivers/regulator/qcom-rpmh-regulator.c | 27 | ||||
-rw-r--r-- | drivers/regulator/qcom_spmi-regulator.c | 39 | ||||
-rw-r--r-- | drivers/regulator/rohm-regulator.c | 16 | ||||
-rw-r--r-- | drivers/regulator/twl-regulator.c | 10 | ||||
-rw-r--r-- | include/linux/mfd/rohm-generic.h | 10 | ||||
-rw-r--r-- | include/linux/regulator/driver.h | 67 |
15 files changed, 367 insertions, 95 deletions
diff --git a/Documentation/devicetree/bindings/regulator/dlg,da9121.yaml b/Documentation/devicetree/bindings/regulator/dlg,da9121.yaml index 228018c87bea..24ace6e1e5ec 100644 --- a/Documentation/devicetree/bindings/regulator/dlg,da9121.yaml +++ b/Documentation/devicetree/bindings/regulator/dlg,da9121.yaml @@ -17,27 +17,39 @@ description: | Dialog Semiconductor DA9130 Single-channel 10A double-phase buck converter Dialog Semiconductor DA9131 Double-channel 5A single-phase buck converter Dialog Semiconductor DA9132 Double-channel 3A single-phase buck converter - - Current limits - - This is PER PHASE, and the current limit setting in the devices reflect - that with a maximum 10A limit. Allowing for transients at/near double - the rated current, this translates across the device range to per - channel figures as so... - - | DA9121 DA9122 DA9220 DA9217 DA9140 - | /DA9130 /DA9131 /DA9132 - ----------------------------------------------------------------------------- - Output current / channel | 10000000 5000000 3000000 6000000 40000000 - Output current / phase | 5000000 5000000 3000000 3000000 9500000 - ----------------------------------------------------------------------------- - Min regulator-min-microvolt| 300000 300000 300000 300000 500000 - Max regulator-max-microvolt| 1900000 1900000 1900000 1900000 1000000 - Device hardware default | 1000000 1000000 1000000 1000000 1000000 - ----------------------------------------------------------------------------- - Min regulator-min-microamp | 7000000 3500000 3500000 7000000 26000000 - Max regulator-max-microamp | 20000000 10000000 6000000 12000000 78000000 - Device hardware default | 15000000 7500000 5500000 11000000 58000000 + Dialog Semiconductor DA9141 Single-channel 40A quad-phase buck converter + Dialog Semiconductor DA9142 Single-channel 20A double-phase buck converter + + Device parameter ranges + + The current limits can be set to at/near double the rated current per channel + to allow for transient peaks. + Current limit changes when the output is enabled are not supported, as a + precaution against undefined behaviour. + + |----------------------------------------------| + | | range & reset default value | + | Device |------------------------------| + | | microvolt | microamp | + |----------------------------------------------| + | DA9121/DA9130 | Min: 300000 | Min: 7000000 | + | | Max: 1900000 | Max: 20000000 | + |----------------------------------------------| + | DA9121/DA9131 | Min: 300000 | Min: 3500000 | + | | Max: 1900000 | Max: 10000000 | + |----------------------------------------------| + | DA9121/DA9131 | Min: 300000 | Min: 3500000 | + | | Max: 1900000 | Max: 6000000 | + |----------------------------------------------| + | DA9217 | Min: 300000 | Min: 7000000 | + | | Max: 1900000 | Max: 12000000 | + |----------------------------------------------| + | DA9141 | Min: 300000 | Min: 26000000 | + | | Max: 1300000 | Max: 78000000 | + |----------------------------------------------| + | DA9142 | Min: 300000 | Min: 13000000 | + | | Max: 1300000 | Max: 39000000 | + |----------------------------------------------| properties: $nodename: @@ -51,7 +63,8 @@ properties: - dlg,da9130 - dlg,da9131 - dlg,da9132 - - dlg,da9140 + - dlg,da9141 + - dlg,da9142 reg: maxItems: 1 @@ -70,26 +83,24 @@ properties: regulators: type: object - $ref: regulator.yaml# description: | - This node defines the settings for the BUCK. The content of the - sub-node is defined by the standard binding for regulators; see regulator.yaml. - The DA9121 regulator is bound using their names listed below - buck1 - BUCK1 - buck2 - BUCK2 //DA9122, DA9220, DA9131, DA9132 only + List of regulators provided by the device patternProperties: "^buck([1-2])$": type: object $ref: regulator.yaml# + description: | + Properties for a single BUCK regulator properties: - regulator-mode: - maxItems: 1 - description: Defined in include/dt-bindings/regulator/dlg,da9121-regulator.h + regulator-name: + pattern: "^BUCK([1-2])$" + description: | + BUCK2 present in DA9122, DA9220, DA9131, DA9132 only regulator-initial-mode: - maxItems: 1 + enum: [ 0, 1, 2, 3 ] description: Defined in include/dt-bindings/regulator/dlg,da9121-regulator.h enable-gpios: @@ -98,6 +109,7 @@ properties: dlg,ripple-cancel: $ref: "/schemas/types.yaml#/definitions/uint32" + enum: [ 0, 1, 2, 3 ] description: | Defined in include/dt-bindings/regulator/dlg,da9121-regulator.h Only present on multi-channel devices (DA9122, DA9220, DA9131, DA9132) diff --git a/Documentation/devicetree/bindings/regulator/maxim,max8973.yaml b/Documentation/devicetree/bindings/regulator/maxim,max8973.yaml index 54522827265b..35c53e27f78c 100644 --- a/Documentation/devicetree/bindings/regulator/maxim,max8973.yaml +++ b/Documentation/devicetree/bindings/regulator/maxim,max8973.yaml @@ -86,6 +86,9 @@ properties: reg: maxItems: 1 + interrupts: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml index b959504e0ea4..5c73d3f639c7 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml @@ -43,6 +43,7 @@ description: | For PM8150L, smps1 - smps8, ldo1 - ldo11, bob, flash, rgb For PM8350, smps1 - smps12, ldo1 - ldo10 For PM8350C, smps1 - smps10, ldo1 - ldo13, bob + For PM8450, smps1 - smps6, ldo1 - ldo4 For PM8998, smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 For PMI8998, bob For PMR735A, smps1 - smps3, ldo1 - ldo7 @@ -62,7 +63,9 @@ properties: - qcom,pm8150l-rpmh-regulators - qcom,pm8350-rpmh-regulators - qcom,pm8350c-rpmh-regulators + - qcom,pm8450-rpmh-regulators - qcom,pm8998-rpmh-regulators + - qcom,pmg1110-rpmh-regulators - qcom,pmi8998-rpmh-regulators - qcom,pmm8155au-rpmh-regulators - qcom,pmr735a-rpmh-regulators diff --git a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt index 2b544059e029..c2a39b121b1b 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt @@ -6,6 +6,7 @@ Qualcomm SPMI Regulators Definition: must be one of: "qcom,pm8004-regulators" "qcom,pm8005-regulators" + "qcom,pm8226-regulators" "qcom,pm8841-regulators" "qcom,pm8916-regulators" "qcom,pm8941-regulators" diff --git a/Documentation/devicetree/bindings/regulator/regulator.yaml b/Documentation/devicetree/bindings/regulator/regulator.yaml index a6ae9ecae5cc..ed560ee8714e 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/regulator.yaml @@ -218,7 +218,7 @@ properties: description: Array of maximum spread between voltages of coupled regulators in microvolts, each value in the array relates to the corresponding couple specified by the regulator-coupled-with property. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: "/schemas/types.yaml#/definitions/uint32-array" regulator-max-step-microvolt: description: Maximum difference between current and target voltages diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index d60fccedb250..00efb18a836c 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -125,27 +125,6 @@ static int bd71837_get_buck34_enable_hwctrl(struct regulator_dev *rdev) return !!(BD718XX_BUCK_RUN_ON & val); } -/* - * On BD71837 (not on BD71847, BD71850, ...) - * Bucks 1 to 4 support DVS. PWM mode is used when voltage is changed. - * Bucks 5 to 8 and LDOs can use PFM and must be disabled when voltage - * is changed. Hence we return -EBUSY for these if voltage is changed - * when BUCK/LDO is enabled. - * - * On BD71847, BD71850, ... The LDO voltage can be changed when LDO is - * enabled. But if voltage is increased the LDO power-good monitoring - * must be disabled for the duration of changing + 1mS to ensure voltage - * has reached the higher level before HW does next under voltage detection - * cycle. - */ -static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev, - unsigned int sel) -{ - if (rdev->desc->ops->is_enabled(rdev)) - return -EBUSY; - - return regulator_set_voltage_sel_regmap(rdev, sel); -} static void voltage_change_done(struct regulator_dev *rdev, unsigned int sel, unsigned int *mask) @@ -642,22 +621,22 @@ BD718XX_OPS(bd71837_pickable_range_buck_ops, bd718x7_set_buck_ovp); BD718XX_OPS(bd71837_ldo_regulator_ops, regulator_list_voltage_linear_range, - NULL, bd71837_set_voltage_sel_restricted, + NULL, rohm_regulator_set_voltage_sel_restricted, regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp, NULL); BD718XX_OPS(bd71837_ldo_regulator_nolinear_ops, regulator_list_voltage_table, - NULL, bd71837_set_voltage_sel_restricted, + NULL, rohm_regulator_set_voltage_sel_restricted, regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp, NULL); BD718XX_OPS(bd71837_buck_regulator_ops, regulator_list_voltage_linear_range, - NULL, bd71837_set_voltage_sel_restricted, + NULL, rohm_regulator_set_voltage_sel_restricted, regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp); BD718XX_OPS(bd71837_buck_regulator_nolinear_ops, regulator_list_voltage_table, - regulator_map_voltage_ascend, bd71837_set_voltage_sel_restricted, + regulator_map_voltage_ascend, rohm_regulator_set_voltage_sel_restricted, regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp); /* diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index e66925090258..6f21223a488e 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -86,6 +86,22 @@ static struct da9121_range da9121_3A_1phase_current = { .reg_max = 6, }; +static struct da9121_range da914x_40A_4phase_current = { + .val_min = 14000000, + .val_max = 80000000, + .val_stp = 2000000, + .reg_min = 1, + .reg_max = 14, +}; + +static struct da9121_range da914x_20A_2phase_current = { + .val_min = 7000000, + .val_max = 40000000, + .val_stp = 2000000, + .reg_min = 1, + .reg_max = 14, +}; + struct da9121_variant_info { int num_bucks; int num_phases; @@ -97,6 +113,8 @@ static const struct da9121_variant_info variant_parameters[] = { { 2, 1, &da9121_3A_1phase_current }, //DA9121_TYPE_DA9220_DA9132 { 2, 1, &da9121_5A_1phase_current }, //DA9121_TYPE_DA9122_DA9131 { 1, 2, &da9121_6A_2phase_current }, //DA9121_TYPE_DA9217 + { 1, 4, &da914x_40A_4phase_current }, //DA9121_TYPE_DA9141 + { 1, 2, &da914x_20A_2phase_current }, //DA9121_TYPE_DA9142 }; struct da9121_field { @@ -253,6 +271,11 @@ static int da9121_set_current_limit(struct regulator_dev *rdev, goto error; } + if (rdev->desc->ops->is_enabled(rdev)) { + ret = -EBUSY; + goto error; + } + ret = da9121_ceiling_selector(rdev, min_ua, max_ua, &sel); if (ret < 0) goto error; @@ -537,11 +560,65 @@ static const struct regulator_desc da9217_reg = { .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, }; +#define DA914X_MIN_MV 500 +#define DA914X_MAX_MV 1000 +#define DA914X_STEP_MV 10 +#define DA914X_MIN_SEL (DA914X_MIN_MV / DA914X_STEP_MV) +#define DA914X_N_VOLTAGES (((DA914X_MAX_MV - DA914X_MIN_MV) / DA914X_STEP_MV) \ + + 1 + DA914X_MIN_SEL) + +static const struct regulator_desc da9141_reg = { + .id = DA9121_IDX_BUCK1, + .name = "DA9141", + .of_match = "buck1", + .of_parse_cb = da9121_of_parse_cb, + .owner = THIS_MODULE, + .regulators_node = of_match_ptr("regulators"), + .of_map_mode = da9121_map_mode, + .ops = &da9121_buck_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = DA914X_N_VOLTAGES, + .min_uV = DA914X_MIN_MV * 1000, + .uV_step = DA914X_STEP_MV * 1000, + .linear_min_sel = DA914X_MIN_SEL, + .vsel_reg = DA9121_REG_BUCK_BUCK1_5, + .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, + .enable_reg = DA9121_REG_BUCK_BUCK1_0, + .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, + /* Default value of BUCK_BUCK1_0.CH1_SRC_DVC_UP */ + .ramp_delay = 20000, + /* tBUCK_EN */ + .enable_time = 20, +}; + +static const struct regulator_desc da9142_reg = { + .id = DA9121_IDX_BUCK1, + .name = "DA9142 BUCK1", + .of_match = "buck1", + .of_parse_cb = da9121_of_parse_cb, + .owner = THIS_MODULE, + .regulators_node = of_match_ptr("regulators"), + .of_map_mode = da9121_map_mode, + .ops = &da9121_buck_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = DA914X_N_VOLTAGES, + .min_uV = DA914X_MIN_MV * 1000, + .uV_step = DA914X_STEP_MV * 1000, + .linear_min_sel = DA914X_MIN_SEL, + .enable_reg = DA9121_REG_BUCK_BUCK1_0, + .enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN, + .vsel_reg = DA9121_REG_BUCK_BUCK1_5, + .vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT, +}; + + static const struct regulator_desc *local_da9121_regulators[][DA9121_IDX_MAX] = { [DA9121_TYPE_DA9121_DA9130] = { &da9121_reg, NULL }, [DA9121_TYPE_DA9220_DA9132] = { &da9220_reg[0], &da9220_reg[1] }, [DA9121_TYPE_DA9122_DA9131] = { &da9122_reg[0], &da9122_reg[1] }, [DA9121_TYPE_DA9217] = { &da9217_reg, NULL }, + [DA9121_TYPE_DA9141] = { &da9141_reg, NULL }, + [DA9121_TYPE_DA9142] = { &da9142_reg, NULL }, }; static void da9121_status_poll_on(struct work_struct *work) @@ -835,7 +912,7 @@ static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip) goto error; } - if (device_id != DA9121_DEVICE_ID) { + if ((device_id != DA9121_DEVICE_ID) && (device_id != DA914x_DEVICE_ID)) { dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id); ret = -ENODEV; goto error; @@ -877,6 +954,22 @@ static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip) break; } + if (device_id == DA914x_DEVICE_ID) { + switch (chip->subvariant_id) { + case DA9121_SUBTYPE_DA9141: + type = "DA9141"; + config_match = (variant_vrc == DA9141_VARIANT_VRC); + break; + case DA9121_SUBTYPE_DA9142: + type = "DA9142"; + config_match = (variant_vrc == DA9142_VARIANT_VRC); + break; + default: + type = "Unknown"; + break; + } + } + dev_info(chip->dev, "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n", device_id, variant_id, type); @@ -890,8 +983,10 @@ static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip) variant_mrc = (variant_id & DA9121_MASK_OTP_VARIANT_ID_MRC) >> DA9121_SHIFT_OTP_VARIANT_ID_MRC; - if ((device_id == DA9121_DEVICE_ID) && - (variant_mrc < DA9121_VARIANT_MRC_BASE)) { + if (((device_id == DA9121_DEVICE_ID) && + (variant_mrc < DA9121_VARIANT_MRC_BASE)) || + ((device_id == DA914x_DEVICE_ID) && + (variant_mrc != DA914x_VARIANT_MRC_BASE))) { dev_err(chip->dev, "Cannot support variant MRC: 0x%02X\n", variant_mrc); ret = -EINVAL; @@ -931,6 +1026,14 @@ static int da9121_assign_chip_model(struct i2c_client *i2c, chip->variant_id = DA9121_TYPE_DA9220_DA9132; regmap = &da9121_2ch_regmap_config; break; + case DA9121_SUBTYPE_DA9141: + chip->variant_id = DA9121_TYPE_DA9141; + regmap = &da9121_1ch_regmap_config; + break; + case DA9121_SUBTYPE_DA9142: + chip->variant_id = DA9121_TYPE_DA9142; + regmap = &da9121_2ch_regmap_config; + break; } /* Set these up for of_regulator_match call which may want .of_map_modes */ @@ -1010,6 +1113,8 @@ static const struct of_device_id da9121_dt_ids[] = { { .compatible = "dlg,da9131", .data = (void *) DA9121_SUBTYPE_DA9131 }, { .compatible = "dlg,da9220", .data = (void *) DA9121_SUBTYPE_DA9220 }, { .compatible = "dlg,da9132", .data = (void *) DA9121_SUBTYPE_DA9132 }, + { .compatible = "dlg,da9141", .data = (void *) DA9121_SUBTYPE_DA9141 }, + { .compatible = "dlg,da9142", .data = (void *) DA9121_SUBTYPE_DA9142 }, { } }; MODULE_DEVICE_TABLE(of, da9121_dt_ids); @@ -1065,7 +1170,7 @@ static int da9121_i2c_remove(struct i2c_client *i2c) { struct da9121 *chip = i2c_get_clientdata(i2c); const int mask_all[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; - int ret = 0; + int ret; free_irq(chip->chip_irq, chip); cancel_delayed_work_sync(&chip->work); @@ -1073,7 +1178,7 @@ static int da9121_i2c_remove(struct i2c_client *i2c) ret = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_MASK_0, mask_all, 4); if (ret != 0) dev_err(chip->dev, "Failed to set IRQ masks: %d\n", ret); - return ret; + return 0; } static const struct i2c_device_id da9121_i2c_id[] = { @@ -1084,6 +1189,8 @@ static const struct i2c_device_id da9121_i2c_id[] = { {"da9131", DA9121_TYPE_DA9122_DA9131}, {"da9220", DA9121_TYPE_DA9220_DA9132}, {"da9132", DA9121_TYPE_DA9220_DA9132}, + {"da9141", DA9121_TYPE_DA9141}, + {"da9142", DA9121_TYPE_DA9142}, {}, }; MODULE_DEVICE_TABLE(i2c, da9121_i2c_id); diff --git a/drivers/regulator/da9121-regulator.h b/drivers/regulator/da9121-regulator.h index 357f416e17c1..a328a0bdfa29 100644 --- a/drivers/regulator/da9121-regulator.h +++ b/drivers/regulator/da9121-regulator.h @@ -26,7 +26,9 @@ enum da9121_variant { DA9121_TYPE_DA9121_DA9130, DA9121_TYPE_DA9220_DA9132, DA9121_TYPE_DA9122_DA9131, - DA9121_TYPE_DA9217 + DA9121_TYPE_DA9217, + DA9121_TYPE_DA9141, + DA9121_TYPE_DA9142 }; enum da9121_subvariant { @@ -36,7 +38,9 @@ enum da9121_subvariant { DA9121_SUBTYPE_DA9132, DA9121_SUBTYPE_DA9122, DA9121_SUBTYPE_DA9131, - DA9121_SUBTYPE_DA9217 + DA9121_SUBTYPE_DA9217, + DA9121_SUBTYPE_DA9141, + DA9121_SUBTYPE_DA9142 }; /* Minimum, maximum and default polling millisecond periods are provided @@ -70,6 +74,14 @@ enum da9121_subvariant { #define DA9121_REG_SYS_GPIO1_1 0x13 #define DA9121_REG_SYS_GPIO2_0 0x14 #define DA9121_REG_SYS_GPIO2_1 0x15 +#define DA914x_REG_SYS_GPIO3_0 0x16 +#define DA914x_REG_SYS_GPIO3_1 0x17 +#define DA914x_REG_SYS_GPIO4_0 0x18 +#define DA914x_REG_SYS_GPIO4_1 0x19 +#define DA914x_REG_SYS_ADMUX1_0 0x1A +#define DA914x_REG_SYS_ADMUX1_1 0x1B +#define DA914x_REG_SYS_ADMUX2_0 0x1C +#define DA914x_REG_SYS_ADMUX2_1 0x1D #define DA9121_REG_BUCK_BUCK1_0 0x20 #define DA9121_REG_BUCK_BUCK1_1 0x21 #define DA9121_REG_BUCK_BUCK1_2 0x22 @@ -276,6 +288,7 @@ enum da9121_subvariant { #define DA9121_MASK_OTP_DEVICE_ID_DEV_ID 0xFF #define DA9121_DEVICE_ID 0x05 +#define DA914x_DEVICE_ID 0x26 /* DA9121_REG_OTP_VARIANT_ID */ @@ -293,6 +306,10 @@ enum da9121_subvariant { #define DA9131_VARIANT_VRC 0x1 #define DA9132_VARIANT_VRC 0x2 +#define DA914x_VARIANT_MRC_BASE 0x0 +#define DA9141_VARIANT_VRC 0x1 +#define DA9142_VARIANT_VRC 0x2 + /* DA9121_REG_OTP_CUSTOMER_ID */ #define DA9121_MASK_OTP_CUSTOMER_ID_CUST_ID 0xFF diff --git a/drivers/regulator/irq_helpers.c b/drivers/regulator/irq_helpers.c index 522764435575..fe7ae0f3f46a 100644 --- a/drivers/regulator/irq_helpers.c +++ b/drivers/regulator/irq_helpers.c @@ -320,7 +320,9 @@ static void init_rdev_errors(struct regulator_irq *h) * IRQF_ONESHOT when requesting the (threaded) irq. * @common_errs: Errors which can be flagged by this IRQ for all rdevs. * When IRQ is re-enabled these errors will be cleared - * from all associated regulators + * from all associated regulators. Use this instead of the + * per_rdev_errs if you use + * regulator_irq_map_event_simple() for event mapping. * @per_rdev_errs: Optional error flag array describing errors specific * for only some of the regulators. These errors will be * or'ed with common errors. If this is given the array @@ -395,3 +397,40 @@ void regulator_irq_helper_cancel(void **handle) } } EXPORT_SYMBOL_GPL(regulator_irq_helper_cancel); + +/** + * regulator_irq_map_event_simple - regulator IRQ notification for trivial IRQs + * + * @irq: Number of IRQ that occurred + * @rid: Information about the event IRQ indicates + * @dev_mask: mask indicating the regulator originating the IRQ + * + * Regulators whose IRQ has single, well defined purpose (always indicate + * exactly one event, and are relevant to exactly one regulator device) can + * use this function as their map_event callbac for their regulator IRQ + * notification helperk. Exactly one rdev and exactly one error (in + * "common_errs"-field) can be given at IRQ helper registration for + * regulator_irq_map_event_simple() to be viable. + */ +int regulator_irq_map_event_simple(int irq, struct regulator_irq_data *rid, + unsigned long *dev_mask) +{ + int err = rid->states[0].possible_errs; + + *dev_mask = 1; + /* + * This helper should only be used in a situation where the IRQ + * can indicate only one type of problem for one specific rdev. + * Something fishy is going on if we are having multiple rdevs or ERROR + * flags here. + */ + if (WARN_ON(rid->num_states != 1 || hweight32(err) != 1)) + return 0; + + rid->states[0].errors = err; + rid->states[0].notifs = regulator_err2notif(err); + + return 0; +} +EXPORT_SYMBOL_GPL(regulator_irq_map_event_simple); + diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 12425f667c00..a3bc0eb6ceb8 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -814,6 +814,11 @@ static const struct rpmh_vreg_init_data pm8998_vreg_data[] = { {} }; +static const struct rpmh_vreg_init_data pmg1110_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"), + {} +}; + static const struct rpmh_vreg_init_data pmi8998_vreg_data[] = { RPMH_VREG("bob", "bob%s1", &pmic4_bob, "vdd-bob"), {} @@ -969,6 +974,20 @@ static const struct rpmh_vreg_init_data pm8350c_vreg_data[] = { {} }; +static const struct rpmh_vreg_init_data pm8450_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps520, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps520, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps520, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps520, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps520, "vdd-s6"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo_lv, "vdd-l4"), + {} +}; + static const struct rpmh_vreg_init_data pm8009_vreg_data[] = { RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"), RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps515, "vdd-s2"), @@ -1214,10 +1233,18 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = { .data = pm8350c_vreg_data, }, { + .compatible = "qcom,pm8450-rpmh-regulators", + .data = pm8450_vreg_data, + }, + { .compatible = "qcom,pm8998-rpmh-regulators", .data = pm8998_vreg_data, }, { + .compatible = "qcom,pmg1110-rpmh-regulators", + .data = pmg1110_vreg_data, + }, + { .compatible = "qcom,pmi8998-rpmh-regulators", .data = pmi8998_vreg_data, }, diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 41424a3366d0..02bfce981150 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -1895,6 +1895,44 @@ static const struct spmi_regulator_data pm8941_regulators[] = { { } }; +static const struct spmi_regulator_data pm8226_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "s3", 0x1a00, "vdd_s3", }, + { "s4", 0x1d00, "vdd_s4", }, + { "s5", 0x2000, "vdd_s5", }, + { "l1", 0x4000, "vdd_l1_l2_l4_l5", }, + { "l2", 0x4100, "vdd_l1_l2_l4_l5", }, + { "l3", 0x4200, "vdd_l3_l24_l26", }, + { "l4", 0x4300, "vdd_l1_l2_l4_l5", }, + { "l5", 0x4400, "vdd_l1_l2_l4_l5", }, + { "l6", 0x4500, "vdd_l6_l7_l8_l9_l27", }, + { "l7", 0x4600, "vdd_l6_l7_l8_l9_l27", }, + { "l8", 0x4700, "vdd_l6_l7_l8_l9_l27", }, + { "l9", 0x4800, "vdd_l6_l7_l8_l9_l27", }, + { "l10", 0x4900, "vdd_l10_l11_l13", }, + { "l11", 0x4a00, "vdd_l10_l11_l13", }, + { "l12", 0x4b00, "vdd_l12_l14", }, + { "l13", 0x4c00, "vdd_l10_l11_l13", }, + { "l14", 0x4d00, "vdd_l12_l14", }, + { "l15", 0x4e00, "vdd_l15_l16_l17_l18", }, + { "l16", 0x4f00, "vdd_l15_l16_l17_l18", }, + { "l17", 0x5000, "vdd_l15_l16_l17_l18", }, + { "l18", 0x5100, "vdd_l15_l16_l17_l18", }, + { "l19", 0x5200, "vdd_l19_l20_l21_l22_l23_l28", }, + { "l20", 0x5300, "vdd_l19_l20_l21_l22_l23_l28", }, + { "l21", 0x5400, "vdd_l19_l20_l21_l22_l23_l28", }, + { "l22", 0x5500, "vdd_l19_l20_l21_l22_l23_l28", }, + { "l23", 0x5600, "vdd_l19_l20_l21_l22_l23_l28", }, + { "l24", 0x5700, "vdd_l3_l24_l26", }, + { "l25", 0x5800, "vdd_l25", }, + { "l26", 0x5900, "vdd_l3_l24_l26", }, + { "l27", 0x5a00, "vdd_l6_l7_l8_l9_l27", }, + { "l28", 0x5b00, "vdd_l19_l20_l21_l22_l23_l28", }, + { "lvs1", 0x8000, "vdd_lvs1", }, + { } +}; + static const struct spmi_regulator_data pm8841_regulators[] = { { "s1", 0x1400, "vdd_s1", }, { "s2", 0x1700, "vdd_s2", NULL, 0x1c08 }, @@ -2095,6 +2133,7 @@ static const struct spmi_regulator_data pms405_regulators[] = { static const struct of_device_id qcom_spmi_regulator_match[] = { { .compatible = "qcom,pm8004-regulators", .data = &pm8004_regulators }, { .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators }, + { .compatible = "qcom,pm8226-regulators", .data = &pm8226_regulators }, { .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators }, { .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators }, { .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators }, diff --git a/drivers/regulator/rohm-regulator.c b/drivers/regulator/rohm-regulator.c index 6e0d9c08ec1c..f97a9a51ee76 100644 --- a/drivers/regulator/rohm-regulator.c +++ b/drivers/regulator/rohm-regulator.c @@ -112,6 +112,22 @@ int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs, } EXPORT_SYMBOL(rohm_regulator_set_dvs_levels); +/* + * Few ROHM PMIC ICs have constrains on voltage changing: + * BD71837 - only buck 1-4 voltages can be changed when they are enabled. + * Other bucks and all LDOs must be disabled when voltage is changed. + * BD96801 - LDO voltage levels can be changed when LDOs are disabled. + */ +int rohm_regulator_set_voltage_sel_restricted(struct regulator_dev *rdev, + unsigned int sel) +{ + if (rdev->desc->ops->is_enabled(rdev)) + return -EBUSY; + + return regulator_set_voltage_sel_regmap(rdev, sel); +} +EXPORT_SYMBOL_GPL(rohm_regulator_set_voltage_sel_restricted); + MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Matti Vaittinen <[email protected]>"); MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers"); diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 4a51cfea45ac..e2a20d512152 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -196,7 +196,6 @@ static int twl4030reg_enable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; - int ret; grp = twlreg_grp(rdev); if (grp < 0) @@ -204,16 +203,13 @@ static int twl4030reg_enable(struct regulator_dev *rdev) grp |= P1_GRP_4030; - ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); - - return ret; + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); } static int twl4030reg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; - int ret; grp = twlreg_grp(rdev); if (grp < 0) @@ -221,9 +217,7 @@ static int twl4030reg_disable(struct regulator_dev *rdev) grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); - ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); - - return ret; + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); } static int twl4030reg_get_status(struct regulator_dev *rdev) diff --git a/include/linux/mfd/rohm-generic.h b/include/linux/mfd/rohm-generic.h index 35b392a0d73a..5ed97a1d0908 100644 --- a/include/linux/mfd/rohm-generic.h +++ b/include/linux/mfd/rohm-generic.h @@ -80,14 +80,8 @@ int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs, const struct regulator_desc *desc, struct regmap *regmap); -#else -static inline int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs, - struct device_node *np, - const struct regulator_desc *desc, - struct regmap *regmap) -{ - return 0; -} +int rohm_regulator_set_voltage_sel_restricted(struct regulator_dev *rdev, + unsigned int sel); #endif #endif diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index bd7a73db2e66..720684995a77 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -90,22 +90,28 @@ enum regulator_detection_severity { * @set_over_current_protection: Support enabling of and setting limits for over * current situation detection. Detection can be configured for three * levels of severity. - * REGULATOR_SEVERITY_PROT should automatically shut down the regulator(s). - * REGULATOR_SEVERITY_ERR should indicate that over-current situation is - * caused by an unrecoverable error but HW does not perform - * automatic shut down. - * REGULATOR_SEVERITY_WARN should indicate situation where hardware is - * still believed to not be damaged but that a board sepcific - * recovery action is needed. If lim_uA is 0 the limit should not - * be changed but the detection should just be enabled/disabled as - * is requested. + * + * - REGULATOR_SEVERITY_PROT should automatically shut down the regulator(s). + * + * - REGULATOR_SEVERITY_ERR should indicate that over-current situation is + * caused by an unrecoverable error but HW does not perform + * automatic shut down. + * + * - REGULATOR_SEVERITY_WARN should indicate situation where hardware is + * still believed to not be damaged but that a board sepcific + * recovery action is needed. If lim_uA is 0 the limit should not + * be changed but the detection should just be enabled/disabled as + * is requested. + * * @set_over_voltage_protection: Support enabling of and setting limits for over * voltage situation detection. Detection can be configured for same - * severities as over current protection. + * severities as over current protection. Units of uV. * @set_under_voltage_protection: Support enabling of and setting limits for - * under situation detection. + * under voltage situation detection. Detection can be configured for same + * severities as over current protection. Units of uV. * @set_thermal_protection: Support enabling of and setting limits for over - * temperature situation detection. + * temperature situation detection.Detection can be configured for same + * severities as over current protection. Units of degree Kelvin. * * @set_active_discharge: Set active discharge enable/disable of regulators. * @@ -552,7 +558,6 @@ struct regulator_irq_data { */ struct regulator_irq_desc { const char *name; - int irq_flags; int fatal_cnt; int reread_ms; int irq_off_ms; @@ -644,6 +649,40 @@ struct regulator_dev { spinlock_t err_lock; }; +/* + * Convert error flags to corresponding notifications. + * + * Can be used by drivers which use the notification helpers to + * find out correct notification flags based on the error flags. Drivers + * can avoid storing both supported notification and error flags which + * may save few bytes. + */ +static inline int regulator_err2notif(int err) +{ + switch (err) { + case REGULATOR_ERROR_UNDER_VOLTAGE: + return REGULATOR_EVENT_UNDER_VOLTAGE; + case REGULATOR_ERROR_OVER_CURRENT: + return REGULATOR_EVENT_OVER_CURRENT; + case REGULATOR_ERROR_REGULATION_OUT: + return REGULATOR_EVENT_REGULATION_OUT; + case REGULATOR_ERROR_FAIL: + return REGULATOR_EVENT_FAIL; + case REGULATOR_ERROR_OVER_TEMP: + return REGULATOR_EVENT_OVER_TEMP; + case REGULATOR_ERROR_UNDER_VOLTAGE_WARN: + return REGULATOR_EVENT_UNDER_VOLTAGE_WARN; + case REGULATOR_ERROR_OVER_CURRENT_WARN: + return REGULATOR_EVENT_OVER_CURRENT_WARN; + case REGULATOR_ERROR_OVER_VOLTAGE_WARN: + return REGULATOR_EVENT_OVER_VOLTAGE_WARN; + case REGULATOR_ERROR_OVER_TEMP_WARN: + return REGULATOR_EVENT_OVER_TEMP_WARN; + } + return 0; +} + + struct regulator_dev * regulator_register(const struct regulator_desc *regulator_desc, const struct regulator_config *config); @@ -665,6 +704,8 @@ void *regulator_irq_helper(struct device *dev, int irq_flags, int common_errs, int *per_rdev_errs, struct regulator_dev **rdev, int rdev_amount); void regulator_irq_helper_cancel(void **handle); +int regulator_irq_map_event_simple(int irq, struct regulator_irq_data *rid, + unsigned long *dev_mask); void *rdev_get_drvdata(struct regulator_dev *rdev); struct device *rdev_get_dev(struct regulator_dev *rdev); |