xref: /openbmc/linux/drivers/mfd/stmpe.c (revision 80e1dd82)
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;
25227e34995SRabin Vincent 	u8 regs[numregs];
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 /*
3377f7f4ea1SViresh Kumar  * STMPE801
3387f7f4ea1SViresh Kumar  */
3397f7f4ea1SViresh Kumar static const u8 stmpe801_regs[] = {
3407f7f4ea1SViresh Kumar 	[STMPE_IDX_CHIP_ID]	= STMPE801_REG_CHIP_ID,
3417f7f4ea1SViresh Kumar 	[STMPE_IDX_ICR_LSB]	= STMPE801_REG_SYS_CTRL,
3427f7f4ea1SViresh Kumar 	[STMPE_IDX_GPMR_LSB]	= STMPE801_REG_GPIO_MP_STA,
3437f7f4ea1SViresh Kumar 	[STMPE_IDX_GPSR_LSB]	= STMPE801_REG_GPIO_SET_PIN,
3447f7f4ea1SViresh Kumar 	[STMPE_IDX_GPCR_LSB]	= STMPE801_REG_GPIO_SET_PIN,
3457f7f4ea1SViresh Kumar 	[STMPE_IDX_GPDR_LSB]	= STMPE801_REG_GPIO_DIR,
3467f7f4ea1SViresh Kumar 	[STMPE_IDX_IEGPIOR_LSB] = STMPE801_REG_GPIO_INT_EN,
3477f7f4ea1SViresh Kumar 	[STMPE_IDX_ISGPIOR_MSB] = STMPE801_REG_GPIO_INT_STA,
3487f7f4ea1SViresh Kumar 
3497f7f4ea1SViresh Kumar };
3507f7f4ea1SViresh Kumar 
3517f7f4ea1SViresh Kumar static struct stmpe_variant_block stmpe801_blocks[] = {
3527f7f4ea1SViresh Kumar 	{
3537f7f4ea1SViresh Kumar 		.cell	= &stmpe_gpio_cell,
3547f7f4ea1SViresh Kumar 		.irq	= 0,
3557f7f4ea1SViresh Kumar 		.block	= STMPE_BLOCK_GPIO,
3567f7f4ea1SViresh Kumar 	},
3577f7f4ea1SViresh Kumar };
3587f7f4ea1SViresh Kumar 
359e31f9b82SChris Blair static struct stmpe_variant_block stmpe801_blocks_noirq[] = {
360e31f9b82SChris Blair 	{
361e31f9b82SChris Blair 		.cell	= &stmpe_gpio_cell_noirq,
362e31f9b82SChris Blair 		.block	= STMPE_BLOCK_GPIO,
363e31f9b82SChris Blair 	},
364e31f9b82SChris Blair };
365e31f9b82SChris Blair 
3667f7f4ea1SViresh Kumar static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks,
3677f7f4ea1SViresh Kumar 			   bool enable)
3687f7f4ea1SViresh Kumar {
3697f7f4ea1SViresh Kumar 	if (blocks & STMPE_BLOCK_GPIO)
3707f7f4ea1SViresh Kumar 		return 0;
3717f7f4ea1SViresh Kumar 	else
3727f7f4ea1SViresh Kumar 		return -EINVAL;
3737f7f4ea1SViresh Kumar }
3747f7f4ea1SViresh Kumar 
3757f7f4ea1SViresh Kumar static struct stmpe_variant_info stmpe801 = {
3767f7f4ea1SViresh Kumar 	.name		= "stmpe801",
3777f7f4ea1SViresh Kumar 	.id_val		= STMPE801_ID,
3787f7f4ea1SViresh Kumar 	.id_mask	= 0xffff,
3797f7f4ea1SViresh Kumar 	.num_gpios	= 8,
3807f7f4ea1SViresh Kumar 	.regs		= stmpe801_regs,
3817f7f4ea1SViresh Kumar 	.blocks		= stmpe801_blocks,
3827f7f4ea1SViresh Kumar 	.num_blocks	= ARRAY_SIZE(stmpe801_blocks),
3837f7f4ea1SViresh Kumar 	.num_irqs	= STMPE801_NR_INTERNAL_IRQS,
3847f7f4ea1SViresh Kumar 	.enable		= stmpe801_enable,
3857f7f4ea1SViresh Kumar };
3867f7f4ea1SViresh Kumar 
387e31f9b82SChris Blair static struct stmpe_variant_info stmpe801_noirq = {
388e31f9b82SChris Blair 	.name		= "stmpe801",
389e31f9b82SChris Blair 	.id_val		= STMPE801_ID,
390e31f9b82SChris Blair 	.id_mask	= 0xffff,
391e31f9b82SChris Blair 	.num_gpios	= 8,
392e31f9b82SChris Blair 	.regs		= stmpe801_regs,
393e31f9b82SChris Blair 	.blocks		= stmpe801_blocks_noirq,
394e31f9b82SChris Blair 	.num_blocks	= ARRAY_SIZE(stmpe801_blocks_noirq),
395e31f9b82SChris Blair 	.enable		= stmpe801_enable,
396e31f9b82SChris Blair };
397e31f9b82SChris Blair 
3987f7f4ea1SViresh Kumar /*
3991cda2394SViresh Kumar  * Touchscreen (STMPE811 or STMPE610)
40027e34995SRabin Vincent  */
40127e34995SRabin Vincent 
40227e34995SRabin Vincent static struct resource stmpe_ts_resources[] = {
40327e34995SRabin Vincent 	{
40427e34995SRabin Vincent 		.name	= "TOUCH_DET",
40527e34995SRabin Vincent 		.flags	= IORESOURCE_IRQ,
40627e34995SRabin Vincent 	},
40727e34995SRabin Vincent 	{
40827e34995SRabin Vincent 		.name	= "FIFO_TH",
40927e34995SRabin Vincent 		.flags	= IORESOURCE_IRQ,
41027e34995SRabin Vincent 	},
41127e34995SRabin Vincent };
41227e34995SRabin Vincent 
4136bbb3c4cSGeert Uytterhoeven static const struct mfd_cell stmpe_ts_cell = {
41427e34995SRabin Vincent 	.name		= "stmpe-ts",
415037db524SVipul Kumar Samar 	.of_compatible	= "st,stmpe-ts",
41627e34995SRabin Vincent 	.resources	= stmpe_ts_resources,
41727e34995SRabin Vincent 	.num_resources	= ARRAY_SIZE(stmpe_ts_resources),
41827e34995SRabin Vincent };
41927e34995SRabin Vincent 
42027e34995SRabin Vincent /*
4211cda2394SViresh Kumar  * STMPE811 or STMPE610
42227e34995SRabin Vincent  */
42327e34995SRabin Vincent 
42427e34995SRabin Vincent static const u8 stmpe811_regs[] = {
42527e34995SRabin Vincent 	[STMPE_IDX_CHIP_ID]	= STMPE811_REG_CHIP_ID,
42627e34995SRabin Vincent 	[STMPE_IDX_ICR_LSB]	= STMPE811_REG_INT_CTRL,
42727e34995SRabin Vincent 	[STMPE_IDX_IER_LSB]	= STMPE811_REG_INT_EN,
42827e34995SRabin Vincent 	[STMPE_IDX_ISR_MSB]	= STMPE811_REG_INT_STA,
42927e34995SRabin Vincent 	[STMPE_IDX_GPMR_LSB]	= STMPE811_REG_GPIO_MP_STA,
43027e34995SRabin Vincent 	[STMPE_IDX_GPSR_LSB]	= STMPE811_REG_GPIO_SET_PIN,
43127e34995SRabin Vincent 	[STMPE_IDX_GPCR_LSB]	= STMPE811_REG_GPIO_CLR_PIN,
43227e34995SRabin Vincent 	[STMPE_IDX_GPDR_LSB]	= STMPE811_REG_GPIO_DIR,
43327e34995SRabin Vincent 	[STMPE_IDX_GPRER_LSB]	= STMPE811_REG_GPIO_RE,
43427e34995SRabin Vincent 	[STMPE_IDX_GPFER_LSB]	= STMPE811_REG_GPIO_FE,
43527e34995SRabin Vincent 	[STMPE_IDX_GPAFR_U_MSB]	= STMPE811_REG_GPIO_AF,
43627e34995SRabin Vincent 	[STMPE_IDX_IEGPIOR_LSB]	= STMPE811_REG_GPIO_INT_EN,
43727e34995SRabin Vincent 	[STMPE_IDX_ISGPIOR_MSB]	= STMPE811_REG_GPIO_INT_STA,
43827e34995SRabin Vincent 	[STMPE_IDX_GPEDR_MSB]	= STMPE811_REG_GPIO_ED,
43927e34995SRabin Vincent };
44027e34995SRabin Vincent 
44127e34995SRabin Vincent static struct stmpe_variant_block stmpe811_blocks[] = {
44227e34995SRabin Vincent 	{
44327e34995SRabin Vincent 		.cell	= &stmpe_gpio_cell,
44427e34995SRabin Vincent 		.irq	= STMPE811_IRQ_GPIOC,
44527e34995SRabin Vincent 		.block	= STMPE_BLOCK_GPIO,
44627e34995SRabin Vincent 	},
44727e34995SRabin Vincent 	{
44827e34995SRabin Vincent 		.cell	= &stmpe_ts_cell,
44927e34995SRabin Vincent 		.irq	= STMPE811_IRQ_TOUCH_DET,
45027e34995SRabin Vincent 		.block	= STMPE_BLOCK_TOUCHSCREEN,
45127e34995SRabin Vincent 	},
45227e34995SRabin Vincent };
45327e34995SRabin Vincent 
45427e34995SRabin Vincent static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
45527e34995SRabin Vincent 			   bool enable)
45627e34995SRabin Vincent {
45727e34995SRabin Vincent 	unsigned int mask = 0;
45827e34995SRabin Vincent 
45927e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_GPIO)
46027e34995SRabin Vincent 		mask |= STMPE811_SYS_CTRL2_GPIO_OFF;
46127e34995SRabin Vincent 
46227e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_ADC)
46327e34995SRabin Vincent 		mask |= STMPE811_SYS_CTRL2_ADC_OFF;
46427e34995SRabin Vincent 
46527e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_TOUCHSCREEN)
46627e34995SRabin Vincent 		mask |= STMPE811_SYS_CTRL2_TSC_OFF;
46727e34995SRabin Vincent 
46827e34995SRabin Vincent 	return __stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask,
46927e34995SRabin Vincent 				enable ? 0 : mask);
47027e34995SRabin Vincent }
47127e34995SRabin Vincent 
47227e34995SRabin Vincent static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
47327e34995SRabin Vincent {
47427e34995SRabin Vincent 	/* 0 for touchscreen, 1 for GPIO */
47527e34995SRabin Vincent 	return block != STMPE_BLOCK_TOUCHSCREEN;
47627e34995SRabin Vincent }
47727e34995SRabin Vincent 
47827e34995SRabin Vincent static struct stmpe_variant_info stmpe811 = {
47927e34995SRabin Vincent 	.name		= "stmpe811",
48027e34995SRabin Vincent 	.id_val		= 0x0811,
48127e34995SRabin Vincent 	.id_mask	= 0xffff,
48227e34995SRabin Vincent 	.num_gpios	= 8,
48327e34995SRabin Vincent 	.af_bits	= 1,
48427e34995SRabin Vincent 	.regs		= stmpe811_regs,
48527e34995SRabin Vincent 	.blocks		= stmpe811_blocks,
48627e34995SRabin Vincent 	.num_blocks	= ARRAY_SIZE(stmpe811_blocks),
48727e34995SRabin Vincent 	.num_irqs	= STMPE811_NR_INTERNAL_IRQS,
48827e34995SRabin Vincent 	.enable		= stmpe811_enable,
48927e34995SRabin Vincent 	.get_altfunc	= stmpe811_get_altfunc,
49027e34995SRabin Vincent };
49127e34995SRabin Vincent 
4921cda2394SViresh Kumar /* Similar to 811, except number of gpios */
4931cda2394SViresh Kumar static struct stmpe_variant_info stmpe610 = {
4941cda2394SViresh Kumar 	.name		= "stmpe610",
4951cda2394SViresh Kumar 	.id_val		= 0x0811,
4961cda2394SViresh Kumar 	.id_mask	= 0xffff,
4971cda2394SViresh Kumar 	.num_gpios	= 6,
4981cda2394SViresh Kumar 	.af_bits	= 1,
4991cda2394SViresh Kumar 	.regs		= stmpe811_regs,
5001cda2394SViresh Kumar 	.blocks		= stmpe811_blocks,
5011cda2394SViresh Kumar 	.num_blocks	= ARRAY_SIZE(stmpe811_blocks),
5021cda2394SViresh Kumar 	.num_irqs	= STMPE811_NR_INTERNAL_IRQS,
5031cda2394SViresh Kumar 	.enable		= stmpe811_enable,
5041cda2394SViresh Kumar 	.get_altfunc	= stmpe811_get_altfunc,
5051cda2394SViresh Kumar };
5061cda2394SViresh Kumar 
50727e34995SRabin Vincent /*
50827e34995SRabin Vincent  * STMPE1601
50927e34995SRabin Vincent  */
51027e34995SRabin Vincent 
51127e34995SRabin Vincent static const u8 stmpe1601_regs[] = {
51227e34995SRabin Vincent 	[STMPE_IDX_CHIP_ID]	= STMPE1601_REG_CHIP_ID,
51327e34995SRabin Vincent 	[STMPE_IDX_ICR_LSB]	= STMPE1601_REG_ICR_LSB,
51427e34995SRabin Vincent 	[STMPE_IDX_IER_LSB]	= STMPE1601_REG_IER_LSB,
51527e34995SRabin Vincent 	[STMPE_IDX_ISR_MSB]	= STMPE1601_REG_ISR_MSB,
51627e34995SRabin Vincent 	[STMPE_IDX_GPMR_LSB]	= STMPE1601_REG_GPIO_MP_LSB,
51727e34995SRabin Vincent 	[STMPE_IDX_GPSR_LSB]	= STMPE1601_REG_GPIO_SET_LSB,
51827e34995SRabin Vincent 	[STMPE_IDX_GPCR_LSB]	= STMPE1601_REG_GPIO_CLR_LSB,
51927e34995SRabin Vincent 	[STMPE_IDX_GPDR_LSB]	= STMPE1601_REG_GPIO_SET_DIR_LSB,
52027e34995SRabin Vincent 	[STMPE_IDX_GPRER_LSB]	= STMPE1601_REG_GPIO_RE_LSB,
52127e34995SRabin Vincent 	[STMPE_IDX_GPFER_LSB]	= STMPE1601_REG_GPIO_FE_LSB,
52280e1dd82SLinus Walleij 	[STMPE_IDX_GPPUR_LSB]	= STMPE1601_REG_GPIO_PU_LSB,
52327e34995SRabin Vincent 	[STMPE_IDX_GPAFR_U_MSB]	= STMPE1601_REG_GPIO_AF_U_MSB,
52427e34995SRabin Vincent 	[STMPE_IDX_IEGPIOR_LSB]	= STMPE1601_REG_INT_EN_GPIO_MASK_LSB,
52527e34995SRabin Vincent 	[STMPE_IDX_ISGPIOR_MSB]	= STMPE1601_REG_INT_STA_GPIO_MSB,
52627e34995SRabin Vincent 	[STMPE_IDX_GPEDR_MSB]	= STMPE1601_REG_GPIO_ED_MSB,
52727e34995SRabin Vincent };
52827e34995SRabin Vincent 
52927e34995SRabin Vincent static struct stmpe_variant_block stmpe1601_blocks[] = {
53027e34995SRabin Vincent 	{
53127e34995SRabin Vincent 		.cell	= &stmpe_gpio_cell,
5325204e51dSLee Jones 		.irq	= STMPE1601_IRQ_GPIOC,
53327e34995SRabin Vincent 		.block	= STMPE_BLOCK_GPIO,
53427e34995SRabin Vincent 	},
53527e34995SRabin Vincent 	{
53627e34995SRabin Vincent 		.cell	= &stmpe_keypad_cell,
5375204e51dSLee Jones 		.irq	= STMPE1601_IRQ_KEYPAD,
53827e34995SRabin Vincent 		.block	= STMPE_BLOCK_KEYPAD,
53927e34995SRabin Vincent 	},
54027e34995SRabin Vincent };
54127e34995SRabin Vincent 
5425981f4e6SSundar R Iyer /* supported autosleep timeout delay (in msecs) */
5435981f4e6SSundar R Iyer static const int stmpe_autosleep_delay[] = {
5445981f4e6SSundar R Iyer 	4, 16, 32, 64, 128, 256, 512, 1024,
5455981f4e6SSundar R Iyer };
5465981f4e6SSundar R Iyer 
5475981f4e6SSundar R Iyer static int stmpe_round_timeout(int timeout)
5485981f4e6SSundar R Iyer {
5495981f4e6SSundar R Iyer 	int i;
5505981f4e6SSundar R Iyer 
5515981f4e6SSundar R Iyer 	for (i = 0; i < ARRAY_SIZE(stmpe_autosleep_delay); i++) {
5525981f4e6SSundar R Iyer 		if (stmpe_autosleep_delay[i] >= timeout)
5535981f4e6SSundar R Iyer 			return i;
5545981f4e6SSundar R Iyer 	}
5555981f4e6SSundar R Iyer 
5565981f4e6SSundar R Iyer 	/*
5575981f4e6SSundar R Iyer 	 * requests for delays longer than supported should not return the
5585981f4e6SSundar R Iyer 	 * longest supported delay
5595981f4e6SSundar R Iyer 	 */
5605981f4e6SSundar R Iyer 	return -EINVAL;
5615981f4e6SSundar R Iyer }
5625981f4e6SSundar R Iyer 
5635981f4e6SSundar R Iyer static int stmpe_autosleep(struct stmpe *stmpe, int autosleep_timeout)
5645981f4e6SSundar R Iyer {
5655981f4e6SSundar R Iyer 	int ret;
5665981f4e6SSundar R Iyer 
5675981f4e6SSundar R Iyer 	if (!stmpe->variant->enable_autosleep)
5685981f4e6SSundar R Iyer 		return -ENOSYS;
5695981f4e6SSundar R Iyer 
5705981f4e6SSundar R Iyer 	mutex_lock(&stmpe->lock);
5715981f4e6SSundar R Iyer 	ret = stmpe->variant->enable_autosleep(stmpe, autosleep_timeout);
5725981f4e6SSundar R Iyer 	mutex_unlock(&stmpe->lock);
5735981f4e6SSundar R Iyer 
5745981f4e6SSundar R Iyer 	return ret;
5755981f4e6SSundar R Iyer }
5765981f4e6SSundar R Iyer 
5775981f4e6SSundar R Iyer /*
5785981f4e6SSundar R Iyer  * Both stmpe 1601/2403 support same layout for autosleep
5795981f4e6SSundar R Iyer  */
5805981f4e6SSundar R Iyer static int stmpe1601_autosleep(struct stmpe *stmpe,
5815981f4e6SSundar R Iyer 		int autosleep_timeout)
5825981f4e6SSundar R Iyer {
5835981f4e6SSundar R Iyer 	int ret, timeout;
5845981f4e6SSundar R Iyer 
5855981f4e6SSundar R Iyer 	/* choose the best available timeout */
5865981f4e6SSundar R Iyer 	timeout = stmpe_round_timeout(autosleep_timeout);
5875981f4e6SSundar R Iyer 	if (timeout < 0) {
5885981f4e6SSundar R Iyer 		dev_err(stmpe->dev, "invalid timeout\n");
5895981f4e6SSundar R Iyer 		return timeout;
5905981f4e6SSundar R Iyer 	}
5915981f4e6SSundar R Iyer 
5925981f4e6SSundar R Iyer 	ret = __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2,
5935981f4e6SSundar R Iyer 			STMPE1601_AUTOSLEEP_TIMEOUT_MASK,
5945981f4e6SSundar R Iyer 			timeout);
5955981f4e6SSundar R Iyer 	if (ret < 0)
5965981f4e6SSundar R Iyer 		return ret;
5975981f4e6SSundar R Iyer 
5985981f4e6SSundar R Iyer 	return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2,
5995981f4e6SSundar R Iyer 			STPME1601_AUTOSLEEP_ENABLE,
6005981f4e6SSundar R Iyer 			STPME1601_AUTOSLEEP_ENABLE);
6015981f4e6SSundar R Iyer }
6025981f4e6SSundar R Iyer 
60327e34995SRabin Vincent static int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks,
60427e34995SRabin Vincent 			    bool enable)
60527e34995SRabin Vincent {
60627e34995SRabin Vincent 	unsigned int mask = 0;
60727e34995SRabin Vincent 
60827e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_GPIO)
60927e34995SRabin Vincent 		mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO;
610b69d2ad6SLinus Walleij 	else
611b69d2ad6SLinus Walleij 		mask &= ~STMPE1601_SYS_CTRL_ENABLE_GPIO;
61227e34995SRabin Vincent 
61327e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_KEYPAD)
61427e34995SRabin Vincent 		mask |= STMPE1601_SYS_CTRL_ENABLE_KPC;
615b69d2ad6SLinus Walleij 	else
616b69d2ad6SLinus Walleij 		mask &= ~STMPE1601_SYS_CTRL_ENABLE_KPC;
617b69d2ad6SLinus Walleij 
618b69d2ad6SLinus Walleij 	if (blocks & STMPE_BLOCK_PWM)
619b69d2ad6SLinus Walleij 		mask |= STMPE1601_SYS_CTRL_ENABLE_SPWM;
620b69d2ad6SLinus Walleij 	else
621b69d2ad6SLinus Walleij 		mask &= ~STMPE1601_SYS_CTRL_ENABLE_SPWM;
62227e34995SRabin Vincent 
62327e34995SRabin Vincent 	return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask,
62427e34995SRabin Vincent 				enable ? mask : 0);
62527e34995SRabin Vincent }
62627e34995SRabin Vincent 
62727e34995SRabin Vincent static int stmpe1601_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
62827e34995SRabin Vincent {
62927e34995SRabin Vincent 	switch (block) {
63027e34995SRabin Vincent 	case STMPE_BLOCK_PWM:
63127e34995SRabin Vincent 		return 2;
63227e34995SRabin Vincent 
63327e34995SRabin Vincent 	case STMPE_BLOCK_KEYPAD:
63427e34995SRabin Vincent 		return 1;
63527e34995SRabin Vincent 
63627e34995SRabin Vincent 	case STMPE_BLOCK_GPIO:
63727e34995SRabin Vincent 	default:
63827e34995SRabin Vincent 		return 0;
63927e34995SRabin Vincent 	}
64027e34995SRabin Vincent }
64127e34995SRabin Vincent 
64227e34995SRabin Vincent static struct stmpe_variant_info stmpe1601 = {
64327e34995SRabin Vincent 	.name		= "stmpe1601",
64427e34995SRabin Vincent 	.id_val		= 0x0210,
64527e34995SRabin Vincent 	.id_mask	= 0xfff0,	/* at least 0x0210 and 0x0212 */
64627e34995SRabin Vincent 	.num_gpios	= 16,
64727e34995SRabin Vincent 	.af_bits	= 2,
64827e34995SRabin Vincent 	.regs		= stmpe1601_regs,
64927e34995SRabin Vincent 	.blocks		= stmpe1601_blocks,
65027e34995SRabin Vincent 	.num_blocks	= ARRAY_SIZE(stmpe1601_blocks),
65127e34995SRabin Vincent 	.num_irqs	= STMPE1601_NR_INTERNAL_IRQS,
65227e34995SRabin Vincent 	.enable		= stmpe1601_enable,
65327e34995SRabin Vincent 	.get_altfunc	= stmpe1601_get_altfunc,
6545981f4e6SSundar R Iyer 	.enable_autosleep	= stmpe1601_autosleep,
65527e34995SRabin Vincent };
65627e34995SRabin Vincent 
65727e34995SRabin Vincent /*
658230f13a5SJean-Nicolas Graux  * STMPE1801
659230f13a5SJean-Nicolas Graux  */
660230f13a5SJean-Nicolas Graux static const u8 stmpe1801_regs[] = {
661230f13a5SJean-Nicolas Graux 	[STMPE_IDX_CHIP_ID]	= STMPE1801_REG_CHIP_ID,
662230f13a5SJean-Nicolas Graux 	[STMPE_IDX_ICR_LSB]	= STMPE1801_REG_INT_CTRL_LOW,
663230f13a5SJean-Nicolas Graux 	[STMPE_IDX_IER_LSB]	= STMPE1801_REG_INT_EN_MASK_LOW,
664230f13a5SJean-Nicolas Graux 	[STMPE_IDX_ISR_LSB]	= STMPE1801_REG_INT_STA_LOW,
665230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPMR_LSB]	= STMPE1801_REG_GPIO_MP_LOW,
666230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPSR_LSB]	= STMPE1801_REG_GPIO_SET_LOW,
667230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPCR_LSB]	= STMPE1801_REG_GPIO_CLR_LOW,
668230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPDR_LSB]	= STMPE1801_REG_GPIO_SET_DIR_LOW,
669230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPRER_LSB]	= STMPE1801_REG_GPIO_RE_LOW,
670230f13a5SJean-Nicolas Graux 	[STMPE_IDX_GPFER_LSB]	= STMPE1801_REG_GPIO_FE_LOW,
67180e1dd82SLinus Walleij 	[STMPE_IDX_GPPUR_LSB]	= STMPE1801_REG_GPIO_PULL_UP_LOW,
672230f13a5SJean-Nicolas Graux 	[STMPE_IDX_IEGPIOR_LSB]	= STMPE1801_REG_INT_EN_GPIO_MASK_LOW,
673230f13a5SJean-Nicolas Graux 	[STMPE_IDX_ISGPIOR_LSB]	= STMPE1801_REG_INT_STA_GPIO_LOW,
674230f13a5SJean-Nicolas Graux };
675230f13a5SJean-Nicolas Graux 
676230f13a5SJean-Nicolas Graux static struct stmpe_variant_block stmpe1801_blocks[] = {
677230f13a5SJean-Nicolas Graux 	{
678230f13a5SJean-Nicolas Graux 		.cell	= &stmpe_gpio_cell,
679230f13a5SJean-Nicolas Graux 		.irq	= STMPE1801_IRQ_GPIOC,
680230f13a5SJean-Nicolas Graux 		.block	= STMPE_BLOCK_GPIO,
681230f13a5SJean-Nicolas Graux 	},
682230f13a5SJean-Nicolas Graux 	{
683230f13a5SJean-Nicolas Graux 		.cell	= &stmpe_keypad_cell,
684230f13a5SJean-Nicolas Graux 		.irq	= STMPE1801_IRQ_KEYPAD,
685230f13a5SJean-Nicolas Graux 		.block	= STMPE_BLOCK_KEYPAD,
686230f13a5SJean-Nicolas Graux 	},
687230f13a5SJean-Nicolas Graux };
688230f13a5SJean-Nicolas Graux 
689230f13a5SJean-Nicolas Graux static int stmpe1801_enable(struct stmpe *stmpe, unsigned int blocks,
690230f13a5SJean-Nicolas Graux 			    bool enable)
691230f13a5SJean-Nicolas Graux {
692230f13a5SJean-Nicolas Graux 	unsigned int mask = 0;
693230f13a5SJean-Nicolas Graux 	if (blocks & STMPE_BLOCK_GPIO)
694230f13a5SJean-Nicolas Graux 		mask |= STMPE1801_MSK_INT_EN_GPIO;
695230f13a5SJean-Nicolas Graux 
696230f13a5SJean-Nicolas Graux 	if (blocks & STMPE_BLOCK_KEYPAD)
697230f13a5SJean-Nicolas Graux 		mask |= STMPE1801_MSK_INT_EN_KPC;
698230f13a5SJean-Nicolas Graux 
699230f13a5SJean-Nicolas Graux 	return __stmpe_set_bits(stmpe, STMPE1801_REG_INT_EN_MASK_LOW, mask,
700230f13a5SJean-Nicolas Graux 				enable ? mask : 0);
701230f13a5SJean-Nicolas Graux }
702230f13a5SJean-Nicolas Graux 
703230f13a5SJean-Nicolas Graux static int stmpe1801_reset(struct stmpe *stmpe)
704230f13a5SJean-Nicolas Graux {
705230f13a5SJean-Nicolas Graux 	unsigned long timeout;
706230f13a5SJean-Nicolas Graux 	int ret = 0;
707230f13a5SJean-Nicolas Graux 
708230f13a5SJean-Nicolas Graux 	ret = __stmpe_set_bits(stmpe, STMPE1801_REG_SYS_CTRL,
709230f13a5SJean-Nicolas Graux 		STMPE1801_MSK_SYS_CTRL_RESET, STMPE1801_MSK_SYS_CTRL_RESET);
710230f13a5SJean-Nicolas Graux 	if (ret < 0)
711230f13a5SJean-Nicolas Graux 		return ret;
712230f13a5SJean-Nicolas Graux 
713230f13a5SJean-Nicolas Graux 	timeout = jiffies + msecs_to_jiffies(100);
714230f13a5SJean-Nicolas Graux 	while (time_before(jiffies, timeout)) {
715230f13a5SJean-Nicolas Graux 		ret = __stmpe_reg_read(stmpe, STMPE1801_REG_SYS_CTRL);
716230f13a5SJean-Nicolas Graux 		if (ret < 0)
717230f13a5SJean-Nicolas Graux 			return ret;
718230f13a5SJean-Nicolas Graux 		if (!(ret & STMPE1801_MSK_SYS_CTRL_RESET))
719230f13a5SJean-Nicolas Graux 			return 0;
720230f13a5SJean-Nicolas Graux 		usleep_range(100, 200);
72152397fe1SSachin Kamat 	}
722230f13a5SJean-Nicolas Graux 	return -EIO;
723230f13a5SJean-Nicolas Graux }
724230f13a5SJean-Nicolas Graux 
725230f13a5SJean-Nicolas Graux static struct stmpe_variant_info stmpe1801 = {
726230f13a5SJean-Nicolas Graux 	.name		= "stmpe1801",
727230f13a5SJean-Nicolas Graux 	.id_val		= STMPE1801_ID,
728230f13a5SJean-Nicolas Graux 	.id_mask	= 0xfff0,
729230f13a5SJean-Nicolas Graux 	.num_gpios	= 18,
730230f13a5SJean-Nicolas Graux 	.af_bits	= 0,
731230f13a5SJean-Nicolas Graux 	.regs		= stmpe1801_regs,
732230f13a5SJean-Nicolas Graux 	.blocks		= stmpe1801_blocks,
733230f13a5SJean-Nicolas Graux 	.num_blocks	= ARRAY_SIZE(stmpe1801_blocks),
734230f13a5SJean-Nicolas Graux 	.num_irqs	= STMPE1801_NR_INTERNAL_IRQS,
735230f13a5SJean-Nicolas Graux 	.enable		= stmpe1801_enable,
736230f13a5SJean-Nicolas Graux 	/* stmpe1801 do not have any gpio alternate function */
737230f13a5SJean-Nicolas Graux 	.get_altfunc	= NULL,
738230f13a5SJean-Nicolas Graux };
739230f13a5SJean-Nicolas Graux 
740230f13a5SJean-Nicolas Graux /*
74127e34995SRabin Vincent  * STMPE24XX
74227e34995SRabin Vincent  */
74327e34995SRabin Vincent 
74427e34995SRabin Vincent static const u8 stmpe24xx_regs[] = {
74527e34995SRabin Vincent 	[STMPE_IDX_CHIP_ID]	= STMPE24XX_REG_CHIP_ID,
74627e34995SRabin Vincent 	[STMPE_IDX_ICR_LSB]	= STMPE24XX_REG_ICR_LSB,
74727e34995SRabin Vincent 	[STMPE_IDX_IER_LSB]	= STMPE24XX_REG_IER_LSB,
74827e34995SRabin Vincent 	[STMPE_IDX_ISR_MSB]	= STMPE24XX_REG_ISR_MSB,
74927e34995SRabin Vincent 	[STMPE_IDX_GPMR_LSB]	= STMPE24XX_REG_GPMR_LSB,
75027e34995SRabin Vincent 	[STMPE_IDX_GPSR_LSB]	= STMPE24XX_REG_GPSR_LSB,
75127e34995SRabin Vincent 	[STMPE_IDX_GPCR_LSB]	= STMPE24XX_REG_GPCR_LSB,
75227e34995SRabin Vincent 	[STMPE_IDX_GPDR_LSB]	= STMPE24XX_REG_GPDR_LSB,
75327e34995SRabin Vincent 	[STMPE_IDX_GPRER_LSB]	= STMPE24XX_REG_GPRER_LSB,
75427e34995SRabin Vincent 	[STMPE_IDX_GPFER_LSB]	= STMPE24XX_REG_GPFER_LSB,
75580e1dd82SLinus Walleij 	[STMPE_IDX_GPPUR_LSB]	= STMPE24XX_REG_GPPUR_LSB,
75680e1dd82SLinus Walleij 	[STMPE_IDX_GPPDR_LSB]	= STMPE24XX_REG_GPPDR_LSB,
75727e34995SRabin Vincent 	[STMPE_IDX_GPAFR_U_MSB]	= STMPE24XX_REG_GPAFR_U_MSB,
75827e34995SRabin Vincent 	[STMPE_IDX_IEGPIOR_LSB]	= STMPE24XX_REG_IEGPIOR_LSB,
75927e34995SRabin Vincent 	[STMPE_IDX_ISGPIOR_MSB]	= STMPE24XX_REG_ISGPIOR_MSB,
76027e34995SRabin Vincent 	[STMPE_IDX_GPEDR_MSB]	= STMPE24XX_REG_GPEDR_MSB,
76127e34995SRabin Vincent };
76227e34995SRabin Vincent 
76327e34995SRabin Vincent static struct stmpe_variant_block stmpe24xx_blocks[] = {
76427e34995SRabin Vincent 	{
76527e34995SRabin Vincent 		.cell	= &stmpe_gpio_cell,
76627e34995SRabin Vincent 		.irq	= STMPE24XX_IRQ_GPIOC,
76727e34995SRabin Vincent 		.block	= STMPE_BLOCK_GPIO,
76827e34995SRabin Vincent 	},
76927e34995SRabin Vincent 	{
77027e34995SRabin Vincent 		.cell	= &stmpe_keypad_cell,
77127e34995SRabin Vincent 		.irq	= STMPE24XX_IRQ_KEYPAD,
77227e34995SRabin Vincent 		.block	= STMPE_BLOCK_KEYPAD,
77327e34995SRabin Vincent 	},
77427e34995SRabin Vincent };
77527e34995SRabin Vincent 
77627e34995SRabin Vincent static int stmpe24xx_enable(struct stmpe *stmpe, unsigned int blocks,
77727e34995SRabin Vincent 			    bool enable)
77827e34995SRabin Vincent {
77927e34995SRabin Vincent 	unsigned int mask = 0;
78027e34995SRabin Vincent 
78127e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_GPIO)
78227e34995SRabin Vincent 		mask |= STMPE24XX_SYS_CTRL_ENABLE_GPIO;
78327e34995SRabin Vincent 
78427e34995SRabin Vincent 	if (blocks & STMPE_BLOCK_KEYPAD)
78527e34995SRabin Vincent 		mask |= STMPE24XX_SYS_CTRL_ENABLE_KPC;
78627e34995SRabin Vincent 
78727e34995SRabin Vincent 	return __stmpe_set_bits(stmpe, STMPE24XX_REG_SYS_CTRL, mask,
78827e34995SRabin Vincent 				enable ? mask : 0);
78927e34995SRabin Vincent }
79027e34995SRabin Vincent 
79127e34995SRabin Vincent static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
79227e34995SRabin Vincent {
79327e34995SRabin Vincent 	switch (block) {
79427e34995SRabin Vincent 	case STMPE_BLOCK_ROTATOR:
79527e34995SRabin Vincent 		return 2;
79627e34995SRabin Vincent 
79727e34995SRabin Vincent 	case STMPE_BLOCK_KEYPAD:
79827e34995SRabin Vincent 		return 1;
79927e34995SRabin Vincent 
80027e34995SRabin Vincent 	case STMPE_BLOCK_GPIO:
80127e34995SRabin Vincent 	default:
80227e34995SRabin Vincent 		return 0;
80327e34995SRabin Vincent 	}
80427e34995SRabin Vincent }
80527e34995SRabin Vincent 
80627e34995SRabin Vincent static struct stmpe_variant_info stmpe2401 = {
80727e34995SRabin Vincent 	.name		= "stmpe2401",
80827e34995SRabin Vincent 	.id_val		= 0x0101,
80927e34995SRabin Vincent 	.id_mask	= 0xffff,
81027e34995SRabin Vincent 	.num_gpios	= 24,
81127e34995SRabin Vincent 	.af_bits	= 2,
81227e34995SRabin Vincent 	.regs		= stmpe24xx_regs,
81327e34995SRabin Vincent 	.blocks		= stmpe24xx_blocks,
81427e34995SRabin Vincent 	.num_blocks	= ARRAY_SIZE(stmpe24xx_blocks),
81527e34995SRabin Vincent 	.num_irqs	= STMPE24XX_NR_INTERNAL_IRQS,
81627e34995SRabin Vincent 	.enable		= stmpe24xx_enable,
81727e34995SRabin Vincent 	.get_altfunc	= stmpe24xx_get_altfunc,
81827e34995SRabin Vincent };
81927e34995SRabin Vincent 
82027e34995SRabin Vincent static struct stmpe_variant_info stmpe2403 = {
82127e34995SRabin Vincent 	.name		= "stmpe2403",
82227e34995SRabin Vincent 	.id_val		= 0x0120,
82327e34995SRabin Vincent 	.id_mask	= 0xffff,
82427e34995SRabin Vincent 	.num_gpios	= 24,
82527e34995SRabin Vincent 	.af_bits	= 2,
82627e34995SRabin Vincent 	.regs		= stmpe24xx_regs,
82727e34995SRabin Vincent 	.blocks		= stmpe24xx_blocks,
82827e34995SRabin Vincent 	.num_blocks	= ARRAY_SIZE(stmpe24xx_blocks),
82927e34995SRabin Vincent 	.num_irqs	= STMPE24XX_NR_INTERNAL_IRQS,
83027e34995SRabin Vincent 	.enable		= stmpe24xx_enable,
83127e34995SRabin Vincent 	.get_altfunc	= stmpe24xx_get_altfunc,
8325981f4e6SSundar R Iyer 	.enable_autosleep	= stmpe1601_autosleep, /* same as stmpe1601 */
83327e34995SRabin Vincent };
83427e34995SRabin Vincent 
835e31f9b82SChris Blair static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
8361cda2394SViresh Kumar 	[STMPE610]	= &stmpe610,
8377f7f4ea1SViresh Kumar 	[STMPE801]	= &stmpe801,
83827e34995SRabin Vincent 	[STMPE811]	= &stmpe811,
83927e34995SRabin Vincent 	[STMPE1601]	= &stmpe1601,
840230f13a5SJean-Nicolas Graux 	[STMPE1801]	= &stmpe1801,
84127e34995SRabin Vincent 	[STMPE2401]	= &stmpe2401,
84227e34995SRabin Vincent 	[STMPE2403]	= &stmpe2403,
84327e34995SRabin Vincent };
84427e34995SRabin Vincent 
845e31f9b82SChris Blair /*
846e31f9b82SChris Blair  * These devices can be connected in a 'no-irq' configuration - the irq pin
847e31f9b82SChris Blair  * is not used and the device cannot interrupt the CPU. Here we only list
848e31f9b82SChris Blair  * devices which support this configuration - the driver will fail probing
849e31f9b82SChris Blair  * for any devices not listed here which are configured in this way.
850e31f9b82SChris Blair  */
851e31f9b82SChris Blair static struct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = {
852e31f9b82SChris Blair 	[STMPE801]	= &stmpe801_noirq,
853e31f9b82SChris Blair };
854e31f9b82SChris Blair 
85527e34995SRabin Vincent static irqreturn_t stmpe_irq(int irq, void *data)
85627e34995SRabin Vincent {
85727e34995SRabin Vincent 	struct stmpe *stmpe = data;
85827e34995SRabin Vincent 	struct stmpe_variant_info *variant = stmpe->variant;
85927e34995SRabin Vincent 	int num = DIV_ROUND_UP(variant->num_irqs, 8);
860230f13a5SJean-Nicolas Graux 	u8 israddr;
86127e34995SRabin Vincent 	u8 isr[num];
86227e34995SRabin Vincent 	int ret;
86327e34995SRabin Vincent 	int i;
86427e34995SRabin Vincent 
8657f7f4ea1SViresh Kumar 	if (variant->id_val == STMPE801_ID) {
86676f93992SLee Jones 		int base = irq_create_mapping(stmpe->domain, 0);
86776f93992SLee Jones 
86876f93992SLee Jones 		handle_nested_irq(base);
8697f7f4ea1SViresh Kumar 		return IRQ_HANDLED;
8707f7f4ea1SViresh Kumar 	}
8717f7f4ea1SViresh Kumar 
872230f13a5SJean-Nicolas Graux 	if (variant->id_val == STMPE1801_ID)
873230f13a5SJean-Nicolas Graux 		israddr = stmpe->regs[STMPE_IDX_ISR_LSB];
874230f13a5SJean-Nicolas Graux 	else
875230f13a5SJean-Nicolas Graux 		israddr = stmpe->regs[STMPE_IDX_ISR_MSB];
876230f13a5SJean-Nicolas Graux 
87727e34995SRabin Vincent 	ret = stmpe_block_read(stmpe, israddr, num, isr);
87827e34995SRabin Vincent 	if (ret < 0)
87927e34995SRabin Vincent 		return IRQ_NONE;
88027e34995SRabin Vincent 
88127e34995SRabin Vincent 	for (i = 0; i < num; i++) {
88227e34995SRabin Vincent 		int bank = num - i - 1;
88327e34995SRabin Vincent 		u8 status = isr[i];
88427e34995SRabin Vincent 		u8 clear;
88527e34995SRabin Vincent 
88627e34995SRabin Vincent 		status &= stmpe->ier[bank];
88727e34995SRabin Vincent 		if (!status)
88827e34995SRabin Vincent 			continue;
88927e34995SRabin Vincent 
89027e34995SRabin Vincent 		clear = status;
89127e34995SRabin Vincent 		while (status) {
89227e34995SRabin Vincent 			int bit = __ffs(status);
89327e34995SRabin Vincent 			int line = bank * 8 + bit;
89476f93992SLee Jones 			int nestedirq = irq_create_mapping(stmpe->domain, line);
89527e34995SRabin Vincent 
89676f93992SLee Jones 			handle_nested_irq(nestedirq);
89727e34995SRabin Vincent 			status &= ~(1 << bit);
89827e34995SRabin Vincent 		}
89927e34995SRabin Vincent 
90027e34995SRabin Vincent 		stmpe_reg_write(stmpe, israddr + i, clear);
90127e34995SRabin Vincent 	}
90227e34995SRabin Vincent 
90327e34995SRabin Vincent 	return IRQ_HANDLED;
90427e34995SRabin Vincent }
90527e34995SRabin Vincent 
90643b8c084SMark Brown static void stmpe_irq_lock(struct irq_data *data)
90727e34995SRabin Vincent {
90843b8c084SMark Brown 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
90927e34995SRabin Vincent 
91027e34995SRabin Vincent 	mutex_lock(&stmpe->irq_lock);
91127e34995SRabin Vincent }
91227e34995SRabin Vincent 
91343b8c084SMark Brown static void stmpe_irq_sync_unlock(struct irq_data *data)
91427e34995SRabin Vincent {
91543b8c084SMark Brown 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
91627e34995SRabin Vincent 	struct stmpe_variant_info *variant = stmpe->variant;
91727e34995SRabin Vincent 	int num = DIV_ROUND_UP(variant->num_irqs, 8);
91827e34995SRabin Vincent 	int i;
91927e34995SRabin Vincent 
92027e34995SRabin Vincent 	for (i = 0; i < num; i++) {
92127e34995SRabin Vincent 		u8 new = stmpe->ier[i];
92227e34995SRabin Vincent 		u8 old = stmpe->oldier[i];
92327e34995SRabin Vincent 
92427e34995SRabin Vincent 		if (new == old)
92527e34995SRabin Vincent 			continue;
92627e34995SRabin Vincent 
92727e34995SRabin Vincent 		stmpe->oldier[i] = new;
92827e34995SRabin Vincent 		stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB] - i, new);
92927e34995SRabin Vincent 	}
93027e34995SRabin Vincent 
93127e34995SRabin Vincent 	mutex_unlock(&stmpe->irq_lock);
93227e34995SRabin Vincent }
93327e34995SRabin Vincent 
93443b8c084SMark Brown static void stmpe_irq_mask(struct irq_data *data)
93527e34995SRabin Vincent {
93643b8c084SMark Brown 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
93776f93992SLee Jones 	int offset = data->hwirq;
93827e34995SRabin Vincent 	int regoffset = offset / 8;
93927e34995SRabin Vincent 	int mask = 1 << (offset % 8);
94027e34995SRabin Vincent 
94127e34995SRabin Vincent 	stmpe->ier[regoffset] &= ~mask;
94227e34995SRabin Vincent }
94327e34995SRabin Vincent 
94443b8c084SMark Brown static void stmpe_irq_unmask(struct irq_data *data)
94527e34995SRabin Vincent {
94643b8c084SMark Brown 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
94776f93992SLee Jones 	int offset = data->hwirq;
94827e34995SRabin Vincent 	int regoffset = offset / 8;
94927e34995SRabin Vincent 	int mask = 1 << (offset % 8);
95027e34995SRabin Vincent 
95127e34995SRabin Vincent 	stmpe->ier[regoffset] |= mask;
95227e34995SRabin Vincent }
95327e34995SRabin Vincent 
95427e34995SRabin Vincent static struct irq_chip stmpe_irq_chip = {
95527e34995SRabin Vincent 	.name			= "stmpe",
95643b8c084SMark Brown 	.irq_bus_lock		= stmpe_irq_lock,
95743b8c084SMark Brown 	.irq_bus_sync_unlock	= stmpe_irq_sync_unlock,
95843b8c084SMark Brown 	.irq_mask		= stmpe_irq_mask,
95943b8c084SMark Brown 	.irq_unmask		= stmpe_irq_unmask,
96027e34995SRabin Vincent };
96127e34995SRabin Vincent 
96276f93992SLee Jones static int stmpe_irq_map(struct irq_domain *d, unsigned int virq,
96376f93992SLee Jones                                 irq_hw_number_t hwirq)
96427e34995SRabin Vincent {
96576f93992SLee Jones 	struct stmpe *stmpe = d->host_data;
9667f7f4ea1SViresh Kumar 	struct irq_chip *chip = NULL;
96727e34995SRabin Vincent 
9687f7f4ea1SViresh Kumar 	if (stmpe->variant->id_val != STMPE801_ID)
9697f7f4ea1SViresh Kumar 		chip = &stmpe_irq_chip;
9707f7f4ea1SViresh Kumar 
97176f93992SLee Jones 	irq_set_chip_data(virq, stmpe);
97276f93992SLee Jones 	irq_set_chip_and_handler(virq, chip, handle_edge_irq);
97376f93992SLee Jones 	irq_set_nested_thread(virq, 1);
97427e34995SRabin Vincent #ifdef CONFIG_ARM
97576f93992SLee Jones 	set_irq_flags(virq, IRQF_VALID);
97627e34995SRabin Vincent #else
97776f93992SLee Jones 	irq_set_noprobe(virq);
97827e34995SRabin Vincent #endif
97927e34995SRabin Vincent 
98027e34995SRabin Vincent 	return 0;
98127e34995SRabin Vincent }
98227e34995SRabin Vincent 
98376f93992SLee Jones static void stmpe_irq_unmap(struct irq_domain *d, unsigned int virq)
98427e34995SRabin Vincent {
98527e34995SRabin Vincent #ifdef CONFIG_ARM
98676f93992SLee Jones 		set_irq_flags(virq, 0);
98727e34995SRabin Vincent #endif
98876f93992SLee Jones 		irq_set_chip_and_handler(virq, NULL, NULL);
98976f93992SLee Jones 		irq_set_chip_data(virq, NULL);
99027e34995SRabin Vincent }
99176f93992SLee Jones 
99276f93992SLee Jones static struct irq_domain_ops stmpe_irq_ops = {
99376f93992SLee Jones         .map    = stmpe_irq_map,
99476f93992SLee Jones         .unmap  = stmpe_irq_unmap,
99576f93992SLee Jones         .xlate  = irq_domain_xlate_twocell,
99676f93992SLee Jones };
99776f93992SLee Jones 
998612b95cdSGreg Kroah-Hartman static int stmpe_irq_init(struct stmpe *stmpe, struct device_node *np)
99976f93992SLee Jones {
1000b20a4371SLee Jones 	int base = 0;
100176f93992SLee Jones 	int num_irqs = stmpe->variant->num_irqs;
100276f93992SLee Jones 
1003b20a4371SLee Jones 	stmpe->domain = irq_domain_add_simple(np, num_irqs, base,
1004b20a4371SLee Jones 					      &stmpe_irq_ops, stmpe);
100576f93992SLee Jones 	if (!stmpe->domain) {
100676f93992SLee Jones 		dev_err(stmpe->dev, "Failed to create irqdomain\n");
100776f93992SLee Jones 		return -ENOSYS;
100876f93992SLee Jones 	}
100976f93992SLee Jones 
101076f93992SLee Jones 	return 0;
101127e34995SRabin Vincent }
101227e34995SRabin Vincent 
1013612b95cdSGreg Kroah-Hartman static int stmpe_chip_init(struct stmpe *stmpe)
101427e34995SRabin Vincent {
101527e34995SRabin Vincent 	unsigned int irq_trigger = stmpe->pdata->irq_trigger;
10165981f4e6SSundar R Iyer 	int autosleep_timeout = stmpe->pdata->autosleep_timeout;
101727e34995SRabin Vincent 	struct stmpe_variant_info *variant = stmpe->variant;
1018e31f9b82SChris Blair 	u8 icr = 0;
101927e34995SRabin Vincent 	unsigned int id;
102027e34995SRabin Vincent 	u8 data[2];
102127e34995SRabin Vincent 	int ret;
102227e34995SRabin Vincent 
102327e34995SRabin Vincent 	ret = stmpe_block_read(stmpe, stmpe->regs[STMPE_IDX_CHIP_ID],
102427e34995SRabin Vincent 			       ARRAY_SIZE(data), data);
102527e34995SRabin Vincent 	if (ret < 0)
102627e34995SRabin Vincent 		return ret;
102727e34995SRabin Vincent 
102827e34995SRabin Vincent 	id = (data[0] << 8) | data[1];
102927e34995SRabin Vincent 	if ((id & variant->id_mask) != variant->id_val) {
103027e34995SRabin Vincent 		dev_err(stmpe->dev, "unknown chip id: %#x\n", id);
103127e34995SRabin Vincent 		return -EINVAL;
103227e34995SRabin Vincent 	}
103327e34995SRabin Vincent 
103427e34995SRabin Vincent 	dev_info(stmpe->dev, "%s detected, chip id: %#x\n", variant->name, id);
103527e34995SRabin Vincent 
103627e34995SRabin Vincent 	/* Disable all modules -- subdrivers should enable what they need. */
103727e34995SRabin Vincent 	ret = stmpe_disable(stmpe, ~0);
103827e34995SRabin Vincent 	if (ret)
103927e34995SRabin Vincent 		return ret;
104027e34995SRabin Vincent 
1041230f13a5SJean-Nicolas Graux 	if (id == STMPE1801_ID)	{
1042230f13a5SJean-Nicolas Graux 		ret =  stmpe1801_reset(stmpe);
1043230f13a5SJean-Nicolas Graux 		if (ret < 0)
1044230f13a5SJean-Nicolas Graux 			return ret;
1045230f13a5SJean-Nicolas Graux 	}
1046230f13a5SJean-Nicolas Graux 
1047e31f9b82SChris Blair 	if (stmpe->irq >= 0) {
10487f7f4ea1SViresh Kumar 		if (id == STMPE801_ID)
10497f7f4ea1SViresh Kumar 			icr = STMPE801_REG_SYS_CTRL_INT_EN;
10507f7f4ea1SViresh Kumar 		else
10517f7f4ea1SViresh Kumar 			icr = STMPE_ICR_LSB_GIM;
10527f7f4ea1SViresh Kumar 
10537f7f4ea1SViresh Kumar 		/* STMPE801 doesn't support Edge interrupts */
10547f7f4ea1SViresh Kumar 		if (id != STMPE801_ID) {
105527e34995SRabin Vincent 			if (irq_trigger == IRQF_TRIGGER_FALLING ||
105627e34995SRabin Vincent 					irq_trigger == IRQF_TRIGGER_RISING)
105727e34995SRabin Vincent 				icr |= STMPE_ICR_LSB_EDGE;
10587f7f4ea1SViresh Kumar 		}
105927e34995SRabin Vincent 
106027e34995SRabin Vincent 		if (irq_trigger == IRQF_TRIGGER_RISING ||
10617f7f4ea1SViresh Kumar 				irq_trigger == IRQF_TRIGGER_HIGH) {
10627f7f4ea1SViresh Kumar 			if (id == STMPE801_ID)
10637f7f4ea1SViresh Kumar 				icr |= STMPE801_REG_SYS_CTRL_INT_HI;
10647f7f4ea1SViresh Kumar 			else
106527e34995SRabin Vincent 				icr |= STMPE_ICR_LSB_HIGH;
10667f7f4ea1SViresh Kumar 		}
1067e31f9b82SChris Blair 	}
106827e34995SRabin Vincent 
10695981f4e6SSundar R Iyer 	if (stmpe->pdata->autosleep) {
10705981f4e6SSundar R Iyer 		ret = stmpe_autosleep(stmpe, autosleep_timeout);
10715981f4e6SSundar R Iyer 		if (ret)
10725981f4e6SSundar R Iyer 			return ret;
10735981f4e6SSundar R Iyer 	}
10745981f4e6SSundar R Iyer 
107527e34995SRabin Vincent 	return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr);
107627e34995SRabin Vincent }
107727e34995SRabin Vincent 
10786bbb3c4cSGeert Uytterhoeven static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell)
107927e34995SRabin Vincent {
108027e34995SRabin Vincent 	return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
10819e9dc7d9SLinus Walleij 			       NULL, 0, stmpe->domain);
108227e34995SRabin Vincent }
108327e34995SRabin Vincent 
1084612b95cdSGreg Kroah-Hartman static int stmpe_devices_init(struct stmpe *stmpe)
108527e34995SRabin Vincent {
108627e34995SRabin Vincent 	struct stmpe_variant_info *variant = stmpe->variant;
108727e34995SRabin Vincent 	unsigned int platform_blocks = stmpe->pdata->blocks;
108827e34995SRabin Vincent 	int ret = -EINVAL;
10897da0cbfcSLee Jones 	int i, j;
109027e34995SRabin Vincent 
109127e34995SRabin Vincent 	for (i = 0; i < variant->num_blocks; i++) {
109227e34995SRabin Vincent 		struct stmpe_variant_block *block = &variant->blocks[i];
109327e34995SRabin Vincent 
109427e34995SRabin Vincent 		if (!(platform_blocks & block->block))
109527e34995SRabin Vincent 			continue;
109627e34995SRabin Vincent 
10977da0cbfcSLee Jones 		for (j = 0; j < block->cell->num_resources; j++) {
10987da0cbfcSLee Jones 			struct resource *res =
10997da0cbfcSLee Jones 				(struct resource *) &block->cell->resources[j];
11007da0cbfcSLee Jones 
11017da0cbfcSLee Jones 			/* Dynamically fill in a variant's IRQ. */
11027da0cbfcSLee Jones 			if (res->flags & IORESOURCE_IRQ)
11037da0cbfcSLee Jones 				res->start = res->end = block->irq + j;
11047da0cbfcSLee Jones 		}
11057da0cbfcSLee Jones 
110627e34995SRabin Vincent 		platform_blocks &= ~block->block;
11077da0cbfcSLee Jones 		ret = stmpe_add_device(stmpe, block->cell);
110827e34995SRabin Vincent 		if (ret)
110927e34995SRabin Vincent 			return ret;
111027e34995SRabin Vincent 	}
111127e34995SRabin Vincent 
111227e34995SRabin Vincent 	if (platform_blocks)
111327e34995SRabin Vincent 		dev_warn(stmpe->dev,
111427e34995SRabin Vincent 			 "platform wants blocks (%#x) not present on variant",
111527e34995SRabin Vincent 			 platform_blocks);
111627e34995SRabin Vincent 
111727e34995SRabin Vincent 	return ret;
111827e34995SRabin Vincent }
111927e34995SRabin Vincent 
1120a9c4055dSMark Brown static void stmpe_of_probe(struct stmpe_platform_data *pdata,
1121a9c4055dSMark Brown 			   struct device_node *np)
1122909582caSLee Jones {
1123909582caSLee Jones 	struct device_node *child;
1124909582caSLee Jones 
1125408a3fa8SGabriel Fernandez 	pdata->id = of_alias_get_id(np, "stmpe-i2c");
1126408a3fa8SGabriel Fernandez 	if (pdata->id < 0)
1127ac713cc9SVipul Kumar Samar 		pdata->id = -1;
1128408a3fa8SGabriel Fernandez 
1129ac713cc9SVipul Kumar Samar 	pdata->irq_trigger = IRQF_TRIGGER_NONE;
1130ac713cc9SVipul Kumar Samar 
1131909582caSLee Jones 	of_property_read_u32(np, "st,autosleep-timeout",
1132909582caSLee Jones 			&pdata->autosleep_timeout);
1133909582caSLee Jones 
1134909582caSLee Jones 	pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
1135909582caSLee Jones 
1136909582caSLee Jones 	for_each_child_of_node(np, child) {
1137909582caSLee Jones 		if (!strcmp(child->name, "stmpe_gpio")) {
1138909582caSLee Jones 			pdata->blocks |= STMPE_BLOCK_GPIO;
1139ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_keypad")) {
1140909582caSLee Jones 			pdata->blocks |= STMPE_BLOCK_KEYPAD;
1141ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_touchscreen")) {
1142909582caSLee Jones 			pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
1143ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_adc")) {
1144909582caSLee Jones 			pdata->blocks |= STMPE_BLOCK_ADC;
1145ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_pwm")) {
1146ac713cc9SVipul Kumar Samar 			pdata->blocks |= STMPE_BLOCK_PWM;
1147ac713cc9SVipul Kumar Samar 		} else if (!strcmp(child->name, "stmpe_rotator")) {
1148ac713cc9SVipul Kumar Samar 			pdata->blocks |= STMPE_BLOCK_ROTATOR;
1149909582caSLee Jones 		}
1150909582caSLee Jones 	}
1151909582caSLee Jones }
1152909582caSLee Jones 
11531a6e4b74SViresh Kumar /* Called from client specific probe routines */
1154c00572bcSLee Jones int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
1155208c4343SSundar Iyer {
11561a6e4b74SViresh Kumar 	struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
1157909582caSLee Jones 	struct device_node *np = ci->dev->of_node;
115827e34995SRabin Vincent 	struct stmpe *stmpe;
115927e34995SRabin Vincent 	int ret;
116027e34995SRabin Vincent 
1161909582caSLee Jones 	if (!pdata) {
1162cb5faba9SViresh Kumar 		if (!np)
116327e34995SRabin Vincent 			return -EINVAL;
116427e34995SRabin Vincent 
1165cb5faba9SViresh Kumar 		pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL);
116627e34995SRabin Vincent 		if (!pdata)
1167909582caSLee Jones 			return -ENOMEM;
1168909582caSLee Jones 
1169909582caSLee Jones 		stmpe_of_probe(pdata, np);
1170a200e320SGabriel Fernandez 
1171a200e320SGabriel Fernandez 		if (of_find_property(np, "interrupts", NULL) == NULL)
1172a200e320SGabriel Fernandez 			ci->irq = -1;
1173909582caSLee Jones 	}
117427e34995SRabin Vincent 
1175cb5faba9SViresh Kumar 	stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL);
117627e34995SRabin Vincent 	if (!stmpe)
117727e34995SRabin Vincent 		return -ENOMEM;
117827e34995SRabin Vincent 
117927e34995SRabin Vincent 	mutex_init(&stmpe->irq_lock);
118027e34995SRabin Vincent 	mutex_init(&stmpe->lock);
118127e34995SRabin Vincent 
11821a6e4b74SViresh Kumar 	stmpe->dev = ci->dev;
11831a6e4b74SViresh Kumar 	stmpe->client = ci->client;
118427e34995SRabin Vincent 	stmpe->pdata = pdata;
11851a6e4b74SViresh Kumar 	stmpe->ci = ci;
11861a6e4b74SViresh Kumar 	stmpe->partnum = partnum;
11871a6e4b74SViresh Kumar 	stmpe->variant = stmpe_variant_info[partnum];
118827e34995SRabin Vincent 	stmpe->regs = stmpe->variant->regs;
118927e34995SRabin Vincent 	stmpe->num_gpios = stmpe->variant->num_gpios;
11909c9e3214SLinus Walleij 	stmpe->vcc = devm_regulator_get_optional(ci->dev, "vcc");
11919c9e3214SLinus Walleij 	if (!IS_ERR(stmpe->vcc)) {
11929c9e3214SLinus Walleij 		ret = regulator_enable(stmpe->vcc);
11939c9e3214SLinus Walleij 		if (ret)
11949c9e3214SLinus Walleij 			dev_warn(ci->dev, "failed to enable VCC supply\n");
11959c9e3214SLinus Walleij 	}
11969c9e3214SLinus Walleij 	stmpe->vio = devm_regulator_get_optional(ci->dev, "vio");
11979c9e3214SLinus Walleij 	if (!IS_ERR(stmpe->vio)) {
11989c9e3214SLinus Walleij 		ret = regulator_enable(stmpe->vio);
11999c9e3214SLinus Walleij 		if (ret)
12009c9e3214SLinus Walleij 			dev_warn(ci->dev, "failed to enable VIO supply\n");
12019c9e3214SLinus Walleij 	}
12021a6e4b74SViresh Kumar 	dev_set_drvdata(stmpe->dev, stmpe);
120327e34995SRabin Vincent 
12041a6e4b74SViresh Kumar 	if (ci->init)
12051a6e4b74SViresh Kumar 		ci->init(stmpe);
120627e34995SRabin Vincent 
120773de16dbSViresh Kumar 	if (pdata->irq_over_gpio) {
1208cb5faba9SViresh Kumar 		ret = devm_gpio_request_one(ci->dev, pdata->irq_gpio,
1209cb5faba9SViresh Kumar 				GPIOF_DIR_IN, "stmpe");
121073de16dbSViresh Kumar 		if (ret) {
121173de16dbSViresh Kumar 			dev_err(stmpe->dev, "failed to request IRQ GPIO: %d\n",
121273de16dbSViresh Kumar 					ret);
1213cb5faba9SViresh Kumar 			return ret;
121473de16dbSViresh Kumar 		}
121573de16dbSViresh Kumar 
121673de16dbSViresh Kumar 		stmpe->irq = gpio_to_irq(pdata->irq_gpio);
121773de16dbSViresh Kumar 	} else {
12181a6e4b74SViresh Kumar 		stmpe->irq = ci->irq;
121973de16dbSViresh Kumar 	}
122073de16dbSViresh Kumar 
1221e31f9b82SChris Blair 	if (stmpe->irq < 0) {
1222e31f9b82SChris Blair 		/* use alternate variant info for no-irq mode, if supported */
1223e31f9b82SChris Blair 		dev_info(stmpe->dev,
1224e31f9b82SChris Blair 			"%s configured in no-irq mode by platform data\n",
1225e31f9b82SChris Blair 			stmpe->variant->name);
1226e31f9b82SChris Blair 		if (!stmpe_noirq_variant_info[stmpe->partnum]) {
1227e31f9b82SChris Blair 			dev_err(stmpe->dev,
1228e31f9b82SChris Blair 				"%s does not support no-irq mode!\n",
1229e31f9b82SChris Blair 				stmpe->variant->name);
1230cb5faba9SViresh Kumar 			return -ENODEV;
1231e31f9b82SChris Blair 		}
1232e31f9b82SChris Blair 		stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum];
1233ac713cc9SVipul Kumar Samar 	} else if (pdata->irq_trigger == IRQF_TRIGGER_NONE) {
12341a5595cbSJavier Martinez Canillas 		pdata->irq_trigger = irq_get_trigger_type(stmpe->irq);
1235e31f9b82SChris Blair 	}
1236e31f9b82SChris Blair 
123727e34995SRabin Vincent 	ret = stmpe_chip_init(stmpe);
123827e34995SRabin Vincent 	if (ret)
1239cb5faba9SViresh Kumar 		return ret;
124027e34995SRabin Vincent 
1241e31f9b82SChris Blair 	if (stmpe->irq >= 0) {
1242909582caSLee Jones 		ret = stmpe_irq_init(stmpe, np);
124327e34995SRabin Vincent 		if (ret)
1244cb5faba9SViresh Kumar 			return ret;
124527e34995SRabin Vincent 
1246cb5faba9SViresh Kumar 		ret = devm_request_threaded_irq(ci->dev, stmpe->irq, NULL,
1247cb5faba9SViresh Kumar 				stmpe_irq, pdata->irq_trigger | IRQF_ONESHOT,
1248e31f9b82SChris Blair 				"stmpe", stmpe);
124927e34995SRabin Vincent 		if (ret) {
1250e31f9b82SChris Blair 			dev_err(stmpe->dev, "failed to request IRQ: %d\n",
1251e31f9b82SChris Blair 					ret);
1252cb5faba9SViresh Kumar 			return ret;
125327e34995SRabin Vincent 		}
1254e31f9b82SChris Blair 	}
125527e34995SRabin Vincent 
125627e34995SRabin Vincent 	ret = stmpe_devices_init(stmpe);
1257cb5faba9SViresh Kumar 	if (!ret)
125827e34995SRabin Vincent 		return 0;
125927e34995SRabin Vincent 
1260cb5faba9SViresh Kumar 	dev_err(stmpe->dev, "failed to add children\n");
126127e34995SRabin Vincent 	mfd_remove_devices(stmpe->dev);
1262cb5faba9SViresh Kumar 
126327e34995SRabin Vincent 	return ret;
126427e34995SRabin Vincent }
126527e34995SRabin Vincent 
12661a6e4b74SViresh Kumar int stmpe_remove(struct stmpe *stmpe)
126727e34995SRabin Vincent {
12689c9e3214SLinus Walleij 	if (!IS_ERR(stmpe->vio))
12699c9e3214SLinus Walleij 		regulator_disable(stmpe->vio);
12709c9e3214SLinus Walleij 	if (!IS_ERR(stmpe->vcc))
12719c9e3214SLinus Walleij 		regulator_disable(stmpe->vcc);
12729c9e3214SLinus Walleij 
127327e34995SRabin Vincent 	mfd_remove_devices(stmpe->dev);
127427e34995SRabin Vincent 
127527e34995SRabin Vincent 	return 0;
127627e34995SRabin Vincent }
127727e34995SRabin Vincent 
1278208c4343SSundar Iyer #ifdef CONFIG_PM
12791a6e4b74SViresh Kumar static int stmpe_suspend(struct device *dev)
12801a6e4b74SViresh Kumar {
12811a6e4b74SViresh Kumar 	struct stmpe *stmpe = dev_get_drvdata(dev);
12821a6e4b74SViresh Kumar 
1283e31f9b82SChris Blair 	if (stmpe->irq >= 0 && device_may_wakeup(dev))
12841a6e4b74SViresh Kumar 		enable_irq_wake(stmpe->irq);
12851a6e4b74SViresh Kumar 
12861a6e4b74SViresh Kumar 	return 0;
12871a6e4b74SViresh Kumar }
12881a6e4b74SViresh Kumar 
12891a6e4b74SViresh Kumar static int stmpe_resume(struct device *dev)
12901a6e4b74SViresh Kumar {
12911a6e4b74SViresh Kumar 	struct stmpe *stmpe = dev_get_drvdata(dev);
12921a6e4b74SViresh Kumar 
1293e31f9b82SChris Blair 	if (stmpe->irq >= 0 && device_may_wakeup(dev))
12941a6e4b74SViresh Kumar 		disable_irq_wake(stmpe->irq);
12951a6e4b74SViresh Kumar 
12961a6e4b74SViresh Kumar 	return 0;
12971a6e4b74SViresh Kumar }
12981a6e4b74SViresh Kumar 
12991a6e4b74SViresh Kumar const struct dev_pm_ops stmpe_dev_pm_ops = {
1300208c4343SSundar Iyer 	.suspend	= stmpe_suspend,
1301208c4343SSundar Iyer 	.resume		= stmpe_resume,
1302208c4343SSundar Iyer };
1303208c4343SSundar Iyer #endif
1304