Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/iio/adc/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 19 kB image not shown  

Quelle  ti-ads7138.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * ADS7138 - Texas Instruments Analog-to-Digital Converter
 */


#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/unaligned.h>

#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/types.h>

/*
 * 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");

Messung V0.5
C=99 H=98 G=98

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.