BCM2708: Fleshes out GPIO interrupt logic.

This commit is contained in:
Gregory Nutt 2017-10-18 10:13:10 -06:00
parent 63b93a9fba
commit 25079a9c93
5 changed files with 322 additions and 60 deletions

View File

@ -193,7 +193,9 @@
/* Second level GPIO interrupts */ /* Second level GPIO interrupts */
#ifdef CONFIG_BCM2708_GPIO_IRQ #ifdef CONFIG_BCM2708_GPIO_IRQ
# define BCM_IRQ_GPIO(n) (NR_INTERRUPTS + (n)) # define BCM_IRQ_GPIO(n) (NR_INTERRUPTS + (n)) /* IRQ number of pin n */
# define BCM_IRQ_GPIO0_FIRST (NR_INTERRUPTS) /* IRQ number of first GPIO0 interrupt */
# define BCM_IRQ_GPIO1_FIRST (NR_INTERRUPTS + 32) /* IRQ number of first GPIO1 interrupt */
# define NR_GPIOINTS (54) # define NR_GPIOINTS (54)
#else #else
# define NR_GPIOINTS (0) # define NR_GPIOINTS (0)

View File

@ -237,7 +237,7 @@ void bcm_gpio_write(gpio_pinset_t pinset, bool value)
regaddr = BCM_GPIO_GPCLR(pin); regaddr = BCM_GPIO_GPCLR(pin);
} }
putreg32(BCM_GPIO_GPSET0_SET(pin), regaddr); putreg32(BCM_GPIO_GPSET_SET(pin), regaddr);
} }
/************************************************************************************ /************************************************************************************
@ -252,7 +252,7 @@ bool bcm_gpio_read(gpio_pinset_t pinset)
{ {
unsigned int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; unsigned int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
uintptr_t regaddr = BCM_GPIO_GPLEV(pin); uintptr_t regaddr = BCM_GPIO_GPLEV(pin);
uint32_t mask = BCM_GPIO_GPLEV0_LEV(pin); uint32_t mask = BCM_GPIO_GPLEV_LEV(pin);
return (getreg32(regaddr) & mask) != 0; return (getreg32(regaddr) & mask) != 0;
} }

View File

@ -261,46 +261,34 @@ void bcm_gpio_write(gpio_pinset_t pinset, bool value);
bool bcm_gpio_read(gpio_pinset_t pinset); bool bcm_gpio_read(gpio_pinset_t pinset);
/************************************************************************************ /****************************************************************************
* Name: bcm_gpio_irqconfig
*
* Description:
* Configure an interrupt for the specified GPIO pin.
*
************************************************************************************/
#ifdef CONFIG_BCM2708_GPIO_IRQ
void bcm_gpio_irqconfig(gpio_pinset_t pinset);
#else
# define bcm_gpio_irqconfig(pinset)
#endif
/************************************************************************************
* Name: bcm_gpio_irqenable * Name: bcm_gpio_irqenable
* *
* Description: * Description:
* Enable the interrupt for specified GPIO IRQ * Configure interrupt event detection for the specified GPIO pin. This
* effective enables the pin interrupts.
* *
************************************************************************************/ ****************************************************************************/
#ifdef CONFIG_BCM2708_GPIO_IRQ #ifdef CONFIG_BCM2708_GPIO_IRQ
void bcm_gpio_irqenable(int irq); void bcm_gpio_irqenable(gpio_pinset_t pinset);
#else #else
# define bcm_gpio_irqenable(irq) # define bcm_gpio_irqenable(p)
#endif #endif
/************************************************************************************ /************************************************************************************
* Name: bcm_gpio_irqdisable * Name: bcm_gpio_irqdisable
* *
* Description: * Description:
* Disable the interrupt for specified GPIO IRQ * Reset interrupt event detection for the specified GPIO pin. This
* effective disables the pin interrupts.
* *
************************************************************************************/ ************************************************************************************/
#ifdef CONFIG_BCM2708_GPIO_IRQ #ifdef CONFIG_BCM2708_GPIO_IRQ
void bcm_gpio_irqdisable(int irq); void bcm_gpio_irqdisable(gpio_pinset_t pinset);
#else #else
# define bcm_gpio_irqdisable(irq) # define bcm_gpio_irqdisable(p)
#endif #endif
#undef EXTERN #undef EXTERN

