diff --git a/arch/arm/include/bcm2708/irq.h b/arch/arm/include/bcm2708/irq.h index 2e13806780c..4b616c5fa92 100644 --- a/arch/arm/include/bcm2708/irq.h +++ b/arch/arm/include/bcm2708/irq.h @@ -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) diff --git a/arch/arm/src/bcm2708/bcm_gpio.c b/arch/arm/src/bcm2708/bcm_gpio.c index 63b6625aee9..3e16326a0ef 100644 --- a/arch/arm/src/bcm2708/bcm_gpio.c +++ b/arch/arm/src/bcm2708/bcm_gpio.c @@ -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; } diff --git a/arch/arm/src/bcm2708/bcm_gpio.h b/arch/arm/src/bcm2708/bcm_gpio.h index 8e5e24728a0..820b37681f2 100644 --- a/arch/arm/src/bcm2708/bcm_gpio.h +++ b/arch/arm/src/bcm2708/bcm_gpio.h @@ -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 diff --git a/arch/arm/src/bcm2708/bcm_gpioint.c b/arch/arm/src/bcm2708/bcm_gpioint.c index 9c25032de25..7f3ac54716c 100644 --- a/arch/arm/src/bcm2708/bcm_gpioint.c +++ b/arch/arm/src/bcm2708/bcm_gpioint.c @@ -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 */ diff --git a/arch/arm/src/bcm2708/chip/bcm2708_gpio.h b/arch/arm/src/bcm2708/chip/bcm2708_gpio.h index d52df50e4d0..b6fad4e1533 100644 --- a/arch/arm/src/bcm2708/chip/bcm2708_gpio.h +++ b/arch/arm/src/bcm2708/chip/bcm2708_gpio.h @@ -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)