Satya Priya (9):
dt-bindings: mfd: pm8008: Add reset-gpios
dt-bindings: mfd: pm8008: Change the address cells
dt-bindings: mfd: pm8008: Add regulators for pm8008
mfd: pm8008: Add reset-gpios
mfd: pm8008: Remove the regmap member from pm8008_data struct
mfd: pm8008: Use i2c_new_dummy_device() API
regulator: Add a regulator driver for the PM8008 PMIC
arm64: dts: qcom: pm8008: Add base dts file
arm64: dts: qcom: sc7280: Add pm8008 support for sc7280-idp
.../devicetree/bindings/mfd/qcom,pm8008.yaml | 69 +++++-
arch/arm64/boot/dts/qcom/pm8008.dtsi | 54 +++++
arch/arm64/boot/dts/qcom/sc7280-idp.dtsi | 66 ++++++
drivers/mfd/qcom-pm8008.c | 60 ++++-
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/qcom-pm8008-regulator.c | 248 +++++++++++++++++++++
include/linux/mfd/qcom_pm8008.h | 9 +
8 files changed, 498 insertions(+), 18 deletions(-)
create mode 100644 arch/arm64/boot/dts/qcom/pm8008.dtsi
create mode 100644 drivers/regulator/qcom-pm8008-regulator.c
create mode 100644 include/linux/mfd/qcom_pm8008.h
--
2.7.4
Add pm8008 infra and regulators support for sc7280 idp.
Signed-off-by: Satya Priya <[email protected]>
Reviewed-by: Stephen Boyd <[email protected]>
---
Changes in V14:
- None.
Changes in V13:
- None.
Changes in V12:
- None.
Changes in V11:
- Add ldos and parent supplies directly under pm8008@8 node.
arch/arm64/boot/dts/qcom/sc7280-idp.dtsi | 66 ++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
index 5eb6689..166812e 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
@@ -271,6 +271,63 @@
};
};
+pm8008_bus: &i2c1 {
+ status = "okay";
+};
+
+#include "pm8008.dtsi"
+
+&pm8008 {
+ interrupt-parent = <&tlmm>;
+ interrupts = <24 IRQ_TYPE_EDGE_RISING>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm8008_active>;
+
+ reset-gpios = <&pm8350c_gpios 4 GPIO_ACTIVE_LOW>;
+
+ vdd_l1_l2-supply = <&vreg_s8b_1p2>;
+ vdd_l3_l4-supply = <&vreg_s1b_1p8>;
+ vdd_l5-supply = <&vreg_bob>;
+ vdd_l6-supply = <&vreg_bob>;
+ vdd_l7-supply = <&vreg_bob>;
+};
+
+&pm8008_l1 {
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1300000>;
+};
+
+&pm8008_l2 {
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1250000>;
+};
+
+&pm8008_l3 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3000000>;
+};
+
+&pm8008_l4 {
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <1600000>;
+};
+
+&pm8008_l5 {
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <3000000>;
+};
+
+&pm8008_l6 {
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <3000000>;
+};
+
+&pm8008_l7 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3544000>;
+};
+
&qfprom {
vcc-supply = <&vreg_l1c_1p8>;
};
@@ -383,6 +440,15 @@
drive-strength = <2>;
};
+&pm8350c_gpios {
+ pm8008_active: pm8008-active {
+ pins = "gpio4";
+ function = "normal";
+ bias-disable;
+ power-source = <0>;
+ };
+};
+
&qspi_cs0 {
bias-disable;
};
--
2.7.4
Add regulators and their parent supplies along with example.
Signed-off-by: Satya Priya <[email protected]>
Reviewed-by: Stephen Boyd <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
Changes in V14:
- None.
Changes in V13:
- None.
Changes in V12:
- None.
Changes in V11:
- Add ldos directly under pm8008@8 node, remove the intermediate "regulators"
node.
Changes in V10:
- Regulators are added as a part of pm8008@8 device. Change bindings doc
accordingly.
.../devicetree/bindings/mfd/qcom,pm8008.yaml | 50 ++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
index a54d1ce0..fd3c51e 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
@@ -47,6 +47,21 @@ properties:
reset-gpios:
maxItems: 1
+ vdd_l1_l2-supply:
+ description: Input supply phandle of ldo1 and ldo2 regulators.
+
+ vdd_l3_l4-supply:
+ description: Input supply phandle of ldo3 and ldo4 regulators.
+
+ vdd_l5-supply:
+ description: Input supply phandle of ldo5 regulator.
+
+ vdd_l6-supply:
+ description: Input supply phandle of ldo6 regulator.
+
+ vdd_l7-supply:
+ description: Input supply phandle of ldo7 regulator.
+
patternProperties:
"^gpio@0,[0-9a-f]+$":
type: object
@@ -88,6 +103,27 @@ patternProperties:
additionalProperties: false
+ "^ldo[1-7]@[1],[0-9a-f]+$":
+ type: object
+
+ $ref: "/schemas/regulator/regulator.yaml#"
+
+ description: PM8008 regulator peripherals of PM8008 regulator device.
+
+ properties:
+ compatible:
+ const: qcom,pm8008-regulator
+
+ reg:
+ description: Peripheral offset and address of the ldo regulator.
+ maxItems: 1
+
+ required:
+ - compatible
+ - reg
+
+ unevaluatedProperties: false
+
required:
- compatible
- reg
@@ -120,6 +156,12 @@ examples:
reset-gpios = <&pm8350c_gpios 4 GPIO_ACTIVE_LOW>;
+ vdd_l1_l2-supply = <&vreg_s8b_1p2>;
+ vdd_l3_l4-supply = <&vreg_s1b_1p8>;
+ vdd_l5-supply = <&vreg_bob>;
+ vdd_l6-supply = <&vreg_bob>;
+ vdd_l7-supply = <&vreg_bob>;
+
pm8008_gpios: gpio@0,c000 {
compatible = "qcom,pm8008-gpio", "qcom,spmi-gpio";
reg = <0x0 0xc000>;
@@ -129,6 +171,14 @@ examples:
interrupt-controller;
#interrupt-cells = <2>;
};
+
+ ldo1@1,4000 {
+ compatible = "qcom,pm8008-regulator";
+ reg = <0x1 0x4000>;
+ regulator-name = "pm8008_ldo1";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1300000>;
+ };
};
};
--
2.7.4
Remove the regmap member from pm8008_data struct as it is
not used outside of probe. Add a local variable for regmap
and pass it to the pm8008_probe_irq_peripherals()
API in pm8008_probe.
Signed-off-by: Satya Priya <[email protected]>
Reviewed-by: Stephen Boyd <[email protected]>
---
Changes in V14:
- None.
Changes in V13:
- None.
Changes in V12:
- None.
Changes in V11:
- New patch added from V11.
drivers/mfd/qcom-pm8008.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c
index 5a670b0..569ffd50 100644
--- a/drivers/mfd/qcom-pm8008.c
+++ b/drivers/mfd/qcom-pm8008.c
@@ -57,7 +57,6 @@ enum {
struct pm8008_data {
struct device *dev;
- struct regmap *regmap;
int irq;
struct regmap_irq_chip_data *irq_data;
};
@@ -151,7 +150,7 @@ static struct regmap_config qcom_mfd_regmap_cfg = {
.max_register = 0xFFFF,
};
-static int pm8008_init(struct pm8008_data *chip)
+static int pm8008_init(struct regmap *regmap)
{
int rc;
@@ -161,32 +160,32 @@ static int pm8008_init(struct pm8008_data *chip)
* This is required to enable the writing of TYPE registers in
* regmap_irq_sync_unlock().
*/
- rc = regmap_write(chip->regmap,
+ rc = regmap_write(regmap,
(PM8008_TEMP_ALARM_ADDR | INT_SET_TYPE_OFFSET),
BIT(0));
if (rc)
return rc;
/* Do the same for GPIO1 and GPIO2 peripherals */
- rc = regmap_write(chip->regmap,
+ rc = regmap_write(regmap,
(PM8008_GPIO1_ADDR | INT_SET_TYPE_OFFSET), BIT(0));
if (rc)
return rc;
- rc = regmap_write(chip->regmap,
+ rc = regmap_write(regmap,
(PM8008_GPIO2_ADDR | INT_SET_TYPE_OFFSET), BIT(0));
return rc;
}
static int pm8008_probe_irq_peripherals(struct pm8008_data *chip,
- int client_irq)
+ struct regmap *regmap, int client_irq)
{
int rc, i;
struct regmap_irq_type *type;
struct regmap_irq_chip_data *irq_data;
- rc = pm8008_init(chip);
+ rc = pm8008_init(regmap);
if (rc) {
dev_err(chip->dev, "Init failed: %d\n", rc);
return rc;
@@ -208,7 +207,7 @@ static int pm8008_probe_irq_peripherals(struct pm8008_data *chip,
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW);
}
- rc = devm_regmap_add_irq_chip(chip->dev, chip->regmap, client_irq,
+ rc = devm_regmap_add_irq_chip(chip->dev, regmap, client_irq,
IRQF_SHARED, 0, &pm8008_irq_chip, &irq_data);
if (rc) {
dev_err(chip->dev, "Failed to add IRQ chip: %d\n", rc);
@@ -223,14 +222,15 @@ static int pm8008_probe(struct i2c_client *client)
int rc;
struct pm8008_data *chip;
struct gpio_desc *reset_gpio;
+ struct regmap *regmap;
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
chip->dev = &client->dev;
- chip->regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg);
- if (!chip->regmap)
+ regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg);
+ if (!regmap)
return -ENODEV;
i2c_set_clientdata(client, chip);
@@ -240,7 +240,7 @@ static int pm8008_probe(struct i2c_client *client)
return PTR_ERR(reset_gpio);
if (of_property_read_bool(chip->dev->of_node, "interrupt-controller")) {
- rc = pm8008_probe_irq_peripherals(chip, client->irq);
+ rc = pm8008_probe_irq_peripherals(chip, regmap, client->irq);
if (rc)
dev_err(chip->dev, "Failed to probe irq periphs: %d\n", rc);
}
--
2.7.4
Change the address cells as '2' so that the first cell
describes the i2c address offset of the clients.
This helps us to define the child nodes of all
clients under the same parent mfd node, instead of
adding separate mfd DT nodes.
Change the gpios reg value accordingly.
Signed-off-by: Satya Priya <[email protected]>
Reviewed-by: Stephen Boyd <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
Changes in V14:
- None.
Changes in V13:
- Fixed nit.
Changes in V12:
- None.
Changes in V11:
- New patch added from V11.
Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
index a89649c..a54d1ce0 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
@@ -39,7 +39,7 @@ properties:
interrupt-controller: true
"#address-cells":
- const: 1
+ const: 2
"#size-cells":
const: 0
@@ -48,7 +48,7 @@ properties:
maxItems: 1
patternProperties:
- "^gpio@[0-9a-f]+$":
+ "^gpio@0,[0-9a-f]+$":
type: object
description: |
@@ -61,7 +61,7 @@ patternProperties:
- const: qcom,spmi-gpio
reg:
- description: Peripheral address of one of the two GPIO peripherals.
+ description: Peripheral offset and address of one of the two GPIO peripherals.
maxItems: 1
gpio-controller: true
@@ -110,7 +110,7 @@ examples:
pm8008i@8 {
compatible = "qcom,pm8008";
reg = <0x8>;
- #address-cells = <1>;
+ #address-cells = <2>;
#size-cells = <0>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -120,9 +120,9 @@ examples:
reset-gpios = <&pm8350c_gpios 4 GPIO_ACTIVE_LOW>;
- pm8008_gpios: gpio@c000 {
+ pm8008_gpios: gpio@0,c000 {
compatible = "qcom,pm8008-gpio", "qcom,spmi-gpio";
- reg = <0xc000>;
+ reg = <0x0 0xc000>;
gpio-controller;
gpio-ranges = <&pm8008_gpios 0 0 2>;
#gpio-cells = <2>;
--
2.7.4
Qualcomm Technologies, Inc. PM8008 is an I2C controlled PMIC
containing 7 LDO regulators. Add a PM8008 regulator driver to
support PMIC regulator management via the regulator framework.
Signed-off-by: Satya Priya <[email protected]>
Reported-by: kernel test robot <[email protected]>
Reported-by: Dan Carpenter <[email protected]>
---
Changes in V14:
- Remove unused headers and debug prints.
- Remove min_uv and max_uv from reg_data[] and set the min/max based
on the voltage_range pointer.
- In get_voltage_sel read voltage from hw and calculate selector instead
of using selector from set_voltage.
- Add errro check after regulator_list_voltage_linear_range().
- Use static_assert to make sure nldo_ranges & pldo_ranges doesn't become
larger and we forget to update the pm8008_reg->rdesc.n_linear_ranges
Changes in V13:
- Added if check to avoid buffer overflow warnings.
for (i = 0; i < ARRAY_SIZE(reg_data); i++)
if (strstr(name, reg_data[i].name))
break;
if (i == ARRAY_SIZE(reg_data)) {
dev_err(dev, "Invalid regulator name %s\n", name);
return -EINVAL;
}
- Removed unused headers.
Changes in V12:
- Get base from reg property in DT node.
Changes in V11:
- Added of_device_id table and compatible to register the ldos.
drivers/regulator/Kconfig | 9 ++
drivers/regulator/Makefile | 1 +
drivers/regulator/qcom-pm8008-regulator.c | 248 ++++++++++++++++++++++++++++++
3 files changed, 258 insertions(+)
create mode 100644 drivers/regulator/qcom-pm8008-regulator.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index cbe0f96..2c6d9c2 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -925,6 +925,15 @@ config REGULATOR_PWM
This driver supports PWM controlled voltage regulators. PWM
duty cycle can increase or decrease the voltage.
+config REGULATOR_QCOM_PM8008
+ tristate "Qualcomm Technologies, Inc. PM8008 PMIC regulators"
+ depends on MFD_QCOM_PM8008
+ help
+ Select this option to get support for the voltage regulators
+ of Qualcomm Technologies, Inc. PM8008 PMIC chip. PM8008 has 7 LDO
+ regulators. This driver provides support for basic operations like
+ set/get voltage and enable/disable.
+
config REGULATOR_QCOM_RPM
tristate "Qualcomm RPM regulator driver"
depends on MFD_QCOM_RPM
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 8d3ee8b..169e686 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o
+obj-$(CONFIG_REGULATOR_QCOM_PM8008) += qcom-pm8008-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
diff --git a/drivers/regulator/qcom-pm8008-regulator.c b/drivers/regulator/qcom-pm8008-regulator.c
new file mode 100644
index 0000000..71cb95c
--- /dev/null
+++ b/drivers/regulator/qcom-pm8008-regulator.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/mfd/qcom_pm8008.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define VSET_STEP_MV 8
+#define VSET_STEP_UV (VSET_STEP_MV * 1000)
+
+#define LDO_ENABLE_REG(base) ((base) + 0x46)
+#define ENABLE_BIT BIT(7)
+
+#define LDO_VSET_LB_REG(base) ((base) + 0x40)
+
+#define LDO_STEPPER_CTL_REG(base) ((base) + 0x3b)
+#define DEFAULT_VOLTAGE_STEPPER_RATE 38400
+#define STEP_RATE_MASK GENMASK(1, 0)
+
+#define NLDO_MIN_UV 528000
+#define NLDO_MAX_UV 1504000
+
+#define PLDO_MIN_UV 1504000
+#define PLDO_MAX_UV 3400000
+
+struct pm8008_regulator_data {
+ const char *name;
+ const char *supply_name;
+ int min_dropout_uv;
+ const struct linear_range *voltage_range;
+};
+
+struct pm8008_regulator {
+ struct device *dev;
+ struct regmap *regmap;
+ struct regulator_desc rdesc;
+ u16 base;
+ int step_rate;
+ int voltage_selector;
+};
+
+static const struct linear_range nldo_ranges[] = {
+ REGULATOR_LINEAR_RANGE(528000, 0, 122, 8000),
+};
+
+static const struct linear_range pldo_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1504000, 0, 237, 8000),
+};
+static_assert(ARRAY_SIZE(pldo_ranges) == 1 && ARRAY_SIZE(nldo_ranges) == 1);
+
+static const struct pm8008_regulator_data reg_data[] = {
+ /* name parent headroom_uv voltage_range */
+ { "ldo1", "vdd_l1_l2", 225000, nldo_ranges, },
+ { "ldo2", "vdd_l1_l2", 225000, nldo_ranges, },
+ { "ldo3", "vdd_l3_l4", 300000, pldo_ranges, },
+ { "ldo4", "vdd_l3_l4", 300000, pldo_ranges, },
+ { "ldo5", "vdd_l5", 200000, pldo_ranges, },
+ { "ldo6", "vdd_l6", 200000, pldo_ranges, },
+ { "ldo7", "vdd_l7", 200000, pldo_ranges, },
+};
+
+static int pm8008_regulator_get_voltage(struct regulator_dev *rdev)
+{
+ struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
+ __le16 mV;
+ int rc, uV;
+
+ regmap_bulk_read(pm8008_reg->regmap,
+ LDO_VSET_LB_REG(pm8008_reg->base), (void *)&mV, 2);
+
+ uV = le16_to_cpu(mV) * 1000;
+ return (uV - pm8008_reg->rdesc.min_uV) / pm8008_reg->rdesc.uV_step;
+}
+
+static inline int pm8008_write_voltage(struct pm8008_regulator *pm8008_reg,
+ int mV)
+{
+ __le16 vset_raw;
+
+ vset_raw = cpu_to_le16(mV);
+
+ return regmap_bulk_write(pm8008_reg->regmap,
+ LDO_VSET_LB_REG(pm8008_reg->base),
+ (const void *)&vset_raw, sizeof(vset_raw));
+}
+
+static int pm8008_regulator_set_voltage_time(struct regulator_dev *rdev,
+ int old_uV, int new_uv)
+{
+ struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
+
+ return DIV_ROUND_UP(abs(new_uv - old_uV), pm8008_reg->step_rate);
+}
+
+static int pm8008_regulator_set_voltage(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
+ int rc, mV;
+
+ rc = regulator_list_voltage_linear_range(rdev, selector);
+ if (rc < 0)
+ return rc;
+
+ /* voltage control register is set with voltage in millivolts */
+ mV = DIV_ROUND_UP(rc, 1000);
+
+ rc = pm8008_write_voltage(pm8008_reg, mV);
+ if (rc < 0)
+ return rc;
+
+ pm8008_reg->voltage_selector = selector;
+
+ return 0;
+}
+
+static const struct regulator_ops pm8008_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_voltage_sel = pm8008_regulator_set_voltage,
+ .get_voltage_sel = pm8008_regulator_get_voltage,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_time = pm8008_regulator_set_voltage_time,
+};
+
+static int pm8008_regulator_probe(struct platform_device *pdev)
+{
+ int rc, i;
+ u32 base;
+ unsigned int reg;
+ const char *name;
+ struct device *dev = &pdev->dev;
+ struct regulator_config reg_config = {};
+ struct regulator_dev *rdev;
+ const struct pm8008_data *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm8008_regulator *pm8008_reg;
+
+ pm8008_reg = devm_kzalloc(dev, sizeof(*pm8008_reg), GFP_KERNEL);
+ if (!pm8008_reg)
+ return -ENOMEM;
+
+ pm8008_reg->regmap = pm8008_get_regmap(chip);
+ if (!pm8008_reg->regmap) {
+ dev_err(dev, "parent regmap is missing\n");
+ return -EINVAL;
+ }
+
+ pm8008_reg->dev = dev;
+
+ rc = of_property_read_string(dev->of_node, "regulator-name", &name);
+ if (rc)
+ return rc;
+
+ /* get the required regulator data */
+ for (i = 0; i < ARRAY_SIZE(reg_data); i++)
+ if (strstr(name, reg_data[i].name))
+ break;
+
+ if (i == ARRAY_SIZE(reg_data)) {
+ dev_err(dev, "Invalid regulator name %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_index(dev->of_node, "reg", 1, &base);
+ if (rc < 0) {
+ dev_err(dev, "%s: failed to get regulator base rc=%d\n", name, rc);
+ return rc;
+ }
+ pm8008_reg->base = base;
+
+ /* get slew rate */
+ rc = regmap_bulk_read(pm8008_reg->regmap,
+ LDO_STEPPER_CTL_REG(pm8008_reg->base), ®, 1);
+ if (rc < 0) {
+ dev_err(dev, "failed to read step rate configuration rc=%d\n", rc);
+ return rc;
+ }
+ reg &= STEP_RATE_MASK;
+ pm8008_reg->step_rate = DEFAULT_VOLTAGE_STEPPER_RATE >> reg;
+
+ pm8008_reg->rdesc.type = REGULATOR_VOLTAGE;
+ pm8008_reg->rdesc.ops = &pm8008_regulator_ops;
+ pm8008_reg->rdesc.name = reg_data[i].name;
+ pm8008_reg->rdesc.supply_name = reg_data[i].supply_name;
+ pm8008_reg->rdesc.of_match = reg_data[i].name;
+ pm8008_reg->rdesc.uV_step = VSET_STEP_UV;
+ pm8008_reg->rdesc.linear_ranges = reg_data[i].voltage_range;
+ pm8008_reg->rdesc.n_linear_ranges = 1;
+
+ if (reg_data[i].voltage_range == nldo_ranges) {
+ pm8008_reg->rdesc.min_uV = NLDO_MIN_UV;
+ pm8008_reg->rdesc.n_voltages
+ = ((NLDO_MAX_UV - NLDO_MIN_UV)
+ / pm8008_reg->rdesc.uV_step) + 1;
+ } else {
+ pm8008_reg->rdesc.min_uV = PLDO_MIN_UV;
+ pm8008_reg->rdesc.n_voltages
+ = ((PLDO_MAX_UV - PLDO_MIN_UV)
+ / pm8008_reg->rdesc.uV_step) + 1;
+ }
+
+ pm8008_reg->rdesc.enable_reg = LDO_ENABLE_REG(pm8008_reg->base);
+ pm8008_reg->rdesc.enable_mask = ENABLE_BIT;
+ pm8008_reg->rdesc.min_dropout_uV = reg_data[i].min_dropout_uv;
+ pm8008_reg->voltage_selector = -ENOTRECOVERABLE;
+
+ reg_config.dev = dev->parent;
+ reg_config.driver_data = pm8008_reg;
+ reg_config.regmap = pm8008_reg->regmap;
+
+ rdev = devm_regulator_register(dev, &pm8008_reg->rdesc, ®_config);
+ if (IS_ERR(rdev)) {
+ rc = PTR_ERR(rdev);
+ dev_err(dev, "%s: failed to register regulator rc=%d\n",
+ reg_data[i].name, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id pm8008_regulator_match_table[] = {
+ { .compatible = "qcom,pm8008-regulator", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pm8008_regulator_match_table);
+
+static struct platform_driver pm8008_regulator_driver = {
+ .driver = {
+ .name = "qcom-pm8008-regulator",
+ .of_match_table = pm8008_regulator_match_table,
+ },
+ .probe = pm8008_regulator_probe,
+};
+
+module_platform_driver(pm8008_regulator_driver);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. PM8008 PMIC Regulator Driver");
+MODULE_LICENSE("GPL");
--
2.7.4
Add the reset-gpio toggling in the pm8008_probe() to bring
pm8008 chip out of reset instead of doing it in DT node using
"output-high" property.
Signed-off-by: Satya Priya <[email protected]>
Reviewed-by: Stephen Boyd <[email protected]>
---
Changes in V14:
- None.
Changes in V13:
- None.
Changes in V12:
- Move reset_gpio acquiring above probe_irq_peripherals in pm8008_probe.
Changes in V11:
- Use local variable for reset_gpios as it is not used outside of probe.
- Use GPIOD_OUT_LOW flag to initialize the gpio and remove below line
as it is not required "gpiod_set_value(chip->reset_gpio, 1);".
drivers/mfd/qcom-pm8008.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c
index c472d7f..5a670b0 100644
--- a/drivers/mfd/qcom-pm8008.c
+++ b/drivers/mfd/qcom-pm8008.c
@@ -4,6 +4,7 @@
*/
#include <linux/bitops.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -221,6 +222,7 @@ static int pm8008_probe(struct i2c_client *client)
{
int rc;
struct pm8008_data *chip;
+ struct gpio_desc *reset_gpio;
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
@@ -233,6 +235,10 @@ static int pm8008_probe(struct i2c_client *client)
i2c_set_clientdata(client, chip);
+ reset_gpio = devm_gpiod_get(chip->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
+
if (of_property_read_bool(chip->dev->of_node, "interrupt-controller")) {
rc = pm8008_probe_irq_peripherals(chip, client->irq);
if (rc)
--
2.7.4
Hi Satya,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on lee-mfd/for-mfd-next]
[also build test WARNING on robh/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/intel-lab-lkp/linux/commits/Satya-Priya/Add-Qualcomm-Technologies-Inc-PM8008-regulator-driver/20220607-195327
base: https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20220608/[email protected]/config)
compiler: gcc-11 (Debian 11.3.0-1) 11.3.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/11e915cb6368e90fdc4186104c56a3619aa63440
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Satya-Priya/Add-Qualcomm-Technologies-Inc-PM8008-regulator-driver/20220607-195327
git checkout 11e915cb6368e90fdc4186104c56a3619aa63440
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/regulator/
If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>
All warnings (new ones prefixed by >>):
drivers/regulator/qcom-pm8008-regulator.c: In function 'pm8008_regulator_get_voltage':
>> drivers/regulator/qcom-pm8008-regulator.c:74:13: warning: unused variable 'rc' [-Wunused-variable]
74 | int rc, uV;
| ^~
vim +/rc +74 drivers/regulator/qcom-pm8008-regulator.c
69
70 static int pm8008_regulator_get_voltage(struct regulator_dev *rdev)
71 {
72 struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
73 __le16 mV;
> 74 int rc, uV;
75
76 regmap_bulk_read(pm8008_reg->regmap,
77 LDO_VSET_LB_REG(pm8008_reg->base), (void *)&mV, 2);
78
79 uV = le16_to_cpu(mV) * 1000;
80 return (uV - pm8008_reg->rdesc.min_uV) / pm8008_reg->rdesc.uV_step;
81 }
82
--
0-DAY CI Kernel Test Service
https://01.org/lkp
Quoting Satya Priya (2022-06-07 04:50:13)
> diff --git a/drivers/regulator/qcom-pm8008-regulator.c b/drivers/regulator/qcom-pm8008-regulator.c
> new file mode 100644
> index 0000000..71cb95c
> --- /dev/null
> +++ b/drivers/regulator/qcom-pm8008-regulator.c
> @@ -0,0 +1,248 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/qcom_pm8008.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/driver.h>
> +
> +#define VSET_STEP_MV 8
> +#define VSET_STEP_UV (VSET_STEP_MV * 1000)
> +
> +#define LDO_ENABLE_REG(base) ((base) + 0x46)
> +#define ENABLE_BIT BIT(7)
> +
> +#define LDO_VSET_LB_REG(base) ((base) + 0x40)
> +
> +#define LDO_STEPPER_CTL_REG(base) ((base) + 0x3b)
> +#define DEFAULT_VOLTAGE_STEPPER_RATE 38400
> +#define STEP_RATE_MASK GENMASK(1, 0)
> +
> +#define NLDO_MIN_UV 528000
> +#define NLDO_MAX_UV 1504000
> +
> +#define PLDO_MIN_UV 1504000
> +#define PLDO_MAX_UV 3400000
> +
> +struct pm8008_regulator_data {
> + const char *name;
> + const char *supply_name;
> + int min_dropout_uv;
> + const struct linear_range *voltage_range;
> +};
> +
> +struct pm8008_regulator {
> + struct device *dev;
Is this used anywhere?
> + struct regmap *regmap;
> + struct regulator_desc rdesc;
> + u16 base;
> + int step_rate;
> + int voltage_selector;
> +};
> +
> +static const struct linear_range nldo_ranges[] = {
> + REGULATOR_LINEAR_RANGE(528000, 0, 122, 8000),
> +};
> +
> +static const struct linear_range pldo_ranges[] = {
> + REGULATOR_LINEAR_RANGE(1504000, 0, 237, 8000),
> +};
> +static_assert(ARRAY_SIZE(pldo_ranges) == 1 && ARRAY_SIZE(nldo_ranges) == 1);
Can this static_assert be placed next to the assignment of
n_linear_ranges in probe?
> +
> +static const struct pm8008_regulator_data reg_data[] = {
> + /* name parent headroom_uv voltage_range */
> + { "ldo1", "vdd_l1_l2", 225000, nldo_ranges, },
> + { "ldo2", "vdd_l1_l2", 225000, nldo_ranges, },
> + { "ldo3", "vdd_l3_l4", 300000, pldo_ranges, },
> + { "ldo4", "vdd_l3_l4", 300000, pldo_ranges, },
> + { "ldo5", "vdd_l5", 200000, pldo_ranges, },
> + { "ldo6", "vdd_l6", 200000, pldo_ranges, },
> + { "ldo7", "vdd_l7", 200000, pldo_ranges, },
> +};
> +
> +static int pm8008_regulator_get_voltage(struct regulator_dev *rdev)
> +{
> + struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
> + __le16 mV;
> + int rc, uV;
> +
> + regmap_bulk_read(pm8008_reg->regmap,
> + LDO_VSET_LB_REG(pm8008_reg->base), (void *)&mV, 2);
> +
> + uV = le16_to_cpu(mV) * 1000;
> + return (uV - pm8008_reg->rdesc.min_uV) / pm8008_reg->rdesc.uV_step;
> +}
> +
> +static inline int pm8008_write_voltage(struct pm8008_regulator *pm8008_reg,
> + int mV)
> +{
> + __le16 vset_raw;
> +
> + vset_raw = cpu_to_le16(mV);
> +
> + return regmap_bulk_write(pm8008_reg->regmap,
> + LDO_VSET_LB_REG(pm8008_reg->base),
> + (const void *)&vset_raw, sizeof(vset_raw));
> +}
> +
> +static int pm8008_regulator_set_voltage_time(struct regulator_dev *rdev,
> + int old_uV, int new_uv)
> +{
> + struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
> +
> + return DIV_ROUND_UP(abs(new_uv - old_uV), pm8008_reg->step_rate);
> +}
> +
> +static int pm8008_regulator_set_voltage(struct regulator_dev *rdev,
> + unsigned int selector)
> +{
> + struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
> + int rc, mV;
> +
> + rc = regulator_list_voltage_linear_range(rdev, selector);
> + if (rc < 0)
> + return rc;
> +
> + /* voltage control register is set with voltage in millivolts */
> + mV = DIV_ROUND_UP(rc, 1000);
> +
> + rc = pm8008_write_voltage(pm8008_reg, mV);
> + if (rc < 0)
> + return rc;
> +
> + pm8008_reg->voltage_selector = selector;
Is this used anywhere? I think not so remove it and the struct member?
> +
> + return 0;
> +}
> +
> +static const struct regulator_ops pm8008_regulator_ops = {
> + .enable = regulator_enable_regmap,
> + .disable = regulator_disable_regmap,
> + .is_enabled = regulator_is_enabled_regmap,
> + .set_voltage_sel = pm8008_regulator_set_voltage,
> + .get_voltage_sel = pm8008_regulator_get_voltage,
> + .list_voltage = regulator_list_voltage_linear,
> + .set_voltage_time = pm8008_regulator_set_voltage_time,
> +};
> +
> +static int pm8008_regulator_probe(struct platform_device *pdev)
> +{
> + int rc, i;
> + u32 base;
> + unsigned int reg;
> + const char *name;
> + struct device *dev = &pdev->dev;
> + struct regulator_config reg_config = {};
> + struct regulator_dev *rdev;
> + const struct pm8008_data *chip = dev_get_drvdata(pdev->dev.parent);
> + struct pm8008_regulator *pm8008_reg;
> +
> + pm8008_reg = devm_kzalloc(dev, sizeof(*pm8008_reg), GFP_KERNEL);
> + if (!pm8008_reg)
> + return -ENOMEM;
> +
> + pm8008_reg->regmap = pm8008_get_regmap(chip);
> + if (!pm8008_reg->regmap) {
> + dev_err(dev, "parent regmap is missing\n");
> + return -EINVAL;
> + }
> +
> + pm8008_reg->dev = dev;
> +
> + rc = of_property_read_string(dev->of_node, "regulator-name", &name);
> + if (rc)
> + return rc;
> +
> + /* get the required regulator data */
> + for (i = 0; i < ARRAY_SIZE(reg_data); i++)
> + if (strstr(name, reg_data[i].name))
> + break;
> +
> + if (i == ARRAY_SIZE(reg_data)) {
> + dev_err(dev, "Invalid regulator name %s\n", name);
> + return -EINVAL;
> + }
> +
> + rc = of_property_read_u32_index(dev->of_node, "reg", 1, &base);
> + if (rc < 0) {
> + dev_err(dev, "%s: failed to get regulator base rc=%d\n", name, rc);
> + return rc;
> + }
> + pm8008_reg->base = base;
> +
> + /* get slew rate */
> + rc = regmap_bulk_read(pm8008_reg->regmap,
> + LDO_STEPPER_CTL_REG(pm8008_reg->base), ®, 1);
> + if (rc < 0) {
> + dev_err(dev, "failed to read step rate configuration rc=%d\n", rc);
> + return rc;
> + }
> + reg &= STEP_RATE_MASK;
> + pm8008_reg->step_rate = DEFAULT_VOLTAGE_STEPPER_RATE >> reg;
> +
> + pm8008_reg->rdesc.type = REGULATOR_VOLTAGE;
> + pm8008_reg->rdesc.ops = &pm8008_regulator_ops;
> + pm8008_reg->rdesc.name = reg_data[i].name;
> + pm8008_reg->rdesc.supply_name = reg_data[i].supply_name;
> + pm8008_reg->rdesc.of_match = reg_data[i].name;
> + pm8008_reg->rdesc.uV_step = VSET_STEP_UV;
> + pm8008_reg->rdesc.linear_ranges = reg_data[i].voltage_range;
> + pm8008_reg->rdesc.n_linear_ranges = 1;
> +
Ideally the static assert is right here.
Hi Stephen,
On 6/9/2022 1:12 AM, Stephen Boyd wrote:
> Quoting Satya Priya (2022-06-07 04:50:13)
>> diff --git a/drivers/regulator/qcom-pm8008-regulator.c b/drivers/regulator/qcom-pm8008-regulator.c
>> new file mode 100644
>> index 0000000..71cb95c
>> --- /dev/null
>> +++ b/drivers/regulator/qcom-pm8008-regulator.c
>> @@ -0,0 +1,248 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mfd/qcom_pm8008.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regmap.h>
>> +#include <linux/regulator/driver.h>
>> +
>> +#define VSET_STEP_MV 8
>> +#define VSET_STEP_UV (VSET_STEP_MV * 1000)
>> +
>> +#define LDO_ENABLE_REG(base) ((base) + 0x46)
>> +#define ENABLE_BIT BIT(7)
>> +
>> +#define LDO_VSET_LB_REG(base) ((base) + 0x40)
>> +
>> +#define LDO_STEPPER_CTL_REG(base) ((base) + 0x3b)
>> +#define DEFAULT_VOLTAGE_STEPPER_RATE 38400
>> +#define STEP_RATE_MASK GENMASK(1, 0)
>> +
>> +#define NLDO_MIN_UV 528000
>> +#define NLDO_MAX_UV 1504000
>> +
>> +#define PLDO_MIN_UV 1504000
>> +#define PLDO_MAX_UV 3400000
>> +
>> +struct pm8008_regulator_data {
>> + const char *name;
>> + const char *supply_name;
>> + int min_dropout_uv;
>> + const struct linear_range *voltage_range;
>> +};
>> +
>> +struct pm8008_regulator {
>> + struct device *dev;
> Is this used anywhere?
Will remove it.
>> + struct regmap *regmap;
>> + struct regulator_desc rdesc;
>> + u16 base;
>> + int step_rate;
>> + int voltage_selector;
>> +};
>> +
>> +static const struct linear_range nldo_ranges[] = {
>> + REGULATOR_LINEAR_RANGE(528000, 0, 122, 8000),
>> +};
>> +
>> +static const struct linear_range pldo_ranges[] = {
>> + REGULATOR_LINEAR_RANGE(1504000, 0, 237, 8000),
>> +};
>> +static_assert(ARRAY_SIZE(pldo_ranges) == 1 && ARRAY_SIZE(nldo_ranges) == 1);
> Can this static_assert be placed next to the assignment of
> n_linear_ranges in probe?
>
>> +
>> +static const struct pm8008_regulator_data reg_data[] = {
>> + /* name parent headroom_uv voltage_range */
>> + { "ldo1", "vdd_l1_l2", 225000, nldo_ranges, },
>> + { "ldo2", "vdd_l1_l2", 225000, nldo_ranges, },
>> + { "ldo3", "vdd_l3_l4", 300000, pldo_ranges, },
>> + { "ldo4", "vdd_l3_l4", 300000, pldo_ranges, },
>> + { "ldo5", "vdd_l5", 200000, pldo_ranges, },
>> + { "ldo6", "vdd_l6", 200000, pldo_ranges, },
>> + { "ldo7", "vdd_l7", 200000, pldo_ranges, },
>> +};
>> +
>> +static int pm8008_regulator_get_voltage(struct regulator_dev *rdev)
>> +{
>> + struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
>> + __le16 mV;
>> + int rc, uV;
>> +
>> + regmap_bulk_read(pm8008_reg->regmap,
>> + LDO_VSET_LB_REG(pm8008_reg->base), (void *)&mV, 2);
>> +
>> + uV = le16_to_cpu(mV) * 1000;
>> + return (uV - pm8008_reg->rdesc.min_uV) / pm8008_reg->rdesc.uV_step;
>> +}
>> +
>> +static inline int pm8008_write_voltage(struct pm8008_regulator *pm8008_reg,
>> + int mV)
>> +{
>> + __le16 vset_raw;
>> +
>> + vset_raw = cpu_to_le16(mV);
>> +
>> + return regmap_bulk_write(pm8008_reg->regmap,
>> + LDO_VSET_LB_REG(pm8008_reg->base),
>> + (const void *)&vset_raw, sizeof(vset_raw));
>> +}
>> +
>> +static int pm8008_regulator_set_voltage_time(struct regulator_dev *rdev,
>> + int old_uV, int new_uv)
>> +{
>> + struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
>> +
>> + return DIV_ROUND_UP(abs(new_uv - old_uV), pm8008_reg->step_rate);
>> +}
>> +
>> +static int pm8008_regulator_set_voltage(struct regulator_dev *rdev,
>> + unsigned int selector)
>> +{
>> + struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
>> + int rc, mV;
>> +
>> + rc = regulator_list_voltage_linear_range(rdev, selector);
>> + if (rc < 0)
>> + return rc;
>> +
>> + /* voltage control register is set with voltage in millivolts */
>> + mV = DIV_ROUND_UP(rc, 1000);
>> +
>> + rc = pm8008_write_voltage(pm8008_reg, mV);
>> + if (rc < 0)
>> + return rc;
>> +
>> + pm8008_reg->voltage_selector = selector;
> Is this used anywhere? I think not so remove it and the struct member?
Okay.
>> +
>> + return 0;
>> +}
>> +
>> +static const struct regulator_ops pm8008_regulator_ops = {
>> + .enable = regulator_enable_regmap,
>> + .disable = regulator_disable_regmap,
>> + .is_enabled = regulator_is_enabled_regmap,
>> + .set_voltage_sel = pm8008_regulator_set_voltage,
>> + .get_voltage_sel = pm8008_regulator_get_voltage,
>> + .list_voltage = regulator_list_voltage_linear,
>> + .set_voltage_time = pm8008_regulator_set_voltage_time,
>> +};
>> +
>> +static int pm8008_regulator_probe(struct platform_device *pdev)
>> +{
>> + int rc, i;
>> + u32 base;
>> + unsigned int reg;
>> + const char *name;
>> + struct device *dev = &pdev->dev;
>> + struct regulator_config reg_config = {};
>> + struct regulator_dev *rdev;
>> + const struct pm8008_data *chip = dev_get_drvdata(pdev->dev.parent);
>> + struct pm8008_regulator *pm8008_reg;
>> +
>> + pm8008_reg = devm_kzalloc(dev, sizeof(*pm8008_reg), GFP_KERNEL);
>> + if (!pm8008_reg)
>> + return -ENOMEM;
>> +
>> + pm8008_reg->regmap = pm8008_get_regmap(chip);
>> + if (!pm8008_reg->regmap) {
>> + dev_err(dev, "parent regmap is missing\n");
>> + return -EINVAL;
>> + }
>> +
>> + pm8008_reg->dev = dev;
>> +
>> + rc = of_property_read_string(dev->of_node, "regulator-name", &name);
>> + if (rc)
>> + return rc;
>> +
>> + /* get the required regulator data */
>> + for (i = 0; i < ARRAY_SIZE(reg_data); i++)
>> + if (strstr(name, reg_data[i].name))
>> + break;
>> +
>> + if (i == ARRAY_SIZE(reg_data)) {
>> + dev_err(dev, "Invalid regulator name %s\n", name);
>> + return -EINVAL;
>> + }
>> +
>> + rc = of_property_read_u32_index(dev->of_node, "reg", 1, &base);
>> + if (rc < 0) {
>> + dev_err(dev, "%s: failed to get regulator base rc=%d\n", name, rc);
>> + return rc;
>> + }
>> + pm8008_reg->base = base;
>> +
>> + /* get slew rate */
>> + rc = regmap_bulk_read(pm8008_reg->regmap,
>> + LDO_STEPPER_CTL_REG(pm8008_reg->base), ®, 1);
>> + if (rc < 0) {
>> + dev_err(dev, "failed to read step rate configuration rc=%d\n", rc);
>> + return rc;
>> + }
>> + reg &= STEP_RATE_MASK;
>> + pm8008_reg->step_rate = DEFAULT_VOLTAGE_STEPPER_RATE >> reg;
>> +
>> + pm8008_reg->rdesc.type = REGULATOR_VOLTAGE;
>> + pm8008_reg->rdesc.ops = &pm8008_regulator_ops;
>> + pm8008_reg->rdesc.name = reg_data[i].name;
>> + pm8008_reg->rdesc.supply_name = reg_data[i].supply_name;
>> + pm8008_reg->rdesc.of_match = reg_data[i].name;
>> + pm8008_reg->rdesc.uV_step = VSET_STEP_UV;
>> + pm8008_reg->rdesc.linear_ranges = reg_data[i].voltage_range;
>> + pm8008_reg->rdesc.n_linear_ranges = 1;
>> +
> Ideally the static assert is right here.
If I place it here below error is seen
error: ISO C90 forbids mixing declarations and code
[-Werror,-Wdeclaration-after-statement]
It could be placed at the beginning of this function near the
declarations though. I see that many of the drivers add it below the
array itself.
Quoting Satya Priya Kakitapalli (Temp) (2022-06-08 22:20:27)
>
> If I place it here below error is seen
>
> error: ISO C90 forbids mixing declarations and code
> [-Werror,-Wdeclaration-after-statement]
>
> It could be placed at the beginning of this function near the
> declarations though. I see that many of the drivers add it below the
> array itself.
>
Ah, use BUILD_BUG_ON() then.