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

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
...@@ -57,6 +57,7 @@ static const struct of_device_id stmpe_of_match[] = { ...@@ -57,6 +57,7 @@ static const struct of_device_id stmpe_of_match[] = {
{ .compatible = "st,stmpe610", .data = (void *)STMPE610, }, { .compatible = "st,stmpe610", .data = (void *)STMPE610, },
{ .compatible = "st,stmpe801", .data = (void *)STMPE801, }, { .compatible = "st,stmpe801", .data = (void *)STMPE801, },
{ .compatible = "st,stmpe811", .data = (void *)STMPE811, }, { .compatible = "st,stmpe811", .data = (void *)STMPE811, },
{ .compatible = "st,stmpe1600", .data = (void *)STMPE1600, },
{ .compatible = "st,stmpe1601", .data = (void *)STMPE1601, }, { .compatible = "st,stmpe1601", .data = (void *)STMPE1601, },
{ .compatible = "st,stmpe1801", .data = (void *)STMPE1801, }, { .compatible = "st,stmpe1801", .data = (void *)STMPE1801, },
{ .compatible = "st,stmpe2401", .data = (void *)STMPE2401, }, { .compatible = "st,stmpe2401", .data = (void *)STMPE2401, },
...@@ -101,6 +102,7 @@ static const struct i2c_device_id stmpe_i2c_id[] = { ...@@ -101,6 +102,7 @@ static const struct i2c_device_id stmpe_i2c_id[] = {
{ "stmpe610", STMPE610 }, { "stmpe610", STMPE610 },
{ "stmpe801", STMPE801 }, { "stmpe801", STMPE801 },
{ "stmpe811", STMPE811 }, { "stmpe811", STMPE811 },
{ "stmpe1600", STMPE1600 },
{ "stmpe1601", STMPE1601 }, { "stmpe1601", STMPE1601 },
{ "stmpe1801", STMPE1801 }, { "stmpe1801", STMPE1801 },
{ "stmpe2401", STMPE2401 }, { "stmpe2401", STMPE2401 },
......
...@@ -552,6 +552,59 @@ static struct stmpe_variant_info stmpe610 = { ...@@ -552,6 +552,59 @@ static struct stmpe_variant_info stmpe610 = {
.get_altfunc = stmpe811_get_altfunc, .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 * STMPE1601
*/ */
...@@ -949,6 +1002,7 @@ static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = { ...@@ -949,6 +1002,7 @@ static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
[STMPE610] = &stmpe610, [STMPE610] = &stmpe610,
[STMPE801] = &stmpe801, [STMPE801] = &stmpe801,
[STMPE811] = &stmpe811, [STMPE811] = &stmpe811,
[STMPE1600] = &stmpe1600,
[STMPE1601] = &stmpe1601, [STMPE1601] = &stmpe1601,
[STMPE1801] = &stmpe1801, [STMPE1801] = &stmpe1801,
[STMPE2401] = &stmpe2401, [STMPE2401] = &stmpe2401,
...@@ -975,7 +1029,8 @@ static irqreturn_t stmpe_irq(int irq, void *data) ...@@ -975,7 +1029,8 @@ static irqreturn_t stmpe_irq(int irq, void *data)
int ret; int ret;
int i; 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); int base = irq_create_mapping(stmpe->domain, 0);
handle_nested_irq(base); handle_nested_irq(base);
...@@ -1149,13 +1204,13 @@ static int stmpe_chip_init(struct stmpe *stmpe) ...@@ -1149,13 +1204,13 @@ static int stmpe_chip_init(struct stmpe *stmpe)
return ret; return ret;
if (stmpe->irq >= 0) { if (stmpe->irq >= 0) {
if (id == STMPE801_ID) if (id == STMPE801_ID || id == STMPE1600_ID)
icr = STMPE_SYS_CTRL_INT_EN; icr = STMPE_SYS_CTRL_INT_EN;
else else
icr = STMPE_ICR_LSB_GIM; icr = STMPE_ICR_LSB_GIM;
/* STMPE801 doesn't support Edge interrupts */ /* STMPE801 and STMPE1600 don't support Edge interrupts */
if (id != STMPE801_ID) { if (id != STMPE801_ID && id != STMPE1600_ID) {
if (irq_trigger == IRQF_TRIGGER_FALLING || if (irq_trigger == IRQF_TRIGGER_FALLING ||
irq_trigger == IRQF_TRIGGER_RISING) irq_trigger == IRQF_TRIGGER_RISING)
icr |= STMPE_ICR_LSB_EDGE; icr |= STMPE_ICR_LSB_EDGE;
...@@ -1163,7 +1218,7 @@ static int stmpe_chip_init(struct stmpe *stmpe) ...@@ -1163,7 +1218,7 @@ static int stmpe_chip_init(struct stmpe *stmpe)
if (irq_trigger == IRQF_TRIGGER_RISING || if (irq_trigger == IRQF_TRIGGER_RISING ||
irq_trigger == IRQF_TRIGGER_HIGH) { irq_trigger == IRQF_TRIGGER_HIGH) {
if (id == STMPE801_ID) if (id == STMPE801_ID || id == STMPE1600_ID)
icr |= STMPE_SYS_CTRL_INT_HI; icr |= STMPE_SYS_CTRL_INT_HI;
else else
icr |= STMPE_ICR_LSB_HIGH; icr |= STMPE_ICR_LSB_HIGH;
......
...@@ -163,6 +163,27 @@ int stmpe_remove(struct stmpe *stmpe); ...@@ -163,6 +163,27 @@ int stmpe_remove(struct stmpe *stmpe);
#define STMPE811_SYS_CTRL2_GPIO_OFF (1 << 2) #define STMPE811_SYS_CTRL2_GPIO_OFF (1 << 2)
#define STMPE811_SYS_CTRL2_TS_OFF (1 << 3) #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 * STMPE1601
*/ */
......
...@@ -26,6 +26,7 @@ enum stmpe_partnum { ...@@ -26,6 +26,7 @@ enum stmpe_partnum {
STMPE610, STMPE610,
STMPE801, STMPE801,
STMPE811, STMPE811,
STMPE1600,
STMPE1601, STMPE1601,
STMPE1801, STMPE1801,
STMPE2401, STMPE2401,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment