Skip to content

Commit e0f8ad2

Browse files
Headcrabedlag-linaro
authored andcommitted
mfd: axp20x: Add support for AXP15060 PMIC
The AXP15060 is a PMIC chip produced by X-Powers, and could be connected via an I2C bus. Describe the regmap and the MFD bits, along with the registers exposed via I2C. Eventually advertise the device using a new compatible string and add support for power off the system. The driver would disable PEK function if IRQ is not configured in device tree, since some boards (For example, Starfive Visionfive 2) didn't connect IRQ line of PMIC to SOC. GPIO function isn't enabled in this commit, since its configuration operation is different from any existing AXP PMICs and needs logic modification on existing driver. GPIO support might come in later patches. Signed-off-by: Shengyu Qu <wiagn233@outlook.com> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Signed-off-by: Lee Jones <lee@kernel.org> Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB2611.JPNP286.PROD.OUTLOOK.COM
1 parent a33c6a2 commit e0f8ad2

3 files changed

Lines changed: 194 additions & 0 deletions

File tree

drivers/mfd/axp20x-i2c.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
6565
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
6666
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
6767
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
68+
{ .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
6869
{ },
6970
};
7071
MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
@@ -78,6 +79,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
7879
{ "axp223", 0 },
7980
{ "axp803", 0 },
8081
{ "axp806", 0 },
82+
{ "axp15060", 0 },
8183
{ },
8284
};
8385
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);

drivers/mfd/axp20x.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ static const char * const axp20x_model_names[] = {
4343
"AXP806",
4444
"AXP809",
4545
"AXP813",
46+
"AXP15060",
4647
};
4748

