| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * ROHM ADC driver for BD79124 ADC/GPO device
- * https://fscdn.rohm.com/en/products/databook/datasheet/ic/data_converter/dac/bd79124muf-c-e.pdf
- *
- * Copyright (c) 2025, ROHM Semiconductor.
- */
- #include <linux/array_size.h>
- #include <linux/bitfield.h>
- #include <linux/bitmap.h>
- #include <linux/bits.h>
- #include <linux/device.h>
- #include <linux/delay.h>
- #include <linux/devm-helpers.h>
- #include <linux/err.h>
- #include <linux/gpio/driver.h>
- #include <linux/i2c.h>
- #include <linux/interrupt.h>
- #include <linux/irqreturn.h>
- #include <linux/module.h>
- #include <linux/mod_devicetable.h>
- #include <linux/regmap.h>
- #include <linux/types.h>
- #include <asm/byteorder.h>
- #include <linux/iio/events.h>
- #include <linux/iio/iio.h>
- #include <linux/iio/adc-helpers.h>
- #define BD79124_I2C_MULTI_READ 0x30
- #define BD79124_I2C_MULTI_WRITE 0x28
- #define BD79124_REG_MAX 0xaf
- #define BD79124_REG_SYSTEM_STATUS 0x00
- #define BD79124_REG_GEN_CFG 0x01
- #define BD79124_REG_OPMODE_CFG 0x04
- #define BD79124_REG_PINCFG 0x05
- #define BD79124_REG_GPO_VAL 0x0B
- #define BD79124_REG_SEQ_CFG 0x10
- #define BD79124_REG_MANUAL_CHANNELS 0x11
- #define BD79124_REG_AUTO_CHANNELS 0x12
- #define BD79124_REG_ALERT_CH_SEL 0x14
- #define BD79124_REG_EVENT_FLAG 0x18
- #define BD79124_REG_EVENT_FLAG_HI 0x1a
- #define BD79124_REG_EVENT_FLAG_LO 0x1c
- #define BD79124_REG_HYSTERESIS_CH0 0x20
- #define BD79124_REG_EVENTCOUNT_CH0 0x22
- #define BD79124_REG_RECENT_CH0_LSB 0xa0
- #define BD79124_REG_RECENT_CH7_MSB 0xaf
- #define BD79124_ADC_BITS 12
- /* Masks for the BD79124_REG_OPMODE_CFG */
- #define BD79124_MSK_CONV_MODE GENMASK(6, 5)
- #define BD79124_CONV_MODE_MANSEQ 0
- #define BD79124_CONV_MODE_AUTO 1
- #define BD79124_MSK_AUTO_INTERVAL GENMASK(1, 0)
- #define BD79124_INTERVAL_750_US 0
- /* Masks for the BD79124_REG_GEN_CFG */
- #define BD79124_MSK_DWC_EN BIT(4)
- #define BD79124_MSK_STATS_EN BIT(5)
- /* Masks for the BD79124_REG_SEQ_CFG */
- #define BD79124_MSK_SEQ_START BIT(4)
- #define BD79124_MSK_SEQ_MODE GENMASK(1, 0)
- #define BD79124_MSK_SEQ_MANUAL 0
- #define BD79124_MSK_SEQ_SEQ 1
- #define BD79124_MSK_HYSTERESIS GENMASK(3, 0)
- #define BD79124_LOW_LIMIT_MIN 0
- #define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0)
- /*
- * The high limit, low limit and last measurement result are each stored in
- * 2 consequtive registers. 4 bits are in the high bits of the first register
- * and 8 bits in the next register.
- *
- * These macros return the address of the first reg for the given channel.
- */
- #define BD79124_GET_HIGH_LIMIT_REG(ch) (BD79124_REG_HYSTERESIS_CH0 + (ch) * 4)
- #define BD79124_GET_LOW_LIMIT_REG(ch) (BD79124_REG_EVENTCOUNT_CH0 + (ch) * 4)
- #define BD79124_GET_LIMIT_REG(ch, dir) ((dir) == IIO_EV_DIR_RISING ? \
- BD79124_GET_HIGH_LIMIT_REG(ch) : BD79124_GET_LOW_LIMIT_REG(ch))
- #define BD79124_GET_RECENT_RES_REG(ch) (BD79124_REG_RECENT_CH0_LSB + (ch) * 2)
- /*
- * The hysteresis for a channel is stored in the same register where the
- * 4 bits of high limit reside.
- */
- #define BD79124_GET_HYSTERESIS_REG(ch) BD79124_GET_HIGH_LIMIT_REG(ch)
- #define BD79124_MAX_NUM_CHANNELS 8
- struct bd79124_data {
- s64 timestamp;
- struct regmap *map;
- struct device *dev;
- int vmax;
- /*
- * Keep measurement status so read_raw() knows if the measurement needs
- * to be started.
- */
- int alarm_monitored[BD79124_MAX_NUM_CHANNELS];
- /*
- * The BD79124 does not allow disabling/enabling limit separately for
- * one direction only. Hence, we do the disabling by changing the limit
- * to maximum/minimum measurable value. This means we need to cache
- * the limit in order to maintain it over the time limit is disabled.
- */
- u16 alarm_r_limit[BD79124_MAX_NUM_CHANNELS];
- u16 alarm_f_limit[BD79124_MAX_NUM_CHANNELS];
- /* Bitmask of disabled events (for rate limiting) for each channel. */
- int alarm_suppressed[BD79124_MAX_NUM_CHANNELS];
- /*
- * The BD79124 is configured to run the measurements in the background.
- * This is done for the event monitoring as well as for the read_raw().
- * Protect the measurement starting/stopping using a mutex.
- */
- struct mutex mutex;
- struct delayed_work alm_enable_work;
- struct gpio_chip gc;
- u8 gpio_valid_mask;
- };
- static const struct regmap_range bd79124_ro_ranges[] = {
- regmap_reg_range(BD79124_REG_EVENT_FLAG, BD79124_REG_EVENT_FLAG),
- regmap_reg_range(BD79124_REG_RECENT_CH0_LSB, BD79124_REG_RECENT_CH7_MSB),
- };
- static const struct regmap_access_table bd79124_ro_regs = {
- .no_ranges = &bd79124_ro_ranges[0],
- .n_no_ranges = ARRAY_SIZE(bd79124_ro_ranges),
- };
- static const struct regmap_range bd79124_volatile_ranges[] = {
- regmap_reg_range(BD79124_REG_RECENT_CH0_LSB, BD79124_REG_RECENT_CH7_MSB),
- regmap_reg_range(BD79124_REG_EVENT_FLAG, BD79124_REG_EVENT_FLAG),
- regmap_reg_range(BD79124_REG_EVENT_FLAG_HI, BD79124_REG_EVENT_FLAG_HI),
- regmap_reg_range(BD79124_REG_EVENT_FLAG_LO, BD79124_REG_EVENT_FLAG_LO),
- regmap_reg_range(BD79124_REG_SYSTEM_STATUS, BD79124_REG_SYSTEM_STATUS),
- };
- static const struct regmap_access_table bd79124_volatile_regs = {
- .yes_ranges = &bd79124_volatile_ranges[0],
- .n_yes_ranges = ARRAY_SIZE(bd79124_volatile_ranges),
- };
- static const struct regmap_range bd79124_precious_ranges[] = {
- regmap_reg_range(BD79124_REG_EVENT_FLAG_HI, BD79124_REG_EVENT_FLAG_HI),
- regmap_reg_range(BD79124_REG_EVENT_FLAG_LO, BD79124_REG_EVENT_FLAG_LO),
- };
- static const struct regmap_access_table bd79124_precious_regs = {
- .yes_ranges = &bd79124_precious_ranges[0],
- .n_yes_ranges = ARRAY_SIZE(bd79124_precious_ranges),
- };
- static const struct regmap_config bd79124_regmap = {
- .reg_bits = 16,
- .val_bits = 8,
- .read_flag_mask = BD79124_I2C_MULTI_READ,
- .write_flag_mask = BD79124_I2C_MULTI_WRITE,
- .max_register = BD79124_REG_MAX,
- .cache_type = REGCACHE_MAPLE,
- .volatile_table = &bd79124_volatile_regs,
- .wr_table = &bd79124_ro_regs,
- .precious_table = &bd79124_precious_regs,
- };
- static int bd79124gpo_direction_get(struct gpio_chip *gc, unsigned int offset)
- {
- return GPIO_LINE_DIRECTION_OUT;
- }
- static int bd79124gpo_set(struct gpio_chip *gc, unsigned int offset, int value)
- {
- struct bd79124_data *data = gpiochip_get_data(gc);
- return regmap_assign_bits(data->map, BD79124_REG_GPO_VAL, BIT(offset),
- value);
- }
- static int bd79124gpo_set_multiple(struct gpio_chip *gc, unsigned long *mask,
- unsigned long *bits)
- {
- unsigned int all_gpos;
- int ret;
- struct bd79124_data *data = gpiochip_get_data(gc);
- /*
- * Ensure all GPIOs in 'mask' are set to be GPIOs
- * The valid_mask was not obeyed by the gpiolib in all cases prior the
- * https://lore.kernel.org/all/cd5e067b80e1bb590027bc3bfa817e7f794f21c3.1741180097.git.mazziesaccount@gmail.com/
- *
- * Keep this check here for a couple of cycles.
- */
- ret = regmap_read(data->map, BD79124_REG_PINCFG, &all_gpos);
- if (ret)
- return ret;
- if (all_gpos ^ *mask) {
- dev_dbg(data->dev, "Invalid mux config. Can't set value.\n");
- return -EINVAL;
- }
- return regmap_update_bits(data->map, BD79124_REG_GPO_VAL, *mask, *bits);
- }
- static int bd79124_init_valid_mask(struct gpio_chip *gc,
- unsigned long *valid_mask,
- unsigned int ngpios)
- {
- struct bd79124_data *data = gpiochip_get_data(gc);
- *valid_mask = data->gpio_valid_mask;
- return 0;
- }
- /* Template for GPIO chip */
- static const struct gpio_chip bd79124gpo_chip = {
- .label = "bd79124-gpo",
- .get_direction = bd79124gpo_direction_get,
- .set = bd79124gpo_set,
- .set_multiple = bd79124gpo_set_multiple,
- .init_valid_mask = bd79124_init_valid_mask,
- .can_sleep = true,
- .ngpio = 8,
- .base = -1,
- };
- struct bd79124_raw {
- u8 val_bit3_0; /* Is set in high bits of the byte */
- u8 val_bit11_4;
- };
- #define BD79124_RAW_TO_INT(r) ((r.val_bit11_4 << 4) | (r.val_bit3_0 >> 4))
- #define BD79124_INT_TO_RAW(val) { \
- .val_bit11_4 = (val) >> 4, \
- .val_bit3_0 = (val) << 4, \
- }
- /*
- * The high and low limits as well as the recent result values are stored in
- * the same way in 2 consequent registers. The first register contains 4 bits
- * of the value. These bits are stored in the high bits [7:4] of register, but
- * they represent the low bits [3:0] of the value.
- * The value bits [11:4] are stored in the next register.
- *
- * Read data from register and convert to integer.
- */
- static int bd79124_read_reg_to_int(struct bd79124_data *data, int reg,
- unsigned int *val)
- {
- int ret;
- struct bd79124_raw raw;
- ret = regmap_bulk_read(data->map, reg, &raw, sizeof(raw));
- if (ret) {
- dev_dbg(data->dev, "bulk_read failed %d\n", ret);
- return ret;
- }
- *val = BD79124_RAW_TO_INT(raw);
- return 0;
- }
- /*
- * The high and low limits as well as the recent result values are stored in
- * the same way in 2 consequent registers. The first register contains 4 bits
- * of the value. These bits are stored in the high bits [7:4] of register, but
- * they represent the low bits [3:0] of the value.
- * The value bits [11:4] are stored in the next register.
- *
- * Convert the integer to register format and write it using rmw cycle.
- */
- static int bd79124_write_int_to_reg(struct bd79124_data *data, int reg,
- unsigned int val)
- {
- struct bd79124_raw raw = BD79124_INT_TO_RAW(val);
- unsigned int tmp;
- int ret;
- ret = regmap_read(data->map, reg, &tmp);
- if (ret)
- return ret;
- raw.val_bit3_0 |= (tmp & 0xf);
- return regmap_bulk_write(data->map, reg, &raw, sizeof(raw));
- }
- static const struct iio_event_spec bd79124_events[] = {
- {
- .type = IIO_EV_TYPE_THRESH,
- .dir = IIO_EV_DIR_RISING,
- .mask_separate = BIT(IIO_EV_INFO_VALUE) |
- BIT(IIO_EV_INFO_ENABLE),
- },
- {
- .type = IIO_EV_TYPE_THRESH,
- .dir = IIO_EV_DIR_FALLING,
- .mask_separate = BIT(IIO_EV_INFO_VALUE) |
- BIT(IIO_EV_INFO_ENABLE),
- },
- {
- .type = IIO_EV_TYPE_THRESH,
- .dir = IIO_EV_DIR_EITHER,
- .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
- },
- };
- static const struct iio_chan_spec bd79124_chan_template_noirq = {
- .type = IIO_VOLTAGE,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
- .indexed = 1,
- };
- static const struct iio_chan_spec bd79124_chan_template = {
- .type = IIO_VOLTAGE,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
- .indexed = 1,
- .event_spec = bd79124_events,
- .num_event_specs = ARRAY_SIZE(bd79124_events),
- };
- static int bd79124_read_event_value(struct iio_dev *iio_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 bd79124_data *data = iio_priv(iio_dev);
- int ret, reg;
- if (chan->channel >= BD79124_MAX_NUM_CHANNELS)
- return -EINVAL;
- switch (info) {
- case IIO_EV_INFO_VALUE:
- if (dir == IIO_EV_DIR_RISING)
- *val = data->alarm_r_limit[chan->channel];
- else if (dir == IIO_EV_DIR_FALLING)
- *val = data->alarm_f_limit[chan->channel];
- else
- return -EINVAL;
- return IIO_VAL_INT;
- case IIO_EV_INFO_HYSTERESIS:
- reg = BD79124_GET_HYSTERESIS_REG(chan->channel);
- ret = regmap_read(data->map, reg, val);
- if (ret)
- return ret;
- *val &= BD79124_MSK_HYSTERESIS;
- /*
- * The data-sheet says the hysteresis register value needs to be
- * shifted left by 3.
- */
- *val <<= 3;
- return IIO_VAL_INT;
- default:
- return -EINVAL;
- }
- }
- static int bd79124_start_measurement(struct bd79124_data *data, int chan)
- {
- unsigned int val, regval;
- int ret;
- /* See if already started */
- ret = regmap_read(data->map, BD79124_REG_AUTO_CHANNELS, &val);
- if (val & BIT(chan))
- return 0;
- /*
- * The sequencer must be stopped when channels are added/removed from
- * the list of the measured channels to ensure the new channel
- * configuration is used.
- */
- ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_START);
- if (ret)
- return ret;
- ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, val | BIT(chan));
- if (ret)
- return ret;
- ret = regmap_set_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_START);
- if (ret)
- return ret;
- /*
- * Start the measurement at the background. Don't bother checking if
- * it was started, regmap has cache.
- */
- regval = FIELD_PREP(BD79124_MSK_CONV_MODE, BD79124_CONV_MODE_AUTO);
- return regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG,
- BD79124_MSK_CONV_MODE, regval);
- }
- static int bd79124_stop_measurement(struct bd79124_data *data, int chan)
- {
- unsigned int enabled_chans;
- int ret;
- /* See if already stopped */
- ret = regmap_read(data->map, BD79124_REG_AUTO_CHANNELS, &enabled_chans);
- if (!(enabled_chans & BIT(chan)))
- return 0;
- ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_START);
- /* Clear the channel from the measured channels */
- enabled_chans &= ~BIT(chan);
- ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS,
- enabled_chans);
- if (ret)
- return ret;
- /*
- * Stop background conversion for power saving if it was the last
- * channel.
- */
- if (!enabled_chans) {
- int regval = FIELD_PREP(BD79124_MSK_CONV_MODE,
- BD79124_CONV_MODE_MANSEQ);
- ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG,
- BD79124_MSK_CONV_MODE, regval);
- if (ret)
- return ret;
- }
- return regmap_set_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_START);
- }
- static int bd79124_read_event_config(struct iio_dev *iio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir)
- {
- struct bd79124_data *data = iio_priv(iio_dev);
- if (chan->channel >= BD79124_MAX_NUM_CHANNELS)
- return -EINVAL;
- return !!(data->alarm_monitored[chan->channel] & BIT(dir));
- }
- static int bd79124_disable_event(struct bd79124_data *data,
- enum iio_event_direction dir, int channel)
- {
- int dir_bit = BIT(dir);
- int reg;
- unsigned int limit;
- guard(mutex)(&data->mutex);
- /*
- * Set thresholds either to 0 or to 2^12 - 1 as appropriate to prevent
- * alerts and thus disable event generation.
- */
- if (dir == IIO_EV_DIR_RISING) {
- reg = BD79124_GET_HIGH_LIMIT_REG(channel);
- limit = BD79124_HIGH_LIMIT_MAX;
- } else if (dir == IIO_EV_DIR_FALLING) {
- reg = BD79124_GET_LOW_LIMIT_REG(channel);
- limit = BD79124_LOW_LIMIT_MIN;
- } else {
- return -EINVAL;
- }
- data->alarm_monitored[channel] &= ~dir_bit;
- /*
- * Stop measurement if there is no more events to monitor.
- * We don't bother checking the retval because the limit
- * setting should in any case effectively disable the alarm.
- */
- if (!data->alarm_monitored[channel]) {
- bd79124_stop_measurement(data, channel);
- regmap_clear_bits(data->map, BD79124_REG_ALERT_CH_SEL,
- BIT(channel));
- }
- return bd79124_write_int_to_reg(data, reg, limit);
- }
- static int bd79124_enable_event(struct bd79124_data *data,
- enum iio_event_direction dir,
- unsigned int channel)
- {
- int dir_bit = BIT(dir);
- int reg, ret;
- u16 *limit;
- guard(mutex)(&data->mutex);
- ret = bd79124_start_measurement(data, channel);
- if (ret)
- return ret;
- data->alarm_monitored[channel] |= dir_bit;
- /* Add the channel to the list of monitored channels */
- ret = regmap_set_bits(data->map, BD79124_REG_ALERT_CH_SEL, BIT(channel));
- if (ret)
- return ret;
- if (dir == IIO_EV_DIR_RISING) {
- limit = &data->alarm_f_limit[channel];
- reg = BD79124_GET_HIGH_LIMIT_REG(channel);
- } else {
- limit = &data->alarm_f_limit[channel];
- reg = BD79124_GET_LOW_LIMIT_REG(channel);
- }
- /*
- * Don't write the new limit to the hardware if we are in the
- * rate-limit period. The timer which re-enables the event will set
- * the limit.
- */
- if (!(data->alarm_suppressed[channel] & dir_bit)) {
- ret = bd79124_write_int_to_reg(data, reg, *limit);
- if (ret)
- return ret;
- }
- /*
- * Enable comparator. Trust the regmap cache, no need to check
- * if it was already enabled.
- *
- * We could do this in the hw-init, but there may be users who
- * never enable alarms and for them it makes sense to not
- * enable the comparator at probe.
- */
- return regmap_set_bits(data->map, BD79124_REG_GEN_CFG,
- BD79124_MSK_DWC_EN);
- }
- static int bd79124_write_event_config(struct iio_dev *iio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir, bool state)
- {
- struct bd79124_data *data = iio_priv(iio_dev);
- if (chan->channel >= BD79124_MAX_NUM_CHANNELS)
- return -EINVAL;
- if (state)
- return bd79124_enable_event(data, dir, chan->channel);
- return bd79124_disable_event(data, dir, chan->channel);
- }
- static int bd79124_write_event_value(struct iio_dev *iio_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 bd79124_data *data = iio_priv(iio_dev);
- int reg;
- if (chan->channel >= BD79124_MAX_NUM_CHANNELS)
- return -EINVAL;
- switch (info) {
- case IIO_EV_INFO_VALUE:
- {
- guard(mutex)(&data->mutex);
- if (dir == IIO_EV_DIR_RISING) {
- data->alarm_r_limit[chan->channel] = val;
- reg = BD79124_GET_HIGH_LIMIT_REG(chan->channel);
- } else if (dir == IIO_EV_DIR_FALLING) {
- data->alarm_f_limit[chan->channel] = val;
- reg = BD79124_GET_LOW_LIMIT_REG(chan->channel);
- } else {
- return -EINVAL;
- }
- /*
- * We don't want to enable the alarm if it is not enabled or
- * if it is suppressed. In that case skip writing to the
- * register.
- */
- if (!(data->alarm_monitored[chan->channel] & BIT(dir)) ||
- data->alarm_suppressed[chan->channel] & BIT(dir))
- return 0;
- return bd79124_write_int_to_reg(data, reg, val);
- }
- case IIO_EV_INFO_HYSTERESIS:
- reg = BD79124_GET_HYSTERESIS_REG(chan->channel);
- val >>= 3;
- return regmap_update_bits(data->map, reg, BD79124_MSK_HYSTERESIS,
- val);
- default:
- return -EINVAL;
- }
- }
- static int bd79124_single_chan_seq(struct bd79124_data *data, int chan, unsigned int *old)
- {
- int ret;
- ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_START);
- if (ret)
- return ret;
- /*
- * It may be we have some channels monitored for alarms so we want to
- * cache the old config and return it when the single channel
- * measurement has been completed.
- */
- ret = regmap_read(data->map, BD79124_REG_AUTO_CHANNELS, old);
- if (ret)
- return ret;
- ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, BIT(chan));
- if (ret)
- return ret;
- /* Restart the sequencer */
- return regmap_set_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_START);
- }
- static int bd79124_single_chan_seq_end(struct bd79124_data *data, unsigned int old)
- {
- int ret;
- ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_START);
- if (ret)
- return ret;
- ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, old);
- if (ret)
- return ret;
- return regmap_set_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_START);
- }
- static int bd79124_read_raw(struct iio_dev *iio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2, long m)
- {
- struct bd79124_data *data = iio_priv(iio_dev);
- int ret;
- if (chan->channel >= BD79124_MAX_NUM_CHANNELS)
- return -EINVAL;
- switch (m) {
- case IIO_CHAN_INFO_RAW:
- {
- unsigned int old_chan_cfg, regval;
- int tmp;
- guard(mutex)(&data->mutex);
- /*
- * Start the automatic conversion. This is needed here if no
- * events have been enabled.
- */
- regval = FIELD_PREP(BD79124_MSK_CONV_MODE,
- BD79124_CONV_MODE_AUTO);
- ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG,
- BD79124_MSK_CONV_MODE, regval);
- if (ret)
- return ret;
- ret = bd79124_single_chan_seq(data, chan->channel, &old_chan_cfg);
- if (ret)
- return ret;
- /* The maximum conversion time is 6 uS. */
- udelay(6);
- ret = bd79124_read_reg_to_int(data,
- BD79124_GET_RECENT_RES_REG(chan->channel), val);
- /*
- * Return the old chan config even if data reading failed in
- * order to re-enable the event monitoring.
- */
- tmp = bd79124_single_chan_seq_end(data, old_chan_cfg);
- if (tmp)
- dev_err(data->dev,
- "Failed to return config. Alarms may be disabled\n");
- if (ret)
- return ret;
- return IIO_VAL_INT;
- }
- case IIO_CHAN_INFO_SCALE:
- *val = data->vmax / 1000;
- *val2 = BD79124_ADC_BITS;
- return IIO_VAL_FRACTIONAL_LOG2;
- default:
- return -EINVAL;
- }
- }
- static const struct iio_info bd79124_info = {
- .read_raw = bd79124_read_raw,
- .read_event_config = &bd79124_read_event_config,
- .write_event_config = &bd79124_write_event_config,
- .read_event_value = &bd79124_read_event_value,
- .write_event_value = &bd79124_write_event_value,
- };
- static void bd79124_re_enable_lo(struct bd79124_data *data, unsigned int channel)
- {
- int ret, evbit = BIT(IIO_EV_DIR_FALLING);
- /*
- * We should not re-enable the event if user has disabled it while
- * rate-limiting was enabled.
- */
- if (!(data->alarm_suppressed[channel] & evbit))
- return;
- data->alarm_suppressed[channel] &= ~evbit;
- if (!(data->alarm_monitored[channel] & evbit))
- return;
- ret = bd79124_write_int_to_reg(data, BD79124_GET_LOW_LIMIT_REG(channel),
- data->alarm_f_limit[channel]);
- if (ret)
- dev_warn(data->dev, "Low limit enabling failed for channel%d\n",
- channel);
- }
- static void bd79124_re_enable_hi(struct bd79124_data *data, unsigned int channel)
- {
- int ret, evbit = BIT(IIO_EV_DIR_RISING);
- /*
- * We should not re-enable the event if user has disabled it while
- * rate-limiting was enabled.
- */
- if (!(data->alarm_suppressed[channel] & evbit))
- return;
- data->alarm_suppressed[channel] &= ~evbit;
- if (!(data->alarm_monitored[channel] & evbit))
- return;
- ret = bd79124_write_int_to_reg(data, BD79124_GET_HIGH_LIMIT_REG(channel),
- data->alarm_r_limit[channel]);
- if (ret)
- dev_warn(data->dev, "High limit enabling failed for channel%d\n",
- channel);
- }
- static void bd79124_alm_enable_worker(struct work_struct *work)
- {
- int i;
- struct bd79124_data *data = container_of(work, struct bd79124_data,
- alm_enable_work.work);
- /* Take the mutex so there is no race with user disabling the alarm */
- guard(mutex)(&data->mutex);
- for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) {
- bd79124_re_enable_hi(data, i);
- bd79124_re_enable_lo(data, i);
- }
- }
- static int __bd79124_event_ratelimit(struct bd79124_data *data, int reg,
- unsigned int limit)
- {
- int ret;
- if (limit > BD79124_HIGH_LIMIT_MAX)
- return -EINVAL;
- ret = bd79124_write_int_to_reg(data, reg, limit);
- if (ret)
- return ret;
- /*
- * We use 1 sec 'grace period'. At the moment I see no reason to make
- * this user configurable. We need an ABI for this if configuration is
- * needed.
- */
- schedule_delayed_work(&data->alm_enable_work, msecs_to_jiffies(1000));
- return 0;
- }
- static int bd79124_event_ratelimit_hi(struct bd79124_data *data,
- unsigned int channel)
- {
- guard(mutex)(&data->mutex);
- data->alarm_suppressed[channel] |= BIT(IIO_EV_DIR_RISING);
- return __bd79124_event_ratelimit(data,
- BD79124_GET_HIGH_LIMIT_REG(channel),
- BD79124_HIGH_LIMIT_MAX);
- }
- static int bd79124_event_ratelimit_lo(struct bd79124_data *data,
- unsigned int channel)
- {
- guard(mutex)(&data->mutex);
- data->alarm_suppressed[channel] |= BIT(IIO_EV_DIR_FALLING);
- return __bd79124_event_ratelimit(data,
- BD79124_GET_LOW_LIMIT_REG(channel),
- BD79124_LOW_LIMIT_MIN);
- }
- static irqreturn_t bd79124_event_handler(int irq, void *priv)
- {
- unsigned int i_hi, i_lo;
- int i, ret;
- struct iio_dev *iio_dev = priv;
- struct bd79124_data *data = iio_priv(iio_dev);
- /*
- * Return IRQ_NONE if bailing-out without acking. This allows the IRQ
- * subsystem to disable the offending IRQ line if we get a hardware
- * problem. This behaviour has saved my poor bottom a few times in the
- * past as, instead of getting unusably unresponsive, the system has
- * spilled out the magic words "...nobody cared".
- */
- ret = regmap_read(data->map, BD79124_REG_EVENT_FLAG_HI, &i_hi);
- if (ret)
- return IRQ_NONE;
- ret = regmap_read(data->map, BD79124_REG_EVENT_FLAG_LO, &i_lo);
- if (ret)
- return IRQ_NONE;
- if (!i_lo && !i_hi)
- return IRQ_NONE;
- for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) {
- u64 ecode;
- if (BIT(i) & i_hi) {
- ecode = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_RISING);
- iio_push_event(iio_dev, ecode, data->timestamp);
- /*
- * The BD79124 keeps the IRQ asserted for as long as
- * the voltage exceeds the threshold. It causes the IRQ
- * to keep firing.
- *
- * Disable the event for the channel and schedule the
- * re-enabling the event later to prevent storm of
- * events.
- */
- ret = bd79124_event_ratelimit_hi(data, i);
- if (ret)
- return IRQ_NONE;
- }
- if (BIT(i) & i_lo) {
- ecode = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_FALLING);
- iio_push_event(iio_dev, ecode, data->timestamp);
- ret = bd79124_event_ratelimit_lo(data, i);
- if (ret)
- return IRQ_NONE;
- }
- }
- ret = regmap_write(data->map, BD79124_REG_EVENT_FLAG_HI, i_hi);
- if (ret)
- return IRQ_NONE;
- ret = regmap_write(data->map, BD79124_REG_EVENT_FLAG_LO, i_lo);
- if (ret)
- return IRQ_NONE;
- return IRQ_HANDLED;
- }
- static irqreturn_t bd79124_irq_handler(int irq, void *priv)
- {
- struct iio_dev *iio_dev = priv;
- struct bd79124_data *data = iio_priv(iio_dev);
- data->timestamp = iio_get_time_ns(iio_dev);
- return IRQ_WAKE_THREAD;
- }
- static int bd79124_chan_init(struct bd79124_data *data, int channel)
- {
- int ret;
- ret = regmap_write(data->map, BD79124_GET_HIGH_LIMIT_REG(channel),
- BD79124_HIGH_LIMIT_MAX);
- if (ret)
- return ret;
- return regmap_write(data->map, BD79124_GET_LOW_LIMIT_REG(channel),
- BD79124_LOW_LIMIT_MIN);
- }
- static int bd79124_get_gpio_pins(const struct iio_chan_spec *cs, int num_channels)
- {
- int i, gpio_channels;
- /*
- * Let's initialize the mux config to say that all 8 channels are
- * GPIOs. Then we can just loop through the iio_chan_spec and clear the
- * bits for found ADC channels.
- */
- gpio_channels = GENMASK(7, 0);
- for (i = 0; i < num_channels; i++)
- gpio_channels &= ~BIT(cs[i].channel);
- return gpio_channels;
- }
- static int bd79124_hw_init(struct bd79124_data *data)
- {
- unsigned int regval;
- int ret, i;
- for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) {
- ret = bd79124_chan_init(data, i);
- if (ret)
- return ret;
- data->alarm_r_limit[i] = BD79124_HIGH_LIMIT_MAX;
- }
- /* Stop auto sequencer */
- ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_START);
- if (ret)
- return ret;
- /* Enable writing the measured values to the regsters */
- ret = regmap_set_bits(data->map, BD79124_REG_GEN_CFG,
- BD79124_MSK_STATS_EN);
- if (ret)
- return ret;
- /* Set no channels to be auto-measured */
- ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, 0x0);
- if (ret)
- return ret;
- /* Set no channels to be manually measured */
- ret = regmap_write(data->map, BD79124_REG_MANUAL_CHANNELS, 0x0);
- if (ret)
- return ret;
- regval = FIELD_PREP(BD79124_MSK_AUTO_INTERVAL, BD79124_INTERVAL_750_US);
- ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG,
- BD79124_MSK_AUTO_INTERVAL, regval);
- if (ret)
- return ret;
- /* Sequencer mode to auto */
- ret = regmap_set_bits(data->map, BD79124_REG_SEQ_CFG,
- BD79124_MSK_SEQ_SEQ);
- if (ret)
- return ret;
- /* Don't start the measurement */
- regval = FIELD_PREP(BD79124_MSK_CONV_MODE, BD79124_CONV_MODE_MANSEQ);
- return regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG,
- BD79124_MSK_CONV_MODE, regval);
- }
- static int bd79124_probe(struct i2c_client *i2c)
- {
- struct bd79124_data *data;
- struct iio_dev *iio_dev;
- const struct iio_chan_spec *template;
- struct iio_chan_spec *cs;
- struct device *dev = &i2c->dev;
- unsigned int gpio_pins;
- int ret;
- iio_dev = devm_iio_device_alloc(dev, sizeof(*data));
- if (!iio_dev)
- return -ENOMEM;
- data = iio_priv(iio_dev);
- data->dev = dev;
- data->map = devm_regmap_init_i2c(i2c, &bd79124_regmap);
- if (IS_ERR(data->map))
- return dev_err_probe(dev, PTR_ERR(data->map),
- "Failed to initialize Regmap\n");
- ret = devm_regulator_get_enable_read_voltage(dev, "vdd");
- if (ret < 0)
- return dev_err_probe(dev, ret, "Failed to get the Vdd\n");
- data->vmax = ret;
- ret = devm_regulator_get_enable(dev, "iovdd");
- if (ret < 0)
- return dev_err_probe(dev, ret, "Failed to enable I/O voltage\n");
- ret = devm_delayed_work_autocancel(dev, &data->alm_enable_work,
- bd79124_alm_enable_worker);
- if (ret)
- return ret;
- if (i2c->irq) {
- template = &bd79124_chan_template;
- } else {
- template = &bd79124_chan_template_noirq;
- dev_dbg(dev, "No IRQ found, events disabled\n");
- }
- ret = devm_mutex_init(dev, &data->mutex);
- if (ret)
- return ret;
- ret = devm_iio_adc_device_alloc_chaninfo_se(dev, template,
- BD79124_MAX_NUM_CHANNELS - 1, &cs);
- if (ret < 0) {
- /* Register all pins as GPOs if there are no ADC channels */
- if (ret == -ENOENT)
- goto register_gpios;
- return ret;
- }
- iio_dev->channels = cs;
- iio_dev->num_channels = ret;
- iio_dev->info = &bd79124_info;
- iio_dev->name = "bd79124";
- iio_dev->modes = INDIO_DIRECT_MODE;
- ret = bd79124_hw_init(data);
- if (ret)
- return ret;
- if (i2c->irq > 0) {
- ret = devm_request_threaded_irq(dev, i2c->irq,
- bd79124_irq_handler, &bd79124_event_handler,
- IRQF_ONESHOT, "adc-thresh-alert", iio_dev);
- if (ret)
- return dev_err_probe(data->dev, ret,
- "Failed to register IRQ\n");
- }
- ret = devm_iio_device_register(data->dev, iio_dev);
- if (ret)
- return dev_err_probe(data->dev, ret, "Failed to register ADC\n");
- register_gpios:
- gpio_pins = bd79124_get_gpio_pins(iio_dev->channels,
- iio_dev->num_channels);
- /*
- * The mux should default to "all ADCs", but better to not trust it.
- * Thus we do set the mux even when we have only ADCs and no GPOs.
- */
- ret = regmap_write(data->map, BD79124_REG_PINCFG, gpio_pins);
- if (ret)
- return ret;
- /* No GPOs if all channels are reserved for ADC, so we're done. */
- if (!gpio_pins)
- return 0;
- data->gpio_valid_mask = gpio_pins;
- data->gc = bd79124gpo_chip;
- data->gc.parent = dev;
- return devm_gpiochip_add_data(dev, &data->gc, data);
- }
- static const struct of_device_id bd79124_of_match[] = {
- { .compatible = "rohm,bd79124" },
- { }
- };
- MODULE_DEVICE_TABLE(of, bd79124_of_match);
- static const struct i2c_device_id bd79124_id[] = {
- { "bd79124" },
- { }
- };
- MODULE_DEVICE_TABLE(i2c, bd79124_id);
- static struct i2c_driver bd79124_driver = {
- .driver = {
- .name = "bd79124",
- .of_match_table = bd79124_of_match,
- },
- .probe = bd79124_probe,
- .id_table = bd79124_id,
- };
- module_i2c_driver(bd79124_driver);
- MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>");
- MODULE_DESCRIPTION("Driver for ROHM BD79124 ADC");
- MODULE_LICENSE("GPL");
- MODULE_IMPORT_NS("IIO_DRIVER");
|