@ -11,6 +11,11 @@
@@ -11,6 +11,11 @@
# include "gpio_utils.h"
# define GPIO_IN_BASE(config) \
( ( __IO u32_t * ) ( GPIO_PARIN_BASE + ( config - > port_num < < 2 ) ) )
# define GPIO_OUT_BASE(config) \
( ( __IO u32_t * ) ( GPIO_PAROUT_BASE + ( config - > port_num < < 2 ) ) )
static const u32_t valid_ctrl_masks [ NUM_MCHP_GPIO_PORTS ] = {
( MCHP_GPIO_PORT_A_BITMAP ) ,
@ -42,23 +47,19 @@ static int gpio_xec_configure(struct device *dev,
@@ -42,23 +47,19 @@ static int gpio_xec_configure(struct device *dev,
{
const struct gpio_xec_config * config = dev - > config - > config_info ;
__IO u32_t * current_pcr1 ;
u32_t pcr1 = 0 ;
u32_t mask = 0 ;
u32_t gpio_interrupt = 0 ;
u32_t pcr1 = 0U ;
u32_t mask = 0U ;
__IO u32_t * gpio_out_reg = GPIO_OUT_BASE ( config ) ;
/* Validate pin number range in terms of current port */
if ( ( valid_ctrl_masks [ config - > port_num ] & BIT ( pin ) ) = = 0 ) {
return - EINVAL ;
}
/* Check for an invalid pin configuration */
if ( ( flags & GPIO_INT ) & & ( flags & GPIO_DIR_OUT ) ) {
if ( ( valid_ctrl_masks [ config - > port_num ] & BIT ( pin ) ) = = 0U ) {
return - EINVAL ;
}
/* Check if GPIO port supports interrupts */
if ( ( flags & GPIO_INT ) & & ( ( config - > flags & GPIO_INT ) = = 0 ) ) {
return - EINVAL ;
/* Don't support "open source" mode */
if ( ( ( flags & GPIO_SINGLE_ENDED ) ! = 0U ) & &
( ( flags & GPIO_LINE_OPEN_DRAIN ) = = 0U ) ) {
return - ENOTSUP ;
}
/* The flags contain options that require touching registers in the
@ -70,13 +71,19 @@ static int gpio_xec_configure(struct device *dev,
@@ -70,13 +71,19 @@ static int gpio_xec_configure(struct device *dev,
mask | = MCHP_GPIO_CTRL_DIR_MASK ;
mask | = MCHP_GPIO_CTRL_INPAD_DIS_MASK ;
if ( access_op = = GPIO_ACCESS_BY_PIN ) {
if ( ( flags & GPIO_DIR_MASK ) = = GPIO_DIR_IN ) {
pcr1 & = ~ BIT ( MCHP_GPIO_CTRL_DIR_POS ) ;
} else { /* GPIO_DIR_OUT */
pcr1 | = BIT ( MCHP_GPIO_CTRL_DIR_POS ) ;
if ( ( flags & GPIO_OUTPUT ) ! = 0U ) {
if ( ( flags & GPIO_OUTPUT_INIT_HIGH ) ! = 0U ) {
* gpio_out_reg | = BIT ( pin ) ;
} else if ( ( flags & GPIO_OUTPUT_INIT_LOW ) ! = 0U ) {
* gpio_out_reg & = ~ BIT ( pin ) ;
}
pcr1 | = MCHP_GPIO_CTRL_DIR_OUTPUT ;
} else {
/* GPIO_INPUT */
pcr1 | = MCHP_GPIO_CTRL_DIR_INPUT ;
}
} else { /* GPIO_ACCESS_BY_PORT is not supported */
return - EINVAL ;
return - ENOTSUP ;
}
/* Figure out the pullup/pulldown configuration and keep it in the
@ -84,69 +91,129 @@ static int gpio_xec_configure(struct device *dev,
@@ -84,69 +91,129 @@ static int gpio_xec_configure(struct device *dev,
*/
mask | = MCHP_GPIO_CTRL_PUD_MASK ;
if ( ( flags & GPIO_PUD_MASK ) = = GPIO_PUD_PULL_UP ) {
if ( ( flags & GPIO_PULL_UP ) ! = 0U ) {
/* Enable the pull and select the pullup resistor. */
pcr1 | = MCHP_GPIO_CTRL_PUD_PU ;
} else if ( ( flags & GPIO_PUD_MASK ) = = GPIO_PUD_PULL_DOWN ) {
} else if ( ( flags & GPIO_PULL_DOWN ) ! = 0U ) {
/* Enable the pull and select the pulldown resistor */
pcr1 | = MCHP_GPIO_CTRL_PUD_PD ;
}
/* Push-pull or open drain */
mask | = MCHP_GPIO_CTRL_BUFT_MASK ;
if ( ( flags & GPIO_OPEN_DRAIN ) ! = 0U ) {
/* Open drain */
pcr1 | = MCHP_GPIO_CTRL_BUFT_OPENDRAIN ;
} else {
/* Push-pull */
pcr1 | = MCHP_GPIO_CTRL_BUFT_PUSHPULL ;
}
/* Use GPIO output register to control pin output, instead of
* using the control register ( = > alternate output disable ) .
*/
mask | = MCHP_GPIO_CTRL_AOD_MASK ;
pcr1 | = MCHP_GPIO_CTRL_AOD_DIS ;
/* Now write contents of pcr1 variable to the PCR1 register that
* corresponds to the GPIO being configured
*/
current_pcr1 = config - > pcr1_base + pin ;
* current_pcr1 = ( * current_pcr1 & ~ mask ) | pcr1 ;
return 0 ;
}
static int gpio_xec_pin_interrupt_configure ( struct device * dev ,
unsigned int pin , enum gpio_int_mode mode ,
enum gpio_int_trig trig )
{
const struct gpio_xec_config * config = dev - > config - > config_info ;
struct gpio_xec_data * drv_data = dev - > driver_data ;
__IO u32_t * current_pcr1 ;
u32_t pcr1 = 0U ;
u32_t mask = 0U ;
u32_t gpio_interrupt = 0U ;
/* Validate pin number range in terms of current port */
if ( ( valid_ctrl_masks [ config - > port_num ] & BIT ( pin ) ) = = 0U ) {
return - EINVAL ;
}
/* Check if GPIO port supports interrupts */
if ( ( mode ! = GPIO_INT_MODE_DISABLED ) & &
( ( config - > flags & GPIO_INT_ENABLE ) = = 0U ) ) {
return - ENOTSUP ;
}
/* Assemble mask for level/edge triggered interrrupts */
mask | = MCHP_GPIO_CTRL_IDET_MASK ;
if ( flags & GPIO_INT ) {
if ( flags & GPIO_INT_EDGE ) {
/* Enable edge interrupts */
if ( flags & GPIO_INT_ACTIVE_HIGH ) {
gpio_interrupt = MCHP_GPIO_CTRL_IDET_REDGE ;
} else if ( flags & GPIO_INT_DOUBLE_EDGE ) {
gpio_interrupt = MCHP_GPIO_CTRL_IDET_BEDGE ;
} else {
gpio_interrupt = MCHP_GPIO_CTRL_IDET_FEDGE ;
}
} else { /* GPIO_INT_LEVEL */
if ( flags & GPIO_INT_ACTIVE_HIGH ) {
if ( mode = = GPIO_INT_MODE_DISABLED ) {
/* Explicitly disable interrupts, otherwise the configuration
* results in level triggered / low interrupts
*/
pcr1 | = MCHP_GPIO_CTRL_IDET_DISABL E;
/* Disable interrupt in the EC aggregator */
MCHP_GIRQ_ENCLR ( config - > girq_id ) = BIT ( pin ) ;
} else {
if ( mode = = GPIO_INT_MODE_LEVEL ) {
/* Enable level interrupts */
if ( trig = = GPIO_INT_TRIG _HIGH) {
gpio_interrupt = MCHP_GPIO_CTRL_IDET_LVL_HI ;
} else {
gpio_interrupt = MCHP_GPIO_CTRL_IDET_LVL_LO ;
}
} else {
/* Enable edge interrupts */
switch ( trig ) {
case GPIO_INT_TRIG_LOW :
gpio_interrupt = MCHP_GPIO_CTRL_IDET_FEDGE ;
break ;
case GPIO_INT_TRIG_HIGH :
gpio_interrupt = MCHP_GPIO_CTRL_IDET_REDGE ;
break ;
case GPIO_INT_TRIG_BOTH :
gpio_interrupt = MCHP_GPIO_CTRL_IDET_BEDGE ;
break ;
default :
return - EINVAL ;
}
}
pcr1 | = gpio_interrupt ;
/* We enable the interrupts in the EC aggregator so that the
* result can be forwarded to the ARM NVIC
* result can be forwarded to the ARM NVIC
*/
MCHP_GIRQ_SRC_CLR ( config - > girq_id , pin ) ;
MCHP_GIRQ_ENSET ( config - > girq_id ) = BIT ( pin ) ;
} else {
/* Explicitly disable interrupts, otherwise the configuration
* results in level triggered / low interrupts
*/
pcr1 | = MCHP_GPIO_CTRL_IDET_DISABLE ;
}
/* Use Gpio output register for writing in order to have simetry with
* respect of Gpio input
*/
mask | = MCHP_GPIO_CTRL_AOD_MASK ;
pcr1 | = MCHP_GPIO_CTRL_AOD_MASK ;
/* Now write contents of pcr1 variable to the PCR1 register that
* corresponds to the GPIO being configured
*/
current_pcr1 = config - > pcr1_base + pin ;
* current_pcr1 = ( * current_pcr1 & ~ mask ) | pcr1 ;
if ( mode = = GPIO_INT_MODE_DISABLED ) {
drv_data - > pin_callback_enables & = ~ BIT ( pin ) ;
} else {
drv_data - > pin_callback_enables | = BIT ( pin ) ;
}
return 0 ;
}
static int gpio_xec_write ( struct device * dev ,
int access_op , u32_t pin , u32_t value )
{
const struct gpio_xec_config * config = dev - > config - > config_info ;
u32_t port_n = config - > port_num ;
/* GPIO output registers are used for writing */
__IO u32_t * gpio_base = ( __IO u32_t * ) ( GPIO_PAROUT_BASE
+ ( port_n < < 2 ) ) ;
__IO u32_t * gpio_base = GPIO_OUT_BASE ( config ) ;
if ( access_op = = GPIO_ACCESS_BY_PIN ) {
if ( value ) {
@ -170,26 +237,79 @@ static int gpio_xec_write(struct device *dev,
@@ -170,26 +237,79 @@ static int gpio_xec_write(struct device *dev,
}
static int gpio_xec_read ( struct device * dev ,
int access_op , u32_t pin , u32_t * value )
static int gpio_xec_port_set_masked_raw ( struct device * dev , u32_t mask ,
u32_t value )
{
const struct gpio_xec_config * config = dev - > config - > config_info ;
/* GPIO output registers are used for writing */
__IO u32_t * gpio_base = GPIO_OUT_BASE ( config ) ;
* gpio_base = ( * gpio_base & ~ mask ) | ( mask & value ) ;
return 0 ;
}
static int gpio_xec_port_set_bits_raw ( struct device * dev , u32_t mask )
{
const struct gpio_xec_config * config = dev - > config - > config_info ;
/* GPIO output registers are used for writing */
__IO u32_t * gpio_base = GPIO_OUT_BASE ( config ) ;
* gpio_base | = mask ;
return 0 ;
}
static int gpio_xec_port_clear_bits_raw ( struct device * dev , u32_t mask )
{
const struct gpio_xec_config * config = dev - > config - > config_info ;
/* GPIO output registers are used for writing */
__IO u32_t * gpio_base = GPIO_OUT_BASE ( config ) ;
* gpio_base & = ~ mask ;
return 0 ;
}
static int gpio_xec_port_toggle_bits ( struct device * dev , u32_t mask )
{
const struct gpio_xec_config * config = dev - > config - > config_info ;
/* GPIO output registers are used for writing */
__IO u32_t * gpio_base = GPIO_OUT_BASE ( config ) ;
* gpio_base ^ = mask ;
return 0 ;
}
static int gpio_xec_port_get_raw ( struct device * dev , u32_t * value )
{
const struct gpio_xec_config * config = dev - > config - > config_info ;
u32_t port_n = config - > port_num ;
/* GPIO input registers are used for reading */
__IO u32_t * gpio_base = ( __IO u32_t * ) ( GPIO_PARIN_BASE + ( port_n < < 2 ) ) ;
__IO u32_t * gpio_base = GPIO_IN_BASE ( config ) ;
* value = * gpio_base ;
return 0 ;
}
static int gpio_xec_read ( struct device * dev ,
int access_op , u32_t pin , u32_t * value )
{
gpio_xec_port_get_raw ( dev , value ) ;
if ( access_op = = GPIO_ACCESS_BY_PIN ) {
* value = ( * value & BIT ( pin ) ) > > pin ;
} else { /* GPIO_ACCESS_BY_PORT not supported */
return - EINVAL ;
}
return 0 ;
}
static int gpio_xec_manage_callback ( struct device * dev ,
struct gpio_callback * callback , bool set )
{
@ -239,7 +359,7 @@ static void gpio_gpio_xec_port_isr(void *arg)
@@ -239,7 +359,7 @@ static void gpio_gpio_xec_port_isr(void *arg)
* aggregator result register
*/
girq_result = MCHP_GIRQ_RESULT ( config - > girq_id ) ;
enabled_int = girq_result & data - > pin_callback_enables ;
enabled_int = girq_result & data - > pin_callback_enables ;
/* Clear source register in aggregator before firing callbacks */
REG32 ( MCHP_GIRQ_SRC_ADDR ( config - > girq_id ) ) = girq_result ;
@ -251,6 +371,12 @@ static const struct gpio_driver_api gpio_xec_driver_api = {
@@ -251,6 +371,12 @@ static const struct gpio_driver_api gpio_xec_driver_api = {
. config = gpio_xec_configure ,
. write = gpio_xec_write ,
. read = gpio_xec_read ,
. port_get_raw = gpio_xec_port_get_raw ,
. port_set_masked_raw = gpio_xec_port_set_masked_raw ,
. port_set_bits_raw = gpio_xec_port_set_bits_raw ,
. port_clear_bits_raw = gpio_xec_port_clear_bits_raw ,
. port_toggle_bits = gpio_xec_port_toggle_bits ,
. pin_interrupt_configure = gpio_xec_pin_interrupt_configure ,
. manage_callback = gpio_xec_manage_callback ,
. enable_callback = gpio_xec_enable_callback ,
. disable_callback = gpio_xec_disable_callback ,
@ -264,7 +390,7 @@ static const struct gpio_xec_config gpio_xec_port000_036_config = {
@@ -264,7 +390,7 @@ static const struct gpio_xec_config gpio_xec_port000_036_config = {
. port_num = MCHP_GPIO_000_036 ,
# ifdef DT_GPIO_XEC_GPIO000_036_IRQ
. girq_id = MCHP_GIRQ11_ID ,
. flags = GPIO_INT ,
. flags = GPIO_INT_ENABLE ,
# else
. flags = 0 ,
# endif
@ -288,7 +414,7 @@ static int gpio_xec_port000_036_init(struct device *dev)
@@ -288,7 +414,7 @@ static int gpio_xec_port000_036_init(struct device *dev)
IRQ_CONNECT ( DT_GPIO_XEC_GPIO000_036_IRQ ,
DT_GPIO_XEC_GPIO000_036_IRQ_PRIORITY ,
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port000_036 ) , 0 ) ;
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port000_036 ) , 0U ) ;
irq_enable ( DT_GPIO_XEC_GPIO000_036_IRQ ) ;
# endif
@ -304,7 +430,7 @@ static const struct gpio_xec_config gpio_xec_port040_076_config = {
@@ -304,7 +430,7 @@ static const struct gpio_xec_config gpio_xec_port040_076_config = {
. port_num = MCHP_GPIO_040_076 ,
# ifdef DT_GPIO_XEC_GPIO040_076_IRQ
. girq_id = MCHP_GIRQ10_ID ,
. flags = GPIO_INT ,
. flags = GPIO_INT_ENABLE ,
# else
. flags = 0 ,
# endif
@ -328,7 +454,7 @@ static int gpio_xec_port040_076_init(struct device *dev)
@@ -328,7 +454,7 @@ static int gpio_xec_port040_076_init(struct device *dev)
IRQ_CONNECT ( DT_GPIO_XEC_GPIO040_076_IRQ ,
DT_GPIO_XEC_GPIO040_076_IRQ_PRIORITY ,
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port040_076 ) , 0 ) ;
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port040_076 ) , 0U ) ;
irq_enable ( DT_GPIO_XEC_GPIO040_076_IRQ ) ;
# endif
@ -344,7 +470,7 @@ static const struct gpio_xec_config gpio_xec_port100_136_config = {
@@ -344,7 +470,7 @@ static const struct gpio_xec_config gpio_xec_port100_136_config = {
. port_num = MCHP_GPIO_100_136 ,
# ifdef DT_GPIO_XEC_GPIO100_136_IRQ
. girq_id = MCHP_GIRQ09_ID ,
. flags = GPIO_INT ,
. flags = GPIO_INT_ENABLE ,
# else
. flags = 0 ,
# endif
@ -368,7 +494,7 @@ static int gpio_xec_port100_136_init(struct device *dev)
@@ -368,7 +494,7 @@ static int gpio_xec_port100_136_init(struct device *dev)
IRQ_CONNECT ( DT_GPIO_XEC_GPIO100_136_IRQ ,
DT_GPIO_XEC_GPIO100_136_IRQ_PRIORITY ,
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port100_136 ) , 0 ) ;
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port100_136 ) , 0U ) ;
irq_enable ( DT_GPIO_XEC_GPIO100_136_IRQ ) ;
# endif
@ -384,7 +510,7 @@ static const struct gpio_xec_config gpio_xec_port140_176_config = {
@@ -384,7 +510,7 @@ static const struct gpio_xec_config gpio_xec_port140_176_config = {
. port_num = MCHP_GPIO_140_176 ,
# ifdef DT_GPIO_XEC_GPIO140_176_IRQ
. girq_id = MCHP_GIRQ08_ID ,
. flags = GPIO_INT ,
. flags = GPIO_INT_ENABLE ,
# else
. flags = 0 ,
# endif
@ -408,7 +534,7 @@ static int gpio_xec_port140_176_init(struct device *dev)
@@ -408,7 +534,7 @@ static int gpio_xec_port140_176_init(struct device *dev)
IRQ_CONNECT ( DT_GPIO_XEC_GPIO140_176_IRQ ,
DT_GPIO_XEC_GPIO140_176_IRQ_PRIORITY ,
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port140_176 ) , 0 ) ;
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port140_176 ) , 0U ) ;
irq_enable ( DT_GPIO_XEC_GPIO140_176_IRQ ) ;
# endif
@ -424,7 +550,7 @@ static const struct gpio_xec_config gpio_xec_port200_236_config = {
@@ -424,7 +550,7 @@ static const struct gpio_xec_config gpio_xec_port200_236_config = {
. port_num = MCHP_GPIO_200_236 ,
# ifdef DT_GPIO_XEC_GPIO200_236_IRQ
. girq_id = MCHP_GIRQ12_ID ,
. flags = GPIO_INT ,
. flags = GPIO_INT_ENABLE ,
# else
. flags = 0 ,
# endif
@ -448,7 +574,7 @@ static int gpio_xec_port200_236_init(struct device *dev)
@@ -448,7 +574,7 @@ static int gpio_xec_port200_236_init(struct device *dev)
IRQ_CONNECT ( DT_GPIO_XEC_GPIO200_236_IRQ ,
DT_GPIO_XEC_GPIO200_236_IRQ_PRIORITY ,
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port200_236 ) , 0 ) ;
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port200_236 ) , 0U ) ;
irq_enable ( DT_GPIO_XEC_GPIO200_236_IRQ ) ;
# endif
@ -464,7 +590,7 @@ static const struct gpio_xec_config gpio_xec_port240_276_config = {
@@ -464,7 +590,7 @@ static const struct gpio_xec_config gpio_xec_port240_276_config = {
. port_num = MCHP_GPIO_240_276 ,
# ifdef DT_GPIO_XEC_GPIO240_276_IRQ
. girq_id = MCHP_GIRQ26_ID ,
. flags = GPIO_INT ,
. flags = GPIO_INT_ENABLE ,
# else
. flags = 0 ,
# endif
@ -488,7 +614,7 @@ static int gpio_xec_port240_276_init(struct device *dev)
@@ -488,7 +614,7 @@ static int gpio_xec_port240_276_init(struct device *dev)
IRQ_CONNECT ( DT_GPIO_XEC_GPIO240_276_IRQ ,
DT_GPIO_XEC_GPIO240_276_IRQ_PRIORITY ,
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port240_276 ) , 0 ) ;
gpio_gpio_xec_port_isr , DEVICE_GET ( gpio_xec_port240_276 ) , 0U ) ;
irq_enable ( DT_GPIO_XEC_GPIO240_276_IRQ ) ;
# endif