diff options
Diffstat (limited to 'drivers/iio/adc/lpc18xx_adc.c')
| -rw-r--r-- | drivers/iio/adc/lpc18xx_adc.c | 90 |
1 files changed, 33 insertions, 57 deletions
diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c index 041dc4a3f66c..7e5d181ff702 100644 --- a/drivers/iio/adc/lpc18xx_adc.c +++ b/drivers/iio/adc/lpc18xx_adc.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * IIO ADC driver for NXP LPC18xx ADC * * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com> * - * 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. - * * UNSUPPORTED hardware features: * - Hardware triggers * - Burst mode @@ -20,10 +17,9 @@ #include <linux/iio/driver.h> #include <linux/io.h> #include <linux/iopoll.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> @@ -118,11 +114,22 @@ static const struct iio_info lpc18xx_adc_info = { .read_raw = lpc18xx_adc_read_raw, }; +static void lpc18xx_clear_cr_reg(void *data) +{ + struct lpc18xx_adc *adc = data; + + writel(0, adc->base + LPC18XX_ADC_CR); +} + +static void lpc18xx_regulator_disable(void *vref) +{ + regulator_disable(vref); +} + static int lpc18xx_adc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; struct lpc18xx_adc *adc; - struct resource *res; unsigned int clkdiv; unsigned long rate; int ret; @@ -131,33 +138,25 @@ static int lpc18xx_adc_probe(struct platform_device *pdev) if (!indio_dev) return -ENOMEM; - platform_set_drvdata(pdev, indio_dev); adc = iio_priv(indio_dev); adc->dev = &pdev->dev; mutex_init(&adc->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - adc->base = devm_ioremap_resource(&pdev->dev, res); + adc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(adc->base)) return PTR_ERR(adc->base); - adc->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(adc->clk)) { - dev_err(&pdev->dev, "error getting clock\n"); - return PTR_ERR(adc->clk); - } - - rate = clk_get_rate(adc->clk); - clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET); + adc->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(adc->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(adc->clk), + "error getting clock\n"); adc->vref = devm_regulator_get(&pdev->dev, "vref"); - if (IS_ERR(adc->vref)) { - dev_err(&pdev->dev, "error getting regulator\n"); - return PTR_ERR(adc->vref); - } + if (IS_ERR(adc->vref)) + return dev_err_probe(&pdev->dev, PTR_ERR(adc->vref), + "error getting regulator\n"); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &lpc18xx_adc_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = lpc18xx_adc_iio_channels; @@ -169,55 +168,32 @@ static int lpc18xx_adc_probe(struct platform_device *pdev) return ret; } - ret = clk_prepare_enable(adc->clk); - if (ret) { - dev_err(&pdev->dev, "unable to enable clock\n"); - goto dis_reg; - } + ret = devm_add_action_or_reset(&pdev->dev, lpc18xx_regulator_disable, adc->vref); + if (ret) + return ret; + + rate = clk_get_rate(adc->clk); + clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET); adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) | LPC18XX_ADC_CR_PDN; writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR); - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&pdev->dev, "unable to register device\n"); - goto dis_clk; - } - - return 0; - -dis_clk: - writel(0, adc->base + LPC18XX_ADC_CR); - clk_disable_unprepare(adc->clk); -dis_reg: - regulator_disable(adc->vref); - return ret; -} - -static int lpc18xx_adc_remove(struct platform_device *pdev) -{ - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - struct lpc18xx_adc *adc = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - writel(0, adc->base + LPC18XX_ADC_CR); - clk_disable_unprepare(adc->clk); - regulator_disable(adc->vref); + ret = devm_add_action_or_reset(&pdev->dev, lpc18xx_clear_cr_reg, adc); + if (ret) + return ret; - return 0; + return devm_iio_device_register(&pdev->dev, indio_dev); } static const struct of_device_id lpc18xx_adc_match[] = { { .compatible = "nxp,lpc1850-adc" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, lpc18xx_adc_match); static struct platform_driver lpc18xx_adc_driver = { .probe = lpc18xx_adc_probe, - .remove = lpc18xx_adc_remove, .driver = { .name = "lpc18xx-adc", .of_match_table = lpc18xx_adc_match, |
