gpio: mchp_xec: fix glitch setting pin to output
A GPIO's parallel output bit in the parallel output registers is read-only until the AOD bit is set to 1 in the pin's control registers. The proper sequence to preset the state of an output pin is: Configure pin as input with AOD=1 in the control register Set pin state in the parallel output register Set direction to output in the pin's control register. Signed-off-by: Scott Worley <scott.worley@microchip.com>
This commit is contained in:
parent
fef7879583
commit
03e510d68b
1 changed files with 70 additions and 58 deletions
|
@ -44,6 +44,17 @@ struct gpio_xec_config {
|
|||
uint32_t flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* notes: The GPIO parallel output bits are read-only until the
|
||||
* Alternate-Output-Disable (AOD) bit is set in the pin's control
|
||||
* register. To preload a parallel output value to prevent certain
|
||||
* classes of glitching for output pins we must:
|
||||
* Set GPIO control AOD=1 with the pin direction set to input.
|
||||
* Program the new pin value in the respective GPIO parallel output
|
||||
* register.
|
||||
* Program other GPIO control bits except direction.
|
||||
* Last step set the GPIO control register direction bit to output.
|
||||
*/
|
||||
static int gpio_xec_configure(const struct device *dev,
|
||||
gpio_pin_t pin, gpio_flags_t flags)
|
||||
{
|
||||
|
@ -66,18 +77,12 @@ static int gpio_xec_configure(const struct device *dev,
|
|||
|
||||
/* The flags contain options that require touching registers in the
|
||||
* PCRs for a given GPIO. There are no GPIO modules in Microchip SOCs!
|
||||
*
|
||||
* Start with the GPIO module and set up the pin direction register.
|
||||
* 0 - pin is input, 1 - pin is output
|
||||
* Keep direction as input until last.
|
||||
* Clear input pad disable allowing input pad to operate.
|
||||
*/
|
||||
mask |= MCHP_GPIO_CTRL_DIR_MASK;
|
||||
mask |= MCHP_GPIO_CTRL_INPAD_DIS_MASK;
|
||||
if ((flags & GPIO_OUTPUT) != 0U) {
|
||||
pcr1 |= MCHP_GPIO_CTRL_DIR_OUTPUT;
|
||||
} else {
|
||||
/* GPIO_INPUT */
|
||||
pcr1 |= MCHP_GPIO_CTRL_DIR_INPUT;
|
||||
}
|
||||
|
||||
/* Figure out the pullup/pulldown configuration and keep it in the
|
||||
* pcr1 variable
|
||||
|
@ -110,7 +115,10 @@ static int gpio_xec_configure(const struct device *dev,
|
|||
pcr1 |= MCHP_GPIO_CTRL_AOD_DIS;
|
||||
|
||||
/* Now write contents of pcr1 variable to the PCR1 register that
|
||||
* corresponds to the GPIO being configured
|
||||
* corresponds to the GPIO being configured.
|
||||
* AOD is 1 and direction is input. HW will allow use to set the
|
||||
* GPIO parallel output bit for this pin and with the pin direction
|
||||
* as input no glitch will occur.
|
||||
*/
|
||||
current_pcr1 = config->pcr1_base + pin;
|
||||
*current_pcr1 = (*current_pcr1 & ~mask) | pcr1;
|
||||
|
@ -121,6 +129,10 @@ static int gpio_xec_configure(const struct device *dev,
|
|||
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
|
||||
*gpio_out_reg &= ~BIT(pin);
|
||||
}
|
||||
|
||||
mask = MCHP_GPIO_CTRL_DIR_MASK;
|
||||
pcr1 = MCHP_GPIO_CTRL_DIR_OUTPUT;
|
||||
*current_pcr1 = (*current_pcr1 & ~mask) | pcr1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue