diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-07-24 17:57:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-07-24 17:57:19 -0400 |
commit | 040bf7d63d624ad63be8b4b3a3c76a495c9cc569 (patch) | |
tree | 7c427332c498b29c23f305fd82272fb4edd1b7a1 /drivers/iio | |
parent | 16fae052074aa44ffa8c15b789719bd9611a1278 (diff) | |
parent | e6ca2d848c9b7b292d22cbf6fe10019ccab72345 (diff) |
Merge tag 'iio-for-3.17d' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
Fourth round of IIO new drivers, functionality and cleanups for the 3.17 cycle
New functionality
* A new modifier to indicate that a rotation is relative to either
true or magnetic north. This is to be used by some magnetometers
that provide data in this way.
* hid magnetometer now supports output rotations from various variants on
North
* HMC5843 driver converted to regmap and reworked to allow easy support
of other similar devices. Support for HMC5983 added via both i2c and SPI.
* Rework of Exynos driver to simplify extension to support more devices.
* Addition of support for the Exynos3250 ADC (which requires an additional
clock) Support for quite a few more devices on its way.
Cleanups
* ad7997 - a number of cleanups and tweaks to how the events are controlled
to make it more intuitive.
* kxcjk - cleanups and minor fixes for this new driver.
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/accel/kxcjk-1013.c | 38 | ||||
-rw-r--r-- | drivers/iio/adc/ad799x.c | 504 | ||||
-rw-r--r-- | drivers/iio/adc/exynos_adc.c | 335 | ||||
-rw-r--r-- | drivers/iio/industrialio-core.c | 4 | ||||
-rw-r--r-- | drivers/iio/magnetometer/hid-sensor-magn-3d.c | 202 |
5 files changed, 731 insertions, 352 deletions
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 72a6dbbc18d1..7941cf2d31ee 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c | |||
@@ -98,7 +98,7 @@ static const struct { | |||
98 | int val2; | 98 | int val2; |
99 | int odr_bits; | 99 | int odr_bits; |
100 | } samp_freq_table[] = { {0, 781000, 0x08}, {1, 563000, 0x09}, | 100 | } samp_freq_table[] = { {0, 781000, 0x08}, {1, 563000, 0x09}, |
101 | {3, 125000, 0x0A}, {6, 25000, 0x0B}, {12, 5000, 0}, | 101 | {3, 125000, 0x0A}, {6, 250000, 0x0B}, {12, 500000, 0}, |
102 | {25, 0, 0x01}, {50, 0, 0x02}, {100, 0, 0x03}, | 102 | {25, 0, 0x01}, {50, 0, 0x02}, {100, 0, 0x03}, |
103 | {200, 0, 0x04}, {400, 0, 0x05}, {800, 0, 0x06}, | 103 | {200, 0, 0x04}, {400, 0, 0x05}, {800, 0, 0x06}, |
104 | {1600, 0, 0x07} }; | 104 | {1600, 0, 0x07} }; |
@@ -138,19 +138,6 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data, | |||
138 | return 0; | 138 | return 0; |
139 | } | 139 | } |
140 | 140 | ||
141 | static int kxcjk1013_chip_ack_intr(struct kxcjk1013_data *data) | ||
142 | { | ||
143 | int ret; | ||
144 | |||
145 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); | ||
146 | if (ret < 0) { | ||
147 | dev_err(&data->client->dev, "Error writing reg_int_rel\n"); | ||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static int kxcjk1013_chip_init(struct kxcjk1013_data *data) | 141 | static int kxcjk1013_chip_init(struct kxcjk1013_data *data) |
155 | { | 142 | { |
156 | int ret; | 143 | int ret; |
@@ -466,7 +453,7 @@ static const struct attribute_group kxcjk1013_attrs_group = { | |||
466 | .realbits = 12, \ | 453 | .realbits = 12, \ |
467 | .storagebits = 16, \ | 454 | .storagebits = 16, \ |
468 | .shift = 4, \ | 455 | .shift = 4, \ |
469 | .endianness = IIO_LE, \ | 456 | .endianness = IIO_CPU, \ |
470 | }, \ | 457 | }, \ |
471 | } | 458 | } |
472 | 459 | ||
@@ -498,15 +485,11 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) | |||
498 | indio_dev->masklength) { | 485 | indio_dev->masklength) { |
499 | ret = kxcjk1013_get_acc_reg(data, bit); | 486 | ret = kxcjk1013_get_acc_reg(data, bit); |
500 | if (ret < 0) { | 487 | if (ret < 0) { |
501 | kxcjk1013_chip_ack_intr(data); | ||
502 | mutex_unlock(&data->mutex); | 488 | mutex_unlock(&data->mutex); |
503 | goto err; | 489 | goto err; |
504 | } | 490 | } |
505 | data->buffer[i++] = ret; | 491 | data->buffer[i++] = ret; |
506 | } | 492 | } |
507 | |||
508 | kxcjk1013_chip_ack_intr(data); | ||
509 | |||
510 | mutex_unlock(&data->mutex); | 493 | mutex_unlock(&data->mutex); |
511 | 494 | ||
512 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 495 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, |
@@ -517,6 +500,21 @@ err: | |||
517 | return IRQ_HANDLED; | 500 | return IRQ_HANDLED; |
518 | } | 501 | } |
519 | 502 | ||
503 | static int kxcjk1013_trig_try_reen(struct iio_trigger *trig) | ||
504 | { | ||
505 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | ||
506 | struct kxcjk1013_data *data = iio_priv(indio_dev); | ||
507 | int ret; | ||
508 | |||
509 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); | ||
510 | if (ret < 0) { | ||
511 | dev_err(&data->client->dev, "Error reading reg_int_rel\n"); | ||
512 | return ret; | ||
513 | } | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
520 | static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, | 518 | static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, |
521 | bool state) | 519 | bool state) |
522 | { | 520 | { |
@@ -543,6 +541,7 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
543 | 541 | ||
544 | static const struct iio_trigger_ops kxcjk1013_trigger_ops = { | 542 | static const struct iio_trigger_ops kxcjk1013_trigger_ops = { |
545 | .set_trigger_state = kxcjk1013_data_rdy_trigger_set_state, | 543 | .set_trigger_state = kxcjk1013_data_rdy_trigger_set_state, |
544 | .try_reenable = kxcjk1013_trig_try_reen, | ||
546 | .owner = THIS_MODULE, | 545 | .owner = THIS_MODULE, |
547 | }; | 546 | }; |
548 | 547 | ||
@@ -645,6 +644,7 @@ static int kxcjk1013_probe(struct i2c_client *client, | |||
645 | iio_trigger_set_drvdata(trig, indio_dev); | 644 | iio_trigger_set_drvdata(trig, indio_dev); |
646 | data->trig = trig; | 645 | data->trig = trig; |
647 | indio_dev->trig = trig; | 646 | indio_dev->trig = trig; |
647 | iio_trigger_get(indio_dev->trig); | ||
648 | 648 | ||
649 | ret = iio_trigger_register(trig); | 649 | ret = iio_trigger_register(trig); |
650 | if (ret) | 650 | if (ret) |
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index 6cf9ee18a216..e37412da15f5 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/err.h> | 33 | #include <linux/err.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/bitops.h> | ||
35 | 36 | ||
36 | #include <linux/iio/iio.h> | 37 | #include <linux/iio/iio.h> |
37 | #include <linux/iio/sysfs.h> | 38 | #include <linux/iio/sysfs.h> |
@@ -41,7 +42,7 @@ | |||
41 | #include <linux/iio/triggered_buffer.h> | 42 | #include <linux/iio/triggered_buffer.h> |
42 | 43 | ||
43 | #define AD799X_CHANNEL_SHIFT 4 | 44 | #define AD799X_CHANNEL_SHIFT 4 |
44 | #define AD799X_STORAGEBITS 16 | 45 | |
45 | /* | 46 | /* |
46 | * AD7991, AD7995 and AD7999 defines | 47 | * AD7991, AD7995 and AD7999 defines |
47 | */ | 48 | */ |
@@ -55,10 +56,10 @@ | |||
55 | * AD7992, AD7993, AD7994, AD7997 and AD7998 defines | 56 | * AD7992, AD7993, AD7994, AD7997 and AD7998 defines |
56 | */ | 57 | */ |
57 | 58 | ||
58 | #define AD7998_FLTR 0x08 | 59 | #define AD7998_FLTR BIT(3) |
59 | #define AD7998_ALERT_EN 0x04 | 60 | #define AD7998_ALERT_EN BIT(2) |
60 | #define AD7998_BUSY_ALERT 0x02 | 61 | #define AD7998_BUSY_ALERT BIT(1) |
61 | #define AD7998_BUSY_ALERT_POL 0x01 | 62 | #define AD7998_BUSY_ALERT_POL BIT(0) |
62 | 63 | ||
63 | #define AD7998_CONV_RES_REG 0x0 | 64 | #define AD7998_CONV_RES_REG 0x0 |
64 | #define AD7998_ALERT_STAT_REG 0x1 | 65 | #define AD7998_ALERT_STAT_REG 0x1 |
@@ -69,7 +70,7 @@ | |||
69 | #define AD7998_DATAHIGH_REG(x) ((x) * 3 + 0x5) | 70 | #define AD7998_DATAHIGH_REG(x) ((x) * 3 + 0x5) |
70 | #define AD7998_HYST_REG(x) ((x) * 3 + 0x6) | 71 | #define AD7998_HYST_REG(x) ((x) * 3 + 0x6) |
71 | 72 | ||
72 | #define AD7998_CYC_MASK 0x7 | 73 | #define AD7998_CYC_MASK GENMASK(2, 0) |
73 | #define AD7998_CYC_DIS 0x0 | 74 | #define AD7998_CYC_DIS 0x0 |
74 | #define AD7998_CYC_TCONF_32 0x1 | 75 | #define AD7998_CYC_TCONF_32 0x1 |
75 | #define AD7998_CYC_TCONF_64 0x2 | 76 | #define AD7998_CYC_TCONF_64 0x2 |
@@ -85,10 +86,8 @@ | |||
85 | * AD7997 and AD7997 defines | 86 | * AD7997 and AD7997 defines |
86 | */ | 87 | */ |
87 | 88 | ||
88 | #define AD7997_8_READ_SINGLE 0x80 | 89 | #define AD7997_8_READ_SINGLE BIT(7) |
89 | #define AD7997_8_READ_SEQUENCE 0x70 | 90 | #define AD7997_8_READ_SEQUENCE (BIT(6) | BIT(5) | BIT(4)) |
90 | /* TODO: move this into a common header */ | ||
91 | #define RES_MASK(bits) ((1 << (bits)) - 1) | ||
92 | 91 | ||
93 | enum { | 92 | enum { |
94 | ad7991, | 93 | ad7991, |
@@ -102,22 +101,32 @@ enum { | |||
102 | }; | 101 | }; |
103 | 102 | ||
104 | /** | 103 | /** |
105 | * struct ad799x_chip_info - chip specific information | 104 | * struct ad799x_chip_config - chip specific information |
106 | * @channel: channel specification | 105 | * @channel: channel specification |
107 | * @num_channels: number of channels | ||
108 | * @default_config: device default configuration | 106 | * @default_config: device default configuration |
109 | * @info: pointer to iio_info struct | 107 | * @info: pointer to iio_info struct |
110 | */ | 108 | */ |
111 | struct ad799x_chip_info { | 109 | struct ad799x_chip_config { |
112 | struct iio_chan_spec channel[9]; | 110 | const struct iio_chan_spec channel[9]; |
113 | int num_channels; | ||
114 | u16 default_config; | 111 | u16 default_config; |
115 | const struct iio_info *info; | 112 | const struct iio_info *info; |
116 | }; | 113 | }; |
117 | 114 | ||
115 | /** | ||
116 | * struct ad799x_chip_info - chip specific information | ||
117 | * @num_channels: number of channels | ||
118 | * @noirq_config: device configuration w/o IRQ | ||
119 | * @irq_config: device configuration w/IRQ | ||
120 | */ | ||
121 | struct ad799x_chip_info { | ||
122 | int num_channels; | ||
123 | const struct ad799x_chip_config noirq_config; | ||
124 | const struct ad799x_chip_config irq_config; | ||
125 | }; | ||
126 | |||
118 | struct ad799x_state { | 127 | struct ad799x_state { |
119 | struct i2c_client *client; | 128 | struct i2c_client *client; |
120 | const struct ad799x_chip_info *chip_info; | 129 | const struct ad799x_chip_config *chip_config; |
121 | struct regulator *reg; | 130 | struct regulator *reg; |
122 | struct regulator *vref; | 131 | struct regulator *vref; |
123 | unsigned id; | 132 | unsigned id; |
@@ -127,6 +136,30 @@ struct ad799x_state { | |||
127 | unsigned int transfer_size; | 136 | unsigned int transfer_size; |
128 | }; | 137 | }; |
129 | 138 | ||
139 | static int ad799x_write_config(struct ad799x_state *st, u16 val) | ||
140 | { | ||
141 | switch (st->id) { | ||
142 | case ad7997: | ||
143 | case ad7998: | ||
144 | return i2c_smbus_write_word_swapped(st->client, AD7998_CONF_REG, | ||
145 | val); | ||
146 | default: | ||
147 | return i2c_smbus_write_byte_data(st->client, AD7998_CONF_REG, | ||
148 | val); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | static int ad799x_read_config(struct ad799x_state *st) | ||
153 | { | ||
154 | switch (st->id) { | ||
155 | case ad7997: | ||
156 | case ad7998: | ||
157 | return i2c_smbus_read_word_swapped(st->client, AD7998_CONF_REG); | ||
158 | default: | ||
159 | return i2c_smbus_read_byte_data(st->client, AD7998_CONF_REG); | ||
160 | } | ||
161 | } | ||
162 | |||
130 | /** | 163 | /** |
131 | * ad799x_trigger_handler() bh of trigger launched polling to ring buffer | 164 | * ad799x_trigger_handler() bh of trigger launched polling to ring buffer |
132 | * | 165 | * |
@@ -175,66 +208,7 @@ out: | |||
175 | return IRQ_HANDLED; | 208 | return IRQ_HANDLED; |
176 | } | 209 | } |
177 | 210 | ||
178 | /* | 211 | static int ad799x_update_scan_mode(struct iio_dev *indio_dev, |
179 | * ad799x register access by I2C | ||
180 | */ | ||
181 | static int ad799x_i2c_read16(struct ad799x_state *st, u8 reg, u16 *data) | ||
182 | { | ||
183 | struct i2c_client *client = st->client; | ||
184 | int ret = 0; | ||
185 | |||
186 | ret = i2c_smbus_read_word_swapped(client, reg); | ||
187 | if (ret < 0) { | ||
188 | dev_err(&client->dev, "I2C read error\n"); | ||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | *data = (u16)ret; | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int ad799x_i2c_read8(struct ad799x_state *st, u8 reg, u8 *data) | ||
198 | { | ||
199 | struct i2c_client *client = st->client; | ||
200 | int ret = 0; | ||
201 | |||
202 | ret = i2c_smbus_read_byte_data(client, reg); | ||
203 | if (ret < 0) { | ||
204 | dev_err(&client->dev, "I2C read error\n"); | ||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | *data = (u8)ret; | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static int ad799x_i2c_write16(struct ad799x_state *st, u8 reg, u16 data) | ||
214 | { | ||
215 | struct i2c_client *client = st->client; | ||
216 | int ret = 0; | ||
217 | |||
218 | ret = i2c_smbus_write_word_swapped(client, reg, data); | ||
219 | if (ret < 0) | ||
220 | dev_err(&client->dev, "I2C write error\n"); | ||
221 | |||
222 | return ret; | ||
223 | } | ||
224 | |||
225 | static int ad799x_i2c_write8(struct ad799x_state *st, u8 reg, u8 data) | ||
226 | { | ||
227 | struct i2c_client *client = st->client; | ||
228 | int ret = 0; | ||
229 | |||
230 | ret = i2c_smbus_write_byte_data(client, reg, data); | ||
231 | if (ret < 0) | ||
232 | dev_err(&client->dev, "I2C write error\n"); | ||
233 | |||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev, | ||
238 | const unsigned long *scan_mask) | 212 | const unsigned long *scan_mask) |
239 | { | 213 | { |
240 | struct ad799x_state *st = iio_priv(indio_dev); | 214 | struct ad799x_state *st = iio_priv(indio_dev); |
@@ -247,33 +221,33 @@ static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev, | |||
247 | st->transfer_size = bitmap_weight(scan_mask, indio_dev->masklength) * 2; | 221 | st->transfer_size = bitmap_weight(scan_mask, indio_dev->masklength) * 2; |
248 | 222 | ||
249 | switch (st->id) { | 223 | switch (st->id) { |
224 | case ad7992: | ||
225 | case ad7993: | ||
226 | case ad7994: | ||
250 | case ad7997: | 227 | case ad7997: |
251 | case ad7998: | 228 | case ad7998: |
252 | return ad799x_i2c_write16(st, AD7998_CONF_REG, | 229 | st->config &= ~(GENMASK(7, 0) << AD799X_CHANNEL_SHIFT); |
253 | st->config | (*scan_mask << AD799X_CHANNEL_SHIFT)); | 230 | st->config |= (*scan_mask << AD799X_CHANNEL_SHIFT); |
231 | return ad799x_write_config(st, st->config); | ||
254 | default: | 232 | default: |
255 | break; | 233 | return 0; |
256 | } | 234 | } |
257 | |||
258 | return 0; | ||
259 | } | 235 | } |
260 | 236 | ||
261 | static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch) | 237 | static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch) |
262 | { | 238 | { |
263 | u16 rxbuf; | ||
264 | u8 cmd; | 239 | u8 cmd; |
265 | int ret; | ||
266 | 240 | ||
267 | switch (st->id) { | 241 | switch (st->id) { |
268 | case ad7991: | 242 | case ad7991: |
269 | case ad7995: | 243 | case ad7995: |
270 | case ad7999: | 244 | case ad7999: |
271 | cmd = st->config | ((1 << ch) << AD799X_CHANNEL_SHIFT); | 245 | cmd = st->config | (BIT(ch) << AD799X_CHANNEL_SHIFT); |
272 | break; | 246 | break; |
273 | case ad7992: | 247 | case ad7992: |
274 | case ad7993: | 248 | case ad7993: |
275 | case ad7994: | 249 | case ad7994: |
276 | cmd = (1 << ch) << AD799X_CHANNEL_SHIFT; | 250 | cmd = BIT(ch) << AD799X_CHANNEL_SHIFT; |
277 | break; | 251 | break; |
278 | case ad7997: | 252 | case ad7997: |
279 | case ad7998: | 253 | case ad7998: |
@@ -283,11 +257,7 @@ static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch) | |||
283 | return -EINVAL; | 257 | return -EINVAL; |
284 | } | 258 | } |
285 | 259 | ||
286 | ret = ad799x_i2c_read16(st, cmd, &rxbuf); | 260 | return i2c_smbus_read_word_swapped(st->client, cmd); |
287 | if (ret < 0) | ||
288 | return ret; | ||
289 | |||
290 | return rxbuf; | ||
291 | } | 261 | } |
292 | 262 | ||
293 | static int ad799x_read_raw(struct iio_dev *indio_dev, | 263 | static int ad799x_read_raw(struct iio_dev *indio_dev, |
@@ -311,7 +281,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, | |||
311 | if (ret < 0) | 281 | if (ret < 0) |
312 | return ret; | 282 | return ret; |
313 | *val = (ret >> chan->scan_type.shift) & | 283 | *val = (ret >> chan->scan_type.shift) & |
314 | RES_MASK(chan->scan_type.realbits); | 284 | GENMASK(chan->scan_type.realbits - 1, 0); |
315 | return IIO_VAL_INT; | 285 | return IIO_VAL_INT; |
316 | case IIO_CHAN_INFO_SCALE: | 286 | case IIO_CHAN_INFO_SCALE: |
317 | ret = regulator_get_voltage(st->vref); | 287 | ret = regulator_get_voltage(st->vref); |
@@ -332,6 +302,7 @@ static const unsigned int ad7998_frequencies[] = { | |||
332 | [AD7998_CYC_TCONF_1024] = 488, | 302 | [AD7998_CYC_TCONF_1024] = 488, |
333 | [AD7998_CYC_TCONF_2048] = 244, | 303 | [AD7998_CYC_TCONF_2048] = 244, |
334 | }; | 304 | }; |
305 | |||
335 | static ssize_t ad799x_read_frequency(struct device *dev, | 306 | static ssize_t ad799x_read_frequency(struct device *dev, |
336 | struct device_attribute *attr, | 307 | struct device_attribute *attr, |
337 | char *buf) | 308 | char *buf) |
@@ -339,15 +310,11 @@ static ssize_t ad799x_read_frequency(struct device *dev, | |||
339 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 310 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
340 | struct ad799x_state *st = iio_priv(indio_dev); | 311 | struct ad799x_state *st = iio_priv(indio_dev); |
341 | 312 | ||
342 | int ret; | 313 | int ret = i2c_smbus_read_byte_data(st->client, AD7998_CYCLE_TMR_REG); |
343 | u8 val; | 314 | if (ret < 0) |
344 | ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &val); | ||
345 | if (ret) | ||
346 | return ret; | 315 | return ret; |
347 | 316 | ||
348 | val &= AD7998_CYC_MASK; | 317 | return sprintf(buf, "%u\n", ad7998_frequencies[ret & AD7998_CYC_MASK]); |
349 | |||
350 | return sprintf(buf, "%u\n", ad7998_frequencies[val]); | ||
351 | } | 318 | } |
352 | 319 | ||
353 | static ssize_t ad799x_write_frequency(struct device *dev, | 320 | static ssize_t ad799x_write_frequency(struct device *dev, |
@@ -360,18 +327,17 @@ static ssize_t ad799x_write_frequency(struct device *dev, | |||
360 | 327 | ||
361 | long val; | 328 | long val; |
362 | int ret, i; | 329 | int ret, i; |
363 | u8 t; | ||
364 | 330 | ||
365 | ret = kstrtol(buf, 10, &val); | 331 | ret = kstrtol(buf, 10, &val); |
366 | if (ret) | 332 | if (ret) |
367 | return ret; | 333 | return ret; |
368 | 334 | ||
369 | mutex_lock(&indio_dev->mlock); | 335 | mutex_lock(&indio_dev->mlock); |
370 | ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &t); | 336 | ret = i2c_smbus_read_byte_data(st->client, AD7998_CYCLE_TMR_REG); |
371 | if (ret) | 337 | if (ret < 0) |
372 | goto error_ret_mutex; | 338 | goto error_ret_mutex; |
373 | /* Wipe the bits clean */ | 339 | /* Wipe the bits clean */ |
374 | t &= ~AD7998_CYC_MASK; | 340 | ret &= ~AD7998_CYC_MASK; |
375 | 341 | ||
376 | for (i = 0; i < ARRAY_SIZE(ad7998_frequencies); i++) | 342 | for (i = 0; i < ARRAY_SIZE(ad7998_frequencies); i++) |
377 | if (val == ad7998_frequencies[i]) | 343 | if (val == ad7998_frequencies[i]) |
@@ -380,13 +346,17 @@ static ssize_t ad799x_write_frequency(struct device *dev, | |||
380 | ret = -EINVAL; | 346 | ret = -EINVAL; |
381 | goto error_ret_mutex; | 347 | goto error_ret_mutex; |
382 | } | 348 | } |
383 | t |= i; | 349 | |
384 | ret = ad799x_i2c_write8(st, AD7998_CYCLE_TMR_REG, t); | 350 | ret = i2c_smbus_write_byte_data(st->client, AD7998_CYCLE_TMR_REG, |
351 | ret | i); | ||
352 | if (ret < 0) | ||
353 | goto error_ret_mutex; | ||
354 | ret = len; | ||
385 | 355 | ||
386 | error_ret_mutex: | 356 | error_ret_mutex: |
387 | mutex_unlock(&indio_dev->mlock); | 357 | mutex_unlock(&indio_dev->mlock); |
388 | 358 | ||
389 | return ret ? ret : len; | 359 | return ret; |
390 | } | 360 | } |
391 | 361 | ||
392 | static int ad799x_read_event_config(struct iio_dev *indio_dev, | 362 | static int ad799x_read_event_config(struct iio_dev *indio_dev, |
@@ -394,7 +364,48 @@ static int ad799x_read_event_config(struct iio_dev *indio_dev, | |||
394 | enum iio_event_type type, | 364 | enum iio_event_type type, |
395 | enum iio_event_direction dir) | 365 | enum iio_event_direction dir) |
396 | { | 366 | { |
397 | return 1; | 367 | struct ad799x_state *st = iio_priv(indio_dev); |
368 | |||
369 | if (!(st->config & AD7998_ALERT_EN)) | ||
370 | return 0; | ||
371 | |||
372 | if ((st->config >> AD799X_CHANNEL_SHIFT) & BIT(chan->scan_index)) | ||
373 | return 1; | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static int ad799x_write_event_config(struct iio_dev *indio_dev, | ||
379 | const struct iio_chan_spec *chan, | ||
380 | enum iio_event_type type, | ||
381 | enum iio_event_direction dir, | ||
382 | int state) | ||
383 | { | ||
384 | struct ad799x_state *st = iio_priv(indio_dev); | ||
385 | int ret; | ||
386 | |||
387 | mutex_lock(&indio_dev->mlock); | ||
388 | if (iio_buffer_enabled(indio_dev)) { | ||
389 | ret = -EBUSY; | ||
390 | goto done; | ||
391 | } | ||
392 | |||
393 | if (state) | ||
394 | st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT; | ||
395 | else | ||
396 | st->config &= ~(BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT); | ||
397 | |||
398 | if (st->config >> AD799X_CHANNEL_SHIFT) | ||
399 | st->config |= AD7998_ALERT_EN; | ||
400 | else | ||
401 | st->config &= ~AD7998_ALERT_EN; | ||
402 | |||
403 | ret = ad799x_write_config(st, st->config); | ||
404 | |||
405 | done: | ||
406 | mutex_unlock(&indio_dev->mlock); | ||
407 | |||
408 | return ret; | ||
398 | } | 409 | } |
399 | 410 | ||
400 | static unsigned int ad799x_threshold_reg(const struct iio_chan_spec *chan, | 411 | static unsigned int ad799x_threshold_reg(const struct iio_chan_spec *chan, |
@@ -426,11 +437,12 @@ static int ad799x_write_event_value(struct iio_dev *indio_dev, | |||
426 | int ret; | 437 | int ret; |
427 | struct ad799x_state *st = iio_priv(indio_dev); | 438 | struct ad799x_state *st = iio_priv(indio_dev); |
428 | 439 | ||
429 | if (val < 0 || val > RES_MASK(chan->scan_type.realbits)) | 440 | if (val < 0 || val > GENMASK(chan->scan_type.realbits - 1, 0)) |
430 | return -EINVAL; | 441 | return -EINVAL; |
431 | 442 | ||
432 | mutex_lock(&indio_dev->mlock); | 443 | mutex_lock(&indio_dev->mlock); |
433 | ret = ad799x_i2c_write16(st, ad799x_threshold_reg(chan, dir, info), | 444 | ret = i2c_smbus_write_word_swapped(st->client, |
445 | ad799x_threshold_reg(chan, dir, info), | ||
434 | val << chan->scan_type.shift); | 446 | val << chan->scan_type.shift); |
435 | mutex_unlock(&indio_dev->mlock); | 447 | mutex_unlock(&indio_dev->mlock); |
436 | 448 | ||
@@ -446,16 +458,15 @@ static int ad799x_read_event_value(struct iio_dev *indio_dev, | |||
446 | { | 458 | { |
447 | int ret; | 459 | int ret; |
448 | struct ad799x_state *st = iio_priv(indio_dev); | 460 | struct ad799x_state *st = iio_priv(indio_dev); |
449 | u16 valin; | ||
450 | 461 | ||
451 | mutex_lock(&indio_dev->mlock); | 462 | mutex_lock(&indio_dev->mlock); |
452 | ret = ad799x_i2c_read16(st, ad799x_threshold_reg(chan, dir, info), | 463 | ret = i2c_smbus_read_word_swapped(st->client, |
453 | &valin); | 464 | ad799x_threshold_reg(chan, dir, info)); |
454 | mutex_unlock(&indio_dev->mlock); | 465 | mutex_unlock(&indio_dev->mlock); |
455 | if (ret < 0) | 466 | if (ret < 0) |
456 | return ret; | 467 | return ret; |
457 | *val = (valin >> chan->scan_type.shift) & | 468 | *val = (ret >> chan->scan_type.shift) & |
458 | RES_MASK(chan->scan_type.realbits); | 469 | GENMASK(chan->scan_type.realbits - 1 , 0); |
459 | 470 | ||
460 | return IIO_VAL_INT; | 471 | return IIO_VAL_INT; |
461 | } | 472 | } |
@@ -464,20 +475,18 @@ static irqreturn_t ad799x_event_handler(int irq, void *private) | |||
464 | { | 475 | { |
465 | struct iio_dev *indio_dev = private; | 476 | struct iio_dev *indio_dev = private; |
466 | struct ad799x_state *st = iio_priv(private); | 477 | struct ad799x_state *st = iio_priv(private); |
467 | u8 status; | ||
468 | int i, ret; | 478 | int i, ret; |
469 | 479 | ||
470 | ret = ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status); | 480 | ret = i2c_smbus_read_byte_data(st->client, AD7998_ALERT_STAT_REG); |
471 | if (ret) | 481 | if (ret <= 0) |
472 | goto done; | 482 | goto done; |
473 | 483 | ||
474 | if (!status) | 484 | if (i2c_smbus_write_byte_data(st->client, AD7998_ALERT_STAT_REG, |
485 | AD7998_ALERT_STAT_CLEAR) < 0) | ||
475 | goto done; | 486 | goto done; |
476 | 487 | ||
477 | ad799x_i2c_write8(st, AD7998_ALERT_STAT_REG, AD7998_ALERT_STAT_CLEAR); | ||
478 | |||
479 | for (i = 0; i < 8; i++) { | 488 | for (i = 0; i < 8; i++) { |
480 | if (status & (1 << i)) | 489 | if (ret & BIT(i)) |
481 | iio_push_event(indio_dev, | 490 | iio_push_event(indio_dev, |
482 | i & 0x1 ? | 491 | i & 0x1 ? |
483 | IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, | 492 | IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, |
@@ -516,14 +525,21 @@ static const struct iio_info ad7991_info = { | |||
516 | .driver_module = THIS_MODULE, | 525 | .driver_module = THIS_MODULE, |
517 | }; | 526 | }; |
518 | 527 | ||
519 | static const struct iio_info ad7993_4_7_8_info = { | 528 | static const struct iio_info ad7993_4_7_8_noirq_info = { |
529 | .read_raw = &ad799x_read_raw, | ||
530 | .driver_module = THIS_MODULE, | ||
531 | .update_scan_mode = ad799x_update_scan_mode, | ||
532 | }; | ||
533 | |||
534 | static const struct iio_info ad7993_4_7_8_irq_info = { | ||
520 | .read_raw = &ad799x_read_raw, | 535 | .read_raw = &ad799x_read_raw, |
521 | .event_attrs = &ad799x_event_attrs_group, | 536 | .event_attrs = &ad799x_event_attrs_group, |
522 | .read_event_config = &ad799x_read_event_config, | 537 | .read_event_config = &ad799x_read_event_config, |
538 | .write_event_config = &ad799x_write_event_config, | ||
523 | .read_event_value = &ad799x_read_event_value, | 539 | .read_event_value = &ad799x_read_event_value, |
524 | .write_event_value = &ad799x_write_event_value, | 540 | .write_event_value = &ad799x_write_event_value, |
525 | .driver_module = THIS_MODULE, | 541 | .driver_module = THIS_MODULE, |
526 | .update_scan_mode = ad7997_8_update_scan_mode, | 542 | .update_scan_mode = ad799x_update_scan_mode, |
527 | }; | 543 | }; |
528 | 544 | ||
529 | static const struct iio_event_spec ad799x_events[] = { | 545 | static const struct iio_event_spec ad799x_events[] = { |
@@ -571,103 +587,175 @@ static const struct iio_event_spec ad799x_events[] = { | |||
571 | 587 | ||
572 | static const struct ad799x_chip_info ad799x_chip_info_tbl[] = { | 588 | static const struct ad799x_chip_info ad799x_chip_info_tbl[] = { |
573 | [ad7991] = { | 589 | [ad7991] = { |
574 | .channel = { | ||
575 | AD799X_CHANNEL(0, 12), | ||
576 | AD799X_CHANNEL(1, 12), | ||
577 | AD799X_CHANNEL(2, 12), | ||
578 | AD799X_CHANNEL(3, 12), | ||
579 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
580 | }, | ||
581 | .num_channels = 5, | 590 | .num_channels = 5, |
582 | .info = &ad7991_info, | 591 | .noirq_config = { |
592 | .channel = { | ||
593 | AD799X_CHANNEL(0, 12), | ||
594 | AD799X_CHANNEL(1, 12), | ||
595 | AD799X_CHANNEL(2, 12), | ||
596 | AD799X_CHANNEL(3, 12), | ||
597 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
598 | }, | ||
599 | .info = &ad7991_info, | ||
600 | }, | ||
583 | }, | 601 | }, |
584 | [ad7995] = { | 602 | [ad7995] = { |
585 | .channel = { | ||
586 | AD799X_CHANNEL(0, 10), | ||
587 | AD799X_CHANNEL(1, 10), | ||
588 | AD799X_CHANNEL(2, 10), | ||
589 | AD799X_CHANNEL(3, 10), | ||
590 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
591 | }, | ||
592 | .num_channels = 5, | 603 | .num_channels = 5, |
593 | .info = &ad7991_info, | 604 | .noirq_config = { |
605 | .channel = { | ||
606 | AD799X_CHANNEL(0, 10), | ||
607 | AD799X_CHANNEL(1, 10), | ||
608 | AD799X_CHANNEL(2, 10), | ||
609 | AD799X_CHANNEL(3, 10), | ||
610 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
611 | }, | ||
612 | .info = &ad7991_info, | ||
613 | }, | ||
594 | }, | 614 | }, |
595 | [ad7999] = { | 615 | [ad7999] = { |
596 | .channel = { | ||
597 | AD799X_CHANNEL(0, 8), | ||
598 | AD799X_CHANNEL(1, 8), | ||
599 | AD799X_CHANNEL(2, 8), | ||
600 | AD799X_CHANNEL(3, 8), | ||
601 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
602 | }, | ||
603 | .num_channels = 5, | 616 | .num_channels = 5, |
604 | .info = &ad7991_info, | 617 | .noirq_config = { |
618 | .channel = { | ||
619 | AD799X_CHANNEL(0, 8), | ||
620 | AD799X_CHANNEL(1, 8), | ||
621 | AD799X_CHANNEL(2, 8), | ||
622 | AD799X_CHANNEL(3, 8), | ||
623 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
624 | }, | ||
625 | .info = &ad7991_info, | ||
626 | }, | ||
605 | }, | 627 | }, |
606 | [ad7992] = { | 628 | [ad7992] = { |
607 | .channel = { | ||
608 | AD799X_CHANNEL_WITH_EVENTS(0, 12), | ||
609 | AD799X_CHANNEL_WITH_EVENTS(1, 12), | ||
610 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
611 | }, | ||
612 | .num_channels = 3, | 629 | .num_channels = 3, |
613 | .default_config = AD7998_ALERT_EN, | 630 | .noirq_config = { |
614 | .info = &ad7993_4_7_8_info, | 631 | .channel = { |
632 | AD799X_CHANNEL(0, 12), | ||
633 | AD799X_CHANNEL(1, 12), | ||
634 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
635 | }, | ||
636 | .info = &ad7993_4_7_8_noirq_info, | ||
637 | }, | ||
638 | .irq_config = { | ||
639 | .channel = { | ||
640 | AD799X_CHANNEL_WITH_EVENTS(0, 12), | ||
641 | AD799X_CHANNEL_WITH_EVENTS(1, 12), | ||
642 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
643 | }, | ||
644 | .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT, | ||
645 | .info = &ad7993_4_7_8_irq_info, | ||
646 | }, | ||
615 | }, | 647 | }, |
616 | [ad7993] = { | 648 | [ad7993] = { |
617 | .channel = { | ||
618 | AD799X_CHANNEL_WITH_EVENTS(0, 10), | ||
619 | AD799X_CHANNEL_WITH_EVENTS(1, 10), | ||
620 | AD799X_CHANNEL_WITH_EVENTS(2, 10), | ||
621 | AD799X_CHANNEL_WITH_EVENTS(3, 10), | ||
622 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
623 | }, | ||
624 | .num_channels = 5, | 649 | .num_channels = 5, |
625 | .default_config = AD7998_ALERT_EN, | 650 | .noirq_config = { |
626 | .info = &ad7993_4_7_8_info, | 651 | .channel = { |
652 | AD799X_CHANNEL(0, 10), | ||
653 | AD799X_CHANNEL(1, 10), | ||
654 | AD799X_CHANNEL(2, 10), | ||
655 | AD799X_CHANNEL(3, 10), | ||
656 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
657 | }, | ||
658 | .info = &ad7993_4_7_8_noirq_info, | ||
659 | }, | ||
660 | .irq_config = { | ||
661 | .channel = { | ||
662 | AD799X_CHANNEL_WITH_EVENTS(0, 10), | ||
663 | AD799X_CHANNEL_WITH_EVENTS(1, 10), | ||
664 | AD799X_CHANNEL_WITH_EVENTS(2, 10), | ||
665 | AD799X_CHANNEL_WITH_EVENTS(3, 10), | ||
666 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
667 | }, | ||
668 | .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT, | ||
669 | .info = &ad7993_4_7_8_irq_info, | ||
670 | }, | ||
627 | }, | 671 | }, |
628 | [ad7994] = { | 672 | [ad7994] = { |
629 | .channel = { | ||
630 | AD799X_CHANNEL_WITH_EVENTS(0, 12), | ||
631 | AD799X_CHANNEL_WITH_EVENTS(1, 12), | ||
632 | AD799X_CHANNEL_WITH_EVENTS(2, 12), | ||
633 | AD799X_CHANNEL_WITH_EVENTS(3, 12), | ||
634 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
635 | }, | ||
636 | .num_channels = 5, | 673 | .num_channels = 5, |
637 | .default_config = AD7998_ALERT_EN, | 674 | .noirq_config = { |
638 | .info = &ad7993_4_7_8_info, | 675 | .channel = { |
676 | AD799X_CHANNEL(0, 12), | ||
677 | AD799X_CHANNEL(1, 12), | ||
678 | AD799X_CHANNEL(2, 12), | ||
679 | AD799X_CHANNEL(3, 12), | ||
680 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
681 | }, | ||
682 | .info = &ad7993_4_7_8_noirq_info, | ||
683 | }, | ||
684 | .irq_config = { | ||
685 | .channel = { | ||
686 | AD799X_CHANNEL_WITH_EVENTS(0, 12), | ||
687 | AD799X_CHANNEL_WITH_EVENTS(1, 12), | ||
688 | AD799X_CHANNEL_WITH_EVENTS(2, 12), | ||
689 | AD799X_CHANNEL_WITH_EVENTS(3, 12), | ||
690 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
691 | }, | ||
692 | .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT, | ||
693 | .info = &ad7993_4_7_8_irq_info, | ||
694 | }, | ||
639 | }, | 695 | }, |
640 | [ad7997] = { | 696 | [ad7997] = { |
641 | .channel = { | ||
642 | AD799X_CHANNEL_WITH_EVENTS(0, 10), | ||
643 | AD799X_CHANNEL_WITH_EVENTS(1, 10), | ||
644 | AD799X_CHANNEL_WITH_EVENTS(2, 10), | ||
645 | AD799X_CHANNEL_WITH_EVENTS(3, 10), | ||
646 | AD799X_CHANNEL(4, 10), | ||
647 | AD799X_CHANNEL(5, 10), | ||
648 | AD799X_CHANNEL(6, 10), | ||
649 | AD799X_CHANNEL(7, 10), | ||
650 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
651 | }, | ||
652 | .num_channels = 9, | 697 | .num_channels = 9, |
653 | .default_config = AD7998_ALERT_EN, | 698 | .noirq_config = { |
654 | .info = &ad7993_4_7_8_info, | 699 | .channel = { |
700 | AD799X_CHANNEL(0, 10), | ||
701 | AD799X_CHANNEL(1, 10), | ||
702 | AD799X_CHANNEL(2, 10), | ||
703 | AD799X_CHANNEL(3, 10), | ||
704 | AD799X_CHANNEL(4, 10), | ||
705 | AD799X_CHANNEL(5, 10), | ||
706 | AD799X_CHANNEL(6, 10), | ||
707 | AD799X_CHANNEL(7, 10), | ||
708 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
709 | }, | ||
710 | .info = &ad7993_4_7_8_noirq_info, | ||
711 | }, | ||
712 | .irq_config = { | ||
713 | .channel = { | ||
714 | AD799X_CHANNEL_WITH_EVENTS(0, 10), | ||
715 | AD799X_CHANNEL_WITH_EVENTS(1, 10), | ||
716 | AD799X_CHANNEL_WITH_EVENTS(2, 10), | ||
717 | AD799X_CHANNEL_WITH_EVENTS(3, 10), | ||
718 | AD799X_CHANNEL(4, 10), | ||
719 | AD799X_CHANNEL(5, 10), | ||
720 | AD799X_CHANNEL(6, 10), | ||
721 | AD799X_CHANNEL(7, 10), | ||
722 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
723 | }, | ||
724 | .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT, | ||
725 | .info = &ad7993_4_7_8_irq_info, | ||
726 | }, | ||
655 | }, | 727 | }, |
656 | [ad7998] = { | 728 | [ad7998] = { |
657 | .channel = { | ||
658 | AD799X_CHANNEL_WITH_EVENTS(0, 12), | ||
659 | AD799X_CHANNEL_WITH_EVENTS(1, 12), | ||
660 | AD799X_CHANNEL_WITH_EVENTS(2, 12), | ||
661 | AD799X_CHANNEL_WITH_EVENTS(3, 12), | ||
662 | AD799X_CHANNEL(4, 12), | ||
663 | AD799X_CHANNEL(5, 12), | ||
664 | AD799X_CHANNEL(6, 12), | ||
665 | AD799X_CHANNEL(7, 12), | ||
666 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
667 | }, | ||
668 | .num_channels = 9, | 729 | .num_channels = 9, |
669 | .default_config = AD7998_ALERT_EN, | 730 | .noirq_config = { |
670 | .info = &ad7993_4_7_8_info, | 731 | .channel = { |
732 | AD799X_CHANNEL(0, 12), | ||
733 | AD799X_CHANNEL(1, 12), | ||
734 | AD799X_CHANNEL(2, 12), | ||
735 | AD799X_CHANNEL(3, 12), | ||
736 | AD799X_CHANNEL(4, 12), | ||
737 | AD799X_CHANNEL(5, 12), | ||
738 | AD799X_CHANNEL(6, 12), | ||
739 | AD799X_CHANNEL(7, 12), | ||
740 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
741 | }, | ||
742 | .info = &ad7993_4_7_8_noirq_info, | ||
743 | }, | ||
744 | .irq_config = { | ||
745 | .channel = { | ||
746 | AD799X_CHANNEL_WITH_EVENTS(0, 12), | ||
747 | AD799X_CHANNEL_WITH_EVENTS(1, 12), | ||
748 | AD799X_CHANNEL_WITH_EVENTS(2, 12), | ||
749 | AD799X_CHANNEL_WITH_EVENTS(3, 12), | ||
750 | AD799X_CHANNEL(4, 12), | ||
751 | AD799X_CHANNEL(5, 12), | ||
752 | AD799X_CHANNEL(6, 12), | ||
753 | AD799X_CHANNEL(7, 12), | ||
754 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
755 | }, | ||
756 | .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT, | ||
757 | .info = &ad7993_4_7_8_irq_info, | ||
758 | }, | ||
671 | }, | 759 | }, |
672 | }; | 760 | }; |
673 | 761 | ||
@@ -677,6 +765,8 @@ static int ad799x_probe(struct i2c_client *client, | |||
677 | int ret; | 765 | int ret; |
678 | struct ad799x_state *st; | 766 | struct ad799x_state *st; |
679 | struct iio_dev *indio_dev; | 767 | struct iio_dev *indio_dev; |
768 | const struct ad799x_chip_info *chip_info = | ||
769 | &ad799x_chip_info_tbl[id->driver_data]; | ||
680 | 770 | ||
681 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); | 771 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); |
682 | if (indio_dev == NULL) | 772 | if (indio_dev == NULL) |
@@ -687,8 +777,10 @@ static int ad799x_probe(struct i2c_client *client, | |||
687 | i2c_set_clientdata(client, indio_dev); | 777 | i2c_set_clientdata(client, indio_dev); |
688 | 778 | ||
689 | st->id = id->driver_data; | 779 | st->id = id->driver_data; |
690 | st->chip_info = &ad799x_chip_info_tbl[st->id]; | 780 | if (client->irq > 0 && chip_info->irq_config.info) |
691 | st->config = st->chip_info->default_config; | 781 | st->chip_config = &chip_info->irq_config; |
782 | else | ||
783 | st->chip_config = &chip_info->noirq_config; | ||
692 | 784 | ||
693 | /* TODO: Add pdata options for filtering and bit delay */ | 785 | /* TODO: Add pdata options for filtering and bit delay */ |
694 | 786 | ||
@@ -711,11 +803,19 @@ static int ad799x_probe(struct i2c_client *client, | |||
711 | 803 | ||
712 | indio_dev->dev.parent = &client->dev; | 804 | indio_dev->dev.parent = &client->dev; |
713 | indio_dev->name = id->name; | 805 | indio_dev->name = id->name; |
714 | indio_dev->info = st->chip_info->info; | 806 | indio_dev->info = st->chip_config->info; |
715 | 807 | ||
716 | indio_dev->modes = INDIO_DIRECT_MODE; | 808 | indio_dev->modes = INDIO_DIRECT_MODE; |
717 | indio_dev->channels = st->chip_info->channel; | 809 | indio_dev->channels = st->chip_config->channel; |
718 | indio_dev->num_channels = st->chip_info->num_channels; | 810 | indio_dev->num_channels = chip_info->num_channels; |
811 | |||
812 | ret = ad799x_write_config(st, st->chip_config->default_config); | ||
813 | if (ret < 0) | ||
814 | goto error_disable_reg; | ||
815 | ret = ad799x_read_config(st); | ||
816 | if (ret < 0) | ||
817 | goto error_disable_reg; | ||
818 | st->config = ret; | ||
719 | 819 | ||
720 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | 820 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
721 | &ad799x_trigger_handler, NULL); | 821 | &ad799x_trigger_handler, NULL); |
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index 010578f1d762..fc9dfc23ecb7 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/errno.h> | ||
27 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | #include <linux/io.h> | 30 | #include <linux/io.h> |
@@ -39,11 +40,6 @@ | |||
39 | #include <linux/iio/machine.h> | 40 | #include <linux/iio/machine.h> |
40 | #include <linux/iio/driver.h> | 41 | #include <linux/iio/driver.h> |
41 | 42 | ||
42 | enum adc_version { | ||
43 | ADC_V1, | ||
44 | ADC_V2 | ||
45 | }; | ||
46 | |||
47 | /* EXYNOS4412/5250 ADC_V1 registers definitions */ | 43 | /* EXYNOS4412/5250 ADC_V1 registers definitions */ |
48 | #define ADC_V1_CON(x) ((x) + 0x00) | 44 | #define ADC_V1_CON(x) ((x) + 0x00) |
49 | #define ADC_V1_DLY(x) ((x) + 0x08) | 45 | #define ADC_V1_DLY(x) ((x) + 0x08) |
@@ -75,8 +71,9 @@ enum adc_version { | |||
75 | #define ADC_V2_CON2_ACH_SEL(x) (((x) & 0xF) << 0) | 71 | #define ADC_V2_CON2_ACH_SEL(x) (((x) & 0xF) << 0) |
76 | #define ADC_V2_CON2_ACH_MASK 0xF | 72 | #define ADC_V2_CON2_ACH_MASK 0xF |
77 | 73 | ||
78 | #define MAX_ADC_V2_CHANNELS 10 | 74 | #define MAX_ADC_V2_CHANNELS 10 |
79 | #define MAX_ADC_V1_CHANNELS 8 | 75 | #define MAX_ADC_V1_CHANNELS 8 |
76 | #define MAX_EXYNOS3250_ADC_CHANNELS 2 | ||
80 | 77 | ||
81 | /* Bit definitions common for ADC_V1 and ADC_V2 */ | 78 | /* Bit definitions common for ADC_V1 and ADC_V2 */ |
82 | #define ADC_CON_EN_START (1u << 0) | 79 | #define ADC_CON_EN_START (1u << 0) |
@@ -85,9 +82,12 @@ enum adc_version { | |||
85 | #define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100)) | 82 | #define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100)) |
86 | 83 | ||
87 | struct exynos_adc { | 84 | struct exynos_adc { |
85 | struct exynos_adc_data *data; | ||
86 | struct device *dev; | ||
88 | void __iomem *regs; | 87 | void __iomem *regs; |
89 | void __iomem *enable_reg; | 88 | void __iomem *enable_reg; |
90 | struct clk *clk; | 89 | struct clk *clk; |
90 | struct clk *sclk; | ||
91 | unsigned int irq; | 91 | unsigned int irq; |
92 | struct regulator *vdd; | 92 | struct regulator *vdd; |
93 | 93 | ||
@@ -97,43 +97,213 @@ struct exynos_adc { | |||
97 | unsigned int version; | 97 | unsigned int version; |
98 | }; | 98 | }; |
99 | 99 | ||
100 | static const struct of_device_id exynos_adc_match[] = { | 100 | struct exynos_adc_data { |
101 | { .compatible = "samsung,exynos-adc-v1", .data = (void *)ADC_V1 }, | 101 | int num_channels; |
102 | { .compatible = "samsung,exynos-adc-v2", .data = (void *)ADC_V2 }, | 102 | bool needs_sclk; |
103 | {}, | 103 | |
104 | void (*init_hw)(struct exynos_adc *info); | ||
105 | void (*exit_hw)(struct exynos_adc *info); | ||
106 | void (*clear_irq)(struct exynos_adc *info); | ||
107 | void (*start_conv)(struct exynos_adc *info, unsigned long addr); | ||
104 | }; | 108 | }; |
105 | MODULE_DEVICE_TABLE(of, exynos_adc_match); | ||
106 | 109 | ||
107 | static inline unsigned int exynos_adc_get_version(struct platform_device *pdev) | 110 | static void exynos_adc_unprepare_clk(struct exynos_adc *info) |
108 | { | 111 | { |
109 | const struct of_device_id *match; | 112 | if (info->data->needs_sclk) |
113 | clk_unprepare(info->sclk); | ||
114 | clk_unprepare(info->clk); | ||
115 | } | ||
110 | 116 | ||
111 | match = of_match_node(exynos_adc_match, pdev->dev.of_node); | 117 | static int exynos_adc_prepare_clk(struct exynos_adc *info) |
112 | return (unsigned int)match->data; | 118 | { |
119 | int ret; | ||
120 | |||
121 | ret = clk_prepare(info->clk); | ||
122 | if (ret) { | ||
123 | dev_err(info->dev, "failed preparing adc clock: %d\n", ret); | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | if (info->data->needs_sclk) { | ||
128 | ret = clk_prepare(info->sclk); | ||
129 | if (ret) { | ||
130 | clk_unprepare(info->clk); | ||
131 | dev_err(info->dev, | ||
132 | "failed preparing sclk_adc clock: %d\n", ret); | ||
133 | return ret; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static void exynos_adc_disable_clk(struct exynos_adc *info) | ||
141 | { | ||
142 | if (info->data->needs_sclk) | ||
143 | clk_disable(info->sclk); | ||
144 | clk_disable(info->clk); | ||
145 | } | ||
146 | |||
147 | static int exynos_adc_enable_clk(struct exynos_adc *info) | ||
148 | { | ||
149 | int ret; | ||
150 | |||
151 | ret = clk_enable(info->clk); | ||
152 | if (ret) { | ||
153 | dev_err(info->dev, "failed enabling adc clock: %d\n", ret); | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | if (info->data->needs_sclk) { | ||
158 | ret = clk_enable(info->sclk); | ||
159 | if (ret) { | ||
160 | clk_disable(info->clk); | ||
161 | dev_err(info->dev, | ||
162 | "failed enabling sclk_adc clock: %d\n", ret); | ||
163 | return ret; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static void exynos_adc_v1_init_hw(struct exynos_adc *info) | ||
171 | { | ||
172 | u32 con1; | ||
173 | |||
174 | writel(1, info->enable_reg); | ||
175 | |||
176 | /* set default prescaler values and Enable prescaler */ | ||
177 | con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN; | ||
178 | |||
179 | /* Enable 12-bit ADC resolution */ | ||
180 | con1 |= ADC_V1_CON_RES; | ||
181 | writel(con1, ADC_V1_CON(info->regs)); | ||
182 | } | ||
183 | |||
184 | static void exynos_adc_v1_exit_hw(struct exynos_adc *info) | ||
185 | { | ||
186 | u32 con; | ||
187 | |||
188 | writel(0, info->enable_reg); | ||
189 | |||
190 | con = readl(ADC_V1_CON(info->regs)); | ||
191 | con |= ADC_V1_CON_STANDBY; | ||
192 | writel(con, ADC_V1_CON(info->regs)); | ||
193 | } | ||
194 | |||
195 | static void exynos_adc_v1_clear_irq(struct exynos_adc *info) | ||
196 | { | ||
197 | writel(1, ADC_V1_INTCLR(info->regs)); | ||
198 | } | ||
199 | |||
200 | static void exynos_adc_v1_start_conv(struct exynos_adc *info, | ||
201 | unsigned long addr) | ||
202 | { | ||
203 | u32 con1; | ||
204 | |||
205 | writel(addr, ADC_V1_MUX(info->regs)); | ||
206 | |||
207 | con1 = readl(ADC_V1_CON(info->regs)); | ||
208 | writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs)); | ||
209 | } | ||
210 | |||
211 | static const struct exynos_adc_data exynos_adc_v1_data = { | ||
212 | .num_channels = MAX_ADC_V1_CHANNELS, | ||
213 | |||
214 | .init_hw = exynos_adc_v1_init_hw, | ||
215 | .exit_hw = exynos_adc_v1_exit_hw, | ||
216 | .clear_irq = exynos_adc_v1_clear_irq, | ||
217 | .start_conv = exynos_adc_v1_start_conv, | ||
218 | }; | ||
219 | |||
220 | static void exynos_adc_v2_init_hw(struct exynos_adc *info) | ||
221 | { | ||
222 | u32 con1, con2; | ||
223 | |||
224 | writel(1, info->enable_reg); | ||
225 | |||
226 | con1 = ADC_V2_CON1_SOFT_RESET; | ||
227 | writel(con1, ADC_V2_CON1(info->regs)); | ||
228 | |||
229 | con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL | | ||
230 | ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0); | ||
231 | writel(con2, ADC_V2_CON2(info->regs)); | ||
232 | |||
233 | /* Enable interrupts */ | ||
234 | writel(1, ADC_V2_INT_EN(info->regs)); | ||
235 | } | ||
236 | |||
237 | static void exynos_adc_v2_exit_hw(struct exynos_adc *info) | ||
238 | { | ||
239 | u32 con; | ||
240 | |||
241 | writel(0, info->enable_reg); | ||
242 | |||
243 | con = readl(ADC_V2_CON1(info->regs)); | ||
244 | con &= ~ADC_CON_EN_START; | ||
245 | writel(con, ADC_V2_CON1(info->regs)); | ||
113 | } | 246 | } |
114 | 247 | ||
115 | static void exynos_adc_hw_init(struct exynos_adc *info) | 248 | static void exynos_adc_v2_clear_irq(struct exynos_adc *info) |
249 | { | ||
250 | writel(1, ADC_V2_INT_ST(info->regs)); | ||
251 | } | ||
252 | |||
253 | static void exynos_adc_v2_start_conv(struct exynos_adc *info, | ||
254 | unsigned long addr) | ||
116 | { | 255 | { |
117 | u32 con1, con2; | 256 | u32 con1, con2; |
118 | 257 | ||
119 | if (info->version == ADC_V2) { | 258 | con2 = readl(ADC_V2_CON2(info->regs)); |
120 | con1 = ADC_V2_CON1_SOFT_RESET; | 259 | con2 &= ~ADC_V2_CON2_ACH_MASK; |
121 | writel(con1, ADC_V2_CON1(info->regs)); | 260 | con2 |= ADC_V2_CON2_ACH_SEL(addr); |
261 | writel(con2, ADC_V2_CON2(info->regs)); | ||
122 | 262 | ||
123 | con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL | | 263 | con1 = readl(ADC_V2_CON1(info->regs)); |
124 | ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0); | 264 | writel(con1 | ADC_CON_EN_START, ADC_V2_CON1(info->regs)); |
125 | writel(con2, ADC_V2_CON2(info->regs)); | 265 | } |
126 | 266 | ||
127 | /* Enable interrupts */ | 267 | static const struct exynos_adc_data exynos_adc_v2_data = { |
128 | writel(1, ADC_V2_INT_EN(info->regs)); | 268 | .num_channels = MAX_ADC_V2_CHANNELS, |
129 | } else { | ||
130 | /* set default prescaler values and Enable prescaler */ | ||
131 | con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN; | ||
132 | 269 | ||
133 | /* Enable 12-bit ADC resolution */ | 270 | .init_hw = exynos_adc_v2_init_hw, |
134 | con1 |= ADC_V1_CON_RES; | 271 | .exit_hw = exynos_adc_v2_exit_hw, |
135 | writel(con1, ADC_V1_CON(info->regs)); | 272 | .clear_irq = exynos_adc_v2_clear_irq, |
136 | } | 273 | .start_conv = exynos_adc_v2_start_conv, |
274 | }; | ||
275 | |||
276 | static const struct exynos_adc_data exynos3250_adc_data = { | ||
277 | .num_channels = MAX_EXYNOS3250_ADC_CHANNELS, | ||
278 | .needs_sclk = true, | ||
279 | |||
280 | .init_hw = exynos_adc_v2_init_hw, | ||
281 | .exit_hw = exynos_adc_v2_exit_hw, | ||
282 | .clear_irq = exynos_adc_v2_clear_irq, | ||
283 | .start_conv = exynos_adc_v2_start_conv, | ||
284 | }; | ||
285 | |||
286 | static const struct of_device_id exynos_adc_match[] = { | ||
287 | { | ||
288 | .compatible = "samsung,exynos-adc-v1", | ||
289 | .data = &exynos_adc_v1_data, | ||
290 | }, { | ||
291 | .compatible = "samsung,exynos-adc-v2", | ||
292 | .data = &exynos_adc_v2_data, | ||
293 | }, { | ||
294 | .compatible = "samsung,exynos3250-adc", | ||
295 | .data = &exynos3250_adc_data, | ||
296 | }, | ||
297 | {}, | ||
298 | }; | ||
299 | MODULE_DEVICE_TABLE(of, exynos_adc_match); | ||
300 | |||
301 | static struct exynos_adc_data *exynos_adc_get_data(struct platform_device *pdev) | ||
302 | { | ||
303 | const struct of_device_id *match; | ||
304 | |||
305 | match = of_match_node(exynos_adc_match, pdev->dev.of_node); | ||
306 | return (struct exynos_adc_data *)match->data; | ||
137 | } | 307 | } |
138 | 308 | ||
139 | static int exynos_read_raw(struct iio_dev *indio_dev, | 309 | static int exynos_read_raw(struct iio_dev *indio_dev, |
@@ -144,7 +314,6 @@ static int exynos_read_raw(struct iio_dev *indio_dev, | |||
144 | { | 314 | { |
145 | struct exynos_adc *info = iio_priv(indio_dev); | 315 | struct exynos_adc *info = iio_priv(indio_dev); |
146 | unsigned long timeout; | 316 | unsigned long timeout; |
147 | u32 con1, con2; | ||
148 | int ret; | 317 | int ret; |
149 | 318 | ||
150 | if (mask != IIO_CHAN_INFO_RAW) | 319 | if (mask != IIO_CHAN_INFO_RAW) |
@@ -154,28 +323,15 @@ static int exynos_read_raw(struct iio_dev *indio_dev, | |||
154 | reinit_completion(&info->completion); | 323 | reinit_completion(&info->completion); |
155 | 324 | ||
156 | /* Select the channel to be used and Trigger conversion */ | 325 | /* Select the channel to be used and Trigger conversion */ |
157 | if (info->version == ADC_V2) { | 326 | if (info->data->start_conv) |
158 | con2 = readl(ADC_V2_CON2(info->regs)); | 327 | info->data->start_conv(info, chan->address); |
159 | con2 &= ~ADC_V2_CON2_ACH_MASK; | ||
160 | con2 |= ADC_V2_CON2_ACH_SEL(chan->address); | ||
161 | writel(con2, ADC_V2_CON2(info->regs)); | ||
162 | |||
163 | con1 = readl(ADC_V2_CON1(info->regs)); | ||
164 | writel(con1 | ADC_CON_EN_START, | ||
165 | ADC_V2_CON1(info->regs)); | ||
166 | } else { | ||
167 | writel(chan->address, ADC_V1_MUX(info->regs)); | ||
168 | |||
169 | con1 = readl(ADC_V1_CON(info->regs)); | ||
170 | writel(con1 | ADC_CON_EN_START, | ||
171 | ADC_V1_CON(info->regs)); | ||
172 | } | ||
173 | 328 | ||
174 | timeout = wait_for_completion_timeout | 329 | timeout = wait_for_completion_timeout |
175 | (&info->completion, EXYNOS_ADC_TIMEOUT); | 330 | (&info->completion, EXYNOS_ADC_TIMEOUT); |
176 | if (timeout == 0) { | 331 | if (timeout == 0) { |
177 | dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n"); | 332 | dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n"); |
178 | exynos_adc_hw_init(info); | 333 | if (info->data->init_hw) |
334 | info->data->init_hw(info); | ||
179 | ret = -ETIMEDOUT; | 335 | ret = -ETIMEDOUT; |
180 | } else { | 336 | } else { |
181 | *val = info->value; | 337 | *val = info->value; |
@@ -193,13 +349,11 @@ static irqreturn_t exynos_adc_isr(int irq, void *dev_id) | |||
193 | struct exynos_adc *info = (struct exynos_adc *)dev_id; | 349 | struct exynos_adc *info = (struct exynos_adc *)dev_id; |
194 | 350 | ||
195 | /* Read value */ | 351 | /* Read value */ |
196 | info->value = readl(ADC_V1_DATX(info->regs)) & | 352 | info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK; |
197 | ADC_DATX_MASK; | 353 | |
198 | /* clear irq */ | 354 | /* clear irq */ |
199 | if (info->version == ADC_V2) | 355 | if (info->data->clear_irq) |
200 | writel(1, ADC_V2_INT_ST(info->regs)); | 356 | info->data->clear_irq(info); |
201 | else | ||
202 | writel(1, ADC_V1_INTCLR(info->regs)); | ||
203 | 357 | ||
204 | complete(&info->completion); | 358 | complete(&info->completion); |
205 | 359 | ||
@@ -277,6 +431,12 @@ static int exynos_adc_probe(struct platform_device *pdev) | |||
277 | 431 | ||
278 | info = iio_priv(indio_dev); | 432 | info = iio_priv(indio_dev); |
279 | 433 | ||
434 | info->data = exynos_adc_get_data(pdev); | ||
435 | if (!info->data) { | ||
436 | dev_err(&pdev->dev, "failed getting exynos_adc_data\n"); | ||
437 | return -EINVAL; | ||
438 | } | ||
439 | |||
280 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 440 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
281 | info->regs = devm_ioremap_resource(&pdev->dev, mem); | 441 | info->regs = devm_ioremap_resource(&pdev->dev, mem); |
282 | if (IS_ERR(info->regs)) | 442 | if (IS_ERR(info->regs)) |
@@ -294,6 +454,7 @@ static int exynos_adc_probe(struct platform_device *pdev) | |||
294 | } | 454 | } |
295 | 455 | ||
296 | info->irq = irq; | 456 | info->irq = irq; |
457 | info->dev = &pdev->dev; | ||
297 | 458 | ||
298 | init_completion(&info->completion); | 459 | init_completion(&info->completion); |
299 | 460 | ||
@@ -304,6 +465,16 @@ static int exynos_adc_probe(struct platform_device *pdev) | |||
304 | return PTR_ERR(info->clk); | 465 | return PTR_ERR(info->clk); |
305 | } | 466 | } |
306 | 467 | ||
468 | if (info->data->needs_sclk) { | ||
469 | info->sclk = devm_clk_get(&pdev->dev, "sclk"); | ||
470 | if (IS_ERR(info->sclk)) { | ||
471 | dev_err(&pdev->dev, | ||
472 | "failed getting sclk clock, err = %ld\n", | ||
473 | PTR_ERR(info->sclk)); | ||
474 | return PTR_ERR(info->sclk); | ||
475 | } | ||
476 | } | ||
477 | |||
307 | info->vdd = devm_regulator_get(&pdev->dev, "vdd"); | 478 | info->vdd = devm_regulator_get(&pdev->dev, "vdd"); |
308 | if (IS_ERR(info->vdd)) { | 479 | if (IS_ERR(info->vdd)) { |
309 | dev_err(&pdev->dev, "failed getting regulator, err = %ld\n", | 480 | dev_err(&pdev->dev, "failed getting regulator, err = %ld\n", |
@@ -315,13 +486,13 @@ static int exynos_adc_probe(struct platform_device *pdev) | |||
315 | if (ret) | 486 | if (ret) |
316 | return ret; | 487 | return ret; |
317 | 488 | ||
318 | ret = clk_prepare_enable(info->clk); | 489 | ret = exynos_adc_prepare_clk(info); |
319 | if (ret) | 490 | if (ret) |
320 | goto err_disable_reg; | 491 | goto err_disable_reg; |
321 | 492 | ||
322 | writel(1, info->enable_reg); | 493 | ret = exynos_adc_enable_clk(info); |
323 | 494 | if (ret) | |
324 | info->version = exynos_adc_get_version(pdev); | 495 | goto err_unprepare_clk; |
325 | 496 | ||
326 | platform_set_drvdata(pdev, indio_dev); | 497 | platform_set_drvdata(pdev, indio_dev); |
327 | 498 | ||
@@ -331,11 +502,7 @@ static int exynos_adc_probe(struct platform_device *pdev) | |||
331 | indio_dev->info = &exynos_adc_iio_info; | 502 | indio_dev->info = &exynos_adc_iio_info; |
332 | indio_dev->modes = INDIO_DIRECT_MODE; | 503 | indio_dev->modes = INDIO_DIRECT_MODE; |
333 | indio_dev->channels = exynos_adc_iio_channels; | 504 | indio_dev->channels = exynos_adc_iio_channels; |
334 | 505 | indio_dev->num_channels = info->data->num_channels; | |
335 | if (info->version == ADC_V1) | ||
336 | indio_dev->num_channels = MAX_ADC_V1_CHANNELS; | ||
337 | else | ||
338 | indio_dev->num_channels = MAX_ADC_V2_CHANNELS; | ||
339 | 506 | ||
340 | ret = request_irq(info->irq, exynos_adc_isr, | 507 | ret = request_irq(info->irq, exynos_adc_isr, |
341 | 0, dev_name(&pdev->dev), info); | 508 | 0, dev_name(&pdev->dev), info); |
@@ -349,7 +516,8 @@ static int exynos_adc_probe(struct platform_device *pdev) | |||
349 | if (ret) | 516 | if (ret) |
350 | goto err_irq; | 517 | goto err_irq; |
351 | 518 | ||
352 | exynos_adc_hw_init(info); | 519 | if (info->data->init_hw) |
520 | info->data->init_hw(info); | ||
353 | 521 | ||
354 | ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev); | 522 | ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev); |
355 | if (ret < 0) { | 523 | if (ret < 0) { |
@@ -366,8 +534,11 @@ err_of_populate: | |||
366 | err_irq: | 534 | err_irq: |
367 | free_irq(info->irq, info); | 535 | free_irq(info->irq, info); |
368 | err_disable_clk: | 536 | err_disable_clk: |
369 | writel(0, info->enable_reg); | 537 | if (info->data->exit_hw) |
370 | clk_disable_unprepare(info->clk); | 538 | info->data->exit_hw(info); |
539 | exynos_adc_disable_clk(info); | ||
540 | err_unprepare_clk: | ||
541 | exynos_adc_unprepare_clk(info); | ||
371 | err_disable_reg: | 542 | err_disable_reg: |
372 | regulator_disable(info->vdd); | 543 | regulator_disable(info->vdd); |
373 | return ret; | 544 | return ret; |
@@ -382,8 +553,10 @@ static int exynos_adc_remove(struct platform_device *pdev) | |||
382 | exynos_adc_remove_devices); | 553 | exynos_adc_remove_devices); |
383 | iio_device_unregister(indio_dev); | 554 | iio_device_unregister(indio_dev); |
384 | free_irq(info->irq, info); | 555 | free_irq(info->irq, info); |
385 | writel(0, info->enable_reg); | 556 | if (info->data->exit_hw) |
386 | clk_disable_unprepare(info->clk); | 557 | info->data->exit_hw(info); |
558 | exynos_adc_disable_clk(info); | ||
559 | exynos_adc_unprepare_clk(info); | ||
387 | regulator_disable(info->vdd); | 560 | regulator_disable(info->vdd); |
388 | 561 | ||
389 | return 0; | 562 | return 0; |
@@ -394,20 +567,10 @@ static int exynos_adc_suspend(struct device *dev) | |||
394 | { | 567 | { |
395 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | 568 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
396 | struct exynos_adc *info = iio_priv(indio_dev); | 569 | struct exynos_adc *info = iio_priv(indio_dev); |
397 | u32 con; | ||
398 | 570 | ||
399 | if (info->version == ADC_V2) { | 571 | if (info->data->exit_hw) |
400 | con = readl(ADC_V2_CON1(info->regs)); | 572 | info->data->exit_hw(info); |
401 | con &= ~ADC_CON_EN_START; | 573 | exynos_adc_disable_clk(info); |
402 | writel(con, ADC_V2_CON1(info->regs)); | ||
403 | } else { | ||
404 | con = readl(ADC_V1_CON(info->regs)); | ||
405 | con |= ADC_V1_CON_STANDBY; | ||
406 | writel(con, ADC_V1_CON(info->regs)); | ||
407 | } | ||
408 | |||
409 | writel(0, info->enable_reg); | ||
410 | clk_disable_unprepare(info->clk); | ||
411 | regulator_disable(info->vdd); | 574 | regulator_disable(info->vdd); |
412 | 575 | ||
413 | return 0; | 576 | return 0; |
@@ -423,12 +586,12 @@ static int exynos_adc_resume(struct device *dev) | |||
423 | if (ret) | 586 | if (ret) |
424 | return ret; | 587 | return ret; |
425 | 588 | ||
426 | ret = clk_prepare_enable(info->clk); | 589 | ret = exynos_adc_enable_clk(info); |
427 | if (ret) | 590 | if (ret) |
428 | return ret; | 591 | return ret; |
429 | 592 | ||
430 | writel(1, info->enable_reg); | 593 | if (info->data->init_hw) |
431 | exynos_adc_hw_init(info); | 594 | info->data->init_hw(info); |
432 | 595 | ||
433 | return 0; | 596 | return 0; |
434 | } | 597 | } |
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 4b1f375c5659..af3e76d652ba 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c | |||
@@ -87,6 +87,10 @@ static const char * const iio_modifier_names[] = { | |||
87 | [IIO_MOD_QUATERNION] = "quaternion", | 87 | [IIO_MOD_QUATERNION] = "quaternion", |
88 | [IIO_MOD_TEMP_AMBIENT] = "ambient", | 88 | [IIO_MOD_TEMP_AMBIENT] = "ambient", |
89 | [IIO_MOD_TEMP_OBJECT] = "object", | 89 | [IIO_MOD_TEMP_OBJECT] = "object", |
90 | [IIO_MOD_NORTH_MAGN] = "from_north_magnetic", | ||
91 | [IIO_MOD_NORTH_TRUE] = "from_north_true", | ||
92 | [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp", | ||
93 | [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp", | ||
90 | }; | 94 | }; |
91 | 95 | ||
92 | /* relies on pairs of these shared then separate */ | 96 | /* relies on pairs of these shared then separate */ |
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index b2b0937d5133..3ec777a8f64e 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c | |||
@@ -35,6 +35,10 @@ enum magn_3d_channel { | |||
35 | CHANNEL_SCAN_INDEX_X, | 35 | CHANNEL_SCAN_INDEX_X, |
36 | CHANNEL_SCAN_INDEX_Y, | 36 | CHANNEL_SCAN_INDEX_Y, |
37 | CHANNEL_SCAN_INDEX_Z, | 37 | CHANNEL_SCAN_INDEX_Z, |
38 | CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP, | ||
39 | CHANNEL_SCAN_INDEX_NORTH_TRUE_TILT_COMP, | ||
40 | CHANNEL_SCAN_INDEX_NORTH_MAGN, | ||
41 | CHANNEL_SCAN_INDEX_NORTH_TRUE, | ||
38 | MAGN_3D_CHANNEL_MAX, | 42 | MAGN_3D_CHANNEL_MAX, |
39 | }; | 43 | }; |
40 | 44 | ||
@@ -42,7 +46,12 @@ struct magn_3d_state { | |||
42 | struct hid_sensor_hub_callbacks callbacks; | 46 | struct hid_sensor_hub_callbacks callbacks; |
43 | struct hid_sensor_common common_attributes; | 47 | struct hid_sensor_common common_attributes; |
44 | struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX]; | 48 | struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX]; |
45 | u32 magn_val[MAGN_3D_CHANNEL_MAX]; | 49 | |
50 | /* dynamically sized array to hold sensor values */ | ||
51 | u32 *iio_vals; | ||
52 | /* array of pointers to sensor value */ | ||
53 | u32 *magn_val_addr[MAGN_3D_CHANNEL_MAX]; | ||
54 | |||
46 | int scale_pre_decml; | 55 | int scale_pre_decml; |
47 | int scale_post_decml; | 56 | int scale_post_decml; |
48 | int scale_precision; | 57 | int scale_precision; |
@@ -52,7 +61,11 @@ struct magn_3d_state { | |||
52 | static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = { | 61 | static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = { |
53 | HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS, | 62 | HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS, |
54 | HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS, | 63 | HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS, |
55 | HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS | 64 | HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS, |
65 | HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH, | ||
66 | HID_USAGE_SENSOR_ORIENT_COMP_TRUE_NORTH, | ||
67 | HID_USAGE_SENSOR_ORIENT_MAGN_NORTH, | ||
68 | HID_USAGE_SENSOR_ORIENT_TRUE_NORTH, | ||
56 | }; | 69 | }; |
57 | 70 | ||
58 | /* Channel definitions */ | 71 | /* Channel definitions */ |
@@ -66,7 +79,6 @@ static const struct iio_chan_spec magn_3d_channels[] = { | |||
66 | BIT(IIO_CHAN_INFO_SCALE) | | 79 | BIT(IIO_CHAN_INFO_SCALE) | |
67 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 80 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
68 | BIT(IIO_CHAN_INFO_HYSTERESIS), | 81 | BIT(IIO_CHAN_INFO_HYSTERESIS), |
69 | .scan_index = CHANNEL_SCAN_INDEX_X, | ||
70 | }, { | 82 | }, { |
71 | .type = IIO_MAGN, | 83 | .type = IIO_MAGN, |
72 | .modified = 1, | 84 | .modified = 1, |
@@ -76,7 +88,6 @@ static const struct iio_chan_spec magn_3d_channels[] = { | |||
76 | BIT(IIO_CHAN_INFO_SCALE) | | 88 | BIT(IIO_CHAN_INFO_SCALE) | |
77 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 89 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
78 | BIT(IIO_CHAN_INFO_HYSTERESIS), | 90 | BIT(IIO_CHAN_INFO_HYSTERESIS), |
79 | .scan_index = CHANNEL_SCAN_INDEX_Y, | ||
80 | }, { | 91 | }, { |
81 | .type = IIO_MAGN, | 92 | .type = IIO_MAGN, |
82 | .modified = 1, | 93 | .modified = 1, |
@@ -86,7 +97,42 @@ static const struct iio_chan_spec magn_3d_channels[] = { | |||
86 | BIT(IIO_CHAN_INFO_SCALE) | | 97 | BIT(IIO_CHAN_INFO_SCALE) | |
87 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 98 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
88 | BIT(IIO_CHAN_INFO_HYSTERESIS), | 99 | BIT(IIO_CHAN_INFO_HYSTERESIS), |
89 | .scan_index = CHANNEL_SCAN_INDEX_Z, | 100 | }, { |
101 | .type = IIO_ROT, | ||
102 | .modified = 1, | ||
103 | .channel2 = IIO_MOD_NORTH_MAGN_TILT_COMP, | ||
104 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
105 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | ||
106 | BIT(IIO_CHAN_INFO_SCALE) | | ||
107 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | ||
108 | BIT(IIO_CHAN_INFO_HYSTERESIS), | ||
109 | }, { | ||
110 | .type = IIO_ROT, | ||
111 | .modified = 1, | ||
112 | .channel2 = IIO_MOD_NORTH_TRUE_TILT_COMP, | ||
113 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
114 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | ||
115 | BIT(IIO_CHAN_INFO_SCALE) | | ||
116 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | ||
117 | BIT(IIO_CHAN_INFO_HYSTERESIS), | ||
118 | }, { | ||
119 | .type = IIO_ROT, | ||
120 | .modified = 1, | ||
121 | .channel2 = IIO_MOD_NORTH_MAGN, | ||
122 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
123 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | ||
124 | BIT(IIO_CHAN_INFO_SCALE) | | ||
125 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | ||
126 | BIT(IIO_CHAN_INFO_HYSTERESIS), | ||
127 | }, { | ||
128 | .type = IIO_ROT, | ||
129 | .modified = 1, | ||
130 | .channel2 = IIO_MOD_NORTH_TRUE, | ||
131 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
132 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | ||
133 | BIT(IIO_CHAN_INFO_SCALE) | | ||
134 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | ||
135 | BIT(IIO_CHAN_INFO_HYSTERESIS), | ||
90 | } | 136 | } |
91 | }; | 137 | }; |
92 | 138 | ||
@@ -126,8 +172,8 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev, | |||
126 | msleep_interruptible(poll_value * 2); | 172 | msleep_interruptible(poll_value * 2); |
127 | 173 | ||
128 | report_id = | 174 | report_id = |
129 | magn_state->magn[chan->scan_index].report_id; | 175 | magn_state->magn[chan->address].report_id; |
130 | address = magn_3d_addresses[chan->scan_index]; | 176 | address = magn_3d_addresses[chan->address]; |
131 | if (report_id >= 0) | 177 | if (report_id >= 0) |
132 | *val = sensor_hub_input_attr_get_raw_value( | 178 | *val = sensor_hub_input_attr_get_raw_value( |
133 | magn_state->common_attributes.hsdev, | 179 | magn_state->common_attributes.hsdev, |
@@ -218,8 +264,8 @@ static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev, | |||
218 | dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n"); | 264 | dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n"); |
219 | if (atomic_read(&magn_state->common_attributes.data_ready)) | 265 | if (atomic_read(&magn_state->common_attributes.data_ready)) |
220 | hid_sensor_push_data(indio_dev, | 266 | hid_sensor_push_data(indio_dev, |
221 | magn_state->magn_val, | 267 | magn_state->iio_vals, |
222 | sizeof(magn_state->magn_val)); | 268 | sizeof(magn_state->iio_vals)); |
223 | 269 | ||
224 | return 0; | 270 | return 0; |
225 | } | 271 | } |
@@ -233,52 +279,126 @@ static int magn_3d_capture_sample(struct hid_sensor_hub_device *hsdev, | |||
233 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | 279 | struct iio_dev *indio_dev = platform_get_drvdata(priv); |
234 | struct magn_3d_state *magn_state = iio_priv(indio_dev); | 280 | struct magn_3d_state *magn_state = iio_priv(indio_dev); |
235 | int offset; | 281 | int offset; |
236 | int ret = -EINVAL; | 282 | int ret = 0; |
283 | u32 *iio_val = NULL; | ||
237 | 284 | ||
238 | switch (usage_id) { | 285 | switch (usage_id) { |
239 | case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS: | 286 | case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS: |
240 | case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS: | 287 | case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS: |
241 | case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS: | 288 | case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS: |
242 | offset = usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS; | 289 | offset = (usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS) |
243 | magn_state->magn_val[CHANNEL_SCAN_INDEX_X + offset] = | 290 | + CHANNEL_SCAN_INDEX_X; |
244 | *(u32 *)raw_data; | 291 | break; |
245 | ret = 0; | 292 | case HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH: |
293 | case HID_USAGE_SENSOR_ORIENT_COMP_TRUE_NORTH: | ||
294 | case HID_USAGE_SENSOR_ORIENT_MAGN_NORTH: | ||
295 | case HID_USAGE_SENSOR_ORIENT_TRUE_NORTH: | ||
296 | offset = (usage_id - HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH) | ||
297 | + CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP; | ||
246 | break; | 298 | break; |
247 | default: | 299 | default: |
248 | break; | 300 | return -EINVAL; |
249 | } | 301 | } |
250 | 302 | ||
303 | iio_val = magn_state->magn_val_addr[offset]; | ||
304 | |||
305 | if (iio_val != NULL) | ||
306 | *iio_val = *((u32 *)raw_data); | ||
307 | else | ||
308 | ret = -EINVAL; | ||
309 | |||
251 | return ret; | 310 | return ret; |
252 | } | 311 | } |
253 | 312 | ||
254 | /* Parse report which is specific to an usage id*/ | 313 | /* Parse report which is specific to an usage id*/ |
255 | static int magn_3d_parse_report(struct platform_device *pdev, | 314 | static int magn_3d_parse_report(struct platform_device *pdev, |
256 | struct hid_sensor_hub_device *hsdev, | 315 | struct hid_sensor_hub_device *hsdev, |
257 | struct iio_chan_spec *channels, | 316 | struct iio_chan_spec **channels, |
317 | int *chan_count, | ||
258 | unsigned usage_id, | 318 | unsigned usage_id, |
259 | struct magn_3d_state *st) | 319 | struct magn_3d_state *st) |
260 | { | 320 | { |
261 | int ret; | ||
262 | int i; | 321 | int i; |
322 | int attr_count = 0; | ||
323 | struct iio_chan_spec *_channels; | ||
324 | |||
325 | /* Scan for each usage attribute supported */ | ||
326 | for (i = 0; i < MAGN_3D_CHANNEL_MAX; i++) { | ||
327 | int status; | ||
328 | u32 address = magn_3d_addresses[i]; | ||
329 | |||
330 | /* Check if usage attribute exists in the sensor hub device */ | ||
331 | status = sensor_hub_input_get_attribute_info(hsdev, | ||
332 | HID_INPUT_REPORT, | ||
333 | usage_id, | ||
334 | address, | ||
335 | &(st->magn[i])); | ||
336 | if (!status) | ||
337 | attr_count++; | ||
338 | } | ||
263 | 339 | ||
264 | for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) { | 340 | if (attr_count <= 0) { |
265 | ret = sensor_hub_input_get_attribute_info(hsdev, | 341 | dev_err(&pdev->dev, |
266 | HID_INPUT_REPORT, | 342 | "failed to find any supported usage attributes in report\n"); |
267 | usage_id, | 343 | return -EINVAL; |
268 | HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS + i, | ||
269 | &st->magn[CHANNEL_SCAN_INDEX_X + i]); | ||
270 | if (ret < 0) | ||
271 | break; | ||
272 | magn_3d_adjust_channel_bit_mask(channels, | ||
273 | CHANNEL_SCAN_INDEX_X + i, | ||
274 | st->magn[CHANNEL_SCAN_INDEX_X + i].size); | ||
275 | } | 344 | } |
276 | dev_dbg(&pdev->dev, "magn_3d %x:%x, %x:%x, %x:%x\n", | 345 | |
346 | dev_dbg(&pdev->dev, "magn_3d Found %d usage attributes\n", | ||
347 | attr_count); | ||
348 | dev_dbg(&pdev->dev, "magn_3d X: %x:%x Y: %x:%x Z: %x:%x\n", | ||
277 | st->magn[0].index, | 349 | st->magn[0].index, |
278 | st->magn[0].report_id, | 350 | st->magn[0].report_id, |
279 | st->magn[1].index, st->magn[1].report_id, | 351 | st->magn[1].index, st->magn[1].report_id, |
280 | st->magn[2].index, st->magn[2].report_id); | 352 | st->magn[2].index, st->magn[2].report_id); |
281 | 353 | ||
354 | /* Setup IIO channel array */ | ||
355 | _channels = devm_kcalloc(&pdev->dev, attr_count, | ||
356 | sizeof(struct iio_chan_spec), | ||
357 | GFP_KERNEL); | ||
358 | if (!_channels) { | ||
359 | dev_err(&pdev->dev, | ||
360 | "failed to allocate space for iio channels\n"); | ||
361 | return -ENOMEM; | ||
362 | } | ||
363 | |||
364 | st->iio_vals = devm_kcalloc(&pdev->dev, attr_count, | ||
365 | sizeof(u32), | ||
366 | GFP_KERNEL); | ||
367 | if (!st->iio_vals) { | ||
368 | dev_err(&pdev->dev, | ||
369 | "failed to allocate space for iio values array\n"); | ||
370 | return -ENOMEM; | ||
371 | } | ||
372 | |||
373 | for (i = 0, *chan_count = 0; | ||
374 | i < MAGN_3D_CHANNEL_MAX && *chan_count < attr_count; | ||
375 | i++){ | ||
376 | if (st->magn[i].index >= 0) { | ||
377 | /* Setup IIO channel struct */ | ||
378 | (_channels[*chan_count]) = magn_3d_channels[i]; | ||
379 | (_channels[*chan_count]).scan_index = *chan_count; | ||
380 | (_channels[*chan_count]).address = i; | ||
381 | |||
382 | /* Set magn_val_addr to iio value address */ | ||
383 | st->magn_val_addr[i] = &(st->iio_vals[*chan_count]); | ||
384 | magn_3d_adjust_channel_bit_mask(_channels, | ||
385 | *chan_count, | ||
386 | st->magn[i].size); | ||
387 | (*chan_count)++; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | if (*chan_count <= 0) { | ||
392 | dev_err(&pdev->dev, | ||
393 | "failed to find any magnetic channels setup\n"); | ||
394 | return -EINVAL; | ||
395 | } | ||
396 | |||
397 | *channels = _channels; | ||
398 | |||
399 | dev_dbg(&pdev->dev, "magn_3d Setup %d IIO channels\n", | ||
400 | *chan_count); | ||
401 | |||
282 | st->scale_precision = hid_sensor_format_scale( | 402 | st->scale_precision = hid_sensor_format_scale( |
283 | HID_USAGE_SENSOR_COMPASS_3D, | 403 | HID_USAGE_SENSOR_COMPASS_3D, |
284 | &st->magn[CHANNEL_SCAN_INDEX_X], | 404 | &st->magn[CHANNEL_SCAN_INDEX_X], |
@@ -296,7 +416,7 @@ static int magn_3d_parse_report(struct platform_device *pdev, | |||
296 | st->common_attributes.sensitivity.report_id); | 416 | st->common_attributes.sensitivity.report_id); |
297 | } | 417 | } |
298 | 418 | ||
299 | return ret; | 419 | return 0; |
300 | } | 420 | } |
301 | 421 | ||
302 | /* Function to initialize the processing for usage id */ | 422 | /* Function to initialize the processing for usage id */ |
@@ -308,6 +428,7 @@ static int hid_magn_3d_probe(struct platform_device *pdev) | |||
308 | struct magn_3d_state *magn_state; | 428 | struct magn_3d_state *magn_state; |
309 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 429 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
310 | struct iio_chan_spec *channels; | 430 | struct iio_chan_spec *channels; |
431 | int chan_count = 0; | ||
311 | 432 | ||
312 | indio_dev = devm_iio_device_alloc(&pdev->dev, | 433 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
313 | sizeof(struct magn_3d_state)); | 434 | sizeof(struct magn_3d_state)); |
@@ -328,22 +449,16 @@ static int hid_magn_3d_probe(struct platform_device *pdev) | |||
328 | return ret; | 449 | return ret; |
329 | } | 450 | } |
330 | 451 | ||
331 | channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels), | 452 | ret = magn_3d_parse_report(pdev, hsdev, |
332 | GFP_KERNEL); | 453 | &channels, &chan_count, |
333 | if (!channels) { | ||
334 | dev_err(&pdev->dev, "failed to duplicate channels\n"); | ||
335 | return -ENOMEM; | ||
336 | } | ||
337 | |||
338 | ret = magn_3d_parse_report(pdev, hsdev, channels, | ||
339 | HID_USAGE_SENSOR_COMPASS_3D, magn_state); | 454 | HID_USAGE_SENSOR_COMPASS_3D, magn_state); |
340 | if (ret) { | 455 | if (ret) { |
341 | dev_err(&pdev->dev, "failed to setup attributes\n"); | 456 | dev_err(&pdev->dev, "failed to parse report\n"); |
342 | goto error_free_dev_mem; | 457 | return ret; |
343 | } | 458 | } |
344 | 459 | ||
345 | indio_dev->channels = channels; | 460 | indio_dev->channels = channels; |
346 | indio_dev->num_channels = ARRAY_SIZE(magn_3d_channels); | 461 | indio_dev->num_channels = chan_count; |
347 | indio_dev->dev.parent = &pdev->dev; | 462 | indio_dev->dev.parent = &pdev->dev; |
348 | indio_dev->info = &magn_3d_info; | 463 | indio_dev->info = &magn_3d_info; |
349 | indio_dev->name = name; | 464 | indio_dev->name = name; |
@@ -353,7 +468,7 @@ static int hid_magn_3d_probe(struct platform_device *pdev) | |||
353 | NULL, NULL); | 468 | NULL, NULL); |
354 | if (ret) { | 469 | if (ret) { |
355 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | 470 | dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); |
356 | goto error_free_dev_mem; | 471 | return ret; |
357 | } | 472 | } |
358 | atomic_set(&magn_state->common_attributes.data_ready, 0); | 473 | atomic_set(&magn_state->common_attributes.data_ready, 0); |
359 | ret = hid_sensor_setup_trigger(indio_dev, name, | 474 | ret = hid_sensor_setup_trigger(indio_dev, name, |
@@ -387,8 +502,6 @@ error_remove_trigger: | |||
387 | hid_sensor_remove_trigger(&magn_state->common_attributes); | 502 | hid_sensor_remove_trigger(&magn_state->common_attributes); |
388 | error_unreg_buffer_funcs: | 503 | error_unreg_buffer_funcs: |
389 | iio_triggered_buffer_cleanup(indio_dev); | 504 | iio_triggered_buffer_cleanup(indio_dev); |
390 | error_free_dev_mem: | ||
391 | kfree(indio_dev->channels); | ||
392 | return ret; | 505 | return ret; |
393 | } | 506 | } |
394 | 507 | ||
@@ -403,7 +516,6 @@ static int hid_magn_3d_remove(struct platform_device *pdev) | |||
403 | iio_device_unregister(indio_dev); | 516 | iio_device_unregister(indio_dev); |
404 | hid_sensor_remove_trigger(&magn_state->common_attributes); | 517 | hid_sensor_remove_trigger(&magn_state->common_attributes); |
405 | iio_triggered_buffer_cleanup(indio_dev); | 518 | iio_triggered_buffer_cleanup(indio_dev); |
406 | kfree(indio_dev->channels); | ||
407 | 519 | ||
408 | return 0; | 520 | return 0; |
409 | } | 521 | } |