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