2008-02-05 09:28:24 +03:00
/*
2011-06-05 04:38:28 +04:00
* Driver for pcf857x , pca857x , and pca967x I2C GPIO expanders
2008-02-05 09:28:24 +03:00
*
* Copyright ( C ) 2007 David Brownell
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* 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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/kernel.h>
# include <linux/slab.h>
2009-09-23 03:46:37 +04:00
# include <linux/gpio.h>
2008-02-05 09:28:24 +03:00
# include <linux/i2c.h>
# include <linux/i2c/pcf857x.h>
2011-07-03 21:38:09 +04:00
# include <linux/module.h>
2008-02-05 09:28:24 +03:00
2008-04-30 01:11:40 +04:00
static const struct i2c_device_id pcf857x_id [ ] = {
{ " pcf8574 " , 8 } ,
2009-09-19 00:45:47 +04:00
{ " pcf8574a " , 8 } ,
2008-04-30 01:11:40 +04:00
{ " pca8574 " , 8 } ,
{ " pca9670 " , 8 } ,
{ " pca9672 " , 8 } ,
{ " pca9674 " , 8 } ,
{ " pcf8575 " , 16 } ,
{ " pca8575 " , 16 } ,
{ " pca9671 " , 16 } ,
{ " pca9673 " , 16 } ,
{ " pca9675 " , 16 } ,
2008-07-22 01:21:34 +04:00
{ " max7328 " , 8 } ,
{ " max7329 " , 8 } ,
2008-04-30 01:11:40 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , pcf857x_id ) ;
2008-02-05 09:28:24 +03:00
/*
* The pcf857x , pca857x , and pca967x chips only expose one read and one
* write register . Writing a " one " bit ( to match the reset state ) lets
* that pin be used as an input ; it ' s not an open - drain model , but acts
* a bit like one . This is described as " quasi-bidirectional " ; read the
* chip documentation for details .
*
* Many other I2C GPIO expander chips ( like the pca953x models ) have
* more complex register models and more conventional circuitry using
* push / pull drivers . They often use the same 0x20 . .0 x27 addresses as
* pcf857x parts , making the " legacy " I2C driver model problematic .
*/
struct pcf857x {
struct gpio_chip chip ;
struct i2c_client * client ;
2008-07-22 01:21:34 +04:00
struct mutex lock ; /* protect 'out' */
2008-02-05 09:28:24 +03:00
unsigned out ; /* software latch */
} ;
/*-------------------------------------------------------------------------*/
/* Talk to 8-bit I/O expander */
static int pcf857x_input8 ( struct gpio_chip * chip , unsigned offset )
{
struct pcf857x * gpio = container_of ( chip , struct pcf857x , chip ) ;
2008-07-22 01:21:34 +04:00
int status ;
2008-02-05 09:28:24 +03:00
2008-07-22 01:21:34 +04:00
mutex_lock ( & gpio - > lock ) ;
2008-02-05 09:28:24 +03:00
gpio - > out | = ( 1 < < offset ) ;
2008-07-22 01:21:34 +04:00
status = i2c_smbus_write_byte ( gpio - > client , gpio - > out ) ;
mutex_unlock ( & gpio - > lock ) ;
return status ;
2008-02-05 09:28:24 +03:00
}
static int pcf857x_get8 ( struct gpio_chip * chip , unsigned offset )
{
struct pcf857x * gpio = container_of ( chip , struct pcf857x , chip ) ;
s32 value ;
value = i2c_smbus_read_byte ( gpio - > client ) ;
return ( value < 0 ) ? 0 : ( value & ( 1 < < offset ) ) ;
}
static int pcf857x_output8 ( struct gpio_chip * chip , unsigned offset , int value )
{
struct pcf857x * gpio = container_of ( chip , struct pcf857x , chip ) ;
unsigned bit = 1 < < offset ;
2008-07-22 01:21:34 +04:00
int status ;
2008-02-05 09:28:24 +03:00
2008-07-22 01:21:34 +04:00
mutex_lock ( & gpio - > lock ) ;
2008-02-05 09:28:24 +03:00
if ( value )
gpio - > out | = bit ;
else
gpio - > out & = ~ bit ;
2008-07-22 01:21:34 +04:00
status = i2c_smbus_write_byte ( gpio - > client , gpio - > out ) ;
mutex_unlock ( & gpio - > lock ) ;
return status ;
2008-02-05 09:28:24 +03:00
}
static void pcf857x_set8 ( struct gpio_chip * chip , unsigned offset , int value )
{
pcf857x_output8 ( chip , offset , value ) ;
}
/*-------------------------------------------------------------------------*/
/* Talk to 16-bit I/O expander */
static int i2c_write_le16 ( struct i2c_client * client , u16 word )
{
u8 buf [ 2 ] = { word & 0xff , word > > 8 , } ;
int status ;
status = i2c_master_send ( client , buf , 2 ) ;
return ( status < 0 ) ? status : 0 ;
}
static int i2c_read_le16 ( struct i2c_client * client )
{
u8 buf [ 2 ] ;
int status ;
status = i2c_master_recv ( client , buf , 2 ) ;
if ( status < 0 )
return status ;
return ( buf [ 1 ] < < 8 ) | buf [ 0 ] ;
}
static int pcf857x_input16 ( struct gpio_chip * chip , unsigned offset )
{
struct pcf857x * gpio = container_of ( chip , struct pcf857x , chip ) ;
2008-07-22 01:21:34 +04:00
int status ;
2008-02-05 09:28:24 +03:00
2008-07-22 01:21:34 +04:00
mutex_lock ( & gpio - > lock ) ;
2008-02-05 09:28:24 +03:00
gpio - > out | = ( 1 < < offset ) ;
2008-07-22 01:21:34 +04:00
status = i2c_write_le16 ( gpio - > client , gpio - > out ) ;
mutex_unlock ( & gpio - > lock ) ;
return status ;
2008-02-05 09:28:24 +03:00
}
static int pcf857x_get16 ( struct gpio_chip * chip , unsigned offset )
{
struct pcf857x * gpio = container_of ( chip , struct pcf857x , chip ) ;
int value ;
value = i2c_read_le16 ( gpio - > client ) ;
return ( value < 0 ) ? 0 : ( value & ( 1 < < offset ) ) ;
}
static int pcf857x_output16 ( struct gpio_chip * chip , unsigned offset , int value )
{
struct pcf857x * gpio = container_of ( chip , struct pcf857x , chip ) ;
unsigned bit = 1 < < offset ;
2008-07-22 01:21:34 +04:00
int status ;
2008-02-05 09:28:24 +03:00
2008-07-22 01:21:34 +04:00
mutex_lock ( & gpio - > lock ) ;
2008-02-05 09:28:24 +03:00
if ( value )
gpio - > out | = bit ;
else
gpio - > out & = ~ bit ;
2008-07-22 01:21:34 +04:00
status = i2c_write_le16 ( gpio - > client , gpio - > out ) ;
mutex_unlock ( & gpio - > lock ) ;
return status ;
2008-02-05 09:28:24 +03:00
}
static void pcf857x_set16 ( struct gpio_chip * chip , unsigned offset , int value )
{
pcf857x_output16 ( chip , offset , value ) ;
}
/*-------------------------------------------------------------------------*/
2008-04-30 01:11:39 +04:00
static int pcf857x_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
2008-02-05 09:28:24 +03:00
{
struct pcf857x_platform_data * pdata ;
struct pcf857x * gpio ;
int status ;
pdata = client - > dev . platform_data ;
2009-01-16 00:50:45 +03:00
if ( ! pdata ) {
dev_dbg ( & client - > dev , " no platform data \n " ) ;
}
2008-02-05 09:28:24 +03:00
/* Allocate, initialize, and register this gpio_chip. */
gpio = kzalloc ( sizeof * gpio , GFP_KERNEL ) ;
if ( ! gpio )
return - ENOMEM ;
2008-07-22 01:21:34 +04:00
mutex_init ( & gpio - > lock ) ;
2010-08-11 05:02:24 +04:00
gpio - > chip . base = pdata ? pdata - > gpio_base : - 1 ;
2008-02-05 09:28:24 +03:00
gpio - > chip . can_sleep = 1 ;
gpio: sysfs interface
This adds a simple sysfs interface for GPIOs.
/sys/class/gpio
/export ... asks the kernel to export a GPIO to userspace
/unexport ... to return a GPIO to the kernel
/gpioN ... for each exported GPIO #N
/value ... always readable, writes fail for input GPIOs
/direction ... r/w as: in, out (default low); write high, low
/gpiochipN ... for each gpiochip; #N is its first GPIO
/base ... (r/o) same as N
/label ... (r/o) descriptive, not necessarily unique
/ngpio ... (r/o) number of GPIOs; numbered N .. N+(ngpio - 1)
GPIOs claimed by kernel code may be exported by its owner using a new
gpio_export() call, which should be most useful for driver debugging.
Such exports may optionally be done without a "direction" attribute.
Userspace may ask to take over a GPIO by writing to a sysfs control file,
helping to cope with incomplete board support or other "one-off"
requirements that don't merit full kernel support:
echo 23 > /sys/class/gpio/export
... will gpio_request(23, "sysfs") and gpio_export(23);
use /sys/class/gpio/gpio-23/direction to (re)configure it,
when that GPIO can be used as both input and output.
echo 23 > /sys/class/gpio/unexport
... will gpio_free(23), when it was exported as above
The extra D-space footprint is a few hundred bytes, except for the sysfs
resources associated with each exported GPIO. The additional I-space
footprint is about two thirds of the current size of gpiolib (!). Since
no /dev node creation is involved, no "udev" support is needed.
Related changes:
* This adds a device pointer to "struct gpio_chip". When GPIO
providers initialize that, sysfs gpio class devices become children of
that device instead of being "virtual" devices.
* The (few) gpio_chip providers which have such a device node have
been updated.
* Some gpio_chip drivers also needed to update their module "owner"
field ... for which missing kerneldoc was added.
* Some gpio_chips don't support input GPIOs. Those GPIOs are now
flagged appropriately when the chip is registered.
Based on previous patches, and discussion both on and off LKML.
A Documentation/ABI/testing/sysfs-gpio update is ready to submit once this
merges to mainline.
[akpm@linux-foundation.org: a few maintenance build fixes]
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de>
Cc: Greg KH <greg@kroah.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-07-25 12:46:07 +04:00
gpio - > chip . dev = & client - > dev ;
2008-04-28 13:14:45 +04:00
gpio - > chip . owner = THIS_MODULE ;
2008-02-05 09:28:24 +03:00
/* NOTE: the OnSemi jlc1562b is also largely compatible with
* these parts , notably for output . It has a low - resolution
* DAC instead of pin change IRQs ; and its inputs can be the
* result of comparators .
*/
/* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f;
* 9670 , 9672 , 9764 , and 9764 a use quite a variety .
*
* NOTE : we don ' t distinguish here between * 4 and * 4 a parts .
*/
2008-04-30 01:11:40 +04:00
gpio - > chip . ngpio = id - > driver_data ;
if ( gpio - > chip . ngpio = = 8 ) {
2008-02-05 09:28:24 +03:00
gpio - > chip . direction_input = pcf857x_input8 ;
gpio - > chip . get = pcf857x_get8 ;
gpio - > chip . direction_output = pcf857x_output8 ;
gpio - > chip . set = pcf857x_set8 ;
if ( ! i2c_check_functionality ( client - > adapter ,
I2C_FUNC_SMBUS_BYTE ) )
status = - EIO ;
/* fail if there's no chip present */
else
status = i2c_smbus_read_byte ( client ) ;
/* '75/'75c addresses are 0x20..0x27, just like the '74;
* the ' 75 c doesn ' t have a current source pulling high .
* 9671 , 9673 , and 9765 use quite a variety of addresses .
*
* NOTE : we don ' t distinguish here between ' 75 and ' 75 c parts .
*/
2008-04-30 01:11:40 +04:00
} else if ( gpio - > chip . ngpio = = 16 ) {
2008-02-05 09:28:24 +03:00
gpio - > chip . direction_input = pcf857x_input16 ;
gpio - > chip . get = pcf857x_get16 ;
gpio - > chip . direction_output = pcf857x_output16 ;
gpio - > chip . set = pcf857x_set16 ;
if ( ! i2c_check_functionality ( client - > adapter , I2C_FUNC_I2C ) )
status = - EIO ;
/* fail if there's no chip present */
else
status = i2c_read_le16 ( client ) ;
2009-01-16 00:50:45 +03:00
} else {
dev_dbg ( & client - > dev , " unsupported number of gpios \n " ) ;
status = - EINVAL ;
}
2008-02-05 09:28:24 +03:00
if ( status < 0 )
goto fail ;
gpio - > chip . label = client - > name ;
gpio - > client = client ;
i2c_set_clientdata ( client , gpio ) ;
/* NOTE: these chips have strange "quasi-bidirectional" I/O pins.
* We can ' t actually know whether a pin is configured ( a ) as output
* and driving the signal low , or ( b ) as input and reporting a low
* value . . . without knowing the last value written since the chip
* came out of reset ( if any ) . We can ' t read the latched output .
*
* In short , the only reliable solution for setting up pin direction
* is to do it explicitly . The setup ( ) method can do that , but it
* may cause transient glitching since it can ' t know the last value
* written ( some pins may need to be driven low ) .
*
* Using pdata - > n_latch avoids that trouble . When left initialized
* to zero , our software copy of the " latch " then matches the chip ' s
* all - ones reset state . Otherwise it flags pins to be driven low .
*/
2010-08-11 05:02:24 +04:00
gpio - > out = pdata ? ~ pdata - > n_latch : ~ 0 ;
2008-02-05 09:28:24 +03:00
status = gpiochip_add ( & gpio - > chip ) ;
if ( status < 0 )
goto fail ;
/* NOTE: these chips can issue "some pin-changed" IRQs, which we
* don ' t yet even try to use . Among other issues , the relevant
* genirq state isn ' t available to modular drivers ; and most irq
* methods can ' t be called from sleeping contexts .
*/
2011-11-06 22:36:18 +04:00
dev_info ( & client - > dev , " %s \n " ,
2008-02-05 09:28:24 +03:00
client - > irq ? " (irq ignored) " : " " ) ;
/* Let platform code set up the GPIOs and their users.
* Now is the first time anyone could use them .
*/
2010-08-11 05:02:24 +04:00
if ( pdata & & pdata - > setup ) {
2008-02-05 09:28:24 +03:00
status = pdata - > setup ( client ,
gpio - > chip . base , gpio - > chip . ngpio ,
pdata - > context ) ;
if ( status < 0 )
dev_warn ( & client - > dev , " setup --> %d \n " , status ) ;
}
return 0 ;
fail :
dev_dbg ( & client - > dev , " probe error %d for '%s' \n " ,
status , client - > name ) ;
kfree ( gpio ) ;
return status ;
}
static int pcf857x_remove ( struct i2c_client * client )
{
struct pcf857x_platform_data * pdata = client - > dev . platform_data ;
struct pcf857x * gpio = i2c_get_clientdata ( client ) ;
int status = 0 ;
2010-08-11 05:02:24 +04:00
if ( pdata & & pdata - > teardown ) {
2008-02-05 09:28:24 +03:00
status = pdata - > teardown ( client ,
gpio - > chip . base , gpio - > chip . ngpio ,
pdata - > context ) ;
if ( status < 0 ) {
dev_err ( & client - > dev , " %s --> %d \n " ,
" teardown " , status ) ;
return status ;
}
}
status = gpiochip_remove ( & gpio - > chip ) ;
if ( status = = 0 )
kfree ( gpio ) ;
else
dev_err ( & client - > dev , " %s --> %d \n " , " remove " , status ) ;
return status ;
}
static struct i2c_driver pcf857x_driver = {
. driver = {
. name = " pcf857x " ,
. owner = THIS_MODULE ,
} ,
. probe = pcf857x_probe ,
. remove = pcf857x_remove ,
2008-04-30 01:11:40 +04:00
. id_table = pcf857x_id ,
2008-02-05 09:28:24 +03:00
} ;
static int __init pcf857x_init ( void )
{
return i2c_add_driver ( & pcf857x_driver ) ;
}
2008-10-16 09:03:13 +04:00
/* register after i2c postcore initcall and before
* subsys initcalls that may rely on these GPIOs
*/
subsys_initcall ( pcf857x_init ) ;
2008-02-05 09:28:24 +03:00
static void __exit pcf857x_exit ( void )
{
i2c_del_driver ( & pcf857x_driver ) ;
}
module_exit ( pcf857x_exit ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " David Brownell " ) ;