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
|
@ -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;
|
||||
}
|
||||
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;
|
||||
|
@ -311,7 +323,7 @@ static int gpio_xec_port000_036_init(const struct device *dev);
|
|||
static const struct gpio_xec_config gpio_xec_port000_036_config = {
|
||||
.common = {
|
||||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_NODE(
|
||||
DT_NODELABEL(gpio_000_036)),
|
||||
DT_NODELABEL(gpio_000_036)),
|
||||
},
|
||||
.pcr1_base = (uint32_t *) DT_REG_ADDR(DT_NODELABEL(gpio_000_036)),
|
||||
.port_num = MCHP_GPIO_000_036,
|
||||
|
@ -326,11 +338,11 @@ static const struct gpio_xec_config gpio_xec_port000_036_config = {
|
|||
static struct gpio_xec_data gpio_xec_port000_036_data;
|
||||
|
||||
DEVICE_AND_API_INIT(gpio_xec_port000_036,
|
||||
DT_LABEL(DT_NODELABEL(gpio_000_036)),
|
||||
gpio_xec_port000_036_init,
|
||||
&gpio_xec_port000_036_data, &gpio_xec_port000_036_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
DT_LABEL(DT_NODELABEL(gpio_000_036)),
|
||||
gpio_xec_port000_036_init,
|
||||
&gpio_xec_port000_036_data, &gpio_xec_port000_036_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
|
||||
static int gpio_xec_port000_036_init(const struct device *dev)
|
||||
{
|
||||
|
@ -341,8 +353,8 @@ static int gpio_xec_port000_036_init(const struct device *dev)
|
|||
MCHP_GIRQ_BLK_SETEN(config->girq_id);
|
||||
|
||||
IRQ_CONNECT(DT_IRQ(DT_NODELABEL(gpio_000_036), irq),
|
||||
DT_IRQ(DT_NODELABEL(gpio_000_036), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port000_036), 0U);
|
||||
DT_IRQ(DT_NODELABEL(gpio_000_036), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port000_036), 0U);
|
||||
|
||||
irq_enable(DT_IRQ(DT_NODELABEL(gpio_000_036), irq));
|
||||
#endif
|
||||
|
@ -356,7 +368,7 @@ static int gpio_xec_port040_076_init(const struct device *dev);
|
|||
static const struct gpio_xec_config gpio_xec_port040_076_config = {
|
||||
.common = {
|
||||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_NODE(
|
||||
DT_NODELABEL(gpio_040_076)),
|
||||
DT_NODELABEL(gpio_040_076)),
|
||||
},
|
||||
.pcr1_base = (uint32_t *) DT_REG_ADDR(DT_NODELABEL(gpio_040_076)),
|
||||
.port_num = MCHP_GPIO_040_076,
|
||||
|
@ -371,11 +383,11 @@ static const struct gpio_xec_config gpio_xec_port040_076_config = {
|
|||
static struct gpio_xec_data gpio_xec_port040_076_data;
|
||||
|
||||
DEVICE_AND_API_INIT(gpio_xec_port040_076,
|
||||
DT_LABEL(DT_NODELABEL(gpio_040_076)),
|
||||
gpio_xec_port040_076_init,
|
||||
&gpio_xec_port040_076_data, &gpio_xec_port040_076_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
DT_LABEL(DT_NODELABEL(gpio_040_076)),
|
||||
gpio_xec_port040_076_init,
|
||||
&gpio_xec_port040_076_data, &gpio_xec_port040_076_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
|
||||
static int gpio_xec_port040_076_init(const struct device *dev)
|
||||
{
|
||||
|
@ -386,8 +398,8 @@ static int gpio_xec_port040_076_init(const struct device *dev)
|
|||
MCHP_GIRQ_BLK_SETEN(config->girq_id);
|
||||
|
||||
IRQ_CONNECT(DT_IRQ(DT_NODELABEL(gpio_040_076), irq),
|
||||
DT_IRQ(DT_NODELABEL(gpio_040_076), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port040_076), 0U);
|
||||
DT_IRQ(DT_NODELABEL(gpio_040_076), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port040_076), 0U);
|
||||
|
||||
irq_enable(DT_IRQ(DT_NODELABEL(gpio_040_076), irq));
|
||||
#endif
|
||||
|
@ -401,7 +413,7 @@ static int gpio_xec_port100_136_init(const struct device *dev);
|
|||
static const struct gpio_xec_config gpio_xec_port100_136_config = {
|
||||
.common = {
|
||||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_NODE(
|
||||
DT_NODELABEL(gpio_100_136)),
|
||||
DT_NODELABEL(gpio_100_136)),
|
||||
},
|
||||
.pcr1_base = (uint32_t *) DT_REG_ADDR(DT_NODELABEL(gpio_100_136)),
|
||||
.port_num = MCHP_GPIO_100_136,
|
||||
|
@ -416,11 +428,11 @@ static const struct gpio_xec_config gpio_xec_port100_136_config = {
|
|||
static struct gpio_xec_data gpio_xec_port100_136_data;
|
||||
|
||||
DEVICE_AND_API_INIT(gpio_xec_port100_136,
|
||||
DT_LABEL(DT_NODELABEL(gpio_100_136)),
|
||||
gpio_xec_port100_136_init,
|
||||
&gpio_xec_port100_136_data, &gpio_xec_port100_136_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
DT_LABEL(DT_NODELABEL(gpio_100_136)),
|
||||
gpio_xec_port100_136_init,
|
||||
&gpio_xec_port100_136_data, &gpio_xec_port100_136_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
|
||||
static int gpio_xec_port100_136_init(const struct device *dev)
|
||||
{
|
||||
|
@ -431,8 +443,8 @@ static int gpio_xec_port100_136_init(const struct device *dev)
|
|||
MCHP_GIRQ_BLK_SETEN(config->girq_id);
|
||||
|
||||
IRQ_CONNECT(DT_IRQ(DT_NODELABEL(gpio_100_136), irq),
|
||||
DT_IRQ(DT_NODELABEL(gpio_100_136), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port100_136), 0U);
|
||||
DT_IRQ(DT_NODELABEL(gpio_100_136), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port100_136), 0U);
|
||||
|
||||
irq_enable(DT_IRQ(DT_NODELABEL(gpio_100_136), irq));
|
||||
#endif
|
||||
|
@ -446,7 +458,7 @@ static int gpio_xec_port140_176_init(const struct device *dev);
|
|||
static const struct gpio_xec_config gpio_xec_port140_176_config = {
|
||||
.common = {
|
||||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_NODE(
|
||||
DT_NODELABEL(gpio_140_176)),
|
||||
DT_NODELABEL(gpio_140_176)),
|
||||
},
|
||||
.pcr1_base = (uint32_t *) DT_REG_ADDR(DT_NODELABEL(gpio_140_176)),
|
||||
.port_num = MCHP_GPIO_140_176,
|
||||
|
@ -461,11 +473,11 @@ static const struct gpio_xec_config gpio_xec_port140_176_config = {
|
|||
static struct gpio_xec_data gpio_xec_port140_176_data;
|
||||
|
||||
DEVICE_AND_API_INIT(gpio_xec_port140_176,
|
||||
DT_LABEL(DT_NODELABEL(gpio_140_176)),
|
||||
gpio_xec_port140_176_init,
|
||||
&gpio_xec_port140_176_data, &gpio_xec_port140_176_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
DT_LABEL(DT_NODELABEL(gpio_140_176)),
|
||||
gpio_xec_port140_176_init,
|
||||
&gpio_xec_port140_176_data, &gpio_xec_port140_176_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
|
||||
static int gpio_xec_port140_176_init(const struct device *dev)
|
||||
{
|
||||
|
@ -476,8 +488,8 @@ static int gpio_xec_port140_176_init(const struct device *dev)
|
|||
MCHP_GIRQ_BLK_SETEN(config->girq_id);
|
||||
|
||||
IRQ_CONNECT(DT_IRQ(DT_NODELABEL(gpio_140_176), irq),
|
||||
DT_IRQ(DT_NODELABEL(gpio_140_176), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port140_176), 0U);
|
||||
DT_IRQ(DT_NODELABEL(gpio_140_176), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port140_176), 0U);
|
||||
|
||||
irq_enable(DT_IRQ(DT_NODELABEL(gpio_140_176), irq));
|
||||
#endif
|
||||
|
@ -491,7 +503,7 @@ static int gpio_xec_port200_236_init(const struct device *dev);
|
|||
static const struct gpio_xec_config gpio_xec_port200_236_config = {
|
||||
.common = {
|
||||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_NODE(
|
||||
DT_NODELABEL(gpio_200_236)),
|
||||
DT_NODELABEL(gpio_200_236)),
|
||||
},
|
||||
.pcr1_base = (uint32_t *) DT_REG_ADDR(DT_NODELABEL(gpio_200_236)),
|
||||
.port_num = MCHP_GPIO_200_236,
|
||||
|
@ -506,11 +518,11 @@ static const struct gpio_xec_config gpio_xec_port200_236_config = {
|
|||
static struct gpio_xec_data gpio_xec_port200_236_data;
|
||||
|
||||
DEVICE_AND_API_INIT(gpio_xec_port200_236,
|
||||
DT_LABEL(DT_NODELABEL(gpio_200_236)),
|
||||
gpio_xec_port200_236_init,
|
||||
&gpio_xec_port200_236_data, &gpio_xec_port200_236_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
DT_LABEL(DT_NODELABEL(gpio_200_236)),
|
||||
gpio_xec_port200_236_init,
|
||||
&gpio_xec_port200_236_data, &gpio_xec_port200_236_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
|
||||
static int gpio_xec_port200_236_init(const struct device *dev)
|
||||
{
|
||||
|
@ -521,8 +533,8 @@ static int gpio_xec_port200_236_init(const struct device *dev)
|
|||
MCHP_GIRQ_BLK_SETEN(config->girq_id);
|
||||
|
||||
IRQ_CONNECT(DT_IRQ(DT_NODELABEL(gpio_200_236), irq),
|
||||
DT_IRQ(DT_NODELABEL(gpio_200_236), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port200_236), 0U);
|
||||
DT_IRQ(DT_NODELABEL(gpio_200_236), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port200_236), 0U);
|
||||
|
||||
irq_enable(DT_IRQ(DT_NODELABEL(gpio_200_236), irq));
|
||||
#endif
|
||||
|
@ -536,7 +548,7 @@ static int gpio_xec_port240_276_init(const struct device *dev);
|
|||
static const struct gpio_xec_config gpio_xec_port240_276_config = {
|
||||
.common = {
|
||||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_NODE(
|
||||
DT_NODELABEL(gpio_240_276)),
|
||||
DT_NODELABEL(gpio_240_276)),
|
||||
},
|
||||
.pcr1_base = (uint32_t *) DT_REG_ADDR(DT_NODELABEL(gpio_240_276)),
|
||||
.port_num = MCHP_GPIO_240_276,
|
||||
|
@ -551,11 +563,11 @@ static const struct gpio_xec_config gpio_xec_port240_276_config = {
|
|||
static struct gpio_xec_data gpio_xec_port240_276_data;
|
||||
|
||||
DEVICE_AND_API_INIT(gpio_xec_port240_276,
|
||||
DT_LABEL(DT_NODELABEL(gpio_240_276)),
|
||||
gpio_xec_port240_276_init,
|
||||
&gpio_xec_port240_276_data, &gpio_xec_port240_276_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
DT_LABEL(DT_NODELABEL(gpio_240_276)),
|
||||
gpio_xec_port240_276_init,
|
||||
&gpio_xec_port240_276_data, &gpio_xec_port240_276_config,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&gpio_xec_driver_api);
|
||||
|
||||
static int gpio_xec_port240_276_init(const struct device *dev)
|
||||
{
|
||||
|
@ -566,8 +578,8 @@ static int gpio_xec_port240_276_init(const struct device *dev)
|
|||
MCHP_GIRQ_BLK_SETEN(config->girq_id);
|
||||
|
||||
IRQ_CONNECT(DT_IRQ(DT_NODELABEL(gpio_240_276), irq),
|
||||
DT_IRQ(DT_NODELABEL(gpio_240_276), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port240_276), 0U);
|
||||
DT_IRQ(DT_NODELABEL(gpio_240_276), priority),
|
||||
gpio_gpio_xec_port_isr, DEVICE_GET(gpio_xec_port240_276), 0U);
|
||||
|
||||
irq_enable(DT_IRQ(DT_NODELABEL(gpio_240_276), irq));
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue