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

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
......@@ -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
......
......@@ -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"
......
......@@ -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
......
/*
* 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");
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment