Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bb9f0d9 authored by Patrice Chotard's avatar Patrice Chotard Committed by Lee Jones
Browse files

mfd: Add STMPE1600 support

STMPE1600 is a 16-bit port expander.
Datasheet is available here :
http://www2.st.com/content/st_com/en/products/interfaces-and-transceivers/


i-o-expanders-and-level-translators/i-o-expanders/stmpe1600.html

Signed-off-by: default avatarAmelie DELAUNAY <amelie.delaunay@st.com>
Signed-off-by: default avatarPatrice Chotard <patrice.chotard@st.com>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent bd495916
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ static const struct of_device_id stmpe_of_match[] = {
	{ .compatible = "st,stmpe610", .data = (void *)STMPE610, },
	{ .compatible = "st,stmpe801", .data = (void *)STMPE801, },
	{ .compatible = "st,stmpe811", .data = (void *)STMPE811, },
	{ .compatible = "st,stmpe1600", .data = (void *)STMPE1600, },
	{ .compatible = "st,stmpe1601", .data = (void *)STMPE1601, },
	{ .compatible = "st,stmpe1801", .data = (void *)STMPE1801, },
	{ .compatible = "st,stmpe2401", .data = (void *)STMPE2401, },
@@ -101,6 +102,7 @@ static const struct i2c_device_id stmpe_i2c_id[] = {
	{ "stmpe610", STMPE610 },
	{ "stmpe801", STMPE801 },
	{ "stmpe811", STMPE811 },
	{ "stmpe1600", STMPE1600 },
	{ "stmpe1601", STMPE1601 },
	{ "stmpe1801", STMPE1801 },
	{ "stmpe2401", STMPE2401 },
+60 −5
Original line number Diff line number Diff line
@@ -552,6 +552,59 @@ static struct stmpe_variant_info stmpe610 = {
	.get_altfunc	= stmpe811_get_altfunc,
};

/*
 * STMPE1600
 * Compared to all others STMPE variant, LSB and MSB regs are located in this
 * order :	LSB   addr
 *		MSB   addr + 1
 * As there is only 2 * 8bits registers for GPMR/GPSR/IEGPIOPR, CSB index is MSB registers
 */

static const u8 stmpe1600_regs[] = {
	[STMPE_IDX_CHIP_ID]	= STMPE1600_REG_CHIP_ID,
	[STMPE_IDX_SYS_CTRL]	= STMPE1600_REG_SYS_CTRL,
	[STMPE_IDX_ICR_LSB]	= STMPE1600_REG_SYS_CTRL,
	[STMPE_IDX_GPMR_LSB]	= STMPE1600_REG_GPMR_LSB,
	[STMPE_IDX_GPMR_CSB]	= STMPE1600_REG_GPMR_MSB,
	[STMPE_IDX_GPSR_LSB]	= STMPE1600_REG_GPSR_LSB,
	[STMPE_IDX_GPSR_CSB]	= STMPE1600_REG_GPSR_MSB,
	[STMPE_IDX_GPDR_LSB]	= STMPE1600_REG_GPDR_LSB,
	[STMPE_IDX_GPDR_CSB]	= STMPE1600_REG_GPDR_MSB,
	[STMPE_IDX_IEGPIOR_LSB]	= STMPE1600_REG_IEGPIOR_LSB,
	[STMPE_IDX_IEGPIOR_CSB]	= STMPE1600_REG_IEGPIOR_MSB,
	[STMPE_IDX_ISGPIOR_LSB]	= STMPE1600_REG_ISGPIOR_LSB,
};

static struct stmpe_variant_block stmpe1600_blocks[] = {
	{
		.cell	= &stmpe_gpio_cell,
		.irq	= 0,
		.block	= STMPE_BLOCK_GPIO,
	},
};

static int stmpe1600_enable(struct stmpe *stmpe, unsigned int blocks,
			   bool enable)
{
	if (blocks & STMPE_BLOCK_GPIO)
		return 0;
	else
		return -EINVAL;
}

static struct stmpe_variant_info stmpe1600 = {
	.name		= "stmpe1600",
	.id_val		= STMPE1600_ID,
	.id_mask	= 0xffff,
	.num_gpios	= 16,
	.af_bits	= 0,
	.regs		= stmpe1600_regs,
	.blocks		= stmpe1600_blocks,
	.num_blocks	= ARRAY_SIZE(stmpe1600_blocks),
	.num_irqs	= STMPE1600_NR_INTERNAL_IRQS,
	.enable		= stmpe1600_enable,
};

/*
 * STMPE1601
 */
@@ -949,6 +1002,7 @@ static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
	[STMPE610]	= &stmpe610,
	[STMPE801]	= &stmpe801,
	[STMPE811]	= &stmpe811,
	[STMPE1600]	= &stmpe1600,
	[STMPE1601]	= &stmpe1601,
	[STMPE1801]	= &stmpe1801,
	[STMPE2401]	= &stmpe2401,
@@ -975,7 +1029,8 @@ static irqreturn_t stmpe_irq(int irq, void *data)
	int ret;
	int i;

	if (variant->id_val == STMPE801_ID) {
	if (variant->id_val == STMPE801_ID ||
	    variant->id_val == STMPE1600_ID) {
		int base = irq_create_mapping(stmpe->domain, 0);

		handle_nested_irq(base);
@@ -1149,13 +1204,13 @@ static int stmpe_chip_init(struct stmpe *stmpe)
		return ret;

	if (stmpe->irq >= 0) {
		if (id == STMPE801_ID)
		if (id == STMPE801_ID || id == STMPE1600_ID)
			icr = STMPE_SYS_CTRL_INT_EN;
		else
			icr = STMPE_ICR_LSB_GIM;

		/* STMPE801 doesn't support Edge interrupts */
		if (id != STMPE801_ID) {
		/* STMPE801 and STMPE1600 don't support Edge interrupts */
		if (id != STMPE801_ID && id != STMPE1600_ID) {
			if (irq_trigger == IRQF_TRIGGER_FALLING ||
					irq_trigger == IRQF_TRIGGER_RISING)
				icr |= STMPE_ICR_LSB_EDGE;
@@ -1163,7 +1218,7 @@ static int stmpe_chip_init(struct stmpe *stmpe)

		if (irq_trigger == IRQF_TRIGGER_RISING ||
				irq_trigger == IRQF_TRIGGER_HIGH) {
			if (id == STMPE801_ID)
			if (id == STMPE801_ID || id == STMPE1600_ID)
				icr |= STMPE_SYS_CTRL_INT_HI;
			else
				icr |= STMPE_ICR_LSB_HIGH;
+21 −0
Original line number Diff line number Diff line
@@ -163,6 +163,27 @@ int stmpe_remove(struct stmpe *stmpe);
#define STMPE811_SYS_CTRL2_GPIO_OFF	(1 << 2)
#define STMPE811_SYS_CTRL2_TS_OFF	(1 << 3)

/*
 * STMPE1600
 */
#define STMPE1600_ID			0x0016
#define STMPE1600_NR_INTERNAL_IRQS	16

#define STMPE1600_REG_CHIP_ID		0x00
#define STMPE1600_REG_SYS_CTRL		0x03
#define STMPE1600_REG_IEGPIOR_LSB	0x08
#define STMPE1600_REG_IEGPIOR_MSB	0x09
#define STMPE1600_REG_ISGPIOR_LSB	0x0A
#define STMPE1600_REG_ISGPIOR_MSB	0x0B
#define STMPE1600_REG_GPMR_LSB		0x10
#define STMPE1600_REG_GPMR_MSB		0x11
#define STMPE1600_REG_GPSR_LSB		0x12
#define STMPE1600_REG_GPSR_MSB		0x13
#define STMPE1600_REG_GPDR_LSB		0x14
#define STMPE1600_REG_GPDR_MSB		0x15
#define STMPE1600_REG_GPPIR_LSB		0x16
#define STMPE1600_REG_GPPIR_MSB		0x17

/*
 * STMPE1601
 */
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ enum stmpe_partnum {
	STMPE610,
	STMPE801,
	STMPE811,
	STMPE1600,
	STMPE1601,
	STMPE1801,
	STMPE2401,