Commit a770d946 authored by Robert Jarzmik's avatar Robert Jarzmik Committed by Linus Walleij

gpio: pxa: add pin control gpio direction and request

If a pin control driver is available, use it to change the gpio
direction. If not fallback to directly manipulating the gpio direction
register.

The reason to use the pin control driver first is that pin control in
pxa2xx architecture implies changing the gpio direction, even for non
gpio functions. In order to do it atomically, only one driver should
control the gpio direction, and if a pin controller is available, it has
to be him.

There is a small catch : if CONFIG_PINCTRL is selected, then a pinctrl
driver has to be probed. If not, gpio_request() will return
-EPROBE_DEFER as pinctrl_request_gpio() returns it in that case.
Signed-off-by: default avatarRobert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 2f46205b
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/syscore_ops.h> #include <linux/syscore_ops.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -251,6 +252,11 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ...@@ -251,6 +252,11 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
void __iomem *base = gpio_bank_base(chip, offset); void __iomem *base = gpio_bank_base(chip, offset);
uint32_t value, mask = GPIO_bit(offset); uint32_t value, mask = GPIO_bit(offset);
unsigned long flags; unsigned long flags;
int ret;
ret = pinctrl_gpio_direction_input(chip->base + offset);
if (!ret)
return 0;
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
...@@ -271,9 +277,14 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, ...@@ -271,9 +277,14 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip,
void __iomem *base = gpio_bank_base(chip, offset); void __iomem *base = gpio_bank_base(chip, offset);
uint32_t tmp, mask = GPIO_bit(offset); uint32_t tmp, mask = GPIO_bit(offset);
unsigned long flags; unsigned long flags;
int ret;
writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
ret = pinctrl_gpio_direction_output(chip->base + offset);
if (!ret)
return 0;
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
tmp = readl_relaxed(base + GPDR_OFFSET); tmp = readl_relaxed(base + GPDR_OFFSET);
...@@ -318,6 +329,16 @@ static int pxa_gpio_of_xlate(struct gpio_chip *gc, ...@@ -318,6 +329,16 @@ static int pxa_gpio_of_xlate(struct gpio_chip *gc,
} }
#endif #endif
static int pxa_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void pxa_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio, static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio,
struct device_node *np, void __iomem *regbase) struct device_node *np, void __iomem *regbase)
{ {
...@@ -336,6 +357,8 @@ static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio, ...@@ -336,6 +357,8 @@ static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio,
pchip->chip.set = pxa_gpio_set; pchip->chip.set = pxa_gpio_set;
pchip->chip.to_irq = pxa_gpio_to_irq; pchip->chip.to_irq = pxa_gpio_to_irq;
pchip->chip.ngpio = ngpio; pchip->chip.ngpio = ngpio;
pchip->chip.request = pxa_gpio_request;
pchip->chip.free = pxa_gpio_free;
#ifdef CONFIG_OF_GPIO #ifdef CONFIG_OF_GPIO
pchip->chip.of_node = np; pchip->chip.of_node = np;
pchip->chip.of_xlate = pxa_gpio_of_xlate; pchip->chip.of_xlate = pxa_gpio_of_xlate;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment