From 1df3a401154add23826d714c808204633b3b1c31 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 18 Sep 2013 18:13:00 +0100 Subject: [PATCH 01/51] HID: Delay opening HID device Don't call hid_open_device till there is actually an user. This saves power by not opening underlying transport for HID. Also close device if there are no active mfd client using HID sensor hub. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina Signed-off-by: Jonathan Cameron --- drivers/hid/hid-sensor-hub.c | 45 ++++++++++++++++++++++++++-------- include/linux/hid-sensor-hub.h | 18 ++++++++++++++ 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 10e1581022cf..88fc5aefcd96 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -465,6 +465,39 @@ static int sensor_hub_raw_event(struct hid_device *hdev, return 1; } +int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev) +{ + int ret = 0; + struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); + + mutex_lock(&data->mutex); + if (!hsdev->ref_cnt) { + ret = hid_hw_open(hsdev->hdev); + if (ret) { + hid_err(hsdev->hdev, "failed to open hid device\n"); + mutex_unlock(&data->mutex); + return ret; + } + } + hsdev->ref_cnt++; + mutex_unlock(&data->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(sensor_hub_device_open); + +void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev) +{ + struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); + + mutex_lock(&data->mutex); + hsdev->ref_cnt--; + if (!hsdev->ref_cnt) + hid_hw_close(hsdev->hdev); + mutex_unlock(&data->mutex); +} +EXPORT_SYMBOL_GPL(sensor_hub_device_close); + static int sensor_hub_probe(struct hid_device *hdev, const struct hid_device_id *id) { @@ -506,12 +539,6 @@ static int sensor_hub_probe(struct hid_device *hdev, hid_err(hdev, "hw start failed\n"); return ret; } - ret = hid_hw_open(hdev); - if (ret) { - hid_err(hdev, "failed to open input interrupt pipe\n"); - goto err_stop_hw; - } - INIT_LIST_HEAD(&sd->dyn_callback_list); sd->hid_sensor_client_cnt = 0; report_enum = &hdev->report_enum[HID_INPUT_REPORT]; @@ -520,7 +547,7 @@ static int sensor_hub_probe(struct hid_device *hdev, if (dev_cnt > HID_MAX_PHY_DEVICES) { hid_err(hdev, "Invalid Physical device count\n"); ret = -EINVAL; - goto err_close; + goto err_stop_hw; } sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt * sizeof(struct mfd_cell), @@ -528,7 +555,7 @@ static int sensor_hub_probe(struct hid_device *hdev, if (sd->hid_sensor_hub_client_devs == NULL) { hid_err(hdev, "Failed to allocate memory for mfd cells\n"); ret = -ENOMEM; - goto err_close; + goto err_stop_hw; } list_for_each_entry(report, &report_enum->report_list, list) { hid_dbg(hdev, "Report id:%x\n", report->id); @@ -565,8 +592,6 @@ err_free_names: for (i = 0; i < sd->hid_sensor_client_cnt ; ++i) kfree(sd->hid_sensor_hub_client_devs[i].name); kfree(sd->hid_sensor_hub_client_devs); -err_close: - hid_hw_close(hdev); err_stop_hw: hid_hw_stop(hdev); diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h index 32ba45158d39..a265af294ea4 100644 --- a/include/linux/hid-sensor-hub.h +++ b/include/linux/hid-sensor-hub.h @@ -47,11 +47,13 @@ struct hid_sensor_hub_attribute_info { * @hdev: Stores the hid instance. * @vendor_id: Vendor id of hub device. * @product_id: Product id of hub device. + * @ref_cnt: Number of MFD clients have opened this device */ struct hid_sensor_hub_device { struct hid_device *hdev; u32 vendor_id; u32 product_id; + int ref_cnt; }; /** @@ -74,6 +76,22 @@ struct hid_sensor_hub_callbacks { void *priv); }; +/** +* sensor_hub_device_open() - Open hub device +* @hsdev: Hub device instance. +* +* Used to open hid device for sensor hub. +*/ +int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev); + +/** +* sensor_hub_device_clode() - Close hub device +* @hsdev: Hub device instance. +* +* Used to clode hid device for sensor hub. +*/ +void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev); + /* Registration functions */ /** From 7d3c192df0457195c4cdd5272b39c8db8334be81 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 18 Sep 2013 18:13:00 +0100 Subject: [PATCH 02/51] IIO: call sensor hub open close function Call hid_sensor_hub_device_open when user space opens device and call hid_sensor_hub_device_close when device is closed. This helps in saving power. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 87419c41b991..b6e77e0fc420 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -34,6 +34,12 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, struct hid_sensor_common *st = iio_trigger_get_drvdata(trig); int state_val; + if (state) { + if (sensor_hub_device_open(st->hsdev)) + return -EIO; + } else + sensor_hub_device_close(st->hsdev); + state_val = state ? 1 : 0; if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS)) ++state_val; From 25682ae5e40f04cb86321dfc5a6713e4b45b55ea Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 03/51] iio:ad5064: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5064.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index b18e8c4347c2..cb9c6366032c 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -239,10 +239,9 @@ static int ad5064_read_raw(struct iio_dev *indio_dev, if (scale_uv < 0) return scale_uv; - scale_uv = (scale_uv * 100) >> chan->scan_type.realbits; - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; + *val = scale_uv / 1000; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; default: break; } From ca3bc8b62634215f899cefde52a31cc6600a686c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 04/51] iio:ad5360: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5360.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c index d2da71ece740..b968af50db0a 100644 --- a/drivers/iio/dac/ad5360.c +++ b/drivers/iio/dac/ad5360.c @@ -379,15 +379,14 @@ static int ad5360_read_raw(struct iio_dev *indio_dev, *val = ret >> chan->scan_type.shift; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - /* vout = 4 * vref * dac_code */ - scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100; + scale_uv = ad5360_get_channel_vref(st, chan->channel); if (scale_uv < 0) return scale_uv; - scale_uv >>= (chan->scan_type.realbits); - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; + /* vout = 4 * vref * dac_code */ + *val = scale_uv * 4 / 1000; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_CALIBBIAS: ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET, chan->address); From 4f2c188597858aa215754be7279e91d778502d8e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 05/51] iio:ad5380: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5380.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 4c791e66e0d7..a59ff0e7b888 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -204,7 +204,6 @@ static int ad5380_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info) { struct ad5380_state *st = iio_priv(indio_dev); - unsigned long scale_uv; int ret; switch (info) { @@ -225,10 +224,9 @@ static int ad5380_read_raw(struct iio_dev *indio_dev, val -= (1 << chan->scan_type.realbits) / 2; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = ((2 * st->vref) >> chan->scan_type.realbits) * 100; - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; + *val = 2 * st->vref; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; default: break; } @@ -271,72 +269,72 @@ static const struct ad5380_chip_info ad5380_chip_info_tbl[] = { [ID_AD5380_3] = { .channel_template = AD5380_CHANNEL(14), .num_channels = 40, - .int_vref = 1250000, + .int_vref = 1250, }, [ID_AD5380_5] = { .channel_template = AD5380_CHANNEL(14), .num_channels = 40, - .int_vref = 2500000, + .int_vref = 2500, }, [ID_AD5381_3] = { .channel_template = AD5380_CHANNEL(12), .num_channels = 16, - .int_vref = 1250000, + .int_vref = 1250, }, [ID_AD5381_5] = { .channel_template = AD5380_CHANNEL(12), .num_channels = 16, - .int_vref = 2500000, + .int_vref = 2500, }, [ID_AD5382_3] = { .channel_template = AD5380_CHANNEL(14), .num_channels = 32, - .int_vref = 1250000, + .int_vref = 1250, }, [ID_AD5382_5] = { .channel_template = AD5380_CHANNEL(14), .num_channels = 32, - .int_vref = 2500000, + .int_vref = 2500, }, [ID_AD5383_3] = { .channel_template = AD5380_CHANNEL(12), .num_channels = 32, - .int_vref = 1250000, + .int_vref = 1250, }, [ID_AD5383_5] = { .channel_template = AD5380_CHANNEL(12), .num_channels = 32, - .int_vref = 2500000, + .int_vref = 2500, }, [ID_AD5390_3] = { .channel_template = AD5380_CHANNEL(14), .num_channels = 16, - .int_vref = 1250000, + .int_vref = 1250, }, [ID_AD5390_5] = { .channel_template = AD5380_CHANNEL(14), .num_channels = 16, - .int_vref = 2500000, + .int_vref = 2500, }, [ID_AD5391_3] = { .channel_template = AD5380_CHANNEL(12), .num_channels = 16, - .int_vref = 1250000, + .int_vref = 1250, }, [ID_AD5391_5] = { .channel_template = AD5380_CHANNEL(12), .num_channels = 16, - .int_vref = 2500000, + .int_vref = 2500, }, [ID_AD5392_3] = { .channel_template = AD5380_CHANNEL(14), .num_channels = 8, - .int_vref = 1250000, + .int_vref = 1250, }, [ID_AD5392_5] = { .channel_template = AD5380_CHANNEL(14), .num_channels = 8, - .int_vref = 2500000, + .int_vref = 2500, }, }; @@ -395,7 +393,7 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap, return ret; } - if (st->chip_info->int_vref == 2500000) + if (st->chip_info->int_vref == 2500) ctrl |= AD5380_CTRL_INT_VREF_2V5; st->vref_reg = devm_regulator_get(dev, "vref"); @@ -411,7 +409,7 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap, if (ret < 0) goto error_disable_reg; - st->vref = ret; + st->vref = ret / 1000; } else { st->vref = st->chip_info->int_vref; ctrl |= AD5380_CTRL_INT_VREF_EN; From bc7c49bc77ba95609236f23082a38ec160416a8d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 06/51] iio:ad5421: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5421.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index 1f78b14abb7d..567c4bd546e5 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -281,18 +281,11 @@ static inline unsigned int ad5421_get_offset(struct ad5421_state *st) return (min * (1 << 16)) / (max - min); } -static inline unsigned int ad5421_get_scale(struct ad5421_state *st) -{ - unsigned int min, max; - - ad5421_get_current_min_max(st, &min, &max); - return ((max - min) * 1000) / (1 << 16); -} - static int ad5421_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long m) { struct ad5421_state *st = iio_priv(indio_dev); + unsigned int min, max; int ret; if (chan->type != IIO_CURRENT) @@ -306,9 +299,10 @@ static int ad5421_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = ad5421_get_scale(st); - return IIO_VAL_INT_PLUS_MICRO; + ad5421_get_current_min_max(st, &min, &max); + *val = max - min; + *val2 = (1 << 16) * 1000; + return IIO_VAL_FRACTIONAL; case IIO_CHAN_INFO_OFFSET: *val = ad5421_get_offset(st); return IIO_VAL_INT; From 0a99b6014343e39d7e01ebfc386fb16c8a5a6826 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 07/51] iio:ad5446: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5446.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 8e28d3633e22..1263b0e5ad84 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -163,18 +163,15 @@ static int ad5446_read_raw(struct iio_dev *indio_dev, long m) { struct ad5446_state *st = iio_priv(indio_dev); - unsigned long scale_uv; switch (m) { case IIO_CHAN_INFO_RAW: *val = st->cached_val; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - + *val = st->vref_mv; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } From 54ea14339ddd28b935773d65257024757c9358d5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 08/51] iio:ad5504: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5504.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index 31f4ff29f914..c0957a918e17 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -100,7 +100,6 @@ static int ad5504_read_raw(struct iio_dev *indio_dev, long m) { struct ad5504_state *st = iio_priv(indio_dev); - unsigned long scale_uv; int ret; switch (m) { @@ -113,11 +112,9 @@ static int ad5504_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - + *val = st->vref_mv; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } From 14229e87a977c3c33bd33a95b77d2de48d2b46e9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 09/51] iio:ad5624r: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5624r_spi.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index dbb1289cc7a6..774dd968145b 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -50,15 +50,12 @@ static int ad5624r_read_raw(struct iio_dev *indio_dev, long m) { struct ad5624r_state *st = iio_priv(indio_dev); - unsigned long scale_uv; switch (m) { case IIO_CHAN_INFO_SCALE: - scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - + *val = st->vref_mv; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } From ecc7e948bca09b97b6b1d0f4b4516bee34e8ce6b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 10/51] iio:ad5686: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5686.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index f472b48445f6..30e506e37dd2 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -201,7 +201,6 @@ static int ad5686_read_raw(struct iio_dev *indio_dev, long m) { struct ad5686_state *st = iio_priv(indio_dev); - unsigned long scale_uv; int ret; switch (m) { @@ -214,12 +213,9 @@ static int ad5686_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (st->vref_mv * 100000) - >> (chan->scan_type.realbits); - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; - + *val = st->vref_mv; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } From ae76751f67110f497848afd71d06a0b6bb4a7c89 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 11/51] iio:ad5755: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5755.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index f305a0c83418..bd31dbc340c1 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -253,15 +253,6 @@ static inline int ad5755_get_offset(struct ad5755_state *st, return (min * (1 << chan->scan_type.realbits)) / (max - min); } -static inline int ad5755_get_scale(struct ad5755_state *st, - struct iio_chan_spec const *chan) -{ - int min, max; - - ad5755_get_min_max(st, chan, &min, &max); - return ((max - min) * 1000000000ULL) >> chan->scan_type.realbits; -} - static int ad5755_chan_reg_info(struct ad5755_state *st, struct iio_chan_spec const *chan, long info, bool write, unsigned int *reg, unsigned int *shift, unsigned int *offset) @@ -303,13 +294,15 @@ static int ad5755_read_raw(struct iio_dev *indio_dev, { struct ad5755_state *st = iio_priv(indio_dev); unsigned int reg, shift, offset; + int min, max; int ret; switch (info) { case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = ad5755_get_scale(st, chan); - return IIO_VAL_INT_PLUS_NANO; + ad5755_get_min_max(st, chan, &min, &max); + *val = max - min; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_OFFSET: *val = ad5755_get_offset(st, chan); return IIO_VAL_INT; From 3f83dae88422992140b6125ab866cdec9fd7b3b6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 12/51] iio:ad5764: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Also fix a off by one error in the comment describing the transfer function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5764.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c index df7e028d9db5..a8ff5b2ed13e 100644 --- a/drivers/iio/dac/ad5764.c +++ b/drivers/iio/dac/ad5764.c @@ -217,7 +217,6 @@ static int ad5764_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info) { struct ad5764_state *st = iio_priv(indio_dev); - unsigned long scale_uv; unsigned int reg; int vref; int ret; @@ -245,15 +244,14 @@ static int ad5764_read_raw(struct iio_dev *indio_dev, *val = sign_extend32(*val, 5); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - /* vout = 4 * vref + ((dac_code / 65535) - 0.5) */ + /* vout = 4 * vref + ((dac_code / 65536) - 0.5) */ vref = ad5764_get_channel_vref(st, chan->channel); if (vref < 0) return vref; - scale_uv = (vref * 4 * 100) >> chan->scan_type.realbits; - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; + *val = vref * 4 / 1000; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_OFFSET: *val = -(1 << chan->scan_type.realbits) / 2; return IIO_VAL_INT; From 213983cd32a7d983675d86ece17ac040bd39fd47 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 13/51] iio:ad5791: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5791.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index 3cee89be68c3..d64acbd89482 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -270,9 +270,9 @@ static int ad5791_read_raw(struct iio_dev *indio_dev, *val >>= chan->scan_type.shift; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits; - return IIO_VAL_INT_PLUS_MICRO; + *val = st->vref_mv; + *val2 = (1 << chan->scan_type.realbits) - 1; + return IIO_VAL_FRACTIONAL; case IIO_CHAN_INFO_OFFSET: val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits); do_div(val64, st->vref_mv); From 998f129c76e2030ad2e68cf59d75eef0e5a58fd3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 14/51] iio:max517: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/max517.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c index 83adcbf1a205..d26be14fff64 100644 --- a/drivers/iio/dac/max517.c +++ b/drivers/iio/dac/max517.c @@ -82,15 +82,13 @@ static int max517_read_raw(struct iio_dev *indio_dev, long m) { struct max517_data *data = iio_priv(indio_dev); - unsigned int scale_uv; switch (m) { case IIO_CHAN_INFO_SCALE: /* Corresponds to Vref / 2^(bits) */ - scale_uv = (data->vref_mv[chan->channel] * 1000) >> 8; - *val = scale_uv / 1000000; - *val2 = scale_uv % 1000000; - return IIO_VAL_INT_PLUS_MICRO; + *val = data->vref_mv[chan->channel]; + *val2 = 8; + return IIO_VAL_FRACTIONAL_LOG2; default: break; } From b117f96f49c92751574042136b99b8ba7eb8977f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 15/51] iio:mcp4725: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Cc: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/dac/mcp4725.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 7a42d85269bb..d982752dd9c4 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -239,17 +239,15 @@ static int mcp4725_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct mcp4725_data *data = iio_priv(indio_dev); - unsigned long scale_uv; switch (mask) { case IIO_CHAN_INFO_RAW: *val = data->dac_value; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (data->vref_mv * 1000) >> 12; - *val = scale_uv / 1000000; - *val2 = scale_uv % 1000000; - return IIO_VAL_INT_PLUS_MICRO; + *val = data->vref_mv; + *val2 = 12; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } From 2ebc39c0bbb30d6f06c3fe65c458e546db275f6d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 16/51] iio:ad7266: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7266.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 656aa3e102f2..f5723cbd2032 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -27,7 +27,7 @@ struct ad7266_state { struct spi_device *spi; struct regulator *reg; - unsigned long vref_uv; + unsigned long vref_mv; struct spi_transfer single_xfer[3]; struct spi_message single_msg; @@ -156,7 +156,7 @@ static int ad7266_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long m) { struct ad7266_state *st = iio_priv(indio_dev); - unsigned long scale_uv; + unsigned long scale_mv; int ret; switch (m) { @@ -174,16 +174,15 @@ static int ad7266_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (st->vref_uv * 100); + scale_mv = st->vref_mv; if (st->mode == AD7266_MODE_DIFF) - scale_uv *= 2; + scale_mv *= 2; if (st->range == AD7266_RANGE_2VREF) - scale_uv *= 2; + scale_mv *= 2; - scale_uv >>= chan->scan_type.realbits; - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; + *val = scale_mv; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_OFFSET: if (st->range == AD7266_RANGE_2VREF && st->mode != AD7266_MODE_DIFF) @@ -414,10 +413,10 @@ static int ad7266_probe(struct spi_device *spi) if (ret < 0) goto error_disable_reg; - st->vref_uv = ret; + st->vref_mv = ret / 1000; } else { /* Use internal reference */ - st->vref_uv = 2500000; + st->vref_mv = 2500; } if (pdata) { From d88c89db9a7550c2ed6551f73b6702faee190434 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 17/51] iio:ad7476: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7476.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c index 8d808b9de909..d141d452c3d1 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c @@ -127,10 +127,9 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, } else { scale_uv = st->chip_info->int_vref_uv; } - scale_uv >>= chan->scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; + *val = scale_uv / 1000; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } From 488a21827a257b735571468632e9f677b13bdddd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 18/51] iio:ad7791: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7791.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index c20203577d2d..c19f8fd1b4b7 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -202,7 +202,6 @@ static int ad7791_read_raw(struct iio_dev *indio_dev, { struct ad7791_state *st = iio_priv(indio_dev); bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR); - unsigned long long scale_pv; switch (info) { case IIO_CHAN_INFO_RAW: @@ -220,23 +219,26 @@ static int ad7791_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: /* The monitor channel uses an internal reference. */ if (chan->address == AD7791_CH_AVDD_MONITOR) { - scale_pv = 5850000000000ULL; + /* + * The signal is attenuated by a factor of 5 and + * compared against a 1.17V internal reference. + */ + *val = 1170 * 5; } else { int voltage_uv; voltage_uv = regulator_get_voltage(st->reg); if (voltage_uv < 0) return voltage_uv; - scale_pv = (unsigned long long)voltage_uv * 1000000; + + *val = voltage_uv / 1000; } if (unipolar) - scale_pv >>= chan->scan_type.realbits; + *val2 = chan->scan_type.realbits; else - scale_pv >>= chan->scan_type.realbits - 1; - *val2 = do_div(scale_pv, 1000000000); - *val = scale_pv; + *val2 = chan->scan_type.realbits - 1; - return IIO_VAL_INT_PLUS_NANO; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; From c45e561ee81477903b8254331cb2e28e04082de5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 19/51] iio:at91: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Cc: Josh Wu Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 78121949d6ef..8b93295369b0 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -366,9 +366,9 @@ static int at91_adc_read_raw(struct iio_dev *idev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = (st->vref_mv * 1000) >> chan->scan_type.realbits; - *val2 = 0; - return IIO_VAL_INT_PLUS_MICRO; + *val = st->vref_mv; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; default: break; } From b2171677cbf8c781679b588fdffabfe0eaecbcdc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 20/51] iio:max1363: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max1363.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index b4bc166d57b0..2b34d2f02cf3 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -397,7 +397,6 @@ 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: @@ -406,10 +405,9 @@ static int max1363_read_raw(struct iio_dev *indio_dev, return ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = st->vref_uv >> st->chip_info->bits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; + *val = st->vref_uv / 1000; + *val2 = st->chip_info->bits; + return IIO_VAL_FRACTIONAL_LOG2; default: return -EINVAL; } From d6570b33a1c0620774fe693030ef9e0317dafd84 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 21/51] staging:iio:ad7280a: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7280a.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index e7191e44a970..8209fa542a8a 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -783,7 +783,6 @@ static int ad7280_read_raw(struct iio_dev *indio_dev, long m) { struct ad7280_state *st = iio_priv(indio_dev); - unsigned int scale_uv; int ret; switch (m) { @@ -804,13 +803,12 @@ static int ad7280_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6) - scale_uv = (4000 * 1000) >> AD7280A_BITS; + *val = 4000; else - scale_uv = (5000 * 1000) >> AD7280A_BITS; + *val = 5000; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; + *val2 = AD7280A_BITS; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } From 9324131b5a3cccd4acf1408539502503a5bee206 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 22/51] staging:iio:ad7606: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_core.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index f042027b5291..2083673a79ca 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -85,7 +85,6 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, { int ret; struct ad7606_state *st = iio_priv(indio_dev); - unsigned int scale_uv; switch (m) { case IIO_CHAN_INFO_RAW: @@ -101,11 +100,9 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, *val = (short) ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (st->range * 1000 * 2) - >> st->chip_info->channels[0].scan_type.realbits; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; + *val = st->range * 2; + *val2 = st->chip_info->channels[0].scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } From c0d014122de56d17f65048e4737d039c89aa7e8f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 23/51] staging:iio:ad7780: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7780.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index 4f2522a9edfb..273add3ed63f 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -90,17 +90,14 @@ static int ad7780_read_raw(struct iio_dev *indio_dev, long m) { struct ad7780_state *st = iio_priv(indio_dev); - unsigned long scale_uv; switch (m) { case IIO_CHAN_INFO_RAW: return ad_sigma_delta_single_conversion(indio_dev, chan, val); case IIO_CHAN_INFO_SCALE: - scale_uv = (st->int_vref_mv * 100000 * st->gain) - >> (chan->scan_type.realbits - 1); - *val = scale_uv / 100000; - *val2 = (scale_uv % 100000) * 10; - return IIO_VAL_INT_PLUS_MICRO; + *val = st->int_vref_mv * st->gain; + *val2 = chan->scan_type.realbits - 1; + return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_OFFSET: *val -= (1 << (chan->scan_type.realbits - 1)); return IIO_VAL_INT; From b740f48a3d0d118b160db7c9559fb75de8af8657 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 24/51] staging:iio:ad799x: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad799x_core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 3f5142b284d1..eb6a690e6e90 100644 --- 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_dev *indio_dev, { int ret; struct ad799x_state *st = iio_priv(indio_dev); - unsigned int scale_uv; switch (m) { case IIO_CHAN_INFO_RAW: @@ -180,10 +179,9 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, 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; + *val = st->int_vref_mv; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } From 4f9be985865f9c83ed724b62be9bb65921226221 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 25/51] staging:iio:ad7746: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 75a533bce021..862d68d99630 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -656,20 +656,21 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, switch (chan->type) { case IIO_CAPACITANCE: /* 8.192pf / 2^24 */ - *val2 = 488; *val = 0; + *val2 = 488; + ret = IIO_VAL_INT_PLUS_NANO; break; case IIO_VOLTAGE: /* 1170mV / 2^23 */ - *val2 = 139475; - *val = 0; + *val = 1170; + *val2 = 23; + ret = IIO_VAL_FRACTIONAL_LOG2; break; default: - ret = -EINVAL; - goto out; + ret = -EINVAL; + break; } - ret = IIO_VAL_INT_PLUS_NANO; break; default: ret = -EINVAL; From bfbab2bcf9718ef5e778df8a746e5f4fb8ccd4f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 26/51] staging:iio:spear_adc: Report scale as fractional value Move the complexity of calculating the fixed point scale to the core. Signed-off-by: Lars-Peter Clausen Cc: Stefan Roese Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/spear_adc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c index 20f2d555e7cd..657e01bd733c 100644 --- a/drivers/staging/iio/adc/spear_adc.c +++ b/drivers/staging/iio/adc/spear_adc.c @@ -168,10 +168,9 @@ static int spear_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_mv = (info->vref_external * 1000) >> DATA_BITS; - *val = scale_mv / 1000; - *val2 = (scale_mv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; + *val = info->vref_external; + *val2 = DATA_BITS; + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; From c2b2db71014696207b24a2bafb2d26867f82dbed Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 Sep 2013 10:31:00 +0100 Subject: [PATCH 27/51] iio: Update unit of the voltage scale in the documentation The documentation says that the result of raw * scale should be in microvolts, but in reallity all drivers actually report the scale so that the result is in millivolts. So update the documentation to match reallity. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index ab1047c20495..2d73620874b2 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -79,7 +79,7 @@ Description: correspond to externally available input one of the named versions may be used. The number must always be specified and unique to allow association with event codes. Units after - application of scale and offset are microvolts. + application of scale and offset are millivolts. What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw KernelVersion: 2.6.35 @@ -90,7 +90,7 @@ Description: physically equivalent inputs when non differential readings are separately available. In differential only parts, then all that is required is a consistent labeling. Units after application - of scale and offset are microvolts. + of scale and offset are millivolts. What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw KernelVersion: 3.2 From 8a5c19132458a0e74c09aea9ccfe061edfea0151 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Thu, 19 Sep 2013 20:35:00 +0100 Subject: [PATCH 28/51] staging:iio:hmc5843: Add pointer to i2c client to data struct and use it to simplify code Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/magnetometer/hmc5843.c | 61 +++++++++------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 76e0cf43197e..05f95d0795c9 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -182,6 +182,7 @@ struct hmc5843_chip_info { /* Each client has this additional data */ struct hmc5843_data { + struct i2c_client *client; struct mutex lock; u8 rate; u8 meas_conf; @@ -200,18 +201,15 @@ static s32 hmc5843_configure(struct i2c_client *client, } /* Return the measurement value from the specified channel */ -static int hmc5843_read_measurement(struct iio_dev *indio_dev, - int address, - int *val) +static int hmc5843_read_measurement(struct hmc5843_data *data, + int address, int *val) { - struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); - struct hmc5843_data *data = iio_priv(indio_dev); s32 result; int tries = 150; mutex_lock(&data->lock); while (tries-- > 0) { - result = i2c_smbus_read_byte_data(client, + result = i2c_smbus_read_byte_data(data->client, HMC5843_STATUS_REG); if (result & HMC5843_DATA_READY) break; @@ -219,12 +217,12 @@ static int hmc5843_read_measurement(struct iio_dev *indio_dev, } if (tries < 0) { - dev_err(&client->dev, "data not ready\n"); + dev_err(&data->client->dev, "data not ready\n"); mutex_unlock(&data->lock); return -EIO; } - result = i2c_smbus_read_word_swapped(client, address); + result = i2c_smbus_read_word_swapped(data->client, address); mutex_unlock(&data->lock); if (result < 0) return -EINVAL; @@ -318,15 +316,13 @@ static IIO_DEVICE_ATTR(operating_mode, * and BN. * */ -static s32 hmc5843_set_meas_conf(struct i2c_client *client, - u8 meas_conf) +static s32 hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct hmc5843_data *data = iio_priv(indio_dev); u8 reg_val; reg_val = (meas_conf & HMC5843_MEAS_CONF_MASK) | (data->rate << HMC5843_RATE_OFFSET); - return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val); + return i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A, + reg_val); } static ssize_t hmc5843_show_measurement_configuration(struct device *dev, @@ -344,7 +340,6 @@ static ssize_t hmc5843_set_measurement_configuration(struct device *dev, size_t count) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); struct hmc5843_data *data = iio_priv(indio_dev); unsigned long meas_conf = 0; int error; @@ -357,7 +352,7 @@ static ssize_t hmc5843_set_measurement_configuration(struct device *dev, mutex_lock(&data->lock); dev_dbg(dev, "set measurement configuration to %lu\n", meas_conf); - if (hmc5843_set_meas_conf(client, meas_conf)) { + if (hmc5843_set_meas_conf(data, meas_conf)) { count = -EINVAL; goto exit; } @@ -396,21 +391,19 @@ static ssize_t hmc5843_show_sampling_frequencies_available(struct device *dev, static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_sampling_frequencies_available); -static s32 hmc5843_set_rate(struct i2c_client *client, - u8 rate) +static s32 hmc5843_set_rate(struct hmc5843_data *data, u8 rate) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct hmc5843_data *data = iio_priv(indio_dev); u8 reg_val; if (rate >= HMC5843_RATE_NOT_USED) { - dev_err(&client->dev, + dev_err(&data->client->dev, "data output rate is not supported\n"); return -EINVAL; } reg_val = data->meas_conf | (rate << HMC5843_RATE_OFFSET); - return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val); + return i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A, + reg_val); } static int hmc5843_check_sampling_frequency(struct hmc5843_data *data, @@ -433,20 +426,19 @@ static ssize_t hmc5843_set_sampling_frequency(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); struct hmc5843_data *data = iio_priv(indio_dev); int rate; rate = hmc5843_check_sampling_frequency(data, buf); if (rate < 0) { - dev_err(&client->dev, + dev_err(&data->client->dev, "sampling frequency is not supported\n"); return rate; } mutex_lock(&data->lock); dev_dbg(dev, "set rate to %d\n", rate); - if (hmc5843_set_rate(client, rate)) { + if (hmc5843_set_rate(data, rate)) { count = -EINVAL; goto exit; } @@ -461,12 +453,11 @@ static ssize_t hmc5843_show_sampling_frequency(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct hmc5843_data *data = iio_priv(indio_dev); s32 rate; - rate = i2c_smbus_read_byte_data(client, this_attr->address); + rate = i2c_smbus_read_byte_data(data->client, this_attr->address); if (rate < 0) return rate; rate = (rate & HMC5843_RATE_BITMASK) >> HMC5843_RATE_OFFSET; @@ -497,7 +488,6 @@ static ssize_t hmc5843_set_range_gain(struct device *dev, size_t count) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct hmc5843_data *data = iio_priv(indio_dev); unsigned long range = 0; @@ -518,7 +508,7 @@ static ssize_t hmc5843_set_range_gain(struct device *dev, data->range = range; range = range << HMC5843_RANGE_GAIN_OFFSET; - if (i2c_smbus_write_byte_data(client, this_attr->address, range)) + if (i2c_smbus_write_byte_data(data->client, this_attr->address, range)) count = -EINVAL; exit: @@ -541,9 +531,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - return hmc5843_read_measurement(indio_dev, - chan->address, - val); + return hmc5843_read_measurement(data, chan->address, val); case IIO_CHAN_INFO_SCALE: *val = 0; *val2 = data->variant->regval_to_nanoscale[data->range]; @@ -621,8 +609,8 @@ static void hmc5843_init_client(struct i2c_client *client, data->variant = &hmc5843_chip_info_tbl[id->driver_data]; indio_dev->channels = data->variant->channels; indio_dev->num_channels = 3; - hmc5843_set_meas_conf(client, data->meas_conf); - hmc5843_set_rate(client, data->rate); + hmc5843_set_meas_conf(data, data->meas_conf); + hmc5843_set_rate(data, data->rate); hmc5843_configure(client, data->operating_mode); i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_B, data->range); mutex_init(&data->lock); @@ -649,6 +637,7 @@ static int hmc5843_probe(struct i2c_client *client, /* default settings at probe */ data = iio_priv(indio_dev); + data->client = client; data->meas_conf = HMC5843_MEAS_CONF_NORMAL; data->range = HMC5843_RANGE_GAIN_DEFAULT; data->operating_mode = HMC5843_MODE_CONVERSION_CONTINUOUS; @@ -687,10 +676,10 @@ static int hmc5843_suspend(struct device *dev) static int hmc5843_resume(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct hmc5843_data *data = iio_priv(i2c_get_clientdata(client)); + struct hmc5843_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); - hmc5843_configure(client, data->operating_mode); + hmc5843_configure(data->client, data->operating_mode); return 0; } From 8e2e2971b0f7135db305121efbcf703c79c4c093 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Thu, 19 Sep 2013 20:35:00 +0100 Subject: [PATCH 29/51] staging:iio:hmc5843: Rewrite init function Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/magnetometer/hmc5843.c | 34 +++++++++------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 05f95d0795c9..581747419c9e 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -78,6 +78,7 @@ enum hmc5843_ids { * HMC5883: Typical data output rate */ #define HMC5843_RATE_OFFSET 0x02 +#define HMC5843_RATE_DEFAULT 0x04 #define HMC5843_RATE_BITMASK 0x1C #define HMC5843_RATE_NOT_USED 0x07 @@ -599,23 +600,13 @@ static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = { }, }; -/* Called when we have found a new HMC58X3 */ -static void hmc5843_init_client(struct i2c_client *client, - const struct i2c_device_id *id) +static void hmc5843_init(struct hmc5843_data *data) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct hmc5843_data *data = iio_priv(indio_dev); - - data->variant = &hmc5843_chip_info_tbl[id->driver_data]; - indio_dev->channels = data->variant->channels; - indio_dev->num_channels = 3; - hmc5843_set_meas_conf(data, data->meas_conf); - hmc5843_set_rate(data, data->rate); - hmc5843_configure(client, data->operating_mode); - i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_B, data->range); - mutex_init(&data->lock); - - pr_info("%s initialized\n", id->name); + hmc5843_set_meas_conf(data, HMC5843_MEAS_CONF_NORMAL); + hmc5843_set_rate(data, HMC5843_RATE_DEFAULT); + hmc5843_configure(data->client, HMC5843_MODE_CONVERSION_CONTINUOUS); + i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_B, + HMC5843_RANGE_GAIN_DEFAULT); } static const struct iio_info hmc5843_info = { @@ -638,17 +629,18 @@ static int hmc5843_probe(struct i2c_client *client, /* default settings at probe */ data = iio_priv(indio_dev); data->client = client; - data->meas_conf = HMC5843_MEAS_CONF_NORMAL; - data->range = HMC5843_RANGE_GAIN_DEFAULT; - data->operating_mode = HMC5843_MODE_CONVERSION_CONTINUOUS; + data->variant = &hmc5843_chip_info_tbl[id->driver_data]; + mutex_init(&data->lock); i2c_set_clientdata(client, indio_dev); - hmc5843_init_client(client, id); - indio_dev->info = &hmc5843_info; indio_dev->name = id->name; indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = data->variant->channels; + indio_dev->num_channels = 3; + + hmc5843_init(data); err = iio_device_register(indio_dev); if (err) From d4dc0a349ee48832550f9aea154ca3af37f244ec Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Thu, 19 Sep 2013 20:35:00 +0100 Subject: [PATCH 30/51] staging:iio:hmc5843: Use INFO_SAMP_FREQ Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/magnetometer/hmc5843.c | 135 +++++++++------------ 1 file changed, 54 insertions(+), 81 deletions(-) diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 581747419c9e..6e813622ded8 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -165,18 +165,19 @@ static const int hmc5883l_regval_to_input_field_mga[] = { * 6 | 50 | 75 * 7 | Not used | Not used */ -static const char * const hmc5843_regval_to_sample_freq[] = { - "0.5", "1", "2", "5", "10", "20", "50", +static const int hmc5843_regval_to_samp_freq[7][2] = { + {0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0} }; -static const char * const hmc5883_regval_to_sample_freq[] = { - "0.75", "1.5", "3", "7.5", "15", "30", "75", +static const int hmc5883_regval_to_samp_freq[7][2] = { + {0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0}, + {75, 0} }; /* Describe chip variants */ struct hmc5843_chip_info { const struct iio_chan_spec *channels; - const char * const *regval_to_sample_freq; + const int (*regval_to_samp_freq)[2]; const int *regval_to_input_field_mga; const int *regval_to_nanoscale; }; @@ -370,17 +371,17 @@ static IIO_DEVICE_ATTR(meas_conf, hmc5843_set_measurement_configuration, 0); -static ssize_t hmc5843_show_sampling_frequencies_available(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t hmc5843_show_samp_freq_avail(struct device *dev, + struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct hmc5843_data *data = iio_priv(indio_dev); + struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev)); ssize_t total_n = 0; int i; for (i = 0; i < HMC5843_RATE_NOT_USED; i++) { - ssize_t n = sprintf(buf, "%s ", data->variant->regval_to_sample_freq[i]); + ssize_t n = sprintf(buf, "%d.%d ", + data->variant->regval_to_samp_freq[i][0], + data->variant->regval_to_samp_freq[i][1]); buf += n; total_n += n; } @@ -390,87 +391,30 @@ static ssize_t hmc5843_show_sampling_frequencies_available(struct device *dev, return total_n; } -static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_sampling_frequencies_available); +static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail); static s32 hmc5843_set_rate(struct hmc5843_data *data, u8 rate) { - u8 reg_val; + u8 reg_val = data->meas_conf | (rate << HMC5843_RATE_OFFSET); - if (rate >= HMC5843_RATE_NOT_USED) { - dev_err(&data->client->dev, - "data output rate is not supported\n"); - return -EINVAL; - } - - reg_val = data->meas_conf | (rate << HMC5843_RATE_OFFSET); return i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A, reg_val); } -static int hmc5843_check_sampling_frequency(struct hmc5843_data *data, - const char *buf) +static int hmc5843_check_samp_freq(struct hmc5843_data *data, + int val, int val2) { - const char * const *samp_freq = data->variant->regval_to_sample_freq; int i; for (i = 0; i < HMC5843_RATE_NOT_USED; i++) { - if (sysfs_streq(buf, samp_freq[i])) + if (val == data->variant->regval_to_samp_freq[i][0] && + val2 == data->variant->regval_to_samp_freq[i][1]) return i; } return -EINVAL; } -static ssize_t hmc5843_set_sampling_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct hmc5843_data *data = iio_priv(indio_dev); - int rate; - - rate = hmc5843_check_sampling_frequency(data, buf); - if (rate < 0) { - dev_err(&data->client->dev, - "sampling frequency is not supported\n"); - return rate; - } - - mutex_lock(&data->lock); - dev_dbg(dev, "set rate to %d\n", rate); - if (hmc5843_set_rate(data, rate)) { - count = -EINVAL; - goto exit; - } - data->rate = rate; - -exit: - mutex_unlock(&data->lock); - return count; -} - -static ssize_t hmc5843_show_sampling_frequency(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct hmc5843_data *data = iio_priv(indio_dev); - s32 rate; - - rate = i2c_smbus_read_byte_data(data->client, this_attr->address); - if (rate < 0) - return rate; - rate = (rate & HMC5843_RATE_BITMASK) >> HMC5843_RATE_OFFSET; - return sprintf(buf, "%s\n", data->variant->regval_to_sample_freq[rate]); -} - -static IIO_DEVICE_ATTR(sampling_frequency, - S_IWUSR | S_IRUGO, - hmc5843_show_sampling_frequency, - hmc5843_set_sampling_frequency, - HMC5843_CONFIG_REG_A); - static ssize_t hmc5843_show_range_gain(struct device *dev, struct device_attribute *attr, char *buf) @@ -525,8 +469,7 @@ static IIO_DEVICE_ATTR(in_magn_range, static int hmc5843_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) + int *val, int *val2, long mask) { struct hmc5843_data *data = iio_priv(indio_dev); @@ -537,17 +480,47 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev, *val = 0; *val2 = data->variant->regval_to_nanoscale[data->range]; return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = data->variant->regval_to_samp_freq[data->rate][0]; + *val2 = data->variant->regval_to_samp_freq[data->rate][1]; + return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; } +static int hmc5843_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct hmc5843_data *data = iio_priv(indio_dev); + int ret, rate; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + rate = hmc5843_check_samp_freq(data, val, val2); + if (rate < 0) + return -EINVAL; + + mutex_lock(&data->lock); + ret = hmc5843_set_rate(data, rate); + if (ret >= 0) + data->rate = rate; + mutex_unlock(&data->lock); + + return ret; + default: + return -EINVAL; + } +} + #define HMC5843_CHANNEL(axis, addr) \ { \ .type = IIO_MAGN, \ .modified = 1, \ .channel2 = IIO_MOD_##axis, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = addr \ } @@ -566,7 +539,6 @@ static const struct iio_chan_spec hmc5883_channels[] = { static struct attribute *hmc5843_attributes[] = { &iio_dev_attr_meas_conf.dev_attr.attr, &iio_dev_attr_operating_mode.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_in_magn_range.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr, NULL @@ -579,21 +551,21 @@ static const struct attribute_group hmc5843_group = { static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = { [HMC5843_ID] = { .channels = hmc5843_channels, - .regval_to_sample_freq = hmc5843_regval_to_sample_freq, + .regval_to_samp_freq = hmc5843_regval_to_samp_freq, .regval_to_input_field_mga = hmc5843_regval_to_input_field_mga, .regval_to_nanoscale = hmc5843_regval_to_nanoscale, }, [HMC5883_ID] = { .channels = hmc5883_channels, - .regval_to_sample_freq = hmc5883_regval_to_sample_freq, + .regval_to_samp_freq = hmc5883_regval_to_samp_freq, .regval_to_input_field_mga = hmc5883_regval_to_input_field_mga, .regval_to_nanoscale = hmc5883_regval_to_nanoscale, }, [HMC5883L_ID] = { .channels = hmc5883_channels, - .regval_to_sample_freq = hmc5883_regval_to_sample_freq, + .regval_to_samp_freq = hmc5883_regval_to_samp_freq, .regval_to_input_field_mga = hmc5883l_regval_to_input_field_mga, .regval_to_nanoscale = hmc5883l_regval_to_nanoscale, @@ -612,6 +584,7 @@ static void hmc5843_init(struct hmc5843_data *data) static const struct iio_info hmc5843_info = { .attrs = &hmc5843_group, .read_raw = &hmc5843_read_raw, + .write_raw = &hmc5843_write_raw, .driver_module = THIS_MODULE, }; From 511c81e64a21b2d1a3f72e998a6933321ea31a04 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Thu, 19 Sep 2013 20:35:00 +0100 Subject: [PATCH 31/51] staging:iio:hmc5843: Remove unused LSB register #defines Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/magnetometer/hmc5843.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 6e813622ded8..e103172a96a1 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -29,16 +29,11 @@ #define HMC5843_CONFIG_REG_B 0x01 #define HMC5843_MODE_REG 0x02 #define HMC5843_DATA_OUT_X_MSB_REG 0x03 -#define HMC5843_DATA_OUT_X_LSB_REG 0x04 #define HMC5843_DATA_OUT_Y_MSB_REG 0x05 -#define HMC5843_DATA_OUT_Y_LSB_REG 0x06 #define HMC5843_DATA_OUT_Z_MSB_REG 0x07 -#define HMC5843_DATA_OUT_Z_LSB_REG 0x08 /* Beware: Y and Z are exchanged on HMC5883 */ #define HMC5883_DATA_OUT_Z_MSB_REG 0x05 -#define HMC5883_DATA_OUT_Z_LSB_REG 0x06 #define HMC5883_DATA_OUT_Y_MSB_REG 0x07 -#define HMC5883_DATA_OUT_Y_LSB_REG 0x08 #define HMC5843_STATUS_REG 0x09 enum hmc5843_ids { @@ -61,8 +56,6 @@ enum hmc5843_ids { */ #define HMC5843_DATA_READY 0x01 #define HMC5843_DATA_OUTPUT_LOCK 0x02 -/* Does not exist on HMC5883, not used */ -#define HMC5843_VOLTAGE_REGULATOR_ENABLED 0x04 /* * Mode register configuration From 9728fe3f8fee9eca682a452b2d615df5d653ff3a Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Thu, 19 Sep 2013 20:35:00 +0100 Subject: [PATCH 32/51] staging:iio:hmc5843: Tighten comments Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/magnetometer/hmc5843.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index e103172a96a1..022f455f9854 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -51,15 +51,11 @@ enum hmc5843_ids { #define HMC5843_RANGE_GAIN_DEFAULT 0x01 #define HMC5843_RANGE_GAIN_MAX 0x07 -/* - * Device status - */ +/* Device status */ #define HMC5843_DATA_READY 0x01 #define HMC5843_DATA_OUTPUT_LOCK 0x02 -/* - * Mode register configuration - */ +/* Mode register configuration */ #define HMC5843_MODE_CONVERSION_CONTINUOUS 0x00 #define HMC5843_MODE_CONVERSION_SINGLE 0x01 #define HMC5843_MODE_IDLE 0x02 @@ -75,18 +71,14 @@ enum hmc5843_ids { #define HMC5843_RATE_BITMASK 0x1C #define HMC5843_RATE_NOT_USED 0x07 -/* - * Device measurement configuration - */ +/* Device measurement configuration */ #define HMC5843_MEAS_CONF_NORMAL 0x00 #define HMC5843_MEAS_CONF_POSITIVE_BIAS 0x01 #define HMC5843_MEAS_CONF_NEGATIVE_BIAS 0x02 #define HMC5843_MEAS_CONF_NOT_USED 0x03 #define HMC5843_MEAS_CONF_MASK 0x03 -/* - * Scaling factors: 10000000/Gain - */ +/* Scaling factors: 10000000/Gain */ static const int hmc5843_regval_to_nanoscale[] = { 6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714 }; From dd28e48278eb2ad5b542b4aa36f28e6251451a73 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Thu, 19 Sep 2013 20:35:00 +0100 Subject: [PATCH 33/51] staging:iio:hmc5843: Introduce helper functions to show/check list of int pairs Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/magnetometer/hmc5843.c | 56 +++++++++++++--------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 022f455f9854..b29622c6f157 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -356,24 +356,42 @@ static IIO_DEVICE_ATTR(meas_conf, hmc5843_set_measurement_configuration, 0); +static ssize_t hmc5843_show_int_plus_micros(char *buf, + const int (*vals)[2], int n) +{ + size_t len = 0; + int i; + + for (i = 0; i < n; i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%d.%d ", vals[i][0], vals[i][1]); + + /* replace trailing space by newline */ + buf[len - 1] = '\n'; + + return len; +} + +static int hmc5843_check_int_plus_micros(const int (*vals)[2], int n, + int val, int val2) +{ + int i; + + for (i = 0; i < n; i++) { + if (val == vals[i][0] && val2 == vals[i][1]) + return i; + } + + return -EINVAL; +} + static ssize_t hmc5843_show_samp_freq_avail(struct device *dev, struct device_attribute *attr, char *buf) { struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev)); - ssize_t total_n = 0; - int i; - for (i = 0; i < HMC5843_RATE_NOT_USED; i++) { - ssize_t n = sprintf(buf, "%d.%d ", - data->variant->regval_to_samp_freq[i][0], - data->variant->regval_to_samp_freq[i][1]); - buf += n; - total_n += n; - } - /* replace trailing space by newline */ - buf[-1] = '\n'; - - return total_n; + return hmc5843_show_int_plus_micros(buf, + data->variant->regval_to_samp_freq, HMC5843_RATE_NOT_USED); } static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail); @@ -389,15 +407,9 @@ static s32 hmc5843_set_rate(struct hmc5843_data *data, u8 rate) static int hmc5843_check_samp_freq(struct hmc5843_data *data, int val, int val2) { - int i; - - for (i = 0; i < HMC5843_RATE_NOT_USED; i++) { - if (val == data->variant->regval_to_samp_freq[i][0] && - val2 == data->variant->regval_to_samp_freq[i][1]) - return i; - } - - return -EINVAL; + return hmc5843_check_int_plus_micros( + data->variant->regval_to_samp_freq, HMC5843_RATE_NOT_USED, + val, val2); } static ssize_t hmc5843_show_range_gain(struct device *dev, From 18da755de59b406ce2371a55fb15ed676eb08ed2 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: [PATCH 34/51] Staging/iio/adc/touchscreen/MXS: add proper clock handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The delay units inside the LRADC depend on the presence of a 2 kHz clock. This change enables the clock to be able to use the delay unit for the touchscreen part of the driver. Signed-off-by: Juergen Beisert Tested-by: Marek Vasut Acked-by: Marek Vasut Tested-by: Lothar Waßmann Signed-off-by: Jonathan Cameron --- arch/arm/boot/dts/imx23.dtsi | 1 + arch/arm/boot/dts/imx28.dtsi | 1 + drivers/staging/iio/adc/mxs-lradc.c | 15 +++++++++++++++ 3 files changed, 17 insertions(+) diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi index 28b5ce289662..07caf767d428 100644 --- a/arch/arm/boot/dts/imx23.dtsi +++ b/arch/arm/boot/dts/imx23.dtsi @@ -430,6 +430,7 @@ reg = <0x80050000 0x2000>; interrupts = <36 37 38 39 40 41 42 43 44>; status = "disabled"; + clocks = <&clks 26>; }; spdif@80054000 { diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index 7363fded95ee..175deefb048b 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -902,6 +902,7 @@ interrupts = <10 14 15 16 17 18 19 20 21 22 23 24 25>; status = "disabled"; + clocks = <&clks 41>; }; spdif: spdif@80054000 { diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 9da64bf00039..93b25ca433cb 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -134,6 +135,8 @@ struct mxs_lradc { void __iomem *base; int irq[13]; + struct clk *clk; + uint32_t *buffer; struct iio_trigger *trig; @@ -922,6 +925,17 @@ static int mxs_lradc_probe(struct platform_device *pdev) if (IS_ERR(lradc->base)) return PTR_ERR(lradc->base); + lradc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(lradc->clk)) { + dev_err(dev, "Failed to get the delay unit clock\n"); + return PTR_ERR(lradc->clk); + } + ret = clk_prepare_enable(lradc->clk); + if (ret != 0) { + dev_err(dev, "Failed to enable the delay unit clock\n"); + return ret; + } + INIT_WORK(&lradc->ts_work, mxs_lradc_ts_work); /* Check if touchscreen is enabled in DT. */ @@ -1014,6 +1028,7 @@ static int mxs_lradc_remove(struct platform_device *pdev) mxs_lradc_trigger_remove(iio); iio_triggered_buffer_cleanup(iio); + clk_disable_unprepare(lradc->clk); return 0; } From ccff52976383c7aff13588e81f23eddaac1dcd05 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: [PATCH 35/51] Staging/iio/adc/touchscreen/MXS: distinguish i.MX23's and i.MX28's LRADC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The LRADC units in i.MX23 and i.MX28 differ and we need to distinguish both SoC variants in order to make the touchscreen work on i.MX23 Signed-off-by: Juergen Beisert Tested-by: Marek Vasut Acked-by: Marek Vasut Tested-by: Lothar Waßmann Signed-off-by: Jonathan Cameron CC: linux-arm-kernel@lists.infradead.org CC: linux-input@vger.kernel.org CC: devel@driverdev.osuosl.org CC: Fabio Estevam CC: Jonathan Cameron --- drivers/staging/iio/adc/mxs-lradc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 93b25ca433cb..1a1219b82233 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -177,6 +177,8 @@ struct mxs_lradc { struct input_dev *ts_input; struct work_struct ts_work; + + enum mxs_lradc_id soc; }; #define LRADC_CTRL0 0x00 @@ -917,6 +919,7 @@ static int mxs_lradc_probe(struct platform_device *pdev) } lradc = iio_priv(iio); + lradc->soc = (enum mxs_lradc_id)of_id->data; /* Grab the memory area */ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); From 7e4d4a6fdb24aeee633a0e19d1ff21a6ec61cedb Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: [PATCH 36/51] Staging/iio/adc/touchscreen/MXS: separate i.MX28 specific register bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to support i.MX23 and i.MX28 within one driver we need to separate the register definitions which differ in both SoC variants. Signed-off-by: Juergen Beisert Tested-by: Marek Vasut Acked-by: Marek Vasut Tested-by: Lothar Waßmann Signed-off-by: Jonathan Cameron CC: linux-arm-kernel@lists.infradead.org CC: linux-input@vger.kernel.org CC: devel@driverdev.osuosl.org CC: Marek Vasut CC: Fabio Estevam --- drivers/staging/iio/adc/mxs-lradc.c | 61 ++++++++++++++++------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 1a1219b82233..1b99d27d4384 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -182,24 +182,29 @@ struct mxs_lradc { }; #define LRADC_CTRL0 0x00 -#define LRADC_CTRL0_TOUCH_DETECT_ENABLE (1 << 23) -#define LRADC_CTRL0_TOUCH_SCREEN_TYPE (1 << 22) -#define LRADC_CTRL0_YNNSW /* YM */ (1 << 21) -#define LRADC_CTRL0_YPNSW /* YP */ (1 << 20) -#define LRADC_CTRL0_YPPSW /* YP */ (1 << 19) -#define LRADC_CTRL0_XNNSW /* XM */ (1 << 18) -#define LRADC_CTRL0_XNPSW /* XM */ (1 << 17) -#define LRADC_CTRL0_XPPSW /* XP */ (1 << 16) -#define LRADC_CTRL0_PLATE_MASK (0x3f << 16) +# define LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE (1 << 23) +# define LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE (1 << 22) +# define LRADC_CTRL0_MX28_YNNSW /* YM */ (1 << 21) +# define LRADC_CTRL0_MX28_YPNSW /* YP */ (1 << 20) +# define LRADC_CTRL0_MX28_YPPSW /* YP */ (1 << 19) +# define LRADC_CTRL0_MX28_XNNSW /* XM */ (1 << 18) +# define LRADC_CTRL0_MX28_XNPSW /* XM */ (1 << 17) +# define LRADC_CTRL0_MX28_XPPSW /* XP */ (1 << 16) + +# define LRADC_CTRL0_MX28_PLATE_MASK \ + (LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \ + LRADC_CTRL0_MX28_YNNSW | LRADC_CTRL0_MX28_YPNSW | \ + LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW | \ + LRADC_CTRL0_MX28_XNPSW | LRADC_CTRL0_MX28_XPPSW) #define LRADC_CTRL1 0x10 #define LRADC_CTRL1_TOUCH_DETECT_IRQ_EN (1 << 24) #define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16)) -#define LRADC_CTRL1_LRADC_IRQ_EN_MASK (0x1fff << 16) +#define LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK (0x1fff << 16) #define LRADC_CTRL1_LRADC_IRQ_EN_OFFSET 16 #define LRADC_CTRL1_TOUCH_DETECT_IRQ (1 << 8) #define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n)) -#define LRADC_CTRL1_LRADC_IRQ_MASK 0x1fff +#define LRADC_CTRL1_MX28_LRADC_IRQ_MASK 0x1fff #define LRADC_CTRL1_LRADC_IRQ_OFFSET 0 #define LRADC_CTRL2 0x20 @@ -267,7 +272,7 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, * Virtual channel 0 is always used here as the others are always not * used if doing raw sampling. */ - writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK, + writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); @@ -322,9 +327,9 @@ static int mxs_lradc_ts_touched(struct mxs_lradc *lradc) uint32_t reg; /* Enable touch detection. */ - writel(LRADC_CTRL0_PLATE_MASK, + writel(LRADC_CTRL0_MX28_PLATE_MASK, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); - writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE, + writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); msleep(LRADC_TS_SAMPLE_DELAY_MS); @@ -370,21 +375,21 @@ static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc, */ switch (plate) { case LRADC_SAMPLE_X: - ctrl0 = LRADC_CTRL0_XPPSW | LRADC_CTRL0_XNNSW; + ctrl0 = LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW; chan = 3; break; case LRADC_SAMPLE_Y: - ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_YNNSW; + ctrl0 = LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW; chan = 4; break; case LRADC_SAMPLE_PRESSURE: - ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_XNNSW; + ctrl0 = LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW; chan = 5; break; } if (change) { - writel(LRADC_CTRL0_PLATE_MASK, + writel(LRADC_CTRL0_MX28_PLATE_MASK, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); writel(ctrl0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); @@ -445,7 +450,7 @@ static void mxs_lradc_ts_work(struct work_struct *ts_work) while (mxs_lradc_ts_touched(lradc)) { /* Disable touch detector so we can sample the touchscreen. */ - writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE, + writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); if (likely(valid)) { @@ -494,7 +499,7 @@ static int mxs_lradc_ts_open(struct input_dev *dev) lradc->stop_touchscreen = false; /* Enable the touch-detect circuitry. */ - writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE, + writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); /* Enable the touch-detect IRQ. */ @@ -520,7 +525,7 @@ static void mxs_lradc_ts_close(struct input_dev *dev) lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); /* Power-down touchscreen touch-detect circuitry. */ - writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE, + writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); } @@ -584,7 +589,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | LRADC_CTRL1_TOUCH_DETECT_IRQ; - if (!(reg & LRADC_CTRL1_LRADC_IRQ_MASK)) + if (!(reg & LRADC_CTRL1_MX28_LRADC_IRQ_MASK)) return IRQ_NONE; /* @@ -604,7 +609,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) complete(&lradc->completion); - writel(reg & LRADC_CTRL1_LRADC_IRQ_MASK, + writel(reg & LRADC_CTRL1_MX28_LRADC_IRQ_MASK, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); return IRQ_HANDLED; @@ -719,7 +724,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) if (ret < 0) goto err_buf; - writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK, + writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); @@ -760,7 +765,7 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR); writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); - writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK, + writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); kfree(lradc->buffer); @@ -864,11 +869,11 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc) writel(0, lradc->base + LRADC_DELAY(3)); /* Configure the touchscreen type */ - writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE, + writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) { - writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE, + writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); } @@ -882,7 +887,7 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) { int i; - writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK, + writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) From f0b83cc84678dadfd62e9cb6ed504dd126bfdc31 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: [PATCH 37/51] Staging/iio/adc/touchscreen/MXS: simplify register access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the individual register access by a few shared access function to make the code easier to read and in order to add the i.MX23 SoC in the next step. Signed-off-by: Juergen Beisert Tested-by: Marek Vasut Acked-by: Marek Vasut Tested-by: Lothar Waßmann Signed-off-by: Jonathan Cameron CC: linux-arm-kernel@lists.infradead.org CC: linux-input@vger.kernel.org CC: devel@driverdev.osuosl.org CC: Marek Vasut CC: Fabio Estevam --- drivers/staging/iio/adc/mxs-lradc.c | 202 ++++++++++++++++------------ 1 file changed, 119 insertions(+), 83 deletions(-) diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 1b99d27d4384..866b8f11d9fe 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -238,6 +238,56 @@ struct mxs_lradc { #define LRADC_RESOLUTION 12 #define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1) +static void mxs_lradc_reg_set(struct mxs_lradc *lradc, u32 val, u32 reg) +{ + writel(val, lradc->base + reg + STMP_OFFSET_REG_SET); +} + +static void mxs_lradc_reg_clear(struct mxs_lradc *lradc, u32 val, u32 reg) +{ + writel(val, lradc->base + reg + STMP_OFFSET_REG_CLR); +} + +static void mxs_lradc_reg_wrt(struct mxs_lradc *lradc, u32 val, u32 reg) +{ + writel(val, lradc->base + reg); +} + +static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc) +{ + return LRADC_CTRL0_MX28_PLATE_MASK; +} + +static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc) +{ + return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK; +} + +static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) +{ + return LRADC_CTRL1_MX28_LRADC_IRQ_MASK; +} + +static u32 mxs_lradc_touch_detect_bit(struct mxs_lradc *lradc) +{ + return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE; +} + +static u32 mxs_lradc_drive_x_plate(struct mxs_lradc *lradc) +{ + return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW; +} + +static u32 mxs_lradc_drive_y_plate(struct mxs_lradc *lradc) +{ + return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW; +} + +static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc) +{ + return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW; +} + /* * Raw I/O operations */ @@ -272,21 +322,19 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, * Virtual channel 0 is always used here as the others are always not * used if doing raw sampling. */ - writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, + LRADC_CTRL1); + mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); /* Clean the slot's previous content, then set new one. */ - writel(LRADC_CTRL4_LRADCSELECT_MASK(0), - lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR); - writel(chan->channel, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET); + mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(0), LRADC_CTRL4); + mxs_lradc_reg_set(lradc, chan->channel, LRADC_CTRL4); - writel(0, lradc->base + LRADC_CH(0)); + mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(0)); /* Enable the IRQ and start sampling the channel. */ - writel(LRADC_CTRL1_LRADC_IRQ_EN(0), - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); - writel(1 << 0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1); + mxs_lradc_reg_set(lradc, 1 << 0, LRADC_CTRL0); /* Wait for completion on the channel, 1 second max. */ ret = wait_for_completion_killable_timeout(&lradc->completion, HZ); @@ -300,8 +348,7 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, ret = IIO_VAL_INT; err: - writel(LRADC_CTRL1_LRADC_IRQ_EN(0), - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1); mutex_unlock(&lradc->lock); @@ -327,10 +374,9 @@ static int mxs_lradc_ts_touched(struct mxs_lradc *lradc) uint32_t reg; /* Enable touch detection. */ - writel(LRADC_CTRL0_MX28_PLATE_MASK, - lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); - writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE, - lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); + mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc), + LRADC_CTRL0); msleep(LRADC_TS_SAMPLE_DELAY_MS); @@ -375,32 +421,33 @@ static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc, */ switch (plate) { case LRADC_SAMPLE_X: - ctrl0 = LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW; + ctrl0 = mxs_lradc_drive_x_plate(lradc); chan = 3; break; case LRADC_SAMPLE_Y: - ctrl0 = LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW; + ctrl0 = mxs_lradc_drive_y_plate(lradc); chan = 4; break; case LRADC_SAMPLE_PRESSURE: - ctrl0 = LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW; + ctrl0 = mxs_lradc_drive_pressure(lradc); chan = 5; break; } if (change) { - writel(LRADC_CTRL0_MX28_PLATE_MASK, - lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); - writel(ctrl0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), + LRADC_CTRL0); + mxs_lradc_reg_set(lradc, ctrl0, LRADC_CTRL0); - writel(LRADC_CTRL4_LRADCSELECT_MASK(slot), - lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR); - writel(chan << LRADC_CTRL4_LRADCSELECT_OFFSET(slot), - lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET); + mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(slot), + LRADC_CTRL4); + mxs_lradc_reg_set(lradc, + chan << LRADC_CTRL4_LRADCSELECT_OFFSET(slot), + LRADC_CTRL4); } - writel(0xffffffff, lradc->base + LRADC_CH(slot) + STMP_OFFSET_REG_CLR); - writel(1 << slot, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + mxs_lradc_reg_clear(lradc, 0xffffffff, LRADC_CH(slot)); + mxs_lradc_reg_set(lradc, 1 << slot, LRADC_CTRL0); delay = jiffies + msecs_to_jiffies(LRADC_TS_SAMPLE_DELAY_MS); do { @@ -410,8 +457,7 @@ static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc, break; } while (time_before(jiff, delay)); - writel(LRADC_CTRL1_LRADC_IRQ(slot), - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(slot), LRADC_CTRL1); if (time_after_eq(jiff, delay)) return -ETIMEDOUT; @@ -450,8 +496,8 @@ static void mxs_lradc_ts_work(struct work_struct *ts_work) while (mxs_lradc_ts_touched(lradc)) { /* Disable touch detector so we can sample the touchscreen. */ - writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE, - lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, mxs_lradc_touch_detect_bit(lradc), + LRADC_CTRL0); if (likely(valid)) { input_report_abs(lradc->ts_input, ABS_X, val_x); @@ -485,10 +531,8 @@ static void mxs_lradc_ts_work(struct work_struct *ts_work) return; /* Restart the touchscreen interrupts. */ - writel(LRADC_CTRL1_TOUCH_DETECT_IRQ, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); } static int mxs_lradc_ts_open(struct input_dev *dev) @@ -499,12 +543,11 @@ static int mxs_lradc_ts_open(struct input_dev *dev) lradc->stop_touchscreen = false; /* Enable the touch-detect circuitry. */ - writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE, - lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc), + LRADC_CTRL0); /* Enable the touch-detect IRQ. */ - writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); return 0; } @@ -521,12 +564,11 @@ static void mxs_lradc_ts_close(struct input_dev *dev) cancel_work_sync(&lradc->ts_work); /* Disable touchscreen touch-detect IRQ. */ - writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, + LRADC_CTRL1); /* Power-down touchscreen touch-detect circuitry. */ - writel(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE, - lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, mxs_lradc_touch_detect_bit(lradc), LRADC_CTRL0); } static int mxs_lradc_ts_register(struct mxs_lradc *lradc) @@ -589,7 +631,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | LRADC_CTRL1_TOUCH_DETECT_IRQ; - if (!(reg & LRADC_CTRL1_MX28_LRADC_IRQ_MASK)) + if (!(reg & mxs_lradc_irq_mask(lradc))) return IRQ_NONE; /* @@ -598,8 +640,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) * it ASAP */ if (reg & LRADC_CTRL1_TOUCH_DETECT_IRQ) { - writel(ts_irq_mask, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, ts_irq_mask, LRADC_CTRL1); if (!lradc->stop_touchscreen) schedule_work(&lradc->ts_work); } @@ -609,8 +650,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) complete(&lradc->completion); - writel(reg & LRADC_CTRL1_MX28_LRADC_IRQ_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1); return IRQ_HANDLED; } @@ -629,7 +669,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) for_each_set_bit(i, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); - writel(chan_value, lradc->base + LRADC_CH(j)); + mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(j)); lradc->buffer[j] &= LRADC_CH_VALUE_MASK; lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP; j++; @@ -648,7 +688,7 @@ static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state) struct mxs_lradc *lradc = iio_priv(iio); const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR; - writel(LRADC_DELAY_KICK, lradc->base + LRADC_DELAY(0) + st); + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_KICK, LRADC_DELAY(0) + st); return 0; } @@ -724,29 +764,26 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) if (ret < 0) goto err_buf; - writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, + LRADC_CTRL1); + mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs); ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs); - writel(chan_value, lradc->base + LRADC_CH(ofs)); + mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(ofs)); bitmap_set(&enable, ofs, 1); ofs++; } - writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK, - lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR); - - writel(ctrl4_clr, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR); - writel(ctrl4_set, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET); - - writel(ctrl1_irq, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); - - writel(enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET, - lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_SET); + mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | + LRADC_DELAY_KICK, LRADC_DELAY(0)); + mxs_lradc_reg_clear(lradc, ctrl4_clr, LRADC_CTRL4); + mxs_lradc_reg_set(lradc, ctrl4_set, LRADC_CTRL4); + mxs_lradc_reg_set(lradc, ctrl1_irq, LRADC_CTRL1); + mxs_lradc_reg_set(lradc, enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET, + LRADC_DELAY(0)); return 0; @@ -761,12 +798,12 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) { struct mxs_lradc *lradc = iio_priv(iio); - writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK, - lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | + LRADC_DELAY_KICK, LRADC_DELAY(0)); - writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); - writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, + LRADC_CTRL1); kfree(lradc->buffer); mutex_unlock(&lradc->lock); @@ -861,24 +898,24 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc) return ret; /* Configure DELAY CHANNEL 0 for generic ADC sampling. */ - writel(adc_cfg, lradc->base + LRADC_DELAY(0)); + mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0)); /* Disable remaining DELAY CHANNELs */ - writel(0, lradc->base + LRADC_DELAY(1)); - writel(0, lradc->base + LRADC_DELAY(2)); - writel(0, lradc->base + LRADC_DELAY(3)); + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(1)); + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); /* Configure the touchscreen type */ - writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, - lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + LRADC_CTRL0); - if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) { - writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, - lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) + mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + LRADC_CTRL0); } /* Start internal temperature sensing. */ - writel(0, lradc->base + LRADC_CTRL2); + mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2); return 0; } @@ -887,11 +924,10 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) { int i; - writel(LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, - lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1); for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) - writel(0, lradc->base + LRADC_DELAY(i)); + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i)); } static const struct of_device_id mxs_lradc_dt_ids[] = { From 8c06f71444abde423710550de3435949240110ba Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: [PATCH 38/51] Staging/iio/adc/touchscreen/MXS: add i.MX23 support to the LRADC touchscreen driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Distinguish i.MX23 and i.MX28 at runtime and do the same for both SoC at least for the 4 wire touchscreen. Signed-off-by: Juergen Beisert Tested-by: Marek Vasut Acked-by: Marek Vasut Teseted-by: Lothar Waßmann Signed-off-by: Jonathan Cameron CC: linux-arm-kernel@lists.infradead.org CC: linux-input@vger.kernel.org CC: devel@driverdev.osuosl.org CC: Marek Vasut CC: Fabio Estevam --- drivers/staging/iio/adc/mxs-lradc.c | 66 ++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 866b8f11d9fe..6d0cdfa0edc1 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -191,20 +191,33 @@ struct mxs_lradc { # define LRADC_CTRL0_MX28_XNPSW /* XM */ (1 << 17) # define LRADC_CTRL0_MX28_XPPSW /* XP */ (1 << 16) +# define LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE (1 << 20) +# define LRADC_CTRL0_MX23_YM (1 << 19) +# define LRADC_CTRL0_MX23_XM (1 << 18) +# define LRADC_CTRL0_MX23_YP (1 << 17) +# define LRADC_CTRL0_MX23_XP (1 << 16) + # define LRADC_CTRL0_MX28_PLATE_MASK \ (LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \ LRADC_CTRL0_MX28_YNNSW | LRADC_CTRL0_MX28_YPNSW | \ LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW | \ LRADC_CTRL0_MX28_XNPSW | LRADC_CTRL0_MX28_XPPSW) +# define LRADC_CTRL0_MX23_PLATE_MASK \ + (LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE | \ + LRADC_CTRL0_MX23_YM | LRADC_CTRL0_MX23_XM | \ + LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XP) + #define LRADC_CTRL1 0x10 #define LRADC_CTRL1_TOUCH_DETECT_IRQ_EN (1 << 24) #define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16)) #define LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK (0x1fff << 16) +#define LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK (0x01ff << 16) #define LRADC_CTRL1_LRADC_IRQ_EN_OFFSET 16 #define LRADC_CTRL1_TOUCH_DETECT_IRQ (1 << 8) #define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n)) #define LRADC_CTRL1_MX28_LRADC_IRQ_MASK 0x1fff +#define LRADC_CTRL1_MX23_LRADC_IRQ_MASK 0x01ff #define LRADC_CTRL1_LRADC_IRQ_OFFSET 0 #define LRADC_CTRL2 0x20 @@ -255,37 +268,58 @@ static void mxs_lradc_reg_wrt(struct mxs_lradc *lradc, u32 val, u32 reg) static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc) { - return LRADC_CTRL0_MX28_PLATE_MASK; + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_PLATE_MASK; + else + return LRADC_CTRL0_MX28_PLATE_MASK; } static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc) { - return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK; + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK; + else + return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK; } static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) { - return LRADC_CTRL1_MX28_LRADC_IRQ_MASK; + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL1_MX23_LRADC_IRQ_MASK; + else + return LRADC_CTRL1_MX28_LRADC_IRQ_MASK; } static u32 mxs_lradc_touch_detect_bit(struct mxs_lradc *lradc) { - return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE; + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE; + else + return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE; } static u32 mxs_lradc_drive_x_plate(struct mxs_lradc *lradc) { - return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW; + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_XP | LRADC_CTRL0_MX23_XM; + else + return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW; } static u32 mxs_lradc_drive_y_plate(struct mxs_lradc *lradc) { - return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW; + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_YM; + else + return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW; } static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc) { - return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW; + if (lradc->soc == IMX23_LRADC) + return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XM; + else + return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW; } /* @@ -322,7 +356,8 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, * Virtual channel 0 is always used here as the others are always not * used if doing raw sampling. */ - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, + if (lradc->soc == IMX28_LRADC) + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, LRADC_CTRL1); mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); @@ -764,7 +799,8 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) if (ret < 0) goto err_buf; - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, + if (lradc->soc == IMX28_LRADC) + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, LRADC_CTRL1); mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); @@ -802,7 +838,8 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) LRADC_DELAY_KICK, LRADC_DELAY(0)); mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, + if (lradc->soc == IMX28_LRADC) + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, LRADC_CTRL1); kfree(lradc->buffer); @@ -906,7 +943,8 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc) mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); /* Configure the touchscreen type */ - mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + if (lradc->soc == IMX28_LRADC) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, LRADC_CTRL0); if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) @@ -995,6 +1033,12 @@ static int mxs_lradc_probe(struct platform_device *pdev) dev_warn(dev, "Unsupported number of touchscreen wires (%d)\n", ts_wires); + if ((lradc->soc == IMX23_LRADC) && (ts_wires == 5)) { + dev_warn(dev, "No support for 5 wire touches on i.MX23\n"); + dev_warn(dev, "Falling back to 4 wire\n"); + ts_wires = 4; + } + /* Grab all IRQ sources */ for (i = 0; i < of_cfg->irq_count; i++) { lradc->irq[i] = platform_get_irq(pdev, i); From dee05308f6029caed91e1a015cafb1545958ba27 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: [PATCH 39/51] Staging/iio/adc/touchscreen/MXS: add interrupt driven touch detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For battery driven systems it is a very bad idea to collect the touchscreen data within a kernel busy loop. This change uses the features of the hardware to delay and accumulate samples in hardware to avoid a high interrupt and CPU load. Signed-off-by: Juergen Beisert Tested-by: Marek Vasut Acked-by: Marek Vasut Tested-by: Lothar Waßmann Signed-off-by: Jonathan Cameron CC: linux-arm-kernel@lists.infradead.org CC: linux-input@vger.kernel.org CC: devel@driverdev.osuosl.org CC: Marek Vasut CC: Fabio Estevam CC: Dmitry Torokhov CC: linux-input@vger.kernel.org --- drivers/staging/iio/adc/mxs-lradc.c | 530 +++++++++++++++++++++++++--- 1 file changed, 476 insertions(+), 54 deletions(-) diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 6d0cdfa0edc1..9e4b6eabf1aa 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -130,6 +130,17 @@ enum mxs_lradc_ts { MXS_LRADC_TOUCHSCREEN_5WIRE, }; +/* + * Touchscreen handling + */ +enum lradc_ts_plate { + LRADC_TOUCH = 0, + LRADC_SAMPLE_X, + LRADC_SAMPLE_Y, + LRADC_SAMPLE_PRESSURE, + LRADC_SAMPLE_VALID, +}; + struct mxs_lradc { struct device *dev; void __iomem *base; @@ -172,13 +183,25 @@ struct mxs_lradc { #define CHAN_MASK_TOUCHSCREEN_4WIRE (0xf << 2) #define CHAN_MASK_TOUCHSCREEN_5WIRE (0x1f << 2) enum mxs_lradc_ts use_touchscreen; - bool stop_touchscreen; bool use_touchbutton; struct input_dev *ts_input; struct work_struct ts_work; enum mxs_lradc_id soc; + enum lradc_ts_plate cur_plate; /* statemachine */ + bool ts_valid; + unsigned ts_x_pos; + unsigned ts_y_pos; + unsigned ts_pressure; + + /* handle touchscreen's physical behaviour */ + /* samples per coordinate */ + unsigned over_sample_cnt; + /* time clocks between samples */ + unsigned over_sample_delay; + /* time in clocks to wait after the plates where switched */ + unsigned settling_delay; }; #define LRADC_CTRL0 0x00 @@ -230,19 +253,33 @@ struct mxs_lradc { #define LRADC_CH_ACCUMULATE (1 << 29) #define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24) #define LRADC_CH_NUM_SAMPLES_OFFSET 24 +#define LRADC_CH_NUM_SAMPLES(x) \ + ((x) << LRADC_CH_NUM_SAMPLES_OFFSET) #define LRADC_CH_VALUE_MASK 0x3ffff #define LRADC_CH_VALUE_OFFSET 0 #define LRADC_DELAY(n) (0xd0 + (0x10 * (n))) #define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xff << 24) #define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24 +#define LRADC_DELAY_TRIGGER(x) \ + (((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \ + LRADC_DELAY_TRIGGER_LRADCS_MASK) #define LRADC_DELAY_KICK (1 << 20) #define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16) #define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16 +#define LRADC_DELAY_TRIGGER_DELAYS(x) \ + (((x) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) & \ + LRADC_DELAY_TRIGGER_DELAYS_MASK) #define LRADC_DELAY_LOOP_COUNT_MASK (0x1f << 11) #define LRADC_DELAY_LOOP_COUNT_OFFSET 11 +#define LRADC_DELAY_LOOP(x) \ + (((x) << LRADC_DELAY_LOOP_COUNT_OFFSET) & \ + LRADC_DELAY_LOOP_COUNT_MASK) #define LRADC_DELAY_DELAY_MASK 0x7ff #define LRADC_DELAY_DELAY_OFFSET 0 +#define LRADC_DELAY_DELAY(x) \ + (((x) << LRADC_DELAY_DELAY_OFFSET) & \ + LRADC_DELAY_DELAY_MASK) #define LRADC_CTRL4 0x140 #define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) @@ -322,6 +359,404 @@ static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc) return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW; } +static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc) +{ + return !!(readl(lradc->base + LRADC_STATUS) & + LRADC_STATUS_TOUCH_DETECT_RAW); +} + +static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) +{ + /* + * prepare for oversampling conversion + * + * from the datasheet: + * "The ACCUMULATE bit in the appropriate channel register + * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0; + * otherwise, the IRQs will not fire." + */ + mxs_lradc_reg_wrt(lradc, LRADC_CH_ACCUMULATE | + LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1), + LRADC_CH(ch)); + + /* from the datasheet: + * "Software must clear this register in preparation for a + * multi-cycle accumulation. + */ + mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch)); + + /* prepare the delay/loop unit according to the oversampling count */ + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) | + LRADC_DELAY_TRIGGER_DELAYS(0) | + LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | + LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | + LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); + + /* wake us again, when the complete conversion is done */ + mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the + * SoC's delay unit and start the conversion later + * and automatically. + */ + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */ + LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */ + LRADC_DELAY_KICK | + LRADC_DELAY_DELAY(lradc->settling_delay), + LRADC_DELAY(2)); +} + +/* + * Pressure detection is special: + * We want to do both required measurements for the pressure detection in + * one turn. Use the hardware features to chain both conversions and let the + * hardware report one interrupt if both conversions are done + */ +static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1, + unsigned ch2) +{ + u32 reg; + + /* + * prepare for oversampling conversion + * + * from the datasheet: + * "The ACCUMULATE bit in the appropriate channel register + * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0; + * otherwise, the IRQs will not fire." + */ + reg = LRADC_CH_ACCUMULATE | + LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1); + mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch1)); + mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch2)); + + /* from the datasheet: + * "Software must clear this register in preparation for a + * multi-cycle accumulation. + */ + mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch1)); + mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch2)); + + /* prepare the delay/loop unit according to the oversampling count */ + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch1) | + LRADC_DELAY_TRIGGER(1 << ch2) | /* start both channels */ + LRADC_DELAY_TRIGGER_DELAYS(0) | + LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | + LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | + LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); + + /* wake us again, when the conversions are done */ + mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the + * SoC's delay unit and start the conversion later + * and automatically. + */ + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */ + LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */ + LRADC_DELAY_KICK | + LRADC_DELAY_DELAY(lradc->settling_delay), LRADC_DELAY(2)); +} + +static unsigned mxs_lradc_read_raw_channel(struct mxs_lradc *lradc, + unsigned channel) +{ + u32 reg; + unsigned num_samples, val; + + reg = readl(lradc->base + LRADC_CH(channel)); + if (reg & LRADC_CH_ACCUMULATE) + num_samples = lradc->over_sample_cnt; + else + num_samples = 1; + + val = (reg & LRADC_CH_VALUE_MASK) >> LRADC_CH_VALUE_OFFSET; + return val / num_samples; +} + +static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc, + unsigned ch1, unsigned ch2) +{ + u32 reg, mask; + unsigned pressure, m1, m2; + + mask = LRADC_CTRL1_LRADC_IRQ(ch1) | LRADC_CTRL1_LRADC_IRQ(ch2); + reg = readl(lradc->base + LRADC_CTRL1) & mask; + + while (reg != mask) { + reg = readl(lradc->base + LRADC_CTRL1) & mask; + dev_dbg(lradc->dev, "One channel is still busy: %X\n", reg); + } + + m1 = mxs_lradc_read_raw_channel(lradc, ch1); + m2 = mxs_lradc_read_raw_channel(lradc, ch2); + + if (m2 == 0) { + dev_warn(lradc->dev, "Cannot calculate pressure\n"); + return 1 << (LRADC_RESOLUTION - 1); + } + + /* simply scale the value from 0 ... max ADC resolution */ + pressure = m1; + pressure *= (1 << LRADC_RESOLUTION); + pressure /= m2; + + dev_dbg(lradc->dev, "Pressure = %u\n", pressure); + return pressure; +} + +#define TS_CH_XP 2 +#define TS_CH_YP 3 +#define TS_CH_XM 4 +#define TS_CH_YM 5 + +static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc) +{ + u32 reg; + int val; + + reg = readl(lradc->base + LRADC_CTRL1); + + /* only channels 3 to 5 are of interest here */ + if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) | + LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1); + val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP); + } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) | + LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1); + val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM); + } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) | + LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1); + val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM); + } else { + return -EIO; + } + + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); + + return val; +} + +/* + * YP(open)--+-------------+ + * | |--+ + * | | | + * YM(-)--+-------------+ | + * +--------------+ + * | | + * XP(weak+) XM(open) + * + * "weak+" means 200k Ohm VDDIO + * (-) means GND + */ +static void mxs_lradc_setup_touch_detection(struct mxs_lradc *lradc) +{ + /* + * In order to detect a touch event the 'touch detect enable' bit + * enables: + * - a weak pullup to the X+ connector + * - a strong ground at the Y- connector + */ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); + mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc), + LRADC_CTRL0); +} + +/* + * YP(meas)--+-------------+ + * | |--+ + * | | | + * YM(open)--+-------------+ | + * +--------------+ + * | | + * XP(+) XM(-) + * + * (+) means here 1.85 V + * (-) means here GND + */ +static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc) +{ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); + mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_X; + mxs_lradc_setup_ts_channel(lradc, TS_CH_YP); +} + +/* + * YP(+)--+-------------+ + * | |--+ + * | | | + * YM(-)--+-------------+ | + * +--------------+ + * | | + * XP(open) XM(meas) + * + * (+) means here 1.85 V + * (-) means here GND + */ +static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc) +{ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); + mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_Y; + mxs_lradc_setup_ts_channel(lradc, TS_CH_XM); +} + +/* + * YP(+)--+-------------+ + * | |--+ + * | | | + * YM(meas)--+-------------+ | + * +--------------+ + * | | + * XP(meas) XM(-) + * + * (+) means here 1.85 V + * (-) means here GND + */ +static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) +{ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); + mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_PRESSURE; + mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); +} + +static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) +{ + mxs_lradc_setup_touch_detection(lradc); + + lradc->cur_plate = LRADC_TOUCH; + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ | + LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); +} + +static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc) +{ + input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos); + input_report_abs(lradc->ts_input, ABS_Y, lradc->ts_y_pos); + input_report_abs(lradc->ts_input, ABS_PRESSURE, lradc->ts_pressure); + input_report_key(lradc->ts_input, BTN_TOUCH, 1); + input_sync(lradc->ts_input); +} + +static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc) +{ + mxs_lradc_setup_touch_detection(lradc); + lradc->cur_plate = LRADC_SAMPLE_VALID; + /* + * start a dummy conversion to burn time to settle the signals + * note: we are not interested in the conversion's value + */ + mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5)); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1); + mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) | + LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */ + LRADC_DELAY(2)); +} + +/* + * in order to avoid false measurements, report only samples where + * the surface is still touched after the position measurement + */ +static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid) +{ + /* if it is still touched, report the sample */ + if (valid && mxs_lradc_check_touch_event(lradc)) { + lradc->ts_valid = true; + mxs_lradc_report_ts_event(lradc); + } + + /* if it is even still touched, continue with the next measurement */ + if (mxs_lradc_check_touch_event(lradc)) { + mxs_lradc_prepare_y_pos(lradc); + return; + } + + if (lradc->ts_valid) { + /* signal the release */ + lradc->ts_valid = false; + input_report_key(lradc->ts_input, BTN_TOUCH, 0); + input_sync(lradc->ts_input); + } + + /* if it is released, wait for the next touch via IRQ */ + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); +} + +/* touchscreen's state machine */ +static void mxs_lradc_handle_touch(struct mxs_lradc *lradc) +{ + int val; + + switch (lradc->cur_plate) { + case LRADC_TOUCH: + /* + * start with the Y-pos, because it uses nearly the same plate + * settings like the touch detection + */ + if (mxs_lradc_check_touch_event(lradc)) { + mxs_lradc_reg_clear(lradc, + LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, + LRADC_CTRL1); + mxs_lradc_prepare_y_pos(lradc); + } + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, + LRADC_CTRL1); + return; + + case LRADC_SAMPLE_Y: + val = mxs_lradc_read_ts_channel(lradc); + if (val < 0) { + mxs_lradc_enable_touch_detection(lradc); /* re-start */ + return; + } + lradc->ts_y_pos = val; + mxs_lradc_prepare_x_pos(lradc); + return; + + case LRADC_SAMPLE_X: + val = mxs_lradc_read_ts_channel(lradc); + if (val < 0) { + mxs_lradc_enable_touch_detection(lradc); /* re-start */ + return; + } + lradc->ts_x_pos = val; + mxs_lradc_prepare_pressure(lradc); + return; + + case LRADC_SAMPLE_PRESSURE: + lradc->ts_pressure = + mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); + mxs_lradc_complete_touch_event(lradc); + return; + + case LRADC_SAMPLE_VALID: + val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */ + mxs_lradc_finish_touch_event(lradc, 1); + break; + } +} + /* * Raw I/O operations */ @@ -395,15 +830,6 @@ static const struct iio_info mxs_lradc_iio_info = { .read_raw = mxs_lradc_read_raw, }; -/* - * Touchscreen handling - */ -enum lradc_ts_plate { - LRADC_SAMPLE_X, - LRADC_SAMPLE_Y, - LRADC_SAMPLE_PRESSURE, -}; - static int mxs_lradc_ts_touched(struct mxs_lradc *lradc) { uint32_t reg; @@ -561,10 +987,6 @@ static void mxs_lradc_ts_work(struct work_struct *ts_work) input_report_key(lradc->ts_input, BTN_TOUCH, 0); input_sync(lradc->ts_input); - /* Do not restart the TS IRQ if the driver is shutting down. */ - if (lradc->stop_touchscreen) - return; - /* Restart the touchscreen interrupts. */ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); @@ -574,36 +996,29 @@ static int mxs_lradc_ts_open(struct input_dev *dev) { struct mxs_lradc *lradc = input_get_drvdata(dev); - /* The touchscreen is starting. */ - lradc->stop_touchscreen = false; - /* Enable the touch-detect circuitry. */ - mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc), - LRADC_CTRL0); - - /* Enable the touch-detect IRQ. */ - mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); + mxs_lradc_enable_touch_detection(lradc); return 0; } +static void mxs_lradc_disable_ts(struct mxs_lradc *lradc) +{ + /* stop all interrupts from firing */ + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | + LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) | + LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5), + LRADC_CTRL1); + + /* Power-down touchscreen touch-detect circuitry. */ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); +} + static void mxs_lradc_ts_close(struct input_dev *dev) { struct mxs_lradc *lradc = input_get_drvdata(dev); - /* Indicate the touchscreen is stopping. */ - lradc->stop_touchscreen = true; - mb(); - - /* Wait until touchscreen thread finishes any possible remnants. */ - cancel_work_sync(&lradc->ts_work); - - /* Disable touchscreen touch-detect IRQ. */ - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, - LRADC_CTRL1); - - /* Power-down touchscreen touch-detect circuitry. */ - mxs_lradc_reg_clear(lradc, mxs_lradc_touch_detect_bit(lradc), LRADC_CTRL0); + mxs_lradc_disable_ts(lradc); } static int mxs_lradc_ts_register(struct mxs_lradc *lradc) @@ -649,8 +1064,7 @@ static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc) if (!lradc->use_touchscreen) return; - cancel_work_sync(&lradc->ts_work); - + mxs_lradc_disable_ts(lradc); input_unregister_device(lradc->ts_input); } @@ -663,22 +1077,17 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) struct mxs_lradc *lradc = iio_priv(iio); unsigned long reg = readl(lradc->base + LRADC_CTRL1); const uint32_t ts_irq_mask = - LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | - LRADC_CTRL1_TOUCH_DETECT_IRQ; + LRADC_CTRL1_TOUCH_DETECT_IRQ | + LRADC_CTRL1_LRADC_IRQ(2) | + LRADC_CTRL1_LRADC_IRQ(3) | + LRADC_CTRL1_LRADC_IRQ(4) | + LRADC_CTRL1_LRADC_IRQ(5); if (!(reg & mxs_lradc_irq_mask(lradc))) return IRQ_NONE; - /* - * Touchscreen IRQ handling code has priority and therefore - * is placed here. In case touchscreen IRQ arrives, disable - * it ASAP - */ - if (reg & LRADC_CTRL1_TOUCH_DETECT_IRQ) { - mxs_lradc_reg_clear(lradc, ts_irq_mask, LRADC_CTRL1); - if (!lradc->stop_touchscreen) - schedule_work(&lradc->ts_work); - } + if (lradc->use_touchscreen && (reg & ts_irq_mask)) + mxs_lradc_handle_touch(lradc); if (iio_buffer_enabled(iio)) iio_trigger_poll(iio->trig, iio_get_time_ns()); @@ -975,6 +1384,17 @@ static const struct of_device_id mxs_lradc_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids); +static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc, + struct device_node *lradc_node) +{ + /* TODO retrieve from device tree */ + lradc->over_sample_cnt = 4; + lradc->over_sample_delay = 2; + lradc->settling_delay = 10; + + return 0; +} + static int mxs_lradc_probe(struct platform_device *pdev) { const struct of_device_id *of_id = @@ -987,7 +1407,7 @@ static int mxs_lradc_probe(struct platform_device *pdev) struct iio_dev *iio; struct resource *iores; uint32_t ts_wires = 0; - int ret = 0; + int ret = 0, touch_ret; int i; /* Allocate the IIO device. */ @@ -1018,7 +1438,7 @@ static int mxs_lradc_probe(struct platform_device *pdev) return ret; } - INIT_WORK(&lradc->ts_work, mxs_lradc_ts_work); + touch_ret = mxs_lradc_probe_touchscreen(lradc, node); /* Check if touchscreen is enabled in DT. */ ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires", @@ -1081,9 +1501,11 @@ static int mxs_lradc_probe(struct platform_device *pdev) goto err_dev; /* Register the touchscreen input device. */ - ret = mxs_lradc_ts_register(lradc); - if (ret) - goto err_ts_register; + if (touch_ret == 0) { + ret = mxs_lradc_ts_register(lradc); + if (ret) + goto err_ts_register; + } /* Register IIO device. */ ret = iio_device_register(iio); From cd6c5586524e10512b910b3ff44465f0aaf5cd1b Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: [PATCH 40/51] Staging/iio/adc/touchscreen/MXS: remove old touchscreen detection implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Juergen Beisert Tested-by: Marek Vasut Acked-by: Marek Vasut Tested-by: Lothar Waßmann Signed-off-by: Jonathan Cameron CC: linux-arm-kernel@lists.infradead.org CC: linux-input@vger.kernel.org CC: devel@driverdev.osuosl.org CC: Marek Vasut CC: Fabio Estevam --- drivers/staging/iio/adc/mxs-lradc.c | 163 ---------------------------- 1 file changed, 163 deletions(-) diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 9e4b6eabf1aa..18510d1ea5c8 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -186,7 +186,6 @@ struct mxs_lradc { bool use_touchbutton; struct input_dev *ts_input; - struct work_struct ts_work; enum mxs_lradc_id soc; enum lradc_ts_plate cur_plate; /* statemachine */ @@ -830,168 +829,6 @@ static const struct iio_info mxs_lradc_iio_info = { .read_raw = mxs_lradc_read_raw, }; -static int mxs_lradc_ts_touched(struct mxs_lradc *lradc) -{ - uint32_t reg; - - /* Enable touch detection. */ - mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); - mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc), - LRADC_CTRL0); - - msleep(LRADC_TS_SAMPLE_DELAY_MS); - - reg = readl(lradc->base + LRADC_STATUS); - - return reg & LRADC_STATUS_TOUCH_DETECT_RAW; -} - -static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc, - enum lradc_ts_plate plate, int change) -{ - unsigned long delay, jiff; - uint32_t reg, ctrl0 = 0, chan = 0; - /* The touchscreen always uses CTRL4 slot #7. */ - const uint8_t slot = 7; - uint32_t val; - - /* - * There are three correct configurations of the controller sampling - * the touchscreen, each of these configuration provides different - * information from the touchscreen. - * - * The following table describes the sampling configurations: - * +-------------+-------+-------+-------+ - * | Wire \ Axis | X | Y | Z | - * +---------------------+-------+-------+ - * | X+ (CH2) | HI | TS | TS | - * +-------------+-------+-------+-------+ - * | X- (CH4) | LO | SH | HI | - * +-------------+-------+-------+-------+ - * | Y+ (CH3) | SH | HI | HI | - * +-------------+-------+-------+-------+ - * | Y- (CH5) | TS | LO | SH | - * +-------------+-------+-------+-------+ - * - * HI ... strong '1' ; LO ... strong '0' - * SH ... sample here ; TS ... tri-state - * - * There are a few other ways of obtaining the Z coordinate - * (aka. pressure), but the one in the table seems to be the - * most reliable one. - */ - switch (plate) { - case LRADC_SAMPLE_X: - ctrl0 = mxs_lradc_drive_x_plate(lradc); - chan = 3; - break; - case LRADC_SAMPLE_Y: - ctrl0 = mxs_lradc_drive_y_plate(lradc); - chan = 4; - break; - case LRADC_SAMPLE_PRESSURE: - ctrl0 = mxs_lradc_drive_pressure(lradc); - chan = 5; - break; - } - - if (change) { - mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), - LRADC_CTRL0); - mxs_lradc_reg_set(lradc, ctrl0, LRADC_CTRL0); - - mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(slot), - LRADC_CTRL4); - mxs_lradc_reg_set(lradc, - chan << LRADC_CTRL4_LRADCSELECT_OFFSET(slot), - LRADC_CTRL4); - } - - mxs_lradc_reg_clear(lradc, 0xffffffff, LRADC_CH(slot)); - mxs_lradc_reg_set(lradc, 1 << slot, LRADC_CTRL0); - - delay = jiffies + msecs_to_jiffies(LRADC_TS_SAMPLE_DELAY_MS); - do { - jiff = jiffies; - reg = readl_relaxed(lradc->base + LRADC_CTRL1); - if (reg & LRADC_CTRL1_LRADC_IRQ(slot)) - break; - } while (time_before(jiff, delay)); - - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(slot), LRADC_CTRL1); - - if (time_after_eq(jiff, delay)) - return -ETIMEDOUT; - - val = readl(lradc->base + LRADC_CH(slot)); - val &= LRADC_CH_VALUE_MASK; - - return val; -} - -static int32_t mxs_lradc_ts_sample_filter(struct mxs_lradc *lradc, - enum lradc_ts_plate plate) -{ - int32_t val, tot = 0; - int i; - - val = mxs_lradc_ts_sample(lradc, plate, 1); - - /* Delay a bit so the touchscreen is stable. */ - mdelay(2); - - for (i = 0; i < LRADC_TS_SAMPLE_AMOUNT; i++) { - val = mxs_lradc_ts_sample(lradc, plate, 0); - tot += val; - } - - return tot / LRADC_TS_SAMPLE_AMOUNT; -} - -static void mxs_lradc_ts_work(struct work_struct *ts_work) -{ - struct mxs_lradc *lradc = container_of(ts_work, - struct mxs_lradc, ts_work); - int val_x, val_y, val_p; - bool valid = false; - - while (mxs_lradc_ts_touched(lradc)) { - /* Disable touch detector so we can sample the touchscreen. */ - mxs_lradc_reg_clear(lradc, mxs_lradc_touch_detect_bit(lradc), - LRADC_CTRL0); - - if (likely(valid)) { - input_report_abs(lradc->ts_input, ABS_X, val_x); - input_report_abs(lradc->ts_input, ABS_Y, val_y); - input_report_abs(lradc->ts_input, ABS_PRESSURE, val_p); - input_report_key(lradc->ts_input, BTN_TOUCH, 1); - input_sync(lradc->ts_input); - } - - valid = false; - - val_x = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_X); - if (val_x < 0) - continue; - val_y = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_Y); - if (val_y < 0) - continue; - val_p = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_PRESSURE); - if (val_p < 0) - continue; - - valid = true; - } - - input_report_abs(lradc->ts_input, ABS_PRESSURE, 0); - input_report_key(lradc->ts_input, BTN_TOUCH, 0); - input_sync(lradc->ts_input); - - /* Restart the touchscreen interrupts. */ - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); - mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); -} - static int mxs_lradc_ts_open(struct input_dev *dev) { struct mxs_lradc *lradc = input_get_drvdata(dev); From e9c88fb5cf05ae198323a3c992b41885397a0b48 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: [PATCH 41/51] Staging/iio/adc/touchscreen/MXS: provide devicetree adaption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an RFC for the new touchscreen properties. Signed-off-by: Juergen Beisert Tested-by: Marek Vasut Acked-by: Marek Vasut Tested-by: Lothar Waßmann Signed-off-by: Jonathan Cameron CC: linux-arm-kernel@lists.infradead.org CC: linux-input@vger.kernel.org CC: devel@driverdev.osuosl.org CC: Marek Vasut CC: Fabio Estevam CC: devicetree@vger.kernel.org --- .../bindings/staging/iio/adc/mxs-lradc.txt | 36 ++++++++++-- arch/arm/boot/dts/imx28-evk.dts | 4 ++ drivers/staging/iio/adc/mxs-lradc.c | 57 ++++++++++++------- 3 files changed, 71 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt index 46882058b59b..ee05dc390694 100644 --- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt +++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt @@ -1,7 +1,8 @@ * Freescale i.MX28 LRADC device driver Required properties: -- compatible: Should be "fsl,imx28-lradc" +- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc" + for i.MX28 SoC - reg: Address and length of the register set for the device - interrupts: Should contain the LRADC interrupts @@ -9,13 +10,38 @@ Optional properties: - fsl,lradc-touchscreen-wires: Number of wires used to connect the touchscreen to LRADC. Valid value is either 4 or 5. If this property is not present, then the touchscreen is - disabled. + disabled. 5 wires is valid for i.MX28 SoC only. +- fsl,ave-ctrl: number of samples per direction to calculate an average value. + Allowed value is 1 ... 31, default is 4 +- fsl,ave-delay: delay between consecutive samples. Allowed value is + 1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at + 2 kHz and its default is 2 (= 1 ms) +- fsl,settling: delay between plate switch to next sample. Allowed value is + 1 ... 2047. It counts at 2 kHz and its default is + 10 (= 5 ms) -Examples: +Example for i.MX23 SoC: + + lradc@80050000 { + compatible = "fsl,imx23-lradc"; + reg = <0x80050000 0x2000>; + interrupts = <36 37 38 39 40 41 42 43 44>; + status = "okay"; + fsl,lradc-touchscreen-wires = <4>; + fsl,ave-ctrl = <4>; + fsl,ave-delay = <2>; + fsl,settling = <10>; + }; + +Example for i.MX28 SoC: lradc@80050000 { compatible = "fsl,imx28-lradc"; reg = <0x80050000 0x2000>; - interrupts = <10 14 15 16 17 18 19 - 20 21 22 23 24 25>; + interrupts = <10 14 15 16 17 18 19 20 21 22 23 24 25>; + status = "okay"; + fsl,lradc-touchscreen-wires = <5>; + fsl,ave-ctrl = <4>; + fsl,ave-delay = <2>; + fsl,settling = <10>; }; diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts index 15715d921d14..aa33393903a8 100644 --- a/arch/arm/boot/dts/imx28-evk.dts +++ b/arch/arm/boot/dts/imx28-evk.dts @@ -183,6 +183,10 @@ lradc@80050000 { status = "okay"; + fsl,lradc-touchscreen-wires = <4>; + fsl,ave-ctrl = <4>; + fsl,ave-delay = <2>; + fsl,settling = <10>; }; i2c0: i2c@80058000 { diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 18510d1ea5c8..dfd1bc1cc56f 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -1224,10 +1224,45 @@ MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids); static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc, struct device_node *lradc_node) { - /* TODO retrieve from device tree */ + int ret; + u32 ts_wires = 0, adapt; + + ret = of_property_read_u32(lradc_node, "fsl,lradc-touchscreen-wires", + &ts_wires); + if (ret) + return -ENODEV; /* touchscreen feature disabled */ + + switch (ts_wires) { + case 4: + lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE; + break; + case 5: + if (lradc->soc == IMX28_LRADC) { + lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE; + break; + } + /* fall through an error message for i.MX23 */ + default: + dev_err(lradc->dev, + "Unsupported number of touchscreen wires (%d)\n", + ts_wires); + return -EINVAL; + } + lradc->over_sample_cnt = 4; + ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt); + if (ret == 0) + lradc->over_sample_cnt = adapt; + lradc->over_sample_delay = 2; + ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt); + if (ret == 0) + lradc->over_sample_delay = adapt; + lradc->settling_delay = 10; + ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt); + if (ret == 0) + lradc->settling_delay = adapt; return 0; } @@ -1243,7 +1278,6 @@ static int mxs_lradc_probe(struct platform_device *pdev) struct mxs_lradc *lradc; struct iio_dev *iio; struct resource *iores; - uint32_t ts_wires = 0; int ret = 0, touch_ret; int i; @@ -1277,25 +1311,6 @@ static int mxs_lradc_probe(struct platform_device *pdev) touch_ret = mxs_lradc_probe_touchscreen(lradc, node); - /* Check if touchscreen is enabled in DT. */ - ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires", - &ts_wires); - if (ret) - dev_info(dev, "Touchscreen not enabled.\n"); - else if (ts_wires == 4) - lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE; - else if (ts_wires == 5) - lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE; - else - dev_warn(dev, "Unsupported number of touchscreen wires (%d)\n", - ts_wires); - - if ((lradc->soc == IMX23_LRADC) && (ts_wires == 5)) { - dev_warn(dev, "No support for 5 wire touches on i.MX23\n"); - dev_warn(dev, "Falling back to 4 wire\n"); - ts_wires = 4; - } - /* Grab all IRQ sources */ for (i = 0; i < of_cfg->irq_count; i++) { lradc->irq[i] = platform_get_irq(pdev, i); From 0a440ee9b6a916322613de0c23080fb6d0fd6e26 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 23 Sep 2013 15:36:00 +0100 Subject: [PATCH 42/51] Staging/iio: add TODO reminder Some things have still to be done to the LRADC driver. Signed-off-by: Juergen Beisert Acked-by: Acked-by: Marek Vasut Signed-off-by: Jonathan Cameron CC: linux-arm-kernel@lists.infradead.org CC: linux-input@vger.kernel.org CC: devel@driverdev.osuosl.org CC: Marek Vasut CC: Fabio Estevam CC: Jonathan Cameron --- drivers/staging/iio/TODO | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/staging/iio/TODO b/drivers/staging/iio/TODO index 04c23262f8e2..c22a0edd1528 100644 --- a/drivers/staging/iio/TODO +++ b/drivers/staging/iio/TODO @@ -13,6 +13,17 @@ Would be nice 3) Expand device set. Lots of other maxim adc's have very similar interfaces. +MXS LRADC driver: +This is a classic MFD device as it combines the following subdevices + - touchscreen controller (input subsystem related device) + - general purpose ADC channels + - battery voltage monitor (power subsystem related device) + - die temperature monitor (thermal management) + +At least the battery voltage and die temperature feature is required in-kernel +by a driver of the SoC's battery charging unit to avoid any damage to the +silicon and the battery. + TSL2561 Would be nice 1) Open question of userspace vs kernel space balance when From 476b9547e872c709c07a45bd47301ce7236f3dc1 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Tue, 1 Oct 2013 17:22:00 +0100 Subject: [PATCH 43/51] HID RTC: Open sensor hub open close Open sensor hub when module is loaded and close when module is removed. This helps saving power by opening HID transport only when there is an user. Signed-off-by: Srinivas Pandruvada Acked-by: Alessandro Zummo Signed-off-by: Jonathan Cameron --- drivers/rtc/rtc-hid-sensor-time.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c index 4e2a81854f51..45560ffb038d 100644 --- a/drivers/rtc/rtc-hid-sensor-time.c +++ b/drivers/rtc/rtc-hid-sensor-time.c @@ -275,6 +275,12 @@ static int hid_time_probe(struct platform_device *pdev) return ret; } + ret = sensor_hub_device_open(hsdev); + if (ret) { + dev_err(&pdev->dev, "failed to open sensor hub device!\n"); + goto err_open; + } + time_state->rtc = devm_rtc_device_register(&pdev->dev, "hid-sensor-time", &hid_time_rtc_ops, THIS_MODULE); @@ -282,17 +288,24 @@ static int hid_time_probe(struct platform_device *pdev) if (IS_ERR_OR_NULL(time_state->rtc)) { ret = time_state->rtc ? PTR_ERR(time_state->rtc) : -ENODEV; time_state->rtc = NULL; - sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME); dev_err(&pdev->dev, "rtc device register failed!\n"); + goto err_rtc; } return ret; + +err_rtc: + sensor_hub_device_close(hsdev); +err_open: + sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME); + return ret; } static int hid_time_remove(struct platform_device *pdev) { struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; + sensor_hub_device_close(hsdev); sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME); return 0; From 66a1891642cf71877ddb89945882281f5ef28672 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Oct 2013 08:45:00 +0100 Subject: [PATCH 44/51] iio:ad5449: Use spi_sync_transfer() Use the spi_sync_transfer() helper function instead of open-coding it. Makes the code a bit shorter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5449.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c index fff7d0762c0c..82e208f6cde2 100644 --- a/drivers/iio/dac/ad5449.c +++ b/drivers/iio/dac/ad5449.c @@ -101,7 +101,6 @@ static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr, { struct ad5449 *st = iio_priv(indio_dev); int ret; - struct spi_message msg; struct spi_transfer t[] = { { .tx_buf = &st->data[0], @@ -114,15 +113,11 @@ static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr, }, }; - spi_message_init(&msg); - spi_message_add_tail(&t[0], &msg); - spi_message_add_tail(&t[1], &msg); - mutex_lock(&indio_dev->mlock); st->data[0] = cpu_to_be16(addr << 12); st->data[1] = cpu_to_be16(AD5449_CMD_NOOP); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); if (ret < 0) goto out_unlock; From af3d5cad0a6699afcae84b578838e698f56028bb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Oct 2013 08:45:00 +0100 Subject: [PATCH 45/51] iio:adis16080: Use spi_sync_transfer() Use the spi_sync_transfer() helper function instead of open-coding it. Makes the code a bit shorter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adis16080.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c index e9ec022ae225..add509837269 100644 --- a/drivers/iio/gyro/adis16080.c +++ b/drivers/iio/gyro/adis16080.c @@ -51,7 +51,6 @@ static int adis16080_read_sample(struct iio_dev *indio_dev, u16 addr, int *val) { struct adis16080_state *st = iio_priv(indio_dev); - struct spi_message m; int ret; struct spi_transfer t[] = { { @@ -66,11 +65,7 @@ static int adis16080_read_sample(struct iio_dev *indio_dev, st->buf = cpu_to_be16(addr | ADIS16080_DIN_WRITE); - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - ret = spi_sync(st->us, &m); + ret = spi_sync_transfer(st->us, t, ARRAY_SIZE(t)); if (ret == 0) *val = sign_extend32(be16_to_cpu(st->buf), 11); From 35734fbdb54bbb5c0c3f47fd7ff78c61380c7eaa Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Oct 2013 08:45:00 +0100 Subject: [PATCH 46/51] iio:adxrs450: Use spi_sync_transfer() Use the spi_sync_transfer() helper function instead of open-coding it. Makes the code a bit shorter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adxrs450.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c index c1f40efbf639..1e546ba7ba45 100644 --- a/drivers/iio/gyro/adxrs450.c +++ b/drivers/iio/gyro/adxrs450.c @@ -90,7 +90,6 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, u8 reg_address, u16 *val) { - struct spi_message msg; struct adxrs450_state *st = iio_priv(indio_dev); u32 tx; int ret; @@ -114,10 +113,7 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, tx |= ADXRS450_P; st->tx = cpu_to_be32(tx); - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", reg_address); @@ -169,7 +165,6 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, **/ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) { - struct spi_message msg; struct adxrs450_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -188,10 +183,7 @@ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) mutex_lock(&st->buf_lock); st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA); - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "Problem while reading sensor data\n"); goto error_ret; From f28607f3bf07a0fce3a34e76554947d2b1eab13d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Oct 2013 08:45:00 +0100 Subject: [PATCH 47/51] iio:adis16130: Use spi_sync_transfer() Use the spi_sync_transfer() helper function instead of open-coding it. Makes the code a bit shorter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adis16130.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/iio/gyro/adis16130.c b/drivers/iio/gyro/adis16130.c index 9155cf6cf287..445c2aecfadd 100644 --- a/drivers/iio/gyro/adis16130.c +++ b/drivers/iio/gyro/adis16130.c @@ -47,7 +47,6 @@ static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val) { int ret; struct adis16130_state *st = iio_priv(indio_dev); - struct spi_message msg; struct spi_transfer xfer = { .tx_buf = st->buf, .rx_buf = st->buf, @@ -59,10 +58,7 @@ static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val) st->buf[0] = ADIS16130_CON_RD | reg_addr; st->buf[1] = st->buf[2] = st->buf[3] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->us, &msg); - + ret = spi_sync_transfer(st->us, &xfer, 1); if (ret == 0) *val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3]; mutex_unlock(&st->buf_lock); From 63e4f052226dd9079409c22b55f38b1e50c5fb95 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Oct 2013 08:45:00 +0100 Subject: [PATCH 48/51] staging:iio:adis16220: Use spi_sync_transfer() Use the spi_sync_transfer() helper function instead of open-coding it. Makes the code a bit shorter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16220_core.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 5c289614357c..4c9364b63c77 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -102,7 +102,6 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, int addr) { struct adis16220_state *st = iio_priv(indio_dev); - struct spi_message msg; struct spi_transfer xfers[] = { { .tx_buf = st->tx, @@ -147,10 +146,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, } xfers[1].len = count; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->adis.spi, &msg); + ret = spi_sync_transfer(st->adis.spi, xfers, ARRAY_SIZE(xfers)); if (ret) { mutex_unlock(&st->buf_lock); From 9aa698a0b316aa15f18f0cc99d7ba371bbba97d2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Oct 2013 08:45:00 +0100 Subject: [PATCH 49/51] staging:iio:ad9852: Use spi_sync_transfer() Use the spi_sync_transfer() helper function instead of open-coding it. Makes the code a bit shorter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/frequency/ad9852.c | 45 +++++++------------------- 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/drivers/staging/iio/frequency/ad9852.c b/drivers/staging/iio/frequency/ad9852.c index 4be2cf8c2ab6..11e4367375d2 100644 --- a/drivers/staging/iio/frequency/ad9852.c +++ b/drivers/staging/iio/frequency/ad9852.c @@ -67,7 +67,6 @@ static ssize_t ad9852_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad9852_config *config = (struct ad9852_config *)buf; @@ -78,99 +77,77 @@ static ssize_t ad9852_set_parameter(struct device *dev, xfer.tx_buf = &config->phajst0[0]; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->phajst1[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 6; xfer.tx_buf = &config->fretun1[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 6; xfer.tx_buf = &config->fretun2[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 6; xfer.tx_buf = &config->dltafre[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->updtclk[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 4; xfer.tx_buf = &config->ramprat[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->control[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->outpskm[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 2; xfer.tx_buf = &config->outpskr[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->daccntl[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: From 630e7377b7d26e0ab530482be594aff88cbb060c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Oct 2013 08:45:00 +0100 Subject: [PATCH 50/51] staging:iio:ad9910: Use spi_sync_transfer() Use the spi_sync_transfer() helper function instead of open-coding it. Makes the code a bit shorter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/frequency/ad9910.c | 82 +++++++------------------- 1 file changed, 20 insertions(+), 62 deletions(-) diff --git a/drivers/staging/iio/frequency/ad9910.c b/drivers/staging/iio/frequency/ad9910.c index a7d528ef620c..755e0482681a 100644 --- a/drivers/staging/iio/frequency/ad9910.c +++ b/drivers/staging/iio/frequency/ad9910.c @@ -119,7 +119,6 @@ static ssize_t ad9910_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad9910_config *config = (struct ad9910_config *)buf; @@ -130,152 +129,118 @@ static ssize_t ad9910_set_parameter(struct device *dev, xfer.tx_buf = &config->auxdac[0]; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->ioupd[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->ftw[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->pow[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->asf[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->multc[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->dig_rampl[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->dig_ramps[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->dig_rampr[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep0[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep1[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep2[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep3[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep4[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep5[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep6[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 9; xfer.tx_buf = &config->sin_tonep7[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: @@ -288,7 +253,6 @@ static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0); static void ad9910_init(struct ad9910_state *st) { - struct spi_message msg; struct spi_transfer xfer; int ret; u8 cfr[5]; @@ -304,9 +268,7 @@ static void ad9910_init(struct ad9910_state *st) xfer.len = 5; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; @@ -319,9 +281,7 @@ static void ad9910_init(struct ad9910_state *st) xfer.len = 5; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; @@ -334,9 +294,7 @@ static void ad9910_init(struct ad9910_state *st) xfer.len = 5; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; From 3658a71b10c8471ac217983ddf2a2bdde71008af Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Oct 2013 08:45:00 +0100 Subject: [PATCH 51/51] staging:iio:ad9951: Use spi_sync_transfer() Use the spi_sync_transfer() helper function instead of open-coding it. Makes the code a bit shorter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/frequency/ad9951.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/staging/iio/frequency/ad9951.c b/drivers/staging/iio/frequency/ad9951.c index 0094c2f392ad..5e8990a0210b 100644 --- a/drivers/staging/iio/frequency/ad9951.c +++ b/drivers/staging/iio/frequency/ad9951.c @@ -60,7 +60,6 @@ static ssize_t ad9951_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad9951_config *config = (struct ad9951_config *)buf; @@ -71,36 +70,28 @@ static ssize_t ad9951_set_parameter(struct device *dev, xfer.tx_buf = &config->asf[0]; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 2; xfer.tx_buf = &config->arr[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 5; xfer.tx_buf = &config->ftw0[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; xfer.len = 3; xfer.tx_buf = &config->ftw1[0]; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: @@ -113,7 +104,6 @@ static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9951_set_parameter, 0); static void ad9951_init(struct ad9951_state *st) { - struct spi_message msg; struct spi_transfer xfer; int ret; u8 cfr[5]; @@ -129,9 +119,7 @@ static void ad9951_init(struct ad9951_state *st) xfer.len = 5; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; @@ -143,9 +131,7 @@ static void ad9951_init(struct ad9951_state *st) xfer.len = 4; xfer.tx_buf = 𝔠 - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret;