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

ad7266.c (12729B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AD7266/65 SPI ADC driver
      4 *
      5 * Copyright 2012 Analog Devices Inc.
      6 */
      7
      8#include <linux/device.h>
      9#include <linux/kernel.h>
     10#include <linux/slab.h>
     11#include <linux/spi/spi.h>
     12#include <linux/regulator/consumer.h>
     13#include <linux/err.h>
     14#include <linux/gpio/consumer.h>
     15#include <linux/module.h>
     16
     17#include <linux/interrupt.h>
     18
     19#include <linux/iio/iio.h>
     20#include <linux/iio/buffer.h>
     21#include <linux/iio/trigger_consumer.h>
     22#include <linux/iio/triggered_buffer.h>
     23
     24#include <linux/platform_data/ad7266.h>
     25
     26struct ad7266_state {
     27	struct spi_device	*spi;
     28	struct regulator	*reg;
     29	unsigned long		vref_mv;
     30
     31	struct spi_transfer	single_xfer[3];
     32	struct spi_message	single_msg;
     33
     34	enum ad7266_range	range;
     35	enum ad7266_mode	mode;
     36	bool			fixed_addr;
     37	struct gpio_desc	*gpios[3];
     38
     39	/*
     40	 * DMA (thus cache coherency maintenance) requires the
     41	 * transfer buffers to live in their own cache lines.
     42	 * The buffer needs to be large enough to hold two samples (4 bytes) and
     43	 * the naturally aligned timestamp (8 bytes).
     44	 */
     45	struct {
     46		__be16 sample[2];
     47		s64 timestamp;
     48	} data ____cacheline_aligned;
     49};
     50
     51static int ad7266_wakeup(struct ad7266_state *st)
     52{
     53	/* Any read with >= 2 bytes will wake the device */
     54	return spi_read(st->spi, &st->data.sample[0], 2);
     55}
     56
     57static int ad7266_powerdown(struct ad7266_state *st)
     58{
     59	/* Any read with < 2 bytes will powerdown the device */
     60	return spi_read(st->spi, &st->data.sample[0], 1);
     61}
     62
     63static int ad7266_preenable(struct iio_dev *indio_dev)
     64{
     65	struct ad7266_state *st = iio_priv(indio_dev);
     66	return ad7266_wakeup(st);
     67}
     68
     69static int ad7266_postdisable(struct iio_dev *indio_dev)
     70{
     71	struct ad7266_state *st = iio_priv(indio_dev);
     72	return ad7266_powerdown(st);
     73}
     74
     75static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
     76	.preenable = &ad7266_preenable,
     77	.postdisable = &ad7266_postdisable,
     78};
     79
     80static irqreturn_t ad7266_trigger_handler(int irq, void *p)
     81{
     82	struct iio_poll_func *pf = p;
     83	struct iio_dev *indio_dev = pf->indio_dev;
     84	struct ad7266_state *st = iio_priv(indio_dev);
     85	int ret;
     86
     87	ret = spi_read(st->spi, st->data.sample, 4);
     88	if (ret == 0) {
     89		iio_push_to_buffers_with_timestamp(indio_dev, &st->data,
     90			    pf->timestamp);
     91	}
     92
     93	iio_trigger_notify_done(indio_dev->trig);
     94
     95	return IRQ_HANDLED;
     96}
     97
     98static void ad7266_select_input(struct ad7266_state *st, unsigned int nr)
     99{
    100	unsigned int i;
    101
    102	if (st->fixed_addr)
    103		return;
    104
    105	switch (st->mode) {
    106	case AD7266_MODE_SINGLE_ENDED:
    107		nr >>= 1;
    108		break;
    109	case AD7266_MODE_PSEUDO_DIFF:
    110		nr |= 1;
    111		break;
    112	case AD7266_MODE_DIFF:
    113		nr &= ~1;
    114		break;
    115	}
    116
    117	for (i = 0; i < 3; ++i)
    118		gpiod_set_value(st->gpios[i], (bool)(nr & BIT(i)));
    119}
    120
    121static int ad7266_update_scan_mode(struct iio_dev *indio_dev,
    122	const unsigned long *scan_mask)
    123{
    124	struct ad7266_state *st = iio_priv(indio_dev);
    125	unsigned int nr = find_first_bit(scan_mask, indio_dev->masklength);
    126
    127	ad7266_select_input(st, nr);
    128
    129	return 0;
    130}
    131
    132static int ad7266_read_single(struct ad7266_state *st, int *val,
    133	unsigned int address)
    134{
    135	int ret;
    136
    137	ad7266_select_input(st, address);
    138
    139	ret = spi_sync(st->spi, &st->single_msg);
    140	*val = be16_to_cpu(st->data.sample[address % 2]);
    141
    142	return ret;
    143}
    144
    145static int ad7266_read_raw(struct iio_dev *indio_dev,
    146	struct iio_chan_spec const *chan, int *val, int *val2, long m)
    147{
    148	struct ad7266_state *st = iio_priv(indio_dev);
    149	unsigned long scale_mv;
    150	int ret;
    151
    152	switch (m) {
    153	case IIO_CHAN_INFO_RAW:
    154		ret = iio_device_claim_direct_mode(indio_dev);
    155		if (ret)
    156			return ret;
    157		ret = ad7266_read_single(st, val, chan->address);
    158		iio_device_release_direct_mode(indio_dev);
    159
    160		*val = (*val >> 2) & 0xfff;
    161		if (chan->scan_type.sign == 's')
    162			*val = sign_extend32(*val,
    163					     chan->scan_type.realbits - 1);
    164
    165		return IIO_VAL_INT;
    166	case IIO_CHAN_INFO_SCALE:
    167		scale_mv = st->vref_mv;
    168		if (st->mode == AD7266_MODE_DIFF)
    169			scale_mv *= 2;
    170		if (st->range == AD7266_RANGE_2VREF)
    171			scale_mv *= 2;
    172
    173		*val = scale_mv;
    174		*val2 = chan->scan_type.realbits;
    175		return IIO_VAL_FRACTIONAL_LOG2;
    176	case IIO_CHAN_INFO_OFFSET:
    177		if (st->range == AD7266_RANGE_2VREF &&
    178			st->mode != AD7266_MODE_DIFF)
    179			*val = 2048;
    180		else
    181			*val = 0;
    182		return IIO_VAL_INT;
    183	}
    184	return -EINVAL;
    185}
    186
    187#define AD7266_CHAN(_chan, _sign) {			\
    188	.type = IIO_VOLTAGE,				\
    189	.indexed = 1,					\
    190	.channel = (_chan),				\
    191	.address = (_chan),				\
    192	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
    193	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
    194		| BIT(IIO_CHAN_INFO_OFFSET),			\
    195	.scan_index = (_chan),				\
    196	.scan_type = {					\
    197		.sign = (_sign),			\
    198		.realbits = 12,				\
    199		.storagebits = 16,			\
    200		.shift = 2,				\
    201		.endianness = IIO_BE,			\
    202	},						\
    203}
    204
    205#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS(_name, _sign) \
    206const struct iio_chan_spec ad7266_channels_##_name[] = { \
    207	AD7266_CHAN(0, (_sign)), \
    208	AD7266_CHAN(1, (_sign)), \
    209	AD7266_CHAN(2, (_sign)), \
    210	AD7266_CHAN(3, (_sign)), \
    211	AD7266_CHAN(4, (_sign)), \
    212	AD7266_CHAN(5, (_sign)), \
    213	AD7266_CHAN(6, (_sign)), \
    214	AD7266_CHAN(7, (_sign)), \
    215	AD7266_CHAN(8, (_sign)), \
    216	AD7266_CHAN(9, (_sign)), \
    217	AD7266_CHAN(10, (_sign)), \
    218	AD7266_CHAN(11, (_sign)), \
    219	IIO_CHAN_SOFT_TIMESTAMP(13), \
    220}
    221
    222#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(_name, _sign) \
    223const struct iio_chan_spec ad7266_channels_##_name##_fixed[] = { \
    224	AD7266_CHAN(0, (_sign)), \
    225	AD7266_CHAN(1, (_sign)), \
    226	IIO_CHAN_SOFT_TIMESTAMP(2), \
    227}
    228
    229static AD7266_DECLARE_SINGLE_ENDED_CHANNELS(u, 'u');
    230static AD7266_DECLARE_SINGLE_ENDED_CHANNELS(s, 's');
    231static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(u, 'u');
    232static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(s, 's');
    233
    234#define AD7266_CHAN_DIFF(_chan, _sign) {			\
    235	.type = IIO_VOLTAGE,				\
    236	.indexed = 1,					\
    237	.channel = (_chan) * 2,				\
    238	.channel2 = (_chan) * 2 + 1,			\
    239	.address = (_chan),				\
    240	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
    241	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
    242		| BIT(IIO_CHAN_INFO_OFFSET),			\
    243	.scan_index = (_chan),				\
    244	.scan_type = {					\
    245		.sign = _sign,			\
    246		.realbits = 12,				\
    247		.storagebits = 16,			\
    248		.shift = 2,				\
    249		.endianness = IIO_BE,			\
    250	},						\
    251	.differential = 1,				\
    252}
    253
    254#define AD7266_DECLARE_DIFF_CHANNELS(_name, _sign) \
    255const struct iio_chan_spec ad7266_channels_diff_##_name[] = { \
    256	AD7266_CHAN_DIFF(0, (_sign)), \
    257	AD7266_CHAN_DIFF(1, (_sign)), \
    258	AD7266_CHAN_DIFF(2, (_sign)), \
    259	AD7266_CHAN_DIFF(3, (_sign)), \
    260	AD7266_CHAN_DIFF(4, (_sign)), \
    261	AD7266_CHAN_DIFF(5, (_sign)), \
    262	IIO_CHAN_SOFT_TIMESTAMP(6), \
    263}
    264
    265static AD7266_DECLARE_DIFF_CHANNELS(s, 's');
    266static AD7266_DECLARE_DIFF_CHANNELS(u, 'u');
    267
    268#define AD7266_DECLARE_DIFF_CHANNELS_FIXED(_name, _sign) \
    269const struct iio_chan_spec ad7266_channels_diff_fixed_##_name[] = { \
    270	AD7266_CHAN_DIFF(0, (_sign)), \
    271	AD7266_CHAN_DIFF(1, (_sign)), \
    272	IIO_CHAN_SOFT_TIMESTAMP(2), \
    273}
    274
    275static AD7266_DECLARE_DIFF_CHANNELS_FIXED(s, 's');
    276static AD7266_DECLARE_DIFF_CHANNELS_FIXED(u, 'u');
    277
    278static const struct iio_info ad7266_info = {
    279	.read_raw = &ad7266_read_raw,
    280	.update_scan_mode = &ad7266_update_scan_mode,
    281};
    282
    283static const unsigned long ad7266_available_scan_masks[] = {
    284	0x003,
    285	0x00c,
    286	0x030,
    287	0x0c0,
    288	0x300,
    289	0xc00,
    290	0x000,
    291};
    292
    293static const unsigned long ad7266_available_scan_masks_diff[] = {
    294	0x003,
    295	0x00c,
    296	0x030,
    297	0x000,
    298};
    299
    300static const unsigned long ad7266_available_scan_masks_fixed[] = {
    301	0x003,
    302	0x000,
    303};
    304
    305struct ad7266_chan_info {
    306	const struct iio_chan_spec *channels;
    307	unsigned int num_channels;
    308	const unsigned long *scan_masks;
    309};
    310
    311#define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \
    312	(((_differential) << 2) | ((_signed) << 1) | ((_fixed) << 0))
    313
    314static const struct ad7266_chan_info ad7266_chan_infos[] = {
    315	[AD7266_CHAN_INFO_INDEX(0, 0, 0)] = {
    316		.channels = ad7266_channels_u,
    317		.num_channels = ARRAY_SIZE(ad7266_channels_u),
    318		.scan_masks = ad7266_available_scan_masks,
    319	},
    320	[AD7266_CHAN_INFO_INDEX(0, 0, 1)] = {
    321		.channels = ad7266_channels_u_fixed,
    322		.num_channels = ARRAY_SIZE(ad7266_channels_u_fixed),
    323		.scan_masks = ad7266_available_scan_masks_fixed,
    324	},
    325	[AD7266_CHAN_INFO_INDEX(0, 1, 0)] = {
    326		.channels = ad7266_channels_s,
    327		.num_channels = ARRAY_SIZE(ad7266_channels_s),
    328		.scan_masks = ad7266_available_scan_masks,
    329	},
    330	[AD7266_CHAN_INFO_INDEX(0, 1, 1)] = {
    331		.channels = ad7266_channels_s_fixed,
    332		.num_channels = ARRAY_SIZE(ad7266_channels_s_fixed),
    333		.scan_masks = ad7266_available_scan_masks_fixed,
    334	},
    335	[AD7266_CHAN_INFO_INDEX(1, 0, 0)] = {
    336		.channels = ad7266_channels_diff_u,
    337		.num_channels = ARRAY_SIZE(ad7266_channels_diff_u),
    338		.scan_masks = ad7266_available_scan_masks_diff,
    339	},
    340	[AD7266_CHAN_INFO_INDEX(1, 0, 1)] = {
    341		.channels = ad7266_channels_diff_fixed_u,
    342		.num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_u),
    343		.scan_masks = ad7266_available_scan_masks_fixed,
    344	},
    345	[AD7266_CHAN_INFO_INDEX(1, 1, 0)] = {
    346		.channels = ad7266_channels_diff_s,
    347		.num_channels = ARRAY_SIZE(ad7266_channels_diff_s),
    348		.scan_masks = ad7266_available_scan_masks_diff,
    349	},
    350	[AD7266_CHAN_INFO_INDEX(1, 1, 1)] = {
    351		.channels = ad7266_channels_diff_fixed_s,
    352		.num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_s),
    353		.scan_masks = ad7266_available_scan_masks_fixed,
    354	},
    355};
    356
    357static void ad7266_init_channels(struct iio_dev *indio_dev)
    358{
    359	struct ad7266_state *st = iio_priv(indio_dev);
    360	bool is_differential, is_signed;
    361	const struct ad7266_chan_info *chan_info;
    362	int i;
    363
    364	is_differential = st->mode != AD7266_MODE_SINGLE_ENDED;
    365	is_signed = (st->range == AD7266_RANGE_2VREF) |
    366		    (st->mode == AD7266_MODE_DIFF);
    367
    368	i = AD7266_CHAN_INFO_INDEX(is_differential, is_signed, st->fixed_addr);
    369	chan_info = &ad7266_chan_infos[i];
    370
    371	indio_dev->channels = chan_info->channels;
    372	indio_dev->num_channels = chan_info->num_channels;
    373	indio_dev->available_scan_masks = chan_info->scan_masks;
    374	indio_dev->masklength = chan_info->num_channels - 1;
    375}
    376
    377static const char * const ad7266_gpio_labels[] = {
    378	"ad0", "ad1", "ad2",
    379};
    380
    381static void ad7266_reg_disable(void *reg)
    382{
    383	regulator_disable(reg);
    384}
    385
    386static int ad7266_probe(struct spi_device *spi)
    387{
    388	struct ad7266_platform_data *pdata = spi->dev.platform_data;
    389	struct iio_dev *indio_dev;
    390	struct ad7266_state *st;
    391	unsigned int i;
    392	int ret;
    393
    394	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
    395	if (indio_dev == NULL)
    396		return -ENOMEM;
    397
    398	st = iio_priv(indio_dev);
    399
    400	st->reg = devm_regulator_get_optional(&spi->dev, "vref");
    401	if (!IS_ERR(st->reg)) {
    402		ret = regulator_enable(st->reg);
    403		if (ret)
    404			return ret;
    405
    406		ret = devm_add_action_or_reset(&spi->dev, ad7266_reg_disable, st->reg);
    407		if (ret)
    408			return ret;
    409
    410		ret = regulator_get_voltage(st->reg);
    411		if (ret < 0)
    412			return ret;
    413
    414		st->vref_mv = ret / 1000;
    415	} else {
    416		/* Any other error indicates that the regulator does exist */
    417		if (PTR_ERR(st->reg) != -ENODEV)
    418			return PTR_ERR(st->reg);
    419		/* Use internal reference */
    420		st->vref_mv = 2500;
    421	}
    422
    423	if (pdata) {
    424		st->fixed_addr = pdata->fixed_addr;
    425		st->mode = pdata->mode;
    426		st->range = pdata->range;
    427
    428		if (!st->fixed_addr) {
    429			for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) {
    430				st->gpios[i] = devm_gpiod_get(&spi->dev,
    431						      ad7266_gpio_labels[i],
    432						      GPIOD_OUT_LOW);
    433				if (IS_ERR(st->gpios[i])) {
    434					ret = PTR_ERR(st->gpios[i]);
    435					return ret;
    436				}
    437			}
    438		}
    439	} else {
    440		st->fixed_addr = true;
    441		st->range = AD7266_RANGE_VREF;
    442		st->mode = AD7266_MODE_DIFF;
    443	}
    444
    445	st->spi = spi;
    446
    447	indio_dev->name = spi_get_device_id(spi)->name;
    448	indio_dev->modes = INDIO_DIRECT_MODE;
    449	indio_dev->info = &ad7266_info;
    450
    451	ad7266_init_channels(indio_dev);
    452
    453	/* wakeup */
    454	st->single_xfer[0].rx_buf = &st->data.sample[0];
    455	st->single_xfer[0].len = 2;
    456	st->single_xfer[0].cs_change = 1;
    457	/* conversion */
    458	st->single_xfer[1].rx_buf = st->data.sample;
    459	st->single_xfer[1].len = 4;
    460	st->single_xfer[1].cs_change = 1;
    461	/* powerdown */
    462	st->single_xfer[2].tx_buf = &st->data.sample[0];
    463	st->single_xfer[2].len = 1;
    464
    465	spi_message_init(&st->single_msg);
    466	spi_message_add_tail(&st->single_xfer[0], &st->single_msg);
    467	spi_message_add_tail(&st->single_xfer[1], &st->single_msg);
    468	spi_message_add_tail(&st->single_xfer[2], &st->single_msg);
    469
    470	ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, &iio_pollfunc_store_time,
    471		&ad7266_trigger_handler, &iio_triggered_buffer_setup_ops);
    472	if (ret)
    473		return ret;
    474
    475	return devm_iio_device_register(&spi->dev, indio_dev);
    476}
    477
    478static const struct spi_device_id ad7266_id[] = {
    479	{"ad7265", 0},
    480	{"ad7266", 0},
    481	{ }
    482};
    483MODULE_DEVICE_TABLE(spi, ad7266_id);
    484
    485static struct spi_driver ad7266_driver = {
    486	.driver = {
    487		.name	= "ad7266",
    488	},
    489	.probe		= ad7266_probe,
    490	.id_table	= ad7266_id,
    491};
    492module_spi_driver(ad7266_driver);
    493
    494MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
    495MODULE_DESCRIPTION("Analog Devices AD7266/65 ADC");
    496MODULE_LICENSE("GPL v2");