On 05/27/11 19:36, Jonathan Cameron wrote: > Note I haven't made any changes to the userspace interface as yet. > This is all about cleaning up what was actually there (handling > all errors etc). Oops. Forgot the header that I moved the platform data definitions into. Without that it doesn't build... That bits trivial so I'll push it out to Greg with that included. > > Signed-off-by: Jonathan Cameron <jic23@xxxxxxxxx> > --- > drivers/staging/iio/resolver/Kconfig | 27 - > drivers/staging/iio/resolver/ad2s1210.c | 856 ++++++++++++++----------------- > 2 files changed, 399 insertions(+), 484 deletions(-) > > diff --git a/drivers/staging/iio/resolver/Kconfig b/drivers/staging/iio/resolver/Kconfig > index a4a3634..6ecd79e 100644 > --- a/drivers/staging/iio/resolver/Kconfig > +++ b/drivers/staging/iio/resolver/Kconfig > @@ -25,30 +25,3 @@ config AD2S1210 > Say yes here to build support for Analog Devices spi resolver > to digital converters, ad2s1210, provides direct access via sysfs. > > -choice > - prompt "Resolution Control" > - depends on AD2S1210 > - default AD2S1210_GPIO_NONE > - help > - In normal mode, the resolution of the digital output is selected > - using the RES0 and RES1 input pins. In configuration mode, the > - resolution is selected by setting the RES0 and RES1 bits in the > - control regsiter. When switching between normal mode and configuration > - mode, there are some schemes to keep them matchs. > - > -config AD2S1210_GPIO_INPUT > - bool "read resolution from gpio pins" > - help > - GPIO pins are sampling RES0 and RES1 pins, read the resolution > - settings from the GPIO pins. > - > -config AD2S1210_GPIO_OUTPUT > - bool "set gpio pins to set resolution" > - help > - RES0 and RES1 pins are controlled by GPIOs, setting GPIO pins to > - set the resolution. > - > -config AD2S1210_GPIO_NONE > - bool "take the responsibility by user" > - > -endchoice > diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c > index 09f4fcf..43521ce 100644 > --- a/drivers/staging/iio/resolver/ad2s1210.c > +++ b/drivers/staging/iio/resolver/ad2s1210.c > @@ -19,44 +19,41 @@ > > #include "../iio.h" > #include "../sysfs.h" > +#include "ad2s1210.h" > > #define DRV_NAME "ad2s1210" > > -#define DEF_CONTROL 0x7E > - > -#define MSB_IS_HIGH 0x80 > -#define MSB_IS_LOW 0x7F > -#define PHASE_LOCK_RANGE_44 0x20 > -#define ENABLE_HYSTERESIS 0x10 > -#define SET_ENRES1 0x08 > -#define SET_ENRES0 0x04 > -#define SET_RES1 0x02 > -#define SET_RES0 0x01 > - > -#define SET_ENRESOLUTION (SET_ENRES1 | SET_ENRES0) > -#define SET_RESOLUTION (SET_RES1 | SET_RES0) > - > -#define REG_POSITION 0x80 > -#define REG_VELOCITY 0x82 > -#define REG_LOS_THRD 0x88 > -#define REG_DOS_OVR_THRD 0x89 > -#define REG_DOS_MIS_THRD 0x8A > -#define REG_DOS_RST_MAX_THRD 0x8B > -#define REG_DOS_RST_MIN_THRD 0x8C > -#define REG_LOT_HIGH_THRD 0x8D > -#define REG_LOT_LOW_THRD 0x8E > -#define REG_EXCIT_FREQ 0x91 > -#define REG_CONTROL 0x92 > -#define REG_SOFT_RESET 0xF0 > -#define REG_FAULT 0xFF > +#define AD2S1210_DEF_CONTROL 0x7E > + > +#define AD2S1210_MSB_IS_HIGH 0x80 > +#define AD2S1210_MSB_IS_LOW 0x7F > +#define AD2S1210_PHASE_LOCK_RANGE_44 0x20 > +#define AD2S1210_ENABLE_HYSTERESIS 0x10 > +#define AD2S1210_SET_ENRES1 0x08 > +#define AD2S1210_SET_ENRES0 0x04 > +#define AD2S1210_SET_RES1 0x02 > +#define AD2S1210_SET_RES0 0x01 > + > +#define AD2S1210_SET_ENRESOLUTION (AD2S1210_SET_ENRES1 | \ > + AD2S1210_SET_ENRES0) > +#define AD2S1210_SET_RESOLUTION (AD2S1210_SET_RES1 | AD2S1210_SET_RES0) > + > +#define AD2S1210_REG_POSITION 0x80 > +#define AD2S1210_REG_VELOCITY 0x82 > +#define AD2S1210_REG_LOS_THRD 0x88 > +#define AD2S1210_REG_DOS_OVR_THRD 0x89 > +#define AD2S1210_REG_DOS_MIS_THRD 0x8A > +#define AD2S1210_REG_DOS_RST_MAX_THRD 0x8B > +#define AD2S1210_REG_DOS_RST_MIN_THRD 0x8C > +#define AD2S1210_REG_LOT_HIGH_THRD 0x8D > +#define AD2S1210_REG_LOT_LOW_THRD 0x8E > +#define AD2S1210_REG_EXCIT_FREQ 0x91 > +#define AD2S1210_REG_CONTROL 0x92 > +#define AD2S1210_REG_SOFT_RESET 0xF0 > +#define AD2S1210_REG_FAULT 0xFF > > /* pin SAMPLE, A0, A1, RES0, RES1, is controlled by driver */ > #define AD2S1210_SAA 3 > -#if defined(CONFIG_AD2S1210_GPIO_INPUT) || defined(CONFIG_AD2S1210_GPIO_OUTPUT) > -# define AD2S1210_RES 2 > -#else > -# define AD2S1210_RES 0 > -#endif > #define AD2S1210_PN (AD2S1210_SAA + AD2S1210_RES) > > #define AD2S1210_MIN_CLKIN 6144000 > @@ -75,190 +72,153 @@ > enum ad2s1210_mode { > MOD_POS = 0, > MOD_VEL, > - MOD_RESERVED, > MOD_CONFIG, > + MOD_RESERVED, > }; > > -enum ad2s1210_res { > - RES_10 = 10, > - RES_12 = 12, > - RES_14 = 14, > - RES_16 = 16, > -}; > - > -static unsigned int resolution_value[] = { > - RES_10, RES_12, RES_14, RES_16}; > +static const unsigned int ad2s1210_resolution_value[] = { 10, 12, 14, 16 }; > > struct ad2s1210_state { > + const struct ad2s1210_platform_data *pdata; > struct mutex lock; > - struct iio_dev *idev; > struct spi_device *sdev; > - struct spi_transfer xfer; > - unsigned int hysteresis; > - unsigned int old_data; > - enum ad2s1210_mode mode; > - enum ad2s1210_res resolution; > unsigned int fclkin; > unsigned int fexcit; > - unsigned short sample; > - unsigned short a0; > - unsigned short a1; > - unsigned short res0; > - unsigned short res1; > - u8 rx[3]; > - u8 tx[3]; > + bool hysteresis; > + bool old_data; > + u8 resolution; > + enum ad2s1210_mode mode; > + u8 rx[2] ____cacheline_aligned; > + u8 tx[2] ____cacheline_aligned; > }; > > -static inline void start_sample(struct ad2s1210_state *st) > -{ > - gpio_set_value(st->sample, 0); > -} > - > -static inline void stop_sample(struct ad2s1210_state *st) > -{ > - gpio_set_value(st->sample, 1); > -} > - > -static inline void set_mode(enum ad2s1210_mode mode, struct ad2s1210_state *st) > +static const int ad2s1210_mode_vals[4][2] = { > + [MOD_POS] = { 0, 0 }, > + [MOD_VEL] = { 0, 1 }, > + [MOD_CONFIG] = { 1, 0 }, > +}; > +static inline void ad2s1210_set_mode(enum ad2s1210_mode mode, > + struct ad2s1210_state *st) > { > - switch (mode) { > - case MOD_POS: > - gpio_set_value(st->a0, 0); > - gpio_set_value(st->a1, 0); > - break; > - case MOD_VEL: > - gpio_set_value(st->a0, 0); > - gpio_set_value(st->a1, 1); > - break; > - case MOD_CONFIG: > - gpio_set_value(st->a0, 1); > - gpio_set_value(st->a1, 1); > - break; > - default: > - /* set to reserved mode */ > - gpio_set_value(st->a0, 1); > - gpio_set_value(st->a1, 0); > - } > + gpio_set_value(st->pdata->a[0], ad2s1210_mode_vals[mode][0]); > + gpio_set_value(st->pdata->a[1], ad2s1210_mode_vals[mode][1]); > st->mode = mode; > } > > /* write 1 bytes (address or data) to the chip */ > -static int config_write(struct ad2s1210_state *st, > - unsigned char data) > +static int ad2s1210_config_write(struct ad2s1210_state *st, u8 data) > { > - struct spi_message msg; > - int ret = 0; > - > - st->xfer.len = 1; > - set_mode(MOD_CONFIG, st); > + int ret; > > - spi_message_init(&msg); > - spi_message_add_tail(&st->xfer, &msg); > + ad2s1210_set_mode(MOD_CONFIG, st); > st->tx[0] = data; > - ret = spi_sync(st->sdev, &msg); > - if (ret) > + ret = spi_write(st->sdev, st->tx, 1); > + if (ret < 0) > return ret; > - st->old_data = 1; > - return ret; > + st->old_data = true; > + > + return 0; > } > > /* read value from one of the registers */ > -static int config_read(struct ad2s1210_state *st, > - unsigned char address, > - unsigned char *data) > -{ > +static int ad2s1210_config_read(struct ad2s1210_state *st, > + unsigned char address) > +{ > + struct spi_transfer xfer = { > + .len = 2, > + .rx_buf = st->rx, > + .tx_buf = st->tx, > + }; > struct spi_message msg; > int ret = 0; > > - st->xfer.len = 2; > - set_mode(MOD_CONFIG, st); > - > + ad2s1210_set_mode(MOD_CONFIG, st); > spi_message_init(&msg); > - spi_message_add_tail(&st->xfer, &msg); > - st->tx[0] = address | MSB_IS_HIGH; > - st->tx[1] = REG_FAULT; > + spi_message_add_tail(&xfer, &msg); > + st->tx[0] = address | AD2S1210_MSB_IS_HIGH; > + st->tx[1] = AD2S1210_REG_FAULT; > ret = spi_sync(st->sdev, &msg); > - if (ret) > + if (ret < 0) > return ret; > - *data = st->rx[1]; > - st->old_data = 1; > - return ret; > + st->old_data = true; > + > + return st->rx[1]; > } > > -static inline void update_frequency_control_word(struct ad2s1210_state *st) > +static inline > +int ad2s1210_update_frequency_control_word(struct ad2s1210_state *st) > { > + int ret; > unsigned char fcw; > + > fcw = (unsigned char)(st->fexcit * (1 << 15) / st->fclkin); > - if (fcw >= AD2S1210_MIN_FCW && fcw <= AD2S1210_MAX_FCW) { > - config_write(st, REG_EXCIT_FREQ); > - config_write(st, fcw); > - } else > + if (fcw < AD2S1210_MIN_FCW || fcw > AD2S1210_MAX_FCW) { > pr_err("ad2s1210: FCW out of range\n"); > + return -ERANGE; > + } > + > + ret = ad2s1210_config_write(st, AD2S1210_REG_EXCIT_FREQ); > + if (ret < 0) > + return ret; > + > + return ad2s1210_config_write(st, fcw); > } > > -#if defined(CONFIG_AD2S1210_GPIO_INPUT) > -static inline unsigned char read_resolution_pin(struct ad2s1210_state *st) > +static inline unsigned char ad2s1210_read_resolution_pin(struct ad2s1210_state *st) > { > - unsigned int data; > - data = (gpio_get_value(st->res0) << 1) | > - gpio_get_value(st->res1); > - return resolution_value[data]; > + return ad2s1210_resolution_value[ > + (gpio_get_value(st->pdata->res[0]) << 1) | > + gpio_get_value(st->pdata->res[1])]; > } > -#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) > -static inline void set_resolution_pin(struct ad2s1210_state *st) > + > +static const int ad2s1210_res_pins[4][2] = { > + { 0, 0 }, {0, 1}, {1, 0}, {1, 1} > +}; > + > +static inline void ad2s1210_set_resolution_pin(struct ad2s1210_state *st) > { > - switch (st->resolution) { > - case RES_10: > - gpio_set_value(st->res0, 0); > - gpio_set_value(st->res1, 0); > - break; > - case RES_12: > - gpio_set_value(st->res0, 0); > - gpio_set_value(st->res1, 1); > - break; > - case RES_14: > - gpio_set_value(st->res0, 1); > - gpio_set_value(st->res1, 0); > - break; > - case RES_16: > - gpio_set_value(st->res0, 1); > - gpio_set_value(st->res1, 1); > - break; > - } > + gpio_set_value(st->pdata->res[0], > + ad2s1210_res_pins[(st->resolution - 10)/2][0]); > + gpio_set_value(st->pdata->res[1], > + ad2s1210_res_pins[(st->resolution - 10)/2][1]); > } > -#endif > > -static inline void soft_reset(struct ad2s1210_state *st) > +static inline int ad2s1210_soft_reset(struct ad2s1210_state *st) > { > - config_write(st, REG_SOFT_RESET); > - config_write(st, 0x0); > + int ret; > + > + ret = ad2s1210_config_write(st, AD2S1210_REG_SOFT_RESET); > + if (ret < 0) > + return ret; > + > + return ad2s1210_config_write(st, 0x0); > } > > > /* return the OLD DATA since last spi bus write */ > static ssize_t ad2s1210_show_raw(struct device *dev, > - struct device_attribute *attr, char *buf) > + struct device_attribute *attr, > + char *buf) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > - int ret; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > + int ret = 0; > > mutex_lock(&st->lock); > if (st->old_data) { > ret = sprintf(buf, "0x%x\n", st->rx[0]); > - st->old_data = 0; > - } else > - ret = 0; > + st->old_data = false; > + } > mutex_unlock(&st->lock); > + > return ret; > } > > static ssize_t ad2s1210_store_raw(struct device *dev, > - struct device_attribute *attr, > - const char *buf, size_t len) > + struct device_attribute *attr, > + const char *buf, > + size_t len) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > unsigned long udata; > unsigned char data; > int ret; > @@ -266,139 +226,157 @@ static ssize_t ad2s1210_store_raw(struct device *dev, > ret = strict_strtoul(buf, 16, &udata); > if (ret) > return -EINVAL; > + > data = udata & 0xff; > mutex_lock(&st->lock); > - config_write(st, data); > + ret = ad2s1210_config_write(st, data); > mutex_unlock(&st->lock); > - return 1; > + > + return ret < 0 ? ret : len; > } > > static ssize_t ad2s1210_store_softreset(struct device *dev, > - struct device_attribute *attr, > - const char *buf, size_t len) > + struct device_attribute *attr, > + const char *buf, > + size_t len) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > + int ret; > + > mutex_lock(&st->lock); > - soft_reset(st); > + ret = ad2s1210_soft_reset(st); > mutex_unlock(&st->lock); > - return len; > + > + return ret < 0 ? ret : len; > } > > static ssize_t ad2s1210_show_fclkin(struct device *dev, > - struct device_attribute *attr, char *buf) > + struct device_attribute *attr, > + char *buf) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > return sprintf(buf, "%d\n", st->fclkin); > } > > static ssize_t ad2s1210_store_fclkin(struct device *dev, > - struct device_attribute *attr, > - const char *buf, size_t len) > + struct device_attribute *attr, > + const char *buf, > + size_t len) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > unsigned long fclkin; > int ret; > > ret = strict_strtoul(buf, 10, &fclkin); > - if (!ret && fclkin >= AD2S1210_MIN_CLKIN && > - fclkin <= AD2S1210_MAX_CLKIN) { > - mutex_lock(&st->lock); > - st->fclkin = fclkin; > - } else { > + if (ret) > + return ret; > + if (fclkin < AD2S1210_MIN_CLKIN || fclkin > AD2S1210_MAX_CLKIN) { > pr_err("ad2s1210: fclkin out of range\n"); > return -EINVAL; > } > - update_frequency_control_word(st); > - soft_reset(st); > + > + mutex_lock(&st->lock); > + st->fclkin = fclkin; > + > + ret = ad2s1210_update_frequency_control_word(st); > + if (ret < 0) > + goto error_ret; > + ret = ad2s1210_soft_reset(st); > +error_ret: > mutex_unlock(&st->lock); > - return len; > + > + return ret < 0 ? ret : len; > } > > static ssize_t ad2s1210_show_fexcit(struct device *dev, > - struct device_attribute *attr, char *buf) > + struct device_attribute *attr, > + char *buf) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > return sprintf(buf, "%d\n", st->fexcit); > } > > static ssize_t ad2s1210_store_fexcit(struct device *dev, > - struct device_attribute *attr, > - const char *buf, size_t len) > + struct device_attribute *attr, > + const char *buf, size_t len) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > unsigned long fexcit; > int ret; > > ret = strict_strtoul(buf, 10, &fexcit); > - if (!ret && fexcit >= AD2S1210_MIN_EXCIT && > - fexcit <= AD2S1210_MAX_EXCIT) { > - mutex_lock(&st->lock); > - st->fexcit = fexcit; > - } else { > + if (ret < 0) > + return ret; > + if (fexcit < AD2S1210_MIN_EXCIT || fexcit > AD2S1210_MAX_EXCIT) { > pr_err("ad2s1210: excitation frequency out of range\n"); > return -EINVAL; > } > - update_frequency_control_word(st); > - soft_reset(st); > + mutex_lock(&st->lock); > + st->fexcit = fexcit; > + ret = ad2s1210_update_frequency_control_word(st); > + if (ret < 0) > + goto error_ret; > + ret = ad2s1210_soft_reset(st); > +error_ret: > mutex_unlock(&st->lock); > - return len; > + > + return ret < 0 ? ret : len; > } > > static ssize_t ad2s1210_show_control(struct device *dev, > - struct device_attribute *attr, char *buf) > + struct device_attribute *attr, > + char *buf) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > - unsigned char data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > + int ret; > mutex_lock(&st->lock); > - config_read(st, REG_CONTROL, &data); > + ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL); > mutex_unlock(&st->lock); > - return sprintf(buf, "0x%x\n", data); > + return ret < 0 ? ret : sprintf(buf, "0x%x\n", ret); > } > > static ssize_t ad2s1210_store_control(struct device *dev, > struct device_attribute *attr, > const char *buf, size_t len) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > unsigned long udata; > unsigned char data; > int ret; > > ret = strict_strtoul(buf, 16, &udata); > - if (ret) { > - ret = -EINVAL; > - goto error_ret; > - } > + if (ret) > + return -EINVAL; > + > mutex_lock(&st->lock); > - config_write(st, REG_CONTROL); > - data = udata & MSB_IS_LOW; > - config_write(st, data); > - config_read(st, REG_CONTROL, &data); > - if (data & MSB_IS_HIGH) { > + ret = ad2s1210_config_write(st, AD2S1210_REG_CONTROL); > + if (ret < 0) > + goto error_ret; > + data = udata & AD2S1210_MSB_IS_LOW; > + ret = ad2s1210_config_write(st, data); > + if (ret < 0) > + goto error_ret; > + > + ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL); > + if (ret < 0) > + goto error_ret; > + if (ret & AD2S1210_MSB_IS_HIGH) { > ret = -EIO; > pr_err("ad2s1210: write control register fail\n"); > goto error_ret; > } > - st->resolution = resolution_value[data & SET_RESOLUTION]; > -#if defined(CONFIG_AD2S1210_GPIO_INPUT) > - data = read_resolution_pin(st); > - if (data != st->resolution) > - pr_warning("ad2s1210: resolution settings not match\n"); > -#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) > - set_resolution_pin(st); > -#endif > + st->resolution > + = ad2s1210_resolution_value[data & AD2S1210_SET_RESOLUTION]; > + if (st->pdata->gpioin) { > + data = ad2s1210_read_resolution_pin(st); > + if (data != st->resolution) > + pr_warning("ad2s1210: resolution settings not match\n"); > + } else > + ad2s1210_set_resolution_pin(st); > + > ret = len; > - if (data & ENABLE_HYSTERESIS) > - st->hysteresis = 1; > - else > - st->hysteresis = 0; > + st->hysteresis = !!(data & AD2S1210_ENABLE_HYSTERESIS); > + > error_ret: > mutex_unlock(&st->lock); > return ret; > @@ -407,8 +385,7 @@ error_ret: > static ssize_t ad2s1210_show_resolution(struct device *dev, > struct device_attribute *attr, char *buf) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > return sprintf(buf, "%d\n", st->resolution); > } > > @@ -416,103 +393,109 @@ static ssize_t ad2s1210_store_resolution(struct device *dev, > struct device_attribute *attr, > const char *buf, size_t len) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > unsigned char data; > unsigned long udata; > int ret; > > ret = strict_strtoul(buf, 10, &udata); > - if (ret || udata < RES_10 || udata > RES_16) { > + if (ret || udata < 10 || udata > 16) { > pr_err("ad2s1210: resolution out of range\n"); > return -EINVAL; > } > mutex_lock(&st->lock); > - config_read(st, REG_CONTROL, &data); > - data &= ~SET_RESOLUTION; > - data |= (udata - RES_10) >> 1; > - config_write(st, REG_CONTROL); > - config_write(st, data & MSB_IS_LOW); > - config_read(st, REG_CONTROL, &data); > - if (data & MSB_IS_HIGH) { > + ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL); > + if (ret < 0) > + goto error_ret; > + data = ret; > + data &= ~AD2S1210_SET_RESOLUTION; > + data |= (udata - 10) >> 1; > + ret = ad2s1210_config_write(st, AD2S1210_REG_CONTROL); > + if (ret < 0) > + goto error_ret; > + ret = ad2s1210_config_write(st, data & AD2S1210_MSB_IS_LOW); > + if (ret < 0) > + goto error_ret; > + ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL); > + if (ret < 0) > + goto error_ret; > + data = ret; > + if (data & AD2S1210_MSB_IS_HIGH) { > ret = -EIO; > pr_err("ad2s1210: setting resolution fail\n"); > goto error_ret; > } > - st->resolution = resolution_value[data & SET_RESOLUTION]; > -#if defined(CONFIG_AD2S1210_GPIO_INPUT) > - data = read_resolution_pin(st); > - if (data != st->resolution) > - pr_warning("ad2s1210: resolution settings not match\n"); > -#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) > - set_resolution_pin(st); > -#endif > + st->resolution > + = ad2s1210_resolution_value[data & AD2S1210_SET_RESOLUTION]; > + if (st->pdata->gpioin) { > + data = ad2s1210_read_resolution_pin(st); > + if (data != st->resolution) > + pr_warning("ad2s1210: resolution settings not match\n"); > + } else > + ad2s1210_set_resolution_pin(st); > ret = len; > error_ret: > mutex_unlock(&st->lock); > return ret; > } > + > /* read the fault register since last sample */ > static ssize_t ad2s1210_show_fault(struct device *dev, > struct device_attribute *attr, char *buf) > { > - int ret = 0; > - ssize_t len = 0; > - unsigned char data; > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > + int ret; > > mutex_lock(&st->lock); > - ret = config_read(st, REG_FAULT, &data); > - > - if (ret) > - goto error_ret; > - len = sprintf(buf, "0x%x\n", data); > -error_ret: > + ret = ad2s1210_config_read(st, AD2S1210_REG_FAULT); > mutex_unlock(&st->lock); > - return ret ? ret : len; > + > + return ret ? ret : sprintf(buf, "0x%x\n", ret); > } > > static ssize_t ad2s1210_clear_fault(struct device *dev, > - struct device_attribute *attr, > - const char *buf, size_t len) > + struct device_attribute *attr, > + const char *buf, > + size_t len) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > - unsigned char data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > + int ret; > > mutex_lock(&st->lock); > - start_sample(st); > + gpio_set_value(st->pdata->sample, 0); > /* delay (2 * tck + 20) nano seconds */ > udelay(1); > - stop_sample(st); > - config_read(st, REG_FAULT, &data); > - start_sample(st); > - stop_sample(st); > + gpio_set_value(st->pdata->sample, 1); > + ret = ad2s1210_config_read(st, AD2S1210_REG_FAULT); > + if (ret < 0) > + goto error_ret; > + gpio_set_value(st->pdata->sample, 0); > + gpio_set_value(st->pdata->sample, 1); > +error_ret: > mutex_unlock(&st->lock); > > - return 0; > + return ret < 0 ? ret : len; > } > > static ssize_t ad2s1210_show_reg(struct device *dev, > - struct device_attribute *attr, char *buf) > + struct device_attribute *attr, > + char *buf) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > - unsigned char data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > struct iio_dev_attr *iattr = to_iio_dev_attr(attr); > + int ret; > > mutex_lock(&st->lock); > - config_read(st, iattr->address, &data); > + ret = ad2s1210_config_read(st, iattr->address); > mutex_unlock(&st->lock); > - return sprintf(buf, "%d\n", data); > + > + return ret < 0 ? ret : sprintf(buf, "%d\n", ret); > } > > static ssize_t ad2s1210_store_reg(struct device *dev, > struct device_attribute *attr, const char *buf, size_t len) > { > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > unsigned long data; > int ret; > struct iio_dev_attr *iattr = to_iio_dev_attr(attr); > @@ -521,183 +504,121 @@ static ssize_t ad2s1210_store_reg(struct device *dev, > if (ret) > return -EINVAL; > mutex_lock(&st->lock); > - config_write(st, iattr->address); > - config_write(st, data & MSB_IS_LOW); > + ret = ad2s1210_config_write(st, iattr->address); > + if (ret < 0) > + goto error_ret; > + ret = ad2s1210_config_write(st, data & AD2S1210_MSB_IS_LOW); > +error_ret: > mutex_unlock(&st->lock); > - return len; > + return ret < 0 ? ret : len; > } > > static ssize_t ad2s1210_show_pos(struct device *dev, > - struct device_attribute *attr, char *buf) > + struct device_attribute *attr, > + char *buf) > { > - struct spi_message msg; > int ret = 0; > ssize_t len = 0; > u16 pos; > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > > - st->xfer.len = 2; > mutex_lock(&st->lock); > - start_sample(st); > + gpio_set_value(st->pdata->sample, 0); > /* delay (6 * tck + 20) nano seconds */ > udelay(1); > > - set_mode(MOD_POS, st); > - > - spi_message_init(&msg); > - spi_message_add_tail(&st->xfer, &msg); > - ret = spi_sync(st->sdev, &msg); > + ad2s1210_set_mode(MOD_POS, st); > + ret = spi_read(st->sdev, st->rx, 2); > if (ret) > goto error_ret; > - pos = ((((u16)(st->rx[0])) << 8) | (st->rx[1])); > + pos = be16_to_cpup((u16 *)st->rx); > if (st->hysteresis) > pos >>= 16 - st->resolution; > len = sprintf(buf, "%d\n", pos); > error_ret: > - stop_sample(st); > + gpio_set_value(st->pdata->sample, 1); > /* delay (2 * tck + 20) nano seconds */ > udelay(1); > mutex_unlock(&st->lock); > > - return ret ? ret : len; > + return ret < 0 ? ret : len; > } > > static ssize_t ad2s1210_show_vel(struct device *dev, > - struct device_attribute *attr, char *buf) > + struct device_attribute *attr, > + char *buf) > { > - struct spi_message msg; > unsigned short negative; > int ret = 0; > ssize_t len = 0; > s16 vel; > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > + struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev)); > > - st->xfer.len = 2; > mutex_lock(&st->lock); > - start_sample(st); > + gpio_set_value(st->pdata->sample, 0); > /* delay (6 * tck + 20) nano seconds */ > udelay(1); > > - set_mode(MOD_VEL, st); > - > - spi_message_init(&msg); > - spi_message_add_tail(&st->xfer, &msg); > - ret = spi_sync(st->sdev, &msg); > + ad2s1210_set_mode(MOD_VEL, st); > + ret = spi_read(st->sdev, st->rx, 2); > if (ret) > goto error_ret; > negative = st->rx[0] & 0x80; > - vel = ((((s16)(st->rx[0])) << 8) | (st->rx[1])); > + vel = be16_to_cpup((s16 *)st->rx); > vel >>= 16 - st->resolution; > - if (negative) { > + if (vel & 0x8000) { > negative = (0xffff >> st->resolution) << st->resolution; > vel |= negative; > } > len = sprintf(buf, "%d\n", vel); > error_ret: > - stop_sample(st); > - /* delay (2 * tck + 20) nano seconds */ > - udelay(1); > - mutex_unlock(&st->lock); > - > - return ret ? ret : len; > -} > - > -static ssize_t ad2s1210_show_pos_vel(struct device *dev, > - struct device_attribute *attr, char *buf) > -{ > - struct spi_message msg; > - unsigned short negative; > - int ret = 0; > - ssize_t len = 0; > - u16 pos; > - s16 vel; > - struct iio_dev *idev = dev_get_drvdata(dev); > - struct ad2s1210_state *st = idev->dev_data; > - > - st->xfer.len = 2; > - mutex_lock(&st->lock); > - start_sample(st); > - /* delay (6 * tck + 20) nano seconds */ > - udelay(1); > - > - set_mode(MOD_POS, st); > - > - spi_message_init(&msg); > - spi_message_add_tail(&st->xfer, &msg); > - ret = spi_sync(st->sdev, &msg); > - if (ret) > - goto error_ret; > - pos = ((((u16)(st->rx[0])) << 8) | (st->rx[1])); > - if (st->hysteresis) > - pos >>= 16 - st->resolution; > - len = sprintf(buf, "%d ", pos); > - > - st->xfer.len = 2; > - set_mode(MOD_VEL, st); > - spi_message_init(&msg); > - spi_message_add_tail(&st->xfer, &msg); > - ret = spi_sync(st->sdev, &msg); > - if (ret) > - goto error_ret; > - negative = st->rx[0] & 0x80; > - vel = ((((s16)(st->rx[0])) << 8) | (st->rx[1])); > - vel >>= 16 - st->resolution; > - if (negative) { > - negative = (0xffff >> st->resolution) << st->resolution; > - vel |= negative; > - } > - len += sprintf(buf + len, "%d\n", vel); > -error_ret: > - stop_sample(st); > + gpio_set_value(st->pdata->sample, 1); > /* delay (2 * tck + 20) nano seconds */ > udelay(1); > mutex_unlock(&st->lock); > > - return ret ? ret : len; > + return ret < 0 ? ret : len; > } > > -static IIO_CONST_ATTR(description, > - "Variable Resolution, 10-Bit to 16Bit R/D\n\ > -Converter with Reference Oscillator"); > static IIO_DEVICE_ATTR(raw_io, S_IRUGO | S_IWUSR, > - ad2s1210_show_raw, ad2s1210_store_raw, 0); > + ad2s1210_show_raw, ad2s1210_store_raw, 0); > static IIO_DEVICE_ATTR(reset, S_IWUSR, > - NULL, ad2s1210_store_softreset, 0); > + NULL, ad2s1210_store_softreset, 0); > static IIO_DEVICE_ATTR(fclkin, S_IRUGO | S_IWUSR, > - ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0); > + ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0); > static IIO_DEVICE_ATTR(fexcit, S_IRUGO | S_IWUSR, > - ad2s1210_show_fexcit, ad2s1210_store_fexcit, 0); > + ad2s1210_show_fexcit, ad2s1210_store_fexcit, 0); > static IIO_DEVICE_ATTR(control, S_IRUGO | S_IWUSR, > - ad2s1210_show_control, ad2s1210_store_control, 0); > + ad2s1210_show_control, ad2s1210_store_control, 0); > static IIO_DEVICE_ATTR(bits, S_IRUGO | S_IWUSR, > - ad2s1210_show_resolution, ad2s1210_store_resolution, 0); > + ad2s1210_show_resolution, ad2s1210_store_resolution, 0); > static IIO_DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, > - ad2s1210_show_fault, ad2s1210_clear_fault, 0); > -static IIO_DEVICE_ATTR(pos, S_IRUGO, > - ad2s1210_show_pos, NULL, 0); > -static IIO_DEVICE_ATTR(vel, S_IRUGO, > - ad2s1210_show_vel, NULL, 0); > -static IIO_DEVICE_ATTR(pos_vel, S_IRUGO, > - ad2s1210_show_pos_vel, NULL, 0); > + ad2s1210_show_fault, ad2s1210_clear_fault, 0); > +static IIO_DEVICE_ATTR(pos, S_IRUGO, ad2s1210_show_pos, NULL, 0); > +static IIO_DEVICE_ATTR(vel, S_IRUGO, ad2s1210_show_vel, NULL, 0); > static IIO_DEVICE_ATTR(los_thrd, S_IRUGO | S_IWUSR, > - ad2s1210_show_reg, ad2s1210_store_reg, REG_LOS_THRD); > + ad2s1210_show_reg, ad2s1210_store_reg, > + AD2S1210_REG_LOS_THRD); > static IIO_DEVICE_ATTR(dos_ovr_thrd, S_IRUGO | S_IWUSR, > - ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_OVR_THRD); > + ad2s1210_show_reg, ad2s1210_store_reg, > + AD2S1210_REG_DOS_OVR_THRD); > static IIO_DEVICE_ATTR(dos_mis_thrd, S_IRUGO | S_IWUSR, > - ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_MIS_THRD); > + ad2s1210_show_reg, ad2s1210_store_reg, > + AD2S1210_REG_DOS_MIS_THRD); > static IIO_DEVICE_ATTR(dos_rst_max_thrd, S_IRUGO | S_IWUSR, > - ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_RST_MAX_THRD); > + ad2s1210_show_reg, ad2s1210_store_reg, > + AD2S1210_REG_DOS_RST_MAX_THRD); > static IIO_DEVICE_ATTR(dos_rst_min_thrd, S_IRUGO | S_IWUSR, > - ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_RST_MIN_THRD); > + ad2s1210_show_reg, ad2s1210_store_reg, > + AD2S1210_REG_DOS_RST_MIN_THRD); > static IIO_DEVICE_ATTR(lot_high_thrd, S_IRUGO | S_IWUSR, > - ad2s1210_show_reg, ad2s1210_store_reg, REG_LOT_HIGH_THRD); > + ad2s1210_show_reg, ad2s1210_store_reg, > + AD2S1210_REG_LOT_HIGH_THRD); > static IIO_DEVICE_ATTR(lot_low_thrd, S_IRUGO | S_IWUSR, > - ad2s1210_show_reg, ad2s1210_store_reg, REG_LOT_LOW_THRD); > + ad2s1210_show_reg, ad2s1210_store_reg, > + AD2S1210_REG_LOT_LOW_THRD); > > static struct attribute *ad2s1210_attributes[] = { > - &iio_const_attr_description.dev_attr.attr, > &iio_dev_attr_raw_io.dev_attr.attr, > &iio_dev_attr_reset.dev_attr.attr, > &iio_dev_attr_fclkin.dev_attr.attr, > @@ -707,7 +628,6 @@ static struct attribute *ad2s1210_attributes[] = { > &iio_dev_attr_fault.dev_attr.attr, > &iio_dev_attr_pos.dev_attr.attr, > &iio_dev_attr_vel.dev_attr.attr, > - &iio_dev_attr_pos_vel.dev_attr.attr, > &iio_dev_attr_los_thrd.dev_attr.attr, > &iio_dev_attr_dos_ovr_thrd.dev_attr.attr, > &iio_dev_attr_dos_mis_thrd.dev_attr.attr, > @@ -729,27 +649,32 @@ static int __devinit ad2s1210_initial(struct ad2s1210_state *st) > int ret; > > mutex_lock(&st->lock); > -#if defined(CONFIG_AD2S1210_GPIO_INPUT) > - st->resolution = read_resolution_pin(st); > -#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) > - set_resolution_pin(st); > -#endif > - > - config_write(st, REG_CONTROL); > - data = DEF_CONTROL & ~(SET_RESOLUTION); > - data |= (st->resolution - RES_10) >> 1; > - config_write(st, data); > - ret = config_read(st, REG_CONTROL, &data); > - if (ret) > + if (st->pdata->gpioin) > + st->resolution = ad2s1210_read_resolution_pin(st); > + else > + ad2s1210_set_resolution_pin(st); > + > + ret = ad2s1210_config_write(st, AD2S1210_REG_CONTROL); > + if (ret < 0) > + goto error_ret; > + data = AD2S1210_DEF_CONTROL & ~(AD2S1210_SET_RESOLUTION); > + data |= (st->resolution - 10) >> 1; > + ret = ad2s1210_config_write(st, data); > + if (ret < 0) > + goto error_ret; > + ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL); > + if (ret < 0) > goto error_ret; > > - if (data & MSB_IS_HIGH) { > + if (ret & AD2S1210_MSB_IS_HIGH) { > ret = -EIO; > goto error_ret; > } > > - update_frequency_control_word(st); > - soft_reset(st); > + ret = ad2s1210_update_frequency_control_word(st); > + if (ret < 0) > + goto error_ret; > + ret = ad2s1210_soft_reset(st); > error_ret: > mutex_unlock(&st->lock); > return ret; > @@ -760,90 +685,107 @@ static const struct iio_info ad2s1210_info = { > .driver_module = THIS_MODULE, > }; > > +static int ad2s1210_setup_gpios(struct ad2s1210_state *st) > +{ > + int ret; > + unsigned long flags = st->pdata->gpioin ? GPIOF_DIR_IN : GPIOF_DIR_OUT; > + > + ret = gpio_request_one(st->pdata->sample, GPIOF_DIR_IN, "sample"); > + if (ret < 0) > + goto error_ret; > + ret = gpio_request_one(st->pdata->a[0], flags, "a0"); > + if (ret < 0) > + goto error_free_sample; > + ret = gpio_request_one(st->pdata->a[1], flags, "a1"); > + if (ret < 0) > + goto error_free_a0; > + ret = gpio_request_one(st->pdata->res[1], flags, "res0"); > + if (ret < 0) > + goto error_free_a1; > + ret = gpio_request_one(st->pdata->res[1], flags, "res1"); > + if (ret < 0) > + goto error_free_res0; > + > + return 0; > +error_free_res0: > + gpio_free(st->pdata->res[0]); > +error_free_a1: > + gpio_free(st->pdata->a[1]); > +error_free_a0: > + gpio_free(st->pdata->a[0]); > +error_free_sample: > + gpio_free(st->pdata->sample); > +error_ret: > + return ret; > +} > + > +static void ad2s1210_free_gpios(struct ad2s1210_state *st) > +{ > + gpio_free(st->pdata->res[1]); > + gpio_free(st->pdata->res[0]); > + gpio_free(st->pdata->a[1]); > + gpio_free(st->pdata->a[0]); > + gpio_free(st->pdata->sample); > +} > + > static int __devinit ad2s1210_probe(struct spi_device *spi) > { > + struct iio_dev *indio_dev; > struct ad2s1210_state *st; > - int pn, ret = 0; > - unsigned short *pins = spi->dev.platform_data; > - > - for (pn = 0; pn < AD2S1210_PN; pn++) { > - if (gpio_request(pins[pn], DRV_NAME)) { > - pr_err("%s: request gpio pin %d failed\n", > - DRV_NAME, pins[pn]); > - goto error_ret; > - } > - if (pn < AD2S1210_SAA) > - gpio_direction_output(pins[pn], 1); > - else { > -#if defined(CONFIG_AD2S1210_GPIO_INPUT) > - gpio_direction_input(pins[pn]); > -#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) > - gpio_direction_output(pins[pn], 1); > -#endif > - } > - } > + int ret; > + > + if (spi->dev.platform_data == NULL) > + return -EINVAL; > > - st = kzalloc(sizeof(*st), GFP_KERNEL); > - if (st == NULL) { > + indio_dev = iio_allocate_device(sizeof(*st)); > + if (indio_dev == NULL) { > ret = -ENOMEM; > goto error_ret; > } > - spi_set_drvdata(spi, st); > + st = iio_priv(indio_dev); > + st->pdata = spi->dev.platform_data; > + ret = ad2s1210_setup_gpios(st); > + if (ret < 0) > + goto error_free_dev; > + > + spi_set_drvdata(spi, indio_dev); > > mutex_init(&st->lock); > st->sdev = spi; > - st->xfer.tx_buf = st->tx; > - st->xfer.rx_buf = st->rx; > - st->hysteresis = 1; > + st->hysteresis = true; > st->mode = MOD_CONFIG; > - st->resolution = RES_12; > - st->fclkin = AD2S1210_DEF_CLKIN; > + st->resolution = 12; > st->fexcit = AD2S1210_DEF_EXCIT; > - st->sample = pins[0]; > - st->a0 = pins[1]; > - st->a1 = pins[2]; > - st->res0 = pins[3]; > - st->res1 = pins[4]; > - > - st->idev = iio_allocate_device(0); > - if (st->idev == NULL) { > - ret = -ENOMEM; > - goto error_free_st; > - } > - st->idev->dev.parent = &spi->dev; > > - st->idev->info = &ad2s1210_info; > - st->idev->dev_data = (void *)(st); > - st->idev->modes = INDIO_DIRECT_MODE; > + indio_dev->dev.parent = &spi->dev; > + indio_dev->info = &ad2s1210_info; > + indio_dev->modes = INDIO_DIRECT_MODE; > > - ret = iio_device_register(st->idev); > + ret = iio_device_register(indio_dev); > if (ret) > - goto error_free_dev; > + goto error_free_gpios; > > - if (spi->max_speed_hz != AD2S1210_DEF_CLKIN) > - st->fclkin = spi->max_speed_hz; > + st->fclkin = spi->max_speed_hz; > spi->mode = SPI_MODE_3; > spi_setup(spi); > - > ad2s1210_initial(st); > + > return 0; > > +error_free_gpios: > + ad2s1210_free_gpios(st); > error_free_dev: > - iio_free_device(st->idev); > -error_free_st: > - kfree(st); > + iio_free_device(indio_dev); > error_ret: > - for (--pn; pn >= 0; pn--) > - gpio_free(pins[pn]); > return ret; > } > > static int __devexit ad2s1210_remove(struct spi_device *spi) > { > - struct ad2s1210_state *st = spi_get_drvdata(spi); > - > - iio_device_unregister(st->idev); > - kfree(st); > + struct iio_dev *indio_dev = spi_get_drvdata(spi); > + struct ad2s1210_state *st = iio_priv(indio_dev); > + iio_device_unregister(indio_dev); > + ad2s1210_free_gpios(st); > > return 0; > } -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html