aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuenter Roeck2013-02-03 00:59:00 +0000
committerJonathan Cameron2013-02-06 18:38:40 +0000
commita405b00e4470b15ed062de97c4ce552d41a0a60b (patch)
treec3a8efd5c7ab535628fe82500e403d3a079bd34e
parent7c3e8675f37503337d901dc254cba253326b572a (diff)
iio/adc: (max1363) Add support for external reference voltage
Implement external reference voltage as regulator named "vref". Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/adc/max1363.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index c5e46c62ffbb..6c1cfb74bdfc 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -163,6 +163,8 @@ struct max1363_chip_info {
* @mask_low: bitmask for enabled low thresholds
* @thresh_high: high threshold values
* @thresh_low: low threshold values
+ * @vref: Reference voltage regulator
+ * @vref_uv: Actual (external or internal) reference voltage
*/
struct max1363_state {
struct i2c_client *client;
@@ -182,6 +184,8 @@ struct max1363_state {
/* 4x unipolar first then the fours bipolar ones */
s16 thresh_high[8];
s16 thresh_low[8];
+ struct regulator *vref;
+ u32 vref_uv;
};
#define MAX1363_MODE_SINGLE(_num, _mask) { \
@@ -393,6 +397,8 @@ static int max1363_read_raw(struct iio_dev *indio_dev,
{
struct max1363_state *st = iio_priv(indio_dev);
int ret;
+ unsigned long scale_uv;
+
switch (m) {
case IIO_CHAN_INFO_RAW:
ret = max1363_read_single_chan(indio_dev, chan, val, m);
@@ -400,16 +406,10 @@ static int max1363_read_raw(struct iio_dev *indio_dev,
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
- if ((1 << (st->chip_info->bits + 1)) >
- st->chip_info->int_vref_mv) {
- *val = 0;
- *val2 = 500000;
- return IIO_VAL_INT_PLUS_MICRO;
- } else {
- *val = (st->chip_info->int_vref_mv)
- >> st->chip_info->bits;
- return IIO_VAL_INT;
- }
+ scale_uv = st->vref_uv >> st->chip_info->bits;
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
@@ -1390,12 +1390,16 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
static int max1363_initial_setup(struct max1363_state *st)
{
- st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD
- | MAX1363_SETUP_POWER_UP_INT_REF
- | MAX1363_SETUP_INT_CLOCK
+ st->setupbyte = MAX1363_SETUP_INT_CLOCK
| MAX1363_SETUP_UNIPOLAR
| MAX1363_SETUP_NORESET;
+ if (st->vref)
+ st->setupbyte |= MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF;
+ else
+ st->setupbyte |= MAX1363_SETUP_POWER_UP_INT_REF
+ | MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT;
+
/* Set scan mode writes the config anyway so wait until then */
st->setupbyte = MAX1363_SETUP_BYTE(st->setupbyte);
st->current_mode = &max1363_mode_table[st->chip_info->default_mode];
@@ -1491,6 +1495,7 @@ static int max1363_probe(struct i2c_client *client,
int ret;
struct max1363_state *st;
struct iio_dev *indio_dev;
+ struct regulator *vref;
indio_dev = iio_device_alloc(sizeof(struct max1363_state));
if (indio_dev == NULL) {
@@ -1521,6 +1526,23 @@ static int max1363_probe(struct i2c_client *client,
st->chip_info = &max1363_chip_info_tbl[id->driver_data];
st->client = client;
+ st->vref_uv = st->chip_info->int_vref_mv * 1000;
+ vref = devm_regulator_get(&client->dev, "vref");
+ if (!IS_ERR(vref)) {
+ int vref_uv;
+
+ ret = regulator_enable(vref);
+ if (ret)
+ goto error_disable_reg;
+ st->vref = vref;
+ vref_uv = regulator_get_voltage(vref);
+ if (vref_uv <= 0) {
+ ret = -EINVAL;
+ goto error_disable_reg;
+ }
+ st->vref_uv = vref_uv;
+ }
+
ret = max1363_alloc_scan_masks(indio_dev);
if (ret)
goto error_disable_reg;
@@ -1562,6 +1584,8 @@ static int max1363_probe(struct i2c_client *client,
error_uninit_buffer:
iio_triggered_buffer_cleanup(indio_dev);
error_disable_reg:
+ if (st->vref)
+ regulator_disable(st->vref);
regulator_disable(st->reg);
error_unregister_map:
iio_map_array_unregister(indio_dev);
@@ -1578,6 +1602,8 @@ static int max1363_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
+ if (st->vref)
+ regulator_disable(st->vref);
regulator_disable(st->reg);
iio_map_array_unregister(indio_dev);
iio_device_free(indio_dev);