// SPDX-License-Identifier: GPL-2.0-or-later /* * ADS7138 - Texas Instruments Analog-to-Digital Converter */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Always assume 16 bits resolution as HW registers are aligned like that and * with enabled oversampling/averaging it actually corresponds to 16 bits. */ #define ADS7138_RES_BITS 16 /* ADS7138 operation codes */ #define ADS7138_OPCODE_SINGLE_WRITE 0x08 #define ADS7138_OPCODE_SET_BIT 0x18 #define ADS7138_OPCODE_CLEAR_BIT 0x20 #define ADS7138_OPCODE_BLOCK_WRITE 0x28 #define ADS7138_OPCODE_BLOCK_READ 0x30 /* ADS7138 registers */ #define ADS7138_REG_GENERAL_CFG 0x01 #define ADS7138_REG_OSR_CFG 0x03 #define ADS7138_REG_OPMODE_CFG 0x04 #define ADS7138_REG_SEQUENCE_CFG 0x10 #define ADS7138_REG_AUTO_SEQ_CH_SEL 0x12 #define ADS7138_REG_ALERT_CH_SEL 0x14 #define ADS7138_REG_EVENT_FLAG 0x18 #define ADS7138_REG_EVENT_HIGH_FLAG 0x1A #define ADS7138_REG_EVENT_LOW_FLAG 0x1C #define ADS7138_REG_HIGH_TH_HYS_CH(x) ((x) * 4 + 0x20) #define ADS7138_REG_LOW_TH_CNT_CH(x) ((x) * 4 + 0x22) #define ADS7138_REG_MAX_LSB_CH(x) ((x) * 2 + 0x60) #define ADS7138_REG_MIN_LSB_CH(x) ((x) * 2 + 0x80) #define ADS7138_REG_RECENT_LSB_CH(x) ((x) * 2 + 0xA0) #define ADS7138_GENERAL_CFG_RST BIT(0) #define ADS7138_GENERAL_CFG_DWC_EN BIT(4) #define ADS7138_GENERAL_CFG_STATS_EN BIT(5) #define ADS7138_OSR_CFG_MASK GENMASK(2, 0) #define ADS7138_OPMODE_CFG_CONV_MODE BIT(5) #define ADS7138_OPMODE_CFG_FREQ_MASK GENMASK(4, 0) #define ADS7138_SEQUENCE_CFG_SEQ_MODE BIT(0) #define ADS7138_SEQUENCE_CFG_SEQ_START BIT(4) #define ADS7138_THRESHOLD_LSB_MASK GENMASK(7, 4) enum ads7138_modes { ADS7138_MODE_MANUAL, ADS7138_MODE_AUTO, }; struct ads7138_chip_data { const char *name; const int channel_num; }; struct ads7138_data { /* Protects RMW access to the I2C interface */ struct mutex lock; struct i2c_client *client; struct regulator *vref_regu; const struct ads7138_chip_data *chip_data; }; /* * 2D array of available sampling frequencies and the corresponding register * values. Structured like this to be easily usable in read_avail function. */ static const int ads7138_samp_freqs_bits[2][26] = { { 163, 244, 326, 488, 651, 977, 1302, 1953, 2604, 3906, 5208, 7813, 10417, 15625, 20833, 31250, 41667, 62500, 83333, 125000, 166667, 250000, 333333, 500000, 666667, 1000000 }, { 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, /* Here is a hole, due to duplicate frequencies */ 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 } }; static const int ads7138_oversampling_ratios[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; static int ads7138_i2c_write_block(const struct i2c_client *client, u8 reg, u8 *values, u8 length) { int ret; int len = length + 2; /* "+ 2" for OPCODE and reg */ u8 *buf __free(kfree) = kmalloc(len, GFP_KERNEL); if (!buf) return -ENOMEM; buf[0] = ADS7138_OPCODE_BLOCK_WRITE; buf[1] = reg; memcpy(&buf[2], values, length); ret = i2c_master_send(client, buf, len); if (ret < 0) return ret; if (ret != len) return -EIO; return 0; } static int ads7138_i2c_write_with_opcode(const struct i2c_client *client, u8 reg, u8 regval, u8 opcode) { u8 buf[3] = { opcode, reg, regval }; int ret; ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); if (ret < 0) return ret; if (ret != ARRAY_SIZE(buf)) return -EIO; return 0; } static int ads7138_i2c_write(const struct i2c_client *client, u8 reg, u8 value) { return ads7138_i2c_write_with_opcode(client, reg, value, ADS7138_OPCODE_SINGLE_WRITE); } static int ads7138_i2c_set_bit(const struct i2c_client *client, u8 reg, u8 bits) { return ads7138_i2c_write_with_opcode(client, reg, bits, ADS7138_OPCODE_SET_BIT); } static int ads7138_i2c_clear_bit(const struct i2c_client *client, u8 reg, u8 bits) { return ads7138_i2c_write_with_opcode(client, reg, bits, ADS7138_OPCODE_CLEAR_BIT); } static int ads7138_i2c_read_block(const struct i2c_client *client, u8 reg, u8 *out_values, u8 length) { u8 buf[2] = { ADS7138_OPCODE_BLOCK_READ, reg }; int ret; struct i2c_msg msgs[] = { { .addr = client->addr, .len = ARRAY_SIZE(buf), .buf = buf, }, { .addr = client->addr, .flags = I2C_M_RD, .len = length, .buf = out_values, }, }; ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (ret < 0) return ret; if (ret != ARRAY_SIZE(msgs)) return -EIO; return 0; } static int ads7138_i2c_read(const struct i2c_client *client, u8 reg) { u8 value; int ret; ret = ads7138_i2c_read_block(client, reg, &value, sizeof(value)); if (ret) return ret; return value; } static int ads7138_freq_to_bits(int freq) { int i; for (i = 0; i < ARRAY_SIZE(ads7138_samp_freqs_bits[0]); i++) if (freq == ads7138_samp_freqs_bits[0][i]) return ads7138_samp_freqs_bits[1][i]; return -EINVAL; } static int ads7138_bits_to_freq(int bits) { int i; for (i = 0; i < ARRAY_SIZE(ads7138_samp_freqs_bits[1]); i++) if (bits == ads7138_samp_freqs_bits[1][i]) return ads7138_samp_freqs_bits[0][i]; return -EINVAL; } static int ads7138_osr_to_bits(int osr) { int i; for (i = 0; i < ARRAY_SIZE(ads7138_oversampling_ratios); i++) if (osr == ads7138_oversampling_ratios[i]) return i; return -EINVAL; } static int ads7138_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct ads7138_data *data = iio_priv(indio_dev); int ret, vref, bits; u8 values[2]; switch (mask) { case IIO_CHAN_INFO_RAW: ret = ads7138_i2c_read_block(data->client, ADS7138_REG_RECENT_LSB_CH(chan->channel), values, ARRAY_SIZE(values)); if (ret) return ret; *val = get_unaligned_le16(values); return IIO_VAL_INT; case IIO_CHAN_INFO_PEAK: ret = ads7138_i2c_read_block(data->client, ADS7138_REG_MAX_LSB_CH(chan->channel), values, ARRAY_SIZE(values)); if (ret) return ret; *val = get_unaligned_le16(values); return IIO_VAL_INT; case IIO_CHAN_INFO_TROUGH: ret = ads7138_i2c_read_block(data->client, ADS7138_REG_MIN_LSB_CH(chan->channel), values, ARRAY_SIZE(values)); if (ret) return ret; *val = get_unaligned_le16(values); return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: ret = ads7138_i2c_read(data->client, ADS7138_REG_OPMODE_CFG); if (ret < 0) return ret; bits = FIELD_GET(ADS7138_OPMODE_CFG_FREQ_MASK, ret); *val = ads7138_bits_to_freq(bits); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: vref = regulator_get_voltage(data->vref_regu); if (vref < 0) return vref; *val = vref / 1000; *val2 = ADS7138_RES_BITS; return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: ret = ads7138_i2c_read(data->client, ADS7138_REG_OSR_CFG); if (ret < 0) return ret; bits = FIELD_GET(ADS7138_OSR_CFG_MASK, ret); *val = ads7138_oversampling_ratios[bits]; return IIO_VAL_INT; default: return -EINVAL; } } static int ads7138_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct ads7138_data *data = iio_priv(indio_dev); int bits, ret; u8 value; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: { bits = ads7138_freq_to_bits(val); if (bits < 0) return bits; guard(mutex)(&data->lock); ret = ads7138_i2c_read(data->client, ADS7138_REG_OPMODE_CFG); if (ret < 0) return ret; value = ret & ~ADS7138_OPMODE_CFG_FREQ_MASK; value |= FIELD_PREP(ADS7138_OPMODE_CFG_FREQ_MASK, bits); return ads7138_i2c_write(data->client, ADS7138_REG_OPMODE_CFG, value); } case IIO_CHAN_INFO_OVERSAMPLING_RATIO: bits = ads7138_osr_to_bits(val); if (bits < 0) return bits; return ads7138_i2c_write(data->client, ADS7138_REG_OSR_CFG, bits); default: return -EINVAL; } } static int ads7138_read_event(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, enum iio_event_info info, int *val, int *val2) { struct ads7138_data *data = iio_priv(indio_dev); u8 reg, values[2]; int ret; switch (info) { case IIO_EV_INFO_VALUE: reg = (dir == IIO_EV_DIR_RISING) ? ADS7138_REG_HIGH_TH_HYS_CH(chan->channel) : ADS7138_REG_LOW_TH_CNT_CH(chan->channel); ret = ads7138_i2c_read_block(data->client, reg, values, ARRAY_SIZE(values)); if (ret) return ret; *val = ((values[1] << 4) | (values[0] >> 4)); return IIO_VAL_INT; case IIO_EV_INFO_HYSTERESIS: ret = ads7138_i2c_read(data->client, ADS7138_REG_HIGH_TH_HYS_CH(chan->channel)); if (ret < 0) return ret; *val = ret & ~ADS7138_THRESHOLD_LSB_MASK; return IIO_VAL_INT; default: return -EINVAL; } } static int ads7138_write_event(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, enum iio_event_info info, int val, int val2) { struct ads7138_data *data = iio_priv(indio_dev); u8 reg, values[2]; int ret; switch (info) { case IIO_EV_INFO_VALUE: { if (val >= BIT(12) || val < 0) return -EINVAL; reg = (dir == IIO_EV_DIR_RISING) ? ADS7138_REG_HIGH_TH_HYS_CH(chan->channel) : ADS7138_REG_LOW_TH_CNT_CH(chan->channel); guard(mutex)(&data->lock); ret = ads7138_i2c_read(data->client, reg); if (ret < 0) return ret; values[0] = ret & ~ADS7138_THRESHOLD_LSB_MASK; values[0] |= FIELD_PREP(ADS7138_THRESHOLD_LSB_MASK, val); values[1] = (val >> 4); return ads7138_i2c_write_block(data->client, reg, values, ARRAY_SIZE(values)); } case IIO_EV_INFO_HYSTERESIS: { if (val >= BIT(4) || val < 0) return -EINVAL; reg = ADS7138_REG_HIGH_TH_HYS_CH(chan->channel); guard(mutex)(&data->lock); ret = ads7138_i2c_read(data->client, reg); if (ret < 0) return ret; values[0] = val & ~ADS7138_THRESHOLD_LSB_MASK; values[0] |= FIELD_PREP(ADS7138_THRESHOLD_LSB_MASK, ret >> 4); return ads7138_i2c_write(data->client, reg, values[0]); } default: return -EINVAL; } } static int ads7138_read_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir) { struct ads7138_data *data = iio_priv(indio_dev); int ret; if (dir != IIO_EV_DIR_EITHER) return -EINVAL; ret = ads7138_i2c_read(data->client, ADS7138_REG_ALERT_CH_SEL); if (ret < 0) return ret; return (ret & BIT(chan->channel)) ? 1 : 0; } static int ads7138_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, bool state) { struct ads7138_data *data = iio_priv(indio_dev); if (dir != IIO_EV_DIR_EITHER) return -EINVAL; if (state) return ads7138_i2c_set_bit(data->client, ADS7138_REG_ALERT_CH_SEL, BIT(chan->channel)); else return ads7138_i2c_clear_bit(data->client, ADS7138_REG_ALERT_CH_SEL, BIT(chan->channel)); } static int ads7138_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, const int **vals, int *type, int *length, long mask) { switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: *vals = ads7138_samp_freqs_bits[0]; *length = ARRAY_SIZE(ads7138_samp_freqs_bits[0]); *type = IIO_VAL_INT; return IIO_AVAIL_LIST; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: *vals = ads7138_oversampling_ratios; *length = ARRAY_SIZE(ads7138_oversampling_ratios); *type = IIO_VAL_INT; return IIO_AVAIL_LIST; default: return -EINVAL; } } static const struct iio_info ti_ads7138_info = { .read_raw = &ads7138_read_raw, .read_avail = &ads7138_read_avail, .write_raw = &ads7138_write_raw, .read_event_value = &ads7138_read_event, .write_event_value = &ads7138_write_event, .read_event_config = &ads7138_read_event_config, .write_event_config = &ads7138_write_event_config, }; static const struct iio_event_spec ads7138_events[] = { { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_RISING, .mask_separate = BIT(IIO_EV_INFO_VALUE) }, { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_FALLING, .mask_separate = BIT(IIO_EV_INFO_VALUE), }, { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_EITHER, .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS) | BIT(IIO_EV_INFO_ENABLE), }, }; #define ADS7138_V_CHAN(_chan) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = _chan, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_PEAK) | \ BIT(IIO_CHAN_INFO_TROUGH), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .info_mask_shared_by_type_available = \ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .datasheet_name = "AIN"#_chan, \ .event_spec = ads7138_events, \ .num_event_specs = ARRAY_SIZE(ads7138_events), \ } static const struct iio_chan_spec ads7138_channels[] = { ADS7138_V_CHAN(0), ADS7138_V_CHAN(1), ADS7138_V_CHAN(2), ADS7138_V_CHAN(3), ADS7138_V_CHAN(4), ADS7138_V_CHAN(5), ADS7138_V_CHAN(6), ADS7138_V_CHAN(7), }; static irqreturn_t ads7138_event_handler(int irq, void *priv) { struct iio_dev *indio_dev = priv; struct ads7138_data *data = iio_priv(indio_dev); struct device *dev = &data->client->dev; u8 i, events_high, events_low; u64 code; int ret; /* Check if interrupt was trigger by us */ ret = ads7138_i2c_read(data->client, ADS7138_REG_EVENT_FLAG); if (ret <= 0) return IRQ_NONE; ret = ads7138_i2c_read(data->client, ADS7138_REG_EVENT_HIGH_FLAG); if (ret < 0) { dev_warn(dev, "Failed to read event high flags: %d\n", ret); return IRQ_HANDLED; } events_high = ret; ret = ads7138_i2c_read(data->client, ADS7138_REG_EVENT_LOW_FLAG); if (ret < 0) { dev_warn(dev, "Failed to read event low flags: %d\n", ret); return IRQ_HANDLED; } events_low = ret; for (i = 0; i < data->chip_data->channel_num; i++) { if (events_high & BIT(i)) { code = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING); iio_push_event(indio_dev, code, iio_get_time_ns(indio_dev)); } if (events_low & BIT(i)) { code = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING); iio_push_event(indio_dev, code, iio_get_time_ns(indio_dev)); } } /* Try to clear all interrupt flags */ ret = ads7138_i2c_write(data->client, ADS7138_REG_EVENT_HIGH_FLAG, 0xFF); if (ret) dev_warn(dev, "Failed to clear event high flags: %d\n", ret); ret = ads7138_i2c_write(data->client, ADS7138_REG_EVENT_LOW_FLAG, 0xFF); if (ret) dev_warn(dev, "Failed to clear event low flags: %d\n", ret); return IRQ_HANDLED; } static int ads7138_set_conv_mode(struct ads7138_data *data, enum ads7138_modes mode) { if (mode == ADS7138_MODE_AUTO) return ads7138_i2c_set_bit(data->client, ADS7138_REG_OPMODE_CFG, ADS7138_OPMODE_CFG_CONV_MODE); return ads7138_i2c_clear_bit(data->client, ADS7138_REG_OPMODE_CFG, ADS7138_OPMODE_CFG_CONV_MODE); } static int ads7138_init_hw(struct ads7138_data *data) { struct device *dev = &data->client->dev; int ret; data->vref_regu = devm_regulator_get(dev, "avdd"); if (IS_ERR(data->vref_regu)) return dev_err_probe(dev, PTR_ERR(data->vref_regu), "Failed to get avdd regulator\n"); ret = regulator_get_voltage(data->vref_regu); if (ret < 0) return dev_err_probe(dev, ret, "Failed to get avdd voltage\n"); /* Reset the chip to get a defined starting configuration */ ret = ads7138_i2c_set_bit(data->client, ADS7138_REG_GENERAL_CFG, ADS7138_GENERAL_CFG_RST); if (ret) return ret; ret = ads7138_set_conv_mode(data, ADS7138_MODE_AUTO); if (ret) return ret; /* Enable statistics and digital window comparator */ ret = ads7138_i2c_set_bit(data->client, ADS7138_REG_GENERAL_CFG, ADS7138_GENERAL_CFG_STATS_EN | ADS7138_GENERAL_CFG_DWC_EN); if (ret) return ret; /* Enable all channels for auto sequencing */ ret = ads7138_i2c_set_bit(data->client, ADS7138_REG_AUTO_SEQ_CH_SEL, 0xFF); if (ret) return ret; /* Set auto sequence mode and start sequencing */ return ads7138_i2c_set_bit(data->client, ADS7138_REG_SEQUENCE_CFG, ADS7138_SEQUENCE_CFG_SEQ_START | ADS7138_SEQUENCE_CFG_SEQ_MODE); } static int ads7138_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct iio_dev *indio_dev; struct ads7138_data *data; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); data->client = client; data->chip_data = i2c_get_match_data(client); if (!data->chip_data) return -ENODEV; ret = devm_mutex_init(dev, &data->lock); if (ret) return ret; indio_dev->name = data->chip_data->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ads7138_channels; indio_dev->num_channels = ARRAY_SIZE(ads7138_channels); indio_dev->info = &ti_ads7138_info; i2c_set_clientdata(client, indio_dev); if (client->irq > 0) { ret = devm_request_threaded_irq(dev, client->irq, NULL, ads7138_event_handler, IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, client->name, indio_dev); if (ret) return ret; } ret = ads7138_init_hw(data); if (ret) return dev_err_probe(dev, ret, "Failed to initialize device\n"); ret = devm_iio_device_register(dev, indio_dev); if (ret) return dev_err_probe(dev, ret, "Failed to register iio device\n"); return 0; } static int ads7138_runtime_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ads7138_data *data = iio_priv(indio_dev); return ads7138_set_conv_mode(data, ADS7138_MODE_MANUAL); } static int ads7138_runtime_resume(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ads7138_data *data = iio_priv(indio_dev); return ads7138_set_conv_mode(data, ADS7138_MODE_AUTO); } static DEFINE_RUNTIME_DEV_PM_OPS(ads7138_pm_ops, ads7138_runtime_suspend, ads7138_runtime_resume, NULL); static const struct ads7138_chip_data ads7128_data = { .name = "ads7128", .channel_num = 8, }; static const struct ads7138_chip_data ads7138_data = { .name = "ads7138", .channel_num = 8, }; static const struct of_device_id ads7138_of_match[] = { { .compatible = "ti,ads7128", .data = &ads7128_data }, { .compatible = "ti,ads7138", .data = &ads7138_data }, { } }; MODULE_DEVICE_TABLE(of, ads7138_of_match); static const struct i2c_device_id ads7138_device_ids[] = { { "ads7128", (kernel_ulong_t)&ads7128_data }, { "ads7138", (kernel_ulong_t)&ads7138_data }, { } }; MODULE_DEVICE_TABLE(i2c, ads7138_device_ids); static struct i2c_driver ads7138_driver = { .driver = { .name = "ads7138", .of_match_table = ads7138_of_match, .pm = pm_ptr(&ads7138_pm_ops), }, .id_table = ads7138_device_ids, .probe = ads7138_probe, }; module_i2c_driver(ads7138_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tobias Sperling "); MODULE_DESCRIPTION("Driver for TI ADS7138 ADCs");