From: Sylvain Lemieux <slemi...@tycoint.com> The current simplify lpc32xx gpio driver implementation assume a maximum of 32 GPIO per port; there are a total of 22 GPI, 24 GPO and 6 GPIO to managed on port 3.
Update the driver to fix the following: 1) When requesting GPI_xx and GPO_xx on port 3 (xx is the same number) the second call to "gpio_request" will return -EBUSY. 2) The status of GPO_xx pin report the status of the corresponding GPI_xx pin when using the "gpio status" command. 3) The gpio driver may setup the direction register for the wrong gpio when calling "gpio_direction_input" (GPI_xx) or "gpio_direction_output" (GPO_xx) on port 3; the call to the direction is require to use the "gpio status" command. The following change were done in the driver: 1) port3 GPI are cache in a separate 32 bits in the array. 2) port3 direction register written only for GPIO pins. 3) port3 GPO & GPIO (as output) are read using "p3_outp_state". 4) LPC32XX_GPI_P3_GRP updated to match the change. Signed-off-by: Sylvain Lemieux <slemi...@tycoint.com> --- To reproduce the issues, the following test can be execute: 1) Add to source code: int ret1 = gpio_request(LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 19), "GPO_19"); int ret2 = gpio_request(LPC32XX_GPIO(LPC32XX_GPI_P3_GRP, 19), "GPI_19"); The second call return "-EBUSY". 2) Setup a logical 0 on GPI_19 pin --> gpio set 115 gpio: pin 115 (gpio 115) value is 1 --> gpio status 115: output: 0 [x] GPO_19 Setup a logic 1 on GPI_19 pin --> gpio clear115 gpio: pin 115 (gpio 115) value is 0 --> gpio status 115: output: 1 [x] GPO_19 3) Add to source code: (void)gpio_request(LPC32XX_GPIO(LPC32XX_GPI_P3_GRP, 25), "GPI_25"); --> gpio status 121: unknown Add to source code: (void)gpio_request(LPC32XX_GPIO(LPC32XX_GPI_P3_GRP, 25), "GPI_25"); (void)gpio_direction_input(LPC32XX_GPIO(LPC32XX_GPI_P3_GRP, 25)); --> gpio status 121: input: 0 [x] GPI_25 The direction register is written and GPIO_0 is configured as input. Changes from v1 to v2: * Regenarate the patch; the patch did not apply. Note: I am sending the patch using <slemieux.t...@gmail.com>, until I can submit patch using my regular e-mail <slemi...@tycoint.com>. arch/arm/include/asm/arch-lpc32xx/gpio_grp.h | 4 +-- drivers/gpio/lpc32xx_gpio.c | 41 ++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/arch/arm/include/asm/arch-lpc32xx/gpio_grp.h b/arch/arm/include/asm/arch-lpc32xx/gpio_grp.h index c9cf9df..64acf15 100644 --- a/arch/arm/include/asm/arch-lpc32xx/gpio_grp.h +++ b/arch/arm/include/asm/arch-lpc32xx/gpio_grp.h @@ -12,7 +12,7 @@ /* * Macro to map the pin for the lpc32xx_gpio driver. - * Note: - GPIOS are considered here as homogeneous and linear, from 0 to 127; + * Note: - GPIOS are considered here as homogeneous and linear from 0 to 159; * mapping is done per register, as group of 32. * (see drivers/gpio/lpc32xx_gpio.c for details). * - macros can be use with the following pins: @@ -26,9 +26,9 @@ #define LPC32XX_GPIO_P0_GRP 0 #define LPC32XX_GPIO_P1_GRP 32 #define LPC32XX_GPIO_P2_GRP 64 -#define LPC32XX_GPI_P3_GRP 96 #define LPC32XX_GPO_P3_GRP 96 #define LPC32XX_GPIO_P3_GRP (LPC32XX_GPO_P3_GRP + 25) +#define LPC32XX_GPI_P3_GRP 128 /* * A specific GPIO can be selected with this macro diff --git a/drivers/gpio/lpc32xx_gpio.c b/drivers/gpio/lpc32xx_gpio.c index 8a9826e..9674ee7 100644 --- a/drivers/gpio/lpc32xx_gpio.c +++ b/drivers/gpio/lpc32xx_gpio.c @@ -22,7 +22,7 @@ * read on another one. * * In order to keep this code simple, GPIOS are considered here as - * homogeneous and linear, from 0 to 127. + * homogeneous and linear, from 0 to 159. * * ** WARNING #1 ** * @@ -35,7 +35,7 @@ * Please read NOTE in description of lpc32xx_gpio_get_function(). */ -#define LPC32XX_GPIOS 128 +#define LPC32XX_GPIOS 160 struct lpc32xx_gpio_priv { struct gpio_regs *regs; @@ -45,11 +45,18 @@ struct lpc32xx_gpio_priv { /** * We have 4 GPIO ports of 32 bits each + * + * Port mapping offset (32 bits each): + * - Port 0: 0 + * - Port 1: 32 + * - Port 2: 64 + * - Port 3: GPO / GPIO (output): 96 + * - Port 3: GPI: 128 */ -#define MAX_GPIO 128 +#define MAX_GPIO 160 -#define GPIO_TO_PORT(gpio) ((gpio / 32) & 3) +#define GPIO_TO_PORT(gpio) ((gpio / 32) & 7) #define GPIO_TO_RANK(gpio) (gpio % 32) #define GPIO_TO_MASK(gpio) (1 << (gpio % 32)) @@ -75,9 +82,16 @@ static int lpc32xx_gpio_direction_input(struct udevice *dev, unsigned offset) break; case 2: /* ports 2 and 3 share a common direction */ - case 3: writel(mask, ®s->p2_p3_dir_clr); break; + case 3: + /* Setup direction only for GPIO_xx. */ + if ((mask >= 25) && (mask <= 30)) + writel(mask, ®s->p2_p3_dir_clr); + break; + case 4: + /* GPI_xx; nothing to do. */ + break; default: return -1; } @@ -111,6 +125,11 @@ static int lpc32xx_gpio_get_value(struct udevice *dev, unsigned offset) value = readl(®s->p2_inp_state); break; case 3: + /* Read GPO_xx and GPIO_xx (as output) using p3_outp_state. */ + value = readl(®s->p3_outp_state); + break; + case 4: + /* Read GPI_xx and GPIO_xx (as input) using p3_inp_state. */ value = readl(®s->p3_inp_state); break; default: @@ -149,6 +168,8 @@ static int gpio_set(struct udevice *dev, unsigned gpio) case 3: writel(mask, ®s->p3_outp_set); break; + case 4: + /* GPI_xx; invalid. */ default: return -1; } @@ -181,6 +202,8 @@ static int gpio_clr(struct udevice *dev, unsigned gpio) case 3: writel(mask, ®s->p3_outp_clr); break; + case 4: + /* GPI_xx; invalid. */ default: return -1; } @@ -223,9 +246,15 @@ static int lpc32xx_gpio_direction_output(struct udevice *dev, unsigned offset, break; case 2: /* ports 2 and 3 share a common direction */ - case 3: writel(mask, ®s->p2_p3_dir_set); break; + case 3: + /* Setup direction only for GPIO_xx. */ + if ((mask >= 25) && (mask <= 30)) + writel(mask, ®s->p2_p3_dir_set); + break; + case 4: + /* GPI_xx; invalid. */ default: return -1; } -- 1.8.3.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot