linux/drivers/staging/iio/meter/ade7854-spi.c
<<
>>
Prefs
   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");
 161