Commit | Line | Data |
---|---|---|
5b264a62 BS |
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> | |
99c97852 | 13 | #include <linux/module.h> |
5b264a62 | 14 | |
06458e27 | 15 | #include <linux/iio/iio.h> |
5b264a62 BS |
16 | #include "ade7854.h" |
17 | ||
e4c771d3 RS |
18 | static int ade7854_i2c_write_reg(struct device *dev, |
19 | u16 reg_address, | |
20 | u32 val, | |
21 | int bits) | |
5b264a62 BS |
22 | { |
23 | int ret; | |
e4c771d3 | 24 | int count; |
196b59c1 | 25 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
937a9601 | 26 | struct ade7854_state *st = iio_priv(indio_dev); |
5b264a62 BS |
27 | |
28 | mutex_lock(&st->buf_lock); | |
29 | st->tx[0] = (reg_address >> 8) & 0xFF; | |
30 | st->tx[1] = reg_address & 0xFF; | |
5b264a62 | 31 | |
e4c771d3 RS |
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: | |
5b264a62 BS |
63 | mutex_unlock(&st->buf_lock); |
64 | ||
4297b23d | 65 | return ret < 0 ? ret : 0; |
5b264a62 BS |
66 | } |
67 | ||
5d55dcbc RS |
68 | static int ade7854_i2c_read_reg(struct device *dev, |
69 | u16 reg_address, | |
70 | u32 *val, | |
71 | int bits) | |
5b264a62 | 72 | { |
196b59c1 | 73 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
937a9601 | 74 | struct ade7854_state *st = iio_priv(indio_dev); |
5b264a62 BS |
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); | |
4297b23d | 82 | if (ret < 0) |
5d55dcbc | 83 | goto unlock; |
5b264a62 | 84 | |
5d55dcbc | 85 | ret = i2c_master_recv(st->i2c, st->rx, bits); |
4297b23d | 86 | if (ret < 0) |
5d55dcbc RS |
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 | } | |
5b264a62 | 107 | |
5d55dcbc | 108 | unlock: |
5b264a62 BS |
109 | mutex_unlock(&st->buf_lock); |
110 | return ret; | |
111 | } | |
112 | ||
5d55dcbc RS |
113 | static int ade7854_i2c_read_reg_8(struct device *dev, |
114 | u16 reg_address, | |
115 | u8 *val) | |
116 | { | |
117 | return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 8); | |
118 | } | |
119 | ||
5b264a62 | 120 | static int ade7854_i2c_read_reg_16(struct device *dev, |
08c95f9a TC |
121 | u16 reg_address, |
122 | u16 *val) | |
5b264a62 | 123 | { |
5d55dcbc | 124 | return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 16); |
5b264a62 BS |
125 | } |
126 | ||
127 | static int ade7854_i2c_read_reg_24(struct device *dev, | |
08c95f9a TC |
128 | u16 reg_address, |
129 | u32 *val) | |
5b264a62 | 130 | { |
5d55dcbc | 131 | return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 24); |
5b264a62 BS |
132 | } |
133 | ||
134 | static int ade7854_i2c_read_reg_32(struct device *dev, | |
08c95f9a TC |
135 | u16 reg_address, |
136 | u32 *val) | |
5b264a62 | 137 | { |
5d55dcbc | 138 | return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 32); |
5b264a62 BS |
139 | } |
140 | ||
4ae1c61f | 141 | static int ade7854_i2c_probe(struct i2c_client *client, |
08c95f9a | 142 | const struct i2c_device_id *id) |
5b264a62 | 143 | { |
937a9601 JC |
144 | struct ade7854_state *st; |
145 | struct iio_dev *indio_dev; | |
146 | ||
b909459f | 147 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); |
f9be1085 | 148 | if (!indio_dev) |
937a9601 JC |
149 | return -ENOMEM; |
150 | st = iio_priv(indio_dev); | |
151 | i2c_set_clientdata(client, indio_dev); | |
5b264a62 BS |
152 | st->read_reg_8 = ade7854_i2c_read_reg_8; |
153 | st->read_reg_16 = ade7854_i2c_read_reg_16; | |
154 | st->read_reg_24 = ade7854_i2c_read_reg_24; | |
155 | st->read_reg_32 = ade7854_i2c_read_reg_32; | |
259a8202 | 156 | st->write_reg = ade7854_i2c_write_reg; |
5b264a62 BS |
157 | st->i2c = client; |
158 | st->irq = client->irq; | |
159 | ||
07f83131 | 160 | return ade7854_probe(indio_dev, &client->dev); |
5b264a62 BS |
161 | } |
162 | ||
5b264a62 BS |
163 | static const struct i2c_device_id ade7854_id[] = { |
164 | { "ade7854", 0 }, | |
165 | { "ade7858", 0 }, | |
166 | { "ade7868", 0 }, | |
167 | { "ade7878", 0 }, | |
168 | { } | |
169 | }; | |
170 | MODULE_DEVICE_TABLE(i2c, ade7854_id); | |
171 | ||
172 | static struct i2c_driver ade7854_i2c_driver = { | |
173 | .driver = { | |
174 | .name = "ade7854", | |
175 | }, | |
176 | .probe = ade7854_i2c_probe, | |
5b264a62 BS |
177 | .id_table = ade7854_id, |
178 | }; | |
6e5af184 | 179 | module_i2c_driver(ade7854_i2c_driver); |
5b264a62 BS |
180 | |
181 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | |
182 | MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC I2C Driver"); | |
183 | MODULE_LICENSE("GPL v2"); |