aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorIrina Tirdea <irina.tirdea@intel.com>2015-01-11 14:10:15 -0500
committerJonathan Cameron <jic23@kernel.org>2015-01-27 13:49:56 -0500
commitd5b97f5c7dfcad98927fb4f3b2e99d4c3beeec9a (patch)
treebe9edae8271a45921155e7dee3ea72ba8258eceb /drivers/iio
parent6da93a6710a3b1eb3d15b88bf96efaac322c893f (diff)
iio: accel: mma9551: split driver to expose mma955x api
Freescale has the MMA955xL family of devices that use the same communication protocol (based on i2c messages): http://www.freescale.com/files/sensors/doc/data_sheet/MMA955xL.pdf. To support more devices from this family, we need to split the mma9551 driver so we can export the common functions that will be used by other mma955x drivers. Signed-off-by: Irina Tirdea <irina.tirdea@intel.com> Reviewed-by: Vlad Dogaru <vlad.dogaru@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/accel/Kconfig5
-rw-r--r--drivers/iio/accel/Makefile4
-rw-r--r--drivers/iio/accel/mma9551.c443
-rw-r--r--drivers/iio/accel/mma9551_core.c615
-rw-r--r--drivers/iio/accel/mma9551_core.h66
5 files changed, 693 insertions, 440 deletions
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 9f67c10291bd..c53047d28ad3 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -111,9 +111,14 @@ config KXCJK1013
111 To compile this driver as a module, choose M here: the module will 111 To compile this driver as a module, choose M here: the module will
112 be called kxcjk-1013. 112 be called kxcjk-1013.
113 113
114config MMA9551_CORE
115 tristate
116
114config MMA9551 117config MMA9551
115 tristate "Freescale MMA9551L Intelligent Motion-Sensing Platform Driver" 118 tristate "Freescale MMA9551L Intelligent Motion-Sensing Platform Driver"
116 depends on I2C 119 depends on I2C
120 select MMA9551_CORE
121
117 help 122 help
118 Say yes here to build support for the Freescale MMA9551L 123 Say yes here to build support for the Freescale MMA9551L
119 Intelligent Motion-Sensing Platform Driver. 124 Intelligent Motion-Sensing Platform Driver.
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index de5b9cb9670f..810531610414 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -9,7 +9,9 @@ obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
9obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o 9obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
10obj-$(CONFIG_KXSD9) += kxsd9.o 10obj-$(CONFIG_KXSD9) += kxsd9.o
11obj-$(CONFIG_MMA8452) += mma8452.o 11obj-$(CONFIG_MMA8452) += mma8452.o
12obj-$(CONFIG_MMA9551) += mma9551.o 12
13obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o
14obj-$(CONFIG_MMA9551) += mma9551.o
13 15
14obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o 16obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
15st_accel-y := st_accel_core.o 17st_accel-y := st_accel_core.o
diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
index f1a5a06a0726..46c38351c6a3 100644
--- a/drivers/iio/accel/mma9551.c
+++ b/drivers/iio/accel/mma9551.c
@@ -23,63 +23,13 @@
23#include <linux/iio/sysfs.h> 23#include <linux/iio/sysfs.h>
24#include <linux/iio/events.h> 24#include <linux/iio/events.h>
25#include <linux/pm_runtime.h> 25#include <linux/pm_runtime.h>
26#include "mma9551_core.h"
26 27
27#define MMA9551_DRV_NAME "mma9551" 28#define MMA9551_DRV_NAME "mma9551"
28#define MMA9551_IRQ_NAME "mma9551_event" 29#define MMA9551_IRQ_NAME "mma9551_event"
29#define MMA9551_GPIO_NAME "mma9551_int" 30#define MMA9551_GPIO_NAME "mma9551_int"
30#define MMA9551_GPIO_COUNT 4 31#define MMA9551_GPIO_COUNT 4
31 32
32/* Applications IDs */
33#define MMA9551_APPID_VERSION 0x00
34#define MMA9551_APPID_GPIO 0x03
35#define MMA9551_APPID_AFE 0x06
36#define MMA9551_APPID_TILT 0x0B
37#define MMA9551_APPID_SLEEP_WAKE 0x12
38#define MMA9551_APPID_RESET 0x17
39#define MMA9551_APPID_NONE 0xff
40
41/* Command masks for mailbox write command */
42#define MMA9551_CMD_READ_VERSION_INFO 0x00
43#define MMA9551_CMD_READ_CONFIG 0x10
44#define MMA9551_CMD_WRITE_CONFIG 0x20
45#define MMA9551_CMD_READ_STATUS 0x30
46
47enum mma9551_gpio_pin {
48 mma9551_gpio6 = 0,
49 mma9551_gpio7,
50 mma9551_gpio8,
51 mma9551_gpio9,
52 mma9551_gpio_max = mma9551_gpio9,
53};
54
55/* Mailbox read command */
56#define MMA9551_RESPONSE_COCO BIT(7)
57
58/* Error-Status codes returned in mailbox read command */
59#define MMA9551_MCI_ERROR_NONE 0x00
60#define MMA9551_MCI_ERROR_PARAM 0x04
61#define MMA9551_MCI_INVALID_COUNT 0x19
62#define MMA9551_MCI_ERROR_COMMAND 0x1C
63#define MMA9551_MCI_ERROR_INVALID_LENGTH 0x21
64#define MMA9551_MCI_ERROR_FIFO_BUSY 0x22
65#define MMA9551_MCI_ERROR_FIFO_ALLOCATED 0x23
66#define MMA9551_MCI_ERROR_FIFO_OVERSIZE 0x24
67
68/* GPIO Application */
69#define MMA9551_GPIO_POL_MSB 0x08
70#define MMA9551_GPIO_POL_LSB 0x09
71
72/* Sleep/Wake application */
73#define MMA9551_SLEEP_CFG 0x06
74#define MMA9551_SLEEP_CFG_SNCEN BIT(0)
75#define MMA9551_SLEEP_CFG_FLEEN BIT(1)
76#define MMA9551_SLEEP_CFG_SCHEN BIT(2)
77
78/* AFE application */
79#define MMA9551_AFE_X_ACCEL_REG 0x00
80#define MMA9551_AFE_Y_ACCEL_REG 0x02
81#define MMA9551_AFE_Z_ACCEL_REG 0x04
82
83/* Tilt application (inclination in IIO terms). */ 33/* Tilt application (inclination in IIO terms). */
84#define MMA9551_TILT_XZ_ANG_REG 0x00 34#define MMA9551_TILT_XZ_ANG_REG 0x00
85#define MMA9551_TILT_YZ_ANG_REG 0x01 35#define MMA9551_TILT_YZ_ANG_REG 0x01
@@ -92,6 +42,8 @@ enum mma9551_gpio_pin {
92#define MMA9551_TILT_CFG_REG 0x01 42#define MMA9551_TILT_CFG_REG 0x01
93#define MMA9551_TILT_ANG_THRESH_MASK GENMASK(3, 0) 43#define MMA9551_TILT_ANG_THRESH_MASK GENMASK(3, 0)
94 44
45#define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */
46
95/* Tilt events are mapped to the first three GPIO pins. */ 47/* Tilt events are mapped to the first three GPIO pins. */
96enum mma9551_tilt_axis { 48enum mma9551_tilt_axis {
97 mma9551_x = 0, 49 mma9551_x = 0,
@@ -99,64 +51,6 @@ enum mma9551_tilt_axis {
99 mma9551_z, 51 mma9551_z,
100}; 52};
101 53
102/*
103 * A response is composed of:
104 * - control registers: MB0-3
105 * - data registers: MB4-31
106 *
107 * A request is composed of:
108 * - mbox to write to (always 0)
109 * - control registers: MB1-4
110 * - data registers: MB5-31
111 */
112#define MMA9551_MAILBOX_CTRL_REGS 4
113#define MMA9551_MAX_MAILBOX_DATA_REGS 28
114#define MMA9551_MAILBOX_REGS 32
115
116#define MMA9551_I2C_READ_RETRIES 5
117#define MMA9551_I2C_READ_DELAY 50 /* us */
118
119#define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */
120#define MMA9551_AUTO_SUSPEND_DELAY_MS 2000
121
122struct mma9551_mbox_request {
123 u8 start_mbox; /* Always 0. */
124 u8 app_id;
125 /*
126 * See Section 5.3.1 of the MMA955xL Software Reference Manual.
127 *
128 * Bit 7: reserved, always 0
129 * Bits 6-4: command
130 * Bits 3-0: upper bits of register offset
131 */
132 u8 cmd_off;
133 u8 lower_off;
134 u8 nbytes;
135 u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1];
136} __packed;
137
138struct mma9551_mbox_response {
139 u8 app_id;
140 /*
141 * See Section 5.3.3 of the MMA955xL Software Reference Manual.
142 *
143 * Bit 7: COCO
144 * Bits 6-0: Error code.
145 */
146 u8 coco_err;
147 u8 nbytes;
148 u8 req_bytes;
149 u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS];
150} __packed;
151
152struct mma9551_version_info {
153 __be32 device_id;
154 u8 rom_version[2];
155 u8 fw_version[2];
156 u8 hw_version[2];
157 u8 fw_build[2];
158};
159
160struct mma9551_data { 54struct mma9551_data {
161 struct i2c_client *client; 55 struct i2c_client *client;
162 struct mutex mutex; 56 struct mutex mutex;
@@ -164,285 +58,6 @@ struct mma9551_data {
164 int irqs[MMA9551_GPIO_COUNT]; 58 int irqs[MMA9551_GPIO_COUNT];
165}; 59};
166 60
167static int mma9551_transfer(struct i2c_client *client,
168 u8 app_id, u8 command, u16 offset,
169 u8 *inbytes, int num_inbytes,
170 u8 *outbytes, int num_outbytes)
171{
172 struct mma9551_mbox_request req;
173 struct mma9551_mbox_response rsp;
174 struct i2c_msg in, out;
175 u8 req_len, err_code;
176 int ret, retries;
177
178 if (offset >= 1 << 12) {
179 dev_err(&client->dev, "register offset too large\n");
180 return -EINVAL;
181 }
182
183 req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes;
184 req.start_mbox = 0;
185 req.app_id = app_id;
186 req.cmd_off = command | (offset >> 8);
187 req.lower_off = offset;
188
189 if (command == MMA9551_CMD_WRITE_CONFIG)
190 req.nbytes = num_inbytes;
191 else
192 req.nbytes = num_outbytes;
193 if (num_inbytes)
194 memcpy(req.buf, inbytes, num_inbytes);
195
196 out.addr = client->addr;
197 out.flags = 0;
198 out.len = req_len;
199 out.buf = (u8 *)&req;
200
201 ret = i2c_transfer(client->adapter, &out, 1);
202 if (ret < 0) {
203 dev_err(&client->dev, "i2c write failed\n");
204 return ret;
205 }
206
207 retries = MMA9551_I2C_READ_RETRIES;
208 do {
209 udelay(MMA9551_I2C_READ_DELAY);
210
211 in.addr = client->addr;
212 in.flags = I2C_M_RD;
213 in.len = sizeof(rsp);
214 in.buf = (u8 *)&rsp;
215
216 ret = i2c_transfer(client->adapter, &in, 1);
217 if (ret < 0) {
218 dev_err(&client->dev, "i2c read failed\n");
219 return ret;
220 }
221
222 if (rsp.coco_err & MMA9551_RESPONSE_COCO)
223 break;
224 } while (--retries > 0);
225
226 if (retries == 0) {
227 dev_err(&client->dev,
228 "timed out while waiting for command response\n");
229 return -ETIMEDOUT;
230 }
231
232 if (rsp.app_id != app_id) {
233 dev_err(&client->dev,
234 "app_id mismatch in response got %02x expected %02x\n",
235 rsp.app_id, app_id);
236 return -EINVAL;
237 }
238
239 err_code = rsp.coco_err & ~MMA9551_RESPONSE_COCO;
240 if (err_code != MMA9551_MCI_ERROR_NONE) {
241 dev_err(&client->dev, "read returned error %x\n", err_code);
242 return -EINVAL;
243 }
244
245 if (rsp.nbytes != rsp.req_bytes) {
246 dev_err(&client->dev,
247 "output length mismatch got %d expected %d\n",
248 rsp.nbytes, rsp.req_bytes);
249 return -EINVAL;
250 }
251
252 if (num_outbytes)
253 memcpy(outbytes, rsp.buf, num_outbytes);
254
255 return 0;
256}
257
258static int mma9551_read_config_byte(struct i2c_client *client, u8 app_id,
259 u16 reg, u8 *val)
260{
261 return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
262 reg, NULL, 0, val, 1);
263}
264
265static int mma9551_write_config_byte(struct i2c_client *client, u8 app_id,
266 u16 reg, u8 val)
267{
268 return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
269 &val, 1, NULL, 0);
270}
271
272static int mma9551_read_status_byte(struct i2c_client *client, u8 app_id,
273 u16 reg, u8 *val)
274{
275 return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
276 reg, NULL, 0, val, 1);
277}
278
279static int mma9551_read_status_word(struct i2c_client *client, u8 app_id,
280 u16 reg, u16 *val)
281{
282 int ret;
283 __be16 v;
284
285 ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
286 reg, NULL, 0, (u8 *)&v, 2);
287 *val = be16_to_cpu(v);
288
289 return ret;
290}
291
292static int mma9551_update_config_bits(struct i2c_client *client, u8 app_id,
293 u16 reg, u8 mask, u8 val)
294{
295 int ret;
296 u8 tmp, orig;
297
298 ret = mma9551_read_config_byte(client, app_id, reg, &orig);
299 if (ret < 0)
300 return ret;
301
302 tmp = orig & ~mask;
303 tmp |= val & mask;
304
305 if (tmp == orig)
306 return 0;
307
308 return mma9551_write_config_byte(client, app_id, reg, tmp);
309}
310
311/*
312 * The polarity parameter is described in section 6.2.2, page 66, of the
313 * Software Reference Manual. Basically, polarity=0 means the interrupt
314 * line has the same value as the selected bit, while polarity=1 means
315 * the line is inverted.
316 */
317static int mma9551_gpio_config(struct i2c_client *client,
318 enum mma9551_gpio_pin pin,
319 u8 app_id, u8 bitnum, int polarity)
320{
321 u8 reg, pol_mask, pol_val;
322 int ret;
323
324 if (pin > mma9551_gpio_max) {
325 dev_err(&client->dev, "bad GPIO pin\n");
326 return -EINVAL;
327 }
328
329 /*
330 * Pin 6 is configured by regs 0x00 and 0x01, pin 7 by 0x02 and
331 * 0x03, and so on.
332 */
333 reg = pin * 2;
334
335 ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO,
336 reg, app_id);
337 if (ret < 0) {
338 dev_err(&client->dev, "error setting GPIO app_id\n");
339 return ret;
340 }
341
342 ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO,
343 reg + 1, bitnum);
344 if (ret < 0) {
345 dev_err(&client->dev, "error setting GPIO bit number\n");
346 return ret;
347 }
348
349 switch (pin) {
350 case mma9551_gpio6:
351 reg = MMA9551_GPIO_POL_LSB;
352 pol_mask = 1 << 6;
353 break;
354 case mma9551_gpio7:
355 reg = MMA9551_GPIO_POL_LSB;
356 pol_mask = 1 << 7;
357 break;
358 case mma9551_gpio8:
359 reg = MMA9551_GPIO_POL_MSB;
360 pol_mask = 1 << 0;
361 break;
362 case mma9551_gpio9:
363 reg = MMA9551_GPIO_POL_MSB;
364 pol_mask = 1 << 1;
365 break;
366 }
367 pol_val = polarity ? pol_mask : 0;
368
369 ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg,
370 pol_mask, pol_val);
371 if (ret < 0)
372 dev_err(&client->dev, "error setting GPIO polarity\n");
373
374 return ret;
375}
376
377static int mma9551_read_version(struct i2c_client *client)
378{
379 struct mma9551_version_info info;
380 int ret;
381
382 ret = mma9551_transfer(client, MMA9551_APPID_VERSION, 0x00, 0x00,
383 NULL, 0, (u8 *)&info, sizeof(info));
384 if (ret < 0)
385 return ret;
386
387 dev_info(&client->dev, "Device ID 0x%x, firmware version %02x.%02x\n",
388 be32_to_cpu(info.device_id), info.fw_version[0],
389 info.fw_version[1]);
390
391 return 0;
392}
393
394/*
395 * Power on chip and enable doze mode.
396 * Use 'false' as the second parameter to cause the device to enter
397 * sleep.
398 */
399static int mma9551_set_device_state(struct i2c_client *client, bool enable)
400{
401 return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE,
402 MMA9551_SLEEP_CFG,
403 MMA9551_SLEEP_CFG_SNCEN |
404 MMA9551_SLEEP_CFG_FLEEN |
405 MMA9551_SLEEP_CFG_SCHEN,
406 enable ? MMA9551_SLEEP_CFG_SCHEN |
407 MMA9551_SLEEP_CFG_FLEEN :
408 MMA9551_SLEEP_CFG_SNCEN);
409}
410
411static int mma9551_set_power_state(struct i2c_client *client, bool on)
412{
413#ifdef CONFIG_PM
414 int ret;
415
416 if (on)
417 ret = pm_runtime_get_sync(&client->dev);
418 else {
419 pm_runtime_mark_last_busy(&client->dev);
420 ret = pm_runtime_put_autosuspend(&client->dev);
421 }
422
423 if (ret < 0) {
424 dev_err(&client->dev,
425 "failed to change power state to %d\n", on);
426 if (on)
427 pm_runtime_put_noidle(&client->dev);
428
429 return ret;
430 }
431#endif
432
433 return 0;
434}
435
436static void mma9551_sleep(int freq)
437{
438 int sleep_val = 1000 / freq;
439
440 if (sleep_val < 20)
441 usleep_range(sleep_val * 1000, 20000);
442 else
443 msleep_interruptible(sleep_val);
444}
445
446static int mma9551_read_incli_chan(struct i2c_client *client, 61static int mma9551_read_incli_chan(struct i2c_client *client,
447 const struct iio_chan_spec *chan, 62 const struct iio_chan_spec *chan,
448 int *val) 63 int *val)
@@ -497,46 +112,6 @@ out_poweroff:
497 return ret; 112 return ret;
498} 113}
499 114
500static int mma9551_read_accel_chan(struct i2c_client *client,
501 const struct iio_chan_spec *chan,
502 int *val, int *val2)
503{
504 u16 reg_addr;
505 s16 raw_accel;
506 int ret;
507
508 switch (chan->channel2) {
509 case IIO_MOD_X:
510 reg_addr = MMA9551_AFE_X_ACCEL_REG;
511 break;
512 case IIO_MOD_Y:
513 reg_addr = MMA9551_AFE_Y_ACCEL_REG;
514 break;
515 case IIO_MOD_Z:
516 reg_addr = MMA9551_AFE_Z_ACCEL_REG;
517 break;
518 default:
519 return -EINVAL;
520 }
521
522 ret = mma9551_set_power_state(client, true);
523 if (ret < 0)
524 return ret;
525
526 ret = mma9551_read_status_word(client, MMA9551_APPID_AFE,
527 reg_addr, &raw_accel);
528 if (ret < 0)
529 goto out_poweroff;
530
531 *val = raw_accel;
532
533 ret = IIO_VAL_INT;
534
535out_poweroff:
536 mma9551_set_power_state(client, false);
537 return ret;
538}
539
540static int mma9551_read_raw(struct iio_dev *indio_dev, 115static int mma9551_read_raw(struct iio_dev *indio_dev,
541 struct iio_chan_spec const *chan, 116 struct iio_chan_spec const *chan,
542 int *val, int *val2, long mask) 117 int *val, int *val2, long mask)
@@ -569,9 +144,7 @@ static int mma9551_read_raw(struct iio_dev *indio_dev,
569 case IIO_CHAN_INFO_SCALE: 144 case IIO_CHAN_INFO_SCALE:
570 switch (chan->type) { 145 switch (chan->type) {
571 case IIO_ACCEL: 146 case IIO_ACCEL:
572 *val = 0; 147 return mma9551_read_accel_scale(val, val2);
573 *val2 = 2440;
574 return IIO_VAL_INT_PLUS_MICRO;
575 default: 148 default:
576 return -EINVAL; 149 return -EINVAL;
577 } 150 }
@@ -740,14 +313,6 @@ static const struct iio_event_spec mma9551_incli_event = {
740 .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), 313 .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
741}; 314};
742 315
743#define MMA9551_ACCEL_CHANNEL(axis) { \
744 .type = IIO_ACCEL, \
745 .modified = 1, \
746 .channel2 = axis, \
747 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
748 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
749}
750
751#define MMA9551_INCLI_CHANNEL(axis) { \ 316#define MMA9551_INCLI_CHANNEL(axis) { \
752 .type = IIO_INCLI, \ 317 .type = IIO_INCLI, \
753 .modified = 1, \ 318 .modified = 1, \
diff --git a/drivers/iio/accel/mma9551_core.c b/drivers/iio/accel/mma9551_core.c
new file mode 100644
index 000000000000..7f1a73e6aa36
--- /dev/null
+++ b/drivers/iio/accel/mma9551_core.c
@@ -0,0 +1,615 @@
1/*
2 * Common code for Freescale MMA955x Intelligent Sensor Platform drivers
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/delay.h>
18#include <linux/iio/iio.h>
19#include <linux/pm_runtime.h>
20#include "mma9551_core.h"
21
22/* Command masks for mailbox write command */
23#define MMA9551_CMD_READ_VERSION_INFO 0x00
24#define MMA9551_CMD_READ_CONFIG 0x10
25#define MMA9551_CMD_WRITE_CONFIG 0x20
26#define MMA9551_CMD_READ_STATUS 0x30
27
28/* Mailbox read command */
29#define MMA9551_RESPONSE_COCO BIT(7)
30
31/* Error-Status codes returned in mailbox read command */
32#define MMA9551_MCI_ERROR_NONE 0x00
33#define MMA9551_MCI_ERROR_PARAM 0x04
34#define MMA9551_MCI_INVALID_COUNT 0x19
35#define MMA9551_MCI_ERROR_COMMAND 0x1C
36#define MMA9551_MCI_ERROR_INVALID_LENGTH 0x21
37#define MMA9551_MCI_ERROR_FIFO_BUSY 0x22
38#define MMA9551_MCI_ERROR_FIFO_ALLOCATED 0x23
39#define MMA9551_MCI_ERROR_FIFO_OVERSIZE 0x24
40
41/* GPIO Application */
42#define MMA9551_GPIO_POL_MSB 0x08
43#define MMA9551_GPIO_POL_LSB 0x09
44
45/* Sleep/Wake application */
46#define MMA9551_SLEEP_CFG 0x06
47#define MMA9551_SLEEP_CFG_SNCEN BIT(0)
48#define MMA9551_SLEEP_CFG_FLEEN BIT(1)
49#define MMA9551_SLEEP_CFG_SCHEN BIT(2)
50
51/* AFE application */
52#define MMA9551_AFE_X_ACCEL_REG 0x00
53#define MMA9551_AFE_Y_ACCEL_REG 0x02
54#define MMA9551_AFE_Z_ACCEL_REG 0x04
55
56/*
57 * A response is composed of:
58 * - control registers: MB0-3
59 * - data registers: MB4-31
60 *
61 * A request is composed of:
62 * - mbox to write to (always 0)
63 * - control registers: MB1-4
64 * - data registers: MB5-31
65 */
66#define MMA9551_MAILBOX_CTRL_REGS 4
67#define MMA9551_MAX_MAILBOX_DATA_REGS 28
68#define MMA9551_MAILBOX_REGS 32
69
70#define MMA9551_I2C_READ_RETRIES 5
71#define MMA9551_I2C_READ_DELAY 50 /* us */
72
73struct mma9551_mbox_request {
74 u8 start_mbox; /* Always 0. */
75 u8 app_id;
76 /*
77 * See Section 5.3.1 of the MMA955xL Software Reference Manual.
78 *
79 * Bit 7: reserved, always 0
80 * Bits 6-4: command
81 * Bits 3-0: upper bits of register offset
82 */
83 u8 cmd_off;
84 u8 lower_off;
85 u8 nbytes;
86 u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1];
87} __packed;
88
89struct mma9551_mbox_response {
90 u8 app_id;
91 /*
92 * See Section 5.3.3 of the MMA955xL Software Reference Manual.
93 *
94 * Bit 7: COCO
95 * Bits 6-0: Error code.
96 */
97 u8 coco_err;
98 u8 nbytes;
99 u8 req_bytes;
100 u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS];
101} __packed;
102
103struct mma9551_version_info {
104 __be32 device_id;
105 u8 rom_version[2];
106 u8 fw_version[2];
107 u8 hw_version[2];
108 u8 fw_build[2];
109};
110
111static int mma9551_transfer(struct i2c_client *client,
112 u8 app_id, u8 command, u16 offset,
113 u8 *inbytes, int num_inbytes,
114 u8 *outbytes, int num_outbytes)
115{
116 struct mma9551_mbox_request req;
117 struct mma9551_mbox_response rsp;
118 struct i2c_msg in, out;
119 u8 req_len, err_code;
120 int ret, retries;
121
122 if (offset >= 1 << 12) {
123 dev_err(&client->dev, "register offset too large\n");
124 return -EINVAL;
125 }
126
127 req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes;
128 req.start_mbox = 0;
129 req.app_id = app_id;
130 req.cmd_off = command | (offset >> 8);
131 req.lower_off = offset;
132
133 if (command == MMA9551_CMD_WRITE_CONFIG)
134 req.nbytes = num_inbytes;
135 else
136 req.nbytes = num_outbytes;
137 if (num_inbytes)
138 memcpy(req.buf, inbytes, num_inbytes);
139
140 out.addr = client->addr;
141 out.flags = 0;
142 out.len = req_len;
143 out.buf = (u8 *)&req;
144
145 ret = i2c_transfer(client->adapter, &out, 1);
146 if (ret < 0) {
147 dev_err(&client->dev, "i2c write failed\n");
148 return ret;
149 }
150
151 retries = MMA9551_I2C_READ_RETRIES;
152 do {
153 udelay(MMA9551_I2C_READ_DELAY);
154
155 in.addr = client->addr;
156 in.flags = I2C_M_RD;
157 in.len = sizeof(rsp);
158 in.buf = (u8 *)&rsp;
159
160 ret = i2c_transfer(client->adapter, &in, 1);
161 if (ret < 0) {
162 dev_err(&client->dev, "i2c read failed\n");
163 return ret;
164 }
165
166 if (rsp.coco_err & MMA9551_RESPONSE_COCO)
167 break;
168 } while (--retries > 0);
169
170 if (retries == 0) {
171 dev_err(&client->dev,
172 "timed out while waiting for command response\n");
173 return -ETIMEDOUT;
174 }
175
176 if (rsp.app_id != app_id) {
177 dev_err(&client->dev,
178 "app_id mismatch in response got %02x expected %02x\n",
179 rsp.app_id, app_id);
180 return -EINVAL;
181 }
182
183 err_code = rsp.coco_err & ~MMA9551_RESPONSE_COCO;
184 if (err_code != MMA9551_MCI_ERROR_NONE) {
185 dev_err(&client->dev, "read returned error %x\n", err_code);
186 return -EINVAL;
187 }
188
189 if (rsp.nbytes != rsp.req_bytes) {
190 dev_err(&client->dev,
191 "output length mismatch got %d expected %d\n",
192 rsp.nbytes, rsp.req_bytes);
193 return -EINVAL;
194 }
195
196 if (num_outbytes)
197 memcpy(outbytes, rsp.buf, num_outbytes);
198
199 return 0;
200}
201
202/**
203 * mma9551_read_config_byte() - read 1 configuration byte
204 * @client: I2C client
205 * @app_id: Application ID
206 * @reg: Application register
207 * @val: Pointer to store value read
208 *
209 * Read one configuration byte from the device using MMA955xL command format.
210 * Commands to the MMA955xL platform consist of a write followed
211 * by one or more reads.
212 *
213 * Locking note: This function must be called with the device lock held.
214 * Locking is not handled inside the function. Callers should ensure they
215 * serialize access to the HW.
216 *
217 * Returns: 0 on success, negative value on failure.
218 */
219int mma9551_read_config_byte(struct i2c_client *client, u8 app_id,
220 u16 reg, u8 *val)
221{
222 return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
223 reg, NULL, 0, val, 1);
224}
225EXPORT_SYMBOL(mma9551_read_config_byte);
226
227/**
228 * mma9551_write_config_byte() - write 1 configuration byte
229 * @client: I2C client
230 * @app_id: Application ID
231 * @reg: Application register
232 * @val: Value to write
233 *
234 * Write one configuration byte from the device using MMA955xL command format.
235 * Commands to the MMA955xL platform consist of a write followed by one or
236 * more reads.
237 *
238 * Locking note: This function must be called with the device lock held.
239 * Locking is not handled inside the function. Callers should ensure they
240 * serialize access to the HW.
241 *
242 * Returns: 0 on success, negative value on failure.
243 */
244int mma9551_write_config_byte(struct i2c_client *client, u8 app_id,
245 u16 reg, u8 val)
246{
247 return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
248 &val, 1, NULL, 0);
249}
250EXPORT_SYMBOL(mma9551_write_config_byte);
251
252/**
253 * mma9551_read_status_byte() - read 1 status byte
254 * @client: I2C client
255 * @app_id: Application ID
256 * @reg: Application register
257 * @val: Pointer to store value read
258 *
259 * Read one status byte from the device using MMA955xL command format.
260 * Commands to the MMA955xL platform consist of a write followed by one or
261 * more reads.
262 *
263 * Locking note: This function must be called with the device lock held.
264 * Locking is not handled inside the function. Callers should ensure they
265 * serialize access to the HW.
266 *
267 * Returns: 0 on success, negative value on failure.
268 */
269int mma9551_read_status_byte(struct i2c_client *client, u8 app_id,
270 u16 reg, u8 *val)
271{
272 return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
273 reg, NULL, 0, val, 1);
274}
275EXPORT_SYMBOL(mma9551_read_status_byte);
276
277/**
278 * mma9551_read_status_word() - read 1 status word
279 * @client: I2C client
280 * @app_id: Application ID
281 * @reg: Application register
282 * @val: Pointer to store value read
283 *
284 * Read one status word from the device using MMA955xL command format.
285 * Commands to the MMA955xL platform consist of a write followed by one or
286 * more reads.
287 *
288 * Locking note: This function must be called with the device lock held.
289 * Locking is not handled inside the function. Callers should ensure they
290 * serialize access to the HW.
291 *
292 * Returns: 0 on success, negative value on failure.
293 */
294int mma9551_read_status_word(struct i2c_client *client, u8 app_id,
295 u16 reg, u16 *val)
296{
297 int ret;
298 __be16 v;
299
300 ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
301 reg, NULL, 0, (u8 *)&v, 2);
302 *val = be16_to_cpu(v);
303
304 return ret;
305}
306EXPORT_SYMBOL(mma9551_read_status_word);
307
308/**
309 * mma9551_update_config_bits() - update bits in register
310 * @client: I2C client
311 * @app_id: Application ID
312 * @reg: Application register
313 * @mask: Mask for the bits to update
314 * @val: Value of the bits to update
315 *
316 * Update bits in the given register using a bit mask.
317 *
318 * Locking note: This function must be called with the device lock held.
319 * Locking is not handled inside the function. Callers should ensure they
320 * serialize access to the HW.
321 *
322 * Returns: 0 on success, negative value on failure.
323 */
324int mma9551_update_config_bits(struct i2c_client *client, u8 app_id,
325 u16 reg, u8 mask, u8 val)
326{
327 int ret;
328 u8 tmp, orig;
329
330 ret = mma9551_read_config_byte(client, app_id, reg, &orig);
331 if (ret < 0)
332 return ret;
333
334 tmp = orig & ~mask;
335 tmp |= val & mask;
336
337 if (tmp == orig)
338 return 0;
339
340 return mma9551_write_config_byte(client, app_id, reg, tmp);
341}
342EXPORT_SYMBOL(mma9551_update_config_bits);
343
344/**
345 * mma9551_gpio_config() - configure gpio
346 * @client: I2C client
347 * @pin: GPIO pin to configure
348 * @app_id: Application ID
349 * @bitnum: Bit number of status register being assigned to the GPIO pin.
350 * @polarity: The polarity parameter is described in section 6.2.2, page 66,
351 * of the Software Reference Manual. Basically, polarity=0 means
352 * the interrupt line has the same value as the selected bit,
353 * while polarity=1 means the line is inverted.
354 *
355 * Assign a bit from an application’s status register to a specific GPIO pin.
356 *
357 * Locking note: This function must be called with the device lock held.
358 * Locking is not handled inside the function. Callers should ensure they
359 * serialize access to the HW.
360 *
361 * Returns: 0 on success, negative value on failure.
362 */
363int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin,
364 u8 app_id, u8 bitnum, int polarity)
365{
366 u8 reg, pol_mask, pol_val;
367 int ret;
368
369 if (pin > mma9551_gpio_max) {
370 dev_err(&client->dev, "bad GPIO pin\n");
371 return -EINVAL;
372 }
373
374 /*
375 * Pin 6 is configured by regs 0x00 and 0x01, pin 7 by 0x02 and
376 * 0x03, and so on.
377 */
378 reg = pin * 2;
379
380 ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO,
381 reg, app_id);
382 if (ret < 0) {
383 dev_err(&client->dev, "error setting GPIO app_id\n");
384 return ret;
385 }
386
387 ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO,
388 reg + 1, bitnum);
389 if (ret < 0) {
390 dev_err(&client->dev, "error setting GPIO bit number\n");
391 return ret;
392 }
393
394 switch (pin) {
395 case mma9551_gpio6:
396 reg = MMA9551_GPIO_POL_LSB;
397 pol_mask = 1 << 6;
398 break;
399 case mma9551_gpio7:
400 reg = MMA9551_GPIO_POL_LSB;
401 pol_mask = 1 << 7;
402 break;
403 case mma9551_gpio8:
404 reg = MMA9551_GPIO_POL_MSB;
405 pol_mask = 1 << 0;
406 break;
407 case mma9551_gpio9:
408 reg = MMA9551_GPIO_POL_MSB;
409 pol_mask = 1 << 1;
410 break;
411 }
412 pol_val = polarity ? pol_mask : 0;
413
414 ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg,
415 pol_mask, pol_val);
416 if (ret < 0)
417 dev_err(&client->dev, "error setting GPIO polarity\n");
418
419 return ret;
420}
421EXPORT_SYMBOL(mma9551_gpio_config);
422
423/**
424 * mma9551_read_version() - read device version information
425 * @client: I2C client
426 *
427 * Read version information and print device id and firmware version.
428 *
429 * Locking note: This function must be called with the device lock held.
430 * Locking is not handled inside the function. Callers should ensure they
431 * serialize access to the HW.
432 *
433 * Returns: 0 on success, negative value on failure.
434 */
435int mma9551_read_version(struct i2c_client *client)
436{
437 struct mma9551_version_info info;
438 int ret;
439
440 ret = mma9551_transfer(client, MMA9551_APPID_VERSION, 0x00, 0x00,
441 NULL, 0, (u8 *)&info, sizeof(info));
442 if (ret < 0)
443 return ret;
444
445 dev_info(&client->dev, "device ID 0x%x, firmware version %02x.%02x\n",
446 be32_to_cpu(info.device_id), info.fw_version[0],
447 info.fw_version[1]);
448
449 return 0;
450}
451EXPORT_SYMBOL(mma9551_read_version);
452
453/**
454 * mma9551_set_device_state() - sets HW power mode
455 * @client: I2C client
456 * @enable: Use true to power on device, false to cause the device
457 * to enter sleep.
458 *
459 * Set power on/off for device using the Sleep/Wake Application.
460 * When enable is true, power on chip and enable doze mode.
461 * When enable is false, enter sleep mode (device remains in the
462 * lowest-power mode).
463 *
464 * Locking note: This function must be called with the device lock held.
465 * Locking is not handled inside the function. Callers should ensure they
466 * serialize access to the HW.
467 *
468 * Returns: 0 on success, negative value on failure.
469 */
470int mma9551_set_device_state(struct i2c_client *client, bool enable)
471{
472 return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE,
473 MMA9551_SLEEP_CFG,
474 MMA9551_SLEEP_CFG_SNCEN |
475 MMA9551_SLEEP_CFG_FLEEN |
476 MMA9551_SLEEP_CFG_SCHEN,
477 enable ? MMA9551_SLEEP_CFG_SCHEN |
478 MMA9551_SLEEP_CFG_FLEEN :
479 MMA9551_SLEEP_CFG_SNCEN);
480}
481EXPORT_SYMBOL(mma9551_set_device_state);
482
483/**
484 * mma9551_set_power_state() - sets runtime PM state
485 * @client: I2C client
486 * @on: Use true to power on device, false to power off
487 *
488 * Resume or suspend the device using Runtime PM.
489 * The device will suspend after the autosuspend delay.
490 *
491 * Returns: 0 on success, negative value on failure.
492 */
493int mma9551_set_power_state(struct i2c_client *client, bool on)
494{
495#ifdef CONFIG_PM
496 int ret;
497
498 if (on)
499 ret = pm_runtime_get_sync(&client->dev);
500 else {
501 pm_runtime_mark_last_busy(&client->dev);
502 ret = pm_runtime_put_autosuspend(&client->dev);
503 }
504
505 if (ret < 0) {
506 dev_err(&client->dev,
507 "failed to change power state to %d\n", on);
508 if (on)
509 pm_runtime_put_noidle(&client->dev);
510
511 return ret;
512 }
513#endif
514
515 return 0;
516}
517EXPORT_SYMBOL(mma9551_set_power_state);
518
519/**
520 * mma9551_sleep() - sleep
521 * @freq: Application frequency
522 *
523 * Firmware applications run at a certain frequency on the
524 * device. Sleep for one application cycle to make sure the
525 * application had time to run once and initialize set values.
526 */
527void mma9551_sleep(int freq)
528{
529 int sleep_val = 1000 / freq;
530
531 if (sleep_val < 20)
532 usleep_range(sleep_val * 1000, 20000);
533 else
534 msleep_interruptible(sleep_val);
535}
536EXPORT_SYMBOL(mma9551_sleep);
537
538/**
539 * mma9551_read_accel_chan() - read accelerometer channel
540 * @client: I2C client
541 * @chan: IIO channel
542 * @val: Pointer to the accelerometer value read
543 * @val2: Unused
544 *
545 * Read accelerometer value for the specified channel.
546 *
547 * Locking note: This function must be called with the device lock held.
548 * Locking is not handled inside the function. Callers should ensure they
549 * serialize access to the HW.
550 *
551 * Returns: IIO_VAL_INT on success, negative value on failure.
552 */
553int mma9551_read_accel_chan(struct i2c_client *client,
554 const struct iio_chan_spec *chan,
555 int *val, int *val2)
556{
557 u16 reg_addr;
558 s16 raw_accel;
559 int ret;
560
561 switch (chan->channel2) {
562 case IIO_MOD_X:
563 reg_addr = MMA9551_AFE_X_ACCEL_REG;
564 break;
565 case IIO_MOD_Y:
566 reg_addr = MMA9551_AFE_Y_ACCEL_REG;
567 break;
568 case IIO_MOD_Z:
569 reg_addr = MMA9551_AFE_Z_ACCEL_REG;
570 break;
571 default:
572 return -EINVAL;
573 }
574
575 ret = mma9551_set_power_state(client, true);
576 if (ret < 0)
577 return ret;
578
579 ret = mma9551_read_status_word(client, MMA9551_APPID_AFE,
580 reg_addr, &raw_accel);
581 if (ret < 0)
582 goto out_poweroff;
583
584 *val = raw_accel;
585
586 ret = IIO_VAL_INT;
587
588out_poweroff:
589 mma9551_set_power_state(client, false);
590 return ret;
591}
592EXPORT_SYMBOL(mma9551_read_accel_chan);
593
594/**
595 * mma9551_read_accel_scale() - read accelerometer scale
596 * @val: Pointer to the accelerometer scale (int value)
597 * @val2: Pointer to the accelerometer scale (micro value)
598 *
599 * Read accelerometer scale.
600 *
601 * Returns: IIO_VAL_INT_PLUS_MICRO.
602 */
603int mma9551_read_accel_scale(int *val, int *val2)
604{
605 *val = 0;
606 *val2 = 2440;
607
608 return IIO_VAL_INT_PLUS_MICRO;
609}
610EXPORT_SYMBOL(mma9551_read_accel_scale);
611
612MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
613MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
614MODULE_LICENSE("GPL v2");
615MODULE_DESCRIPTION("MMA955xL sensors core");
diff --git a/drivers/iio/accel/mma9551_core.h b/drivers/iio/accel/mma9551_core.h
new file mode 100644
index 000000000000..e6efd027f49a
--- /dev/null
+++ b/drivers/iio/accel/mma9551_core.h
@@ -0,0 +1,66 @@
1/*
2 * Common code for Freescale MMA955x Intelligent Sensor Platform drivers
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#ifndef _MMA9551_CORE_H_
16#define _MMA9551_CORE_H_
17
18/* Applications IDs */
19#define MMA9551_APPID_VERSION 0x00
20#define MMA9551_APPID_GPIO 0x03
21#define MMA9551_APPID_AFE 0x06
22#define MMA9551_APPID_TILT 0x0B
23#define MMA9551_APPID_SLEEP_WAKE 0x12
24#define MMA9551_APPID_RESET 0x17
25#define MMA9551_APPID_NONE 0xff
26
27#define MMA9551_AUTO_SUSPEND_DELAY_MS 2000
28
29enum mma9551_gpio_pin {
30 mma9551_gpio6 = 0,
31 mma9551_gpio7,
32 mma9551_gpio8,
33 mma9551_gpio9,
34 mma9551_gpio_max = mma9551_gpio9,
35};
36
37#define MMA9551_ACCEL_CHANNEL(axis) { \
38 .type = IIO_ACCEL, \
39 .modified = 1, \
40 .channel2 = axis, \
41 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
42 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
43}
44
45int mma9551_read_config_byte(struct i2c_client *client, u8 app_id,
46 u16 reg, u8 *val);
47int mma9551_write_config_byte(struct i2c_client *client, u8 app_id,
48 u16 reg, u8 val);
49int mma9551_read_status_byte(struct i2c_client *client, u8 app_id,
50 u16 reg, u8 *val);
51int mma9551_read_status_word(struct i2c_client *client, u8 app_id,
52 u16 reg, u16 *val);
53int mma9551_update_config_bits(struct i2c_client *client, u8 app_id,
54 u16 reg, u8 mask, u8 val);
55int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin,
56 u8 app_id, u8 bitnum, int polarity);
57int mma9551_read_version(struct i2c_client *client);
58int mma9551_set_device_state(struct i2c_client *client, bool enable);
59int mma9551_set_power_state(struct i2c_client *client, bool on);
60void mma9551_sleep(int freq);
61int mma9551_read_accel_chan(struct i2c_client *client,
62 const struct iio_chan_spec *chan,
63 int *val, int *val2);
64int mma9551_read_accel_scale(int *val, int *val2);
65
66#endif /* _MMA9551_CORE_H_ */