From 73327b4c80713da3a854fb04ef7e9739fe006709 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 28 Sep 2012 10:57:00 +0100 Subject: [PATCH 01/15] drivers/staging/iio: Remove unnecessary semicolon A simplified version of the semantic patch that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r1@ statement S; position p,p1; @@ S@p1;@p @script:python r2@ p << r1.p; p1 << r1.p1; @@ if p[0].line != p1[0].line_end: cocci.include_match(False) @@ position r1.p; @@ -;@p // Signed-off-by: Peter Senna Tschudin Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201_core.c | 4 ++-- drivers/staging/iio/accel/adis16204_core.c | 2 +- drivers/staging/iio/accel/adis16209_core.c | 4 ++-- drivers/staging/iio/accel/kxsd9.c | 2 +- drivers/staging/iio/adc/mxs-lradc.c | 2 +- drivers/staging/iio/cdc/ad7150.c | 12 ++++++------ drivers/staging/iio/cdc/ad7152.c | 2 +- drivers/staging/iio/cdc/ad7746.c | 2 +- drivers/staging/iio/gyro/adis16260_core.c | 4 ++-- drivers/staging/iio/magnetometer/hmc5843.c | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 8e37d6e04277..5d2ae5dc380a 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -345,7 +345,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } mutex_lock(&indio_dev->mlock); addr = adis16201_addresses[chan->address][1]; ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16); @@ -382,7 +382,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } val16 = val & ((1 << bits) - 1); addr = adis16201_addresses[chan->address][1]; return adis16201_spi_write_reg_16(indio_dev, addr, val16); diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 05bdb7c2c8e3..c6bf6419743e 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -389,7 +389,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } val16 = val & ((1 << bits) - 1); addr = adis16204_addresses[chan->address][1]; return adis16204_spi_write_reg_16(indio_dev, addr, val16); diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index b7333bfe0b2f..4f70efd4ed99 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -295,7 +295,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } val16 = val & ((1 << bits) - 1); addr = adis16209_addresses[chan->address][1]; return adis16209_spi_write_reg_16(indio_dev, addr, val16); @@ -373,7 +373,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } mutex_lock(&indio_dev->mlock); addr = adis16209_addresses[chan->address][1]; ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16); diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c index fdd5fbded660..e8e6e3fbcec0 100644 --- a/drivers/staging/iio/accel/kxsd9.c +++ b/drivers/staging/iio/accel/kxsd9.c @@ -171,7 +171,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK]; ret = IIO_VAL_INT_PLUS_MICRO; break; - }; + } error_ret: return ret; diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index ca7c1fa88e71..df5bba284b73 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -351,7 +351,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) writel(chan_value, lradc->base + LRADC_CH(ofs)); enable |= 1 << ofs; ofs++; - }; + } writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK, lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR); diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index 6a4041417d4e..c72a6c074b46 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -156,7 +156,7 @@ static int ad7150_read_event_config(struct iio_dev *indio_dev, u64 event_code) return !adaptive && (threshtype == 0x1); else return !adaptive && (threshtype == 0x0); - }; + } return -EINVAL; } @@ -194,7 +194,7 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code) break; default: return -EINVAL; - }; + } ret = i2c_smbus_write_byte_data(chip->client, ad7150_addresses[chan][4], sens); @@ -257,7 +257,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev, default: ret = -EINVAL; goto error_ret; - }; + } cfg |= (!adaptive << 7) | (thresh_type << 5); @@ -327,7 +327,7 @@ static int ad7150_write_event_value(struct iio_dev *indio_dev, default: ret = -EINVAL; goto error_ret; - }; + } /* write back if active */ ret = ad7150_write_event_params(indio_dev, event_code); @@ -360,7 +360,7 @@ static ssize_t ad7150_show_timeout(struct device *dev, break; default: return -EINVAL; - }; + } return sprintf(buf, "%d\n", value); } @@ -394,7 +394,7 @@ static ssize_t ad7150_store_timeout(struct device *dev, default: ret = -EINVAL; goto error_ret; - }; + } ret = ad7150_write_event_params(indio_dev, this_attr->address); error_ret: diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index 98c3015116aa..288b33e8dadd 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -405,7 +405,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, break; default: ret = -EINVAL; - }; + } out: mutex_unlock(&indio_dev->mlock); return ret; diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 754e11e87193..e6c11d934ada 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -677,7 +677,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, break; default: ret = -EINVAL; - }; + } out: mutex_unlock(&indio_dev->mlock); return ret; diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 9571c03aa4cc..ff16430a0d2e 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -528,7 +528,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } mutex_lock(&indio_dev->mlock); addr = adis16260_addresses[chan->address][1]; ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); @@ -548,7 +548,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, break; default: return -EINVAL; - }; + } mutex_lock(&indio_dev->mlock); addr = adis16260_addresses[chan->address][2]; ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 10e095486e54..f7edf69a3bc4 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -555,7 +555,7 @@ 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; - }; + } return -EINVAL; } From e1562ef30438d4850e3f4ea0fc5711ea658a1f69 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sat, 13 Oct 2012 09:06:00 +0100 Subject: [PATCH 02/15] iio: remove useless irq_enabled variable in at91 irq_enabled is only set, but never read Signed-off-by: Peter Meerwald Acked-by: Maxime Ripard Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 3ed94bf80596..b3ba8af4f261 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -46,7 +46,6 @@ struct at91_adc_state { struct clk *clk; bool done; int irq; - bool irq_enabled; u16 last_value; struct mutex lock; u8 num_channels; @@ -85,7 +84,6 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) buffer->access->store_to(buffer, (u8 *)st->buffer); iio_trigger_notify_done(idev->trig); - st->irq_enabled = true; /* Needed to ACK the DRDY interruption */ at91_adc_readl(st, AT91_ADC_LCDR); @@ -106,7 +104,6 @@ static irqreturn_t at91_adc_eoc_trigger(int irq, void *private) if (iio_buffer_enabled(idev)) { disable_irq_nosync(irq); - st->irq_enabled = false; iio_trigger_poll(idev->trig, iio_get_time_ns()); } else { st->last_value = at91_adc_readl(st, AT91_ADC_LCDR); From 1217c48f51704d01019581cb1baa1b9124eaa0a7 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sat, 13 Oct 2012 09:06:00 +0100 Subject: [PATCH 03/15] iio: use iio_push_to_buffer() in at91 driver Signed-off-by: Peter Meerwald Acked-by: Maxime Ripard Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index b3ba8af4f261..2e2c9a80aa37 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -81,7 +81,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) *timestamp = pf->timestamp; } - buffer->access->store_to(buffer, (u8 *)st->buffer); + iio_push_to_buffer(buffer, st->buffer); iio_trigger_notify_done(idev->trig); From ace43fcefb1f7078cc19ab07df9d877eefffa57f Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sat, 13 Oct 2012 09:06:00 +0100 Subject: [PATCH 04/15] iio: fix spelling of Accelerometer in Kconfig Signed-off-by: Peter Meerwald Acked-by: Srinivas pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index b2510c4d9a5a..fe4bcd7c5b12 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -8,7 +8,7 @@ config HID_SENSOR_ACCEL_3D select IIO_BUFFER select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON - tristate "HID Acelerometers 3D" + tristate "HID Accelerometers 3D" help Say yes here to build support for the HID SENSOR accelerometers 3D. From 231a7c5f5f9c95803dc84b1b311204ef55f7d8f6 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sat, 13 Oct 2012 09:06:00 +0100 Subject: [PATCH 05/15] staging iio: use iio_trigger_generic_data_rdy_poll() in accel/adis16209,adis16240 driver Signed-off-by: Peter Meerwald Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16209_trigger.c | 11 +---------- drivers/staging/iio/accel/adis16240_trigger.c | 11 +---------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c index 2ad93dcaf40d..112280346eb6 100644 --- a/drivers/staging/iio/accel/adis16209_trigger.c +++ b/drivers/staging/iio/accel/adis16209_trigger.c @@ -7,15 +7,6 @@ #include #include "adis16209.h" -/** - * adis16209_data_rdy_trig_poll() the event handler for the data rdy trig - **/ -static irqreturn_t adis16209_data_rdy_trig_poll(int irq, void *trig) -{ - iio_trigger_poll(trig, iio_get_time_ns()); - return IRQ_HANDLED; -} - /** * adis16209_data_rdy_trigger_set_state() set datardy interrupt state **/ @@ -45,7 +36,7 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev) } ret = request_irq(st->us->irq, - adis16209_data_rdy_trig_poll, + iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, "adis16209", st->trig); diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c index fa90a22b143e..f3caf09dcb89 100644 --- a/drivers/staging/iio/accel/adis16240_trigger.c +++ b/drivers/staging/iio/accel/adis16240_trigger.c @@ -7,15 +7,6 @@ #include #include "adis16240.h" -/** - * adis16240_data_rdy_trig_poll() the event handler for the data rdy trig - **/ -static irqreturn_t adis16240_data_rdy_trig_poll(int irq, void *trig) -{ - iio_trigger_poll(trig, iio_get_time_ns()); - return IRQ_HANDLED; -} - /** * adis16240_data_rdy_trigger_set_state() set datardy interrupt state **/ @@ -45,7 +36,7 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev) } ret = request_irq(st->us->irq, - adis16240_data_rdy_trig_poll, + iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, "adis16240", st->trig); From 48edf8eb53daf98b1fc4498ac54b27c08b955248 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 4 Oct 2012 14:33:00 +0100 Subject: [PATCH 06/15] staging:iio: Remove unused DRIVER_NAME defines Some drivers define a DRIVER_NAME, but never use the define. This patch removes defines. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16203_core.c | 2 -- drivers/staging/iio/accel/adis16204_core.c | 2 -- drivers/staging/iio/accel/adis16209_core.c | 2 -- drivers/staging/iio/accel/adis16220_core.c | 2 -- drivers/staging/iio/accel/adis16240_core.c | 2 -- drivers/staging/iio/gyro/adis16260_core.c | 2 -- drivers/staging/iio/meter/ade7753.h | 2 -- drivers/staging/iio/meter/ade7754.h | 2 -- drivers/staging/iio/meter/ade7758.h | 3 --- drivers/staging/iio/meter/ade7759.h | 2 -- drivers/staging/iio/meter/ade7854.h | 2 -- 11 files changed, 23 deletions(-) diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 002fa9dfc375..2064710a6b86 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -21,8 +21,6 @@ #include "adis16203.h" -#define DRIVER_NAME "adis16203" - /** * adis16203_spi_write_reg_8() - write single byte to a register * @indio_dev: iio device associated with child of actual device diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index c6bf6419743e..d0828d97f501 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -24,8 +24,6 @@ #include "adis16204.h" -#define DRIVER_NAME "adis16204" - /** * adis16204_spi_write_reg_8() - write single byte to a register * @dev: device associated with child of actual device (iio_dev or iio_trig) diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index 4f70efd4ed99..420256e2e61d 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -22,8 +22,6 @@ #include "adis16209.h" -#define DRIVER_NAME "adis16209" - /** * adis16209_spi_write_reg_8() - write single byte to a register * @indio_dev: iio device associated with actual device diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index c755089c7117..adf70b7d0320 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -20,8 +20,6 @@ #include "adis16220.h" -#define DRIVER_NAME "adis16220" - /** * adis16220_spi_write_reg_8() - write single byte to a register * @indio_dev: iio device associated with child of actual device diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 0fc26a49d681..9f486114ed51 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -25,8 +25,6 @@ #include "adis16240.h" -#define DRIVER_NAME "adis16240" - static int adis16240_check_status(struct iio_dev *indio_dev); /** diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index ff16430a0d2e..2753333a02b6 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -24,8 +24,6 @@ #include "adis16260.h" -#define DRIVER_NAME "adis16260" - static int adis16260_check_status(struct iio_dev *indio_dev); /** diff --git a/drivers/staging/iio/meter/ade7753.h b/drivers/staging/iio/meter/ade7753.h index 3f059d3d9392..a9d93cc1c414 100644 --- a/drivers/staging/iio/meter/ade7753.h +++ b/drivers/staging/iio/meter/ade7753.h @@ -55,8 +55,6 @@ #define ADE7753_SPI_BURST (u32)(1000 * 1000) #define ADE7753_SPI_FAST (u32)(2000 * 1000) -#define DRIVER_NAME "ade7753" - /** * struct ade7753_state - device instance specific data * @us: actual spi_device diff --git a/drivers/staging/iio/meter/ade7754.h b/drivers/staging/iio/meter/ade7754.h index 6121125520f6..e42ffc387a14 100644 --- a/drivers/staging/iio/meter/ade7754.h +++ b/drivers/staging/iio/meter/ade7754.h @@ -73,8 +73,6 @@ #define ADE7754_SPI_BURST (u32)(1000 * 1000) #define ADE7754_SPI_FAST (u32)(2000 * 1000) -#define DRIVER_NAME "ade7754" - /** * struct ade7754_state - device instance specific data * @us: actual spi_device diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index 1e11ad5ae5a4..07318203a836 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -105,9 +105,6 @@ #define AD7758_APP_PWR 4 #define AD7758_WT(p, w) (((w) << 2) | (p)) -#define DRIVER_NAME "ade7758" - - /** * struct ade7758_state - device instance specific data * @us: actual spi_device diff --git a/drivers/staging/iio/meter/ade7759.h b/drivers/staging/iio/meter/ade7759.h index c81d23d730d2..f9ff1f8e7372 100644 --- a/drivers/staging/iio/meter/ade7759.h +++ b/drivers/staging/iio/meter/ade7759.h @@ -36,8 +36,6 @@ #define ADE7759_SPI_BURST (u32)(1000 * 1000) #define ADE7759_SPI_FAST (u32)(2000 * 1000) -#define DRIVER_NAME "ade7759" - /** * struct ade7759_state - device instance specific data * @us: actual spi_device diff --git a/drivers/staging/iio/meter/ade7854.h b/drivers/staging/iio/meter/ade7854.h index 2c96e8695d57..06534577f6c3 100644 --- a/drivers/staging/iio/meter/ade7854.h +++ b/drivers/staging/iio/meter/ade7854.h @@ -142,8 +142,6 @@ #define ADE7854_SPI_BURST (u32)(1000 * 1000) #define ADE7854_SPI_FAST (u32)(2000 * 1000) -#define DRIVER_NAME "ade7854" - /** * struct ade7854_state - device instance specific data * @spi: actual spi_device From 65cb587d7058441c8c910e8766ee86538c7274d8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 28 Sep 2012 22:36:00 +0100 Subject: [PATCH 07/15] staging/iio/lis3l02dq: fix building without irq_to_gpio The driver has not been building for some time after the irq_to_gpio function has been removed from the kernel. The only board in the upstream kernel that provides this device is the "Stargate 2", which is also maintained by Jonathan Cameron. Rather than working around the problem by adding new platform data for this driver, this patch uses the of_gpio framework to get to the gpio number. However, the stargate2 code does not (yet) use DT based probing, so it is still broken, but at least building allyesconfig works again. Signed-off-by: Arnd Bergmann Cc: Lars-Peter Clausen Cc: Jonathan Cameron Cc: Greg Kroah-Hartman Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/lis3l02dq.h | 1 + drivers/staging/iio/accel/lis3l02dq_core.c | 10 ++++++---- drivers/staging/iio/accel/lis3l02dq_ring.c | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h index f9bcd41f7188..2bac7221837c 100644 --- a/drivers/staging/iio/accel/lis3l02dq.h +++ b/drivers/staging/iio/accel/lis3l02dq.h @@ -158,6 +158,7 @@ struct lis3l02dq_state { struct spi_device *us; struct iio_trigger *trig; struct mutex buf_lock; + int gpio; bool trigger_on; u8 tx[LIS3L02DQ_MAX_RX] ____cacheline_aligned; diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 21b0469f8bc2..d13c7e98978d 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -690,6 +691,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); st->us = spi; + st->gpio = of_get_gpio(spi->dev.of_node, 0); mutex_init(&st->buf_lock); indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; @@ -711,7 +713,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) goto error_unreg_buffer_funcs; } - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { + if (spi->irq) { ret = request_threaded_irq(st->us->irq, &lis3l02dq_th, &lis3l02dq_event_handler, @@ -738,10 +740,10 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) return 0; error_remove_trigger: - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq))) + if (spi->irq) lis3l02dq_remove_trigger(indio_dev); error_free_interrupt: - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + if (spi->irq) free_irq(st->us->irq, indio_dev); error_uninitialize_buffer: iio_buffer_unregister(indio_dev); @@ -790,7 +792,7 @@ static int __devexit lis3l02dq_remove(struct spi_device *spi) lis3l02dq_disable_all_events(indio_dev); lis3l02dq_stop_device(indio_dev); - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + if (spi->irq) free_irq(st->us->irq, indio_dev); lis3l02dq_remove_trigger(indio_dev); diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index fa4190d96247..13c0b4bd5baa 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -263,7 +263,7 @@ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig) /* If gpio still high (or high again) * In theory possible we will need to do this several times */ for (i = 0; i < 5; i++) - if (gpio_get_value(irq_to_gpio(st->us->irq))) + if (gpio_get_value(st->gpio)) lis3l02dq_read_all(indio_dev, NULL); else break; From cdf71c7f6d6208cea8dd83c78b49a9a646e3208e Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 30 Sep 2012 11:05:00 +0100 Subject: [PATCH 08/15] staging iio: consistent commas in adis16400 channel spec probably not the most important patch in the world Signed-off-by: Peter Meerwald Cc: manuel.stahl@iis.fraunhofer.de Signed-off-by: Jonathan Cameron --- drivers/staging/iio/imu/adis16400_core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index b302c9ba2712..5eab327a09d2 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -622,7 +622,7 @@ static const struct iio_chan_spec adis16400_channels[] = { IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in_supply, .scan_index = ADIS16400_SCAN_SUPPLY, - .scan_type = IIO_ST('u', 14, 16, 0) + .scan_type = IIO_ST('u', 14, 16, 0), }, { .type = IIO_ANGL_VEL, .modified = 1, @@ -633,7 +633,7 @@ static const struct iio_chan_spec adis16400_channels[] = { IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, .address = gyro_x, .scan_index = ADIS16400_SCAN_GYRO_X, - .scan_type = IIO_ST('s', 14, 16, 0) + .scan_type = IIO_ST('s', 14, 16, 0), }, { .type = IIO_ANGL_VEL, .modified = 1, @@ -752,7 +752,7 @@ static const struct iio_chan_spec adis16350_channels[] = { IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in_supply, .scan_index = ADIS16400_SCAN_SUPPLY, - .scan_type = IIO_ST('u', 12, 16, 0) + .scan_type = IIO_ST('u', 12, 16, 0), }, { .type = IIO_ANGL_VEL, .modified = 1, @@ -763,7 +763,7 @@ static const struct iio_chan_spec adis16350_channels[] = { IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, .address = gyro_x, .scan_index = ADIS16400_SCAN_GYRO_X, - .scan_type = IIO_ST('s', 14, 16, 0) + .scan_type = IIO_ST('s', 14, 16, 0), }, { .type = IIO_ANGL_VEL, .modified = 1, @@ -877,7 +877,7 @@ static const struct iio_chan_spec adis16300_channels[] = { IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in_supply, .scan_index = ADIS16400_SCAN_SUPPLY, - .scan_type = IIO_ST('u', 12, 16, 0) + .scan_type = IIO_ST('u', 12, 16, 0), }, { .type = IIO_ANGL_VEL, .modified = 1, From 6fae58f39207d03ae78b0b03347810d0f8452ab6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 18 Oct 2012 15:43:00 +0100 Subject: [PATCH 09/15] staging:iio: Don't compare boolean values with true/false Fixes the following coccicheck warnings: drivers/staging/iio/accel/lis3l02dq_ring.c:240:5-10: WARNING: Comparison to bool drivers/staging/iio/iio_dummy_evgen.c:111:6-25: WARNING: Comparison to bool Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/lis3l02dq_ring.c | 2 +- drivers/staging/iio/iio_dummy_evgen.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 13c0b4bd5baa..246352716537 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -237,7 +237,7 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig, u8 t; __lis3l02dq_write_data_ready_config(indio_dev, state); - if (state == false) { + if (!state) { /* * A possible quirk with the handler is currently worked around * by ensuring outstanding read events are cleared. diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c index 74e24e8aa876..132d278c5010 100644 --- a/drivers/staging/iio/iio_dummy_evgen.c +++ b/drivers/staging/iio/iio_dummy_evgen.c @@ -108,7 +108,7 @@ int iio_dummy_evgen_get_irq(void) mutex_lock(&iio_evgen->lock); for (i = 0; i < IIO_EVENTGEN_NO; i++) - if (iio_evgen->inuse[i] == false) { + if (!iio_evgen->inuse[i]) { ret = iio_evgen->base + i; iio_evgen->inuse[i] = true; break; From 6c724cb0ad772ae43928467f0a44731848eb22b2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 18 Oct 2012 15:43:00 +0100 Subject: [PATCH 10/15] staging:iio:lpc32xx_adc: Use resource_size instead of opencoding it Fixes the following error from coccicheck: drivers/staging/iio/adc/lpc32xx_adc.c:153:43-46: ERROR: Missing resource_size with res Signed-off-by: Lars-Peter Clausen Acked-by: Roland Stigge Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/lpc32xx_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c index 7e9bd0001cc7..10c59622671f 100644 --- a/drivers/staging/iio/adc/lpc32xx_adc.c +++ b/drivers/staging/iio/adc/lpc32xx_adc.c @@ -150,7 +150,7 @@ static int __devinit lpc32xx_adc_probe(struct platform_device *pdev) info = iio_priv(iodev); - info->adc_base = ioremap(res->start, res->end - res->start + 1); + info->adc_base = ioremap(res->start, resource_size(res)); if (!info->adc_base) { dev_err(&pdev->dev, "failed mapping memory\n"); retval = -EBUSY; From 7737fa6d1ea3385428bd36a0dddcb33c526f7d74 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 18 Oct 2012 15:43:00 +0100 Subject: [PATCH 11/15] iio: Don't compare boolean values to true/false Fixes the following warnings from coccicheck: drivers/iio/inkern.c:81:6-14: WARNING: Comparison to bool drivers/iio/dac/ad5686.c:191:5-11: WARNING: Comparison to bool Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5686.c | 2 +- drivers/iio/inkern.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 6948d75e1036..bc92ff9309c2 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -188,7 +188,7 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, if (ret) return ret; - if (readin == true) + if (readin) st->pwr_down_mask |= (0x3 << (chan->channel * 2)); else st->pwr_down_mask &= ~(0x3 << (chan->channel * 2)); diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index f2b78d4fe457..5230a33886c0 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -78,7 +78,7 @@ int iio_map_array_unregister(struct iio_dev *indio_dev, found_it = true; break; } - if (found_it == false) { + if (!found_it) { ret = -ENODEV; goto error_ret; } From 45259859492812c8b700ae1d157be01a8d2babfe Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 18 Oct 2012 15:43:00 +0100 Subject: [PATCH 12/15] iio: at91_adc: Use devm_kcalloc to allocate arrays Use dev_kcalloc instead of devm_kzalloc to allocate arrays since it is semantically more appropriate. While we are at it the patch also fixes the following coccinelle warning: drivers/iio/adc/at91_adc.c:277:25-31: ERROR: application of sizeof to pointer Signed-off-by: Lars-Peter Clausen Acked-By: Maxime Ripard Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 2e2c9a80aa37..a9176722042f 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -123,10 +123,8 @@ static int at91_adc_channel_init(struct iio_dev *idev) idev->num_channels = bitmap_weight(&st->channels_mask, st->num_channels) + 1; - chan_array = devm_kzalloc(&idev->dev, - ((idev->num_channels + 1) * - sizeof(struct iio_chan_spec)), - GFP_KERNEL); + chan_array = devm_kcalloc(&idev->dev, idev->num_channels + 1, + sizeof(*chan_array), GFP_KERNEL); if (!chan_array) return -ENOMEM; @@ -270,9 +268,8 @@ static int at91_adc_trigger_init(struct iio_dev *idev) struct at91_adc_state *st = iio_priv(idev); int i, ret; - st->trig = devm_kzalloc(&idev->dev, - st->trigger_number * sizeof(st->trig), - GFP_KERNEL); + st->trig = devm_kcalloc(&idev->dev, st->trigger_number, + sizeof(*st->trig), GFP_KERNEL); if (st->trig == NULL) { ret = -ENOMEM; @@ -454,9 +451,8 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, st->registers->trigger_register = prop; st->trigger_number = of_get_child_count(node); - st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number * - sizeof(struct at91_adc_trigger), - GFP_KERNEL); + st->trigger_list = devm_kcalloc(&idev->dev, st->trigger_number, + sizeof(*st->trigger_list), GFP_KERNEL); if (!st->trigger_list) { dev_err(&idev->dev, "Could not allocate trigger list memory.\n"); ret = -ENOMEM; From 948ad20504894436c008c8a50f74e277edeff9a1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 18 Oct 2012 14:47:00 +0100 Subject: [PATCH 13/15] iio: Use strict_strtouint instead of kstrtoul strict_strto* has been deprecated in favor of kstrto*. Use strict_strtouint respective strict_strtoint, since that is what the functions we pass the converted values to expect. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 6 +++--- drivers/iio/industrialio-event.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index d4ad37455a67..722a83fd8d85 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -371,12 +371,12 @@ ssize_t iio_buffer_write_length(struct device *dev, const char *buf, size_t len) { - int ret; - ulong val; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; + unsigned int val; + int ret; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtouint(buf, 10, &val); if (ret) return ret; diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index fa6543bf6731..857e6306c5c3 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -239,13 +239,13 @@ static ssize_t iio_ev_value_store(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long val; + int val; int ret; if (!indio_dev->info->write_event_value) return -EINVAL; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtoint(buf, 10, &val); if (ret) return ret; From 103d9fb907058e4eb052f4f7302d1b07eb6a7792 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 16 Oct 2012 17:29:00 +0100 Subject: [PATCH 14/15] iio: Add a logarithmic fractional value type For ADCs or DACs the denominator for fractional types often is a power of two. In this case we can use a shift operation instead of the rather expensive 64 bit division. This patch adds a new fractional type which expects the denominator to be specified as the log2 of the actual denominator. E.g. for ADCs and DACs this will usually be the number of significant bits. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 5 +++++ drivers/iio/inkern.c | 3 +++ include/linux/iio/types.h | 1 + 3 files changed, 9 insertions(+) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 6eb24dbc081e..37650a72b31f 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -397,6 +397,11 @@ static ssize_t iio_read_channel_info(struct device *dev, val2 = do_div(tmp, 1000000000LL); val = tmp; return sprintf(buf, "%d.%09u\n", val, val2); + case IIO_VAL_FRACTIONAL_LOG2: + tmp = (s64)val * 1000000000LL >> val2; + val2 = do_div(tmp, 1000000000LL); + val = tmp; + return sprintf(buf, "%d.%09u\n", val, val2); default: return 0; } diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 5230a33886c0..b394621d362c 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -314,6 +314,9 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, *processed = div_s64(raw64 * (s64)scale_val * scale, scale_val2); break; + case IIO_VAL_FRACTIONAL_LOG2: + *processed = (raw64 * (s64)scale_val * scale) >> scale_val2; + break; default: return -EINVAL; } diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 5c647ecfd5ba..87b196a2d698 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -58,5 +58,6 @@ enum iio_modifier { #define IIO_VAL_INT_PLUS_NANO 3 #define IIO_VAL_INT_PLUS_MICRO_DB 4 #define IIO_VAL_FRACTIONAL 10 +#define IIO_VAL_FRACTIONAL_LOG2 11 #endif /* _IIO_TYPES_H_ */ From 8341dc04dfb33fbae71727ae648e20c51abc40e3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 16 Oct 2012 17:29:00 +0100 Subject: [PATCH 15/15] iio:dac: Add support for the ad5449 This patch adds support for the AD5415, AD5426, AD5429, AD5432, AD5439, AD5443 and AD5449 single and dual channel DACs. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/Kconfig | 10 + drivers/iio/dac/Makefile | 1 + drivers/iio/dac/ad5449.c | 375 +++++++++++++++++++++++++++ include/linux/platform_data/ad5449.h | 40 +++ 4 files changed, 426 insertions(+) create mode 100644 drivers/iio/dac/ad5449.c create mode 100644 include/linux/platform_data/ad5449.h diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index b1c0ee5294ca..f68756e6dd62 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -67,6 +67,16 @@ config AD5446 To compile this driver as a module, choose M here: the module will be called ad5446. +config AD5449 + tristate "Analog Device AD5449 and similar DACs driver" + depends on SPI_MASTER + help + Say yes here to build support for Analog Devices AD5415, AD5426, AD5429, + AD5432, AD5439, AD5443, AD5449 Digital to Analog Converters. + + To compile this driver as a module, choose M here: the + module will be called ad5449. + config AD5504 tristate "Analog Devices AD5504/AD5501 DAC SPI driver" depends on SPI diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index c0d333b23ba3..5b528ebb3343 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o obj-$(CONFIG_AD5064) += ad5064.o obj-$(CONFIG_AD5504) += ad5504.o obj-$(CONFIG_AD5446) += ad5446.o +obj-$(CONFIG_AD5449) += ad5449.o obj-$(CONFIG_AD5755) += ad5755.o obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c new file mode 100644 index 000000000000..5b43030fe6e3 --- /dev/null +++ b/drivers/iio/dac/ad5449.c @@ -0,0 +1,375 @@ +/* + * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog + * Converter driver. + * + * Copyright 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define AD5449_MAX_CHANNELS 2 +#define AD5449_MAX_VREFS 2 + +#define AD5449_CMD_NOOP 0x0 +#define AD5449_CMD_LOAD_AND_UPDATE(x) (0x1 + (x) * 3) +#define AD5449_CMD_READ(x) (0x2 + (x) * 3) +#define AD5449_CMD_LOAD(x) (0x3 + (x) * 3) +#define AD5449_CMD_CTRL 13 + +#define AD5449_CTRL_SDO_OFFSET 10 +#define AD5449_CTRL_DAISY_CHAIN BIT(9) +#define AD5449_CTRL_HCLR_TO_MIDSCALE BIT(8) +#define AD5449_CTRL_SAMPLE_RISING BIT(7) + +/** + * struct ad5449_chip_info - chip specific information + * @channels: Channel specification + * @num_channels: Number of channels + * @has_ctrl: Chip has a control register + */ +struct ad5449_chip_info { + const struct iio_chan_spec *channels; + unsigned int num_channels; + bool has_ctrl; +}; + +/** + * struct ad5449 - driver instance specific data + * @spi: the SPI device for this driver instance + * @chip_info: chip model specific constants, available modes etc + * @vref_reg: vref supply regulators + * @has_sdo: whether the SDO line is connected + * @dac_cache: Cache for the DAC values + * @data: spi transfer buffers + */ +struct ad5449 { + struct spi_device *spi; + const struct ad5449_chip_info *chip_info; + struct regulator_bulk_data vref_reg[AD5449_MAX_VREFS]; + + bool has_sdo; + uint16_t dac_cache[AD5449_MAX_CHANNELS]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + __be16 data[2] ____cacheline_aligned; +}; + +enum ad5449_type { + ID_AD5426, + ID_AD5429, + ID_AD5432, + ID_AD5439, + ID_AD5443, + ID_AD5449, +}; + +static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr, + unsigned int val) +{ + struct ad5449 *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + st->data[0] = cpu_to_be16((addr << 12) | val); + ret = spi_write(st->spi, st->data, 2); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr, + unsigned int *val) +{ + struct ad5449 *st = iio_priv(indio_dev); + int ret; + struct spi_message msg; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0], + .len = 2, + .cs_change = 1, + }, { + .tx_buf = &st->data[1], + .rx_buf = &st->data[1], + .len = 2, + }, + }; + + 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); + if (ret < 0) + return ret; + + *val = be16_to_cpu(st->data[1]); + mutex_unlock(&indio_dev->mlock); + + return 0; +} + +static int ad5449_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long info) +{ + struct ad5449 *st = iio_priv(indio_dev); + struct regulator_bulk_data *reg; + int scale_uv; + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + if (st->has_sdo) { + ret = ad5449_read(indio_dev, + AD5449_CMD_READ(chan->address), val); + if (ret) + return ret; + *val &= 0xfff; + } else { + *val = st->dac_cache[chan->address]; + } + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + reg = &st->vref_reg[chan->channel]; + scale_uv = regulator_get_voltage(reg->consumer); + if (scale_uv < 0) + return scale_uv; + + *val = scale_uv / 1000; + *val2 = chan->scan_type.realbits; + + return IIO_VAL_FRACTIONAL_LOG2; + default: + break; + } + + return -EINVAL; +} + +static int ad5449_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long info) +{ + struct ad5449 *st = iio_priv(indio_dev); + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + if (val < 0 || val >= (1 << chan->scan_type.realbits)) + return -EINVAL; + + ret = ad5449_write(indio_dev, + AD5449_CMD_LOAD_AND_UPDATE(chan->address), + val << chan->scan_type.shift); + if (ret == 0) + st->dac_cache[chan->address] = val; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static const struct iio_info ad5449_info = { + .read_raw = ad5449_read_raw, + .write_raw = ad5449_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD5449_CHANNEL(chan, bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ + .address = (chan), \ + .scan_type = IIO_ST('u', (bits), 16, 12 - (bits)), \ +} + +#define DECLARE_AD5449_CHANNELS(name, bits) \ +const struct iio_chan_spec name[] = { \ + AD5449_CHANNEL(0, bits), \ + AD5449_CHANNEL(1, bits), \ +} + +static DECLARE_AD5449_CHANNELS(ad5429_channels, 8); +static DECLARE_AD5449_CHANNELS(ad5439_channels, 10); +static DECLARE_AD5449_CHANNELS(ad5449_channels, 12); + +static const struct ad5449_chip_info ad5449_chip_info[] = { + [ID_AD5426] = { + .channels = ad5429_channels, + .num_channels = 1, + .has_ctrl = false, + }, + [ID_AD5429] = { + .channels = ad5429_channels, + .num_channels = 2, + .has_ctrl = true, + }, + [ID_AD5432] = { + .channels = ad5439_channels, + .num_channels = 1, + .has_ctrl = false, + }, + [ID_AD5439] = { + .channels = ad5439_channels, + .num_channels = 2, + .has_ctrl = true, + }, + [ID_AD5443] = { + .channels = ad5449_channels, + .num_channels = 1, + .has_ctrl = false, + }, + [ID_AD5449] = { + .channels = ad5449_channels, + .num_channels = 2, + .has_ctrl = true, + }, +}; + +static const char *ad5449_vref_name(struct ad5449 *st, int n) +{ + if (st->chip_info->num_channels == 1) + return "VREF"; + + if (n == 0) + return "VREFA"; + else + return "VREFB"; +} + +static int __devinit ad5449_spi_probe(struct spi_device *spi) +{ + struct ad5449_platform_data *pdata = spi->dev.platform_data; + const struct spi_device_id *id = spi_get_device_id(spi); + struct iio_dev *indio_dev; + struct ad5449 *st; + unsigned int i; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + st->chip_info = &ad5449_chip_info[id->driver_data]; + st->spi = spi; + + for (i = 0; i < st->chip_info->num_channels; ++i) + st->vref_reg[i].supply = ad5449_vref_name(st, i); + + ret = regulator_bulk_get(&spi->dev, st->chip_info->num_channels, + st->vref_reg); + if (ret) + goto error_free; + + ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg); + if (ret) + goto error_free_reg; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = id->name; + indio_dev->info = &ad5449_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + + if (st->chip_info->has_ctrl) { + unsigned int ctrl = 0x00; + if (pdata) { + if (pdata->hardware_clear_to_midscale) + ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE; + ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET; + st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED; + } else { + st->has_sdo = true; + } + ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl); + } + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + return 0; + +error_disable_reg: + regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); +error_free_reg: + regulator_bulk_free(st->chip_info->num_channels, st->vref_reg); +error_free: + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad5449_spi_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5449 *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); + regulator_bulk_free(st->chip_info->num_channels, st->vref_reg); + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5449_spi_ids[] = { + { "ad5415", ID_AD5449 }, + { "ad5426", ID_AD5426 }, + { "ad5429", ID_AD5429 }, + { "ad5432", ID_AD5432 }, + { "ad5439", ID_AD5439 }, + { "ad5443", ID_AD5443 }, + { "ad5449", ID_AD5449 }, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5449_spi_ids); + +static struct spi_driver ad5449_spi_driver = { + .driver = { + .name = "ad5449", + .owner = THIS_MODULE, + }, + .probe = ad5449_spi_probe, + .remove = __devexit_p(ad5449_spi_remove), + .id_table = ad5449_spi_ids, +}; +module_spi_driver(ad5449_spi_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/platform_data/ad5449.h b/include/linux/platform_data/ad5449.h new file mode 100644 index 000000000000..bd712bd4b94e --- /dev/null +++ b/include/linux/platform_data/ad5449.h @@ -0,0 +1,40 @@ +/* + * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog + * Converter driver. + * + * Copyright 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#ifndef __LINUX_PLATFORM_DATA_AD5449_H__ +#define __LINUX_PLATFORM_DATA_AD5449_H__ + +/** + * enum ad5449_sdo_mode - AD5449 SDO pin configuration + * @AD5449_SDO_DRIVE_FULL: Drive the SDO pin with full strength. + * @AD5449_SDO_DRIVE_WEAK: Drive the SDO pin with not full strength. + * @AD5449_SDO_OPEN_DRAIN: Operate the SDO pin in open-drain mode. + * @AD5449_SDO_DISABLED: Disable the SDO pin, in this mode it is not possible to + * read back from the device. + */ +enum ad5449_sdo_mode { + AD5449_SDO_DRIVE_FULL = 0x0, + AD5449_SDO_DRIVE_WEAK = 0x1, + AD5449_SDO_OPEN_DRAIN = 0x2, + AD5449_SDO_DISABLED = 0x3, +}; + +/** + * struct ad5449_platform_data - Platform data for the ad5449 DAC driver + * @sdo_mode: SDO pin mode + * @hardware_clear_to_midscale: Whether asserting the hardware CLR pin sets the + * outputs to midscale (true) or to zero scale(false). + */ +struct ad5449_platform_data { + enum ad5449_sdo_mode sdo_mode; + bool hardware_clear_to_midscale; +}; + +#endif