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