2009-04-01 02:24:33 +04: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-21 00:27:56 +03:00
# include <linux/pm.h>
2012-09-27 00:58:19 +04:00
# include <linux/of.h>
# include <linux/of_platform.h>
2012-09-27 00:58:24 +04:00
# include <linux/of_device.h>
2009-04-01 02:24:33 +04: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 15:57:28 +04:00
reg | = CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen ;
2009-04-01 02:24:33 +04:00
return lis3 - > write ( lis3 , CTRL_REG1 , reg ) ;
}
2010-10-02 01:14:25 +04:00
static union axis_conversion lis3lv02d_axis_normal =
{ . as_array = { 1 , 2 , 3 } } ;
2009-04-01 02:24:33 +04:00
2012-09-27 00:58:19 +04:00
# ifdef CONFIG_OF
2015-03-16 22:20:26 +03:00
static const struct of_device_id lis302dl_spi_dt_ids [ ] = {
2012-09-27 00:58:19 +04:00
{ . compatible = " st,lis302dl-spi " } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , lis302dl_spi_dt_ids ) ;
# endif
2012-11-19 22:23:05 +04:00
static int lis302dl_spi_probe ( struct spi_device * spi )
2009-04-01 02:24:33 +04:00
{
int ret ;
spi - > bits_per_word = 8 ;
spi - > mode = SPI_MODE_0 ;
ret = spi_setup ( spi ) ;
if ( ret < 0 )
return ret ;
2009-09-22 04:04:45 +04: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-27 00:58:19 +04:00
# ifdef CONFIG_OF
2012-09-27 00:58:24 +04:00
if ( of_match_device ( lis302dl_spi_dt_ids , & spi - > dev ) ) {
2012-09-27 00:58:19 +04:00
lis3_dev . of_node = spi - > dev . of_node ;
2012-09-27 00:58:24 +04:00
ret = lis3lv02d_init_dt ( & lis3_dev ) ;
if ( ret )
return ret ;
}
2012-09-27 00:58:19 +04:00
# endif
2009-04-01 02:24:33 +04:00
spi_set_drvdata ( spi , & lis3_dev ) ;
2009-09-22 04:04:45 +04:00
return lis3lv02d_init_device ( & lis3_dev ) ;
2009-04-01 02:24:33 +04:00
}
2012-11-19 22:26:02 +04:00
static int lis302dl_spi_remove ( struct spi_device * spi )
2009-04-01 02:24:33 +04:00
{
struct lis3lv02d * lis3 = spi_get_drvdata ( spi ) ;
2011-11-01 04:11:02 +04:00
lis3lv02d_joystick_disable ( lis3 ) ;
2009-04-01 02:24:33 +04:00
lis3lv02d_poweroff ( lis3 ) ;
2009-10-08 03:32:35 +04:00
return lis3lv02d_remove_fs ( & lis3_dev ) ;
2009-04-01 02:24:33 +04:00
}
2011-01-21 00:27:56 +03:00
# ifdef CONFIG_PM_SLEEP
static int lis3lv02d_spi_suspend ( struct device * dev )
2009-09-22 04:04:44 +04:00
{
2011-01-21 00:27:56 +03:00
struct spi_device * spi = to_spi_device ( dev ) ;
2009-09-22 04:04:44 +04:00
struct lis3lv02d * lis3 = spi_get_drvdata ( spi ) ;
2010-09-17 19:24:10 +04:00
if ( ! lis3 - > pdata | | ! lis3 - > pdata - > wakeup_flags )
2009-09-22 04:04:44 +04:00
lis3lv02d_poweroff ( & lis3_dev ) ;
return 0 ;
}
2011-01-21 00:27:56 +03:00
static int lis3lv02d_spi_resume ( struct device * dev )
2009-09-22 04:04:44 +04:00
{
2011-01-21 00:27:56 +03:00
struct spi_device * spi = to_spi_device ( dev ) ;
2009-09-22 04:04:44 +04:00
struct lis3lv02d * lis3 = spi_get_drvdata ( spi ) ;
2010-09-17 19:24:10 +04:00
if ( ! lis3 - > pdata | | ! lis3 - > pdata - > wakeup_flags )
2009-09-22 04:04:44 +04:00
lis3lv02d_poweron ( lis3 ) ;
return 0 ;
}
# endif
2011-01-21 00:27:56 +03:00
static SIMPLE_DEV_PM_OPS ( lis3lv02d_spi_pm , lis3lv02d_spi_suspend ,
lis3lv02d_spi_resume ) ;
2009-04-01 02:24:33 +04:00
static struct spi_driver lis302dl_spi_driver = {
. driver = {
. name = DRV_NAME ,
2011-01-21 00:27:56 +03:00
. pm = & lis3lv02d_spi_pm ,
2012-09-27 00:58:19 +04:00
. of_match_table = of_match_ptr ( lis302dl_spi_dt_ids ) ,
2009-04-01 02:24:33 +04:00
} ,
. probe = lis302dl_spi_probe ,
2012-11-19 22:21:23 +04:00
. remove = lis302dl_spi_remove ,
2009-04-01 02:24:33 +04:00
} ;
2012-01-22 11:38:22 +04:00
module_spi_driver ( lis302dl_spi_driver ) ;
2009-04-01 02:24:33 +04:00
MODULE_AUTHOR ( " Daniel Mack <daniel@caiaq.de> " ) ;
MODULE_DESCRIPTION ( " lis3lv02d SPI glue layer " ) ;
MODULE_LICENSE ( " GPL " ) ;
2009-09-23 03:46:08 +04:00
MODULE_ALIAS ( " spi: " DRV_NAME ) ;