Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a3cecf5 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'iio-for-3.14c' of...

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

Jonathan writes:

Third round of new drivers, features and cleanups for IIO in the 3.14 cycle.

One new driver a spot of new functionality and a cleanup.

* New driver for the Capella CM32181 ambient light sensor. This is the first
  driver directly from Kevin at Capella with more already in the pipeline.
* Support for configurable predividers on the mxs lradc
* Convert a field to a bitmap in mxs lradc instead of using an array of
  unsigned longs to store boolean values.
parents edd236af 38125b2c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ adt7461 +/-1C TDM Extended Temp Range I.C
at,24c08		i2c serial eeprom  (24cxx)
atmel,24c02		i2c serial eeprom  (24cxx)
atmel,at97sc3204t	i2c trusted platform module (TPM)
capella,cm32181		CM32181: Ambient Light Sensor
catalyst,24c32		i2c serial eeprom
dallas,ds1307		64 x 8, Serial, I2C Real-Time Clock
dallas,ds1338		I2C RTC with 56-Byte NV RAM
+11 −0
Original line number Diff line number Diff line
@@ -27,6 +27,17 @@ config APDS9300
	 To compile this driver as a module, choose M here: the
	 module will be called apds9300.

config CM32181
	depends on I2C
	tristate "CM32181 driver"
	help
	 Say Y here if you use cm32181.
	 This option enables ambient light sensor using
	 Capella cm32181 device driver.

	 To compile this driver as a module, choose M here:
	 the module will be called cm32181.

config CM36651
	depends on I2C
	tristate "CM36651 driver"
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADJD_S311)		+= adjd_s311.o
obj-$(CONFIG_APDS9300)		+= apds9300.o
obj-$(CONFIG_CM32181)		+= cm32181.o
obj-$(CONFIG_CM36651)		+= cm36651.o
obj-$(CONFIG_GP2AP020A00F)	+= gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS)	+= hid-sensor-als.o
+379 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 Capella Microsystems Inc.
 * Author: Kevin Tsai <ktsai@capellamicro.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.
 */

#include <linux/delay.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include <linux/init.h>

/* Registers Address */
#define CM32181_REG_ADDR_CMD		0x00
#define CM32181_REG_ADDR_ALS		0x04
#define CM32181_REG_ADDR_STATUS		0x06
#define CM32181_REG_ADDR_ID		0x07

/* Number of Configurable Registers */
#define CM32181_CONF_REG_NUM		0x01

/* CMD register */
#define CM32181_CMD_ALS_ENABLE		0x00
#define CM32181_CMD_ALS_DISABLE		0x01
#define CM32181_CMD_ALS_INT_EN		0x02

#define CM32181_CMD_ALS_IT_SHIFT	6
#define CM32181_CMD_ALS_IT_MASK		(0x0F << CM32181_CMD_ALS_IT_SHIFT)
#define CM32181_CMD_ALS_IT_DEFAULT	(0x00 << CM32181_CMD_ALS_IT_SHIFT)

#define CM32181_CMD_ALS_SM_SHIFT	11
#define CM32181_CMD_ALS_SM_MASK		(0x03 << CM32181_CMD_ALS_SM_SHIFT)
#define CM32181_CMD_ALS_SM_DEFAULT	(0x01 << CM32181_CMD_ALS_SM_SHIFT)

#define CM32181_MLUX_PER_BIT		5	/* ALS_SM=01 IT=800ms */
#define CM32181_MLUX_PER_BIT_BASE_IT	800000	/* Based on IT=800ms */
#define	CM32181_CALIBSCALE_DEFAULT	1000
#define CM32181_CALIBSCALE_RESOLUTION	1000
#define MLUX_PER_LUX			1000

static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = {
	CM32181_REG_ADDR_CMD,
};

static const int als_it_bits[] = {12, 8, 0, 1, 2, 3};
static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000,
	800000};

struct cm32181_chip {
	struct i2c_client *client;
	struct mutex lock;
	u16 conf_regs[CM32181_CONF_REG_NUM];
	int calibscale;
};

/**
 * cm32181_reg_init() - Initialize CM32181 registers
 * @cm32181:	pointer of struct cm32181.
 *
 * Initialize CM32181 ambient light sensor register to default values.
 *
 * Return: 0 for success; otherwise for error code.
 */
