summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorChen-Yu Tsai <wens@csie.org>2016-08-27 15:55:38 +0800
committerLee Jones <lee.jones@linaro.org>2016-09-13 14:10:04 +0100
commit8824ee8573483e1c91691b5be3d3730e75551dce (patch)
tree7a3b45b900a1432d5a433d7d8158dacf071afec7 /drivers
parent204ae2963e101344e50e3a679912f795e6b852c5 (diff)
mfd: axp20x: Add support for AXP806 PMIC
The X-Powers AXP806 is a new PMIC that is paired with Allwinner's A80 SoC, along with a master AXP809 PMIC. This PMIC has a new register layout, and supports some functions not seen in other X-Powers PMICs, such as master-slave mode, or having multiple AXP806 PMICs on the same bus with address space extension, or supporting both I2C and RSB mode. I2C has not been tested. This patch adds support for the interrupts of the PMIC. A regulator sub-device is enabled, but actual regulator support will come in a later patch. Signed-off-by: Chen-Yu Tsai <wens@csie.org> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/axp20x-rsb.c1
-rw-r--r--drivers/mfd/axp20x.c72
2 files changed, 73 insertions, 0 deletions
diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c
index a407527bcd09..a732cb50bcff 100644
--- a/drivers/mfd/axp20x-rsb.c
+++ b/drivers/mfd/axp20x-rsb.c
@@ -61,6 +61,7 @@ static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev)
static const struct of_device_id axp20x_rsb_of_match[] = {
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
+ { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
{ .compatible = "x-powers,axp809", .data = (void *)AXP809_ID },
{ },
};
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index fd80b0981f0f..96102753847f 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -38,6 +38,7 @@ static const char * const axp20x_model_names[] = {
"AXP221",
"AXP223",
"AXP288",
+ "AXP806",
"AXP809",
};
@@ -129,6 +130,27 @@ static const struct regmap_access_table axp288_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(axp288_volatile_ranges),
};
+static const struct regmap_range axp806_writeable_ranges[] = {
+ regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)),
+ regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
+ regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ2_EN),
+ regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
+};
+
+static const struct regmap_range axp806_volatile_ranges[] = {
+ regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
+};
+
+static const struct regmap_access_table axp806_writeable_table = {
+ .yes_ranges = axp806_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp806_writeable_ranges),
+};
+
+static const struct regmap_access_table axp806_volatile_table = {
+ .yes_ranges = axp806_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
+};
+
static struct resource axp152_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -278,6 +300,15 @@ static const struct regmap_config axp288_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
+static const struct regmap_config axp806_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .wr_table = &axp806_writeable_table,
+ .volatile_table = &axp806_volatile_table,
+ .max_register = AXP806_VREF_TEMP_WARN_L,
+ .cache_type = REGCACHE_RBTREE,
+};
+
#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \
[_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
@@ -409,6 +440,21 @@ static const struct regmap_irq axp288_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1),
};
+static const struct regmap_irq axp806_regmap_irqs[] = {
+ INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV1, 0, 0),
+ INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV2, 0, 1),
+ INIT_REGMAP_IRQ(AXP806, DCDCA_V_LOW, 0, 3),
+ INIT_REGMAP_IRQ(AXP806, DCDCB_V_LOW, 0, 4),
+ INIT_REGMAP_IRQ(AXP806, DCDCC_V_LOW, 0, 5),
+ INIT_REGMAP_IRQ(AXP806, DCDCD_V_LOW, 0, 6),
+ INIT_REGMAP_IRQ(AXP806, DCDCE_V_LOW, 0, 7),
+ INIT_REGMAP_IRQ(AXP806, PWROK_LONG, 1, 0),
+ INIT_REGMAP_IRQ(AXP806, PWROK_SHORT, 1, 1),
+ INIT_REGMAP_IRQ(AXP806, WAKEUP, 1, 4),
+ INIT_REGMAP_IRQ(AXP806, PWROK_FALL, 1, 5),
+ INIT_REGMAP_IRQ(AXP806, PWROK_RISE, 1, 6),
+};
+
static const struct regmap_irq axp809_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V, 0, 7),
INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN, 0, 6),
@@ -494,6 +540,18 @@ static const struct regmap_irq_chip axp288_regmap_irq_chip = {
};
+static const struct regmap_irq_chip axp806_regmap_irq_chip = {
+ .name = "axp806",
+ .status_base = AXP20X_IRQ1_STATE,
+ .ack_base = AXP20X_IRQ1_STATE,
+ .mask_base = AXP20X_IRQ1_EN,
+ .mask_invert = true,
+ .init_ack_masked = true,
+ .irqs = axp806_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(axp806_regmap_irqs),
+ .num_regs = 2,
+};
+
static const struct regmap_irq_chip axp809_regmap_irq_chip = {
.name = "axp809",
.status_base = AXP20X_IRQ1_STATE,
@@ -660,12 +718,20 @@ static struct mfd_cell axp288_cells[] = {
},
};
+static struct mfd_cell axp806_cells[] = {
+ {
+ .id = 2,
+ .name = "axp20x-regulator",
+ },
+};
+
static struct mfd_cell axp809_cells[] = {
{
.name = "axp20x-pek",
.num_resources = ARRAY_SIZE(axp809_pek_resources),
.resources = axp809_pek_resources,
}, {
+ .id = 1,
.name = "axp20x-regulator",
},
};
@@ -732,6 +798,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_cfg = &axp288_regmap_config;
axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
break;
+ case AXP806_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
+ axp20x->cells = axp806_cells;
+ axp20x->regmap_cfg = &axp806_regmap_config;
+ axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
+ break;
case AXP809_ID:
axp20x->nr_cells = ARRAY_SIZE(axp809_cells);
axp20x->cells = axp809_cells;