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 */
#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)
#else
# 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);
}
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;
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;
}

View File

@ -261,46 +261,34 @@ void bcm_gpio_write(gpio_pinset_t pinset, bool value);
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
*
* 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
void bcm_gpio_irqenable(int irq);
void bcm_gpio_irqenable(gpio_pinset_t pinset);
#else
# define bcm_gpio_irqenable(irq)
# define bcm_gpio_irqenable(p)
#endif
/************************************************************************************
* Name: bcm_gpio_irqdisable
*
* 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
void bcm_gpio_irqdisable(int irq);
void bcm_gpio_irqdisable(gpio_pinset_t pinset);
#else
# define bcm_gpio_irqdisable(irq)
# define bcm_gpio_irqdisable(p)
#endif
#undef EXTERN

View File

@ -44,60 +44,332 @@
#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
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Name: bcm_gpio_irqinitialize
*
* 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)
{
#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
*
* 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
*
* 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 */

View File

@ -254,16 +254,16 @@
# 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_GPSET0_SET(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPCLR0_CLR(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPLEV0_LEV(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPEDS0_EDS(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPREN0_REN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPFEN0_FEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPHEN0_HEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPLEN0_LEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPAREN0_AREN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPAFEN0_AFEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPSET_SET(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPCLR_CLR(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPLEV_LEV(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPEDS_EDS(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPREN_REN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPFEN_FEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPHEN_HEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPLEN_LEN(n) (1 << ((n) & 0x1f))
#define BCM_GPIO_GPAREN_AREN(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_MASK (3 << BCM_GPIO_GPPUD_PUD_SHIFT)