diff options
author | Patrice Chotard <patrice.chotard@stericsson.com> | 2013-01-24 03:47:22 -0500 |
---|---|---|
committer | Wolfram Sang <w.sang@pengutronix.de> | 2013-01-27 23:26:43 -0500 |
commit | 24e9e157d5197e469a414d0f52ce04e8b539a715 (patch) | |
tree | b69ab7d12fa3a118c84e696c8ba4cc29ae43bade | |
parent | 631056c399d2bdf34ee147c99401fee093ee4bfe (diff) |
i2c: nomadik: adopt pinctrl support
Amend the I2C nomadik pin controller to optionally take a pin control
handle and set the state of the pins to:
- "default" on boot, resume and before performing an i2c transfer
- "idle" after initial default, after resume default, and after each
i2c xfer
- "sleep" on suspend()
This should make it possible to optimize energy usage for the pins
both for the suspend/resume cycle, and for runtime cases inbetween
I2C transfers.
Signed-off-by: Patrice Chotard <patrice.chotard@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
[wsa: fixed braces on one else-branch]
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-rw-r--r-- | drivers/i2c/busses/i2c-nomadik.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 8b2ffcf45322..dd6a6913bd73 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/platform_data/i2c-nomadik.h> | 26 | #include <linux/platform_data/i2c-nomadik.h> |
27 | #include <linux/of.h> | 27 | #include <linux/of.h> |
28 | #include <linux/of_i2c.h> | 28 | #include <linux/of_i2c.h> |
29 | #include <linux/pinctrl/consumer.h> | ||
29 | 30 | ||
30 | #define DRIVER_NAME "nmk-i2c" | 31 | #define DRIVER_NAME "nmk-i2c" |
31 | 32 | ||
@@ -147,6 +148,10 @@ struct i2c_nmk_client { | |||
147 | * @stop: stop condition. | 148 | * @stop: stop condition. |
148 | * @xfer_complete: acknowledge completion for a I2C message. | 149 | * @xfer_complete: acknowledge completion for a I2C message. |
149 | * @result: controller propogated result. | 150 | * @result: controller propogated result. |
151 | * @pinctrl: pinctrl handle. | ||
152 | * @pins_default: default state for the pins. | ||
153 | * @pins_idle: idle state for the pins. | ||
154 | * @pins_sleep: sleep state for the pins. | ||
150 | * @busy: Busy doing transfer. | 155 | * @busy: Busy doing transfer. |
151 | */ | 156 | */ |
152 | struct nmk_i2c_dev { | 157 | struct nmk_i2c_dev { |
@@ -160,6 +165,11 @@ struct nmk_i2c_dev { | |||
160 | int stop; | 165 | int stop; |
161 | struct completion xfer_complete; | 166 | struct completion xfer_complete; |
162 | int result; | 167 | int result; |
168 | /* Three pin states - default, idle & sleep */ | ||
169 | struct pinctrl *pinctrl; | ||
170 | struct pinctrl_state *pins_default; | ||
171 | struct pinctrl_state *pins_idle; | ||
172 | struct pinctrl_state *pins_sleep; | ||
163 | bool busy; | 173 | bool busy; |
164 | }; | 174 | }; |
165 | 175 | ||
@@ -636,6 +646,15 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
636 | goto out_clk; | 646 | goto out_clk; |
637 | } | 647 | } |
638 | 648 | ||
649 | /* Optionaly enable pins to be muxed in and configured */ | ||
650 | if (!IS_ERR(dev->pins_default)) { | ||
651 | status = pinctrl_select_state(dev->pinctrl, | ||
652 | dev->pins_default); | ||
653 | if (status) | ||
654 | dev_err(&dev->adev->dev, | ||
655 | "could not set default pins\n"); | ||
656 | } | ||
657 | |||
639 | status = init_hw(dev); | 658 | status = init_hw(dev); |
640 | if (status) | 659 | if (status) |
641 | goto out; | 660 | goto out; |
@@ -663,6 +682,15 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
663 | out: | 682 | out: |
664 | clk_disable_unprepare(dev->clk); | 683 | clk_disable_unprepare(dev->clk); |
665 | out_clk: | 684 | out_clk: |
685 | /* Optionally let pins go into idle state */ | ||
686 | if (!IS_ERR(dev->pins_idle)) { | ||
687 | status = pinctrl_select_state(dev->pinctrl, | ||
688 | dev->pins_idle); | ||
689 | if (status) | ||
690 | dev_err(&dev->adev->dev, | ||
691 | "could not set pins to idle state\n"); | ||
692 | } | ||
693 | |||
666 | pm_runtime_put_sync(&dev->adev->dev); | 694 | pm_runtime_put_sync(&dev->adev->dev); |
667 | 695 | ||
668 | dev->busy = false; | 696 | dev->busy = false; |
@@ -857,15 +885,41 @@ static int nmk_i2c_suspend(struct device *dev) | |||
857 | { | 885 | { |
858 | struct amba_device *adev = to_amba_device(dev); | 886 | struct amba_device *adev = to_amba_device(dev); |
859 | struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); | 887 | struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); |
888 | int ret; | ||
860 | 889 | ||
861 | if (nmk_i2c->busy) | 890 | if (nmk_i2c->busy) |
862 | return -EBUSY; | 891 | return -EBUSY; |
863 | 892 | ||
893 | if (!IS_ERR(nmk_i2c->pins_sleep)) { | ||
894 | ret = pinctrl_select_state(nmk_i2c->pinctrl, | ||
895 | nmk_i2c->pins_sleep); | ||
896 | if (ret) | ||
897 | dev_err(dev, "could not set pins to sleep state\n"); | ||
898 | } | ||
899 | |||
864 | return 0; | 900 | return 0; |
865 | } | 901 | } |
866 | 902 | ||
867 | static int nmk_i2c_resume(struct device *dev) | 903 | static int nmk_i2c_resume(struct device *dev) |
868 | { | 904 | { |
905 | struct amba_device *adev = to_amba_device(dev); | ||
906 | struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); | ||
907 | int ret; | ||
908 | |||
909 | /* First go to the default state */ | ||
910 | if (!IS_ERR(nmk_i2c->pins_default)) { | ||
911 | ret = pinctrl_select_state(nmk_i2c->pinctrl, | ||
912 | nmk_i2c->pins_default); | ||
913 | if (ret) | ||
914 | dev_err(dev, "could not set pins to default state\n"); | ||
915 | } | ||
916 | /* Then let's idle the pins until the next transfer happens */ | ||
917 | if (!IS_ERR(nmk_i2c->pins_idle)) { | ||
918 | ret = pinctrl_select_state(nmk_i2c->pinctrl, | ||
919 | nmk_i2c->pins_idle); | ||
920 | if (ret) | ||
921 | dev_err(dev, "could not set pins to idle state\n"); | ||
922 | } | ||
869 | return 0; | 923 | return 0; |
870 | } | 924 | } |
871 | #else | 925 | #else |
@@ -953,6 +1007,40 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) | |||
953 | dev->adev = adev; | 1007 | dev->adev = adev; |
954 | amba_set_drvdata(adev, dev); | 1008 | amba_set_drvdata(adev, dev); |
955 | 1009 | ||
1010 | dev->pinctrl = devm_pinctrl_get(&adev->dev); | ||
1011 | if (IS_ERR(dev->pinctrl)) { | ||
1012 | ret = PTR_ERR(dev->pinctrl); | ||
1013 | goto err_pinctrl; | ||
1014 | } | ||
1015 | |||
1016 | dev->pins_default = pinctrl_lookup_state(dev->pinctrl, | ||
1017 | PINCTRL_STATE_DEFAULT); | ||
1018 | if (IS_ERR(dev->pins_default)) { | ||
1019 | dev_err(&adev->dev, "could not get default pinstate\n"); | ||
1020 | } else { | ||
1021 | ret = pinctrl_select_state(dev->pinctrl, | ||
1022 | dev->pins_default); | ||
1023 | if (ret) | ||
1024 | dev_dbg(&adev->dev, "could not set default pinstate\n"); | ||
1025 | } | ||
1026 | |||
1027 | dev->pins_idle = pinctrl_lookup_state(dev->pinctrl, | ||
1028 | PINCTRL_STATE_IDLE); | ||
1029 | if (IS_ERR(dev->pins_idle)) { | ||
1030 | dev_dbg(&adev->dev, "could not get idle pinstate\n"); | ||
1031 | } else { | ||
1032 | /* If possible, let's go to idle until the first transfer */ | ||
1033 | ret = pinctrl_select_state(dev->pinctrl, | ||
1034 | dev->pins_idle); | ||
1035 | if (ret) | ||
1036 | dev_dbg(&adev->dev, "could not set idle pinstate\n"); | ||
1037 | } | ||
1038 | |||
1039 | dev->pins_sleep = pinctrl_lookup_state(dev->pinctrl, | ||
1040 | PINCTRL_STATE_SLEEP); | ||
1041 | if (IS_ERR(dev->pins_sleep)) | ||
1042 | dev_dbg(&adev->dev, "could not get sleep pinstate\n"); | ||
1043 | |||
956 | dev->virtbase = ioremap(adev->res.start, resource_size(&adev->res)); | 1044 | dev->virtbase = ioremap(adev->res.start, resource_size(&adev->res)); |
957 | if (!dev->virtbase) { | 1045 | if (!dev->virtbase) { |
958 | ret = -ENOMEM; | 1046 | ret = -ENOMEM; |
@@ -1022,6 +1110,7 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) | |||
1022 | err_no_ioremap: | 1110 | err_no_ioremap: |
1023 | amba_set_drvdata(adev, NULL); | 1111 | amba_set_drvdata(adev, NULL); |
1024 | kfree(dev); | 1112 | kfree(dev); |
1113 | err_pinctrl: | ||
1025 | err_no_mem: | 1114 | err_no_mem: |
1026 | 1115 | ||
1027 | return ret; | 1116 | return ret; |