2009-03-31 15:24:33 -07:00
/*
* lis3lv02d_spi - SPI glue layer for lis3lv02d
*
* Copyright ( c ) 2009 Daniel Mack < daniel @ caiaq . de >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* publishhed by the Free Software Foundation .
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/err.h>
# include <linux/input.h>
# include <linux/interrupt.h>
# include <linux/workqueue.h>
# include <linux/spi/spi.h>
2011-01-20 21:27:56 +00:00
# include <linux/pm.h>
2012-09-26 13:58:19 -07:00
# include <linux/of.h>
# include <linux/of_platform.h>
2012-09-26 13:58:24 -07:00
# include <linux/of_device.h>
2009-03-31 15:24:33 -07:00
# include "lis3lv02d.h"
# define DRV_NAME "lis3lv02d_spi"
# define LIS3_SPI_READ 0x80
static int lis3_spi_read ( struct lis3lv02d * lis3 , int reg , u8 * v )
{
struct spi_device * spi = lis3 - > bus_priv ;
int ret = spi_w8r8 ( spi , reg | LIS3_SPI_READ ) ;
if ( ret < 0 )
return - EINVAL ;
* v = ( u8 ) ret ;
return 0 ;
}
static int lis3_spi_write ( struct lis3lv02d * lis3 , int reg , u8 val )
{
u8 tmp [ 2 ] = { reg , val } ;
struct spi_device * spi = lis3 - > bus_priv ;
return spi_write ( spi , tmp , sizeof ( tmp ) ) ;
}
static int lis3_spi_init ( struct lis3lv02d * lis3 )
{
u8 reg ;
int ret ;
/* power up the device */
ret = lis3 - > read ( lis3 , CTRL_REG1 , & reg ) ;
if ( ret < 0 )
return ret ;
2010-10-22 07:57:28 -04:00
reg | = CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen ;
2009-03-31 15:24:33 -07:00
return lis3 - > write ( lis3 , CTRL_REG1 , reg ) ;
}
2010-10-01 17:14:25 -04:00
static union axis_conversion lis3lv02d_axis_normal =
{ . as_array = { 1 , 2 , 3 } } ;
2009-03-31 15:24:33 -07:00
2012-09-26 13:58:19 -07:00
# ifdef CONFIG_OF
2015-03-16 20:20:26 +01:00
static const struct of_device_id lis302dl_spi_dt_ids [ ] = {
2012-09-26 13:58:19 -07:00
{ . compatible = " st,lis302dl-spi " } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , lis302dl_spi_dt_ids ) ;
# endif
2012-11-19 13:23:05 -05:00
static int lis302dl_spi_probe ( struct spi_device * spi )
2009-03-31 15:24:33 -07:00
{
int ret ;
spi - > bits_per_word = 8 ;
spi - > mode = SPI_MODE_0 ;
ret = spi_setup ( spi ) ;
if ( ret < 0 )
return ret ;
2009-09-21 17:04:45 -07:00
lis3_dev . bus_priv = spi ;
lis3_dev . init = lis3_spi_init ;
lis3_dev . read = lis3_spi_read ;
lis3_dev . write = lis3_spi_write ;
lis3_dev . irq = spi - > irq ;
lis3_dev . ac = lis3lv02d_axis_normal ;
lis3_dev . pdata = spi - > dev . platform_data ;
2012-09-26 13:58:19 -07:00
# ifdef CONFIG_OF
2012-09-26 13:58:24 -07:00
if ( of_match_device ( lis302dl_spi_dt_ids , & spi - > dev ) ) {
2012-09-26 13:58:19 -07:00
lis3_dev . of_node = spi - > dev . of_node ;
2012-09-26 13:58:24 -07:00
ret = lis3lv02d_init_dt ( & lis3_dev ) ;
if ( ret )
return ret ;
}
2012-09-26 13:58:19 -07:00
# endif
2009-03-31 15:24:33 -07:00
spi_set_drvdata ( spi , & lis3_dev ) ;
2009-09-21 17:04:45 -07:00
return lis3lv02d_init_device ( & lis3_dev ) ;
2009-03-31 15:24:33 -07:00
}
2012-11-19 13:26:02 -05:00
static int lis302dl_spi_remove ( struct spi_device * spi )
2009-03-31 15:24:33 -07:00
{
struct lis3lv02d * lis3 = spi_get_drvdata ( spi ) ;
2011-10-31 17:11:02 -07:00
lis3lv02d_joystick_disable ( lis3 ) ;
2009-03-31 15:24:33 -07:00
lis3lv02d_poweroff ( lis3 ) ;
2009-10-07 16:32:35 -07:00
return lis3lv02d_remove_fs ( & lis3_dev ) ;
2009-03-31 15:24:33 -07:00
}
2011-01-20 21:27:56 +00:00
# ifdef CONFIG_PM_SLEEP
static int lis3lv02d_spi_suspend ( struct device * dev )
2009-09-21 17:04:44 -07:00
{
2011-01-20 21:27:56 +00:00
struct spi_device * spi = to_spi_device ( dev ) ;
2009-09-21 17:04:44 -07:00
struct lis3lv02d * lis3 = spi_get_drvdata ( spi ) ;
2010-09-17 17:24:10 +02:00
if ( ! lis3 - > pdata | | ! lis3 - > pdata - > wakeup_flags )
2009-09-21 17:04:44 -07:00
lis3lv02d_poweroff ( & lis3_dev ) ;
return 0 ;
}
2011-01-20 21:27:56 +00:00
static int lis3lv02d_spi_resume ( struct device * dev )
2009-09-21 17:04:44 -07:00
{
2011-01-20 21:27:56 +00:00
struct spi_device * spi = to_spi_device ( dev ) ;
2009-09-21 17:04:44 -07:00
struct lis3lv02d * lis3 = spi_get_drvdata ( spi ) ;
2010-09-17 17:24:10 +02:00
if ( ! lis3 - > pdata | | ! lis3 - > pdata - > wakeup_flags )
2009-09-21 17:04:44 -07:00
lis3lv02d_poweron ( lis3 ) ;
return 0 ;
}
# endif
2011-01-20 21:27:56 +00:00
static SIMPLE_DEV_PM_OPS ( lis3lv02d_spi_pm , lis3lv02d_spi_suspend ,
lis3lv02d_spi_resume ) ;
2009-03-31 15:24:33 -07:00
static struct spi_driver lis302dl_spi_driver = {
. driver = {
. name = DRV_NAME ,
. owner = THIS_MODULE ,
2011-01-20 21:27:56 +00:00
. pm = & lis3lv02d_spi_pm ,
2012-09-26 13:58:19 -07:00
. of_match_table = of_match_ptr ( lis302dl_spi_dt_ids ) ,
2009-03-31 15:24:33 -07:00
} ,
. probe = lis302dl_spi_probe ,
2012-11-19 13:21:23 -05:00
. remove = lis302dl_spi_remove ,
2009-03-31 15:24:33 -07:00
} ;
2012-01-22 15:38:22 +08:00
module_spi_driver ( lis302dl_spi_driver ) ;
2009-03-31 15:24:33 -07:00
MODULE_AUTHOR ( " Daniel Mack <daniel@caiaq.de> " ) ;
MODULE_DESCRIPTION ( " lis3lv02d SPI glue layer " ) ;
MODULE_LICENSE ( " GPL " ) ;
2009-09-22 16:46:08 -07:00
MODULE_ALIAS ( " spi: " DRV_NAME ) ;