2019-05-27 08:55:06 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-07-23 22:24:00 +01:00
/*
* Rockchip Successive Approximation Register ( SAR ) A / D Converter
* Copyright ( C ) 2014 ROCKCHIP , Inc .
*/
2023-06-04 00:23:34 +05:30
# include <linux/bitfield.h>
2014-07-23 22:24:00 +01:00
# include <linux/module.h>
2022-10-04 15:49:00 +02:00
# include <linux/mutex.h>
2014-07-23 22:24:00 +01:00
# include <linux/platform_device.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/of.h>
# include <linux/clk.h>
# include <linux/completion.h>
2016-07-27 22:24:04 +08:00
# include <linux/delay.h>
# include <linux/reset.h>
2014-07-23 22:24:00 +01:00
# include <linux/regulator/consumer.h>
2020-06-24 01:30:11 +02:00
# include <linux/iio/buffer.h>
2014-07-23 22:24:00 +01:00
# include <linux/iio/iio.h>
2020-06-24 01:30:11 +02:00
# include <linux/iio/trigger_consumer.h>
# include <linux/iio/triggered_buffer.h>
2014-07-23 22:24:00 +01:00
# define SARADC_DATA 0x00
# define SARADC_STAS 0x04
# define SARADC_STAS_BUSY BIT(0)
# define SARADC_CTRL 0x08
# define SARADC_CTRL_IRQ_STATUS BIT(6)
# define SARADC_CTRL_IRQ_ENABLE BIT(5)
# define SARADC_CTRL_POWER_CTRL BIT(3)
# define SARADC_CTRL_CHN_MASK 0x7
# define SARADC_DLY_PU_SOC 0x0c
# define SARADC_DLY_PU_SOC_MASK 0x3f
# define SARADC_TIMEOUT msecs_to_jiffies(100)
2021-07-12 09:45:07 +08:00
# define SARADC_MAX_CHANNELS 8
2014-07-23 22:24:00 +01:00
2023-06-04 00:23:34 +05:30
/* v2 registers */
# define SARADC2_CONV_CON 0x000
# define SARADC_T_PD_SOC 0x004
# define SARADC_T_DAS_SOC 0x00c
# define SARADC2_END_INT_EN 0x104
# define SARADC2_ST_CON 0x108
# define SARADC2_STATUS 0x10c
# define SARADC2_END_INT_ST 0x110
# define SARADC2_DATA_BASE 0x120
# define SARADC2_EN_END_INT BIT(0)
# define SARADC2_START BIT(4)
# define SARADC2_SINGLE_MODE BIT(5)
# define SARADC2_CONV_CHANNELS GENMASK(15, 0)
2023-06-04 00:23:33 +05:30
struct rockchip_saradc ;
2014-09-15 22:47:00 +01:00
struct rockchip_saradc_data {
const struct iio_chan_spec * channels ;
int num_channels ;
unsigned long clk_rate ;
2023-06-04 00:23:33 +05:30
void ( * start ) ( struct rockchip_saradc * info , int chn ) ;
int ( * read ) ( struct rockchip_saradc * info ) ;
void ( * power_down ) ( struct rockchip_saradc * info ) ;
2014-09-15 22:47:00 +01:00
} ;
2014-07-23 22:24:00 +01:00
struct rockchip_saradc {
void __iomem * regs ;
struct clk * pclk ;
struct clk * clk ;
struct completion completion ;
struct regulator * vref ;
2022-10-04 15:49:00 +02:00
/* lock to protect against multiple access to the device */
struct mutex lock ;
2021-08-10 09:10:07 +08:00
int uv_vref ;
2016-07-27 22:24:04 +08:00
struct reset_control * reset ;
2014-09-15 22:47:00 +01:00
const struct rockchip_saradc_data * data ;
2014-07-23 22:24:00 +01:00
u16 last_val ;
2020-06-24 01:30:11 +02:00
const struct iio_chan_spec * last_chan ;
2021-08-10 09:10:07 +08:00
struct notifier_block nb ;
2014-07-23 22:24:00 +01:00
} ;
2023-06-04 00:23:33 +05:30
static void rockchip_saradc_reset_controller ( struct reset_control * reset ) ;
static void rockchip_saradc_start_v1 ( struct rockchip_saradc * info , int chn )
{
/* 8 clock periods as delay between power up and start cmd */
writel_relaxed ( 8 , info - > regs + SARADC_DLY_PU_SOC ) ;
/* Select the channel to be used and trigger conversion */
writel ( SARADC_CTRL_POWER_CTRL | ( chn & SARADC_CTRL_CHN_MASK ) |
SARADC_CTRL_IRQ_ENABLE , info - > regs + SARADC_CTRL ) ;
}
2023-06-04 00:23:34 +05:30
static void rockchip_saradc_start_v2 ( struct rockchip_saradc * info , int chn )
{
int val ;
if ( info - > reset )
rockchip_saradc_reset_controller ( info - > reset ) ;
writel_relaxed ( 0xc , info - > regs + SARADC_T_DAS_SOC ) ;
writel_relaxed ( 0x20 , info - > regs + SARADC_T_PD_SOC ) ;
val = FIELD_PREP ( SARADC2_EN_END_INT , 1 ) ;
val | = val < < 16 ;
writel_relaxed ( val , info - > regs + SARADC2_END_INT_EN ) ;
val = FIELD_PREP ( SARADC2_START , 1 ) |
FIELD_PREP ( SARADC2_SINGLE_MODE , 1 ) |
FIELD_PREP ( SARADC2_CONV_CHANNELS , chn ) ;
val | = val < < 16 ;
writel ( val , info - > regs + SARADC2_CONV_CON ) ;
}
2023-06-04 00:23:33 +05:30
static void rockchip_saradc_start ( struct rockchip_saradc * info , int chn )
{
info - > data - > start ( info , chn ) ;
}
static int rockchip_saradc_read_v1 ( struct rockchip_saradc * info )
{
return readl_relaxed ( info - > regs + SARADC_DATA ) ;
}
2023-06-04 00:23:34 +05:30
static int rockchip_saradc_read_v2 ( struct rockchip_saradc * info )
{
int offset ;
/* Clear irq */
writel_relaxed ( 0x1 , info - > regs + SARADC2_END_INT_ST ) ;
offset = SARADC2_DATA_BASE + info - > last_chan - > channel * 0x4 ;
return readl_relaxed ( info - > regs + offset ) ;
}
2023-06-04 00:23:33 +05:30
static int rockchip_saradc_read ( struct rockchip_saradc * info )
{
return info - > data - > read ( info ) ;
}
static void rockchip_saradc_power_down_v1 ( struct rockchip_saradc * info )
2020-06-24 01:30:11 +02:00
{
writel_relaxed ( 0 , info - > regs + SARADC_CTRL ) ;
}
2023-06-04 00:23:33 +05:30
static void rockchip_saradc_power_down ( struct rockchip_saradc * info )
{
if ( info - > data - > power_down )
info - > data - > power_down ( info ) ;
}
2020-06-24 01:30:11 +02:00
static int rockchip_saradc_conversion ( struct rockchip_saradc * info ,
2023-06-04 00:23:37 +05:30
struct iio_chan_spec const * chan )
2020-06-24 01:30:11 +02:00
{
reinit_completion ( & info - > completion ) ;
info - > last_chan = chan ;
2023-06-04 00:23:33 +05:30
rockchip_saradc_start ( info , chan - > channel ) ;
2020-06-24 01:30:11 +02:00
if ( ! wait_for_completion_timeout ( & info - > completion , SARADC_TIMEOUT ) )
return - ETIMEDOUT ;
return 0 ;
}
2014-07-23 22:24:00 +01:00
static int rockchip_saradc_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val , int * val2 , long mask )
{
struct rockchip_saradc * info = iio_priv ( indio_dev ) ;
int ret ;
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
2022-10-04 15:49:00 +02:00
mutex_lock ( & info - > lock ) ;
2014-07-23 22:24:00 +01:00
2020-06-24 01:30:11 +02:00
ret = rockchip_saradc_conversion ( info , chan ) ;
if ( ret ) {
rockchip_saradc_power_down ( info ) ;
2022-10-04 15:49:00 +02:00
mutex_unlock ( & info - > lock ) ;
2020-06-24 01:30:11 +02:00
return ret ;
2014-07-23 22:24:00 +01:00
}
* val = info - > last_val ;
2022-10-04 15:49:00 +02:00
mutex_unlock ( & info - > lock ) ;
2014-07-23 22:24:00 +01:00
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SCALE :
2021-08-10 09:10:07 +08:00
* val = info - > uv_vref / 1000 ;
2020-06-24 01:30:11 +02:00
* val2 = chan - > scan_type . realbits ;
2014-07-23 22:24:00 +01:00
return IIO_VAL_FRACTIONAL_LOG2 ;
default :
return - EINVAL ;
}
}
static irqreturn_t rockchip_saradc_isr ( int irq , void * dev_id )
{
2017-04-01 19:36:14 +05:30
struct rockchip_saradc * info = dev_id ;
2014-07-23 22:24:00 +01:00
/* Read value */
2023-06-04 00:23:33 +05:30
info - > last_val = rockchip_saradc_read ( info ) ;
2020-06-24 01:30:11 +02:00
info - > last_val & = GENMASK ( info - > last_chan - > scan_type . realbits - 1 , 0 ) ;
2014-07-23 22:24:00 +01:00
2020-06-24 01:30:11 +02:00
rockchip_saradc_power_down ( info ) ;
2014-07-23 22:24:00 +01:00
complete ( & info - > completion ) ;
return IRQ_HANDLED ;
}
static const struct iio_info rockchip_saradc_iio_info = {
. read_raw = rockchip_saradc_read_raw ,
} ;
2020-06-24 01:30:11 +02:00
# define SARADC_CHANNEL(_index, _id, _res) { \
2014-07-23 22:24:00 +01:00
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. channel = _index , \
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) , \
. datasheet_name = _id , \
2020-06-24 01:30:11 +02:00
. scan_index = _index , \
. scan_type = { \
. sign = ' u ' , \
. realbits = _res , \
. storagebits = 16 , \
. endianness = IIO_CPU , \
} , \
2014-07-23 22:24:00 +01:00
}
static const struct iio_chan_spec rockchip_saradc_iio_channels [ ] = {
2020-06-24 01:30:11 +02:00
SARADC_CHANNEL ( 0 , " adc0 " , 10 ) ,
SARADC_CHANNEL ( 1 , " adc1 " , 10 ) ,
SARADC_CHANNEL ( 2 , " adc2 " , 10 ) ,
2014-07-23 22:24:00 +01:00
} ;
2014-09-15 22:47:00 +01:00
static const struct rockchip_saradc_data saradc_data = {
. channels = rockchip_saradc_iio_channels ,
. num_channels = ARRAY_SIZE ( rockchip_saradc_iio_channels ) ,
. clk_rate = 1000000 ,
2023-06-04 00:23:33 +05:30
. start = rockchip_saradc_start_v1 ,
. read = rockchip_saradc_read_v1 ,
. power_down = rockchip_saradc_power_down_v1 ,
2014-09-15 22:47:00 +01:00
} ;
static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels [ ] = {
2020-06-24 01:30:11 +02:00
SARADC_CHANNEL ( 0 , " adc0 " , 12 ) ,
SARADC_CHANNEL ( 1 , " adc1 " , 12 ) ,
2014-09-15 22:47:00 +01:00
} ;
static const struct rockchip_saradc_data rk3066_tsadc_data = {
. channels = rockchip_rk3066_tsadc_iio_channels ,
. num_channels = ARRAY_SIZE ( rockchip_rk3066_tsadc_iio_channels ) ,
. clk_rate = 50000 ,
2023-06-04 00:23:33 +05:30
. start = rockchip_saradc_start_v1 ,
. read = rockchip_saradc_read_v1 ,
. power_down = rockchip_saradc_power_down_v1 ,
2014-09-15 22:47:00 +01:00
} ;
2016-03-16 01:44:15 +08:00
static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels [ ] = {
2020-06-24 01:30:11 +02:00
SARADC_CHANNEL ( 0 , " adc0 " , 10 ) ,
SARADC_CHANNEL ( 1 , " adc1 " , 10 ) ,
SARADC_CHANNEL ( 2 , " adc2 " , 10 ) ,
SARADC_CHANNEL ( 3 , " adc3 " , 10 ) ,
SARADC_CHANNEL ( 4 , " adc4 " , 10 ) ,
SARADC_CHANNEL ( 5 , " adc5 " , 10 ) ,
2016-03-16 01:44:15 +08:00
} ;
static const struct rockchip_saradc_data rk3399_saradc_data = {
. channels = rockchip_rk3399_saradc_iio_channels ,
. num_channels = ARRAY_SIZE ( rockchip_rk3399_saradc_iio_channels ) ,
. clk_rate = 1000000 ,
2023-06-04 00:23:33 +05:30
. start = rockchip_saradc_start_v1 ,
. read = rockchip_saradc_read_v1 ,
. power_down = rockchip_saradc_power_down_v1 ,
2016-03-16 01:44:15 +08:00
} ;
2021-07-12 09:45:07 +08:00
static const struct iio_chan_spec rockchip_rk3568_saradc_iio_channels [ ] = {
SARADC_CHANNEL ( 0 , " adc0 " , 10 ) ,
SARADC_CHANNEL ( 1 , " adc1 " , 10 ) ,
SARADC_CHANNEL ( 2 , " adc2 " , 10 ) ,
SARADC_CHANNEL ( 3 , " adc3 " , 10 ) ,
SARADC_CHANNEL ( 4 , " adc4 " , 10 ) ,
SARADC_CHANNEL ( 5 , " adc5 " , 10 ) ,
SARADC_CHANNEL ( 6 , " adc6 " , 10 ) ,
SARADC_CHANNEL ( 7 , " adc7 " , 10 ) ,
} ;
static const struct rockchip_saradc_data rk3568_saradc_data = {
. channels = rockchip_rk3568_saradc_iio_channels ,
. num_channels = ARRAY_SIZE ( rockchip_rk3568_saradc_iio_channels ) ,
. clk_rate = 1000000 ,
2023-06-04 00:23:33 +05:30
. start = rockchip_saradc_start_v1 ,
. read = rockchip_saradc_read_v1 ,
. power_down = rockchip_saradc_power_down_v1 ,
2021-07-12 09:45:07 +08:00
} ;
2023-06-04 00:23:34 +05:30
static const struct iio_chan_spec rockchip_rk3588_saradc_iio_channels [ ] = {
SARADC_CHANNEL ( 0 , " adc0 " , 12 ) ,
SARADC_CHANNEL ( 1 , " adc1 " , 12 ) ,
SARADC_CHANNEL ( 2 , " adc2 " , 12 ) ,
SARADC_CHANNEL ( 3 , " adc3 " , 12 ) ,
SARADC_CHANNEL ( 4 , " adc4 " , 12 ) ,
SARADC_CHANNEL ( 5 , " adc5 " , 12 ) ,
SARADC_CHANNEL ( 6 , " adc6 " , 12 ) ,
SARADC_CHANNEL ( 7 , " adc7 " , 12 ) ,
} ;
static const struct rockchip_saradc_data rk3588_saradc_data = {
. channels = rockchip_rk3588_saradc_iio_channels ,
. num_channels = ARRAY_SIZE ( rockchip_rk3588_saradc_iio_channels ) ,
. clk_rate = 1000000 ,
. start = rockchip_saradc_start_v2 ,
. read = rockchip_saradc_read_v2 ,
} ;
2014-09-15 22:47:00 +01:00
static const struct of_device_id rockchip_saradc_match [ ] = {
{
. compatible = " rockchip,saradc " ,
. data = & saradc_data ,
} , {
. compatible = " rockchip,rk3066-tsadc " ,
. data = & rk3066_tsadc_data ,
2016-03-16 01:44:15 +08:00
} , {
. compatible = " rockchip,rk3399-saradc " ,
. data = & rk3399_saradc_data ,
2021-07-12 09:45:07 +08:00
} , {
. compatible = " rockchip,rk3568-saradc " ,
. data = & rk3568_saradc_data ,
2023-06-04 00:23:34 +05:30
} , {
. compatible = " rockchip,rk3588-saradc " ,
. data = & rk3588_saradc_data ,
2014-09-15 22:47:00 +01:00
} ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , rockchip_saradc_match ) ;
2020-07-17 17:55:38 +01:00
/*
2016-07-27 22:24:04 +08:00
* Reset SARADC Controller .
*/
static void rockchip_saradc_reset_controller ( struct reset_control * reset )
{
reset_control_assert ( reset ) ;
usleep_range ( 10 , 20 ) ;
reset_control_deassert ( reset ) ;
}
2020-06-24 01:30:09 +02:00
static void rockchip_saradc_regulator_disable ( void * data )
{
struct rockchip_saradc * info = data ;
regulator_disable ( info - > vref ) ;
}
2020-06-24 01:30:11 +02:00
static irqreturn_t rockchip_saradc_trigger_handler ( int irq , void * p )
{
struct iio_poll_func * pf = p ;
struct iio_dev * i_dev = pf - > indio_dev ;
struct rockchip_saradc * info = iio_priv ( i_dev ) ;
/*
* @ values : each channel takes an u16 value
* @ timestamp : will be 8 - byte aligned automatically
*/
struct {
u16 values [ SARADC_MAX_CHANNELS ] ;
int64_t timestamp ;
} data ;
int ret ;
int i , j = 0 ;
2022-10-04 15:49:00 +02:00
mutex_lock ( & info - > lock ) ;
2020-06-24 01:30:11 +02:00
for_each_set_bit ( i , i_dev - > active_scan_mask , i_dev - > masklength ) {
const struct iio_chan_spec * chan = & i_dev - > channels [ i ] ;
ret = rockchip_saradc_conversion ( info , chan ) ;
if ( ret ) {
rockchip_saradc_power_down ( info ) ;
goto out ;
}
data . values [ j ] = info - > last_val ;
j + + ;
}
iio_push_to_buffers_with_timestamp ( i_dev , & data , iio_get_time_ns ( i_dev ) ) ;
out :
2022-10-04 15:49:00 +02:00
mutex_unlock ( & info - > lock ) ;
2020-06-24 01:30:11 +02:00
iio_trigger_notify_done ( i_dev - > trig ) ;
return IRQ_HANDLED ;
}
2021-08-10 09:10:07 +08:00
static int rockchip_saradc_volt_notify ( struct notifier_block * nb ,
2023-06-04 00:23:37 +05:30
unsigned long event , void * data )
2021-08-10 09:10:07 +08:00
{
struct rockchip_saradc * info =
container_of ( nb , struct rockchip_saradc , nb ) ;
if ( event & REGULATOR_EVENT_VOLTAGE_CHANGE )
info - > uv_vref = ( unsigned long ) data ;
return NOTIFY_OK ;
}
static void rockchip_saradc_regulator_unreg_notifier ( void * data )
{
struct rockchip_saradc * info = data ;
regulator_unregister_notifier ( info - > vref , & info - > nb ) ;
}
2014-07-23 22:24:00 +01:00
static int rockchip_saradc_probe ( struct platform_device * pdev )
{
2023-06-04 00:23:36 +05:30
const struct rockchip_saradc_data * match_data ;
2014-07-23 22:24:00 +01:00
struct rockchip_saradc * info = NULL ;
struct device_node * np = pdev - > dev . of_node ;
struct iio_dev * indio_dev = NULL ;
int ret ;
int irq ;
if ( ! np )
return - ENODEV ;
indio_dev = devm_iio_device_alloc ( & pdev - > dev , sizeof ( * info ) ) ;
2023-06-04 00:23:38 +05:30
if ( ! indio_dev )
return dev_err_probe ( & pdev - > dev , - ENOMEM ,
" failed allocating iio device \n " ) ;
2014-07-23 22:24:00 +01:00
info = iio_priv ( indio_dev ) ;
2023-06-04 00:23:36 +05:30
match_data = of_device_get_match_data ( & pdev - > dev ) ;
2023-06-04 00:23:38 +05:30
if ( ! match_data )
return dev_err_probe ( & pdev - > dev , - ENODEV ,
" failed to match device \n " ) ;
2017-07-07 01:51:31 -05:00
2023-06-04 00:23:36 +05:30
info - > data = match_data ;
2014-09-15 22:47:00 +01:00
2020-06-24 01:30:11 +02:00
/* Sanity check for possible later IP variants with more channels */
2023-06-04 00:23:38 +05:30
if ( info - > data - > num_channels > SARADC_MAX_CHANNELS )
return dev_err_probe ( & pdev - > dev , - EINVAL ,
" max channels exceeded " ) ;
2020-06-24 01:30:11 +02:00
2021-09-08 18:56:30 +08:00
info - > regs = devm_platform_ioremap_resource ( pdev , 0 ) ;
2014-07-23 22:24:00 +01:00
if ( IS_ERR ( info - > regs ) )
return PTR_ERR ( info - > regs ) ;
2016-07-27 22:24:04 +08:00
/*
* The reset should be an optional property , as it should work
* with old devicetrees as well
*/
2017-07-19 17:25:35 +02:00
info - > reset = devm_reset_control_get_exclusive ( & pdev - > dev ,
" saradc-apb " ) ;
2016-07-27 22:24:04 +08:00
if ( IS_ERR ( info - > reset ) ) {
ret = PTR_ERR ( info - > reset ) ;
if ( ret ! = - ENOENT )
2021-10-08 17:28:56 +08:00
return dev_err_probe ( & pdev - > dev , ret ,
" failed to get saradc-apb \n " ) ;
2016-07-27 22:24:04 +08:00
dev_dbg ( & pdev - > dev , " no reset control found \n " ) ;
info - > reset = NULL ;
}
2014-07-23 22:24:00 +01:00
init_completion ( & info - > completion ) ;
irq = platform_get_irq ( pdev , 0 ) ;
2019-07-30 11:15:19 -07:00
if ( irq < 0 )
2023-07-27 15:39:12 +08:00
return irq ;
2014-07-23 22:24:00 +01:00
ret = devm_request_irq ( & pdev - > dev , irq , rockchip_saradc_isr ,
0 , dev_name ( & pdev - > dev ) , info ) ;
if ( ret < 0 ) {
dev_err ( & pdev - > dev , " failed requesting irq %d \n " , irq ) ;
return ret ;
}
info - > vref = devm_regulator_get ( & pdev - > dev , " vref " ) ;
2021-10-08 17:28:56 +08:00
if ( IS_ERR ( info - > vref ) )
return dev_err_probe ( & pdev - > dev , PTR_ERR ( info - > vref ) ,
" failed to get regulator \n " ) ;
2014-07-23 22:24:00 +01:00
2016-07-27 22:24:04 +08:00
if ( info - > reset )
rockchip_saradc_reset_controller ( info - > reset ) ;
2014-07-23 22:24:00 +01:00
/*
2014-09-15 22:47:00 +01:00
* Use a default value for the converter clock .
2014-07-23 22:24:00 +01:00
* This may become user - configurable in the future .
*/
2014-09-15 22:47:00 +01:00
ret = clk_set_rate ( info - > clk , info - > data - > clk_rate ) ;
2023-06-04 00:23:38 +05:30
if ( ret < 0 )
return dev_err_probe ( & pdev - > dev , ret ,
" failed to set adc clk rate \n " ) ;
2014-07-23 22:24:00 +01:00
ret = regulator_enable ( info - > vref ) ;
2023-06-04 00:23:38 +05:30
if ( ret < 0 )
return dev_err_probe ( & pdev - > dev , ret ,
" failed to enable vref regulator \n " ) ;
2020-06-24 01:30:09 +02:00
ret = devm_add_action_or_reset ( & pdev - > dev ,
rockchip_saradc_regulator_disable , info ) ;
2023-06-04 00:23:38 +05:30
if ( ret )
return dev_err_probe ( & pdev - > dev , ret ,
" failed to register devm action \n " ) ;
2014-07-23 22:24:00 +01:00
2021-08-10 09:10:07 +08:00
ret = regulator_get_voltage ( info - > vref ) ;
if ( ret < 0 )
return ret ;
info - > uv_vref = ret ;
2023-06-04 00:23:35 +05:30
info - > pclk = devm_clk_get_enabled ( & pdev - > dev , " apb_pclk " ) ;
if ( IS_ERR ( info - > pclk ) )
return dev_err_probe ( & pdev - > dev , PTR_ERR ( info - > pclk ) ,
" failed to get pclk \n " ) ;
2014-07-23 22:24:00 +01:00
2023-06-04 00:23:35 +05:30
info - > clk = devm_clk_get_enabled ( & pdev - > dev , " saradc " ) ;
if ( IS_ERR ( info - > clk ) )
return dev_err_probe ( & pdev - > dev , PTR_ERR ( info - > clk ) ,
" failed to get adc clock \n " ) ;
2014-07-23 22:24:00 +01:00
platform_set_drvdata ( pdev , indio_dev ) ;
indio_dev - > name = dev_name ( & pdev - > dev ) ;
indio_dev - > info = & rockchip_saradc_iio_info ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
2014-09-15 22:47:00 +01:00
indio_dev - > channels = info - > data - > channels ;
indio_dev - > num_channels = info - > data - > num_channels ;
2020-06-24 01:30:11 +02:00
ret = devm_iio_triggered_buffer_setup ( & indio_dev - > dev , indio_dev , NULL ,
rockchip_saradc_trigger_handler ,
NULL ) ;
if ( ret )
return ret ;
2014-07-23 22:24:00 +01:00
2021-08-10 09:10:07 +08:00
info - > nb . notifier_call = rockchip_saradc_volt_notify ;
ret = regulator_register_notifier ( info - > vref , & info - > nb ) ;
if ( ret )
return ret ;
ret = devm_add_action_or_reset ( & pdev - > dev ,
rockchip_saradc_regulator_unreg_notifier ,
info ) ;
if ( ret )
return ret ;
2022-10-04 15:49:00 +02:00
mutex_init ( & info - > lock ) ;
2020-06-24 01:30:09 +02:00
return devm_iio_device_register ( & pdev - > dev , indio_dev ) ;
2014-07-23 22:24:00 +01:00
}
static int rockchip_saradc_suspend ( struct device * dev )
{
struct iio_dev * indio_dev = dev_get_drvdata ( dev ) ;
struct rockchip_saradc * info = iio_priv ( indio_dev ) ;
clk_disable_unprepare ( info - > clk ) ;
clk_disable_unprepare ( info - > pclk ) ;
regulator_disable ( info - > vref ) ;
return 0 ;
}
static int rockchip_saradc_resume ( struct device * dev )
{
struct iio_dev * indio_dev = dev_get_drvdata ( dev ) ;
struct rockchip_saradc * info = iio_priv ( indio_dev ) ;
int ret ;
ret = regulator_enable ( info - > vref ) ;
if ( ret )
return ret ;
ret = clk_prepare_enable ( info - > pclk ) ;
if ( ret )
return ret ;
ret = clk_prepare_enable ( info - > clk ) ;
if ( ret )
2020-11-03 20:07:43 +08:00
clk_disable_unprepare ( info - > pclk ) ;
2014-07-23 22:24:00 +01:00
return ret ;
}
2022-01-30 19:31:10 +00:00
static DEFINE_SIMPLE_DEV_PM_OPS ( rockchip_saradc_pm_ops ,
rockchip_saradc_suspend ,
rockchip_saradc_resume ) ;
2014-07-23 22:24:00 +01:00
static struct platform_driver rockchip_saradc_driver = {
. probe = rockchip_saradc_probe ,
. driver = {
. name = " rockchip-saradc " ,
. of_match_table = rockchip_saradc_match ,
2022-01-30 19:31:10 +00:00
. pm = pm_sleep_ptr ( & rockchip_saradc_pm_ops ) ,
2014-07-23 22:24:00 +01:00
} ,
} ;
module_platform_driver ( rockchip_saradc_driver ) ;
2015-05-25 22:36:58 +02:00
MODULE_AUTHOR ( " Heiko Stuebner <heiko@sntech.de> " ) ;
MODULE_DESCRIPTION ( " Rockchip SARADC driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;