Commit | Line | Data |
---|---|---|
2506abea | 1 | // SPDX-License-Identifier: GPL-2.0+ |
5b264a62 BS |
2 | /* |
3 | * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (I2C Bus) | |
4 | * | |
5 | * Copyright 2010 Analog Devices Inc. | |
5b264a62 BS |
6 | */ |
7 | ||
8 | #include <linux/device.h> | |
9 | #include <linux/kernel.h> | |
10 | #include <linux/i2c.h> | |
11 | #include <linux/slab.h> | |
99c97852 | 12 | #include <linux/module.h> |
5b264a62 | 13 | |
06458e27 | 14 | #include <linux/iio/iio.h> |
5b264a62 BS |
15 | #include "ade7854.h" |
16 | ||
e4c771d3 RS |
17 | static int ade7854_i2c_write_reg(struct device *dev, |
18 | u16 reg_address, | |
19 | u32 val, | |
20 | int bits) | |
5b264a62 BS |
21 | { |
22 | int ret; | |
e4c771d3 | 23 | int count; |
196b59c1 | 24 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
937a9601 | 25 | struct ade7854_state *st = iio_priv(indio_dev); |
5b264a62 BS |
26 | |
27 | mutex_lock(&st->buf_lock); | |
28 | st->tx[0] = (reg_address >> 8) & 0xFF; | |
29 | st->tx[1] = reg_address & 0xFF; | |
5b264a62 | 30 | |
e4c771d3 RS |
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: | |
5b264a62 BS |
62 | mutex_unlock(&st->buf_lock); |
63 | ||
4297b23d | 64 | return ret < 0 ? ret : 0; |
5b264a62 BS |
65 | } |
66 | ||
5d55dcbc RS |
67 | static int ade7854_i2c_read_reg(struct device *dev, |
68 | u16 reg_address, | |
69 | u32 *val, | |
70 | int bits) | |
5b264a62 | 71 | { |
196b59c1 | 72 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
937a9601 | 73 | struct ade7854_state *st = iio_priv(indio_dev); |
5b264a62 BS |
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); | |
4297b23d | 81 | if (ret < 0) |
5d55dcbc | 82 | goto unlock; |
5b264a62 | 83 | |
5d55dcbc | 84 | ret = i2c_master_recv(st->i2c, st->rx, bits); |
4297b23d | 85 | if (ret < 0) |
5d55dcbc RS |
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 | } | |
5b264a62 | 106 | |
5d55dcbc | 107 | unlock: |
5b264a62 BS |
108 | mutex_unlock(&st->buf_lock); |
109 | return ret; | |
110 | } | |
111 | ||
4ae1c61f | 112 | static int ade7854_i2c_probe(struct i2c_client *client, |
08c95f9a | 113 | const struct i2c_device_id *id) |
5b264a62 | 114 | { |
937a9601 JC |
115 | struct ade7854_state *st; |
116 | struct iio_dev *indio_dev; | |
117 | ||
b909459f | 118 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); |
f9be1085 | 119 | if (!indio_dev) |
937a9601 JC |
120 | return -ENOMEM; |
121 | st = iio_priv(indio_dev); | |
122 | i2c_set_clientdata(client, indio_dev); | |
8ea0fa7c | 123 | st->read_reg = ade7854_i2c_read_reg; |
259a8202 | 124 | st->write_reg = ade7854_i2c_write_reg; |
5b264a62 BS |
125 | st->i2c = client; |
126 | st->irq = client->irq; | |
127 | ||
07f83131 | 128 | return ade7854_probe(indio_dev, &client->dev); |
5b264a62 BS |
129 | } |
130 | ||
5b264a62 BS |
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, | |
5b264a62 BS |
145 | .id_table = ade7854_id, |
146 | }; | |
6e5af184 | 147 | module_i2c_driver(ade7854_i2c_driver); |
5b264a62 BS |
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"); |