struct ltc2664_chip_info { constchar *name; int (*scale_get)(conststruct ltc2664_state *st, int c); int (*offset_get)(conststruct ltc2664_state *st, int c); int measurement_type; unsignedint num_channels; constint (*span_helper)[2]; unsignedint num_span; unsignedint internal_vref_mv; bool manual_span_support; bool rfsadj_support;
};
struct ltc2664_chan { /* indicates if the channel should be toggled */ bool toggle_chan; /* indicates if the channel is in powered down state */ bool powerdown; /* span code of the channel */
u8 span; /* raw data of the current state of the chip registers (A/B) */
u16 raw[2];
};
struct ltc2664_state { struct spi_device *spi; struct regmap *regmap; struct ltc2664_chan channels[LTC2672_MAX_CHANNEL]; /* lock to protect against multiple access to the device and shared data */ struct mutex lock; conststruct ltc2664_chip_info *chip_info; struct iio_chan_spec *iio_channels; int vref_mv;
u32 rfsadj_ohms;
u32 toggle_sel; bool global_toggle;
};
guard(mutex)(&st->lock); /* select the correct input register to write to */ if (c->toggle_chan) {
ret = regmap_write(st->regmap, LTC2664_CMD_TOGGLE_SEL,
input << chan); if (ret) return ret;
} /* * If in toggle mode the dac should be updated by an * external signal (or sw toggle) and not here.
*/ if (st->toggle_sel & BIT(chan))
reg = LTC2664_CMD_WRITE_N(chan); else
reg = LTC2664_CMD_WRITE_N_UPDATE_N(chan);
ret = regmap_write(st->regmap, reg, code); if (ret) return ret;
c->raw[input] = code;
if (c->toggle_chan) {
ret = regmap_write(st->regmap, LTC2664_CMD_TOGGLE_SEL,
st->toggle_sel); if (ret) return ret;
}
guard(mutex)(&st->lock); switch (private) { case LTC2664_POWERDOWN:
ret = regmap_write(st->regmap,
en ? LTC2664_CMD_POWER_DOWN_N(chan->channel) :
LTC2664_CMD_UPDATE_N(chan->channel), en); if (ret) return ret;
st->channels[chan->channel].powerdown = en;
return len; case LTC2664_TOGGLE_EN: if (en)
st->toggle_sel |= BIT(chan->channel); else
st->toggle_sel &= ~BIT(chan->channel);
ret = regmap_write(st->regmap, LTC2664_CMD_TOGGLE_SEL,
st->toggle_sel); if (ret) return ret;
return len; case LTC2664_GLOBAL_TOGGLE:
ret = regmap_write(st->regmap, LTC2664_CMD_GLOBAL_TOGGLE, en); if (ret) return ret;
mspan = LTC2664_MSPAN_SOFTSPAN;
ret = device_property_read_u32(dev, "adi,manual-span-operation-config",
&mspan); if (!ret) { if (!chip_info->manual_span_support) return dev_err_probe(dev, -EINVAL, "adi,manual-span-operation-config not supported\n");
if (mspan >= ARRAY_SIZE(ltc2664_mspan_lut)) return dev_err_probe(dev, -EINVAL, "adi,manual-span-operation-config not in range\n");
}
st->rfsadj_ohms = 20000;
ret = device_property_read_u32(dev, "adi,rfsadj-ohms", &st->rfsadj_ohms); if (!ret) { if (!chip_info->rfsadj_support) return dev_err_probe(dev, -EINVAL, "adi,rfsadj-ohms not supported\n");
if (st->rfsadj_ohms < 19000 || st->rfsadj_ohms > 41000) return dev_err_probe(dev, -EINVAL, "adi,rfsadj-ohms not in range\n");
}
/* If we have a clr/reset pin, use that to reset the chip. */
gpio = devm_gpiod_get_optional(&st->spi->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(gpio)) return dev_err_probe(&st->spi->dev, PTR_ERR(gpio), "Failed to get reset gpio"); if (gpio) {
fsleep(1000);
gpiod_set_value_cansleep(gpio, 0);
}
/* * Duplicate the default channel configuration as it can change during * @ltc2664_channel_config()
*/
st->iio_channels = devm_kcalloc(&st->spi->dev,
chip_info->num_channels, sizeof(struct iio_chan_spec),
GFP_KERNEL); if (!st->iio_channels) return -ENOMEM;
for (i = 0; i < chip_info->num_channels; i++) {
st->iio_channels[i] = ltc2664_channel_template;
st->iio_channels[i].type = chip_info->measurement_type;
st->iio_channels[i].channel = i;
}
ret = ltc2664_channel_config(st); if (ret) return ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM;
st = iio_priv(indio_dev);
st->spi = spi;
chip_info = spi_get_device_match_data(spi); if (!chip_info) return -ENODEV;
st->chip_info = chip_info;
mutex_init(&st->lock);
st->regmap = devm_regmap_init_spi(spi, <c2664_regmap_config); if (IS_ERR(st->regmap)) return dev_err_probe(dev, PTR_ERR(st->regmap), "Failed to init regmap");
ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulators),
regulators); if (ret) return dev_err_probe(dev, ret, "Failed to enable regulators\n");
ret = devm_regulator_get_enable_read_voltage(dev, "ref"); if (ret < 0 && ret != -ENODEV) return ret;
st->vref_mv = ret > 0 ? ret / 1000 : chip_info->internal_vref_mv;
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.