2010-07-02 15:22:09 +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
*/
# include <linux/init.h>
# include <linux/platform_device.h>
# include <linux/slab.h>
# include <linux/gpio.h>
# include <linux/interrupt.h>
2012-11-26 15:36:51 +04:00
# include <linux/of.h>
2010-07-02 15:22:09 +04:00
# include <linux/mfd/stmpe.h>
2014-10-02 09:55:41 +04:00
# include <linux/seq_file.h>
2010-07-02 15:22:09 +04:00
/*
* These registers are modified under the irq bus lock and cached to avoid
* unnecessary writes in bus_sync_unlock .
*/
enum { REG_RE , REG_FE , REG_IE } ;
2016-08-10 10:39:12 +03:00
enum { LSB , CSB , MSB } ;
2010-07-02 15:22:09 +04:00
# define CACHE_NR_REGS 3
2014-05-09 01:16:34 +04:00
/* No variant has more than 24 GPIOs */
# define CACHE_NR_BANKS (24 / 8)
2010-07-02 15:22:09 +04:00
struct stmpe_gpio {
struct gpio_chip chip ;
struct stmpe * stmpe ;
struct device * dev ;
struct mutex irq_lock ;
2015-01-13 10:00:29 +03:00
u32 norequest_mask ;
2010-07-02 15:22:09 +04:00
/* Caches of interrupt control registers for bus_lock */
u8 regs [ CACHE_NR_REGS ] [ CACHE_NR_BANKS ] ;
u8 oldregs [ CACHE_NR_REGS ] [ CACHE_NR_BANKS ] ;
} ;
static int stmpe_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( chip ) ;
2010-07-02 15:22:09 +04:00
struct stmpe * stmpe = stmpe_gpio - > stmpe ;
2016-08-10 10:39:12 +03:00
u8 reg = stmpe - > regs [ STMPE_IDX_GPMR_LSB + ( offset / 8 ) ] ;
2010-07-02 15:22:09 +04:00
u8 mask = 1 < < ( offset % 8 ) ;
int ret ;
ret = stmpe_reg_read ( stmpe , reg ) ;
if ( ret < 0 )
return ret ;
2012-02-27 09:49:43 +04:00
return ! ! ( ret & mask ) ;
2010-07-02 15:22:09 +04:00
}
static void stmpe_gpio_set ( struct gpio_chip * chip , unsigned offset , int val )
{
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( chip ) ;
2010-07-02 15:22:09 +04:00
struct stmpe * stmpe = stmpe_gpio - > stmpe ;
int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB ;
2016-08-10 10:39:12 +03:00
u8 reg = stmpe - > regs [ which + ( offset / 8 ) ] ;
2010-07-02 15:22:09 +04:00
u8 mask = 1 < < ( offset % 8 ) ;
2011-12-14 07:58:27 +04:00
/*
* Some variants have single register for gpio set / clear functionality .
* For them we need to write 0 to clear and 1 to set .
*/
if ( stmpe - > regs [ STMPE_IDX_GPSR_LSB ] = = stmpe - > regs [ STMPE_IDX_GPCR_LSB ] )
stmpe_set_bits ( stmpe , reg , mask , val ? mask : 0 ) ;
else
stmpe_reg_write ( stmpe , reg , mask ) ;
2010-07-02 15:22:09 +04:00
}
2016-04-28 16:00:18 +03:00
static int stmpe_gpio_get_direction ( struct gpio_chip * chip ,
unsigned offset )
{
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( chip ) ;
struct stmpe * stmpe = stmpe_gpio - > stmpe ;
u8 reg = stmpe - > regs [ STMPE_IDX_GPDR_LSB ] - ( offset / 8 ) ;
u8 mask = 1 < < ( offset % 8 ) ;
int ret ;
ret = stmpe_reg_read ( stmpe , reg ) ;
if ( ret < 0 )
return ret ;
return ! ( ret & mask ) ;
}
2010-07-02 15:22:09 +04:00
static int stmpe_gpio_direction_output ( struct gpio_chip * chip ,
unsigned offset , int val )
{
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( chip ) ;
2010-07-02 15:22:09 +04:00
struct stmpe * stmpe = stmpe_gpio - > stmpe ;
2016-08-10 10:39:12 +03:00
u8 reg = stmpe - > regs [ STMPE_IDX_GPDR_LSB + ( offset / 8 ) ] ;
2010-07-02 15:22:09 +04:00
u8 mask = 1 < < ( offset % 8 ) ;
stmpe_gpio_set ( chip , offset , val ) ;
return stmpe_set_bits ( stmpe , reg , mask , mask ) ;
}
static int stmpe_gpio_direction_input ( struct gpio_chip * chip ,
unsigned offset )
{
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( chip ) ;
2010-07-02 15:22:09 +04:00
struct stmpe * stmpe = stmpe_gpio - > stmpe ;
2016-08-10 10:39:12 +03:00
u8 reg = stmpe - > regs [ STMPE_IDX_GPDR_LSB + ( offset / 8 ) ] ;
2010-07-02 15:22:09 +04:00
u8 mask = 1 < < ( offset % 8 ) ;
return stmpe_set_bits ( stmpe , reg , mask , 0 ) ;
}
static int stmpe_gpio_request ( struct gpio_chip * chip , unsigned offset )
{
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( chip ) ;
2010-07-02 15:22:09 +04:00
struct stmpe * stmpe = stmpe_gpio - > stmpe ;
2010-08-16 19:14:44 +04:00
if ( stmpe_gpio - > norequest_mask & ( 1 < < offset ) )
return - EINVAL ;
2010-07-02 15:22:09 +04:00
return stmpe_set_altfunc ( stmpe , 1 < < offset , STMPE_BLOCK_GPIO ) ;
}
static struct gpio_chip template_chip = {
. label = " stmpe " ,
. owner = THIS_MODULE ,
2016-04-28 16:00:18 +03:00
. get_direction = stmpe_gpio_get_direction ,
2010-07-02 15:22:09 +04:00
. direction_input = stmpe_gpio_direction_input ,
. get = stmpe_gpio_get ,
. direction_output = stmpe_gpio_direction_output ,
. set = stmpe_gpio_set ,
. request = stmpe_gpio_request ,
2013-12-04 17:42:46 +04:00
. can_sleep = true ,
2010-07-02 15:22:09 +04:00
} ;
2011-01-13 04:00:17 +03:00
static int stmpe_gpio_irq_set_type ( struct irq_data * d , unsigned int type )
2010-07-02 15:22:09 +04:00
{
2014-04-16 01:38:56 +04:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( gc ) ;
2012-12-10 14:07:54 +04:00
int offset = d - > hwirq ;
2010-07-02 15:22:09 +04:00
int regoffset = offset / 8 ;
int mask = 1 < < ( offset % 8 ) ;
2014-10-02 09:55:27 +04:00
if ( type & IRQ_TYPE_LEVEL_LOW | | type & IRQ_TYPE_LEVEL_HIGH )
2010-07-02 15:22:09 +04:00
return - EINVAL ;
2011-12-14 07:58:27 +04:00
/* STMPE801 doesn't have RE and FE registers */
if ( stmpe_gpio - > stmpe - > partnum = = STMPE801 )
return 0 ;
2014-10-02 09:55:27 +04:00
if ( type & IRQ_TYPE_EDGE_RISING )
2010-07-02 15:22:09 +04:00
stmpe_gpio - > regs [ REG_RE ] [ regoffset ] | = mask ;
else
stmpe_gpio - > regs [ REG_RE ] [ regoffset ] & = ~ mask ;
2014-10-02 09:55:27 +04:00
if ( type & IRQ_TYPE_EDGE_FALLING )
2010-07-02 15:22:09 +04:00
stmpe_gpio - > regs [ REG_FE ] [ regoffset ] | = mask ;
else
stmpe_gpio - > regs [ REG_FE ] [ regoffset ] & = ~ mask ;
return 0 ;
}
2011-01-13 04:00:17 +03:00
static void stmpe_gpio_irq_lock ( struct irq_data * d )
2010-07-02 15:22:09 +04:00
{
2014-04-16 01:38:56 +04:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( gc ) ;
2010-07-02 15:22:09 +04:00
mutex_lock ( & stmpe_gpio - > irq_lock ) ;
}
2011-01-13 04:00:17 +03:00
static void stmpe_gpio_irq_sync_unlock ( struct irq_data * d )
2010-07-02 15:22:09 +04:00
{
2014-04-16 01:38:56 +04:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( gc ) ;
2010-07-02 15:22:09 +04:00
struct stmpe * stmpe = stmpe_gpio - > stmpe ;
int num_banks = DIV_ROUND_UP ( stmpe - > num_gpios , 8 ) ;
2016-08-10 10:39:12 +03:00
static const u8 regmap [ CACHE_NR_REGS ] [ CACHE_NR_BANKS ] = {
[ REG_RE ] [ LSB ] = STMPE_IDX_GPRER_LSB ,
[ REG_RE ] [ CSB ] = STMPE_IDX_GPRER_CSB ,
[ REG_RE ] [ MSB ] = STMPE_IDX_GPRER_MSB ,
[ REG_FE ] [ LSB ] = STMPE_IDX_GPFER_LSB ,
[ REG_FE ] [ CSB ] = STMPE_IDX_GPFER_CSB ,
[ REG_FE ] [ MSB ] = STMPE_IDX_GPFER_MSB ,
[ REG_IE ] [ LSB ] = STMPE_IDX_IEGPIOR_LSB ,
[ REG_IE ] [ CSB ] = STMPE_IDX_IEGPIOR_CSB ,
[ REG_IE ] [ MSB ] = STMPE_IDX_IEGPIOR_MSB ,
2010-07-02 15:22:09 +04:00
} ;
int i , j ;
for ( i = 0 ; i < CACHE_NR_REGS ; i + + ) {
2011-12-14 07:58:27 +04:00
/* STMPE801 doesn't have RE and FE registers */
if ( ( stmpe - > partnum = = STMPE801 ) & &
( i ! = REG_IE ) )
continue ;
2010-07-02 15:22:09 +04:00
for ( j = 0 ; j < num_banks ; j + + ) {
u8 old = stmpe_gpio - > oldregs [ i ] [ j ] ;
u8 new = stmpe_gpio - > regs [ i ] [ j ] ;
if ( new = = old )
continue ;
stmpe_gpio - > oldregs [ i ] [ j ] = new ;
2016-08-10 10:39:12 +03:00
stmpe_reg_write ( stmpe , stmpe - > regs [ regmap [ i ] [ j ] ] , new ) ;
2010-07-02 15:22:09 +04:00
}
}
mutex_unlock ( & stmpe_gpio - > irq_lock ) ;
}
2011-01-13 04:00:17 +03:00
static void stmpe_gpio_irq_mask ( struct irq_data * d )
2010-07-02 15:22:09 +04:00
{
2014-04-16 01:38:56 +04:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( gc ) ;
2012-12-10 14:07:54 +04:00
int offset = d - > hwirq ;
2010-07-02 15:22:09 +04:00
int regoffset = offset / 8 ;
int mask = 1 < < ( offset % 8 ) ;
stmpe_gpio - > regs [ REG_IE ] [ regoffset ] & = ~ mask ;
}
2011-01-13 04:00:17 +03:00
static void stmpe_gpio_irq_unmask ( struct irq_data * d )
2010-07-02 15:22:09 +04:00
{
2014-04-16 01:38:56 +04:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( gc ) ;
2012-12-10 14:07:54 +04:00
int offset = d - > hwirq ;
2010-07-02 15:22:09 +04:00
int regoffset = offset / 8 ;
int mask = 1 < < ( offset % 8 ) ;
stmpe_gpio - > regs [ REG_IE ] [ regoffset ] | = mask ;
}
2014-10-02 09:55:41 +04:00
static void stmpe_dbg_show_one ( struct seq_file * s ,
struct gpio_chip * gc ,
unsigned offset , unsigned gpio )
{
2015-12-07 16:32:13 +03:00
struct stmpe_gpio * stmpe_gpio = gpiochip_get_data ( gc ) ;
2014-10-02 09:55:41 +04:00
struct stmpe * stmpe = stmpe_gpio - > stmpe ;
const char * label = gpiochip_is_requested ( gc , offset ) ;
bool val = ! ! stmpe_gpio_get ( gc , offset ) ;
2016-08-10 10:39:12 +03:00
u8 bank = offset / 8 ;
u8 dir_reg = stmpe - > regs [ STMPE_IDX_GPDR_LSB + bank ] ;
2014-10-02 09:55:41 +04:00
u8 mask = 1 < < ( offset % 8 ) ;
int ret ;
u8 dir ;
ret = stmpe_reg_read ( stmpe , dir_reg ) ;
if ( ret < 0 )
return ;
dir = ! ! ( ret & mask ) ;
if ( dir ) {
seq_printf ( s , " gpio-%-3d (%-20.20s) out %s " ,
gpio , label ? : " (none) " ,
val ? " hi " : " lo " ) ;
} else {
2016-08-10 10:39:08 +03:00
u8 edge_det_reg ;
u8 rise_reg ;
u8 fall_reg ;
u8 irqen_reg ;
char * edge_det_values [ ] = { " edge-inactive " ,
" edge-asserted " ,
" not-supported " } ;
char * rise_values [ ] = { " no-rising-edge-detection " ,
" rising-edge-detection " ,
" not-supported " } ;
char * fall_values [ ] = { " no-falling-edge-detection " ,
" falling-edge-detection " ,
" not-supported " } ;
# define NOT_SUPPORTED_IDX 2
u8 edge_det = NOT_SUPPORTED_IDX ;
u8 rise = NOT_SUPPORTED_IDX ;
u8 fall = NOT_SUPPORTED_IDX ;
2014-10-02 09:55:41 +04:00
bool irqen ;
2016-08-10 10:39:08 +03:00
switch ( stmpe - > partnum ) {
case STMPE610 :
case STMPE811 :
case STMPE1601 :
case STMPE2401 :
case STMPE2403 :
2016-08-10 10:39:12 +03:00
edge_det_reg = stmpe - > regs [ STMPE_IDX_GPEDR_LSB + bank ] ;
2016-08-10 10:39:08 +03:00
ret = stmpe_reg_read ( stmpe , edge_det_reg ) ;
if ( ret < 0 )
return ;
edge_det = ! ! ( ret & mask ) ;
case STMPE1801 :
2016-08-10 10:39:12 +03:00
rise_reg = stmpe - > regs [ STMPE_IDX_GPRER_LSB + bank ] ;
fall_reg = stmpe - > regs [ STMPE_IDX_GPFER_LSB + bank ] ;
2016-08-10 10:39:08 +03:00
ret = stmpe_reg_read ( stmpe , rise_reg ) ;
if ( ret < 0 )
return ;
rise = ! ! ( ret & mask ) ;
ret = stmpe_reg_read ( stmpe , fall_reg ) ;
if ( ret < 0 )
return ;
fall = ! ! ( ret & mask ) ;
case STMPE801 :
2016-08-10 10:39:12 +03:00
irqen_reg = stmpe - > regs [ STMPE_IDX_IEGPIOR_LSB + bank ] ;
2016-08-10 10:39:08 +03:00
break ;
default :
2014-10-02 09:55:41 +04:00
return ;
2016-08-10 10:39:08 +03:00
}
2014-10-02 09:55:41 +04:00
ret = stmpe_reg_read ( stmpe , irqen_reg ) ;
if ( ret < 0 )
return ;
irqen = ! ! ( ret & mask ) ;
2016-08-10 10:39:08 +03:00
seq_printf ( s , " gpio-%-3d (%-20.20s) in %s %13s %13s %25s %25s " ,
2014-10-02 09:55:41 +04:00
gpio , label ? : " (none) " ,
val ? " hi " : " lo " ,
2016-08-10 10:39:08 +03:00
edge_det_values [ edge_det ] ,
irqen ? " IRQ-enabled " : " IRQ-disabled " ,
rise_values [ rise ] ,
fall_values [ fall ] ) ;
2014-10-02 09:55:41 +04:00
}
}
static void stmpe_dbg_show ( struct seq_file * s , struct gpio_chip * gc )
{
unsigned i ;
unsigned gpio = gc - > base ;
for ( i = 0 ; i < gc - > ngpio ; i + + , gpio + + ) {
stmpe_dbg_show_one ( s , gc , i , gpio ) ;
seq_printf ( s , " \n " ) ;
}
}
2010-07-02 15:22:09 +04:00
static struct irq_chip stmpe_gpio_irq_chip = {
. name = " stmpe-gpio " ,
2011-01-13 04:00:17 +03:00
. irq_bus_lock = stmpe_gpio_irq_lock ,
. irq_bus_sync_unlock = stmpe_gpio_irq_sync_unlock ,
. irq_mask = stmpe_gpio_irq_mask ,
. irq_unmask = stmpe_gpio_irq_unmask ,
. irq_set_type = stmpe_gpio_irq_set_type ,
2010-07-02 15:22:09 +04:00
} ;
static irqreturn_t stmpe_gpio_irq ( int irq , void * dev )
{
struct stmpe_gpio * stmpe_gpio = dev ;
struct stmpe * stmpe = stmpe_gpio - > stmpe ;
u8 statmsbreg = stmpe - > regs [ STMPE_IDX_ISGPIOR_MSB ] ;
int num_banks = DIV_ROUND_UP ( stmpe - > num_gpios , 8 ) ;
u8 status [ num_banks ] ;
int ret ;
int i ;
ret = stmpe_block_read ( stmpe , statmsbreg , num_banks , status ) ;
if ( ret < 0 )
return IRQ_NONE ;
for ( i = 0 ; i < num_banks ; i + + ) {
int bank = num_banks - i - 1 ;
unsigned int enabled = stmpe_gpio - > regs [ REG_IE ] [ bank ] ;
unsigned int stat = status [ i ] ;
stat & = enabled ;
if ( ! stat )
continue ;
while ( stat ) {
int bit = __ffs ( stat ) ;
int line = bank * 8 + bit ;
2014-04-16 01:38:56 +04:00
int child_irq = irq_find_mapping ( stmpe_gpio - > chip . irqdomain ,
2013-10-11 21:51:38 +04:00
line ) ;
2010-07-02 15:22:09 +04:00
2013-10-11 21:51:38 +04:00
handle_nested_irq ( child_irq ) ;
2010-07-02 15:22:09 +04:00
stat & = ~ ( 1 < < bit ) ;
}
2016-08-10 10:39:09 +03:00
/*
* interrupt status register write has no effect on
* 801 and 1801 , bits are cleared when read .
* Edge detect register is not present on 801 and 1801
*/
if ( stmpe - > partnum ! = STMPE801 | | stmpe - > partnum ! = STMPE1801 ) {
stmpe_reg_write ( stmpe , statmsbreg + i , status [ i ] ) ;
2016-08-10 10:39:12 +03:00
stmpe_reg_write ( stmpe ,
stmpe - > regs [ STMPE_IDX_GPEDR_LSB + i ] ,
status [ i ] ) ;
2016-08-10 10:39:09 +03:00
}
2010-07-02 15:22:09 +04:00
}
return IRQ_HANDLED ;
}
2012-11-19 22:22:34 +04:00
static int stmpe_gpio_probe ( struct platform_device * pdev )
2010-07-02 15:22:09 +04:00
{
struct stmpe * stmpe = dev_get_drvdata ( pdev - > dev . parent ) ;
2012-11-26 15:36:51 +04:00
struct device_node * np = pdev - > dev . of_node ;
2010-07-02 15:22:09 +04:00
struct stmpe_gpio * stmpe_gpio ;
int ret ;
2012-01-27 01:17:15 +04:00
int irq = 0 ;
2010-07-02 15:22:09 +04:00
irq = platform_get_irq ( pdev , 0 ) ;
stmpe_gpio = kzalloc ( sizeof ( struct stmpe_gpio ) , GFP_KERNEL ) ;
if ( ! stmpe_gpio )
return - ENOMEM ;
mutex_init ( & stmpe_gpio - > irq_lock ) ;
stmpe_gpio - > dev = & pdev - > dev ;
stmpe_gpio - > stmpe = stmpe ;
stmpe_gpio - > chip = template_chip ;
stmpe_gpio - > chip . ngpio = stmpe - > num_gpios ;
2015-11-04 11:56:26 +03:00
stmpe_gpio - > chip . parent = & pdev - > dev ;
2013-03-18 14:45:05 +04:00
stmpe_gpio - > chip . of_node = np ;
2014-05-09 01:16:34 +04:00
stmpe_gpio - > chip . base = - 1 ;
2010-07-02 15:22:09 +04:00
2014-10-02 09:55:41 +04:00
if ( IS_ENABLED ( CONFIG_DEBUG_FS ) )
stmpe_gpio - > chip . dbg_show = stmpe_dbg_show ;
2015-01-13 10:00:29 +03:00
of_property_read_u32 ( np , " st,norequest-mask " ,
& stmpe_gpio - > norequest_mask ) ;
2012-11-26 15:36:51 +04:00
2014-05-09 01:16:34 +04:00
if ( irq < 0 )
2012-01-27 01:17:15 +04:00
dev_info ( & pdev - > dev ,
2014-04-16 01:38:56 +04:00
" device configured in no-irq mode: "
2012-01-27 01:17:15 +04:00
" irqs are not available \n " ) ;
2010-07-02 15:22:09 +04:00
ret = stmpe_enable ( stmpe , STMPE_BLOCK_GPIO ) ;
if ( ret )
2010-09-12 22:57:19 +04:00
goto out_free ;
2010-07-02 15:22:09 +04:00
2015-12-07 16:32:13 +03:00
ret = gpiochip_add_data ( & stmpe_gpio - > chip , stmpe_gpio ) ;
2014-09-26 16:19:52 +04:00
if ( ret ) {
dev_err ( & pdev - > dev , " unable to add gpiochip: %d \n " , ret ) ;
goto out_disable ;
}
2014-04-16 01:38:56 +04:00
if ( irq > 0 ) {
ret = devm_request_threaded_irq ( & pdev - > dev , irq , NULL ,
stmpe_gpio_irq , IRQF_ONESHOT ,
" stmpe-gpio " , stmpe_gpio ) ;
2012-01-27 01:17:15 +04:00
if ( ret ) {
dev_err ( & pdev - > dev , " unable to get irq: %d \n " , ret ) ;
2012-12-10 14:07:54 +04:00
goto out_disable ;
2012-01-27 01:17:15 +04:00
}
2014-04-16 01:38:56 +04:00
ret = gpiochip_irqchip_add ( & stmpe_gpio - > chip ,
& stmpe_gpio_irq_chip ,
0 ,
handle_simple_irq ,
IRQ_TYPE_NONE ) ;
if ( ret ) {
dev_err ( & pdev - > dev ,
" could not connect irqchip to gpiochip \n " ) ;
2014-09-26 16:19:52 +04:00
goto out_disable ;
2014-04-16 01:38:56 +04:00
}
2010-07-02 15:22:09 +04:00
2014-09-26 16:19:52 +04:00
gpiochip_set_chained_irqchip ( & stmpe_gpio - > chip ,
& stmpe_gpio_irq_chip ,
irq ,
NULL ) ;
2010-07-02 15:22:09 +04:00
}
platform_set_drvdata ( pdev , stmpe_gpio ) ;
return 0 ;
2010-09-12 22:57:19 +04:00
out_disable :
stmpe_disable ( stmpe , STMPE_BLOCK_GPIO ) ;
2014-09-26 16:19:52 +04:00
gpiochip_remove ( & stmpe_gpio - > chip ) ;
2010-07-02 15:22:09 +04:00
out_free :
kfree ( stmpe_gpio ) ;
return ret ;
}
static struct platform_driver stmpe_gpio_driver = {
2016-05-10 02:59:56 +03:00
. driver = {
. suppress_bind_attrs = true ,
. name = " stmpe-gpio " ,
} ,
2010-07-02 15:22:09 +04:00
. probe = stmpe_gpio_probe ,
} ;
static int __init stmpe_gpio_init ( void )
{
return platform_driver_register ( & stmpe_gpio_driver ) ;
}
subsys_initcall ( stmpe_gpio_init ) ;