diff options
author | Julien Delacou <julien.delacou@stericsson.com> | 2012-12-10 08:47:33 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-01-11 15:48:05 -0500 |
commit | 840a47ba43a2aefbd9834924228549879ee3cb49 (patch) | |
tree | e507b5f5dc2b0c81fdbf16e99b5511d0197a9ac3 | |
parent | 89216494ae23dc0071a2b7f8d8264cee55cc211d (diff) |
pinctrl: add sleep mode management for hogs
This fix allows handling sleep mode for hogged
pins in pinctrl. It provides functions to set pins
to sleep/default configurations according to their
current state.
Signed-off-by: Julien Delacou <julien.delacou@stericsson.com>
Reviewed-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/core.c | 37 | ||||
-rw-r--r-- | drivers/pinctrl/core.h | 7 |
2 files changed, 41 insertions, 3 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 5b4885c27d12..361175372598 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
@@ -1076,6 +1076,30 @@ void pinctrl_unregister_map(struct pinctrl_map const *map) | |||
1076 | } | 1076 | } |
1077 | } | 1077 | } |
1078 | 1078 | ||
1079 | /** | ||
1080 | * pinctrl_force_sleep() - turn a given controller device into sleep state | ||
1081 | * @pctldev: pin controller device | ||
1082 | */ | ||
1083 | int pinctrl_force_sleep(struct pinctrl_dev *pctldev) | ||
1084 | { | ||
1085 | if (!IS_ERR(pctldev->p) && !IS_ERR(pctldev->hog_sleep)) | ||
1086 | return pinctrl_select_state(pctldev->p, pctldev->hog_sleep); | ||
1087 | return 0; | ||
1088 | } | ||
1089 | EXPORT_SYMBOL_GPL(pinctrl_force_sleep); | ||
1090 | |||
1091 | /** | ||
1092 | * pinctrl_force_default() - turn a given controller device into default state | ||
1093 | * @pctldev: pin controller device | ||
1094 | */ | ||
1095 | int pinctrl_force_default(struct pinctrl_dev *pctldev) | ||
1096 | { | ||
1097 | if (!IS_ERR(pctldev->p) && !IS_ERR(pctldev->hog_default)) | ||
1098 | return pinctrl_select_state(pctldev->p, pctldev->hog_default); | ||
1099 | return 0; | ||
1100 | } | ||
1101 | EXPORT_SYMBOL_GPL(pinctrl_force_default); | ||
1102 | |||
1079 | #ifdef CONFIG_DEBUG_FS | 1103 | #ifdef CONFIG_DEBUG_FS |
1080 | 1104 | ||
1081 | static int pinctrl_pins_show(struct seq_file *s, void *what) | 1105 | static int pinctrl_pins_show(struct seq_file *s, void *what) |
@@ -1521,16 +1545,23 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, | |||
1521 | 1545 | ||
1522 | pctldev->p = pinctrl_get_locked(pctldev->dev); | 1546 | pctldev->p = pinctrl_get_locked(pctldev->dev); |
1523 | if (!IS_ERR(pctldev->p)) { | 1547 | if (!IS_ERR(pctldev->p)) { |
1524 | struct pinctrl_state *s = | 1548 | pctldev->hog_default = |
1525 | pinctrl_lookup_state_locked(pctldev->p, | 1549 | pinctrl_lookup_state_locked(pctldev->p, |
1526 | PINCTRL_STATE_DEFAULT); | 1550 | PINCTRL_STATE_DEFAULT); |
1527 | if (IS_ERR(s)) { | 1551 | if (IS_ERR(pctldev->hog_default)) { |
1528 | dev_dbg(dev, "failed to lookup the default state\n"); | 1552 | dev_dbg(dev, "failed to lookup the default state\n"); |
1529 | } else { | 1553 | } else { |
1530 | if (pinctrl_select_state_locked(pctldev->p, s)) | 1554 | if (pinctrl_select_state_locked(pctldev->p, |
1555 | pctldev->hog_default)) | ||
1531 | dev_err(dev, | 1556 | dev_err(dev, |
1532 | "failed to select default state\n"); | 1557 | "failed to select default state\n"); |
1533 | } | 1558 | } |
1559 | |||
1560 | pctldev->hog_sleep = | ||
1561 | pinctrl_lookup_state_locked(pctldev->p, | ||
1562 | PINCTRL_STATE_SLEEP); | ||
1563 | if (IS_ERR(pctldev->hog_sleep)) | ||
1564 | dev_dbg(dev, "failed to lookup the sleep state\n"); | ||
1534 | } | 1565 | } |
1535 | 1566 | ||
1536 | mutex_unlock(&pinctrl_mutex); | 1567 | mutex_unlock(&pinctrl_mutex); |
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 12f5694f3d5d..232a9f6db4aa 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h | |||
@@ -30,6 +30,8 @@ struct pinctrl_gpio_range; | |||
30 | * @driver_data: driver data for drivers registering to the pin controller | 30 | * @driver_data: driver data for drivers registering to the pin controller |
31 | * subsystem | 31 | * subsystem |
32 | * @p: result of pinctrl_get() for this device | 32 | * @p: result of pinctrl_get() for this device |
33 | * @hog_default: default state for pins hogged by this device | ||
34 | * @hog_sleep: sleep state for pins hogged by this device | ||
33 | * @device_root: debugfs root for this device | 35 | * @device_root: debugfs root for this device |
34 | */ | 36 | */ |
35 | struct pinctrl_dev { | 37 | struct pinctrl_dev { |
@@ -41,6 +43,8 @@ struct pinctrl_dev { | |||
41 | struct module *owner; | 43 | struct module *owner; |
42 | void *driver_data; | 44 | void *driver_data; |
43 | struct pinctrl *p; | 45 | struct pinctrl *p; |
46 | struct pinctrl_state *hog_default; | ||
47 | struct pinctrl_state *hog_sleep; | ||
44 | #ifdef CONFIG_DEBUG_FS | 48 | #ifdef CONFIG_DEBUG_FS |
45 | struct dentry *device_root; | 49 | struct dentry *device_root; |
46 | #endif | 50 | #endif |
@@ -164,5 +168,8 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, | |||
164 | bool dup, bool locked); | 168 | bool dup, bool locked); |
165 | void pinctrl_unregister_map(struct pinctrl_map const *map); | 169 | void pinctrl_unregister_map(struct pinctrl_map const *map); |
166 | 170 | ||
171 | extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev); | ||
172 | extern int pinctrl_force_default(struct pinctrl_dev *pctldev); | ||
173 | |||
167 | extern struct mutex pinctrl_mutex; | 174 | extern struct mutex pinctrl_mutex; |
168 | extern struct list_head pinctrldev_list; | 175 | extern struct list_head pinctrldev_list; |