Commit | Line | Data |
---|---|---|
c78b9171 VD |
1 | /* |
2 | * Freescale MMA9551L Intelligent Motion-Sensing Platform driver | |
3 | * Copyright (c) 2014, Intel Corporation. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms and conditions of the GNU General Public License, | |
7 | * version 2, as published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | */ | |
14 | ||
15 | #include <linux/module.h> | |
16 | #include <linux/i2c.h> | |
17 | #include <linux/interrupt.h> | |
18 | #include <linux/slab.h> | |
19 | #include <linux/acpi.h> | |
20 | #include <linux/delay.h> | |
21 | #include <linux/gpio/consumer.h> | |
22 | #include <linux/iio/iio.h> | |
23 | #include <linux/iio/sysfs.h> | |
24 | #include <linux/iio/events.h> | |
6da93a67 | 25 | #include <linux/pm_runtime.h> |
d5b97f5c | 26 | #include "mma9551_core.h" |
c78b9171 VD |
27 | |
28 | #define MMA9551_DRV_NAME "mma9551" | |
29 | #define MMA9551_IRQ_NAME "mma9551_event" | |
30 | #define MMA9551_GPIO_NAME "mma9551_int" | |
31 | #define MMA9551_GPIO_COUNT 4 | |
32 | ||
c78b9171 VD |
33 | /* Tilt application (inclination in IIO terms). */ |
34 | #define MMA9551_TILT_XZ_ANG_REG 0x00 | |
35 | #define MMA9551_TILT_YZ_ANG_REG 0x01 | |
36 | #define MMA9551_TILT_XY_ANG_REG 0x02 | |
37 | #define MMA9551_TILT_ANGFLG BIT(7) | |
38 | #define MMA9551_TILT_QUAD_REG 0x03 | |
39 | #define MMA9551_TILT_XY_QUAD_SHIFT 0 | |
40 | #define MMA9551_TILT_YZ_QUAD_SHIFT 2 | |
41 | #define MMA9551_TILT_XZ_QUAD_SHIFT 4 | |
42 | #define MMA9551_TILT_CFG_REG 0x01 | |
43 | #define MMA9551_TILT_ANG_THRESH_MASK GENMASK(3, 0) | |
44 | ||
d5b97f5c IT |
45 | #define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */ |
46 | ||
c78b9171 VD |
47 | /* Tilt events are mapped to the first three GPIO pins. */ |
48 | enum mma9551_tilt_axis { | |
49 | mma9551_x = 0, | |
50 | mma9551_y, | |
51 | mma9551_z, | |
52 | }; | |
53 | ||
c78b9171 VD |
54 | struct mma9551_data { |
55 | struct i2c_client *client; | |
56 | struct mutex mutex; | |
57 | int event_enabled[3]; | |
58 | int irqs[MMA9551_GPIO_COUNT]; | |
59 | }; | |
60 | ||
c78b9171 VD |
61 | static int mma9551_read_incli_chan(struct i2c_client *client, |
62 | const struct iio_chan_spec *chan, | |
63 | int *val) | |
64 | { | |
65 | u8 quad_shift, angle, quadrant; | |
66 | u16 reg_addr; | |
67 | int ret; | |
68 | ||
69 | switch (chan->channel2) { | |
70 | case IIO_MOD_X: | |
71 | reg_addr = MMA9551_TILT_YZ_ANG_REG; | |
72 | quad_shift = MMA9551_TILT_YZ_QUAD_SHIFT; | |
73 | break; | |
74 | case IIO_MOD_Y: | |
75 | reg_addr = MMA9551_TILT_XZ_ANG_REG; | |
76 | quad_shift = MMA9551_TILT_XZ_QUAD_SHIFT; | |
77 | break; | |
78 | case IIO_MOD_Z: | |
79 | reg_addr = MMA9551_TILT_XY_ANG_REG; | |
80 | quad_shift = MMA9551_TILT_XY_QUAD_SHIFT; | |
81 | break; | |
82 | default: | |
83 | return -EINVAL; | |
84 | } | |
85 | ||
6da93a67 IT |
86 | ret = mma9551_set_power_state(client, true); |
87 | if (ret < 0) | |
88 | return ret; | |
89 | ||
c78b9171 VD |
90 | ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, |
91 | reg_addr, &angle); | |
92 | if (ret < 0) | |
6da93a67 | 93 | goto out_poweroff; |
c78b9171 VD |
94 | |
95 | ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, | |
96 | MMA9551_TILT_QUAD_REG, &quadrant); | |
97 | if (ret < 0) | |
6da93a67 | 98 | goto out_poweroff; |
c78b9171 VD |
99 | |
100 | angle &= ~MMA9551_TILT_ANGFLG; | |
101 | quadrant = (quadrant >> quad_shift) & 0x03; | |
102 | ||
103 | if (quadrant == 1 || quadrant == 3) | |
104 | *val = 90 * (quadrant + 1) - angle; | |
105 | else | |
106 | *val = angle + 90 * quadrant; | |
107 | ||
6da93a67 IT |
108 | ret = IIO_VAL_INT; |
109 | ||
110 | out_poweroff: | |
111 | mma9551_set_power_state(client, false); | |
112 | return ret; | |
c78b9171 VD |
113 | } |
114 | ||
c78b9171 VD |
115 | static int mma9551_read_raw(struct iio_dev *indio_dev, |
116 | struct iio_chan_spec const *chan, | |
117 | int *val, int *val2, long mask) | |
118 | { | |
119 | struct mma9551_data *data = iio_priv(indio_dev); | |
120 | int ret; | |
121 | ||
122 | switch (mask) { | |
123 | case IIO_CHAN_INFO_PROCESSED: | |
124 | switch (chan->type) { | |
125 | case IIO_INCLI: | |
126 | mutex_lock(&data->mutex); | |
127 | ret = mma9551_read_incli_chan(data->client, chan, val); | |
128 | mutex_unlock(&data->mutex); | |
129 | return ret; | |
130 | default: | |
131 | return -EINVAL; | |
132 | } | |
133 | case IIO_CHAN_INFO_RAW: | |
134 | switch (chan->type) { | |
135 | case IIO_ACCEL: | |
136 | mutex_lock(&data->mutex); | |
137 | ret = mma9551_read_accel_chan(data->client, | |
138 | chan, val, val2); | |
139 | mutex_unlock(&data->mutex); | |
140 | return ret; | |
141 | default: | |
142 | return -EINVAL; | |
143 | } | |
144 | case IIO_CHAN_INFO_SCALE: | |
145 | switch (chan->type) { | |
146 | case IIO_ACCEL: | |
d5b97f5c | 147 | return mma9551_read_accel_scale(val, val2); |
c78b9171 VD |
148 | default: |
149 | return -EINVAL; | |
150 | } | |
151 | default: | |
152 | return -EINVAL; | |
153 | } | |
154 | } | |
155 | ||
156 | static int mma9551_read_event_config(struct iio_dev *indio_dev, | |
157 | const struct iio_chan_spec *chan, | |
158 | enum iio_event_type type, | |
159 | enum iio_event_direction dir) | |
160 | { | |
161 | struct mma9551_data *data = iio_priv(indio_dev); | |
162 | ||
163 | switch (chan->type) { | |
164 | case IIO_INCLI: | |
165 | /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ | |
166 | return data->event_enabled[chan->channel2 - 1]; | |
167 | default: | |
168 | return -EINVAL; | |
169 | } | |
170 | } | |
171 | ||
172 | static int mma9551_config_incli_event(struct iio_dev *indio_dev, | |
173 | enum iio_modifier axis, | |
174 | int state) | |
175 | { | |
176 | struct mma9551_data *data = iio_priv(indio_dev); | |
177 | enum mma9551_tilt_axis mma_axis; | |
178 | int ret; | |
179 | ||
180 | /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ | |
181 | mma_axis = axis - 1; | |
182 | ||
183 | if (data->event_enabled[mma_axis] == state) | |
184 | return 0; | |
185 | ||
186 | if (state == 0) { | |
60347e71 VD |
187 | ret = mma9551_gpio_config(data->client, |
188 | (enum mma9551_gpio_pin)mma_axis, | |
c78b9171 VD |
189 | MMA9551_APPID_NONE, 0, 0); |
190 | if (ret < 0) | |
191 | return ret; | |
6da93a67 IT |
192 | |
193 | ret = mma9551_set_power_state(data->client, false); | |
194 | if (ret < 0) | |
195 | return ret; | |
c78b9171 VD |
196 | } else { |
197 | int bitnum; | |
198 | ||
199 | /* Bit 7 of each angle register holds the angle flag. */ | |
200 | switch (axis) { | |
201 | case IIO_MOD_X: | |
202 | bitnum = 7 + 8 * MMA9551_TILT_YZ_ANG_REG; | |
203 | break; | |
204 | case IIO_MOD_Y: | |
205 | bitnum = 7 + 8 * MMA9551_TILT_XZ_ANG_REG; | |
206 | break; | |
207 | case IIO_MOD_Z: | |
208 | bitnum = 7 + 8 * MMA9551_TILT_XY_ANG_REG; | |
209 | break; | |
210 | default: | |
211 | return -EINVAL; | |
212 | } | |
213 | ||
6da93a67 IT |
214 | |
215 | ret = mma9551_set_power_state(data->client, true); | |
216 | if (ret < 0) | |
217 | return ret; | |
218 | ||
60347e71 VD |
219 | ret = mma9551_gpio_config(data->client, |
220 | (enum mma9551_gpio_pin)mma_axis, | |
c78b9171 | 221 | MMA9551_APPID_TILT, bitnum, 0); |
6da93a67 IT |
222 | if (ret < 0) { |
223 | mma9551_set_power_state(data->client, false); | |
c78b9171 | 224 | return ret; |
6da93a67 | 225 | } |
c78b9171 VD |
226 | } |
227 | ||
228 | data->event_enabled[mma_axis] = state; | |
229 | ||
230 | return ret; | |
231 | } | |
232 | ||
233 | static int mma9551_write_event_config(struct iio_dev *indio_dev, | |
234 | const struct iio_chan_spec *chan, | |
235 | enum iio_event_type type, | |
236 | enum iio_event_direction dir, | |
237 | int state) | |
238 | { | |
239 | struct mma9551_data *data = iio_priv(indio_dev); | |
240 | int ret; | |
241 | ||
242 | switch (chan->type) { | |
243 | case IIO_INCLI: | |
244 | mutex_lock(&data->mutex); | |
245 | ret = mma9551_config_incli_event(indio_dev, | |
246 | chan->channel2, state); | |
247 | mutex_unlock(&data->mutex); | |
248 | return ret; | |
249 | default: | |
250 | return -EINVAL; | |
251 | } | |
252 | } | |
253 | ||
254 | static int mma9551_write_event_value(struct iio_dev *indio_dev, | |
255 | const struct iio_chan_spec *chan, | |
256 | enum iio_event_type type, | |
257 | enum iio_event_direction dir, | |
258 | enum iio_event_info info, | |
259 | int val, int val2) | |
260 | { | |
261 | struct mma9551_data *data = iio_priv(indio_dev); | |
262 | int ret; | |
263 | ||
264 | switch (chan->type) { | |
265 | case IIO_INCLI: | |
266 | if (val2 != 0 || val < 1 || val > 10) | |
267 | return -EINVAL; | |
268 | mutex_lock(&data->mutex); | |
269 | ret = mma9551_update_config_bits(data->client, | |
270 | MMA9551_APPID_TILT, | |
271 | MMA9551_TILT_CFG_REG, | |
272 | MMA9551_TILT_ANG_THRESH_MASK, | |
273 | val); | |
274 | mutex_unlock(&data->mutex); | |
275 | return ret; | |
276 | default: | |
277 | return -EINVAL; | |
278 | } | |
279 | } | |
280 | ||
281 | static int mma9551_read_event_value(struct iio_dev *indio_dev, | |
282 | const struct iio_chan_spec *chan, | |
283 | enum iio_event_type type, | |
284 | enum iio_event_direction dir, | |
285 | enum iio_event_info info, | |
286 | int *val, int *val2) | |
287 | { | |
288 | struct mma9551_data *data = iio_priv(indio_dev); | |
289 | int ret; | |
290 | u8 tmp; | |
291 | ||
292 | switch (chan->type) { | |
293 | case IIO_INCLI: | |
294 | mutex_lock(&data->mutex); | |
295 | ret = mma9551_read_config_byte(data->client, | |
296 | MMA9551_APPID_TILT, | |
297 | MMA9551_TILT_CFG_REG, &tmp); | |
298 | mutex_unlock(&data->mutex); | |
299 | if (ret < 0) | |
300 | return ret; | |
301 | *val = tmp & MMA9551_TILT_ANG_THRESH_MASK; | |
302 | *val2 = 0; | |
303 | return IIO_VAL_INT; | |
304 | default: | |
305 | return -EINVAL; | |
306 | } | |
307 | } | |
308 | ||
309 | static const struct iio_event_spec mma9551_incli_event = { | |
310 | .type = IIO_EV_TYPE_ROC, | |
311 | .dir = IIO_EV_DIR_RISING, | |
312 | .mask_separate = BIT(IIO_EV_INFO_ENABLE), | |
313 | .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), | |
314 | }; | |
315 | ||
c78b9171 VD |
316 | #define MMA9551_INCLI_CHANNEL(axis) { \ |
317 | .type = IIO_INCLI, \ | |
318 | .modified = 1, \ | |
319 | .channel2 = axis, \ | |
320 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ | |
321 | .event_spec = &mma9551_incli_event, \ | |
322 | .num_event_specs = 1, \ | |
323 | } | |
324 | ||
325 | static const struct iio_chan_spec mma9551_channels[] = { | |
326 | MMA9551_ACCEL_CHANNEL(IIO_MOD_X), | |
327 | MMA9551_ACCEL_CHANNEL(IIO_MOD_Y), | |
328 | MMA9551_ACCEL_CHANNEL(IIO_MOD_Z), | |
329 | ||
330 | MMA9551_INCLI_CHANNEL(IIO_MOD_X), | |
331 | MMA9551_INCLI_CHANNEL(IIO_MOD_Y), | |
332 | MMA9551_INCLI_CHANNEL(IIO_MOD_Z), | |
333 | }; | |
334 | ||
335 | static const struct iio_info mma9551_info = { | |
336 | .driver_module = THIS_MODULE, | |
337 | .read_raw = mma9551_read_raw, | |
338 | .read_event_config = mma9551_read_event_config, | |
339 | .write_event_config = mma9551_write_event_config, | |
340 | .read_event_value = mma9551_read_event_value, | |
341 | .write_event_value = mma9551_write_event_value, | |
342 | }; | |
343 | ||
344 | static irqreturn_t mma9551_event_handler(int irq, void *private) | |
345 | { | |
346 | struct iio_dev *indio_dev = private; | |
347 | struct mma9551_data *data = iio_priv(indio_dev); | |
348 | int i, ret, mma_axis = -1; | |
349 | u16 reg; | |
350 | u8 val; | |
351 | ||
352 | mutex_lock(&data->mutex); | |
353 | ||
354 | for (i = 0; i < 3; i++) | |
355 | if (irq == data->irqs[i]) { | |
356 | mma_axis = i; | |
357 | break; | |
358 | } | |
359 | ||
360 | if (mma_axis == -1) { | |
361 | /* IRQ was triggered on 4th line, which we don't use. */ | |
362 | dev_warn(&data->client->dev, | |
363 | "irq triggered on unused line %d\n", data->irqs[3]); | |
364 | goto out; | |
365 | } | |
366 | ||
367 | switch (mma_axis) { | |
368 | case mma9551_x: | |
369 | reg = MMA9551_TILT_YZ_ANG_REG; | |
370 | break; | |
371 | case mma9551_y: | |
372 | reg = MMA9551_TILT_XZ_ANG_REG; | |
373 | break; | |
374 | case mma9551_z: | |
375 | reg = MMA9551_TILT_XY_ANG_REG; | |
376 | break; | |
377 | } | |
378 | ||
379 | /* | |
380 | * Read the angle even though we don't use it, otherwise we | |
381 | * won't get any further interrupts. | |
382 | */ | |
383 | ret = mma9551_read_status_byte(data->client, MMA9551_APPID_TILT, | |
384 | reg, &val); | |
385 | if (ret < 0) { | |
386 | dev_err(&data->client->dev, | |
387 | "error %d reading tilt register in IRQ\n", ret); | |
388 | goto out; | |
389 | } | |
390 | ||
391 | iio_push_event(indio_dev, | |
392 | IIO_MOD_EVENT_CODE(IIO_INCLI, 0, (mma_axis + 1), | |
393 | IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING), | |
394 | iio_get_time_ns()); | |
395 | ||
396 | out: | |
397 | mutex_unlock(&data->mutex); | |
398 | ||
399 | return IRQ_HANDLED; | |
400 | } | |
401 | ||
402 | static int mma9551_init(struct mma9551_data *data) | |
403 | { | |
404 | int ret; | |
405 | ||
406 | ret = mma9551_read_version(data->client); | |
407 | if (ret) | |
408 | return ret; | |
409 | ||
6da93a67 | 410 | return mma9551_set_device_state(data->client, true); |
c78b9171 VD |
411 | } |
412 | ||
413 | static int mma9551_gpio_probe(struct iio_dev *indio_dev) | |
414 | { | |
415 | struct gpio_desc *gpio; | |
416 | int i, ret; | |
417 | struct mma9551_data *data = iio_priv(indio_dev); | |
418 | struct device *dev = &data->client->dev; | |
419 | ||
420 | for (i = 0; i < MMA9551_GPIO_COUNT; i++) { | |
b457f53a UKK |
421 | gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i, |
422 | GPIOD_IN); | |
c78b9171 VD |
423 | if (IS_ERR(gpio)) { |
424 | dev_err(dev, "acpi gpio get index failed\n"); | |
425 | return PTR_ERR(gpio); | |
426 | } | |
427 | ||
debf6d84 RD |
428 | ret = gpiod_to_irq(gpio); |
429 | if (ret < 0) | |
430 | return ret; | |
431 | ||
432 | data->irqs[i] = ret; | |
c78b9171 VD |
433 | ret = devm_request_threaded_irq(dev, data->irqs[i], |
434 | NULL, mma9551_event_handler, | |
435 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | |
436 | MMA9551_IRQ_NAME, indio_dev); | |
437 | if (ret < 0) { | |
438 | dev_err(dev, "request irq %d failed\n", data->irqs[i]); | |
439 | return ret; | |
440 | } | |
441 | ||
442 | dev_dbg(dev, "gpio resource, no:%d irq:%d\n", | |
443 | desc_to_gpio(gpio), data->irqs[i]); | |
444 | } | |
445 | ||
446 | return 0; | |
447 | } | |
448 | ||
449 | static const char *mma9551_match_acpi_device(struct device *dev) | |
450 | { | |
451 | const struct acpi_device_id *id; | |
452 | ||
453 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | |
454 | if (!id) | |
455 | return NULL; | |
456 | ||
457 | return dev_name(dev); | |
458 | } | |
459 | ||
460 | static int mma9551_probe(struct i2c_client *client, | |
461 | const struct i2c_device_id *id) | |
462 | { | |
463 | struct mma9551_data *data; | |
464 | struct iio_dev *indio_dev; | |
465 | const char *name = NULL; | |
466 | int ret; | |
467 | ||
468 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
469 | if (!indio_dev) | |
470 | return -ENOMEM; | |
471 | ||
472 | data = iio_priv(indio_dev); | |
473 | i2c_set_clientdata(client, indio_dev); | |
474 | data->client = client; | |
475 | ||
476 | if (id) | |
477 | name = id->name; | |
478 | else if (ACPI_HANDLE(&client->dev)) | |
479 | name = mma9551_match_acpi_device(&client->dev); | |
480 | ||
481 | ret = mma9551_init(data); | |
482 | if (ret < 0) | |
483 | return ret; | |
484 | ||
485 | mutex_init(&data->mutex); | |
486 | ||
487 | indio_dev->dev.parent = &client->dev; | |
488 | indio_dev->channels = mma9551_channels; | |
489 | indio_dev->num_channels = ARRAY_SIZE(mma9551_channels); | |
490 | indio_dev->name = name; | |
491 | indio_dev->modes = INDIO_DIRECT_MODE; | |
492 | indio_dev->info = &mma9551_info; | |
493 | ||
494 | ret = mma9551_gpio_probe(indio_dev); | |
495 | if (ret < 0) | |
496 | goto out_poweroff; | |
497 | ||
6da93a67 IT |
498 | ret = pm_runtime_set_active(&client->dev); |
499 | if (ret < 0) | |
7d0ead5c | 500 | goto out_poweroff; |
6da93a67 IT |
501 | |
502 | pm_runtime_enable(&client->dev); | |
503 | pm_runtime_set_autosuspend_delay(&client->dev, | |
504 | MMA9551_AUTO_SUSPEND_DELAY_MS); | |
505 | pm_runtime_use_autosuspend(&client->dev); | |
506 | ||
7d0ead5c AR |
507 | ret = iio_device_register(indio_dev); |
508 | if (ret < 0) { | |
509 | dev_err(&client->dev, "unable to register iio device\n"); | |
510 | goto out_poweroff; | |
511 | } | |
512 | ||
c78b9171 VD |
513 | return 0; |
514 | ||
515 | out_poweroff: | |
516 | mma9551_set_device_state(client, false); | |
517 | ||
518 | return ret; | |
519 | } | |
520 | ||
521 | static int mma9551_remove(struct i2c_client *client) | |
522 | { | |
523 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
524 | struct mma9551_data *data = iio_priv(indio_dev); | |
525 | ||
7d0ead5c AR |
526 | iio_device_unregister(indio_dev); |
527 | ||
6da93a67 IT |
528 | pm_runtime_disable(&client->dev); |
529 | pm_runtime_set_suspended(&client->dev); | |
530 | pm_runtime_put_noidle(&client->dev); | |
531 | ||
c78b9171 VD |
532 | mutex_lock(&data->mutex); |
533 | mma9551_set_device_state(data->client, false); | |
534 | mutex_unlock(&data->mutex); | |
535 | ||
536 | return 0; | |
537 | } | |
538 | ||
6da93a67 IT |
539 | #ifdef CONFIG_PM |
540 | static int mma9551_runtime_suspend(struct device *dev) | |
541 | { | |
542 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
543 | struct mma9551_data *data = iio_priv(indio_dev); | |
544 | int ret; | |
545 | ||
546 | mutex_lock(&data->mutex); | |
547 | ret = mma9551_set_device_state(data->client, false); | |
548 | mutex_unlock(&data->mutex); | |
549 | if (ret < 0) { | |
550 | dev_err(&data->client->dev, "powering off device failed\n"); | |
551 | return -EAGAIN; | |
552 | } | |
553 | ||
554 | return 0; | |
555 | } | |
556 | ||
557 | static int mma9551_runtime_resume(struct device *dev) | |
558 | { | |
559 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
560 | struct mma9551_data *data = iio_priv(indio_dev); | |
561 | int ret; | |
562 | ||
563 | ret = mma9551_set_device_state(data->client, true); | |
564 | if (ret < 0) | |
565 | return ret; | |
566 | ||
567 | mma9551_sleep(MMA9551_DEFAULT_SAMPLE_RATE); | |
568 | ||
569 | return 0; | |
570 | } | |
571 | #endif | |
572 | ||
c78b9171 VD |
573 | #ifdef CONFIG_PM_SLEEP |
574 | static int mma9551_suspend(struct device *dev) | |
575 | { | |
576 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
577 | struct mma9551_data *data = iio_priv(indio_dev); | |
6da93a67 | 578 | int ret; |
c78b9171 VD |
579 | |
580 | mutex_lock(&data->mutex); | |
6da93a67 | 581 | ret = mma9551_set_device_state(data->client, false); |
c78b9171 VD |
582 | mutex_unlock(&data->mutex); |
583 | ||
6da93a67 | 584 | return ret; |
c78b9171 VD |
585 | } |
586 | ||
587 | static int mma9551_resume(struct device *dev) | |
588 | { | |
589 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
590 | struct mma9551_data *data = iio_priv(indio_dev); | |
6da93a67 | 591 | int ret; |
c78b9171 VD |
592 | |
593 | mutex_lock(&data->mutex); | |
6da93a67 | 594 | ret = mma9551_set_device_state(data->client, true); |
c78b9171 VD |
595 | mutex_unlock(&data->mutex); |
596 | ||
6da93a67 | 597 | return ret; |
c78b9171 | 598 | } |
c78b9171 VD |
599 | #endif |
600 | ||
601 | static const struct dev_pm_ops mma9551_pm_ops = { | |
602 | SET_SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume) | |
6da93a67 IT |
603 | SET_RUNTIME_PM_OPS(mma9551_runtime_suspend, |
604 | mma9551_runtime_resume, NULL) | |
c78b9171 VD |
605 | }; |
606 | ||
607 | static const struct acpi_device_id mma9551_acpi_match[] = { | |
608 | {"MMA9551", 0}, | |
609 | {}, | |
610 | }; | |
611 | ||
612 | MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match); | |
613 | ||
614 | static const struct i2c_device_id mma9551_id[] = { | |
615 | {"mma9551", 0}, | |
616 | {} | |
617 | }; | |
618 | ||
619 | MODULE_DEVICE_TABLE(i2c, mma9551_id); | |
620 | ||
621 | static struct i2c_driver mma9551_driver = { | |
622 | .driver = { | |
623 | .name = MMA9551_DRV_NAME, | |
624 | .acpi_match_table = ACPI_PTR(mma9551_acpi_match), | |
625 | .pm = &mma9551_pm_ops, | |
626 | }, | |
627 | .probe = mma9551_probe, | |
628 | .remove = mma9551_remove, | |
629 | .id_table = mma9551_id, | |
630 | }; | |
631 | ||
632 | module_i2c_driver(mma9551_driver); | |
633 | ||
634 | MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>"); | |
635 | MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>"); | |
636 | MODULE_LICENSE("GPL v2"); | |
637 | MODULE_DESCRIPTION("MMA9551L motion-sensing platform driver"); |