* [PATCH v2 1/5] mfd: axp20x: add AXP221 PMIC support
2014-05-26 14:58 [PATCH v2 0/5] mfd: axp20x: add AXP221 PMIC support Boris BREZILLON
@ 2014-05-26 14:58 ` Boris BREZILLON
2014-05-26 15:29 ` Boris BREZILLON
2014-05-26 14:58 ` [PATCH v2 2/5] regulator: axp20x: prepare support for multiple AXP chip families Boris BREZILLON
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Boris BREZILLON @ 2014-05-26 14:58 UTC (permalink / raw)
To: linux-arm-kernel
Add support for the AXP221 PMIC device to the existing AXP20x driver.
The AXP221 defines a new set of registers, power supplies and regulators,
but most of the API is similar to the AXP20x ones.
The AXP20x irq chip definition is reused, though some interrupts are not
available in the AXP221.
Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
---
drivers/mfd/axp20x.c | 58 +++++++++++++++++++++++++++++++++++++++++++---
include/linux/mfd/axp20x.h | 56 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+), 3 deletions(-)
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index dee6539..ca9fe2e 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -33,6 +33,11 @@ static const struct regmap_range axp20x_writeable_ranges[] = {
regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
};
+static const struct regmap_range axp22x_writeable_ranges[] = {
+ regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+ regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
+};
+
static const struct regmap_range axp20x_volatile_ranges[] = {
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
};
@@ -42,6 +47,11 @@ static const struct regmap_access_table axp20x_writeable_table = {
.n_yes_ranges = ARRAY_SIZE(axp20x_writeable_ranges),
};
+static const struct regmap_access_table axp22x_writeable_table = {
+ .yes_ranges = axp22x_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp22x_writeable_ranges),
+};
+
static const struct regmap_access_table axp20x_volatile_table = {
.yes_ranges = axp20x_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
@@ -70,6 +80,15 @@ static const struct regmap_config axp20x_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
+static const struct regmap_config axp22x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .wr_table = &axp22x_writeable_table,
+ .volatile_table = &axp20x_volatile_table,
+ .max_register = AXP22X_BATLOW_THRES1,
+ .cache_type = REGCACHE_RBTREE,
+};
+
#define AXP20X_IRQ(_irq, _off, _mask) \
[AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
@@ -116,6 +135,7 @@ static const struct regmap_irq axp20x_regmap_irqs[] = {
static const struct of_device_id axp20x_of_match[] = {
{ .compatible = "x-powers,axp202", .data = (void *) AXP202_ID },
{ .compatible = "x-powers,axp209", .data = (void *) AXP209_ID },
+ { .compatible = "x-powers,axp221", .data = (void *) AXP221_ID },
{ },
};
MODULE_DEVICE_TABLE(of, axp20x_of_match);
@@ -149,6 +169,21 @@ static const char * const axp20x_supplies[] = {
"ldo5in",
};
+static const char *axp22x_supplies[] = {
+ "vbus",
+ "acin",
+ "vin1",
+ "vin2",
+ "vin3",
+ "vin4",
+ "vin5",
+ "aldoin",
+ "dldoin",
+ "eldoin",
+ "ldoioin",
+ "rtcldoin",
+};
+
static struct mfd_cell axp20x_cells[] = {
{
.name = "axp20x-pek",
@@ -161,6 +196,14 @@ static struct mfd_cell axp20x_cells[] = {
},
};
+static struct mfd_cell axp22x_cells[] = {
+ {
+ .name = "axp20x-regulator",
+ .parent_supplies = axp22x_supplies,
+ .num_parent_supplies = ARRAY_SIZE(axp22x_supplies),
+ },
+};
+
static struct axp20x_dev *axp20x_pm_power_off;
static void axp20x_power_off(void)
{
@@ -190,7 +233,12 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
axp20x->dev = &i2c->dev;
dev_set_drvdata(axp20x->dev, axp20x);
- axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
+ if (axp20x->variant == AXP221_ID)
+ axp20x->regmap = devm_regmap_init_i2c(i2c,
+ &axp22x_regmap_config);
+ else
+ axp20x->regmap = devm_regmap_init_i2c(i2c,
+ &axp20x_regmap_config);
if (IS_ERR(axp20x->regmap)) {
ret = PTR_ERR(axp20x->regmap);
dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
@@ -206,8 +254,12 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
return ret;
}
- ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
- ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
+ if (axp20x->variant == AXP221_ID)
+ ret = mfd_add_devices(axp20x->dev, -1, axp22x_cells,
+ ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
+ else
+ ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
+ ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
if (ret) {
dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index d0e31a2..8a8ce02 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -14,6 +14,7 @@
enum {
AXP202_ID = 0,
AXP209_ID,
+ AXP221_ID,
};
#define AXP20X_DATACACHE(m) (0x04 + (m))
@@ -43,6 +44,28 @@ enum {
#define AXP20X_V_LTF_DISCHRG 0x3c
#define AXP20X_V_HTF_DISCHRG 0x3d
+#define AXP22X_PWR_OUT_CTRL1 0x10
+#define AXP22X_PWR_OUT_CTRL2 0x12
+#define AXP22X_PWR_OUT_CTRL3 0x13
+#define AXP22X_DLDO1_V_OUT 0x15
+#define AXP22X_DLDO2_V_OUT 0x16
+#define AXP22X_DLDO3_V_OUT 0x17
+#define AXP22X_DLDO4_V_OUT 0x18
+#define AXP22X_ELDO1_V_OUT 0x19
+#define AXP22X_ELDO2_V_OUT 0x1a
+#define AXP22X_ELDO3_V_OUT 0x1b
+#define AXP22X_DC5LDO_V_OUT 0x1c
+#define AXP22X_DCDC1_V_OUT 0x21
+#define AXP22X_DCDC2_V_OUT 0x22
+#define AXP22X_DCDC3_V_OUT 0x23
+#define AXP22X_DCDC4_V_OUT 0x24
+#define AXP22X_DCDC5_V_OUT 0x25
+#define AXP22X_DCDC23_V_RAMP_CTRL 0x27
+#define AXP22X_ALDO1_V_OUT 0x28
+#define AXP22X_ALDO2_V_OUT 0x29
+#define AXP22X_ALDO3_V_OUT 0x2a
+#define AXP22X_CHRG_CTRL3 0x35
+
/* Interrupt */
#define AXP20X_IRQ1_EN 0x40
#define AXP20X_IRQ2_EN 0x41
@@ -96,6 +119,9 @@ enum {
#define AXP20X_VBUS_MON 0x8b
#define AXP20X_OVER_TMP 0x8f
+#define AXP22X_PWREN_CTRL1 0x8c
+#define AXP22X_PWREN_CTRL2 0x8d
+
/* GPIO */
#define AXP20X_GPIO0_CTRL 0x90
#define AXP20X_LDO5_V_OUT 0x91
@@ -104,6 +130,11 @@ enum {
#define AXP20X_GPIO20_SS 0x94
#define AXP20X_GPIO3_CTRL 0x95
+#define AXP22X_LDO_IO0_V_OUT 0x91
+#define AXP22X_LDO_IO1_V_OUT 0x93
+#define AXP22X_GPIO_STATE 0x94
+#define AXP22X_GPIO_PULL_DOWN 0x95
+
/* Battery */
#define AXP20X_CHRG_CC_31_24 0xb0
#define AXP20X_CHRG_CC_23_16 0xb1
@@ -116,6 +147,8 @@ enum {
#define AXP20X_CC_CTRL 0xb8
#define AXP20X_FG_RES 0xb9
+#define AXP22X_BATLOW_THRES1 0xe6
+
/* Regulators IDs */
enum {
AXP20X_LDO1 = 0,
@@ -128,6 +161,29 @@ enum {
AXP20X_REG_ID_MAX,
};
+enum {
+ AXP22X_DCDC1 = 0,
+ AXP22X_DCDC2,
+ AXP22X_DCDC3,
+ AXP22X_DCDC4,
+ AXP22X_DCDC5,
+ AXP22X_DC5LDO,
+ AXP22X_ALDO1,
+ AXP22X_ALDO2,
+ AXP22X_ALDO3,
+ AXP22X_ELDO1,
+ AXP22X_ELDO2,
+ AXP22X_ELDO3,
+ AXP22X_DLDO1,
+ AXP22X_DLDO2,
+ AXP22X_DLDO3,
+ AXP22X_DLDO4,
+ AXP22X_RTC_LDO,
+ AXP22X_LDO_IO0,
+ AXP22X_LDO_IO1,
+ AXP22X_REG_ID_MAX,
+};
+
/* IRQs */
enum {
AXP20X_IRQ_ACIN_OVER_V = 1,
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 1/5] mfd: axp20x: add AXP221 PMIC support
2014-05-26 14:58 ` [PATCH v2 1/5] " Boris BREZILLON
@ 2014-05-26 15:29 ` Boris BREZILLON
0 siblings, 0 replies; 10+ messages in thread
From: Boris BREZILLON @ 2014-05-26 15:29 UTC (permalink / raw)
To: linux-arm-kernel
On 26/05/2014 16:58, Boris BREZILLON wrote:
> Add support for the AXP221 PMIC device to the existing AXP20x driver.
>
> The AXP221 defines a new set of registers, power supplies and regulators,
> but most of the API is similar to the AXP20x ones.
> The AXP20x irq chip definition is reused, though some interrupts are not
> available in the AXP221.
>
> Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
> ---
> drivers/mfd/axp20x.c | 58 +++++++++++++++++++++++++++++++++++++++++++---
> include/linux/mfd/axp20x.h | 56 ++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 111 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index dee6539..ca9fe2e 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -33,6 +33,11 @@ static const struct regmap_range axp20x_writeable_ranges[] = {
> regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
> };
>
> +static const struct regmap_range axp22x_writeable_ranges[] = {
> + regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
> + regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
> +};
> +
> static const struct regmap_range axp20x_volatile_ranges[] = {
> regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
> };
> @@ -42,6 +47,11 @@ static const struct regmap_access_table axp20x_writeable_table = {
> .n_yes_ranges = ARRAY_SIZE(axp20x_writeable_ranges),
> };
>
> +static const struct regmap_access_table axp22x_writeable_table = {
> + .yes_ranges = axp22x_writeable_ranges,
> + .n_yes_ranges = ARRAY_SIZE(axp22x_writeable_ranges),
> +};
> +
> static const struct regmap_access_table axp20x_volatile_table = {
> .yes_ranges = axp20x_volatile_ranges,
> .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
> @@ -70,6 +80,15 @@ static const struct regmap_config axp20x_regmap_config = {
> .cache_type = REGCACHE_RBTREE,
> };
>
> +static const struct regmap_config axp22x_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .wr_table = &axp22x_writeable_table,
> + .volatile_table = &axp20x_volatile_table,
> + .max_register = AXP22X_BATLOW_THRES1,
> + .cache_type = REGCACHE_RBTREE,
> +};
> +
> #define AXP20X_IRQ(_irq, _off, _mask) \
> [AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
>
> @@ -116,6 +135,7 @@ static const struct regmap_irq axp20x_regmap_irqs[] = {
> static const struct of_device_id axp20x_of_match[] = {
> { .compatible = "x-powers,axp202", .data = (void *) AXP202_ID },
> { .compatible = "x-powers,axp209", .data = (void *) AXP209_ID },
> + { .compatible = "x-powers,axp221", .data = (void *) AXP221_ID },
> { },
> };
> MODULE_DEVICE_TABLE(of, axp20x_of_match);
> @@ -149,6 +169,21 @@ static const char * const axp20x_supplies[] = {
> "ldo5in",
> };
>
> +static const char *axp22x_supplies[] = {
> + "vbus",
> + "acin",
> + "vin1",
> + "vin2",
> + "vin3",
> + "vin4",
> + "vin5",
> + "aldoin",
> + "dldoin",
> + "eldoin",
> + "ldoioin",
> + "rtcldoin",
> +};
> +
> static struct mfd_cell axp20x_cells[] = {
> {
> .name = "axp20x-pek",
> @@ -161,6 +196,14 @@ static struct mfd_cell axp20x_cells[] = {
> },
> };
>
> +static struct mfd_cell axp22x_cells[] = {
> + {
> + .name = "axp20x-regulator",
> + .parent_supplies = axp22x_supplies,
> + .num_parent_supplies = ARRAY_SIZE(axp22x_supplies),
> + },
> +};
> +
> static struct axp20x_dev *axp20x_pm_power_off;
> static void axp20x_power_off(void)
> {
> @@ -190,7 +233,12 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
> axp20x->dev = &i2c->dev;
> dev_set_drvdata(axp20x->dev, axp20x);
>
> - axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
> + if (axp20x->variant == AXP221_ID)
> + axp20x->regmap = devm_regmap_init_i2c(i2c,
> + &axp22x_regmap_config);
> + else
> + axp20x->regmap = devm_regmap_init_i2c(i2c,
> + &axp20x_regmap_config);
> if (IS_ERR(axp20x->regmap)) {
> ret = PTR_ERR(axp20x->regmap);
> dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
> @@ -206,8 +254,12 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
> return ret;
> }
>
> - ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
> - ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
> + if (axp20x->variant == AXP221_ID)
> + ret = mfd_add_devices(axp20x->dev, -1, axp22x_cells,
> + ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
Copy/paste error here: this should be ARRAY_SIZE(axp22x_cells).
> + else
> + ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
> + ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
>
> if (ret) {
> dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
> diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
> index d0e31a2..8a8ce02 100644
> --- a/include/linux/mfd/axp20x.h
> +++ b/include/linux/mfd/axp20x.h
> @@ -14,6 +14,7 @@
> enum {
> AXP202_ID = 0,
> AXP209_ID,
> + AXP221_ID,
> };
>
> #define AXP20X_DATACACHE(m) (0x04 + (m))
> @@ -43,6 +44,28 @@ enum {
> #define AXP20X_V_LTF_DISCHRG 0x3c
> #define AXP20X_V_HTF_DISCHRG 0x3d
>
> +#define AXP22X_PWR_OUT_CTRL1 0x10
> +#define AXP22X_PWR_OUT_CTRL2 0x12
> +#define AXP22X_PWR_OUT_CTRL3 0x13
> +#define AXP22X_DLDO1_V_OUT 0x15
> +#define AXP22X_DLDO2_V_OUT 0x16
> +#define AXP22X_DLDO3_V_OUT 0x17
> +#define AXP22X_DLDO4_V_OUT 0x18
> +#define AXP22X_ELDO1_V_OUT 0x19
> +#define AXP22X_ELDO2_V_OUT 0x1a
> +#define AXP22X_ELDO3_V_OUT 0x1b
> +#define AXP22X_DC5LDO_V_OUT 0x1c
> +#define AXP22X_DCDC1_V_OUT 0x21
> +#define AXP22X_DCDC2_V_OUT 0x22
> +#define AXP22X_DCDC3_V_OUT 0x23
> +#define AXP22X_DCDC4_V_OUT 0x24
> +#define AXP22X_DCDC5_V_OUT 0x25
> +#define AXP22X_DCDC23_V_RAMP_CTRL 0x27
> +#define AXP22X_ALDO1_V_OUT 0x28
> +#define AXP22X_ALDO2_V_OUT 0x29
> +#define AXP22X_ALDO3_V_OUT 0x2a
> +#define AXP22X_CHRG_CTRL3 0x35
> +
> /* Interrupt */
> #define AXP20X_IRQ1_EN 0x40
> #define AXP20X_IRQ2_EN 0x41
> @@ -96,6 +119,9 @@ enum {
> #define AXP20X_VBUS_MON 0x8b
> #define AXP20X_OVER_TMP 0x8f
>
> +#define AXP22X_PWREN_CTRL1 0x8c
> +#define AXP22X_PWREN_CTRL2 0x8d
> +
> /* GPIO */
> #define AXP20X_GPIO0_CTRL 0x90
> #define AXP20X_LDO5_V_OUT 0x91
> @@ -104,6 +130,11 @@ enum {
> #define AXP20X_GPIO20_SS 0x94
> #define AXP20X_GPIO3_CTRL 0x95
>
> +#define AXP22X_LDO_IO0_V_OUT 0x91
> +#define AXP22X_LDO_IO1_V_OUT 0x93
> +#define AXP22X_GPIO_STATE 0x94
> +#define AXP22X_GPIO_PULL_DOWN 0x95
> +
> /* Battery */
> #define AXP20X_CHRG_CC_31_24 0xb0
> #define AXP20X_CHRG_CC_23_16 0xb1
> @@ -116,6 +147,8 @@ enum {
> #define AXP20X_CC_CTRL 0xb8
> #define AXP20X_FG_RES 0xb9
>
> +#define AXP22X_BATLOW_THRES1 0xe6
> +
> /* Regulators IDs */
> enum {
> AXP20X_LDO1 = 0,
> @@ -128,6 +161,29 @@ enum {
> AXP20X_REG_ID_MAX,
> };
>
> +enum {
> + AXP22X_DCDC1 = 0,
> + AXP22X_DCDC2,
> + AXP22X_DCDC3,
> + AXP22X_DCDC4,
> + AXP22X_DCDC5,
> + AXP22X_DC5LDO,
> + AXP22X_ALDO1,
> + AXP22X_ALDO2,
> + AXP22X_ALDO3,
> + AXP22X_ELDO1,
> + AXP22X_ELDO2,
> + AXP22X_ELDO3,
> + AXP22X_DLDO1,
> + AXP22X_DLDO2,
> + AXP22X_DLDO3,
> + AXP22X_DLDO4,
> + AXP22X_RTC_LDO,
> + AXP22X_LDO_IO0,
> + AXP22X_LDO_IO1,
> + AXP22X_REG_ID_MAX,
> +};
> +
> /* IRQs */
> enum {
> AXP20X_IRQ_ACIN_OVER_V = 1,
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 2/5] regulator: axp20x: prepare support for multiple AXP chip families
2014-05-26 14:58 [PATCH v2 0/5] mfd: axp20x: add AXP221 PMIC support Boris BREZILLON
2014-05-26 14:58 ` [PATCH v2 1/5] " Boris BREZILLON
@ 2014-05-26 14:58 ` Boris BREZILLON
2014-05-26 14:58 ` [PATCH v2 3/5] regulator: axp20x: add support for AXP221 regulators Boris BREZILLON
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Boris BREZILLON @ 2014-05-26 14:58 UTC (permalink / raw)
To: linux-arm-kernel
Rework the AXP20X_ macros to support the several chip families, so that
each family can define it's own set of regulators, and regulator matches.
Pass a match table to the axp20x_regulator_parse_dt function instead of
statically using the axp20x match table.
Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
---
drivers/regulator/axp20x-regulator.c | 74 +++++++++++++++++++-----------------
1 file changed, 39 insertions(+), 35 deletions(-)
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 61ae4d4..5a59982 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -32,13 +32,13 @@
#define AXP20X_FREQ_DCDC_MASK 0x0f
-#define AXP20X_DESC_IO(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg, \
- _emask, _enable_val, _disable_val) \
- [AXP20X_##_id] = { \
+#define AXP_DESC_IO(_family, _id, _supply, _min, _max, _step, _vreg, _vmask, \
+ _ereg, _emask, _enable_val, _disable_val) \
+ [_family##_##_id] = { \
.name = #_id, \
.supply_name = (_supply), \
.type = REGULATOR_VOLTAGE, \
- .id = AXP20X_##_id, \
+ .id = _family##_##_id, \
.n_voltages = (((_max) - (_min)) / (_step) + 1), \
.owner = THIS_MODULE, \
.min_uV = (_min) * 1000, \
@@ -52,13 +52,13 @@
.ops = &axp20x_ops, \
}
-#define AXP20X_DESC(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg, \
- _emask) \
- [AXP20X_##_id] = { \
+#define AXP_DESC(_family, _id, _supply, _min, _max, _step, _vreg, _vmask, \
+ _ereg, _emask) \
+ [_family##_##_id] = { \
.name = #_id, \
.supply_name = (_supply), \
.type = REGULATOR_VOLTAGE, \
- .id = AXP20X_##_id, \
+ .id = _family##_##_id, \
.n_voltages = (((_max) - (_min)) / (_step) + 1), \
.owner = THIS_MODULE, \
.min_uV = (_min) * 1000, \
@@ -70,24 +70,25 @@
.ops = &axp20x_ops, \
}
-#define AXP20X_DESC_FIXED(_id, _supply, _volt) \
- [AXP20X_##_id] = { \
+#define AXP_DESC_FIXED(_family, _id, _supply, _volt) \
+ [_family##_##_id] = { \
.name = #_id, \
.supply_name = (_supply), \
.type = REGULATOR_VOLTAGE, \
- .id = AXP20X_##_id, \
+ .id = _family##_##_id, \
.n_voltages = 1, \
.owner = THIS_MODULE, \
.min_uV = (_volt) * 1000, \
.ops = &axp20x_ops_fixed \
}
-#define AXP20X_DESC_TABLE(_id, _supply, _table, _vreg, _vmask, _ereg, _emask) \
- [AXP20X_##_id] = { \
+#define AXP_DESC_TABLE(_family, _id, _supply, _table, _vreg, _vmask, _ereg, \
+ _emask) \
+ [_family##_##_id] = { \
.name = #_id, \
.supply_name = (_supply), \
.type = REGULATOR_VOLTAGE, \
- .id = AXP20X_##_id, \
+ .id = _family##_##_id, \
.n_voltages = ARRAY_SIZE(_table), \
.owner = THIS_MODULE, \
.vsel_reg = (_vreg), \
@@ -126,36 +127,36 @@ static struct regulator_ops axp20x_ops = {
};
static const struct regulator_desc axp20x_regulators[] = {
- AXP20X_DESC(DCDC2, "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT, 0x3f,
+ AXP_DESC(AXP20X, DCDC2, "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT, 0x3f,
AXP20X_PWR_OUT_CTRL, 0x10),
- AXP20X_DESC(DCDC3, "vin3", 700, 3500, 25, AXP20X_DCDC3_V_OUT, 0x7f,
+ AXP_DESC(AXP20X, DCDC3, "vin3", 700, 3500, 25, AXP20X_DCDC3_V_OUT, 0x7f,
AXP20X_PWR_OUT_CTRL, 0x02),
- AXP20X_DESC_FIXED(LDO1, "acin", 1300),
- AXP20X_DESC(LDO2, "ldo24in", 1800, 3300, 100, AXP20X_LDO24_V_OUT, 0xf0,
+ AXP_DESC_FIXED(AXP20X, LDO1, "acin", 1300),
+ AXP_DESC(AXP20X, LDO2, "ldo24in", 1800, 3300, 100, AXP20X_LDO24_V_OUT, 0xf0,
AXP20X_PWR_OUT_CTRL, 0x04),
- AXP20X_DESC(LDO3, "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT, 0x7f,
+ AXP_DESC(AXP20X, LDO3, "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT, 0x7f,
AXP20X_PWR_OUT_CTRL, 0x40),
- AXP20X_DESC_TABLE(LDO4, "ldo24in", axp20x_ldo4_data, AXP20X_LDO24_V_OUT, 0x0f,
+ AXP_DESC_TABLE(AXP20X, LDO4, "ldo24in", axp20x_ldo4_data, AXP20X_LDO24_V_OUT, 0x0f,
AXP20X_PWR_OUT_CTRL, 0x08),
- AXP20X_DESC_IO(LDO5, "ldo5in", 1800, 3300, 100, AXP20X_LDO5_V_OUT, 0xf0,
+ AXP_DESC_IO(AXP20X, LDO5, "ldo5in", 1800, 3300, 100, AXP20X_LDO5_V_OUT, 0xf0,
AXP20X_GPIO0_CTRL, 0x07, AXP20X_IO_ENABLED,
AXP20X_IO_DISABLED),
};
-#define AXP_MATCH(_name, _id) \
- [AXP20X_##_id] = { \
+#define AXP_MATCH(_family, _name, _id) \
+ [_family##_##_id] = { \
.name = #_name, \
- .driver_data = (void *) &axp20x_regulators[AXP20X_##_id], \
+ .driver_data = (void *) &axp20x_regulators[_family##_##_id], \
}
static struct of_regulator_match axp20x_matches[] = {
- AXP_MATCH(dcdc2, DCDC2),
- AXP_MATCH(dcdc3, DCDC3),
- AXP_MATCH(ldo1, LDO1),
- AXP_MATCH(ldo2, LDO2),
- AXP_MATCH(ldo3, LDO3),
- AXP_MATCH(ldo4, LDO4),
- AXP_MATCH(ldo5, LDO5),
+ AXP_MATCH(AXP20X, dcdc2, DCDC2),
+ AXP_MATCH(AXP20X, dcdc3, DCDC3),
+ AXP_MATCH(AXP20X, ldo1, LDO1),
+ AXP_MATCH(AXP20X, ldo2, LDO2),
+ AXP_MATCH(AXP20X, ldo3, LDO3),
+ AXP_MATCH(AXP20X, ldo4, LDO4),
+ AXP_MATCH(AXP20X, ldo5, LDO5),
};
static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
@@ -178,7 +179,9 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
AXP20X_FREQ_DCDC_MASK, dcdcfreq);
}
-static int axp20x_regulator_parse_dt(struct platform_device *pdev)
+static int axp20x_regulator_parse_dt(struct platform_device *pdev,
+ struct of_regulator_match *matches,
+ int nmatches)
{
struct device_node *np, *regulators;
int ret;
@@ -192,8 +195,8 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev)
if (!regulators) {
dev_warn(&pdev->dev, "regulators node not found\n");
} else {
- ret = of_regulator_match(&pdev->dev, regulators, axp20x_matches,
- ARRAY_SIZE(axp20x_matches));
+ ret = of_regulator_match(&pdev->dev, regulators, matches,
+ nmatches);
if (ret < 0) {
dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret);
return ret;
@@ -237,7 +240,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
int ret, i;
u32 workmode;
- ret = axp20x_regulator_parse_dt(pdev);
+ ret = axp20x_regulator_parse_dt(pdev, axp20x_matches,
+ ARRAY_SIZE(axp20x_matches));
if (ret)
return ret;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 3/5] regulator: axp20x: add support for AXP221 regulators
2014-05-26 14:58 [PATCH v2 0/5] mfd: axp20x: add AXP221 PMIC support Boris BREZILLON
2014-05-26 14:58 ` [PATCH v2 1/5] " Boris BREZILLON
2014-05-26 14:58 ` [PATCH v2 2/5] regulator: axp20x: prepare support for multiple AXP chip families Boris BREZILLON
@ 2014-05-26 14:58 ` Boris BREZILLON
2014-05-26 14:58 ` [PATCH v2 4/5] regulator: axp20x: reset probe data before each probe Boris BREZILLON
2014-05-26 14:58 ` [PATCH v2 5/5] regulator: axp20x: resolve self dependency issue Boris BREZILLON
4 siblings, 0 replies; 10+ messages in thread
From: Boris BREZILLON @ 2014-05-26 14:58 UTC (permalink / raw)
To: linux-arm-kernel
Add AXP221 regulator definitions and choose the appropriate definitions
according to the variant id passed by the MFD device.
Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
---
drivers/regulator/axp20x-regulator.c | 98 +++++++++++++++++++++++++++++++++---
1 file changed, 90 insertions(+), 8 deletions(-)
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 5a59982..feaa0b5 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -27,6 +27,9 @@
#define AXP20X_IO_ENABLED 0x03
#define AXP20X_IO_DISABLED 0x07
+#define AXP22X_IO_ENABLED 0x04
+#define AXP22X_IO_DISABLED 0x03
+
#define AXP20X_WORKMODE_DCDC2_MASK BIT(2)
#define AXP20X_WORKMODE_DCDC3_MASK BIT(1)
@@ -143,6 +146,48 @@ static const struct regulator_desc axp20x_regulators[] = {
AXP20X_IO_DISABLED),
};
+static const struct regulator_desc axp22x_regulators[] = {
+ AXP_DESC(AXP22X, DCDC1, "vin1", 1600, 3400, 100, AXP22X_DCDC1_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL1, BIT(1)),
+ AXP_DESC(AXP22X, DCDC2, "vin2", 600, 1540, 20, AXP22X_DCDC2_V_OUT, 0x3f,
+ AXP22X_PWR_OUT_CTRL1, BIT(2)),
+ AXP_DESC(AXP22X, DCDC3, "vin3", 600, 1860, 20, AXP22X_DCDC3_V_OUT, 0x3f,
+ AXP22X_PWR_OUT_CTRL1, BIT(3)),
+ AXP_DESC(AXP22X, DCDC4, "vin4", 600, 1540, 20, AXP22X_DCDC4_V_OUT, 0x3f,
+ AXP22X_PWR_OUT_CTRL1, BIT(3)),
+ AXP_DESC(AXP22X, DCDC5, "vin5", 1000, 2550, 50, AXP22X_DCDC5_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL1, BIT(4)),
+ AXP_DESC(AXP22X, DC5LDO, "vin5", 700, 1400, 100, AXP22X_DC5LDO_V_OUT, 0x7,
+ AXP22X_PWR_OUT_CTRL1, BIT(0)),
+ AXP_DESC(AXP22X, ALDO1, "aldoin", 700, 3300, 100, AXP22X_ALDO1_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL1, BIT(6)),
+ AXP_DESC(AXP22X, ALDO2, "aldoin", 700, 3300, 100, AXP22X_ALDO2_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL1, BIT(7)),
+ AXP_DESC(AXP22X, ALDO3, "aldoin", 700, 3300, 100, AXP22X_ALDO3_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL3, BIT(7)),
+ AXP_DESC(AXP22X, DLDO1, "dldoin", 700, 3300, 100, AXP22X_DLDO1_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL2, BIT(3)),
+ AXP_DESC(AXP22X, DLDO2, "dldoin", 700, 3300, 100, AXP22X_DLDO2_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL2, BIT(4)),
+ AXP_DESC(AXP22X, DLDO3, "dldoin", 700, 3300, 100, AXP22X_DLDO3_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL2, BIT(5)),
+ AXP_DESC(AXP22X, DLDO4, "dldoin", 700, 3300, 100, AXP22X_DLDO4_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL2, BIT(6)),
+ AXP_DESC(AXP22X, ELDO1, "eldoin", 700, 3300, 100, AXP22X_ELDO1_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL2, BIT(0)),
+ AXP_DESC(AXP22X, ELDO2, "eldoin", 700, 3300, 100, AXP22X_ELDO2_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL2, BIT(1)),
+ AXP_DESC(AXP22X, ELDO3, "eldoin", 700, 3300, 100, AXP22X_ELDO3_V_OUT, 0x1f,
+ AXP22X_PWR_OUT_CTRL2, BIT(2)),
+ AXP_DESC_IO(AXP22X, LDO_IO0, "ldoioin", 1800, 3300, 100, AXP22X_LDO_IO0_V_OUT,
+ 0x1f, AXP20X_GPIO0_CTRL, 0x07, AXP22X_IO_ENABLED,
+ AXP22X_IO_DISABLED),
+ AXP_DESC_IO(AXP22X, LDO_IO1, "ldoioin", 1800, 3300, 100, AXP22X_LDO_IO1_V_OUT,
+ 0x1f, AXP20X_GPIO1_CTRL, 0x07, AXP22X_IO_ENABLED,
+ AXP22X_IO_DISABLED),
+ AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtcldoin", 3000),
+};
+
#define AXP_MATCH(_family, _name, _id) \
[_family##_##_id] = { \
.name = #_name, \
@@ -159,6 +204,28 @@ static struct of_regulator_match axp20x_matches[] = {
AXP_MATCH(AXP20X, ldo5, LDO5),
};
+static struct of_regulator_match axp22x_matches[] = {
+ AXP_MATCH(AXP22X, dcdc1, DCDC1),
+ AXP_MATCH(AXP22X, dcdc2, DCDC2),
+ AXP_MATCH(AXP22X, dcdc3, DCDC3),
+ AXP_MATCH(AXP22X, dcdc4, DCDC4),
+ AXP_MATCH(AXP22X, dcdc5, DCDC5),
+ AXP_MATCH(AXP22X, dc5ldo, DC5LDO),
+ AXP_MATCH(AXP22X, aldo1, ALDO1),
+ AXP_MATCH(AXP22X, aldo2, ALDO2),
+ AXP_MATCH(AXP22X, aldo3, ALDO3),
+ AXP_MATCH(AXP22X, dldo1, DLDO1),
+ AXP_MATCH(AXP22X, dldo2, DLDO2),
+ AXP_MATCH(AXP22X, dldo3, DLDO3),
+ AXP_MATCH(AXP22X, dldo4, DLDO4),
+ AXP_MATCH(AXP22X, eldo1, ELDO1),
+ AXP_MATCH(AXP22X, eldo2, ELDO2),
+ AXP_MATCH(AXP22X, eldo3, ELDO3),
+ AXP_MATCH(AXP22X, ldo_io0, LDO_IO0),
+ AXP_MATCH(AXP22X, ldo_io1, LDO_IO1),
+ AXP_MATCH(AXP22X, rtc_ldo, RTC_LDO),
+};
+
static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
@@ -237,37 +304,52 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
struct regulator_init_data *init_data;
+ struct of_regulator_match *matches;
+ int nmatches;
+ const struct regulator_desc *regulators;
+ int nregulators;
int ret, i;
u32 workmode;
- ret = axp20x_regulator_parse_dt(pdev, axp20x_matches,
- ARRAY_SIZE(axp20x_matches));
+ if (axp20x->variant == AXP221_ID) {
+ matches = axp22x_matches;
+ nmatches = ARRAY_SIZE(axp22x_matches);
+ regulators = axp22x_regulators;
+ nregulators = AXP22X_REG_ID_MAX;
+ } else {
+ matches = axp20x_matches;
+ nmatches = ARRAY_SIZE(axp20x_matches);
+ regulators = axp20x_regulators;
+ nregulators = AXP20X_REG_ID_MAX;
+ }
+
+ ret = axp20x_regulator_parse_dt(pdev, matches, nmatches);
if (ret)
return ret;
for (i = 0; i < AXP20X_REG_ID_MAX; i++) {
- init_data = axp20x_matches[i].init_data;
+ init_data = matches[i].init_data;
config.dev = &pdev->dev;
config.init_data = init_data;
config.regmap = axp20x->regmap;
- config.of_node = axp20x_matches[i].of_node;
+ config.of_node = matches[i].of_node;
- rdev = devm_regulator_register(&pdev->dev, &axp20x_regulators[i],
+ rdev = devm_regulator_register(&pdev->dev, ®ulators[i],
&config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register %s\n",
- axp20x_regulators[i].name);
+ regulators[i].name);
return PTR_ERR(rdev);
}
- ret = of_property_read_u32(axp20x_matches[i].of_node, "x-powers,dcdc-workmode",
+ ret = of_property_read_u32(matches[i].of_node, "x-powers,dcdc-workmode",
&workmode);
if (!ret) {
if (axp20x_set_dcdc_workmode(rdev, i, workmode))
dev_err(&pdev->dev, "Failed to set workmode on %s\n",
- axp20x_regulators[i].name);
+ regulators[i].name);
}
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 4/5] regulator: axp20x: reset probe data before each probe
2014-05-26 14:58 [PATCH v2 0/5] mfd: axp20x: add AXP221 PMIC support Boris BREZILLON
` (2 preceding siblings ...)
2014-05-26 14:58 ` [PATCH v2 3/5] regulator: axp20x: add support for AXP221 regulators Boris BREZILLON
@ 2014-05-26 14:58 ` Boris BREZILLON
2014-05-26 14:58 ` [PATCH v2 5/5] regulator: axp20x: resolve self dependency issue Boris BREZILLON
4 siblings, 0 replies; 10+ messages in thread
From: Boris BREZILLON @ 2014-05-26 14:58 UTC (permalink / raw)
To: linux-arm-kernel
The init_data and of_node fields of the axp2xx_matches tables are filled
at each device probe by the axp20x_regulator_parse_dt function (which then
calls the of_regulator_match function).
This means we can probe a new device and consider data initialized during
the probe of another device as valid.
Reset init_data and of_node field to NULL before each probe in order to
avoid this kind of issue.
Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
---
drivers/regulator/axp20x-regulator.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index feaa0b5..4486517 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -323,6 +323,15 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
nregulators = AXP20X_REG_ID_MAX;
}
+ /*
+ * Reset matches table (this table might have been modified by a
+ * previous AXP2xx device probe).
+ */
+ for (i = 0; i < nmatches; i++) {
+ matches[i].init_data = NULL;
+ matches[i].of_node = NULL;
+ }
+
ret = axp20x_regulator_parse_dt(pdev, matches, nmatches);
if (ret)
return ret;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 5/5] regulator: axp20x: resolve self dependency issue
2014-05-26 14:58 [PATCH v2 0/5] mfd: axp20x: add AXP221 PMIC support Boris BREZILLON
` (3 preceding siblings ...)
2014-05-26 14:58 ` [PATCH v2 4/5] regulator: axp20x: reset probe data before each probe Boris BREZILLON
@ 2014-05-26 14:58 ` Boris BREZILLON
2014-05-26 15:43 ` Mark Brown
4 siblings, 1 reply; 10+ messages in thread
From: Boris BREZILLON @ 2014-05-26 14:58 UTC (permalink / raw)
To: linux-arm-kernel
Some regulators might take their power supply from other regulators defined
by the same PMIC.
Retry regulators registration until all regulators are registered or the
last iteration didn't manage to register any new regulator (which means
there's an external dependency missing and we can thus return
EPROBE_DEFER).
Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
---
drivers/regulator/axp20x-regulator.c | 75 ++++++++++++++++++++++++++++--------
1 file changed, 58 insertions(+), 17 deletions(-)
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 4486517..c5b665e 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -146,6 +146,8 @@ static const struct regulator_desc axp20x_regulators[] = {
AXP20X_IO_DISABLED),
};
+static bool axp20x_registered_regulators[AXP20X_REG_ID_MAX];
+
static const struct regulator_desc axp22x_regulators[] = {
AXP_DESC(AXP22X, DCDC1, "vin1", 1600, 3400, 100, AXP22X_DCDC1_V_OUT, 0x1f,
AXP22X_PWR_OUT_CTRL1, BIT(1)),
@@ -188,6 +190,8 @@ static const struct regulator_desc axp22x_regulators[] = {
AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtcldoin", 3000),
};
+static bool axp22x_registered_regulators[AXP22X_REG_ID_MAX];
+
#define AXP_MATCH(_family, _name, _id) \
[_family##_##_id] = { \
.name = #_name, \
@@ -308,6 +312,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
int nmatches;
const struct regulator_desc *regulators;
int nregulators;
+ bool *registered;
+ int nregistered = 0;
+ int prev_nregistered = -1;
int ret, i;
u32 workmode;
@@ -316,11 +323,13 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
nmatches = ARRAY_SIZE(axp22x_matches);
regulators = axp22x_regulators;
nregulators = AXP22X_REG_ID_MAX;
+ registered = axp22x_registered_regulators;
} else {
matches = axp20x_matches;
nmatches = ARRAY_SIZE(axp20x_matches);
regulators = axp20x_regulators;
nregulators = AXP20X_REG_ID_MAX;
+ registered = axp20x_registered_regulators;
}
/*
@@ -332,36 +341,68 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
matches[i].of_node = NULL;
}
+ /*
+ * Reset registered status table (this table might have been modified
+ * by a previous AXP2xx device probe).
+ */
+ memset(registered, 0, nregulators * sizeof(*registered));
+
ret = axp20x_regulator_parse_dt(pdev, matches, nmatches);
if (ret)
return ret;
- for (i = 0; i < AXP20X_REG_ID_MAX; i++) {
- init_data = matches[i].init_data;
+ /*
+ * Some regulators might take their power supply from other regulators
+ * defined by the same PMIC.
+ *
+ * Retry regulators registration until all regulators are registered
+ * or the last iteration didn't manage to register any new regulator
+ * (which means there's an external dependency missing and we can thus
+ * return EPROBE_DEFER).
+ */
+ while (nregistered < nregulators &&
+ prev_nregistered < nregistered) {
- config.dev = &pdev->dev;
- config.init_data = init_data;
- config.regmap = axp20x->regmap;
- config.of_node = matches[i].of_node;
+ prev_nregistered = nregistered;
- rdev = devm_regulator_register(&pdev->dev, ®ulators[i],
- &config);
- if (IS_ERR(rdev)) {
- dev_err(&pdev->dev, "Failed to register %s\n",
+ for (i = 0; i < nregulators; i++) {
+ if (registered[i])
+ continue;
+
+ init_data = matches[i].init_data;
+
+ config.dev = &pdev->dev;
+ config.init_data = init_data;
+ config.regmap = axp20x->regmap;
+ config.of_node = matches[i].of_node;
+
+ rdev = devm_regulator_register(&pdev->dev,
+ ®ulators[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "Failed to register %s\n",
regulators[i].name);
- return PTR_ERR(rdev);
- }
+ return PTR_ERR(rdev);
+ }
- ret = of_property_read_u32(matches[i].of_node, "x-powers,dcdc-workmode",
- &workmode);
- if (!ret) {
- if (axp20x_set_dcdc_workmode(rdev, i, workmode))
- dev_err(&pdev->dev, "Failed to set workmode on %s\n",
+ ret = of_property_read_u32(matches[i].of_node,
+ "x-powers,dcdc-workmode",
+ &workmode);
+ if (!ret &&
+ axp20x_set_dcdc_workmode(rdev, i, workmode))
+ dev_err(&pdev->dev,
+ "Failed to set workmode on %s\n",
regulators[i].name);
+
+ registered[i] = true;
+ nregistered++;
}
}
+ if (nregistered < nregulators)
+ return -EPROBE_DEFER;
+
return 0;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 5/5] regulator: axp20x: resolve self dependency issue
2014-05-26 14:58 ` [PATCH v2 5/5] regulator: axp20x: resolve self dependency issue Boris BREZILLON
@ 2014-05-26 15:43 ` Mark Brown
2014-05-26 16:58 ` Boris BREZILLON
0 siblings, 1 reply; 10+ messages in thread
From: Mark Brown @ 2014-05-26 15:43 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, May 26, 2014 at 04:58:12PM +0200, Boris BREZILLON wrote:
> Some regulators might take their power supply from other regulators defined
> by the same PMIC.
>
> Retry regulators registration until all regulators are registered or the
> last iteration didn't manage to register any new regulator (which means
> there's an external dependency missing and we can thus return
> EPROBE_DEFER).
This is going to apply to most PMICs - we should factor this out into
the core rather than implementing it individual drivers. It works
normally because typically the dependency is from DCDCs to LDOs and so
with common naming schemes alphabetic sorting saves us.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140526/de651b6f/attachment.sig>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 5/5] regulator: axp20x: resolve self dependency issue
2014-05-26 15:43 ` Mark Brown
@ 2014-05-26 16:58 ` Boris BREZILLON
2014-05-26 18:17 ` Mark Brown
0 siblings, 1 reply; 10+ messages in thread
From: Boris BREZILLON @ 2014-05-26 16:58 UTC (permalink / raw)
To: linux-arm-kernel
Hello Mark,
On 26/05/2014 17:43, Mark Brown wrote:
> On Mon, May 26, 2014 at 04:58:12PM +0200, Boris BREZILLON wrote:
>> Some regulators might take their power supply from other regulators defined
>> by the same PMIC.
>>
>> Retry regulators registration until all regulators are registered or the
>> last iteration didn't manage to register any new regulator (which means
>> there's an external dependency missing and we can thus return
>> EPROBE_DEFER).
> This is going to apply to most PMICs - we should factor this out into
> the core rather than implementing it individual drivers. It works
> normally because typically the dependency is from DCDCs to LDOs and so
> with common naming schemes alphabetic sorting saves us.
I'm not sure I get what you mean.
AFAIU, we could factorize it by the mean of an helper function (say
devm_regulators_register), which would take a matches table and a
regulator desc table and do pretty much what I'm doing in this patch.
Is that what you had in mind ?
Best Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 10+ messages in thread