Skip to content

Commit 3ce6f4f

Browse files
fschrempfbroonie
authored andcommitted
regulator: pca9450: Fix control register for LDO5
For LDO5 we need to be able to check the status of the SD_VSEL input in order to know which control register is used. Read the status of the SD_VSEL signal via GPIO and use the correct register accordingly. To use this, the LDO5 node in the devicetree needs the sd-vsel-gpios property to reference the GPIO that is used to read back the SD_VSEL status internally. Please note that the SION bit in the IOMUX must be set if the signal is muxed as VSELECT and controlled by the USDHC controller. Signed-off-by: Frieder Schrempf <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent c73be62 commit 3ce6f4f

File tree

1 file changed

+86
-3
lines changed

1 file changed

+86
-3
lines changed

drivers/regulator/pca9450-regulator.c

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <linux/err.h>
8+
#include <linux/gpio/consumer.h>
89
#include <linux/i2c.h>
910
#include <linux/interrupt.h>
1011
#include <linux/kernel.h>
@@ -31,6 +32,7 @@ struct pca9450_regulator_desc {
3132
struct pca9450 {
3233
struct device *dev;
3334
struct regmap *regmap;
35+
struct gpio_desc *sd_vsel_gpio;
3436
enum pca9450_chip_type type;
3537
unsigned int rcnt;
3638
int irq;
@@ -96,6 +98,58 @@ static const struct regulator_ops pca9450_ldo_regulator_ops = {
9698
.get_voltage_sel = regulator_get_voltage_sel_regmap,
9799
};
98100

101+
static unsigned int pca9450_ldo5_get_reg_voltage_sel(struct regulator_dev *rdev)
102+
{
103+
struct pca9450 *pca9450 = rdev_get_drvdata(rdev);
104+
105+
if (pca9450->sd_vsel_gpio && !gpiod_get_value(pca9450->sd_vsel_gpio))
106+
return PCA9450_REG_LDO5CTRL_L;
107+
108+
return rdev->desc->vsel_reg;
109+
}
110+
111+
static int pca9450_ldo5_get_voltage_sel_regmap(struct regulator_dev *rdev)
112+
{
113+
unsigned int val;
114+
int ret;
115+
116+
ret = regmap_read(rdev->regmap, pca9450_ldo5_get_reg_voltage_sel(rdev), &val);
117+
if (ret != 0)
118+
return ret;
119+
120+
val &= rdev->desc->vsel_mask;
121+
val >>= ffs(rdev->desc->vsel_mask) - 1;
122+
123+
return val;
124+
}
125+
126+
static int pca9450_ldo5_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned int sel)
127+
{
128+
int ret;
129+
130+
sel <<= ffs(rdev->desc->vsel_mask) - 1;
131+
132+
ret = regmap_update_bits(rdev->regmap, pca9450_ldo5_get_reg_voltage_sel(rdev),
133+
rdev->desc->vsel_mask, sel);
134+
if (ret)
135+
return ret;
136+
137+
if (rdev->desc->apply_bit)
138+
ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,
139+
rdev->desc->apply_bit,
140+
rdev->desc->apply_bit);
141+
return ret;
142+
}
143+
144+
static const struct regulator_ops pca9450_ldo5_regulator_ops = {
145+
.enable = regulator_enable_regmap,
146+
.disable = regulator_disable_regmap,
147+
.is_enabled = regulator_is_enabled_regmap,
148+
.list_voltage = regulator_list_voltage_linear_range,
149+
.set_voltage_sel = pca9450_ldo5_set_voltage_sel_regmap,
150+
.get_voltage_sel = pca9450_ldo5_get_voltage_sel_regmap,
151+
};
152+
99153
/*
100154
* BUCK1/2/3
101155
* 0.60 to 2.1875V (12.5mV step)
@@ -451,7 +505,7 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
451505
.of_match = of_match_ptr("LDO5"),
452506
.regulators_node = of_match_ptr("regulators"),
453507
.id = PCA9450_LDO5,
454-
.ops = &pca9450_ldo_regulator_ops,
508+
.ops = &pca9450_ldo5_regulator_ops,
455509
.type = REGULATOR_VOLTAGE,
456510
.n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
457511
.linear_ranges = pca9450_ldo5_volts,
@@ -665,7 +719,7 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
665719
.of_match = of_match_ptr("LDO5"),
666720
.regulators_node = of_match_ptr("regulators"),
667721
.id = PCA9450_LDO5,
668-
.ops = &pca9450_ldo_regulator_ops,
722+
.ops = &pca9450_ldo5_regulator_ops,
669723
.type = REGULATOR_VOLTAGE,
670724
.n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
671725
.linear_ranges = pca9450_ldo5_volts,
@@ -855,7 +909,7 @@ static const struct pca9450_regulator_desc pca9451a_regulators[] = {
855909
.of_match = of_match_ptr("LDO5"),
856910
.regulators_node = of_match_ptr("regulators"),
857911
.id = PCA9450_LDO5,
858-
.ops = &pca9450_ldo_regulator_ops,
912+
.ops = &pca9450_ldo5_regulator_ops,
859913
.type = REGULATOR_VOLTAGE,
860914
.n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
861915
.linear_ranges = pca9450_ldo5_volts,
@@ -913,6 +967,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
913967
of_device_get_match_data(&i2c->dev);
914968
const struct pca9450_regulator_desc *regulator_desc;
915969
struct regulator_config config = { };
970+
struct regulator_dev *ldo5;
916971
struct pca9450 *pca9450;
917972
unsigned int device_id, i;
918973
unsigned int reset_ctrl;
@@ -978,11 +1033,15 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
9781033

9791034
config.regmap = pca9450->regmap;
9801035
config.dev = pca9450->dev;
1036+
config.driver_data = pca9450;
9811037

9821038
rdev = devm_regulator_register(pca9450->dev, desc, &config);
9831039
if (IS_ERR(rdev))
9841040
return dev_err_probe(pca9450->dev, PTR_ERR(rdev),
9851041
"Failed to register regulator(%s)\n", desc->name);
1042+
1043+
if (!strcmp(desc->name, "ldo5"))
1044+
ldo5 = rdev;
9861045
}
9871046

9881047
if (pca9450->irq) {
@@ -1029,6 +1088,30 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
10291088
"Failed to enable I2C level translator\n");
10301089
}
10311090

1091+
/*
1092+
* For LDO5 we need to be able to check the status of the SD_VSEL input in
1093+
* order to know which control register is used. Most boards connect SD_VSEL
1094+
* to the VSELECT signal, so we can use the GPIO that is internally routed
1095+
* to this signal (if SION bit is set in IOMUX).
1096+
*/
1097+
pca9450->sd_vsel_gpio = gpiod_get_optional(&ldo5->dev, "sd-vsel", GPIOD_IN);
1098+
if (IS_ERR(pca9450->sd_vsel_gpio)) {
1099+
dev_err(&i2c->dev, "Failed to get SD_VSEL GPIO\n");
1100+
return ret;
1101+
}
1102+
1103+
/*
1104+
* For LDO5 we need to be able to check the status of the SD_VSEL input in
1105+
* order to know which control register is used. Most boards connect SD_VSEL
1106+
* to the VSELECT signal, so we can use the GPIO that is internally routed
1107+
* to this signal (if SION bit is set in IOMUX).
1108+
*/
1109+
pca9450->sd_vsel_gpio = gpiod_get_optional(&ldo5->dev, "sd-vsel", GPIOD_IN);
1110+
if (IS_ERR(pca9450->sd_vsel_gpio)) {
1111+
dev_err(&i2c->dev, "Failed to get SD_VSEL GPIO\n");
1112+
return ret;
1113+
}
1114+
10321115
dev_info(&i2c->dev, "%s probed.\n",
10331116
type == PCA9450_TYPE_PCA9450A ? "pca9450a" :
10341117
(type == PCA9450_TYPE_PCA9451A ? "pca9451a" : "pca9450bc"));

0 commit comments

Comments
 (0)