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

ad7816.c (10936B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * AD7816 digital temperature sensor driver supporting AD7816/7/8
      4 *
      5 * Copyright 2010 Analog Devices Inc.
      6 */
      7
      8#include <linux/interrupt.h>
      9#include <linux/gpio/consumer.h>
     10#include <linux/device.h>
     11#include <linux/kernel.h>
     12#include <linux/slab.h>
     13#include <linux/sysfs.h>
     14#include <linux/list.h>
     15#include <linux/spi/spi.h>
     16#include <linux/module.h>
     17
     18#include <linux/iio/iio.h>
     19#include <linux/iio/sysfs.h>
     20#include <linux/iio/events.h>
     21
     22/*
     23 * AD7816 config masks
     24 */
     25#define AD7816_FULL			0x1
     26#define AD7816_PD			0x2
     27#define AD7816_CS_MASK			0x7
     28#define AD7816_CS_MAX			0x4
     29
     30/*
     31 * AD7816 temperature masks
     32 */
     33#define AD7816_VALUE_OFFSET		6
     34#define AD7816_BOUND_VALUE_BASE		0x8
     35#define AD7816_BOUND_VALUE_MIN		-95
     36#define AD7816_BOUND_VALUE_MAX		152
     37#define AD7816_TEMP_FLOAT_OFFSET	2
     38#define AD7816_TEMP_FLOAT_MASK		0x3
     39
     40/*
     41 * struct ad7816_chip_info - chip specific information
     42 */
     43
     44struct ad7816_chip_info {
     45	kernel_ulong_t id;
     46	struct spi_device *spi_dev;
     47	struct gpio_desc *rdwr_pin;
     48	struct gpio_desc *convert_pin;
     49	struct gpio_desc *busy_pin;
     50	u8  oti_data[AD7816_CS_MAX + 1];
     51	u8  channel_id;	/* 0 always be temperature */
     52	u8  mode;
     53};
     54
     55enum ad7816_type {
     56	ID_AD7816,
     57	ID_AD7817,
     58	ID_AD7818,
     59};
     60
     61/*
     62 * ad7816 data access by SPI
     63 */
     64static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
     65{
     66	struct spi_device *spi_dev = chip->spi_dev;
     67	int ret;
     68	__be16 buf;
     69
     70	gpiod_set_value(chip->rdwr_pin, 1);
     71	gpiod_set_value(chip->rdwr_pin, 0);
     72	ret = spi_write(spi_dev, &chip->channel_id, sizeof(chip->channel_id));
     73	if (ret < 0) {
     74		dev_err(&spi_dev->dev, "SPI channel setting error\n");
     75		return ret;
     76	}
     77	gpiod_set_value(chip->rdwr_pin, 1);
     78
     79	if (chip->mode == AD7816_PD) { /* operating mode 2 */
     80		gpiod_set_value(chip->convert_pin, 1);
     81		gpiod_set_value(chip->convert_pin, 0);
     82	} else { /* operating mode 1 */
     83		gpiod_set_value(chip->convert_pin, 0);
     84		gpiod_set_value(chip->convert_pin, 1);
     85	}
     86
     87	if (chip->id == ID_AD7816 || chip->id == ID_AD7817) {
     88		while (gpiod_get_value(chip->busy_pin))
     89			cpu_relax();
     90	}
     91
     92	gpiod_set_value(chip->rdwr_pin, 0);
     93	gpiod_set_value(chip->rdwr_pin, 1);
     94	ret = spi_read(spi_dev, &buf, sizeof(*data));
     95	if (ret < 0) {
     96		dev_err(&spi_dev->dev, "SPI data read error\n");
     97		return ret;
     98	}
     99
    100	*data = be16_to_cpu(buf);
    101
    102	return ret;
    103}
    104
    105static int ad7816_spi_write(struct ad7816_chip_info *chip, u8 data)
    106{
    107	struct spi_device *spi_dev = chip->spi_dev;
    108	int ret;
    109
    110	gpiod_set_value(chip->rdwr_pin, 1);
    111	gpiod_set_value(chip->rdwr_pin, 0);
    112	ret = spi_write(spi_dev, &data, sizeof(data));
    113	if (ret < 0)
    114		dev_err(&spi_dev->dev, "SPI oti data write error\n");
    115
    116	return ret;
    117}
    118
    119static ssize_t ad7816_show_mode(struct device *dev,
    120				struct device_attribute *attr,
    121				char *buf)
    122{
    123	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    124	struct ad7816_chip_info *chip = iio_priv(indio_dev);
    125
    126	if (chip->mode)
    127		return sprintf(buf, "power-save\n");
    128	return sprintf(buf, "full\n");
    129}
    130
    131static ssize_t ad7816_store_mode(struct device *dev,
    132				 struct device_attribute *attr,
    133				 const char *buf,
    134				 size_t len)
    135{
    136	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    137	struct ad7816_chip_info *chip = iio_priv(indio_dev);
    138
    139	if (strcmp(buf, "full")) {
    140		gpiod_set_value(chip->rdwr_pin, 1);
    141		chip->mode = AD7816_FULL;
    142	} else {
    143		gpiod_set_value(chip->rdwr_pin, 0);
    144		chip->mode = AD7816_PD;
    145	}
    146
    147	return len;
    148}
    149
    150static IIO_DEVICE_ATTR(mode, 0644,
    151		ad7816_show_mode,
    152		ad7816_store_mode,
    153		0);
    154
    155static ssize_t ad7816_show_available_modes(struct device *dev,
    156					   struct device_attribute *attr,
    157					   char *buf)
    158{
    159	return sprintf(buf, "full\npower-save\n");
    160}
    161
    162static IIO_DEVICE_ATTR(available_modes, 0444, ad7816_show_available_modes,
    163			NULL, 0);
    164
    165static ssize_t ad7816_show_channel(struct device *dev,
    166				   struct device_attribute *attr,
    167				   char *buf)
    168{
    169	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    170	struct ad7816_chip_info *chip = iio_priv(indio_dev);
    171
    172	return sprintf(buf, "%d\n", chip->channel_id);
    173}
    174
    175static ssize_t ad7816_store_channel(struct device *dev,
    176				    struct device_attribute *attr,
    177				    const char *buf,
    178				    size_t len)
    179{
    180	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    181	struct ad7816_chip_info *chip = iio_priv(indio_dev);
    182	unsigned long data;
    183	int ret;
    184
    185	ret = kstrtoul(buf, 10, &data);
    186	if (ret)
    187		return ret;
    188
    189	if (data > AD7816_CS_MAX && data != AD7816_CS_MASK) {
    190		dev_err(&chip->spi_dev->dev, "Invalid channel id %lu for %s.\n",
    191			data, indio_dev->name);
    192		return -EINVAL;
    193	} else if (strcmp(indio_dev->name, "ad7818") == 0 && data > 1) {
    194		dev_err(&chip->spi_dev->dev,
    195			"Invalid channel id %lu for ad7818.\n", data);
    196		return -EINVAL;
    197	} else if (strcmp(indio_dev->name, "ad7816") == 0 && data > 0) {
    198		dev_err(&chip->spi_dev->dev,
    199			"Invalid channel id %lu for ad7816.\n", data);
    200		return -EINVAL;
    201	}
    202
    203	chip->channel_id = data;
    204
    205	return len;
    206}
    207
    208static IIO_DEVICE_ATTR(channel, 0644,
    209		ad7816_show_channel,
    210		ad7816_store_channel,
    211		0);
    212
    213static ssize_t ad7816_show_value(struct device *dev,
    214				 struct device_attribute *attr,
    215				 char *buf)
    216{
    217	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    218	struct ad7816_chip_info *chip = iio_priv(indio_dev);
    219	u16 data;
    220	s8 value;
    221	int ret;
    222
    223	ret = ad7816_spi_read(chip, &data);
    224	if (ret)
    225		return -EIO;
    226
    227	data >>= AD7816_VALUE_OFFSET;
    228
    229	if (chip->channel_id == 0) {
    230		value = (s8)((data >> AD7816_TEMP_FLOAT_OFFSET) - 103);
    231		data &= AD7816_TEMP_FLOAT_MASK;
    232		if (value < 0)
    233			data = BIT(AD7816_TEMP_FLOAT_OFFSET) - data;
    234		return sprintf(buf, "%d.%.2d\n", value, data * 25);
    235	}
    236	return sprintf(buf, "%u\n", data);
    237}
    238
    239static IIO_DEVICE_ATTR(value, 0444, ad7816_show_value, NULL, 0);
    240
    241static struct attribute *ad7816_attributes[] = {
    242	&iio_dev_attr_available_modes.dev_attr.attr,
    243	&iio_dev_attr_mode.dev_attr.attr,
    244	&iio_dev_attr_channel.dev_attr.attr,
    245	&iio_dev_attr_value.dev_attr.attr,
    246	NULL,
    247};
    248
    249static const struct attribute_group ad7816_attribute_group = {
    250	.attrs = ad7816_attributes,
    251};
    252
    253/*
    254 * temperature bound events
    255 */
    256
    257#define IIO_EVENT_CODE_AD7816_OTI IIO_UNMOD_EVENT_CODE(IIO_TEMP,	\
    258						       0,		\
    259						       IIO_EV_TYPE_THRESH, \
    260						       IIO_EV_DIR_FALLING)
    261
    262static irqreturn_t ad7816_event_handler(int irq, void *private)
    263{
    264	iio_push_event(private, IIO_EVENT_CODE_AD7816_OTI,
    265		       iio_get_time_ns(private));
    266	return IRQ_HANDLED;
    267}
    268
    269static ssize_t ad7816_show_oti(struct device *dev,
    270			       struct device_attribute *attr,
    271			       char *buf)
    272{
    273	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    274	struct ad7816_chip_info *chip = iio_priv(indio_dev);
    275	int value;
    276
    277	if (chip->channel_id > AD7816_CS_MAX) {
    278		dev_err(dev, "Invalid oti channel id %d.\n", chip->channel_id);
    279		return -EINVAL;
    280	} else if (chip->channel_id == 0) {
    281		value = AD7816_BOUND_VALUE_MIN +
    282			(chip->oti_data[chip->channel_id] -
    283			AD7816_BOUND_VALUE_BASE);
    284		return sprintf(buf, "%d\n", value);
    285	}
    286	return sprintf(buf, "%u\n", chip->oti_data[chip->channel_id]);
    287}
    288
    289static inline ssize_t ad7816_set_oti(struct device *dev,
    290				     struct device_attribute *attr,
    291				     const char *buf,
    292				     size_t len)
    293{
    294	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    295	struct ad7816_chip_info *chip = iio_priv(indio_dev);
    296	long value;
    297	u8 data;
    298	int ret;
    299
    300	ret = kstrtol(buf, 10, &value);
    301	if (ret)
    302		return ret;
    303
    304	if (chip->channel_id > AD7816_CS_MAX) {
    305		dev_err(dev, "Invalid oti channel id %d.\n", chip->channel_id);
    306		return -EINVAL;
    307	} else if (chip->channel_id == 0) {
    308		if (value < AD7816_BOUND_VALUE_MIN ||
    309		    value > AD7816_BOUND_VALUE_MAX)
    310			return -EINVAL;
    311
    312		data = (u8)(value - AD7816_BOUND_VALUE_MIN +
    313			AD7816_BOUND_VALUE_BASE);
    314	} else {
    315		if (value < AD7816_BOUND_VALUE_BASE || value > 255)
    316			return -EINVAL;
    317
    318		data = (u8)value;
    319	}
    320
    321	ret = ad7816_spi_write(chip, data);
    322	if (ret)
    323		return -EIO;
    324
    325	chip->oti_data[chip->channel_id] = data;
    326
    327	return len;
    328}
    329
    330static IIO_DEVICE_ATTR(oti, 0644,
    331		       ad7816_show_oti, ad7816_set_oti, 0);
    332
    333static struct attribute *ad7816_event_attributes[] = {
    334	&iio_dev_attr_oti.dev_attr.attr,
    335	NULL,
    336};
    337
    338static const struct attribute_group ad7816_event_attribute_group = {
    339	.attrs = ad7816_event_attributes,
    340	.name = "events",
    341};
    342
    343static const struct iio_info ad7816_info = {
    344	.attrs = &ad7816_attribute_group,
    345	.event_attrs = &ad7816_event_attribute_group,
    346};
    347
    348/*
    349 * device probe and remove
    350 */
    351
    352static int ad7816_probe(struct spi_device *spi_dev)
    353{
    354	struct ad7816_chip_info *chip;
    355	struct iio_dev *indio_dev;
    356	int i, ret;
    357
    358	indio_dev = devm_iio_device_alloc(&spi_dev->dev, sizeof(*chip));
    359	if (!indio_dev)
    360		return -ENOMEM;
    361	chip = iio_priv(indio_dev);
    362	/* this is only used for device removal purposes */
    363	dev_set_drvdata(&spi_dev->dev, indio_dev);
    364
    365	chip->spi_dev = spi_dev;
    366	for (i = 0; i <= AD7816_CS_MAX; i++)
    367		chip->oti_data[i] = 203;
    368
    369	chip->id = spi_get_device_id(spi_dev)->driver_data;
    370	chip->rdwr_pin = devm_gpiod_get(&spi_dev->dev, "rdwr", GPIOD_OUT_HIGH);
    371	if (IS_ERR(chip->rdwr_pin)) {
    372		ret = PTR_ERR(chip->rdwr_pin);
    373		dev_err(&spi_dev->dev, "Failed to request rdwr GPIO: %d\n",
    374			ret);
    375		return ret;
    376	}
    377	chip->convert_pin = devm_gpiod_get(&spi_dev->dev, "convert",
    378					   GPIOD_OUT_HIGH);
    379	if (IS_ERR(chip->convert_pin)) {
    380		ret = PTR_ERR(chip->convert_pin);
    381		dev_err(&spi_dev->dev, "Failed to request convert GPIO: %d\n",
    382			ret);
    383		return ret;
    384	}
    385	if (chip->id == ID_AD7816 || chip->id == ID_AD7817) {
    386		chip->busy_pin = devm_gpiod_get(&spi_dev->dev, "busy",
    387						GPIOD_IN);
    388		if (IS_ERR(chip->busy_pin)) {
    389			ret = PTR_ERR(chip->busy_pin);
    390			dev_err(&spi_dev->dev, "Failed to request busy GPIO: %d\n",
    391				ret);
    392			return ret;
    393		}
    394	}
    395
    396	indio_dev->name = spi_get_device_id(spi_dev)->name;
    397	indio_dev->info = &ad7816_info;
    398	indio_dev->modes = INDIO_DIRECT_MODE;
    399
    400	if (spi_dev->irq) {
    401		/* Only low trigger is supported in ad7816/7/8 */
    402		ret = devm_request_threaded_irq(&spi_dev->dev, spi_dev->irq,
    403						NULL,
    404						&ad7816_event_handler,
    405						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
    406						indio_dev->name,
    407						indio_dev);
    408		if (ret)
    409			return ret;
    410	}
    411
    412	ret = devm_iio_device_register(&spi_dev->dev, indio_dev);
    413	if (ret)
    414		return ret;
    415
    416	dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n",
    417		 indio_dev->name);
    418
    419	return 0;
    420}
    421
    422static const struct of_device_id ad7816_of_match[] = {
    423	{ .compatible = "adi,ad7816", },
    424	{ .compatible = "adi,ad7817", },
    425	{ .compatible = "adi,ad7818", },
    426	{ }
    427};
    428MODULE_DEVICE_TABLE(of, ad7816_of_match);
    429
    430static const struct spi_device_id ad7816_id[] = {
    431	{ "ad7816", ID_AD7816 },
    432	{ "ad7817", ID_AD7817 },
    433	{ "ad7818", ID_AD7818 },
    434	{}
    435};
    436
    437MODULE_DEVICE_TABLE(spi, ad7816_id);
    438
    439static struct spi_driver ad7816_driver = {
    440	.driver = {
    441		.name = "ad7816",
    442		.of_match_table = ad7816_of_match,
    443	},
    444	.probe = ad7816_probe,
    445	.id_table = ad7816_id,
    446};
    447module_spi_driver(ad7816_driver);
    448
    449MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
    450MODULE_DESCRIPTION("Analog Devices AD7816/7/8 digital temperature sensor driver");
    451MODULE_LICENSE("GPL v2");