Skip to content

Commit 75c8cb2

Browse files
Haxk20lag-linaro
authored andcommitted
mfd: axp20x: Add support for AXP313a PMIC
The AXP313a is a PMIC chip produced by X-Powers, it can be connected via an I2C bus. The name AXP1530 seems to appear as well, and this is what is used in the BSP driver. From all we know it's the same chip, just a different name. However we have only seen AXP313a chips in the wild, so go with this name. Compared to the other AXP PMICs it's a rather simple affair: just three DCDC converters, three LDOs, and no battery charging support. Describe the regmap and the MFD bits, along with the registers exposed via I2C. Aside from the various regulators, also describe the power key interrupts, and adjust the shutdown handler routine to use a different register than the other PMICs. Eventually advertise the device using the new compatible string. Signed-off-by: Martin Botka <martin.botka@somainline.org> Signed-off-by: Andre Przywara <andre.przywara@arm.com> Reviewed-by: Chen-Yu Tsai <wens@csie.org> Link: https://lore.kernel.org/r/20230524000012.15028-2-andre.przywara@arm.com Signed-off-by: Lee Jones <lee@kernel.org>
1 parent ac9a786 commit 75c8cb2

3 files changed

Lines changed: 111 additions & 1 deletion

File tree

drivers/mfd/axp20x-i2c.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
6363
{ .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
6464
{ .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
6565
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
66+
{ .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID },
6667
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
6768
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
6869
{ .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
@@ -77,6 +78,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
7778
{ "axp209", 0 },
7879
{ "axp221", 0 },
7980
{ "axp223", 0 },
81+
{ "axp313a", 0 },
8082
{ "axp803", 0 },
8183
{ "axp806", 0 },
8284
{ "axp15060", 0 },

drivers/mfd/axp20x.c

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ static const char * const axp20x_model_names[] = {
3939
"AXP221",
4040
"AXP223",
4141
"AXP288",
42+
"AXP313a",
4243
"AXP803",
4344
"AXP806",
4445
"AXP809",
@@ -156,6 +157,25 @@ static const struct regmap_range axp806_writeable_ranges[] = {
156157
regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT),
157158
};
158159

160+
static const struct regmap_range axp313a_writeable_ranges[] = {
161+
regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE),
162+
};
163+
164+
static const struct regmap_range axp313a_volatile_ranges[] = {
165+
regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL),
166+
regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE),
167+
};
168+
169+
static const struct regmap_access_table axp313a_writeable_table = {
170+
.yes_ranges = axp313a_writeable_ranges,
171+
.n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges),
172+
};
173+
174+
static const struct regmap_access_table axp313a_volatile_table = {
175+
.yes_ranges = axp313a_volatile_ranges,
176+
.n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges),
177+
};
178+
159179
static const struct regmap_range axp806_volatile_ranges[] = {
160180
regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
161181
};
@@ -248,6 +268,11 @@ static const struct resource axp288_fuel_gauge_resources[] = {
248268
DEFINE_RES_IRQ(AXP288_IRQ_WL1),
249269
};
250270

271+
static const struct resource axp313a_pek_resources[] = {
272+
DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
273+
DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
274+
};
275+
251276
static const struct resource axp803_pek_resources[] = {
252277
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
253278
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -304,6 +329,15 @@ static const struct regmap_config axp288_regmap_config = {
304329
.cache_type = REGCACHE_RBTREE,
305330
};
306331

332+
static const struct regmap_config axp313a_regmap_config = {
333+
.reg_bits = 8,
334+
.val_bits = 8,
335+
.wr_table = &axp313a_writeable_table,
336+
.volatile_table = &axp313a_volatile_table,
337+
.max_register = AXP313A_IRQ_STATE,
338+
.cache_type = REGCACHE_RBTREE,
339+
};
340+
307341
static const struct regmap_config axp806_regmap_config = {
308342
.reg_bits = 8,
309343
.val_bits = 8,
@@ -456,6 +490,16 @@ static const struct regmap_irq axp288_regmap_irqs[] = {
456490
INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1),
457491
};
458492

493+
static const struct regmap_irq axp313a_regmap_irqs[] = {
494+
INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE, 0, 7),
495+
INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE, 0, 6),
496+
INIT_REGMAP_IRQ(AXP313A, PEK_SHORT, 0, 5),
497+
INIT_REGMAP_IRQ(AXP313A, PEK_LONG, 0, 4),
498+
INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW, 0, 3),
499+
INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW, 0, 2),
500+
INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0),
501+
};
502+
459503
static const struct regmap_irq axp803_regmap_irqs[] = {
460504
INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7),
461505
INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6),
@@ -606,6 +650,17 @@ static const struct regmap_irq_chip axp288_regmap_irq_chip = {
606650

607651
};
608652

