aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/lis3lv02d.c
diff options
context:
space:
mode:
authorSamu Onkalo <samu.p.onkalo@nokia.com>2010-10-22 07:57:23 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2010-10-25 17:11:38 -0400
commit2a346996626ecbb4269c239e9ff7372a182907e9 (patch)
tree9e1cd9d3f2a44e6dfaae7726613c0c13f2ab33e5 /drivers/hwmon/lis3lv02d.c
parent0ab83a7ce5c566b84d492d598dc64a19bfaef9ab (diff)
hwmon: lis3: pm_runtime support
Add pm_runtime support to lis3 core driver. Add pm_runtime support to lis3 i2c driver. spi and hp_accel drivers are not yet supported. Old always on functionality remains for those. For sysfs there is 5 second delay before turning off the chip to avoid long ramp up delay. Signed-off-by: Samu Onkalo <samu.p.onkalo@nokia.com> Acked-by: Jonathan Cameron <jic23@cam.ac.uk> 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.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 25f385010953..383a84938a98 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -34,6 +34,7 @@
34#include <linux/freezer.h> 34#include <linux/freezer.h>
35#include <linux/uaccess.h> 35#include <linux/uaccess.h>
36#include <linux/miscdevice.h> 36#include <linux/miscdevice.h>
37#include <linux/pm_runtime.h>
37#include <asm/atomic.h> 38#include <asm/atomic.h>
38#include "lis3lv02d.h" 39#include "lis3lv02d.h"
39 40
@@ -43,6 +44,9 @@
43#define MDPS_POLL_INTERVAL 50 44#define MDPS_POLL_INTERVAL 50
44#define MDPS_POLL_MIN 0 45#define MDPS_POLL_MIN 0
45#define MDPS_POLL_MAX 2000 46#define MDPS_POLL_MAX 2000
47
48#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
49
46/* 50/*
47 * The sensor can also generate interrupts (DRDY) but it's pretty pointless 51 * The sensor can also generate interrupts (DRDY) but it's pretty pointless
48 * because they are generated even if the data do not change. So it's better 52 * because they are generated even if the data do not change. So it's better
@@ -296,6 +300,18 @@ static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
296 mutex_unlock(&lis3_dev.mutex); 300 mutex_unlock(&lis3_dev.mutex);
297} 301}
298 302
303static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
304{
305 if (lis3_dev.pm_dev)
306 pm_runtime_get_sync(lis3_dev.pm_dev);
307}
308
309static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
310{
311 if (lis3_dev.pm_dev)
312 pm_runtime_put(lis3_dev.pm_dev);
313}
314
299static irqreturn_t lis302dl_interrupt(int irq, void *dummy) 315static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
300{ 316{
301 if (!test_bit(0, &lis3_dev.misc_opened)) 317 if (!test_bit(0, &lis3_dev.misc_opened))
@@ -390,6 +406,9 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
390 if (test_and_set_bit(0, &lis3_dev.misc_opened)) 406 if (test_and_set_bit(0, &lis3_dev.misc_opened))
391 return -EBUSY; /* already open */ 407 return -EBUSY; /* already open */
392 408
409 if (lis3_dev.pm_dev)
410 pm_runtime_get_sync(lis3_dev.pm_dev);
411
393 atomic_set(&lis3_dev.count, 0); 412 atomic_set(&lis3_dev.count, 0);
394 return 0; 413 return 0;
395} 414}
@@ -398,6 +417,8 @@ static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
398{ 417{
399 fasync_helper(-1, file, 0, &lis3_dev.async_queue); 418 fasync_helper(-1, file, 0, &lis3_dev.async_queue);
400 clear_bit(0, &lis3_dev.misc_opened); /* release the device */ 419 clear_bit(0, &lis3_dev.misc_opened); /* release the device */
420 if (lis3_dev.pm_dev)
421 pm_runtime_put(lis3_dev.pm_dev);
401 return 0; 422 return 0;
402} 423}
403 424
@@ -494,6 +515,8 @@ int lis3lv02d_joystick_enable(void)
494 return -ENOMEM; 515 return -ENOMEM;
495 516
496 lis3_dev.idev->poll = lis3lv02d_joystick_poll; 517 lis3_dev.idev->poll = lis3lv02d_joystick_poll;
518 lis3_dev.idev->open = lis3lv02d_joystick_open;
519 lis3_dev.idev->close = lis3lv02d_joystick_close;
497 lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL; 520 lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
498 lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN; 521 lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
499 lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX; 522 lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
@@ -546,12 +569,30 @@ void lis3lv02d_joystick_disable(void)
546EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); 569EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
547 570
548/* Sysfs stuff */ 571/* Sysfs stuff */
572static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
573{
574 /*
575 * SYSFS functions are fast visitors so put-call
576 * immediately after the get-call. However, keep
577 * chip running for a while and schedule delayed
578 * suspend. This way periodic sysfs calls doesn't
579 * suffer from relatively long power up time.
580 */
581
582 if (lis3->pm_dev) {
583 pm_runtime_get_sync(lis3->pm_dev);
584 pm_runtime_put_noidle(lis3->pm_dev);
585 pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
586 }
587}
588
549static ssize_t lis3lv02d_selftest_show(struct device *dev, 589static ssize_t lis3lv02d_selftest_show(struct device *dev,
550 struct device_attribute *attr, char *buf) 590 struct device_attribute *attr, char *buf)
551{ 591{
552 int result; 592 int result;
553 s16 values[3]; 593 s16 values[3];
554 594
595 lis3lv02d_sysfs_poweron(&lis3_dev);
555 result = lis3lv02d_selftest(&lis3_dev, values); 596 result = lis3lv02d_selftest(&lis3_dev, values);
556 return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL", 597 return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL",
557 values[0], values[1], values[2]); 598 values[0], values[1], values[2]);
@@ -562,6 +603,7 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
562{ 603{
563 int x, y, z; 604 int x, y, z;
564 605
606 lis3lv02d_sysfs_poweron(&lis3_dev);
565 mutex_lock(&lis3_dev.mutex); 607 mutex_lock(&lis3_dev.mutex);
566 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); 608 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
567 mutex_unlock(&lis3_dev.mutex); 609 mutex_unlock(&lis3_dev.mutex);
@@ -571,6 +613,7 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
571static ssize_t lis3lv02d_rate_show(struct device *dev, 613static ssize_t lis3lv02d_rate_show(struct device *dev,
572 struct device_attribute *attr, char *buf) 614 struct device_attribute *attr, char *buf)
573{ 615{
616 lis3lv02d_sysfs_poweron(&lis3_dev);
574 return sprintf(buf, "%d\n", lis3lv02d_get_odr()); 617 return sprintf(buf, "%d\n", lis3lv02d_get_odr());
575} 618}
576 619
@@ -583,6 +626,7 @@ static ssize_t lis3lv02d_rate_set(struct device *dev,
583 if (strict_strtoul(buf, 0, &rate)) 626 if (strict_strtoul(buf, 0, &rate))
584 return -EINVAL; 627 return -EINVAL;
585 628
629 lis3lv02d_sysfs_poweron(&lis3_dev);
586 if (lis3lv02d_set_odr(rate)) 630 if (lis3lv02d_set_odr(rate))
587 return -EINVAL; 631 return -EINVAL;
588 632
@@ -619,6 +663,17 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
619{ 663{
620 sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group); 664 sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
621 platform_device_unregister(lis3->pdev); 665 platform_device_unregister(lis3->pdev);
666 if (lis3->pm_dev) {
667 /* Barrier after the sysfs remove */
668 pm_runtime_barrier(lis3->pm_dev);
669
670 /* SYSFS may have left chip running. Turn off if necessary */
671 if (!pm_runtime_suspended(lis3->pm_dev))
672 lis3lv02d_poweroff(&lis3_dev);
673
674 pm_runtime_disable(lis3->pm_dev);
675 pm_runtime_set_suspended(lis3->pm_dev);
676 }
622 return 0; 677 return 0;
623} 678}
624EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); 679EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
@@ -728,6 +783,11 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
728 lis3lv02d_add_fs(dev); 783 lis3lv02d_add_fs(dev);
729 lis3lv02d_poweron(dev); 784 lis3lv02d_poweron(dev);
730 785
786 if (dev->pm_dev) {
787 pm_runtime_set_active(dev->pm_dev);
788 pm_runtime_enable(dev->pm_dev);
789 }
790
731 if (lis3lv02d_joystick_enable()) 791 if (lis3lv02d_joystick_enable())
732 printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); 792 printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
733 793