This source file includes following definitions.
- mma9551_transfer
- mma9551_read_config_byte
- mma9551_write_config_byte
- mma9551_read_status_byte
- mma9551_read_config_word
- mma9551_write_config_word
- mma9551_read_status_word
- mma9551_read_config_words
- mma9551_read_status_words
- mma9551_write_config_words
- mma9551_update_config_bits
- mma9551_gpio_config
- mma9551_read_version
- mma9551_set_device_state
- mma9551_set_power_state
- mma9551_sleep
- mma9551_read_accel_chan
- mma9551_read_accel_scale
- mma9551_app_reset
1
2
3
4
5
6
7 #include <linux/module.h>
8 #include <linux/i2c.h>
9 #include <linux/delay.h>
10 #include <linux/iio/iio.h>
11 #include <linux/pm_runtime.h>
12 #include "mma9551_core.h"
13
14
15 #define MMA9551_CMD_READ_VERSION_INFO 0x00
16 #define MMA9551_CMD_READ_CONFIG 0x10
17 #define MMA9551_CMD_WRITE_CONFIG 0x20
18 #define MMA9551_CMD_READ_STATUS 0x30
19
20
21 #define MMA9551_RESPONSE_COCO BIT(7)
22
23
24 #define MMA9551_MCI_ERROR_NONE 0x00
25 #define MMA9551_MCI_ERROR_PARAM 0x04
26 #define MMA9551_MCI_INVALID_COUNT 0x19
27 #define MMA9551_MCI_ERROR_COMMAND 0x1C
28 #define MMA9551_MCI_ERROR_INVALID_LENGTH 0x21
29 #define MMA9551_MCI_ERROR_FIFO_BUSY 0x22
30 #define MMA9551_MCI_ERROR_FIFO_ALLOCATED 0x23
31 #define MMA9551_MCI_ERROR_FIFO_OVERSIZE 0x24
32
33
34 #define MMA9551_GPIO_POL_MSB 0x08
35 #define MMA9551_GPIO_POL_LSB 0x09
36
37
38 #define MMA9551_SLEEP_CFG 0x06
39 #define MMA9551_SLEEP_CFG_SNCEN BIT(0)
40 #define MMA9551_SLEEP_CFG_FLEEN BIT(1)
41 #define MMA9551_SLEEP_CFG_SCHEN BIT(2)
42
43
44 #define MMA9551_AFE_X_ACCEL_REG 0x00
45 #define MMA9551_AFE_Y_ACCEL_REG 0x02
46 #define MMA9551_AFE_Z_ACCEL_REG 0x04
47
48
49 #define MMA9551_RSC_RESET 0x00
50 #define MMA9551_RSC_OFFSET(mask) (3 - (ffs(mask) - 1) / 8)
51 #define MMA9551_RSC_VAL(mask) (mask >> (((ffs(mask) - 1) / 8) * 8))
52
53
54
55
56
57
58
59
60
61
62
63 #define MMA9551_MAILBOX_CTRL_REGS 4
64 #define MMA9551_MAX_MAILBOX_DATA_REGS 28
65 #define MMA9551_MAILBOX_REGS 32
66
67 #define MMA9551_I2C_READ_RETRIES 5
68 #define MMA9551_I2C_READ_DELAY 50
69
70 struct mma9551_mbox_request {
71 u8 start_mbox;
72 u8 app_id;
73
74
75
76
77
78
79
80 u8 cmd_off;
81 u8 lower_off;
82 u8 nbytes;
83 u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1];
84 } __packed;
85
86 struct mma9551_mbox_response {
87 u8 app_id;
88
89
90
91
92
93
94 u8 coco_err;
95 u8 nbytes;
96 u8 req_bytes;
97 u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS];
98 } __packed;
99
100 struct mma9551_version_info {
101 __be32 device_id;
102 u8 rom_version[2];
103 u8 fw_version[2];
104 u8 hw_version[2];
105 u8 fw_build[2];
106 };
107
108 static int mma9551_transfer(struct i2c_client *client,
109 u8 app_id, u8 command, u16 offset,
110 u8 *inbytes, int num_inbytes,
111 u8 *outbytes, int num_outbytes)
112 {
113 struct mma9551_mbox_request req;
114 struct mma9551_mbox_response rsp;
115 struct i2c_msg in, out;
116 u8 req_len, err_code;
117 int ret, retries;
118
119 if (offset >= 1 << 12) {
120 dev_err(&client->dev, "register offset too large\n");
121 return -EINVAL;
122 }
123
124 req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes;
125 req.start_mbox = 0;
126 req.app_id = app_id;
127 req.cmd_off = command | (offset >> 8);
128 req.lower_off = offset;
129
130 if (command == MMA9551_CMD_WRITE_CONFIG)
131 req.nbytes = num_inbytes;
132 else
133 req.nbytes = num_outbytes;
134 if (num_inbytes)
135 memcpy(req.buf, inbytes, num_inbytes);
136
137 out.addr = client->addr;
138 out.flags = 0;
139 out.len = req_len;
140 out.buf = (u8 *)&req;
141
142 ret = i2c_transfer(client->adapter, &out, 1);
143 if (ret < 0) {
144 dev_err(&client->dev, "i2c write failed\n");
145 return ret;
146 }
147
148 retries = MMA9551_I2C_READ_RETRIES;
149 do {
150 udelay(MMA9551_I2C_READ_DELAY);
151
152 in.addr = client->addr;
153 in.flags = I2C_M_RD;
154 in.len = sizeof(rsp);
155 in.buf = (u8 *)&rsp;
156
157 ret = i2c_transfer(client->adapter, &in, 1);
158 if (ret < 0) {
159 dev_err(&client->dev, "i2c read failed\n");
160 return ret;
161 }
162
163 if (rsp.coco_err & MMA9551_RESPONSE_COCO)
164 break;
165 } while (--retries > 0);
166
167 if (retries == 0) {
168 dev_err(&client->dev,
169 "timed out while waiting for command response\n");
170 return -ETIMEDOUT;
171 }
172
173 if (rsp.app_id != app_id) {
174 dev_err(&client->dev,
175 "app_id mismatch in response got %02x expected %02x\n",
176 rsp.app_id, app_id);
177 return -EINVAL;
178 }
179
180 err_code = rsp.coco_err & ~MMA9551_RESPONSE_COCO;
181 if (err_code != MMA9551_MCI_ERROR_NONE) {
182 dev_err(&client->dev, "read returned error %x\n", err_code);
183 return -EINVAL;
184 }
185
186 if (rsp.nbytes != rsp.req_bytes) {
187 dev_err(&client->dev,
188 "output length mismatch got %d expected %d\n",
189 rsp.nbytes, rsp.req_bytes);
190 return -EINVAL;
191 }
192
193 if (num_outbytes)
194 memcpy(outbytes, rsp.buf, num_outbytes);
195
196 return 0;
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216 int mma9551_read_config_byte(struct i2c_client *client, u8 app_id,
217 u16 reg, u8 *val)
218 {
219 return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
220 reg, NULL, 0, val, 1);
221 }
222 EXPORT_SYMBOL(mma9551_read_config_byte);
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 int mma9551_write_config_byte(struct i2c_client *client, u8 app_id,
242 u16 reg, u8 val)
243 {
244 return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
245 &val, 1, NULL, 0);
246 }
247 EXPORT_SYMBOL(mma9551_write_config_byte);
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266 int mma9551_read_status_byte(struct i2c_client *client, u8 app_id,
267 u16 reg, u8 *val)
268 {
269 return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
270 reg, NULL, 0, val, 1);
271 }
272 EXPORT_SYMBOL(mma9551_read_status_byte);
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291 int mma9551_read_config_word(struct i2c_client *client, u8 app_id,
292 u16 reg, u16 *val)
293 {
294 int ret;
295 __be16 v;
296
297 ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
298 reg, NULL, 0, (u8 *)&v, 2);
299 *val = be16_to_cpu(v);
300
301 return ret;
302 }
303 EXPORT_SYMBOL(mma9551_read_config_word);
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322 int mma9551_write_config_word(struct i2c_client *client, u8 app_id,
323 u16 reg, u16 val)
324 {
325 __be16 v = cpu_to_be16(val);
326
327 return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
328 (u8 *)&v, 2, NULL, 0);
329 }
330 EXPORT_SYMBOL(mma9551_write_config_word);
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 int mma9551_read_status_word(struct i2c_client *client, u8 app_id,
350 u16 reg, u16 *val)
351 {
352 int ret;
353 __be16 v;
354
355 ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
356 reg, NULL, 0, (u8 *)&v, 2);
357 *val = be16_to_cpu(v);
358
359 return ret;
360 }
361 EXPORT_SYMBOL(mma9551_read_status_word);
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379 int mma9551_read_config_words(struct i2c_client *client, u8 app_id,
380 u16 reg, u8 len, u16 *buf)
381 {
382 int ret, i;
383 __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
384
385 if (len > ARRAY_SIZE(be_buf)) {
386 dev_err(&client->dev, "Invalid buffer size %d\n", len);
387 return -EINVAL;
388 }
389
390 ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
391 reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16));
392 if (ret < 0)
393 return ret;
394
395 for (i = 0; i < len; i++)
396 buf[i] = be16_to_cpu(be_buf[i]);
397
398 return 0;
399 }
400 EXPORT_SYMBOL(mma9551_read_config_words);
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418 int mma9551_read_status_words(struct i2c_client *client, u8 app_id,
419 u16 reg, u8 len, u16 *buf)
420 {
421 int ret, i;
422 __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
423
424 if (len > ARRAY_SIZE(be_buf)) {
425 dev_err(&client->dev, "Invalid buffer size %d\n", len);
426 return -EINVAL;
427 }
428
429 ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
430 reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16));
431 if (ret < 0)
432 return ret;
433
434 for (i = 0; i < len; i++)
435 buf[i] = be16_to_cpu(be_buf[i]);
436
437 return 0;
438 }
439 EXPORT_SYMBOL(mma9551_read_status_words);
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457 int mma9551_write_config_words(struct i2c_client *client, u8 app_id,
458 u16 reg, u8 len, u16 *buf)
459 {
460 int i;
461 __be16 be_buf[(MMA9551_MAX_MAILBOX_DATA_REGS - 1) / 2];
462
463 if (len > ARRAY_SIZE(be_buf)) {
464 dev_err(&client->dev, "Invalid buffer size %d\n", len);
465 return -EINVAL;
466 }
467
468 for (i = 0; i < len; i++)
469 be_buf[i] = cpu_to_be16(buf[i]);
470
471 return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG,
472 reg, (u8 *)be_buf, len * sizeof(u16), NULL, 0);
473 }
474 EXPORT_SYMBOL(mma9551_write_config_words);
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492 int mma9551_update_config_bits(struct i2c_client *client, u8 app_id,
493 u16 reg, u8 mask, u8 val)
494 {
495 int ret;
496 u8 tmp, orig;
497
498 ret = mma9551_read_config_byte(client, app_id, reg, &orig);
499 if (ret < 0)
500 return ret;
501
502 tmp = orig & ~mask;
503 tmp |= val & mask;
504
505 if (tmp == orig)
506 return 0;
507
508 return mma9551_write_config_byte(client, app_id, reg, tmp);
509 }
510 EXPORT_SYMBOL(mma9551_update_config_bits);
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531 int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin,
532 u8 app_id, u8 bitnum, int polarity)
533 {
534 u8 reg, pol_mask, pol_val;
535 int ret;
536
537 if (pin > mma9551_gpio_max) {
538 dev_err(&client->dev, "bad GPIO pin\n");
539 return -EINVAL;
540 }
541
542
543
544
545
546 reg = pin * 2;
547
548 ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO,
549 reg, app_id);
550 if (ret < 0) {
551 dev_err(&client->dev, "error setting GPIO app_id\n");
552 return ret;
553 }
554
555 ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO,
556 reg + 1, bitnum);
557 if (ret < 0) {
558 dev_err(&client->dev, "error setting GPIO bit number\n");
559 return ret;
560 }
561
562 switch (pin) {
563 case mma9551_gpio6:
564 reg = MMA9551_GPIO_POL_LSB;
565 pol_mask = 1 << 6;
566 break;
567 case mma9551_gpio7:
568 reg = MMA9551_GPIO_POL_LSB;
569 pol_mask = 1 << 7;
570 break;
571 case mma9551_gpio8:
572 reg = MMA9551_GPIO_POL_MSB;
573 pol_mask = 1 << 0;
574 break;
575 case mma9551_gpio9:
576 reg = MMA9551_GPIO_POL_MSB;
577 pol_mask = 1 << 1;
578 break;
579 }
580 pol_val = polarity ? pol_mask : 0;
581
582 ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg,
583 pol_mask, pol_val);
584 if (ret < 0)
585 dev_err(&client->dev, "error setting GPIO polarity\n");
586
587 return ret;
588 }
589 EXPORT_SYMBOL(mma9551_gpio_config);
590
591
592
593
594
595
596
597
598
599
600
601
602
603 int mma9551_read_version(struct i2c_client *client)
604 {
605 struct mma9551_version_info info;
606 int ret;
607
608 ret = mma9551_transfer(client, MMA9551_APPID_VERSION, 0x00, 0x00,
609 NULL, 0, (u8 *)&info, sizeof(info));
610 if (ret < 0)
611 return ret;
612
613 dev_info(&client->dev, "device ID 0x%x, firmware version %02x.%02x\n",
614 be32_to_cpu(info.device_id), info.fw_version[0],
615 info.fw_version[1]);
616
617 return 0;
618 }
619 EXPORT_SYMBOL(mma9551_read_version);
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638 int mma9551_set_device_state(struct i2c_client *client, bool enable)
639 {
640 return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE,
641 MMA9551_SLEEP_CFG,
642 MMA9551_SLEEP_CFG_SNCEN |
643 MMA9551_SLEEP_CFG_FLEEN |
644 MMA9551_SLEEP_CFG_SCHEN,
645 enable ? MMA9551_SLEEP_CFG_SCHEN |
646 MMA9551_SLEEP_CFG_FLEEN :
647 MMA9551_SLEEP_CFG_SNCEN);
648 }
649 EXPORT_SYMBOL(mma9551_set_device_state);
650
651
652
653
654
655
656
657
658
659
660
661 int mma9551_set_power_state(struct i2c_client *client, bool on)
662 {
663 #ifdef CONFIG_PM
664 int ret;
665
666 if (on)
667 ret = pm_runtime_get_sync(&client->dev);
668 else {
669 pm_runtime_mark_last_busy(&client->dev);
670 ret = pm_runtime_put_autosuspend(&client->dev);
671 }
672
673 if (ret < 0) {
674 dev_err(&client->dev,
675 "failed to change power state to %d\n", on);
676 if (on)
677 pm_runtime_put_noidle(&client->dev);
678
679 return ret;
680 }
681 #endif
682
683 return 0;
684 }
685 EXPORT_SYMBOL(mma9551_set_power_state);
686
687
688
689
690
691
692
693
694
695 void mma9551_sleep(int freq)
696 {
697 int sleep_val = 1000 / freq;
698
699 if (sleep_val < 20)
700 usleep_range(sleep_val * 1000, 20000);
701 else
702 msleep_interruptible(sleep_val);
703 }
704 EXPORT_SYMBOL(mma9551_sleep);
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721 int mma9551_read_accel_chan(struct i2c_client *client,
722 const struct iio_chan_spec *chan,
723 int *val, int *val2)
724 {
725 u16 reg_addr;
726 s16 raw_accel;
727 int ret;
728
729 switch (chan->channel2) {
730 case IIO_MOD_X:
731 reg_addr = MMA9551_AFE_X_ACCEL_REG;
732 break;
733 case IIO_MOD_Y:
734 reg_addr = MMA9551_AFE_Y_ACCEL_REG;
735 break;
736 case IIO_MOD_Z:
737 reg_addr = MMA9551_AFE_Z_ACCEL_REG;
738 break;
739 default:
740 return -EINVAL;
741 }
742
743 ret = mma9551_set_power_state(client, true);
744 if (ret < 0)
745 return ret;
746
747 ret = mma9551_read_status_word(client, MMA9551_APPID_AFE,
748 reg_addr, &raw_accel);
749 if (ret < 0)
750 goto out_poweroff;
751
752 *val = raw_accel;
753
754 ret = IIO_VAL_INT;
755
756 out_poweroff:
757 mma9551_set_power_state(client, false);
758 return ret;
759 }
760 EXPORT_SYMBOL(mma9551_read_accel_chan);
761
762
763
764
765
766
767
768
769
770
771 int mma9551_read_accel_scale(int *val, int *val2)
772 {
773 *val = 0;
774 *val2 = 2440;
775
776 return IIO_VAL_INT_PLUS_MICRO;
777 }
778 EXPORT_SYMBOL(mma9551_read_accel_scale);
779
780
781
782
783
784
785
786
787
788
789
790 int mma9551_app_reset(struct i2c_client *client, u32 app_mask)
791 {
792 return mma9551_write_config_byte(client, MMA9551_APPID_RSC,
793 MMA9551_RSC_RESET +
794 MMA9551_RSC_OFFSET(app_mask),
795 MMA9551_RSC_VAL(app_mask));
796 }
797 EXPORT_SYMBOL(mma9551_app_reset);
798
799 MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
800 MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
801 MODULE_LICENSE("GPL v2");
802 MODULE_DESCRIPTION("MMA955xL sensors core");