/* Index corresponds to the value of IRS_REG_DATA_RATE register. */ staticconstint irsd200_data_rates[] = {
50,
100,
};
/* Index corresponds to the (field) value of IRS_REG_FILTER register. */ staticconstunsignedint irsd200_lp_filter_freq[] = {
10,
7,
};
/* * Index corresponds to the (field) value of IRS_REG_FILTER register. Note that * this represents a fractional value (e.g the first value corresponds to 3 / 10 * = 0.3 Hz).
*/ staticconstunsignedint irsd200_hp_filter_freq[][2] = {
{ 3, 10 },
{ 5, 10 },
};
staticint irsd200_setup(struct irsd200_data *data)
{ unsignedint val; int ret;
/* Disable all interrupt sources. */
ret = regmap_write(data->regmap, IRS_REG_INTR, 0); if (ret) {
dev_err(data->dev, "Could not set interrupt sources (%d)\n",
ret); return ret;
}
/* Set operation to active. */
ret = regmap_write(data->regmap, IRS_REG_OP, IRS_OP_ACTIVE); if (ret) {
dev_err(data->dev, "Could not set operation mode (%d)\n", ret); return ret;
}
/* Clear threshold count. */
ret = regmap_read(data->regmap, IRS_REG_COUNT, &val); if (ret) {
dev_err(data->dev, "Could not clear threshold count (%d)\n",
ret); return ret;
}
/* Clear status. */
ret = regmap_write(data->regmap, IRS_REG_STATUS, 0x0f); if (ret) {
dev_err(data->dev, "Could not clear status (%d)\n", ret); return ret;
}
return 0;
}
staticint irsd200_read_threshold(struct irsd200_data *data, enum iio_event_direction dir, int *val)
{ unsignedint regval; unsignedint reg; int scale; int ret;
ret = regmap_bulk_read(data->regmap, IRS_REG_DATA_LO, &buf, sizeof(buf)); if (ret) {
dev_err(data->dev, "Could not bulk read data (%d)\n", ret); return ret;
}
*val = le16_to_cpu(buf);
return 0;
}
staticint irsd200_read_data_rate(struct irsd200_data *data, int *val)
{ unsignedint regval; int ret;
ret = regmap_read(data->regmap, IRS_REG_DATA_RATE, ®val); if (ret) {
dev_err(data->dev, "Could not read data rate (%d)\n", ret); return ret;
}
if (regval >= ARRAY_SIZE(irsd200_data_rates)) return -ERANGE;
*val = irsd200_data_rates[regval];
return 0;
}
staticint irsd200_write_data_rate(struct irsd200_data *data, int val)
{
size_t idx; int ret;
for (idx = 0; idx < ARRAY_SIZE(irsd200_data_rates); ++idx) { if (irsd200_data_rates[idx] == val) break;
}
if (idx == ARRAY_SIZE(irsd200_data_rates)) return -ERANGE;
ret = regmap_write(data->regmap, IRS_REG_DATA_RATE, idx); if (ret) {
dev_err(data->dev, "Could not write data rate (%d)\n", ret); return ret;
}
/* * Data sheet says the device needs 3 seconds of settling time. The * device operates normally during this period though. This is more of a * "guarantee" than trying to prevent other user space reads/writes.
*/
ssleep(3);
return 0;
}
staticint irsd200_read_timer(struct irsd200_data *data, int *val, int *val2)
{
__le16 buf; int ret;
ret = regmap_bulk_read(data->regmap, IRS_REG_TIMER_LO, &buf, sizeof(buf)); if (ret) {
dev_err(data->dev, "Could not bulk read timer (%d)\n", ret); return ret;
}
ret = irsd200_read_data_rate(data, val2); if (ret) return ret;
*val = le16_to_cpu(buf);
return 0;
}
staticint irsd200_write_timer(struct irsd200_data *data, int val, int val2)
{ unsignedint regval; int data_rate;
__le16 buf; int ret;
if (val < 0 || val2 < 0) return -ERANGE;
ret = irsd200_read_data_rate(data, &data_rate); if (ret) return ret;
/* Quantize from seconds. */
regval = val * data_rate + (val2 * data_rate) / 1000000;
/* Value is 10 bits. */ if (regval >= BIT(10)) return -ERANGE;
buf = cpu_to_le16((u16)regval);
ret = regmap_bulk_write(data->regmap, IRS_REG_TIMER_LO, &buf, sizeof(buf)); if (ret) {
dev_err(data->dev, "Could not bulk write timer (%d)\n", ret); return ret;
}
return 0;
}
staticint irsd200_read_nr_count(struct irsd200_data *data, int *val)
{ unsignedint regval; int ret;
ret = regmap_read(data->regmap, IRS_REG_NR_COUNT, ®val); if (ret) {
dev_err(data->dev, "Could not read nr count (%d)\n", ret); return ret;
}
*val = regval;
return 0;
}
staticint irsd200_write_nr_count(struct irsd200_data *data, int val)
{ unsignedint regval; int ret;
/* A value of zero means that IRS_REG_STATUS is never set. */ if (val <= 0 || val >= 8) return -ERANGE;
regval = val;
if (regval >= 2) { /* * According to the data sheet, timer must be also set in this * case (i.e. be non-zero). Check and enforce that.
*/
ret = irsd200_read_timer(data, &val, &val); if (ret) return ret;
if (val == 0) {
dev_err(data->dev, "Timer must be non-zero when nr count is %u\n",
regval); return -EPERM;
}
}
ret = regmap_write(data->regmap, IRS_REG_NR_COUNT, regval); if (ret) {
dev_err(data->dev, "Could not write nr count (%d)\n", ret); return ret;
}
return 0;
}
staticint irsd200_read_lp_filter(struct irsd200_data *data, int *val)
{ unsignedint regval; int ret;
ret = regmap_field_read(data->regfields[IRS_REGF_LP_FILTER], ®val); if (ret) {
dev_err(data->dev, "Could not read lp filter frequency (%d)\n",
ret); return ret;
}
*val = irsd200_lp_filter_freq[regval];
return 0;
}
staticint irsd200_write_lp_filter(struct irsd200_data *data, int val)
{
size_t idx; int ret;
for (idx = 0; idx < ARRAY_SIZE(irsd200_lp_filter_freq); ++idx) { if (irsd200_lp_filter_freq[idx] == val) break;
}
if (idx == ARRAY_SIZE(irsd200_lp_filter_freq)) return -ERANGE;
ret = regmap_field_write(data->regfields[IRS_REGF_LP_FILTER], idx); if (ret) {
dev_err(data->dev, "Could not write lp filter frequency (%d)\n",
ret); return ret;
}
return 0;
}
staticint irsd200_read_hp_filter(struct irsd200_data *data, int *val, int *val2)
{ unsignedint regval; int ret;
ret = regmap_field_read(data->regfields[IRS_REGF_HP_FILTER], ®val); if (ret) {
dev_err(data->dev, "Could not read hp filter frequency (%d)\n",
ret); return ret;
}
staticint irsd200_write_hp_filter(struct irsd200_data *data, int val, int val2)
{
size_t idx; int ret;
/* Truncate fractional part to one digit. */
val2 /= 100000;
for (idx = 0; idx < ARRAY_SIZE(irsd200_hp_filter_freq); ++idx) { if (irsd200_hp_filter_freq[idx][0] == val2) break;
}
if (idx == ARRAY_SIZE(irsd200_hp_filter_freq) || val != 0) return -ERANGE;
ret = regmap_field_write(data->regfields[IRS_REGF_HP_FILTER], idx); if (ret) {
dev_err(data->dev, "Could not write hp filter frequency (%d)\n",
ret); return ret;
}
return 0;
}
staticint irsd200_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct irsd200_data *data = iio_priv(indio_dev); int ret;
s16 buf;
switch (mask) { case IIO_CHAN_INFO_RAW:
ret = irsd200_read_data(data, &buf); if (ret) return ret;
*val = buf; return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ:
ret = irsd200_read_data_rate(data, val); if (ret) return ret;
return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
ret = irsd200_read_lp_filter(data, val); if (ret) return ret;
return IIO_VAL_INT; case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
ret = irsd200_read_hp_filter(data, val, val2); if (ret) return ret;
switch (type) { case IIO_EV_TYPE_THRESH: /* Clear the count register (by reading from it). */
ret = regmap_read(data->regmap, IRS_REG_COUNT, &tmp); if (ret) return ret;
if (status & BIT(IRS_INTR_COUNT_THR_OR) &&
source & BIT(IRS_INTR_COUNT_THR_OR)) { /* * The register value resets to zero after reading. We therefore * need to read once and manually extract the lower and upper * count register fields.
*/
ret = regmap_read(data->regmap, IRS_REG_COUNT, &count); if (ret)
dev_err(data->dev, "Could not read count (%d)\n", ret);
/* * We only check the OR mode to be able to push events for * rising and falling thresholds. AND mode is covered when both * upper and lower count is non-zero, and is signaled with * IIO_EV_DIR_EITHER.
*/ if (upper_count && !lower_count)
dir = IIO_EV_DIR_RISING; elseif (!upper_count && lower_count)
dir = IIO_EV_DIR_FALLING; else
dir = IIO_EV_DIR_EITHER;
/* * The OR mode will always trigger when the AND mode does, but * not vice versa. However, it seems like the AND bit needs to * be cleared if data capture _and_ threshold count interrupts * are desirable, even though it hasn't explicitly been selected * (with IRS_REG_INTR). Either way, it doesn't hurt...
*/
clear |= BIT(IRS_INTR_COUNT_THR_OR) |
BIT(IRS_INTR_COUNT_THR_AND);
}
if (!clear) return IRQ_NONE;
ret = regmap_write(data->regmap, IRS_REG_STATUS, clear); if (ret)
dev_err(data->dev, "Could not clear interrupt status (%d)\n", ret);
ret = regmap_field_write(data->regfields[IRS_REGF_INTR_DATA], state); if (ret) {
dev_err(data->dev, "Could not %s data interrupt source (%d)\n",
str_enable_disable(state), ret);
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) return dev_err_probe(&client->dev, -ENOMEM, "Could not allocate iio device\n");
data = iio_priv(indio_dev);
data->dev = &client->dev;
data->regmap = devm_regmap_init_i2c(client, &irsd200_regmap_config); if (IS_ERR(data->regmap)) return dev_err_probe(data->dev, PTR_ERR(data->regmap), "Could not initialize regmap\n");
for (i = 0; i < IRS_REGF_MAX; ++i) {
data->regfields[i] = devm_regmap_field_alloc(
data->dev, data->regmap, irsd200_regfields[i]); if (IS_ERR(data->regfields[i])) return dev_err_probe(
data->dev, PTR_ERR(data->regfields[i]), "Could not allocate register field %zu\n", i);
}
ret = devm_regulator_get_enable(data->dev, "vdd"); if (ret) return dev_err_probe(data->dev, ret, "Could not get and enable regulator\n");
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.