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_8(struct device *dev,
  19                u16 reg_address,
  20                u8 value)
  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
  26        mutex_lock(&st->buf_lock);
  27        st->tx[0] = (reg_address >> 8) & 0xFF;
  28        st->tx[1] = reg_address & 0xFF;
  29        st->tx[2] = value;
  30
  31        ret = i2c_master_send(st->i2c, st->tx, 3);
  32        mutex_unlock(&st->buf_lock);
  33
  34        return ret;
  35}
  36
  37static int ade7854_i2c_write_reg_16(struct device *dev,
  38                u16 reg_address,
  39                u16 value)
  40{
  41        int ret;
  42        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  43        struct ade7854_state *st = iio_priv(indio_dev);
  44
  45        mutex_lock(&st->buf_lock);
  46        st->tx[0] = (reg_address >> 8) & 0xFF;
  47        st->tx[1] = reg_address & 0xFF;
  48        st->tx[2] = (value >> 8) & 0xFF;
  49        st->tx[3] = value & 0xFF;
  50
  51        ret = i2c_master_send(st->i2c, st->tx, 4);
  52        mutex_unlock(&st->buf_lock);
  53
  54        return ret;
  55}
  56
  57static int ade7854_i2c_write_reg_24(struct device *dev,
  58                u16 reg_address,
  59                u32 value)
  60{
  61        int ret;
  62        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  63        struct ade7854_state *st = iio_priv(indio_dev);
  64
  65        mutex_lock(&st->buf_lock);
  66        st->tx[0] = (reg_address >> 8) & 0xFF;
  67        st->tx[1] = reg_address & 0xFF;
  68        st->tx[2] = (value >> 16) & 0xFF;
  69        st->tx[3] = (value >> 8) & 0xFF;
  70        st->tx[4] = value & 0xFF;
  71
  72        ret = i2c_master_send(st->i2c, st->tx, 5);
  73        mutex_unlock(&st->buf_lock);
  74
  75        return ret;
  76}
  77
  78static int ade7854_i2c_write_reg_32(struct device *dev,
  79                u16 reg_address,
  80                u32 value)
  81{
  82        int ret;
  83        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  84        struct ade7854_state *st = iio_priv(indio_dev);
  85
  86        mutex_lock(&st->buf_lock);
  87        st->tx[0] = (reg_address >> 8) & 0xFF;
  88        st->tx[1] = reg_address & 0xFF;
  89        st->tx[2] = (value >> 24) & 0xFF;
  90        st->tx[3] = (value >> 16) & 0xFF;
  91        st->tx[4] = (value >> 8) & 0xFF;
  92        st->tx[5] = value & 0xFF;
  93
  94        ret = i2c_master_send(st->i2c, st->tx, 6);
  95        mutex_unlock(&st->buf_lock);
  96
  97        return ret;
  98}
  99
 100static int ade7854_i2c_read_reg_8(struct device *dev,
 101                u16 reg_address,
 102                u8 *val)
 103{
 104        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 105        struct ade7854_state *st = iio_priv(indio_dev);
 106        int ret;
 107
 108        mutex_lock(&st->buf_lock);
 109        st->tx[0] = (reg_address >> 8) & 0xFF;
 110        st->tx[1] = reg_address & 0xFF;
 111
 112        ret = i2c_master_send(st->i2c, st->tx, 2);
 113        if (ret)
 114                goto out;
 115
 116        ret = i2c_master_recv(st->i2c, st->rx, 1);
 117        if (ret)
 118                goto out;
 119
 120        *val = st->rx[0];
 121out:
 122        mutex_unlock(&st->buf_lock);
 123        return ret;
 124}
 125
 126static int ade7854_i2c_read_reg_16(struct device *dev,
 127                u16 reg_address,
 128                u16 *val)
 129{
 130        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 131        struct ade7854_state *st = iio_priv(indio_dev);
 132        int ret;
 133
 134        mutex_lock(&st->buf_lock);
 135        st->tx[0] = (reg_address >> 8) & 0xFF;
 136        st->tx[1] = reg_address & 0xFF;
 137
 138        ret = i2c_master_send(st->i2c, st->tx, 2);
 139        if (ret)
 140                goto out;
 141
 142        ret = i2c_master_recv(st->i2c, st->rx, 2);
 143        if (ret)
 144                goto out;
 145
 146        *val = (st->rx[0] << 8) | st->rx[1];
 147out:
 148        mutex_unlock(&st->buf_lock);
 149        return ret;
 150}
 151
 152static int ade7854_i2c_read_reg_24(struct device *dev,
 153                u16 reg_address,
 154                u32 *val)
 155{
 156        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 157        struct ade7854_state *st = iio_priv(indio_dev);
 158        int ret;
 159
 160        mutex_lock(&st->buf_lock);
 161        st->tx[0] = (reg_address >> 8) & 0xFF;
 162        st->tx[1] = reg_address & 0xFF;
 163
 164        ret = i2c_master_send(st->i2c, st->tx, 2);
 165        if (ret)
 166                goto out;
 167
 168        ret = i2c_master_recv(st->i2c, st->rx, 3);
 169        if (ret)
 170                goto out;
 171
 172        *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
 173out:
 174        mutex_unlock(&st->buf_lock);
 175        return ret;
 176}
 177
 178static int ade7854_i2c_read_reg_32(struct device *dev,
 179                u16 reg_address,
 180                u32 *val)
 181{
 182        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 183        struct ade7854_state *st = iio_priv(indio_dev);
 184        int ret;
 185
 186        mutex_lock(&st->buf_lock);
 187        st->tx[0] = (reg_address >> 8) & 0xFF;
 188        st->tx[1] = reg_address & 0xFF;
 189
 190        ret = i2c_master_send(st->i2c, st->tx, 2);
 191        if (ret)
 192                goto out;
 193
 194        ret = i2c_master_recv(st->i2c, st->rx, 3);
 195        if (ret)
 196                goto out;
 197
 198        *val = (st->rx[0] << 24) | (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3];
 199out:
 200        mutex_unlock(&st->buf_lock);
 201        return ret;
 202}
 203
 204static int ade7854_i2c_probe(struct i2c_client *client,
 205                const struct i2c_device_id *id)
 206{
 207        int ret;
 208        struct ade7854_state *st;
 209        struct iio_dev *indio_dev;
 210
 211        indio_dev = iio_device_alloc(sizeof(*st));
 212        if (indio_dev == NULL)
 213                return -ENOMEM;
 214        st = iio_priv(indio_dev);
 215        i2c_set_clientdata(client, indio_dev);
 216        st->read_reg_8 = ade7854_i2c_read_reg_8;
 217        st->read_reg_16 = ade7854_i2c_read_reg_16;
 218        st->read_reg_24 = ade7854_i2c_read_reg_24;
 219        st->read_reg_32 = ade7854_i2c_read_reg_32;
 220        st->write_reg_8 = ade7854_i2c_write_reg_8;
 221        st->write_reg_16 = ade7854_i2c_write_reg_16;
 222        st->write_reg_24 = ade7854_i2c_write_reg_24;
 223        st->write_reg_32 = ade7854_i2c_write_reg_32;
 224        st->i2c = client;
 225        st->irq = client->irq;
 226
 227        ret = ade7854_probe(indio_dev, &client->dev);
 228        if (ret)
 229                iio_device_free(indio_dev);
 230
 231        return ret;
 232}
 233
 234static int ade7854_i2c_remove(struct i2c_client *client)
 235{
 236        return ade7854_remove(i2c_get_clientdata(client));
 237}
 238
 239static const struct i2c_device_id ade7854_id[] = {
 240        { "ade7854", 0 },
 241        { "ade7858", 0 },
 242        { "ade7868", 0 },
 243        { "ade7878", 0 },
 244        { }
 245};
 246MODULE_DEVICE_TABLE(i2c, ade7854_id);
 247
 248static struct i2c_driver ade7854_i2c_driver = {
 249        .driver = {
 250                .name = "ade7854",
 251        },
 252        .probe    = ade7854_i2c_probe,
 253        .remove   = ade7854_i2c_remove,
 254        .id_table = ade7854_id,
 255};
 256module_i2c_driver(ade7854_i2c_driver);
 257
 258MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
 259MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC I2C Driver");
 260MODULE_LICENSE("GPL v2");
 261