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-i2c.c (3178B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (I2C Bus)
      4 *
      5 * Copyright 2010 Analog Devices Inc.
      6 */
      7
      8#include <linux/device.h>
      9#include <linux/kernel.h>
     10#include <linux/i2c.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_i2c_write_reg(struct device *dev,
     18				 u16 reg_address,
     19				 u32 val,
     20				 int bits)
     21{
     22	int ret;
     23	int count;
     24	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
     25	struct ade7854_state *st = iio_priv(indio_dev);
     26
     27	mutex_lock(&st->buf_lock);
     28	st->tx[0] = (reg_address >> 8) & 0xFF;
     29	st->tx[1] = reg_address & 0xFF;
     30
     31	switch (bits) {
     32	case 8:
     33		st->tx[2] = val & 0xFF;
     34		count = 3;
     35		break;
     36	case 16:
     37		st->tx[2] = (val >> 8) & 0xFF;
     38		st->tx[3] = val & 0xFF;
     39		count = 4;
     40		break;
     41	case 24:
     42		st->tx[2] = (val >> 16) & 0xFF;
     43		st->tx[3] = (val >> 8) & 0xFF;
     44		st->tx[4] = val & 0xFF;
     45		count = 5;
     46		break;
     47	case 32:
     48		st->tx[2] = (val >> 24) & 0xFF;
     49		st->tx[3] = (val >> 16) & 0xFF;
     50		st->tx[4] = (val >> 8) & 0xFF;
     51		st->tx[5] = val & 0xFF;
     52		count = 6;
     53		break;
     54	default:
     55		ret = -EINVAL;
     56		goto unlock;
     57	}
     58
     59	ret = i2c_master_send(st->i2c, st->tx, count);
     60
     61unlock:
     62	mutex_unlock(&st->buf_lock);
     63
     64	return ret < 0 ? ret : 0;
     65}
     66
     67static int ade7854_i2c_read_reg(struct device *dev,
     68				u16 reg_address,
     69				u32 *val,
     70				int bits)
     71{
     72	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
     73	struct ade7854_state *st = iio_priv(indio_dev);
     74	int ret;
     75
     76	mutex_lock(&st->buf_lock);
     77	st->tx[0] = (reg_address >> 8) & 0xFF;
     78	st->tx[1] = reg_address & 0xFF;
     79
     80	ret = i2c_master_send(st->i2c, st->tx, 2);
     81	if (ret < 0)
     82		goto unlock;
     83
     84	ret = i2c_master_recv(st->i2c, st->rx, bits);
     85	if (ret < 0)
     86		goto unlock;
     87
     88	switch (bits) {
     89	case 8:
     90		*val = st->rx[0];
     91		break;
     92	case 16:
     93		*val = (st->rx[0] << 8) | st->rx[1];
     94		break;
     95	case 24:
     96		*val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
     97		break;
     98	case 32:
     99		*val = (st->rx[0] << 24) | (st->rx[1] << 16) |
    100			(st->rx[2] << 8) | st->rx[3];
    101		break;
    102	default:
    103		ret = -EINVAL;
    104		goto unlock;
    105	}
    106
    107unlock:
    108	mutex_unlock(&st->buf_lock);
    109	return ret;
    110}
    111
    112static int ade7854_i2c_probe(struct i2c_client *client,
    113			     const struct i2c_device_id *id)
    114{
    115	struct ade7854_state *st;
    116	struct iio_dev *indio_dev;
    117
    118	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
    119	if (!indio_dev)
    120		return -ENOMEM;
    121	st = iio_priv(indio_dev);
    122	i2c_set_clientdata(client, indio_dev);
    123	st->read_reg = ade7854_i2c_read_reg;
    124	st->write_reg = ade7854_i2c_write_reg;
    125	st->i2c = client;
    126	st->irq = client->irq;
    127
    128	return ade7854_probe(indio_dev, &client->dev);
    129}
    130
    131static const struct i2c_device_id ade7854_id[] = {
    132	{ "ade7854", 0 },
    133	{ "ade7858", 0 },
    134	{ "ade7868", 0 },
    135	{ "ade7878", 0 },
    136	{ }
    137};
    138MODULE_DEVICE_TABLE(i2c, ade7854_id);
    139
    140static struct i2c_driver ade7854_i2c_driver = {
    141	.driver = {
    142		.name = "ade7854",
    143	},
    144	.probe    = ade7854_i2c_probe,
    145	.id_table = ade7854_id,
    146};
    147module_i2c_driver(ade7854_i2c_driver);
    148
    149MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
    150MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC I2C Driver");
    151MODULE_LICENSE("GPL v2");