static int cm32181_reg_init(struct cm32181_chip *cm32181)
{
	struct i2c_client *client = cm32181->client;
	int i;
	s32 ret;

	ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ID);
	if (ret < 0)
		return ret;

	/* check device ID */
	if ((ret & 0xFF) != 0x81)
		return -ENODEV;

	/* Default Values */
	cm32181->conf_regs[CM32181_REG_ADDR_CMD] = CM32181_CMD_ALS_ENABLE |
			CM32181_CMD_ALS_IT_DEFAULT | CM32181_CMD_ALS_SM_DEFAULT;
	cm32181->calibscale = CM32181_CALIBSCALE_DEFAULT;

	/* Initialize registers*/
	for (i = 0; i < CM32181_CONF_REG_NUM; i++) {
		ret = i2c_smbus_write_word_data(client, cm32181_reg[i],
			cm32181->conf_regs[i]);
		if (ret < 0)
			return ret;
	}

	return 0;
}

/**
 *  cm32181_read_als_it() - Get sensor integration time (ms)
 *  @cm32181:	pointer of struct cm32181
 *  @val:	pointer of int to load the als_it value.
 *
 *  Report the current integartion time by millisecond.
 *
 *  Return: IIO_VAL_INT for success, otherwise -EINVAL.
 */
static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val)
{
	u16 als_it;
	int i;

	als_it = cm32181->conf_regs[CM32181_REG_ADDR_CMD];
	als_it &= CM32181_CMD_ALS_IT_MASK;
	als_it >>= CM32181_CMD_ALS_IT_SHIFT;
	for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) {
		if (als_it == als_it_bits[i]) {
			*val = als_it_value[i];
			return IIO_VAL_INT;
		}
	}

	return -EINVAL;
}

/**
 * cm32181_write_als_it() - Write sensor integration time
 * @cm32181:	pointer of struct cm32181.
 * @val:	integration time by millisecond.
 *
 * Convert integration time (ms) to sensor value.
 *
 * Return: i2c_smbus_write_word_data command return value.
 */
static int cm32181_write_als_it(struct cm32181_chip *cm32181, int val)
{
	struct i2c_client *client = cm32181->client;
	u16 als_it;
	int ret, i, n;

	n = ARRAY_SIZE(als_it_value);
	for (i = 0; i < n; i++)
		if (val <= als_it_value[i])
			break;
	if (i >= n)
		i = n - 1;

	als_it = als_it_bits[i];
	als_it <<= CM32181_CMD_ALS_IT_SHIFT;

	mutex_lock(&cm32181->lock);
	cm32181->conf_regs[CM32181_REG_ADDR_CMD] &=
		~CM32181_CMD_ALS_IT_MASK;
	cm32181->conf_regs[CM32181_REG_ADDR_CMD] |=
		als_it;
	ret = i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD,
			cm32181->conf_regs[CM32181_REG_ADDR_CMD]);
	mutex_unlock(&cm32181->lock);

	return ret;
}

/**
 * cm32181_get_lux() - report current lux value
 * @cm32181:	pointer of struct cm32181.
 *
 * Convert sensor raw data to lux.  It depends on integration
 * time and claibscale variable.
 *
 * Return: Positive value is lux, otherwise is error code.
 */
static int cm32181_get_lux(struct cm32181_chip *cm32181)
{
	struct i2c_client *client = cm32181->client;
	int ret;
	int als_it;
	unsigned long lux;

	ret = cm32181_read_als_it(cm32181, &als_it);
	if (ret < 0)
		return -EINVAL;

	lux = CM32181_MLUX_PER_BIT;
	lux *= CM32181_MLUX_PER_BIT_BASE_IT;
	lux /= als_it;

	ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ALS);
	if (ret < 0)
		return ret;

	lux *= ret;
	lux *= cm32181->calibscale;
	lux /= CM32181_CALIBSCALE_RESOLUTION;
	lux /= MLUX_PER_LUX;

	if (lux > 0xFFFF)
		lux = 0xFFFF;

	return lux;
}

