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

hi8435.c (13675B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Holt Integrated Circuits HI-8435 threshold detector driver
      4 *
      5 * Copyright (C) 2015 Zodiac Inflight Innovations
      6 * Copyright (C) 2015 Cogent Embedded, Inc.
      7 */
      8
      9#include <linux/delay.h>
     10#include <linux/iio/events.h>
     11#include <linux/iio/iio.h>
     12#include <linux/iio/sysfs.h>
     13#include <linux/iio/trigger.h>
     14#include <linux/iio/trigger_consumer.h>
     15#include <linux/iio/triggered_event.h>
     16#include <linux/interrupt.h>
     17#include <linux/module.h>
     18#include <linux/mod_devicetable.h>
     19#include <linux/spi/spi.h>
     20#include <linux/gpio/consumer.h>
     21
     22#define DRV_NAME "hi8435"
     23
     24/* Register offsets for HI-8435 */
     25#define HI8435_CTRL_REG		0x02
     26#define HI8435_PSEN_REG		0x04
     27#define HI8435_TMDATA_REG	0x1E
     28#define HI8435_GOCENHYS_REG	0x3A
     29#define HI8435_SOCENHYS_REG	0x3C
     30#define HI8435_SO7_0_REG	0x10
     31#define HI8435_SO15_8_REG	0x12
     32#define HI8435_SO23_16_REG	0x14
     33#define HI8435_SO31_24_REG	0x16
     34#define HI8435_SO31_0_REG	0x78
     35
     36#define HI8435_WRITE_OPCODE	0x00
     37#define HI8435_READ_OPCODE	0x80
     38
     39/* CTRL register bits */
     40#define HI8435_CTRL_TEST	0x01
     41#define HI8435_CTRL_SRST	0x02
     42
     43struct hi8435_priv {
     44	struct spi_device *spi;
     45	struct mutex lock;
     46
     47	unsigned long event_scan_mask; /* soft mask/unmask channels events */
     48	unsigned int event_prev_val;
     49
     50	unsigned threshold_lo[2]; /* GND-Open and Supply-Open thresholds */
     51	unsigned threshold_hi[2]; /* GND-Open and Supply-Open thresholds */
     52	u8 reg_buffer[3] ____cacheline_aligned;
     53};
     54
     55static int hi8435_readb(struct hi8435_priv *priv, u8 reg, u8 *val)
     56{
     57	reg |= HI8435_READ_OPCODE;
     58	return spi_write_then_read(priv->spi, &reg, 1, val, 1);
     59}
     60
     61static int hi8435_readw(struct hi8435_priv *priv, u8 reg, u16 *val)
     62{
     63	int ret;
     64	__be16 be_val;
     65
     66	reg |= HI8435_READ_OPCODE;
     67	ret = spi_write_then_read(priv->spi, &reg, 1, &be_val, 2);
     68	*val = be16_to_cpu(be_val);
     69
     70	return ret;
     71}
     72
     73static int hi8435_readl(struct hi8435_priv *priv, u8 reg, u32 *val)
     74{
     75	int ret;
     76	__be32 be_val;
     77
     78	reg |= HI8435_READ_OPCODE;
     79	ret = spi_write_then_read(priv->spi, &reg, 1, &be_val, 4);
     80	*val = be32_to_cpu(be_val);
     81
     82	return ret;
     83}
     84
     85static int hi8435_writeb(struct hi8435_priv *priv, u8 reg, u8 val)
     86{
     87	priv->reg_buffer[0] = reg | HI8435_WRITE_OPCODE;
     88	priv->reg_buffer[1] = val;
     89
     90	return spi_write(priv->spi, priv->reg_buffer, 2);
     91}
     92
     93static int hi8435_writew(struct hi8435_priv *priv, u8 reg, u16 val)
     94{
     95	priv->reg_buffer[0] = reg | HI8435_WRITE_OPCODE;
     96	priv->reg_buffer[1] = (val >> 8) & 0xff;
     97	priv->reg_buffer[2] = val & 0xff;
     98
     99	return spi_write(priv->spi, priv->reg_buffer, 3);
    100}
    101
    102static int hi8435_read_raw(struct iio_dev *idev,
    103			   const struct iio_chan_spec *chan,
    104			   int *val, int *val2, long mask)
    105{
    106	struct hi8435_priv *priv = iio_priv(idev);
    107	u32 tmp;
    108	int ret;
    109
    110	switch (mask) {
    111	case IIO_CHAN_INFO_RAW:
    112		ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp);
    113		if (ret < 0)
    114			return ret;
    115		*val = !!(tmp & BIT(chan->channel));
    116		return IIO_VAL_INT;
    117	default:
    118		return -EINVAL;
    119	}
    120}
    121
    122static int hi8435_read_event_config(struct iio_dev *idev,
    123				    const struct iio_chan_spec *chan,
    124				    enum iio_event_type type,
    125				    enum iio_event_direction dir)
    126{
    127	struct hi8435_priv *priv = iio_priv(idev);
    128
    129	return !!(priv->event_scan_mask & BIT(chan->channel));
    130}
    131
    132static int hi8435_write_event_config(struct iio_dev *idev,
    133				     const struct iio_chan_spec *chan,
    134				     enum iio_event_type type,
    135				     enum iio_event_direction dir, int state)
    136{
    137	struct hi8435_priv *priv = iio_priv(idev);
    138	int ret;
    139	u32 tmp;
    140
    141	if (state) {
    142		ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp);
    143		if (ret < 0)
    144			return ret;
    145		if (tmp & BIT(chan->channel))
    146			priv->event_prev_val |= BIT(chan->channel);
    147		else
    148			priv->event_prev_val &= ~BIT(chan->channel);
    149
    150		priv->event_scan_mask |= BIT(chan->channel);
    151	} else
    152		priv->event_scan_mask &= ~BIT(chan->channel);
    153
    154	return 0;
    155}
    156
    157static int hi8435_read_event_value(struct iio_dev *idev,
    158				   const struct iio_chan_spec *chan,
    159				   enum iio_event_type type,
    160				   enum iio_event_direction dir,
    161				   enum iio_event_info info,
    162				   int *val, int *val2)
    163{
    164	struct hi8435_priv *priv = iio_priv(idev);
    165	int ret;
    166	u8 mode, psen;
    167	u16 reg;
    168
    169	ret = hi8435_readb(priv, HI8435_PSEN_REG, &psen);
    170	if (ret < 0)
    171		return ret;
    172
    173	/* Supply-Open or GND-Open sensing mode */
    174	mode = !!(psen & BIT(chan->channel / 8));
    175
    176	ret = hi8435_readw(priv, mode ? HI8435_SOCENHYS_REG :
    177				 HI8435_GOCENHYS_REG, &reg);
    178	if (ret < 0)
    179		return ret;
    180
    181	if (dir == IIO_EV_DIR_FALLING)
    182		*val = ((reg & 0xff) - (reg >> 8)) / 2;
    183	else if (dir == IIO_EV_DIR_RISING)
    184		*val = ((reg & 0xff) + (reg >> 8)) / 2;
    185
    186	return IIO_VAL_INT;
    187}
    188
    189static int hi8435_write_event_value(struct iio_dev *idev,
    190				    const struct iio_chan_spec *chan,
    191				    enum iio_event_type type,
    192				    enum iio_event_direction dir,
    193				    enum iio_event_info info,
    194				    int val, int val2)
    195{
    196	struct hi8435_priv *priv = iio_priv(idev);
    197	int ret;
    198	u8 mode, psen;
    199	u16 reg;
    200
    201	ret = hi8435_readb(priv, HI8435_PSEN_REG, &psen);
    202	if (ret < 0)
    203		return ret;
    204
    205	/* Supply-Open or GND-Open sensing mode */
    206	mode = !!(psen & BIT(chan->channel / 8));
    207
    208	ret = hi8435_readw(priv, mode ? HI8435_SOCENHYS_REG :
    209				 HI8435_GOCENHYS_REG, &reg);
    210	if (ret < 0)
    211		return ret;
    212
    213	if (dir == IIO_EV_DIR_FALLING) {
    214		/* falling threshold range 2..21V, hysteresis minimum 2V */
    215		if (val < 2 || val > 21 || (val + 2) > priv->threshold_hi[mode])
    216			return -EINVAL;
    217
    218		if (val == priv->threshold_lo[mode])
    219			return 0;
    220
    221		priv->threshold_lo[mode] = val;
    222
    223		/* hysteresis must not be odd */
    224		if ((priv->threshold_hi[mode] - priv->threshold_lo[mode]) % 2)
    225			priv->threshold_hi[mode]--;
    226	} else if (dir == IIO_EV_DIR_RISING) {
    227		/* rising threshold range 3..22V, hysteresis minimum 2V */
    228		if (val < 3 || val > 22 || val < (priv->threshold_lo[mode] + 2))
    229			return -EINVAL;
    230
    231		if (val == priv->threshold_hi[mode])
    232			return 0;
    233
    234		priv->threshold_hi[mode] = val;
    235
    236		/* hysteresis must not be odd */
    237		if ((priv->threshold_hi[mode] - priv->threshold_lo[mode]) % 2)
    238			priv->threshold_lo[mode]++;
    239	}
    240
    241	/* program thresholds */
    242	mutex_lock(&priv->lock);
    243
    244	ret = hi8435_readw(priv, mode ? HI8435_SOCENHYS_REG :
    245				 HI8435_GOCENHYS_REG, &reg);
    246	if (ret < 0) {
    247		mutex_unlock(&priv->lock);
    248		return ret;
    249	}
    250
    251	/* hysteresis */
    252	reg = priv->threshold_hi[mode] - priv->threshold_lo[mode];
    253	reg <<= 8;
    254	/* threshold center */
    255	reg |= (priv->threshold_hi[mode] + priv->threshold_lo[mode]);
    256
    257	ret = hi8435_writew(priv, mode ? HI8435_SOCENHYS_REG :
    258				  HI8435_GOCENHYS_REG, reg);
    259
    260	mutex_unlock(&priv->lock);
    261
    262	return ret;
    263}
    264
    265static int hi8435_debugfs_reg_access(struct iio_dev *idev,
    266				     unsigned reg, unsigned writeval,
    267				     unsigned *readval)
    268{
    269	struct hi8435_priv *priv = iio_priv(idev);
    270	int ret;
    271	u8 val;
    272
    273	if (readval != NULL) {
    274		ret = hi8435_readb(priv, reg, &val);
    275		*readval = val;
    276	} else {
    277		val = (u8)writeval;
    278		ret = hi8435_writeb(priv, reg, val);
    279	}
    280
    281	return ret;
    282}
    283
    284static const struct iio_event_spec hi8435_events[] = {
    285	{
    286		.type = IIO_EV_TYPE_THRESH,
    287		.dir = IIO_EV_DIR_RISING,
    288		.mask_separate = BIT(IIO_EV_INFO_VALUE),
    289	}, {
    290		.type = IIO_EV_TYPE_THRESH,
    291		.dir = IIO_EV_DIR_FALLING,
    292		.mask_separate = BIT(IIO_EV_INFO_VALUE),
    293	}, {
    294		.type = IIO_EV_TYPE_THRESH,
    295		.dir = IIO_EV_DIR_EITHER,
    296		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
    297	},
    298};
    299
    300static int hi8435_get_sensing_mode(struct iio_dev *idev,
    301				   const struct iio_chan_spec *chan)
    302{
    303	struct hi8435_priv *priv = iio_priv(idev);
    304	int ret;
    305	u8 reg;
    306
    307	ret = hi8435_readb(priv, HI8435_PSEN_REG, &reg);
    308	if (ret < 0)
    309		return ret;
    310
    311	return !!(reg & BIT(chan->channel / 8));
    312}
    313
    314static int hi8435_set_sensing_mode(struct iio_dev *idev,
    315				   const struct iio_chan_spec *chan,
    316				   unsigned int mode)
    317{
    318	struct hi8435_priv *priv = iio_priv(idev);
    319	int ret;
    320	u8 reg;
    321
    322	mutex_lock(&priv->lock);
    323
    324	ret = hi8435_readb(priv, HI8435_PSEN_REG, &reg);
    325	if (ret < 0) {
    326		mutex_unlock(&priv->lock);
    327		return ret;
    328	}
    329
    330	reg &= ~BIT(chan->channel / 8);
    331	if (mode)
    332		reg |= BIT(chan->channel / 8);
    333
    334	ret = hi8435_writeb(priv, HI8435_PSEN_REG, reg);
    335
    336	mutex_unlock(&priv->lock);
    337
    338	return ret;
    339}
    340
    341static const char * const hi8435_sensing_modes[] = { "GND-Open",
    342						     "Supply-Open" };
    343
    344static const struct iio_enum hi8435_sensing_mode = {
    345	.items = hi8435_sensing_modes,
    346	.num_items = ARRAY_SIZE(hi8435_sensing_modes),
    347	.get = hi8435_get_sensing_mode,
    348	.set = hi8435_set_sensing_mode,
    349};
    350
    351static const struct iio_chan_spec_ext_info hi8435_ext_info[] = {
    352	IIO_ENUM("sensing_mode", IIO_SEPARATE, &hi8435_sensing_mode),
    353	IIO_ENUM_AVAILABLE("sensing_mode", IIO_SHARED_BY_TYPE, &hi8435_sensing_mode),
    354	{},
    355};
    356
    357#define HI8435_VOLTAGE_CHANNEL(num)			\
    358{							\
    359	.type = IIO_VOLTAGE,				\
    360	.indexed = 1,					\
    361	.channel = num,					\
    362	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
    363	.event_spec = hi8435_events,			\
    364	.num_event_specs = ARRAY_SIZE(hi8435_events),	\
    365	.ext_info = hi8435_ext_info,			\
    366}
    367
    368static const struct iio_chan_spec hi8435_channels[] = {
    369	HI8435_VOLTAGE_CHANNEL(0),
    370	HI8435_VOLTAGE_CHANNEL(1),
    371	HI8435_VOLTAGE_CHANNEL(2),
    372	HI8435_VOLTAGE_CHANNEL(3),
    373	HI8435_VOLTAGE_CHANNEL(4),
    374	HI8435_VOLTAGE_CHANNEL(5),
    375	HI8435_VOLTAGE_CHANNEL(6),
    376	HI8435_VOLTAGE_CHANNEL(7),
    377	HI8435_VOLTAGE_CHANNEL(8),
    378	HI8435_VOLTAGE_CHANNEL(9),
    379	HI8435_VOLTAGE_CHANNEL(10),
    380	HI8435_VOLTAGE_CHANNEL(11),
    381	HI8435_VOLTAGE_CHANNEL(12),
    382	HI8435_VOLTAGE_CHANNEL(13),
    383	HI8435_VOLTAGE_CHANNEL(14),
    384	HI8435_VOLTAGE_CHANNEL(15),
    385	HI8435_VOLTAGE_CHANNEL(16),
    386	HI8435_VOLTAGE_CHANNEL(17),
    387	HI8435_VOLTAGE_CHANNEL(18),
    388	HI8435_VOLTAGE_CHANNEL(19),
    389	HI8435_VOLTAGE_CHANNEL(20),
    390	HI8435_VOLTAGE_CHANNEL(21),
    391	HI8435_VOLTAGE_CHANNEL(22),
    392	HI8435_VOLTAGE_CHANNEL(23),
    393	HI8435_VOLTAGE_CHANNEL(24),
    394	HI8435_VOLTAGE_CHANNEL(25),
    395	HI8435_VOLTAGE_CHANNEL(26),
    396	HI8435_VOLTAGE_CHANNEL(27),
    397	HI8435_VOLTAGE_CHANNEL(28),
    398	HI8435_VOLTAGE_CHANNEL(29),
    399	HI8435_VOLTAGE_CHANNEL(30),
    400	HI8435_VOLTAGE_CHANNEL(31),
    401	IIO_CHAN_SOFT_TIMESTAMP(32),
    402};
    403
    404static const struct iio_info hi8435_info = {
    405	.read_raw = hi8435_read_raw,
    406	.read_event_config = hi8435_read_event_config,
    407	.write_event_config = hi8435_write_event_config,
    408	.read_event_value = hi8435_read_event_value,
    409	.write_event_value = hi8435_write_event_value,
    410	.debugfs_reg_access = hi8435_debugfs_reg_access,
    411};
    412
    413static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val)
    414{
    415	struct hi8435_priv *priv = iio_priv(idev);
    416	enum iio_event_direction dir;
    417	unsigned int i;
    418	unsigned int status = priv->event_prev_val ^ val;
    419
    420	if (!status)
    421		return;
    422
    423	for_each_set_bit(i, &priv->event_scan_mask, 32) {
    424		if (status & BIT(i)) {
    425			dir = val & BIT(i) ? IIO_EV_DIR_RISING :
    426					     IIO_EV_DIR_FALLING;
    427			iio_push_event(idev,
    428				       IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,
    429						    IIO_EV_TYPE_THRESH, dir),
    430				       iio_get_time_ns(idev));
    431		}
    432	}
    433
    434	priv->event_prev_val = val;
    435}
    436
    437static irqreturn_t hi8435_trigger_handler(int irq, void *private)
    438{
    439	struct iio_poll_func *pf = private;
    440	struct iio_dev *idev = pf->indio_dev;
    441	struct hi8435_priv *priv = iio_priv(idev);
    442	u32 val;
    443	int ret;
    444
    445	ret = hi8435_readl(priv, HI8435_SO31_0_REG, &val);
    446	if (ret < 0)
    447		goto err_read;
    448
    449	hi8435_iio_push_event(idev, val);
    450
    451err_read:
    452	iio_trigger_notify_done(idev->trig);
    453
    454	return IRQ_HANDLED;
    455}
    456
    457static void hi8435_triggered_event_cleanup(void *data)
    458{
    459	iio_triggered_event_cleanup(data);
    460}
    461
    462static int hi8435_probe(struct spi_device *spi)
    463{
    464	struct iio_dev *idev;
    465	struct hi8435_priv *priv;
    466	struct gpio_desc *reset_gpio;
    467	int ret;
    468
    469	idev = devm_iio_device_alloc(&spi->dev, sizeof(*priv));
    470	if (!idev)
    471		return -ENOMEM;
    472
    473	priv = iio_priv(idev);
    474	priv->spi = spi;
    475
    476	reset_gpio = devm_gpiod_get(&spi->dev, NULL, GPIOD_OUT_LOW);
    477	if (IS_ERR(reset_gpio)) {
    478		/* chip s/w reset if h/w reset failed */
    479		hi8435_writeb(priv, HI8435_CTRL_REG, HI8435_CTRL_SRST);
    480		hi8435_writeb(priv, HI8435_CTRL_REG, 0);
    481	} else {
    482		udelay(5);
    483		gpiod_set_value_cansleep(reset_gpio, 1);
    484	}
    485
    486	mutex_init(&priv->lock);
    487
    488	idev->name		= spi_get_device_id(spi)->name;
    489	idev->modes		= INDIO_DIRECT_MODE;
    490	idev->info		= &hi8435_info;
    491	idev->channels		= hi8435_channels;
    492	idev->num_channels	= ARRAY_SIZE(hi8435_channels);
    493
    494	/* unmask all events */
    495	priv->event_scan_mask = ~(0);
    496	/*
    497	 * There is a restriction in the chip - the hysteresis can not be odd.
    498	 * If the hysteresis is set to odd value then chip gets into lock state
    499	 * and not functional anymore.
    500	 * After chip reset the thresholds are in undefined state, so we need to
    501	 * initialize thresholds to some initial values and then prevent
    502	 * userspace setting odd hysteresis.
    503	 *
    504	 * Set threshold low voltage to 2V, threshold high voltage to 4V
    505	 * for both GND-Open and Supply-Open sensing modes.
    506	 */
    507	priv->threshold_lo[0] = priv->threshold_lo[1] = 2;
    508	priv->threshold_hi[0] = priv->threshold_hi[1] = 4;
    509	hi8435_writew(priv, HI8435_GOCENHYS_REG, 0x206);
    510	hi8435_writew(priv, HI8435_SOCENHYS_REG, 0x206);
    511
    512	ret = iio_triggered_event_setup(idev, NULL, hi8435_trigger_handler);
    513	if (ret)
    514		return ret;
    515
    516	ret = devm_add_action_or_reset(&spi->dev,
    517				       hi8435_triggered_event_cleanup,
    518				       idev);
    519	if (ret)
    520		return ret;
    521
    522	return devm_iio_device_register(&spi->dev, idev);
    523}
    524
    525static const struct of_device_id hi8435_dt_ids[] = {
    526	{ .compatible = "holt,hi8435" },
    527	{},
    528};
    529MODULE_DEVICE_TABLE(of, hi8435_dt_ids);
    530
    531static const struct spi_device_id hi8435_id[] = {
    532	{ "hi8435", 0 },
    533	{ }
    534};
    535MODULE_DEVICE_TABLE(spi, hi8435_id);
    536
    537static struct spi_driver hi8435_driver = {
    538	.driver	= {
    539		.name		= DRV_NAME,
    540		.of_match_table	= hi8435_dt_ids,
    541	},
    542	.probe		= hi8435_probe,
    543	.id_table	= hi8435_id,
    544};
    545module_spi_driver(hi8435_driver);
    546
    547MODULE_LICENSE("GPL");
    548MODULE_AUTHOR("Vladimir Barinov");
    549MODULE_DESCRIPTION("HI-8435 threshold detector");