2015-01-06 23:47:35 +03:00
/*
* Copyright ( c ) 2014 - 2015 Imagination Technologies Ltd .
*
* 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 published by
* the Free Software Foundation .
*
*/
# include <linux/clk.h>
# include <linux/delay.h>
# include <linux/err.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/of_device.h>
# include <linux/platform_device.h>
# include <linux/regulator/consumer.h>
# include <linux/slab.h>
# include <linux/iio/buffer.h>
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
# include <linux/iio/trigger.h>
# include <linux/iio/trigger_consumer.h>
# include <linux/iio/triggered_buffer.h>
/* Registers */
# define CC10001_ADC_CONFIG 0x00
# define CC10001_ADC_START_CONV BIT(4)
# define CC10001_ADC_MODE_SINGLE_CONV BIT(5)
# define CC10001_ADC_DDATA_OUT 0x04
# define CC10001_ADC_EOC 0x08
# define CC10001_ADC_EOC_SET BIT(0)
# define CC10001_ADC_CHSEL_SAMPLED 0x0c
2015-05-08 00:22:18 +03:00
# define CC10001_ADC_POWER_DOWN 0x10
# define CC10001_ADC_POWER_DOWN_SET BIT(0)
2015-01-06 23:47:35 +03:00
# define CC10001_ADC_DEBUG 0x14
# define CC10001_ADC_DATA_COUNT 0x20
# define CC10001_ADC_DATA_MASK GENMASK(9, 0)
# define CC10001_ADC_NUM_CHANNELS 8
# define CC10001_ADC_CH_MASK GENMASK(2, 0)
# define CC10001_INVALID_SAMPLED 0xffff
# define CC10001_MAX_POLL_COUNT 20
/*
* As per device specification , wait six clock cycles after power - up to
* activate START . Since adding two more clock cycles delay does not
* impact the performance too much , we are adding two additional cycles delay
* intentionally here .
*/
# define CC10001_WAIT_CYCLES 8
struct cc10001_adc_device {
void __iomem * reg_base ;
struct clk * adc_clk ;
struct regulator * reg ;
u16 * buf ;
2015-05-08 00:24:02 +03:00
bool shared ;
2015-01-06 23:47:35 +03:00
struct mutex lock ;
unsigned int start_delay_ns ;
unsigned int eoc_delay_ns ;
} ;
static inline void cc10001_adc_write_reg ( struct cc10001_adc_device * adc_dev ,
u32 reg , u32 val )
{
writel ( val , adc_dev - > reg_base + reg ) ;
}
static inline u32 cc10001_adc_read_reg ( struct cc10001_adc_device * adc_dev ,
u32 reg )
{
return readl ( adc_dev - > reg_base + reg ) ;
}
2015-05-08 00:22:18 +03:00
static void cc10001_adc_power_up ( struct cc10001_adc_device * adc_dev )
{
cc10001_adc_write_reg ( adc_dev , CC10001_ADC_POWER_DOWN , 0 ) ;
ndelay ( adc_dev - > start_delay_ns ) ;
}
static void cc10001_adc_power_down ( struct cc10001_adc_device * adc_dev )
{
cc10001_adc_write_reg ( adc_dev , CC10001_ADC_POWER_DOWN ,
CC10001_ADC_POWER_DOWN_SET ) ;
}
2015-01-06 23:47:35 +03:00
static void cc10001_adc_start ( struct cc10001_adc_device * adc_dev ,
unsigned int channel )
{
u32 val ;
/* Channel selection and mode of operation */
val = ( channel & CC10001_ADC_CH_MASK ) | CC10001_ADC_MODE_SINGLE_CONV ;
cc10001_adc_write_reg ( adc_dev , CC10001_ADC_CONFIG , val ) ;
2015-05-08 00:22:20 +03:00
udelay ( 1 ) ;
2015-01-06 23:47:35 +03:00
val = cc10001_adc_read_reg ( adc_dev , CC10001_ADC_CONFIG ) ;
val = val | CC10001_ADC_START_CONV ;
cc10001_adc_write_reg ( adc_dev , CC10001_ADC_CONFIG , val ) ;
}
static u16 cc10001_adc_poll_done ( struct iio_dev * indio_dev ,
unsigned int channel ,
unsigned int delay )
{
struct cc10001_adc_device * adc_dev = iio_priv ( indio_dev ) ;
unsigned int poll_count = 0 ;
while ( ! ( cc10001_adc_read_reg ( adc_dev , CC10001_ADC_EOC ) &
CC10001_ADC_EOC_SET ) ) {
ndelay ( delay ) ;
if ( poll_count + + = = CC10001_MAX_POLL_COUNT )
return CC10001_INVALID_SAMPLED ;
}
poll_count = 0 ;
while ( ( cc10001_adc_read_reg ( adc_dev , CC10001_ADC_CHSEL_SAMPLED ) &
CC10001_ADC_CH_MASK ) ! = channel ) {
ndelay ( delay ) ;
if ( poll_count + + = = CC10001_MAX_POLL_COUNT )
return CC10001_INVALID_SAMPLED ;
}
/* Read the 10 bit output register */
return cc10001_adc_read_reg ( adc_dev , CC10001_ADC_DDATA_OUT ) &
CC10001_ADC_DATA_MASK ;
}
static irqreturn_t cc10001_adc_trigger_h ( int irq , void * p )
{
struct cc10001_adc_device * adc_dev ;
struct iio_poll_func * pf = p ;
struct iio_dev * indio_dev ;
unsigned int delay_ns ;
unsigned int channel ;
2015-05-08 00:22:17 +03:00
unsigned int scan_idx ;
2015-01-06 23:47:35 +03:00
bool sample_invalid ;
u16 * data ;
int i ;
indio_dev = pf - > indio_dev ;
adc_dev = iio_priv ( indio_dev ) ;
data = adc_dev - > buf ;
mutex_lock ( & adc_dev - > lock ) ;
2015-05-08 00:24:02 +03:00
if ( ! adc_dev - > shared )
cc10001_adc_power_up ( adc_dev ) ;
2015-01-06 23:47:35 +03:00
/* Calculate delay step for eoc and sampled data */
delay_ns = adc_dev - > eoc_delay_ns / CC10001_MAX_POLL_COUNT ;
i = 0 ;
sample_invalid = false ;
2015-05-08 00:22:17 +03:00
for_each_set_bit ( scan_idx , indio_dev - > active_scan_mask ,
2015-01-06 23:47:35 +03:00
indio_dev - > masklength ) {
2015-05-08 00:22:17 +03:00
channel = indio_dev - > channels [ scan_idx ] . channel ;
2015-01-06 23:47:35 +03:00
cc10001_adc_start ( adc_dev , channel ) ;
data [ i ] = cc10001_adc_poll_done ( indio_dev , channel , delay_ns ) ;
if ( data [ i ] = = CC10001_INVALID_SAMPLED ) {
dev_warn ( & indio_dev - > dev ,
" invalid sample on channel %d \n " , channel ) ;
sample_invalid = true ;
goto done ;
}
i + + ;
}
done :
2015-05-08 00:24:02 +03:00
if ( ! adc_dev - > shared )
cc10001_adc_power_down ( adc_dev ) ;
2015-01-06 23:47:35 +03:00
mutex_unlock ( & adc_dev - > lock ) ;
if ( ! sample_invalid )
iio_push_to_buffers_with_timestamp ( indio_dev , data ,
2016-03-09 21:05:49 +03:00
iio_get_time_ns ( indio_dev ) ) ;
2015-01-06 23:47:35 +03:00
iio_trigger_notify_done ( indio_dev - > trig ) ;
return IRQ_HANDLED ;
}
static u16 cc10001_adc_read_raw_voltage ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan )
{
struct cc10001_adc_device * adc_dev = iio_priv ( indio_dev ) ;
unsigned int delay_ns ;
u16 val ;
2015-05-08 00:24:02 +03:00
if ( ! adc_dev - > shared )
cc10001_adc_power_up ( adc_dev ) ;
2015-01-06 23:47:35 +03:00
/* Calculate delay step for eoc and sampled data */
delay_ns = adc_dev - > eoc_delay_ns / CC10001_MAX_POLL_COUNT ;
cc10001_adc_start ( adc_dev , chan - > channel ) ;
val = cc10001_adc_poll_done ( indio_dev , chan - > channel , delay_ns ) ;
2015-05-08 00:24:02 +03:00
if ( ! adc_dev - > shared )
cc10001_adc_power_down ( adc_dev ) ;
2015-01-06 23:47:35 +03:00
return val ;
}
static int cc10001_adc_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val , int * val2 , long mask )
{
struct cc10001_adc_device * adc_dev = iio_priv ( indio_dev ) ;
int ret ;
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
if ( iio_buffer_enabled ( indio_dev ) )
return - EBUSY ;
mutex_lock ( & adc_dev - > lock ) ;
* val = cc10001_adc_read_raw_voltage ( indio_dev , chan ) ;
mutex_unlock ( & adc_dev - > lock ) ;
if ( * val = = CC10001_INVALID_SAMPLED )
return - EIO ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SCALE :
ret = regulator_get_voltage ( adc_dev - > reg ) ;
2015-05-08 00:22:19 +03:00
if ( ret < 0 )
2015-01-06 23:47:35 +03:00
return ret ;
* val = ret / 1000 ;
* val2 = chan - > scan_type . realbits ;
return IIO_VAL_FRACTIONAL_LOG2 ;
default :
return - EINVAL ;
}
}
static int cc10001_update_scan_mode ( struct iio_dev * indio_dev ,
const unsigned long * scan_mask )
{
struct cc10001_adc_device * adc_dev = iio_priv ( indio_dev ) ;
kfree ( adc_dev - > buf ) ;
adc_dev - > buf = kmalloc ( indio_dev - > scan_bytes , GFP_KERNEL ) ;
if ( ! adc_dev - > buf )
return - ENOMEM ;
return 0 ;
}
static const struct iio_info cc10001_adc_info = {
. read_raw = & cc10001_adc_read_raw ,
. update_scan_mode = & cc10001_update_scan_mode ,
} ;
2015-05-08 00:22:17 +03:00
static int cc10001_adc_channel_init ( struct iio_dev * indio_dev ,
unsigned long channel_map )
2015-01-06 23:47:35 +03:00
{
struct iio_chan_spec * chan_array , * timestamp ;
unsigned int bit , idx = 0 ;
2015-05-08 00:22:17 +03:00
indio_dev - > num_channels = bitmap_weight ( & channel_map ,
CC10001_ADC_NUM_CHANNELS ) + 1 ;
2015-01-06 23:47:35 +03:00
2015-05-08 00:22:17 +03:00
chan_array = devm_kcalloc ( & indio_dev - > dev , indio_dev - > num_channels ,
2015-01-06 23:47:35 +03:00
sizeof ( struct iio_chan_spec ) ,
GFP_KERNEL ) ;
if ( ! chan_array )
return - ENOMEM ;
2015-05-08 00:22:17 +03:00
for_each_set_bit ( bit , & channel_map , CC10001_ADC_NUM_CHANNELS ) {
2015-01-06 23:47:35 +03:00
struct iio_chan_spec * chan = & chan_array [ idx ] ;
chan - > type = IIO_VOLTAGE ;
chan - > indexed = 1 ;
chan - > channel = bit ;
chan - > scan_index = idx ;
chan - > scan_type . sign = ' u ' ;
chan - > scan_type . realbits = 10 ;
chan - > scan_type . storagebits = 16 ;
chan - > info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) ;
chan - > info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) ;
idx + + ;
}
timestamp = & chan_array [ idx ] ;
timestamp - > type = IIO_TIMESTAMP ;
timestamp - > channel = - 1 ;
timestamp - > scan_index = idx ;
timestamp - > scan_type . sign = ' s ' ;
timestamp - > scan_type . realbits = 64 ;
timestamp - > scan_type . storagebits = 64 ;
indio_dev - > channels = chan_array ;
return 0 ;
}
static int cc10001_adc_probe ( struct platform_device * pdev )
{
struct device_node * node = pdev - > dev . of_node ;
struct cc10001_adc_device * adc_dev ;
unsigned long adc_clk_rate ;
struct resource * res ;
struct iio_dev * indio_dev ;
2015-05-08 00:22:17 +03:00
unsigned long channel_map ;
2015-01-06 23:47:35 +03:00
int ret ;
indio_dev = devm_iio_device_alloc ( & pdev - > dev , sizeof ( * adc_dev ) ) ;
if ( indio_dev = = NULL )
return - ENOMEM ;
adc_dev = iio_priv ( indio_dev ) ;
2015-05-08 00:22:17 +03:00
channel_map = GENMASK ( CC10001_ADC_NUM_CHANNELS - 1 , 0 ) ;
2015-05-08 00:24:02 +03:00
if ( ! of_property_read_u32 ( node , " adc-reserved-channels " , & ret ) ) {
adc_dev - > shared = true ;
2015-05-08 00:22:17 +03:00
channel_map & = ~ ret ;
2015-05-08 00:24:02 +03:00
}
2015-01-06 23:47:35 +03:00
adc_dev - > reg = devm_regulator_get ( & pdev - > dev , " vref " ) ;
if ( IS_ERR ( adc_dev - > reg ) )
return PTR_ERR ( adc_dev - > reg ) ;
ret = regulator_enable ( adc_dev - > reg ) ;
if ( ret )
return ret ;
indio_dev - > dev . parent = & pdev - > dev ;
indio_dev - > name = dev_name ( & pdev - > dev ) ;
indio_dev - > info = & cc10001_adc_info ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
adc_dev - > reg_base = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( adc_dev - > reg_base ) ) {
ret = PTR_ERR ( adc_dev - > reg_base ) ;
goto err_disable_reg ;
}
adc_dev - > adc_clk = devm_clk_get ( & pdev - > dev , " adc " ) ;
if ( IS_ERR ( adc_dev - > adc_clk ) ) {
dev_err ( & pdev - > dev , " failed to get the clock \n " ) ;
ret = PTR_ERR ( adc_dev - > adc_clk ) ;
goto err_disable_reg ;
}
ret = clk_prepare_enable ( adc_dev - > adc_clk ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " failed to enable the clock \n " ) ;
goto err_disable_reg ;
}
adc_clk_rate = clk_get_rate ( adc_dev - > adc_clk ) ;
if ( ! adc_clk_rate ) {
ret = - EINVAL ;
dev_err ( & pdev - > dev , " null clock rate! \n " ) ;
goto err_disable_clk ;
}
adc_dev - > eoc_delay_ns = NSEC_PER_SEC / adc_clk_rate ;
adc_dev - > start_delay_ns = adc_dev - > eoc_delay_ns * CC10001_WAIT_CYCLES ;
2015-05-08 00:24:02 +03:00
/*
* There is only one register to power - up / power - down the AUX ADC .
* If the ADC is shared among multiple CPUs , always power it up here .
* If the ADC is used only by the MIPS , power - up / power - down at runtime .
*/
if ( adc_dev - > shared )
cc10001_adc_power_up ( adc_dev ) ;
2015-01-06 23:47:35 +03:00
/* Setup the ADC channels available on the device */
2015-05-08 00:22:17 +03:00
ret = cc10001_adc_channel_init ( indio_dev , channel_map ) ;
2015-01-06 23:47:35 +03:00
if ( ret < 0 )
goto err_disable_clk ;
mutex_init ( & adc_dev - > lock ) ;
ret = iio_triggered_buffer_setup ( indio_dev , NULL ,
& cc10001_adc_trigger_h , NULL ) ;
if ( ret < 0 )
goto err_disable_clk ;
ret = iio_device_register ( indio_dev ) ;
if ( ret < 0 )
goto err_cleanup_buffer ;
platform_set_drvdata ( pdev , indio_dev ) ;
return 0 ;
err_cleanup_buffer :
iio_triggered_buffer_cleanup ( indio_dev ) ;
err_disable_clk :
clk_disable_unprepare ( adc_dev - > adc_clk ) ;
err_disable_reg :
regulator_disable ( adc_dev - > reg ) ;
return ret ;
}
static int cc10001_adc_remove ( struct platform_device * pdev )
{
struct iio_dev * indio_dev = platform_get_drvdata ( pdev ) ;
struct cc10001_adc_device * adc_dev = iio_priv ( indio_dev ) ;
2015-05-08 00:24:02 +03:00
cc10001_adc_power_down ( adc_dev ) ;
2015-01-06 23:47:35 +03:00
iio_device_unregister ( indio_dev ) ;
iio_triggered_buffer_cleanup ( indio_dev ) ;
clk_disable_unprepare ( adc_dev - > adc_clk ) ;
regulator_disable ( adc_dev - > reg ) ;
return 0 ;
}
static const struct of_device_id cc10001_adc_dt_ids [ ] = {
{ . compatible = " cosmic,10001-adc " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , cc10001_adc_dt_ids ) ;
static struct platform_driver cc10001_adc_driver = {
. driver = {
. name = " cc10001-adc " ,
. of_match_table = cc10001_adc_dt_ids ,
} ,
. probe = cc10001_adc_probe ,
. remove = cc10001_adc_remove ,
} ;
module_platform_driver ( cc10001_adc_driver ) ;
MODULE_AUTHOR ( " Phani Movva <Phani.Movva@imgtec.com> " ) ;
MODULE_DESCRIPTION ( " Cosmic Circuits ADC driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;