2010-06-30 01:40:52 -07:00
/*
* AD7879 / AD7889 touchscreen ( SPI bus )
*
* Copyright ( C ) 2008 - 2010 Michael Hennerich , Analog Devices Inc .
*
* Licensed under the GPL - 2 or later .
*/
# include <linux/input.h> /* BUS_SPI */
2011-01-20 22:48:44 -08:00
# include <linux/pm.h>
2010-06-30 01:40:52 -07:00
# include <linux/spi/spi.h>
# include "ad7879.h"
# define AD7879_DEVID 0x7A /* AD7879/AD7889 */
# define MAX_SPI_FREQ_HZ 5000000
# define AD7879_CMD_MAGIC 0xE000
# define AD7879_CMD_READ (1 << 10)
# define AD7879_CMD(reg) (AD7879_CMD_MAGIC | ((reg) & 0xF))
# define AD7879_WRITECMD(reg) (AD7879_CMD(reg))
# define AD7879_READCMD(reg) (AD7879_CMD(reg) | AD7879_CMD_READ)
2011-01-20 22:48:44 -08:00
# ifdef CONFIG_PM_SLEEP
static int ad7879_spi_suspend ( struct device * dev )
2010-06-30 01:40:52 -07:00
{
2011-01-20 22:48:44 -08:00
struct spi_device * spi = to_spi_device ( dev ) ;
2010-06-30 01:40:52 -07:00
struct ad7879 * ts = spi_get_drvdata ( spi ) ;
2010-06-30 14:50:51 -07:00
ad7879_suspend ( ts ) ;
2010-06-30 01:40:52 -07:00
return 0 ;
}
2011-01-20 22:48:44 -08:00
static int ad7879_spi_resume ( struct device * dev )
2010-06-30 01:40:52 -07:00
{
2011-01-20 22:48:44 -08:00
struct spi_device * spi = to_spi_device ( dev ) ;
2010-06-30 01:40:52 -07:00
struct ad7879 * ts = spi_get_drvdata ( spi ) ;
2010-06-30 14:50:51 -07:00
ad7879_resume ( ts ) ;
2010-06-30 01:40:52 -07:00
return 0 ;
}
# endif
2011-01-20 22:48:44 -08:00
static SIMPLE_DEV_PM_OPS ( ad7879_spi_pm , ad7879_spi_suspend , ad7879_spi_resume ) ;
2010-06-30 01:40:52 -07:00
/*
* ad7879_read / write are only used for initial setup and for sysfs controls .
* The main traffic is done in ad7879_collect ( ) .
*/
static int ad7879_spi_xfer ( struct spi_device * spi ,
u16 cmd , u8 count , u16 * tx_buf , u16 * rx_buf )
{
struct spi_message msg ;
struct spi_transfer * xfers ;
void * spi_data ;
u16 * command ;
u16 * _rx_buf = _rx_buf ; /* shut gcc up */
u8 idx ;
int ret ;
xfers = spi_data = kzalloc ( sizeof ( * xfers ) * ( count + 2 ) , GFP_KERNEL ) ;
if ( ! spi_data )
return - ENOMEM ;
spi_message_init ( & msg ) ;
command = spi_data ;
command [ 0 ] = cmd ;
if ( count = = 1 ) {
/* ad7879_spi_{read,write} gave us buf on stack */
command [ 1 ] = * tx_buf ;
tx_buf = & command [ 1 ] ;
_rx_buf = rx_buf ;
rx_buf = & command [ 2 ] ;
}
+ + xfers ;
xfers [ 0 ] . tx_buf = command ;
xfers [ 0 ] . len = 2 ;
spi_message_add_tail ( & xfers [ 0 ] , & msg ) ;
+ + xfers ;
for ( idx = 0 ; idx < count ; + + idx ) {
if ( rx_buf )
xfers [ idx ] . rx_buf = & rx_buf [ idx ] ;
if ( tx_buf )
xfers [ idx ] . tx_buf = & tx_buf [ idx ] ;
xfers [ idx ] . len = 2 ;
spi_message_add_tail ( & xfers [ idx ] , & msg ) ;
}
ret = spi_sync ( spi , & msg ) ;
if ( count = = 1 )
_rx_buf [ 0 ] = command [ 2 ] ;
kfree ( spi_data ) ;
return ret ;
}
static int ad7879_spi_multi_read ( struct device * dev ,
u8 first_reg , u8 count , u16 * buf )
{
struct spi_device * spi = to_spi_device ( dev ) ;
return ad7879_spi_xfer ( spi , AD7879_READCMD ( first_reg ) , count , NULL , buf ) ;
}
static int ad7879_spi_read ( struct device * dev , u8 reg )
{
struct spi_device * spi = to_spi_device ( dev ) ;
u16 ret , dummy ;
return ad7879_spi_xfer ( spi , AD7879_READCMD ( reg ) , 1 , & dummy , & ret ) ? : ret ;
}
static int ad7879_spi_write ( struct device * dev , u8 reg , u16 val )
{
struct spi_device * spi = to_spi_device ( dev ) ;
u16 dummy ;
return ad7879_spi_xfer ( spi , AD7879_WRITECMD ( reg ) , 1 , & val , & dummy ) ;
}
static const struct ad7879_bus_ops ad7879_spi_bus_ops = {
. bustype = BUS_SPI ,
. read = ad7879_spi_read ,
. multi_read = ad7879_spi_multi_read ,
. write = ad7879_spi_write ,
} ;
static int __devinit ad7879_spi_probe ( struct spi_device * spi )
{
struct ad7879 * ts ;
2010-06-30 14:51:09 -07:00
int err ;
2010-06-30 01:40:52 -07:00
/* don't exceed max specified SPI CLK frequency */
if ( spi - > max_speed_hz > MAX_SPI_FREQ_HZ ) {
dev_err ( & spi - > dev , " SPI CLK %d Hz? \n " , spi - > max_speed_hz ) ;
return - EINVAL ;
}
2010-06-30 14:51:09 -07:00
spi - > bits_per_word = 16 ;
err = spi_setup ( spi ) ;
if ( err ) {
dev_dbg ( & spi - > dev , " spi master doesn't support 16 bits/word \n " ) ;
return err ;
}
2010-06-30 01:40:52 -07:00
ts = ad7879_probe ( & spi - > dev , AD7879_DEVID , spi - > irq , & ad7879_spi_bus_ops ) ;
if ( IS_ERR ( ts ) )
return PTR_ERR ( ts ) ;
spi_set_drvdata ( spi , ts ) ;
return 0 ;
}
static int __devexit ad7879_spi_remove ( struct spi_device * spi )
{
struct ad7879 * ts = spi_get_drvdata ( spi ) ;
ad7879_remove ( ts ) ;
spi_set_drvdata ( spi , NULL ) ;
return 0 ;
}
static struct spi_driver ad7879_spi_driver = {
. driver = {
. name = " ad7879 " ,
. bus = & spi_bus_type ,
. owner = THIS_MODULE ,
2011-01-20 22:48:44 -08:00
. pm = & ad7879_spi_pm ,
2010-06-30 01:40:52 -07:00
} ,
. probe = ad7879_spi_probe ,
. remove = __devexit_p ( ad7879_spi_remove ) ,
} ;
static int __init ad7879_spi_init ( void )
{
return spi_register_driver ( & ad7879_spi_driver ) ;
}
module_init ( ad7879_spi_init ) ;
static void __exit ad7879_spi_exit ( void )
{
spi_unregister_driver ( & ad7879_spi_driver ) ;
}
module_exit ( ad7879_spi_exit ) ;
MODULE_AUTHOR ( " Michael Hennerich <hennerich@blackfin.uclinux.org> " ) ;
MODULE_DESCRIPTION ( " AD7879(-1) touchscreen SPI bus driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " spi:ad7879 " ) ;