diff options
Diffstat (limited to 'drivers/mfd/axp20x.c')
| -rw-r--r-- | drivers/mfd/axp20x.c | 108 | 
1 files changed, 108 insertions, 0 deletions
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 01a6bbb6d266..72b87aae60cc 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -43,6 +43,7 @@ static const char * const axp20x_model_names[] = {  	"AXP806",  	"AXP809",  	"AXP813", +	"AXP15060",  };  static const struct regmap_range axp152_writeable_ranges[] = { @@ -119,6 +120,7 @@ static const struct regmap_access_table axp22x_volatile_table = {  /* AXP288 ranges are shared with the AXP803, as they cover the same range */  static const struct regmap_range axp288_writeable_ranges[] = { +	regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON),  	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),  	regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),  }; @@ -168,6 +170,31 @@ static const struct regmap_access_table axp806_volatile_table = {  	.n_yes_ranges	= ARRAY_SIZE(axp806_volatile_ranges),  }; +static const struct regmap_range axp15060_writeable_ranges[] = { +	regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2), +	regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL), +	regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), +	regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY), +	regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN), +	regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), +}; + +static const struct regmap_range axp15060_volatile_ranges[] = { +	regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC), +	regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), +	regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), +}; + +static const struct regmap_access_table axp15060_writeable_table = { +	.yes_ranges	= axp15060_writeable_ranges, +	.n_yes_ranges	= ARRAY_SIZE(axp15060_writeable_ranges), +}; + +static const struct regmap_access_table axp15060_volatile_table = { +	.yes_ranges	= axp15060_volatile_ranges, +	.n_yes_ranges	= ARRAY_SIZE(axp15060_volatile_ranges), +}; +  static const 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"), @@ -236,6 +263,11 @@ static const struct resource axp809_pek_resources[] = {  	DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),  }; +static const struct resource axp15060_pek_resources[] = { +	DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"), +	DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"), +}; +  static const struct regmap_config axp152_regmap_config = {  	.reg_bits	= 8,  	.val_bits	= 8, @@ -281,6 +313,15 @@ static const struct regmap_config axp806_regmap_config = {  	.cache_type	= REGCACHE_RBTREE,  }; +static const struct regmap_config axp15060_regmap_config = { +	.reg_bits	= 8, +	.val_bits	= 8, +	.wr_table	= &axp15060_writeable_table, +	.volatile_table	= &axp15060_volatile_table, +	.max_register	= AXP15060_IRQ2_STATE, +	.cache_type	= REGCACHE_RBTREE, +}; +  #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask)			\  	[_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } @@ -502,6 +543,23 @@ static const struct regmap_irq axp809_regmap_irqs[] = {  	INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT,		4, 0),  }; +static const struct regmap_irq axp15060_regmap_irqs[] = { +	INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1,	0, 0), +	INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2,	0, 1), +	INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW,		0, 2), +	INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW,		0, 3), +	INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW,		0, 4), +	INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW,		0, 5), +	INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW,		0, 6), +	INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW,		0, 7), +	INIT_REGMAP_IRQ(AXP15060, PEK_LONG,			1, 0), +	INIT_REGMAP_IRQ(AXP15060, PEK_SHORT,			1, 1), +	INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT,		1, 2), +	INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE,			1, 3), +	INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE,			1, 4), +	INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT,		1, 5), +}; +  static const struct regmap_irq_chip axp152_regmap_irq_chip = {  	.name			= "axp152_irq_chip",  	.status_base		= AXP152_IRQ1_STATE, @@ -581,6 +639,17 @@ static const struct regmap_irq_chip axp809_regmap_irq_chip = {  	.num_regs		= 5,  }; +static const struct regmap_irq_chip axp15060_regmap_irq_chip = { +	.name			= "axp15060", +	.status_base		= AXP15060_IRQ1_STATE, +	.ack_base		= AXP15060_IRQ1_STATE, +	.unmask_base		= AXP15060_IRQ1_EN, +	.init_ack_masked	= true, +	.irqs			= axp15060_regmap_irqs, +	.num_irqs		= ARRAY_SIZE(axp15060_regmap_irqs), +	.num_regs		= 2, +}; +  static const struct mfd_cell axp20x_cells[] = {  	{  		.name		= "axp20x-gpio", @@ -825,6 +894,23 @@ static const struct mfd_cell axp813_cells[] = {  	},  }; +static const struct mfd_cell axp15060_cells[] = { +	{ +		.name		= "axp221-pek", +		.num_resources	= ARRAY_SIZE(axp15060_pek_resources), +		.resources	= axp15060_pek_resources, +	}, { +		.name		= "axp20x-regulator", +	}, +}; + +/* For boards that don't have IRQ line connected to SOC. */ +static const struct mfd_cell axp_regulator_only_cells[] = { +	{ +		.name		= "axp20x-regulator", +	}, +}; +  static int axp20x_power_off(struct sys_off_data *data)  {  	struct axp20x_dev *axp20x = data->cb_data; @@ -934,6 +1020,28 @@ int axp20x_match_device(struct axp20x_dev *axp20x)  		 */  		axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;  		break; +	case AXP15060_ID: +		/* +		 * Don't register the power key part if there is no interrupt +		 * line. +		 * +		 * Since most use cases of AXP PMICs are Allwinner SOCs, board +		 * designers follow Allwinner's reference design and connects +		 * IRQ line to SOC, there's no need for those variants to deal +		 * with cases that IRQ isn't connected. However, AXP15660 is +		 * used by some other vendors' SOCs that didn't connect IRQ +		 * line, we need to deal with this case. +		 */ +		if (axp20x->irq > 0) { +			axp20x->nr_cells = ARRAY_SIZE(axp15060_cells); +			axp20x->cells = axp15060_cells; +		} else { +			axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells); +			axp20x->cells = axp_regulator_only_cells; +		} +		axp20x->regmap_cfg = &axp15060_regmap_config; +		axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip; +		break;  	default:  		dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);  		return -EINVAL;  |