fix some warning for mpu6050
[firefly-linux-kernel-4.4.55.git] / drivers / misc / inv_mpu / accel / mpu6050.c
1 /*
2         $License:
3         Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
4
5         This program is free software; you can redistribute it and/or modify
6         it under the terms of the GNU General Public License as published by
7         the Free Software Foundation; either version 2 of the License, or
8         (at your option) any later version.
9
10         This program is distributed in the hope that it will be useful,
11         but WITHOUT ANY WARRANTY; without even the implied warranty of
12         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13         GNU General Public License for more details.
14
15         You should have received a copy of the GNU General Public License
16         along with this program.  If not, see <http://www.gnu.org/licenses/>.
17         $
18  */
19
20 /**
21  *  @addtogroup ACCELDL
22  *  @brief      Provides the interface to setup and handle an accelerometer.
23  *
24  *  @{
25  *      @file   mpu6050.c
26  *      @brief  Accelerometer setup and handling methods for Invensense MPU6050
27  */
28
29 /* -------------------------------------------------------------------------- */
30
31 #include <linux/i2c.h>
32 #include <linux/module.h>
33 #include <linux/moduleparam.h>
34 #include <linux/kernel.h>
35 #include <linux/errno.h>
36 #include <linux/delay.h>
37 #include <linux/slab.h>
38 #include "mpu-dev.h"
39
40 #include <log.h>
41 #include <linux/mpu.h>
42 #include "mpu6050b1.h"
43 #include "mlsl.h"
44 #include "mldl_cfg.h"
45 #undef MPL_LOG_TAG
46 #define MPL_LOG_TAG "MPL-acc"
47
48 /* -------------------------------------------------------------------------- */
49
50 struct mpu6050_config {
51         unsigned int odr;               /**< output data rate 1/1000 Hz */
52         unsigned int fsr;               /**< full scale range mg */
53         unsigned int ths;               /**< mot/no-mot thseshold mg */
54         unsigned int dur;               /**< mot/no-mot duration ms */
55         unsigned int irq_type;          /**< irq type */
56 };
57
58 struct mpu6050_private_data {
59         struct mpu6050_config suspend;
60         struct mpu6050_config resume;
61         struct mldl_cfg *mldl_cfg_ref;
62 };
63
64 /* -------------------------------------------------------------------------- */
65
66 static int mpu6050_set_mldl_cfg_ref(void *mlsl_handle,
67                         struct ext_slave_platform_data *pdata,
68                         struct mldl_cfg *mldl_cfg_ref)
69 {
70         struct mpu6050_private_data *private_data =
71                         (struct mpu6050_private_data *)pdata->private_data;
72         private_data->mldl_cfg_ref = mldl_cfg_ref;
73         return 0;
74 }
75 static int mpu6050_set_lp_mode(void *mlsl_handle,
76                         struct ext_slave_platform_data *pdata,
77                         unsigned char lpa_freq)
78 {
79         unsigned char b = 0;
80         /* Reducing the duration setting for lp mode */
81         b = 1;
82         inv_serial_single_write(mlsl_handle, pdata->address,
83                                 MPUREG_ACCEL_MOT_DUR, b);
84         /* Setting the cycle bit and LPA wake up freq */
85         inv_serial_read(mlsl_handle, pdata->address, MPUREG_PWR_MGMT_1, 1,
86                         &b);
87         b |= BIT_CYCLE | BIT_PD_PTAT;
88         inv_serial_single_write(mlsl_handle, pdata->address,
89                                 MPUREG_PWR_MGMT_1,
90                                 b);
91         inv_serial_read(mlsl_handle, pdata->address,
92                         MPUREG_PWR_MGMT_2, 1, &b);
93         b |= lpa_freq & BITS_LPA_WAKE_CTRL;
94         inv_serial_single_write(mlsl_handle, pdata->address,
95                                 MPUREG_PWR_MGMT_2, b);
96
97         return INV_SUCCESS;
98 }
99
100 static int mpu6050_set_fp_mode(void *mlsl_handle,
101                                 struct ext_slave_platform_data *pdata)
102 {
103         unsigned char b;
104         struct mpu6050_private_data *private_data =
105                         (struct mpu6050_private_data *)pdata->private_data;
106         /* Resetting the cycle bit and LPA wake up freq */
107         inv_serial_read(mlsl_handle, pdata->address,
108                         MPUREG_PWR_MGMT_1, 1, &b);
109         b &= ~BIT_CYCLE & ~BIT_PD_PTAT;
110         inv_serial_single_write(mlsl_handle, pdata->address,
111                                 MPUREG_PWR_MGMT_1, b);
112         inv_serial_read(mlsl_handle, pdata->address,
113                         MPUREG_PWR_MGMT_2, 1, &b);
114         b &= ~BITS_LPA_WAKE_CTRL;
115         inv_serial_single_write(mlsl_handle, pdata->address,
116                                 MPUREG_PWR_MGMT_2, b);
117         /* Resetting the duration setting for fp mode */
118         b = (unsigned char)private_data->suspend.ths / ACCEL_MOT_DUR_LSB;
119         inv_serial_single_write(mlsl_handle, pdata->address,
120                                 MPUREG_ACCEL_MOT_DUR, b);
121
122         return INV_SUCCESS;
123 }
124 /**
125  * Record the odr for use in computing duration values.
126  *
127  * @param config Config to set, suspend or resume structure
128  * @param odr output data rate in 1/1000 hz
129  */
130 static int mpu6050_set_odr(void *mlsl_handle,
131                           struct ext_slave_platform_data *pdata,
132                           struct mpu6050_config *config, long apply, long odr)
133 {
134         int result;
135         unsigned char b;
136         unsigned char lpa_freq = 1; /* Default value */
137         long base;
138         int total_divider;
139         struct mpu6050_private_data *private_data =
140                         (struct mpu6050_private_data *)pdata->private_data;
141         struct mldl_cfg *mldl_cfg_ref =
142                         (struct mldl_cfg *)private_data->mldl_cfg_ref;
143
144         if (mldl_cfg_ref) {
145                 base = 1000 *
146                         inv_mpu_get_sampling_rate_hz(mldl_cfg_ref->mpu_gyro_cfg)
147                         * (mldl_cfg_ref->mpu_gyro_cfg->divider + 1);
148         } else {
149                 /* have no reference to mldl_cfg => assume base rate is 1000 */
150                 base = 1000000L;
151         }
152
153         if (odr != 0) {
154                 total_divider = (base / odr) - 1;
155                 /* final odr MAY be different from requested odr due to
156                    integer truncation */
157                 config->odr = base / (total_divider + 1);
158         } else {
159                 config->odr = 0;
160                 return 0;
161         }
162
163         /* if the DMP and/or gyros are on, don't set the ODR =>
164            the DMP/gyro mldl_cfg->divider setting will handle it */
165         if (apply
166             && (mldl_cfg_ref &&
167             !(mldl_cfg_ref->inv_mpu_cfg->requested_sensors &
168                     INV_DMP_PROCESSOR))) {
169                 result = inv_serial_single_write(mlsl_handle, pdata->address,
170                                         MPUREG_SMPLRT_DIV,
171                                         (unsigned char)total_divider);
172                 if (result) {
173                         LOG_RESULT_LOCATION(result);
174                         return result;
175                 }
176                 MPL_LOGI("ODR : %d mHz\n", config->odr);
177         }
178         /* Decide whether to put accel in LP mode or pull out of LP mode
179            based on the odr. */
180         switch (odr) {
181         case 1000:
182                 lpa_freq = BITS_LPA_WAKE_1HZ;
183                 break;
184         case 2000:
185                 lpa_freq = BITS_LPA_WAKE_2HZ;
186                 break;
187         case 10000:
188                 lpa_freq = BITS_LPA_WAKE_10HZ;
189                 break;
190         case 40000:
191                 lpa_freq = BITS_LPA_WAKE_40HZ;
192                 break;
193         default:
194                 inv_serial_read(mlsl_handle, pdata->address,
195                                 MPUREG_PWR_MGMT_1, 1, &b);
196                 b &= BIT_CYCLE;
197                 if (b == BIT_CYCLE) {
198                         MPL_LOGI(" Accel LP - > FP mode. \n ");
199                         mpu6050_set_fp_mode(mlsl_handle, pdata);
200                 }
201         }
202         /* If lpa_freq default value was changed, set into LP mode */
203         if (lpa_freq != 1) {
204                 MPL_LOGI(" Accel FP - > LP mode. \n ");
205                 mpu6050_set_lp_mode(mlsl_handle, pdata, lpa_freq);
206         }
207         return 0;
208 }
209
210 static int mpu6050_set_fsr(void *mlsl_handle,
211                           struct ext_slave_platform_data *pdata,
212                           struct mpu6050_config *config, long apply, long fsr)
213 {
214         unsigned char fsr_mask;
215         int result;
216
217         if (fsr <= 2000) {
218                 config->fsr = 2000;
219                 fsr_mask = 0x00;
220         } else if (fsr <= 4000) {
221                 config->fsr = 4000;
222                 fsr_mask = 0x08;
223         } else if (fsr <= 8000) {
224                 config->fsr = 8000;
225                 fsr_mask = 0x10;
226         } else { /* fsr = [8001, oo) */
227                 config->fsr = 16000;
228                 fsr_mask = 0x18;
229         }
230
231         if (apply) {
232                 unsigned char reg;
233                 result = inv_serial_read(mlsl_handle, pdata->address,
234                                          MPUREG_ACCEL_CONFIG, 1, &reg);
235                 if (result) {
236                         LOG_RESULT_LOCATION(result);
237                         return result;
238                 }
239                 result = inv_serial_single_write(mlsl_handle, pdata->address,
240                                                  MPUREG_ACCEL_CONFIG,
241                                                  reg | fsr_mask);
242                 if (result) {
243                         LOG_RESULT_LOCATION(result);
244                         return result;
245                 }
246                 MPL_LOGV("FSR: %d\n", config->fsr);
247         }
248         return 0;
249 }
250
251 static int mpu6050_set_irq(void *mlsl_handle,
252                           struct ext_slave_platform_data *pdata,
253                           struct mpu6050_config *config, long apply,
254                           long irq_type)
255 {
256
257         /* HACK, no need for interrupts for MPU6050 accel
258                 - use of soft interrupt is required */
259 #if 0
260         switch (irq_type) {
261         case MPU_SLAVE_IRQ_TYPE_DATA_READY:
262                 config->irq_type = irq_type;
263                 reg_int_cfg = BIT_RAW_RDY_EN;
264                 break;
265         /* todo: add MOTION, NO_MOTION, and FREEFALL */
266         case MPU_SLAVE_IRQ_TYPE_NONE:
267                 /* Do nothing, not even set the interrupt because it is
268                    shared with the gyro */
269                 config->irq_type = irq_type;
270                 return 0;
271         default:
272                 return INV_ERROR_INVALID_PARAMETER;
273         }
274
275         if (apply) {
276                 result = inv_serial_single_write(mlsl_handle, pdata->address,
277                                                  MPUREG_INT_ENABLE,
278                                                  reg_int_cfg);
279                 if (result) {
280                         LOG_RESULT_LOCATION(result);
281                         return result;
282                 }
283                 MPL_LOGV("irq_type: %d\n", config->irq_type);
284         }
285 #endif
286
287         return 0;
288 }
289
290 static int mpu6050_set_ths(void *mlsl_handle,
291                           struct ext_slave_platform_data *slave,
292                           struct mpu6050_config *config, long apply, long ths)
293 {
294         if (ths < 0)
295                 ths = 0;
296
297         config->ths = ths;
298         MPL_LOGV("THS: %d\n", config->ths);
299         return 0;
300 }
301
302 static int mpu6050_set_dur(void *mlsl_handle,
303                           struct ext_slave_platform_data *slave,
304                           struct mpu6050_config *config, long apply, long dur)
305 {
306         if (dur < 0)
307                 dur = 0;
308
309         config->dur = dur;
310         MPL_LOGV("DUR: %d\n", config->dur);
311         return 0;
312 }
313
314
315 static int mpu6050_init(void *mlsl_handle,
316                        struct ext_slave_descr *slave,
317                        struct ext_slave_platform_data *pdata)
318 {
319         int result;
320         struct mpu6050_private_data *private_data;
321
322
323         private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
324
325         if (!private_data)
326                 return INV_ERROR_MEMORY_EXAUSTED;
327
328         pdata->private_data = private_data;
329
330         result = mpu6050_set_odr(mlsl_handle, pdata, &private_data->suspend,
331                                  false, 0);
332         if (result) {
333                 LOG_RESULT_LOCATION(result);
334                 return result;
335         }
336         result = mpu6050_set_odr(mlsl_handle, pdata, &private_data->resume,
337                                  false, 200000);
338         if (result) {
339                 LOG_RESULT_LOCATION(result);
340                 return result;
341         }
342         result = mpu6050_set_fsr(mlsl_handle, pdata, &private_data->suspend,
343                                  false, 2000);
344         if (result) {
345                 LOG_RESULT_LOCATION(result);
346                 return result;
347         }
348         result = mpu6050_set_fsr(mlsl_handle, pdata, &private_data->resume,
349                                  false, 2000);
350         if (result) {
351                 LOG_RESULT_LOCATION(result);
352                 return result;
353         }
354
355         result = mpu6050_set_irq(mlsl_handle, pdata, &private_data->suspend,
356                                  false, MPU_SLAVE_IRQ_TYPE_NONE);
357         if (result) {
358                 LOG_RESULT_LOCATION(result);
359                 return result;
360         }
361         result = mpu6050_set_irq(mlsl_handle, pdata, &private_data->resume,
362                                  false, MPU_SLAVE_IRQ_TYPE_NONE);
363         if (result) {
364                 LOG_RESULT_LOCATION(result);
365                 return result;
366         }
367
368         result = mpu6050_set_ths(mlsl_handle, pdata, &private_data->suspend,
369                                  false, 80);
370         if (result) {
371                 LOG_RESULT_LOCATION(result);
372                 return result;
373         }
374         result = mpu6050_set_ths(mlsl_handle, pdata, &private_data->resume,
375                                  false, 40);
376         if (result) {
377                 LOG_RESULT_LOCATION(result);
378                 return result;
379         }
380         result = mpu6050_set_dur(mlsl_handle, pdata, &private_data->suspend,
381                                  false, 1000);
382         if (result) {
383                 LOG_RESULT_LOCATION(result);
384                 return result;
385         }
386         result = mpu6050_set_dur(mlsl_handle, pdata, &private_data->resume,
387                                  false, 2540);
388         if (result) {
389                 LOG_RESULT_LOCATION(result);
390                 return result;
391         }
392
393         return 0;
394 }
395
396 static int mpu6050_exit(void *mlsl_handle,
397                        struct ext_slave_descr *slave,
398                        struct ext_slave_platform_data *pdata)
399 {
400         kfree(pdata->private_data);
401         pdata->private_data = NULL;
402         return 0;
403 }
404
405 static int mpu6050_suspend(void *mlsl_handle,
406                            struct ext_slave_descr *slave,
407                            struct ext_slave_platform_data *pdata)
408 {
409         unsigned char reg;
410         int result;
411         struct mpu6050_private_data *private_data =
412                         (struct mpu6050_private_data *)pdata->private_data;
413
414         result = mpu6050_set_odr(mlsl_handle, pdata, &private_data->suspend,
415                                 true, private_data->suspend.odr);
416         if (result) {
417                 LOG_RESULT_LOCATION(result);
418                 return result;
419         }
420
421         result = mpu6050_set_irq(mlsl_handle, pdata, &private_data->suspend,
422                                 true, private_data->suspend.irq_type);
423         if (result) {
424                 LOG_RESULT_LOCATION(result);
425                 return result;
426         }
427
428         result = inv_serial_read(mlsl_handle, pdata->address,
429                                  MPUREG_PWR_MGMT_2, 1, &reg);
430         if (result) {
431                 LOG_RESULT_LOCATION(result);
432                 return result;
433         }
434         reg |= (BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA);
435
436         result = inv_serial_single_write(mlsl_handle, pdata->address,
437                                          MPUREG_PWR_MGMT_2, reg);
438         if (result) {
439                 LOG_RESULT_LOCATION(result);
440                 return result;
441         }
442
443         return 0;
444 }
445
446 static int mpu6050_resume(void *mlsl_handle,
447                           struct ext_slave_descr *slave,
448                           struct ext_slave_platform_data *pdata)
449 {
450         int result;
451         unsigned char reg;
452         struct mpu6050_private_data *private_data =
453                 (struct mpu6050_private_data *)pdata->private_data;
454
455         result = inv_serial_read(mlsl_handle, pdata->address,
456                                  MPUREG_PWR_MGMT_1, 1, &reg);
457         if (result) {
458                 LOG_RESULT_LOCATION(result);
459                 return result;
460         }
461
462         if (reg & BIT_SLEEP) {
463                 result = inv_serial_single_write(mlsl_handle, pdata->address,
464                                         MPUREG_PWR_MGMT_1, reg & ~BIT_SLEEP);
465                 if (result) {
466                         LOG_RESULT_LOCATION(result);
467                         return result;
468                 }
469         }
470         msleep(2);
471
472         result = inv_serial_read(mlsl_handle, pdata->address,
473                         MPUREG_PWR_MGMT_2, 1, &reg);
474         if (result) {
475                 LOG_RESULT_LOCATION(result);
476                 return result;
477         }
478         reg &= ~(BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA);
479         result = inv_serial_single_write(mlsl_handle, pdata->address,
480                                        MPUREG_PWR_MGMT_2, reg);
481         if (result) {
482                 LOG_RESULT_LOCATION(result);
483                 return result;
484         }
485
486         /* settings */
487
488         result = mpu6050_set_fsr(mlsl_handle, pdata, &private_data->resume,
489                                  true, private_data->resume.fsr);
490         if (result) {
491                 LOG_RESULT_LOCATION(result);
492                 return result;
493         }
494         result = mpu6050_set_odr(mlsl_handle, pdata, &private_data->resume,
495                                  true, private_data->resume.odr);
496         if (result) {
497                 LOG_RESULT_LOCATION(result);
498                 return result;
499         }
500         result = mpu6050_set_irq(mlsl_handle, pdata, &private_data->resume,
501                                  true, private_data->resume.irq_type);
502
503         /* motion, no_motion */
504         /* TODO : port these in their respective _set_thrs and _set_dur
505                   functions and use the APPLY paremeter to apply just like
506                   _set_odr, _set_irq, and _set_fsr. */
507         reg = (unsigned char)private_data->suspend.ths / ACCEL_MOT_THR_LSB;
508         result = inv_serial_single_write(mlsl_handle, pdata->address,
509                                          MPUREG_ACCEL_MOT_THR, reg);
510         if (result) {
511                 LOG_RESULT_LOCATION(result);
512                 return result;
513         }
514         reg = (unsigned char)
515             ACCEL_ZRMOT_THR_LSB_CONVERSION(private_data->resume.ths);
516         result = inv_serial_single_write(mlsl_handle, pdata->address,
517                                          MPUREG_ACCEL_ZRMOT_THR, reg);
518         if (result) {
519                 LOG_RESULT_LOCATION(result);
520                 return result;
521         }
522         reg = (unsigned char)private_data->suspend.ths / ACCEL_MOT_DUR_LSB;
523         result = inv_serial_single_write(mlsl_handle, pdata->address,
524                                          MPUREG_ACCEL_MOT_DUR, reg);
525         if (result) {
526                 LOG_RESULT_LOCATION(result);
527                 return result;
528         }
529         reg = (unsigned char)private_data->resume.ths / ACCEL_ZRMOT_DUR_LSB;
530         result = inv_serial_single_write(mlsl_handle, pdata->address,
531                                          MPUREG_ACCEL_ZRMOT_DUR, reg);
532         if (result) {
533                 LOG_RESULT_LOCATION(result);
534                 return result;
535         }
536         return 0;
537 }
538
539 static int mpu6050_read(void *mlsl_handle,
540                         struct ext_slave_descr *slave,
541                         struct ext_slave_platform_data *pdata,
542                         unsigned char *data)
543 {
544         int result;
545         result = inv_serial_read(mlsl_handle, pdata->address,
546                                  slave->read_reg, slave->read_len, data);
547         return result;
548 }
549
550 static int mpu6050_config(void *mlsl_handle,
551                          struct ext_slave_descr *slave,
552                          struct ext_slave_platform_data *pdata,
553                          struct ext_slave_config *data)
554 {
555         struct mpu6050_private_data *private_data =
556                 (struct mpu6050_private_data *)pdata->private_data;
557         if (!data->data)
558                 return INV_ERROR_INVALID_PARAMETER;
559
560         switch (data->key) {
561         case MPU_SLAVE_CONFIG_ODR_SUSPEND:
562                 return mpu6050_set_odr(mlsl_handle, pdata,
563                                       &private_data->suspend,
564                                       data->apply, *((long *)data->data));
565         case MPU_SLAVE_CONFIG_ODR_RESUME:
566                 return mpu6050_set_odr(mlsl_handle, pdata,
567                                       &private_data->resume,
568                                       data->apply, *((long *)data->data));
569         case MPU_SLAVE_CONFIG_FSR_SUSPEND:
570                 return mpu6050_set_fsr(mlsl_handle, pdata,
571                                       &private_data->suspend,
572                                       data->apply, *((long *)data->data));
573         case MPU_SLAVE_CONFIG_FSR_RESUME:
574                 return mpu6050_set_fsr(mlsl_handle, pdata,
575                                       &private_data->resume,
576                                       data->apply, *((long *)data->data));
577         case MPU_SLAVE_CONFIG_MOT_THS:
578                 return mpu6050_set_ths(mlsl_handle, pdata,
579                                       &private_data->suspend,
580                                       data->apply, *((long *)data->data));
581         case MPU_SLAVE_CONFIG_NMOT_THS:
582                 return mpu6050_set_ths(mlsl_handle, pdata,
583                                       &private_data->resume,
584                                       data->apply, *((long *)data->data));
585         case MPU_SLAVE_CONFIG_MOT_DUR:
586                 return mpu6050_set_dur(mlsl_handle, pdata,
587                                       &private_data->suspend,
588                                       data->apply, *((long *)data->data));
589         case MPU_SLAVE_CONFIG_NMOT_DUR:
590                 return mpu6050_set_dur(mlsl_handle, pdata,
591                                       &private_data->resume,
592                                       data->apply, *((long *)data->data));
593         case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
594                 return mpu6050_set_irq(mlsl_handle, pdata,
595                                       &private_data->suspend,
596                                       data->apply, *((long *)data->data));
597                 break;
598         case MPU_SLAVE_CONFIG_IRQ_RESUME:
599                 return mpu6050_set_irq(mlsl_handle, pdata,
600                                       &private_data->resume,
601                                       data->apply, *((long *)data->data));
602         case MPU_SLAVE_CONFIG_INTERNAL_REFERENCE:
603                 return mpu6050_set_mldl_cfg_ref(mlsl_handle, pdata,
604                                                (struct mldl_cfg *)data->data);
605                 break;
606
607         default:
608                 return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
609         };
610
611         return 0;
612 }
613
614 static int mpu6050_get_config(void *mlsl_handle,
615                              struct ext_slave_descr *slave,
616                              struct ext_slave_platform_data *pdata,
617                              struct ext_slave_config *data)
618 {
619         struct mpu6050_private_data *private_data =
620                 (struct mpu6050_private_data *)pdata->private_data;
621         if (!data->data)
622                 return INV_ERROR_INVALID_PARAMETER;
623
624         switch (data->key) {
625         case MPU_SLAVE_CONFIG_ODR_SUSPEND:
626                 (*(unsigned long *)data->data) =
627                     (unsigned long)private_data->suspend.odr;
628                 break;
629         case MPU_SLAVE_CONFIG_ODR_RESUME:
630                 (*(unsigned long *)data->data) =
631                     (unsigned long)private_data->resume.odr;
632                 break;
633         case MPU_SLAVE_CONFIG_FSR_SUSPEND:
634                 (*(unsigned long *)data->data) =
635                     (unsigned long)private_data->suspend.fsr;
636                 break;
637         case MPU_SLAVE_CONFIG_FSR_RESUME:
638                 (*(unsigned long *)data->data) =
639                     (unsigned long)private_data->resume.fsr;
640                 break;
641         case MPU_SLAVE_CONFIG_MOT_THS:
642                 (*(unsigned long *)data->data) =
643                     (unsigned long)private_data->suspend.ths;
644                 break;
645         case MPU_SLAVE_CONFIG_NMOT_THS:
646                 (*(unsigned long *)data->data) =
647                     (unsigned long)private_data->resume.ths;
648                 break;
649         case MPU_SLAVE_CONFIG_MOT_DUR:
650                 (*(unsigned long *)data->data) =
651                     (unsigned long)private_data->suspend.dur;
652                 break;
653         case MPU_SLAVE_CONFIG_NMOT_DUR:
654                 (*(unsigned long *)data->data) =
655                     (unsigned long)private_data->resume.dur;
656                 break;
657         case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
658                 (*(unsigned long *)data->data) =
659                     (unsigned long)private_data->suspend.irq_type;
660                 break;
661         case MPU_SLAVE_CONFIG_IRQ_RESUME:
662                 (*(unsigned long *)data->data) =
663                     (unsigned long)private_data->resume.irq_type;
664                 break;
665         default:
666                 return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
667         };
668
669         return 0;
670 }
671
672 static struct ext_slave_descr mpu6050_descr = {
673         .init             = mpu6050_init,
674         .exit             = mpu6050_exit,
675         .suspend          = mpu6050_suspend,
676         .resume           = mpu6050_resume,
677         .read             = mpu6050_read,
678         .config           = mpu6050_config,
679         .get_config       = mpu6050_get_config,
680         .name             = "mpu6050",
681         .type             = EXT_SLAVE_TYPE_ACCEL,
682         .id               = ACCEL_ID_MPU6050,
683         .read_reg         = 0x3B,
684         .read_len         = 6,
685         .endian           = EXT_SLAVE_BIG_ENDIAN,
686         .range            = {2, 0},
687         .trigger          = NULL,
688 };
689
690 struct ext_slave_descr *mpu6050_get_slave_descr(void)
691 {
692         return &mpu6050_descr;
693 }
694
695 /**
696  *  @}
697  */