2010-08-10 18:02:27 -07:00
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2016-04-01 14:49:35 -04:00
*
* Driver for Semtech SX150X I2C GPIO Expanders
*
* Author : Gregory Bean < gbean @ codeaurora . org >
2010-08-10 18:02:27 -07:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 , USA .
*/
# include <linux/gpio.h>
# include <linux/i2c.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/irq.h>
# include <linux/mutex.h>
# include <linux/slab.h>
2015-01-15 08:16:10 +08:00
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/of_irq.h>
# include <linux/of_gpio.h>
# include <linux/of_device.h>
2010-08-10 18:02:27 -07:00
2011-02-14 18:08:51 +01:00
# define NO_UPDATE_PENDING -1
2014-12-04 20:12:09 +08:00
/* The chip models of sx150x */
2015-12-15 23:01:34 +01:00
# define SX150X_123 0
# define SX150X_456 1
# define SX150X_789 2
struct sx150x_123_pri {
u8 reg_pld_mode ;
u8 reg_pld_table0 ;
u8 reg_pld_table1 ;
u8 reg_pld_table2 ;
u8 reg_pld_table3 ;
u8 reg_pld_table4 ;
u8 reg_advance ;
} ;
2014-12-04 20:12:09 +08:00
struct sx150x_456_pri {
u8 reg_pld_mode ;
u8 reg_pld_table0 ;
u8 reg_pld_table1 ;
u8 reg_pld_table2 ;
u8 reg_pld_table3 ;
u8 reg_pld_table4 ;
u8 reg_advance ;
} ;
struct sx150x_789_pri {
u8 reg_drain ;
u8 reg_polarity ;
u8 reg_clock ;
u8 reg_misc ;
u8 reg_reset ;
u8 ngpios ;
} ;
2010-08-10 18:02:27 -07:00
struct sx150x_device_data {
2014-12-04 20:12:09 +08:00
u8 model ;
2010-08-10 18:02:27 -07:00
u8 reg_pullup ;
u8 reg_pulldn ;
u8 reg_dir ;
u8 reg_data ;
u8 reg_irq_mask ;
u8 reg_irq_src ;
u8 reg_sense ;
u8 ngpios ;
2014-12-04 20:12:09 +08:00
union {
2015-12-15 23:01:34 +01:00
struct sx150x_123_pri x123 ;
2014-12-04 20:12:09 +08:00
struct sx150x_456_pri x456 ;
struct sx150x_789_pri x789 ;
} pri ;
2010-08-10 18:02:27 -07:00
} ;
2016-04-09 10:52:26 +02:00
/**
* struct sx150x_platform_data - config data for SX150x driver
* @ gpio_base : The index number of the first GPIO assigned to this
* GPIO expander . The expander will create a block of
* consecutively numbered gpios beginning at the given base ,
* with the size of the block depending on the model of the
* expander chip .
* @ oscio_is_gpo : If set to true , the driver will configure OSCIO as a GPO
* instead of as an oscillator , increasing the size of the
* GP ( I ) O pool created by this expander by one . The
* output - only GPO pin will be added at the end of the block .
* @ io_pullup_ena : A bit - mask which enables or disables the pull - up resistor
* for each IO line in the expander . Setting the bit at
* position n will enable the pull - up for the IO at
* the corresponding offset . For chips with fewer than
* 16 IO pins , high - end bits are ignored .
* @ io_pulldn_ena : A bit - mask which enables - or disables the pull - down
* resistor for each IO line in the expander . Setting the
* bit at position n will enable the pull - down for the IO at
* the corresponding offset . For chips with fewer than
* 16 IO pins , high - end bits are ignored .
* @ io_polarity : A bit - mask which enables polarity inversion for each IO line
* in the expander . Setting the bit at position n inverts
* the polarity of that IO line , while clearing it results
* in normal polarity . For chips with fewer than 16 IO pins ,
* high - end bits are ignored .
* @ irq_summary : The ' summary IRQ ' line to which the GPIO expander ' s INT line
* is connected , via which it reports interrupt events
* across all GPIO lines . This must be a real ,
* pre - existing IRQ line .
* Setting this value < 0 disables the irq_chip functionality
* of the driver .
* @ irq_base : The first ' virtual IRQ ' line at which our block of GPIO - based
* IRQ lines will appear . Similarly to gpio_base , the expander
* will create a block of irqs beginning at this number .
* This value is ignored if irq_summary is < 0.
* @ reset_during_probe : If set to true , the driver will trigger a full
* reset of the chip at the beginning of the probe
* in order to place it in a known state .
*/
struct sx150x_platform_data {
unsigned gpio_base ;
bool oscio_is_gpo ;
u16 io_pullup_ena ;
u16 io_pulldn_ena ;
u16 io_polarity ;
int irq_summary ;
unsigned irq_base ;
bool reset_during_probe ;
} ;
2010-08-10 18:02:27 -07:00
struct sx150x_chip {
struct gpio_chip gpio_chip ;
struct i2c_client * client ;
const struct sx150x_device_data * dev_cfg ;
int irq_summary ;
int irq_base ;
2011-02-14 18:08:51 +01:00
int irq_update ;
2010-08-10 18:02:27 -07:00
u32 irq_sense ;
2011-02-14 18:08:51 +01:00
u32 irq_masked ;
u32 dev_sense ;
u32 dev_masked ;
2010-08-10 18:02:27 -07:00
struct irq_chip irq_chip ;
struct mutex lock ;
} ;
static const struct sx150x_device_data sx150x_devices [ ] = {
[ 0 ] = { /* sx1508q */
2014-12-04 20:12:09 +08:00
. model = SX150X_789 ,
. reg_pullup = 0x03 ,
. reg_pulldn = 0x04 ,
. reg_dir = 0x07 ,
. reg_data = 0x08 ,
. reg_irq_mask = 0x09 ,
. reg_irq_src = 0x0c ,
. reg_sense = 0x0b ,
. pri . x789 = {
. reg_drain = 0x05 ,
. reg_polarity = 0x06 ,
. reg_clock = 0x0f ,
. reg_misc = 0x10 ,
. reg_reset = 0x7d ,
} ,
. ngpios = 8 ,
2010-08-10 18:02:27 -07:00
} ,
[ 1 ] = { /* sx1509q */
2014-12-04 20:12:09 +08:00
. model = SX150X_789 ,
. reg_pullup = 0x07 ,
. reg_pulldn = 0x09 ,
. reg_dir = 0x0f ,
. reg_data = 0x11 ,
. reg_irq_mask = 0x13 ,
. reg_irq_src = 0x19 ,
. reg_sense = 0x17 ,
. pri . x789 = {
. reg_drain = 0x0b ,
. reg_polarity = 0x0d ,
. reg_clock = 0x1e ,
. reg_misc = 0x1f ,
. reg_reset = 0x7d ,
} ,
. ngpios = 16
} ,
[ 2 ] = { /* sx1506q */
. model = SX150X_456 ,
. reg_pullup = 0x05 ,
. reg_pulldn = 0x07 ,
. reg_dir = 0x03 ,
. reg_data = 0x01 ,
. reg_irq_mask = 0x09 ,
. reg_irq_src = 0x0f ,
. reg_sense = 0x0d ,
. pri . x456 = {
. reg_pld_mode = 0x21 ,
. reg_pld_table0 = 0x23 ,
. reg_pld_table1 = 0x25 ,
. reg_pld_table2 = 0x27 ,
. reg_pld_table3 = 0x29 ,
. reg_pld_table4 = 0x2b ,
. reg_advance = 0xad ,
} ,
. ngpios = 16
2010-08-10 18:02:27 -07:00
} ,
2015-12-15 23:01:34 +01:00
[ 3 ] = { /* sx1502q */
. model = SX150X_123 ,
. reg_pullup = 0x02 ,
. reg_pulldn = 0x03 ,
. reg_dir = 0x01 ,
. reg_data = 0x00 ,
. reg_irq_mask = 0x05 ,
. reg_irq_src = 0x08 ,
. reg_sense = 0x07 ,
. pri . x123 = {
. reg_pld_mode = 0x10 ,
. reg_pld_table0 = 0x11 ,
. reg_pld_table1 = 0x12 ,
. reg_pld_table2 = 0x13 ,
. reg_pld_table3 = 0x14 ,
. reg_pld_table4 = 0x15 ,
. reg_advance = 0xad ,
} ,
. ngpios = 8 ,
} ,
2010-08-10 18:02:27 -07:00
} ;
static const struct i2c_device_id sx150x_id [ ] = {
{ " sx1508q " , 0 } ,
{ " sx1509q " , 1 } ,
2014-12-04 20:12:09 +08:00
{ " sx1506q " , 2 } ,
2015-12-15 23:01:34 +01:00
{ " sx1502q " , 3 } ,
2010-08-10 18:02:27 -07:00
{ }
} ;
2015-01-22 09:45:24 +01:00
static const struct of_device_id sx150x_of_match [ ] = {
2015-01-15 08:16:10 +08:00
{ . compatible = " semtech,sx1508q " } ,
{ . compatible = " semtech,sx1509q " } ,
{ . compatible = " semtech,sx1506q " } ,
2015-12-15 23:01:34 +01:00
{ . compatible = " semtech,sx1502q " } ,
2015-01-15 08:16:10 +08:00
{ } ,
} ;
2010-08-10 18:02:27 -07:00
static s32 sx150x_i2c_write ( struct i2c_client * client , u8 reg , u8 val )
{
s32 err = i2c_smbus_write_byte_data ( client , reg , val ) ;
if ( err < 0 )
dev_warn ( & client - > dev ,
" i2c write fail: can't write %02x to %02x: %d \n " ,
val , reg , err ) ;
return err ;
}
static s32 sx150x_i2c_read ( struct i2c_client * client , u8 reg , u8 * val )
{
s32 err = i2c_smbus_read_byte_data ( client , reg ) ;
if ( err > = 0 )
* val = err ;
else
dev_warn ( & client - > dev ,
" i2c read fail: can't read from %02x: %d \n " ,
reg , err ) ;
return err ;
}
static inline bool offset_is_oscio ( struct sx150x_chip * chip , unsigned offset )
{
return ( chip - > dev_cfg - > ngpios = = offset ) ;
}
/*
* These utility functions solve the common problem of locating and setting
* configuration bits . Configuration bits are grouped into registers
* whose indexes increase downwards . For example , with eight - bit registers ,
* sixteen gpios would have their config bits grouped in the following order :
* REGISTER N - 1 [ f e d c b a 9 8 ]
* N [ 7 6 5 4 3 2 1 0 ]
*
* For multi - bit configurations , the pattern gets wider :
* REGISTER N - 3 [ f f e e d d c c ]
* N - 2 [ b b a a 9 9 8 8 ]
* N - 1 [ 7 7 6 6 5 5 4 4 ]
* N [ 3 3 2 2 1 1 0 0 ]
*
* Given the address of the starting register ' N ' , the index of the gpio
* whose configuration we seek to change , and the width in bits of that
* configuration , these functions allow us to locate the correct
* register and mask the correct bits .
*/
static inline void sx150x_find_cfg ( u8 offset , u8 width ,
u8 * reg , u8 * mask , u8 * shift )
{
* reg - = offset * width / 8 ;
* mask = ( 1 < < width ) - 1 ;
* shift = ( offset * width ) % 8 ;
* mask < < = * shift ;
}
static s32 sx150x_write_cfg ( struct sx150x_chip * chip ,
u8 offset , u8 width , u8 reg , u8 val )
{
u8 mask ;
u8 data ;
u8 shift ;
s32 err ;
sx150x_find_cfg ( offset , width , & reg , & mask , & shift ) ;
err = sx150x_i2c_read ( chip - > client , reg , & data ) ;
if ( err < 0 )
return err ;
data & = ~ mask ;
data | = ( val < < shift ) & mask ;
return sx150x_i2c_write ( chip - > client , reg , data ) ;
}
static int sx150x_get_io ( struct sx150x_chip * chip , unsigned offset )
{
u8 reg = chip - > dev_cfg - > reg_data ;
u8 mask ;
u8 data ;
u8 shift ;
s32 err ;
sx150x_find_cfg ( offset , 1 , & reg , & mask , & shift ) ;
err = sx150x_i2c_read ( chip - > client , reg , & data ) ;
if ( err > = 0 )
err = ( data & mask ) ! = 0 ? 1 : 0 ;
return err ;
}
static void sx150x_set_oscio ( struct sx150x_chip * chip , int val )
{
sx150x_i2c_write ( chip - > client ,
2014-12-04 20:12:09 +08:00
chip - > dev_cfg - > pri . x789 . reg_clock ,
2010-08-10 18:02:27 -07:00
( val ? 0x1f : 0x10 ) ) ;
}
static void sx150x_set_io ( struct sx150x_chip * chip , unsigned offset , int val )
{
sx150x_write_cfg ( chip ,
offset ,
1 ,
chip - > dev_cfg - > reg_data ,
( val ? 1 : 0 ) ) ;
}
static int sx150x_io_input ( struct sx150x_chip * chip , unsigned offset )
{
return sx150x_write_cfg ( chip ,
offset ,
1 ,
chip - > dev_cfg - > reg_dir ,
1 ) ;
}
static int sx150x_io_output ( struct sx150x_chip * chip , unsigned offset , int val )
{
int err ;
err = sx150x_write_cfg ( chip ,
offset ,
1 ,
chip - > dev_cfg - > reg_data ,
( val ? 1 : 0 ) ) ;
if ( err > = 0 )
err = sx150x_write_cfg ( chip ,
offset ,
1 ,
chip - > dev_cfg - > reg_dir ,
0 ) ;
return err ;
}
static int sx150x_gpio_get ( struct gpio_chip * gc , unsigned offset )
{
2015-12-07 14:36:31 +01:00
struct sx150x_chip * chip = gpiochip_get_data ( gc ) ;
2010-08-10 18:02:27 -07:00
int status = - EINVAL ;
if ( ! offset_is_oscio ( chip , offset ) ) {
mutex_lock ( & chip - > lock ) ;
status = sx150x_get_io ( chip , offset ) ;
mutex_unlock ( & chip - > lock ) ;
}
2015-12-21 11:41:06 +01:00
return ( status < 0 ) ? status : ! ! status ;
2010-08-10 18:02:27 -07:00
}
static void sx150x_gpio_set ( struct gpio_chip * gc , unsigned offset , int val )
{
2015-12-07 14:36:31 +01:00
struct sx150x_chip * chip = gpiochip_get_data ( gc ) ;
2010-08-10 18:02:27 -07:00
mutex_lock ( & chip - > lock ) ;
if ( offset_is_oscio ( chip , offset ) )
sx150x_set_oscio ( chip , val ) ;
else
sx150x_set_io ( chip , offset , val ) ;
mutex_unlock ( & chip - > lock ) ;
}
2016-04-09 13:13:36 +02:00
static int sx150x_gpio_set_single_ended ( struct gpio_chip * gc ,
unsigned offset ,
enum single_ended_mode mode )
{
struct sx150x_chip * chip = gpiochip_get_data ( gc ) ;
/* On the SX160X 789 we can set open drain */
if ( chip - > dev_cfg - > model ! = SX150X_789 )
return - ENOTSUPP ;
if ( mode = = LINE_MODE_PUSH_PULL )
return sx150x_write_cfg ( chip ,
offset ,
1 ,
chip - > dev_cfg - > pri . x789 . reg_drain ,
0 ) ;
if ( mode = = LINE_MODE_OPEN_DRAIN )
return sx150x_write_cfg ( chip ,
offset ,
1 ,
chip - > dev_cfg - > pri . x789 . reg_drain ,
1 ) ;
return - ENOTSUPP ;
}
2010-08-10 18:02:27 -07:00
static int sx150x_gpio_direction_input ( struct gpio_chip * gc , unsigned offset )
{
2015-12-07 14:36:31 +01:00
struct sx150x_chip * chip = gpiochip_get_data ( gc ) ;
2010-08-10 18:02:27 -07:00
int status = - EINVAL ;
if ( ! offset_is_oscio ( chip , offset ) ) {
mutex_lock ( & chip - > lock ) ;
status = sx150x_io_input ( chip , offset ) ;
mutex_unlock ( & chip - > lock ) ;
}
return status ;
}
static int sx150x_gpio_direction_output ( struct gpio_chip * gc ,
unsigned offset ,
int val )
{
2015-12-07 14:36:31 +01:00
struct sx150x_chip * chip = gpiochip_get_data ( gc ) ;
2010-08-10 18:02:27 -07:00
int status = 0 ;
if ( ! offset_is_oscio ( chip , offset ) ) {
mutex_lock ( & chip - > lock ) ;
status = sx150x_io_output ( chip , offset , val ) ;
mutex_unlock ( & chip - > lock ) ;
}
return status ;
}
2011-01-12 17:00:18 -08:00
static void sx150x_irq_mask ( struct irq_data * d )
2010-08-10 18:02:27 -07:00
{
2015-12-07 14:36:31 +01:00
struct sx150x_chip * chip = gpiochip_get_data ( irq_data_get_irq_chip_data ( d ) ) ;
2014-12-04 20:12:08 +08:00
unsigned n = d - > hwirq ;
2010-08-10 18:02:27 -07:00
2011-02-14 18:08:51 +01:00
chip - > irq_masked | = ( 1 < < n ) ;
chip - > irq_update = n ;
2010-08-10 18:02:27 -07:00
}
2011-01-12 17:00:18 -08:00
static void sx150x_irq_unmask ( struct irq_data * d )
2010-08-10 18:02:27 -07:00
{
2015-12-07 14:36:31 +01:00
struct sx150x_chip * chip = gpiochip_get_data ( irq_data_get_irq_chip_data ( d ) ) ;
2014-12-04 20:12:08 +08:00
unsigned n = d - > hwirq ;
2010-08-10 18:02:27 -07:00
2011-02-14 18:08:51 +01:00
chip - > irq_masked & = ~ ( 1 < < n ) ;
chip - > irq_update = n ;
2010-08-10 18:02:27 -07:00
}
2011-01-12 17:00:18 -08:00
static int sx150x_irq_set_type ( struct irq_data * d , unsigned int flow_type )
2010-08-10 18:02:27 -07:00
{
2015-12-07 14:36:31 +01:00
struct sx150x_chip * chip = gpiochip_get_data ( irq_data_get_irq_chip_data ( d ) ) ;
2010-08-10 18:02:27 -07:00
unsigned n , val = 0 ;
if ( flow_type & ( IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW ) )
return - EINVAL ;
2014-12-04 20:12:08 +08:00
n = d - > hwirq ;
2010-08-10 18:02:27 -07:00
if ( flow_type & IRQ_TYPE_EDGE_RISING )
val | = 0x1 ;
if ( flow_type & IRQ_TYPE_EDGE_FALLING )
val | = 0x2 ;
chip - > irq_sense & = ~ ( 3UL < < ( n * 2 ) ) ;
chip - > irq_sense | = val < < ( n * 2 ) ;
2011-02-14 18:08:51 +01:00
chip - > irq_update = n ;
2010-08-10 18:02:27 -07:00
return 0 ;
}
static irqreturn_t sx150x_irq_thread_fn ( int irq , void * dev_id )
{
struct sx150x_chip * chip = ( struct sx150x_chip * ) dev_id ;
unsigned nhandled = 0 ;
unsigned sub_irq ;
unsigned n ;
s32 err ;
u8 val ;
int i ;
for ( i = ( chip - > dev_cfg - > ngpios / 8 ) - 1 ; i > = 0 ; - - i ) {
err = sx150x_i2c_read ( chip - > client ,
chip - > dev_cfg - > reg_irq_src - i ,
& val ) ;
if ( err < 0 )
continue ;
sx150x_i2c_write ( chip - > client ,
chip - > dev_cfg - > reg_irq_src - i ,
val ) ;
for ( n = 0 ; n < 8 ; + + n ) {
if ( val & ( 1 < < n ) ) {
2014-12-04 20:12:08 +08:00
sub_irq = irq_find_mapping (
chip - > gpio_chip . irqdomain ,
( i * 8 ) + n ) ;
2010-08-10 18:02:27 -07:00
handle_nested_irq ( sub_irq ) ;
+ + nhandled ;
}
}
}
return ( nhandled > 0 ? IRQ_HANDLED : IRQ_NONE ) ;
}
2011-01-12 17:00:18 -08:00
static void sx150x_irq_bus_lock ( struct irq_data * d )
2010-08-10 18:02:27 -07:00
{
2015-12-07 14:36:31 +01:00
struct sx150x_chip * chip = gpiochip_get_data ( irq_data_get_irq_chip_data ( d ) ) ;
2010-08-10 18:02:27 -07:00
mutex_lock ( & chip - > lock ) ;
}
2011-01-12 17:00:18 -08:00
static void sx150x_irq_bus_sync_unlock ( struct irq_data * d )
2010-08-10 18:02:27 -07:00
{
2015-12-07 14:36:31 +01:00
struct sx150x_chip * chip = gpiochip_get_data ( irq_data_get_irq_chip_data ( d ) ) ;
2010-08-10 18:02:27 -07:00
unsigned n ;
2011-02-14 18:08:51 +01:00
if ( chip - > irq_update = = NO_UPDATE_PENDING )
goto out ;
n = chip - > irq_update ;
chip - > irq_update = NO_UPDATE_PENDING ;
2010-08-10 18:02:27 -07:00
2011-02-14 18:08:51 +01:00
/* Avoid updates if nothing changed */
if ( chip - > dev_sense = = chip - > irq_sense & &
2014-12-16 14:22:27 +08:00
chip - > dev_masked = = chip - > irq_masked )
2011-02-14 18:08:51 +01:00
goto out ;
chip - > dev_sense = chip - > irq_sense ;
chip - > dev_masked = chip - > irq_masked ;
if ( chip - > irq_masked & ( 1 < < n ) ) {
sx150x_write_cfg ( chip , n , 1 , chip - > dev_cfg - > reg_irq_mask , 1 ) ;
sx150x_write_cfg ( chip , n , 2 , chip - > dev_cfg - > reg_sense , 0 ) ;
} else {
sx150x_write_cfg ( chip , n , 1 , chip - > dev_cfg - > reg_irq_mask , 0 ) ;
sx150x_write_cfg ( chip , n , 2 , chip - > dev_cfg - > reg_sense ,
chip - > irq_sense > > ( n * 2 ) ) ;
}
out :
2010-08-10 18:02:27 -07:00
mutex_unlock ( & chip - > lock ) ;
}
static void sx150x_init_chip ( struct sx150x_chip * chip ,
struct i2c_client * client ,
kernel_ulong_t driver_data ,
struct sx150x_platform_data * pdata )
{
mutex_init ( & chip - > lock ) ;
chip - > client = client ;
chip - > dev_cfg = & sx150x_devices [ driver_data ] ;
2015-11-04 09:56:26 +01:00
chip - > gpio_chip . parent = & client - > dev ;
2010-08-10 18:02:27 -07:00
chip - > gpio_chip . label = client - > name ;
chip - > gpio_chip . direction_input = sx150x_gpio_direction_input ;
chip - > gpio_chip . direction_output = sx150x_gpio_direction_output ;
chip - > gpio_chip . get = sx150x_gpio_get ;
chip - > gpio_chip . set = sx150x_gpio_set ;
2016-04-09 13:13:36 +02:00
chip - > gpio_chip . set_single_ended = sx150x_gpio_set_single_ended ;
2010-08-10 18:02:27 -07:00
chip - > gpio_chip . base = pdata - > gpio_base ;
2013-12-04 14:42:46 +01:00
chip - > gpio_chip . can_sleep = true ;
2010-08-10 18:02:27 -07:00
chip - > gpio_chip . ngpio = chip - > dev_cfg - > ngpios ;
2015-01-22 09:45:24 +01:00
# ifdef CONFIG_OF_GPIO
2015-01-15 08:16:10 +08:00
chip - > gpio_chip . of_node = client - > dev . of_node ;
chip - > gpio_chip . of_gpio_n_cells = 2 ;
2015-01-22 09:45:24 +01:00
# endif
2010-08-10 18:02:27 -07:00
if ( pdata - > oscio_is_gpo )
+ + chip - > gpio_chip . ngpio ;
2011-01-12 17:00:18 -08:00
chip - > irq_chip . name = client - > name ;
chip - > irq_chip . irq_mask = sx150x_irq_mask ;
chip - > irq_chip . irq_unmask = sx150x_irq_unmask ;
chip - > irq_chip . irq_set_type = sx150x_irq_set_type ;
chip - > irq_chip . irq_bus_lock = sx150x_irq_bus_lock ;
chip - > irq_chip . irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock ;
chip - > irq_summary = - 1 ;
chip - > irq_base = - 1 ;
2011-02-14 18:08:51 +01:00
chip - > irq_masked = ~ 0 ;
2011-01-12 17:00:18 -08:00
chip - > irq_sense = 0 ;
2011-02-14 18:08:51 +01:00
chip - > dev_masked = ~ 0 ;
chip - > dev_sense = 0 ;
chip - > irq_update = NO_UPDATE_PENDING ;
2010-08-10 18:02:27 -07:00
}
static int sx150x_init_io ( struct sx150x_chip * chip , u8 base , u16 cfg )
{
int err = 0 ;
unsigned n ;
for ( n = 0 ; err > = 0 & & n < ( chip - > dev_cfg - > ngpios / 8 ) ; + + n )
err = sx150x_i2c_write ( chip - > client , base - n , cfg > > ( n * 8 ) ) ;
return err ;
}
gpio: sx150x: correct and refine reset-on-probe behavior
Replace the arbitrary software-reset call from the device-probe
method, because:
- It is defective. To work correctly, it should be two byte writes,
not a single word write. As it stands, it does nothing.
- Some devices with sx150x expanders installed have their NRESET pins
ganged on the same line, so resetting one causes the others to reset -
not a nice thing to do arbitrarily!
- The probe, usually taking place at boot, implies a recent hard-reset,
so a software reset at this point is just a waste of energy anyway.
Therefore, make it optional, defaulting to off, as this will match the
common case of probing at powerup and also matches the current broken
no-op behavior.
Signed-off-by: Gregory Bean <gbean@codeaurora.org>
Reviewed-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-09 16:38:02 -07:00
static int sx150x_reset ( struct sx150x_chip * chip )
2010-08-10 18:02:27 -07:00
{
gpio: sx150x: correct and refine reset-on-probe behavior
Replace the arbitrary software-reset call from the device-probe
method, because:
- It is defective. To work correctly, it should be two byte writes,
not a single word write. As it stands, it does nothing.
- Some devices with sx150x expanders installed have their NRESET pins
ganged on the same line, so resetting one causes the others to reset -
not a nice thing to do arbitrarily!
- The probe, usually taking place at boot, implies a recent hard-reset,
so a software reset at this point is just a waste of energy anyway.
Therefore, make it optional, defaulting to off, as this will match the
common case of probing at powerup and also matches the current broken
no-op behavior.
Signed-off-by: Gregory Bean <gbean@codeaurora.org>
Reviewed-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-09 16:38:02 -07:00
int err ;
2010-08-10 18:02:27 -07:00
gpio: sx150x: correct and refine reset-on-probe behavior
Replace the arbitrary software-reset call from the device-probe
method, because:
- It is defective. To work correctly, it should be two byte writes,
not a single word write. As it stands, it does nothing.
- Some devices with sx150x expanders installed have their NRESET pins
ganged on the same line, so resetting one causes the others to reset -
not a nice thing to do arbitrarily!
- The probe, usually taking place at boot, implies a recent hard-reset,
so a software reset at this point is just a waste of energy anyway.
Therefore, make it optional, defaulting to off, as this will match the
common case of probing at powerup and also matches the current broken
no-op behavior.
Signed-off-by: Gregory Bean <gbean@codeaurora.org>
Reviewed-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-09 16:38:02 -07:00
err = i2c_smbus_write_byte_data ( chip - > client ,
2014-12-04 20:12:09 +08:00
chip - > dev_cfg - > pri . x789 . reg_reset ,
gpio: sx150x: correct and refine reset-on-probe behavior
Replace the arbitrary software-reset call from the device-probe
method, because:
- It is defective. To work correctly, it should be two byte writes,
not a single word write. As it stands, it does nothing.
- Some devices with sx150x expanders installed have their NRESET pins
ganged on the same line, so resetting one causes the others to reset -
not a nice thing to do arbitrarily!
- The probe, usually taking place at boot, implies a recent hard-reset,
so a software reset at this point is just a waste of energy anyway.
Therefore, make it optional, defaulting to off, as this will match the
common case of probing at powerup and also matches the current broken
no-op behavior.
Signed-off-by: Gregory Bean <gbean@codeaurora.org>
Reviewed-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-09 16:38:02 -07:00
0x12 ) ;
2010-08-10 18:02:27 -07:00
if ( err < 0 )
return err ;
gpio: sx150x: correct and refine reset-on-probe behavior
Replace the arbitrary software-reset call from the device-probe
method, because:
- It is defective. To work correctly, it should be two byte writes,
not a single word write. As it stands, it does nothing.
- Some devices with sx150x expanders installed have their NRESET pins
ganged on the same line, so resetting one causes the others to reset -
not a nice thing to do arbitrarily!
- The probe, usually taking place at boot, implies a recent hard-reset,
so a software reset at this point is just a waste of energy anyway.
Therefore, make it optional, defaulting to off, as this will match the
common case of probing at powerup and also matches the current broken
no-op behavior.
Signed-off-by: Gregory Bean <gbean@codeaurora.org>
Reviewed-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-09 16:38:02 -07:00
err = i2c_smbus_write_byte_data ( chip - > client ,
2014-12-04 20:12:09 +08:00
chip - > dev_cfg - > pri . x789 . reg_reset ,
gpio: sx150x: correct and refine reset-on-probe behavior
Replace the arbitrary software-reset call from the device-probe
method, because:
- It is defective. To work correctly, it should be two byte writes,
not a single word write. As it stands, it does nothing.
- Some devices with sx150x expanders installed have their NRESET pins
ganged on the same line, so resetting one causes the others to reset -
not a nice thing to do arbitrarily!
- The probe, usually taking place at boot, implies a recent hard-reset,
so a software reset at this point is just a waste of energy anyway.
Therefore, make it optional, defaulting to off, as this will match the
common case of probing at powerup and also matches the current broken
no-op behavior.
Signed-off-by: Gregory Bean <gbean@codeaurora.org>
Reviewed-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-09 16:38:02 -07:00
0x34 ) ;
return err ;
}
static int sx150x_init_hw ( struct sx150x_chip * chip ,
struct sx150x_platform_data * pdata )
{
int err = 0 ;
if ( pdata - > reset_during_probe ) {
err = sx150x_reset ( chip ) ;
if ( err < 0 )
return err ;
}
2014-12-04 20:12:09 +08:00
if ( chip - > dev_cfg - > model = = SX150X_789 )
err = sx150x_i2c_write ( chip - > client ,
chip - > dev_cfg - > pri . x789 . reg_misc ,
0x01 ) ;
2015-12-15 23:01:34 +01:00
else if ( chip - > dev_cfg - > model = = SX150X_456 )
2014-12-04 20:12:09 +08:00
err = sx150x_i2c_write ( chip - > client ,
chip - > dev_cfg - > pri . x456 . reg_advance ,
0x04 ) ;
2015-12-15 23:01:34 +01:00
else
err = sx150x_i2c_write ( chip - > client ,
chip - > dev_cfg - > pri . x123 . reg_advance ,
0x00 ) ;
2010-08-10 18:02:27 -07:00
if ( err < 0 )
return err ;
err = sx150x_init_io ( chip , chip - > dev_cfg - > reg_pullup ,
pdata - > io_pullup_ena ) ;
if ( err < 0 )
return err ;
err = sx150x_init_io ( chip , chip - > dev_cfg - > reg_pulldn ,
pdata - > io_pulldn_ena ) ;
if ( err < 0 )
return err ;
2014-12-04 20:12:09 +08:00
if ( chip - > dev_cfg - > model = = SX150X_789 ) {
err = sx150x_init_io ( chip ,
chip - > dev_cfg - > pri . x789 . reg_polarity ,
pdata - > io_polarity ) ;
if ( err < 0 )
return err ;
2015-12-15 23:01:34 +01:00
} else if ( chip - > dev_cfg - > model = = SX150X_456 ) {
2014-12-04 20:12:09 +08:00
/* Set all pins to work in normal mode */
err = sx150x_init_io ( chip ,
chip - > dev_cfg - > pri . x456 . reg_pld_mode ,
0 ) ;
if ( err < 0 )
return err ;
2015-12-15 23:01:34 +01:00
} else {
/* Set all pins to work in normal mode */
err = sx150x_init_io ( chip ,
chip - > dev_cfg - > pri . x123 . reg_pld_mode ,
0 ) ;
if ( err < 0 )
return err ;
2014-12-04 20:12:09 +08:00
}
2010-08-10 18:02:27 -07:00
if ( pdata - > oscio_is_gpo )
sx150x_set_oscio ( chip , 0 ) ;
return err ;
}
static int sx150x_install_irq_chip ( struct sx150x_chip * chip ,
int irq_summary ,
int irq_base )
{
int err ;
chip - > irq_summary = irq_summary ;
chip - > irq_base = irq_base ;
2014-12-04 20:12:08 +08:00
/* Add gpio chip to irq subsystem */
err = gpiochip_irqchip_add ( & chip - > gpio_chip ,
& chip - > irq_chip , chip - > irq_base ,
handle_edge_irq , IRQ_TYPE_EDGE_BOTH ) ;
if ( err ) {
dev_err ( & chip - > client - > dev ,
" could not connect irqchip to gpiochip \n " ) ;
return err ;
2010-08-10 18:02:27 -07:00
}
2013-05-28 15:02:50 -07:00
err = devm_request_threaded_irq ( & chip - > client - > dev ,
2014-12-04 20:12:08 +08:00
irq_summary , NULL , sx150x_irq_thread_fn ,
IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_FALLING ,
chip - > irq_chip . name , chip ) ;
2010-08-10 18:02:27 -07:00
if ( err < 0 ) {
chip - > irq_summary = - 1 ;
chip - > irq_base = - 1 ;
}
return err ;
}
2012-11-19 13:22:34 -05:00
static int sx150x_probe ( struct i2c_client * client ,
2010-08-10 18:02:27 -07:00
const struct i2c_device_id * id )
{
static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WRITE_WORD_DATA ;
struct sx150x_platform_data * pdata ;
struct sx150x_chip * chip ;
int rc ;
2013-07-30 17:08:05 +09:00
pdata = dev_get_platdata ( & client - > dev ) ;
2010-08-10 18:02:27 -07:00
if ( ! pdata )
return - EINVAL ;
if ( ! i2c_check_functionality ( client - > adapter , i2c_funcs ) )
return - ENOSYS ;
2013-05-28 15:02:50 -07:00
chip = devm_kzalloc ( & client - > dev ,
sizeof ( struct sx150x_chip ) , GFP_KERNEL ) ;
2010-08-10 18:02:27 -07:00
if ( ! chip )
return - ENOMEM ;
sx150x_init_chip ( chip , client , id - > driver_data , pdata ) ;
rc = sx150x_init_hw ( chip , pdata ) ;
if ( rc < 0 )
2013-05-28 15:02:50 -07:00
return rc ;
2010-08-10 18:02:27 -07:00
2016-02-22 17:43:28 +05:30
rc = devm_gpiochip_add_data ( & client - > dev , & chip - > gpio_chip , chip ) ;
2013-05-28 15:02:50 -07:00
if ( rc )
return rc ;
2010-08-10 18:02:27 -07:00
if ( pdata - > irq_summary > = 0 ) {
rc = sx150x_install_irq_chip ( chip ,
pdata - > irq_summary ,
pdata - > irq_base ) ;
if ( rc < 0 )
2016-02-22 17:43:28 +05:30
return rc ;
2010-08-10 18:02:27 -07:00
}
i2c_set_clientdata ( client , chip ) ;
return 0 ;
}
static struct i2c_driver sx150x_driver = {
. driver = {
. name = " sx150x " ,
2015-01-22 09:45:24 +01:00
. of_match_table = of_match_ptr ( sx150x_of_match ) ,
2010-08-10 18:02:27 -07:00
} ,
. probe = sx150x_probe ,
. id_table = sx150x_id ,
} ;
static int __init sx150x_init ( void )
{
return i2c_add_driver ( & sx150x_driver ) ;
}
subsys_initcall ( sx150x_init ) ;