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