Commit 029756d0b8856f52d83dee81c01dd3af786cadff

Authored by Samu Onkalo
Committed by Guenter Roeck
1 parent f10a5407b5

hwmon: lis3: Enhance lis3 selftest with IRQ line test

Configure chip to data ready mode in selftest and count received
interrupts to see that interrupt line(s) are working.

Signed-off-by: Samu Onkalo <samu.p.onkalo@nokia.com>
Acked-by: Eric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>

Showing 2 changed files with 82 additions and 9 deletions Side-by-side Diff

drivers/hwmon/lis3lv02d.c
... ... @@ -48,6 +48,13 @@
48 48  
49 49 #define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
50 50  
  51 +#define SELFTEST_OK 0
  52 +#define SELFTEST_FAIL -1
  53 +#define SELFTEST_IRQ -2
  54 +
  55 +#define IRQ_LINE0 0
  56 +#define IRQ_LINE1 1
  57 +
51 58 /*
52 59 * The sensor can also generate interrupts (DRDY) but it's pretty pointless
53 60 * because they are generated even if the data do not change. So it's better
54 61  
... ... @@ -226,8 +233,25 @@
226 233 s16 x, y, z;
227 234 u8 selftest;
228 235 int ret;
  236 + u8 ctrl_reg_data;
  237 + unsigned char irq_cfg;
229 238  
230 239 mutex_lock(&lis3->mutex);
  240 +
  241 + irq_cfg = lis3->irq_cfg;
  242 + if (lis3_dev.whoami == WAI_8B) {
  243 + lis3->data_ready_count[IRQ_LINE0] = 0;
  244 + lis3->data_ready_count[IRQ_LINE1] = 0;
  245 +
  246 + /* Change interrupt cfg to data ready for selftest */
  247 + atomic_inc(&lis3_dev.wake_thread);
  248 + lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
  249 + lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
  250 + lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
  251 + ~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
  252 + (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
  253 + }
  254 +
231 255 if (lis3_dev.whoami == WAI_3DC) {
232 256 ctlreg = CTRL_REG4;
233 257 selftest = CTRL4_ST0;
234 258  
... ... @@ -257,13 +281,33 @@
257 281 results[2] = z - lis3->read_data(lis3, OUTZ);
258 282  
259 283 ret = 0;
  284 +
  285 + if (lis3_dev.whoami == WAI_8B) {
  286 + /* Restore original interrupt configuration */
  287 + atomic_dec(&lis3_dev.wake_thread);
  288 + lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
  289 + lis3->irq_cfg = irq_cfg;
  290 +
  291 + if ((irq_cfg & LIS3_IRQ1_MASK) &&
  292 + lis3->data_ready_count[IRQ_LINE0] < 2) {
  293 + ret = SELFTEST_IRQ;
  294 + goto fail;
  295 + }
  296 +
  297 + if ((irq_cfg & LIS3_IRQ2_MASK) &&
  298 + lis3->data_ready_count[IRQ_LINE1] < 2) {
  299 + ret = SELFTEST_IRQ;
  300 + goto fail;
  301 + }
  302 + }
  303 +
260 304 if (lis3->pdata) {
261 305 int i;
262 306 for (i = 0; i < 3; i++) {
263 307 /* Check against selftest acceptance limits */
264 308 if ((results[i] < lis3->pdata->st_min_limits[i]) ||
265 309 (results[i] > lis3->pdata->st_max_limits[i])) {
266   - ret = -EIO;
  310 + ret = SELFTEST_FAIL;
267 311 goto fail;
268 312 }
269 313 }
270 314  
271 315  
272 316  
273 317  
274 318  
... ... @@ -426,13 +470,24 @@
426 470 mutex_unlock(&lis3->mutex);
427 471 }
428 472  
429   -static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
  473 +static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
430 474 {
  475 + int dummy;
431 476  
  477 + /* Dummy read to ack interrupt */
  478 + lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
  479 + lis3->data_ready_count[index]++;
  480 +}
  481 +
  482 +static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
  483 +{
432 484 struct lis3lv02d *lis3 = data;
  485 + u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
433 486  
434   - if ((lis3->irq_cfg & LIS3_IRQ1_MASK) == LIS3_IRQ1_CLICK)
  487 + if (irq_cfg == LIS3_IRQ1_CLICK)
435 488 lis302dl_interrupt_handle_click(lis3);
  489 + else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
  490 + lis302dl_data_ready(lis3, IRQ_LINE0);
436 491 else
437 492 lis3lv02d_joystick_poll(lis3->idev);
438 493  
439 494  
440 495  
441 496  
... ... @@ -441,11 +496,13 @@
441 496  
442 497 static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
443 498 {
444   -
445 499 struct lis3lv02d *lis3 = data;
  500 + u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
446 501  
447   - if ((lis3->irq_cfg & LIS3_IRQ2_MASK) == LIS3_IRQ2_CLICK)
  502 + if (irq_cfg == LIS3_IRQ2_CLICK)
448 503 lis302dl_interrupt_handle_click(lis3);
  504 + else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
  505 + lis302dl_data_ready(lis3, IRQ_LINE1);
449 506 else
450 507 lis3lv02d_joystick_poll(lis3->idev);
451 508  
452 509  
453 510  
... ... @@ -648,12 +705,27 @@
648 705 static ssize_t lis3lv02d_selftest_show(struct device *dev,
649 706 struct device_attribute *attr, char *buf)
650 707 {
651   - int result;
652 708 s16 values[3];
653 709  
  710 + static const char ok[] = "OK";
  711 + static const char fail[] = "FAIL";
  712 + static const char irq[] = "FAIL_IRQ";
  713 + const char *res;
  714 +
654 715 lis3lv02d_sysfs_poweron(&lis3_dev);
655   - result = lis3lv02d_selftest(&lis3_dev, values);
656   - return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL",
  716 + switch (lis3lv02d_selftest(&lis3_dev, values)) {
  717 + case SELFTEST_FAIL:
  718 + res = fail;
  719 + break;
  720 + case SELFTEST_IRQ:
  721 + res = irq;
  722 + break;
  723 + case SELFTEST_OK:
  724 + default:
  725 + res = ok;
  726 + break;
  727 + }
  728 + return sprintf(buf, "%s %d %d %d\n", res,
657 729 values[0], values[1], values[2]);
658 730 }
659 731  
drivers/hwmon/lis3lv02d.h
... ... @@ -273,7 +273,8 @@
273 273 struct fasync_struct *async_queue; /* queue for the misc device */
274 274 wait_queue_head_t misc_wait; /* Wait queue for the misc device */
275 275 unsigned long misc_opened; /* bit0: whether the device is open */
276   - atomic_t wake_thread;
  276 + int data_ready_count[2];
  277 + atomic_t wake_thread;
277 278 unsigned char irq_cfg;
278 279  
279 280 struct lis3lv02d_platform_data *pdata; /* for passing board config */