diff options
author | Robert Jarzmik <robert.jarzmik@free.fr> | 2015-11-21 13:04:51 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-12-10 10:12:35 -0500 |
commit | aedf08b664b71ecf0b35891eb6c83e26b888342a (patch) | |
tree | 4b79d97ae546b904aa1d7025656ea4cc708d3d97 | |
parent | d530ef9b88e5162a1972050994264d66ca884f3f (diff) |
pinctrl: pxa: pxa2xx: add pin configuration support
Add pin configuration for pxa2xx architectures. PXA doesn't provide any
bias, push, pull capabilities. The only capability is to set a state for
the pins when the platform enter sleep or deep sleep mode.
The state of a pin is set by :
- whether the GPIO direction was input or output
- if it is output, a register set programs whether the pin should be
held to ground or VccIO
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/pxa/pinctrl-pxa2xx.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c index a4ba82459af8..e01914460219 100644 --- a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c +++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c | |||
@@ -184,7 +184,70 @@ static const struct pinmux_ops pxa2xx_pinmux_ops = { | |||
184 | .gpio_set_direction = pxa2xx_pmx_gpio_set_direction, | 184 | .gpio_set_direction = pxa2xx_pmx_gpio_set_direction, |
185 | }; | 185 | }; |
186 | 186 | ||
187 | static int pxa2xx_pconf_group_get(struct pinctrl_dev *pctldev, | ||
188 | unsigned group, | ||
189 | unsigned long *config) | ||
190 | { | ||
191 | struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
192 | struct pxa_pinctrl_group *g = pctl->groups + group; | ||
193 | unsigned long flags; | ||
194 | unsigned pin = g->pin; | ||
195 | void __iomem *pgsr = pctl->base_pgsr[pin / 32]; | ||
196 | u32 val; | ||
197 | |||
198 | spin_lock_irqsave(&pctl->lock, flags); | ||
199 | val = readl_relaxed(pgsr) & BIT(pin % 32); | ||
200 | *config = val ? PIN_CONFIG_LOW_POWER_MODE : 0; | ||
201 | spin_unlock_irqrestore(&pctl->lock, flags); | ||
202 | |||
203 | dev_dbg(pctl->dev, "get sleep gpio state(pin=%d) %d\n", | ||
204 | pin, !!val); | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int pxa2xx_pconf_group_set(struct pinctrl_dev *pctldev, | ||
209 | unsigned group, | ||
210 | unsigned long *configs, | ||
211 | unsigned num_configs) | ||
212 | { | ||
213 | struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
214 | struct pxa_pinctrl_group *g = pctl->groups + group; | ||
215 | unsigned long flags; | ||
216 | unsigned pin = g->pin; | ||
217 | void __iomem *pgsr = pctl->base_pgsr[pin / 32]; | ||
218 | int i, is_set = 0; | ||
219 | u32 val; | ||
220 | |||
221 | for (i = 0; i < num_configs; i++) { | ||
222 | switch (pinconf_to_config_param(configs[i])) { | ||
223 | case PIN_CONFIG_LOW_POWER_MODE: | ||
224 | is_set = pinconf_to_config_argument(configs[i]); | ||
225 | break; | ||
226 | default: | ||
227 | return -EINVAL; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | dev_dbg(pctl->dev, "set sleep gpio state(pin=%d) %d\n", | ||
232 | pin, is_set); | ||
233 | |||
234 | spin_lock_irqsave(&pctl->lock, flags); | ||
235 | val = readl_relaxed(pgsr); | ||
236 | val = (val & ~BIT(pin % 32)) | (is_set ? BIT(pin % 32) : 0); | ||
237 | writel_relaxed(val, pgsr); | ||
238 | spin_unlock_irqrestore(&pctl->lock, flags); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static const struct pinconf_ops pxa2xx_pconf_ops = { | ||
244 | .pin_config_group_get = pxa2xx_pconf_group_get, | ||
245 | .pin_config_group_set = pxa2xx_pconf_group_set, | ||
246 | .is_generic = true, | ||
247 | }; | ||
248 | |||
187 | static struct pinctrl_desc pxa2xx_pinctrl_desc = { | 249 | static struct pinctrl_desc pxa2xx_pinctrl_desc = { |
250 | .confops = &pxa2xx_pconf_ops, | ||
188 | .pctlops = &pxa2xx_pctl_ops, | 251 | .pctlops = &pxa2xx_pctl_ops, |
189 | .pmxops = &pxa2xx_pinmux_ops, | 252 | .pmxops = &pxa2xx_pinmux_ops, |
190 | }; | 253 | }; |