1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Common code for Freescale MMA955x Intelligent Sensor Platform drivers |
4 | * Copyright (c) 2014, Intel Corporation. |
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 | /* Command masks for mailbox write command */ |
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 | /* Mailbox read command */ |
21 | #define MMA9551_RESPONSE_COCO BIT(7) |
22 | |
23 | /* Error-Status codes returned in mailbox read command */ |
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 | /* GPIO Application */ |
34 | #define MMA9551_GPIO_POL_MSB 0x08 |
35 | #define MMA9551_GPIO_POL_LSB 0x09 |
36 | |
37 | /* Sleep/Wake application */ |
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 | /* AFE application */ |
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 | /* Reset/Suspend/Clear application */ |
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 | * A response is composed of: |
55 | * - control registers: MB0-3 |
56 | * - data registers: MB4-31 |
57 | * |
58 | * A request is composed of: |
59 | * - mbox to write to (always 0) |
60 | * - control registers: MB1-4 |
61 | * - data registers: MB5-31 |
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 /* us */ |
69 | |
70 | struct mma9551_mbox_request { |
71 | u8 start_mbox; /* Always 0. */ |
72 | u8 app_id; |
73 | /* |
74 | * See Section 5.3.1 of the MMA955xL Software Reference Manual. |
75 | * |
76 | * Bit 7: reserved, always 0 |
77 | * Bits 6-4: command |
78 | * Bits 3-0: upper bits of register offset |
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 | * See Section 5.3.3 of the MMA955xL Software Reference Manual. |
90 | * |
91 | * Bit 7: COCO |
92 | * Bits 6-0: Error code. |
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(adap: client->adapter, msgs: &out, num: 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(adap: client->adapter, msgs: &in, num: 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 | * mma9551_read_config_byte() - read 1 configuration byte |
201 | * @client: I2C client |
202 | * @app_id: Application ID |
203 | * @reg: Application register |
204 | * @val: Pointer to store value read |
205 | * |
206 | * Read one configuration byte from the device using MMA955xL command format. |
207 | * Commands to the MMA955xL platform consist of a write followed |
208 | * by one or more reads. |
209 | * |
210 | * Locking note: This function must be called with the device lock held. |
211 | * Locking is not handled inside the function. Callers should ensure they |
212 | * serialize access to the HW. |
213 | * |
214 | * Returns: 0 on success, negative value on failure. |
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 | offset: reg, NULL, num_inbytes: 0, outbytes: val, num_outbytes: 1); |
221 | } |
222 | EXPORT_SYMBOL_NS(mma9551_read_config_byte, IIO_MMA9551); |
223 | |
224 | /** |
225 | * mma9551_write_config_byte() - write 1 configuration byte |
226 | * @client: I2C client |
227 | * @app_id: Application ID |
228 | * @reg: Application register |
229 | * @val: Value to write |
230 | * |
231 | * Write one configuration byte from the device using MMA955xL command format. |
232 | * Commands to the MMA955xL platform consist of a write followed by one or |
233 | * more reads. |
234 | * |
235 | * Locking note: This function must be called with the device lock held. |
236 | * Locking is not handled inside the function. Callers should ensure they |
237 | * serialize access to the HW. |
238 | * |
239 | * Returns: 0 on success, negative value on failure. |
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, offset: reg, |
245 | inbytes: &val, num_inbytes: 1, NULL, num_outbytes: 0); |
246 | } |
247 | EXPORT_SYMBOL_NS(mma9551_write_config_byte, IIO_MMA9551); |
248 | |
249 | /** |
250 | * mma9551_read_status_byte() - read 1 status byte |
251 | * @client: I2C client |
252 | * @app_id: Application ID |
253 | * @reg: Application register |
254 | * @val: Pointer to store value read |
255 | * |
256 | * Read one status byte from the device using MMA955xL command format. |
257 | * Commands to the MMA955xL platform consist of a write followed by one or |
258 | * more reads. |
259 | * |
260 | * Locking note: This function must be called with the device lock held. |
261 | * Locking is not handled inside the function. Callers should ensure they |
262 | * serialize access to the HW. |
263 | * |
264 | * Returns: 0 on success, negative value on failure. |
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 | offset: reg, NULL, num_inbytes: 0, outbytes: val, num_outbytes: 1); |
271 | } |
272 | EXPORT_SYMBOL_NS(mma9551_read_status_byte, IIO_MMA9551); |
273 | |
274 | /** |
275 | * mma9551_read_config_word() - read 1 config word |
276 | * @client: I2C client |
277 | * @app_id: Application ID |
278 | * @reg: Application register |
279 | * @val: Pointer to store value read |
280 | * |
281 | * Read one configuration word from the device using MMA955xL command format. |
282 | * Commands to the MMA955xL platform consist of a write followed by one or |
283 | * more reads. |
284 | * |
285 | * Locking note: This function must be called with the device lock held. |
286 | * Locking is not handled inside the function. Callers should ensure they |
287 | * serialize access to the HW. |
288 | * |
289 | * Returns: 0 on success, negative value on failure. |
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 | offset: reg, NULL, num_inbytes: 0, outbytes: (u8 *)&v, num_outbytes: 2); |
299 | if (ret < 0) |
300 | return ret; |
301 | |
302 | *val = be16_to_cpu(v); |
303 | |
304 | return 0; |
305 | } |
306 | EXPORT_SYMBOL_NS(mma9551_read_config_word, IIO_MMA9551); |
307 | |
308 | /** |
309 | * mma9551_write_config_word() - write 1 config word |
310 | * @client: I2C client |
311 | * @app_id: Application ID |
312 | * @reg: Application register |
313 | * @val: Value to write |
314 | * |
315 | * Write one configuration word from the device using MMA955xL command format. |
316 | * Commands to the MMA955xL platform consist of a write followed by one or |
317 | * more reads. |
318 | * |
319 | * Locking note: This function must be called with the device lock held. |
320 | * Locking is not handled inside the function. Callers should ensure they |
321 | * serialize access to the HW. |
322 | * |
323 | * Returns: 0 on success, negative value on failure. |
324 | */ |
325 | int mma9551_write_config_word(struct i2c_client *client, u8 app_id, |
326 | u16 reg, u16 val) |
327 | { |
328 | __be16 v = cpu_to_be16(val); |
329 | |
330 | return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, offset: reg, |
331 | inbytes: (u8 *)&v, num_inbytes: 2, NULL, num_outbytes: 0); |
332 | } |
333 | EXPORT_SYMBOL_NS(mma9551_write_config_word, IIO_MMA9551); |
334 | |
335 | /** |
336 | * mma9551_read_status_word() - read 1 status word |
337 | * @client: I2C client |
338 | * @app_id: Application ID |
339 | * @reg: Application register |
340 | * @val: Pointer to store value read |
341 | * |
342 | * Read one status word from the device using MMA955xL command format. |
343 | * Commands to the MMA955xL platform consist of a write followed by one or |
344 | * more reads. |
345 | * |
346 | * Locking note: This function must be called with the device lock held. |
347 | * Locking is not handled inside the function. Callers should ensure they |
348 | * serialize access to the HW. |
349 | * |
350 | * Returns: 0 on success, negative value on failure. |
351 | */ |
352 | int mma9551_read_status_word(struct i2c_client *client, u8 app_id, |
353 | u16 reg, u16 *val) |
354 | { |
355 | int ret; |
356 | __be16 v; |
357 | |
358 | ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, |
359 | offset: reg, NULL, num_inbytes: 0, outbytes: (u8 *)&v, num_outbytes: 2); |
360 | if (ret < 0) |
361 | return ret; |
362 | |
363 | *val = be16_to_cpu(v); |
364 | |
365 | return 0; |
366 | } |
367 | EXPORT_SYMBOL_NS(mma9551_read_status_word, IIO_MMA9551); |
368 | |
369 | /** |
370 | * mma9551_read_config_words() - read multiple config words |
371 | * @client: I2C client |
372 | * @app_id: Application ID |
373 | * @reg: Application register |
374 | * @len: Length of array to read (in words) |
375 | * @buf: Array of words to read |
376 | * |
377 | * Read multiple configuration registers (word-sized registers). |
378 | * |
379 | * Locking note: This function must be called with the device lock held. |
380 | * Locking is not handled inside the function. Callers should ensure they |
381 | * serialize access to the HW. |
382 | * |
383 | * Returns: 0 on success, negative value on failure. |
384 | */ |
385 | int mma9551_read_config_words(struct i2c_client *client, u8 app_id, |
386 | u16 reg, u8 len, u16 *buf) |
387 | { |
388 | int ret, i; |
389 | __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2]; |
390 | |
391 | if (len > ARRAY_SIZE(be_buf)) { |
392 | dev_err(&client->dev, "Invalid buffer size %d\n" , len); |
393 | return -EINVAL; |
394 | } |
395 | |
396 | ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, |
397 | offset: reg, NULL, num_inbytes: 0, outbytes: (u8 *)be_buf, num_outbytes: len * sizeof(u16)); |
398 | if (ret < 0) |
399 | return ret; |
400 | |
401 | for (i = 0; i < len; i++) |
402 | buf[i] = be16_to_cpu(be_buf[i]); |
403 | |
404 | return 0; |
405 | } |
406 | EXPORT_SYMBOL_NS(mma9551_read_config_words, IIO_MMA9551); |
407 | |
408 | /** |
409 | * mma9551_read_status_words() - read multiple status words |
410 | * @client: I2C client |
411 | * @app_id: Application ID |
412 | * @reg: Application register |
413 | * @len: Length of array to read (in words) |
414 | * @buf: Array of words to read |
415 | * |
416 | * Read multiple status registers (word-sized registers). |
417 | * |
418 | * Locking note: This function must be called with the device lock held. |
419 | * Locking is not handled inside the function. Callers should ensure they |
420 | * serialize access to the HW. |
421 | * |
422 | * Returns: 0 on success, negative value on failure. |
423 | */ |
424 | int mma9551_read_status_words(struct i2c_client *client, u8 app_id, |
425 | u16 reg, u8 len, u16 *buf) |
426 | { |
427 | int ret, i; |
428 | __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2]; |
429 | |
430 | if (len > ARRAY_SIZE(be_buf)) { |
431 | dev_err(&client->dev, "Invalid buffer size %d\n" , len); |
432 | return -EINVAL; |
433 | } |
434 | |
435 | ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, |
436 | offset: reg, NULL, num_inbytes: 0, outbytes: (u8 *)be_buf, num_outbytes: len * sizeof(u16)); |
437 | if (ret < 0) |
438 | return ret; |
439 | |
440 | for (i = 0; i < len; i++) |
441 | buf[i] = be16_to_cpu(be_buf[i]); |
442 | |
443 | return 0; |
444 | } |
445 | EXPORT_SYMBOL_NS(mma9551_read_status_words, IIO_MMA9551); |
446 | |
447 | /** |
448 | * mma9551_write_config_words() - write multiple config words |
449 | * @client: I2C client |
450 | * @app_id: Application ID |
451 | * @reg: Application register |
452 | * @len: Length of array to write (in words) |
453 | * @buf: Array of words to write |
454 | * |
455 | * Write multiple configuration registers (word-sized registers). |
456 | * |
457 | * Locking note: This function must be called with the device lock held. |
458 | * Locking is not handled inside the function. Callers should ensure they |
459 | * serialize access to the HW. |
460 | * |
461 | * Returns: 0 on success, negative value on failure. |
462 | */ |
463 | int mma9551_write_config_words(struct i2c_client *client, u8 app_id, |
464 | u16 reg, u8 len, u16 *buf) |
465 | { |
466 | int i; |
467 | __be16 be_buf[(MMA9551_MAX_MAILBOX_DATA_REGS - 1) / 2]; |
468 | |
469 | if (len > ARRAY_SIZE(be_buf)) { |
470 | dev_err(&client->dev, "Invalid buffer size %d\n" , len); |
471 | return -EINVAL; |
472 | } |
473 | |
474 | for (i = 0; i < len; i++) |
475 | be_buf[i] = cpu_to_be16(buf[i]); |
476 | |
477 | return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, |
478 | offset: reg, inbytes: (u8 *)be_buf, num_inbytes: len * sizeof(u16), NULL, num_outbytes: 0); |
479 | } |
480 | EXPORT_SYMBOL_NS(mma9551_write_config_words, IIO_MMA9551); |
481 | |
482 | /** |
483 | * mma9551_update_config_bits() - update bits in register |
484 | * @client: I2C client |
485 | * @app_id: Application ID |
486 | * @reg: Application register |
487 | * @mask: Mask for the bits to update |
488 | * @val: Value of the bits to update |
489 | * |
490 | * Update bits in the given register using a bit mask. |
491 | * |
492 | * Locking note: This function must be called with the device lock held. |
493 | * Locking is not handled inside the function. Callers should ensure they |
494 | * serialize access to the HW. |
495 | * |
496 | * Returns: 0 on success, negative value on failure. |
497 | */ |
498 | int mma9551_update_config_bits(struct i2c_client *client, u8 app_id, |
499 | u16 reg, u8 mask, u8 val) |
500 | { |
501 | int ret; |
502 | u8 tmp, orig; |
503 | |
504 | ret = mma9551_read_config_byte(client, app_id, reg, &orig); |
505 | if (ret < 0) |
506 | return ret; |
507 | |
508 | tmp = orig & ~mask; |
509 | tmp |= val & mask; |
510 | |
511 | if (tmp == orig) |
512 | return 0; |
513 | |
514 | return mma9551_write_config_byte(client, app_id, reg, tmp); |
515 | } |
516 | EXPORT_SYMBOL_NS(mma9551_update_config_bits, IIO_MMA9551); |
517 | |
518 | /** |
519 | * mma9551_gpio_config() - configure gpio |
520 | * @client: I2C client |
521 | * @pin: GPIO pin to configure |
522 | * @app_id: Application ID |
523 | * @bitnum: Bit number of status register being assigned to the GPIO pin. |
524 | * @polarity: The polarity parameter is described in section 6.2.2, page 66, |
525 | * of the Software Reference Manual. Basically, polarity=0 means |
526 | * the interrupt line has the same value as the selected bit, |
527 | * while polarity=1 means the line is inverted. |
528 | * |
529 | * Assign a bit from an application’s status register to a specific GPIO pin. |
530 | * |
531 | * Locking note: This function must be called with the device lock held. |
532 | * Locking is not handled inside the function. Callers should ensure they |
533 | * serialize access to the HW. |
534 | * |
535 | * Returns: 0 on success, negative value on failure. |
536 | */ |
537 | int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin, |
538 | u8 app_id, u8 bitnum, int polarity) |
539 | { |
540 | u8 reg, pol_mask, pol_val; |
541 | int ret; |
542 | |
543 | if (pin > mma9551_gpio_max) { |
544 | dev_err(&client->dev, "bad GPIO pin\n" ); |
545 | return -EINVAL; |
546 | } |
547 | |
548 | /* |
549 | * Pin 6 is configured by regs 0x00 and 0x01, pin 7 by 0x02 and |
550 | * 0x03, and so on. |
551 | */ |
552 | reg = pin * 2; |
553 | |
554 | ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, |
555 | reg, app_id); |
556 | if (ret < 0) { |
557 | dev_err(&client->dev, "error setting GPIO app_id\n" ); |
558 | return ret; |
559 | } |
560 | |
561 | ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, |
562 | reg + 1, bitnum); |
563 | if (ret < 0) { |
564 | dev_err(&client->dev, "error setting GPIO bit number\n" ); |
565 | return ret; |
566 | } |
567 | |
568 | switch (pin) { |
569 | case mma9551_gpio6: |
570 | reg = MMA9551_GPIO_POL_LSB; |
571 | pol_mask = 1 << 6; |
572 | break; |
573 | case mma9551_gpio7: |
574 | reg = MMA9551_GPIO_POL_LSB; |
575 | pol_mask = 1 << 7; |
576 | break; |
577 | case mma9551_gpio8: |
578 | reg = MMA9551_GPIO_POL_MSB; |
579 | pol_mask = 1 << 0; |
580 | break; |
581 | case mma9551_gpio9: |
582 | reg = MMA9551_GPIO_POL_MSB; |
583 | pol_mask = 1 << 1; |
584 | break; |
585 | } |
586 | pol_val = polarity ? pol_mask : 0; |
587 | |
588 | ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg, |
589 | pol_mask, pol_val); |
590 | if (ret < 0) |
591 | dev_err(&client->dev, "error setting GPIO polarity\n" ); |
592 | |
593 | return ret; |
594 | } |
595 | EXPORT_SYMBOL_NS(mma9551_gpio_config, IIO_MMA9551); |
596 | |
597 | /** |
598 | * mma9551_read_version() - read device version information |
599 | * @client: I2C client |
600 | * |
601 | * Read version information and print device id and firmware version. |
602 | * |
603 | * Locking note: This function must be called with the device lock held. |
604 | * Locking is not handled inside the function. Callers should ensure they |
605 | * serialize access to the HW. |
606 | * |
607 | * Returns: 0 on success, negative value on failure. |
608 | */ |
609 | int mma9551_read_version(struct i2c_client *client) |
610 | { |
611 | struct mma9551_version_info info; |
612 | int ret; |
613 | |
614 | ret = mma9551_transfer(client, MMA9551_APPID_VERSION, command: 0x00, offset: 0x00, |
615 | NULL, num_inbytes: 0, outbytes: (u8 *)&info, num_outbytes: sizeof(info)); |
616 | if (ret < 0) |
617 | return ret; |
618 | |
619 | dev_info(&client->dev, "device ID 0x%x, firmware version %02x.%02x\n" , |
620 | be32_to_cpu(info.device_id), info.fw_version[0], |
621 | info.fw_version[1]); |
622 | |
623 | return 0; |
624 | } |
625 | EXPORT_SYMBOL_NS(mma9551_read_version, IIO_MMA9551); |
626 | |
627 | /** |
628 | * mma9551_set_device_state() - sets HW power mode |
629 | * @client: I2C client |
630 | * @enable: Use true to power on device, false to cause the device |
631 | * to enter sleep. |
632 | * |
633 | * Set power on/off for device using the Sleep/Wake Application. |
634 | * When enable is true, power on chip and enable doze mode. |
635 | * When enable is false, enter sleep mode (device remains in the |
636 | * lowest-power mode). |
637 | * |
638 | * Locking note: This function must be called with the device lock held. |
639 | * Locking is not handled inside the function. Callers should ensure they |
640 | * serialize access to the HW. |
641 | * |
642 | * Returns: 0 on success, negative value on failure. |
643 | */ |
644 | int mma9551_set_device_state(struct i2c_client *client, bool enable) |
645 | { |
646 | return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE, |
647 | MMA9551_SLEEP_CFG, |
648 | MMA9551_SLEEP_CFG_SNCEN | |
649 | MMA9551_SLEEP_CFG_FLEEN | |
650 | MMA9551_SLEEP_CFG_SCHEN, |
651 | enable ? MMA9551_SLEEP_CFG_SCHEN | |
652 | MMA9551_SLEEP_CFG_FLEEN : |
653 | MMA9551_SLEEP_CFG_SNCEN); |
654 | } |
655 | EXPORT_SYMBOL_NS(mma9551_set_device_state, IIO_MMA9551); |
656 | |
657 | /** |
658 | * mma9551_set_power_state() - sets runtime PM state |
659 | * @client: I2C client |
660 | * @on: Use true to power on device, false to power off |
661 | * |
662 | * Resume or suspend the device using Runtime PM. |
663 | * The device will suspend after the autosuspend delay. |
664 | * |
665 | * Returns: 0 on success, negative value on failure. |
666 | */ |
667 | int mma9551_set_power_state(struct i2c_client *client, bool on) |
668 | { |
669 | #ifdef CONFIG_PM |
670 | int ret; |
671 | |
672 | if (on) |
673 | ret = pm_runtime_resume_and_get(dev: &client->dev); |
674 | else { |
675 | pm_runtime_mark_last_busy(dev: &client->dev); |
676 | ret = pm_runtime_put_autosuspend(dev: &client->dev); |
677 | } |
678 | |
679 | if (ret < 0) { |
680 | dev_err(&client->dev, |
681 | "failed to change power state to %d\n" , on); |
682 | |
683 | return ret; |
684 | } |
685 | #endif |
686 | |
687 | return 0; |
688 | } |
689 | EXPORT_SYMBOL_NS(mma9551_set_power_state, IIO_MMA9551); |
690 | |
691 | /** |
692 | * mma9551_sleep() - sleep |
693 | * @freq: Application frequency |
694 | * |
695 | * Firmware applications run at a certain frequency on the |
696 | * device. Sleep for one application cycle to make sure the |
697 | * application had time to run once and initialize set values. |
698 | */ |
699 | void mma9551_sleep(int freq) |
700 | { |
701 | int sleep_val = 1000 / freq; |
702 | |
703 | if (sleep_val < 20) |
704 | usleep_range(min: sleep_val * 1000, max: 20000); |
705 | else |
706 | msleep_interruptible(msecs: sleep_val); |
707 | } |
708 | EXPORT_SYMBOL_NS(mma9551_sleep, IIO_MMA9551); |
709 | |
710 | /** |
711 | * mma9551_read_accel_chan() - read accelerometer channel |
712 | * @client: I2C client |
713 | * @chan: IIO channel |
714 | * @val: Pointer to the accelerometer value read |
715 | * @val2: Unused |
716 | * |
717 | * Read accelerometer value for the specified channel. |
718 | * |
719 | * Locking note: This function must be called with the device lock held. |
720 | * Locking is not handled inside the function. Callers should ensure they |
721 | * serialize access to the HW. |
722 | * |
723 | * Returns: IIO_VAL_INT on success, negative value on failure. |
724 | */ |
725 | int mma9551_read_accel_chan(struct i2c_client *client, |
726 | const struct iio_chan_spec *chan, |
727 | int *val, int *val2) |
728 | { |
729 | u16 reg_addr; |
730 | s16 raw_accel; |
731 | int ret; |
732 | |
733 | switch (chan->channel2) { |
734 | case IIO_MOD_X: |
735 | reg_addr = MMA9551_AFE_X_ACCEL_REG; |
736 | break; |
737 | case IIO_MOD_Y: |
738 | reg_addr = MMA9551_AFE_Y_ACCEL_REG; |
739 | break; |
740 | case IIO_MOD_Z: |
741 | reg_addr = MMA9551_AFE_Z_ACCEL_REG; |
742 | break; |
743 | default: |
744 | return -EINVAL; |
745 | } |
746 | |
747 | ret = mma9551_set_power_state(client, true); |
748 | if (ret < 0) |
749 | return ret; |
750 | |
751 | ret = mma9551_read_status_word(client, MMA9551_APPID_AFE, |
752 | reg_addr, &raw_accel); |
753 | if (ret < 0) |
754 | goto out_poweroff; |
755 | |
756 | *val = raw_accel; |
757 | |
758 | ret = IIO_VAL_INT; |
759 | |
760 | out_poweroff: |
761 | mma9551_set_power_state(client, false); |
762 | return ret; |
763 | } |
764 | EXPORT_SYMBOL_NS(mma9551_read_accel_chan, IIO_MMA9551); |
765 | |
766 | /** |
767 | * mma9551_read_accel_scale() - read accelerometer scale |
768 | * @val: Pointer to the accelerometer scale (int value) |
769 | * @val2: Pointer to the accelerometer scale (micro value) |
770 | * |
771 | * Read accelerometer scale. |
772 | * |
773 | * Returns: IIO_VAL_INT_PLUS_MICRO. |
774 | */ |
775 | int mma9551_read_accel_scale(int *val, int *val2) |
776 | { |
777 | *val = 0; |
778 | *val2 = 2440; |
779 | |
780 | return IIO_VAL_INT_PLUS_MICRO; |
781 | } |
782 | EXPORT_SYMBOL_NS(mma9551_read_accel_scale, IIO_MMA9551); |
783 | |
784 | /** |
785 | * mma9551_app_reset() - reset application |
786 | * @client: I2C client |
787 | * @app_mask: Application to reset |
788 | * |
789 | * Reset the given application (using the Reset/Suspend/Clear |
790 | * Control Application) |
791 | * |
792 | * Returns: 0 on success, negative value on failure. |
793 | */ |
794 | int mma9551_app_reset(struct i2c_client *client, u32 app_mask) |
795 | { |
796 | return mma9551_write_config_byte(client, MMA9551_APPID_RSC, |
797 | MMA9551_RSC_RESET + |
798 | MMA9551_RSC_OFFSET(app_mask), |
799 | MMA9551_RSC_VAL(app_mask)); |
800 | } |
801 | EXPORT_SYMBOL_NS(mma9551_app_reset, IIO_MMA9551); |
802 | |
803 | MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>" ); |
804 | MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>" ); |
805 | MODULE_LICENSE("GPL v2" ); |
806 | MODULE_DESCRIPTION("MMA955xL sensors core" ); |
807 | |