GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / staging / iio / meter / ade7854-i2c.c
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
18 static 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
62 unlock:
63         mutex_unlock(&st->buf_lock);
64
65         return ret < 0 ? ret : 0;
66 }
67
68 static 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
108 unlock:
109         mutex_unlock(&st->buf_lock);
110         return ret;
111 }
112
113 static 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
132 static const struct i2c_device_id ade7854_id[] = {
133         { "ade7854", 0 },
134         { "ade7858", 0 },
135         { "ade7868", 0 },
136         { "ade7878", 0 },
137         { }
138 };
139 MODULE_DEVICE_TABLE(i2c, ade7854_id);
140
141 static struct i2c_driver ade7854_i2c_driver = {
142         .driver = {
143                 .name = "ade7854",
144         },
145         .probe    = ade7854_i2c_probe,
146         .id_table = ade7854_id,
147 };
148 module_i2c_driver(ade7854_i2c_driver);
149
150 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
151 MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC I2C Driver");
152 MODULE_LICENSE("GPL v2");