gpio: lpc32xx: fix issues with port3 gpio

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 <slemieux@tycoint.com>
This commit is contained in:
Sylvain Lemieux 2015-09-09 11:35:58 -04:00 committed by Tom Rini
parent f3b44e8b27
commit 89983478bd
2 changed files with 37 additions and 8 deletions

View File

@ -12,7 +12,7 @@
/* /*
* Macro to map the pin for the lpc32xx_gpio driver. * 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. * mapping is done per register, as group of 32.
* (see drivers/gpio/lpc32xx_gpio.c for details). * (see drivers/gpio/lpc32xx_gpio.c for details).
* - macros can be use with the following pins: * - macros can be use with the following pins:
@ -26,9 +26,9 @@
#define LPC32XX_GPIO_P0_GRP 0 #define LPC32XX_GPIO_P0_GRP 0
#define LPC32XX_GPIO_P1_GRP 32 #define LPC32XX_GPIO_P1_GRP 32
#define LPC32XX_GPIO_P2_GRP 64 #define LPC32XX_GPIO_P2_GRP 64
#define LPC32XX_GPI_P3_GRP 96
#define LPC32XX_GPO_P3_GRP 96 #define LPC32XX_GPO_P3_GRP 96
#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPO_P3_GRP + 25) #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 * A specific GPIO can be selected with this macro

View File

@ -22,7 +22,7 @@
* read on another one. * read on another one.
* *
* In order to keep this code simple, GPIOS are considered here as * 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 ** * ** WARNING #1 **
* *
@ -35,7 +35,7 @@
* Please read NOTE in description of lpc32xx_gpio_get_function(). * Please read NOTE in description of lpc32xx_gpio_get_function().
*/ */
#define LPC32XX_GPIOS 128 #define LPC32XX_GPIOS 160
struct lpc32xx_gpio_priv { struct lpc32xx_gpio_priv {
struct gpio_regs *regs; struct gpio_regs *regs;
@ -45,11 +45,18 @@ struct lpc32xx_gpio_priv {
/** /**
* We have 4 GPIO ports of 32 bits each * 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_RANK(gpio) (gpio % 32)
#define GPIO_TO_MASK(gpio) (1 << (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; break;
case 2: case 2:
/* ports 2 and 3 share a common direction */ /* ports 2 and 3 share a common direction */
case 3:
writel(mask, &regs->p2_p3_dir_clr); writel(mask, &regs->p2_p3_dir_clr);
break; break;
case 3:
/* Setup direction only for GPIO_xx. */
if ((mask >= 25) && (mask <= 30))
writel(mask, &regs->p2_p3_dir_clr);
break;
case 4:
/* GPI_xx; nothing to do. */
break;
default: default:
return -1; return -1;
} }
@ -111,6 +125,11 @@ static int lpc32xx_gpio_get_value(struct udevice *dev, unsigned offset)
value = readl(&regs->p2_inp_state); value = readl(&regs->p2_inp_state);
break; break;
case 3: case 3:
/* Read GPO_xx and GPIO_xx (as output) using p3_outp_state. */
value = readl(&regs->p3_outp_state);
break;
case 4:
/* Read GPI_xx and GPIO_xx (as input) using p3_inp_state. */
value = readl(&regs->p3_inp_state); value = readl(&regs->p3_inp_state);
break; break;
default: default:
@ -149,6 +168,8 @@ static int gpio_set(struct udevice *dev, unsigned gpio)
case 3: case 3:
writel(mask, &regs->p3_outp_set); writel(mask, &regs->p3_outp_set);
break; break;
case 4:
/* GPI_xx; invalid. */
default: default:
return -1; return -1;
} }
@ -181,6 +202,8 @@ static int gpio_clr(struct udevice *dev, unsigned gpio)
case 3: case 3:
writel(mask, &regs->p3_outp_clr); writel(mask, &regs->p3_outp_clr);
break; break;
case 4:
/* GPI_xx; invalid. */
default: default:
return -1; return -1;
} }
@ -223,9 +246,15 @@ static int lpc32xx_gpio_direction_output(struct udevice *dev, unsigned offset,
break; break;
case 2: case 2:
/* ports 2 and 3 share a common direction */ /* ports 2 and 3 share a common direction */
case 3:
writel(mask, &regs->p2_p3_dir_set); writel(mask, &regs->p2_p3_dir_set);
break; break;
case 3:
/* Setup direction only for GPIO_xx. */
if ((mask >= 25) && (mask <= 30))
writel(mask, &regs->p2_p3_dir_set);
break;
case 4:
/* GPI_xx; invalid. */
default: default:
return -1; return -1;
} }