Commit | Line | Data |
---|---|---|
8a27a023 MH |
1 | /* |
2 | * ADE7758 Poly Phase Multifunction Energy Metering IC driver | |
3 | * | |
4 | * Copyright 2010-2011 Analog Devices Inc. | |
5 | * | |
6 | * Licensed under the GPL-2. | |
7 | */ | |
8e336a72 | 8 | #include <linux/export.h> |
8210cfe9 | 9 | #include <linux/interrupt.h> |
8210cfe9 BS |
10 | #include <linux/kernel.h> |
11 | #include <linux/spi/spi.h> | |
12 | #include <linux/slab.h> | |
8a27a023 | 13 | #include <asm/unaligned.h> |
8210cfe9 | 14 | |
06458e27 | 15 | #include <linux/iio/iio.h> |
94f3c7cd | 16 | #include <linux/iio/kfifo_buf.h> |
06458e27 | 17 | #include <linux/iio/trigger_consumer.h> |
8210cfe9 BS |
18 | #include "ade7758.h" |
19 | ||
20 | /** | |
8a27a023 | 21 | * ade7758_spi_read_burst() - read data registers |
2a0b871c | 22 | * @indio_dev: the IIO device |
8210cfe9 | 23 | **/ |
2a0b871c | 24 | static int ade7758_spi_read_burst(struct iio_dev *indio_dev) |
8210cfe9 | 25 | { |
a3f02370 | 26 | struct ade7758_state *st = iio_priv(indio_dev); |
8210cfe9 BS |
27 | int ret; |
28 | ||
8a27a023 | 29 | ret = spi_sync(st->us, &st->ring_msg); |
8210cfe9 BS |
30 | if (ret) |
31 | dev_err(&st->us->dev, "problem when reading WFORM value\n"); | |
32 | ||
8a27a023 MH |
33 | return ret; |
34 | } | |
35 | ||
36 | static int ade7758_write_waveform_type(struct device *dev, unsigned type) | |
37 | { | |
38 | int ret; | |
39 | u8 reg; | |
40 | ||
41 | ret = ade7758_spi_read_reg_8(dev, | |
42 | ADE7758_WAVMODE, | |
43 | ®); | |
44 | if (ret) | |
45 | goto out; | |
46 | ||
47 | reg &= ~0x1F; | |
48 | reg |= type & 0x1F; | |
8210cfe9 | 49 | |
8a27a023 MH |
50 | ret = ade7758_spi_write_reg_8(dev, |
51 | ADE7758_WAVMODE, | |
52 | reg); | |
53 | out: | |
8210cfe9 BS |
54 | return ret; |
55 | } | |
56 | ||
7d241b27 | 57 | /* Whilst this makes a lot of calls to iio_sw_ring functions - it is too device |
8210cfe9 BS |
58 | * specific to be rolled into the core. |
59 | */ | |
3f00ca47 | 60 | static irqreturn_t ade7758_trigger_handler(int irq, void *p) |
8210cfe9 | 61 | { |
3f00ca47 | 62 | struct iio_poll_func *pf = p; |
e65bc6ac | 63 | struct iio_dev *indio_dev = pf->indio_dev; |
a3f02370 | 64 | struct ade7758_state *st = iio_priv(indio_dev); |
8a27a023 MH |
65 | s64 dat64[2]; |
66 | u32 *dat32 = (u32 *)dat64; | |
8210cfe9 | 67 | |
550268ca | 68 | if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) |
2a0b871c | 69 | if (ade7758_spi_read_burst(indio_dev) >= 0) |
8a27a023 | 70 | *dat32 = get_unaligned_be32(&st->rx_buf[5]) & 0xFFFFFF; |
8210cfe9 BS |
71 | |
72 | /* Guaranteed to be aligned with 8 byte boundary */ | |
fd6487f8 | 73 | if (indio_dev->scan_timestamp) |
8a27a023 | 74 | dat64[1] = pf->timestamp; |
8210cfe9 | 75 | |
84b36ce5 | 76 | iio_push_to_buffers(indio_dev, (u8 *)dat64); |
8210cfe9 | 77 | |
a3f02370 | 78 | iio_trigger_notify_done(indio_dev->trig); |
8210cfe9 | 79 | |
3f00ca47 | 80 | return IRQ_HANDLED; |
8210cfe9 BS |
81 | } |
82 | ||
8a27a023 MH |
83 | /** |
84 | * ade7758_ring_preenable() setup the parameters of the ring before enabling | |
85 | * | |
4abf6f8b | 86 | * The complex nature of the setting of the number of bytes per datum is due |
8a27a023 MH |
87 | * to this driver currently ensuring that the timestamp is stored at an 8 |
88 | * byte boundary. | |
89 | **/ | |
90 | static int ade7758_ring_preenable(struct iio_dev *indio_dev) | |
91 | { | |
a3f02370 | 92 | struct ade7758_state *st = iio_priv(indio_dev); |
8a27a023 | 93 | unsigned channel; |
c562ccbf | 94 | int ret; |
8a27a023 | 95 | |
550268ca | 96 | if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) |
8a27a023 MH |
97 | return -EINVAL; |
98 | ||
c562ccbf JC |
99 | ret = iio_sw_buffer_preenable(indio_dev); |
100 | if (ret < 0) | |
101 | return ret; | |
102 | ||
550268ca JC |
103 | channel = find_first_bit(indio_dev->active_scan_mask, |
104 | indio_dev->masklength); | |
8a27a023 | 105 | |
8a27a023 MH |
106 | ade7758_write_waveform_type(&indio_dev->dev, |
107 | st->ade7758_ring_channels[channel].address); | |
108 | ||
109 | return 0; | |
110 | } | |
111 | ||
14555b14 | 112 | static const struct iio_buffer_setup_ops ade7758_ring_setup_ops = { |
5565a450 | 113 | .preenable = &ade7758_ring_preenable, |
3b99fb76 JC |
114 | .postenable = &iio_triggered_buffer_postenable, |
115 | .predisable = &iio_triggered_buffer_predisable, | |
ee0312a0 | 116 | .validate_scan_mask = &iio_validate_scan_mask_onehot, |
5565a450 JC |
117 | }; |
118 | ||
8210cfe9 BS |
119 | void ade7758_unconfigure_ring(struct iio_dev *indio_dev) |
120 | { | |
0ed731d2 | 121 | iio_dealloc_pollfunc(indio_dev->pollfunc); |
94f3c7cd | 122 | iio_kfifo_free(indio_dev->buffer); |
8210cfe9 BS |
123 | } |
124 | ||
125 | int ade7758_configure_ring(struct iio_dev *indio_dev) | |
126 | { | |
a3f02370 | 127 | struct ade7758_state *st = iio_priv(indio_dev); |
8210cfe9 | 128 | int ret = 0; |
8210cfe9 | 129 | |
94f3c7cd | 130 | indio_dev->buffer = iio_kfifo_allocate(indio_dev); |
14555b14 | 131 | if (!indio_dev->buffer) { |
8210cfe9 BS |
132 | ret = -ENOMEM; |
133 | return ret; | |
134 | } | |
8a27a023 | 135 | |
1612244f | 136 | indio_dev->setup_ops = &ade7758_ring_setup_ops; |
8210cfe9 | 137 | |
0ed731d2 JC |
138 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, |
139 | &ade7758_trigger_handler, | |
140 | 0, | |
141 | indio_dev, | |
142 | "ade7759_consumer%d", | |
143 | indio_dev->id); | |
3f00ca47 JC |
144 | if (indio_dev->pollfunc == NULL) { |
145 | ret = -ENOMEM; | |
94f3c7cd | 146 | goto error_iio_kfifo_free; |
3f00ca47 | 147 | } |
0ed731d2 | 148 | |
ec3afa40 | 149 | indio_dev->modes |= INDIO_BUFFER_TRIGGERED; |
3f00ca47 | 150 | |
8a27a023 MH |
151 | st->tx_buf[0] = ADE7758_READ_REG(ADE7758_RSTATUS); |
152 | st->tx_buf[1] = 0; | |
153 | st->tx_buf[2] = 0; | |
154 | st->tx_buf[3] = 0; | |
155 | st->tx_buf[4] = ADE7758_READ_REG(ADE7758_WFORM); | |
156 | st->tx_buf[5] = 0; | |
157 | st->tx_buf[6] = 0; | |
158 | st->tx_buf[7] = 0; | |
159 | ||
160 | /* build spi ring message */ | |
161 | st->ring_xfer[0].tx_buf = &st->tx_buf[0]; | |
162 | st->ring_xfer[0].len = 1; | |
163 | st->ring_xfer[0].bits_per_word = 8; | |
164 | st->ring_xfer[0].delay_usecs = 4; | |
165 | st->ring_xfer[1].rx_buf = &st->rx_buf[1]; | |
166 | st->ring_xfer[1].len = 3; | |
167 | st->ring_xfer[1].bits_per_word = 8; | |
168 | st->ring_xfer[1].cs_change = 1; | |
169 | ||
170 | st->ring_xfer[2].tx_buf = &st->tx_buf[4]; | |
171 | st->ring_xfer[2].len = 1; | |
172 | st->ring_xfer[2].bits_per_word = 8; | |
173 | st->ring_xfer[2].delay_usecs = 1; | |
174 | st->ring_xfer[3].rx_buf = &st->rx_buf[5]; | |
175 | st->ring_xfer[3].len = 3; | |
176 | st->ring_xfer[3].bits_per_word = 8; | |
177 | ||
178 | spi_message_init(&st->ring_msg); | |
179 | spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg); | |
180 | spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg); | |
181 | spi_message_add_tail(&st->ring_xfer[2], &st->ring_msg); | |
182 | spi_message_add_tail(&st->ring_xfer[3], &st->ring_msg); | |
183 | ||
8210cfe9 BS |
184 | return 0; |
185 | ||
94f3c7cd JC |
186 | error_iio_kfifo_free: |
187 | iio_kfifo_free(indio_dev->buffer); | |
8210cfe9 BS |
188 | return ret; |
189 | } | |
190 | ||
1aa04278 | 191 | void ade7758_uninitialize_ring(struct iio_dev *indio_dev) |
8210cfe9 | 192 | { |
14555b14 | 193 | iio_buffer_unregister(indio_dev); |
8210cfe9 | 194 | } |