4849
static const struct regmap_range axp152_writeable_ranges[] = {
@@ -169,6 +170,31 @@ static const struct regmap_access_table axp806_volatile_table = {
169170
.n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
170171
};
171172

173+
static const struct regmap_range axp15060_writeable_ranges[] = {
174+
regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2),
175+
regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL),
176+
regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
177+
regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY),
178+
regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN),
179+
regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
180+
};
181+
182+
static const struct regmap_range axp15060_volatile_ranges[] = {
183+
regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC),
184+
regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
185+
regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
186+
};
187+
188+
static const struct regmap_access_table axp15060_writeable_table = {
189+
.yes_ranges = axp15060_writeable_ranges,
190+
.n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges),
191+
};
192+
193+
static const struct regmap_access_table axp15060_volatile_table = {
194+
.yes_ranges = axp15060_volatile_ranges,
195+
.n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges),
196+
};
197+
172198
static const struct resource axp152_pek_resources[] = {
173199
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
174200
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -237,6 +263,11 @@ static const struct resource axp809_pek_resources[] = {
237263
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
238264
};
239265

266+
static const struct resource axp15060_pek_resources[] = {
267+
DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
268+
DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
269+
};
270+
240271
static const struct regmap_config axp152_regmap_config = {
241272
.reg_bits = 8,
242273
.val_bits = 8,
@@ -282,6 +313,15 @@ static const struct regmap_config axp806_regmap_config = {
282313
.cache_type = REGCACHE_RBTREE,
283314
};
284315

316+
static const struct regmap_config axp15060_regmap_config = {
317+
.reg_bits = 8,
318+
.val_bits = 8,
319+
.wr_table = &axp15060_writeable_table,
320+
.volatile_table = &axp15060_volatile_table,
321+
.max_register = AXP15060_IRQ2_STATE,
322+
.cache_type = REGCACHE_RBTREE,
323+
};
324+
285325
#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \
286326
[_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
287327

@@ -503,6 +543,23 @@ static const struct regmap_irq axp809_regmap_irqs[] = {
503543
INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0),
504544
};
505545

546+
static const struct regmap_irq axp15060_regmap_irqs[] = {
547+
INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0),
548+
INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1),
549+
INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2),
550+
INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3),
551+
INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4),
552+
INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5),
553+
INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6),
554+
INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7),
555+
INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0),
556+
INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1),
557+
INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2),
558+
INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3),
559+
INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4),
560+
INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5),
561+
};
562+
506563
static const struct regmap_irq_chip axp152_regmap_irq_chip = {
507564
.name = "axp152_irq_chip",
508565
.status_base = AXP152_IRQ1_STATE,
@@ -582,6 +639,17 @@ static const struct regmap_irq_chip axp809_regmap_irq_chip = {
582639
.num_regs = 5,
583640
};
584641

642+
static const struct regmap_irq_chip axp15060_regmap_irq_chip = {
643+
.name = "axp15060",
644+
.status_base = AXP15060_IRQ1_STATE,
645+
.ack_base = AXP15060_IRQ1_STATE,
646+
.unmask_base = AXP15060_IRQ1_EN,
647+
.init_ack_masked = true,
648+
.irqs = axp15060_regmap_irqs,
649+
.num_irqs = ARRAY_SIZE(axp15060_regmap_irqs),
650+
.num_regs = 2,
651+
};
652+
585653
static const struct mfd_cell axp20x_cells[] = {
586654
{
587655
.name = "axp20x-gpio",
@@ -826,6 +894,23 @@ static const struct mfd_cell axp813_cells[] = {
826894
},
827895
};
828896

897+
static const struct mfd_cell axp15060_cells[] = {
898+
{
899+
.name = "axp221-pek",
900+
.num_resources = ARRAY_SIZE(axp15060_pek_resources),
901+
.resources = axp15060_pek_resources,
902+
}, {
903+
.name = "axp20x-regulator",
904+
},
905+
};
906+
907+
/* For boards that don't have IRQ line connected to SOC. */
908+
static const struct mfd_cell axp_regulator_only_cells[] = {
909+
{
910+
.name = "axp20x-regulator",
911+
},
912+
};
913+
829914
static int axp20x_power_off(struct sys_off_data *data)
830915
{
831916
struct axp20x_dev *axp20x = data->cb_data;
@@ -935,6 +1020,28 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
9351020
*/
9361021
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
9371022
break;
1023+
case AXP15060_ID:
1024+
/*
1025+
* Don't register the power key part if there is no interrupt
1026+
* line.
1027+
*
1028+
* Since most use cases of AXP PMICs are Allwinner SOCs, board
1029+
* designers follow Allwinner's reference design and connects
1030+
* IRQ line to SOC, there's no need for those variants to deal
1031+
* with cases that IRQ isn't connected. However, AXP15660 is
1032+
* used by some other vendors' SOCs that didn't connect IRQ
1033+
* line, we need to deal with this case.
1034+
*/
1035+
if (axp20x->irq > 0) {
1036+
axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
1037+
axp20x->cells = axp15060_cells;
1038+
} else {
1039+
axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
1040+
axp20x->cells = axp_regulator_only_cells;
1041+
}
1042+
axp20x->regmap_cfg = &axp15060_regmap_config;
1043+
axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
1044+
break;
9381045
default:
9391046
dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
9401047
return -EINVAL;

include/linux/mfd/axp20x.h

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ enum axp20x_variants {
2121
AXP806_ID,
2222
AXP809_ID,
2323
AXP813_ID,
24+
AXP15060_ID,
2425
NR_AXP20X_VARIANTS,
2526
};
2627

@@ -131,6 +132,39 @@ enum axp20x_variants {
131132
/* Other DCDC regulator control registers are the same as AXP803 */
132133
#define AXP813_DCDC7_V_OUT 0x26
133134

135+
#define AXP15060_STARTUP_SRC 0x00
136+
#define AXP15060_PWR_OUT_CTRL1 0x10
137+
#define AXP15060_PWR_OUT_CTRL2 0x11
138+
#define AXP15060_PWR_OUT_CTRL3 0x12
139+
#define AXP15060_DCDC1_V_CTRL 0x13
140+
#define AXP15060_DCDC2_V_CTRL 0x14
141+
#define AXP15060_DCDC3_V_CTRL 0x15
142+
#define AXP15060_DCDC4_V_CTRL 0x16
143+
#define AXP15060_DCDC5_V_CTRL 0x17
144+
#define AXP15060_DCDC6_V_CTRL 0x18
145+
#define AXP15060_ALDO1_V_CTRL 0x19
146+
#define AXP15060_DCDC_MODE_CTRL1 0x1a
147+
#define AXP15060_DCDC_MODE_CTRL2 0x1b
148+
#define AXP15060_OUTPUT_MONITOR_DISCHARGE 0x1e
149+
#define AXP15060_IRQ_PWROK_VOFF 0x1f
150+
#define AXP15060_ALDO2_V_CTRL 0x20
151+
#define AXP15060_ALDO3_V_CTRL 0x21
152+
#define AXP15060_ALDO4_V_CTRL 0x22
153+
#define AXP15060_ALDO5_V_CTRL 0x23
154+
#define AXP15060_BLDO1_V_CTRL 0x24
155+
#define AXP15060_BLDO2_V_CTRL 0x25
156+
#define AXP15060_BLDO3_V_CTRL 0x26
157+
#define AXP15060_BLDO4_V_CTRL 0x27
158+
#define AXP15060_BLDO5_V_CTRL 0x28
159+
#define AXP15060_CLDO1_V_CTRL 0x29
160+
#define AXP15060_CLDO2_V_CTRL 0x2a
161+
#define AXP15060_CLDO3_V_CTRL 0x2b
162+
#define AXP15060_CLDO4_V_CTRL 0x2d
163+
#define AXP15060_CPUSLDO_V_CTRL 0x2e
164+
#define AXP15060_PWR_WAKEUP_CTRL 0x31
165+
#define AXP15060_PWR_DISABLE_DOWN_SEQ 0x32
166+
#define AXP15060_PEK_KEY 0x36
167+
134168
/* Interrupt */
135169
#define AXP152_IRQ1_EN 0x40
136170
#define AXP152_IRQ2_EN 0x41
@@ -152,6 +186,11 @@ enum axp20x_variants {
152186
#define AXP20X_IRQ5_STATE 0x4c
153187
#define AXP20X_IRQ6_STATE 0x4d
154188

189+
#define AXP15060_IRQ1_EN 0x40
190+
#define AXP15060_IRQ2_EN 0x41
191+
#define AXP15060_IRQ1_STATE 0x48
192+
#define AXP15060_IRQ2_STATE 0x49
193+
155194
/* ADC */
156195
#define AXP20X_ACIN_V_ADC_H 0x56
157196
#define AXP20X_ACIN_V_ADC_L 0x57
@@ -222,6 +261,8 @@ enum axp20x_variants {
222261
#define AXP22X_GPIO_STATE 0x94
223262
#define AXP22X_GPIO_PULL_DOWN 0x95
224263

264+
#define AXP15060_CLDO4_GPIO2_MODESET 0x2c
265+
225266
/* Battery */
226267
#define AXP20X_CHRG_CC_31_24 0xb0
227268
#define AXP20X_CHRG_CC_23_16 0xb1
@@ -419,6 +460,33 @@ enum {
419460
AXP813_REG_ID_MAX,
420461
};
421462

463+
enum {
464+
AXP15060_DCDC1 = 0,
465+
AXP15060_DCDC2,
466+
AXP15060_DCDC3,
467+
AXP15060_DCDC4,
468+
AXP15060_DCDC5,
469+
AXP15060_DCDC6,
470+
AXP15060_ALDO1,
471+
AXP15060_ALDO2,
472+
AXP15060_ALDO3,
473+
AXP15060_ALDO4,
474+
AXP15060_ALDO5,
475+
AXP15060_BLDO1,
476+
AXP15060_BLDO2,
477+
AXP15060_BLDO3,
478+
AXP15060_BLDO4,
479+
AXP15060_BLDO5,
480+
AXP15060_CLDO1,
481+
AXP15060_CLDO2,
482+
AXP15060_CLDO3,
483+
AXP15060_CLDO4,
484+
AXP15060_CPUSLDO,
485+
AXP15060_SW,
486+
AXP15060_RTC_LDO,
487+
AXP15060_REG_ID_MAX,
488+
};
489+
422490
/* IRQs */
423491
enum {
424492
AXP152_IRQ_LDO0IN_CONNECT = 1,
@@ -637,6 +705,23 @@ enum axp809_irqs {
637705
AXP809_IRQ_GPIO0_INPUT,
638706
};
639707

708+
enum axp15060_irqs {
709+
AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1,
710+
AXP15060_IRQ_DIE_TEMP_HIGH_LV2,
711+
AXP15060_IRQ_DCDC1_V_LOW,
712+
AXP15060_IRQ_DCDC2_V_LOW,
713+
AXP15060_IRQ_DCDC3_V_LOW,
714+
AXP15060_IRQ_DCDC4_V_LOW,
715+
AXP15060_IRQ_DCDC5_V_LOW,
716+
AXP15060_IRQ_DCDC6_V_LOW,
717+
AXP15060_IRQ_PEK_LONG,
718+
AXP15060_IRQ_PEK_SHORT,
719+
AXP15060_IRQ_GPIO1_INPUT,
720+
AXP15060_IRQ_PEK_FAL_EDGE,
721+
AXP15060_IRQ_PEK_RIS_EDGE,
722+
AXP15060_IRQ_GPIO2_INPUT,
723+
};
724+
640725
struct axp20x_dev {
641726
struct device *dev;
642727
int irq;

0 commit comments

Comments
 (0)