2010-07-02 15:22:08 +04:00
/*
2011-11-17 09:32:20 +04:00
* ST Microelectronics MFD : stmpe ' s driver
*
2010-07-02 15:22:08 +04:00
* Copyright ( C ) ST - Ericsson SA 2010
*
* License Terms : GNU General Public License , version 2
* Author : Rabin Vincent < rabin . vincent @ stericsson . com > for ST - Ericsson
*/
2012-12-07 18:59:37 +04:00
# include <linux/err.h>
2011-11-08 08:14:06 +04:00
# include <linux/gpio.h>
2011-12-20 21:34:36 +04:00
# include <linux/export.h>
2010-07-02 15:22:08 +04:00
# include <linux/kernel.h>
# include <linux/interrupt.h>
# include <linux/irq.h>
2012-11-05 19:10:31 +04:00
# include <linux/irqdomain.h>
2012-11-12 21:20:49 +04:00
# include <linux/of.h>
2012-12-07 18:59:37 +04:00
# include <linux/of_gpio.h>
2011-11-17 09:32:20 +04:00
# include <linux/pm.h>
2010-07-02 15:22:08 +04:00
# include <linux/slab.h>
# include <linux/mfd/core.h>
2013-04-09 12:35:19 +04:00
# include <linux/delay.h>
2014-05-09 01:16:35 +04:00
# include <linux/regulator/consumer.h>
2010-07-02 15:22:08 +04:00
# include "stmpe.h"
2016-05-25 15:22:02 +03:00
/**
* struct stmpe_platform_data - STMPE platform data
* @ id : device id to distinguish between multiple STMPEs on the same board
* @ blocks : bitmask of blocks to enable ( use STMPE_BLOCK_ * )
* @ irq_trigger : IRQ trigger to use for the interrupt to the host
* @ autosleep : bool to enable / disable stmpe autosleep
* @ autosleep_timeout : inactivity timeout in milliseconds for autosleep
* @ irq_over_gpio : true if gpio is used to get irq
* @ irq_gpio : gpio number over which irq will be requested ( significant only if
* irq_over_gpio is true )
*/
struct stmpe_platform_data {
int id ;
unsigned int blocks ;
unsigned int irq_trigger ;
bool autosleep ;
bool irq_over_gpio ;
int irq_gpio ;
int autosleep_timeout ;
} ;
2010-07-02 15:22:08 +04:00
static int __stmpe_enable ( struct stmpe * stmpe , unsigned int blocks )
{
return stmpe - > variant - > enable ( stmpe , blocks , true ) ;
}
static int __stmpe_disable ( struct stmpe * stmpe , unsigned int blocks )
{
return stmpe - > variant - > enable ( stmpe , blocks , false ) ;
}
static int __stmpe_reg_read ( struct stmpe * stmpe , u8 reg )
{
int ret ;
2011-11-17 09:32:20 +04:00
ret = stmpe - > ci - > read_byte ( stmpe , reg ) ;
2010-07-02 15:22:08 +04:00
if ( ret < 0 )
2011-11-17 09:32:20 +04:00
dev_err ( stmpe - > dev , " failed to read reg %#x: %d \n " , reg , ret ) ;
2010-07-02 15:22:08 +04:00
dev_vdbg ( stmpe - > dev , " rd: reg %#x => data %#x \n " , reg , ret ) ;
return ret ;
}
static int __stmpe_reg_write ( struct stmpe * stmpe , u8 reg , u8 val )
{
int ret ;
dev_vdbg ( stmpe - > dev , " wr: reg %#x <= %#x \n " , reg , val ) ;
2011-11-17 09:32:20 +04:00
ret = stmpe - > ci - > write_byte ( stmpe , reg , val ) ;
2010-07-02 15:22:08 +04:00
if ( ret < 0 )
2011-11-17 09:32:20 +04:00
dev_err ( stmpe - > dev , " failed to write reg %#x: %d \n " , reg , ret ) ;
2010-07-02 15:22:08 +04:00
return ret ;
}
static int __stmpe_set_bits ( struct stmpe * stmpe , u8 reg , u8 mask , u8 val )
{
int ret ;
ret = __stmpe_reg_read ( stmpe , reg ) ;
if ( ret < 0 )
return ret ;
ret & = ~ mask ;
ret | = val ;
return __stmpe_reg_write ( stmpe , reg , ret ) ;
}
static int __stmpe_block_read ( struct stmpe * stmpe , u8 reg , u8 length ,
u8 * values )
{
int ret ;
2011-11-17 09:32:20 +04:00
ret = stmpe - > ci - > read_block ( stmpe , reg , length , values ) ;
2010-07-02 15:22:08 +04:00
if ( ret < 0 )
2011-11-17 09:32:20 +04:00
dev_err ( stmpe - > dev , " failed to read regs %#x: %d \n " , reg , ret ) ;
2010-07-02 15:22:08 +04:00
dev_vdbg ( stmpe - > dev , " rd: reg %#x (%d) => ret %#x \n " , reg , length , ret ) ;
stmpe_dump_bytes ( " stmpe rd: " , values , length ) ;
return ret ;
}
static int __stmpe_block_write ( struct stmpe * stmpe , u8 reg , u8 length ,
const u8 * values )
{
int ret ;
dev_vdbg ( stmpe - > dev , " wr: regs %#x (%d) \n " , reg , length ) ;
stmpe_dump_bytes ( " stmpe wr: " , values , length ) ;
2011-11-17 09:32:20 +04:00
ret = stmpe - > ci - > write_block ( stmpe , reg , length , values ) ;
2010-07-02 15:22:08 +04:00
if ( ret < 0 )
2011-11-17 09:32:20 +04:00
dev_err ( stmpe - > dev , " failed to write regs %#x: %d \n " , reg , ret ) ;
2010-07-02 15:22:08 +04:00
return ret ;
}
/**
* stmpe_enable - enable blocks on an STMPE device
* @ stmpe : Device to work on
* @ blocks : Mask of blocks ( enum stmpe_block values ) to enable
*/
int stmpe_enable ( struct stmpe * stmpe , unsigned int blocks )
{
int ret ;
mutex_lock ( & stmpe - > lock ) ;
ret = __stmpe_enable ( stmpe , blocks ) ;
mutex_unlock ( & stmpe - > lock ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( stmpe_enable ) ;
/**
* stmpe_disable - disable blocks on an STMPE device
* @ stmpe : Device to work on
* @ blocks : Mask of blocks ( enum stmpe_block values ) to enable
*/
int stmpe_disable ( struct stmpe * stmpe , unsigned int blocks )
{
int ret ;
mutex_lock ( & stmpe - > lock ) ;
ret = __stmpe_disable ( stmpe , blocks ) ;
mutex_unlock ( & stmpe - > lock ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( stmpe_disable ) ;
/**
* stmpe_reg_read ( ) - read a single STMPE register
* @ stmpe : Device to read from
* @ reg : Register to read
*/
int stmpe_reg_read ( struct stmpe * stmpe , u8 reg )
{
int ret ;
mutex_lock ( & stmpe - > lock ) ;
ret = __stmpe_reg_read ( stmpe , reg ) ;
mutex_unlock ( & stmpe - > lock ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( stmpe_reg_read ) ;
/**
* stmpe_reg_write ( ) - write a single STMPE register
* @ stmpe : Device to write to
* @ reg : Register to write
* @ val : Value to write
*/
int stmpe_reg_write ( struct stmpe * stmpe , u8 reg , u8 val )
{
int ret ;
mutex_lock ( & stmpe - > lock ) ;
ret = __stmpe_reg_write ( stmpe , reg , val ) ;
mutex_unlock ( & stmpe - > lock ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( stmpe_reg_write ) ;
/**
* stmpe_set_bits ( ) - set the value of a bitfield in a STMPE register
* @ stmpe : Device to write to
* @ reg : Register to write
* @ mask : Mask of bits to set
* @ val : Value to set
*/
int stmpe_set_bits ( struct stmpe * stmpe , u8 reg , u8 mask , u8 val )
{
int ret ;
mutex_lock ( & stmpe - > lock ) ;
ret = __stmpe_set_bits ( stmpe , reg , mask , val ) ;
mutex_unlock ( & stmpe - > lock ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( stmpe_set_bits ) ;
/**
* stmpe_block_read ( ) - read multiple STMPE registers
* @ stmpe : Device to read from
* @ reg : First register
* @ length : Number of registers
* @ values : Buffer to write to
*/
int stmpe_block_read ( struct stmpe * stmpe , u8 reg , u8 length , u8 * values )
{
int ret ;
mutex_lock ( & stmpe - > lock ) ;
ret = __stmpe_block_read ( stmpe , reg , length , values ) ;
mutex_unlock ( & stmpe - > lock ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( stmpe_block_read ) ;
/**
* stmpe_block_write ( ) - write multiple STMPE registers
* @ stmpe : Device to write to
* @ reg : First register
* @ length : Number of registers
* @ values : Values to write
*/
int stmpe_block_write ( struct stmpe * stmpe , u8 reg , u8 length ,
const u8 * values )
{
int ret ;
mutex_lock ( & stmpe - > lock ) ;
ret = __stmpe_block_write ( stmpe , reg , length , values ) ;
mutex_unlock ( & stmpe - > lock ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( stmpe_block_write ) ;
/**
2011-06-27 11:54:22 +04:00
* stmpe_set_altfunc ( ) - set the alternate function for STMPE pins
2010-07-02 15:22:08 +04:00
* @ stmpe : Device to configure
* @ pins : Bitmask of pins to affect
* @ block : block to enable alternate functions for
*
* @ pins is assumed to have a bit set for each of the bits whose alternate
* function is to be changed , numbered according to the GPIOXY numbers .
*
* If the GPIO module is not enabled , this function automatically enables it in
* order to perform the change .
*/
int stmpe_set_altfunc ( struct stmpe * stmpe , u32 pins , enum stmpe_block block )
{
struct stmpe_variant_info * variant = stmpe - > variant ;
u8 regaddr = stmpe - > regs [ STMPE_IDX_GPAFR_U_MSB ] ;
int af_bits = variant - > af_bits ;
int numregs = DIV_ROUND_UP ( stmpe - > num_gpios * af_bits , 8 ) ;
int mask = ( 1 < < af_bits ) - 1 ;
2014-08-28 14:20:33 +04:00
u8 regs [ 8 ] ;
2011-11-17 09:32:23 +04:00
int af , afperreg , ret ;
if ( ! variant - > get_altfunc )
return 0 ;
2010-07-02 15:22:08 +04:00
2011-11-17 09:32:23 +04:00
afperreg = 8 / af_bits ;
2010-07-02 15:22:08 +04:00
mutex_lock ( & stmpe - > lock ) ;
ret = __stmpe_enable ( stmpe , STMPE_BLOCK_GPIO ) ;
if ( ret < 0 )
goto out ;
ret = __stmpe_block_read ( stmpe , regaddr , numregs , regs ) ;
if ( ret < 0 )
goto out ;
af = variant - > get_altfunc ( stmpe , block ) ;
while ( pins ) {
int pin = __ffs ( pins ) ;
int regoffset = numregs - ( pin / afperreg ) - 1 ;
int pos = ( pin % afperreg ) * ( 8 / afperreg ) ;
regs [ regoffset ] & = ~ ( mask < < pos ) ;
regs [ regoffset ] | = af < < pos ;
pins & = ~ ( 1 < < pin ) ;
}
ret = __stmpe_block_write ( stmpe , regaddr , numregs , regs ) ;
out :
mutex_unlock ( & stmpe - > lock ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( stmpe_set_altfunc ) ;
/*
* GPIO ( all variants )
*/
static struct resource stmpe_gpio_resources [ ] = {
/* Start and end filled dynamically */
{
. flags = IORESOURCE_IRQ ,
} ,
} ;
2013-11-18 17:33:01 +04:00
static const struct mfd_cell stmpe_gpio_cell = {
2010-07-02 15:22:08 +04:00
. name = " stmpe-gpio " ,
2012-11-26 15:36:51 +04:00
. of_compatible = " st,stmpe-gpio " ,
2010-07-02 15:22:08 +04:00
. resources = stmpe_gpio_resources ,
. num_resources = ARRAY_SIZE ( stmpe_gpio_resources ) ,
} ;
2013-11-18 17:33:01 +04:00
static const struct mfd_cell stmpe_gpio_cell_noirq = {
2012-01-27 01:17:03 +04:00
. name = " stmpe-gpio " ,
2012-11-26 15:36:51 +04:00
. of_compatible = " st,stmpe-gpio " ,
2012-01-27 01:17:03 +04:00
/* gpio cell resources consist of an irq only so no resources here */
} ;
2010-07-02 15:22:08 +04:00
/*
* Keypad ( 1601 , 2401 , 2403 )
*/
static struct resource stmpe_keypad_resources [ ] = {
{
. name = " KEYPAD " ,
. flags = IORESOURCE_IRQ ,
} ,
{
. name = " KEYPAD_OVER " ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
2013-11-18 17:33:01 +04:00
static const struct mfd_cell stmpe_keypad_cell = {
2010-07-02 15:22:08 +04:00
. name = " stmpe-keypad " ,
2012-11-14 20:55:21 +04:00
. of_compatible = " st,stmpe-keypad " ,
2010-07-02 15:22:08 +04:00
. resources = stmpe_keypad_resources ,
. num_resources = ARRAY_SIZE ( stmpe_keypad_resources ) ,
} ;
2016-02-14 16:07:07 +03:00
/*
* PWM ( 1601 , 2401 , 2403 )
*/
static struct resource stmpe_pwm_resources [ ] = {
{
. name = " PWM0 " ,
. flags = IORESOURCE_IRQ ,
} ,
{
. name = " PWM1 " ,
. flags = IORESOURCE_IRQ ,
} ,
{
. name = " PWM2 " ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static const struct mfd_cell stmpe_pwm_cell = {
. name = " stmpe-pwm " ,
. of_compatible = " st,stmpe-pwm " ,
. resources = stmpe_pwm_resources ,
. num_resources = ARRAY_SIZE ( stmpe_pwm_resources ) ,
} ;
2011-11-17 09:32:23 +04:00
/*
* STMPE801
*/
static const u8 stmpe801_regs [ ] = {
[ STMPE_IDX_CHIP_ID ] = STMPE801_REG_CHIP_ID ,
[ STMPE_IDX_ICR_LSB ] = STMPE801_REG_SYS_CTRL ,
[ STMPE_IDX_GPMR_LSB ] = STMPE801_REG_GPIO_MP_STA ,
[ STMPE_IDX_GPSR_LSB ] = STMPE801_REG_GPIO_SET_PIN ,
[ STMPE_IDX_GPCR_LSB ] = STMPE801_REG_GPIO_SET_PIN ,
[ STMPE_IDX_GPDR_LSB ] = STMPE801_REG_GPIO_DIR ,
[ STMPE_IDX_IEGPIOR_LSB ] = STMPE801_REG_GPIO_INT_EN ,
[ STMPE_IDX_ISGPIOR_MSB ] = STMPE801_REG_GPIO_INT_STA ,
} ;
static struct stmpe_variant_block stmpe801_blocks [ ] = {
{
. cell = & stmpe_gpio_cell ,
. irq = 0 ,
. block = STMPE_BLOCK_GPIO ,
} ,
} ;
2012-01-27 01:17:03 +04:00
static struct stmpe_variant_block stmpe801_blocks_noirq [ ] = {
{
. cell = & stmpe_gpio_cell_noirq ,
. block = STMPE_BLOCK_GPIO ,
} ,
} ;
2011-11-17 09:32:23 +04:00
static int stmpe801_enable ( struct stmpe * stmpe , unsigned int blocks ,
bool enable )
{
if ( blocks & STMPE_BLOCK_GPIO )
return 0 ;
else
return - EINVAL ;
}
static struct stmpe_variant_info stmpe801 = {
. name = " stmpe801 " ,
. id_val = STMPE801_ID ,
. id_mask = 0xffff ,
. num_gpios = 8 ,
. regs = stmpe801_regs ,
. blocks = stmpe801_blocks ,
. num_blocks = ARRAY_SIZE ( stmpe801_blocks ) ,
. num_irqs = STMPE801_NR_INTERNAL_IRQS ,
. enable = stmpe801_enable ,
} ;
2012-01-27 01:17:03 +04:00
static struct stmpe_variant_info stmpe801_noirq = {
. name = " stmpe801 " ,
. id_val = STMPE801_ID ,
. id_mask = 0xffff ,
. num_gpios = 8 ,
. regs = stmpe801_regs ,
. blocks = stmpe801_blocks_noirq ,
. num_blocks = ARRAY_SIZE ( stmpe801_blocks_noirq ) ,
. enable = stmpe801_enable ,
} ;
2010-07-02 15:22:08 +04:00
/*
2011-11-17 09:32:22 +04:00
* Touchscreen ( STMPE811 or STMPE610 )
2010-07-02 15:22:08 +04:00
*/
static struct resource stmpe_ts_resources [ ] = {
{
. name = " TOUCH_DET " ,
. flags = IORESOURCE_IRQ ,
} ,
{
. name = " FIFO_TH " ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
2013-11-18 17:33:01 +04:00
static const struct mfd_cell stmpe_ts_cell = {
2010-07-02 15:22:08 +04:00
. name = " stmpe-ts " ,
2012-11-23 11:42:12 +04:00
. of_compatible = " st,stmpe-ts " ,
2010-07-02 15:22:08 +04:00
. resources = stmpe_ts_resources ,
. num_resources = ARRAY_SIZE ( stmpe_ts_resources ) ,
} ;
/*
2011-11-17 09:32:22 +04:00
* STMPE811 or STMPE610
2010-07-02 15:22:08 +04:00
*/
static const u8 stmpe811_regs [ ] = {
[ STMPE_IDX_CHIP_ID ] = STMPE811_REG_CHIP_ID ,
2016-08-10 10:39:06 +03:00
[ STMPE_IDX_SYS_CTRL ] = STMPE811_REG_SYS_CTRL ,
[ STMPE_IDX_SYS_CTRL2 ] = STMPE811_REG_SYS_CTRL2 ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_ICR_LSB ] = STMPE811_REG_INT_CTRL ,
[ STMPE_IDX_IER_LSB ] = STMPE811_REG_INT_EN ,
[ STMPE_IDX_ISR_MSB ] = STMPE811_REG_INT_STA ,
[ STMPE_IDX_GPMR_LSB ] = STMPE811_REG_GPIO_MP_STA ,
[ STMPE_IDX_GPSR_LSB ] = STMPE811_REG_GPIO_SET_PIN ,
[ STMPE_IDX_GPCR_LSB ] = STMPE811_REG_GPIO_CLR_PIN ,
[ STMPE_IDX_GPDR_LSB ] = STMPE811_REG_GPIO_DIR ,
[ STMPE_IDX_GPRER_LSB ] = STMPE811_REG_GPIO_RE ,
[ STMPE_IDX_GPFER_LSB ] = STMPE811_REG_GPIO_FE ,
[ STMPE_IDX_GPAFR_U_MSB ] = STMPE811_REG_GPIO_AF ,
[ STMPE_IDX_IEGPIOR_LSB ] = STMPE811_REG_GPIO_INT_EN ,
[ STMPE_IDX_ISGPIOR_MSB ] = STMPE811_REG_GPIO_INT_STA ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPEDR_LSB ] = STMPE811_REG_GPIO_ED ,
2010-07-02 15:22:08 +04:00
} ;
static struct stmpe_variant_block stmpe811_blocks [ ] = {
{
. cell = & stmpe_gpio_cell ,
. irq = STMPE811_IRQ_GPIOC ,
. block = STMPE_BLOCK_GPIO ,
} ,
{
. cell = & stmpe_ts_cell ,
. irq = STMPE811_IRQ_TOUCH_DET ,
. block = STMPE_BLOCK_TOUCHSCREEN ,
} ,
} ;
static int stmpe811_enable ( struct stmpe * stmpe , unsigned int blocks ,
bool enable )
{
unsigned int mask = 0 ;
if ( blocks & STMPE_BLOCK_GPIO )
mask | = STMPE811_SYS_CTRL2_GPIO_OFF ;
if ( blocks & STMPE_BLOCK_ADC )
mask | = STMPE811_SYS_CTRL2_ADC_OFF ;
if ( blocks & STMPE_BLOCK_TOUCHSCREEN )
mask | = STMPE811_SYS_CTRL2_TSC_OFF ;
2016-08-10 10:39:06 +03:00
return __stmpe_set_bits ( stmpe , stmpe - > regs [ STMPE_IDX_SYS_CTRL2 ] , mask ,
2010-07-02 15:22:08 +04:00
enable ? 0 : mask ) ;
}
static int stmpe811_get_altfunc ( struct stmpe * stmpe , enum stmpe_block block )
{
/* 0 for touchscreen, 1 for GPIO */
return block ! = STMPE_BLOCK_TOUCHSCREEN ;
}
static struct stmpe_variant_info stmpe811 = {
. name = " stmpe811 " ,
. id_val = 0x0811 ,
. id_mask = 0xffff ,
. num_gpios = 8 ,
. af_bits = 1 ,
. regs = stmpe811_regs ,
. blocks = stmpe811_blocks ,
. num_blocks = ARRAY_SIZE ( stmpe811_blocks ) ,
. num_irqs = STMPE811_NR_INTERNAL_IRQS ,
. enable = stmpe811_enable ,
. get_altfunc = stmpe811_get_altfunc ,
} ;
2011-11-17 09:32:22 +04:00
/* Similar to 811, except number of gpios */
static struct stmpe_variant_info stmpe610 = {
. name = " stmpe610 " ,
. id_val = 0x0811 ,
. id_mask = 0xffff ,
. num_gpios = 6 ,
. af_bits = 1 ,
. regs = stmpe811_regs ,
. blocks = stmpe811_blocks ,
. num_blocks = ARRAY_SIZE ( stmpe811_blocks ) ,
. num_irqs = STMPE811_NR_INTERNAL_IRQS ,
. enable = stmpe811_enable ,
. get_altfunc = stmpe811_get_altfunc ,
} ;
2016-08-10 10:39:14 +03:00
/*
* STMPE1600
* Compared to all others STMPE variant , LSB and MSB regs are located in this
* order : LSB addr
* MSB addr + 1
* As there is only 2 * 8 bits registers for GPMR / GPSR / IEGPIOPR , CSB index is MSB registers
*/
static const u8 stmpe1600_regs [ ] = {
[ STMPE_IDX_CHIP_ID ] = STMPE1600_REG_CHIP_ID ,
[ STMPE_IDX_SYS_CTRL ] = STMPE1600_REG_SYS_CTRL ,
[ STMPE_IDX_ICR_LSB ] = STMPE1600_REG_SYS_CTRL ,
[ STMPE_IDX_GPMR_LSB ] = STMPE1600_REG_GPMR_LSB ,
[ STMPE_IDX_GPMR_CSB ] = STMPE1600_REG_GPMR_MSB ,
[ STMPE_IDX_GPSR_LSB ] = STMPE1600_REG_GPSR_LSB ,
[ STMPE_IDX_GPSR_CSB ] = STMPE1600_REG_GPSR_MSB ,
2017-03-31 11:12:39 +03:00
[ STMPE_IDX_GPCR_LSB ] = STMPE1600_REG_GPSR_LSB ,
[ STMPE_IDX_GPCR_CSB ] = STMPE1600_REG_GPSR_MSB ,
2016-08-10 10:39:14 +03:00
[ STMPE_IDX_GPDR_LSB ] = STMPE1600_REG_GPDR_LSB ,
[ STMPE_IDX_GPDR_CSB ] = STMPE1600_REG_GPDR_MSB ,
[ STMPE_IDX_IEGPIOR_LSB ] = STMPE1600_REG_IEGPIOR_LSB ,
[ STMPE_IDX_IEGPIOR_CSB ] = STMPE1600_REG_IEGPIOR_MSB ,
[ STMPE_IDX_ISGPIOR_LSB ] = STMPE1600_REG_ISGPIOR_LSB ,
} ;
static struct stmpe_variant_block stmpe1600_blocks [ ] = {
{
. cell = & stmpe_gpio_cell ,
. irq = 0 ,
. block = STMPE_BLOCK_GPIO ,
} ,
} ;
static int stmpe1600_enable ( struct stmpe * stmpe , unsigned int blocks ,
bool enable )
{
if ( blocks & STMPE_BLOCK_GPIO )
return 0 ;
else
return - EINVAL ;
}
static struct stmpe_variant_info stmpe1600 = {
. name = " stmpe1600 " ,
. id_val = STMPE1600_ID ,
. id_mask = 0xffff ,
. num_gpios = 16 ,
. af_bits = 0 ,
. regs = stmpe1600_regs ,
. blocks = stmpe1600_blocks ,
. num_blocks = ARRAY_SIZE ( stmpe1600_blocks ) ,
. num_irqs = STMPE1600_NR_INTERNAL_IRQS ,
. enable = stmpe1600_enable ,
} ;
2010-07-02 15:22:08 +04:00
/*
* STMPE1601
*/
static const u8 stmpe1601_regs [ ] = {
[ STMPE_IDX_CHIP_ID ] = STMPE1601_REG_CHIP_ID ,
2016-08-10 10:39:06 +03:00
[ STMPE_IDX_SYS_CTRL ] = STMPE1601_REG_SYS_CTRL ,
[ STMPE_IDX_SYS_CTRL2 ] = STMPE1601_REG_SYS_CTRL2 ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_ICR_LSB ] = STMPE1601_REG_ICR_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_IER_MSB ] = STMPE1601_REG_IER_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_IER_LSB ] = STMPE1601_REG_IER_LSB ,
[ STMPE_IDX_ISR_MSB ] = STMPE1601_REG_ISR_MSB ,
[ STMPE_IDX_GPMR_LSB ] = STMPE1601_REG_GPIO_MP_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPMR_CSB ] = STMPE1601_REG_GPIO_MP_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPSR_LSB ] = STMPE1601_REG_GPIO_SET_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPSR_CSB ] = STMPE1601_REG_GPIO_SET_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPCR_LSB ] = STMPE1601_REG_GPIO_CLR_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPCR_CSB ] = STMPE1601_REG_GPIO_CLR_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPDR_LSB ] = STMPE1601_REG_GPIO_SET_DIR_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPDR_CSB ] = STMPE1601_REG_GPIO_SET_DIR_MSB ,
[ STMPE_IDX_GPEDR_LSB ] = STMPE1601_REG_GPIO_ED_LSB ,
[ STMPE_IDX_GPEDR_CSB ] = STMPE1601_REG_GPIO_ED_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPRER_LSB ] = STMPE1601_REG_GPIO_RE_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPRER_CSB ] = STMPE1601_REG_GPIO_RE_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPFER_LSB ] = STMPE1601_REG_GPIO_FE_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPFER_CSB ] = STMPE1601_REG_GPIO_FE_MSB ,
2014-11-04 03:48:47 +03:00
[ STMPE_IDX_GPPUR_LSB ] = STMPE1601_REG_GPIO_PU_LSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPAFR_U_MSB ] = STMPE1601_REG_GPIO_AF_U_MSB ,
[ STMPE_IDX_IEGPIOR_LSB ] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_IEGPIOR_CSB ] = STMPE1601_REG_INT_EN_GPIO_MASK_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_ISGPIOR_MSB ] = STMPE1601_REG_INT_STA_GPIO_MSB ,
} ;
static struct stmpe_variant_block stmpe1601_blocks [ ] = {
{
. cell = & stmpe_gpio_cell ,
2012-11-05 19:10:32 +04:00
. irq = STMPE1601_IRQ_GPIOC ,
2010-07-02 15:22:08 +04:00
. block = STMPE_BLOCK_GPIO ,
} ,
{
. cell = & stmpe_keypad_cell ,
2012-11-05 19:10:32 +04:00
. irq = STMPE1601_IRQ_KEYPAD ,
2010-07-02 15:22:08 +04:00
. block = STMPE_BLOCK_KEYPAD ,
} ,
2016-02-14 16:07:07 +03:00
{
. cell = & stmpe_pwm_cell ,
. irq = STMPE1601_IRQ_PWM0 ,
. block = STMPE_BLOCK_PWM ,
} ,
2010-07-02 15:22:08 +04:00
} ;
2010-07-21 10:11:07 +04:00
/* supported autosleep timeout delay (in msecs) */
static const int stmpe_autosleep_delay [ ] = {
4 , 16 , 32 , 64 , 128 , 256 , 512 , 1024 ,
} ;
static int stmpe_round_timeout ( int timeout )
{
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( stmpe_autosleep_delay ) ; i + + ) {
if ( stmpe_autosleep_delay [ i ] > = timeout )
return i ;
}
/*
* requests for delays longer than supported should not return the
* longest supported delay
*/
return - EINVAL ;
}
static int stmpe_autosleep ( struct stmpe * stmpe , int autosleep_timeout )
{
int ret ;
if ( ! stmpe - > variant - > enable_autosleep )
return - ENOSYS ;
mutex_lock ( & stmpe - > lock ) ;
ret = stmpe - > variant - > enable_autosleep ( stmpe , autosleep_timeout ) ;
mutex_unlock ( & stmpe - > lock ) ;
return ret ;
}
/*
* Both stmpe 1601 / 2403 support same layout for autosleep
*/
static int stmpe1601_autosleep ( struct stmpe * stmpe ,
int autosleep_timeout )
{
int ret , timeout ;
/* choose the best available timeout */
timeout = stmpe_round_timeout ( autosleep_timeout ) ;
if ( timeout < 0 ) {
dev_err ( stmpe - > dev , " invalid timeout \n " ) ;
return timeout ;
}
2016-08-10 10:39:06 +03:00
ret = __stmpe_set_bits ( stmpe , stmpe - > regs [ STMPE_IDX_SYS_CTRL2 ] ,
2010-07-21 10:11:07 +04:00
STMPE1601_AUTOSLEEP_TIMEOUT_MASK ,
timeout ) ;
if ( ret < 0 )
return ret ;
2016-08-10 10:39:06 +03:00
return __stmpe_set_bits ( stmpe , stmpe - > regs [ STMPE_IDX_SYS_CTRL2 ] ,
2010-07-21 10:11:07 +04:00
STPME1601_AUTOSLEEP_ENABLE ,
STPME1601_AUTOSLEEP_ENABLE ) ;
}
2010-07-02 15:22:08 +04:00
static int stmpe1601_enable ( struct stmpe * stmpe , unsigned int blocks ,
bool enable )
{
unsigned int mask = 0 ;
if ( blocks & STMPE_BLOCK_GPIO )
mask | = STMPE1601_SYS_CTRL_ENABLE_GPIO ;
2014-05-09 01:16:37 +04:00
else
mask & = ~ STMPE1601_SYS_CTRL_ENABLE_GPIO ;
2010-07-02 15:22:08 +04:00
if ( blocks & STMPE_BLOCK_KEYPAD )
mask | = STMPE1601_SYS_CTRL_ENABLE_KPC ;
2014-05-09 01:16:37 +04:00
else
mask & = ~ STMPE1601_SYS_CTRL_ENABLE_KPC ;
if ( blocks & STMPE_BLOCK_PWM )
mask | = STMPE1601_SYS_CTRL_ENABLE_SPWM ;
else
mask & = ~ STMPE1601_SYS_CTRL_ENABLE_SPWM ;
2010-07-02 15:22:08 +04:00
2016-08-10 10:39:06 +03:00
return __stmpe_set_bits ( stmpe , stmpe - > regs [ STMPE_IDX_SYS_CTRL ] , mask ,
2010-07-02 15:22:08 +04:00
enable ? mask : 0 ) ;
}
static int stmpe1601_get_altfunc ( struct stmpe * stmpe , enum stmpe_block block )
{
switch ( block ) {
case STMPE_BLOCK_PWM :
return 2 ;
case STMPE_BLOCK_KEYPAD :
return 1 ;
case STMPE_BLOCK_GPIO :
default :
return 0 ;
}
}
static struct stmpe_variant_info stmpe1601 = {
. name = " stmpe1601 " ,
. id_val = 0x0210 ,
. id_mask = 0xfff0 , /* at least 0x0210 and 0x0212 */
. num_gpios = 16 ,
. af_bits = 2 ,
. regs = stmpe1601_regs ,
. blocks = stmpe1601_blocks ,
. num_blocks = ARRAY_SIZE ( stmpe1601_blocks ) ,
. num_irqs = STMPE1601_NR_INTERNAL_IRQS ,
. enable = stmpe1601_enable ,
. get_altfunc = stmpe1601_get_altfunc ,
2010-07-21 10:11:07 +04:00
. enable_autosleep = stmpe1601_autosleep ,
2010-07-02 15:22:08 +04:00
} ;
2013-04-09 12:35:19 +04:00
/*
* STMPE1801
*/
static const u8 stmpe1801_regs [ ] = {
[ STMPE_IDX_CHIP_ID ] = STMPE1801_REG_CHIP_ID ,
2016-08-10 10:39:06 +03:00
[ STMPE_IDX_SYS_CTRL ] = STMPE1801_REG_SYS_CTRL ,
2013-04-09 12:35:19 +04:00
[ STMPE_IDX_ICR_LSB ] = STMPE1801_REG_INT_CTRL_LOW ,
[ STMPE_IDX_IER_LSB ] = STMPE1801_REG_INT_EN_MASK_LOW ,
[ STMPE_IDX_ISR_LSB ] = STMPE1801_REG_INT_STA_LOW ,
[ STMPE_IDX_GPMR_LSB ] = STMPE1801_REG_GPIO_MP_LOW ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPMR_CSB ] = STMPE1801_REG_GPIO_MP_MID ,
[ STMPE_IDX_GPMR_MSB ] = STMPE1801_REG_GPIO_MP_HIGH ,
2013-04-09 12:35:19 +04:00
[ STMPE_IDX_GPSR_LSB ] = STMPE1801_REG_GPIO_SET_LOW ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPSR_CSB ] = STMPE1801_REG_GPIO_SET_MID ,
[ STMPE_IDX_GPSR_MSB ] = STMPE1801_REG_GPIO_SET_HIGH ,
2013-04-09 12:35:19 +04:00
[ STMPE_IDX_GPCR_LSB ] = STMPE1801_REG_GPIO_CLR_LOW ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPCR_CSB ] = STMPE1801_REG_GPIO_CLR_MID ,
[ STMPE_IDX_GPCR_MSB ] = STMPE1801_REG_GPIO_CLR_HIGH ,
2013-04-09 12:35:19 +04:00
[ STMPE_IDX_GPDR_LSB ] = STMPE1801_REG_GPIO_SET_DIR_LOW ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPDR_CSB ] = STMPE1801_REG_GPIO_SET_DIR_MID ,
[ STMPE_IDX_GPDR_MSB ] = STMPE1801_REG_GPIO_SET_DIR_HIGH ,
2013-04-09 12:35:19 +04:00
[ STMPE_IDX_GPRER_LSB ] = STMPE1801_REG_GPIO_RE_LOW ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPRER_CSB ] = STMPE1801_REG_GPIO_RE_MID ,
[ STMPE_IDX_GPRER_MSB ] = STMPE1801_REG_GPIO_RE_HIGH ,
2013-04-09 12:35:19 +04:00
[ STMPE_IDX_GPFER_LSB ] = STMPE1801_REG_GPIO_FE_LOW ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPFER_CSB ] = STMPE1801_REG_GPIO_FE_MID ,
[ STMPE_IDX_GPFER_MSB ] = STMPE1801_REG_GPIO_FE_HIGH ,
2014-11-04 03:48:47 +03:00
[ STMPE_IDX_GPPUR_LSB ] = STMPE1801_REG_GPIO_PULL_UP_LOW ,
2013-04-09 12:35:19 +04:00
[ STMPE_IDX_IEGPIOR_LSB ] = STMPE1801_REG_INT_EN_GPIO_MASK_LOW ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_IEGPIOR_CSB ] = STMPE1801_REG_INT_EN_GPIO_MASK_MID ,
[ STMPE_IDX_IEGPIOR_MSB ] = STMPE1801_REG_INT_EN_GPIO_MASK_HIGH ,
[ STMPE_IDX_ISGPIOR_MSB ] = STMPE1801_REG_INT_STA_GPIO_HIGH ,
2013-04-09 12:35:19 +04:00
} ;
static struct stmpe_variant_block stmpe1801_blocks [ ] = {
{
. cell = & stmpe_gpio_cell ,
. irq = STMPE1801_IRQ_GPIOC ,
. block = STMPE_BLOCK_GPIO ,
} ,
{
. cell = & stmpe_keypad_cell ,
. irq = STMPE1801_IRQ_KEYPAD ,
. block = STMPE_BLOCK_KEYPAD ,
} ,
} ;
static int stmpe1801_enable ( struct stmpe * stmpe , unsigned int blocks ,
bool enable )
{
unsigned int mask = 0 ;
if ( blocks & STMPE_BLOCK_GPIO )
mask | = STMPE1801_MSK_INT_EN_GPIO ;
if ( blocks & STMPE_BLOCK_KEYPAD )
mask | = STMPE1801_MSK_INT_EN_KPC ;
return __stmpe_set_bits ( stmpe , STMPE1801_REG_INT_EN_MASK_LOW , mask ,
enable ? mask : 0 ) ;
}
2016-08-10 10:39:07 +03:00
static int stmpe_reset ( struct stmpe * stmpe )
2013-04-09 12:35:19 +04:00
{
2016-08-10 10:39:07 +03:00
u16 id_val = stmpe - > variant - > id_val ;
2013-04-09 12:35:19 +04:00
unsigned long timeout ;
int ret = 0 ;
2016-08-10 10:39:07 +03:00
u8 reset_bit ;
if ( id_val = = STMPE811_ID )
/* STMPE801 and STMPE610 use bit 1 of SYS_CTRL register */
reset_bit = STMPE811_SYS_CTRL_RESET ;
else
/* all other STMPE variant use bit 7 of SYS_CTRL register */
reset_bit = STMPE_SYS_CTRL_RESET ;
2013-04-09 12:35:19 +04:00
2016-08-10 10:39:06 +03:00
ret = __stmpe_set_bits ( stmpe , stmpe - > regs [ STMPE_IDX_SYS_CTRL ] ,
2016-08-10 10:39:07 +03:00
reset_bit , reset_bit ) ;
2013-04-09 12:35:19 +04:00
if ( ret < 0 )
return ret ;
2016-11-01 12:22:53 +03:00
msleep ( 10 ) ;
2013-04-09 12:35:19 +04:00
timeout = jiffies + msecs_to_jiffies ( 100 ) ;
while ( time_before ( jiffies , timeout ) ) {
2016-08-10 10:39:06 +03:00
ret = __stmpe_reg_read ( stmpe , stmpe - > regs [ STMPE_IDX_SYS_CTRL ] ) ;
2013-04-09 12:35:19 +04:00
if ( ret < 0 )
return ret ;
2016-08-10 10:39:07 +03:00
if ( ! ( ret & reset_bit ) )
2013-04-09 12:35:19 +04:00
return 0 ;
usleep_range ( 100 , 200 ) ;
2014-02-04 13:07:13 +04:00
}
2013-04-09 12:35:19 +04:00
return - EIO ;
}
static struct stmpe_variant_info stmpe1801 = {
. name = " stmpe1801 " ,
. id_val = STMPE1801_ID ,
. id_mask = 0xfff0 ,
. num_gpios = 18 ,
. af_bits = 0 ,
. regs = stmpe1801_regs ,
. blocks = stmpe1801_blocks ,
. num_blocks = ARRAY_SIZE ( stmpe1801_blocks ) ,
. num_irqs = STMPE1801_NR_INTERNAL_IRQS ,
. enable = stmpe1801_enable ,
/* stmpe1801 do not have any gpio alternate function */
. get_altfunc = NULL ,
} ;
2010-07-02 15:22:08 +04:00
/*
* STMPE24XX
*/
static const u8 stmpe24xx_regs [ ] = {
[ STMPE_IDX_CHIP_ID ] = STMPE24XX_REG_CHIP_ID ,
2016-08-10 10:39:06 +03:00
[ STMPE_IDX_SYS_CTRL ] = STMPE24XX_REG_SYS_CTRL ,
[ STMPE_IDX_SYS_CTRL2 ] = STMPE24XX_REG_SYS_CTRL2 ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_ICR_LSB ] = STMPE24XX_REG_ICR_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_IER_MSB ] = STMPE24XX_REG_IER_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_IER_LSB ] = STMPE24XX_REG_IER_LSB ,
[ STMPE_IDX_ISR_MSB ] = STMPE24XX_REG_ISR_MSB ,
[ STMPE_IDX_GPMR_LSB ] = STMPE24XX_REG_GPMR_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPMR_CSB ] = STMPE24XX_REG_GPMR_CSB ,
[ STMPE_IDX_GPMR_MSB ] = STMPE24XX_REG_GPMR_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPSR_LSB ] = STMPE24XX_REG_GPSR_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPSR_CSB ] = STMPE24XX_REG_GPSR_CSB ,
[ STMPE_IDX_GPSR_MSB ] = STMPE24XX_REG_GPSR_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPCR_LSB ] = STMPE24XX_REG_GPCR_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPCR_CSB ] = STMPE24XX_REG_GPCR_CSB ,
[ STMPE_IDX_GPCR_MSB ] = STMPE24XX_REG_GPCR_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPDR_LSB ] = STMPE24XX_REG_GPDR_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPDR_CSB ] = STMPE24XX_REG_GPDR_CSB ,
[ STMPE_IDX_GPDR_MSB ] = STMPE24XX_REG_GPDR_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPRER_LSB ] = STMPE24XX_REG_GPRER_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPRER_CSB ] = STMPE24XX_REG_GPRER_CSB ,
[ STMPE_IDX_GPRER_MSB ] = STMPE24XX_REG_GPRER_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPFER_LSB ] = STMPE24XX_REG_GPFER_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPFER_CSB ] = STMPE24XX_REG_GPFER_CSB ,
[ STMPE_IDX_GPFER_MSB ] = STMPE24XX_REG_GPFER_MSB ,
2014-11-04 03:48:47 +03:00
[ STMPE_IDX_GPPUR_LSB ] = STMPE24XX_REG_GPPUR_LSB ,
[ STMPE_IDX_GPPDR_LSB ] = STMPE24XX_REG_GPPDR_LSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPAFR_U_MSB ] = STMPE24XX_REG_GPAFR_U_MSB ,
[ STMPE_IDX_IEGPIOR_LSB ] = STMPE24XX_REG_IEGPIOR_LSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_IEGPIOR_CSB ] = STMPE24XX_REG_IEGPIOR_CSB ,
[ STMPE_IDX_IEGPIOR_MSB ] = STMPE24XX_REG_IEGPIOR_MSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_ISGPIOR_MSB ] = STMPE24XX_REG_ISGPIOR_MSB ,
2016-08-10 10:39:11 +03:00
[ STMPE_IDX_GPEDR_LSB ] = STMPE24XX_REG_GPEDR_LSB ,
[ STMPE_IDX_GPEDR_CSB ] = STMPE24XX_REG_GPEDR_CSB ,
2010-07-02 15:22:08 +04:00
[ STMPE_IDX_GPEDR_MSB ] = STMPE24XX_REG_GPEDR_MSB ,
} ;
static struct stmpe_variant_block stmpe24xx_blocks [ ] = {
{
. cell = & stmpe_gpio_cell ,
. irq = STMPE24XX_IRQ_GPIOC ,
. block = STMPE_BLOCK_GPIO ,
} ,
{
. cell = & stmpe_keypad_cell ,
. irq = STMPE24XX_IRQ_KEYPAD ,
. block = STMPE_BLOCK_KEYPAD ,
} ,
2016-02-14 16:07:07 +03:00
{
. cell = & stmpe_pwm_cell ,
. irq = STMPE24XX_IRQ_PWM0 ,
. block = STMPE_BLOCK_PWM ,
} ,
2010-07-02 15:22:08 +04:00
} ;
static int stmpe24xx_enable ( struct stmpe * stmpe , unsigned int blocks ,
bool enable )
{
unsigned int mask = 0 ;
if ( blocks & STMPE_BLOCK_GPIO )
mask | = STMPE24XX_SYS_CTRL_ENABLE_GPIO ;
if ( blocks & STMPE_BLOCK_KEYPAD )
mask | = STMPE24XX_SYS_CTRL_ENABLE_KPC ;
2016-08-10 10:39:06 +03:00
return __stmpe_set_bits ( stmpe , stmpe - > regs [ STMPE_IDX_SYS_CTRL ] , mask ,
2010-07-02 15:22:08 +04:00
enable ? mask : 0 ) ;
}
static int stmpe24xx_get_altfunc ( struct stmpe * stmpe , enum stmpe_block block )
{
switch ( block ) {
case STMPE_BLOCK_ROTATOR :
return 2 ;
case STMPE_BLOCK_KEYPAD :
2015-08-28 00:50:02 +03:00
case STMPE_BLOCK_PWM :
2010-07-02 15:22:08 +04:00
return 1 ;
case STMPE_BLOCK_GPIO :
default :
return 0 ;
}
}
static struct stmpe_variant_info stmpe2401 = {
. name = " stmpe2401 " ,
. id_val = 0x0101 ,
. id_mask = 0xffff ,
. num_gpios = 24 ,
. af_bits = 2 ,
. regs = stmpe24xx_regs ,
. blocks = stmpe24xx_blocks ,
. num_blocks = ARRAY_SIZE ( stmpe24xx_blocks ) ,
. num_irqs = STMPE24XX_NR_INTERNAL_IRQS ,
. enable = stmpe24xx_enable ,
. get_altfunc = stmpe24xx_get_altfunc ,
} ;
static struct stmpe_variant_info stmpe2403 = {
. name = " stmpe2403 " ,
. id_val = 0x0120 ,
. id_mask = 0xffff ,
. num_gpios = 24 ,
. af_bits = 2 ,
. regs = stmpe24xx_regs ,
. blocks = stmpe24xx_blocks ,
. num_blocks = ARRAY_SIZE ( stmpe24xx_blocks ) ,
. num_irqs = STMPE24XX_NR_INTERNAL_IRQS ,
. enable = stmpe24xx_enable ,
. get_altfunc = stmpe24xx_get_altfunc ,
2010-07-21 10:11:07 +04:00
. enable_autosleep = stmpe1601_autosleep , /* same as stmpe1601 */
2010-07-02 15:22:08 +04:00
} ;
2012-01-27 01:17:03 +04:00
static struct stmpe_variant_info * stmpe_variant_info [ STMPE_NBR_PARTS ] = {
2011-11-17 09:32:22 +04:00
[ STMPE610 ] = & stmpe610 ,
2011-11-17 09:32:23 +04:00
[ STMPE801 ] = & stmpe801 ,
2010-07-02 15:22:08 +04:00
[ STMPE811 ] = & stmpe811 ,
2016-08-10 10:39:14 +03:00
[ STMPE1600 ] = & stmpe1600 ,
2010-07-02 15:22:08 +04:00
[ STMPE1601 ] = & stmpe1601 ,
2013-04-09 12:35:19 +04:00
[ STMPE1801 ] = & stmpe1801 ,
2010-07-02 15:22:08 +04:00
[ STMPE2401 ] = & stmpe2401 ,
[ STMPE2403 ] = & stmpe2403 ,
} ;
2012-01-27 01:17:03 +04:00
/*
* These devices can be connected in a ' no - irq ' configuration - the irq pin
* is not used and the device cannot interrupt the CPU . Here we only list
* devices which support this configuration - the driver will fail probing
* for any devices not listed here which are configured in this way .
*/
static struct stmpe_variant_info * stmpe_noirq_variant_info [ STMPE_NBR_PARTS ] = {
[ STMPE801 ] = & stmpe801_noirq ,
} ;
2010-07-02 15:22:08 +04:00
static irqreturn_t stmpe_irq ( int irq , void * data )
{
struct stmpe * stmpe = data ;
struct stmpe_variant_info * variant = stmpe - > variant ;
int num = DIV_ROUND_UP ( variant - > num_irqs , 8 ) ;
2013-04-09 12:35:19 +04:00
u8 israddr ;
2014-08-28 14:20:33 +04:00
u8 isr [ 3 ] ;
2010-07-02 15:22:08 +04:00
int ret ;
int i ;
2016-08-10 10:39:14 +03:00
if ( variant - > id_val = = STMPE801_ID | |
variant - > id_val = = STMPE1600_ID ) {
2012-11-05 19:10:31 +04:00
int base = irq_create_mapping ( stmpe - > domain , 0 ) ;
handle_nested_irq ( base ) ;
2011-11-17 09:32:23 +04:00
return IRQ_HANDLED ;
}
2013-04-09 12:35:19 +04:00
if ( variant - > id_val = = STMPE1801_ID )
israddr = stmpe - > regs [ STMPE_IDX_ISR_LSB ] ;
else
israddr = stmpe - > regs [ STMPE_IDX_ISR_MSB ] ;
2010-07-02 15:22:08 +04:00
ret = stmpe_block_read ( stmpe , israddr , num , isr ) ;
if ( ret < 0 )
return IRQ_NONE ;
for ( i = 0 ; i < num ; i + + ) {
int bank = num - i - 1 ;
u8 status = isr [ i ] ;
u8 clear ;
status & = stmpe - > ier [ bank ] ;
if ( ! status )
continue ;
clear = status ;
while ( status ) {
int bit = __ffs ( status ) ;
int line = bank * 8 + bit ;
2012-11-05 19:10:31 +04:00
int nestedirq = irq_create_mapping ( stmpe - > domain , line ) ;
2010-07-02 15:22:08 +04:00
2012-11-05 19:10:31 +04:00
handle_nested_irq ( nestedirq ) ;
2010-07-02 15:22:08 +04:00
status & = ~ ( 1 < < bit ) ;
}
stmpe_reg_write ( stmpe , israddr + i , clear ) ;
}
return IRQ_HANDLED ;
}
2010-12-12 15:01:08 +03:00
static void stmpe_irq_lock ( struct irq_data * data )
2010-07-02 15:22:08 +04:00
{
2010-12-12 15:01:08 +03:00
struct stmpe * stmpe = irq_data_get_irq_chip_data ( data ) ;
2010-07-02 15:22:08 +04:00
mutex_lock ( & stmpe - > irq_lock ) ;
}
2010-12-12 15:01:08 +03:00
static void stmpe_irq_sync_unlock ( struct irq_data * data )
2010-07-02 15:22:08 +04:00
{
2010-12-12 15:01:08 +03:00
struct stmpe * stmpe = irq_data_get_irq_chip_data ( data ) ;
2010-07-02 15:22:08 +04:00
struct stmpe_variant_info * variant = stmpe - > variant ;
int num = DIV_ROUND_UP ( variant - > num_irqs , 8 ) ;
int i ;
for ( i = 0 ; i < num ; i + + ) {
u8 new = stmpe - > ier [ i ] ;
u8 old = stmpe - > oldier [ i ] ;
if ( new = = old )
continue ;
stmpe - > oldier [ i ] = new ;
2016-08-10 10:39:11 +03:00
stmpe_reg_write ( stmpe , stmpe - > regs [ STMPE_IDX_IER_LSB + i ] , new ) ;
2010-07-02 15:22:08 +04:00
}
mutex_unlock ( & stmpe - > irq_lock ) ;
}
2010-12-12 15:01:08 +03:00
static void stmpe_irq_mask ( struct irq_data * data )
2010-07-02 15:22:08 +04:00
{
2010-12-12 15:01:08 +03:00
struct stmpe * stmpe = irq_data_get_irq_chip_data ( data ) ;
2012-11-05 19:10:31 +04:00
int offset = data - > hwirq ;
2010-07-02 15:22:08 +04:00
int regoffset = offset / 8 ;
int mask = 1 < < ( offset % 8 ) ;
stmpe - > ier [ regoffset ] & = ~ mask ;
}
2010-12-12 15:01:08 +03:00
static void stmpe_irq_unmask ( struct irq_data * data )
2010-07-02 15:22:08 +04:00
{
2010-12-12 15:01:08 +03:00
struct stmpe * stmpe = irq_data_get_irq_chip_data ( data ) ;
2012-11-05 19:10:31 +04:00
int offset = data - > hwirq ;
2010-07-02 15:22:08 +04:00
int regoffset = offset / 8 ;
int mask = 1 < < ( offset % 8 ) ;
stmpe - > ier [ regoffset ] | = mask ;
}
static struct irq_chip stmpe_irq_chip = {
. name = " stmpe " ,
2010-12-12 15:01:08 +03:00
. irq_bus_lock = stmpe_irq_lock ,
. irq_bus_sync_unlock = stmpe_irq_sync_unlock ,
. irq_mask = stmpe_irq_mask ,
. irq_unmask = stmpe_irq_unmask ,
2010-07-02 15:22:08 +04:00
} ;
2012-11-05 19:10:31 +04:00
static int stmpe_irq_map ( struct irq_domain * d , unsigned int virq ,
irq_hw_number_t hwirq )
2010-07-02 15:22:08 +04:00
{
2012-11-05 19:10:31 +04:00
struct stmpe * stmpe = d - > host_data ;
2011-11-17 09:32:23 +04:00
struct irq_chip * chip = NULL ;
2010-07-02 15:22:08 +04:00
2011-11-17 09:32:23 +04:00
if ( stmpe - > variant - > id_val ! = STMPE801_ID )
chip = & stmpe_irq_chip ;
2012-11-05 19:10:31 +04:00
irq_set_chip_data ( virq , stmpe ) ;
irq_set_chip_and_handler ( virq , chip , handle_edge_irq ) ;
irq_set_nested_thread ( virq , 1 ) ;
irq_set_noprobe ( virq ) ;
2010-07-02 15:22:08 +04:00
return 0 ;
}
2012-11-05 19:10:31 +04:00
static void stmpe_irq_unmap ( struct irq_domain * d , unsigned int virq )
2010-07-02 15:22:08 +04:00
{
2012-11-05 19:10:31 +04:00
irq_set_chip_and_handler ( virq , NULL , NULL ) ;
irq_set_chip_data ( virq , NULL ) ;
}
2015-04-27 15:54:13 +03:00
static const struct irq_domain_ops stmpe_irq_ops = {
2012-11-05 19:10:31 +04:00
. map = stmpe_irq_map ,
. unmap = stmpe_irq_unmap ,
. xlate = irq_domain_xlate_twocell ,
} ;
2012-12-22 03:03:15 +04:00
static int stmpe_irq_init ( struct stmpe * stmpe , struct device_node * np )
2012-11-05 19:10:31 +04:00
{
2012-11-23 19:19:29 +04:00
int base = 0 ;
2012-11-05 19:10:31 +04:00
int num_irqs = stmpe - > variant - > num_irqs ;
2012-11-23 19:19:29 +04:00
stmpe - > domain = irq_domain_add_simple ( np , num_irqs , base ,
& stmpe_irq_ops , stmpe ) ;
2012-11-05 19:10:31 +04:00
if ( ! stmpe - > domain ) {
dev_err ( stmpe - > dev , " Failed to create irqdomain \n " ) ;
return - ENOSYS ;
2010-07-02 15:22:08 +04:00
}
2012-11-05 19:10:31 +04:00
return 0 ;
2010-07-02 15:22:08 +04:00
}
2012-12-22 03:03:15 +04:00
static int stmpe_chip_init ( struct stmpe * stmpe )
2010-07-02 15:22:08 +04:00
{
unsigned int irq_trigger = stmpe - > pdata - > irq_trigger ;
2010-07-21 10:11:07 +04:00
int autosleep_timeout = stmpe - > pdata - > autosleep_timeout ;
2010-07-02 15:22:08 +04:00
struct stmpe_variant_info * variant = stmpe - > variant ;
2012-01-27 01:17:03 +04:00
u8 icr = 0 ;
2010-07-02 15:22:08 +04:00
unsigned int id ;
u8 data [ 2 ] ;
int ret ;
ret = stmpe_block_read ( stmpe , stmpe - > regs [ STMPE_IDX_CHIP_ID ] ,
ARRAY_SIZE ( data ) , data ) ;
if ( ret < 0 )
return ret ;
id = ( data [ 0 ] < < 8 ) | data [ 1 ] ;
if ( ( id & variant - > id_mask ) ! = variant - > id_val ) {
dev_err ( stmpe - > dev , " unknown chip id: %#x \n " , id ) ;
return - EINVAL ;
}
dev_info ( stmpe - > dev , " %s detected, chip id: %#x \n " , variant - > name , id ) ;
/* Disable all modules -- subdrivers should enable what they need. */
ret = stmpe_disable ( stmpe , ~ 0 ) ;
if ( ret )
return ret ;
2016-08-10 10:39:07 +03:00
ret = stmpe_reset ( stmpe ) ;
if ( ret < 0 )
return ret ;
2013-04-09 12:35:19 +04:00
2012-01-27 01:17:03 +04:00
if ( stmpe - > irq > = 0 ) {
2016-08-10 10:39:14 +03:00
if ( id = = STMPE801_ID | | id = = STMPE1600_ID )
2016-08-10 10:39:10 +03:00
icr = STMPE_SYS_CTRL_INT_EN ;
2011-11-17 09:32:23 +04:00
else
2012-01-27 01:17:03 +04:00
icr = STMPE_ICR_LSB_GIM ;
2010-07-02 15:22:08 +04:00
2016-08-10 10:39:14 +03:00
/* STMPE801 and STMPE1600 don't support Edge interrupts */
if ( id ! = STMPE801_ID & & id ! = STMPE1600_ID ) {
2012-01-27 01:17:03 +04:00
if ( irq_trigger = = IRQF_TRIGGER_FALLING | |
irq_trigger = = IRQF_TRIGGER_RISING )
icr | = STMPE_ICR_LSB_EDGE ;
}
if ( irq_trigger = = IRQF_TRIGGER_RISING | |
irq_trigger = = IRQF_TRIGGER_HIGH ) {
2016-08-10 10:39:14 +03:00
if ( id = = STMPE801_ID | | id = = STMPE1600_ID )
2016-08-10 10:39:10 +03:00
icr | = STMPE_SYS_CTRL_INT_HI ;
2012-01-27 01:17:03 +04:00
else
icr | = STMPE_ICR_LSB_HIGH ;
}
2011-11-17 09:32:23 +04:00
}
2010-07-02 15:22:08 +04:00
2010-07-21 10:11:07 +04:00
if ( stmpe - > pdata - > autosleep ) {
ret = stmpe_autosleep ( stmpe , autosleep_timeout ) ;
if ( ret )
return ret ;
}
2010-07-02 15:22:08 +04:00
return stmpe_reg_write ( stmpe , stmpe - > regs [ STMPE_IDX_ICR_LSB ] , icr ) ;
}
2013-11-18 17:33:01 +04:00
static int stmpe_add_device ( struct stmpe * stmpe , const struct mfd_cell * cell )
2010-07-02 15:22:08 +04:00
{
return mfd_add_devices ( stmpe - > dev , stmpe - > pdata - > id , cell , 1 ,
2014-05-09 01:16:34 +04:00
NULL , 0 , stmpe - > domain ) ;
2010-07-02 15:22:08 +04:00
}
2012-12-22 03:03:15 +04:00
static int stmpe_devices_init ( struct stmpe * stmpe )
2010-07-02 15:22:08 +04:00
{
struct stmpe_variant_info * variant = stmpe - > variant ;
unsigned int platform_blocks = stmpe - > pdata - > blocks ;
int ret = - EINVAL ;
2012-11-05 19:10:30 +04:00
int i , j ;
2010-07-02 15:22:08 +04:00
for ( i = 0 ; i < variant - > num_blocks ; i + + ) {
struct stmpe_variant_block * block = & variant - > blocks [ i ] ;
if ( ! ( platform_blocks & block - > block ) )
continue ;
2012-11-05 19:10:30 +04:00
for ( j = 0 ; j < block - > cell - > num_resources ; j + + ) {
struct resource * res =
( struct resource * ) & block - > cell - > resources [ j ] ;
/* Dynamically fill in a variant's IRQ. */
if ( res - > flags & IORESOURCE_IRQ )
res - > start = res - > end = block - > irq + j ;
}
2010-07-02 15:22:08 +04:00
platform_blocks & = ~ block - > block ;
2012-11-05 19:10:30 +04:00
ret = stmpe_add_device ( stmpe , block - > cell ) ;
2010-07-02 15:22:08 +04:00
if ( ret )
return ret ;
}
if ( platform_blocks )
dev_warn ( stmpe - > dev ,
" platform wants blocks (%#x) not present on variant " ,
platform_blocks ) ;
return ret ;
}
2013-07-28 18:03:48 +04:00
static void stmpe_of_probe ( struct stmpe_platform_data * pdata ,
struct device_node * np )
2012-11-05 19:10:33 +04:00
{
struct device_node * child ;
2013-03-01 16:07:26 +04:00
pdata - > id = of_alias_get_id ( np , " stmpe-i2c " ) ;
if ( pdata - > id < 0 )
pdata - > id = - 1 ;
2014-09-12 07:18:33 +04:00
pdata - > irq_gpio = of_get_named_gpio_flags ( np , " irq-gpio " , 0 ,
& pdata - > irq_trigger ) ;
if ( gpio_is_valid ( pdata - > irq_gpio ) )
pdata - > irq_over_gpio = 1 ;
else
pdata - > irq_trigger = IRQF_TRIGGER_NONE ;
2012-12-07 18:59:37 +04:00
2012-11-05 19:10:33 +04:00
of_property_read_u32 ( np , " st,autosleep-timeout " ,
& pdata - > autosleep_timeout ) ;
pdata - > autosleep = ( pdata - > autosleep_timeout ) ? true : false ;
for_each_child_of_node ( np , child ) {
if ( ! strcmp ( child - > name , " stmpe_gpio " ) ) {
pdata - > blocks | = STMPE_BLOCK_GPIO ;
2012-12-07 18:59:37 +04:00
} else if ( ! strcmp ( child - > name , " stmpe_keypad " ) ) {
2012-11-05 19:10:33 +04:00
pdata - > blocks | = STMPE_BLOCK_KEYPAD ;
2012-12-07 18:59:37 +04:00
} else if ( ! strcmp ( child - > name , " stmpe_touchscreen " ) ) {
2012-11-05 19:10:33 +04:00
pdata - > blocks | = STMPE_BLOCK_TOUCHSCREEN ;
2012-12-07 18:59:37 +04:00
} else if ( ! strcmp ( child - > name , " stmpe_adc " ) ) {
2012-11-05 19:10:33 +04:00
pdata - > blocks | = STMPE_BLOCK_ADC ;
2012-12-07 18:59:37 +04:00
} else if ( ! strcmp ( child - > name , " stmpe_pwm " ) ) {
pdata - > blocks | = STMPE_BLOCK_PWM ;
} else if ( ! strcmp ( child - > name , " stmpe_rotator " ) ) {
pdata - > blocks | = STMPE_BLOCK_ROTATOR ;
2012-11-05 19:10:33 +04:00
}
}
}
2011-11-17 09:32:20 +04:00
/* Called from client specific probe routines */
2014-07-02 14:54:32 +04:00
int stmpe_probe ( struct stmpe_client_info * ci , enum stmpe_partnum partnum )
2010-09-15 09:00:54 +04:00
{
2016-05-25 15:22:02 +03:00
struct stmpe_platform_data * pdata ;
2012-11-05 19:10:33 +04:00
struct device_node * np = ci - > dev - > of_node ;
2010-07-02 15:22:08 +04:00
struct stmpe * stmpe ;
int ret ;
2016-05-25 15:22:02 +03:00
pdata = devm_kzalloc ( ci - > dev , sizeof ( * pdata ) , GFP_KERNEL ) ;
if ( ! pdata )
return - ENOMEM ;
2012-11-22 09:10:29 +04:00
2016-05-25 15:22:02 +03:00
stmpe_of_probe ( pdata , np ) ;
2013-03-01 16:07:16 +04:00
2016-05-25 15:22:02 +03:00
if ( of_find_property ( np , " interrupts " , NULL ) = = NULL )
ci - > irq = - 1 ;
2010-07-02 15:22:08 +04:00
2012-11-22 09:10:29 +04:00
stmpe = devm_kzalloc ( ci - > dev , sizeof ( struct stmpe ) , GFP_KERNEL ) ;
2010-07-02 15:22:08 +04:00
if ( ! stmpe )
return - ENOMEM ;
mutex_init ( & stmpe - > irq_lock ) ;
mutex_init ( & stmpe - > lock ) ;
2011-11-17 09:32:20 +04:00
stmpe - > dev = ci - > dev ;
stmpe - > client = ci - > client ;
2010-07-02 15:22:08 +04:00
stmpe - > pdata = pdata ;
2011-11-17 09:32:20 +04:00
stmpe - > ci = ci ;
stmpe - > partnum = partnum ;
stmpe - > variant = stmpe_variant_info [ partnum ] ;
2010-07-02 15:22:08 +04:00
stmpe - > regs = stmpe - > variant - > regs ;
stmpe - > num_gpios = stmpe - > variant - > num_gpios ;
2014-05-09 01:16:35 +04:00
stmpe - > vcc = devm_regulator_get_optional ( ci - > dev , " vcc " ) ;
if ( ! IS_ERR ( stmpe - > vcc ) ) {
ret = regulator_enable ( stmpe - > vcc ) ;
if ( ret )
dev_warn ( ci - > dev , " failed to enable VCC supply \n " ) ;
}
stmpe - > vio = devm_regulator_get_optional ( ci - > dev , " vio " ) ;
if ( ! IS_ERR ( stmpe - > vio ) ) {
ret = regulator_enable ( stmpe - > vio ) ;
if ( ret )
dev_warn ( ci - > dev , " failed to enable VIO supply \n " ) ;
}
2011-11-17 09:32:20 +04:00
dev_set_drvdata ( stmpe - > dev , stmpe ) ;
2010-07-02 15:22:08 +04:00
2011-11-17 09:32:20 +04:00
if ( ci - > init )
ci - > init ( stmpe ) ;
2010-07-02 15:22:08 +04:00
2011-11-08 08:14:06 +04:00
if ( pdata - > irq_over_gpio ) {
2012-11-22 09:10:29 +04:00
ret = devm_gpio_request_one ( ci - > dev , pdata - > irq_gpio ,
GPIOF_DIR_IN , " stmpe " ) ;
2011-11-08 08:14:06 +04:00
if ( ret ) {
dev_err ( stmpe - > dev , " failed to request IRQ GPIO: %d \n " ,
ret ) ;
2012-11-22 09:10:29 +04:00
return ret ;
2011-11-08 08:14:06 +04:00
}
stmpe - > irq = gpio_to_irq ( pdata - > irq_gpio ) ;
} else {
2011-11-17 09:32:20 +04:00
stmpe - > irq = ci - > irq ;
2011-11-08 08:14:06 +04:00
}
2012-01-27 01:17:03 +04:00
if ( stmpe - > irq < 0 ) {
/* use alternate variant info for no-irq mode, if supported */
dev_info ( stmpe - > dev ,
" %s configured in no-irq mode by platform data \n " ,
stmpe - > variant - > name ) ;
if ( ! stmpe_noirq_variant_info [ stmpe - > partnum ] ) {
dev_err ( stmpe - > dev ,
" %s does not support no-irq mode! \n " ,
stmpe - > variant - > name ) ;
2012-11-22 09:10:29 +04:00
return - ENODEV ;
2012-01-27 01:17:03 +04:00
}
stmpe - > variant = stmpe_noirq_variant_info [ stmpe - > partnum ] ;
2012-12-07 18:59:37 +04:00
} else if ( pdata - > irq_trigger = = IRQF_TRIGGER_NONE ) {
2013-06-14 20:40:46 +04:00
pdata - > irq_trigger = irq_get_trigger_type ( stmpe - > irq ) ;
2012-01-27 01:17:03 +04:00
}
2010-07-02 15:22:08 +04:00
ret = stmpe_chip_init ( stmpe ) ;
if ( ret )
2012-11-22 09:10:29 +04:00
return ret ;
2010-07-02 15:22:08 +04:00
2012-01-27 01:17:03 +04:00
if ( stmpe - > irq > = 0 ) {
2012-11-05 19:10:33 +04:00
ret = stmpe_irq_init ( stmpe , np ) ;
2012-01-27 01:17:03 +04:00
if ( ret )
2012-11-22 09:10:29 +04:00
return ret ;
2010-07-02 15:22:08 +04:00
2012-11-22 09:10:29 +04:00
ret = devm_request_threaded_irq ( ci - > dev , stmpe - > irq , NULL ,
stmpe_irq , pdata - > irq_trigger | IRQF_ONESHOT ,
2012-01-27 01:17:03 +04:00
" stmpe " , stmpe ) ;
if ( ret ) {
dev_err ( stmpe - > dev , " failed to request IRQ: %d \n " ,
ret ) ;
2012-11-22 09:10:29 +04:00
return ret ;
2012-01-27 01:17:03 +04:00
}
2010-07-02 15:22:08 +04:00
}
ret = stmpe_devices_init ( stmpe ) ;
2012-11-22 09:10:29 +04:00
if ( ! ret )
return 0 ;
2010-07-02 15:22:08 +04:00
2012-11-22 09:10:29 +04:00
dev_err ( stmpe - > dev , " failed to add children \n " ) ;
2010-07-02 15:22:08 +04:00
mfd_remove_devices ( stmpe - > dev ) ;
2012-11-22 09:10:29 +04:00
2010-07-02 15:22:08 +04:00
return ret ;
}
2011-11-17 09:32:20 +04:00
int stmpe_remove ( struct stmpe * stmpe )
2010-07-02 15:22:08 +04:00
{
2014-05-09 01:16:35 +04:00
if ( ! IS_ERR ( stmpe - > vio ) )
regulator_disable ( stmpe - > vio ) ;
if ( ! IS_ERR ( stmpe - > vcc ) )
regulator_disable ( stmpe - > vcc ) ;
2010-07-02 15:22:08 +04:00
mfd_remove_devices ( stmpe - > dev ) ;
return 0 ;
}
2010-09-15 09:00:54 +04:00
# ifdef CONFIG_PM
2011-11-17 09:32:20 +04:00
static int stmpe_suspend ( struct device * dev )
{
struct stmpe * stmpe = dev_get_drvdata ( dev ) ;
2010-09-15 09:00:54 +04:00
2012-01-27 01:17:03 +04:00
if ( stmpe - > irq > = 0 & & device_may_wakeup ( dev ) )
2011-11-17 09:32:20 +04:00
enable_irq_wake ( stmpe - > irq ) ;
2010-07-02 15:22:08 +04:00
2011-11-17 09:32:20 +04:00
return 0 ;
2010-07-02 15:22:08 +04:00
}
2011-11-17 09:32:20 +04:00
static int stmpe_resume ( struct device * dev )
2010-07-02 15:22:08 +04:00
{
2011-11-17 09:32:20 +04:00
struct stmpe * stmpe = dev_get_drvdata ( dev ) ;
2012-01-27 01:17:03 +04:00
if ( stmpe - > irq > = 0 & & device_may_wakeup ( dev ) )
2011-11-17 09:32:20 +04:00
disable_irq_wake ( stmpe - > irq ) ;
return 0 ;
2010-07-02 15:22:08 +04:00
}
2011-11-17 09:32:20 +04:00
const struct dev_pm_ops stmpe_dev_pm_ops = {
. suspend = stmpe_suspend ,
. resume = stmpe_resume ,
} ;
# endif