From f770294db66ba738d995e9a0184309722ffb4990 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 20 Oct 2014 06:32:40 +0000 Subject: [PATCH] kernel/adc: backport essential fixes for ad799x This patch ports back some fixes of the ad799x driver, which were committed between 3.10 and 3.15. Signed-off-by: Hartmut Knaack SVN-Revision: 42993 --- .../065-iio_ad799x_backport_fixes.patch | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 target/linux/generic/patches-3.10/065-iio_ad799x_backport_fixes.patch diff --git a/target/linux/generic/patches-3.10/065-iio_ad799x_backport_fixes.patch b/target/linux/generic/patches-3.10/065-iio_ad799x_backport_fixes.patch new file mode 100644 index 0000000000..4368ec7dec --- /dev/null +++ b/target/linux/generic/patches-3.10/065-iio_ad799x_backport_fixes.patch @@ -0,0 +1,159 @@ +Backport essential fixes from 3.15 + +From Linux 3.10 on this driver required platform data to load, which makes it +unusable in OpenWRT. This commit backports the following fixes: + * Move to regulator framework for scaling + * Set endianness of the ADC to Big endian + * Fix device-removal path +This commit should not be moved to newer kernel versions! + +Signed-off-by: Hartmut Knaack +--- +diff -uprN a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c +--- a/drivers/staging/iio/adc/ad799x_core.c ++++ b/drivers/staging/iio/adc/ad799x_core.c +@@ -163,7 +163,6 @@ static int ad799x_read_raw(struct iio_de + { + int ret; + struct ad799x_state *st = iio_priv(indio_dev); +- unsigned int scale_uv; + + switch (m) { + case IIO_CHAN_INFO_RAW: +@@ -180,10 +179,12 @@ static int ad799x_read_raw(struct iio_de + RES_MASK(chan->scan_type.realbits); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: +- scale_uv = (st->int_vref_mv * 1000) >> chan->scan_type.realbits; +- *val = scale_uv / 1000; +- *val2 = (scale_uv % 1000) * 1000; +- return IIO_VAL_INT_PLUS_MICRO; ++ ret = regulator_get_voltage(st->vref); ++ if (ret < 0) ++ return ret; ++ *val = ret / 1000; ++ *val2 = chan->scan_type.realbits; ++ return IIO_VAL_FRACTIONAL_LOG2; + } + return -EINVAL; + } +@@ -474,7 +475,13 @@ static const struct iio_info ad7993_4_7_ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = (_index), \ +- .scan_type = IIO_ST('u', _realbits, 16, 12 - (_realbits)), \ ++ .scan_type = { \ ++ .sign = 'u', \ ++ .realbits = (_realbits), \ ++ .storagebits = 16, \ ++ .shift = 12 - (_realbits), \ ++ .endianness = IIO_BE, \ ++ }, \ + .event_mask = (_evmask), \ + } + +@@ -584,7 +591,6 @@ static int ad799x_probe(struct i2c_clien + const struct i2c_device_id *id) + { + int ret; +- struct ad799x_platform_data *pdata = client->dev.platform_data; + struct ad799x_state *st; + struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); + +@@ -601,17 +607,21 @@ static int ad799x_probe(struct i2c_clien + + /* TODO: Add pdata options for filtering and bit delay */ + +- if (!pdata) +- return -EINVAL; +- +- st->int_vref_mv = pdata->vref_mv; +- +- st->reg = regulator_get(&client->dev, "vcc"); +- if (!IS_ERR(st->reg)) { +- ret = regulator_enable(st->reg); +- if (ret) +- goto error_put_reg; ++ st->reg = devm_regulator_get(&client->dev, "vcc"); ++ if (IS_ERR(st->reg)) ++ return PTR_ERR(st->reg); ++ ret = regulator_enable(st->reg); ++ if (ret) ++ return ret; ++ st->vref = devm_regulator_get(&client->dev, "vref"); ++ if (IS_ERR(st->vref)) { ++ ret = PTR_ERR(st->vref); ++ goto error_disable_reg; + } ++ ret = regulator_enable(st->vref); ++ if (ret) ++ goto error_disable_reg; ++ + st->client = client; + + indio_dev->dev.parent = &client->dev; +@@ -624,7 +634,7 @@ static int ad799x_probe(struct i2c_clien + + ret = ad799x_register_ring_funcs_and_init(indio_dev); + if (ret) +- goto error_disable_reg; ++ goto error_disable_vref; + + if (client->irq > 0) { + ret = request_threaded_irq(client->irq, +@@ -648,12 +658,10 @@ error_free_irq: + free_irq(client->irq, indio_dev); + error_cleanup_ring: + ad799x_ring_cleanup(indio_dev); ++error_disable_vref: ++ regulator_disable(st->vref); + error_disable_reg: +- if (!IS_ERR(st->reg)) +- regulator_disable(st->reg); +-error_put_reg: +- if (!IS_ERR(st->reg)) +- regulator_put(st->reg); ++ regulator_disable(st->reg); + iio_device_free(indio_dev); + + return ret; +@@ -669,10 +677,8 @@ static int ad799x_remove(struct i2c_clie + free_irq(client->irq, indio_dev); + + ad799x_ring_cleanup(indio_dev); +- if (!IS_ERR(st->reg)) { +- regulator_disable(st->reg); +- regulator_put(st->reg); +- } ++ regulator_disable(st->vref); ++ regulator_disable(st->reg); + kfree(st->rx_buf); + iio_device_free(indio_dev); + +diff -uprN a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h +--- a/drivers/staging/iio/adc/ad799x.h ++++ b/drivers/staging/iio/adc/ad799x.h +@@ -103,7 +103,7 @@ struct ad799x_state { + struct i2c_client *client; + const struct ad799x_chip_info *chip_info; + struct regulator *reg; +- u16 int_vref_mv; ++ struct regulator *vref; + unsigned id; + u16 config; + +@@ -111,14 +111,6 @@ struct ad799x_state { + unsigned int transfer_size; + }; + +-/* +- * TODO: struct ad799x_platform_data needs to go into include/linux/iio +- */ +- +-struct ad799x_platform_data { +- u16 vref_mv; +-}; +- + #ifdef CONFIG_AD799X_RING_BUFFER + int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev); + void ad799x_ring_cleanup(struct iio_dev *indio_dev); -- 2.30.2