diff options
Diffstat (limited to 'drivers/iio/adc/imx8qxp-adc.c')
| -rw-r--r-- | drivers/iio/adc/imx8qxp-adc.c | 49 |
1 files changed, 26 insertions, 23 deletions
diff --git a/drivers/iio/adc/imx8qxp-adc.c b/drivers/iio/adc/imx8qxp-adc.c index 901dd8e1b32f..6fc50394ad90 100644 --- a/drivers/iio/adc/imx8qxp-adc.c +++ b/drivers/iio/adc/imx8qxp-adc.c @@ -19,6 +19,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -37,8 +38,8 @@ #define IMX8QXP_ADR_ADC_FCTRL 0x30 #define IMX8QXP_ADR_ADC_SWTRIG 0x34 #define IMX8QXP_ADR_ADC_TCTRL(tid) (0xc0 + (tid) * 4) -#define IMX8QXP_ADR_ADC_CMDH(cid) (0x100 + (cid) * 8) -#define IMX8QXP_ADR_ADC_CMDL(cid) (0x104 + (cid) * 8) +#define IMX8QXP_ADR_ADC_CMDL(cid) (0x100 + (cid) * 8) +#define IMX8QXP_ADR_ADC_CMDH(cid) (0x104 + (cid) * 8) #define IMX8QXP_ADR_ADC_RESFIFO 0x300 #define IMX8QXP_ADR_ADC_TST 0xffc @@ -85,6 +86,8 @@ #define IMX8QXP_ADC_TIMEOUT msecs_to_jiffies(100) +#define IMX8QXP_ADC_MAX_FIFO_SIZE 16 + struct imx8qxp_adc { struct device *dev; void __iomem *regs; @@ -94,6 +97,7 @@ struct imx8qxp_adc { /* Serialise ADC channel reads */ struct mutex lock; struct completion completion; + u32 fifo[IMX8QXP_ADC_MAX_FIFO_SIZE]; }; #define IMX8QXP_ADC_CHAN(_idx) { \ @@ -201,7 +205,7 @@ static int imx8qxp_adc_read_raw(struct iio_dev *indio_dev, struct imx8qxp_adc *adc = iio_priv(indio_dev); struct device *dev = adc->dev; - u32 ctrl, vref_uv; + u32 ctrl; long ret; switch (mask) { @@ -225,7 +229,6 @@ static int imx8qxp_adc_read_raw(struct iio_dev *indio_dev, ret = wait_for_completion_interruptible_timeout(&adc->completion, IMX8QXP_ADC_TIMEOUT); - pm_runtime_mark_last_busy(dev); pm_runtime_put_sync_autosuspend(dev); if (ret == 0) { @@ -237,15 +240,16 @@ static int imx8qxp_adc_read_raw(struct iio_dev *indio_dev, return ret; } - *val = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK, - readl(adc->regs + IMX8QXP_ADR_ADC_RESFIFO)); + *val = adc->fifo[0]; mutex_unlock(&adc->lock); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - vref_uv = regulator_get_voltage(adc->vref); - *val = vref_uv / 1000; + ret = regulator_get_voltage(adc->vref); + if (ret < 0) + return ret; + *val = ret / 1000; *val2 = 12; return IIO_VAL_FRACTIONAL_LOG2; @@ -262,10 +266,15 @@ static irqreturn_t imx8qxp_adc_isr(int irq, void *dev_id) { struct imx8qxp_adc *adc = dev_id; u32 fifo_count; + int i; fifo_count = FIELD_GET(IMX8QXP_ADC_FCTRL_FCOUNT_MASK, readl(adc->regs + IMX8QXP_ADR_ADC_FCTRL)); + for (i = 0; i < fifo_count; i++) + adc->fifo[i] = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK, + readl_relaxed(adc->regs + IMX8QXP_ADR_ADC_RESFIFO)); + if (fifo_count) complete(&adc->completion); @@ -285,7 +294,6 @@ static int imx8qxp_adc_reg_access(struct iio_dev *indio_dev, unsigned int reg, *readval = readl(adc->regs + reg); - pm_runtime_mark_last_busy(dev); pm_runtime_put_sync_autosuspend(dev); return 0; @@ -305,10 +313,8 @@ static int imx8qxp_adc_probe(struct platform_device *pdev) int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*adc)); - if (!indio_dev) { - dev_err(dev, "Failed allocating iio device\n"); + if (!indio_dev) return -ENOMEM; - } adc = iio_priv(indio_dev); adc->dev = dev; @@ -394,7 +400,7 @@ error_regulator_disable: return ret; } -static int imx8qxp_adc_remove(struct platform_device *pdev) +static void imx8qxp_adc_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct imx8qxp_adc *adc = iio_priv(indio_dev); @@ -412,11 +418,9 @@ static int imx8qxp_adc_remove(struct platform_device *pdev) pm_runtime_disable(dev); pm_runtime_put_noidle(dev); - - return 0; } -static __maybe_unused int imx8qxp_adc_runtime_suspend(struct device *dev) +static int imx8qxp_adc_runtime_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct imx8qxp_adc *adc = iio_priv(indio_dev); @@ -430,7 +434,7 @@ static __maybe_unused int imx8qxp_adc_runtime_suspend(struct device *dev) return 0; } -static __maybe_unused int imx8qxp_adc_runtime_resume(struct device *dev) +static int imx8qxp_adc_runtime_resume(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct imx8qxp_adc *adc = iio_priv(indio_dev); @@ -467,14 +471,13 @@ err_disable_reg: return ret; } -static const struct dev_pm_ops imx8qxp_adc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(imx8qxp_adc_runtime_suspend, imx8qxp_adc_runtime_resume, NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(imx8qxp_adc_pm_ops, + imx8qxp_adc_runtime_suspend, + imx8qxp_adc_runtime_resume, NULL); static const struct of_device_id imx8qxp_adc_match[] = { { .compatible = "nxp,imx8qxp-adc", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, imx8qxp_adc_match); @@ -484,7 +487,7 @@ static struct platform_driver imx8qxp_adc_driver = { .driver = { .name = ADC_DRIVER_NAME, .of_match_table = imx8qxp_adc_match, - .pm = &imx8qxp_adc_pm_ops, + .pm = pm_ptr(&imx8qxp_adc_pm_ops), }, }; |
