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

ti-adc0832.c (8156B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ADC0831/ADC0832/ADC0834/ADC0838 8-bit ADC driver
      4 *
      5 * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com>
      6 *
      7 * Datasheet: https://www.ti.com/lit/ds/symlink/adc0832-n.pdf
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/mod_devicetable.h>
     12#include <linux/spi/spi.h>
     13#include <linux/iio/iio.h>
     14#include <linux/regulator/consumer.h>
     15#include <linux/iio/buffer.h>
     16#include <linux/iio/trigger.h>
     17#include <linux/iio/triggered_buffer.h>
     18#include <linux/iio/trigger_consumer.h>
     19
     20enum {
     21	adc0831,
     22	adc0832,
     23	adc0834,
     24	adc0838,
     25};
     26
     27struct adc0832 {
     28	struct spi_device *spi;
     29	struct regulator *reg;
     30	struct mutex lock;
     31	u8 mux_bits;
     32	/*
     33	 * Max size needed: 16x 1 byte ADC data + 8 bytes timestamp
     34	 * May be shorter if not all channels are enabled subject
     35	 * to the timestamp remaining 8 byte aligned.
     36	 */
     37	u8 data[24] __aligned(8);
     38
     39	u8 tx_buf[2] ____cacheline_aligned;
     40	u8 rx_buf[2];
     41};
     42
     43#define ADC0832_VOLTAGE_CHANNEL(chan)					\
     44	{								\
     45		.type = IIO_VOLTAGE,					\
     46		.indexed = 1,						\
     47		.channel = chan,					\
     48		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
     49		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
     50		.scan_index = chan,					\
     51		.scan_type = {						\
     52			.sign = 'u',					\
     53			.realbits = 8,					\
     54			.storagebits = 8,				\
     55		},							\
     56	}
     57
     58#define ADC0832_VOLTAGE_CHANNEL_DIFF(chan1, chan2, si)			\
     59	{								\
     60		.type = IIO_VOLTAGE,					\
     61		.indexed = 1,						\
     62		.channel = (chan1),					\
     63		.channel2 = (chan2),					\
     64		.differential = 1,					\
     65		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
     66		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
     67		.scan_index = si,					\
     68		.scan_type = {						\
     69			.sign = 'u',					\
     70			.realbits = 8,					\
     71			.storagebits = 8,				\
     72		},							\
     73	}
     74
     75static const struct iio_chan_spec adc0831_channels[] = {
     76	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 0),
     77	IIO_CHAN_SOFT_TIMESTAMP(1),
     78};
     79
     80static const struct iio_chan_spec adc0832_channels[] = {
     81	ADC0832_VOLTAGE_CHANNEL(0),
     82	ADC0832_VOLTAGE_CHANNEL(1),
     83	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 2),
     84	ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0, 3),
     85	IIO_CHAN_SOFT_TIMESTAMP(4),
     86};
     87
     88static const struct iio_chan_spec adc0834_channels[] = {
     89	ADC0832_VOLTAGE_CHANNEL(0),
     90	ADC0832_VOLTAGE_CHANNEL(1),
     91	ADC0832_VOLTAGE_CHANNEL(2),
     92	ADC0832_VOLTAGE_CHANNEL(3),
     93	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 4),
     94	ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0, 5),
     95	ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3, 6),
     96	ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2, 7),
     97	IIO_CHAN_SOFT_TIMESTAMP(8),
     98};
     99
    100static const struct iio_chan_spec adc0838_channels[] = {
    101	ADC0832_VOLTAGE_CHANNEL(0),
    102	ADC0832_VOLTAGE_CHANNEL(1),
    103	ADC0832_VOLTAGE_CHANNEL(2),
    104	ADC0832_VOLTAGE_CHANNEL(3),
    105	ADC0832_VOLTAGE_CHANNEL(4),
    106	ADC0832_VOLTAGE_CHANNEL(5),
    107	ADC0832_VOLTAGE_CHANNEL(6),
    108	ADC0832_VOLTAGE_CHANNEL(7),
    109	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 8),
    110	ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0, 9),
    111	ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3, 10),
    112	ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2, 11),
    113	ADC0832_VOLTAGE_CHANNEL_DIFF(4, 5, 12),
    114	ADC0832_VOLTAGE_CHANNEL_DIFF(5, 4, 13),
    115	ADC0832_VOLTAGE_CHANNEL_DIFF(6, 7, 14),
    116	ADC0832_VOLTAGE_CHANNEL_DIFF(7, 6, 15),
    117	IIO_CHAN_SOFT_TIMESTAMP(16),
    118};
    119
    120static int adc0831_adc_conversion(struct adc0832 *adc)
    121{
    122	struct spi_device *spi = adc->spi;
    123	int ret;
    124
    125	ret = spi_read(spi, &adc->rx_buf, 2);
    126	if (ret)
    127		return ret;
    128
    129	/*
    130	 * Skip TRI-STATE and a leading zero
    131	 */
    132	return (adc->rx_buf[0] << 2 & 0xff) | (adc->rx_buf[1] >> 6);
    133}
    134
    135static int adc0832_adc_conversion(struct adc0832 *adc, int channel,
    136				bool differential)
    137{
    138	struct spi_device *spi = adc->spi;
    139	struct spi_transfer xfer = {
    140		.tx_buf = adc->tx_buf,
    141		.rx_buf = adc->rx_buf,
    142		.len = 2,
    143	};
    144	int ret;
    145
    146	if (!adc->mux_bits)
    147		return adc0831_adc_conversion(adc);
    148
    149	/* start bit */
    150	adc->tx_buf[0] = 1 << (adc->mux_bits + 1);
    151	/* single-ended or differential */
    152	adc->tx_buf[0] |= differential ? 0 : (1 << adc->mux_bits);
    153	/* odd / sign */
    154	adc->tx_buf[0] |= (channel % 2) << (adc->mux_bits - 1);
    155	/* select */
    156	if (adc->mux_bits > 1)
    157		adc->tx_buf[0] |= channel / 2;
    158
    159	/* align Data output BIT7 (MSB) to 8-bit boundary */
    160	adc->tx_buf[0] <<= 1;
    161
    162	ret = spi_sync_transfer(spi, &xfer, 1);
    163	if (ret)
    164		return ret;
    165
    166	return adc->rx_buf[1];
    167}
    168
    169static int adc0832_read_raw(struct iio_dev *iio,
    170			struct iio_chan_spec const *channel, int *value,
    171			int *shift, long mask)
    172{
    173	struct adc0832 *adc = iio_priv(iio);
    174
    175	switch (mask) {
    176	case IIO_CHAN_INFO_RAW:
    177		mutex_lock(&adc->lock);
    178		*value = adc0832_adc_conversion(adc, channel->channel,
    179						channel->differential);
    180		mutex_unlock(&adc->lock);
    181		if (*value < 0)
    182			return *value;
    183
    184		return IIO_VAL_INT;
    185	case IIO_CHAN_INFO_SCALE:
    186		*value = regulator_get_voltage(adc->reg);
    187		if (*value < 0)
    188			return *value;
    189
    190		/* convert regulator output voltage to mV */
    191		*value /= 1000;
    192		*shift = 8;
    193
    194		return IIO_VAL_FRACTIONAL_LOG2;
    195	}
    196
    197	return -EINVAL;
    198}
    199
    200static const struct iio_info adc0832_info = {
    201	.read_raw = adc0832_read_raw,
    202};
    203
    204static irqreturn_t adc0832_trigger_handler(int irq, void *p)
    205{
    206	struct iio_poll_func *pf = p;
    207	struct iio_dev *indio_dev = pf->indio_dev;
    208	struct adc0832 *adc = iio_priv(indio_dev);
    209	int scan_index;
    210	int i = 0;
    211
    212	mutex_lock(&adc->lock);
    213
    214	for_each_set_bit(scan_index, indio_dev->active_scan_mask,
    215			 indio_dev->masklength) {
    216		const struct iio_chan_spec *scan_chan =
    217				&indio_dev->channels[scan_index];
    218		int ret = adc0832_adc_conversion(adc, scan_chan->channel,
    219						 scan_chan->differential);
    220		if (ret < 0) {
    221			dev_warn(&adc->spi->dev,
    222				 "failed to get conversion data\n");
    223			goto out;
    224		}
    225
    226		adc->data[i] = ret;
    227		i++;
    228	}
    229	iio_push_to_buffers_with_timestamp(indio_dev, adc->data,
    230					   iio_get_time_ns(indio_dev));
    231out:
    232	mutex_unlock(&adc->lock);
    233
    234	iio_trigger_notify_done(indio_dev->trig);
    235
    236	return IRQ_HANDLED;
    237}
    238
    239static void adc0832_reg_disable(void *reg)
    240{
    241	regulator_disable(reg);
    242}
    243
    244static int adc0832_probe(struct spi_device *spi)
    245{
    246	struct iio_dev *indio_dev;
    247	struct adc0832 *adc;
    248	int ret;
    249
    250	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
    251	if (!indio_dev)
    252		return -ENOMEM;
    253
    254	adc = iio_priv(indio_dev);
    255	adc->spi = spi;
    256	mutex_init(&adc->lock);
    257
    258	indio_dev->name = spi_get_device_id(spi)->name;
    259	indio_dev->info = &adc0832_info;
    260	indio_dev->modes = INDIO_DIRECT_MODE;
    261
    262	switch (spi_get_device_id(spi)->driver_data) {
    263	case adc0831:
    264		adc->mux_bits = 0;
    265		indio_dev->channels = adc0831_channels;
    266		indio_dev->num_channels = ARRAY_SIZE(adc0831_channels);
    267		break;
    268	case adc0832:
    269		adc->mux_bits = 1;
    270		indio_dev->channels = adc0832_channels;
    271		indio_dev->num_channels = ARRAY_SIZE(adc0832_channels);
    272		break;
    273	case adc0834:
    274		adc->mux_bits = 2;
    275		indio_dev->channels = adc0834_channels;
    276		indio_dev->num_channels = ARRAY_SIZE(adc0834_channels);
    277		break;
    278	case adc0838:
    279		adc->mux_bits = 3;
    280		indio_dev->channels = adc0838_channels;
    281		indio_dev->num_channels = ARRAY_SIZE(adc0838_channels);
    282		break;
    283	default:
    284		return -EINVAL;
    285	}
    286
    287	adc->reg = devm_regulator_get(&spi->dev, "vref");
    288	if (IS_ERR(adc->reg))
    289		return PTR_ERR(adc->reg);
    290
    291	ret = regulator_enable(adc->reg);
    292	if (ret)
    293		return ret;
    294
    295	ret = devm_add_action_or_reset(&spi->dev, adc0832_reg_disable,
    296				       adc->reg);
    297	if (ret)
    298		return ret;
    299
    300	ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL,
    301					      adc0832_trigger_handler, NULL);
    302	if (ret)
    303		return ret;
    304
    305	return devm_iio_device_register(&spi->dev, indio_dev);
    306}
    307
    308static const struct of_device_id adc0832_dt_ids[] = {
    309	{ .compatible = "ti,adc0831", },
    310	{ .compatible = "ti,adc0832", },
    311	{ .compatible = "ti,adc0834", },
    312	{ .compatible = "ti,adc0838", },
    313	{}
    314};
    315MODULE_DEVICE_TABLE(of, adc0832_dt_ids);
    316
    317static const struct spi_device_id adc0832_id[] = {
    318	{ "adc0831", adc0831 },
    319	{ "adc0832", adc0832 },
    320	{ "adc0834", adc0834 },
    321	{ "adc0838", adc0838 },
    322	{}
    323};
    324MODULE_DEVICE_TABLE(spi, adc0832_id);
    325
    326static struct spi_driver adc0832_driver = {
    327	.driver = {
    328		.name = "adc0832",
    329		.of_match_table = adc0832_dt_ids,
    330	},
    331	.probe = adc0832_probe,
    332	.id_table = adc0832_id,
    333};
    334module_spi_driver(adc0832_driver);
    335
    336MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
    337MODULE_DESCRIPTION("ADC0831/ADC0832/ADC0834/ADC0838 driver");
    338MODULE_LICENSE("GPL v2");