156ca9db8SPaul Cercueil /* 256ca9db8SPaul Cercueil * AD5592R Digital <-> Analog converters driver 356ca9db8SPaul Cercueil * 456ca9db8SPaul Cercueil * Copyright 2014-2016 Analog Devices Inc. 556ca9db8SPaul Cercueil * Author: Paul Cercueil <paul.cercueil@analog.com> 656ca9db8SPaul Cercueil * 756ca9db8SPaul Cercueil * Licensed under the GPL-2. 856ca9db8SPaul Cercueil */ 956ca9db8SPaul Cercueil 1056ca9db8SPaul Cercueil #include <linux/bitops.h> 1156ca9db8SPaul Cercueil #include <linux/delay.h> 1256ca9db8SPaul Cercueil #include <linux/iio/iio.h> 1356ca9db8SPaul Cercueil #include <linux/module.h> 1456ca9db8SPaul Cercueil #include <linux/mutex.h> 1556ca9db8SPaul Cercueil #include <linux/of.h> 1656ca9db8SPaul Cercueil #include <linux/regulator/consumer.h> 1756ca9db8SPaul Cercueil #include <linux/gpio/consumer.h> 1856ca9db8SPaul Cercueil #include <linux/gpio/driver.h> 1956ca9db8SPaul Cercueil #include <linux/gpio.h> 2056ca9db8SPaul Cercueil #include <linux/property.h> 2156ca9db8SPaul Cercueil 2256ca9db8SPaul Cercueil #include <dt-bindings/iio/adi,ad5592r.h> 2356ca9db8SPaul Cercueil 2456ca9db8SPaul Cercueil #include "ad5592r-base.h" 2556ca9db8SPaul Cercueil 2656ca9db8SPaul Cercueil static int ad5592r_gpio_get(struct gpio_chip *chip, unsigned offset) 2756ca9db8SPaul Cercueil { 2856ca9db8SPaul Cercueil struct ad5592r_state *st = gpiochip_get_data(chip); 2956ca9db8SPaul Cercueil int ret = 0; 3056ca9db8SPaul Cercueil u8 val; 3156ca9db8SPaul Cercueil 3256ca9db8SPaul Cercueil mutex_lock(&st->gpio_lock); 3356ca9db8SPaul Cercueil 3456ca9db8SPaul Cercueil if (st->gpio_out & BIT(offset)) 3556ca9db8SPaul Cercueil val = st->gpio_val; 3656ca9db8SPaul Cercueil else 3756ca9db8SPaul Cercueil ret = st->ops->gpio_read(st, &val); 3856ca9db8SPaul Cercueil 3956ca9db8SPaul Cercueil mutex_unlock(&st->gpio_lock); 4056ca9db8SPaul Cercueil 4156ca9db8SPaul Cercueil if (ret < 0) 4256ca9db8SPaul Cercueil return ret; 4356ca9db8SPaul Cercueil 4456ca9db8SPaul Cercueil return !!(val & BIT(offset)); 4556ca9db8SPaul Cercueil } 4656ca9db8SPaul Cercueil 4756ca9db8SPaul Cercueil static void ad5592r_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 4856ca9db8SPaul Cercueil { 4956ca9db8SPaul Cercueil struct ad5592r_state *st = gpiochip_get_data(chip); 5056ca9db8SPaul Cercueil 5156ca9db8SPaul Cercueil mutex_lock(&st->gpio_lock); 5256ca9db8SPaul Cercueil 5356ca9db8SPaul Cercueil if (value) 5456ca9db8SPaul Cercueil st->gpio_val |= BIT(offset); 5556ca9db8SPaul Cercueil else 5656ca9db8SPaul Cercueil st->gpio_val &= ~BIT(offset); 5756ca9db8SPaul Cercueil 5856ca9db8SPaul Cercueil st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); 5956ca9db8SPaul Cercueil 6056ca9db8SPaul Cercueil mutex_unlock(&st->gpio_lock); 6156ca9db8SPaul Cercueil } 6256ca9db8SPaul Cercueil 6356ca9db8SPaul Cercueil static int ad5592r_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 6456ca9db8SPaul Cercueil { 6556ca9db8SPaul Cercueil struct ad5592r_state *st = gpiochip_get_data(chip); 6656ca9db8SPaul Cercueil int ret; 6756ca9db8SPaul Cercueil 6856ca9db8SPaul Cercueil mutex_lock(&st->gpio_lock); 6956ca9db8SPaul Cercueil 7056ca9db8SPaul Cercueil st->gpio_out &= ~BIT(offset); 7156ca9db8SPaul Cercueil st->gpio_in |= BIT(offset); 7256ca9db8SPaul Cercueil 7356ca9db8SPaul Cercueil ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); 7456ca9db8SPaul Cercueil if (ret < 0) 7556ca9db8SPaul Cercueil goto err_unlock; 7656ca9db8SPaul Cercueil 7756ca9db8SPaul Cercueil ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); 7856ca9db8SPaul Cercueil 7956ca9db8SPaul Cercueil err_unlock: 8056ca9db8SPaul Cercueil mutex_unlock(&st->gpio_lock); 8156ca9db8SPaul Cercueil 8256ca9db8SPaul Cercueil return ret; 8356ca9db8SPaul Cercueil } 8456ca9db8SPaul Cercueil 8556ca9db8SPaul Cercueil static int ad5592r_gpio_direction_output(struct gpio_chip *chip, 8656ca9db8SPaul Cercueil unsigned offset, int value) 8756ca9db8SPaul Cercueil { 8856ca9db8SPaul Cercueil struct ad5592r_state *st = gpiochip_get_data(chip); 8956ca9db8SPaul Cercueil int ret; 9056ca9db8SPaul Cercueil 9156ca9db8SPaul Cercueil mutex_lock(&st->gpio_lock); 9256ca9db8SPaul Cercueil 9356ca9db8SPaul Cercueil if (value) 9456ca9db8SPaul Cercueil st->gpio_val |= BIT(offset); 9556ca9db8SPaul Cercueil else 9656ca9db8SPaul Cercueil st->gpio_val &= ~BIT(offset); 9756ca9db8SPaul Cercueil 9856ca9db8SPaul Cercueil st->gpio_in &= ~BIT(offset); 9956ca9db8SPaul Cercueil st->gpio_out |= BIT(offset); 10056ca9db8SPaul Cercueil 10156ca9db8SPaul Cercueil ret = st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); 10256ca9db8SPaul Cercueil if (ret < 0) 10356ca9db8SPaul Cercueil goto err_unlock; 10456ca9db8SPaul Cercueil 10556ca9db8SPaul Cercueil ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); 10656ca9db8SPaul Cercueil if (ret < 0) 10756ca9db8SPaul Cercueil goto err_unlock; 10856ca9db8SPaul Cercueil 10956ca9db8SPaul Cercueil ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); 11056ca9db8SPaul Cercueil 11156ca9db8SPaul Cercueil err_unlock: 11256ca9db8SPaul Cercueil mutex_unlock(&st->gpio_lock); 11356ca9db8SPaul Cercueil 11456ca9db8SPaul Cercueil return ret; 11556ca9db8SPaul Cercueil } 11656ca9db8SPaul Cercueil 11756ca9db8SPaul Cercueil static int ad5592r_gpio_request(struct gpio_chip *chip, unsigned offset) 11856ca9db8SPaul Cercueil { 11956ca9db8SPaul Cercueil struct ad5592r_state *st = gpiochip_get_data(chip); 12056ca9db8SPaul Cercueil 12156ca9db8SPaul Cercueil if (!(st->gpio_map & BIT(offset))) { 12256ca9db8SPaul Cercueil dev_err(st->dev, "GPIO %d is reserved by alternate function\n", 12356ca9db8SPaul Cercueil offset); 12456ca9db8SPaul Cercueil return -ENODEV; 12556ca9db8SPaul Cercueil } 12656ca9db8SPaul Cercueil 12756ca9db8SPaul Cercueil return 0; 12856ca9db8SPaul Cercueil } 12956ca9db8SPaul Cercueil 13056ca9db8SPaul Cercueil static int ad5592r_gpio_init(struct ad5592r_state *st) 13156ca9db8SPaul Cercueil { 13256ca9db8SPaul Cercueil if (!st->gpio_map) 13356ca9db8SPaul Cercueil return 0; 13456ca9db8SPaul Cercueil 13556ca9db8SPaul Cercueil st->gpiochip.label = dev_name(st->dev); 13656ca9db8SPaul Cercueil st->gpiochip.base = -1; 13756ca9db8SPaul Cercueil st->gpiochip.ngpio = 8; 13856ca9db8SPaul Cercueil st->gpiochip.parent = st->dev; 13956ca9db8SPaul Cercueil st->gpiochip.can_sleep = true; 14056ca9db8SPaul Cercueil st->gpiochip.direction_input = ad5592r_gpio_direction_input; 14156ca9db8SPaul Cercueil st->gpiochip.direction_output = ad5592r_gpio_direction_output; 14256ca9db8SPaul Cercueil st->gpiochip.get = ad5592r_gpio_get; 14356ca9db8SPaul Cercueil st->gpiochip.set = ad5592r_gpio_set; 14456ca9db8SPaul Cercueil st->gpiochip.request = ad5592r_gpio_request; 14556ca9db8SPaul Cercueil st->gpiochip.owner = THIS_MODULE; 14656ca9db8SPaul Cercueil 14756ca9db8SPaul Cercueil mutex_init(&st->gpio_lock); 14856ca9db8SPaul Cercueil 14956ca9db8SPaul Cercueil return gpiochip_add_data(&st->gpiochip, st); 15056ca9db8SPaul Cercueil } 15156ca9db8SPaul Cercueil 15256ca9db8SPaul Cercueil static void ad5592r_gpio_cleanup(struct ad5592r_state *st) 15356ca9db8SPaul Cercueil { 15456ca9db8SPaul Cercueil if (st->gpio_map) 15556ca9db8SPaul Cercueil gpiochip_remove(&st->gpiochip); 15656ca9db8SPaul Cercueil } 15756ca9db8SPaul Cercueil 15856ca9db8SPaul Cercueil static int ad5592r_reset(struct ad5592r_state *st) 15956ca9db8SPaul Cercueil { 16056ca9db8SPaul Cercueil struct gpio_desc *gpio; 16156ca9db8SPaul Cercueil struct iio_dev *iio_dev = iio_priv_to_dev(st); 16256ca9db8SPaul Cercueil 16356ca9db8SPaul Cercueil gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW); 16456ca9db8SPaul Cercueil if (IS_ERR(gpio)) 16556ca9db8SPaul Cercueil return PTR_ERR(gpio); 16656ca9db8SPaul Cercueil 16756ca9db8SPaul Cercueil if (gpio) { 16856ca9db8SPaul Cercueil udelay(1); 16956ca9db8SPaul Cercueil gpiod_set_value(gpio, 1); 17056ca9db8SPaul Cercueil } else { 17156ca9db8SPaul Cercueil mutex_lock(&iio_dev->mlock); 17256ca9db8SPaul Cercueil /* Writing this magic value resets the device */ 17356ca9db8SPaul Cercueil st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac); 17456ca9db8SPaul Cercueil mutex_unlock(&iio_dev->mlock); 17556ca9db8SPaul Cercueil } 17656ca9db8SPaul Cercueil 17756ca9db8SPaul Cercueil udelay(250); 17856ca9db8SPaul Cercueil 17956ca9db8SPaul Cercueil return 0; 18056ca9db8SPaul Cercueil } 18156ca9db8SPaul Cercueil 18256ca9db8SPaul Cercueil static int ad5592r_get_vref(struct ad5592r_state *st) 18356ca9db8SPaul Cercueil { 18456ca9db8SPaul Cercueil int ret; 18556ca9db8SPaul Cercueil 18656ca9db8SPaul Cercueil if (st->reg) { 18756ca9db8SPaul Cercueil ret = regulator_get_voltage(st->reg); 18856ca9db8SPaul Cercueil if (ret < 0) 18956ca9db8SPaul Cercueil return ret; 19056ca9db8SPaul Cercueil 19156ca9db8SPaul Cercueil return ret / 1000; 19256ca9db8SPaul Cercueil } else { 19356ca9db8SPaul Cercueil return 2500; 19456ca9db8SPaul Cercueil } 19556ca9db8SPaul Cercueil } 19656ca9db8SPaul Cercueil 19756ca9db8SPaul Cercueil static int ad5592r_set_channel_modes(struct ad5592r_state *st) 19856ca9db8SPaul Cercueil { 19956ca9db8SPaul Cercueil const struct ad5592r_rw_ops *ops = st->ops; 20056ca9db8SPaul Cercueil int ret; 20156ca9db8SPaul Cercueil unsigned i; 20256ca9db8SPaul Cercueil struct iio_dev *iio_dev = iio_priv_to_dev(st); 20356ca9db8SPaul Cercueil u8 pulldown = 0, tristate = 0, dac = 0, adc = 0; 20456ca9db8SPaul Cercueil u16 read_back; 20556ca9db8SPaul Cercueil 20656ca9db8SPaul Cercueil for (i = 0; i < st->num_channels; i++) { 20756ca9db8SPaul Cercueil switch (st->channel_modes[i]) { 20856ca9db8SPaul Cercueil case CH_MODE_DAC: 20956ca9db8SPaul Cercueil dac |= BIT(i); 21056ca9db8SPaul Cercueil break; 21156ca9db8SPaul Cercueil 21256ca9db8SPaul Cercueil case CH_MODE_ADC: 21356ca9db8SPaul Cercueil adc |= BIT(i); 21456ca9db8SPaul Cercueil break; 21556ca9db8SPaul Cercueil 21656ca9db8SPaul Cercueil case CH_MODE_DAC_AND_ADC: 21756ca9db8SPaul Cercueil dac |= BIT(i); 21856ca9db8SPaul Cercueil adc |= BIT(i); 21956ca9db8SPaul Cercueil break; 22056ca9db8SPaul Cercueil 22156ca9db8SPaul Cercueil case CH_MODE_GPIO: 22256ca9db8SPaul Cercueil st->gpio_map |= BIT(i); 22356ca9db8SPaul Cercueil st->gpio_in |= BIT(i); /* Default to input */ 22456ca9db8SPaul Cercueil break; 22556ca9db8SPaul Cercueil 22656ca9db8SPaul Cercueil case CH_MODE_UNUSED: 22756ca9db8SPaul Cercueil /* fall-through */ 22856ca9db8SPaul Cercueil default: 22956ca9db8SPaul Cercueil switch (st->channel_offstate[i]) { 23056ca9db8SPaul Cercueil case CH_OFFSTATE_OUT_TRISTATE: 23156ca9db8SPaul Cercueil tristate |= BIT(i); 23256ca9db8SPaul Cercueil break; 23356ca9db8SPaul Cercueil 23456ca9db8SPaul Cercueil case CH_OFFSTATE_OUT_LOW: 23556ca9db8SPaul Cercueil st->gpio_out |= BIT(i); 23656ca9db8SPaul Cercueil break; 23756ca9db8SPaul Cercueil 23856ca9db8SPaul Cercueil case CH_OFFSTATE_OUT_HIGH: 23956ca9db8SPaul Cercueil st->gpio_out |= BIT(i); 24056ca9db8SPaul Cercueil st->gpio_val |= BIT(i); 24156ca9db8SPaul Cercueil break; 24256ca9db8SPaul Cercueil 24356ca9db8SPaul Cercueil case CH_OFFSTATE_PULLDOWN: 24456ca9db8SPaul Cercueil /* fall-through */ 24556ca9db8SPaul Cercueil default: 24656ca9db8SPaul Cercueil pulldown |= BIT(i); 24756ca9db8SPaul Cercueil break; 24856ca9db8SPaul Cercueil } 24956ca9db8SPaul Cercueil } 25056ca9db8SPaul Cercueil } 25156ca9db8SPaul Cercueil 25256ca9db8SPaul Cercueil mutex_lock(&iio_dev->mlock); 25356ca9db8SPaul Cercueil 25456ca9db8SPaul Cercueil /* Pull down unused pins to GND */ 25556ca9db8SPaul Cercueil ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown); 25656ca9db8SPaul Cercueil if (ret) 25756ca9db8SPaul Cercueil goto err_unlock; 25856ca9db8SPaul Cercueil 25956ca9db8SPaul Cercueil ret = ops->reg_write(st, AD5592R_REG_TRISTATE, tristate); 26056ca9db8SPaul Cercueil if (ret) 26156ca9db8SPaul Cercueil goto err_unlock; 26256ca9db8SPaul Cercueil 26356ca9db8SPaul Cercueil /* Configure pins that we use */ 26456ca9db8SPaul Cercueil ret = ops->reg_write(st, AD5592R_REG_DAC_EN, dac); 26556ca9db8SPaul Cercueil if (ret) 26656ca9db8SPaul Cercueil goto err_unlock; 26756ca9db8SPaul Cercueil 26856ca9db8SPaul Cercueil ret = ops->reg_write(st, AD5592R_REG_ADC_EN, adc); 26956ca9db8SPaul Cercueil if (ret) 27056ca9db8SPaul Cercueil goto err_unlock; 27156ca9db8SPaul Cercueil 27256ca9db8SPaul Cercueil ret = ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); 27356ca9db8SPaul Cercueil if (ret) 27456ca9db8SPaul Cercueil goto err_unlock; 27556ca9db8SPaul Cercueil 27656ca9db8SPaul Cercueil ret = ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); 27756ca9db8SPaul Cercueil if (ret) 27856ca9db8SPaul Cercueil goto err_unlock; 27956ca9db8SPaul Cercueil 28056ca9db8SPaul Cercueil ret = ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); 28156ca9db8SPaul Cercueil if (ret) 28256ca9db8SPaul Cercueil goto err_unlock; 28356ca9db8SPaul Cercueil 28456ca9db8SPaul Cercueil /* Verify that we can read back at least one register */ 28556ca9db8SPaul Cercueil ret = ops->reg_read(st, AD5592R_REG_ADC_EN, &read_back); 28656ca9db8SPaul Cercueil if (!ret && (read_back & 0xff) != adc) 28756ca9db8SPaul Cercueil ret = -EIO; 28856ca9db8SPaul Cercueil 28956ca9db8SPaul Cercueil err_unlock: 29056ca9db8SPaul Cercueil mutex_unlock(&iio_dev->mlock); 29156ca9db8SPaul Cercueil return ret; 29256ca9db8SPaul Cercueil } 29356ca9db8SPaul Cercueil 29456ca9db8SPaul Cercueil static int ad5592r_reset_channel_modes(struct ad5592r_state *st) 29556ca9db8SPaul Cercueil { 29656ca9db8SPaul Cercueil int i; 29756ca9db8SPaul Cercueil 29856ca9db8SPaul Cercueil for (i = 0; i < ARRAY_SIZE(st->channel_modes); i++) 29956ca9db8SPaul Cercueil st->channel_modes[i] = CH_MODE_UNUSED; 30056ca9db8SPaul Cercueil 30156ca9db8SPaul Cercueil return ad5592r_set_channel_modes(st); 30256ca9db8SPaul Cercueil } 30356ca9db8SPaul Cercueil 30456ca9db8SPaul Cercueil static int ad5592r_write_raw(struct iio_dev *iio_dev, 30556ca9db8SPaul Cercueil struct iio_chan_spec const *chan, int val, int val2, long mask) 30656ca9db8SPaul Cercueil { 30756ca9db8SPaul Cercueil struct ad5592r_state *st = iio_priv(iio_dev); 30856ca9db8SPaul Cercueil int ret; 30956ca9db8SPaul Cercueil 31056ca9db8SPaul Cercueil switch (mask) { 31156ca9db8SPaul Cercueil case IIO_CHAN_INFO_RAW: 31256ca9db8SPaul Cercueil 31356ca9db8SPaul Cercueil if (val >= (1 << chan->scan_type.realbits) || val < 0) 31456ca9db8SPaul Cercueil return -EINVAL; 31556ca9db8SPaul Cercueil 31656ca9db8SPaul Cercueil if (!chan->output) 31756ca9db8SPaul Cercueil return -EINVAL; 31856ca9db8SPaul Cercueil 31956ca9db8SPaul Cercueil mutex_lock(&iio_dev->mlock); 32056ca9db8SPaul Cercueil ret = st->ops->write_dac(st, chan->channel, val); 32156ca9db8SPaul Cercueil if (!ret) 32256ca9db8SPaul Cercueil st->cached_dac[chan->channel] = val; 32356ca9db8SPaul Cercueil mutex_unlock(&iio_dev->mlock); 32456ca9db8SPaul Cercueil return ret; 32556ca9db8SPaul Cercueil case IIO_CHAN_INFO_SCALE: 32656ca9db8SPaul Cercueil if (chan->type == IIO_VOLTAGE) { 32756ca9db8SPaul Cercueil bool gain; 32856ca9db8SPaul Cercueil 32956ca9db8SPaul Cercueil if (val == st->scale_avail[0][0] && 33056ca9db8SPaul Cercueil val2 == st->scale_avail[0][1]) 33156ca9db8SPaul Cercueil gain = false; 33256ca9db8SPaul Cercueil else if (val == st->scale_avail[1][0] && 33356ca9db8SPaul Cercueil val2 == st->scale_avail[1][1]) 33456ca9db8SPaul Cercueil gain = true; 33556ca9db8SPaul Cercueil else 33656ca9db8SPaul Cercueil return -EINVAL; 33756ca9db8SPaul Cercueil 33856ca9db8SPaul Cercueil mutex_lock(&iio_dev->mlock); 33956ca9db8SPaul Cercueil 34056ca9db8SPaul Cercueil ret = st->ops->reg_read(st, AD5592R_REG_CTRL, 34156ca9db8SPaul Cercueil &st->cached_gp_ctrl); 34256ca9db8SPaul Cercueil if (ret < 0) { 34356ca9db8SPaul Cercueil mutex_unlock(&iio_dev->mlock); 34456ca9db8SPaul Cercueil return ret; 34556ca9db8SPaul Cercueil } 34656ca9db8SPaul Cercueil 34756ca9db8SPaul Cercueil if (chan->output) { 34856ca9db8SPaul Cercueil if (gain) 34956ca9db8SPaul Cercueil st->cached_gp_ctrl |= 35056ca9db8SPaul Cercueil AD5592R_REG_CTRL_DAC_RANGE; 35156ca9db8SPaul Cercueil else 35256ca9db8SPaul Cercueil st->cached_gp_ctrl &= 35356ca9db8SPaul Cercueil ~AD5592R_REG_CTRL_DAC_RANGE; 35456ca9db8SPaul Cercueil } else { 35556ca9db8SPaul Cercueil if (gain) 35656ca9db8SPaul Cercueil st->cached_gp_ctrl |= 35756ca9db8SPaul Cercueil AD5592R_REG_CTRL_ADC_RANGE; 35856ca9db8SPaul Cercueil else 35956ca9db8SPaul Cercueil st->cached_gp_ctrl &= 36056ca9db8SPaul Cercueil ~AD5592R_REG_CTRL_ADC_RANGE; 36156ca9db8SPaul Cercueil } 36256ca9db8SPaul Cercueil 36356ca9db8SPaul Cercueil ret = st->ops->reg_write(st, AD5592R_REG_CTRL, 36456ca9db8SPaul Cercueil st->cached_gp_ctrl); 36556ca9db8SPaul Cercueil mutex_unlock(&iio_dev->mlock); 36656ca9db8SPaul Cercueil 36756ca9db8SPaul Cercueil return ret; 36856ca9db8SPaul Cercueil } 36956ca9db8SPaul Cercueil break; 37056ca9db8SPaul Cercueil default: 37156ca9db8SPaul Cercueil return -EINVAL; 37256ca9db8SPaul Cercueil } 37356ca9db8SPaul Cercueil 37456ca9db8SPaul Cercueil return 0; 37556ca9db8SPaul Cercueil } 37656ca9db8SPaul Cercueil 37756ca9db8SPaul Cercueil static int ad5592r_read_raw(struct iio_dev *iio_dev, 37856ca9db8SPaul Cercueil struct iio_chan_spec const *chan, 37956ca9db8SPaul Cercueil int *val, int *val2, long m) 38056ca9db8SPaul Cercueil { 38156ca9db8SPaul Cercueil struct ad5592r_state *st = iio_priv(iio_dev); 38256ca9db8SPaul Cercueil u16 read_val; 38356ca9db8SPaul Cercueil int ret; 38456ca9db8SPaul Cercueil 38556ca9db8SPaul Cercueil switch (m) { 38656ca9db8SPaul Cercueil case IIO_CHAN_INFO_RAW: 38756ca9db8SPaul Cercueil mutex_lock(&iio_dev->mlock); 38856ca9db8SPaul Cercueil 38956ca9db8SPaul Cercueil if (!chan->output) { 39056ca9db8SPaul Cercueil ret = st->ops->read_adc(st, chan->channel, &read_val); 39156ca9db8SPaul Cercueil if (ret) 39256ca9db8SPaul Cercueil goto unlock; 39356ca9db8SPaul Cercueil 39456ca9db8SPaul Cercueil if ((read_val >> 12 & 0x7) != (chan->channel & 0x7)) { 39556ca9db8SPaul Cercueil dev_err(st->dev, "Error while reading channel %u\n", 39656ca9db8SPaul Cercueil chan->channel); 39756ca9db8SPaul Cercueil ret = -EIO; 39856ca9db8SPaul Cercueil goto unlock; 39956ca9db8SPaul Cercueil } 40056ca9db8SPaul Cercueil 40156ca9db8SPaul Cercueil read_val &= GENMASK(11, 0); 40256ca9db8SPaul Cercueil 40356ca9db8SPaul Cercueil } else { 40456ca9db8SPaul Cercueil read_val = st->cached_dac[chan->channel]; 40556ca9db8SPaul Cercueil } 40656ca9db8SPaul Cercueil 40756ca9db8SPaul Cercueil dev_dbg(st->dev, "Channel %u read: 0x%04hX\n", 40856ca9db8SPaul Cercueil chan->channel, read_val); 40956ca9db8SPaul Cercueil 41056ca9db8SPaul Cercueil *val = (int) read_val; 41156ca9db8SPaul Cercueil ret = IIO_VAL_INT; 41256ca9db8SPaul Cercueil break; 41356ca9db8SPaul Cercueil case IIO_CHAN_INFO_SCALE: 41456ca9db8SPaul Cercueil *val = ad5592r_get_vref(st); 41556ca9db8SPaul Cercueil 41656ca9db8SPaul Cercueil if (chan->type == IIO_TEMP) { 41756ca9db8SPaul Cercueil s64 tmp = *val * (3767897513LL / 25LL); 41856ca9db8SPaul Cercueil *val = div_s64_rem(tmp, 1000000000LL, val2); 41956ca9db8SPaul Cercueil 42056ca9db8SPaul Cercueil ret = IIO_VAL_INT_PLUS_MICRO; 42156ca9db8SPaul Cercueil } else { 42256ca9db8SPaul Cercueil int mult; 42356ca9db8SPaul Cercueil 42456ca9db8SPaul Cercueil mutex_lock(&iio_dev->mlock); 42556ca9db8SPaul Cercueil 42656ca9db8SPaul Cercueil if (chan->output) 42756ca9db8SPaul Cercueil mult = !!(st->cached_gp_ctrl & 42856ca9db8SPaul Cercueil AD5592R_REG_CTRL_DAC_RANGE); 42956ca9db8SPaul Cercueil else 43056ca9db8SPaul Cercueil mult = !!(st->cached_gp_ctrl & 43156ca9db8SPaul Cercueil AD5592R_REG_CTRL_ADC_RANGE); 43256ca9db8SPaul Cercueil 43356ca9db8SPaul Cercueil *val *= ++mult; 43456ca9db8SPaul Cercueil 43556ca9db8SPaul Cercueil *val2 = chan->scan_type.realbits; 43656ca9db8SPaul Cercueil ret = IIO_VAL_FRACTIONAL_LOG2; 43756ca9db8SPaul Cercueil } 43856ca9db8SPaul Cercueil break; 43956ca9db8SPaul Cercueil case IIO_CHAN_INFO_OFFSET: 44056ca9db8SPaul Cercueil ret = ad5592r_get_vref(st); 44156ca9db8SPaul Cercueil 44256ca9db8SPaul Cercueil mutex_lock(&iio_dev->mlock); 44356ca9db8SPaul Cercueil 44456ca9db8SPaul Cercueil if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE) 44556ca9db8SPaul Cercueil *val = (-34365 * 25) / ret; 44656ca9db8SPaul Cercueil else 44756ca9db8SPaul Cercueil *val = (-75365 * 25) / ret; 44856ca9db8SPaul Cercueil ret = IIO_VAL_INT; 44956ca9db8SPaul Cercueil break; 45056ca9db8SPaul Cercueil default: 45156ca9db8SPaul Cercueil ret = -EINVAL; 45256ca9db8SPaul Cercueil } 45356ca9db8SPaul Cercueil 45456ca9db8SPaul Cercueil unlock: 45556ca9db8SPaul Cercueil mutex_unlock(&iio_dev->mlock); 45656ca9db8SPaul Cercueil return ret; 45756ca9db8SPaul Cercueil } 45856ca9db8SPaul Cercueil 45956ca9db8SPaul Cercueil static int ad5592r_write_raw_get_fmt(struct iio_dev *indio_dev, 46056ca9db8SPaul Cercueil struct iio_chan_spec const *chan, long mask) 46156ca9db8SPaul Cercueil { 46256ca9db8SPaul Cercueil switch (mask) { 46356ca9db8SPaul Cercueil case IIO_CHAN_INFO_SCALE: 46456ca9db8SPaul Cercueil return IIO_VAL_INT_PLUS_NANO; 46556ca9db8SPaul Cercueil 46656ca9db8SPaul Cercueil default: 46756ca9db8SPaul Cercueil return IIO_VAL_INT_PLUS_MICRO; 46856ca9db8SPaul Cercueil } 46956ca9db8SPaul Cercueil 47056ca9db8SPaul Cercueil return -EINVAL; 47156ca9db8SPaul Cercueil } 47256ca9db8SPaul Cercueil 47356ca9db8SPaul Cercueil static const struct iio_info ad5592r_info = { 47456ca9db8SPaul Cercueil .read_raw = ad5592r_read_raw, 47556ca9db8SPaul Cercueil .write_raw = ad5592r_write_raw, 47656ca9db8SPaul Cercueil .write_raw_get_fmt = ad5592r_write_raw_get_fmt, 47756ca9db8SPaul Cercueil .driver_module = THIS_MODULE, 47856ca9db8SPaul Cercueil }; 47956ca9db8SPaul Cercueil 48056ca9db8SPaul Cercueil static ssize_t ad5592r_show_scale_available(struct iio_dev *iio_dev, 48156ca9db8SPaul Cercueil uintptr_t private, 48256ca9db8SPaul Cercueil const struct iio_chan_spec *chan, 48356ca9db8SPaul Cercueil char *buf) 48456ca9db8SPaul Cercueil { 48556ca9db8SPaul Cercueil struct ad5592r_state *st = iio_priv(iio_dev); 48656ca9db8SPaul Cercueil 48756ca9db8SPaul Cercueil return sprintf(buf, "%d.%09u %d.%09u\n", 48856ca9db8SPaul Cercueil st->scale_avail[0][0], st->scale_avail[0][1], 48956ca9db8SPaul Cercueil st->scale_avail[1][0], st->scale_avail[1][1]); 49056ca9db8SPaul Cercueil } 49156ca9db8SPaul Cercueil 49256ca9db8SPaul Cercueil static struct iio_chan_spec_ext_info ad5592r_ext_info[] = { 49356ca9db8SPaul Cercueil { 49456ca9db8SPaul Cercueil .name = "scale_available", 49556ca9db8SPaul Cercueil .read = ad5592r_show_scale_available, 49656ca9db8SPaul Cercueil .shared = true, 49756ca9db8SPaul Cercueil }, 49856ca9db8SPaul Cercueil {}, 49956ca9db8SPaul Cercueil }; 50056ca9db8SPaul Cercueil 50156ca9db8SPaul Cercueil static void ad5592r_setup_channel(struct iio_dev *iio_dev, 50256ca9db8SPaul Cercueil struct iio_chan_spec *chan, bool output, unsigned id) 50356ca9db8SPaul Cercueil { 50456ca9db8SPaul Cercueil chan->type = IIO_VOLTAGE; 50556ca9db8SPaul Cercueil chan->indexed = 1; 50656ca9db8SPaul Cercueil chan->output = output; 50756ca9db8SPaul Cercueil chan->channel = id; 50856ca9db8SPaul Cercueil chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); 50956ca9db8SPaul Cercueil chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); 51056ca9db8SPaul Cercueil chan->scan_type.sign = 'u'; 51156ca9db8SPaul Cercueil chan->scan_type.realbits = 12; 51256ca9db8SPaul Cercueil chan->scan_type.storagebits = 16; 51356ca9db8SPaul Cercueil chan->ext_info = ad5592r_ext_info; 51456ca9db8SPaul Cercueil } 51556ca9db8SPaul Cercueil 51656ca9db8SPaul Cercueil static int ad5592r_alloc_channels(struct ad5592r_state *st) 51756ca9db8SPaul Cercueil { 51856ca9db8SPaul Cercueil unsigned i, curr_channel = 0, 51956ca9db8SPaul Cercueil num_channels = st->num_channels; 52056ca9db8SPaul Cercueil struct iio_dev *iio_dev = iio_priv_to_dev(st); 52156ca9db8SPaul Cercueil struct iio_chan_spec *channels; 52256ca9db8SPaul Cercueil struct fwnode_handle *child; 52356ca9db8SPaul Cercueil u32 reg, tmp; 52456ca9db8SPaul Cercueil int ret; 52556ca9db8SPaul Cercueil 52656ca9db8SPaul Cercueil device_for_each_child_node(st->dev, child) { 52756ca9db8SPaul Cercueil ret = fwnode_property_read_u32(child, "reg", ®); 52856ca9db8SPaul Cercueil if (ret || reg > ARRAY_SIZE(st->channel_modes)) 52956ca9db8SPaul Cercueil continue; 53056ca9db8SPaul Cercueil 53156ca9db8SPaul Cercueil ret = fwnode_property_read_u32(child, "adi,mode", &tmp); 53256ca9db8SPaul Cercueil if (!ret) 53356ca9db8SPaul Cercueil st->channel_modes[reg] = tmp; 53456ca9db8SPaul Cercueil 53556ca9db8SPaul Cercueil fwnode_property_read_u32(child, "adi,off-state", &tmp); 53656ca9db8SPaul Cercueil if (!ret) 53756ca9db8SPaul Cercueil st->channel_offstate[reg] = tmp; 53856ca9db8SPaul Cercueil } 53956ca9db8SPaul Cercueil 54056ca9db8SPaul Cercueil channels = devm_kzalloc(st->dev, 54156ca9db8SPaul Cercueil (1 + 2 * num_channels) * sizeof(*channels), GFP_KERNEL); 54256ca9db8SPaul Cercueil if (!channels) 54356ca9db8SPaul Cercueil return -ENOMEM; 54456ca9db8SPaul Cercueil 54556ca9db8SPaul Cercueil for (i = 0; i < num_channels; i++) { 54656ca9db8SPaul Cercueil switch (st->channel_modes[i]) { 54756ca9db8SPaul Cercueil case CH_MODE_DAC: 54856ca9db8SPaul Cercueil ad5592r_setup_channel(iio_dev, &channels[curr_channel], 54956ca9db8SPaul Cercueil true, i); 55056ca9db8SPaul Cercueil curr_channel++; 55156ca9db8SPaul Cercueil break; 55256ca9db8SPaul Cercueil 55356ca9db8SPaul Cercueil case CH_MODE_ADC: 55456ca9db8SPaul Cercueil ad5592r_setup_channel(iio_dev, &channels[curr_channel], 55556ca9db8SPaul Cercueil false, i); 55656ca9db8SPaul Cercueil curr_channel++; 55756ca9db8SPaul Cercueil break; 55856ca9db8SPaul Cercueil 55956ca9db8SPaul Cercueil case CH_MODE_DAC_AND_ADC: 56056ca9db8SPaul Cercueil ad5592r_setup_channel(iio_dev, &channels[curr_channel], 56156ca9db8SPaul Cercueil true, i); 56256ca9db8SPaul Cercueil curr_channel++; 56356ca9db8SPaul Cercueil ad5592r_setup_channel(iio_dev, &channels[curr_channel], 56456ca9db8SPaul Cercueil false, i); 56556ca9db8SPaul Cercueil curr_channel++; 56656ca9db8SPaul Cercueil break; 56756ca9db8SPaul Cercueil 56856ca9db8SPaul Cercueil default: 56956ca9db8SPaul Cercueil continue; 57056ca9db8SPaul Cercueil } 57156ca9db8SPaul Cercueil } 57256ca9db8SPaul Cercueil 57356ca9db8SPaul Cercueil channels[curr_channel].type = IIO_TEMP; 57456ca9db8SPaul Cercueil channels[curr_channel].channel = 8; 57556ca9db8SPaul Cercueil channels[curr_channel].info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 57656ca9db8SPaul Cercueil BIT(IIO_CHAN_INFO_SCALE) | 57756ca9db8SPaul Cercueil BIT(IIO_CHAN_INFO_OFFSET); 57856ca9db8SPaul Cercueil curr_channel++; 57956ca9db8SPaul Cercueil 58056ca9db8SPaul Cercueil iio_dev->num_channels = curr_channel; 58156ca9db8SPaul Cercueil iio_dev->channels = channels; 58256ca9db8SPaul Cercueil 58356ca9db8SPaul Cercueil return 0; 58456ca9db8SPaul Cercueil } 58556ca9db8SPaul Cercueil 58656ca9db8SPaul Cercueil static void ad5592r_init_scales(struct ad5592r_state *st, int vref_mV) 58756ca9db8SPaul Cercueil { 58856ca9db8SPaul Cercueil s64 tmp = (s64)vref_mV * 1000000000LL >> 12; 58956ca9db8SPaul Cercueil 59056ca9db8SPaul Cercueil st->scale_avail[0][0] = 59156ca9db8SPaul Cercueil div_s64_rem(tmp, 1000000000LL, &st->scale_avail[0][1]); 59256ca9db8SPaul Cercueil st->scale_avail[1][0] = 59356ca9db8SPaul Cercueil div_s64_rem(tmp * 2, 1000000000LL, &st->scale_avail[1][1]); 59456ca9db8SPaul Cercueil } 59556ca9db8SPaul Cercueil 59656ca9db8SPaul Cercueil int ad5592r_probe(struct device *dev, const char *name, 59756ca9db8SPaul Cercueil const struct ad5592r_rw_ops *ops) 59856ca9db8SPaul Cercueil { 59956ca9db8SPaul Cercueil struct iio_dev *iio_dev; 60056ca9db8SPaul Cercueil struct ad5592r_state *st; 60156ca9db8SPaul Cercueil int ret; 60256ca9db8SPaul Cercueil 60356ca9db8SPaul Cercueil iio_dev = devm_iio_device_alloc(dev, sizeof(*st)); 60456ca9db8SPaul Cercueil if (!iio_dev) 60556ca9db8SPaul Cercueil return -ENOMEM; 60656ca9db8SPaul Cercueil 60756ca9db8SPaul Cercueil st = iio_priv(iio_dev); 60856ca9db8SPaul Cercueil st->dev = dev; 60956ca9db8SPaul Cercueil st->ops = ops; 61056ca9db8SPaul Cercueil st->num_channels = 8; 61156ca9db8SPaul Cercueil dev_set_drvdata(dev, iio_dev); 61256ca9db8SPaul Cercueil 61356ca9db8SPaul Cercueil st->reg = devm_regulator_get_optional(dev, "vref"); 61456ca9db8SPaul Cercueil if (IS_ERR(st->reg)) { 61556ca9db8SPaul Cercueil if ((PTR_ERR(st->reg) != -ENODEV) && dev->of_node) 61656ca9db8SPaul Cercueil return PTR_ERR(st->reg); 61756ca9db8SPaul Cercueil 61856ca9db8SPaul Cercueil st->reg = NULL; 61956ca9db8SPaul Cercueil } else { 62056ca9db8SPaul Cercueil ret = regulator_enable(st->reg); 62156ca9db8SPaul Cercueil if (ret) 62256ca9db8SPaul Cercueil return ret; 62356ca9db8SPaul Cercueil } 62456ca9db8SPaul Cercueil 62556ca9db8SPaul Cercueil iio_dev->dev.parent = dev; 62656ca9db8SPaul Cercueil iio_dev->name = name; 62756ca9db8SPaul Cercueil iio_dev->info = &ad5592r_info; 62856ca9db8SPaul Cercueil iio_dev->modes = INDIO_DIRECT_MODE; 62956ca9db8SPaul Cercueil 63056ca9db8SPaul Cercueil ad5592r_init_scales(st, ad5592r_get_vref(st)); 63156ca9db8SPaul Cercueil 63256ca9db8SPaul Cercueil ret = ad5592r_reset(st); 63356ca9db8SPaul Cercueil if (ret) 63456ca9db8SPaul Cercueil goto error_disable_reg; 63556ca9db8SPaul Cercueil 63656ca9db8SPaul Cercueil ret = ops->reg_write(st, AD5592R_REG_PD, 63756ca9db8SPaul Cercueil (st->reg == NULL) ? AD5592R_REG_PD_EN_REF : 0); 63856ca9db8SPaul Cercueil if (ret) 63956ca9db8SPaul Cercueil goto error_disable_reg; 64056ca9db8SPaul Cercueil 64156ca9db8SPaul Cercueil ret = ad5592r_alloc_channels(st); 64256ca9db8SPaul Cercueil if (ret) 64356ca9db8SPaul Cercueil goto error_disable_reg; 64456ca9db8SPaul Cercueil 64556ca9db8SPaul Cercueil ret = ad5592r_set_channel_modes(st); 64656ca9db8SPaul Cercueil if (ret) 64756ca9db8SPaul Cercueil goto error_reset_ch_modes; 64856ca9db8SPaul Cercueil 64956ca9db8SPaul Cercueil ret = iio_device_register(iio_dev); 65056ca9db8SPaul Cercueil if (ret) 65156ca9db8SPaul Cercueil goto error_reset_ch_modes; 65256ca9db8SPaul Cercueil 65356ca9db8SPaul Cercueil ret = ad5592r_gpio_init(st); 65456ca9db8SPaul Cercueil if (ret) 65556ca9db8SPaul Cercueil goto error_dev_unregister; 65656ca9db8SPaul Cercueil 65756ca9db8SPaul Cercueil return 0; 65856ca9db8SPaul Cercueil 65956ca9db8SPaul Cercueil error_dev_unregister: 66056ca9db8SPaul Cercueil iio_device_unregister(iio_dev); 66156ca9db8SPaul Cercueil 66256ca9db8SPaul Cercueil error_reset_ch_modes: 66356ca9db8SPaul Cercueil ad5592r_reset_channel_modes(st); 66456ca9db8SPaul Cercueil 66556ca9db8SPaul Cercueil error_disable_reg: 66656ca9db8SPaul Cercueil if (st->reg) 66756ca9db8SPaul Cercueil regulator_disable(st->reg); 66856ca9db8SPaul Cercueil 66956ca9db8SPaul Cercueil return ret; 67056ca9db8SPaul Cercueil } 67156ca9db8SPaul Cercueil EXPORT_SYMBOL_GPL(ad5592r_probe); 67256ca9db8SPaul Cercueil 67356ca9db8SPaul Cercueil int ad5592r_remove(struct device *dev) 67456ca9db8SPaul Cercueil { 67556ca9db8SPaul Cercueil struct iio_dev *iio_dev = dev_get_drvdata(dev); 67656ca9db8SPaul Cercueil struct ad5592r_state *st = iio_priv(iio_dev); 67756ca9db8SPaul Cercueil 67856ca9db8SPaul Cercueil iio_device_unregister(iio_dev); 67956ca9db8SPaul Cercueil ad5592r_reset_channel_modes(st); 68056ca9db8SPaul Cercueil ad5592r_gpio_cleanup(st); 68156ca9db8SPaul Cercueil 68256ca9db8SPaul Cercueil if (st->reg) 68356ca9db8SPaul Cercueil regulator_disable(st->reg); 68456ca9db8SPaul Cercueil 68556ca9db8SPaul Cercueil return 0; 68656ca9db8SPaul Cercueil } 68756ca9db8SPaul Cercueil EXPORT_SYMBOL_GPL(ad5592r_remove); 68856ca9db8SPaul Cercueil 68956ca9db8SPaul Cercueil MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>"); 69056ca9db8SPaul Cercueil MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters"); 69156ca9db8SPaul Cercueil MODULE_LICENSE("GPL v2"); 692