Merge tag 'iio-for-4.7a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

First round of IIO new device support, features and cleanups for the 4.7 cycle.

New core support
* UV light modifier (for intensity)
* UV light index channel type.

New device support
* hp206c barometer and altimeter
  - new driver.
* mcp4131 potentiometer
  - new driver supporting lots of parts from Microchip.
* mma8452
  - FXLS8471Q support
- NXP LPC18XX SOC ADC
  - new driver.
- NXP LPC18XX SOC DAC
  - new driver.
- rockchip_saradc
  - support rk3399
* st accel
  - h3lis331dl support

Staging driver removals
* adis16204
  - obsolete part making it hard to get parts to test the driver in order
    to clean it up.
* adis16220
  - obsolete part making it hard to get the parts test the driver in order
    to clean it up.

Features
* core
  - convenience functions to claim / release direct access to the device.
    Makes more consistent handling of this corner easier. Used in ad7192 driver.
* ak8975
  - power regulator support.
* at91-sama5d2
  - differential channel support.
* mma8452
  - runtime pm support
  - drop device specific autosleep and use the runtime pm one instead.
* ms5611
  - DT bindings
  - oversampling ratio support

Cleanups and minor fixes
* MAINTAINERS
  - Peter got married - hence name change!

* Documentation
  - Fix a typo in in_proximity_raw description.
  - Add some missing docs for iio_buffer_access_funcs.

* Tools
  - update iio_event_monitor names to match new stuff.
  - make generic_buffer look for triggers ending in -trigger as we let these in
  for a number of drivers a long time back and now it is a fairly common
  option.

Drivers
* staging wide
  - convert bare unsigned usage to unsigned int to comply with coding style.
* non staging wide:
  - since boiler plate gpio handling of interrupts has been moved into the
   ACPI core we don't need to include gpio/consumer.h in a load of drivers so
   drop it.
* ad7606
  - fix an endian casting sparse warning.
* ak8975
  - fix a possible unitialized warning from gcc.
  - drop and unused field left over from earlier cleanups
  - fix a missing regulator_disable on exit.
* at91-sama5d2
  - typo and indentation
  - missing IOMEM dependency.
  - cleanup mode register usage by avoidling erasing whole thing when changing
  the sampling frequency.
* bmc150
  - use the core demux and available_scan_masks to simplify buffer handling
  - optimize the transfers in the trigger handler now we have a magic function
  to emulate bulk reads (under circumstances met here).  This matters with some
  rather dumb i2c adapters in particular.
  - use a single regmap_conf for all bus types as they were all the same.
* bmg160
  - use the core demux and available_scan_masks to simplify the buffer handling
  - optimize the transfers in the trigger handler now we have a magic funciton
  to emulate bulk rads (under circumstances met here).
  - drop gpio interrupt probing from the driver (ACPI) as now handled by the
  ACPI core.
* ina2xx-adc
  - update the CALIB register when RShunt changes.
  - fix scale for VShunt - in reality this error canceled out when used.
* isl29028
  - use regmap to retrieve the struct device instead of carrying a second
  copy of it around.
* kxcjk-1013
  - use core demux
  - optimize i2c transfers in the trigger handler.
* mcp4531
  - refactor to use a pointer to access model parameters instead of indexing
    into the array each time.
* mma8452
  - style fixes
  - avoid swtiching to active whenever the config changes
  - add missin i2c_device_id for mma8451
* mpu6050
  - fix possible NULL dereference.
  - fix the name / chip_id used when ACPI used (otherwise reports as NULL).
* ms5611
  - fix a missing regulator_disable that left the regulator on during removal.
* mxc4005
  - drop gpio interrupt handling for ACPI case from driver as the core now
  handles this case.
* st-sensors
  - note that there are only ever a maximum of 3 axis on current st-sensors
  so just allocate a fixed sized buffer big enough for that.
* tpl0102
  - change the i2c_check_functionality condition to bring it inline with other
    IIO users as EOPNOTSUPP.
* tsl2563
  - replace deprecated flush_scheduled_work
This commit is contained in:
Greg Kroah-Hartman
2016-04-04 12:31:05 -07:00
78 changed files with 2494 additions and 1475 deletions

View File

