Skip to content

Commit 1dbe0cc

Browse files
Icenowybroonie
authored andcommitted
regulator: axp20x-regulator: add support for AXP803
AXP803 PMIC also have a series of regulators (DCDCs and LDOs) controllable via I2C/RSB bus. Add support for them. Signed-off-by: Icenowy Zheng <[email protected]> Acked-by: Chen-Yu Tsai <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 2ea659a commit 1dbe0cc

File tree

2 files changed

+168
-22
lines changed

2 files changed

+168
-22
lines changed

drivers/regulator/axp20x-regulator.c

Lines changed: 131 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,82 @@ static const struct regulator_desc axp22x_drivevbus_regulator = {
244244
.ops = &axp20x_ops_sw,
245245
};
246246

247+
static const struct regulator_linear_range axp803_dcdc234_ranges[] = {
248+
REGULATOR_LINEAR_RANGE(500000, 0x0, 0x46, 10000),
249+
REGULATOR_LINEAR_RANGE(1220000, 0x47, 0x4b, 20000),
250+
};
251+
252+
static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
253+
REGULATOR_LINEAR_RANGE(800000, 0x0, 0x20, 10000),
254+
REGULATOR_LINEAR_RANGE(1140000, 0x21, 0x44, 20000),
255+
};
256+
257+
static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
258+
REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
259+
REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
260+
};
261+
262+
/* AXP806's CLDO2 and AXP809's DLDO1 shares the same range */
263+
static const struct regulator_linear_range axp803_dldo2_ranges[] = {
264+
REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
265+
REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
266+
};
267+
268+
static const struct regulator_desc axp803_regulators[] = {
269+
AXP_DESC(AXP803, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
270+
AXP803_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
271+
AXP_DESC_RANGES(AXP803, DCDC2, "dcdc2", "vin2", axp803_dcdc234_ranges,
272+
76, AXP803_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
273+
BIT(1)),
274+
AXP_DESC_RANGES(AXP803, DCDC3, "dcdc3", "vin3", axp803_dcdc234_ranges,
275+
76, AXP803_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
276+
BIT(2)),
277+
AXP_DESC_RANGES(AXP803, DCDC4, "dcdc4", "vin4", axp803_dcdc234_ranges,
278+
76, AXP803_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
279+
BIT(3)),
280+
AXP_DESC_RANGES(AXP803, DCDC5, "dcdc5", "vin5", axp803_dcdc5_ranges,
281+
68, AXP803_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
282+
BIT(4)),
283+
AXP_DESC_RANGES(AXP803, DCDC6, "dcdc6", "vin6", axp803_dcdc6_ranges,
284+
72, AXP803_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
285+
BIT(5)),
286+
/* secondary switchable output of DCDC1 */
287+
AXP_DESC_SW(AXP803, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
288+
BIT(7)),
289+
AXP_DESC(AXP803, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
290+
AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
291+
AXP_DESC(AXP803, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
292+
AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
293+
AXP_DESC(AXP803, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
294+
AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
295+
AXP_DESC(AXP803, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
296+
AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
297+
AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges,
298+
32, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
299+
BIT(4)),
300+
AXP_DESC(AXP803, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
301+
AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
302+
AXP_DESC(AXP803, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
303+
AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
304+
AXP_DESC(AXP803, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
305+
AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
306+
AXP_DESC(AXP803, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
307+
AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
308+
AXP_DESC(AXP803, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
309+
AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
310+
AXP_DESC(AXP803, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
311+
AXP803_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
312+
AXP_DESC(AXP803, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
313+
AXP803_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
314+
AXP_DESC_IO(AXP803, LDO_IO0, "ldo-io0", "ips", 700, 3300, 100,
315+
AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
316+
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
317+
AXP_DESC_IO(AXP803, LDO_IO1, "ldo-io1", "ips", 700, 3300, 100,
318+
AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
319+
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
320+
AXP_DESC_FIXED(AXP803, RTC_LDO, "rtc-ldo", "ips", 3000),
321+
};
322+
247323
static const struct regulator_linear_range axp806_dcdca_ranges[] = {
248324
REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
249325
REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
@@ -254,11 +330,6 @@ static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
254330
REGULATOR_LINEAR_RANGE(1600000, 0x2e, 0x3f, 100000),
255331
};
256332

257-
static const struct regulator_linear_range axp806_cldo2_ranges[] = {
258-
REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
259-
REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
260-
};
261-
262333
static const struct regulator_desc axp806_regulators[] = {
263334
AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina", axp806_dcdca_ranges,
264335
72, AXP806_DCDCA_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
@@ -289,7 +360,7 @@ static const struct regulator_desc axp806_regulators[] = {
289360
AXP806_BLDO4_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(3)),
290361
AXP_DESC(AXP806, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
291362
AXP806_CLDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(4)),
292-
AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp806_cldo2_ranges,
363+
AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp803_dldo2_ranges,
293364
32, AXP806_CLDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2,
294365
BIT(5)),
295366
AXP_DESC(AXP806, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
@@ -326,7 +397,7 @@ static const struct regulator_desc axp809_regulators[] = {
326397
AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
327398
AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
328399
AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
329-
AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp806_cldo2_ranges,
400+
AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp803_dldo2_ranges,
330401
32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
331402
BIT(3)),
332403
AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
@@ -369,14 +440,21 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
369440
def = 1500;
370441
step = 75;
371442
break;
372-
case AXP806_ID:
443+
case AXP803_ID:
373444
/*
374-
* AXP806 DCDC work frequency setting has the same range and
445+
* AXP803 DCDC work frequency setting has the same range and
375446
* step as AXP22X, but at a different register.
376447
* Fall through to the check below.
377448
* (See include/linux/mfd/axp20x.h)
378449
*/
379-
reg = AXP806_DCDC_FREQ_CTRL;
450+
reg = AXP803_DCDC_FREQ_CTRL;
451+
case AXP806_ID:
452+
/*
453+
* AXP806 also have DCDC work frequency setting register at a
454+
* different position.
455+
*/
456+
if (axp20x->variant == AXP806_ID)
457+
reg = AXP806_DCDC_FREQ_CTRL;
380458
case AXP221_ID:
381459
case AXP223_ID:
382460
case AXP809_ID:
@@ -475,6 +553,14 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
475553
workmode <<= id - AXP22X_DCDC1;
476554
break;
477555

556+
case AXP803_ID:
557+
if (id < AXP803_DCDC1 || id > AXP803_DCDC6)
558+
return -EINVAL;
559+
560+
mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP803_DCDC1);
561+
workmode <<= id - AXP803_DCDC1;
562+
break;
563+
478564
default:
479565
/* should not happen */
480566
WARN_ON(1);
@@ -492,20 +578,38 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
492578
{
493579
u32 reg = 0;
494580

495-
/* Only AXP806 has poly-phase outputs */
496-
if (axp20x->variant != AXP806_ID)
497-
return false;
581+
/*
582+
* Currently in our supported AXP variants, only AXP803 and AXP806
583+
* have polyphase regulators.
584+
*/
585+
switch (axp20x->variant) {
586+
case AXP803_ID:
587+
regmap_read(axp20x->regmap, AXP803_POLYPHASE_CTRL, &reg);
588+
589+
switch (id) {
590+
case AXP803_DCDC3:
591+
return !!(reg & BIT(6));
592+
case AXP803_DCDC6:
593+
return !!(reg & BIT(7));
594+
}
595+
break;
498596

499-
regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, &reg);
597+
case AXP806_ID:
598+
regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, &reg);
599+
600+
switch (id) {
601+
case AXP806_DCDCB:
602+
return (((reg & GENMASK(7, 6)) == BIT(6)) ||
603+
((reg & GENMASK(7, 6)) == BIT(7)));
604+
case AXP806_DCDCC:
605+
return ((reg & GENMASK(7, 6)) == BIT(7));
606+
case AXP806_DCDCE:
607+
return !!(reg & BIT(5));
608+
}
609+
break;
500610

501-
switch (id) {
502-
case AXP806_DCDCB:
503-
return (((reg & GENMASK(7, 6)) == BIT(6)) ||
504-
((reg & GENMASK(7, 6)) == BIT(7)));
505-
case AXP806_DCDCC:
506-
return ((reg & GENMASK(7, 6)) == BIT(7));
507-
case AXP806_DCDCE:
508-
return !!(reg & BIT(5));
611+
default:
612+
return false;
509613
}
510614

511615
return false;
@@ -540,6 +644,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
540644
drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
541645
"x-powers,drive-vbus-en");
542646
break;
647+
case AXP803_ID:
648+
regulators = axp803_regulators;
649+
nregulators = AXP803_REG_ID_MAX;
650+
break;
543651
case AXP806_ID:
544652
regulators = axp806_regulators;
545653
nregulators = AXP806_REG_ID_MAX;
@@ -579,6 +687,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
579687
* name.
580688
*/
581689
if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
690+
(regulators == axp803_regulators && i == AXP803_DC1SW) ||
582691
(regulators == axp809_regulators && i == AXP809_DC1SW)) {
583692
new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
584693
GFP_KERNEL);

include/linux/mfd/axp20x.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ enum axp20x_variants {
119119
#define AXP806_BUS_ADDR_EXT 0xfe
120120
#define AXP806_REG_ADDR_EXT 0xff
121121

122+
#define AXP803_POLYPHASE_CTRL 0x14
123+
#define AXP803_FLDO1_V_OUT 0x1c
124+
#define AXP803_FLDO2_V_OUT 0x1d
125+
#define AXP803_DCDC1_V_OUT 0x20
126+
#define AXP803_DCDC2_V_OUT 0x21
127+
#define AXP803_DCDC3_V_OUT 0x22
128+
#define AXP803_DCDC4_V_OUT 0x23
129+
#define AXP803_DCDC5_V_OUT 0x24
130+
#define AXP803_DCDC6_V_OUT 0x25
131+
#define AXP803_DCDC_FREQ_CTRL 0x3b
132+
122133
/* Interrupt */
123134
#define AXP152_IRQ1_EN 0x40
124135
#define AXP152_IRQ2_EN 0x41
@@ -350,6 +361,32 @@ enum {
350361
AXP809_REG_ID_MAX,
351362
};
352363

364+
enum {
365+
AXP803_DCDC1 = 0,
366+
AXP803_DCDC2,
367+
AXP803_DCDC3,
368+
AXP803_DCDC4,
369+
AXP803_DCDC5,
370+
AXP803_DCDC6,
371+
AXP803_DC1SW,
372+
AXP803_ALDO1,
373+
AXP803_ALDO2,
374+
AXP803_ALDO3,
375+
AXP803_DLDO1,
376+
AXP803_DLDO2,
377+
AXP803_DLDO3,
378+
AXP803_DLDO4,
379+
AXP803_ELDO1,
380+
AXP803_ELDO2,
381+
AXP803_ELDO3,
382+
AXP803_FLDO1,
383+
AXP803_FLDO2,
384+
AXP803_RTC_LDO,
385+
AXP803_LDO_IO0,
386+
AXP803_LDO_IO1,
387+
AXP803_REG_ID_MAX,
388+
};
389+
353390
/* IRQs */
354391
enum {
355392
AXP152_IRQ_LDO0IN_CONNECT = 1,

0 commit comments

Comments
 (0)