Commit c7301b84 authored by William Breathitt Gray's avatar William Breathitt Gray Committed by Jonathan Cameron

iio: addac: stx104: Migrate to the regmap API

The regmap API supports IO port accessors so we can take advantage of
regmap abstractions rather than handling access to the device registers
directly in the driver.

In addition, to improve code organization in stx104_probe(), the
devm_iio_device_register() call is moved above GPIO configuration in
order to keep relevant code closer together.
Suggested-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: default avatarWilliam Breathitt Gray <william.gray@linaro.org>
Link: https://lore.kernel.org/r/0bcdfc4738cc019fb2ff83f61eb46a3488bc166d.1680790580.git.william.gray@linaro.orgSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent a94abc74
...@@ -35,7 +35,9 @@ config STX104 ...@@ -35,7 +35,9 @@ config STX104
tristate "Apex Embedded Systems STX104 driver" tristate "Apex Embedded Systems STX104 driver"
depends on PC104 && X86 depends on PC104 && X86
select ISA_BUS_API select ISA_BUS_API
select REGMAP_MMIO
select GPIOLIB select GPIOLIB
select GPIO_REGMAP
help help
Say yes here to build support for the Apex Embedded Systems STX104 Say yes here to build support for the Apex Embedded Systems STX104
integrated analog PC/104 card. integrated analog PC/104 card.
......
...@@ -3,21 +3,20 @@ ...@@ -3,21 +3,20 @@
* IIO driver for the Apex Embedded Systems STX104 * IIO driver for the Apex Embedded Systems STX104
* Copyright (C) 2016 William Breathitt Gray * Copyright (C) 2016 William Breathitt Gray
*/ */
#include <linux/bitfield.h>
#include <linux/bits.h> #include <linux/bits.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/errno.h> #include <linux/err.h>
#include <linux/gpio/driver.h> #include <linux/gpio/regmap.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/types.h> #include <linux/iio/types.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/isa.h> #include <linux/isa.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/spinlock.h> #include <linux/regmap.h>
#include <linux/types.h> #include <linux/types.h>
#define STX104_OUT_CHAN(chan) { \ #define STX104_OUT_CHAN(chan) { \
...@@ -47,107 +46,207 @@ static unsigned int num_stx104; ...@@ -47,107 +46,207 @@ static unsigned int num_stx104;
module_param_hw_array(base, uint, ioport, &num_stx104, 0); module_param_hw_array(base, uint, ioport, &num_stx104, 0);
MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
/** #define STX104_AIO_BASE 0x0
* struct stx104_reg - device register structure #define STX104_SOFTWARE_STROBE STX104_AIO_BASE
* @ssr_ad: Software Strobe Register and ADC Data #define STX104_ADC_DATA STX104_AIO_BASE
* @achan: ADC Channel #define STX104_ADC_CHANNEL (STX104_AIO_BASE + 0x2)
* @dio: Digital I/O #define STX104_DIO_REG (STX104_AIO_BASE + 0x3)
* @dac: DAC Channels #define STX104_DAC_BASE (STX104_AIO_BASE + 0x4)
* @cir_asr: Clear Interrupts and ADC Status #define STX104_ADC_STATUS (STX104_AIO_BASE + 0x8)
* @acr: ADC Control #define STX104_ADC_CONTROL (STX104_AIO_BASE + 0x9)
* @pccr_fsh: Pacer Clock Control and FIFO Status MSB #define STX104_ADC_CONFIGURATION (STX104_AIO_BASE + 0x11)
* @acfg: ADC Configuration
*/ #define STX104_AIO_DATA_STRIDE 2
struct stx104_reg { #define STX104_DAC_OFFSET(_channel) (STX104_DAC_BASE + STX104_AIO_DATA_STRIDE * (_channel))
u16 ssr_ad;
u8 achan; /* ADC Channel */
u8 dio; #define STX104_FC GENMASK(3, 0)
u16 dac[2]; #define STX104_LC GENMASK(7, 4)
u8 cir_asr; #define STX104_SINGLE_CHANNEL(_channel) \
u8 acr; (u8_encode_bits(_channel, STX104_FC) | u8_encode_bits(_channel, STX104_LC))
u8 pccr_fsh;
u8 acfg; /* ADC Status */
}; #define STX104_SD BIT(5)
#define STX104_CNV BIT(7)
#define STX104_DIFFERENTIAL 1
/* ADC Control */
#define STX104_ALSS GENMASK(1, 0)
#define STX104_SOFTWARE_TRIGGER u8_encode_bits(0x0, STX104_ALSS)
/* ADC Configuration */
#define STX104_GAIN GENMASK(1, 0)
#define STX104_ADBU BIT(2)
#define STX104_BIPOLAR 0
#define STX104_GAIN_X1 0
#define STX104_GAIN_X2 1
#define STX104_GAIN_X4 2
#define STX104_GAIN_X8 3
/** /**
* struct stx104_iio - IIO device private data structure * struct stx104_iio - IIO device private data structure
* @lock: synchronization lock to prevent I/O race conditions * @lock: synchronization lock to prevent I/O race conditions
* @chan_out_states: channels' output states * @aio_data_map: Regmap for analog I/O data
* @reg: I/O address offset for the device registers * @aio_ctl_map: Regmap for analog I/O control
*/ */
struct stx104_iio { struct stx104_iio {
struct mutex lock; struct mutex lock;
unsigned int chan_out_states[STX104_NUM_OUT_CHAN]; struct regmap *aio_data_map;
struct stx104_reg __iomem *reg; struct regmap *aio_ctl_map;
}; };
/** static const struct regmap_range aio_ctl_wr_ranges[] = {
* struct stx104_gpio - GPIO device private data structure regmap_reg_range(0x0, 0x0), regmap_reg_range(0x2, 0x2), regmap_reg_range(0x9, 0x9),
* @chip: instance of the gpio_chip regmap_reg_range(0x11, 0x11),
* @lock: synchronization lock to prevent I/O race conditions };
* @base: base port address of the GPIO device static const struct regmap_range aio_ctl_rd_ranges[] = {
* @out_state: output bits state regmap_reg_range(0x2, 0x2), regmap_reg_range(0x8, 0x9), regmap_reg_range(0x11, 0x11),
*/ };
struct stx104_gpio { static const struct regmap_range aio_ctl_volatile_ranges[] = {
struct gpio_chip chip; regmap_reg_range(0x8, 0x8),
spinlock_t lock; };
u8 __iomem *base; static const struct regmap_access_table aio_ctl_wr_table = {
unsigned int out_state; .yes_ranges = aio_ctl_wr_ranges,
.n_yes_ranges = ARRAY_SIZE(aio_ctl_wr_ranges),
};
static const struct regmap_access_table aio_ctl_rd_table = {
.yes_ranges = aio_ctl_rd_ranges,
.n_yes_ranges = ARRAY_SIZE(aio_ctl_rd_ranges),
};
static const struct regmap_access_table aio_ctl_volatile_table = {
.yes_ranges = aio_ctl_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(aio_ctl_volatile_ranges),
};
static const struct regmap_config aio_ctl_regmap_config = {
.name = "aio_ctl",
.reg_bits = 8,
.reg_stride = 1,
.reg_base = STX104_AIO_BASE,
.val_bits = 8,
.io_port = true,
.wr_table = &aio_ctl_wr_table,
.rd_table = &aio_ctl_rd_table,
.volatile_table = &aio_ctl_volatile_table,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_range aio_data_wr_ranges[] = {
regmap_reg_range(0x4, 0x6),
};
static const struct regmap_range aio_data_rd_ranges[] = {
regmap_reg_range(0x0, 0x0),
};
static const struct regmap_access_table aio_data_wr_table = {
.yes_ranges = aio_data_wr_ranges,
.n_yes_ranges = ARRAY_SIZE(aio_data_wr_ranges),
};
static const struct regmap_access_table aio_data_rd_table = {
.yes_ranges = aio_data_rd_ranges,
.n_yes_ranges = ARRAY_SIZE(aio_data_rd_ranges),
};
static const struct regmap_config aio_data_regmap_config = {
.name = "aio_data",
.reg_bits = 16,
.reg_stride = STX104_AIO_DATA_STRIDE,
.reg_base = STX104_AIO_BASE,
.val_bits = 16,
.io_port = true,
.wr_table = &aio_data_wr_table,
.rd_table = &aio_data_rd_table,
.volatile_table = &aio_data_rd_table,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config dio_regmap_config = {
.name = "dio",
.reg_bits = 8,
.reg_stride = 1,
.reg_base = STX104_DIO_REG,
.val_bits = 8,
.io_port = true,
}; };
static int stx104_read_raw(struct iio_dev *indio_dev, static int stx104_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long mask) struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ {
struct stx104_iio *const priv = iio_priv(indio_dev); struct stx104_iio *const priv = iio_priv(indio_dev);
struct stx104_reg __iomem *const reg = priv->reg; int err;
unsigned int adc_config; unsigned int adc_config;
int adbu; unsigned int value;
int gain; unsigned int adc_status;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_HARDWAREGAIN: case IIO_CHAN_INFO_HARDWAREGAIN:
/* get gain configuration */ err = regmap_read(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, &adc_config);
adc_config = ioread8(&reg->acfg); if (err)
gain = adc_config & 0x3; return err;
*val = 1 << gain; *val = BIT(u8_get_bits(adc_config, STX104_GAIN));
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
if (chan->output) { if (chan->output) {
*val = priv->chan_out_states[chan->channel]; err = regmap_read(priv->aio_data_map, STX104_DAC_OFFSET(chan->channel),
&value);
if (err)
return err;
*val = value;
return IIO_VAL_INT; return IIO_VAL_INT;
} }
mutex_lock(&priv->lock); mutex_lock(&priv->lock);
/* select ADC channel */ /* select ADC channel */
iowrite8(chan->channel | (chan->channel << 4), &reg->achan); err = regmap_write(priv->aio_ctl_map, STX104_ADC_CHANNEL,
STX104_SINGLE_CHANNEL(chan->channel));
if (err) {
mutex_unlock(&priv->lock);
return err;
}
/* trigger ADC sample capture by writing to the 8-bit /* trigger ADC sample capture by writing to the 8-bit
* Software Strobe Register and wait for completion * Software Strobe Register and wait for completion
*/ */
iowrite8(0, &reg->ssr_ad); err = regmap_write(priv->aio_ctl_map, STX104_SOFTWARE_STROBE, 0);
while (ioread8(&reg->cir_asr) & BIT(7)); if (err) {
mutex_unlock(&priv->lock);
return err;
}
do {
err = regmap_read(priv->aio_ctl_map, STX104_ADC_STATUS, &adc_status);
if (err) {
mutex_unlock(&priv->lock);
return err;
}
} while (u8_get_bits(adc_status, STX104_CNV));
*val = ioread16(&reg->ssr_ad); err = regmap_read(priv->aio_data_map, STX104_ADC_DATA, &value);
if (err) {
mutex_unlock(&priv->lock);
return err;
}
*val = value;
mutex_unlock(&priv->lock); mutex_unlock(&priv->lock);
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET: case IIO_CHAN_INFO_OFFSET:
/* get ADC bipolar/unipolar configuration */ /* get ADC bipolar/unipolar configuration */
adc_config = ioread8(&reg->acfg); err = regmap_read(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, &adc_config);
adbu = !(adc_config & BIT(2)); if (err)
return err;
*val = -32768 * adbu; *val = (u8_get_bits(adc_config, STX104_ADBU) == STX104_BIPOLAR) ? -32768 : 0;
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
/* get ADC bipolar/unipolar and gain configuration */ /* get ADC bipolar/unipolar and gain configuration */
adc_config = ioread8(&reg->acfg); err = regmap_read(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, &adc_config);
adbu = !(adc_config & BIT(2)); if (err)
gain = adc_config & 0x3; return err;
*val = 5; *val = 5;
*val2 = 15 - adbu + gain; *val2 = (u8_get_bits(adc_config, STX104_ADBU) == STX104_BIPOLAR) ? 14 : 15;
*val2 += u8_get_bits(adc_config, STX104_GAIN);
return IIO_VAL_FRACTIONAL_LOG2; return IIO_VAL_FRACTIONAL_LOG2;
} }
...@@ -158,28 +257,29 @@ static int stx104_write_raw(struct iio_dev *indio_dev, ...@@ -158,28 +257,29 @@ static int stx104_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long mask) struct iio_chan_spec const *chan, int val, int val2, long mask)
{ {
struct stx104_iio *const priv = iio_priv(indio_dev); struct stx104_iio *const priv = iio_priv(indio_dev);
u8 gain;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_HARDWAREGAIN: case IIO_CHAN_INFO_HARDWAREGAIN:
/* Only four gain states (x1, x2, x4, x8) */ /* Only four gain states (x1, x2, x4, x8) */
switch (val) { switch (val) {
case 1: case 1:
iowrite8(0, &priv->reg->acfg); gain = STX104_GAIN_X1;
break; break;
case 2: case 2:
iowrite8(1, &priv->reg->acfg); gain = STX104_GAIN_X2;
break; break;
case 4: case 4:
iowrite8(2, &priv->reg->acfg); gain = STX104_GAIN_X4;
break; break;
case 8: case 8:
iowrite8(3, &priv->reg->acfg); gain = STX104_GAIN_X8;
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
return 0; return regmap_write(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, gain);
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
if (!chan->output) if (!chan->output)
return -EINVAL; return -EINVAL;
...@@ -187,13 +287,7 @@ static int stx104_write_raw(struct iio_dev *indio_dev, ...@@ -187,13 +287,7 @@ static int stx104_write_raw(struct iio_dev *indio_dev,
if (val < 0 || val > U16_MAX) if (val < 0 || val > U16_MAX)
return -EINVAL; return -EINVAL;
mutex_lock(&priv->lock); return regmap_write(priv->aio_data_map, STX104_DAC_OFFSET(chan->channel), val);
priv->chan_out_states[chan->channel] = val;
iowrite16(val, &priv->reg->dac[chan->channel]);
mutex_unlock(&priv->lock);
return 0;
} }
return -EINVAL; return -EINVAL;
...@@ -222,119 +316,66 @@ static const struct iio_chan_spec stx104_channels_diff[] = { ...@@ -222,119 +316,66 @@ static const struct iio_chan_spec stx104_channels_diff[] = {
STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1) STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1)
}; };
static int stx104_gpio_get_direction(struct gpio_chip *chip, static int stx104_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base,
unsigned int offset) unsigned int offset, unsigned int *const reg,
unsigned int *const mask)
{ {
/* GPIO 0-3 are input only, while the rest are output only */ /* Output lines are located at same register bit offsets as input lines */
if (offset < 4)
return 1;
return 0;
}
static int stx104_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
if (offset >= 4)
return -EINVAL;
return 0;
}
static int stx104_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
if (offset < 4)
return -EINVAL;
chip->set(chip, offset, value);
return 0;
}
static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
if (offset >= 4) if (offset >= 4)
return -EINVAL; offset -= 4;
return !!(ioread8(stx104gpio->base) & BIT(offset));
}
static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
unsigned long *bits)
{
struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
*bits = ioread8(stx104gpio->base); *reg = base;
*mask = BIT(offset);
return 0; return 0;
} }
static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
const unsigned int mask = BIT(offset) >> 4;
unsigned long flags;
if (offset < 4)
return;
spin_lock_irqsave(&stx104gpio->lock, flags);
if (value)
stx104gpio->out_state |= mask;
else
stx104gpio->out_state &= ~mask;
iowrite8(stx104gpio->out_state, stx104gpio->base);
spin_unlock_irqrestore(&stx104gpio->lock, flags);
}
#define STX104_NGPIO 8 #define STX104_NGPIO 8
static const char *stx104_names[STX104_NGPIO] = { static const char *stx104_names[STX104_NGPIO] = {
"DIN0", "DIN1", "DIN2", "DIN3", "DOUT0", "DOUT1", "DOUT2", "DOUT3" "DIN0", "DIN1", "DIN2", "DIN3", "DOUT0", "DOUT1", "DOUT2", "DOUT3"
}; };
static void stx104_gpio_set_multiple(struct gpio_chip *chip, static int stx104_init_hw(struct stx104_iio *const priv)
unsigned long *mask, unsigned long *bits)
{ {
struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip); int err;
unsigned long flags;
/* verify masked GPIO are output */
if (!(*mask & 0xF0))
return;
*mask >>= 4; /* configure device for software trigger operation */
*bits >>= 4; err = regmap_write(priv->aio_ctl_map, STX104_ADC_CONTROL, STX104_SOFTWARE_TRIGGER);
if (err)
return err;
spin_lock_irqsave(&stx104gpio->lock, flags); /* initialize gain setting to x1 */
err = regmap_write(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, STX104_GAIN_X1);
if (err)
return err;
stx104gpio->out_state &= ~*mask; /* initialize DAC outputs to 0V */
stx104gpio->out_state |= *mask & *bits; err = regmap_write(priv->aio_data_map, STX104_DAC_BASE, 0);
iowrite8(stx104gpio->out_state, stx104gpio->base); if (err)
return err;
err = regmap_write(priv->aio_data_map, STX104_DAC_BASE + STX104_AIO_DATA_STRIDE, 0);
if (err)
return err;
spin_unlock_irqrestore(&stx104gpio->lock, flags); return 0;
} }
static int stx104_probe(struct device *dev, unsigned int id) static int stx104_probe(struct device *dev, unsigned int id)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct stx104_iio *priv; struct stx104_iio *priv;
struct stx104_gpio *stx104gpio; struct gpio_regmap_config gpio_config;
void __iomem *stx104_base;
struct regmap *aio_ctl_map;
struct regmap *aio_data_map;
struct regmap *dio_map;
int err; int err;
unsigned int adc_status;
indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
if (!indio_dev) if (!indio_dev)
return -ENOMEM; return -ENOMEM;
stx104gpio = devm_kzalloc(dev, sizeof(*stx104gpio), GFP_KERNEL);
if (!stx104gpio)
return -ENOMEM;
if (!devm_request_region(dev, base[id], STX104_EXTENT, if (!devm_request_region(dev, base[id], STX104_EXTENT,
dev_name(dev))) { dev_name(dev))) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
...@@ -342,16 +383,37 @@ static int stx104_probe(struct device *dev, unsigned int id) ...@@ -342,16 +383,37 @@ static int stx104_probe(struct device *dev, unsigned int id)
return -EBUSY; return -EBUSY;
} }
priv = iio_priv(indio_dev); stx104_base = devm_ioport_map(dev, base[id], STX104_EXTENT);
priv->reg = devm_ioport_map(dev, base[id], STX104_EXTENT); if (!stx104_base)
if (!priv->reg)
return -ENOMEM; return -ENOMEM;
aio_ctl_map = devm_regmap_init_mmio(dev, stx104_base, &aio_ctl_regmap_config);
if (IS_ERR(aio_ctl_map))
return dev_err_probe(dev, PTR_ERR(aio_ctl_map),
"Unable to initialize aio_ctl register map\n");
aio_data_map = devm_regmap_init_mmio(dev, stx104_base, &aio_data_regmap_config);
if (IS_ERR(aio_data_map))
return dev_err_probe(dev, PTR_ERR(aio_data_map),
"Unable to initialize aio_data register map\n");
dio_map = devm_regmap_init_mmio(dev, stx104_base, &dio_regmap_config);
if (IS_ERR(dio_map))
return dev_err_probe(dev, PTR_ERR(dio_map),
"Unable to initialize dio register map\n");
priv = iio_priv(indio_dev);
priv->aio_ctl_map = aio_ctl_map;
priv->aio_data_map = aio_data_map;
indio_dev->info = &stx104_info; indio_dev->info = &stx104_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
/* determine if differential inputs */ err = regmap_read(aio_ctl_map, STX104_ADC_STATUS, &adc_status);
if (ioread8(&priv->reg->cir_asr) & BIT(5)) { if (err)
return err;
if (u8_get_bits(adc_status, STX104_SD) == STX104_DIFFERENTIAL) {
indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff); indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff);
indio_dev->channels = stx104_channels_diff; indio_dev->channels = stx104_channels_diff;
} else { } else {
...@@ -363,41 +425,27 @@ static int stx104_probe(struct device *dev, unsigned int id) ...@@ -363,41 +425,27 @@ static int stx104_probe(struct device *dev, unsigned int id)
mutex_init(&priv->lock); mutex_init(&priv->lock);
/* configure device for software trigger operation */ err = stx104_init_hw(priv);
iowrite8(0, &priv->reg->acr); if (err)
return err;
/* initialize gain setting to x1 */ err = devm_iio_device_register(dev, indio_dev);
iowrite8(0, &priv->reg->acfg); if (err)
/* initialize DAC output to 0V */
iowrite16(0, &priv->reg->dac[0]);
iowrite16(0, &priv->reg->dac[1]);
stx104gpio->chip.label = dev_name(dev);
stx104gpio->chip.parent = dev;
stx104gpio->chip.owner = THIS_MODULE;
stx104gpio->chip.base = -1;
stx104gpio->chip.ngpio = STX104_NGPIO;
stx104gpio->chip.names = stx104_names;
stx104gpio->chip.get_direction = stx104_gpio_get_direction;
stx104gpio->chip.direction_input = stx104_gpio_direction_input;
stx104gpio->chip.direction_output = stx104_gpio_direction_output;
stx104gpio->chip.get = stx104_gpio_get;
stx104gpio->chip.get_multiple = stx104_gpio_get_multiple;
stx104gpio->chip.set = stx104_gpio_set;
stx104gpio->chip.set_multiple = stx104_gpio_set_multiple;
stx104gpio->base = &priv->reg->dio;
stx104gpio->out_state = 0x0;
spin_lock_init(&stx104gpio->lock);
err = devm_gpiochip_add_data(dev, &stx104gpio->chip, stx104gpio);
if (err) {
dev_err(dev, "GPIO registering failed (%d)\n", err);
return err; return err;
}
return devm_iio_device_register(dev, indio_dev); gpio_config = (struct gpio_regmap_config) {
.parent = dev,
.regmap = dio_map,
.ngpio = STX104_NGPIO,
.names = stx104_names,
.reg_dat_base = GPIO_REGMAP_ADDR(STX104_DIO_REG),
.reg_set_base = GPIO_REGMAP_ADDR(STX104_DIO_REG),
.ngpio_per_reg = STX104_NGPIO,
.reg_mask_xlate = stx104_reg_mask_xlate,
.drvdata = dio_map,
};
return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
} }
static struct isa_driver stx104_driver = { static struct isa_driver stx104_driver = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment