Commit | Line | Data |
---|---|---|
09434ef7 | 1 | /* |
72db6eb6 | 2 | * ADE7753 Single-Phase Multifunction Metering IC with di/dt Sensor Interface |
09434ef7 BS |
3 | * |
4 | * Copyright 2010 Analog Devices Inc. | |
5 | * | |
6 | * Licensed under the GPL-2 or later. | |
7 | */ | |
8 | ||
9 | #include <linux/interrupt.h> | |
10 | #include <linux/irq.h> | |
11 | #include <linux/gpio.h> | |
12 | #include <linux/delay.h> | |
13 | #include <linux/mutex.h> | |
14 | #include <linux/device.h> | |
15 | #include <linux/kernel.h> | |
16 | #include <linux/spi/spi.h> | |
17 | #include <linux/slab.h> | |
18 | #include <linux/sysfs.h> | |
19 | #include <linux/list.h> | |
99c97852 | 20 | #include <linux/module.h> |
09434ef7 BS |
21 | |
22 | #include "../iio.h" | |
23 | #include "../sysfs.h" | |
24 | #include "meter.h" | |
25 | #include "ade7753.h" | |
26 | ||
72db6eb6 JC |
27 | static int ade7753_spi_write_reg_8(struct device *dev, |
28 | u8 reg_address, | |
29 | u8 val) | |
09434ef7 BS |
30 | { |
31 | int ret; | |
32 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
bfccd4fb | 33 | struct ade7753_state *st = iio_priv(indio_dev); |
09434ef7 BS |
34 | |
35 | mutex_lock(&st->buf_lock); | |
36 | st->tx[0] = ADE7753_WRITE_REG(reg_address); | |
37 | st->tx[1] = val; | |
38 | ||
39 | ret = spi_write(st->us, st->tx, 2); | |
40 | mutex_unlock(&st->buf_lock); | |
41 | ||
42 | return ret; | |
43 | } | |
44 | ||
45 | static int ade7753_spi_write_reg_16(struct device *dev, | |
46 | u8 reg_address, | |
47 | u16 value) | |
48 | { | |
49 | int ret; | |
09434ef7 | 50 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
bfccd4fb | 51 | struct ade7753_state *st = iio_priv(indio_dev); |
09434ef7 BS |
52 | |
53 | mutex_lock(&st->buf_lock); | |
54 | st->tx[0] = ADE7753_WRITE_REG(reg_address); | |
55 | st->tx[1] = (value >> 8) & 0xFF; | |
56 | st->tx[2] = value & 0xFF; | |
72db6eb6 | 57 | ret = spi_write(st->us, st->tx, 3); |
09434ef7 BS |
58 | mutex_unlock(&st->buf_lock); |
59 | ||
60 | return ret; | |
61 | } | |
62 | ||
63 | static int ade7753_spi_read_reg_8(struct device *dev, | |
64 | u8 reg_address, | |
65 | u8 *val) | |
66 | { | |
09434ef7 | 67 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
bfccd4fb | 68 | struct ade7753_state *st = iio_priv(indio_dev); |
72db6eb6 | 69 | ssize_t ret; |
09434ef7 | 70 | |
72db6eb6 JC |
71 | ret = spi_w8r8(st->us, ADE7753_READ_REG(reg_address)); |
72 | if (ret < 0) { | |
09434ef7 BS |
73 | dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", |
74 | reg_address); | |
72db6eb6 | 75 | return ret; |
09434ef7 | 76 | } |
72db6eb6 | 77 | *val = ret; |
09434ef7 | 78 | |
72db6eb6 | 79 | return 0; |
09434ef7 BS |
80 | } |
81 | ||
82 | static int ade7753_spi_read_reg_16(struct device *dev, | |
83 | u8 reg_address, | |
84 | u16 *val) | |
85 | { | |
09434ef7 | 86 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
bfccd4fb | 87 | struct ade7753_state *st = iio_priv(indio_dev); |
72db6eb6 | 88 | ssize_t ret; |
09434ef7 | 89 | |
72db6eb6 JC |
90 | ret = spi_w8r16(st->us, ADE7753_READ_REG(reg_address)); |
91 | if (ret < 0) { | |
09434ef7 | 92 | dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", |
72db6eb6 JC |
93 | reg_address); |
94 | return ret; | |
09434ef7 | 95 | } |
09434ef7 | 96 | |
72db6eb6 JC |
97 | *val = ret; |
98 | *val = be16_to_cpup(val); | |
99 | ||
100 | return 0; | |
09434ef7 BS |
101 | } |
102 | ||
103 | static int ade7753_spi_read_reg_24(struct device *dev, | |
104 | u8 reg_address, | |
105 | u32 *val) | |
106 | { | |
107 | struct spi_message msg; | |
108 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
bfccd4fb | 109 | struct ade7753_state *st = iio_priv(indio_dev); |
09434ef7 BS |
110 | int ret; |
111 | struct spi_transfer xfers[] = { | |
112 | { | |
113 | .tx_buf = st->tx, | |
09434ef7 | 114 | .bits_per_word = 8, |
72db6eb6 JC |
115 | .len = 1, |
116 | }, { | |
117 | .rx_buf = st->tx, | |
118 | .bits_per_word = 8, | |
119 | .len = 3, | |
120 | } | |
09434ef7 BS |
121 | }; |
122 | ||
123 | mutex_lock(&st->buf_lock); | |
124 | st->tx[0] = ADE7753_READ_REG(reg_address); | |
09434ef7 BS |
125 | |
126 | spi_message_init(&msg); | |
72db6eb6 JC |
127 | spi_message_add_tail(&xfers[0], &msg); |
128 | spi_message_add_tail(&xfers[1], &msg); | |
09434ef7 BS |
129 | ret = spi_sync(st->us, &msg); |
130 | if (ret) { | |
131 | dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", | |
132 | reg_address); | |
133 | goto error_ret; | |
134 | } | |
72db6eb6 | 135 | *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; |
09434ef7 BS |
136 | |
137 | error_ret: | |
138 | mutex_unlock(&st->buf_lock); | |
139 | return ret; | |
140 | } | |
141 | ||
142 | static ssize_t ade7753_read_8bit(struct device *dev, | |
143 | struct device_attribute *attr, | |
144 | char *buf) | |
145 | { | |
146 | int ret; | |
72db6eb6 | 147 | u8 val; |
09434ef7 BS |
148 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
149 | ||
150 | ret = ade7753_spi_read_reg_8(dev, this_attr->address, &val); | |
151 | if (ret) | |
152 | return ret; | |
153 | ||
154 | return sprintf(buf, "%u\n", val); | |
155 | } | |
156 | ||
157 | static ssize_t ade7753_read_16bit(struct device *dev, | |
158 | struct device_attribute *attr, | |
159 | char *buf) | |
160 | { | |
161 | int ret; | |
72db6eb6 | 162 | u16 val; |
09434ef7 BS |
163 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
164 | ||
165 | ret = ade7753_spi_read_reg_16(dev, this_attr->address, &val); | |
166 | if (ret) | |
167 | return ret; | |
168 | ||
169 | return sprintf(buf, "%u\n", val); | |
170 | } | |
171 | ||
172 | static ssize_t ade7753_read_24bit(struct device *dev, | |
173 | struct device_attribute *attr, | |
174 | char *buf) | |
175 | { | |
176 | int ret; | |
72db6eb6 | 177 | u32 val; |
09434ef7 BS |
178 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
179 | ||
180 | ret = ade7753_spi_read_reg_24(dev, this_attr->address, &val); | |
181 | if (ret) | |
182 | return ret; | |
183 | ||
72db6eb6 | 184 | return sprintf(buf, "%u\n", val); |
09434ef7 BS |
185 | } |
186 | ||
187 | static ssize_t ade7753_write_8bit(struct device *dev, | |
188 | struct device_attribute *attr, | |
189 | const char *buf, | |
190 | size_t len) | |
191 | { | |
192 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | |
193 | int ret; | |
194 | long val; | |
195 | ||
196 | ret = strict_strtol(buf, 10, &val); | |
197 | if (ret) | |
198 | goto error_ret; | |
199 | ret = ade7753_spi_write_reg_8(dev, this_attr->address, val); | |
200 | ||
201 | error_ret: | |
202 | return ret ? ret : len; | |
203 | } | |
204 | ||
205 | static ssize_t ade7753_write_16bit(struct device *dev, | |
206 | struct device_attribute *attr, | |
207 | const char *buf, | |
208 | size_t len) | |
209 | { | |
210 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | |
211 | int ret; | |
212 | long val; | |
213 | ||
214 | ret = strict_strtol(buf, 10, &val); | |
215 | if (ret) | |
216 | goto error_ret; | |
217 | ret = ade7753_spi_write_reg_16(dev, this_attr->address, val); | |
218 | ||
219 | error_ret: | |
220 | return ret ? ret : len; | |
221 | } | |
222 | ||
223 | static int ade7753_reset(struct device *dev) | |
224 | { | |
09434ef7 | 225 | u16 val; |
72db6eb6 JC |
226 | |
227 | ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val); | |
09434ef7 | 228 | val |= 1 << 6; /* Software Chip Reset */ |
09434ef7 | 229 | |
72db6eb6 | 230 | return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val); |
09434ef7 BS |
231 | } |
232 | ||
233 | static ssize_t ade7753_write_reset(struct device *dev, | |
234 | struct device_attribute *attr, | |
235 | const char *buf, size_t len) | |
236 | { | |
237 | if (len < 1) | |
238 | return -1; | |
239 | switch (buf[0]) { | |
240 | case '1': | |
241 | case 'y': | |
242 | case 'Y': | |
243 | return ade7753_reset(dev); | |
244 | } | |
245 | return -1; | |
246 | } | |
247 | ||
248 | static IIO_DEV_ATTR_AENERGY(ade7753_read_24bit, ADE7753_AENERGY); | |
249 | static IIO_DEV_ATTR_LAENERGY(ade7753_read_24bit, ADE7753_LAENERGY); | |
250 | static IIO_DEV_ATTR_VAENERGY(ade7753_read_24bit, ADE7753_VAENERGY); | |
251 | static IIO_DEV_ATTR_LVAENERGY(ade7753_read_24bit, ADE7753_LVAENERGY); | |
252 | static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO, | |
253 | ade7753_read_16bit, | |
254 | ade7753_write_16bit, | |
255 | ADE7753_CFDEN); | |
256 | static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO, | |
257 | ade7753_read_8bit, | |
258 | ade7753_write_8bit, | |
259 | ADE7753_CFNUM); | |
260 | static IIO_DEV_ATTR_CHKSUM(ade7753_read_8bit, ADE7753_CHKSUM); | |
261 | static IIO_DEV_ATTR_PHCAL(S_IWUSR | S_IRUGO, | |
262 | ade7753_read_16bit, | |
263 | ade7753_write_16bit, | |
264 | ADE7753_PHCAL); | |
265 | static IIO_DEV_ATTR_APOS(S_IWUSR | S_IRUGO, | |
266 | ade7753_read_16bit, | |
267 | ade7753_write_16bit, | |
268 | ADE7753_APOS); | |
269 | static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO, | |
270 | ade7753_read_8bit, | |
271 | ade7753_write_8bit, | |
272 | ADE7753_SAGCYC); | |
273 | static IIO_DEV_ATTR_SAGLVL(S_IWUSR | S_IRUGO, | |
274 | ade7753_read_8bit, | |
275 | ade7753_write_8bit, | |
276 | ADE7753_SAGLVL); | |
277 | static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO, | |
278 | ade7753_read_8bit, | |
279 | ade7753_write_8bit, | |
280 | ADE7753_LINECYC); | |
281 | static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO, | |
282 | ade7753_read_8bit, | |
283 | ade7753_write_8bit, | |
284 | ADE7753_WDIV); | |
285 | static IIO_DEV_ATTR_IRMS(S_IWUSR | S_IRUGO, | |
286 | ade7753_read_24bit, | |
287 | NULL, | |
288 | ADE7753_IRMS); | |
289 | static IIO_DEV_ATTR_VRMS(S_IRUGO, | |
290 | ade7753_read_24bit, | |
291 | NULL, | |
292 | ADE7753_VRMS); | |
293 | static IIO_DEV_ATTR_IRMSOS(S_IWUSR | S_IRUGO, | |
294 | ade7753_read_16bit, | |
295 | ade7753_write_16bit, | |
296 | ADE7753_IRMSOS); | |
297 | static IIO_DEV_ATTR_VRMSOS(S_IWUSR | S_IRUGO, | |
298 | ade7753_read_16bit, | |
299 | ade7753_write_16bit, | |
300 | ADE7753_VRMSOS); | |
301 | static IIO_DEV_ATTR_WGAIN(S_IWUSR | S_IRUGO, | |
302 | ade7753_read_16bit, | |
303 | ade7753_write_16bit, | |
304 | ADE7753_WGAIN); | |
305 | static IIO_DEV_ATTR_VAGAIN(S_IWUSR | S_IRUGO, | |
306 | ade7753_read_16bit, | |
307 | ade7753_write_16bit, | |
308 | ADE7753_VAGAIN); | |
309 | static IIO_DEV_ATTR_PGA_GAIN(S_IWUSR | S_IRUGO, | |
310 | ade7753_read_16bit, | |
311 | ade7753_write_16bit, | |
312 | ADE7753_GAIN); | |
313 | static IIO_DEV_ATTR_IPKLVL(S_IWUSR | S_IRUGO, | |
314 | ade7753_read_8bit, | |
315 | ade7753_write_8bit, | |
316 | ADE7753_IPKLVL); | |
317 | static IIO_DEV_ATTR_VPKLVL(S_IWUSR | S_IRUGO, | |
318 | ade7753_read_8bit, | |
319 | ade7753_write_8bit, | |
320 | ADE7753_VPKLVL); | |
321 | static IIO_DEV_ATTR_IPEAK(S_IRUGO, | |
322 | ade7753_read_24bit, | |
323 | NULL, | |
324 | ADE7753_IPEAK); | |
325 | static IIO_DEV_ATTR_VPEAK(S_IRUGO, | |
326 | ade7753_read_24bit, | |
327 | NULL, | |
328 | ADE7753_VPEAK); | |
329 | static IIO_DEV_ATTR_VPERIOD(S_IRUGO, | |
330 | ade7753_read_16bit, | |
331 | NULL, | |
332 | ADE7753_PERIOD); | |
333 | static IIO_DEV_ATTR_CH_OFF(1, S_IWUSR | S_IRUGO, | |
334 | ade7753_read_8bit, | |
335 | ade7753_write_8bit, | |
336 | ADE7753_CH1OS); | |
337 | static IIO_DEV_ATTR_CH_OFF(2, S_IWUSR | S_IRUGO, | |
338 | ade7753_read_8bit, | |
339 | ade7753_write_8bit, | |
340 | ADE7753_CH2OS); | |
341 | ||
342 | static int ade7753_set_irq(struct device *dev, bool enable) | |
343 | { | |
344 | int ret; | |
345 | u8 irqen; | |
346 | ret = ade7753_spi_read_reg_8(dev, ADE7753_IRQEN, &irqen); | |
347 | if (ret) | |
348 | goto error_ret; | |
349 | ||
350 | if (enable) | |
351 | irqen |= 1 << 3; /* Enables an interrupt when a data is | |
352 | present in the waveform register */ | |
353 | else | |
354 | irqen &= ~(1 << 3); | |
355 | ||
356 | ret = ade7753_spi_write_reg_8(dev, ADE7753_IRQEN, irqen); | |
09434ef7 BS |
357 | |
358 | error_ret: | |
359 | return ret; | |
360 | } | |
361 | ||
362 | /* Power down the device */ | |
72db6eb6 | 363 | static int ade7753_stop_device(struct device *dev) |
09434ef7 | 364 | { |
09434ef7 | 365 | u16 val; |
72db6eb6 JC |
366 | |
367 | ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val); | |
09434ef7 | 368 | val |= 1 << 4; /* AD converters can be turned off */ |
09434ef7 | 369 | |
72db6eb6 | 370 | return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val); |
09434ef7 BS |
371 | } |
372 | ||
bfccd4fb | 373 | static int ade7753_initial_setup(struct iio_dev *indio_dev) |
09434ef7 BS |
374 | { |
375 | int ret; | |
bfccd4fb JC |
376 | struct device *dev = &indio_dev->dev; |
377 | struct ade7753_state *st = iio_priv(indio_dev); | |
09434ef7 BS |
378 | |
379 | /* use low spi speed for init */ | |
380 | st->us->mode = SPI_MODE_3; | |
381 | spi_setup(st->us); | |
382 | ||
383 | /* Disable IRQ */ | |
384 | ret = ade7753_set_irq(dev, false); | |
385 | if (ret) { | |
386 | dev_err(dev, "disable irq failed"); | |
387 | goto err_ret; | |
388 | } | |
389 | ||
390 | ade7753_reset(dev); | |
391 | msleep(ADE7753_STARTUP_DELAY); | |
392 | ||
393 | err_ret: | |
394 | return ret; | |
395 | } | |
396 | ||
397 | static ssize_t ade7753_read_frequency(struct device *dev, | |
398 | struct device_attribute *attr, | |
399 | char *buf) | |
400 | { | |
401 | int ret, len = 0; | |
e1703b32 | 402 | u16 t; |
09434ef7 | 403 | int sps; |
e1703b32 | 404 | ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, &t); |
09434ef7 BS |
405 | if (ret) |
406 | return ret; | |
407 | ||
408 | t = (t >> 11) & 0x3; | |
409 | sps = 27900 / (1 + t); | |
410 | ||
72db6eb6 | 411 | len = sprintf(buf, "%d\n", sps); |
09434ef7 BS |
412 | return len; |
413 | } | |
414 | ||
415 | static ssize_t ade7753_write_frequency(struct device *dev, | |
416 | struct device_attribute *attr, | |
417 | const char *buf, | |
418 | size_t len) | |
419 | { | |
420 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
bfccd4fb | 421 | struct ade7753_state *st = iio_priv(indio_dev); |
09434ef7 BS |
422 | unsigned long val; |
423 | int ret; | |
424 | u16 reg, t; | |
425 | ||
426 | ret = strict_strtol(buf, 10, &val); | |
427 | if (ret) | |
428 | return ret; | |
429 | ||
430 | mutex_lock(&indio_dev->mlock); | |
431 | ||
432 | t = (27900 / val); | |
433 | if (t > 0) | |
434 | t--; | |
435 | ||
436 | if (t > 1) | |
437 | st->us->max_speed_hz = ADE7753_SPI_SLOW; | |
438 | else | |
439 | st->us->max_speed_hz = ADE7753_SPI_FAST; | |
440 | ||
72db6eb6 | 441 | ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, ®); |
09434ef7 BS |
442 | if (ret) |
443 | goto out; | |
444 | ||
445 | reg &= ~(3 << 11); | |
446 | reg |= t << 11; | |
447 | ||
72db6eb6 | 448 | ret = ade7753_spi_write_reg_16(dev, ADE7753_MODE, reg); |
09434ef7 BS |
449 | |
450 | out: | |
451 | mutex_unlock(&indio_dev->mlock); | |
452 | ||
453 | return ret ? ret : len; | |
454 | } | |
72db6eb6 | 455 | |
09434ef7 BS |
456 | static IIO_DEV_ATTR_TEMP_RAW(ade7753_read_8bit); |
457 | static IIO_CONST_ATTR(temp_offset, "-25 C"); | |
458 | static IIO_CONST_ATTR(temp_scale, "0.67 C"); | |
459 | ||
460 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, | |
461 | ade7753_read_frequency, | |
462 | ade7753_write_frequency); | |
463 | ||
464 | static IIO_DEV_ATTR_RESET(ade7753_write_reset); | |
465 | ||
466 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500"); | |
467 | ||
09434ef7 BS |
468 | static struct attribute *ade7753_attributes[] = { |
469 | &iio_dev_attr_temp_raw.dev_attr.attr, | |
470 | &iio_const_attr_temp_offset.dev_attr.attr, | |
471 | &iio_const_attr_temp_scale.dev_attr.attr, | |
472 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | |
473 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | |
474 | &iio_dev_attr_reset.dev_attr.attr, | |
09434ef7 BS |
475 | &iio_dev_attr_phcal.dev_attr.attr, |
476 | &iio_dev_attr_cfden.dev_attr.attr, | |
477 | &iio_dev_attr_aenergy.dev_attr.attr, | |
478 | &iio_dev_attr_laenergy.dev_attr.attr, | |
479 | &iio_dev_attr_vaenergy.dev_attr.attr, | |
480 | &iio_dev_attr_lvaenergy.dev_attr.attr, | |
481 | &iio_dev_attr_cfnum.dev_attr.attr, | |
482 | &iio_dev_attr_apos.dev_attr.attr, | |
483 | &iio_dev_attr_sagcyc.dev_attr.attr, | |
484 | &iio_dev_attr_saglvl.dev_attr.attr, | |
485 | &iio_dev_attr_linecyc.dev_attr.attr, | |
486 | &iio_dev_attr_chksum.dev_attr.attr, | |
487 | &iio_dev_attr_pga_gain.dev_attr.attr, | |
488 | &iio_dev_attr_wgain.dev_attr.attr, | |
489 | &iio_dev_attr_choff_1.dev_attr.attr, | |
490 | &iio_dev_attr_choff_2.dev_attr.attr, | |
491 | &iio_dev_attr_wdiv.dev_attr.attr, | |
492 | &iio_dev_attr_irms.dev_attr.attr, | |
493 | &iio_dev_attr_vrms.dev_attr.attr, | |
494 | &iio_dev_attr_irmsos.dev_attr.attr, | |
495 | &iio_dev_attr_vrmsos.dev_attr.attr, | |
496 | &iio_dev_attr_vagain.dev_attr.attr, | |
497 | &iio_dev_attr_ipklvl.dev_attr.attr, | |
498 | &iio_dev_attr_vpklvl.dev_attr.attr, | |
499 | &iio_dev_attr_ipeak.dev_attr.attr, | |
500 | &iio_dev_attr_vpeak.dev_attr.attr, | |
501 | &iio_dev_attr_vperiod.dev_attr.attr, | |
502 | NULL, | |
503 | }; | |
504 | ||
505 | static const struct attribute_group ade7753_attribute_group = { | |
506 | .attrs = ade7753_attributes, | |
507 | }; | |
508 | ||
6fe8135f JC |
509 | static const struct iio_info ade7753_info = { |
510 | .attrs = &ade7753_attribute_group, | |
511 | .driver_module = THIS_MODULE, | |
512 | }; | |
513 | ||
09434ef7 BS |
514 | static int __devinit ade7753_probe(struct spi_device *spi) |
515 | { | |
26d25ae3 | 516 | int ret; |
bfccd4fb JC |
517 | struct ade7753_state *st; |
518 | struct iio_dev *indio_dev; | |
519 | ||
520 | /* setup the industrialio driver allocated elements */ | |
521 | indio_dev = iio_allocate_device(sizeof(*st)); | |
522 | if (indio_dev == NULL) { | |
523 | ret = -ENOMEM; | |
09434ef7 BS |
524 | goto error_ret; |
525 | } | |
526 | /* this is only used for removal purposes */ | |
bfccd4fb | 527 | spi_set_drvdata(spi, indio_dev); |
09434ef7 | 528 | |
bfccd4fb | 529 | st = iio_priv(indio_dev); |
09434ef7 BS |
530 | st->us = spi; |
531 | mutex_init(&st->buf_lock); | |
09434ef7 | 532 | |
bfccd4fb JC |
533 | indio_dev->name = spi->dev.driver->name; |
534 | indio_dev->dev.parent = &spi->dev; | |
535 | indio_dev->info = &ade7753_info; | |
536 | indio_dev->modes = INDIO_DIRECT_MODE; | |
09434ef7 | 537 | |
26d25ae3 JC |
538 | /* Get the device into a sane initial state */ |
539 | ret = ade7753_initial_setup(indio_dev); | |
09434ef7 | 540 | if (ret) |
72db6eb6 | 541 | goto error_free_dev; |
09434ef7 | 542 | |
26d25ae3 | 543 | ret = iio_device_register(indio_dev); |
09434ef7 | 544 | if (ret) |
72db6eb6 | 545 | goto error_free_dev; |
26d25ae3 | 546 | |
09434ef7 BS |
547 | return 0; |
548 | ||
09434ef7 | 549 | error_free_dev: |
26d25ae3 | 550 | iio_free_device(indio_dev); |
bfccd4fb | 551 | |
09434ef7 BS |
552 | error_ret: |
553 | return ret; | |
554 | } | |
555 | ||
556 | /* fixme, confirm ordering in this function */ | |
557 | static int ade7753_remove(struct spi_device *spi) | |
558 | { | |
559 | int ret; | |
bfccd4fb | 560 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
09434ef7 BS |
561 | |
562 | ret = ade7753_stop_device(&(indio_dev->dev)); | |
563 | if (ret) | |
564 | goto err_ret; | |
565 | ||
09434ef7 | 566 | iio_device_unregister(indio_dev); |
09434ef7 BS |
567 | |
568 | err_ret: | |
569 | return ret; | |
570 | } | |
571 | ||
572 | static struct spi_driver ade7753_driver = { | |
573 | .driver = { | |
574 | .name = "ade7753", | |
575 | .owner = THIS_MODULE, | |
576 | }, | |
577 | .probe = ade7753_probe, | |
578 | .remove = __devexit_p(ade7753_remove), | |
579 | }; | |
580 | ||
581 | static __init int ade7753_init(void) | |
582 | { | |
583 | return spi_register_driver(&ade7753_driver); | |
584 | } | |
585 | module_init(ade7753_init); | |
586 | ||
587 | static __exit void ade7753_exit(void) | |
588 | { | |
589 | spi_unregister_driver(&ade7753_driver); | |
590 | } | |
591 | module_exit(ade7753_exit); | |
592 | ||
593 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | |
72db6eb6 | 594 | MODULE_DESCRIPTION("Analog Devices ADE7753/6 Single-Phase Multifunction Meter"); |
09434ef7 | 595 | MODULE_LICENSE("GPL v2"); |