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

ade7854-spi.c (3311B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (SPI Bus)
      4 *
      5 * Copyright 2010 Analog Devices Inc.
      6 */
      7
      8#include <linux/device.h>
      9#include <linux/kernel.h>
     10#include <linux/spi/spi.h>
     11#include <linux/slab.h>
     12#include <linux/module.h>
     13
     14#include <linux/iio/iio.h>
     15#include "ade7854.h"
     16
     17static int ade7854_spi_write_reg(struct device *dev,
     18				 u16 reg_address,
     19				 u32 val,
     20				 int bits)
     21{
     22	int ret;
     23	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
     24	struct ade7854_state *st = iio_priv(indio_dev);
     25	struct spi_transfer xfer = {
     26		.tx_buf = st->tx,
     27		.bits_per_word = 8,
     28		.len = 4,
     29	};
     30
     31	mutex_lock(&st->buf_lock);
     32	st->tx[0] = ADE7854_WRITE_REG;
     33	st->tx[1] = (reg_address >> 8) & 0xFF;
     34	st->tx[2] = reg_address & 0xFF;
     35	switch (bits) {
     36	case 8:
     37		st->tx[3] = val & 0xFF;
     38		break;
     39	case 16:
     40		xfer.len = 5;
     41		st->tx[3] = (val >> 8) & 0xFF;
     42		st->tx[4] = val & 0xFF;
     43		break;
     44	case 24:
     45		xfer.len = 6;
     46		st->tx[3] = (val >> 16) & 0xFF;
     47		st->tx[4] = (val >> 8) & 0xFF;
     48		st->tx[5] = val & 0xFF;
     49		break;
     50	case 32:
     51		xfer.len = 7;
     52		st->tx[3] = (val >> 24) & 0xFF;
     53		st->tx[4] = (val >> 16) & 0xFF;
     54		st->tx[5] = (val >> 8) & 0xFF;
     55		st->tx[6] = val & 0xFF;
     56		break;
     57	default:
     58		ret = -EINVAL;
     59		goto unlock;
     60	}
     61
     62	ret = spi_sync_transfer(st->spi, &xfer, 1);
     63unlock:
     64	mutex_unlock(&st->buf_lock);
     65
     66	return ret;
     67}
     68
     69static int ade7854_spi_read_reg(struct device *dev,
     70				u16 reg_address,
     71				u32 *val,
     72				int bits)
     73{
     74	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
     75	struct ade7854_state *st = iio_priv(indio_dev);
     76	int ret;
     77	struct spi_transfer xfers[] = {
     78		{
     79			.tx_buf = st->tx,
     80			.bits_per_word = 8,
     81			.len = 3,
     82		}, {
     83			.rx_buf = st->rx,
     84			.bits_per_word = 8,
     85			.len = bits,
     86		}
     87	};
     88
     89	mutex_lock(&st->buf_lock);
     90
     91	st->tx[0] = ADE7854_READ_REG;
     92	st->tx[1] = (reg_address >> 8) & 0xFF;
     93	st->tx[2] = reg_address & 0xFF;
     94
     95	ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
     96	if (ret < 0) {
     97		dev_err(&st->spi->dev, "problem when reading register 0x%02X",
     98			reg_address);
     99		goto unlock;
    100	}
    101
    102	switch (bits) {
    103	case 8:
    104		*val = st->rx[0];
    105		break;
    106	case 16:
    107		*val = be16_to_cpup((const __be16 *)st->rx);
    108		break;
    109	case 24:
    110		*val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
    111		break;
    112	case 32:
    113		*val = be32_to_cpup((const __be32 *)st->rx);
    114		break;
    115	}
    116
    117unlock:
    118	mutex_unlock(&st->buf_lock);
    119	return ret;
    120}
    121
    122static int ade7854_spi_probe(struct spi_device *spi)
    123{
    124	struct ade7854_state *st;
    125	struct iio_dev *indio_dev;
    126
    127	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
    128	if (!indio_dev)
    129		return -ENOMEM;
    130	st = iio_priv(indio_dev);
    131	spi_set_drvdata(spi, indio_dev);
    132	st->read_reg = ade7854_spi_read_reg;
    133	st->write_reg = ade7854_spi_write_reg;
    134	st->irq = spi->irq;
    135	st->spi = spi;
    136
    137	return ade7854_probe(indio_dev, &spi->dev);
    138}
    139
    140static const struct spi_device_id ade7854_id[] = {
    141	{ "ade7854", 0 },
    142	{ "ade7858", 0 },
    143	{ "ade7868", 0 },
    144	{ "ade7878", 0 },
    145	{ }
    146};
    147MODULE_DEVICE_TABLE(spi, ade7854_id);
    148
    149static struct spi_driver ade7854_driver = {
    150	.driver = {
    151		.name = "ade7854",
    152	},
    153	.probe = ade7854_spi_probe,
    154	.id_table = ade7854_id,
    155};
    156module_spi_driver(ade7854_driver);
    157
    158MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
    159MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 SPI Driver");
    160MODULE_LICENSE("GPL v2");