summaryrefslogtreecommitdiff
path: root/drivers/regulator/pca9450-regulator.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-03-19 16:08:51 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-03-19 16:08:51 +0100
commit1c6d58b8a03b656bfe4c6930a7d6052782c0bc89 (patch)
tree70991c25d188f5b1cd6f5d84f9f352ec2fa2effa /drivers/regulator/pca9450-regulator.c
parent744943ac89cd209aec9414dd751c53528d5757e7 (diff)
parent4aea1dc4cad17cd146072e13b1fd404f32b8b3ef (diff)
Merge v6.18.19linux-rolling-lts
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/regulator/pca9450-regulator.c')
-rw-r--r--drivers/regulator/pca9450-regulator.c172
1 files changed, 149 insertions, 23 deletions
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
index 91b96dbab328..f991dc9365f1 100644
--- a/drivers/regulator/pca9450-regulator.c
+++ b/drivers/regulator/pca9450-regulator.c
@@ -1117,6 +1117,143 @@ static int pca9450_i2c_restart_handler(struct sys_off_data *data)
return 0;
}
+static int pca9450_of_init(struct pca9450 *pca9450)
+{
+ struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev);
+ int ret;
+ unsigned int val;
+ unsigned int reset_ctrl;
+ unsigned int rstb_deb_ctrl;
+ unsigned int t_on_deb, t_off_deb;
+ unsigned int t_on_step, t_off_step;
+ unsigned int t_restart;
+
+ if (of_property_read_bool(i2c->dev.of_node, "nxp,wdog_b-warm-reset"))
+ reset_ctrl = WDOG_B_CFG_WARM;
+ else
+ reset_ctrl = WDOG_B_CFG_COLD_LDO12;
+
+ /* Set reset behavior on assertion of WDOG_B signal */
+ ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
+ WDOG_B_CFG_MASK, reset_ctrl);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Failed to set WDOG_B reset behavior\n");
+
+ ret = of_property_read_u32(i2c->dev.of_node, "npx,pmic-rst-b-debounce-ms", &val);
+ if (ret == -EINVAL)
+ rstb_deb_ctrl = T_PMIC_RST_DEB_50MS;
+ else if (ret)
+ return ret;
+ else {
+ switch (val) {
+ case 10: rstb_deb_ctrl = T_PMIC_RST_DEB_10MS; break;
+ case 50: rstb_deb_ctrl = T_PMIC_RST_DEB_50MS; break;
+ case 100: rstb_deb_ctrl = T_PMIC_RST_DEB_100MS; break;
+ case 500: rstb_deb_ctrl = T_PMIC_RST_DEB_500MS; break;
+ case 1000: rstb_deb_ctrl = T_PMIC_RST_DEB_1S; break;
+ case 2000: rstb_deb_ctrl = T_PMIC_RST_DEB_2S; break;
+ case 4000: rstb_deb_ctrl = T_PMIC_RST_DEB_4S; break;
+ case 8000: rstb_deb_ctrl = T_PMIC_RST_DEB_8S; break;
+ default: return -EINVAL;
+ }
+ }
+ ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
+ T_PMIC_RST_DEB_MASK, rstb_deb_ctrl);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Failed to set PMIC_RST_B debounce time\n");
+
+ ret = of_property_read_u32(i2c->dev.of_node, "nxp,pmic-on-req-on-debounce-us", &val);
+ if (ret == -EINVAL)
+ t_on_deb = T_ON_DEB_20MS;
+ else if (ret)
+ return ret;
+ else {
+ switch (val) {
+ case 120: t_on_deb = T_ON_DEB_120US; break;
+ case 20000: t_on_deb = T_ON_DEB_20MS; break;
+ case 100000: t_on_deb = T_ON_DEB_100MS; break;
+ case 750000: t_on_deb = T_ON_DEB_750MS; break;
+ default: return -EINVAL;
+ }
+ }
+
+ ret = of_property_read_u32(i2c->dev.of_node, "nxp,pmic-on-req-off-debounce-us", &val);
+ if (ret == -EINVAL)
+ t_off_deb = T_OFF_DEB_120US;
+ else if (ret)
+ return ret;
+ else {
+ switch (val) {
+ case 120: t_off_deb = T_OFF_DEB_120US; break;
+ case 2000: t_off_deb = T_OFF_DEB_2MS; break;
+ default: return -EINVAL;
+ }
+ }
+
+ ret = of_property_read_u32(i2c->dev.of_node, "nxp,power-on-step-ms", &val);
+ if (ret == -EINVAL)
+ t_on_step = T_ON_STEP_2MS;
+ else if (ret)
+ return ret;
+ else {
+ switch (val) {
+ case 1: t_on_step = T_ON_STEP_1MS; break;
+ case 2: t_on_step = T_ON_STEP_2MS; break;
+ case 4: t_on_step = T_ON_STEP_4MS; break;
+ case 8: t_on_step = T_ON_STEP_8MS; break;
+ default: return -EINVAL;
+ }
+ }
+
+ ret = of_property_read_u32(i2c->dev.of_node, "nxp,power-down-step-ms", &val);
+ if (ret == -EINVAL)
+ t_off_step = T_OFF_STEP_8MS;
+ else if (ret)
+ return ret;
+ else {
+ switch (val) {
+ case 2: t_off_step = T_OFF_STEP_2MS; break;
+ case 4: t_off_step = T_OFF_STEP_4MS; break;
+ case 8: t_off_step = T_OFF_STEP_8MS; break;
+ case 16: t_off_step = T_OFF_STEP_16MS; break;
+ default: return -EINVAL;
+ }
+ }
+
+ ret = of_property_read_u32(i2c->dev.of_node, "nxp,restart-ms", &val);
+ if (ret == -EINVAL)
+ t_restart = T_RESTART_250MS;
+ else if (ret)
+ return ret;
+ else {
+ switch (val) {
+ case 250: t_restart = T_RESTART_250MS; break;
+ case 500: t_restart = T_RESTART_500MS; break;
+ default: return -EINVAL;
+ }
+ }
+
+ ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_PWRCTRL,
+ T_ON_DEB_MASK | T_OFF_DEB_MASK | T_ON_STEP_MASK |
+ T_OFF_STEP_MASK | T_RESTART_MASK,
+ t_on_deb | t_off_deb | t_on_step |
+ t_off_step | t_restart);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret,
+ "Failed to set PWR_CTRL debounce configuration\n");
+
+ if (of_property_read_bool(i2c->dev.of_node, "nxp,i2c-lt-enable")) {
+ /* Enable I2C Level Translator */
+ ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_CONFIG2,
+ I2C_LT_MASK, I2C_LT_ON_STANDBY_RUN);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret,
+ "Failed to enable I2C level translator\n");
+ }
+
+ return 0;
+}
+
static int pca9450_i2c_probe(struct i2c_client *i2c)
{
enum pca9450_chip_type type = (unsigned int)(uintptr_t)
@@ -1126,7 +1263,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
struct regulator_dev *ldo5;
struct pca9450 *pca9450;
unsigned int device_id, i;
- unsigned int reset_ctrl;
+ const char *type_name;
int ret;
pca9450 = devm_kzalloc(&i2c->dev, sizeof(struct pca9450), GFP_KERNEL);
@@ -1137,15 +1274,22 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
case PCA9450_TYPE_PCA9450A:
regulator_desc = pca9450a_regulators;
pca9450->rcnt = ARRAY_SIZE(pca9450a_regulators);
+ type_name = "pca9450a";
break;
case PCA9450_TYPE_PCA9450BC:
regulator_desc = pca9450bc_regulators;
pca9450->rcnt = ARRAY_SIZE(pca9450bc_regulators);
+ type_name = "pca9450bc";
break;
case PCA9450_TYPE_PCA9451A:
+ regulator_desc = pca9451a_regulators;
+ pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators);
+ type_name = "pca9451a";
+ break;
case PCA9450_TYPE_PCA9452:
regulator_desc = pca9451a_regulators;
pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators);
+ type_name = "pca9452";
break;
default:
dev_err(&i2c->dev, "Unknown device type");
@@ -1203,7 +1347,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
if (pca9450->irq) {
ret = devm_request_threaded_irq(pca9450->dev, pca9450->irq, NULL,
pca9450_irq_handler,
- (IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
+ (IRQF_TRIGGER_LOW | IRQF_ONESHOT),
"pca9450-irq", pca9450);
if (ret != 0)
return dev_err_probe(pca9450->dev, ret, "Failed to request IRQ: %d\n",
@@ -1224,25 +1368,9 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
if (ret)
return dev_err_probe(&i2c->dev, ret, "Failed to clear PRESET_EN bit\n");
- if (of_property_read_bool(i2c->dev.of_node, "nxp,wdog_b-warm-reset"))
- reset_ctrl = WDOG_B_CFG_WARM;
- else
- reset_ctrl = WDOG_B_CFG_COLD_LDO12;
-
- /* Set reset behavior on assertion of WDOG_B signal */
- ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
- WDOG_B_CFG_MASK, reset_ctrl);
+ ret = pca9450_of_init(pca9450);
if (ret)
- return dev_err_probe(&i2c->dev, ret, "Failed to set WDOG_B reset behavior\n");
-
- if (of_property_read_bool(i2c->dev.of_node, "nxp,i2c-lt-enable")) {
- /* Enable I2C Level Translator */
- ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_CONFIG2,
- I2C_LT_MASK, I2C_LT_ON_STANDBY_RUN);
- if (ret)
- return dev_err_probe(&i2c->dev, ret,
- "Failed to enable I2C level translator\n");
- }
+ return dev_err_probe(&i2c->dev, ret, "Unable to parse OF data\n");
/*
* For LDO5 we need to be able to check the status of the SD_VSEL input in
@@ -1263,9 +1391,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
pca9450_i2c_restart_handler, pca9450))
dev_warn(&i2c->dev, "Failed to register restart handler\n");
- dev_info(&i2c->dev, "%s probed.\n",
- type == PCA9450_TYPE_PCA9450A ? "pca9450a" :
- (type == PCA9450_TYPE_PCA9451A ? "pca9451a" : "pca9450bc"));
+ dev_info(&i2c->dev, "%s probed.\n", type_name);
return 0;
}