aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/lis3lv02d.c
diff options
context:
space:
mode:
authorSamu Onkalo <samu.p.onkalo@nokia.com>2010-10-22 07:57:32 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2010-10-25 17:11:39 -0400
commit029756d0b8856f52d83dee81c01dd3af786cadff (patch)
tree573ac19fe3461f1ffece64fd42af8573c011fa5d /drivers/hwmon/lis3lv02d.c
parentf10a5407b58603fb3b084d7fbdbd50f47d010c82 (diff)
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>
Diffstat (limited to 'drivers/hwmon/lis3lv02d.c')
-rw-r--r--drivers/hwmon/lis3lv02d.c88
1 files changed, 80 insertions, 8 deletions
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 0780de0550df..0cee73a6124e 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -48,6 +48,13 @@
48 48
49#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */ 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 * The sensor can also generate interrupts (DRDY) but it's pretty pointless 59 * The sensor can also generate interrupts (DRDY) but it's pretty pointless
53 * because they are generated even if the data do not change. So it's better 60 * because they are generated even if the data do not change. So it's better
@@ -226,8 +233,25 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
226 s16 x, y, z; 233 s16 x, y, z;
227 u8 selftest; 234 u8 selftest;
228 int ret; 235 int ret;
236 u8 ctrl_reg_data;
237 unsigned char irq_cfg;
229 238
230 mutex_lock(&lis3->mutex); 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 if (lis3_dev.whoami == WAI_3DC) { 255 if (lis3_dev.whoami == WAI_3DC) {
232 ctlreg = CTRL_REG4; 256 ctlreg = CTRL_REG4;
233 selftest = CTRL4_ST0; 257 selftest = CTRL4_ST0;
@@ -257,13 +281,33 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
257 results[2] = z - lis3->read_data(lis3, OUTZ); 281 results[2] = z - lis3->read_data(lis3, OUTZ);
258 282
259 ret = 0; 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 if (lis3->pdata) { 304 if (lis3->pdata) {
261 int i; 305 int i;
262 for (i = 0; i < 3; i++) { 306 for (i = 0; i < 3; i++) {
263 /* Check against selftest acceptance limits */ 307 /* Check against selftest acceptance limits */
264 if ((results[i] < lis3->pdata->st_min_limits[i]) || 308 if ((results[i] < lis3->pdata->st_min_limits[i]) ||
265 (results[i] > lis3->pdata->st_max_limits[i])) { 309 (results[i] > lis3->pdata->st_max_limits[i])) {
266 ret = -EIO; 310 ret = SELFTEST_FAIL;
267 goto fail; 311 goto fail;
268 } 312 }
269 } 313 }
@@ -426,13 +470,24 @@ static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
426 mutex_unlock(&lis3->mutex); 470 mutex_unlock(&lis3->mutex);
427} 471}
428 472
429static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data) 473static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
430{ 474{
475 int dummy;
476
477 /* Dummy read to ack interrupt */
478 lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
479 lis3->data_ready_count[index]++;
480}
431 481
482static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
483{
432 struct lis3lv02d *lis3 = data; 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 lis302dl_interrupt_handle_click(lis3); 488 lis302dl_interrupt_handle_click(lis3);
489 else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
490 lis302dl_data_ready(lis3, IRQ_LINE0);
436 else 491 else
437 lis3lv02d_joystick_poll(lis3->idev); 492 lis3lv02d_joystick_poll(lis3->idev);
438 493
@@ -441,11 +496,13 @@ static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
441 496
442static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data) 497static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
443{ 498{
444
445 struct lis3lv02d *lis3 = data; 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 lis302dl_interrupt_handle_click(lis3); 503 lis302dl_interrupt_handle_click(lis3);
504 else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
505 lis302dl_data_ready(lis3, IRQ_LINE1);
449 else 506 else
450 lis3lv02d_joystick_poll(lis3->idev); 507 lis3lv02d_joystick_poll(lis3->idev);
451 508
@@ -648,12 +705,27 @@ static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
648static ssize_t lis3lv02d_selftest_show(struct device *dev, 705static ssize_t lis3lv02d_selftest_show(struct device *dev,
649 struct device_attribute *attr, char *buf) 706 struct device_attribute *attr, char *buf)
650{ 707{
651 int result;
652 s16 values[3]; 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 lis3lv02d_sysfs_poweron(&lis3_dev); 715 lis3lv02d_sysfs_poweron(&lis3_dev);
655 result = lis3lv02d_selftest(&lis3_dev, values); 716 switch (lis3lv02d_selftest(&lis3_dev, values)) {
656 return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL", 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 values[0], values[1], values[2]); 729 values[0], values[1], values[2]);
658} 730}
659 731