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
70struct 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
86struct 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
100struct 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
108static 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
216int 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}
222EXPORT_SYMBOL(mma9551_read_config_byte);
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241int 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}
247EXPORT_SYMBOL(mma9551_write_config_byte);
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266int 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}
272EXPORT_SYMBOL(mma9551_read_status_byte);
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291int 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}
303EXPORT_SYMBOL(mma9551_read_config_word);
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322int 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}
330EXPORT_SYMBOL(mma9551_write_config_word);
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349int 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}
361EXPORT_SYMBOL(mma9551_read_status_word);
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379int 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}
400EXPORT_SYMBOL(mma9551_read_config_words);
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418int 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}
439EXPORT_SYMBOL(mma9551_read_status_words);
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457int 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}
474EXPORT_SYMBOL(mma9551_write_config_words);
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492int 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}
510EXPORT_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
531int 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}
589EXPORT_SYMBOL(mma9551_gpio_config);
590
591
592
593
594
595
596
597
598
599
600
601
602
603int 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}
619EXPORT_SYMBOL(mma9551_read_version);
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638int 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}
649EXPORT_SYMBOL(mma9551_set_device_state);
650
651
652
653
654
655
656
657
658
659
660
661int 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_resume_and_get(&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
677 return ret;
678 }
679#endif
680
681 return 0;
682}
683EXPORT_SYMBOL(mma9551_set_power_state);
684
685
686
687
688
689
690
691
692
693void mma9551_sleep(int freq)
694{
695 int sleep_val = 1000 / freq;
696
697 if (sleep_val < 20)
698 usleep_range(sleep_val * 1000, 20000);
699 else
700 msleep_interruptible(sleep_val);
701}
702EXPORT_SYMBOL(mma9551_sleep);
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719int mma9551_read_accel_chan(struct i2c_client *client,
720 const struct iio_chan_spec *chan,
721 int *val, int *val2)
722{
723 u16 reg_addr;
724 s16 raw_accel;
725 int ret;
726
727 switch (chan->channel2) {
728 case IIO_MOD_X:
729 reg_addr = MMA9551_AFE_X_ACCEL_REG;
730 break;
731 case IIO_MOD_Y:
732 reg_addr = MMA9551_AFE_Y_ACCEL_REG;
733 break;
734 case IIO_MOD_Z:
735 reg_addr = MMA9551_AFE_Z_ACCEL_REG;
736 break;
737 default:
738 return -EINVAL;
739 }
740
741 ret = mma9551_set_power_state(client, true);
742 if (ret < 0)
743 return ret;
744
745 ret = mma9551_read_status_word(client, MMA9551_APPID_AFE,
746 reg_addr, &raw_accel);
747 if (ret < 0)
748 goto out_poweroff;
749
750 *val = raw_accel;
751
752 ret = IIO_VAL_INT;
753
754out_poweroff:
755 mma9551_set_power_state(client, false);
756 return ret;
757}
758EXPORT_SYMBOL(mma9551_read_accel_chan);
759
760
761
762
763
764
765
766
767
768
769int mma9551_read_accel_scale(int *val, int *val2)
770{
771 *val = 0;
772 *val2 = 2440;
773
774 return IIO_VAL_INT_PLUS_MICRO;
775}
776EXPORT_SYMBOL(mma9551_read_accel_scale);
777
778
779
780
781
782
783
784
785
786
787
788int mma9551_app_reset(struct i2c_client *client, u32 app_mask)
789{
790 return mma9551_write_config_byte(client, MMA9551_APPID_RSC,
791 MMA9551_RSC_RESET +
792 MMA9551_RSC_OFFSET(app_mask),
793 MMA9551_RSC_VAL(app_mask));
794}
795EXPORT_SYMBOL(mma9551_app_reset);
796
797MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
798MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
799MODULE_LICENSE("GPL v2");
800MODULE_DESCRIPTION("MMA955xL sensors core");
801