653+
static const struct regmap_irq_chip axp313a_regmap_irq_chip = {
654+
.name = "axp313a_irq_chip",
655+
.status_base = AXP313A_IRQ_STATE,
656+
.ack_base = AXP313A_IRQ_STATE,
657+
.unmask_base = AXP313A_IRQ_EN,
658+
.init_ack_masked = true,
659+
.irqs = axp313a_regmap_irqs,
660+
.num_irqs = ARRAY_SIZE(axp313a_regmap_irqs),
661+
.num_regs = 1,
662+
};
663+
609664
static const struct regmap_irq_chip axp803_regmap_irq_chip = {
610665
.name = "axp803",
611666
.status_base = AXP20X_IRQ1_STATE,
@@ -745,6 +800,11 @@ static const struct mfd_cell axp152_cells[] = {
745800
},
746801
};
747802

803+
static struct mfd_cell axp313a_cells[] = {
804+
MFD_CELL_NAME("axp20x-regulator"),
805+
MFD_CELL_RES("axp313a-pek", axp313a_pek_resources),
806+
};
807+
748808
static const struct resource axp288_adc_resources[] = {
749809
DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
750810
};
@@ -914,8 +974,18 @@ static const struct mfd_cell axp_regulator_only_cells[] = {
914974
static int axp20x_power_off(struct sys_off_data *data)
915975
{
916976
struct axp20x_dev *axp20x = data->cb_data;
977+
unsigned int shutdown_reg;
917978

918-
regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF);
979+
switch (axp20x->variant) {
980+
case AXP313A_ID:
981+
shutdown_reg = AXP313A_SHUTDOWN_CTRL;
982+
break;
983+
default:
984+
shutdown_reg = AXP20X_OFF_CTRL;
985+
break;
986+
}
987+
988+
regmap_write(axp20x->regmap, shutdown_reg, AXP20X_OFF);
919989

920990
/* Give capacitors etc. time to drain to avoid kernel panic msg. */
921991
mdelay(500);
@@ -978,6 +1048,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
9781048
axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
9791049
axp20x->irq_flags = IRQF_TRIGGER_LOW;
9801050
break;
1051+
case AXP313A_ID:
1052+
axp20x->nr_cells = ARRAY_SIZE(axp313a_cells);
1053+
axp20x->cells = axp313a_cells;
1054+
axp20x->regmap_cfg = &axp313a_regmap_config;
1055+
axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip;
1056+
break;
9811057
case AXP803_ID:
9821058
axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
9831059
axp20x->cells = axp803_cells;

include/linux/mfd/axp20x.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ enum axp20x_variants {
1717
AXP221_ID,
1818
AXP223_ID,
1919
AXP288_ID,
20+
AXP313A_ID,
2021
AXP803_ID,
2122
AXP806_ID,
2223
AXP809_ID,
@@ -92,6 +93,17 @@ enum axp20x_variants {
9293
#define AXP22X_ALDO3_V_OUT 0x2a
9394
#define AXP22X_CHRG_CTRL3 0x35
9495

96+
#define AXP313A_ON_INDICATE 0x00
97+
#define AXP313A_OUTPUT_CONTROL 0x10
98+
#define AXP313A_DCDC1_CONRTOL 0x13
99+
#define AXP313A_DCDC2_CONRTOL 0x14
100+
#define AXP313A_DCDC3_CONRTOL 0x15
101+
#define AXP313A_ALDO1_CONRTOL 0x16
102+
#define AXP313A_DLDO1_CONRTOL 0x17
103+
#define AXP313A_SHUTDOWN_CTRL 0x1a
104+
#define AXP313A_IRQ_EN 0x20
105+
#define AXP313A_IRQ_STATE 0x21
106+
95107
#define AXP806_STARTUP_SRC 0x00
96108
#define AXP806_CHIP_ID 0x03
97109
#define AXP806_PWR_OUT_CTRL1 0x10
@@ -363,6 +375,16 @@ enum {
363375
AXP22X_REG_ID_MAX,
364376
};
365377

378+
enum {
379+
AXP313A_DCDC1 = 0,
380+
AXP313A_DCDC2,
381+
AXP313A_DCDC3,
382+
AXP313A_ALDO1,
383+
AXP313A_DLDO1,
384+
AXP313A_RTC_LDO,
385+
AXP313A_REG_ID_MAX,
386+
};
387+
366388
enum {
367389
AXP806_DCDCA = 0,
368390
AXP806_DCDCB,
@@ -616,6 +638,16 @@ enum axp288_irqs {
616638
AXP288_IRQ_BC_USB_CHNG,
617639
};
618640

641+
enum axp313a_irqs {
642+
AXP313A_IRQ_DIE_TEMP_HIGH,
643+
AXP313A_IRQ_DCDC2_V_LOW = 2,
644+
AXP313A_IRQ_DCDC3_V_LOW,
645+
AXP313A_IRQ_PEK_LONG,
646+
AXP313A_IRQ_PEK_SHORT,
647+
AXP313A_IRQ_PEK_FAL_EDGE,
648+
AXP313A_IRQ_PEK_RIS_EDGE,
649+
};
650+
619651
enum axp803_irqs {
620652
AXP803_IRQ_ACIN_OVER_V = 1,
621653
AXP803_IRQ_ACIN_PLUGIN,

0 commit comments

Comments
 (0)