Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (I2C Bus)
0004  *
0005  * Copyright 2010 Analog Devices Inc.
0006  */
0007 
0008 #include <linux/device.h>
0009 #include <linux/kernel.h>
0010 #include <linux/i2c.h>
0011 #include <linux/slab.h>
0012 #include <linux/module.h>
0013 
0014 #include <linux/iio/iio.h>
0015 #include "ade7854.h"
0016 
0017 static int ade7854_i2c_write_reg(struct device *dev,
0018                  u16 reg_address,
0019                  u32 val,
0020                  int bits)
0021 {
0022     int ret;
0023     int count;
0024     struct iio_dev *indio_dev = dev_to_iio_dev(dev);
0025     struct ade7854_state *st = iio_priv(indio_dev);
0026 
0027     mutex_lock(&st->buf_lock);
0028     st->tx[0] = (reg_address >> 8) & 0xFF;
0029     st->tx[1] = reg_address & 0xFF;
0030 
0031     switch (bits) {
0032     case 8:
0033         st->tx[2] = val & 0xFF;
0034         count = 3;
0035         break;
0036     case 16:
0037         st->tx[2] = (val >> 8) & 0xFF;
0038         st->tx[3] = val & 0xFF;
0039         count = 4;
0040         break;
0041     case 24:
0042         st->tx[2] = (val >> 16) & 0xFF;
0043         st->tx[3] = (val >> 8) & 0xFF;
0044         st->tx[4] = val & 0xFF;
0045         count = 5;
0046         break;
0047     case 32:
0048         st->tx[2] = (val >> 24) & 0xFF;
0049         st->tx[3] = (val >> 16) & 0xFF;
0050         st->tx[4] = (val >> 8) & 0xFF;
0051         st->tx[5] = val & 0xFF;
0052         count = 6;
0053         break;
0054     default:
0055         ret = -EINVAL;
0056         goto unlock;
0057     }
0058 
0059     ret = i2c_master_send(st->i2c, st->tx, count);
0060 
0061 unlock:
0062     mutex_unlock(&st->buf_lock);
0063 
0064     return ret < 0 ? ret : 0;
0065 }
0066 
0067 static int ade7854_i2c_read_reg(struct device *dev,
0068                 u16 reg_address,
0069                 u32 *val,
0070                 int bits)
0071 {
0072     struct iio_dev *indio_dev = dev_to_iio_dev(dev);
0073     struct ade7854_state *st = iio_priv(indio_dev);
0074     int ret;
0075 
0076     mutex_lock(&st->buf_lock);
0077     st->tx[0] = (reg_address >> 8) & 0xFF;
0078     st->tx[1] = reg_address & 0xFF;
0079 
0080     ret = i2c_master_send(st->i2c, st->tx, 2);
0081     if (ret < 0)
0082         goto unlock;
0083 
0084     ret = i2c_master_recv(st->i2c, st->rx, bits);
0085     if (ret < 0)
0086         goto unlock;
0087 
0088     switch (bits) {
0089     case 8:
0090         *val = st->rx[0];
0091         break;
0092     case 16:
0093         *val = (st->rx[0] << 8) | st->rx[1];
0094         break;
0095     case 24:
0096         *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
0097         break;
0098     case 32:
0099         *val = (st->rx[0] << 24) | (st->rx[1] << 16) |
0100             (st->rx[2] << 8) | st->rx[3];
0101         break;
0102     default:
0103         ret = -EINVAL;
0104         goto unlock;
0105     }
0106 
0107 unlock:
0108     mutex_unlock(&st->buf_lock);
0109     return ret;
0110 }
0111 
0112 static int ade7854_i2c_probe(struct i2c_client *client,
0113                  const struct i2c_device_id *id)
0114 {
0115     struct ade7854_state *st;
0116     struct iio_dev *indio_dev;
0117 
0118     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
0119     if (!indio_dev)
0120         return -ENOMEM;
0121     st = iio_priv(indio_dev);
0122     i2c_set_clientdata(client, indio_dev);
0123     st->read_reg = ade7854_i2c_read_reg;
0124     st->write_reg = ade7854_i2c_write_reg;
0125     st->i2c = client;
0126     st->irq = client->irq;
0127 
0128     return ade7854_probe(indio_dev, &client->dev);
0129 }
0130 
0131 static const struct i2c_device_id ade7854_id[] = {
0132     { "ade7854", 0 },
0133     { "ade7858", 0 },
0134     { "ade7868", 0 },
0135     { "ade7878", 0 },
0136     { }
0137 };
0138 MODULE_DEVICE_TABLE(i2c, ade7854_id);
0139 
0140 static struct i2c_driver ade7854_i2c_driver = {
0141     .driver = {
0142         .name = "ade7854",
0143     },
0144     .probe    = ade7854_i2c_probe,
0145     .id_table = ade7854_id,
0146 };
0147 module_i2c_driver(ade7854_i2c_driver);
0148 
0149 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
0150 MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC I2C Driver");
0151 MODULE_LICENSE("GPL v2");