iio: adc: rockchip_saradc: add support rk3588 new saradc
Refactor conversion operation to support new saradc, separate start, read, powerdown in respective hooks. Change-Id: Iacb043d14f7867b45bf0c4c74c2bedd21d398944 Signed-off-by: Simon Xue <xxm@rock-chips.com>
This commit is contained in:
@ -46,10 +46,29 @@
|
||||
#define SARADC_TIMEOUT msecs_to_jiffies(100)
|
||||
#define SARADC_MAX_CHANNELS 8
|
||||
|
||||
/* v2 registers */
|
||||
#define SARADC2_CONV_CON 0x0
|
||||
#define SARADC_T_PD_SOC 0x4
|
||||
#define SARADC_T_DAS_SOC 0xc
|
||||
#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)
|
||||
|
||||
struct rockchip_saradc;
|
||||
|
||||
struct rockchip_saradc_data {
|
||||
const struct iio_chan_spec *channels;
|
||||
int num_channels;
|
||||
unsigned long clk_rate;
|
||||
void (*start)(struct rockchip_saradc *info, int chn);
|
||||
int (*read)(struct rockchip_saradc *info);
|
||||
void (*power_down)(struct rockchip_saradc *info);
|
||||
};
|
||||
|
||||
struct rockchip_saradc {
|
||||
@ -64,18 +83,83 @@ struct rockchip_saradc {
|
||||
u16 last_val;
|
||||
bool suspended;
|
||||
#ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN
|
||||
struct timer_list timer;
|
||||
bool test;
|
||||
u32 chn;
|
||||
spinlock_t lock;
|
||||
struct workqueue_struct *wq;
|
||||
struct delayed_work work;
|
||||
#endif
|
||||
const struct iio_chan_spec *last_chan;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void rockchip_saradc_start_v2(struct rockchip_saradc *info,
|
||||
int chn)
|
||||
{
|
||||
int val;
|
||||
|
||||
/* If read other chn at anytime, then chn1 will error, assert
|
||||
* controller as a workaround.
|
||||
*/
|
||||
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 = SARADC2_EN_END_INT << 16 | SARADC2_EN_END_INT;
|
||||
writel_relaxed(val, info->regs + SARADC2_END_INT_EN);
|
||||
val = SARADC2_START | SARADC2_SINGLE_MODE | chn;
|
||||
writel(val << 16 | val, info->regs + SARADC2_CONV_CON);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
writel_relaxed(0, info->regs + SARADC_CTRL);
|
||||
}
|
||||
|
||||
static void rockchip_saradc_power_down(struct rockchip_saradc *info)
|
||||
{
|
||||
/* Clear irq & power down adc */
|
||||
writel_relaxed(0, info->regs + SARADC_CTRL);
|
||||
if (info->data->power_down)
|
||||
info->data->power_down(info);
|
||||
}
|
||||
|
||||
static int rockchip_saradc_conversion(struct rockchip_saradc *info,
|
||||
@ -83,16 +167,9 @@ static int rockchip_saradc_conversion(struct rockchip_saradc *info,
|
||||
{
|
||||
reinit_completion(&info->completion);
|
||||
|
||||
/* 8 clock periods as delay between power up and start cmd */
|
||||
writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
|
||||
|
||||
/* prevent isr get NULL last_chan */
|
||||
info->last_chan = chan;
|
||||
|
||||
/* Select the channel to be used and trigger conversion */
|
||||
writel(SARADC_CTRL_POWER_CTRL
|
||||
| (chan->channel & SARADC_CTRL_CHN_MASK)
|
||||
| SARADC_CTRL_IRQ_ENABLE,
|
||||
info->regs + SARADC_CTRL);
|
||||
rockchip_saradc_start(info, chan->channel);
|
||||
|
||||
if (!wait_for_completion_timeout(&info->completion, SARADC_TIMEOUT))
|
||||
return -ETIMEDOUT;
|
||||
@ -151,7 +228,7 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)
|
||||
#endif
|
||||
|
||||
/* Read value */
|
||||
info->last_val = readl_relaxed(info->regs + SARADC_DATA);
|
||||
info->last_val = rockchip_saradc_read(info);
|
||||
info->last_val &= GENMASK(info->last_chan->scan_type.realbits - 1, 0);
|
||||
|
||||
rockchip_saradc_power_down(info);
|
||||
@ -161,7 +238,7 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
if (info->test) {
|
||||
pr_info("chn[%d] val = %d\n", info->chn, info->last_val);
|
||||
mod_timer(&info->timer, jiffies + HZ/1000);
|
||||
mod_delayed_work(info->wq, &info->work, msecs_to_jiffies(100));
|
||||
}
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
#endif
|
||||
@ -198,6 +275,9 @@ static const struct rockchip_saradc_data saradc_data = {
|
||||
.channels = rockchip_saradc_iio_channels,
|
||||
.num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels),
|
||||
.clk_rate = 1000000,
|
||||
.start = rockchip_saradc_start_v1,
|
||||
.read = rockchip_saradc_read_v1,
|
||||
.power_down = rockchip_saradc_power_down_v1,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = {
|
||||
@ -209,6 +289,9 @@ 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,
|
||||
.start = rockchip_saradc_start_v1,
|
||||
.read = rockchip_saradc_read_v1,
|
||||
.power_down = rockchip_saradc_power_down_v1,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
|
||||
@ -224,6 +307,9 @@ 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,
|
||||
.start = rockchip_saradc_start_v1,
|
||||
.read = rockchip_saradc_read_v1,
|
||||
.power_down = rockchip_saradc_power_down_v1,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec rockchip_rk3568_saradc_iio_channels[] = {
|
||||
@ -241,6 +327,28 @@ 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,
|
||||
.start = rockchip_saradc_start_v1,
|
||||
.read = rockchip_saradc_read_v1,
|
||||
.power_down = rockchip_saradc_power_down_v1,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
static const struct of_device_id rockchip_saradc_match[] = {
|
||||
@ -256,6 +364,9 @@ static const struct of_device_id rockchip_saradc_match[] = {
|
||||
}, {
|
||||
.compatible = "rockchip,rk3568-saradc",
|
||||
.data = &rk3568_saradc_data,
|
||||
}, {
|
||||
.compatible = "rockchip,rk3588-saradc",
|
||||
.data = &rk3588_saradc_data,
|
||||
},
|
||||
{},
|
||||
};
|
||||
@ -293,18 +404,6 @@ static void rockchip_saradc_regulator_disable(void *data)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN
|
||||
static void rockchip_saradc_timer(struct timer_list *t)
|
||||
{
|
||||
struct rockchip_saradc *info = from_timer(info, t, timer);
|
||||
|
||||
/* 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 | (info->chn & SARADC_CTRL_CHN_MASK) |
|
||||
SARADC_CTRL_IRQ_ENABLE, info->regs + SARADC_CTRL);
|
||||
}
|
||||
|
||||
static ssize_t saradc_test_chn_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
@ -323,15 +422,15 @@ static ssize_t saradc_test_chn_store(struct device *dev,
|
||||
|
||||
if (val > SARADC_CTRL_CHN_MASK && info->test) {
|
||||
info->test = false;
|
||||
del_timer_sync(&info->timer);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
cancel_delayed_work_sync(&info->work);
|
||||
return size;
|
||||
}
|
||||
|
||||
if (!info->test && val < SARADC_CTRL_CHN_MASK) {
|
||||
info->test = true;
|
||||
info->chn = val;
|
||||
mod_timer(&info->timer, jiffies + HZ/1000);
|
||||
mod_delayed_work(info->wq, &info->work, msecs_to_jiffies(100));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
@ -356,6 +455,21 @@ static void rockchip_saradc_remove_sysgroup(void *data)
|
||||
|
||||
sysfs_remove_group(&pdev->dev.kobj, &rockchip_saradc_attr_group);
|
||||
}
|
||||
|
||||
static void rockchip_saradc_destroy_wq(void *data)
|
||||
{
|
||||
struct rockchip_saradc *info = data;
|
||||
|
||||
destroy_workqueue(info->wq);
|
||||
}
|
||||
|
||||
static void rockchip_saradc_test_work(struct work_struct *work)
|
||||
{
|
||||
struct rockchip_saradc *info = container_of(work,
|
||||
struct rockchip_saradc, work.work);
|
||||
|
||||
rockchip_saradc_start(info, info->chn);
|
||||
}
|
||||
#endif
|
||||
|
||||
static irqreturn_t rockchip_saradc_trigger_handler(int irq, void *p)
|
||||
@ -562,8 +676,9 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN
|
||||
info->wq = create_singlethread_workqueue("adc_wq");
|
||||
INIT_DELAYED_WORK(&info->work, rockchip_saradc_test_work);
|
||||
spin_lock_init(&info->lock);
|
||||
timer_setup(&info->timer, rockchip_saradc_timer, 0);
|
||||
ret = sysfs_create_group(&pdev->dev.kobj, &rockchip_saradc_attr_group);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -575,6 +690,14 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(&pdev->dev,
|
||||
rockchip_saradc_destroy_wq, info);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register destroy_wq, %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return devm_iio_device_register(&pdev->dev, indio_dev);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user