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

ad7292.c (8491B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Analog Devices AD7292 SPI ADC driver
      4 *
      5 * Copyright 2019 Analog Devices Inc.
      6 */
      7
      8#include <linux/bitfield.h>
      9#include <linux/device.h>
     10#include <linux/module.h>
     11#include <linux/regulator/consumer.h>
     12#include <linux/spi/spi.h>
     13
     14#include <linux/iio/iio.h>
     15
     16#define ADI_VENDOR_ID 0x0018
     17
     18/* AD7292 registers definition */
     19#define AD7292_REG_VENDOR_ID		0x00
     20#define AD7292_REG_CONF_BANK		0x05
     21#define AD7292_REG_CONV_COMM		0x0E
     22#define AD7292_REG_ADC_CH(x)		(0x10 + (x))
     23
     24/* AD7292 configuration bank subregisters definition */
     25#define AD7292_BANK_REG_VIN_RNG0	0x10
     26#define AD7292_BANK_REG_VIN_RNG1	0x11
     27#define AD7292_BANK_REG_SAMP_MODE	0x12
     28
     29#define AD7292_RD_FLAG_MSK(x)		(BIT(7) | ((x) & 0x3F))
     30
     31/* AD7292_REG_ADC_CONVERSION */
     32#define AD7292_ADC_DATA_MASK		GENMASK(15, 6)
     33#define AD7292_ADC_DATA(x)		FIELD_GET(AD7292_ADC_DATA_MASK, x)
     34
     35/* AD7292_CHANNEL_SAMPLING_MODE */
     36#define AD7292_CH_SAMP_MODE(reg, ch)	(((reg) >> 8) & BIT(ch))
     37
     38/* AD7292_CHANNEL_VIN_RANGE */
     39#define AD7292_CH_VIN_RANGE(reg, ch)	((reg) & BIT(ch))
     40
     41#define AD7292_VOLTAGE_CHAN(_chan)					\
     42{									\
     43	.type = IIO_VOLTAGE,						\
     44	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\
     45			      BIT(IIO_CHAN_INFO_SCALE),			\
     46	.indexed = 1,							\
     47	.channel = _chan,						\
     48}
     49
     50static const struct iio_chan_spec ad7292_channels[] = {
     51	AD7292_VOLTAGE_CHAN(0),
     52	AD7292_VOLTAGE_CHAN(1),
     53	AD7292_VOLTAGE_CHAN(2),
     54	AD7292_VOLTAGE_CHAN(3),
     55	AD7292_VOLTAGE_CHAN(4),
     56	AD7292_VOLTAGE_CHAN(5),
     57	AD7292_VOLTAGE_CHAN(6),
     58	AD7292_VOLTAGE_CHAN(7)
     59};
     60
     61static const struct iio_chan_spec ad7292_channels_diff[] = {
     62	{
     63		.type = IIO_VOLTAGE,
     64		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
     65		.indexed = 1,
     66		.differential = 1,
     67		.channel = 0,
     68		.channel2 = 1,
     69	},
     70	AD7292_VOLTAGE_CHAN(2),
     71	AD7292_VOLTAGE_CHAN(3),
     72	AD7292_VOLTAGE_CHAN(4),
     73	AD7292_VOLTAGE_CHAN(5),
     74	AD7292_VOLTAGE_CHAN(6),
     75	AD7292_VOLTAGE_CHAN(7)
     76};
     77
     78struct ad7292_state {
     79	struct spi_device *spi;
     80	struct regulator *reg;
     81	unsigned short vref_mv;
     82
     83	__be16 d16 ____cacheline_aligned;
     84	u8 d8[2];
     85};
     86
     87static int ad7292_spi_reg_read(struct ad7292_state *st, unsigned int addr)
     88{
     89	int ret;
     90
     91	st->d8[0] = AD7292_RD_FLAG_MSK(addr);
     92
     93	ret = spi_write_then_read(st->spi, st->d8, 1, &st->d16, 2);
     94	if (ret < 0)
     95		return ret;
     96
     97	return be16_to_cpu(st->d16);
     98}
     99
    100static int ad7292_spi_subreg_read(struct ad7292_state *st, unsigned int addr,
    101				  unsigned int sub_addr, unsigned int len)
    102{
    103	unsigned int shift = 16 - (8 * len);
    104	int ret;
    105
    106	st->d8[0] = AD7292_RD_FLAG_MSK(addr);
    107	st->d8[1] = sub_addr;
    108
    109	ret = spi_write_then_read(st->spi, st->d8, 2, &st->d16, len);
    110	if (ret < 0)
    111		return ret;
    112
    113	return (be16_to_cpu(st->d16) >> shift);
    114}
    115
    116static int ad7292_single_conversion(struct ad7292_state *st,
    117				    unsigned int chan_addr)
    118{
    119	int ret;
    120
    121	struct spi_transfer t[] = {
    122		{
    123			.tx_buf = &st->d8,
    124			.len = 4,
    125			.delay = {
    126				.value = 6,
    127				.unit = SPI_DELAY_UNIT_USECS
    128			},
    129		}, {
    130			.rx_buf = &st->d16,
    131			.len = 2,
    132		},
    133	};
    134
    135	st->d8[0] = chan_addr;
    136	st->d8[1] = AD7292_RD_FLAG_MSK(AD7292_REG_CONV_COMM);
    137
    138	ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
    139
    140	if (ret < 0)
    141		return ret;
    142
    143	return be16_to_cpu(st->d16);
    144}
    145
    146static int ad7292_vin_range_multiplier(struct ad7292_state *st, int channel)
    147{
    148	int samp_mode, range0, range1, factor = 1;
    149
    150	/*
    151	 * Every AD7292 ADC channel may have its input range adjusted according
    152	 * to the settings at the ADC sampling mode and VIN range subregisters.
    153	 * For a given channel, the minimum input range is equal to Vref, and it
    154	 * may be increased by a multiplier factor of 2 or 4 according to the
    155	 * following rule:
    156	 * If channel is being sampled with respect to AGND:
    157	 *	factor = 4 if VIN range0 and VIN range1 equal 0
    158	 *	factor = 2 if only one of VIN ranges equal 1
    159	 *	factor = 1 if both VIN range0 and VIN range1 equal 1
    160	 * If channel is being sampled with respect to AVDD:
    161	 *	factor = 4 if VIN range0 and VIN range1 equal 0
    162	 *	Behavior is undefined if any of VIN range doesn't equal 0
    163	 */
    164
    165	samp_mode = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK,
    166					   AD7292_BANK_REG_SAMP_MODE, 2);
    167
    168	if (samp_mode < 0)
    169		return samp_mode;
    170
    171	range0 = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK,
    172					AD7292_BANK_REG_VIN_RNG0, 2);
    173
    174	if (range0 < 0)
    175		return range0;
    176
    177	range1 = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK,
    178					AD7292_BANK_REG_VIN_RNG1, 2);
    179
    180	if (range1 < 0)
    181		return range1;
    182
    183	if (AD7292_CH_SAMP_MODE(samp_mode, channel)) {
    184		/* Sampling with respect to AGND */
    185		if (!AD7292_CH_VIN_RANGE(range0, channel))
    186			factor *= 2;
    187
    188		if (!AD7292_CH_VIN_RANGE(range1, channel))
    189			factor *= 2;
    190
    191	} else {
    192		/* Sampling with respect to AVDD */
    193		if (AD7292_CH_VIN_RANGE(range0, channel) ||
    194		    AD7292_CH_VIN_RANGE(range1, channel))
    195			return -EPERM;
    196
    197		factor = 4;
    198	}
    199
    200	return factor;
    201}
    202
    203static int ad7292_read_raw(struct iio_dev *indio_dev,
    204			   const struct iio_chan_spec *chan,
    205			   int *val, int *val2, long info)
    206{
    207	struct ad7292_state *st = iio_priv(indio_dev);
    208	unsigned int ch_addr;
    209	int ret;
    210
    211	switch (info) {
    212	case IIO_CHAN_INFO_RAW:
    213		ch_addr = AD7292_REG_ADC_CH(chan->channel);
    214		ret = ad7292_single_conversion(st, ch_addr);
    215		if (ret < 0)
    216			return ret;
    217
    218		*val = AD7292_ADC_DATA(ret);
    219
    220		return IIO_VAL_INT;
    221	case IIO_CHAN_INFO_SCALE:
    222		/*
    223		 * To convert a raw value to standard units, the IIO defines
    224		 * this formula: Scaled value = (raw + offset) * scale.
    225		 * For the scale to be a correct multiplier for (raw + offset),
    226		 * it must be calculated as the input range divided by the
    227		 * number of possible distinct input values. Given the ADC data
    228		 * is 10 bit long, it may assume 2^10 distinct values.
    229		 * Hence, scale = range / 2^10. The IIO_VAL_FRACTIONAL_LOG2
    230		 * return type indicates to the IIO API to divide *val by 2 to
    231		 * the power of *val2 when returning from read_raw.
    232		 */
    233
    234		ret = ad7292_vin_range_multiplier(st, chan->channel);
    235		if (ret < 0)
    236			return ret;
    237
    238		*val = st->vref_mv * ret;
    239		*val2 = 10;
    240		return IIO_VAL_FRACTIONAL_LOG2;
    241	default:
    242		break;
    243	}
    244	return -EINVAL;
    245}
    246
    247static const struct iio_info ad7292_info = {
    248	.read_raw = ad7292_read_raw,
    249};
    250
    251static void ad7292_regulator_disable(void *data)
    252{
    253	struct ad7292_state *st = data;
    254
    255	regulator_disable(st->reg);
    256}
    257
    258static int ad7292_probe(struct spi_device *spi)
    259{
    260	struct ad7292_state *st;
    261	struct iio_dev *indio_dev;
    262	struct device_node *child;
    263	bool diff_channels = false;
    264	int ret;
    265
    266	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
    267	if (!indio_dev)
    268		return -ENOMEM;
    269
    270	st = iio_priv(indio_dev);
    271	st->spi = spi;
    272
    273	ret = ad7292_spi_reg_read(st, AD7292_REG_VENDOR_ID);
    274	if (ret != ADI_VENDOR_ID) {
    275		dev_err(&spi->dev, "Wrong vendor id 0x%x\n", ret);
    276		return -EINVAL;
    277	}
    278
    279	st->reg = devm_regulator_get_optional(&spi->dev, "vref");
    280	if (!IS_ERR(st->reg)) {
    281		ret = regulator_enable(st->reg);
    282		if (ret) {
    283			dev_err(&spi->dev,
    284				"Failed to enable external vref supply\n");
    285			return ret;
    286		}
    287
    288		ret = devm_add_action_or_reset(&spi->dev,
    289					       ad7292_regulator_disable, st);
    290		if (ret) {
    291			regulator_disable(st->reg);
    292			return ret;
    293		}
    294
    295		ret = regulator_get_voltage(st->reg);
    296		if (ret < 0)
    297			return ret;
    298
    299		st->vref_mv = ret / 1000;
    300	} else {
    301		/* Use the internal voltage reference. */
    302		st->vref_mv = 1250;
    303	}
    304
    305	indio_dev->name = spi_get_device_id(spi)->name;
    306	indio_dev->modes = INDIO_DIRECT_MODE;
    307	indio_dev->info = &ad7292_info;
    308
    309	for_each_available_child_of_node(spi->dev.of_node, child) {
    310		diff_channels = of_property_read_bool(child, "diff-channels");
    311		if (diff_channels) {
    312			of_node_put(child);
    313			break;
    314		}
    315	}
    316
    317	if (diff_channels) {
    318		indio_dev->num_channels = ARRAY_SIZE(ad7292_channels_diff);
    319		indio_dev->channels = ad7292_channels_diff;
    320	} else {
    321		indio_dev->num_channels = ARRAY_SIZE(ad7292_channels);
    322		indio_dev->channels = ad7292_channels;
    323	}
    324
    325	return devm_iio_device_register(&spi->dev, indio_dev);
    326}
    327
    328static const struct spi_device_id ad7292_id_table[] = {
    329	{ "ad7292", 0 },
    330	{}
    331};
    332MODULE_DEVICE_TABLE(spi, ad7292_id_table);
    333
    334static const struct of_device_id ad7292_of_match[] = {
    335	{ .compatible = "adi,ad7292" },
    336	{ },
    337};
    338MODULE_DEVICE_TABLE(of, ad7292_of_match);
    339
    340static struct spi_driver ad7292_driver = {
    341	.driver = {
    342		.name = "ad7292",
    343		.of_match_table = ad7292_of_match,
    344	},
    345	.probe = ad7292_probe,
    346	.id_table = ad7292_id_table,
    347};
    348module_spi_driver(ad7292_driver);
    349
    350MODULE_AUTHOR("Marcelo Schmitt <marcelo.schmitt1@gmail.com>");
    351MODULE_DESCRIPTION("Analog Devices AD7292 ADC driver");
    352MODULE_LICENSE("GPL v2");