diff options
author | Wenyou Yang <wenyou.yang@atmel.com> | 2014-10-24 02:50:15 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2014-11-10 03:34:59 -0500 |
commit | d64a818859af3b6fbe0f6d61b4b82676b561ce5c (patch) | |
tree | 446a6228adb322a46d0b1dd614ab244a58ba77d5 /drivers/i2c/busses/i2c-at91.c | |
parent | 194fa7ff67f102023d198dfe658614a31dcad8d4 (diff) |
i2c: at91: add support for runtime PM
Drivers should put the device into low power states proactively whenever the
device is not in use. Thus implement support for runtime PM and use the
autosuspend feature to make sure that we can still perform well in case we see
lots of i2c traffic within short period of time.
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/busses/i2c-at91.c')
-rw-r--r-- | drivers/i2c/busses/i2c-at91.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index e05a672db3e5..76d16713508f 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c | |||
@@ -31,10 +31,12 @@ | |||
31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/platform_data/dma-atmel.h> | 33 | #include <linux/platform_data/dma-atmel.h> |
34 | #include <linux/pm_runtime.h> | ||
34 | 35 | ||
35 | #define DEFAULT_TWI_CLK_HZ 100000 /* max 400 Kbits/s */ | 36 | #define DEFAULT_TWI_CLK_HZ 100000 /* max 400 Kbits/s */ |
36 | #define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */ | 37 | #define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */ |
37 | #define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */ | 38 | #define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */ |
39 | #define AUTOSUSPEND_TIMEOUT 2000 | ||
38 | 40 | ||
39 | /* AT91 TWI register definitions */ | 41 | /* AT91 TWI register definitions */ |
40 | #define AT91_TWI_CR 0x0000 /* Control Register */ | 42 | #define AT91_TWI_CR 0x0000 /* Control Register */ |
@@ -481,6 +483,10 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) | |||
481 | 483 | ||
482 | dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num); | 484 | dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num); |
483 | 485 | ||
486 | ret = pm_runtime_get_sync(dev->dev); | ||
487 | if (ret < 0) | ||
488 | goto out; | ||
489 | |||
484 | /* | 490 | /* |
485 | * The hardware can handle at most two messages concatenated by a | 491 | * The hardware can handle at most two messages concatenated by a |
486 | * repeated start via it's internal address feature. | 492 | * repeated start via it's internal address feature. |
@@ -488,18 +494,21 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) | |||
488 | if (num > 2) { | 494 | if (num > 2) { |
489 | dev_err(dev->dev, | 495 | dev_err(dev->dev, |
490 | "cannot handle more than two concatenated messages.\n"); | 496 | "cannot handle more than two concatenated messages.\n"); |
491 | return 0; | 497 | ret = 0; |
498 | goto out; | ||
492 | } else if (num == 2) { | 499 | } else if (num == 2) { |
493 | int internal_address = 0; | 500 | int internal_address = 0; |
494 | int i; | 501 | int i; |
495 | 502 | ||
496 | if (msg->flags & I2C_M_RD) { | 503 | if (msg->flags & I2C_M_RD) { |
497 | dev_err(dev->dev, "first transfer must be write.\n"); | 504 | dev_err(dev->dev, "first transfer must be write.\n"); |
498 | return -EINVAL; | 505 | ret = -EINVAL; |
506 | goto out; | ||
499 | } | 507 | } |
500 | if (msg->len > 3) { | 508 | if (msg->len > 3) { |
501 | dev_err(dev->dev, "first message size must be <= 3.\n"); | 509 | dev_err(dev->dev, "first message size must be <= 3.\n"); |
502 | return -EINVAL; | 510 | ret = -EINVAL; |
511 | goto out; | ||
503 | } | 512 | } |
504 | 513 | ||
505 | /* 1st msg is put into the internal address, start with 2nd */ | 514 | /* 1st msg is put into the internal address, start with 2nd */ |
@@ -523,7 +532,12 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) | |||
523 | 532 | ||
524 | ret = at91_do_twi_transfer(dev); | 533 | ret = at91_do_twi_transfer(dev); |
525 | 534 | ||
526 | return (ret < 0) ? ret : num; | 535 | ret = (ret < 0) ? ret : num; |
536 | out: | ||
537 | pm_runtime_mark_last_busy(dev->dev); | ||
538 | pm_runtime_put_autosuspend(dev->dev); | ||
539 | |||
540 | return ret; | ||
527 | } | 541 | } |
528 | 542 | ||
529 | static u32 at91_twi_func(struct i2c_adapter *adapter) | 543 | static u32 at91_twi_func(struct i2c_adapter *adapter) |
@@ -795,11 +809,20 @@ static int at91_twi_probe(struct platform_device *pdev) | |||
795 | dev->adapter.timeout = AT91_I2C_TIMEOUT; | 809 | dev->adapter.timeout = AT91_I2C_TIMEOUT; |
796 | dev->adapter.dev.of_node = pdev->dev.of_node; | 810 | dev->adapter.dev.of_node = pdev->dev.of_node; |
797 | 811 | ||
812 | pm_runtime_set_autosuspend_delay(dev->dev, AUTOSUSPEND_TIMEOUT); | ||
813 | pm_runtime_use_autosuspend(dev->dev); | ||
814 | pm_runtime_set_active(dev->dev); | ||
815 | pm_runtime_enable(dev->dev); | ||
816 | |||
798 | rc = i2c_add_numbered_adapter(&dev->adapter); | 817 | rc = i2c_add_numbered_adapter(&dev->adapter); |
799 | if (rc) { | 818 | if (rc) { |
800 | dev_err(dev->dev, "Adapter %s registration failed\n", | 819 | dev_err(dev->dev, "Adapter %s registration failed\n", |
801 | dev->adapter.name); | 820 | dev->adapter.name); |
802 | clk_disable_unprepare(dev->clk); | 821 | clk_disable_unprepare(dev->clk); |
822 | |||
823 | pm_runtime_disable(dev->dev); | ||
824 | pm_runtime_set_suspended(dev->dev); | ||
825 | |||
803 | return rc; | 826 | return rc; |
804 | } | 827 | } |
805 | 828 | ||
@@ -814,6 +837,9 @@ static int at91_twi_remove(struct platform_device *pdev) | |||
814 | i2c_del_adapter(&dev->adapter); | 837 | i2c_del_adapter(&dev->adapter); |
815 | clk_disable_unprepare(dev->clk); | 838 | clk_disable_unprepare(dev->clk); |
816 | 839 | ||
840 | pm_runtime_disable(dev->dev); | ||
841 | pm_runtime_set_suspended(dev->dev); | ||
842 | |||
817 | return 0; | 843 | return 0; |
818 | } | 844 | } |
819 | 845 | ||
@@ -823,7 +849,7 @@ static int at91_twi_runtime_suspend(struct device *dev) | |||
823 | { | 849 | { |
824 | struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); | 850 | struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); |
825 | 851 | ||
826 | clk_disable(twi_dev->clk); | 852 | clk_disable_unprepare(twi_dev->clk); |
827 | 853 | ||
828 | return 0; | 854 | return 0; |
829 | } | 855 | } |
@@ -832,7 +858,7 @@ static int at91_twi_runtime_resume(struct device *dev) | |||
832 | { | 858 | { |
833 | struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); | 859 | struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); |
834 | 860 | ||
835 | return clk_enable(twi_dev->clk); | 861 | return clk_prepare_enable(twi_dev->clk); |
836 | } | 862 | } |
837 | 863 | ||
838 | static const struct dev_pm_ops at91_twi_pm = { | 864 | static const struct dev_pm_ops at91_twi_pm = { |