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

ad5449.c (8463B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog
      4 * Converter driver.
      5 *
      6 * Copyright 2012 Analog Devices Inc.
      7 *  Author: Lars-Peter Clausen <lars@metafoo.de>
      8 */
      9
     10#include <linux/device.h>
     11#include <linux/err.h>
     12#include <linux/module.h>
     13#include <linux/kernel.h>
     14#include <linux/spi/spi.h>
     15#include <linux/slab.h>
     16#include <linux/sysfs.h>
     17#include <linux/regulator/consumer.h>
     18#include <asm/unaligned.h>
     19
     20#include <linux/iio/iio.h>
     21#include <linux/iio/sysfs.h>
     22
     23#include <linux/platform_data/ad5449.h>
     24
     25#define AD5449_MAX_CHANNELS		2
     26#define AD5449_MAX_VREFS		2
     27
     28#define AD5449_CMD_NOOP			0x0
     29#define AD5449_CMD_LOAD_AND_UPDATE(x)	(0x1 + (x) * 3)
     30#define AD5449_CMD_READ(x)		(0x2 + (x) * 3)
     31#define AD5449_CMD_LOAD(x)		(0x3 + (x) * 3)
     32#define AD5449_CMD_CTRL			13
     33
     34#define AD5449_CTRL_SDO_OFFSET		10
     35#define AD5449_CTRL_DAISY_CHAIN		BIT(9)
     36#define AD5449_CTRL_HCLR_TO_MIDSCALE	BIT(8)
     37#define AD5449_CTRL_SAMPLE_RISING	BIT(7)
     38
     39/**
     40 * struct ad5449_chip_info - chip specific information
     41 * @channels:		Channel specification
     42 * @num_channels:	Number of channels
     43 * @has_ctrl:		Chip has a control register
     44 */
     45struct ad5449_chip_info {
     46	const struct iio_chan_spec *channels;
     47	unsigned int num_channels;
     48	bool has_ctrl;
     49};
     50
     51/**
     52 * struct ad5449 - driver instance specific data
     53 * @spi:		the SPI device for this driver instance
     54 * @chip_info:		chip model specific constants, available modes etc
     55 * @vref_reg:		vref supply regulators
     56 * @has_sdo:		whether the SDO line is connected
     57 * @dac_cache:		Cache for the DAC values
     58 * @data:		spi transfer buffers
     59 * @lock:		lock to protect the data buffer during SPI ops
     60 */
     61struct ad5449 {
     62	struct spi_device		*spi;
     63	const struct ad5449_chip_info	*chip_info;
     64	struct regulator_bulk_data	vref_reg[AD5449_MAX_VREFS];
     65	struct mutex			lock;
     66
     67	bool has_sdo;
     68	uint16_t dac_cache[AD5449_MAX_CHANNELS];
     69
     70	/*
     71	 * DMA (thus cache coherency maintenance) requires the
     72	 * transfer buffers to live in their own cache lines.
     73	 */
     74	__be16 data[2] ____cacheline_aligned;
     75};
     76
     77enum ad5449_type {
     78	ID_AD5426,
     79	ID_AD5429,
     80	ID_AD5432,
     81	ID_AD5439,
     82	ID_AD5443,
     83	ID_AD5449,
     84};
     85
     86static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr,
     87	unsigned int val)
     88{
     89	struct ad5449 *st = iio_priv(indio_dev);
     90	int ret;
     91
     92	mutex_lock(&st->lock);
     93	st->data[0] = cpu_to_be16((addr << 12) | val);
     94	ret = spi_write(st->spi, st->data, 2);
     95	mutex_unlock(&st->lock);
     96
     97	return ret;
     98}
     99
    100static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
    101	unsigned int *val)
    102{
    103	struct ad5449 *st = iio_priv(indio_dev);
    104	int ret;
    105	struct spi_transfer t[] = {
    106		{
    107			.tx_buf = &st->data[0],
    108			.len = 2,
    109			.cs_change = 1,
    110		}, {
    111			.tx_buf = &st->data[1],
    112			.rx_buf = &st->data[1],
    113			.len = 2,
    114		},
    115	};
    116
    117	mutex_lock(&st->lock);
    118	st->data[0] = cpu_to_be16(addr << 12);
    119	st->data[1] = cpu_to_be16(AD5449_CMD_NOOP);
    120
    121	ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
    122	if (ret < 0)
    123		goto out_unlock;
    124
    125	*val = be16_to_cpu(st->data[1]);
    126
    127out_unlock:
    128	mutex_unlock(&st->lock);
    129	return ret;
    130}
    131
    132static int ad5449_read_raw(struct iio_dev *indio_dev,
    133	struct iio_chan_spec const *chan, int *val, int *val2, long info)
    134{
    135	struct ad5449 *st = iio_priv(indio_dev);
    136	struct regulator_bulk_data *reg;
    137	int scale_uv;
    138	int ret;
    139
    140	switch (info) {
    141	case IIO_CHAN_INFO_RAW:
    142		if (st->has_sdo) {
    143			ret = ad5449_read(indio_dev,
    144				AD5449_CMD_READ(chan->address), val);
    145			if (ret)
    146				return ret;
    147			*val &= 0xfff;
    148		} else {
    149			*val = st->dac_cache[chan->address];
    150		}
    151
    152		return IIO_VAL_INT;
    153	case IIO_CHAN_INFO_SCALE:
    154		reg = &st->vref_reg[chan->channel];
    155		scale_uv = regulator_get_voltage(reg->consumer);
    156		if (scale_uv < 0)
    157			return scale_uv;
    158
    159		*val = scale_uv / 1000;
    160		*val2 = chan->scan_type.realbits;
    161
    162		return IIO_VAL_FRACTIONAL_LOG2;
    163	default:
    164		break;
    165	}
    166
    167	return -EINVAL;
    168}
    169
    170static int ad5449_write_raw(struct iio_dev *indio_dev,
    171	struct iio_chan_spec const *chan, int val, int val2, long info)
    172{
    173	struct ad5449 *st = iio_priv(indio_dev);
    174	int ret;
    175
    176	switch (info) {
    177	case IIO_CHAN_INFO_RAW:
    178		if (val < 0 || val >= (1 << chan->scan_type.realbits))
    179			return -EINVAL;
    180
    181		ret = ad5449_write(indio_dev,
    182			AD5449_CMD_LOAD_AND_UPDATE(chan->address),
    183			val << chan->scan_type.shift);
    184		if (ret == 0)
    185			st->dac_cache[chan->address] = val;
    186		break;
    187	default:
    188		ret = -EINVAL;
    189	}
    190
    191	return ret;
    192}
    193
    194static const struct iio_info ad5449_info = {
    195	.read_raw = ad5449_read_raw,
    196	.write_raw = ad5449_write_raw,
    197};
    198
    199#define AD5449_CHANNEL(chan, bits) {				\
    200	.type = IIO_VOLTAGE,					\
    201	.indexed = 1,						\
    202	.output = 1,						\
    203	.channel = (chan),					\
    204	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
    205		BIT(IIO_CHAN_INFO_SCALE),			\
    206	.address = (chan),					\
    207	.scan_type = {						\
    208		.sign = 'u',					\
    209		.realbits = (bits),				\
    210		.storagebits = 16,				\
    211		.shift = 12 - (bits),				\
    212	},							\
    213}
    214
    215#define DECLARE_AD5449_CHANNELS(name, bits) \
    216const struct iio_chan_spec name[] = { \
    217	AD5449_CHANNEL(0, bits), \
    218	AD5449_CHANNEL(1, bits), \
    219}
    220
    221static DECLARE_AD5449_CHANNELS(ad5429_channels, 8);
    222static DECLARE_AD5449_CHANNELS(ad5439_channels, 10);
    223static DECLARE_AD5449_CHANNELS(ad5449_channels, 12);
    224
    225static const struct ad5449_chip_info ad5449_chip_info[] = {
    226	[ID_AD5426] = {
    227		.channels = ad5429_channels,
    228		.num_channels = 1,
    229		.has_ctrl = false,
    230	},
    231	[ID_AD5429] = {
    232		.channels = ad5429_channels,
    233		.num_channels = 2,
    234		.has_ctrl = true,
    235	},
    236	[ID_AD5432] = {
    237		.channels = ad5439_channels,
    238		.num_channels = 1,
    239		.has_ctrl = false,
    240	},
    241	[ID_AD5439] = {
    242		.channels = ad5439_channels,
    243		.num_channels = 2,
    244		.has_ctrl = true,
    245	},
    246	[ID_AD5443] = {
    247		.channels = ad5449_channels,
    248		.num_channels = 1,
    249		.has_ctrl = false,
    250	},
    251	[ID_AD5449] = {
    252		.channels = ad5449_channels,
    253		.num_channels = 2,
    254		.has_ctrl = true,
    255	},
    256};
    257
    258static const char *ad5449_vref_name(struct ad5449 *st, int n)
    259{
    260	if (st->chip_info->num_channels == 1)
    261		return "VREF";
    262
    263	if (n == 0)
    264		return "VREFA";
    265	else
    266		return "VREFB";
    267}
    268
    269static int ad5449_spi_probe(struct spi_device *spi)
    270{
    271	struct ad5449_platform_data *pdata = spi->dev.platform_data;
    272	const struct spi_device_id *id = spi_get_device_id(spi);
    273	struct iio_dev *indio_dev;
    274	struct ad5449 *st;
    275	unsigned int i;
    276	int ret;
    277
    278	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
    279	if (indio_dev == NULL)
    280		return -ENOMEM;
    281
    282	st = iio_priv(indio_dev);
    283	spi_set_drvdata(spi, indio_dev);
    284
    285	st->chip_info = &ad5449_chip_info[id->driver_data];
    286	st->spi = spi;
    287
    288	for (i = 0; i < st->chip_info->num_channels; ++i)
    289		st->vref_reg[i].supply = ad5449_vref_name(st, i);
    290
    291	ret = devm_regulator_bulk_get(&spi->dev, st->chip_info->num_channels,
    292				st->vref_reg);
    293	if (ret)
    294		return ret;
    295
    296	ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg);
    297	if (ret)
    298		return ret;
    299
    300	indio_dev->name = id->name;
    301	indio_dev->info = &ad5449_info;
    302	indio_dev->modes = INDIO_DIRECT_MODE;
    303	indio_dev->channels = st->chip_info->channels;
    304	indio_dev->num_channels = st->chip_info->num_channels;
    305
    306	mutex_init(&st->lock);
    307
    308	if (st->chip_info->has_ctrl) {
    309		unsigned int ctrl = 0x00;
    310		if (pdata) {
    311			if (pdata->hardware_clear_to_midscale)
    312				ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE;
    313			ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET;
    314			st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED;
    315		} else {
    316			st->has_sdo = true;
    317		}
    318		ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl);
    319	}
    320
    321	ret = iio_device_register(indio_dev);
    322	if (ret)
    323		goto error_disable_reg;
    324
    325	return 0;
    326
    327error_disable_reg:
    328	regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
    329
    330	return ret;
    331}
    332
    333static void ad5449_spi_remove(struct spi_device *spi)
    334{
    335	struct iio_dev *indio_dev = spi_get_drvdata(spi);
    336	struct ad5449 *st = iio_priv(indio_dev);
    337
    338	iio_device_unregister(indio_dev);
    339
    340	regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
    341}
    342
    343static const struct spi_device_id ad5449_spi_ids[] = {
    344	{ "ad5415", ID_AD5449 },
    345	{ "ad5426", ID_AD5426 },
    346	{ "ad5429", ID_AD5429 },
    347	{ "ad5432", ID_AD5432 },
    348	{ "ad5439", ID_AD5439 },
    349	{ "ad5443", ID_AD5443 },
    350	{ "ad5449", ID_AD5449 },
    351	{}
    352};
    353MODULE_DEVICE_TABLE(spi, ad5449_spi_ids);
    354
    355static struct spi_driver ad5449_spi_driver = {
    356	.driver = {
    357		.name = "ad5449",
    358	},
    359	.probe = ad5449_spi_probe,
    360	.remove = ad5449_spi_remove,
    361	.id_table = ad5449_spi_ids,
    362};
    363module_spi_driver(ad5449_spi_driver);
    364
    365MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
    366MODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs");
    367MODULE_LICENSE("GPL v2");