static int cm32181_read_raw(struct iio_dev *indio_dev,
			    struct iio_chan_spec const *chan,
			    int *val, int *val2, long mask)
{
	struct cm32181_chip *cm32181 = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_PROCESSED:
		ret = cm32181_get_lux(cm32181);
		if (ret < 0)
			return ret;
		*val = ret;
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_CALIBSCALE:
		*val = cm32181->calibscale;
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_INT_TIME:
		ret = cm32181_read_als_it(cm32181, val);
		return ret;
	}

	return -EINVAL;
}

static int cm32181_write_raw(struct iio_dev *indio_dev,
			     struct iio_chan_spec const *chan,
			     int val, int val2, long mask)
{
	struct cm32181_chip *cm32181 = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_CALIBSCALE:
		cm32181->calibscale = val;
		return val;
	case IIO_CHAN_INFO_INT_TIME:
		ret = cm32181_write_als_it(cm32181, val);
		return ret;
	}

	return -EINVAL;
}

/**
 * cm32181_get_it_available() - Get available ALS IT value
 * @dev:	pointer of struct device.
 * @attr:	pointer of struct device_attribute.
 * @buf:	pointer of return string buffer.
 *
 * Display the available integration time values by millisecond.
 *
 * Return: string length.
 */
static ssize_t cm32181_get_it_available(struct device *dev,
			struct device_attribute *attr, char *buf)
{
	int i, n, len;

	n = ARRAY_SIZE(als_it_value);
	for (i = 0, len = 0; i < n; i++)
		len += sprintf(buf + len, "%d ", als_it_value[i]);
	return len + sprintf(buf + len, "\n");
}

static const struct iio_chan_spec cm32181_channels[] = {
	{
		.type = IIO_LIGHT,
		.info_mask_separate =
			BIT(IIO_CHAN_INFO_PROCESSED) |
			BIT(IIO_CHAN_INFO_CALIBSCALE) |
			BIT(IIO_CHAN_INFO_INT_TIME),
	}
};

static IIO_DEVICE_ATTR(in_illuminance_integration_time_available,
			S_IRUGO, cm32181_get_it_available, NULL, 0);

static struct attribute *cm32181_attributes[] = {
	&iio_dev_attr_in_illuminance_integration_time_available.dev_attr.attr,
	NULL,
};

static const struct attribute_group cm32181_attribute_group = {
	.attrs = cm32181_attributes
};

static const struct iio_info cm32181_info = {
	.driver_module		= THIS_MODULE,
	.read_raw		= &cm32181_read_raw,
	.write_raw		= &cm32181_write_raw,
	.attrs			= &cm32181_attribute_group,
};

static int cm32181_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct cm32181_chip *cm32181;
	struct iio_dev *indio_dev;
	int ret;

	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181));
	if (!indio_dev) {
		dev_err(&client->dev, "devm_iio_device_alloc failed\n");
		return -ENOMEM;
	}

	cm32181 = iio_priv(indio_dev);
	i2c_set_clientdata(client, indio_dev);
	cm32181->client = client;

	mutex_init(&cm32181->lock);
	indio_dev->dev.parent = &client->dev;
	indio_dev->channels = cm32181_channels;
	indio_dev->num_channels = ARRAY_SIZE(cm32181_channels);
	indio_dev->info = &cm32181_info;
	indio_dev->name = id->name;
	indio_dev->modes = INDIO_DIRECT_MODE;

	ret = cm32181_reg_init(cm32181);
	if (ret) {
		dev_err(&client->dev,
			"%s: register init failed\n",
			__func__);
		return ret;
	}

	ret = iio_device_register(indio_dev);
	if (ret) {
		dev_err(&client->dev,
			"%s: regist device failed\n",
			__func__);
		return ret;
	}

	return 0;
}

static int cm32181_remove(struct i2c_client *client)
{
	struct iio_dev *indio_dev = i2c_get_clientdata(client);

	iio_device_unregister(indio_dev);
	return 0;
}

static const struct i2c_device_id cm32181_id[] = {
	{ "cm32181", 0 },
	{ }
};

MODULE_DEVICE_TABLE(i2c, cm32181_id);

static const struct of_device_id cm32181_of_match[] = {
	{ .compatible = "capella,cm32181" },
	{ }
};

