summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
authorBoris BREZILLON <boris.brezillon@free-electrons.com>2015-04-10 07:09:01 +0300
committerLee Jones <lee.jones@linaro.org>2015-05-13 18:25:35 +0300
commitf05be589ff32e87821b86845625ed3d402d37dc7 (patch)
tree609fb7e7130f064651bd305a089ee0388ea6900d /drivers/mfd
parent5ebe6afaf0057ac3eaeb98defd5456894b446d22 (diff)
downloadlinux-f05be589ff32e87821b86845625ed3d402d37dc7.tar.xz
mfd: axp20x: Add AXP22x PMIC support
Add support for the AXP22x PMIC devices to the existing AXP20x driver. This includes the AXP221 and AXP223, which are identical except for the external data bus. Only AXP221 is added for now. AXP223 will be added after it's Reduced Serial Bus (RSB) interface is supported. AXP22x defines a new set of registers, power supplies and regulators, but most of the API is similar to the AXP20x ones. A new irq chip definition is used, even though the available interrupts on AXP22x is a subset of those on AXP20x. This is done so the interrupt numbers match those on the datasheet. This patch only enables the interrupts, system power-off function, and PEK sub-device. The regulator driver must first support different variants before we enable it from the mfd driver. Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com> [wens@csie.org: fix interrupts and move regulators to separate patch] Signed-off-by: Chen-Yu Tsai <wens@csie.org> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/axp20x.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index d18029be6a78..cfbb7d7aead6 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -32,6 +32,7 @@
static const char * const axp20x_model_names[] = {
"AXP202",
"AXP209",
+ "AXP221",
"AXP288",
};
@@ -54,6 +55,25 @@ static const struct regmap_access_table axp20x_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
};
+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 axp22x_volatile_ranges[] = {
+ regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+};
+
+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 axp22x_volatile_table = {
+ .yes_ranges = axp22x_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp22x_volatile_ranges),
+};
+
static const struct regmap_range axp288_writeable_ranges[] = {
regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
@@ -87,6 +107,20 @@ static struct resource axp20x_pek_resources[] = {
},
};
+static struct resource axp22x_pek_resources[] = {
+ {
+ .name = "PEK_DBR",
+ .start = AXP22X_IRQ_PEK_RIS_EDGE,
+ .end = AXP22X_IRQ_PEK_RIS_EDGE,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .name = "PEK_DBF",
+ .start = AXP22X_IRQ_PEK_FAL_EDGE,
+ .end = AXP22X_IRQ_PEK_FAL_EDGE,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static struct resource axp288_fuel_gauge_resources[] = {
{
.start = AXP288_IRQ_QWBTU,
@@ -129,6 +163,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 = &axp22x_volatile_table,
+ .max_register = AXP22X_BATLOW_THRES1,
+ .cache_type = REGCACHE_RBTREE,
+};
+
static const struct regmap_config axp288_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -181,6 +224,34 @@ static const struct regmap_irq axp20x_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT, 4, 0),
};
+static const struct regmap_irq axp22x_regmap_irqs[] = {
+ INIT_REGMAP_IRQ(AXP22X, ACIN_OVER_V, 0, 7),
+ INIT_REGMAP_IRQ(AXP22X, ACIN_PLUGIN, 0, 6),
+ INIT_REGMAP_IRQ(AXP22X, ACIN_REMOVAL, 0, 5),
+ INIT_REGMAP_IRQ(AXP22X, VBUS_OVER_V, 0, 4),
+ INIT_REGMAP_IRQ(AXP22X, VBUS_PLUGIN, 0, 3),
+ INIT_REGMAP_IRQ(AXP22X, VBUS_REMOVAL, 0, 2),
+ INIT_REGMAP_IRQ(AXP22X, VBUS_V_LOW, 0, 1),
+ INIT_REGMAP_IRQ(AXP22X, BATT_PLUGIN, 1, 7),
+ INIT_REGMAP_IRQ(AXP22X, BATT_REMOVAL, 1, 6),
+ INIT_REGMAP_IRQ(AXP22X, BATT_ENT_ACT_MODE, 1, 5),
+ INIT_REGMAP_IRQ(AXP22X, BATT_EXIT_ACT_MODE, 1, 4),
+ INIT_REGMAP_IRQ(AXP22X, CHARG, 1, 3),
+ INIT_REGMAP_IRQ(AXP22X, CHARG_DONE, 1, 2),
+ INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_HIGH, 1, 1),
+ INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_LOW, 1, 0),
+ INIT_REGMAP_IRQ(AXP22X, DIE_TEMP_HIGH, 2, 7),
+ INIT_REGMAP_IRQ(AXP22X, PEK_SHORT, 2, 1),
+ INIT_REGMAP_IRQ(AXP22X, PEK_LONG, 2, 0),
+ INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL1, 3, 1),
+ INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL2, 3, 0),
+ INIT_REGMAP_IRQ(AXP22X, TIMER, 4, 7),
+ INIT_REGMAP_IRQ(AXP22X, PEK_RIS_EDGE, 4, 6),
+ INIT_REGMAP_IRQ(AXP22X, PEK_FAL_EDGE, 4, 5),
+ INIT_REGMAP_IRQ(AXP22X, GPIO1_INPUT, 4, 1),
+ INIT_REGMAP_IRQ(AXP22X, GPIO0_INPUT, 4, 0),
+};
+
/* some IRQs are compatible with axp20x models */
static const struct regmap_irq axp288_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP288, VBUS_FALL, 0, 2),
@@ -224,6 +295,7 @@ static const struct regmap_irq axp288_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);
@@ -258,6 +330,18 @@ static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
};
+static const struct regmap_irq_chip axp22x_regmap_irq_chip = {
+ .name = "axp22x_irq_chip",
+ .status_base = AXP20X_IRQ1_STATE,
+ .ack_base = AXP20X_IRQ1_STATE,
+ .mask_base = AXP20X_IRQ1_EN,
+ .mask_invert = true,
+ .init_ack_masked = true,
+ .irqs = axp22x_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(axp22x_regmap_irqs),
+ .num_regs = 5,
+};
+
static const struct regmap_irq_chip axp288_regmap_irq_chip = {
.name = "axp288_irq_chip",
.status_base = AXP20X_IRQ1_STATE,
@@ -281,6 +365,14 @@ static struct mfd_cell axp20x_cells[] = {
},
};
+static struct mfd_cell axp22x_cells[] = {
+ {
+ .name = "axp20x-pek",
+ .num_resources = ARRAY_SIZE(axp22x_pek_resources),
+ .resources = axp22x_pek_resources,
+ },
+};
+
static struct resource axp288_adc_resources[] = {
{
.name = "GPADC",
@@ -426,6 +518,12 @@ static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev)
axp20x->regmap_cfg = &axp20x_regmap_config;
axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
break;
+ case AXP221_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp22x_cells);
+ axp20x->cells = axp22x_cells;
+ axp20x->regmap_cfg = &axp22x_regmap_config;
+ axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip;
+ break;
case AXP288_ID:
axp20x->cells = axp288_cells;
axp20x->nr_cells = ARRAY_SIZE(axp288_cells);