ARM: tegra12: loki: Fix regulator warnings
[linux-3.10.git] / drivers / misc / inv_mpu / accel / lis331.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   lis331.c
26  *      @brief  Accelerometer setup and handling methods for ST LIS331DLH.
27  */
28
29 /* -------------------------------------------------------------------------- */
30
31 #undef MPL_LOG_NDEBUG
32 #define MPL_LOG_NDEBUG 1
33
34 #include <linux/i2c.h>
35 #include <linux/module.h>
36 #include <linux/moduleparam.h>
37 #include <linux/kernel.h>
38 #include <linux/errno.h>
39 #include <linux/slab.h>
40 #include <linux/delay.h>
41 #include "mpu-dev.h"
42
43 #include <log.h>
44 #include <linux/mpu.h>
45 #include "mlsl.h"
46 #include "mldl_cfg.h"
47 #undef MPL_LOG_TAG
48 #define MPL_LOG_TAG "MPL-acc"
49
50 /* full scale setting - register & mask */
51 #define LIS331DLH_CTRL_REG1         (0x20)
52 #define LIS331DLH_CTRL_REG2         (0x21)
53 #define LIS331DLH_CTRL_REG3         (0x22)
54 #define LIS331DLH_CTRL_REG4         (0x23)
55 #define LIS331DLH_CTRL_REG5         (0x24)
56 #define LIS331DLH_HP_FILTER_RESET   (0x25)
57 #define LIS331DLH_REFERENCE         (0x26)
58 #define LIS331DLH_STATUS_REG        (0x27)
59 #define LIS331DLH_OUT_X_L           (0x28)
60 #define LIS331DLH_OUT_X_H           (0x29)
61 #define LIS331DLH_OUT_Y_L           (0x2a)
62 #define LIS331DLH_OUT_Y_H           (0x2b)
63 #define LIS331DLH_OUT_Z_L           (0x2b)
64 #define LIS331DLH_OUT_Z_H           (0x2d)
65
66 #define LIS331DLH_INT1_CFG          (0x30)
67 #define LIS331DLH_INT1_SRC          (0x31)
68 #define LIS331DLH_INT1_THS          (0x32)
69 #define LIS331DLH_INT1_DURATION     (0x33)
70
71 #define LIS331DLH_INT2_CFG          (0x34)
72 #define LIS331DLH_INT2_SRC          (0x35)
73 #define LIS331DLH_INT2_THS          (0x36)
74 #define LIS331DLH_INT2_DURATION     (0x37)
75
76 /* CTRL_REG1 */
77 #define LIS331DLH_CTRL_MASK         (0x30)
78 #define LIS331DLH_SLEEP_MASK        (0x20)
79 #define LIS331DLH_PWR_MODE_NORMAL   (0x20)
80
81 #define LIS331DLH_MAX_DUR           (0x7F)
82
83
84 /* -------------------------------------------------------------------------- */
85
86 struct lis331dlh_config {
87         unsigned int odr;
88         unsigned int fsr;       /* full scale range mg */
89         unsigned int ths;       /* Motion no-motion thseshold mg */
90         unsigned int dur;       /* Motion no-motion duration ms */
91         unsigned char reg_ths;
92         unsigned char reg_dur;
93         unsigned char ctrl_reg1;
94         unsigned char irq_type;
95         unsigned char mot_int1_cfg;
96 };
97
98 struct lis331dlh_private_data {
99         struct lis331dlh_config suspend;
100         struct lis331dlh_config resume;
101 };
102
103 /* -------------------------------------------------------------------------- */
104 static int lis331dlh_set_ths(void *mlsl_handle,
105                              struct ext_slave_platform_data *pdata,
106                              struct lis331dlh_config *config,
107                              int apply, long ths)
108 {
109         int result = INV_SUCCESS;
110         if ((unsigned int)ths >= config->fsr)
111                 ths = (long)config->fsr - 1;
112
113         if (ths < 0)
114                 ths = 0;
115
116         config->ths = ths;
117         config->reg_ths = (unsigned char)(long)((ths * 128L) / (config->fsr));
118         MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
119         if (apply)
120                 result = inv_serial_single_write(mlsl_handle, pdata->address,
121                                                  LIS331DLH_INT1_THS,
122                                                  config->reg_ths);
123         return result;
124 }
125
126 static int lis331dlh_set_dur(void *mlsl_handle,
127                              struct ext_slave_platform_data *pdata,
128                              struct lis331dlh_config *config,
129                              int apply, long dur)
130 {
131         int result = INV_SUCCESS;
132         long reg_dur = (dur * config->odr) / 1000000L;
133         config->dur = dur;
134
135         if (reg_dur > LIS331DLH_MAX_DUR)
136                 reg_dur = LIS331DLH_MAX_DUR;
137
138         config->reg_dur = (unsigned char)reg_dur;
139         MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
140         if (apply)
141                 result = inv_serial_single_write(mlsl_handle, pdata->address,
142                                                  LIS331DLH_INT1_DURATION,
143                                                  (unsigned char)reg_dur);
144         return result;
145 }
146
147 /**
148  * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
149  * duration will not be used uless the type is MOT or NMOT.
150  *
151  * @param config configuration to apply to, suspend or resume
152  * @param irq_type The type of IRQ.  Valid values are
153  * - MPU_SLAVE_IRQ_TYPE_NONE
154  * - MPU_SLAVE_IRQ_TYPE_MOTION
155  * - MPU_SLAVE_IRQ_TYPE_DATA_READY
156  */
157 static int lis331dlh_set_irq(void *mlsl_handle,
158                              struct ext_slave_platform_data *pdata,
159                              struct lis331dlh_config *config,
160                              int apply, long irq_type)
161 {
162         int result = INV_SUCCESS;
163         unsigned char reg1;
164         unsigned char reg2;
165
166         config->irq_type = (unsigned char)irq_type;
167         if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
168                 reg1 = 0x02;
169                 reg2 = 0x00;
170         } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
171                 reg1 = 0x00;
172                 reg2 = config->mot_int1_cfg;
173         } else {
174                 reg1 = 0x00;
175                 reg2 = 0x00;
176         }
177
178         if (apply) {
179                 result = inv_serial_single_write(mlsl_handle, pdata->address,
180                                                  LIS331DLH_CTRL_REG3, reg1);
181                 result = inv_serial_single_write(mlsl_handle, pdata->address,
182                                                  LIS331DLH_INT1_CFG, reg2);
183         }
184
185         return result;
186 }
187
188 /**
189  * Set the Output data rate for the particular configuration
190  *
191  * @param config Config to modify with new ODR
192  * @param odr Output data rate in units of 1/1000Hz
193  */
194 static int lis331dlh_set_odr(void *mlsl_handle,
195                              struct ext_slave_platform_data *pdata,
196                              struct lis331dlh_config *config,
197                              int apply, long odr)
198 {
199         unsigned char bits;
200         int result = INV_SUCCESS;
201
202         /* normal power modes */
203         if (odr > 400000) {
204                 config->odr = 1000000;
205                 bits = LIS331DLH_PWR_MODE_NORMAL | 0x18;
206         } else if (odr > 100000) {
207                 config->odr = 400000;
208                 bits = LIS331DLH_PWR_MODE_NORMAL | 0x10;
209         } else if (odr > 50000) {
210                 config->odr = 100000;
211                 bits = LIS331DLH_PWR_MODE_NORMAL | 0x08;
212         } else if (odr > 10000) {
213                 config->odr = 50000;
214                 bits = LIS331DLH_PWR_MODE_NORMAL | 0x00;
215         /* low power modes */
216         } else if (odr > 5000) {
217                 config->odr = 10000;
218                 bits = 0xC0;
219         } else if (odr > 2000) {
220                 config->odr = 5000;
221                 bits = 0xA0;
222         } else if (odr > 1000) {
223                 config->odr = 2000;
224                 bits = 0x80;
225         } else if (odr > 500) {
226                 config->odr = 1000;
227                 bits = 0x60;
228         } else if (odr > 0) {
229                 config->odr = 500;
230                 bits = 0x40;
231         } else {
232                 config->odr = 0;
233                 bits = 0;
234         }
235
236         config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0x7);
237         lis331dlh_set_dur(mlsl_handle, pdata, config, apply, config->dur);
238         MPL_LOGV("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
239         if (apply)
240                 result = inv_serial_single_write(mlsl_handle, pdata->address,
241                                                  LIS331DLH_CTRL_REG1,
242                                                  config->ctrl_reg1);
243         return result;
244 }
245
246 /**
247  * Set the full scale range of the accels
248  *
249  * @param config pointer to configuration
250  * @param fsr requested full scale range
251  */
252 static int lis331dlh_set_fsr(void *mlsl_handle,
253                              struct ext_slave_platform_data *pdata,
254                              struct lis331dlh_config *config,
255                              int apply, long fsr)
256 {
257         unsigned char reg1 = 0x40;
258         int result = INV_SUCCESS;
259
260         if (fsr <= 2048) {
261                 config->fsr = 2048;
262         } else if (fsr <= 4096) {
263                 reg1 |= 0x30;
264                 config->fsr = 4096;
265         } else {
266                 reg1 |= 0x10;
267                 config->fsr = 8192;
268         }
269
270         lis331dlh_set_ths(mlsl_handle, pdata, config, apply, config->ths);
271         MPL_LOGV("FSR: %d\n", config->fsr);
272         if (apply)
273                 result = inv_serial_single_write(mlsl_handle, pdata->address,
274                                                  LIS331DLH_CTRL_REG4, reg1);
275
276         return result;
277 }
278
279 static int lis331dlh_suspend(void *mlsl_handle,
280                              struct ext_slave_descr *slave,
281                              struct ext_slave_platform_data *pdata)
282 {
283         int result = INV_SUCCESS;
284         unsigned char reg1;
285         unsigned char reg2;
286         struct lis331dlh_private_data *private_data =
287                 (struct lis331dlh_private_data *)(pdata->private_data);
288
289         result = inv_serial_single_write(mlsl_handle, pdata->address,
290                                          LIS331DLH_CTRL_REG1,
291                                          private_data->suspend.ctrl_reg1);
292
293         result = inv_serial_single_write(mlsl_handle, pdata->address,
294                                          LIS331DLH_CTRL_REG2, 0x0f);
295         reg1 = 0x40;
296         if (private_data->suspend.fsr == 8192)
297                 reg1 |= 0x30;
298         else if (private_data->suspend.fsr == 4096)
299                 reg1 |= 0x10;
300         /* else bits [4..5] are already zero */
301
302         result = inv_serial_single_write(mlsl_handle, pdata->address,
303                                          LIS331DLH_CTRL_REG4, reg1);
304         result = inv_serial_single_write(mlsl_handle, pdata->address,
305                                          LIS331DLH_INT1_THS,
306                                          private_data->suspend.reg_ths);
307         result = inv_serial_single_write(mlsl_handle, pdata->address,
308                                          LIS331DLH_INT1_DURATION,
309                                          private_data->suspend.reg_dur);
310
311         if (private_data->suspend.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
312                 reg1 = 0x02;
313                 reg2 = 0x00;
314         } else if (private_data->suspend.irq_type ==
315                    MPU_SLAVE_IRQ_TYPE_MOTION) {
316                 reg1 = 0x00;
317                 reg2 = private_data->suspend.mot_int1_cfg;
318         } else {
319                 reg1 = 0x00;
320                 reg2 = 0x00;
321         }
322         result = inv_serial_single_write(mlsl_handle, pdata->address,
323                                          LIS331DLH_CTRL_REG3, reg1);
324         result = inv_serial_single_write(mlsl_handle, pdata->address,
325                                          LIS331DLH_INT1_CFG, reg2);
326         result = inv_serial_read(mlsl_handle, pdata->address,
327                                  LIS331DLH_HP_FILTER_RESET, 1, &reg1);
328         return result;
329 }
330
331 static int lis331dlh_resume(void *mlsl_handle,
332                             struct ext_slave_descr *slave,
333                             struct ext_slave_platform_data *pdata)
334 {
335         int result = INV_SUCCESS;
336         unsigned char reg1;
337         unsigned char reg2;
338         struct lis331dlh_private_data *private_data =
339                 (struct lis331dlh_private_data *)(pdata->private_data);
340
341         result = inv_serial_single_write(mlsl_handle, pdata->address,
342                                          LIS331DLH_CTRL_REG1,
343                                          private_data->resume.ctrl_reg1);
344         if (result) {
345                 LOG_RESULT_LOCATION(result);
346                 return result;
347         }
348         msleep(6);
349
350         /* Full Scale */
351         reg1 = 0x40;
352         if (private_data->resume.fsr == 8192)
353                 reg1 |= 0x30;
354         else if (private_data->resume.fsr == 4096)
355                 reg1 |= 0x10;
356
357         result = inv_serial_single_write(mlsl_handle, pdata->address,
358                                          LIS331DLH_CTRL_REG4, reg1);
359         if (result) {
360                 LOG_RESULT_LOCATION(result);
361                 return result;
362         }
363
364         /* Configure high pass filter */
365         result = inv_serial_single_write(mlsl_handle, pdata->address,
366                                          LIS331DLH_CTRL_REG2, 0x0F);
367         if (result) {
368                 LOG_RESULT_LOCATION(result);
369                 return result;
370         }
371
372         if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
373                 reg1 = 0x02;
374                 reg2 = 0x00;
375         } else if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
376                 reg1 = 0x00;
377                 reg2 = private_data->resume.mot_int1_cfg;
378         } else {
379                 reg1 = 0x00;
380                 reg2 = 0x00;
381         }
382         result = inv_serial_single_write(mlsl_handle, pdata->address,
383                                          LIS331DLH_CTRL_REG3, reg1);
384         if (result) {
385                 LOG_RESULT_LOCATION(result);
386                 return result;
387         }
388         result = inv_serial_single_write(mlsl_handle, pdata->address,
389                                          LIS331DLH_INT1_THS,
390                                          private_data->resume.reg_ths);
391         if (result) {
392                 LOG_RESULT_LOCATION(result);
393                 return result;
394         }
395         result = inv_serial_single_write(mlsl_handle, pdata->address,
396                                          LIS331DLH_INT1_DURATION,
397                                          private_data->resume.reg_dur);
398         if (result) {
399                 LOG_RESULT_LOCATION(result);
400                 return result;
401         }
402         result = inv_serial_single_write(mlsl_handle, pdata->address,
403                                          LIS331DLH_INT1_CFG, reg2);
404         if (result) {
405                 LOG_RESULT_LOCATION(result);
406                 return result;
407         }
408         result = inv_serial_read(mlsl_handle, pdata->address,
409                                  LIS331DLH_HP_FILTER_RESET, 1, &reg1);
410         if (result) {
411                 LOG_RESULT_LOCATION(result);
412                 return result;
413         }
414         return result;
415 }
416
417 static int lis331dlh_read(void *mlsl_handle,
418                           struct ext_slave_descr *slave,
419                           struct ext_slave_platform_data *pdata,
420                           unsigned char *data)
421 {
422         int result = INV_SUCCESS;
423         result = inv_serial_read(mlsl_handle, pdata->address,
424                                  LIS331DLH_STATUS_REG, 1, data);
425         if (data[0] & 0x0F) {
426                 result = inv_serial_read(mlsl_handle, pdata->address,
427                                          slave->read_reg, slave->read_len,
428                                          data);
429                 return result;
430         } else
431                 return INV_ERROR_ACCEL_DATA_NOT_READY;
432 }
433
434 static int lis331dlh_init(void *mlsl_handle,
435                           struct ext_slave_descr *slave,
436                           struct ext_slave_platform_data *pdata)
437 {
438         struct lis331dlh_private_data *private_data;
439         long range;
440         private_data = (struct lis331dlh_private_data *)
441             kzalloc(sizeof(struct lis331dlh_private_data), GFP_KERNEL);
442
443         if (!private_data)
444                 return INV_ERROR_MEMORY_EXAUSTED;
445
446         pdata->private_data = private_data;
447
448         private_data->resume.ctrl_reg1 = 0x37;
449         private_data->suspend.ctrl_reg1 = 0x47;
450         private_data->resume.mot_int1_cfg = 0x95;
451         private_data->suspend.mot_int1_cfg = 0x2a;
452
453         lis331dlh_set_odr(mlsl_handle, pdata, &private_data->suspend, false, 0);
454         lis331dlh_set_odr(mlsl_handle, pdata, &private_data->resume,
455                           false, 200000);
456
457         range = range_fixedpoint_to_long_mg(slave->range);
458         lis331dlh_set_fsr(mlsl_handle, pdata, &private_data->suspend,
459                         false, range);
460         lis331dlh_set_fsr(mlsl_handle, pdata, &private_data->resume,
461                         false, range);
462
463         lis331dlh_set_ths(mlsl_handle, pdata, &private_data->suspend,
464                           false, 80);
465         lis331dlh_set_ths(mlsl_handle, pdata, &private_data->resume, false, 40);
466
467
468         lis331dlh_set_dur(mlsl_handle, pdata, &private_data->suspend,
469                           false, 1000);
470         lis331dlh_set_dur(mlsl_handle, pdata, &private_data->resume,
471                           false, 2540);
472
473         lis331dlh_set_irq(mlsl_handle, pdata, &private_data->suspend,
474                           false, MPU_SLAVE_IRQ_TYPE_NONE);
475         lis331dlh_set_irq(mlsl_handle, pdata, &private_data->resume,
476                           false, MPU_SLAVE_IRQ_TYPE_NONE);
477         return INV_SUCCESS;
478 }
479
480 static int lis331dlh_exit(void *mlsl_handle,
481                           struct ext_slave_descr *slave,
482                           struct ext_slave_platform_data *pdata)
483 {
484         kfree(pdata->private_data);
485         return INV_SUCCESS;
486 }
487
488 static int lis331dlh_config(void *mlsl_handle,
489                             struct ext_slave_descr *slave,
490                             struct ext_slave_platform_data *pdata,
491                             struct ext_slave_config *data)
492 {
493         struct lis331dlh_private_data *private_data = pdata->private_data;
494         if (!data->data)
495                 return INV_ERROR_INVALID_PARAMETER;
496
497         switch (data->key) {
498         case MPU_SLAVE_CONFIG_ODR_SUSPEND:
499                 return lis331dlh_set_odr(mlsl_handle, pdata,
500                                          &private_data->suspend,
501                                          data->apply, *((long *)data->data));
502         case MPU_SLAVE_CONFIG_ODR_RESUME:
503                 return lis331dlh_set_odr(mlsl_handle, pdata,
504                                          &private_data->resume,
505                                          data->apply, *((long *)data->data));
506         case MPU_SLAVE_CONFIG_FSR_SUSPEND:
507                 return lis331dlh_set_fsr(mlsl_handle, pdata,
508                                          &private_data->suspend,
509                                          data->apply, *((long *)data->data));
510         case MPU_SLAVE_CONFIG_FSR_RESUME:
511                 return lis331dlh_set_fsr(mlsl_handle, pdata,
512                                          &private_data->resume,
513                                          data->apply, *((long *)data->data));
514         case MPU_SLAVE_CONFIG_MOT_THS:
515                 return lis331dlh_set_ths(mlsl_handle, pdata,
516                                          &private_data->suspend,
517                                          data->apply, *((long *)data->data));
518         case MPU_SLAVE_CONFIG_NMOT_THS:
519                 return lis331dlh_set_ths(mlsl_handle, pdata,
520                                          &private_data->resume,
521                                          data->apply, *((long *)data->data));
522         case MPU_SLAVE_CONFIG_MOT_DUR:
523                 return lis331dlh_set_dur(mlsl_handle, pdata,
524                                          &private_data->suspend,
525                                          data->apply, *((long *)data->data));
526         case MPU_SLAVE_CONFIG_NMOT_DUR:
527                 return lis331dlh_set_dur(mlsl_handle, pdata,
528                                          &private_data->resume,
529                                          data->apply, *((long *)data->data));
530         case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
531                 return lis331dlh_set_irq(mlsl_handle, pdata,
532                                          &private_data->suspend,
533                                          data->apply, *((long *)data->data));
534         case MPU_SLAVE_CONFIG_IRQ_RESUME:
535                 return lis331dlh_set_irq(mlsl_handle, pdata,
536                                          &private_data->resume,
537                                          data->apply, *((long *)data->data));
538         default:
539                 LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
540                 return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
541         };
542
543         return INV_SUCCESS;
544 }
545
546 static int lis331dlh_get_config(void *mlsl_handle,
547                                 struct ext_slave_descr *slave,
548                                 struct ext_slave_platform_data *pdata,
549                                 struct ext_slave_config *data)
550 {
551         struct lis331dlh_private_data *private_data = pdata->private_data;
552         if (!data->data)
553                 return INV_ERROR_INVALID_PARAMETER;
554
555         switch (data->key) {
556         case MPU_SLAVE_CONFIG_ODR_SUSPEND:
557                 (*(unsigned long *)data->data) =
558                     (unsigned long)private_data->suspend.odr;
559                 break;
560         case MPU_SLAVE_CONFIG_ODR_RESUME:
561                 (*(unsigned long *)data->data) =
562                     (unsigned long)private_data->resume.odr;
563                 break;
564         case MPU_SLAVE_CONFIG_FSR_SUSPEND:
565                 (*(unsigned long *)data->data) =
566                     (unsigned long)private_data->suspend.fsr;
567                 break;
568         case MPU_SLAVE_CONFIG_FSR_RESUME:
569                 (*(unsigned long *)data->data) =
570                     (unsigned long)private_data->resume.fsr;
571                 break;
572         case MPU_SLAVE_CONFIG_MOT_THS:
573                 (*(unsigned long *)data->data) =
574                     (unsigned long)private_data->suspend.ths;
575                 break;
576         case MPU_SLAVE_CONFIG_NMOT_THS:
577                 (*(unsigned long *)data->data) =
578                     (unsigned long)private_data->resume.ths;
579                 break;
580         case MPU_SLAVE_CONFIG_MOT_DUR:
581                 (*(unsigned long *)data->data) =
582                     (unsigned long)private_data->suspend.dur;
583                 break;
584         case MPU_SLAVE_CONFIG_NMOT_DUR:
585                 (*(unsigned long *)data->data) =
586                     (unsigned long)private_data->resume.dur;
587                 break;
588         case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
589                 (*(unsigned long *)data->data) =
590                     (unsigned long)private_data->suspend.irq_type;
591                 break;
592         case MPU_SLAVE_CONFIG_IRQ_RESUME:
593                 (*(unsigned long *)data->data) =
594                     (unsigned long)private_data->resume.irq_type;
595                 break;
596         default:
597                 LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
598                 return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
599         };
600
601         return INV_SUCCESS;
602 }
603
604 static struct ext_slave_descr lis331dlh_descr = {
605         .init             = lis331dlh_init,
606         .exit             = lis331dlh_exit,
607         .suspend          = lis331dlh_suspend,
608         .resume           = lis331dlh_resume,
609         .read             = lis331dlh_read,
610         .config           = lis331dlh_config,
611         .get_config       = lis331dlh_get_config,
612         .name             = "lis331dlh",
613         .type             = EXT_SLAVE_TYPE_ACCEL,
614         .id               = ACCEL_ID_LIS331,
615         .read_reg         = (0x28 | 0x80), /* 0x80 for burst reads */
616         .read_len         = 6,
617         .endian           = EXT_SLAVE_BIG_ENDIAN,
618         .range            = {2, 480},
619         .trigger          = NULL,
620 };
621
622 static
623 struct ext_slave_descr *lis331_get_slave_descr(void)
624 {
625         return &lis331dlh_descr;
626 }
627
628 /* -------------------------------------------------------------------------- */
629 struct lis331_mod_private_data {
630         struct i2c_client *client;
631         struct ext_slave_platform_data *pdata;
632 };
633
634 static unsigned short normal_i2c[] = { I2C_CLIENT_END };
635
636 static int lis331_mod_probe(struct i2c_client *client,
637                            const struct i2c_device_id *devid)
638 {
639         struct ext_slave_platform_data *pdata;
640         struct lis331_mod_private_data *private_data;
641         int result = 0;
642
643         dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
644
645         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
646                 result = -ENODEV;
647                 goto out_no_free;
648         }
649
650         pdata = client->dev.platform_data;
651         if (!pdata) {
652                 dev_err(&client->adapter->dev,
653                         "Missing platform data for slave %s\n", devid->name);
654                 result = -EFAULT;
655                 goto out_no_free;
656         }
657
658         private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
659         if (!private_data) {
660                 result = -ENOMEM;
661                 goto out_no_free;
662         }
663
664         i2c_set_clientdata(client, private_data);
665         private_data->client = client;
666         private_data->pdata = pdata;
667
668         result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
669                                         lis331_get_slave_descr);
670         if (result) {
671                 dev_err(&client->adapter->dev,
672                         "Slave registration failed: %s, %d\n",
673                         devid->name, result);
674                 goto out_free_memory;
675         }
676
677         return result;
678
679 out_free_memory:
680         kfree(private_data);
681 out_no_free:
682         dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
683         return result;
684
685 }
686
687 static int lis331_mod_remove(struct i2c_client *client)
688 {
689         struct lis331_mod_private_data *private_data =
690                 i2c_get_clientdata(client);
691
692         dev_dbg(&client->adapter->dev, "%s\n", __func__);
693
694         inv_mpu_unregister_slave(client, private_data->pdata,
695                                 lis331_get_slave_descr);
696
697         kfree(private_data);
698         return 0;
699 }
700
701 static const struct i2c_device_id lis331_mod_id[] = {
702         { "lis331", ACCEL_ID_LIS331 },
703         {}
704 };
705
706 MODULE_DEVICE_TABLE(i2c, lis331_mod_id);
707
708 static struct i2c_driver lis331_mod_driver = {
709         .class = I2C_CLASS_HWMON,
710         .probe = lis331_mod_probe,
711         .remove = lis331_mod_remove,
712         .id_table = lis331_mod_id,
713         .driver = {
714                    .owner = THIS_MODULE,
715                    .name = "lis331_mod",
716                    },
717         .address_list = normal_i2c,
718 };
719
720 static int __init lis331_mod_init(void)
721 {
722         int res = i2c_add_driver(&lis331_mod_driver);
723         pr_info("%s: Probe name %s\n", __func__, "lis331_mod");
724         if (res)
725                 pr_err("%s failed\n", __func__);
726         return res;
727 }
728
729 static void __exit lis331_mod_exit(void)
730 {
731         pr_info("%s\n", __func__);
732         i2c_del_driver(&lis331_mod_driver);
733 }
734
735 module_init(lis331_mod_init);
736 module_exit(lis331_mod_exit);
737
738 MODULE_AUTHOR("Invensense Corporation");
739 MODULE_DESCRIPTION("Driver to integrate LIS331 sensor with the MPU");
740 MODULE_LICENSE("GPL");
741 MODULE_ALIAS("lis331_mod");
742
743 /**
744  *  @}
745  */