cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ad7091r-base.c (6560B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * AD7091RX Analog to Digital converter driver
      4 *
      5 * Copyright 2014-2019 Analog Devices Inc.
      6 */
      7
      8#include <linux/bitops.h>
      9#include <linux/iio/events.h>
     10#include <linux/iio/iio.h>
     11#include <linux/interrupt.h>
     12#include <linux/module.h>
     13#include <linux/regmap.h>
     14#include <linux/regulator/consumer.h>
     15
     16#include "ad7091r-base.h"
     17
     18#define AD7091R_REG_RESULT  0
     19#define AD7091R_REG_CHANNEL 1
     20#define AD7091R_REG_CONF    2
     21#define AD7091R_REG_ALERT   3
     22#define AD7091R_REG_CH_LOW_LIMIT(ch) ((ch) * 3 + 4)
     23#define AD7091R_REG_CH_HIGH_LIMIT(ch) ((ch) * 3 + 5)
     24#define AD7091R_REG_CH_HYSTERESIS(ch) ((ch) * 3 + 6)
     25
     26/* AD7091R_REG_RESULT */
     27#define AD7091R_REG_RESULT_CH_ID(x)	    (((x) >> 13) & 0x3)
     28#define AD7091R_REG_RESULT_CONV_RESULT(x)   ((x) & 0xfff)
     29
     30/* AD7091R_REG_CONF */
     31#define AD7091R_REG_CONF_AUTO   BIT(8)
     32#define AD7091R_REG_CONF_CMD    BIT(10)
     33
     34#define AD7091R_REG_CONF_MODE_MASK  \
     35	(AD7091R_REG_CONF_AUTO | AD7091R_REG_CONF_CMD)
     36
     37enum ad7091r_mode {
     38	AD7091R_MODE_SAMPLE,
     39	AD7091R_MODE_COMMAND,
     40	AD7091R_MODE_AUTOCYCLE,
     41};
     42
     43struct ad7091r_state {
     44	struct device *dev;
     45	struct regmap *map;
     46	struct regulator *vref;
     47	const struct ad7091r_chip_info *chip_info;
     48	enum ad7091r_mode mode;
     49	struct mutex lock; /*lock to prevent concurent reads */
     50};
     51
     52static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode)
     53{
     54	int ret, conf;
     55
     56	switch (mode) {
     57	case AD7091R_MODE_SAMPLE:
     58		conf = 0;
     59		break;
     60	case AD7091R_MODE_COMMAND:
     61		conf = AD7091R_REG_CONF_CMD;
     62		break;
     63	case AD7091R_MODE_AUTOCYCLE:
     64		conf = AD7091R_REG_CONF_AUTO;
     65		break;
     66	default:
     67		return -EINVAL;
     68	}
     69
     70	ret = regmap_update_bits(st->map, AD7091R_REG_CONF,
     71				 AD7091R_REG_CONF_MODE_MASK, conf);
     72	if (ret)
     73		return ret;
     74
     75	st->mode = mode;
     76
     77	return 0;
     78}
     79
     80static int ad7091r_set_channel(struct ad7091r_state *st, unsigned int channel)
     81{
     82	unsigned int dummy;
     83	int ret;
     84
     85	/* AD7091R_REG_CHANNEL specified which channels to be converted */
     86	ret = regmap_write(st->map, AD7091R_REG_CHANNEL,
     87			BIT(channel) | (BIT(channel) << 8));
     88	if (ret)
     89		return ret;
     90
     91	/*
     92	 * There is a latency of one conversion before the channel conversion
     93	 * sequence is updated
     94	 */
     95	return regmap_read(st->map, AD7091R_REG_RESULT, &dummy);
     96}
     97
     98static int ad7091r_read_one(struct iio_dev *iio_dev,
     99		unsigned int channel, unsigned int *read_val)
    100{
    101	struct ad7091r_state *st = iio_priv(iio_dev);
    102	unsigned int val;
    103	int ret;
    104
    105	ret = ad7091r_set_channel(st, channel);
    106	if (ret)
    107		return ret;
    108
    109	ret = regmap_read(st->map, AD7091R_REG_RESULT, &val);
    110	if (ret)
    111		return ret;
    112
    113	if (AD7091R_REG_RESULT_CH_ID(val) != channel)
    114		return -EIO;
    115
    116	*read_val = AD7091R_REG_RESULT_CONV_RESULT(val);
    117
    118	return 0;
    119}
    120
    121static int ad7091r_read_raw(struct iio_dev *iio_dev,
    122			   struct iio_chan_spec const *chan,
    123			   int *val, int *val2, long m)
    124{
    125	struct ad7091r_state *st = iio_priv(iio_dev);
    126	unsigned int read_val;
    127	int ret;
    128
    129	mutex_lock(&st->lock);
    130
    131	switch (m) {
    132	case IIO_CHAN_INFO_RAW:
    133		if (st->mode != AD7091R_MODE_COMMAND) {
    134			ret = -EBUSY;
    135			goto unlock;
    136		}
    137
    138		ret = ad7091r_read_one(iio_dev, chan->channel, &read_val);
    139		if (ret)
    140			goto unlock;
    141
    142		*val = read_val;
    143		ret = IIO_VAL_INT;
    144		break;
    145
    146	case IIO_CHAN_INFO_SCALE:
    147		if (st->vref) {
    148			ret = regulator_get_voltage(st->vref);
    149			if (ret < 0)
    150				goto unlock;
    151
    152			*val = ret / 1000;
    153		} else {
    154			*val = st->chip_info->vref_mV;
    155		}
    156
    157		*val2 = chan->scan_type.realbits;
    158		ret = IIO_VAL_FRACTIONAL_LOG2;
    159		break;
    160
    161	default:
    162		ret = -EINVAL;
    163		break;
    164	}
    165
    166unlock:
    167	mutex_unlock(&st->lock);
    168	return ret;
    169}
    170
    171static const struct iio_info ad7091r_info = {
    172	.read_raw = ad7091r_read_raw,
    173};
    174
    175static irqreturn_t ad7091r_event_handler(int irq, void *private)
    176{
    177	struct ad7091r_state *st = (struct ad7091r_state *) private;
    178	struct iio_dev *iio_dev = dev_get_drvdata(st->dev);
    179	unsigned int i, read_val;
    180	int ret;
    181	s64 timestamp = iio_get_time_ns(iio_dev);
    182
    183	ret = regmap_read(st->map, AD7091R_REG_ALERT, &read_val);
    184	if (ret)
    185		return IRQ_HANDLED;
    186
    187	for (i = 0; i < st->chip_info->num_channels; i++) {
    188		if (read_val & BIT(i * 2))
    189			iio_push_event(iio_dev,
    190					IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,
    191						IIO_EV_TYPE_THRESH,
    192						IIO_EV_DIR_RISING), timestamp);
    193		if (read_val & BIT(i * 2 + 1))
    194			iio_push_event(iio_dev,
    195					IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,
    196						IIO_EV_TYPE_THRESH,
    197						IIO_EV_DIR_FALLING), timestamp);
    198	}
    199
    200	return IRQ_HANDLED;
    201}
    202
    203static void ad7091r_remove(void *data)
    204{
    205	struct ad7091r_state *st = data;
    206
    207	regulator_disable(st->vref);
    208}
    209
    210int ad7091r_probe(struct device *dev, const char *name,
    211		const struct ad7091r_chip_info *chip_info,
    212		struct regmap *map, int irq)
    213{
    214	struct iio_dev *iio_dev;
    215	struct ad7091r_state *st;
    216	int ret;
    217
    218	iio_dev = devm_iio_device_alloc(dev, sizeof(*st));
    219	if (!iio_dev)
    220		return -ENOMEM;
    221
    222	st = iio_priv(iio_dev);
    223	st->dev = dev;
    224	st->chip_info = chip_info;
    225	st->map = map;
    226
    227	iio_dev->name = name;
    228	iio_dev->info = &ad7091r_info;
    229	iio_dev->modes = INDIO_DIRECT_MODE;
    230
    231	iio_dev->num_channels = chip_info->num_channels;
    232	iio_dev->channels = chip_info->channels;
    233
    234	if (irq) {
    235		ret = devm_request_threaded_irq(dev, irq, NULL,
    236				ad7091r_event_handler,
    237				IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, st);
    238		if (ret)
    239			return ret;
    240	}
    241
    242	st->vref = devm_regulator_get_optional(dev, "vref");
    243	if (IS_ERR(st->vref)) {
    244		if (PTR_ERR(st->vref) == -EPROBE_DEFER)
    245			return -EPROBE_DEFER;
    246		st->vref = NULL;
    247	} else {
    248		ret = regulator_enable(st->vref);
    249		if (ret)
    250			return ret;
    251		ret = devm_add_action_or_reset(dev, ad7091r_remove, st);
    252		if (ret)
    253			return ret;
    254	}
    255
    256	/* Use command mode by default to convert only desired channels*/
    257	ret = ad7091r_set_mode(st, AD7091R_MODE_COMMAND);
    258	if (ret)
    259		return ret;
    260
    261	return devm_iio_device_register(dev, iio_dev);
    262}
    263EXPORT_SYMBOL_NS_GPL(ad7091r_probe, IIO_AD7091R);
    264
    265static bool ad7091r_writeable_reg(struct device *dev, unsigned int reg)
    266{
    267	switch (reg) {
    268	case AD7091R_REG_RESULT:
    269	case AD7091R_REG_ALERT:
    270		return false;
    271	default:
    272		return true;
    273	}
    274}
    275
    276static bool ad7091r_volatile_reg(struct device *dev, unsigned int reg)
    277{
    278	switch (reg) {
    279	case AD7091R_REG_RESULT:
    280	case AD7091R_REG_ALERT:
    281		return true;
    282	default:
    283		return false;
    284	}
    285}
    286
    287const struct regmap_config ad7091r_regmap_config = {
    288	.reg_bits = 8,
    289	.val_bits = 16,
    290	.writeable_reg = ad7091r_writeable_reg,
    291	.volatile_reg = ad7091r_volatile_reg,
    292};
    293EXPORT_SYMBOL_NS_GPL(ad7091r_regmap_config, IIO_AD7091R);
    294
    295MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>");
    296MODULE_DESCRIPTION("Analog Devices AD7091Rx multi-channel converters");
    297MODULE_LICENSE("GPL v2");