View File

@ -44,60 +44,332 @@
#ifdef CONFIG_BCM2708_GPIO_IRQ #ifdef CONFIG_BCM2708_GPIO_IRQ
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bcm_gpio_risingedge
*
* Description:
* Set/clear rising edge detection.
*
****************************************************************************/
static void bcm_gpio_risingedge(unsigned int pin, gpio_pinset_t pinset)
{
uintptr_t regaddr = BCM_GPIO_GPREN(pin);
uint32_t mask = BCM_GPIO_GPREN_REN(pin;
if ((pinset & GPIO_INT_MASK) == GPIO_INT_RISING
{
modifiyreg32(regaddr, 0, mask);
}
else
{
modifiyreg32(regaddr, mask, 0);
}
}
/****************************************************************************
* Name: bcm_gpio_fallingedge
*
* Description:
* Set/clear falling edge detection.
*
****************************************************************************/
static void bcm_gpio_fallingedge(unsigned int pin, gpio_pinset_t pinset)
{
uintptr_t regaddr = BCM_GPIO_GPFEN(pin);
uint32_t mask = BCM_GPIO_GPFEN_FEN(pin;
if ((pinset & GPIO_INT_MASK) == GPIO_INT_FALLING
{
modifiyreg32(regaddr, 0, mask);
}
else
{
modifiyreg32(regaddr, mask, 0);
}
}
/****************************************************************************
* Name: bcm_gpio_highlevel
*
* Description:
* Set/clear high level detection.
*
****************************************************************************/
static void bcm_gpio_highlevel(unsigned int pin, gpio_pinset_t pinset)
{
uintptr_t regaddr = BCM_GPIO_GPHEN(pin);
uint32_t mask = BCM_GPIO_GPHEN_HEN(pin;
if ((pinset & GPIO_INT_MASK) == GPIO_INT_HIGHLEVEL
{
modifiyreg32(regaddr, 0, mask);
}
else
{
modifiyreg32(regaddr, mask, 0);
}
}
/****************************************************************************
* Name: bcm_gpio_lowlevel
*
* Description:
* Set/clear low level detection.
*
****************************************************************************/
static void bcm_gpio_lowlevel(unsigned int pin, gpio_pinset_t pinset)
{
uintptr_t regaddr = BCM_GPIO_GPLEN(pin);
uint32_t mask = BCM_GPIO_GPHEN_HEN(pin;
if ((pinset & GPIO_INT_MASK) == GPIO_INT_LOWLEVEL
{
modifiyreg32(regaddr, 0, mask);
}
else
{
modifiyreg32(regaddr, mask, 0);
}
}
/****************************************************************************
* Name: bcm_gpio_async_risingedge
*
* Description:
* Set/clear asynchronous rising edge detection.
*
****************************************************************************/
static void bcm_gpio_async_risingedge(unsigned int pin, gpio_pinset_t pinset)
{
uintptr_t regaddr = BCM_GPIO_GPAREN(pin);
uint32_t mask = BCM_GPIO_GPAREN_AREN(pin;
if ((pinset & GPIO_INT_MASK) == GPIO_INT_ASYNCHRISING
{
modifiyreg32(regaddr, 0, mask);
}
else
{
modifiyreg32(regaddr, mask, 0);
}
}
/****************************************************************************
* Name: bcm_gpio_async_fallingedge
*
* Description:
* Set/clear asynchronous falling edge detection.
*
****************************************************************************/
static void bcm_gpio_async_fallingedge(unsigned int pin, gpio_pinset_t pinset)
{
uintptr_t regaddr = BCM_GPIO_GPAFEN(pin);
uint32_t mask = BCM_GPIO_GPAFEN_AFEN(pin;
if ((pinset & GPIO_INT_MASK) == GPIO_INT_ASYNCHFALLING
{
modifiyreg32(regaddr, 0, mask);
}
else
{
modifiyreg32(regaddr, mask, 0);
}
}
/****************************************************************************
* Name: bcm_gpio_async_fallingedge
*
* Description:
* Set/clear falling edge detection.
*
****************************************************************************/
static void bcm_gpio_async_fallingedge(unsigned int pin, gpio_pinset_t pinset)
{
uintptr_t regaddr = BCM_GPIO_GPAFEN(pin);
uint32_t mask = BCM_GPIO_GPAFEN_AFEN(pin;
if ((pinset & GPIO_INT_MASK) == GPIO_INT_ASYNCHFALLING
{
modifiyreg32(regaddr, 0, mask);
}
else
{
modifiyreg32(regaddr, mask, 0);
}
}
/****************************************************************************
* Name: bcm_gpio0_interrupt
*
* Description:
* GPIO0 interrupt handler
*
****************************************************************************/
int bcm_gpio0_interrupt(int irq, FAR void *context, FAR void *arg)
{
uint32_t eds;
uint32_t mask;
int i;
/* Clear all pending interrpts */
eds = getreg32(BCM_GPIO_GPEDS0);
putreg32(eds, BCM_GPIO_GPEDS0);
/* Then process each pending GPIO interrupt */
for (i = 0; i < 32 && eds != NULL; i++)
{
mask = (uint32_t)1 << i;
if ((eds & mask) != 0)
{
/* Remove the pending interrupt bit from the mask */
eds &= ~mask;
/* And disptach the GPIO interrupt to the register handler */
irq_dispatch(BCM_IRQ_GPIO0_FIRST + i, context);
}
}
return OK;
}
/****************************************************************************
* Name: bcm_gpio1_interrupt
*
* Description:
* GPIO1 interrupt handler
*
****************************************************************************/
int bcm_gpio1_interrupt(int irq, FAR void *context, FAR void *arg)
{
uint32_t eds;
uint32_t mask;
int i;
/* Clear all pending interrpts */
eds = getreg32(BCM_GPIO_GPEDS1);
putreg32(eds, BCM_GPIO_GPEDS1);
/* Then process each pending GPIO interrupt */
for (i = 0; i < 32 && eds != NULL; i++)
{
mask = (uint32_t)1 << i;
if ((eds & mask) != 0)
{
/* Remove the pending interrupt bit from the mask */
eds &= ~mask;
/* And disptach the GPIO interrupt to the register handler */
irq_dispatch(BCM_IRQ_GPIO1_FIRST + i, context);
}
}
return OK;
}
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
/************************************************************************************ /****************************************************************************
* Name: bcm_gpio_irqinitialize * Name: bcm_gpio_irqinitialize
* *
* Description: * Description:
* Initialize logic to support a second level of interrupt decoding for GPIO pins. * Initialize logic to support a second level of interrupt decoding for
* GPIO pins.
* *
************************************************************************************/ ****************************************************************************/
void bcm_gpio_irqinitialize(void) void bcm_gpio_irqinitialize(void)
{ {
#warning Missing Logic /* Disabled all event detections */
putreg32(0, BCM_GPIO_GPREN0);
putreg32(0, BCM_GPIO_GPREN1);
putreg32(0, BCM_GPIO_GPFEN0);
putreg32(0, BCM_GPIO_GPFEN1);
putreg32(0, BCM_GPIO_GPHEN0);
putreg32(0, BCM_GPIO_GPHEN1);
putreg32(0, BCM_GPIO_GPLEN0);
putreg32(0, BCM_GPIO_GPLEN1);
putreg32(0, BCM_GPIO_GPAREN0);
putreg32(0, BCM_GPIO_GPAREN1);
putreg32(0, BCM_GPIO_GPAFEN0);
putreg32(0, BCM_GPIO_GPAFEN1);
/* Attach and enable the GPIO interrupt handlers */
(void) irq_attach(BCM_IRQ_GPIO0, bcm_gpio0_interrupt);
(void) irq_attach(BCM_IRQ_GPIO1, bcm_gpio1_interrupt);
up_enable_irq(BCM_IRQ_GPIO0);
up_enable_irq(BCM_IRQ_GPIO1);
} }
/************************************************************************************ /****************************************************************************
* Name: bcm_gpio_irqconfig
*
* Description:
* Configure an interrupt for the specified GPIO pin.
*
************************************************************************************/
void bcm_gpio_irqconfig(gpio_pinset_t pinset)
{
#warning Missing Logic
}
/************************************************************************************
* Name: bcm_gpio_irqenable * Name: bcm_gpio_irqenable
* *
* Description: * Description:
* Enable the interrupt for specified GPIO IRQ * Configure interrupt event detection for the specified GPIO pin. This
* effective enables the pin interrupts.
* *
************************************************************************************/ ****************************************************************************/
void bcm_gpio_irqenable(int irq) void bcm_gpio_irqenable(gpio_pinset_t pinset)
{ {
#warning Missing Logic unsigned int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
/* Configure pin detection settings */
bcm_gpio_risingedge(pin, pinset);
bcm_gpio_fallingedge(pin, pinset);
bcm_gpio_highlevel(pin, pinset);
bcm_gpio_lowlevel(pin, pinset);
bcm_gpio_async_risingedge(pin, pinset);
bcm_gpio_async_fallingedge(pin, pinset);
} }
/************************************************************************************ /************************************************************************************
* Name: bcm_gpio_irqdisable * Name: bcm_gpio_irqdisable
* *
* Description: * Description:
* Disable the interrupt for specified GPIO IRQ * Reset interrupt event detection for the specified GPIO pin. This
* effective disables the pin interrupts.
* *
************************************************************************************/ ************************************************************************************/
void bcm_gpio_irqdisable(int irq) void bcm_gpio_irqdisable(gpio_pinset_t pinset);
{ {
#warning Missing Logic unsigned int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
/* Reset pin detection settings */
bcm_gpio_risingedge(pin, 0);
bcm_gpio_fallingedge(pin, 0);
bcm_gpio_highlevel(pin, 0);
bcm_gpio_lowlevel(pin, 0);
bcm_gpio_async_risingedge(pin, 0);
bcm_gpio_async_fallingedge(pin, 0);
} }
#endif /* CONFIG_BCM2708_GPIO_IRQ */ #endif /* CONFIG_BCM2708_GPIO_IRQ */

View File

@ -254,16 +254,16 @@
# define BCM_GPIO_GPFSEL_FSELx9_ALT4 (3 << BCM_GPIO_GPFSEL_FSELx9_SHIFT) # define BCM_GPIO_GPFSEL_FSELx9_ALT4 (3 << BCM_GPIO_GPFSEL_FSELx9_SHIFT)
# define BCM_GPIO_GPFSEL_FSELx9_ALT5 (2 << BCM_GPIO_GPFSEL_FSELx9_SHIFT) # define BCM_GPIO_GPFSEL_FSELx9_ALT5 (2 << BCM_GPIO_GPFSEL_FSELx9_SHIFT)
#define BCM_GPIO_GPSET0_SET(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPSET_SET(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPCLR0_CLR(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPCLR_CLR(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPLEV0_LEV(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPLEV_LEV(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPEDS0_EDS(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPEDS_EDS(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPREN0_REN(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPREN_REN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPFEN0_FEN(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPFEN_FEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPHEN0_HEN(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPHEN_HEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPLEN0_LEN(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPLEN_LEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPAREN0_AREN(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPAREN_AREN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPAFEN0_AFEN(n) (1 << ((n) & 0x1f)) #define BCM_GPIO_GPAFEN_AFEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPPUD_PUD_SHIFT 0 /* bit 0-1: Pull-up/down register */ #define BCM_GPIO_GPPUD_PUD_SHIFT 0 /* bit 0-1: Pull-up/down register */
#define BCM_GPIO_GPPUD_PUD_MASK (3 << BCM_GPIO_GPPUD_PUD_SHIFT) #define BCM_GPIO_GPPUD_PUD_MASK (3 << BCM_GPIO_GPPUD_PUD_SHIFT)