xref: /openbmc/linux/drivers/mfd/stmpe.c (revision b273c5e0)
127e34995SRabin Vincent /*
21a6e4b74SViresh Kumar  * ST Microelectronics MFD: stmpe's driver
31a6e4b74SViresh Kumar  *
427e34995SRabin Vincent  * Copyright (C) ST-Ericsson SA 2010
527e34995SRabin Vincent  *
627e34995SRabin Vincent  * License Terms: GNU General Public License, version 2
727e34995SRabin Vincent  * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
827e34995SRabin Vincent  */
927e34995SRabin Vincent 
10ac713cc9SVipul Kumar Samar #include <linux/err.h>
1173de16dbSViresh Kumar #include <linux/gpio.h>
12dba61c8fSSamuel Ortiz #include <linux/export.h>
1327e34995SRabin Vincent #include <linux/kernel.h>
1427e34995SRabin Vincent #include <linux/interrupt.h>
1527e34995SRabin Vincent #include <linux/irq.h>
1676f93992SLee Jones #include <linux/irqdomain.h>
1720d5c7deSRandy Dunlap #include <linux/of.h>
18ac713cc9SVipul Kumar Samar #include <linux/of_gpio.h>
191a6e4b74SViresh Kumar #include <linux/pm.h>
2027e34995SRabin Vincent #include <linux/slab.h>
2127e34995SRabin Vincent #include <linux/mfd/core.h>
22230f13a5SJean-Nicolas Graux #include <linux/delay.h>
239c9e3214SLinus Walleij #include <linux/regulator/consumer.h>
2427e34995SRabin Vincent #include "stmpe.h"
2527e34995SRabin Vincent 
2627e34995SRabin Vincent static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks)
2727e34995SRabin Vincent {
2827e34995SRabin Vincent 	return stmpe->variant->enable(stmpe, blocks, true);
2927e34995SRabin Vincent }
3027e34995SRabin Vincent 
3127e34995SRabin Vincent static int __stmpe_disable(struct stmpe *stmpe, unsigned int blocks)
3227e34995SRabin Vincent {
3327e34995SRabin Vincent 	return stmpe->variant->enable(stmpe, blocks, false);
3427e34995SRabin Vincent }
3527e34995SRabin Vincent 
3627e34995SRabin Vincent static int __stmpe_reg_read(struct stmpe *stmpe, u8 reg)
3727e34995SRabin Vincent {
3827e34995SRabin Vincent 	int ret;
3927e34995SRabin Vincent 
401a6e4b74SViresh Kumar 	ret = stmpe->ci->read_byte(stmpe, reg);
4127e34995SRabin Vincent 	if (ret < 0)
421a6e4b74SViresh Kumar 		dev_err(stmpe->dev, "failed to read reg %#x: %d\n", reg, ret);
4327e34995SRabin Vincent 
4427e34995SRabin Vincent 	dev_vdbg(stmpe->dev, "rd: reg %#x => data %#x\n", reg, ret);
4527e34995SRabin Vincent 
4627e34995SRabin Vincent 	return ret;
4727e34995SRabin Vincent }
4827e34995SRabin Vincent 
4927e34995SRabin Vincent static int __stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
5027e34995SRabin Vincent {
5127e34995SRabin Vincent 	int ret;
5227e34995SRabin Vincent 
5327e34995SRabin Vincent 	dev_vdbg(stmpe->dev, "wr: reg %#x <= %#x\n", reg, val);
5427e34995SRabin Vincent 
551a6e4b74SViresh Kumar 	ret = stmpe->ci->write_byte(stmpe, reg, val);
5627e34995SRabin Vincent 	if (ret < 0)
571a6e4b74SViresh Kumar 		dev_err(stmpe->dev, "failed to write reg %#x: %d\n", reg, ret);
5827e34995SRabin Vincent 
5927e34995SRabin Vincent 	return ret;
6027e34995SRabin Vincent }
6127e34995SRabin Vincent 
6227e34995SRabin Vincent static int __stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val)
6327e34995SRabin Vincent {
6427e34995SRabin Vincent 	int ret;
6527e34995SRabin Vincent 
6627e34995SRabin Vincent 	ret = __stmpe_reg_read(stmpe, reg);
6727e34995SRabin Vincent 	if (ret < 0)
6827e34995SRabin Vincent 		return ret;
6927e34995SRabin Vincent 
7027e34995SRabin Vincent 	ret &= ~mask;
7127e34995SRabin Vincent 	ret |= val;
7227e34995SRabin Vincent 
7327e34995SRabin Vincent 	return __stmpe_reg_write(stmpe, reg, ret);
7427e34995SRabin Vincent }
7527e34995SRabin Vincent 
7627e34995SRabin Vincent static int __stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length,
7727e34995SRabin Vincent 			      u8 *values)
7827e34995SRabin Vincent {
7927e34995SRabin Vincent 	int ret;
8027e34995SRabin Vincent 
811a6e4b74SViresh Kumar 	ret = stmpe->ci->read_block(stmpe, reg, length, values);
8227e34995SRabin Vincent 	if (ret < 0)
831a6e4b74SViresh Kumar 		dev_err(stmpe->dev, "failed to read regs %#x: %d\n", reg, ret);
8427e34995SRabin Vincent 
8527e34995SRabin Vincent 	dev_vdbg(stmpe->dev, "rd: reg %#x (%d) => ret %#x\n", reg, length, ret);
8627e34995SRabin Vincent 	stmpe_dump_bytes("stmpe rd: ", values, length);
8727e34995SRabin Vincent 
8827e34995SRabin Vincent 	return ret;
8927e34995SRabin Vincent }
9027e34995SRabin Vincent 
9127e34995SRabin Vincent static int __stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length,
9227e34995SRabin Vincent 			const u8 *values)
9327e34995SRabin Vincent {
9427e34995SRabin Vincent 	int ret;
9527e34995SRabin Vincent 
9627e34995SRabin Vincent 	dev_vdbg(stmpe->dev, "wr: regs %#x (%d)\n", reg, length);
9727e34995SRabin Vincent 	stmpe_dump_bytes("stmpe wr: ", values, length);
9827e34995SRabin Vincent 
991a6e4b74SViresh Kumar 	ret = stmpe->ci->write_block(stmpe, reg, length, values);
10027e34995SRabin Vincent 	if (ret < 0)
1011a6e4b74SViresh Kumar 		dev_err(stmpe->dev, "failed to write regs %#x: %d\n", reg, ret);
10227e34995SRabin Vincent 
10327e34995SRabin Vincent 	return ret;
10427e34995SRabin Vincent }
10527e34995SRabin Vincent 
10627e34995SRabin Vincent /**
10727e34995SRabin Vincent  * stmpe_enable - enable blocks on an STMPE device
10827e34995SRabin Vincent  * @stmpe:	Device to work on
10927e34995SRabin Vincent  * @blocks:	Mask of blocks (enum stmpe_block values) to enable
11027e34995SRabin Vincent  */
11127e34995SRabin Vincent int stmpe_enable(struct stmpe *stmpe, unsigned int blocks)
11227e34995SRabin Vincent {
11327e34995SRabin Vincent 	int ret;
11427e34995SRabin Vincent 
11527e34995SRabin Vincent 	mutex_lock(&stmpe->lock);
11627e34995SRabin Vincent 	ret = __stmpe_enable(stmpe, blocks);
11727e34995SRabin Vincent 	mutex_unlock(&stmpe->lock);
11827e34995SRabin Vincent 
11927e34995SRabin Vincent 	return ret;
12027e34995SRabin Vincent }
12127e34995SRabin Vincent EXPORT_SYMBOL_GPL(stmpe_enable);
12227e34995SRabin Vincent 
12327e34995SRabin Vincent /**
12427e34995SRabin Vincent  * stmpe_disable - disable blocks on an STMPE device
12527e34995SRabin Vincent  * @stmpe:	Device to work on
12627e34995SRabin Vincent  * @blocks:	Mask of blocks (enum stmpe_block values) to enable
12727e34995SRabin Vincent  */
12827e34995SRabin Vincent int stmpe_disable(struct stmpe *stmpe, unsigned int blocks)
12927e34995SRabin Vincent {
13027e34995SRabin Vincent 	int ret;
13127e34995SRabin Vincent 
13227e34995SRabin Vincent 	mutex_lock(&stmpe->lock);
13327e34995SRabin Vincent 	ret = __stmpe_disable(stmpe, blocks);
13427e34995SRabin Vincent 	mutex_unlock(&stmpe->lock);
13527e34995SRabin Vincent 
13627e34995SRabin Vincent 	return ret;
13727e34995SRabin Vincent }
13827e34995SRabin Vincent EXPORT_SYMBOL_GPL(stmpe_disable);
13927e34995SRabin Vincent 
14027e34995SRabin Vincent /**
14127e34995SRabin Vincent  * stmpe_reg_read() - read a single STMPE register
14227e34995SRabin Vincent  * @stmpe:	Device to read from
14327e34995SRabin Vincent  * @reg:	Register to read
14427e34995SRabin Vincent  */
14527e34995SRabin Vincent int stmpe_reg_read(struct stmpe *stmpe, u8 reg)
14627e34995SRabin Vincent {
14727e34995SRabin Vincent 	int ret;
14827e34995SRabin Vincent 
14927e34995SRabin Vincent 	mutex_lock(&stmpe->lock);
15027e34995SRabin Vincent 	ret = __stmpe_reg_read(stmpe, reg);
15127e34995SRabin Vincent 	mutex_unlock(&stmpe->lock);
15227e34995SRabin Vincent 
15327e34995SRabin Vincent 	return ret;
15427e34995SRabin Vincent }
15527e34995SRabin Vincent EXPORT_SYMBOL_GPL(stmpe_reg_read);
15627e34995SRabin Vincent 
15727e34995SRabin Vincent /**
15827e34995SRabin Vincent  * stmpe_reg_write() - write a single STMPE register
15927e34995SRabin Vincent  * @stmpe:	Device to write to
16027e34995SRabin Vincent  * @reg:	Register to write
16127e34995SRabin Vincent  * @val:	Value to write
16227e34995SRabin Vincent  */
16327e34995SRabin Vincent int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
16427e34995SRabin Vincent {
16527e34995SRabin Vincent 	int ret;
16627e34995SRabin Vincent 
16727e34995SRabin Vincent 	mutex_lock(&stmpe->lock);
16827e34995SRabin Vincent 	ret = __stmpe_reg_write(stmpe, reg, val);
16927e34995SRabin Vincent 	mutex_unlock(&stmpe->lock);
17027e34995SRabin Vincent 
17127e34995SRabin Vincent 	return ret;
17227e34995SRabin Vincent }
17327e34995SRabin Vincent EXPORT_SYMBOL_GPL(stmpe_reg_write);
17427e34995SRabin Vincent 
17527e34995SRabin Vincent /**
17627e34995SRabin Vincent  * stmpe_set_bits() - set the value of a bitfield in a STMPE register
17727e34995SRabin Vincent  * @stmpe:	Device to write to
17827e34995SRabin Vincent  * @reg:	Register to write
17927e34995SRabin Vincent  * @mask:	Mask of bits to set
18027e34995SRabin Vincent  * @val:	Value to set
18127e34995SRabin Vincent  */
18227e34995SRabin Vincent int stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val)
18327e34995SRabin Vincent {
18427e34995SRabin Vincent 	int ret;
18527e34995SRabin Vincent 
18627e34995SRabin Vincent 	mutex_lock(&stmpe->lock);
18727e34995SRabin Vincent 	ret = __stmpe_set_bits(stmpe, reg, mask, val);
18827e34995SRabin Vincent 	mutex_unlock(&stmpe->lock);
18927e34995SRabin Vincent 
19027e34995SRabin Vincent 	return ret;
19127e34995SRabin Vincent }
19227e34995SRabin Vincent EXPORT_SYMBOL_GPL(stmpe_set_bits);
19327e34995SRabin Vincent 
19427e34995SRabin Vincent /**
19527e34995SRabin Vincent  * stmpe_block_read() - read multiple STMPE registers
19627e34995SRabin Vincent  * @stmpe:	Device to read from
19727e34995SRabin Vincent  * @reg:	First register
19827e34995SRabin Vincent  * @length:	Number of registers
19927e34995SRabin Vincent  * @values:	Buffer to write to
20027e34995SRabin Vincent  */
20127e34995SRabin Vincent int stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values)
20227e34995SRabin Vincent {
20327e34995SRabin Vincent 	int ret;
20427e34995SRabin Vincent 
20527e34995SRabin Vincent 	mutex_lock(&stmpe->lock);
20627e34995SRabin Vincent 	ret = __stmpe_block_read(stmpe, reg, length, values);
20727e34995SRabin Vincent 	mutex_unlock(&stmpe->lock);
20827e34995SRabin Vincent 
20927e34995SRabin Vincent 	return ret;
21027e34995SRabin Vincent }
21127e34995SRabin Vincent EXPORT_SYMBOL_GPL(stmpe_block_read);
21227e34995SRabin Vincent 
21327e34995SRabin Vincent /**
21427e34995SRabin Vincent  * stmpe_block_write() - write multiple STMPE registers
21527e34995SRabin Vincent  * @stmpe:	Device to write to
21627e34995SRabin Vincent  * @reg:	First register
21727e34995SRabin Vincent  * @length:	Number of registers
21827e34995SRabin Vincent  * @values:	Values to write
21927e34995SRabin Vincent  */
22027e34995SRabin Vincent int stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length,
22127e34995SRabin Vincent 		      const u8 *values)
22227e34995SRabin Vincent {
22327e34995SRabin Vincent 	int ret;
22427e34995SRabin Vincent 
22527e34995SRabin Vincent 	mutex_lock(&stmpe->lock);
22627e34995SRabin Vincent 	ret = __stmpe_block_write(stmpe, reg, length, values);
22727e34995SRabin Vincent 	mutex_unlock(&stmpe->lock);
22827e34995SRabin Vincent 
22927e34995SRabin Vincent 	return ret;
23027e34995SRabin Vincent }
23127e34995SRabin Vincent EXPORT_SYMBOL_GPL(stmpe_block_write);
23227e34995SRabin Vincent 
23327e34995SRabin Vincent /**
2344dcaa6b6SOm Prakash  * stmpe_set_altfunc()- set the alternate function for STMPE pins
23527e34995SRabin Vincent  * @stmpe:	Device to configure
23627e34995SRabin Vincent  * @pins:	Bitmask of pins to affect
23727e34995SRabin Vincent  * @block:	block to enable alternate functions for
23827e34995SRabin Vincent  *
23927e34995SRabin Vincent  * @pins is assumed to have a bit set for each of the bits whose alternate
24027e34995SRabin Vincent  * function is to be changed, numbered according to the GPIOXY numbers.
24127e34995SRabin Vincent  *
24227e34995SRabin Vincent  * If the GPIO module is not enabled, this function automatically enables it in
24327e34995SRabin Vincent  * order to perform the change.
24427e34995SRabin Vincent  */
24527e34995SRabin Vincent int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block)
24627e34995SRabin Vincent {
24727e34995SRabin Vincent 	struct stmpe_variant_info *variant = stmpe->variant;
24827e34995SRabin Vincent 	u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB];
24927e34995SRabin Vincent 	int af_bits = variant->af_bits;
25027e34995SRabin Vincent 	int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8);
25127e34995SRabin Vincent 	int mask = (1 << af_bits) - 1;
2527929fa77SLee Jones 	u8 regs[8];
2537f7f4ea1SViresh Kumar 	int af, afperreg, ret;
25427e34995SRabin Vincent 
2557f7f4ea1SViresh Kumar 	if (!variant->get_altfunc)
2567f7f4ea1SViresh Kumar 		return 0;
2577f7f4ea1SViresh Kumar 
2587f7f4ea1SViresh Kumar 	afperreg = 8 / af_bits;
25927e34995SRabin Vincent 	mutex_lock(&stmpe->lock);
26027e34995SRabin Vincent 
26127e34995SRabin Vincent 	ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
26227e34995SRabin Vincent 	if (ret < 0)
26327e34995SRabin Vincent 		goto out;
26427e34995SRabin Vincent 
26527e34995SRabin Vincent 	ret = __stmpe_block_read(stmpe, regaddr, numregs, regs);
26627e34995SRabin Vincent 	if (ret < 0)
26727e34995SRabin Vincent 		goto out;
26827e34995SRabin Vincent 
26927e34995SRabin Vincent 	af = variant->get_altfunc(stmpe, block);
27027e34995SRabin Vincent 
27127e34995SRabin Vincent 	while (pins) {
27227e34995SRabin Vincent 		int pin = __ffs(pins);
27327e34995SRabin Vincent 		int regoffset = numregs - (pin / afperreg) - 1;
27427e34995SRabin Vincent 		int pos = (pin % afperreg) * (8 / afperreg);
27527e34995SRabin Vincent 
27627e34995SRabin Vincent 		regs[regoffset] &= ~(mask << pos);
27727e34995SRabin Vincent 		regs[regoffset] |= af << pos;
27827e34995SRabin Vincent 
27927e34995SRabin Vincent 		pins &= ~(1 << pin);
28027e34995SRabin Vincent 	}
28127e34995SRabin Vincent 
28227e34995SRabin Vincent 	ret = __stmpe_block_write(stmpe, regaddr, numregs, regs);
28327e34995SRabin Vincent 
28427e34995SRabin Vincent out:
28527e34995SRabin Vincent 	mutex_unlock(&stmpe->lock);
28627e34995SRabin Vincent 	return ret;
28727e34995SRabin Vincent }
28827e34995SRabin Vincent EXPORT_SYMBOL_GPL(stmpe_set_altfunc);
28927e34995SRabin Vincent 
29027e34995SRabin Vincent /*
29127e34995SRabin Vincent  * GPIO (all variants)
29227e34995SRabin Vincent  */
29327e34995SRabin Vincent 
29427e34995SRabin Vincent static struct resource stmpe_gpio_resources[] = {
29527e34995SRabin Vincent 	/* Start and end filled dynamically */
29627e34995SRabin Vincent 	{
29727e34995SRabin Vincent 		.flags	= IORESOURCE_IRQ,
29827e34995SRabin Vincent 	},
29927e34995SRabin Vincent };
30027e34995SRabin Vincent 
3016bbb3c4cSGeert Uytterhoeven static const struct mfd_cell stmpe_gpio_cell = {
30227e34995SRabin Vincent 	.name		= "stmpe-gpio",
30386605cfeSVipul Kumar Samar 	.of_compatible	= "st,stmpe-gpio",
30427e34995SRabin Vincent 	.resources	= stmpe_gpio_resources,
30527e34995SRabin Vincent 	.num_resources	= ARRAY_SIZE(stmpe_gpio_resources),
30627e34995SRabin Vincent };
30727e34995SRabin Vincent 
3086bbb3c4cSGeert Uytterhoeven static const struct mfd_cell stmpe_gpio_cell_noirq = {
309e31f9b82SChris Blair 	.name		= "stmpe-gpio",
31086605cfeSVipul Kumar Samar 	.of_compatible	= "st,stmpe-gpio",
311e31f9b82SChris Blair 	/* gpio cell resources consist of an irq only so no resources here */
312e31f9b82SChris Blair };
313e31f9b82SChris Blair 
31427e34995SRabin Vincent /*
31527e34995SRabin Vincent  * Keypad (1601, 2401, 2403)
31627e34995SRabin Vincent  */
31727e34995SRabin Vincent 
31827e34995SRabin Vincent static struct resource stmpe_keypad_resources[] = {
31927e34995SRabin Vincent 	{
32027e34995SRabin Vincent 		.name	= "KEYPAD",
32127e34995SRabin Vincent 		.flags	= IORESOURCE_IRQ,
32227e34995SRabin Vincent 	},
32327e34995SRabin Vincent 	{
32427e34995SRabin Vincent 		.name	= "KEYPAD_OVER",
32527e34995SRabin Vincent 		.flags	= IORESOURCE_IRQ,
32627e34995SRabin Vincent 	},
32727e34995SRabin Vincent };
32827e34995SRabin Vincent 
3296bbb3c4cSGeert Uytterhoeven static const struct mfd_cell stmpe_keypad_cell = {
33027e34995SRabin Vincent 	.name		= "stmpe-keypad",
3316ea32387SDmitry Torokhov 	.of_compatible  = "st,stmpe-keypad",
33227e34995SRabin Vincent 	.resources	= stmpe_keypad_resources,
33327e34995SRabin Vincent 	.num_resources	= ARRAY_SIZE(stmpe_keypad_resources),
33427e34995SRabin Vincent };
33527e34995SRabin Vincent 
33627e34995SRabin Vincent /*
337b273c5e0SLinus Walleij  * PWM (1601, 2401, 2403)
338b273c5e0SLinus Walleij  */
339b273c5e0SLinus Walleij static struct resource stmpe_pwm_resources[] = {
340b273c5e0SLinus Walleij 	{
341b273c5e0SLinus Walleij 		.name	= "PWM0",
342b273c5e0SLinus Walleij 		.flags	= IORESOURCE_IRQ,
343b273c5e0SLinus Walleij 	},
344b273c5e0SLinus Walleij 	{
345b273c5e0SLinus Walleij 		.name	= "PWM1",
346b273c5e0SLinus Walleij 		.flags	= IORESOURCE_IRQ,
347b273c5e0SLinus Walleij 	},
348b273c5e0SLinus Walleij 	{
349b273c5e0SLinus Walleij 		.name	= "PWM2",
350b273c5e0SLinus Walleij 		.flags	= IORESOURCE_IRQ,
351b273c5e0SLinus Walleij 	},
352b273c5e0SLinus Walleij };
353b273c5e0SLinus Walleij 
354b273c5e0SLinus Walleij static const struct mfd_cell stmpe_pwm_cell = {
355b273c5e0SLinus Walleij 	.name		= "stmpe-pwm",
356b273c5e0SLinus Walleij 	.of_compatible  = "st,stmpe-pwm",
357b273c5e0SLinus Walleij 	.resources	= stmpe_pwm_resources,
358b273c5e0SLinus Walleij 	.num_resources	= ARRAY_SIZE(stmpe_pwm_resources),
359b273c5e0SLinus Walleij };
360b273c5e0SLinus Walleij 
361b273c5e0SLinus Walleij /*
3627f7f4ea1SViresh Kumar  * STMPE801
3637f7f4ea1SViresh Kumar  */
3647f7f4ea1SViresh Kumar static const u8 stmpe801_regs[] = {
3657f7f4ea1SViresh Kumar 	[STMPE_IDX_CHIP_ID]	= STMPE801_REG_CHIP_ID,
3667f7f4ea1SViresh Kumar 	[STMPE_IDX_ICR_LSB]	= STMPE801_REG_SYS_CTRL,
3677f7f4ea1SViresh Kumar 	[STMPE_IDX_GPMR_LSB]	= STMPE801_REG_GPIO_MP_STA,
3687f7f4ea1SViresh Kumar 	[STMPE_IDX_GPSR_LSB]	= STMPE801_REG_GPIO_SET_PIN,
3697f7f4ea1SViresh Kumar 	[STMPE_IDX_GPCR_LSB]	= STMPE801_REG_GPIO_SET_PIN,
3707f7f4ea1SViresh Kumar 	[STMPE_IDX_GPDR_LSB]	= STMPE801_REG_GPIO_DIR,
3717f7f4ea1SViresh Kumar 	[STMPE_IDX_IEGPIOR_LSB] = STMPE801_REG_GPIO_INT_EN,
3727f7f4ea1SViresh Kumar 	[STMPE_IDX_ISGPIOR_MSB] = STMPE801_REG_GPIO_INT_STA,
3737f7f4ea1SViresh Kumar 
3747f7f4ea1SViresh Kumar };
3757f7f4ea1SViresh Kumar 
3767f7f4ea1SViresh Kumar static struct stmpe_variant_block stmpe801_blocks[] = {
3777f7f4ea1SViresh Kumar 	{
3787f7f4ea1SViresh Kumar 		.cell	= &stmpe_gpio_cell,
3797f7f4ea1SViresh Kumar 		.irq	= 0,
3807f7f4ea1SViresh Kumar 		.block	= STMPE_BLOCK_GPIO,
3817f7f4ea1SViresh Kumar 	},
3827f7f4ea1SViresh Kumar };
3837f7f4ea1SViresh Kumar 
384e31f9b82SChris Blair static struct stmpe_variant_block stmpe801_blocks_noirq[] = {
385e31f9b82SChris Blair 	{
386e31f9b82SChris Blair 		.cell	= &stmpe_gpio_cell_noirq,
387e31f9b82SChris Blair 		.block	= STMPE_BLOCK_GPIO,
388e31f9b82SChris Blair 	},
389e31f9b82SChris Blair };
390e31f9b82SChris Blair 
3917f7f4ea1SViresh Kumar static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks,
3927f7f4ea1SViresh Kumar 			   bool enable)
3937f7f4ea1SViresh Kumar {
3947f7f4ea1SViresh Kumar 	if (blocks & STMPE_BLOCK_GPIO)
3957f7f4ea1SViresh Kumar 		return 0;
3967f7f4ea1SViresh Kumar 	else
3977f7f4ea1SViresh Kumar 		return -EINVAL;
3987f7f4ea1SViresh Kumar }
3997f7f4ea1SViresh Kumar 
4007f7f4ea1SViresh Kumar static struct stmpe_variant_info stmpe801 = {
4017f7f4ea1SViresh Kumar 	.name		= "stmpe801",
4027f7f4ea1SViresh Kumar 	.id_val		= STMPE801_ID,
4037f7f4ea1SViresh Kumar 	.id_mask	= 0xffff,
4047f7f4ea1SViresh Kumar 	.num_gpios	= 8,
4057f7f4ea1SViresh Kumar 	.regs		= stmpe801_regs,
4067f7f4ea1SViresh Kumar 	.blocks		= stmpe801_blocks,
4077f7f4ea1SViresh Kumar 	.num_blocks	= ARRAY_SIZE(stmpe801_blocks),
4087f7f4ea1SViresh Kumar 	.num_irqs	= STMPE801_NR_INTERNAL_IRQS,
4097f7f4ea1SViresh Kumar 	.enable		= stmpe801_enable,
4107f7f4ea1SViresh Kumar };
4117f7f4ea1SViresh Kumar 
412e31f9b82SChris Blair static struct stmpe_variant_info stmpe801_noirq = {
413e31f9b82SChris Blair 	.name		= "stmpe801",
414e31f9b82SChris Blair 	.id_val		= STMPE801_ID,
415e31f9b82SChris Blair 	.id_mask	= 0xffff,
416e31f9b82SChris Blair 	.num_gpios	= 8,
417e31f9b82SChris Blair 	.regs		= stmpe801_regs,
418e31f9b82SChris Blair 	.blocks		= stmpe801_blocks_noirq,
419e31f9b82SChris Blair 	.num_blocks	= ARRAY_SIZE(stmpe801_blocks_noirq),
420e31f9b82SChris Blair 	.enable		= stmpe801_enable,
421e31f9b82SChris Blair };
422e31f9b82SChris Blair 
4237f7f4ea1SViresh Kumar /*
4241cda2394SViresh Kumar  * Touchscreen (STMPE811 or STMPE610)
42527e34995SRabin Vincent  */
42627e34995SRabin Vincent 
42727e34995SRabin Vincent static struct resource stmpe_ts_resources[] = {
42827e34995SRabin Vincent 	{
42927e34995SRabin Vincent 		.name	= "TOUCH_DET",
43027e34995SRabin Vincent 		.flags	= IORESOURCE_IRQ,
43127e34995SRabin Vincent 	},
43227e34995SRabin Vincent 	{
43327e34995SRabin Vincent 		.name	= "FIFO_TH",
43427e34995SRabin Vincent 		.flags	= IORESOURCE_IRQ,
43527e34995SRabin Vincent 	},
43627e34995SRabin Vincent };
43727e34995SRabin Vincent 
4386bbb3c4cSGeert Uytterhoeven static const struct mfd_cell stmpe_ts_cell = {
43927e34995SRabin Vincent 	.name		= "stmpe-ts",
440037db524SVipul Kumar Samar 	.of_compatible	= "st,stmpe-ts",
44127e34995SRabin Vincent 	.resources	= stmpe_ts_resources,
44227e34995SRabin Vincent 	.num_resources	= ARRAY_SIZE(stmpe_ts_resources),
44327e34995SRabin Vincent };
44427e34995SRabin Vincent 
44527e34995SRabin Vincent /*
4461cda2394SViresh Kumar  * STMPE811 or STMPE610
44727e34995SRabin Vincent  */
44827e34995SRabin Vincent 
44927e34995SRabin Vincent static const u8 stmpe811_regs[] = {
45027e34995SRabin Vincent 	[STMPE_IDX_CHIP_ID]	= STMPE811_REG_CHIP_ID,
45127e34995SRabin Vincent 	[STMPE_IDX_ICR_LSB]	= STMPE811_REG_INT_CTRL,
45227e34995SRabin Vincent 	[STMPE_IDX_IER_LSB]	= STMPE811_REG_INT_EN,
45327e34995SRabin Vincent 	[STMPE_IDX_ISR_MSB]	= STMPE811_REG_INT_STA,
45427e34995SRabin Vincent 	[STMPE_IDX_GPMR_LSB]	= STMPE811_REG_GPIO_MP_STA,
45527e34995SRabin Vincent 	[STMPE_IDX_GPSR_LSB]	= STMPE811_REG_GPIO_SET_PIN,
45627e34995SRabin Vincent 	[STMPE_IDX_GPCR_LSB]	= STMPE811_REG_GPIO_CLR_PIN,
45727e34995SRabin Vincent 	[STMPE_IDX_GPDR_LSB]	= STMPE811_REG_GPIO_DIR,
45827e34995SRabin Vincent 	[STMPE_IDX_GPRER_LSB]	= STMPE811_REG_GPIO_RE,
45927e34995SRabin Vincent 	[STMPE_IDX_GPFER_LSB]	= STMPE811_REG_GPIO_FE,
46027e34995SRabin Vincent 	[STMPE_IDX_GPAFR_U_MSB]	= STMPE811_REG_GPIO_AF,
46127e34995SRabin Vincent 	[STMPE_IDX_IEGPIOR_LSB]	= STMPE811_REG_GPIO_INT_EN,
46227e34995SRabin Vincent 	[STMPE_IDX_ISGPIOR_MSB]	= STMPE811_REG_GPIO_INT_STA,
46327e34995SRabin Vincent 	[STMPE_IDX_GPEDR_MSB]	= STMPE811_REG_GPIO_ED,
46427e34995SRabin Vincent };
46527e34995SRabin Vincent 
46627e34995SRabin Vincent static struct stmpe_variant_block stmpe811_blocks[] = {
46727e34995SRabin Vincent 	{
46827e34995SRabin Vincent 		.cell	= &stmpe_gpio_cell,
46927e34995SRabin Vincent 		.irq	= STMPE811_IRQ_GPIOC,
47027e34995SRabin Vincent 		.block	= STMPE_BLOCK_GPIO,
47127e34995SRabin Vincent 	},
47227e34995SRabin Vincent 	{
47327e34995SRabin Vincent 		.cell	= &stmpe_ts_cell,
47427e34995SRabin Vincent 		.irq	= STMPE811_IRQ_TOUCH_DET,
47527e34995SRabin Vincent 		.block	= STMPE_BLOCK_TOUCHSCREEN,
47627e34995SRabin Vincent 	},
47727e34995SRabin Vincent };
47827e34995SRabin Vincent 
47927e34995SRabin Vincent static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
48027e34995SRabin Vincent 			   bool enable)
48127e34995SRabin Vincent {
48227e34995SRabin Vincent 	unsigned int mask = 0;
48327e34995SRabin Vincent 
48427e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_GPIO)
48527e34995SRabin Vincent 		mask |= STMPE811_SYS_CTRL2_GPIO_OFF;
48627e34995SRabin Vincent 
48727e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_ADC)
48827e34995SRabin Vincent 		mask |= STMPE811_SYS_CTRL2_ADC_OFF;
48927e34995SRabin Vincent 
49027e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_TOUCHSCREEN)
49127e34995SRabin Vincent 		mask |= STMPE811_SYS_CTRL2_TSC_OFF;
49227e34995SRabin Vincent 
49327e34995SRabin Vincent 	return __stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask,
49427e34995SRabin Vincent 				enable ? 0 : mask);
49527e34995SRabin Vincent }
49627e34995SRabin Vincent 
49727e34995SRabin Vincent static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
49827e34995SRabin Vincent {
49927e34995SRabin Vincent 	/* 0 for touchscreen, 1 for GPIO */
50027e34995SRabin Vincent 	return block != STMPE_BLOCK_TOUCHSCREEN;
50127e34995SRabin Vincent }
50227e34995SRabin Vincent 
50327e34995SRabin Vincent static struct stmpe_variant_info stmpe811 = {
50427e34995SRabin Vincent 	.name		= "stmpe811",
50527e34995SRabin Vincent 	.id_val		= 0x0811,
50627e34995SRabin Vincent 	.id_mask	= 0xffff,
50727e34995SRabin Vincent 	.num_gpios	= 8,
50827e34995SRabin Vincent 	.af_bits	= 1,
50927e34995SRabin Vincent 	.regs		= stmpe811_regs,
51027e34995SRabin Vincent 	.blocks		= stmpe811_blocks,
51127e34995SRabin Vincent 	.num_blocks	= ARRAY_SIZE(stmpe811_blocks),
51227e34995SRabin Vincent 	.num_irqs	= STMPE811_NR_INTERNAL_IRQS,
51327e34995SRabin Vincent 	.enable		= stmpe811_enable,
51427e34995SRabin Vincent 	.get_altfunc	= stmpe811_get_altfunc,
51527e34995SRabin Vincent };
51627e34995SRabin Vincent 
5171cda2394SViresh Kumar /* Similar to 811, except number of gpios */
5181cda2394SViresh Kumar static struct stmpe_variant_info stmpe610 = {
5191cda2394SViresh Kumar 	.name		= "stmpe610",
5201cda2394SViresh Kumar 	.id_val		= 0x0811,
5211cda2394SViresh Kumar 	.id_mask	= 0xffff,
5221cda2394SViresh Kumar 	.num_gpios	= 6,
5231cda2394SViresh Kumar 	.af_bits	= 1,
5241cda2394SViresh Kumar 	.regs		= stmpe811_regs,
5251cda2394SViresh Kumar 	.blocks		= stmpe811_blocks,
5261cda2394SViresh Kumar 	.num_blocks	= ARRAY_SIZE(stmpe811_blocks),
5271cda2394SViresh Kumar 	.num_irqs	= STMPE811_NR_INTERNAL_IRQS,
5281cda2394SViresh Kumar 	.enable		= stmpe811_enable,
5291cda2394SViresh Kumar 	.get_altfunc	= stmpe811_get_altfunc,
5301cda2394SViresh Kumar };
5311cda2394SViresh Kumar 
53227e34995SRabin Vincent /*
53327e34995SRabin Vincent  * STMPE1601
53427e34995SRabin Vincent  */
53527e34995SRabin Vincent 
53627e34995SRabin Vincent static const u8 stmpe1601_regs[] = {
53727e34995SRabin Vincent 	[STMPE_IDX_CHIP_ID]	= STMPE1601_REG_CHIP_ID,
53827e34995SRabin Vincent 	[STMPE_IDX_ICR_LSB]	= STMPE1601_REG_ICR_LSB,
53927e34995SRabin Vincent 	[STMPE_IDX_IER_LSB]	= STMPE1601_REG_IER_LSB,
54027e34995SRabin Vincent 	[STMPE_IDX_ISR_MSB]	= STMPE1601_REG_ISR_MSB,
54127e34995SRabin Vincent 	[STMPE_IDX_GPMR_LSB]	= STMPE1601_REG_GPIO_MP_LSB,
54227e34995SRabin Vincent 	[STMPE_IDX_GPSR_LSB]	= STMPE1601_REG_GPIO_SET_LSB,
54327e34995SRabin Vincent 	[STMPE_IDX_GPCR_LSB]	= STMPE1601_REG_GPIO_CLR_LSB,
54427e34995SRabin Vincent 	[STMPE_IDX_GPDR_LSB]	= STMPE1601_REG_GPIO_SET_DIR_LSB,
54527e34995SRabin Vincent 	[STMPE_IDX_GPRER_LSB]	= STMPE1601_REG_GPIO_RE_LSB,
54627e34995SRabin Vincent 	[STMPE_IDX_GPFER_LSB]	= STMPE1601_REG_GPIO_FE_LSB,
54780e1dd82SLinus Walleij 	[STMPE_IDX_GPPUR_LSB]	= STMPE1601_REG_GPIO_PU_LSB,
54827e34995SRabin Vincent 	[STMPE_IDX_GPAFR_U_MSB]	= STMPE1601_REG_GPIO_AF_U_MSB,
54927e34995SRabin Vincent 	[STMPE_IDX_IEGPIOR_LSB]	= STMPE1601_REG_INT_EN_GPIO_MASK_LSB,
55027e34995SRabin Vincent 	[STMPE_IDX_ISGPIOR_MSB]	= STMPE1601_REG_INT_STA_GPIO_MSB,
55127e34995SRabin Vincent 	[STMPE_IDX_GPEDR_MSB]	= STMPE1601_REG_GPIO_ED_MSB,
55227e34995SRabin Vincent };
55327e34995SRabin Vincent 
55427e34995SRabin Vincent static struct stmpe_variant_block stmpe1601_blocks[] = {
55527e34995SRabin Vincent 	{
55627e34995SRabin Vincent 		.cell	= &stmpe_gpio_cell,
5575204e51dSLee Jones 		.irq	= STMPE1601_IRQ_GPIOC,
55827e34995SRabin Vincent 		.block	= STMPE_BLOCK_GPIO,
55927e34995SRabin Vincent 	},
56027e34995SRabin Vincent 	{
56127e34995SRabin Vincent 		.cell	= &stmpe_keypad_cell,
5625204e51dSLee Jones 		.irq	= STMPE1601_IRQ_KEYPAD,
56327e34995SRabin Vincent 		.block	= STMPE_BLOCK_KEYPAD,
56427e34995SRabin Vincent 	},
565b273c5e0SLinus Walleij 	{
566b273c5e0SLinus Walleij 		.cell	= &stmpe_pwm_cell,
567b273c5e0SLinus Walleij 		.irq	= STMPE1601_IRQ_PWM0,
568b273c5e0SLinus Walleij 		.block	= STMPE_BLOCK_PWM,
569b273c5e0SLinus Walleij 	},
57027e34995SRabin Vincent };
57127e34995SRabin Vincent 
5725981f4e6SSundar R Iyer /* supported autosleep timeout delay (in msecs) */
5735981f4e6SSundar R Iyer static const int stmpe_autosleep_delay[] = {
5745981f4e6SSundar R Iyer 	4, 16, 32, 64, 128, 256, 512, 1024,
5755981f4e6SSundar R Iyer };
5765981f4e6SSundar R Iyer 
5775981f4e6SSundar R Iyer static int stmpe_round_timeout(int timeout)
5785981f4e6SSundar R Iyer {
5795981f4e6SSundar R Iyer 	int i;
5805981f4e6SSundar R Iyer 
5815981f4e6SSundar R Iyer 	for (i = 0; i < ARRAY_SIZE(stmpe_autosleep_delay); i++) {
5825981f4e6SSundar R Iyer 		if (stmpe_autosleep_delay[i] >= timeout)
5835981f4e6SSundar R Iyer 			return i;
5845981f4e6SSundar R Iyer 	}
5855981f4e6SSundar R Iyer 
5865981f4e6SSundar R Iyer 	/*
5875981f4e6SSundar R Iyer 	 * requests for delays longer than supported should not return the
5885981f4e6SSundar R Iyer 	 * longest supported delay
5895981f4e6SSundar R Iyer 	 */
5905981f4e6SSundar R Iyer 	return -EINVAL;
5915981f4e6SSundar R Iyer }
5925981f4e6SSundar R Iyer 
5935981f4e6SSundar R Iyer static int stmpe_autosleep(struct stmpe *stmpe, int autosleep_timeout)
5945981f4e6SSundar R Iyer {
5955981f4e6SSundar R Iyer 	int ret;
5965981f4e6SSundar R Iyer 
5975981f4e6SSundar R Iyer 	if (!stmpe->variant->enable_autosleep)
5985981f4e6SSundar R Iyer 		return -ENOSYS;
5995981f4e6SSundar R Iyer 
6005981f4e6SSundar R Iyer 	mutex_lock(&stmpe->lock);
6015981f4e6SSundar R Iyer 	ret = stmpe->variant->enable_autosleep(stmpe, autosleep_timeout);
6025981f4e6SSundar R Iyer 	mutex_unlock(&stmpe->lock);
6035981f4e6SSundar R Iyer 
6045981f4e6SSundar R Iyer 	return ret;
6055981f4e6SSundar R Iyer }
6065981f4e6SSundar R Iyer 
6075981f4e6SSundar R Iyer /*
6085981f4e6SSundar R Iyer  * Both stmpe 1601/2403 support same layout for autosleep
6095981f4e6SSundar R Iyer  */
6105981f4e6SSundar R Iyer static int stmpe1601_autosleep(struct stmpe *stmpe,
6115981f4e6SSundar R Iyer 		int autosleep_timeout)
6125981f4e6SSundar R Iyer {
6135981f4e6SSundar R Iyer 	int ret, timeout;
6145981f4e6SSundar R Iyer 
6155981f4e6SSundar R Iyer 	/* choose the best available timeout */
6165981f4e6SSundar R Iyer 	timeout = stmpe_round_timeout(autosleep_timeout);
6175981f4e6SSundar R Iyer 	if (timeout < 0) {
6185981f4e6SSundar R Iyer 		dev_err(stmpe->dev, "invalid timeout\n");
6195981f4e6SSundar R Iyer 		return timeout;
6205981f4e6SSundar R Iyer 	}
6215981f4e6SSundar R Iyer 
6225981f4e6SSundar R Iyer 	ret = __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2,
6235981f4e6SSundar R Iyer 			STMPE1601_AUTOSLEEP_TIMEOUT_MASK,
6245981f4e6SSundar R Iyer 			timeout);
6255981f4e6SSundar R Iyer 	if (ret < 0)
6265981f4e6SSundar R Iyer 		return ret;
6275981f4e6SSundar R Iyer 
6285981f4e6SSundar R Iyer 	return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2,
6295981f4e6SSundar R Iyer 			STPME1601_AUTOSLEEP_ENABLE,
6305981f4e6SSundar R Iyer 			STPME1601_AUTOSLEEP_ENABLE);
6315981f4e6SSundar R Iyer }
6325981f4e6SSundar R Iyer 
63327e34995SRabin Vincent static int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks,
63427e34995SRabin Vincent 			    bool enable)
63527e34995SRabin Vincent {
63627e34995SRabin Vincent 	unsigned int mask = 0;
63727e34995SRabin Vincent 
63827e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_GPIO)
63927e34995SRabin Vincent 		mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO;
640b69d2ad6SLinus Walleij 	else
641b69d2ad6SLinus Walleij 		mask &= ~STMPE1601_SYS_CTRL_ENABLE_GPIO;
64227e34995SRabin Vincent 
64327e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_KEYPAD)
64427e34995SRabin Vincent 		mask |= STMPE1601_SYS_CTRL_ENABLE_KPC;
645b69d2ad6SLinus Walleij 	else
646b69d2ad6SLinus Walleij 		mask &= ~STMPE1601_SYS_CTRL_ENABLE_KPC;
647b69d2ad6SLinus Walleij 
648b69d2ad6SLinus Walleij 	if (blocks & STMPE_BLOCK_PWM)
649b69d2ad6SLinus Walleij 		mask |= STMPE1601_SYS_CTRL_ENABLE_SPWM;
650b69d2ad6SLinus Walleij 	else
651b69d2ad6SLinus Walleij 		mask &= ~STMPE1601_SYS_CTRL_ENABLE_SPWM;
65227e34995SRabin Vincent 
65327e34995SRabin Vincent 	return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask,
65427e34995SRabin Vincent 				enable ? mask : 0);
65527e34995SRabin Vincent }
65627e34995SRabin Vincent 
65727e34995SRabin Vincent static int stmpe1601_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
65827e34995SRabin Vincent {
65927e34995SRabin Vincent 	switch (block) {
66027e34995SRabin Vincent 	case STMPE_BLOCK_PWM:
66127e34995SRabin Vincent 		return 2;
66227e34995SRabin Vincent 
66327e34995SRabin Vincent 	case STMPE_BLOCK_KEYPAD:
66427e34995SRabin Vincent 		return 1;
66527e34995SRabin Vincent 
66627e34995SRabin Vincent 	case STMPE_BLOCK_GPIO:
66727e34995SRabin Vincent 	default:
66827e34995SRabin Vincent 		return 0;
66927e34995SRabin Vincent 	}
67027e34995SRabin Vincent }
67127e34995SRabin Vincent 
67227e34995SRabin Vincent static struct stmpe_variant_info stmpe1601 = {
67327e34995SRabin Vincent 	.name		= "stmpe1601",
67427e34995SRabin Vincent 	.id_val		= 0x0210,
67527e34995SRabin Vincent 	.id_mask	= 0xfff0,	/* at least 0x0210 and 0x0212 */
67627e34995SRabin Vincent 	.num_gpios	= 16,
67727e34995SRabin Vincent 	.af_bits	= 2,
67827e34995SRabin Vincent 	.regs		= stmpe1601_regs,
67927e34995SRabin Vincent 	.blocks		= stmpe1601_blocks,
68027e34995SRabin Vincent 	.num_blocks	= ARRAY_SIZE(stmpe1601_blocks),
68127e34995SRabin Vincent 	.num_irqs	= STMPE1601_NR_INTERNAL_IRQS,
68227e34995SRabin Vincent 	.enable		= stmpe1601_enable,
68327e34995SRabin Vincent 	.get_altfunc	= stmpe1601_get_altfunc,
6845981f4e6SSundar R Iyer 	.enable_autosleep	= stmpe1601_autosleep,
68527e34995SRabin Vincent };
68627e34995SRabin Vincent 
68727e34995SRabin Vincent /*
688230f13a5SJean-Nicolas Graux  * STMPE1801
689230f13a5SJean-Nicolas Graux  */
690230f13a5SJean-Nicolas Graux static const u8 stmpe1801_regs[] = {
691230f13a5SJean-Nicolas Graux 	[STMPE_IDX_CHIP_ID]	= STMPE1801_REG_CHIP_ID,
692230f13a5SJean-Nicolas Graux 	[STMPE_IDX_ICR_LSB]	= STMPE1801_REG_INT_CTRL_LOW,
693230f13a5SJean-Nicolas Graux 	[STMPE_IDX_IER_LSB]	= STMPE1801_REG_INT_EN_MASK_LOW,
694230f13a5SJean-Nicolas Graux 	[STMPE_IDX_ISR_LSB]	= STMPE1801_REG_INT_STA_LOW,
695230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPMR_LSB]	= STMPE1801_REG_GPIO_MP_LOW,
696230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPSR_LSB]	= STMPE1801_REG_GPIO_SET_LOW,
697230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPCR_LSB]	= STMPE1801_REG_GPIO_CLR_LOW,
698230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPDR_LSB]	= STMPE1801_REG_GPIO_SET_DIR_LOW,
699230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPRER_LSB]	= STMPE1801_REG_GPIO_RE_LOW,
700230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPFER_LSB]	= STMPE1801_REG_GPIO_FE_LOW,
70180e1dd82SLinus Walleij 	[STMPE_IDX_GPPUR_LSB]	= STMPE1801_REG_GPIO_PULL_UP_LOW,
702230f13a5SJean-Nicolas Graux 	[STMPE_IDX_IEGPIOR_LSB]	= STMPE1801_REG_INT_EN_GPIO_MASK_LOW,
703230f13a5SJean-Nicolas Graux 	[STMPE_IDX_ISGPIOR_LSB]	= STMPE1801_REG_INT_STA_GPIO_LOW,
704230f13a5SJean-Nicolas Graux };
705230f13a5SJean-Nicolas Graux 
706230f13a5SJean-Nicolas Graux static struct stmpe_variant_block stmpe1801_blocks[] = {
707230f13a5SJean-Nicolas Graux 	{
708230f13a5SJean-Nicolas Graux 		.cell	= &stmpe_gpio_cell,
709230f13a5SJean-Nicolas Graux 		.irq	= STMPE1801_IRQ_GPIOC,
710230f13a5SJean-Nicolas Graux 		.block	= STMPE_BLOCK_GPIO,
711230f13a5SJean-Nicolas Graux 	},
712230f13a5SJean-Nicolas Graux 	{
713230f13a5SJean-Nicolas Graux 		.cell	= &stmpe_keypad_cell,
714230f13a5SJean-Nicolas Graux 		.irq	= STMPE1801_IRQ_KEYPAD,
715230f13a5SJean-Nicolas Graux 		.block	= STMPE_BLOCK_KEYPAD,
716230f13a5SJean-Nicolas Graux 	},
717230f13a5SJean-Nicolas Graux };
718230f13a5SJean-Nicolas Graux 
719230f13a5SJean-Nicolas Graux static int stmpe1801_enable(struct stmpe *stmpe, unsigned int blocks,
720230f13a5SJean-Nicolas Graux 			    bool enable)
721230f13a5SJean-Nicolas Graux {
722230f13a5SJean-Nicolas Graux 	unsigned int mask = 0;
723230f13a5SJean-Nicolas Graux 	if (blocks & STMPE_BLOCK_GPIO)
724230f13a5SJean-Nicolas Graux 		mask |= STMPE1801_MSK_INT_EN_GPIO;
725230f13a5SJean-Nicolas Graux 
726230f13a5SJean-Nicolas Graux 	if (blocks & STMPE_BLOCK_KEYPAD)
727230f13a5SJean-Nicolas Graux 		mask |= STMPE1801_MSK_INT_EN_KPC;
728230f13a5SJean-Nicolas Graux 
729230f13a5SJean-Nicolas Graux 	return __stmpe_set_bits(stmpe, STMPE1801_REG_INT_EN_MASK_LOW, mask,
730230f13a5SJean-Nicolas Graux 				enable ? mask : 0);
731230f13a5SJean-Nicolas Graux }
732230f13a5SJean-Nicolas Graux 
733230f13a5SJean-Nicolas Graux static int stmpe1801_reset(struct stmpe *stmpe)
734230f13a5SJean-Nicolas Graux {
735230f13a5SJean-Nicolas Graux 	unsigned long timeout;
736230f13a5SJean-Nicolas Graux 	int ret = 0;
737230f13a5SJean-Nicolas Graux 
738230f13a5SJean-Nicolas Graux 	ret = __stmpe_set_bits(stmpe, STMPE1801_REG_SYS_CTRL,
739230f13a5SJean-Nicolas Graux 		STMPE1801_MSK_SYS_CTRL_RESET, STMPE1801_MSK_SYS_CTRL_RESET);
740230f13a5SJean-Nicolas Graux 	if (ret < 0)
741230f13a5SJean-Nicolas Graux 		return ret;
742230f13a5SJean-Nicolas Graux 
743230f13a5SJean-Nicolas Graux 	timeout = jiffies + msecs_to_jiffies(100);
744230f13a5SJean-Nicolas Graux 	while (time_before(jiffies, timeout)) {
745230f13a5SJean-Nicolas Graux 		ret = __stmpe_reg_read(stmpe, STMPE1801_REG_SYS_CTRL);
746230f13a5SJean-Nicolas Graux 		if (ret < 0)
747230f13a5SJean-Nicolas Graux 			return ret;
748230f13a5SJean-Nicolas Graux 		if (!(ret & STMPE1801_MSK_SYS_CTRL_RESET))
749230f13a5SJean-Nicolas Graux 			return 0;
750230f13a5SJean-Nicolas Graux 		usleep_range(100, 200);
75152397fe1SSachin Kamat 	}
752230f13a5SJean-Nicolas Graux 	return -EIO;
753230f13a5SJean-Nicolas Graux }
754230f13a5SJean-Nicolas Graux 
755230f13a5SJean-Nicolas Graux static struct stmpe_variant_info stmpe1801 = {
756230f13a5SJean-Nicolas Graux 	.name		= "stmpe1801",
757230f13a5SJean-Nicolas Graux 	.id_val		= STMPE1801_ID,
758230f13a5SJean-Nicolas Graux 	.id_mask	= 0xfff0,
759230f13a5SJean-Nicolas Graux 	.num_gpios	= 18,
760230f13a5SJean-Nicolas Graux 	.af_bits	= 0,
761230f13a5SJean-Nicolas Graux 	.regs		= stmpe1801_regs,
762230f13a5SJean-Nicolas Graux 	.blocks		= stmpe1801_blocks,
763230f13a5SJean-Nicolas Graux 	.num_blocks	= ARRAY_SIZE(stmpe1801_blocks),
764230f13a5SJean-Nicolas Graux 	.num_irqs	= STMPE1801_NR_INTERNAL_IRQS,
765230f13a5SJean-Nicolas Graux 	.enable		= stmpe1801_enable,
766230f13a5SJean-Nicolas Graux 	/* stmpe1801 do not have any gpio alternate function */
767230f13a5SJean-Nicolas Graux 	.get_altfunc	= NULL,
768230f13a5SJean-Nicolas Graux };
769230f13a5SJean-Nicolas Graux 
770230f13a5SJean-Nicolas Graux /*
77127e34995SRabin Vincent  * STMPE24XX
77227e34995SRabin Vincent  */
77327e34995SRabin Vincent 
77427e34995SRabin Vincent static const u8 stmpe24xx_regs[] = {
77527e34995SRabin Vincent 	[STMPE_IDX_CHIP_ID]	= STMPE24XX_REG_CHIP_ID,
77627e34995SRabin Vincent 	[STMPE_IDX_ICR_LSB]	= STMPE24XX_REG_ICR_LSB,
77727e34995SRabin Vincent 	[STMPE_IDX_IER_LSB]	= STMPE24XX_REG_IER_LSB,
77827e34995SRabin Vincent 	[STMPE_IDX_ISR_MSB]	= STMPE24XX_REG_ISR_MSB,
77927e34995SRabin Vincent 	[STMPE_IDX_GPMR_LSB]	= STMPE24XX_REG_GPMR_LSB,
78027e34995SRabin Vincent 	[STMPE_IDX_GPSR_LSB]	= STMPE24XX_REG_GPSR_LSB,
78127e34995SRabin Vincent 	[STMPE_IDX_GPCR_LSB]	= STMPE24XX_REG_GPCR_LSB,
78227e34995SRabin Vincent 	[STMPE_IDX_GPDR_LSB]	= STMPE24XX_REG_GPDR_LSB,
78327e34995SRabin Vincent 	[STMPE_IDX_GPRER_LSB]	= STMPE24XX_REG_GPRER_LSB,
78427e34995SRabin Vincent 	[STMPE_IDX_GPFER_LSB]	= STMPE24XX_REG_GPFER_LSB,
78580e1dd82SLinus Walleij 	[STMPE_IDX_GPPUR_LSB]	= STMPE24XX_REG_GPPUR_LSB,
78680e1dd82SLinus Walleij 	[STMPE_IDX_GPPDR_LSB]	= STMPE24XX_REG_GPPDR_LSB,
78727e34995SRabin Vincent 	[STMPE_IDX_GPAFR_U_MSB]	= STMPE24XX_REG_GPAFR_U_MSB,
78827e34995SRabin Vincent 	[STMPE_IDX_IEGPIOR_LSB]	= STMPE24XX_REG_IEGPIOR_LSB,
78927e34995SRabin Vincent 	[STMPE_IDX_ISGPIOR_MSB]	= STMPE24XX_REG_ISGPIOR_MSB,
79027e34995SRabin Vincent 	[STMPE_IDX_GPEDR_MSB]	= STMPE24XX_REG_GPEDR_MSB,
79127e34995SRabin Vincent };
79227e34995SRabin Vincent 
79327e34995SRabin Vincent static struct stmpe_variant_block stmpe24xx_blocks[] = {
79427e34995SRabin Vincent 	{
79527e34995SRabin Vincent 		.cell	= &stmpe_gpio_cell,
79627e34995SRabin Vincent 		.irq	= STMPE24XX_IRQ_GPIOC,
79727e34995SRabin Vincent 		.block	= STMPE_BLOCK_GPIO,
79827e34995SRabin Vincent 	},
79927e34995SRabin Vincent 	{
80027e34995SRabin Vincent 		.cell	= &stmpe_keypad_cell,
80127e34995SRabin Vincent 		.irq	= STMPE24XX_IRQ_KEYPAD,
80227e34995SRabin Vincent 		.block	= STMPE_BLOCK_KEYPAD,
80327e34995SRabin Vincent 	},
804b273c5e0SLinus Walleij 	{
805b273c5e0SLinus Walleij 		.cell	= &stmpe_pwm_cell,
806b273c5e0SLinus Walleij 		.irq	= STMPE24XX_IRQ_PWM0,
807b273c5e0SLinus Walleij 		.block	= STMPE_BLOCK_PWM,
808b273c5e0SLinus Walleij 	},
80927e34995SRabin Vincent };
81027e34995SRabin Vincent 
81127e34995SRabin Vincent static int stmpe24xx_enable(struct stmpe *stmpe, unsigned int blocks,
81227e34995SRabin Vincent 			    bool enable)
81327e34995SRabin Vincent {
81427e34995SRabin Vincent 	unsigned int mask = 0;
81527e34995SRabin Vincent 
81627e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_GPIO)
81727e34995SRabin Vincent 		mask |= STMPE24XX_SYS_CTRL_ENABLE_GPIO;
81827e34995SRabin Vincent 
81927e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_KEYPAD)
82027e34995SRabin Vincent 		mask |= STMPE24XX_SYS_CTRL_ENABLE_KPC;
82127e34995SRabin Vincent 
82227e34995SRabin Vincent 	return __stmpe_set_bits(stmpe, STMPE24XX_REG_SYS_CTRL, mask,
82327e34995SRabin Vincent 				enable ? mask : 0);
82427e34995SRabin Vincent }
82527e34995SRabin Vincent 
82627e34995SRabin Vincent static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
82727e34995SRabin Vincent {
82827e34995SRabin Vincent 	switch (block) {
82927e34995SRabin Vincent 	case STMPE_BLOCK_ROTATOR:
83027e34995SRabin Vincent 		return 2;
83127e34995SRabin Vincent 
83227e34995SRabin Vincent 	case STMPE_BLOCK_KEYPAD:
833f6d10341SLinus Walleij 	case STMPE_BLOCK_PWM:
83427e34995SRabin Vincent 		return 1;
83527e34995SRabin Vincent 
83627e34995SRabin Vincent 	case STMPE_BLOCK_GPIO:
83727e34995SRabin Vincent 	default:
83827e34995SRabin Vincent 		return 0;
83927e34995SRabin Vincent 	}
84027e34995SRabin Vincent }
84127e34995SRabin Vincent 
84227e34995SRabin Vincent static struct stmpe_variant_info stmpe2401 = {
84327e34995SRabin Vincent 	.name		= "stmpe2401",
84427e34995SRabin Vincent 	.id_val		= 0x0101,
84527e34995SRabin Vincent 	.id_mask	= 0xffff,
84627e34995SRabin Vincent 	.num_gpios	= 24,
84727e34995SRabin Vincent 	.af_bits	= 2,
84827e34995SRabin Vincent 	.regs		= stmpe24xx_regs,
84927e34995SRabin Vincent 	.blocks		= stmpe24xx_blocks,
85027e34995SRabin Vincent 	.num_blocks	= ARRAY_SIZE(stmpe24xx_blocks),
85127e34995SRabin Vincent 	.num_irqs	= STMPE24XX_NR_INTERNAL_IRQS,
85227e34995SRabin Vincent 	.enable		= stmpe24xx_enable,
85327e34995SRabin Vincent 	.get_altfunc	= stmpe24xx_get_altfunc,
85427e34995SRabin Vincent };
85527e34995SRabin Vincent 
85627e34995SRabin Vincent static struct stmpe_variant_info stmpe2403 = {
85727e34995SRabin Vincent 	.name		= "stmpe2403",
85827e34995SRabin Vincent 	.id_val		= 0x0120,
85927e34995SRabin Vincent 	.id_mask	= 0xffff,
86027e34995SRabin Vincent 	.num_gpios	= 24,
86127e34995SRabin Vincent 	.af_bits	= 2,
86227e34995SRabin Vincent 	.regs		= stmpe24xx_regs,
86327e34995SRabin Vincent 	.blocks		= stmpe24xx_blocks,
86427e34995SRabin Vincent 	.num_blocks	= ARRAY_SIZE(stmpe24xx_blocks),
86527e34995SRabin Vincent 	.num_irqs	= STMPE24XX_NR_INTERNAL_IRQS,
86627e34995SRabin Vincent 	.enable		= stmpe24xx_enable,
86727e34995SRabin Vincent 	.get_altfunc	= stmpe24xx_get_altfunc,
8685981f4e6SSundar R Iyer 	.enable_autosleep	= stmpe1601_autosleep, /* same as stmpe1601 */
86927e34995SRabin Vincent };
87027e34995SRabin Vincent 
871e31f9b82SChris Blair static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
8721cda2394SViresh Kumar 	[STMPE610]	= &stmpe610,
8737f7f4ea1SViresh Kumar 	[STMPE801]	= &stmpe801,
87427e34995SRabin Vincent 	[STMPE811]	= &stmpe811,
87527e34995SRabin Vincent 	[STMPE1601]	= &stmpe1601,
876230f13a5SJean-Nicolas Graux 	[STMPE1801]	= &stmpe1801,
87727e34995SRabin Vincent 	[STMPE2401]	= &stmpe2401,
87827e34995SRabin Vincent 	[STMPE2403]	= &stmpe2403,
87927e34995SRabin Vincent };
88027e34995SRabin Vincent 
881e31f9b82SChris Blair /*
882e31f9b82SChris Blair  * These devices can be connected in a 'no-irq' configuration - the irq pin
883e31f9b82SChris Blair  * is not used and the device cannot interrupt the CPU. Here we only list
884e31f9b82SChris Blair  * devices which support this configuration - the driver will fail probing
885e31f9b82SChris Blair  * for any devices not listed here which are configured in this way.
886e31f9b82SChris Blair  */
887e31f9b82SChris Blair static struct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = {
888e31f9b82SChris Blair 	[STMPE801]	= &stmpe801_noirq,
889e31f9b82SChris Blair };
890e31f9b82SChris Blair 
89127e34995SRabin Vincent static irqreturn_t stmpe_irq(int irq, void *data)
89227e34995SRabin Vincent {
89327e34995SRabin Vincent 	struct stmpe *stmpe = data;
89427e34995SRabin Vincent 	struct stmpe_variant_info *variant = stmpe->variant;
89527e34995SRabin Vincent 	int num = DIV_ROUND_UP(variant->num_irqs, 8);
896230f13a5SJean-Nicolas Graux 	u8 israddr;
8977929fa77SLee Jones 	u8 isr[3];
89827e34995SRabin Vincent 	int ret;
89927e34995SRabin Vincent 	int i;
90027e34995SRabin Vincent 
9017f7f4ea1SViresh Kumar 	if (variant->id_val == STMPE801_ID) {
90276f93992SLee Jones 		int base = irq_create_mapping(stmpe->domain, 0);
90376f93992SLee Jones 
90476f93992SLee Jones 		handle_nested_irq(base);
9057f7f4ea1SViresh Kumar 		return IRQ_HANDLED;
9067f7f4ea1SViresh Kumar 	}
9077f7f4ea1SViresh Kumar 
908230f13a5SJean-Nicolas Graux 	if (variant->id_val == STMPE1801_ID)
909230f13a5SJean-Nicolas Graux 		israddr = stmpe->regs[STMPE_IDX_ISR_LSB];
910230f13a5SJean-Nicolas Graux 	else
911230f13a5SJean-Nicolas Graux 		israddr = stmpe->regs[STMPE_IDX_ISR_MSB];
912230f13a5SJean-Nicolas Graux 
91327e34995SRabin Vincent 	ret = stmpe_block_read(stmpe, israddr, num, isr);
91427e34995SRabin Vincent 	if (ret < 0)
91527e34995SRabin Vincent 		return IRQ_NONE;
91627e34995SRabin Vincent 
91727e34995SRabin Vincent 	for (i = 0; i < num; i++) {
91827e34995SRabin Vincent 		int bank = num - i - 1;
91927e34995SRabin Vincent 		u8 status = isr[i];
92027e34995SRabin Vincent 		u8 clear;
92127e34995SRabin Vincent 
92227e34995SRabin Vincent 		status &= stmpe->ier[bank];
92327e34995SRabin Vincent 		if (!status)
92427e34995SRabin Vincent 			continue;
92527e34995SRabin Vincent 
92627e34995SRabin Vincent 		clear = status;
92727e34995SRabin Vincent 		while (status) {
92827e34995SRabin Vincent 			int bit = __ffs(status);
92927e34995SRabin Vincent 			int line = bank * 8 + bit;
93076f93992SLee Jones 			int nestedirq = irq_create_mapping(stmpe->domain, line);
93127e34995SRabin Vincent 
93276f93992SLee Jones 			handle_nested_irq(nestedirq);
93327e34995SRabin Vincent 			status &= ~(1 << bit);
93427e34995SRabin Vincent 		}
93527e34995SRabin Vincent 
93627e34995SRabin Vincent 		stmpe_reg_write(stmpe, israddr + i, clear);
93727e34995SRabin Vincent 	}
93827e34995SRabin Vincent 
93927e34995SRabin Vincent 	return IRQ_HANDLED;
94027e34995SRabin Vincent }
94127e34995SRabin Vincent 
94243b8c084SMark Brown static void stmpe_irq_lock(struct irq_data *data)
94327e34995SRabin Vincent {
94443b8c084SMark Brown 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
94527e34995SRabin Vincent 
94627e34995SRabin Vincent 	mutex_lock(&stmpe->irq_lock);
94727e34995SRabin Vincent }
94827e34995SRabin Vincent 
94943b8c084SMark Brown static void stmpe_irq_sync_unlock(struct irq_data *data)
95027e34995SRabin Vincent {
95143b8c084SMark Brown 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
95227e34995SRabin Vincent 	struct stmpe_variant_info *variant = stmpe->variant;
95327e34995SRabin Vincent 	int num = DIV_ROUND_UP(variant->num_irqs, 8);
95427e34995SRabin Vincent 	int i;
95527e34995SRabin Vincent 
95627e34995SRabin Vincent 	for (i = 0; i < num; i++) {
95727e34995SRabin Vincent 		u8 new = stmpe->ier[i];
95827e34995SRabin Vincent 		u8 old = stmpe->oldier[i];
95927e34995SRabin Vincent 
96027e34995SRabin Vincent 		if (new == old)
96127e34995SRabin Vincent 			continue;
96227e34995SRabin Vincent 
96327e34995SRabin Vincent 		stmpe->oldier[i] = new;
96427e34995SRabin Vincent 		stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB] - i, new);
96527e34995SRabin Vincent 	}
96627e34995SRabin Vincent 
96727e34995SRabin Vincent 	mutex_unlock(&stmpe->irq_lock);
96827e34995SRabin Vincent }
96927e34995SRabin Vincent 
97043b8c084SMark Brown static void stmpe_irq_mask(struct irq_data *data)
97127e34995SRabin Vincent {
97243b8c084SMark Brown 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
97376f93992SLee Jones 	int offset = data->hwirq;
97427e34995SRabin Vincent 	int regoffset = offset / 8;
97527e34995SRabin Vincent 	int mask = 1 << (offset % 8);
97627e34995SRabin Vincent 
97727e34995SRabin Vincent 	stmpe->ier[regoffset] &= ~mask;
97827e34995SRabin Vincent }
97927e34995SRabin Vincent 
98043b8c084SMark Brown static void stmpe_irq_unmask(struct irq_data *data)
98127e34995SRabin Vincent {
98243b8c084SMark Brown 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
98376f93992SLee Jones 	int offset = data->hwirq;
98427e34995SRabin Vincent 	int regoffset = offset / 8;
98527e34995SRabin Vincent 	int mask = 1 << (offset % 8);
98627e34995SRabin Vincent 
98727e34995SRabin Vincent 	stmpe->ier[regoffset] |= mask;
98827e34995SRabin Vincent }
98927e34995SRabin Vincent 
99027e34995SRabin Vincent static struct irq_chip stmpe_irq_chip = {
99127e34995SRabin Vincent 	.name			= "stmpe",
99243b8c084SMark Brown 	.irq_bus_lock		= stmpe_irq_lock,
99343b8c084SMark Brown 	.irq_bus_sync_unlock	= stmpe_irq_sync_unlock,
99443b8c084SMark Brown 	.irq_mask		= stmpe_irq_mask,
99543b8c084SMark Brown 	.irq_unmask		= stmpe_irq_unmask,
99627e34995SRabin Vincent };
99727e34995SRabin Vincent 
99876f93992SLee Jones static int stmpe_irq_map(struct irq_domain *d, unsigned int virq,
99976f93992SLee Jones                                 irq_hw_number_t hwirq)
100027e34995SRabin Vincent {
100176f93992SLee Jones 	struct stmpe *stmpe = d->host_data;
10027f7f4ea1SViresh Kumar 	struct irq_chip *chip = NULL;
100327e34995SRabin Vincent 
10047f7f4ea1SViresh Kumar 	if (stmpe->variant->id_val != STMPE801_ID)
10057f7f4ea1SViresh Kumar 		chip = &stmpe_irq_chip;
10067f7f4ea1SViresh Kumar 
100776f93992SLee Jones 	irq_set_chip_data(virq, stmpe);
100876f93992SLee Jones 	irq_set_chip_and_handler(virq, chip, handle_edge_irq);
100976f93992SLee Jones 	irq_set_nested_thread(virq, 1);
101076f93992SLee Jones 	irq_set_noprobe(virq);
101127e34995SRabin Vincent 
101227e34995SRabin Vincent 	return 0;
101327e34995SRabin Vincent }
101427e34995SRabin Vincent 
101576f93992SLee Jones static void stmpe_irq_unmap(struct irq_domain *d, unsigned int virq)
101627e34995SRabin Vincent {
101776f93992SLee Jones 		irq_set_chip_and_handler(virq, NULL, NULL);
101876f93992SLee Jones 		irq_set_chip_data(virq, NULL);
101927e34995SRabin Vincent }
102076f93992SLee Jones 
10217ce7b26fSKrzysztof Kozlowski static const struct irq_domain_ops stmpe_irq_ops = {
102276f93992SLee Jones         .map    = stmpe_irq_map,
102376f93992SLee Jones         .unmap  = stmpe_irq_unmap,
102476f93992SLee Jones         .xlate  = irq_domain_xlate_twocell,
102576f93992SLee Jones };
102676f93992SLee Jones 
1027612b95cdSGreg Kroah-Hartman static int stmpe_irq_init(struct stmpe *stmpe, struct device_node *np)
102876f93992SLee Jones {
1029b20a4371SLee Jones 	int base = 0;
103076f93992SLee Jones 	int num_irqs = stmpe->variant->num_irqs;
103176f93992SLee Jones 
1032b20a4371SLee Jones 	stmpe->domain = irq_domain_add_simple(np, num_irqs, base,
1033b20a4371SLee Jones 					      &stmpe_irq_ops, stmpe);
103476f93992SLee Jones 	if (!stmpe->domain) {
103576f93992SLee Jones 		dev_err(stmpe->dev, "Failed to create irqdomain\n");
103676f93992SLee Jones 		return -ENOSYS;
103776f93992SLee Jones 	}
103876f93992SLee Jones 
103976f93992SLee Jones 	return 0;
104027e34995SRabin Vincent }
104127e34995SRabin Vincent 
1042612b95cdSGreg Kroah-Hartman static int stmpe_chip_init(struct stmpe *stmpe)
104327e34995SRabin Vincent {
104427e34995SRabin Vincent 	unsigned int irq_trigger = stmpe->pdata->irq_trigger;
10455981f4e6SSundar R Iyer 	int autosleep_timeout = stmpe->pdata->autosleep_timeout;
104627e34995SRabin Vincent 	struct stmpe_variant_info *variant = stmpe->variant;
1047e31f9b82SChris Blair 	u8 icr = 0;
104827e34995SRabin Vincent 	unsigned int id;
104927e34995SRabin Vincent 	u8 data[2];
105027e34995SRabin Vincent 	int ret;
105127e34995SRabin Vincent 
105227e34995SRabin Vincent 	ret = stmpe_block_read(stmpe, stmpe->regs[STMPE_IDX_CHIP_ID],
105327e34995SRabin Vincent 			       ARRAY_SIZE(data), data);
105427e34995SRabin Vincent 	if (ret < 0)
105527e34995SRabin Vincent 		return ret;
105627e34995SRabin Vincent 
105727e34995SRabin Vincent 	id = (data[0] << 8) | data[1];
105827e34995SRabin Vincent 	if ((id & variant->id_mask) != variant->id_val) {
105927e34995SRabin Vincent 		dev_err(stmpe->dev, "unknown chip id: %#x\n", id);
106027e34995SRabin Vincent 		return -EINVAL;
106127e34995SRabin Vincent 	}
106227e34995SRabin Vincent 
106327e34995SRabin Vincent 	dev_info(stmpe->dev, "%s detected, chip id: %#x\n", variant->name, id);
106427e34995SRabin Vincent 
106527e34995SRabin Vincent 	/* Disable all modules -- subdrivers should enable what they need. */
106627e34995SRabin Vincent 	ret = stmpe_disable(stmpe, ~0);
106727e34995SRabin Vincent 	if (ret)
106827e34995SRabin Vincent 		return ret;
106927e34995SRabin Vincent 
1070230f13a5SJean-Nicolas Graux 	if (id == STMPE1801_ID)	{
1071230f13a5SJean-Nicolas Graux 		ret =  stmpe1801_reset(stmpe);
1072230f13a5SJean-Nicolas Graux 		if (ret < 0)
1073230f13a5SJean-Nicolas Graux 			return ret;
1074230f13a5SJean-Nicolas Graux 	}
1075230f13a5SJean-Nicolas Graux 
1076e31f9b82SChris Blair 	if (stmpe->irq >= 0) {
10777f7f4ea1SViresh Kumar 		if (id == STMPE801_ID)
10787f7f4ea1SViresh Kumar 			icr = STMPE801_REG_SYS_CTRL_INT_EN;
10797f7f4ea1SViresh Kumar 		else
10807f7f4ea1SViresh Kumar 			icr = STMPE_ICR_LSB_GIM;
10817f7f4ea1SViresh Kumar 
10827f7f4ea1SViresh Kumar 		/* STMPE801 doesn't support Edge interrupts */
10837f7f4ea1SViresh Kumar 		if (id != STMPE801_ID) {
108427e34995SRabin Vincent 			if (irq_trigger == IRQF_TRIGGER_FALLING ||
108527e34995SRabin Vincent 					irq_trigger == IRQF_TRIGGER_RISING)
108627e34995SRabin Vincent 				icr |= STMPE_ICR_LSB_EDGE;
10877f7f4ea1SViresh Kumar 		}
108827e34995SRabin Vincent 
108927e34995SRabin Vincent 		if (irq_trigger == IRQF_TRIGGER_RISING ||
10907f7f4ea1SViresh Kumar 				irq_trigger == IRQF_TRIGGER_HIGH) {
10917f7f4ea1SViresh Kumar 			if (id == STMPE801_ID)
10927f7f4ea1SViresh Kumar 				icr |= STMPE801_REG_SYS_CTRL_INT_HI;
10937f7f4ea1SViresh Kumar 			else
109427e34995SRabin Vincent 				icr |= STMPE_ICR_LSB_HIGH;
10957f7f4ea1SViresh Kumar 		}
1096e31f9b82SChris Blair 	}
109727e34995SRabin Vincent 
10985981f4e6SSundar R Iyer 	if (stmpe->pdata->autosleep) {
10995981f4e6SSundar R Iyer 		ret = stmpe_autosleep(stmpe, autosleep_timeout);
11005981f4e6SSundar R Iyer 		if (ret)
11015981f4e6SSundar R Iyer 			return ret;
11025981f4e6SSundar R Iyer 	}
11035981f4e6SSundar R Iyer 
110427e34995SRabin Vincent 	return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr);
110527e34995SRabin Vincent }
110627e34995SRabin Vincent 
11076bbb3c4cSGeert Uytterhoeven static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell)
110827e34995SRabin Vincent {
110927e34995SRabin Vincent 	return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
11109e9dc7d9SLinus Walleij 			       NULL, 0, stmpe->domain);
111127e34995SRabin Vincent }
111227e34995SRabin Vincent 
1113612b95cdSGreg Kroah-Hartman static int stmpe_devices_init(struct stmpe *stmpe)
111427e34995SRabin Vincent {
111527e34995SRabin Vincent 	struct stmpe_variant_info *variant = stmpe->variant;
111627e34995SRabin Vincent 	unsigned int platform_blocks = stmpe->pdata->blocks;
111727e34995SRabin Vincent 	int ret = -EINVAL;
11187da0cbfcSLee Jones 	int i, j;
111927e34995SRabin Vincent 
112027e34995SRabin Vincent 	for (i = 0; i < variant->num_blocks; i++) {
112127e34995SRabin Vincent 		struct stmpe_variant_block *block = &variant->blocks[i];
112227e34995SRabin Vincent 
112327e34995SRabin Vincent 		if (!(platform_blocks & block->block))
112427e34995SRabin Vincent 			continue;
112527e34995SRabin Vincent 
11267da0cbfcSLee Jones 		for (j = 0; j < block->cell->num_resources; j++) {
11277da0cbfcSLee Jones 			struct resource *res =
11287da0cbfcSLee Jones 				(struct resource *) &block->cell->resources[j];
11297da0cbfcSLee Jones 
11307da0cbfcSLee Jones 			/* Dynamically fill in a variant's IRQ. */
11317da0cbfcSLee Jones 			if (res->flags & IORESOURCE_IRQ)
11327da0cbfcSLee Jones 				res->start = res->end = block->irq + j;
11337da0cbfcSLee Jones 		}
11347da0cbfcSLee Jones 
113527e34995SRabin Vincent 		platform_blocks &= ~block->block;
11367da0cbfcSLee Jones 		ret = stmpe_add_device(stmpe, block->cell);
113727e34995SRabin Vincent 		if (ret)
113827e34995SRabin Vincent 			return ret;
113927e34995SRabin Vincent 	}
114027e34995SRabin Vincent 
114127e34995SRabin Vincent 	if (platform_blocks)
114227e34995SRabin Vincent 		dev_warn(stmpe->dev,
114327e34995SRabin Vincent 			 "platform wants blocks (%#x) not present on variant",
114427e34995SRabin Vincent 			 platform_blocks);
114527e34995SRabin Vincent 
114627e34995SRabin Vincent 	return ret;
114727e34995SRabin Vincent }
114827e34995SRabin Vincent 
1149a9c4055dSMark Brown static void stmpe_of_probe(struct stmpe_platform_data *pdata,
1150a9c4055dSMark Brown 			   struct device_node *np)
1151909582caSLee Jones {
1152909582caSLee Jones 	struct device_node *child;
1153909582caSLee Jones 
1154408a3fa8SGabriel Fernandez 	pdata->id = of_alias_get_id(np, "stmpe-i2c");
1155408a3fa8SGabriel Fernandez 	if (pdata->id < 0)
1156ac713cc9SVipul Kumar Samar 		pdata->id = -1;
1157408a3fa8SGabriel Fernandez 
1158851ec596SSean Cross 	pdata->irq_gpio = of_get_named_gpio_flags(np, "irq-gpio", 0,
1159851ec596SSean Cross 				&pdata->irq_trigger);
1160851ec596SSean Cross 	if (gpio_is_valid(pdata->irq_gpio))
1161851ec596SSean Cross 		pdata->irq_over_gpio = 1;
1162851ec596SSean Cross 	else
1163ac713cc9SVipul Kumar Samar 		pdata->irq_trigger = IRQF_TRIGGER_NONE;
1164ac713cc9SVipul Kumar Samar 
1165909582caSLee Jones 	of_property_read_u32(np, "st,autosleep-timeout",
1166909582caSLee Jones 			&pdata->autosleep_timeout);
1167909582caSLee Jones 
1168909582caSLee Jones 	pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
1169909582caSLee Jones 
1170909582caSLee Jones 	for_each_child_of_node(np, child) {
1171909582caSLee Jones 		if (!strcmp(child->name, "stmpe_gpio")) {
1172909582caSLee Jones 			pdata->blocks |= STMPE_BLOCK_GPIO;
1173ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_keypad")) {
1174909582caSLee Jones 			pdata->blocks |= STMPE_BLOCK_KEYPAD;
1175ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_touchscreen")) {
1176909582caSLee Jones 			pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
1177ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_adc")) {
1178909582caSLee Jones 			pdata->blocks |= STMPE_BLOCK_ADC;
1179ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_pwm")) {
1180ac713cc9SVipul Kumar Samar 			pdata->blocks |= STMPE_BLOCK_PWM;
1181ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_rotator")) {
1182ac713cc9SVipul Kumar Samar 			pdata->blocks |= STMPE_BLOCK_ROTATOR;
1183909582caSLee Jones 		}
1184909582caSLee Jones 	}
1185909582caSLee Jones }
1186909582caSLee Jones 
11871a6e4b74SViresh Kumar /* Called from client specific probe routines */
1188c00572bcSLee Jones int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
1189208c4343SSundar Iyer {
11901a6e4b74SViresh Kumar 	struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
1191909582caSLee Jones 	struct device_node *np = ci->dev->of_node;
119227e34995SRabin Vincent 	struct stmpe *stmpe;
119327e34995SRabin Vincent 	int ret;
119427e34995SRabin Vincent 
1195909582caSLee Jones 	if (!pdata) {
1196cb5faba9SViresh Kumar 		if (!np)
119727e34995SRabin Vincent 			return -EINVAL;
119827e34995SRabin Vincent 
1199cb5faba9SViresh Kumar 		pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL);
120027e34995SRabin Vincent 		if (!pdata)
1201909582caSLee Jones 			return -ENOMEM;
1202909582caSLee Jones 
1203909582caSLee Jones 		stmpe_of_probe(pdata, np);
1204a200e320SGabriel Fernandez 
1205a200e320SGabriel Fernandez 		if (of_find_property(np, "interrupts", NULL) == NULL)
1206a200e320SGabriel Fernandez 			ci->irq = -1;
1207909582caSLee Jones 	}
120827e34995SRabin Vincent 
1209cb5faba9SViresh Kumar 	stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL);
121027e34995SRabin Vincent 	if (!stmpe)
121127e34995SRabin Vincent 		return -ENOMEM;
121227e34995SRabin Vincent 
121327e34995SRabin Vincent 	mutex_init(&stmpe->irq_lock);
121427e34995SRabin Vincent 	mutex_init(&stmpe->lock);
121527e34995SRabin Vincent 
12161a6e4b74SViresh Kumar 	stmpe->dev = ci->dev;
12171a6e4b74SViresh Kumar 	stmpe->client = ci->client;
121827e34995SRabin Vincent 	stmpe->pdata = pdata;
12191a6e4b74SViresh Kumar 	stmpe->ci = ci;
12201a6e4b74SViresh Kumar 	stmpe->partnum = partnum;
12211a6e4b74SViresh Kumar 	stmpe->variant = stmpe_variant_info[partnum];
122227e34995SRabin Vincent 	stmpe->regs = stmpe->variant->regs;
122327e34995SRabin Vincent 	stmpe->num_gpios = stmpe->variant->num_gpios;
12249c9e3214SLinus Walleij 	stmpe->vcc = devm_regulator_get_optional(ci->dev, "vcc");
12259c9e3214SLinus Walleij 	if (!IS_ERR(stmpe->vcc)) {
12269c9e3214SLinus Walleij 		ret = regulator_enable(stmpe->vcc);
12279c9e3214SLinus Walleij 		if (ret)
12289c9e3214SLinus Walleij 			dev_warn(ci->dev, "failed to enable VCC supply\n");
12299c9e3214SLinus Walleij 	}
12309c9e3214SLinus Walleij 	stmpe->vio = devm_regulator_get_optional(ci->dev, "vio");
12319c9e3214SLinus Walleij 	if (!IS_ERR(stmpe->vio)) {
12329c9e3214SLinus Walleij 		ret = regulator_enable(stmpe->vio);
12339c9e3214SLinus Walleij 		if (ret)
12349c9e3214SLinus Walleij 			dev_warn(ci->dev, "failed to enable VIO supply\n");
12359c9e3214SLinus Walleij 	}
12361a6e4b74SViresh Kumar 	dev_set_drvdata(stmpe->dev, stmpe);
123727e34995SRabin Vincent 
12381a6e4b74SViresh Kumar 	if (ci->init)
12391a6e4b74SViresh Kumar 		ci->init(stmpe);
124027e34995SRabin Vincent 
124173de16dbSViresh Kumar 	if (pdata->irq_over_gpio) {
1242cb5faba9SViresh Kumar 		ret = devm_gpio_request_one(ci->dev, pdata->irq_gpio,
1243cb5faba9SViresh Kumar 				GPIOF_DIR_IN, "stmpe");
124473de16dbSViresh Kumar 		if (ret) {
124573de16dbSViresh Kumar 			dev_err(stmpe->dev, "failed to request IRQ GPIO: %d\n",
124673de16dbSViresh Kumar 					ret);
1247cb5faba9SViresh Kumar 			return ret;
124873de16dbSViresh Kumar 		}
124973de16dbSViresh Kumar 
125073de16dbSViresh Kumar 		stmpe->irq = gpio_to_irq(pdata->irq_gpio);
125173de16dbSViresh Kumar 	} else {
12521a6e4b74SViresh Kumar 		stmpe->irq = ci->irq;
125373de16dbSViresh Kumar 	}
125473de16dbSViresh Kumar 
1255e31f9b82SChris Blair 	if (stmpe->irq < 0) {
1256e31f9b82SChris Blair 		/* use alternate variant info for no-irq mode, if supported */
1257e31f9b82SChris Blair 		dev_info(stmpe->dev,
1258e31f9b82SChris Blair 			"%s configured in no-irq mode by platform data\n",
1259e31f9b82SChris Blair 			stmpe->variant->name);
1260e31f9b82SChris Blair 		if (!stmpe_noirq_variant_info[stmpe->partnum]) {
1261e31f9b82SChris Blair 			dev_err(stmpe->dev,
1262e31f9b82SChris Blair 				"%s does not support no-irq mode!\n",
1263e31f9b82SChris Blair 				stmpe->variant->name);
1264cb5faba9SViresh Kumar 			return -ENODEV;
1265e31f9b82SChris Blair 		}
1266e31f9b82SChris Blair 		stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum];
1267ac713cc9SVipul Kumar Samar 	} else if (pdata->irq_trigger == IRQF_TRIGGER_NONE) {
12681a5595cbSJavier Martinez Canillas 		pdata->irq_trigger = irq_get_trigger_type(stmpe->irq);
1269e31f9b82SChris Blair 	}
1270e31f9b82SChris Blair 
127127e34995SRabin Vincent 	ret = stmpe_chip_init(stmpe);
127227e34995SRabin Vincent 	if (ret)
1273cb5faba9SViresh Kumar 		return ret;
127427e34995SRabin Vincent 
1275e31f9b82SChris Blair 	if (stmpe->irq >= 0) {
1276909582caSLee Jones 		ret = stmpe_irq_init(stmpe, np);
127727e34995SRabin Vincent 		if (ret)
1278cb5faba9SViresh Kumar 			return ret;
127927e34995SRabin Vincent 
1280cb5faba9SViresh Kumar 		ret = devm_request_threaded_irq(ci->dev, stmpe->irq, NULL,
1281cb5faba9SViresh Kumar 				stmpe_irq, pdata->irq_trigger | IRQF_ONESHOT,
1282e31f9b82SChris Blair 				"stmpe", stmpe);
128327e34995SRabin Vincent 		if (ret) {
1284e31f9b82SChris Blair 			dev_err(stmpe->dev, "failed to request IRQ: %d\n",
1285e31f9b82SChris Blair 					ret);
1286cb5faba9SViresh Kumar 			return ret;
128727e34995SRabin Vincent 		}
1288e31f9b82SChris Blair 	}
128927e34995SRabin Vincent 
129027e34995SRabin Vincent 	ret = stmpe_devices_init(stmpe);
1291cb5faba9SViresh Kumar 	if (!ret)
129227e34995SRabin Vincent 		return 0;
129327e34995SRabin Vincent 
1294cb5faba9SViresh Kumar 	dev_err(stmpe->dev, "failed to add children\n");
129527e34995SRabin Vincent 	mfd_remove_devices(stmpe->dev);
1296cb5faba9SViresh Kumar 
129727e34995SRabin Vincent 	return ret;
129827e34995SRabin Vincent }
129927e34995SRabin Vincent 
13001a6e4b74SViresh Kumar int stmpe_remove(struct stmpe *stmpe)
130127e34995SRabin Vincent {
13029c9e3214SLinus Walleij 	if (!IS_ERR(stmpe->vio))
13039c9e3214SLinus Walleij 		regulator_disable(stmpe->vio);
13049c9e3214SLinus Walleij 	if (!IS_ERR(stmpe->vcc))
13059c9e3214SLinus Walleij 		regulator_disable(stmpe->vcc);
13069c9e3214SLinus Walleij 
130727e34995SRabin Vincent 	mfd_remove_devices(stmpe->dev);
130827e34995SRabin Vincent 
130927e34995SRabin Vincent 	return 0;
131027e34995SRabin Vincent }
131127e34995SRabin Vincent 
1312208c4343SSundar Iyer #ifdef CONFIG_PM
13131a6e4b74SViresh Kumar static int stmpe_suspend(struct device *dev)
13141a6e4b74SViresh Kumar {
13151a6e4b74SViresh Kumar 	struct stmpe *stmpe = dev_get_drvdata(dev);
13161a6e4b74SViresh Kumar 
1317e31f9b82SChris Blair 	if (stmpe->irq >= 0 && device_may_wakeup(dev))
13181a6e4b74SViresh Kumar 		enable_irq_wake(stmpe->irq);
13191a6e4b74SViresh Kumar 
13201a6e4b74SViresh Kumar 	return 0;
13211a6e4b74SViresh Kumar }
13221a6e4b74SViresh Kumar 
13231a6e4b74SViresh Kumar static int stmpe_resume(struct device *dev)
13241a6e4b74SViresh Kumar {
13251a6e4b74SViresh Kumar 	struct stmpe *stmpe = dev_get_drvdata(dev);
13261a6e4b74SViresh Kumar 
1327e31f9b82SChris Blair 	if (stmpe->irq >= 0 && device_may_wakeup(dev))
13281a6e4b74SViresh Kumar 		disable_irq_wake(stmpe->irq);
13291a6e4b74SViresh Kumar 
13301a6e4b74SViresh Kumar 	return 0;
13311a6e4b74SViresh Kumar }
13321a6e4b74SViresh Kumar 
13331a6e4b74SViresh Kumar const struct dev_pm_ops stmpe_dev_pm_ops = {
1334208c4343SSundar Iyer 	.suspend	= stmpe_suspend,
1335208c4343SSundar Iyer 	.resume		= stmpe_resume,
1336208c4343SSundar Iyer };
1337208c4343SSundar Iyer #endif
1338