From 0c35e3a8b406061005c481fccdb9bf2cfe09fd41 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 23 Sep 2015 12:13:00 -0600 Subject: ARM: tegra: don't enable GPIOs until direction is set Tegra's GPIO driver currently enables pins as GPIO as soon as they're requested. This is not safe, since the desired direction and output value are not yet known. This could cause a glitch on the output pins between gpio_request() and gpio_direction_*(), depending on what values happen to be in the GPIO controller's in/out and out-value registers vs. the final desired configuration. To solve this, defer enabling pins as GPIOs until some gpio_direction_*() is invoked, and the desired configuration is explicitly programmed. In theory this change could cause regressions, if code exists that claims a GPIO, never explicitly sets a direction, and then gets/sets the GPIO value based on that assumption. However, I've read through all the Tegra- related board files and device drivers that touch GPIOs and I do not see such buggy code anywhere. Signed-off-by: Stephen Warren Reviewed-by: Simon Glass Signed-off-by: Tom Warren --- drivers/gpio/tegra_gpio.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/gpio/tegra_gpio.c') diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c index c0ae771..2dfd02d 100644 --- a/drivers/gpio/tegra_gpio.c +++ b/drivers/gpio/tegra_gpio.c @@ -136,17 +136,6 @@ static void set_level(unsigned gpio, int high) * Generic_GPIO primitives. */ -static int tegra_gpio_request(struct udevice *dev, unsigned offset, - const char *label) -{ - struct tegra_port_info *state = dev_get_priv(dev); - - /* Configure as a GPIO */ - set_config(state->base_gpio + offset, 1); - - return 0; -} - /* set GPIO pin 'gpio' as an input */ static int tegra_gpio_direction_input(struct udevice *dev, unsigned offset) { @@ -155,6 +144,9 @@ static int tegra_gpio_direction_input(struct udevice *dev, unsigned offset) /* Configure GPIO direction as input. */ set_direction(state->base_gpio + offset, 0); + /* Enable the pin as a GPIO */ + set_config(state->base_gpio + offset, 1); + return 0; } @@ -171,6 +163,9 @@ static int tegra_gpio_direction_output(struct udevice *dev, unsigned offset, /* Configure GPIO direction as output. */ set_direction(gpio, 1); + /* Enable the pin as a GPIO */ + set_config(state->base_gpio + offset, 1); + return 0; } @@ -256,7 +251,6 @@ static int tegra_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, } static const struct dm_gpio_ops gpio_tegra_ops = { - .request = tegra_gpio_request, .direction_input = tegra_gpio_direction_input, .direction_output = tegra_gpio_direction_output, .get_value = tegra_gpio_get_value, -- cgit v1.1