524 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * IIO driver for the Apex Embedded Systems STX1044 * Copyright (C) 2016 William Breathitt Gray5 */6#include <linux/bitfield.h>7#include <linux/bits.h>8#include <linux/device.h>9#include <linux/err.h>10#include <linux/gpio/regmap.h>11#include <linux/i8254.h>12#include <linux/iio/iio.h>13#include <linux/iio/types.h>14#include <linux/isa.h>15#include <linux/kernel.h>16#include <linux/limits.h>17#include <linux/module.h>18#include <linux/moduleparam.h>19#include <linux/mutex.h>20#include <linux/regmap.h>21#include <linux/types.h>22 23#define STX104_OUT_CHAN(chan) { \24 .type = IIO_VOLTAGE, \25 .channel = chan, \26 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \27 .indexed = 1, \28 .output = 1 \29}30#define STX104_IN_CHAN(chan, diff) { \31 .type = IIO_VOLTAGE, \32 .channel = chan, \33 .channel2 = chan, \34 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \35 BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), \36 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \37 .indexed = 1, \38 .differential = diff \39}40 41#define STX104_NUM_OUT_CHAN 242 43#define STX104_EXTENT 1644 45static unsigned int base[max_num_isa_dev(STX104_EXTENT)];46static unsigned int num_stx104;47module_param_hw_array(base, uint, ioport, &num_stx104, 0);48MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");49 50#define STX104_AIO_BASE 0x051#define STX104_SOFTWARE_STROBE STX104_AIO_BASE52#define STX104_ADC_DATA STX104_AIO_BASE53#define STX104_ADC_CHANNEL (STX104_AIO_BASE + 0x2)54#define STX104_DIO_REG (STX104_AIO_BASE + 0x3)55#define STX104_DAC_BASE (STX104_AIO_BASE + 0x4)56#define STX104_ADC_STATUS (STX104_AIO_BASE + 0x8)57#define STX104_ADC_CONTROL (STX104_AIO_BASE + 0x9)58#define STX104_ADC_CONFIGURATION (STX104_AIO_BASE + 0x11)59#define STX104_I8254_BASE (STX104_AIO_BASE + 0x12)60 61#define STX104_AIO_DATA_STRIDE 262#define STX104_DAC_OFFSET(_channel) (STX104_DAC_BASE + STX104_AIO_DATA_STRIDE * (_channel))63 64/* ADC Channel */65#define STX104_FC GENMASK(3, 0)66#define STX104_LC GENMASK(7, 4)67#define STX104_SINGLE_CHANNEL(_channel) \68 (u8_encode_bits(_channel, STX104_FC) | u8_encode_bits(_channel, STX104_LC))69 70/* ADC Status */71#define STX104_SD BIT(5)72#define STX104_CNV BIT(7)73#define STX104_DIFFERENTIAL 174 75/* ADC Control */76#define STX104_ALSS GENMASK(1, 0)77#define STX104_SOFTWARE_TRIGGER u8_encode_bits(0x0, STX104_ALSS)78 79/* ADC Configuration */80#define STX104_GAIN GENMASK(1, 0)81#define STX104_ADBU BIT(2)82#define STX104_RBK GENMASK(7, 4)83#define STX104_BIPOLAR 084#define STX104_GAIN_X1 085#define STX104_GAIN_X2 186#define STX104_GAIN_X4 287#define STX104_GAIN_X8 388 89/**90 * struct stx104_iio - IIO device private data structure91 * @lock: synchronization lock to prevent I/O race conditions92 * @aio_data_map: Regmap for analog I/O data93 * @aio_ctl_map: Regmap for analog I/O control94 */95struct stx104_iio {96 struct mutex lock;97 struct regmap *aio_data_map;98 struct regmap *aio_ctl_map;99};100 101static const struct regmap_range aio_ctl_wr_ranges[] = {102 regmap_reg_range(0x0, 0x0), regmap_reg_range(0x2, 0x2), regmap_reg_range(0x9, 0x9),103 regmap_reg_range(0x11, 0x11),104};105static const struct regmap_range aio_ctl_rd_ranges[] = {106 regmap_reg_range(0x2, 0x2), regmap_reg_range(0x8, 0x9), regmap_reg_range(0x11, 0x11),107};108static const struct regmap_range aio_ctl_volatile_ranges[] = {109 regmap_reg_range(0x8, 0x8),110};111static const struct regmap_access_table aio_ctl_wr_table = {112 .yes_ranges = aio_ctl_wr_ranges,113 .n_yes_ranges = ARRAY_SIZE(aio_ctl_wr_ranges),114};115static const struct regmap_access_table aio_ctl_rd_table = {116 .yes_ranges = aio_ctl_rd_ranges,117 .n_yes_ranges = ARRAY_SIZE(aio_ctl_rd_ranges),118};119static const struct regmap_access_table aio_ctl_volatile_table = {120 .yes_ranges = aio_ctl_volatile_ranges,121 .n_yes_ranges = ARRAY_SIZE(aio_ctl_volatile_ranges),122};123 124static const struct regmap_config aio_ctl_regmap_config = {125 .name = "aio_ctl",126 .reg_bits = 8,127 .reg_stride = 1,128 .reg_base = STX104_AIO_BASE,129 .val_bits = 8,130 .io_port = true,131 .wr_table = &aio_ctl_wr_table,132 .rd_table = &aio_ctl_rd_table,133 .volatile_table = &aio_ctl_volatile_table,134 .cache_type = REGCACHE_FLAT,135};136 137static const struct regmap_range aio_data_wr_ranges[] = {138 regmap_reg_range(0x4, 0x6),139};140static const struct regmap_range aio_data_rd_ranges[] = {141 regmap_reg_range(0x0, 0x0),142};143static const struct regmap_access_table aio_data_wr_table = {144 .yes_ranges = aio_data_wr_ranges,145 .n_yes_ranges = ARRAY_SIZE(aio_data_wr_ranges),146};147static const struct regmap_access_table aio_data_rd_table = {148 .yes_ranges = aio_data_rd_ranges,149 .n_yes_ranges = ARRAY_SIZE(aio_data_rd_ranges),150};151 152static const struct regmap_config aio_data_regmap_config = {153 .name = "aio_data",154 .reg_bits = 16,155 .reg_stride = STX104_AIO_DATA_STRIDE,156 .reg_base = STX104_AIO_BASE,157 .val_bits = 16,158 .io_port = true,159 .wr_table = &aio_data_wr_table,160 .rd_table = &aio_data_rd_table,161 .volatile_table = &aio_data_rd_table,162 .cache_type = REGCACHE_FLAT,163};164 165static const struct regmap_config dio_regmap_config = {166 .name = "dio",167 .reg_bits = 8,168 .reg_stride = 1,169 .reg_base = STX104_DIO_REG,170 .val_bits = 8,171 .io_port = true,172};173 174static const struct regmap_range pit_wr_ranges[] = {175 regmap_reg_range(0x0, 0x3),176};177static const struct regmap_range pit_rd_ranges[] = {178 regmap_reg_range(0x0, 0x2),179};180static const struct regmap_access_table pit_wr_table = {181 .yes_ranges = pit_wr_ranges,182 .n_yes_ranges = ARRAY_SIZE(pit_wr_ranges),183};184static const struct regmap_access_table pit_rd_table = {185 .yes_ranges = pit_rd_ranges,186 .n_yes_ranges = ARRAY_SIZE(pit_rd_ranges),187};188 189static const struct regmap_config pit_regmap_config = {190 .name = "i8254",191 .reg_bits = 8,192 .reg_stride = 1,193 .reg_base = STX104_I8254_BASE,194 .val_bits = 8,195 .io_port = true,196 .wr_table = &pit_wr_table,197 .rd_table = &pit_rd_table,198};199 200static int stx104_read_raw(struct iio_dev *indio_dev,201 struct iio_chan_spec const *chan, int *val, int *val2, long mask)202{203 struct stx104_iio *const priv = iio_priv(indio_dev);204 int err;205 unsigned int adc_config;206 unsigned int value;207 unsigned int adc_status;208 209 switch (mask) {210 case IIO_CHAN_INFO_HARDWAREGAIN:211 err = regmap_read(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, &adc_config);212 if (err)213 return err;214 215 *val = BIT(u8_get_bits(adc_config, STX104_GAIN));216 return IIO_VAL_INT;217 case IIO_CHAN_INFO_RAW:218 if (chan->output) {219 err = regmap_read(priv->aio_data_map, STX104_DAC_OFFSET(chan->channel),220 &value);221 if (err)222 return err;223 *val = value;224 return IIO_VAL_INT;225 }226 227 mutex_lock(&priv->lock);228 229 /* select ADC channel */230 err = regmap_write(priv->aio_ctl_map, STX104_ADC_CHANNEL,231 STX104_SINGLE_CHANNEL(chan->channel));232 if (err) {233 mutex_unlock(&priv->lock);234 return err;235 }236 237 /*238 * Trigger ADC sample capture by writing to the 8-bit Software Strobe Register and239 * wait for completion; the conversion time range is 5 microseconds to 53.68 seconds240 * in steps of 25 nanoseconds. The actual Analog Input Frame Timer time interval is241 * calculated as:242 * ai_time_frame_ns = ( AIFT + 1 ) * ( 25 nanoseconds ).243 * Where 0 <= AIFT <= 2147483648.244 */245 err = regmap_write(priv->aio_ctl_map, STX104_SOFTWARE_STROBE, 0);246 if (err) {247 mutex_unlock(&priv->lock);248 return err;249 }250 err = regmap_read_poll_timeout(priv->aio_ctl_map, STX104_ADC_STATUS, adc_status,251 !u8_get_bits(adc_status, STX104_CNV), 0, 53687092);252 if (err) {253 mutex_unlock(&priv->lock);254 return err;255 }256 257 err = regmap_read(priv->aio_data_map, STX104_ADC_DATA, &value);258 if (err) {259 mutex_unlock(&priv->lock);260 return err;261 }262 *val = value;263 264 mutex_unlock(&priv->lock);265 return IIO_VAL_INT;266 case IIO_CHAN_INFO_OFFSET:267 /* get ADC bipolar/unipolar configuration */268 err = regmap_read(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, &adc_config);269 if (err)270 return err;271 272 *val = (u8_get_bits(adc_config, STX104_ADBU) == STX104_BIPOLAR) ? -32768 : 0;273 return IIO_VAL_INT;274 case IIO_CHAN_INFO_SCALE:275 /* get ADC bipolar/unipolar and gain configuration */276 err = regmap_read(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, &adc_config);277 if (err)278 return err;279 280 *val = 5;281 *val2 = (u8_get_bits(adc_config, STX104_ADBU) == STX104_BIPOLAR) ? 14 : 15;282 *val2 += u8_get_bits(adc_config, STX104_GAIN);283 return IIO_VAL_FRACTIONAL_LOG2;284 }285 286 return -EINVAL;287}288 289static int stx104_write_raw(struct iio_dev *indio_dev,290 struct iio_chan_spec const *chan, int val, int val2, long mask)291{292 struct stx104_iio *const priv = iio_priv(indio_dev);293 u8 gain;294 295 switch (mask) {296 case IIO_CHAN_INFO_HARDWAREGAIN:297 /* Only four gain states (x1, x2, x4, x8) */298 switch (val) {299 case 1:300 gain = STX104_GAIN_X1;301 break;302 case 2:303 gain = STX104_GAIN_X2;304 break;305 case 4:306 gain = STX104_GAIN_X4;307 break;308 case 8:309 gain = STX104_GAIN_X8;310 break;311 default:312 return -EINVAL;313 }314 315 return regmap_write(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, gain);316 case IIO_CHAN_INFO_RAW:317 if (!chan->output)318 return -EINVAL;319 320 if (val < 0 || val > U16_MAX)321 return -EINVAL;322 323 return regmap_write(priv->aio_data_map, STX104_DAC_OFFSET(chan->channel), val);324 }325 326 return -EINVAL;327}328 329static const struct iio_info stx104_info = {330 .read_raw = stx104_read_raw,331 .write_raw = stx104_write_raw332};333 334/* single-ended input channels configuration */335static const struct iio_chan_spec stx104_channels_sing[] = {336 STX104_OUT_CHAN(0), STX104_OUT_CHAN(1),337 STX104_IN_CHAN(0, 0), STX104_IN_CHAN(1, 0), STX104_IN_CHAN(2, 0),338 STX104_IN_CHAN(3, 0), STX104_IN_CHAN(4, 0), STX104_IN_CHAN(5, 0),339 STX104_IN_CHAN(6, 0), STX104_IN_CHAN(7, 0), STX104_IN_CHAN(8, 0),340 STX104_IN_CHAN(9, 0), STX104_IN_CHAN(10, 0), STX104_IN_CHAN(11, 0),341 STX104_IN_CHAN(12, 0), STX104_IN_CHAN(13, 0), STX104_IN_CHAN(14, 0),342 STX104_IN_CHAN(15, 0)343};344/* differential input channels configuration */345static const struct iio_chan_spec stx104_channels_diff[] = {346 STX104_OUT_CHAN(0), STX104_OUT_CHAN(1),347 STX104_IN_CHAN(0, 1), STX104_IN_CHAN(1, 1), STX104_IN_CHAN(2, 1),348 STX104_IN_CHAN(3, 1), STX104_IN_CHAN(4, 1), STX104_IN_CHAN(5, 1),349 STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1)350};351 352static int stx104_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base,353 unsigned int offset, unsigned int *const reg,354 unsigned int *const mask)355{356 /* Output lines are located at same register bit offsets as input lines */357 if (offset >= 4)358 offset -= 4;359 360 *reg = base;361 *mask = BIT(offset);362 363 return 0;364}365 366#define STX104_NGPIO 8367static const char *stx104_names[STX104_NGPIO] = {368 "DIN0", "DIN1", "DIN2", "DIN3", "DOUT0", "DOUT1", "DOUT2", "DOUT3"369};370 371static int bank_select_i8254(struct regmap *map)372{373 const u8 select_i8254[] = { 0x3, 0xB, 0xA };374 size_t i;375 int err;376 377 for (i = 0; i < ARRAY_SIZE(select_i8254); i++) {378 err = regmap_write_bits(map, STX104_ADC_CONFIGURATION, STX104_RBK, select_i8254[i]);379 if (err)380 return err;381 }382 383 return 0;384}385 386static int stx104_init_hw(struct stx104_iio *const priv)387{388 int err;389 390 /* configure device for software trigger operation */391 err = regmap_write(priv->aio_ctl_map, STX104_ADC_CONTROL, STX104_SOFTWARE_TRIGGER);392 if (err)393 return err;394 395 /* initialize gain setting to x1 */396 err = regmap_write(priv->aio_ctl_map, STX104_ADC_CONFIGURATION, STX104_GAIN_X1);397 if (err)398 return err;399 400 /* initialize DAC outputs to 0V */401 err = regmap_write(priv->aio_data_map, STX104_DAC_BASE, 0);402 if (err)403 return err;404 err = regmap_write(priv->aio_data_map, STX104_DAC_BASE + STX104_AIO_DATA_STRIDE, 0);405 if (err)406 return err;407 408 return bank_select_i8254(priv->aio_ctl_map);409}410 411static int stx104_probe(struct device *dev, unsigned int id)412{413 struct iio_dev *indio_dev;414 struct stx104_iio *priv;415 struct gpio_regmap_config gpio_config;416 struct i8254_regmap_config pit_config;417 void __iomem *stx104_base;418 struct regmap *aio_ctl_map;419 struct regmap *aio_data_map;420 struct regmap *dio_map;421 int err;422 unsigned int adc_status;423 424 indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));425 if (!indio_dev)426 return -ENOMEM;427 428 if (!devm_request_region(dev, base[id], STX104_EXTENT,429 dev_name(dev))) {430 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",431 base[id], base[id] + STX104_EXTENT);432 return -EBUSY;433 }434 435 stx104_base = devm_ioport_map(dev, base[id], STX104_EXTENT);436 if (!stx104_base)437 return -ENOMEM;438 439 aio_ctl_map = devm_regmap_init_mmio(dev, stx104_base, &aio_ctl_regmap_config);440 if (IS_ERR(aio_ctl_map))441 return dev_err_probe(dev, PTR_ERR(aio_ctl_map),442 "Unable to initialize aio_ctl register map\n");443 444 aio_data_map = devm_regmap_init_mmio(dev, stx104_base, &aio_data_regmap_config);445 if (IS_ERR(aio_data_map))446 return dev_err_probe(dev, PTR_ERR(aio_data_map),447 "Unable to initialize aio_data register map\n");448 449 dio_map = devm_regmap_init_mmio(dev, stx104_base, &dio_regmap_config);450 if (IS_ERR(dio_map))451 return dev_err_probe(dev, PTR_ERR(dio_map),452 "Unable to initialize dio register map\n");453 454 pit_config.map = devm_regmap_init_mmio(dev, stx104_base, &pit_regmap_config);455 if (IS_ERR(pit_config.map))456 return dev_err_probe(dev, PTR_ERR(pit_config.map),457 "Unable to initialize i8254 register map\n");458 459 priv = iio_priv(indio_dev);460 priv->aio_ctl_map = aio_ctl_map;461 priv->aio_data_map = aio_data_map;462 463 indio_dev->info = &stx104_info;464 indio_dev->modes = INDIO_DIRECT_MODE;465 466 err = regmap_read(aio_ctl_map, STX104_ADC_STATUS, &adc_status);467 if (err)468 return err;469 470 if (u8_get_bits(adc_status, STX104_SD) == STX104_DIFFERENTIAL) {471 indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff);472 indio_dev->channels = stx104_channels_diff;473 } else {474 indio_dev->num_channels = ARRAY_SIZE(stx104_channels_sing);475 indio_dev->channels = stx104_channels_sing;476 }477 478 indio_dev->name = dev_name(dev);479 480 mutex_init(&priv->lock);481 482 err = stx104_init_hw(priv);483 if (err)484 return err;485 486 err = devm_iio_device_register(dev, indio_dev);487 if (err)488 return err;489 490 gpio_config = (struct gpio_regmap_config) {491 .parent = dev,492 .regmap = dio_map,493 .ngpio = STX104_NGPIO,494 .names = stx104_names,495 .reg_dat_base = GPIO_REGMAP_ADDR(STX104_DIO_REG),496 .reg_set_base = GPIO_REGMAP_ADDR(STX104_DIO_REG),497 .ngpio_per_reg = STX104_NGPIO,498 .reg_mask_xlate = stx104_reg_mask_xlate,499 .drvdata = dio_map,500 };501 502 err = PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));503 if (err)504 return err;505 506 pit_config.parent = dev;507 508 return devm_i8254_regmap_register(dev, &pit_config);509}510 511static struct isa_driver stx104_driver = {512 .probe = stx104_probe,513 .driver = {514 .name = "stx104"515 },516};517 518module_isa_driver(stx104_driver, num_stx104);519 520MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");521MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");522MODULE_LICENSE("GPL v2");523MODULE_IMPORT_NS(I8254);524