static struct i2c_driver cm32181_driver = {
	.driver = {
		.name	= "cm32181",
		.of_match_table = of_match_ptr(cm32181_of_match),
		.owner	= THIS_MODULE,
	},
	.id_table       = cm32181_id,
	.probe		= cm32181_probe,
	.remove		= cm32181_remove,
};

module_i2c_driver(cm32181_driver);

MODULE_AUTHOR("Kevin Tsai <ktsai@capellamicro.com>");
MODULE_DESCRIPTION("CM32181 ambient light sensor driver");
MODULE_LICENSE("GPL");
+219 −3
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#include <linux/clk.h>

#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
@@ -111,16 +112,59 @@ static const char * const mx28_lradc_irq_names[] = {
struct mxs_lradc_of_config {
	const int		irq_count;
	const char * const	*irq_name;
	const uint32_t		*vref_mv;
};

#define VREF_MV_BASE 1850

static const uint32_t mx23_vref_mv[LRADC_MAX_TOTAL_CHANS] = {
	VREF_MV_BASE,		/* CH0 */
	VREF_MV_BASE,		/* CH1 */
	VREF_MV_BASE,		/* CH2 */
	VREF_MV_BASE,		/* CH3 */
	VREF_MV_BASE,		/* CH4 */
	VREF_MV_BASE,		/* CH5 */
	VREF_MV_BASE * 2,	/* CH6 VDDIO */
	VREF_MV_BASE * 4,	/* CH7 VBATT */
	VREF_MV_BASE,		/* CH8 Temp sense 0 */
	VREF_MV_BASE,		/* CH9 Temp sense 1 */
	VREF_MV_BASE,		/* CH10 */
	VREF_MV_BASE,		/* CH11 */
	VREF_MV_BASE,		/* CH12 USB_DP */
	VREF_MV_BASE,		/* CH13 USB_DN */
	VREF_MV_BASE,		/* CH14 VBG */
	VREF_MV_BASE * 4,	/* CH15 VDD5V */
};

static const uint32_t mx28_vref_mv[LRADC_MAX_TOTAL_CHANS] = {
	VREF_MV_BASE,		/* CH0 */
	VREF_MV_BASE,		/* CH1 */
	VREF_MV_BASE,		/* CH2 */
	VREF_MV_BASE,		/* CH3 */
	VREF_MV_BASE,		/* CH4 */
	VREF_MV_BASE,		/* CH5 */
	VREF_MV_BASE,		/* CH6 */
	VREF_MV_BASE * 4,	/* CH7 VBATT */
	VREF_MV_BASE,		/* CH8 Temp sense 0 */
	VREF_MV_BASE,		/* CH9 Temp sense 1 */
	VREF_MV_BASE * 2,	/* CH10 VDDIO */
	VREF_MV_BASE,		/* CH11 VTH */
	VREF_MV_BASE * 2,	/* CH12 VDDA */
	VREF_MV_BASE,		/* CH13 VDDD */
	VREF_MV_BASE,		/* CH14 VBG */
	VREF_MV_BASE * 4,	/* CH15 VDD5V */
};

static const struct mxs_lradc_of_config mxs_lradc_of_config[] = {
	[IMX23_LRADC] = {
		.irq_count	= ARRAY_SIZE(mx23_lradc_irq_names),
		.irq_name	= mx23_lradc_irq_names,
		.vref_mv	= mx23_vref_mv,
	},
	[IMX28_LRADC] = {
		.irq_count	= ARRAY_SIZE(mx28_lradc_irq_names),
		.irq_name	= mx28_lradc_irq_names,
		.vref_mv	= mx28_vref_mv,
	},
};

@@ -141,6 +185,16 @@ enum lradc_ts_plate {
	LRADC_SAMPLE_VALID,
};

enum mxs_lradc_divbytwo {
	MXS_LRADC_DIV_DISABLED = 0,
	MXS_LRADC_DIV_ENABLED,
};

struct mxs_lradc_scale {
	unsigned int		integer;
	unsigned int		nano;
};

struct mxs_lradc {
	struct device		*dev;
	void __iomem		*base;
@@ -155,6 +209,10 @@ struct mxs_lradc {

	struct completion	completion;

	const uint32_t		*vref_mv;
	struct mxs_lradc_scale	scale_avail[LRADC_MAX_TOTAL_CHANS][2];
	unsigned long		is_divided;

	/*
	 * Touchscreen LRADC channels receives a private slot in the CTRL4
	 * register, the slot #7. Therefore only 7 slots instead of 8 in the
@@ -243,6 +301,7 @@ struct mxs_lradc {
#define	LRADC_CTRL1_LRADC_IRQ_OFFSET		0

#define	LRADC_CTRL2				0x20
#define	LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET	24
#define	LRADC_CTRL2_TEMPSENSE_PWD		(1 << 15)

#define	LRADC_STATUS				0x40
@@ -836,6 +895,8 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
			const struct iio_chan_spec *chan,
			int *val, int *val2, long m)
{
	struct mxs_lradc *lradc = iio_priv(iio_dev);

	/* Check for invalid channel */
	if (chan->channel > LRADC_MAX_TOTAL_CHANS)
		return -EINVAL;
@@ -857,7 +918,10 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
			return IIO_VAL_INT_PLUS_MICRO;
		}

		return -EINVAL;
		*val = lradc->vref_mv[chan->channel];
		*val2 = chan->scan_type.realbits -
			test_bit(chan->channel, &lradc->is_divided);
		return IIO_VAL_FRACTIONAL_LOG2;

	case IIO_CHAN_INFO_OFFSET:
		if (chan->type == IIO_TEMP) {
@@ -880,9 +944,136 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
	return -EINVAL;
}

static int mxs_lradc_write_raw(struct iio_dev *iio_dev,
			       const struct iio_chan_spec *chan,
			       int val, int val2, long m)
{
	struct mxs_lradc *lradc = iio_priv(iio_dev);
	struct mxs_lradc_scale *scale_avail =
			lradc->scale_avail[chan->channel];
	int ret;

	ret = mutex_trylock(&lradc->lock);
	if (!ret)
		return -EBUSY;

	switch (m) {
	case IIO_CHAN_INFO_SCALE:
		ret = -EINVAL;
		if (val == scale_avail[MXS_LRADC_DIV_DISABLED].integer &&
		    val2 == scale_avail[MXS_LRADC_DIV_DISABLED].nano) {
			/* divider by two disabled */
			writel(1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET,
			       lradc->base + LRADC_CTRL2 + STMP_OFFSET_REG_CLR);
			clear_bit(chan->channel, &lradc->is_divided);
			ret = 0;
		} else if (val == scale_avail[MXS_LRADC_DIV_ENABLED].integer &&
			   val2 == scale_avail[MXS_LRADC_DIV_ENABLED].nano) {
			/* divider by two enabled */
			writel(1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET,
			       lradc->base + LRADC_CTRL2 + STMP_OFFSET_REG_SET);
			set_bit(chan->channel, &lradc->is_divided);
			ret = 0;
		}

		break;
	default:
		ret = -EINVAL;
		break;
	}

	mutex_unlock(&lradc->lock);

	return ret;
}

static int mxs_lradc_write_raw_get_fmt(struct iio_dev *iio_dev,
				       const struct iio_chan_spec *chan,
				       long m)
{
	return IIO_VAL_INT_PLUS_NANO;
}

static ssize_t mxs_lradc_show_scale_available_ch(struct device *dev,
		struct device_attribute *attr,
		char *buf,
		int ch)
{
	struct iio_dev *iio = dev_to_iio_dev(dev);
	struct mxs_lradc *lradc = iio_priv(iio);
	int i, len = 0;

	for (i = 0; i < ARRAY_SIZE(lradc->scale_avail[ch]); i++)
		len += sprintf(buf + len, "%d.%09u ",
			       lradc->scale_avail[ch][i].integer,
			       lradc->scale_avail[ch][i].nano);

	len += sprintf(buf + len, "\n");

	return len;
}

static ssize_t mxs_lradc_show_scale_available(struct device *dev,
		struct device_attribute *attr,
		char *buf)
{
	struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr);

	return mxs_lradc_show_scale_available_ch(dev, attr, buf,
						 iio_attr->address);
}

#define SHOW_SCALE_AVAILABLE_ATTR(ch)					\
static IIO_DEVICE_ATTR(in_voltage##ch##_scale_available, S_IRUGO,	\
		       mxs_lradc_show_scale_available, NULL, ch)

SHOW_SCALE_AVAILABLE_ATTR(0);
SHOW_SCALE_AVAILABLE_ATTR(1);
SHOW_SCALE_AVAILABLE_ATTR(2);
SHOW_SCALE_AVAILABLE_ATTR(3);
SHOW_SCALE_AVAILABLE_ATTR(4);
SHOW_SCALE_AVAILABLE_ATTR(5);
SHOW_SCALE_AVAILABLE_ATTR(6);
SHOW_SCALE_AVAILABLE_ATTR(7);
SHOW_SCALE_AVAILABLE_ATTR(8);
SHOW_SCALE_AVAILABLE_ATTR(9);
SHOW_SCALE_AVAILABLE_ATTR(10);
SHOW_SCALE_AVAILABLE_ATTR(11);
SHOW_SCALE_AVAILABLE_ATTR(12);
SHOW_SCALE_AVAILABLE_ATTR(13);
SHOW_SCALE_AVAILABLE_ATTR(14);
SHOW_SCALE_AVAILABLE_ATTR(15);

static struct attribute *mxs_lradc_attributes[] = {
	&iio_dev_attr_in_voltage0_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage1_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage2_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage3_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage4_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage5_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage6_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage7_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage8_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage9_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage10_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage11_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage12_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage13_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage14_scale_available.dev_attr.attr,
	&iio_dev_attr_in_voltage15_scale_available.dev_attr.attr,
	NULL
};

static const struct attribute_group mxs_lradc_attribute_group = {
	.attrs = mxs_lradc_attributes,
};

static const struct iio_info mxs_lradc_iio_info = {
	.driver_module		= THIS_MODULE,
	.read_raw		= mxs_lradc_read_raw,
	.write_raw		= mxs_lradc_write_raw,
	.write_raw_get_fmt	= mxs_lradc_write_raw_get_fmt,
	.attrs			= &mxs_lradc_attribute_group,
};

static int mxs_lradc_ts_open(struct input_dev *dev)
@@ -1189,8 +1380,10 @@ static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = {
	.type = (chan_type),					\
	.indexed = 1,						\
	.scan_index = (idx),					\
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
			      BIT(IIO_CHAN_INFO_SCALE),		\
	.channel = (idx),					\
	.address = (idx),					\
	.scan_type = {						\
		.sign = 'u',					\
		.realbits = LRADC_RESOLUTION,			\
@@ -1336,7 +1529,8 @@ static int mxs_lradc_probe(struct platform_device *pdev)
	struct iio_dev *iio;
	struct resource *iores;
	int ret = 0, touch_ret;
	int i;
	int i, s;
	unsigned int scale_uv;

	/* Allocate the IIO device. */
	iio = devm_iio_device_alloc(dev, sizeof(*lradc));
@@ -1381,6 +1575,8 @@ static int mxs_lradc_probe(struct platform_device *pdev)
			return ret;
	}

	lradc->vref_mv = of_cfg->vref_mv;

	platform_set_drvdata(pdev, iio);

	init_completion(&lradc->completion);
@@ -1404,6 +1600,26 @@ static int mxs_lradc_probe(struct platform_device *pdev)
	if (ret)
		goto err_trig;

	/* Populate available ADC input ranges */
	for (i = 0; i < LRADC_MAX_TOTAL_CHANS; i++) {
		for (s = 0; s < ARRAY_SIZE(lradc->scale_avail[i]); s++) {
			/*
			 * [s=0] = optional divider by two disabled (default)
			 * [s=1] = optional divider by two enabled
			 *
			 * The scale is calculated by doing:
			 *   Vref >> (realbits - s)
			 * which multiplies by two on the second component
			 * of the array.
			 */
			scale_uv = ((u64)lradc->vref_mv[i] * 100000000) >>
				   (iio->channels[i].scan_type.realbits - s);
			lradc->scale_avail[i][s].nano =
					do_div(scale_uv, 100000000) * 10;
			lradc->scale_avail[i][s].integer = scale_uv;
		}
	}

	/* Configure the hardware. */
	ret = mxs_lradc_hw_init(lradc);
	if (ret)