]>
Commit | Line | Data |
---|---|---|
40cb7613 IT |
1 | /* |
2 | * Freescale MMA9553L Intelligent Pedometer 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/gpio/consumer.h> | |
21 | #include <linux/iio/iio.h> | |
22 | #include <linux/iio/sysfs.h> | |
23 | #include <linux/iio/events.h> | |
24 | #include <linux/pm_runtime.h> | |
25 | #include "mma9551_core.h" | |
26 | ||
27 | #define MMA9553_DRV_NAME "mma9553" | |
28 | #define MMA9553_IRQ_NAME "mma9553_event" | |
29 | #define MMA9553_GPIO_NAME "mma9553_int" | |
30 | ||
31 | /* Pedometer configuration registers (R/W) */ | |
32 | #define MMA9553_REG_CONF_SLEEPMIN 0x00 | |
33 | #define MMA9553_REG_CONF_SLEEPMAX 0x02 | |
34 | #define MMA9553_REG_CONF_SLEEPTHD 0x04 | |
35 | #define MMA9553_MASK_CONF_WORD GENMASK(15, 0) | |
36 | ||
37 | #define MMA9553_REG_CONF_CONF_STEPLEN 0x06 | |
38 | #define MMA9553_MASK_CONF_CONFIG BIT(15) | |
39 | #define MMA9553_MASK_CONF_ACT_DBCNTM BIT(14) | |
40 | #define MMA9553_MASK_CONF_SLP_DBCNTM BIT(13) | |
41 | #define MMA9553_MASK_CONF_STEPLEN GENMASK(7, 0) | |
42 | ||
43 | #define MMA9553_REG_CONF_HEIGHT_WEIGHT 0x08 | |
44 | #define MMA9553_MASK_CONF_HEIGHT GENMASK(15, 8) | |
45 | #define MMA9553_MASK_CONF_WEIGHT GENMASK(7, 0) | |
46 | ||
47 | #define MMA9553_REG_CONF_FILTER 0x0A | |
48 | #define MMA9553_MASK_CONF_FILTSTEP GENMASK(15, 8) | |
49 | #define MMA9553_MASK_CONF_MALE BIT(7) | |
50 | #define MMA9553_MASK_CONF_FILTTIME GENMASK(6, 0) | |
51 | ||
52 | #define MMA9553_REG_CONF_SPEED_STEP 0x0C | |
53 | #define MMA9553_MASK_CONF_SPDPRD GENMASK(15, 8) | |
54 | #define MMA9553_MASK_CONF_STEPCOALESCE GENMASK(7, 0) | |
55 | ||
56 | #define MMA9553_REG_CONF_ACTTHD 0x0E | |
1d93353d | 57 | #define MMA9553_MAX_ACTTHD GENMASK(15, 0) |
40cb7613 IT |
58 | |
59 | /* Pedometer status registers (R-only) */ | |
60 | #define MMA9553_REG_STATUS 0x00 | |
61 | #define MMA9553_MASK_STATUS_MRGFL BIT(15) | |
62 | #define MMA9553_MASK_STATUS_SUSPCHG BIT(14) | |
63 | #define MMA9553_MASK_STATUS_STEPCHG BIT(13) | |
64 | #define MMA9553_MASK_STATUS_ACTCHG BIT(12) | |
65 | #define MMA9553_MASK_STATUS_SUSP BIT(11) | |
66 | #define MMA9553_MASK_STATUS_ACTIVITY (BIT(10) | BIT(9) | BIT(8)) | |
67 | #define MMA9553_MASK_STATUS_VERSION 0x00FF | |
68 | ||
69 | #define MMA9553_REG_STEPCNT 0x02 | |
70 | #define MMA9553_REG_DISTANCE 0x04 | |
71 | #define MMA9553_REG_SPEED 0x06 | |
72 | #define MMA9553_REG_CALORIES 0x08 | |
73 | #define MMA9553_REG_SLEEPCNT 0x0A | |
74 | ||
75 | /* Pedometer events are always mapped to this pin. */ | |
76 | #define MMA9553_DEFAULT_GPIO_PIN mma9551_gpio6 | |
77 | #define MMA9553_DEFAULT_GPIO_POLARITY 0 | |
78 | ||
79 | /* Bitnum used for gpio configuration = bit number in high status byte */ | |
80 | #define STATUS_TO_BITNUM(bit) (ffs(bit) - 9) | |
81 | ||
82 | #define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ | |
83 | ||
84 | /* | |
85 | * The internal activity level must be stable for ACTTHD samples before | |
86 | * ACTIVITY is updated.The ACTIVITY variable contains the current activity | |
87 | * level and is updated every time a step is detected or once a second | |
88 | * if there are no steps. | |
89 | */ | |
90 | #define MMA9553_ACTIVITY_THD_TO_SEC(thd) ((thd) / MMA9553_DEFAULT_SAMPLE_RATE) | |
91 | #define MMA9553_ACTIVITY_SEC_TO_THD(sec) ((sec) * MMA9553_DEFAULT_SAMPLE_RATE) | |
92 | ||
93 | /* | |
94 | * Autonomously suspend pedometer if acceleration vector magnitude | |
95 | * is near 1g (4096 at 0.244 mg/LSB resolution) for 30 seconds. | |
96 | */ | |
97 | #define MMA9553_DEFAULT_SLEEPMIN 3688 /* 0,9 g */ | |
98 | #define MMA9553_DEFAULT_SLEEPMAX 4508 /* 1,1 g */ | |
99 | #define MMA9553_DEFAULT_SLEEPTHD (MMA9553_DEFAULT_SAMPLE_RATE * 30) | |
100 | ||
101 | #define MMA9553_CONFIG_RETRIES 2 | |
102 | ||
103 | /* Status register - activity field */ | |
104 | enum activity_level { | |
105 | ACTIVITY_UNKNOWN, | |
106 | ACTIVITY_REST, | |
107 | ACTIVITY_WALKING, | |
108 | ACTIVITY_JOGGING, | |
109 | ACTIVITY_RUNNING, | |
110 | }; | |
111 | ||
112 | static struct mma9553_event_info { | |
113 | enum iio_chan_type type; | |
114 | enum iio_modifier mod; | |
115 | enum iio_event_direction dir; | |
116 | } mma9553_events_info[] = { | |
117 | { | |
118 | .type = IIO_STEPS, | |
119 | .mod = IIO_NO_MOD, | |
120 | .dir = IIO_EV_DIR_NONE, | |
121 | }, | |
122 | { | |
123 | .type = IIO_ACTIVITY, | |
124 | .mod = IIO_MOD_STILL, | |
125 | .dir = IIO_EV_DIR_RISING, | |
126 | }, | |
127 | { | |
128 | .type = IIO_ACTIVITY, | |
129 | .mod = IIO_MOD_STILL, | |
130 | .dir = IIO_EV_DIR_FALLING, | |
131 | }, | |
132 | { | |
133 | .type = IIO_ACTIVITY, | |
134 | .mod = IIO_MOD_WALKING, | |
135 | .dir = IIO_EV_DIR_RISING, | |
136 | }, | |
137 | { | |
138 | .type = IIO_ACTIVITY, | |
139 | .mod = IIO_MOD_WALKING, | |
140 | .dir = IIO_EV_DIR_FALLING, | |
141 | }, | |
142 | { | |
143 | .type = IIO_ACTIVITY, | |
144 | .mod = IIO_MOD_JOGGING, | |
145 | .dir = IIO_EV_DIR_RISING, | |
146 | }, | |
147 | { | |
148 | .type = IIO_ACTIVITY, | |
149 | .mod = IIO_MOD_JOGGING, | |
150 | .dir = IIO_EV_DIR_FALLING, | |
151 | }, | |
152 | { | |
153 | .type = IIO_ACTIVITY, | |
154 | .mod = IIO_MOD_RUNNING, | |
155 | .dir = IIO_EV_DIR_RISING, | |
156 | }, | |
157 | { | |
158 | .type = IIO_ACTIVITY, | |
159 | .mod = IIO_MOD_RUNNING, | |
160 | .dir = IIO_EV_DIR_FALLING, | |
161 | }, | |
162 | }; | |
163 | ||
164 | #define MMA9553_EVENTS_INFO_SIZE ARRAY_SIZE(mma9553_events_info) | |
165 | ||
166 | struct mma9553_event { | |
167 | struct mma9553_event_info *info; | |
168 | bool enabled; | |
169 | }; | |
170 | ||
171 | struct mma9553_conf_regs { | |
172 | u16 sleepmin; | |
173 | u16 sleepmax; | |
174 | u16 sleepthd; | |
175 | u16 config; | |
176 | u16 height_weight; | |
177 | u16 filter; | |
178 | u16 speed_step; | |
179 | u16 actthd; | |
180 | } __packed; | |
181 | ||
182 | struct mma9553_data { | |
183 | struct i2c_client *client; | |
184 | struct mutex mutex; | |
185 | struct mma9553_conf_regs conf; | |
186 | struct mma9553_event events[MMA9553_EVENTS_INFO_SIZE]; | |
187 | int num_events; | |
188 | u8 gpio_bitnum; | |
189 | /* | |
190 | * This is used for all features that depend on step count: | |
191 | * step count, distance, speed, calories. | |
192 | */ | |
193 | bool stepcnt_enabled; | |
194 | u16 stepcnt; | |
195 | u8 activity; | |
196 | s64 timestamp; | |
197 | }; | |
198 | ||
199 | static u8 mma9553_get_bits(u16 val, u16 mask) | |
200 | { | |
201 | return (val & mask) >> (ffs(mask) - 1); | |
202 | } | |
203 | ||
204 | static u16 mma9553_set_bits(u16 current_val, u16 val, u16 mask) | |
205 | { | |
206 | return (current_val & ~mask) | (val << (ffs(mask) - 1)); | |
207 | } | |
208 | ||
209 | static enum iio_modifier mma9553_activity_to_mod(enum activity_level activity) | |
210 | { | |
211 | switch (activity) { | |
212 | case ACTIVITY_RUNNING: | |
213 | return IIO_MOD_RUNNING; | |
214 | case ACTIVITY_JOGGING: | |
215 | return IIO_MOD_JOGGING; | |
216 | case ACTIVITY_WALKING: | |
217 | return IIO_MOD_WALKING; | |
218 | case ACTIVITY_REST: | |
219 | return IIO_MOD_STILL; | |
220 | case ACTIVITY_UNKNOWN: | |
221 | default: | |
222 | return IIO_NO_MOD; | |
223 | } | |
224 | } | |
225 | ||
226 | static void mma9553_init_events(struct mma9553_data *data) | |
227 | { | |
228 | int i; | |
229 | ||
230 | data->num_events = MMA9553_EVENTS_INFO_SIZE; | |
231 | for (i = 0; i < data->num_events; i++) { | |
232 | data->events[i].info = &mma9553_events_info[i]; | |
233 | data->events[i].enabled = false; | |
234 | } | |
235 | } | |
236 | ||
237 | static struct mma9553_event *mma9553_get_event(struct mma9553_data *data, | |
238 | enum iio_chan_type type, | |
239 | enum iio_modifier mod, | |
240 | enum iio_event_direction dir) | |
241 | { | |
242 | int i; | |
243 | ||
244 | for (i = 0; i < data->num_events; i++) | |
245 | if (data->events[i].info->type == type && | |
246 | data->events[i].info->mod == mod && | |
247 | data->events[i].info->dir == dir) | |
248 | return &data->events[i]; | |
249 | ||
250 | return NULL; | |
251 | } | |
252 | ||
253 | static bool mma9553_is_any_event_enabled(struct mma9553_data *data, | |
254 | bool check_type, | |
255 | enum iio_chan_type type) | |
256 | { | |
257 | int i; | |
258 | ||
259 | for (i = 0; i < data->num_events; i++) | |
260 | if ((check_type && data->events[i].info->type == type && | |
261 | data->events[i].enabled) || | |
262 | (!check_type && data->events[i].enabled)) | |
263 | return true; | |
264 | ||
265 | return false; | |
266 | } | |
267 | ||
268 | static int mma9553_set_config(struct mma9553_data *data, u16 reg, | |
269 | u16 *p_reg_val, u16 val, u16 mask) | |
270 | { | |
271 | int ret, retries; | |
272 | u16 reg_val, config; | |
273 | ||
274 | reg_val = *p_reg_val; | |
275 | if (val == mma9553_get_bits(reg_val, mask)) | |
276 | return 0; | |
277 | ||
278 | reg_val = mma9553_set_bits(reg_val, val, mask); | |
279 | ret = mma9551_write_config_word(data->client, MMA9551_APPID_PEDOMETER, | |
280 | reg, reg_val); | |
281 | if (ret < 0) { | |
282 | dev_err(&data->client->dev, | |
283 | "error writing config register 0x%x\n", reg); | |
284 | return ret; | |
285 | } | |
286 | ||
287 | *p_reg_val = reg_val; | |
288 | ||
289 | /* Reinitializes the pedometer with current configuration values */ | |
290 | config = mma9553_set_bits(data->conf.config, 1, | |
291 | MMA9553_MASK_CONF_CONFIG); | |
292 | ||
293 | ret = mma9551_write_config_word(data->client, MMA9551_APPID_PEDOMETER, | |
294 | MMA9553_REG_CONF_CONF_STEPLEN, config); | |
295 | if (ret < 0) { | |
296 | dev_err(&data->client->dev, | |
297 | "error writing config register 0x%x\n", | |
298 | MMA9553_REG_CONF_CONF_STEPLEN); | |
299 | return ret; | |
300 | } | |
301 | ||
302 | retries = MMA9553_CONFIG_RETRIES; | |
303 | do { | |
304 | mma9551_sleep(MMA9553_DEFAULT_SAMPLE_RATE); | |
305 | ret = mma9551_read_config_word(data->client, | |
306 | MMA9551_APPID_PEDOMETER, | |
307 | MMA9553_REG_CONF_CONF_STEPLEN, | |
308 | &config); | |
309 | if (ret < 0) | |
310 | return ret; | |
311 | } while (mma9553_get_bits(config, MMA9553_MASK_CONF_CONFIG) && | |
312 | --retries > 0); | |
313 | ||
314 | return 0; | |
315 | } | |
316 | ||
317 | static int mma9553_read_activity_stepcnt(struct mma9553_data *data, | |
318 | u8 *activity, u16 *stepcnt) | |
319 | { | |
cd62322a | 320 | u16 buf[2]; |
40cb7613 IT |
321 | int ret; |
322 | ||
323 | ret = mma9551_read_status_words(data->client, MMA9551_APPID_PEDOMETER, | |
cd62322a | 324 | MMA9553_REG_STATUS, sizeof(u32), buf); |
40cb7613 IT |
325 | if (ret < 0) { |
326 | dev_err(&data->client->dev, | |
327 | "error reading status and stepcnt\n"); | |
328 | return ret; | |
329 | } | |
330 | ||
cd62322a IT |
331 | *activity = mma9553_get_bits(buf[0], MMA9553_MASK_STATUS_ACTIVITY); |
332 | *stepcnt = buf[1]; | |
40cb7613 IT |
333 | |
334 | return 0; | |
335 | } | |
336 | ||
337 | static int mma9553_conf_gpio(struct mma9553_data *data) | |
338 | { | |
339 | u8 bitnum = 0, appid = MMA9551_APPID_PEDOMETER; | |
340 | int ret; | |
341 | struct mma9553_event *ev_step_detect; | |
342 | bool activity_enabled; | |
343 | ||
344 | activity_enabled = | |
345 | mma9553_is_any_event_enabled(data, true, IIO_ACTIVITY); | |
346 | ev_step_detect = | |
347 | mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD, IIO_EV_DIR_NONE); | |
348 | ||
349 | /* | |
350 | * If both step detector and activity are enabled, use the MRGFL bit. | |
351 | * This bit is the logical OR of the SUSPCHG, STEPCHG, and ACTCHG flags. | |
352 | */ | |
353 | if (activity_enabled && ev_step_detect->enabled) | |
354 | bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_MRGFL); | |
355 | else if (ev_step_detect->enabled) | |
356 | bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_STEPCHG); | |
357 | else if (activity_enabled) | |
358 | bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_ACTCHG); | |
359 | else /* Reset */ | |
360 | appid = MMA9551_APPID_NONE; | |
361 | ||
362 | if (data->gpio_bitnum == bitnum) | |
363 | return 0; | |
364 | ||
365 | /* Save initial values for activity and stepcnt */ | |
366 | if (activity_enabled || ev_step_detect->enabled) | |
367 | mma9553_read_activity_stepcnt(data, &data->activity, | |
368 | &data->stepcnt); | |
369 | ||
370 | ret = mma9551_gpio_config(data->client, | |
371 | MMA9553_DEFAULT_GPIO_PIN, | |
372 | appid, bitnum, MMA9553_DEFAULT_GPIO_POLARITY); | |
373 | if (ret < 0) | |
374 | return ret; | |
375 | data->gpio_bitnum = bitnum; | |
376 | ||
377 | return 0; | |
378 | } | |
379 | ||
380 | static int mma9553_init(struct mma9553_data *data) | |
381 | { | |
382 | int ret; | |
383 | ||
384 | ret = mma9551_read_version(data->client); | |
385 | if (ret) | |
386 | return ret; | |
387 | ||
388 | /* | |
389 | * Read all the pedometer configuration registers. This is used as | |
390 | * a device identification command to differentiate the MMA9553L | |
391 | * from the MMA9550L. | |
392 | */ | |
393 | ret = | |
394 | mma9551_read_config_words(data->client, MMA9551_APPID_PEDOMETER, | |
395 | MMA9553_REG_CONF_SLEEPMIN, | |
396 | sizeof(data->conf), (u16 *) &data->conf); | |
397 | if (ret < 0) { | |
398 | dev_err(&data->client->dev, | |
399 | "device is not MMA9553L: failed to read cfg regs\n"); | |
400 | return ret; | |
401 | } | |
402 | ||
403 | ||
404 | /* Reset gpio */ | |
405 | data->gpio_bitnum = -1; | |
406 | ret = mma9553_conf_gpio(data); | |
407 | if (ret < 0) | |
408 | return ret; | |
409 | ||
410 | ret = mma9551_app_reset(data->client, MMA9551_RSC_PED); | |
411 | if (ret < 0) | |
412 | return ret; | |
413 | ||
414 | /* Init config registers */ | |
415 | data->conf.sleepmin = MMA9553_DEFAULT_SLEEPMIN; | |
416 | data->conf.sleepmax = MMA9553_DEFAULT_SLEEPMAX; | |
417 | data->conf.sleepthd = MMA9553_DEFAULT_SLEEPTHD; | |
418 | data->conf.config = | |
419 | mma9553_set_bits(data->conf.config, 1, MMA9553_MASK_CONF_CONFIG); | |
420 | /* | |
421 | * Clear the activity debounce counter when the activity level changes, | |
422 | * so that the confidence level applies for any activity level. | |
423 | */ | |
424 | data->conf.config = mma9553_set_bits(data->conf.config, 1, | |
425 | MMA9553_MASK_CONF_ACT_DBCNTM); | |
426 | ret = | |
427 | mma9551_write_config_words(data->client, MMA9551_APPID_PEDOMETER, | |
428 | MMA9553_REG_CONF_SLEEPMIN, | |
429 | sizeof(data->conf), (u16 *) &data->conf); | |
430 | if (ret < 0) { | |
431 | dev_err(&data->client->dev, | |
432 | "failed to write configuration registers\n"); | |
433 | return ret; | |
434 | } | |
435 | ||
436 | return mma9551_set_device_state(data->client, true); | |
437 | } | |
438 | ||
439 | static int mma9553_read_raw(struct iio_dev *indio_dev, | |
440 | struct iio_chan_spec const *chan, | |
441 | int *val, int *val2, long mask) | |
442 | { | |
443 | struct mma9553_data *data = iio_priv(indio_dev); | |
444 | int ret; | |
445 | u16 tmp; | |
446 | u8 activity; | |
447 | bool powered_on; | |
448 | ||
449 | switch (mask) { | |
450 | case IIO_CHAN_INFO_PROCESSED: | |
451 | switch (chan->type) { | |
452 | case IIO_STEPS: | |
453 | /* | |
454 | * The HW only counts steps and other dependent | |
455 | * parameters (speed, distance, calories, activity) | |
456 | * if power is on (from enabling an event or the | |
457 | * step counter */ | |
458 | powered_on = | |
459 | mma9553_is_any_event_enabled(data, false, 0) || | |
460 | data->stepcnt_enabled; | |
461 | if (!powered_on) { | |
462 | dev_err(&data->client->dev, | |
463 | "No channels enabled\n"); | |
464 | return -EINVAL; | |
465 | } | |
466 | mutex_lock(&data->mutex); | |
467 | ret = mma9551_read_status_word(data->client, | |
468 | MMA9551_APPID_PEDOMETER, | |
469 | MMA9553_REG_STEPCNT, | |
470 | &tmp); | |
471 | mutex_unlock(&data->mutex); | |
472 | if (ret < 0) | |
473 | return ret; | |
474 | *val = tmp; | |
475 | return IIO_VAL_INT; | |
476 | case IIO_DISTANCE: | |
477 | powered_on = | |
478 | mma9553_is_any_event_enabled(data, false, 0) || | |
479 | data->stepcnt_enabled; | |
480 | if (!powered_on) { | |
481 | dev_err(&data->client->dev, | |
482 | "No channels enabled\n"); | |
483 | return -EINVAL; | |
484 | } | |
485 | mutex_lock(&data->mutex); | |
486 | ret = mma9551_read_status_word(data->client, | |
487 | MMA9551_APPID_PEDOMETER, | |
488 | MMA9553_REG_DISTANCE, | |
489 | &tmp); | |
490 | mutex_unlock(&data->mutex); | |
491 | if (ret < 0) | |
492 | return ret; | |
493 | *val = tmp; | |
494 | return IIO_VAL_INT; | |
495 | case IIO_ACTIVITY: | |
496 | powered_on = | |
497 | mma9553_is_any_event_enabled(data, false, 0) || | |
498 | data->stepcnt_enabled; | |
499 | if (!powered_on) { | |
500 | dev_err(&data->client->dev, | |
501 | "No channels enabled\n"); | |
502 | return -EINVAL; | |
503 | } | |
504 | mutex_lock(&data->mutex); | |
505 | ret = mma9551_read_status_word(data->client, | |
506 | MMA9551_APPID_PEDOMETER, | |
507 | MMA9553_REG_STATUS, | |
508 | &tmp); | |
509 | mutex_unlock(&data->mutex); | |
510 | if (ret < 0) | |
511 | return ret; | |
512 | ||
513 | activity = | |
514 | mma9553_get_bits(tmp, MMA9553_MASK_STATUS_ACTIVITY); | |
515 | ||
516 | /* | |
517 | * The device does not support confidence value levels, | |
518 | * so we will always have 100% for current activity and | |
519 | * 0% for the others. | |
520 | */ | |
521 | if (chan->channel2 == mma9553_activity_to_mod(activity)) | |
522 | *val = 100; | |
523 | else | |
524 | *val = 0; | |
525 | return IIO_VAL_INT; | |
526 | default: | |
527 | return -EINVAL; | |
528 | } | |
529 | case IIO_CHAN_INFO_RAW: | |
530 | switch (chan->type) { | |
531 | case IIO_VELOCITY: /* m/h */ | |
532 | if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) | |
533 | return -EINVAL; | |
534 | powered_on = | |
535 | mma9553_is_any_event_enabled(data, false, 0) || | |
536 | data->stepcnt_enabled; | |
537 | if (!powered_on) { | |
538 | dev_err(&data->client->dev, | |
539 | "No channels enabled\n"); | |
540 | return -EINVAL; | |
541 | } | |
542 | mutex_lock(&data->mutex); | |
543 | ret = mma9551_read_status_word(data->client, | |
544 | MMA9551_APPID_PEDOMETER, | |
545 | MMA9553_REG_SPEED, &tmp); | |
546 | mutex_unlock(&data->mutex); | |
547 | if (ret < 0) | |
548 | return ret; | |
549 | *val = tmp; | |
550 | return IIO_VAL_INT; | |
551 | case IIO_ENERGY: /* Cal or kcal */ | |
552 | powered_on = | |
553 | mma9553_is_any_event_enabled(data, false, 0) || | |
554 | data->stepcnt_enabled; | |
555 | if (!powered_on) { | |
556 | dev_err(&data->client->dev, | |
557 | "No channels enabled\n"); | |
558 | return -EINVAL; | |
559 | } | |
560 | mutex_lock(&data->mutex); | |
561 | ret = mma9551_read_status_word(data->client, | |
562 | MMA9551_APPID_PEDOMETER, | |
563 | MMA9553_REG_CALORIES, | |
564 | &tmp); | |
565 | mutex_unlock(&data->mutex); | |
566 | if (ret < 0) | |
567 | return ret; | |
568 | *val = tmp; | |
569 | return IIO_VAL_INT; | |
570 | case IIO_ACCEL: | |
571 | mutex_lock(&data->mutex); | |
572 | ret = mma9551_read_accel_chan(data->client, | |
573 | chan, val, val2); | |
574 | mutex_unlock(&data->mutex); | |
575 | return ret; | |
576 | default: | |
577 | return -EINVAL; | |
578 | } | |
579 | case IIO_CHAN_INFO_SCALE: | |
580 | switch (chan->type) { | |
581 | case IIO_VELOCITY: /* m/h to m/s */ | |
582 | if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) | |
583 | return -EINVAL; | |
584 | *val = 0; | |
585 | *val2 = 277; /* 0.000277 */ | |
586 | return IIO_VAL_INT_PLUS_MICRO; | |
587 | case IIO_ENERGY: /* Cal or kcal to J */ | |
588 | *val = 4184; | |
589 | return IIO_VAL_INT; | |
590 | case IIO_ACCEL: | |
591 | return mma9551_read_accel_scale(val, val2); | |
592 | default: | |
593 | return -EINVAL; | |
594 | } | |
595 | case IIO_CHAN_INFO_ENABLE: | |
596 | *val = data->stepcnt_enabled; | |
597 | return IIO_VAL_INT; | |
598 | case IIO_CHAN_INFO_CALIBHEIGHT: | |
599 | tmp = mma9553_get_bits(data->conf.height_weight, | |
600 | MMA9553_MASK_CONF_HEIGHT); | |
601 | *val = tmp / 100; /* cm to m */ | |
602 | *val2 = (tmp % 100) * 10000; | |
603 | return IIO_VAL_INT_PLUS_MICRO; | |
604 | case IIO_CHAN_INFO_CALIBWEIGHT: | |
605 | *val = mma9553_get_bits(data->conf.height_weight, | |
606 | MMA9553_MASK_CONF_WEIGHT); | |
607 | return IIO_VAL_INT; | |
608 | case IIO_CHAN_INFO_DEBOUNCE_COUNT: | |
609 | switch (chan->type) { | |
610 | case IIO_STEPS: | |
611 | *val = mma9553_get_bits(data->conf.filter, | |
612 | MMA9553_MASK_CONF_FILTSTEP); | |
613 | return IIO_VAL_INT; | |
614 | default: | |
615 | return -EINVAL; | |
616 | } | |
617 | case IIO_CHAN_INFO_DEBOUNCE_TIME: | |
618 | switch (chan->type) { | |
619 | case IIO_STEPS: | |
620 | *val = mma9553_get_bits(data->conf.filter, | |
621 | MMA9553_MASK_CONF_FILTTIME); | |
622 | return IIO_VAL_INT; | |
623 | default: | |
624 | return -EINVAL; | |
625 | } | |
626 | case IIO_CHAN_INFO_INT_TIME: | |
627 | switch (chan->type) { | |
628 | case IIO_VELOCITY: | |
629 | if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) | |
630 | return -EINVAL; | |
631 | *val = mma9553_get_bits(data->conf.speed_step, | |
632 | MMA9553_MASK_CONF_SPDPRD); | |
633 | return IIO_VAL_INT; | |
634 | default: | |
635 | return -EINVAL; | |
636 | } | |
637 | default: | |
638 | return -EINVAL; | |
639 | } | |
640 | } | |
641 | ||
642 | static int mma9553_write_raw(struct iio_dev *indio_dev, | |
643 | struct iio_chan_spec const *chan, | |
644 | int val, int val2, long mask) | |
645 | { | |
646 | struct mma9553_data *data = iio_priv(indio_dev); | |
647 | int ret, tmp; | |
648 | ||
649 | switch (mask) { | |
650 | case IIO_CHAN_INFO_ENABLE: | |
651 | if (data->stepcnt_enabled == !!val) | |
652 | return 0; | |
653 | mutex_lock(&data->mutex); | |
654 | ret = mma9551_set_power_state(data->client, val); | |
655 | if (ret < 0) { | |
656 | mutex_unlock(&data->mutex); | |
657 | return ret; | |
658 | } | |
659 | data->stepcnt_enabled = val; | |
660 | mutex_unlock(&data->mutex); | |
661 | return 0; | |
662 | case IIO_CHAN_INFO_CALIBHEIGHT: | |
663 | /* m to cm */ | |
664 | tmp = val * 100 + val2 / 10000; | |
665 | if (tmp < 0 || tmp > 255) | |
666 | return -EINVAL; | |
667 | mutex_lock(&data->mutex); | |
668 | ret = mma9553_set_config(data, | |
669 | MMA9553_REG_CONF_HEIGHT_WEIGHT, | |
670 | &data->conf.height_weight, | |
671 | tmp, MMA9553_MASK_CONF_HEIGHT); | |
672 | mutex_unlock(&data->mutex); | |
673 | return ret; | |
674 | case IIO_CHAN_INFO_CALIBWEIGHT: | |
675 | if (val < 0 || val > 255) | |
676 | return -EINVAL; | |
677 | mutex_lock(&data->mutex); | |
678 | ret = mma9553_set_config(data, | |
679 | MMA9553_REG_CONF_HEIGHT_WEIGHT, | |
680 | &data->conf.height_weight, | |
681 | val, MMA9553_MASK_CONF_WEIGHT); | |
682 | mutex_unlock(&data->mutex); | |
683 | return ret; | |
684 | case IIO_CHAN_INFO_DEBOUNCE_COUNT: | |
685 | switch (chan->type) { | |
686 | case IIO_STEPS: | |
687 | /* | |
688 | * Set to 0 to disable step filtering. If the value | |
689 | * specified is greater than 6, then 6 will be used. | |
690 | */ | |
691 | if (val < 0) | |
692 | return -EINVAL; | |
693 | if (val > 6) | |
694 | val = 6; | |
695 | mutex_lock(&data->mutex); | |
696 | ret = mma9553_set_config(data, MMA9553_REG_CONF_FILTER, | |
697 | &data->conf.filter, val, | |
698 | MMA9553_MASK_CONF_FILTSTEP); | |
699 | mutex_unlock(&data->mutex); | |
700 | return ret; | |
701 | default: | |
702 | return -EINVAL; | |
703 | } | |
704 | case IIO_CHAN_INFO_DEBOUNCE_TIME: | |
705 | switch (chan->type) { | |
706 | case IIO_STEPS: | |
707 | if (val < 0 || val > 127) | |
708 | return -EINVAL; | |
709 | mutex_lock(&data->mutex); | |
710 | ret = mma9553_set_config(data, MMA9553_REG_CONF_FILTER, | |
711 | &data->conf.filter, val, | |
712 | MMA9553_MASK_CONF_FILTTIME); | |
713 | mutex_unlock(&data->mutex); | |
714 | return ret; | |
715 | default: | |
716 | return -EINVAL; | |
717 | } | |
718 | case IIO_CHAN_INFO_INT_TIME: | |
719 | switch (chan->type) { | |
720 | case IIO_VELOCITY: | |
721 | if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) | |
722 | return -EINVAL; | |
723 | /* | |
724 | * If set to a value greater than 5, then 5 will be | |
725 | * used. Warning: Do not set SPDPRD to 0 or 1 as | |
726 | * this may cause undesirable behavior. | |
727 | */ | |
728 | if (val < 2) | |
729 | return -EINVAL; | |
730 | if (val > 5) | |
731 | val = 5; | |
732 | mutex_lock(&data->mutex); | |
733 | ret = mma9553_set_config(data, | |
734 | MMA9553_REG_CONF_SPEED_STEP, | |
735 | &data->conf.speed_step, val, | |
736 | MMA9553_MASK_CONF_SPDPRD); | |
737 | mutex_unlock(&data->mutex); | |
738 | return ret; | |
739 | default: | |
740 | return -EINVAL; | |
741 | } | |
742 | default: | |
743 | return -EINVAL; | |
744 | } | |
745 | } | |
746 | ||
747 | static int mma9553_read_event_config(struct iio_dev *indio_dev, | |
748 | const struct iio_chan_spec *chan, | |
749 | enum iio_event_type type, | |
750 | enum iio_event_direction dir) | |
751 | { | |
752 | ||
753 | struct mma9553_data *data = iio_priv(indio_dev); | |
754 | struct mma9553_event *event; | |
755 | ||
756 | event = mma9553_get_event(data, chan->type, chan->channel2, dir); | |
757 | if (!event) | |
758 | return -EINVAL; | |
759 | ||
760 | return event->enabled; | |
761 | } | |
762 | ||
763 | static int mma9553_write_event_config(struct iio_dev *indio_dev, | |
764 | const struct iio_chan_spec *chan, | |
765 | enum iio_event_type type, | |
766 | enum iio_event_direction dir, int state) | |
767 | { | |
768 | struct mma9553_data *data = iio_priv(indio_dev); | |
769 | struct mma9553_event *event; | |
770 | int ret; | |
771 | ||
772 | event = mma9553_get_event(data, chan->type, chan->channel2, dir); | |
773 | if (!event) | |
774 | return -EINVAL; | |
775 | ||
776 | if (event->enabled == state) | |
777 | return 0; | |
778 | ||
779 | mutex_lock(&data->mutex); | |
780 | ||
781 | ret = mma9551_set_power_state(data->client, state); | |
782 | if (ret < 0) | |
783 | goto err_out; | |
784 | event->enabled = state; | |
785 | ||
786 | ret = mma9553_conf_gpio(data); | |
787 | if (ret < 0) | |
788 | goto err_conf_gpio; | |
789 | ||
790 | mutex_unlock(&data->mutex); | |
791 | ||
792 | return ret; | |
793 | ||
794 | err_conf_gpio: | |
795 | if (state) { | |
796 | event->enabled = false; | |
797 | mma9551_set_power_state(data->client, false); | |
798 | } | |
799 | err_out: | |
800 | mutex_unlock(&data->mutex); | |
801 | return ret; | |
802 | } | |
803 | ||
804 | static int mma9553_read_event_value(struct iio_dev *indio_dev, | |
805 | const struct iio_chan_spec *chan, | |
806 | enum iio_event_type type, | |
807 | enum iio_event_direction dir, | |
808 | enum iio_event_info info, | |
809 | int *val, int *val2) | |
810 | { | |
811 | struct mma9553_data *data = iio_priv(indio_dev); | |
812 | ||
813 | *val2 = 0; | |
814 | switch (info) { | |
815 | case IIO_EV_INFO_VALUE: | |
816 | switch (chan->type) { | |
817 | case IIO_STEPS: | |
818 | *val = mma9553_get_bits(data->conf.speed_step, | |
819 | MMA9553_MASK_CONF_STEPCOALESCE); | |
820 | return IIO_VAL_INT; | |
821 | case IIO_ACTIVITY: | |
822 | /* | |
823 | * The device does not support confidence value levels. | |
824 | * We set an average of 50%. | |
825 | */ | |
826 | *val = 50; | |
827 | return IIO_VAL_INT; | |
828 | default: | |
829 | return -EINVAL; | |
830 | } | |
831 | case IIO_EV_INFO_PERIOD: | |
832 | switch (chan->type) { | |
833 | case IIO_ACTIVITY: | |
834 | *val = MMA9553_ACTIVITY_THD_TO_SEC(data->conf.actthd); | |
835 | return IIO_VAL_INT; | |
836 | default: | |
837 | return -EINVAL; | |
838 | } | |
839 | default: | |
840 | return -EINVAL; | |
841 | } | |
842 | } | |
843 | ||
844 | static int mma9553_write_event_value(struct iio_dev *indio_dev, | |
845 | const struct iio_chan_spec *chan, | |
846 | enum iio_event_type type, | |
847 | enum iio_event_direction dir, | |
848 | enum iio_event_info info, | |
849 | int val, int val2) | |
850 | { | |
851 | struct mma9553_data *data = iio_priv(indio_dev); | |
852 | int ret; | |
853 | ||
854 | switch (info) { | |
855 | case IIO_EV_INFO_VALUE: | |
856 | switch (chan->type) { | |
857 | case IIO_STEPS: | |
858 | if (val < 0 || val > 255) | |
859 | return -EINVAL; | |
860 | mutex_lock(&data->mutex); | |
861 | ret = mma9553_set_config(data, | |
862 | MMA9553_REG_CONF_SPEED_STEP, | |
863 | &data->conf.speed_step, val, | |
864 | MMA9553_MASK_CONF_STEPCOALESCE); | |
865 | mutex_unlock(&data->mutex); | |
866 | return ret; | |
867 | default: | |
868 | return -EINVAL; | |
869 | } | |
870 | case IIO_EV_INFO_PERIOD: | |
871 | switch (chan->type) { | |
872 | case IIO_ACTIVITY: | |
1d93353d IT |
873 | if (val < 0 || val > MMA9553_ACTIVITY_THD_TO_SEC( |
874 | MMA9553_MAX_ACTTHD)) | |
875 | return -EINVAL; | |
40cb7613 IT |
876 | mutex_lock(&data->mutex); |
877 | ret = mma9553_set_config(data, MMA9553_REG_CONF_ACTTHD, | |
878 | &data->conf.actthd, | |
879 | MMA9553_ACTIVITY_SEC_TO_THD | |
880 | (val), MMA9553_MASK_CONF_WORD); | |
881 | mutex_unlock(&data->mutex); | |
882 | return ret; | |
883 | default: | |
884 | return -EINVAL; | |
885 | } | |
886 | default: | |
887 | return -EINVAL; | |
888 | } | |
889 | } | |
890 | ||
891 | static int mma9553_get_calibgender_mode(struct iio_dev *indio_dev, | |
892 | const struct iio_chan_spec *chan) | |
893 | { | |
894 | struct mma9553_data *data = iio_priv(indio_dev); | |
895 | u8 gender; | |
896 | ||
897 | gender = mma9553_get_bits(data->conf.filter, MMA9553_MASK_CONF_MALE); | |
898 | /* | |
899 | * HW expects 0 for female and 1 for male, | |
900 | * while iio index is 0 for male and 1 for female | |
901 | */ | |
902 | return !gender; | |
903 | } | |
904 | ||
905 | static int mma9553_set_calibgender_mode(struct iio_dev *indio_dev, | |
906 | const struct iio_chan_spec *chan, | |
907 | unsigned int mode) | |
908 | { | |
909 | struct mma9553_data *data = iio_priv(indio_dev); | |
910 | u8 gender = !mode; | |
911 | int ret; | |
912 | ||
913 | if ((mode != 0) && (mode != 1)) | |
914 | return -EINVAL; | |
915 | mutex_lock(&data->mutex); | |
916 | ret = mma9553_set_config(data, MMA9553_REG_CONF_FILTER, | |
917 | &data->conf.filter, gender, | |
918 | MMA9553_MASK_CONF_MALE); | |
919 | mutex_unlock(&data->mutex); | |
920 | ||
921 | return ret; | |
922 | } | |
923 | ||
924 | static const struct iio_event_spec mma9553_step_event = { | |
925 | .type = IIO_EV_TYPE_CHANGE, | |
926 | .dir = IIO_EV_DIR_NONE, | |
927 | .mask_separate = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_VALUE), | |
928 | }; | |
929 | ||
930 | static const struct iio_event_spec mma9553_activity_events[] = { | |
931 | { | |
932 | .type = IIO_EV_TYPE_THRESH, | |
933 | .dir = IIO_EV_DIR_RISING, | |
934 | .mask_separate = BIT(IIO_EV_INFO_ENABLE) | | |
935 | BIT(IIO_EV_INFO_VALUE) | | |
936 | BIT(IIO_EV_INFO_PERIOD), | |
937 | }, | |
938 | { | |
939 | .type = IIO_EV_TYPE_THRESH, | |
940 | .dir = IIO_EV_DIR_FALLING, | |
941 | .mask_separate = BIT(IIO_EV_INFO_ENABLE) | | |
942 | BIT(IIO_EV_INFO_VALUE) | | |
943 | BIT(IIO_EV_INFO_PERIOD), | |
944 | }, | |
945 | }; | |
946 | ||
947 | static const char * const calibgender_modes[] = { "male", "female" }; | |
948 | ||
949 | static const struct iio_enum mma9553_calibgender_enum = { | |
950 | .items = calibgender_modes, | |
951 | .num_items = ARRAY_SIZE(calibgender_modes), | |
952 | .get = mma9553_get_calibgender_mode, | |
953 | .set = mma9553_set_calibgender_mode, | |
954 | }; | |
955 | ||
956 | static const struct iio_chan_spec_ext_info mma9553_ext_info[] = { | |
957 | IIO_ENUM("calibgender", IIO_SHARED_BY_TYPE, &mma9553_calibgender_enum), | |
958 | IIO_ENUM_AVAILABLE("calibgender", &mma9553_calibgender_enum), | |
959 | {}, | |
960 | }; | |
961 | ||
962 | #define MMA9553_PEDOMETER_CHANNEL(_type, _mask) { \ | |
963 | .type = _type, \ | |
964 | .info_mask_separate = BIT(IIO_CHAN_INFO_ENABLE) | \ | |
965 | BIT(IIO_CHAN_INFO_CALIBHEIGHT) | \ | |
966 | _mask, \ | |
967 | .ext_info = mma9553_ext_info, \ | |
968 | } | |
969 | ||
970 | #define MMA9553_ACTIVITY_CHANNEL(_chan2) { \ | |
971 | .type = IIO_ACTIVITY, \ | |
972 | .modified = 1, \ | |
973 | .channel2 = _chan2, \ | |
974 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ | |
ae2ec959 IT |
975 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBHEIGHT) | \ |
976 | BIT(IIO_CHAN_INFO_ENABLE), \ | |
40cb7613 IT |
977 | .event_spec = mma9553_activity_events, \ |
978 | .num_event_specs = ARRAY_SIZE(mma9553_activity_events), \ | |
979 | .ext_info = mma9553_ext_info, \ | |
980 | } | |
981 | ||
982 | static const struct iio_chan_spec mma9553_channels[] = { | |
983 | MMA9551_ACCEL_CHANNEL(IIO_MOD_X), | |
984 | MMA9551_ACCEL_CHANNEL(IIO_MOD_Y), | |
985 | MMA9551_ACCEL_CHANNEL(IIO_MOD_Z), | |
986 | ||
987 | { | |
988 | .type = IIO_STEPS, | |
989 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | | |
990 | BIT(IIO_CHAN_INFO_ENABLE) | | |
991 | BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) | | |
992 | BIT(IIO_CHAN_INFO_DEBOUNCE_TIME), | |
993 | .event_spec = &mma9553_step_event, | |
994 | .num_event_specs = 1, | |
995 | }, | |
996 | ||
997 | MMA9553_PEDOMETER_CHANNEL(IIO_DISTANCE, BIT(IIO_CHAN_INFO_PROCESSED)), | |
998 | { | |
999 | .type = IIO_VELOCITY, | |
1000 | .modified = 1, | |
1001 | .channel2 = IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z, | |
1002 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
1003 | BIT(IIO_CHAN_INFO_SCALE) | | |
1004 | BIT(IIO_CHAN_INFO_INT_TIME) | | |
1005 | BIT(IIO_CHAN_INFO_ENABLE), | |
1006 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBHEIGHT), | |
1007 | .ext_info = mma9553_ext_info, | |
1008 | }, | |
1009 | MMA9553_PEDOMETER_CHANNEL(IIO_ENERGY, BIT(IIO_CHAN_INFO_RAW) | | |
1010 | BIT(IIO_CHAN_INFO_SCALE) | | |
1011 | BIT(IIO_CHAN_INFO_CALIBWEIGHT)), | |
1012 | ||
1013 | MMA9553_ACTIVITY_CHANNEL(IIO_MOD_RUNNING), | |
1014 | MMA9553_ACTIVITY_CHANNEL(IIO_MOD_JOGGING), | |
1015 | MMA9553_ACTIVITY_CHANNEL(IIO_MOD_WALKING), | |
1016 | MMA9553_ACTIVITY_CHANNEL(IIO_MOD_STILL), | |
1017 | }; | |
1018 | ||
1019 | static const struct iio_info mma9553_info = { | |
1020 | .driver_module = THIS_MODULE, | |
1021 | .read_raw = mma9553_read_raw, | |
1022 | .write_raw = mma9553_write_raw, | |
1023 | .read_event_config = mma9553_read_event_config, | |
1024 | .write_event_config = mma9553_write_event_config, | |
1025 | .read_event_value = mma9553_read_event_value, | |
1026 | .write_event_value = mma9553_write_event_value, | |
1027 | }; | |
1028 | ||
1029 | static irqreturn_t mma9553_irq_handler(int irq, void *private) | |
1030 | { | |
1031 | struct iio_dev *indio_dev = private; | |
1032 | struct mma9553_data *data = iio_priv(indio_dev); | |
1033 | ||
1034 | data->timestamp = iio_get_time_ns(); | |
1035 | /* | |
1036 | * Since we only configure the interrupt pin when an | |
1037 | * event is enabled, we are sure we have at least | |
1038 | * one event enabled at this point. | |
1039 | */ | |
1040 | return IRQ_WAKE_THREAD; | |
1041 | } | |
1042 | ||
1043 | static irqreturn_t mma9553_event_handler(int irq, void *private) | |
1044 | { | |
1045 | struct iio_dev *indio_dev = private; | |
1046 | struct mma9553_data *data = iio_priv(indio_dev); | |
1047 | u16 stepcnt; | |
1048 | u8 activity; | |
1049 | struct mma9553_event *ev_activity, *ev_prev_activity, *ev_step_detect; | |
1050 | int ret; | |
1051 | ||
1052 | mutex_lock(&data->mutex); | |
1053 | ret = mma9553_read_activity_stepcnt(data, &activity, &stepcnt); | |
1054 | if (ret < 0) { | |
1055 | mutex_unlock(&data->mutex); | |
1056 | return IRQ_HANDLED; | |
1057 | } | |
1058 | ||
1059 | ev_prev_activity = | |
1060 | mma9553_get_event(data, IIO_ACTIVITY, | |
1061 | mma9553_activity_to_mod(data->activity), | |
1062 | IIO_EV_DIR_FALLING); | |
1063 | ev_activity = | |
1064 | mma9553_get_event(data, IIO_ACTIVITY, | |
1065 | mma9553_activity_to_mod(activity), | |
1066 | IIO_EV_DIR_RISING); | |
1067 | ev_step_detect = | |
1068 | mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD, IIO_EV_DIR_NONE); | |
1069 | ||
1070 | if (ev_step_detect->enabled && (stepcnt != data->stepcnt)) { | |
1071 | data->stepcnt = stepcnt; | |
1072 | iio_push_event(indio_dev, | |
1073 | IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, | |
1074 | IIO_EV_DIR_NONE, IIO_EV_TYPE_CHANGE, 0, 0, 0), | |
1075 | data->timestamp); | |
1076 | } | |
1077 | ||
1078 | if (activity != data->activity) { | |
1079 | data->activity = activity; | |
1080 | /* ev_activity can be NULL if activity == ACTIVITY_UNKNOWN */ | |
1081 | if (ev_prev_activity && ev_prev_activity->enabled) | |
1082 | iio_push_event(indio_dev, | |
1083 | IIO_EVENT_CODE(IIO_ACTIVITY, 0, | |
1084 | ev_prev_activity->info->mod, | |
1085 | IIO_EV_DIR_FALLING, | |
1086 | IIO_EV_TYPE_THRESH, 0, 0, 0), | |
1087 | data->timestamp); | |
1088 | ||
1089 | if (ev_activity && ev_activity->enabled) | |
1090 | iio_push_event(indio_dev, | |
1091 | IIO_EVENT_CODE(IIO_ACTIVITY, 0, | |
1092 | ev_activity->info->mod, | |
1093 | IIO_EV_DIR_RISING, | |
1094 | IIO_EV_TYPE_THRESH, 0, 0, 0), | |
1095 | data->timestamp); | |
1096 | } | |
1097 | mutex_unlock(&data->mutex); | |
1098 | ||
1099 | return IRQ_HANDLED; | |
1100 | } | |
1101 | ||
1102 | static int mma9553_gpio_probe(struct i2c_client *client) | |
1103 | { | |
1104 | struct device *dev; | |
1105 | struct gpio_desc *gpio; | |
1106 | int ret; | |
1107 | ||
1108 | if (!client) | |
1109 | return -EINVAL; | |
1110 | ||
1111 | dev = &client->dev; | |
1112 | ||
1113 | /* data ready gpio interrupt pin */ | |
b457f53a | 1114 | gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0, GPIOD_IN); |
40cb7613 IT |
1115 | if (IS_ERR(gpio)) { |
1116 | dev_err(dev, "acpi gpio get index failed\n"); | |
1117 | return PTR_ERR(gpio); | |
1118 | } | |
1119 | ||
40cb7613 IT |
1120 | ret = gpiod_to_irq(gpio); |
1121 | ||
1122 | dev_dbg(dev, "gpio resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | |
1123 | ||
1124 | return ret; | |
1125 | } | |
1126 | ||
1127 | static const char *mma9553_match_acpi_device(struct device *dev) | |
1128 | { | |
1129 | const struct acpi_device_id *id; | |
1130 | ||
1131 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | |
1132 | if (!id) | |
1133 | return NULL; | |
1134 | ||
1135 | return dev_name(dev); | |
1136 | } | |
1137 | ||
1138 | static int mma9553_probe(struct i2c_client *client, | |
1139 | const struct i2c_device_id *id) | |
1140 | { | |
1141 | struct mma9553_data *data; | |
1142 | struct iio_dev *indio_dev; | |
1143 | const char *name = NULL; | |
1144 | int ret; | |
1145 | ||
1146 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
1147 | if (!indio_dev) | |
1148 | return -ENOMEM; | |
1149 | ||
1150 | data = iio_priv(indio_dev); | |
1151 | i2c_set_clientdata(client, indio_dev); | |
1152 | data->client = client; | |
1153 | ||
1154 | if (id) | |
1155 | name = id->name; | |
1156 | else if (ACPI_HANDLE(&client->dev)) | |
1157 | name = mma9553_match_acpi_device(&client->dev); | |
1158 | else | |
1159 | return -ENOSYS; | |
1160 | ||
1161 | mutex_init(&data->mutex); | |
1162 | mma9553_init_events(data); | |
1163 | ||
1164 | ret = mma9553_init(data); | |
1165 | if (ret < 0) | |
1166 | return ret; | |
1167 | ||
1168 | indio_dev->dev.parent = &client->dev; | |
1169 | indio_dev->channels = mma9553_channels; | |
1170 | indio_dev->num_channels = ARRAY_SIZE(mma9553_channels); | |
1171 | indio_dev->name = name; | |
1172 | indio_dev->modes = INDIO_DIRECT_MODE; | |
1173 | indio_dev->info = &mma9553_info; | |
1174 | ||
1175 | if (client->irq < 0) | |
1176 | client->irq = mma9553_gpio_probe(client); | |
1177 | ||
1178 | if (client->irq >= 0) { | |
1179 | ret = devm_request_threaded_irq(&client->dev, client->irq, | |
1180 | mma9553_irq_handler, | |
1181 | mma9553_event_handler, | |
1182 | IRQF_TRIGGER_RISING, | |
1183 | MMA9553_IRQ_NAME, indio_dev); | |
1184 | if (ret < 0) { | |
1185 | dev_err(&client->dev, "request irq %d failed\n", | |
1186 | client->irq); | |
1187 | goto out_poweroff; | |
1188 | } | |
1189 | ||
1190 | } | |
1191 | ||
1192 | ret = iio_device_register(indio_dev); | |
1193 | if (ret < 0) { | |
1194 | dev_err(&client->dev, "unable to register iio device\n"); | |
1195 | goto out_poweroff; | |
1196 | } | |
1197 | ||
1198 | ret = pm_runtime_set_active(&client->dev); | |
1199 | if (ret < 0) | |
1200 | goto out_iio_unregister; | |
1201 | ||
1202 | pm_runtime_enable(&client->dev); | |
1203 | pm_runtime_set_autosuspend_delay(&client->dev, | |
1204 | MMA9551_AUTO_SUSPEND_DELAY_MS); | |
1205 | pm_runtime_use_autosuspend(&client->dev); | |
1206 | ||
1207 | dev_dbg(&indio_dev->dev, "Registered device %s\n", name); | |
1208 | ||
1209 | return 0; | |
1210 | ||
1211 | out_iio_unregister: | |
1212 | iio_device_unregister(indio_dev); | |
1213 | out_poweroff: | |
1214 | mma9551_set_device_state(client, false); | |
1215 | return ret; | |
1216 | } | |
1217 | ||
1218 | static int mma9553_remove(struct i2c_client *client) | |
1219 | { | |
1220 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
1221 | struct mma9553_data *data = iio_priv(indio_dev); | |
1222 | ||
1223 | pm_runtime_disable(&client->dev); | |
1224 | pm_runtime_set_suspended(&client->dev); | |
1225 | pm_runtime_put_noidle(&client->dev); | |
1226 | ||
1227 | iio_device_unregister(indio_dev); | |
1228 | mutex_lock(&data->mutex); | |
1229 | mma9551_set_device_state(data->client, false); | |
1230 | mutex_unlock(&data->mutex); | |
1231 | ||
1232 | return 0; | |
1233 | } | |
1234 | ||
1235 | #ifdef CONFIG_PM | |
1236 | static int mma9553_runtime_suspend(struct device *dev) | |
1237 | { | |
1238 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
1239 | struct mma9553_data *data = iio_priv(indio_dev); | |
1240 | int ret; | |
1241 | ||
1242 | mutex_lock(&data->mutex); | |
1243 | ret = mma9551_set_device_state(data->client, false); | |
1244 | mutex_unlock(&data->mutex); | |
1245 | if (ret < 0) { | |
1246 | dev_err(&data->client->dev, "powering off device failed\n"); | |
1247 | return -EAGAIN; | |
1248 | } | |
1249 | ||
1250 | return 0; | |
1251 | } | |
1252 | ||
1253 | static int mma9553_runtime_resume(struct device *dev) | |
1254 | { | |
1255 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
1256 | struct mma9553_data *data = iio_priv(indio_dev); | |
1257 | int ret; | |
1258 | ||
1259 | ret = mma9551_set_device_state(data->client, true); | |
1260 | if (ret < 0) | |
1261 | return ret; | |
1262 | ||
1263 | mma9551_sleep(MMA9553_DEFAULT_SAMPLE_RATE); | |
1264 | ||
1265 | return 0; | |
1266 | } | |
1267 | #endif | |
1268 | ||
1269 | #ifdef CONFIG_PM_SLEEP | |
1270 | static int mma9553_suspend(struct device *dev) | |
1271 | { | |
1272 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
1273 | struct mma9553_data *data = iio_priv(indio_dev); | |
1274 | int ret; | |
1275 | ||
1276 | mutex_lock(&data->mutex); | |
1277 | ret = mma9551_set_device_state(data->client, false); | |
1278 | mutex_unlock(&data->mutex); | |
1279 | ||
1280 | return ret; | |
1281 | } | |
1282 | ||
1283 | static int mma9553_resume(struct device *dev) | |
1284 | { | |
1285 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
1286 | struct mma9553_data *data = iio_priv(indio_dev); | |
1287 | int ret; | |
1288 | ||
1289 | mutex_lock(&data->mutex); | |
1290 | ret = mma9551_set_device_state(data->client, true); | |
1291 | mutex_unlock(&data->mutex); | |
1292 | ||
1293 | return ret; | |
1294 | } | |
1295 | #endif | |
1296 | ||
1297 | static const struct dev_pm_ops mma9553_pm_ops = { | |
1298 | SET_SYSTEM_SLEEP_PM_OPS(mma9553_suspend, mma9553_resume) | |
1299 | SET_RUNTIME_PM_OPS(mma9553_runtime_suspend, | |
1300 | mma9553_runtime_resume, NULL) | |
1301 | }; | |
1302 | ||
1303 | static const struct acpi_device_id mma9553_acpi_match[] = { | |
1304 | {"MMA9553", 0}, | |
1305 | {}, | |
1306 | }; | |
1307 | ||
1308 | MODULE_DEVICE_TABLE(acpi, mma9553_acpi_match); | |
1309 | ||
1310 | static const struct i2c_device_id mma9553_id[] = { | |
1311 | {"mma9553", 0}, | |
1312 | {}, | |
1313 | }; | |
1314 | ||
1315 | MODULE_DEVICE_TABLE(i2c, mma9553_id); | |
1316 | ||
1317 | static struct i2c_driver mma9553_driver = { | |
1318 | .driver = { | |
1319 | .name = MMA9553_DRV_NAME, | |
1320 | .acpi_match_table = ACPI_PTR(mma9553_acpi_match), | |
1321 | .pm = &mma9553_pm_ops, | |
1322 | }, | |
1323 | .probe = mma9553_probe, | |
1324 | .remove = mma9553_remove, | |
1325 | .id_table = mma9553_id, | |
1326 | }; | |
1327 | ||
1328 | module_i2c_driver(mma9553_driver); | |
1329 | ||
1330 | MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>"); | |
1331 | MODULE_LICENSE("GPL v2"); | |
1332 | MODULE_DESCRIPTION("MMA9553L pedometer platform driver"); |