]>
Commit | Line | Data |
---|---|---|
d5b97f5c IT |
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 | ||
40cb7613 IT |
56 | /* Reset/Suspend/Clear application */ |
57 | #define MMA9551_RSC_RESET 0x00 | |
58 | #define MMA9551_RSC_OFFSET(mask) (3 - (ffs(mask) - 1) / 8) | |
59 | #define MMA9551_RSC_VAL(mask) (mask >> (((ffs(mask) - 1) / 8) * 8)) | |
60 | ||
d5b97f5c IT |
61 | /* |
62 | * A response is composed of: | |
63 | * - control registers: MB0-3 | |
64 | * - data registers: MB4-31 | |
65 | * | |
66 | * A request is composed of: | |
67 | * - mbox to write to (always 0) | |
68 | * - control registers: MB1-4 | |
69 | * - data registers: MB5-31 | |
70 | */ | |
71 | #define MMA9551_MAILBOX_CTRL_REGS 4 | |
72 | #define MMA9551_MAX_MAILBOX_DATA_REGS 28 | |
73 | #define MMA9551_MAILBOX_REGS 32 | |
74 | ||
75 | #define MMA9551_I2C_READ_RETRIES 5 | |
76 | #define MMA9551_I2C_READ_DELAY 50 /* us */ | |
77 | ||
78 | struct mma9551_mbox_request { | |
79 | u8 start_mbox; /* Always 0. */ | |
80 | u8 app_id; | |
81 | /* | |
82 | * See Section 5.3.1 of the MMA955xL Software Reference Manual. | |
83 | * | |
84 | * Bit 7: reserved, always 0 | |
85 | * Bits 6-4: command | |
86 | * Bits 3-0: upper bits of register offset | |
87 | */ | |
88 | u8 cmd_off; | |
89 | u8 lower_off; | |
90 | u8 nbytes; | |
91 | u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1]; | |
92 | } __packed; | |
93 | ||
94 | struct mma9551_mbox_response { | |
95 | u8 app_id; | |
96 | /* | |
97 | * See Section 5.3.3 of the MMA955xL Software Reference Manual. | |
98 | * | |
99 | * Bit 7: COCO | |
100 | * Bits 6-0: Error code. | |
101 | */ | |
102 | u8 coco_err; | |
103 | u8 nbytes; | |
104 | u8 req_bytes; | |
105 | u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS]; | |
106 | } __packed; | |
107 | ||
108 | struct mma9551_version_info { | |
109 | __be32 device_id; | |
110 | u8 rom_version[2]; | |
111 | u8 fw_version[2]; | |
112 | u8 hw_version[2]; | |
113 | u8 fw_build[2]; | |
114 | }; | |
115 | ||
116 | static int mma9551_transfer(struct i2c_client *client, | |
117 | u8 app_id, u8 command, u16 offset, | |
118 | u8 *inbytes, int num_inbytes, | |
119 | u8 *outbytes, int num_outbytes) | |
120 | { | |
121 | struct mma9551_mbox_request req; | |
122 | struct mma9551_mbox_response rsp; | |
123 | struct i2c_msg in, out; | |
124 | u8 req_len, err_code; | |
125 | int ret, retries; | |
126 | ||
127 | if (offset >= 1 << 12) { | |
128 | dev_err(&client->dev, "register offset too large\n"); | |
129 | return -EINVAL; | |
130 | } | |
131 | ||
132 | req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes; | |
133 | req.start_mbox = 0; | |
134 | req.app_id = app_id; | |
135 | req.cmd_off = command | (offset >> 8); | |
136 | req.lower_off = offset; | |
137 | ||
138 | if (command == MMA9551_CMD_WRITE_CONFIG) | |
139 | req.nbytes = num_inbytes; | |
140 | else | |
141 | req.nbytes = num_outbytes; | |
142 | if (num_inbytes) | |
143 | memcpy(req.buf, inbytes, num_inbytes); | |
144 | ||
145 | out.addr = client->addr; | |
146 | out.flags = 0; | |
147 | out.len = req_len; | |
148 | out.buf = (u8 *)&req; | |
149 | ||
150 | ret = i2c_transfer(client->adapter, &out, 1); | |
151 | if (ret < 0) { | |
152 | dev_err(&client->dev, "i2c write failed\n"); | |
153 | return ret; | |
154 | } | |
155 | ||
156 | retries = MMA9551_I2C_READ_RETRIES; | |
157 | do { | |
158 | udelay(MMA9551_I2C_READ_DELAY); | |
159 | ||
160 | in.addr = client->addr; | |
161 | in.flags = I2C_M_RD; | |
162 | in.len = sizeof(rsp); | |
163 | in.buf = (u8 *)&rsp; | |
164 | ||
165 | ret = i2c_transfer(client->adapter, &in, 1); | |
166 | if (ret < 0) { | |
167 | dev_err(&client->dev, "i2c read failed\n"); | |
168 | return ret; | |
169 | } | |
170 | ||
171 | if (rsp.coco_err & MMA9551_RESPONSE_COCO) | |
172 | break; | |
173 | } while (--retries > 0); | |
174 | ||
175 | if (retries == 0) { | |
176 | dev_err(&client->dev, | |
177 | "timed out while waiting for command response\n"); | |
178 | return -ETIMEDOUT; | |
179 | } | |
180 | ||
181 | if (rsp.app_id != app_id) { | |
182 | dev_err(&client->dev, | |
183 | "app_id mismatch in response got %02x expected %02x\n", | |
184 | rsp.app_id, app_id); | |
185 | return -EINVAL; | |
186 | } | |
187 | ||
188 | err_code = rsp.coco_err & ~MMA9551_RESPONSE_COCO; | |
189 | if (err_code != MMA9551_MCI_ERROR_NONE) { | |
190 | dev_err(&client->dev, "read returned error %x\n", err_code); | |
191 | return -EINVAL; | |
192 | } | |
193 | ||
194 | if (rsp.nbytes != rsp.req_bytes) { | |
195 | dev_err(&client->dev, | |
196 | "output length mismatch got %d expected %d\n", | |
197 | rsp.nbytes, rsp.req_bytes); | |
198 | return -EINVAL; | |
199 | } | |
200 | ||
201 | if (num_outbytes) | |
202 | memcpy(outbytes, rsp.buf, num_outbytes); | |
203 | ||
204 | return 0; | |
205 | } | |
206 | ||
207 | /** | |
208 | * mma9551_read_config_byte() - read 1 configuration byte | |
209 | * @client: I2C client | |
210 | * @app_id: Application ID | |
211 | * @reg: Application register | |
212 | * @val: Pointer to store value read | |
213 | * | |
214 | * Read one configuration byte from the device using MMA955xL command format. | |
215 | * Commands to the MMA955xL platform consist of a write followed | |
216 | * by one or more reads. | |
217 | * | |
218 | * Locking note: This function must be called with the device lock held. | |
219 | * Locking is not handled inside the function. Callers should ensure they | |
220 | * serialize access to the HW. | |
221 | * | |
222 | * Returns: 0 on success, negative value on failure. | |
223 | */ | |
224 | int mma9551_read_config_byte(struct i2c_client *client, u8 app_id, | |
225 | u16 reg, u8 *val) | |
226 | { | |
227 | return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, | |
228 | reg, NULL, 0, val, 1); | |
229 | } | |
230 | EXPORT_SYMBOL(mma9551_read_config_byte); | |
231 | ||
232 | /** | |
233 | * mma9551_write_config_byte() - write 1 configuration byte | |
234 | * @client: I2C client | |
235 | * @app_id: Application ID | |
236 | * @reg: Application register | |
237 | * @val: Value to write | |
238 | * | |
239 | * Write one configuration byte from the device using MMA955xL command format. | |
240 | * Commands to the MMA955xL platform consist of a write followed by one or | |
241 | * more reads. | |
242 | * | |
243 | * Locking note: This function must be called with the device lock held. | |
244 | * Locking is not handled inside the function. Callers should ensure they | |
245 | * serialize access to the HW. | |
246 | * | |
247 | * Returns: 0 on success, negative value on failure. | |
248 | */ | |
249 | int mma9551_write_config_byte(struct i2c_client *client, u8 app_id, | |
250 | u16 reg, u8 val) | |
251 | { | |
252 | return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg, | |
253 | &val, 1, NULL, 0); | |
254 | } | |
255 | EXPORT_SYMBOL(mma9551_write_config_byte); | |
256 | ||
257 | /** | |
258 | * mma9551_read_status_byte() - read 1 status byte | |
259 | * @client: I2C client | |
260 | * @app_id: Application ID | |
261 | * @reg: Application register | |
262 | * @val: Pointer to store value read | |
263 | * | |
264 | * Read one status byte from the device using MMA955xL command format. | |
265 | * Commands to the MMA955xL platform consist of a write followed by one or | |
266 | * more reads. | |
267 | * | |
268 | * Locking note: This function must be called with the device lock held. | |
269 | * Locking is not handled inside the function. Callers should ensure they | |
270 | * serialize access to the HW. | |
271 | * | |
272 | * Returns: 0 on success, negative value on failure. | |
273 | */ | |
274 | int mma9551_read_status_byte(struct i2c_client *client, u8 app_id, | |
275 | u16 reg, u8 *val) | |
276 | { | |
277 | return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, | |
278 | reg, NULL, 0, val, 1); | |
279 | } | |
280 | EXPORT_SYMBOL(mma9551_read_status_byte); | |
281 | ||
40cb7613 IT |
282 | /** |
283 | * mma9551_read_config_word() - read 1 config word | |
284 | * @client: I2C client | |
285 | * @app_id: Application ID | |
286 | * @reg: Application register | |
287 | * @val: Pointer to store value read | |
288 | * | |
289 | * Read one configuration word from the device using MMA955xL command format. | |
290 | * Commands to the MMA955xL platform consist of a write followed by one or | |
291 | * more reads. | |
292 | * | |
293 | * Locking note: This function must be called with the device lock held. | |
294 | * Locking is not handled inside the function. Callers should ensure they | |
295 | * serialize access to the HW. | |
296 | * | |
297 | * Returns: 0 on success, negative value on failure. | |
298 | */ | |
299 | int mma9551_read_config_word(struct i2c_client *client, u8 app_id, | |
b37c1990 | 300 | u16 reg, u16 *val) |
40cb7613 IT |
301 | { |
302 | int ret; | |
303 | __be16 v; | |
304 | ||
305 | ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, | |
306 | reg, NULL, 0, (u8 *)&v, 2); | |
307 | *val = be16_to_cpu(v); | |
308 | ||
309 | return ret; | |
310 | } | |
311 | EXPORT_SYMBOL(mma9551_read_config_word); | |
312 | ||
313 | /** | |
314 | * mma9551_write_config_word() - write 1 config word | |
315 | * @client: I2C client | |
316 | * @app_id: Application ID | |
317 | * @reg: Application register | |
318 | * @val: Value to write | |
319 | * | |
320 | * Write one configuration word from the device using MMA955xL command format. | |
321 | * Commands to the MMA955xL platform consist of a write followed by one or | |
322 | * more reads. | |
323 | * | |
324 | * Locking note: This function must be called with the device lock held. | |
325 | * Locking is not handled inside the function. Callers should ensure they | |
326 | * serialize access to the HW. | |
327 | * | |
328 | * Returns: 0 on success, negative value on failure. | |
329 | */ | |
330 | int mma9551_write_config_word(struct i2c_client *client, u8 app_id, | |
b37c1990 | 331 | u16 reg, u16 val) |
40cb7613 IT |
332 | { |
333 | __be16 v = cpu_to_be16(val); | |
334 | ||
335 | return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg, | |
b37c1990 | 336 | (u8 *)&v, 2, NULL, 0); |
40cb7613 IT |
337 | } |
338 | EXPORT_SYMBOL(mma9551_write_config_word); | |
339 | ||
d5b97f5c IT |
340 | /** |
341 | * mma9551_read_status_word() - read 1 status word | |
342 | * @client: I2C client | |
343 | * @app_id: Application ID | |
344 | * @reg: Application register | |
345 | * @val: Pointer to store value read | |
346 | * | |
347 | * Read one status word from the device using MMA955xL command format. | |
348 | * Commands to the MMA955xL platform consist of a write followed by one or | |
349 | * more reads. | |
350 | * | |
351 | * Locking note: This function must be called with the device lock held. | |
352 | * Locking is not handled inside the function. Callers should ensure they | |
353 | * serialize access to the HW. | |
354 | * | |
355 | * Returns: 0 on success, negative value on failure. | |
356 | */ | |
357 | int mma9551_read_status_word(struct i2c_client *client, u8 app_id, | |
358 | u16 reg, u16 *val) | |
359 | { | |
360 | int ret; | |
361 | __be16 v; | |
362 | ||
363 | ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, | |
364 | reg, NULL, 0, (u8 *)&v, 2); | |
365 | *val = be16_to_cpu(v); | |
366 | ||
367 | return ret; | |
368 | } | |
369 | EXPORT_SYMBOL(mma9551_read_status_word); | |
370 | ||
40cb7613 IT |
371 | /** |
372 | * mma9551_read_config_words() - read multiple config words | |
373 | * @client: I2C client | |
374 | * @app_id: Application ID | |
375 | * @reg: Application register | |
c0d901cc | 376 | * @len: Length of array to read (in words) |
b39f0c94 | 377 | * @buf: Array of words to read |
40cb7613 IT |
378 | * |
379 | * Read multiple configuration registers (word-sized registers). | |
380 | * | |
381 | * Locking note: This function must be called with the device lock held. | |
382 | * Locking is not handled inside the function. Callers should ensure they | |
383 | * serialize access to the HW. | |
384 | * | |
385 | * Returns: 0 on success, negative value on failure. | |
386 | */ | |
387 | int mma9551_read_config_words(struct i2c_client *client, u8 app_id, | |
b37c1990 | 388 | u16 reg, u8 len, u16 *buf) |
40cb7613 IT |
389 | { |
390 | int ret, i; | |
2a4d2032 IT |
391 | __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2]; |
392 | ||
c0d901cc | 393 | if (len > ARRAY_SIZE(be_buf)) { |
2a4d2032 IT |
394 | dev_err(&client->dev, "Invalid buffer size %d\n", len); |
395 | return -EINVAL; | |
396 | } | |
40cb7613 IT |
397 | |
398 | ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, | |
c0d901cc | 399 | reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16)); |
40cb7613 IT |
400 | if (ret < 0) |
401 | return ret; | |
402 | ||
c0d901cc | 403 | for (i = 0; i < len; i++) |
40cb7613 IT |
404 | buf[i] = be16_to_cpu(be_buf[i]); |
405 | ||
406 | return 0; | |
407 | } | |
408 | EXPORT_SYMBOL(mma9551_read_config_words); | |
409 | ||
410 | /** | |
411 | * mma9551_read_status_words() - read multiple status words | |
412 | * @client: I2C client | |
413 | * @app_id: Application ID | |
414 | * @reg: Application register | |
c0d901cc | 415 | * @len: Length of array to read (in words) |
b39f0c94 | 416 | * @buf: Array of words to read |
40cb7613 IT |
417 | * |
418 | * Read multiple status registers (word-sized registers). | |
419 | * | |
420 | * Locking note: This function must be called with the device lock held. | |
421 | * Locking is not handled inside the function. Callers should ensure they | |
422 | * serialize access to the HW. | |
423 | * | |
424 | * Returns: 0 on success, negative value on failure. | |
425 | */ | |
426 | int mma9551_read_status_words(struct i2c_client *client, u8 app_id, | |
427 | u16 reg, u8 len, u16 *buf) | |
428 | { | |
429 | int ret, i; | |
2a4d2032 IT |
430 | __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2]; |
431 | ||
c0d901cc | 432 | if (len > ARRAY_SIZE(be_buf)) { |
2a4d2032 IT |
433 | dev_err(&client->dev, "Invalid buffer size %d\n", len); |
434 | return -EINVAL; | |
435 | } | |
40cb7613 IT |
436 | |
437 | ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, | |
c0d901cc | 438 | reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16)); |
40cb7613 IT |
439 | if (ret < 0) |
440 | return ret; | |
441 | ||
c0d901cc | 442 | for (i = 0; i < len; i++) |
40cb7613 IT |
443 | buf[i] = be16_to_cpu(be_buf[i]); |
444 | ||
445 | return 0; | |
446 | } | |
447 | EXPORT_SYMBOL(mma9551_read_status_words); | |
448 | ||
449 | /** | |
450 | * mma9551_write_config_words() - write multiple config words | |
451 | * @client: I2C client | |
452 | * @app_id: Application ID | |
453 | * @reg: Application register | |
c0d901cc | 454 | * @len: Length of array to write (in words) |
b39f0c94 | 455 | * @buf: Array of words to write |
40cb7613 IT |
456 | * |
457 | * Write multiple configuration registers (word-sized registers). | |
458 | * | |
459 | * Locking note: This function must be called with the device lock held. | |
460 | * Locking is not handled inside the function. Callers should ensure they | |
461 | * serialize access to the HW. | |
462 | * | |
463 | * Returns: 0 on success, negative value on failure. | |
464 | */ | |
465 | int mma9551_write_config_words(struct i2c_client *client, u8 app_id, | |
466 | u16 reg, u8 len, u16 *buf) | |
467 | { | |
468 | int i; | |
2a4d2032 IT |
469 | __be16 be_buf[(MMA9551_MAX_MAILBOX_DATA_REGS - 1) / 2]; |
470 | ||
c0d901cc | 471 | if (len > ARRAY_SIZE(be_buf)) { |
2a4d2032 IT |
472 | dev_err(&client->dev, "Invalid buffer size %d\n", len); |
473 | return -EINVAL; | |
474 | } | |
40cb7613 | 475 | |
c0d901cc | 476 | for (i = 0; i < len; i++) |
40cb7613 IT |
477 | be_buf[i] = cpu_to_be16(buf[i]); |
478 | ||
479 | return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, | |
c0d901cc | 480 | reg, (u8 *)be_buf, len * sizeof(u16), NULL, 0); |
40cb7613 IT |
481 | } |
482 | EXPORT_SYMBOL(mma9551_write_config_words); | |
483 | ||
d5b97f5c IT |
484 | /** |
485 | * mma9551_update_config_bits() - update bits in register | |
486 | * @client: I2C client | |
487 | * @app_id: Application ID | |
488 | * @reg: Application register | |
489 | * @mask: Mask for the bits to update | |
490 | * @val: Value of the bits to update | |
491 | * | |
492 | * Update bits in the given register using a bit mask. | |
493 | * | |
494 | * Locking note: This function must be called with the device lock held. | |
495 | * Locking is not handled inside the function. Callers should ensure they | |
496 | * serialize access to the HW. | |
497 | * | |
498 | * Returns: 0 on success, negative value on failure. | |
499 | */ | |
500 | int mma9551_update_config_bits(struct i2c_client *client, u8 app_id, | |
501 | u16 reg, u8 mask, u8 val) | |
502 | { | |
503 | int ret; | |
504 | u8 tmp, orig; | |
505 | ||
506 | ret = mma9551_read_config_byte(client, app_id, reg, &orig); | |
507 | if (ret < 0) | |
508 | return ret; | |
509 | ||
510 | tmp = orig & ~mask; | |
511 | tmp |= val & mask; | |
512 | ||
513 | if (tmp == orig) | |
514 | return 0; | |
515 | ||
516 | return mma9551_write_config_byte(client, app_id, reg, tmp); | |
517 | } | |
518 | EXPORT_SYMBOL(mma9551_update_config_bits); | |
519 | ||
520 | /** | |
521 | * mma9551_gpio_config() - configure gpio | |
522 | * @client: I2C client | |
523 | * @pin: GPIO pin to configure | |
524 | * @app_id: Application ID | |
525 | * @bitnum: Bit number of status register being assigned to the GPIO pin. | |
526 | * @polarity: The polarity parameter is described in section 6.2.2, page 66, | |
527 | * of the Software Reference Manual. Basically, polarity=0 means | |
528 | * the interrupt line has the same value as the selected bit, | |
529 | * while polarity=1 means the line is inverted. | |
530 | * | |
531 | * Assign a bit from an application’s status register to a specific GPIO pin. | |
532 | * | |
533 | * Locking note: This function must be called with the device lock held. | |
534 | * Locking is not handled inside the function. Callers should ensure they | |
535 | * serialize access to the HW. | |
536 | * | |
537 | * Returns: 0 on success, negative value on failure. | |
538 | */ | |
539 | int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin, | |
540 | u8 app_id, u8 bitnum, int polarity) | |
541 | { | |
542 | u8 reg, pol_mask, pol_val; | |
543 | int ret; | |
544 | ||
545 | if (pin > mma9551_gpio_max) { | |
546 | dev_err(&client->dev, "bad GPIO pin\n"); | |
547 | return -EINVAL; | |
548 | } | |
549 | ||
550 | /* | |
551 | * Pin 6 is configured by regs 0x00 and 0x01, pin 7 by 0x02 and | |
552 | * 0x03, and so on. | |
553 | */ | |
554 | reg = pin * 2; | |
555 | ||
556 | ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, | |
557 | reg, app_id); | |
558 | if (ret < 0) { | |
559 | dev_err(&client->dev, "error setting GPIO app_id\n"); | |
560 | return ret; | |
561 | } | |
562 | ||
563 | ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, | |
564 | reg + 1, bitnum); | |
565 | if (ret < 0) { | |
566 | dev_err(&client->dev, "error setting GPIO bit number\n"); | |
567 | return ret; | |
568 | } | |
569 | ||
570 | switch (pin) { | |
571 | case mma9551_gpio6: | |
572 | reg = MMA9551_GPIO_POL_LSB; | |
573 | pol_mask = 1 << 6; | |
574 | break; | |
575 | case mma9551_gpio7: | |
576 | reg = MMA9551_GPIO_POL_LSB; | |
577 | pol_mask = 1 << 7; | |
578 | break; | |
579 | case mma9551_gpio8: | |
580 | reg = MMA9551_GPIO_POL_MSB; | |
581 | pol_mask = 1 << 0; | |
582 | break; | |
583 | case mma9551_gpio9: | |
584 | reg = MMA9551_GPIO_POL_MSB; | |
585 | pol_mask = 1 << 1; | |
586 | break; | |
587 | } | |
588 | pol_val = polarity ? pol_mask : 0; | |
589 | ||
590 | ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg, | |
591 | pol_mask, pol_val); | |
592 | if (ret < 0) | |
593 | dev_err(&client->dev, "error setting GPIO polarity\n"); | |
594 | ||
595 | return ret; | |
596 | } | |
597 | EXPORT_SYMBOL(mma9551_gpio_config); | |
598 | ||
599 | /** | |
600 | * mma9551_read_version() - read device version information | |
601 | * @client: I2C client | |
602 | * | |
603 | * Read version information and print device id and firmware version. | |
604 | * | |
605 | * Locking note: This function must be called with the device lock held. | |
606 | * Locking is not handled inside the function. Callers should ensure they | |
607 | * serialize access to the HW. | |
608 | * | |
609 | * Returns: 0 on success, negative value on failure. | |
610 | */ | |
611 | int mma9551_read_version(struct i2c_client *client) | |
612 | { | |
613 | struct mma9551_version_info info; | |
614 | int ret; | |
615 | ||
616 | ret = mma9551_transfer(client, MMA9551_APPID_VERSION, 0x00, 0x00, | |
617 | NULL, 0, (u8 *)&info, sizeof(info)); | |
618 | if (ret < 0) | |
619 | return ret; | |
620 | ||
621 | dev_info(&client->dev, "device ID 0x%x, firmware version %02x.%02x\n", | |
622 | be32_to_cpu(info.device_id), info.fw_version[0], | |
623 | info.fw_version[1]); | |
624 | ||
625 | return 0; | |
626 | } | |
627 | EXPORT_SYMBOL(mma9551_read_version); | |
628 | ||
629 | /** | |
630 | * mma9551_set_device_state() - sets HW power mode | |
631 | * @client: I2C client | |
632 | * @enable: Use true to power on device, false to cause the device | |
633 | * to enter sleep. | |
634 | * | |
635 | * Set power on/off for device using the Sleep/Wake Application. | |
636 | * When enable is true, power on chip and enable doze mode. | |
637 | * When enable is false, enter sleep mode (device remains in the | |
638 | * lowest-power mode). | |
639 | * | |
640 | * Locking note: This function must be called with the device lock held. | |
641 | * Locking is not handled inside the function. Callers should ensure they | |
642 | * serialize access to the HW. | |
643 | * | |
644 | * Returns: 0 on success, negative value on failure. | |
645 | */ | |
646 | int mma9551_set_device_state(struct i2c_client *client, bool enable) | |
647 | { | |
648 | return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE, | |
649 | MMA9551_SLEEP_CFG, | |
650 | MMA9551_SLEEP_CFG_SNCEN | | |
651 | MMA9551_SLEEP_CFG_FLEEN | | |
652 | MMA9551_SLEEP_CFG_SCHEN, | |
653 | enable ? MMA9551_SLEEP_CFG_SCHEN | | |
654 | MMA9551_SLEEP_CFG_FLEEN : | |
655 | MMA9551_SLEEP_CFG_SNCEN); | |
656 | } | |
657 | EXPORT_SYMBOL(mma9551_set_device_state); | |
658 | ||
659 | /** | |
660 | * mma9551_set_power_state() - sets runtime PM state | |
661 | * @client: I2C client | |
662 | * @on: Use true to power on device, false to power off | |
663 | * | |
664 | * Resume or suspend the device using Runtime PM. | |
665 | * The device will suspend after the autosuspend delay. | |
666 | * | |
667 | * Returns: 0 on success, negative value on failure. | |
668 | */ | |
669 | int mma9551_set_power_state(struct i2c_client *client, bool on) | |
670 | { | |
671 | #ifdef CONFIG_PM | |
672 | int ret; | |
673 | ||
674 | if (on) | |
675 | ret = pm_runtime_get_sync(&client->dev); | |
676 | else { | |
677 | pm_runtime_mark_last_busy(&client->dev); | |
678 | ret = pm_runtime_put_autosuspend(&client->dev); | |
679 | } | |
680 | ||
681 | if (ret < 0) { | |
682 | dev_err(&client->dev, | |
683 | "failed to change power state to %d\n", on); | |
684 | if (on) | |
685 | pm_runtime_put_noidle(&client->dev); | |
686 | ||
687 | return ret; | |
688 | } | |
689 | #endif | |
690 | ||
691 | return 0; | |
692 | } | |
693 | EXPORT_SYMBOL(mma9551_set_power_state); | |
694 | ||
695 | /** | |
696 | * mma9551_sleep() - sleep | |
697 | * @freq: Application frequency | |
698 | * | |
699 | * Firmware applications run at a certain frequency on the | |
700 | * device. Sleep for one application cycle to make sure the | |
701 | * application had time to run once and initialize set values. | |
702 | */ | |
703 | void mma9551_sleep(int freq) | |
704 | { | |
705 | int sleep_val = 1000 / freq; | |
706 | ||
707 | if (sleep_val < 20) | |
708 | usleep_range(sleep_val * 1000, 20000); | |
709 | else | |
710 | msleep_interruptible(sleep_val); | |
711 | } | |
712 | EXPORT_SYMBOL(mma9551_sleep); | |
713 | ||
714 | /** | |
715 | * mma9551_read_accel_chan() - read accelerometer channel | |
716 | * @client: I2C client | |
717 | * @chan: IIO channel | |
718 | * @val: Pointer to the accelerometer value read | |
719 | * @val2: Unused | |
720 | * | |
721 | * Read accelerometer value for the specified channel. | |
722 | * | |
723 | * Locking note: This function must be called with the device lock held. | |
724 | * Locking is not handled inside the function. Callers should ensure they | |
725 | * serialize access to the HW. | |
726 | * | |
727 | * Returns: IIO_VAL_INT on success, negative value on failure. | |
728 | */ | |
729 | int mma9551_read_accel_chan(struct i2c_client *client, | |
730 | const struct iio_chan_spec *chan, | |
731 | int *val, int *val2) | |
732 | { | |
733 | u16 reg_addr; | |
734 | s16 raw_accel; | |
735 | int ret; | |
736 | ||
737 | switch (chan->channel2) { | |
738 | case IIO_MOD_X: | |
739 | reg_addr = MMA9551_AFE_X_ACCEL_REG; | |
740 | break; | |
741 | case IIO_MOD_Y: | |
742 | reg_addr = MMA9551_AFE_Y_ACCEL_REG; | |
743 | break; | |
744 | case IIO_MOD_Z: | |
745 | reg_addr = MMA9551_AFE_Z_ACCEL_REG; | |
746 | break; | |
747 | default: | |
748 | return -EINVAL; | |
749 | } | |
750 | ||
751 | ret = mma9551_set_power_state(client, true); | |
752 | if (ret < 0) | |
753 | return ret; | |
754 | ||
755 | ret = mma9551_read_status_word(client, MMA9551_APPID_AFE, | |
756 | reg_addr, &raw_accel); | |
757 | if (ret < 0) | |
758 | goto out_poweroff; | |
759 | ||
760 | *val = raw_accel; | |
761 | ||
762 | ret = IIO_VAL_INT; | |
763 | ||
764 | out_poweroff: | |
765 | mma9551_set_power_state(client, false); | |
766 | return ret; | |
767 | } | |
768 | EXPORT_SYMBOL(mma9551_read_accel_chan); | |
769 | ||
770 | /** | |
771 | * mma9551_read_accel_scale() - read accelerometer scale | |
772 | * @val: Pointer to the accelerometer scale (int value) | |
773 | * @val2: Pointer to the accelerometer scale (micro value) | |
774 | * | |
775 | * Read accelerometer scale. | |
776 | * | |
777 | * Returns: IIO_VAL_INT_PLUS_MICRO. | |
778 | */ | |
779 | int mma9551_read_accel_scale(int *val, int *val2) | |
780 | { | |
781 | *val = 0; | |
782 | *val2 = 2440; | |
783 | ||
784 | return IIO_VAL_INT_PLUS_MICRO; | |
785 | } | |
786 | EXPORT_SYMBOL(mma9551_read_accel_scale); | |
787 | ||
40cb7613 IT |
788 | /** |
789 | * mma9551_app_reset() - reset application | |
790 | * @client: I2C client | |
791 | * @app_mask: Application to reset | |
792 | * | |
793 | * Reset the given application (using the Reset/Suspend/Clear | |
794 | * Control Application) | |
795 | * | |
796 | * Returns: 0 on success, negative value on failure. | |
797 | */ | |
798 | int mma9551_app_reset(struct i2c_client *client, u32 app_mask) | |
799 | { | |
476c41a7 | 800 | return mma9551_write_config_byte(client, MMA9551_APPID_RSC, |
40cb7613 IT |
801 | MMA9551_RSC_RESET + |
802 | MMA9551_RSC_OFFSET(app_mask), | |
803 | MMA9551_RSC_VAL(app_mask)); | |
804 | } | |
805 | EXPORT_SYMBOL(mma9551_app_reset); | |
806 | ||
d5b97f5c IT |
807 | MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>"); |
808 | MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>"); | |
809 | MODULE_LICENSE("GPL v2"); | |
810 | MODULE_DESCRIPTION("MMA955xL sensors core"); |