1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * mag3110.c - Support for Freescale MAG3110 magnetometer sensor |
4 | * |
5 | * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net> |
6 | * |
7 | * (7-bit I2C slave address 0x0e) |
8 | * |
9 | * TODO: irq, user offset, oversampling, continuous mode |
10 | */ |
11 | |
12 | #include <linux/module.h> |
13 | #include <linux/i2c.h> |
14 | #include <linux/iio/iio.h> |
15 | #include <linux/iio/sysfs.h> |
16 | #include <linux/iio/trigger_consumer.h> |
17 | #include <linux/iio/buffer.h> |
18 | #include <linux/iio/triggered_buffer.h> |
19 | #include <linux/delay.h> |
20 | #include <linux/regulator/consumer.h> |
21 | |
22 | #define MAG3110_STATUS 0x00 |
23 | #define MAG3110_OUT_X 0x01 /* MSB first */ |
24 | #define MAG3110_OUT_Y 0x03 |
25 | #define MAG3110_OUT_Z 0x05 |
26 | #define MAG3110_WHO_AM_I 0x07 |
27 | #define MAG3110_SYSMOD 0x08 |
28 | #define MAG3110_OFF_X 0x09 /* MSB first */ |
29 | #define MAG3110_OFF_Y 0x0b |
30 | #define MAG3110_OFF_Z 0x0d |
31 | #define MAG3110_DIE_TEMP 0x0f |
32 | #define MAG3110_CTRL_REG1 0x10 |
33 | #define MAG3110_CTRL_REG2 0x11 |
34 | |
35 | #define MAG3110_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) |
36 | |
37 | #define MAG3110_CTRL_DR_MASK (BIT(7) | BIT(6) | BIT(5)) |
38 | #define MAG3110_CTRL_DR_SHIFT 5 |
39 | #define MAG3110_CTRL_DR_DEFAULT 0 |
40 | |
41 | #define MAG3110_SYSMOD_MODE_MASK GENMASK(1, 0) |
42 | |
43 | #define MAG3110_CTRL_TM BIT(1) /* trigger single measurement */ |
44 | #define MAG3110_CTRL_AC BIT(0) /* continuous measurements */ |
45 | |
46 | #define MAG3110_CTRL_AUTO_MRST_EN BIT(7) /* magnetic auto-reset */ |
47 | #define MAG3110_CTRL_RAW BIT(5) /* measurements not user-offset corrected */ |
48 | |
49 | #define MAG3110_DEVICE_ID 0xc4 |
50 | |
51 | /* Each client has this additional data */ |
52 | struct mag3110_data { |
53 | struct i2c_client *client; |
54 | struct mutex lock; |
55 | u8 ctrl_reg1; |
56 | int sleep_val; |
57 | struct regulator *vdd_reg; |
58 | struct regulator *vddio_reg; |
59 | /* Ensure natural alignment of timestamp */ |
60 | struct { |
61 | __be16 channels[3]; |
62 | u8 temperature; |
63 | s64 ts __aligned(8); |
64 | } scan; |
65 | }; |
66 | |
67 | static int mag3110_request(struct mag3110_data *data) |
68 | { |
69 | int ret, tries = 150; |
70 | |
71 | if ((data->ctrl_reg1 & MAG3110_CTRL_AC) == 0) { |
72 | /* trigger measurement */ |
73 | ret = i2c_smbus_write_byte_data(client: data->client, MAG3110_CTRL_REG1, |
74 | value: data->ctrl_reg1 | MAG3110_CTRL_TM); |
75 | if (ret < 0) |
76 | return ret; |
77 | } |
78 | |
79 | while (tries-- > 0) { |
80 | ret = i2c_smbus_read_byte_data(client: data->client, MAG3110_STATUS); |
81 | if (ret < 0) |
82 | return ret; |
83 | /* wait for data ready */ |
84 | if ((ret & MAG3110_STATUS_DRDY) == MAG3110_STATUS_DRDY) |
85 | break; |
86 | |
87 | if (data->sleep_val <= 20) |
88 | usleep_range(min: data->sleep_val * 250, max: data->sleep_val * 500); |
89 | else |
90 | msleep(msecs: 20); |
91 | } |
92 | |
93 | if (tries < 0) { |
94 | dev_err(&data->client->dev, "data not ready\n" ); |
95 | return -EIO; |
96 | } |
97 | |
98 | return 0; |
99 | } |
100 | |
101 | static int mag3110_read(struct mag3110_data *data, __be16 buf[3]) |
102 | { |
103 | int ret; |
104 | |
105 | mutex_lock(&data->lock); |
106 | ret = mag3110_request(data); |
107 | if (ret < 0) { |
108 | mutex_unlock(lock: &data->lock); |
109 | return ret; |
110 | } |
111 | ret = i2c_smbus_read_i2c_block_data(client: data->client, |
112 | MAG3110_OUT_X, length: 3 * sizeof(__be16), values: (u8 *) buf); |
113 | mutex_unlock(lock: &data->lock); |
114 | |
115 | return ret; |
116 | } |
117 | |
118 | static ssize_t mag3110_show_int_plus_micros(char *buf, |
119 | const int (*vals)[2], int n) |
120 | { |
121 | size_t len = 0; |
122 | |
123 | while (n-- > 0) |
124 | len += scnprintf(buf: buf + len, PAGE_SIZE - len, |
125 | fmt: "%d.%06d " , vals[n][0], vals[n][1]); |
126 | |
127 | /* replace trailing space by newline */ |
128 | buf[len - 1] = '\n'; |
129 | |
130 | return len; |
131 | } |
132 | |
133 | static int mag3110_get_int_plus_micros_index(const int (*vals)[2], int n, |
134 | int val, int val2) |
135 | { |
136 | while (n-- > 0) |
137 | if (val == vals[n][0] && val2 == vals[n][1]) |
138 | return n; |
139 | |
140 | return -EINVAL; |
141 | } |
142 | |
143 | static const int mag3110_samp_freq[8][2] = { |
144 | {80, 0}, {40, 0}, {20, 0}, {10, 0}, {5, 0}, {2, 500000}, |
145 | {1, 250000}, {0, 625000} |
146 | }; |
147 | |
148 | static ssize_t mag3110_show_samp_freq_avail(struct device *dev, |
149 | struct device_attribute *attr, char *buf) |
150 | { |
151 | return mag3110_show_int_plus_micros(buf, vals: mag3110_samp_freq, n: 8); |
152 | } |
153 | |
154 | static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mag3110_show_samp_freq_avail); |
155 | |
156 | static int mag3110_get_samp_freq_index(struct mag3110_data *data, |
157 | int val, int val2) |
158 | { |
159 | return mag3110_get_int_plus_micros_index(vals: mag3110_samp_freq, n: 8, val, |
160 | val2); |
161 | } |
162 | |
163 | static int mag3110_calculate_sleep(struct mag3110_data *data) |
164 | { |
165 | int ret, i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT; |
166 | |
167 | if (mag3110_samp_freq[i][0] > 0) |
168 | ret = 1000 / mag3110_samp_freq[i][0]; |
169 | else |
170 | ret = 1000; |
171 | |
172 | return ret == 0 ? 1 : ret; |
173 | } |
174 | |
175 | static int mag3110_standby(struct mag3110_data *data) |
176 | { |
177 | return i2c_smbus_write_byte_data(client: data->client, MAG3110_CTRL_REG1, |
178 | value: data->ctrl_reg1 & ~MAG3110_CTRL_AC); |
179 | } |
180 | |
181 | static int mag3110_wait_standby(struct mag3110_data *data) |
182 | { |
183 | int ret, tries = 30; |
184 | |
185 | /* |
186 | * Takes up to 1/ODR to come out of active mode into stby |
187 | * Longest expected period is 12.5seconds. |
188 | * We'll sleep for 500ms between checks |
189 | */ |
190 | while (tries-- > 0) { |
191 | ret = i2c_smbus_read_byte_data(client: data->client, MAG3110_SYSMOD); |
192 | if (ret < 0) { |
193 | dev_err(&data->client->dev, "i2c error\n" ); |
194 | return ret; |
195 | } |
196 | /* wait for standby */ |
197 | if ((ret & MAG3110_SYSMOD_MODE_MASK) == 0) |
198 | break; |
199 | |
200 | msleep_interruptible(msecs: 500); |
201 | } |
202 | |
203 | if (tries < 0) { |
204 | dev_err(&data->client->dev, "device not entering standby mode\n" ); |
205 | return -EIO; |
206 | } |
207 | |
208 | return 0; |
209 | } |
210 | |
211 | static int mag3110_active(struct mag3110_data *data) |
212 | { |
213 | return i2c_smbus_write_byte_data(client: data->client, MAG3110_CTRL_REG1, |
214 | value: data->ctrl_reg1); |
215 | } |
216 | |
217 | /* returns >0 if active, 0 if in standby and <0 on error */ |
218 | static int mag3110_is_active(struct mag3110_data *data) |
219 | { |
220 | int reg; |
221 | |
222 | reg = i2c_smbus_read_byte_data(client: data->client, MAG3110_CTRL_REG1); |
223 | if (reg < 0) |
224 | return reg; |
225 | |
226 | return reg & MAG3110_CTRL_AC; |
227 | } |
228 | |
229 | static int mag3110_change_config(struct mag3110_data *data, u8 reg, u8 val) |
230 | { |
231 | int ret; |
232 | int is_active; |
233 | |
234 | mutex_lock(&data->lock); |
235 | |
236 | is_active = mag3110_is_active(data); |
237 | if (is_active < 0) { |
238 | ret = is_active; |
239 | goto fail; |
240 | } |
241 | |
242 | /* config can only be changed when in standby */ |
243 | if (is_active > 0) { |
244 | ret = mag3110_standby(data); |
245 | if (ret < 0) |
246 | goto fail; |
247 | } |
248 | |
249 | /* |
250 | * After coming out of active we must wait for the part |
251 | * to transition to STBY. This can take up to 1 /ODR to occur |
252 | */ |
253 | ret = mag3110_wait_standby(data); |
254 | if (ret < 0) |
255 | goto fail; |
256 | |
257 | ret = i2c_smbus_write_byte_data(client: data->client, command: reg, value: val); |
258 | if (ret < 0) |
259 | goto fail; |
260 | |
261 | if (is_active > 0) { |
262 | ret = mag3110_active(data); |
263 | if (ret < 0) |
264 | goto fail; |
265 | } |
266 | |
267 | ret = 0; |
268 | fail: |
269 | mutex_unlock(lock: &data->lock); |
270 | |
271 | return ret; |
272 | } |
273 | |
274 | static int mag3110_read_raw(struct iio_dev *indio_dev, |
275 | struct iio_chan_spec const *chan, |
276 | int *val, int *val2, long mask) |
277 | { |
278 | struct mag3110_data *data = iio_priv(indio_dev); |
279 | __be16 buffer[3]; |
280 | int i, ret; |
281 | |
282 | switch (mask) { |
283 | case IIO_CHAN_INFO_RAW: |
284 | ret = iio_device_claim_direct_mode(indio_dev); |
285 | if (ret) |
286 | return ret; |
287 | |
288 | switch (chan->type) { |
289 | case IIO_MAGN: /* in 0.1 uT / LSB */ |
290 | ret = mag3110_read(data, buf: buffer); |
291 | if (ret < 0) |
292 | goto release; |
293 | *val = sign_extend32( |
294 | be16_to_cpu(buffer[chan->scan_index]), |
295 | index: chan->scan_type.realbits - 1); |
296 | ret = IIO_VAL_INT; |
297 | break; |
298 | case IIO_TEMP: /* in 1 C / LSB */ |
299 | mutex_lock(&data->lock); |
300 | ret = mag3110_request(data); |
301 | if (ret < 0) { |
302 | mutex_unlock(lock: &data->lock); |
303 | goto release; |
304 | } |
305 | ret = i2c_smbus_read_byte_data(client: data->client, |
306 | MAG3110_DIE_TEMP); |
307 | mutex_unlock(lock: &data->lock); |
308 | if (ret < 0) |
309 | goto release; |
310 | *val = sign_extend32(value: ret, |
311 | index: chan->scan_type.realbits - 1); |
312 | ret = IIO_VAL_INT; |
313 | break; |
314 | default: |
315 | ret = -EINVAL; |
316 | } |
317 | release: |
318 | iio_device_release_direct_mode(indio_dev); |
319 | return ret; |
320 | |
321 | case IIO_CHAN_INFO_SCALE: |
322 | switch (chan->type) { |
323 | case IIO_MAGN: |
324 | *val = 0; |
325 | *val2 = 1000; |
326 | return IIO_VAL_INT_PLUS_MICRO; |
327 | case IIO_TEMP: |
328 | *val = 1000; |
329 | return IIO_VAL_INT; |
330 | default: |
331 | return -EINVAL; |
332 | } |
333 | case IIO_CHAN_INFO_SAMP_FREQ: |
334 | i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT; |
335 | *val = mag3110_samp_freq[i][0]; |
336 | *val2 = mag3110_samp_freq[i][1]; |
337 | return IIO_VAL_INT_PLUS_MICRO; |
338 | case IIO_CHAN_INFO_CALIBBIAS: |
339 | ret = i2c_smbus_read_word_swapped(client: data->client, |
340 | MAG3110_OFF_X + 2 * chan->scan_index); |
341 | if (ret < 0) |
342 | return ret; |
343 | *val = sign_extend32(value: ret >> 1, index: 14); |
344 | return IIO_VAL_INT; |
345 | } |
346 | return -EINVAL; |
347 | } |
348 | |
349 | static int mag3110_write_raw(struct iio_dev *indio_dev, |
350 | struct iio_chan_spec const *chan, |
351 | int val, int val2, long mask) |
352 | { |
353 | struct mag3110_data *data = iio_priv(indio_dev); |
354 | int rate, ret; |
355 | |
356 | ret = iio_device_claim_direct_mode(indio_dev); |
357 | if (ret) |
358 | return ret; |
359 | |
360 | switch (mask) { |
361 | case IIO_CHAN_INFO_SAMP_FREQ: |
362 | rate = mag3110_get_samp_freq_index(data, val, val2); |
363 | if (rate < 0) { |
364 | ret = -EINVAL; |
365 | break; |
366 | } |
367 | data->ctrl_reg1 &= 0xff & ~MAG3110_CTRL_DR_MASK |
368 | & ~MAG3110_CTRL_AC; |
369 | data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT; |
370 | data->sleep_val = mag3110_calculate_sleep(data); |
371 | if (data->sleep_val < 40) |
372 | data->ctrl_reg1 |= MAG3110_CTRL_AC; |
373 | |
374 | ret = mag3110_change_config(data, MAG3110_CTRL_REG1, |
375 | val: data->ctrl_reg1); |
376 | break; |
377 | case IIO_CHAN_INFO_CALIBBIAS: |
378 | if (val < -10000 || val > 10000) { |
379 | ret = -EINVAL; |
380 | break; |
381 | } |
382 | ret = i2c_smbus_write_word_swapped(client: data->client, |
383 | MAG3110_OFF_X + 2 * chan->scan_index, value: val << 1); |
384 | break; |
385 | default: |
386 | ret = -EINVAL; |
387 | break; |
388 | } |
389 | iio_device_release_direct_mode(indio_dev); |
390 | return ret; |
391 | } |
392 | |
393 | static irqreturn_t mag3110_trigger_handler(int irq, void *p) |
394 | { |
395 | struct iio_poll_func *pf = p; |
396 | struct iio_dev *indio_dev = pf->indio_dev; |
397 | struct mag3110_data *data = iio_priv(indio_dev); |
398 | int ret; |
399 | |
400 | ret = mag3110_read(data, buf: data->scan.channels); |
401 | if (ret < 0) |
402 | goto done; |
403 | |
404 | if (test_bit(3, indio_dev->active_scan_mask)) { |
405 | ret = i2c_smbus_read_byte_data(client: data->client, |
406 | MAG3110_DIE_TEMP); |
407 | if (ret < 0) |
408 | goto done; |
409 | data->scan.temperature = ret; |
410 | } |
411 | |
412 | iio_push_to_buffers_with_timestamp(indio_dev, data: &data->scan, |
413 | timestamp: iio_get_time_ns(indio_dev)); |
414 | |
415 | done: |
416 | iio_trigger_notify_done(trig: indio_dev->trig); |
417 | return IRQ_HANDLED; |
418 | } |
419 | |
420 | #define MAG3110_CHANNEL(axis, idx) { \ |
421 | .type = IIO_MAGN, \ |
422 | .modified = 1, \ |
423 | .channel2 = IIO_MOD_##axis, \ |
424 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
425 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ |
426 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ |
427 | BIT(IIO_CHAN_INFO_SCALE), \ |
428 | .scan_index = idx, \ |
429 | .scan_type = { \ |
430 | .sign = 's', \ |
431 | .realbits = 16, \ |
432 | .storagebits = 16, \ |
433 | .endianness = IIO_BE, \ |
434 | }, \ |
435 | } |
436 | |
437 | static const struct iio_chan_spec mag3110_channels[] = { |
438 | MAG3110_CHANNEL(X, 0), |
439 | MAG3110_CHANNEL(Y, 1), |
440 | MAG3110_CHANNEL(Z, 2), |
441 | { |
442 | .type = IIO_TEMP, |
443 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
444 | BIT(IIO_CHAN_INFO_SCALE), |
445 | .scan_index = 3, |
446 | .scan_type = { |
447 | .sign = 's', |
448 | .realbits = 8, |
449 | .storagebits = 8, |
450 | }, |
451 | }, |
452 | IIO_CHAN_SOFT_TIMESTAMP(4), |
453 | }; |
454 | |
455 | static struct attribute *mag3110_attributes[] = { |
456 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, |
457 | NULL |
458 | }; |
459 | |
460 | static const struct attribute_group mag3110_group = { |
461 | .attrs = mag3110_attributes, |
462 | }; |
463 | |
464 | static const struct iio_info mag3110_info = { |
465 | .attrs = &mag3110_group, |
466 | .read_raw = &mag3110_read_raw, |
467 | .write_raw = &mag3110_write_raw, |
468 | }; |
469 | |
470 | static const unsigned long mag3110_scan_masks[] = {0x7, 0xf, 0}; |
471 | |
472 | static int mag3110_probe(struct i2c_client *client) |
473 | { |
474 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
475 | struct mag3110_data *data; |
476 | struct iio_dev *indio_dev; |
477 | int ret; |
478 | |
479 | indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*data)); |
480 | if (!indio_dev) |
481 | return -ENOMEM; |
482 | |
483 | data = iio_priv(indio_dev); |
484 | |
485 | data->vdd_reg = devm_regulator_get(dev: &client->dev, id: "vdd" ); |
486 | if (IS_ERR(ptr: data->vdd_reg)) |
487 | return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: data->vdd_reg), |
488 | fmt: "failed to get VDD regulator!\n" ); |
489 | |
490 | data->vddio_reg = devm_regulator_get(dev: &client->dev, id: "vddio" ); |
491 | if (IS_ERR(ptr: data->vddio_reg)) |
492 | return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: data->vddio_reg), |
493 | fmt: "failed to get VDDIO regulator!\n" ); |
494 | |
495 | ret = regulator_enable(regulator: data->vdd_reg); |
496 | if (ret) { |
497 | dev_err(&client->dev, "failed to enable VDD regulator!\n" ); |
498 | return ret; |
499 | } |
500 | |
501 | ret = regulator_enable(regulator: data->vddio_reg); |
502 | if (ret) { |
503 | dev_err(&client->dev, "failed to enable VDDIO regulator!\n" ); |
504 | goto disable_regulator_vdd; |
505 | } |
506 | |
507 | ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I); |
508 | if (ret < 0) |
509 | goto disable_regulators; |
510 | if (ret != MAG3110_DEVICE_ID) { |
511 | ret = -ENODEV; |
512 | goto disable_regulators; |
513 | } |
514 | |
515 | data->client = client; |
516 | mutex_init(&data->lock); |
517 | |
518 | i2c_set_clientdata(client, data: indio_dev); |
519 | indio_dev->info = &mag3110_info; |
520 | indio_dev->name = id->name; |
521 | indio_dev->modes = INDIO_DIRECT_MODE; |
522 | indio_dev->channels = mag3110_channels; |
523 | indio_dev->num_channels = ARRAY_SIZE(mag3110_channels); |
524 | indio_dev->available_scan_masks = mag3110_scan_masks; |
525 | |
526 | data->ctrl_reg1 = MAG3110_CTRL_DR_DEFAULT << MAG3110_CTRL_DR_SHIFT; |
527 | data->sleep_val = mag3110_calculate_sleep(data); |
528 | if (data->sleep_val < 40) |
529 | data->ctrl_reg1 |= MAG3110_CTRL_AC; |
530 | |
531 | ret = mag3110_change_config(data, MAG3110_CTRL_REG1, val: data->ctrl_reg1); |
532 | if (ret < 0) |
533 | goto disable_regulators; |
534 | |
535 | ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2, |
536 | MAG3110_CTRL_AUTO_MRST_EN); |
537 | if (ret < 0) |
538 | goto standby_on_error; |
539 | |
540 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
541 | mag3110_trigger_handler, NULL); |
542 | if (ret < 0) |
543 | goto standby_on_error; |
544 | |
545 | ret = iio_device_register(indio_dev); |
546 | if (ret < 0) |
547 | goto buffer_cleanup; |
548 | return 0; |
549 | |
550 | buffer_cleanup: |
551 | iio_triggered_buffer_cleanup(indio_dev); |
552 | standby_on_error: |
553 | mag3110_standby(data: iio_priv(indio_dev)); |
554 | disable_regulators: |
555 | regulator_disable(regulator: data->vddio_reg); |
556 | disable_regulator_vdd: |
557 | regulator_disable(regulator: data->vdd_reg); |
558 | |
559 | return ret; |
560 | } |
561 | |
562 | static void mag3110_remove(struct i2c_client *client) |
563 | { |
564 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
565 | struct mag3110_data *data = iio_priv(indio_dev); |
566 | |
567 | iio_device_unregister(indio_dev); |
568 | iio_triggered_buffer_cleanup(indio_dev); |
569 | mag3110_standby(data: iio_priv(indio_dev)); |
570 | regulator_disable(regulator: data->vddio_reg); |
571 | regulator_disable(regulator: data->vdd_reg); |
572 | } |
573 | |
574 | static int mag3110_suspend(struct device *dev) |
575 | { |
576 | struct mag3110_data *data = iio_priv(indio_dev: i2c_get_clientdata( |
577 | to_i2c_client(dev))); |
578 | int ret; |
579 | |
580 | ret = mag3110_standby(data: iio_priv(indio_dev: i2c_get_clientdata( |
581 | to_i2c_client(dev)))); |
582 | if (ret) |
583 | return ret; |
584 | |
585 | ret = regulator_disable(regulator: data->vddio_reg); |
586 | if (ret) { |
587 | dev_err(dev, "failed to disable VDDIO regulator\n" ); |
588 | return ret; |
589 | } |
590 | |
591 | ret = regulator_disable(regulator: data->vdd_reg); |
592 | if (ret) { |
593 | dev_err(dev, "failed to disable VDD regulator\n" ); |
594 | return ret; |
595 | } |
596 | |
597 | return 0; |
598 | } |
599 | |
600 | static int mag3110_resume(struct device *dev) |
601 | { |
602 | struct mag3110_data *data = iio_priv(indio_dev: i2c_get_clientdata( |
603 | to_i2c_client(dev))); |
604 | int ret; |
605 | |
606 | ret = regulator_enable(regulator: data->vdd_reg); |
607 | if (ret) { |
608 | dev_err(dev, "failed to enable VDD regulator\n" ); |
609 | return ret; |
610 | } |
611 | |
612 | ret = regulator_enable(regulator: data->vddio_reg); |
613 | if (ret) { |
614 | dev_err(dev, "failed to enable VDDIO regulator\n" ); |
615 | regulator_disable(regulator: data->vdd_reg); |
616 | return ret; |
617 | } |
618 | |
619 | return i2c_smbus_write_byte_data(client: data->client, MAG3110_CTRL_REG1, |
620 | value: data->ctrl_reg1); |
621 | } |
622 | |
623 | static DEFINE_SIMPLE_DEV_PM_OPS(mag3110_pm_ops, mag3110_suspend, |
624 | mag3110_resume); |
625 | |
626 | static const struct i2c_device_id mag3110_id[] = { |
627 | { "mag3110" , 0 }, |
628 | { } |
629 | }; |
630 | MODULE_DEVICE_TABLE(i2c, mag3110_id); |
631 | |
632 | static const struct of_device_id mag3110_of_match[] = { |
633 | { .compatible = "fsl,mag3110" }, |
634 | { } |
635 | }; |
636 | MODULE_DEVICE_TABLE(of, mag3110_of_match); |
637 | |
638 | static struct i2c_driver mag3110_driver = { |
639 | .driver = { |
640 | .name = "mag3110" , |
641 | .of_match_table = mag3110_of_match, |
642 | .pm = pm_sleep_ptr(&mag3110_pm_ops), |
643 | }, |
644 | .probe = mag3110_probe, |
645 | .remove = mag3110_remove, |
646 | .id_table = mag3110_id, |
647 | }; |
648 | module_i2c_driver(mag3110_driver); |
649 | |
650 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>" ); |
651 | MODULE_DESCRIPTION("Freescale MAG3110 magnetometer driver" ); |
652 | MODULE_LICENSE("GPL" ); |
653 | |