@@ -134,6 +134,7 @@ config AT91_ADC
config AT91_SAMA5D2_ADC
tristate "Atmel AT91 SAMA5D2 ADC"
depends on ARCH_AT91 || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for Atmel SAMA5D2 ADC which is
available on SAMA5D2 SoC family.
@@ -241,6 +242,16 @@ config LP8788_ADC
To compile this driver as a module, choose M here: the module will be
called lp8788_adc.
config LPC18XX_ADC
tristate "NXP LPC18xx ADC driver"
depends on ARCH_LPC18XX || COMPILE_TEST
depends on OF && HAS_IOMEM
help
Say yes here to build support for NXP LPC18XX ADC.
To compile this driver as a module, choose M here: the module will be
called lpc18xx_adc.
config MAX1027
tristate "Maxim max1027 ADC driver"
depends on SPI

View File

@@ -25,6 +25,7 @@ obj-$(CONFIG_HI8435) += hi8435.o
obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MCP320X) += mcp320x.o

View File

@@ -66,8 +66,10 @@
#define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET)
#define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8
#define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff
#define AT91_SAMA5D2_MR_PRESCAL_MASK GENMASK(15, 8)
/* Startup Time */
#define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16)
#define AT91_SAMA5D2_MR_STARTUP_MASK GENMASK(19, 16)
/* Analog Change */
#define AT91_SAMA5D2_MR_ANACH BIT(23)
/* Tracking Time */
@@ -92,13 +94,13 @@
/* Last Converted Data Register */
#define AT91_SAMA5D2_LCDR 0x20
/* Interrupt Enable Register */
#define AT91_SAMA5D2_IER 0x24
#define AT91_SAMA5D2_IER 0x24
/* Interrupt Disable Register */
#define AT91_SAMA5D2_IDR 0x28
#define AT91_SAMA5D2_IDR 0x28
/* Interrupt Mask Register */
#define AT91_SAMA5D2_IMR 0x2c
#define AT91_SAMA5D2_IMR 0x2c
/* Interrupt Status Register */
#define AT91_SAMA5D2_ISR 0x30
#define AT91_SAMA5D2_ISR 0x30
/* Last Channel Trigger Mode Register */
#define AT91_SAMA5D2_LCTMR 0x34
/* Last Channel Compare Window Register */
@@ -106,17 +108,20 @@
/* Overrun Status Register */
#define AT91_SAMA5D2_OVER 0x3c
/* Extended Mode Register */
#define AT91_SAMA5D2_EMR 0x40
#define AT91_SAMA5D2_EMR 0x40
/* Compare Window Register */
#define AT91_SAMA5D2_CWR 0x44
#define AT91_SAMA5D2_CWR 0x44
/* Channel Gain Register */
#define AT91_SAMA5D2_CGR 0x48
#define AT91_SAMA5D2_CGR 0x48
/* Channel Offset Register */
#define AT91_SAMA5D2_COR 0x4c
#define AT91_SAMA5D2_COR 0x4c
#define AT91_SAMA5D2_COR_DIFF_OFFSET 16
/* Channel Data Register 0 */
#define AT91_SAMA5D2_CDR0 0x50
/* Analog Control Register */
#define AT91_SAMA5D2_ACR 0x94
#define AT91_SAMA5D2_ACR 0x94
/* Touchscreen Mode Register */
#define AT91_SAMA5D2_TSMR 0xb0
/* Touchscreen X Position Register */
@@ -130,7 +135,7 @@
/* Correction Select Register */
#define AT91_SAMA5D2_COSR 0xd0
/* Correction Value Register */
#define AT91_SAMA5D2_CVR 0xd4
#define AT91_SAMA5D2_CVR 0xd4
/* Channel Error Correction Register */
#define AT91_SAMA5D2_CECR 0xd8
/* Write Protection Mode Register */
@@ -140,7 +145,7 @@
/* Version Register */
#define AT91_SAMA5D2_VERSION 0xfc
#define AT91_AT91_SAMA5D2_CHAN(num, addr) \
#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
{ \
.type = IIO_VOLTAGE, \
.channel = num, \
@@ -156,6 +161,24 @@
.indexed = 1, \
}
#define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr) \
{ \
.type = IIO_VOLTAGE, \
.differential = 1, \
.channel = num, \
.channel2 = num2, \
.address = addr, \
.scan_type = { \
.sign = 's', \
.realbits = 12, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
.datasheet_name = "CH"#num"-CH"#num2, \
.indexed = 1, \
}
#define at91_adc_readl(st, reg) readl_relaxed(st->base + reg)
#define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg)
@@ -185,18 +208,24 @@ struct at91_adc_state {
};
static const struct iio_chan_spec at91_adc_channels[] = {
AT91_AT91_SAMA5D2_CHAN(0, 0x50),
AT91_AT91_SAMA5D2_CHAN(1, 0x54),
AT91_AT91_SAMA5D2_CHAN(2, 0x58),
AT91_AT91_SAMA5D2_CHAN(3, 0x5c),
AT91_AT91_SAMA5D2_CHAN(4, 0x60),
AT91_AT91_SAMA5D2_CHAN(5, 0x64),
AT91_AT91_SAMA5D2_CHAN(6, 0x68),
AT91_AT91_SAMA5D2_CHAN(7, 0x6c),
AT91_AT91_SAMA5D2_CHAN(8, 0x70),
AT91_AT91_SAMA5D2_CHAN(9, 0x74),
AT91_AT91_SAMA5D2_CHAN(10, 0x78),
AT91_AT91_SAMA5D2_CHAN(11, 0x7c),
AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
AT91_SAMA5D2_CHAN_SINGLE(2, 0x58),
AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c),
AT91_SAMA5D2_CHAN_SINGLE(4, 0x60),
AT91_SAMA5D2_CHAN_SINGLE(5, 0x64),
AT91_SAMA5D2_CHAN_SINGLE(6, 0x68),
AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c),
AT91_SAMA5D2_CHAN_SINGLE(8, 0x70),
AT91_SAMA5D2_CHAN_SINGLE(9, 0x74),
AT91_SAMA5D2_CHAN_SINGLE(10, 0x78),
AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c),
AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50),
AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58),
AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60),
AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
};
static unsigned at91_adc_startup_time(unsigned startup_time_min,
@@ -226,7 +255,7 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min,
static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
{
struct iio_dev *indio_dev = iio_priv_to_dev(st);
unsigned f_per, prescal, startup;
unsigned f_per, prescal, startup, mr;
f_per = clk_get_rate(st->per_clk);
prescal = (f_per / (2 * freq)) - 1;
@@ -234,10 +263,11 @@ static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
startup = at91_adc_startup_time(st->soc_info.startup_time,
freq / 1000);
at91_adc_writel(st, AT91_SAMA5D2_MR,
AT91_SAMA5D2_MR_TRANSFER(2)
| AT91_SAMA5D2_MR_STARTUP(startup)
| AT91_SAMA5D2_MR_PRESCAL(prescal));
mr = at91_adc_readl(st, AT91_SAMA5D2_MR);
mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK);
mr |= AT91_SAMA5D2_MR_STARTUP(startup);
mr |= AT91_SAMA5D2_MR_PRESCAL(prescal);
at91_adc_writel(st, AT91_SAMA5D2_MR, mr);
dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
freq, startup, prescal);
@@ -278,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct at91_adc_state *st = iio_priv(indio_dev);
u32 cor = 0;
int ret;
switch (mask) {
@@ -286,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
st->chan = chan;
if (chan->differential)
cor = (BIT(chan->channel) | BIT(chan->channel2)) <<
AT91_SAMA5D2_COR_DIFF_OFFSET;
at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
@@ -298,6 +334,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
if (ret > 0) {
*val = st->conversion_value;
if (chan->scan_type.sign == 's')
*val = sign_extend32(*val, 11);
ret = IIO_VAL_INT;
st->conversion_done = false;
}
@@ -310,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
*val = st->vref_uv / 1000;
if (chan->differential)
*val *= 2;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
@@ -444,6 +484,12 @@ static int at91_adc_probe(struct platform_device *pdev)
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
/*
* Transfer field must be set to 2 according to the datasheet and
* allows different analog settings for each channel.
*/
at91_adc_writel(st, AT91_SAMA5D2_MR,
AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);

View File

@@ -185,9 +185,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
switch (chan->address) {
case INA2XX_SHUNT_VOLTAGE:
/* processed (mV) = raw*1000/shunt_div */
/* processed (mV) = raw/shunt_div */
*val2 = chip->config->shunt_div;
*val = 1000;
*val = 1;
return IIO_VAL_FRACTIONAL;
case INA2XX_BUS_VOLTAGE:
@@ -350,6 +350,23 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev,
return len;
}
/*
* Set current LSB to 1mA, shunt is in uOhms
* (equation 13 in datasheet). We hardcode a Current_LSB
* of 1.0 x10-6. The only remaining parameter is RShunt.
* There is no need to expose the CALIBRATION register
* to the user for now. But we need to reset this register
* if the user updates RShunt after driver init, e.g upon
* reading an EEPROM/Probe-type value.
*/
static int ina2xx_set_calibration(struct ina2xx_chip_info *chip)
{
u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
chip->shunt_resistor);
return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
}
static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val)
{
if (val <= 0 || val > chip->config->calibration_factor)
@@ -385,6 +402,11 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
if (ret)
return ret;
/* Update the Calibration register */
ret = ina2xx_set_calibration(chip);
if (ret)
return ret;
return len;
}
@@ -602,24 +624,11 @@ static const struct iio_info ina2xx_info = {
/* Initialize the configuration and calibration registers. */
static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config)
{
u16 regval;
int ret;
ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
int ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
if (ret)
return ret;
/*
* Set current LSB to 1mA, shunt is in uOhms
* (equation 13 in datasheet). We hardcode a Current_LSB
* of 1.0 x10-6. The only remaining parameter is RShunt.
* There is no need to expose the CALIBRATION register
* to the user for now.
*/
regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
chip->shunt_resistor);
return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
return ina2xx_set_calibration(chip);
}
static int ina2xx_probe(struct i2c_client *client,

View File

@@ -0,0 +1,231 @@
/*
* 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
* - Interrupts
* - DMA
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/io.h>
#include <linux/iopoll.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>
/* LPC18XX ADC registers and bits */
#define LPC18XX_ADC_CR 0x000
#define LPC18XX_ADC_CR_CLKDIV_SHIFT 8
#define LPC18XX_ADC_CR_PDN BIT(21)
#define LPC18XX_ADC_CR_START_NOW (0x1 << 24)
#define LPC18XX_ADC_GDR 0x004
/* Data register bits */
#define LPC18XX_ADC_SAMPLE_SHIFT 6
#define LPC18XX_ADC_SAMPLE_MASK 0x3ff
#define LPC18XX_ADC_CONV_DONE BIT(31)
/* Clock should be 4.5 MHz or less */
#define LPC18XX_ADC_CLK_TARGET 4500000
struct lpc18xx_adc {
struct regulator *vref;
void __iomem *base;
struct device *dev;
struct mutex lock;
struct clk *clk;
u32 cr_reg;
};
#define LPC18XX_ADC_CHAN(_idx) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _idx, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = {
LPC18XX_ADC_CHAN(0),
LPC18XX_ADC_CHAN(1),
LPC18XX_ADC_CHAN(2),
LPC18XX_ADC_CHAN(3),
LPC18XX_ADC_CHAN(4),
LPC18XX_ADC_CHAN(5),
LPC18XX_ADC_CHAN(6),
LPC18XX_ADC_CHAN(7),
};
static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch)
{
int ret;
u32 reg;
reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW;
writel(reg, adc->base + LPC18XX_ADC_CR);
ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg,
reg & LPC18XX_ADC_CONV_DONE, 3, 9);
if (ret) {
dev_warn(adc->dev, "adc read timed out\n");
return ret;
}
return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK;
}
static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct lpc18xx_adc *adc = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&adc->lock);
*val = lpc18xx_adc_read_chan(adc, chan->channel);
mutex_unlock(&adc->lock);
if (*val < 0)
return *val;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = regulator_get_voltage(adc->vref) / 1000;
*val2 = 10;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
static const struct iio_info lpc18xx_adc_info = {
.read_raw = lpc18xx_adc_read_raw,
.driver_module = THIS_MODULE,
};
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;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
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);
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->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);
}
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;
indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels);
ret = regulator_enable(adc->vref);
if (ret) {
dev_err(&pdev->dev, "unable to enable regulator\n");
return ret;
}
ret = clk_prepare_enable(adc->clk);
if (ret) {
dev_err(&pdev->dev, "unable to enable clock\n");
goto dis_reg;
}
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);
return 0;
}
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,
},
};
module_platform_driver(lpc18xx_adc_driver);
MODULE_DESCRIPTION("LPC18xx ADC driver");
MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
MODULE_LICENSE("GPL v2");

View File

@@ -159,6 +159,22 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = {
.clk_rate = 50000,
};
static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
ADC_CHANNEL(0, "adc0"),
ADC_CHANNEL(1, "adc1"),
ADC_CHANNEL(2, "adc2"),
ADC_CHANNEL(3, "adc3"),
ADC_CHANNEL(4, "adc4"),
ADC_CHANNEL(5, "adc5"),
};
static const struct rockchip_saradc_data rk3399_saradc_data = {
.num_bits = 10,
.channels = rockchip_rk3399_saradc_iio_channels,
.num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels),
.clk_rate = 1000000,
};
static const struct of_device_id rockchip_saradc_match[] = {
{
.compatible = "rockchip,saradc",
@@ -166,6 +182,9 @@ static const struct of_device_id rockchip_saradc_match[] = {
}, {
.compatible = "rockchip,rk3066-tsadc",
.data = &rk3066_tsadc_data,
}, {
.compatible = "rockchip,rk3399-saradc",
.data = &rk3399_saradc_data,
},
{},
};