diff --git a/arch/arm64/include/a64/irq.h b/arch/arm64/include/a64/irq.h index 8207ba69af1..aac684ec0e1 100644 --- a/arch/arm64/include/a64/irq.h +++ b/arch/arm64/include/a64/irq.h @@ -85,6 +85,8 @@ #define A64_IRQ_TIMER0 (50) /* 0x00C8 Timer 0 interrupt */ #define A64_IRQ_TIMER1 (51) /* 0x00CC Timer 1 interrupt */ +#define A64_IRQ_PH_EINT (53) /* 0x00C4 PH_EINT interrupt */ + #define A64_IRQ_AC_DET (60) /* 0x00F0 Audio Codec earphone detect interrupt */ #define A64_IRQ_AUDIO_CODEC (61) /* 0x00F4 Audio Codec interrupt */ #define A64_IRQ_KEYADC (62) /* 0x00F8 KEYADC interrupt */ diff --git a/arch/arm64/src/a64/a64_pio.c b/arch/arm64/src/a64/a64_pio.c index 2630891d493..385ce368d7b 100644 --- a/arch/arm64/src/a64/a64_pio.c +++ b/arch/arm64/src/a64/a64_pio.c @@ -42,7 +42,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: a64_pio_pin + * Name: a64_pio_port * * Description: * Return the Port Number for the bit-encoded description of the pin. @@ -63,6 +63,42 @@ static inline int a64_pio_port(pio_pinset_t cfgset) return port; } +/**************************************************************************** + * Name: a64_pio_ext + * + * Description: + * Return the External Port Number for the bit-encoded description of the + * pin. + * + * Input Parameters: + * cfgset - Bit-encoded description of a pin that supports External + * Interrupts + * + * Returned Value: + * 0 for Port B, 1 for Port G, 2 for Port H, -1 otherwise + * + ****************************************************************************/ + +static inline int a64_pio_ext(pio_pinset_t cfgset) +{ + int port = (cfgset & PIO_PORT_MASK) >> PIO_PORT_SHIFT; + + switch (port) + { + case PIO_REG_PORTB: + return 0; + + case PIO_REG_PORTG: + return 1; + + case PIO_REG_PORTH: + return 2; + + default: + return -1; /* External Interrupt not supported for the Port */ + } +} + /**************************************************************************** * Name: a64_pio_pin * @@ -85,6 +121,53 @@ static inline int a64_pio_pin(pio_pinset_t cfgset) return pin; } +/**************************************************************************** + * Name: a64_pio_irq + * + * Description: + * Enable or disable the interrupt for specified PIO pin. Only Ports B, G + * and H are supported for interrupts. + * + * Input Parameters: + * pinset - Bit-encoded description of a pin. Port should be B, G or H. + * enable - True to enable interrupt; False to disable. + * + * Returned Value: + * Zero (OK) on success; -EINVAL if pin is not from Port B, G or H. + * + ****************************************************************************/ + +static int a64_pio_irq(pio_pinset_t pinset, bool enable) +{ + const unsigned int port = a64_pio_port(pinset); + const unsigned int ext = a64_pio_ext(pinset); + const unsigned int pin = a64_pio_pin(pinset); + const uint32_t pin_mask = PIO_INT_CTL(pin); + const uint32_t pin_val = enable ? pin_mask : 0; + const unsigned long pin_addr = A64_PIO_INT_CTL(ext); + irqstate_t flags; + + if (ext < 0) + { + gpioerr("External Interrupt not supported for Port %d\n", port); + return -EINVAL; + } + + /* Enter Critical Section */ + + flags = enter_critical_section(); + + /* Enable or disable the interrupt */ + + modreg32(pin_val, pin_mask, pin_addr); + + /* Leave Critical Section */ + + leave_critical_section(flags); + + return OK; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -106,6 +189,7 @@ static inline int a64_pio_pin(pio_pinset_t cfgset) int a64_pio_config(pio_pinset_t cfgset) { unsigned int port = a64_pio_port(cfgset); + unsigned int ext = a64_pio_ext(cfgset); unsigned int pin = a64_pio_pin(cfgset); unsigned int shift; unsigned int value; @@ -131,7 +215,7 @@ int a64_pio_config(pio_pinset_t cfgset) A64_PIO_CFG0(port); intaddr = (port == PIO_REG_PORTL) ? A64_RPIO_INT_CFG0 : - A64_PIO_INT_CFG0; + A64_PIO_INT_CFG0(ext); break; case 1: /* PIO 8-15 */ @@ -140,7 +224,7 @@ int a64_pio_config(pio_pinset_t cfgset) A64_PIO_CFG1(port); intaddr = (port == PIO_REG_PORTL) ? A64_RPIO_INT_CFG1 : - A64_PIO_INT_CFG1; + A64_PIO_INT_CFG1(ext); break; case 2: /* PIO 16-23 */ @@ -149,7 +233,7 @@ int a64_pio_config(pio_pinset_t cfgset) A64_PIO_CFG2(port); intaddr = (port == PIO_REG_PORTL) ? A64_RPIO_INT_CFG2 : - A64_PIO_INT_CFG2; + A64_PIO_INT_CFG2(ext); break; case 3: /* PIO 24-31 */ @@ -158,7 +242,7 @@ int a64_pio_config(pio_pinset_t cfgset) A64_PIO_CFG3(port); intaddr = (port == PIO_REG_PORTL) ? A64_RPIO_INT_CFG3 : - A64_PIO_INT_CFG3; + A64_PIO_INT_CFG3(ext); break; default: @@ -180,6 +264,12 @@ int a64_pio_config(pio_pinset_t cfgset) if ((cfgset & PIO_EINT_MASK) == PIO_EINT) { + if (ext < 0) + { + gpioerr("External Interrupt not supported for Port %d\n", port); + return -EINVAL; + } + value = (cfgset & PIO_INT_MASK) >> PIO_INT_SHIFT; regval = getreg32(intaddr); @@ -327,3 +417,43 @@ bool a64_pio_read(pio_pinset_t pinset) regval = getreg32(regaddr); return ((regval & PIO_DAT(pin)) != 0); } + +/**************************************************************************** + * Name: a64_pio_irqenable + * + * Description: + * Enable the interrupt for specified PIO pin. Only Ports B, G and H are + * supported for interrupts. + * + * Input Parameters: + * cfgset - Bit-encoded description of a pin. Port should be B, G or H. + * + * Returned Value: + * Zero (OK) on success; -EINVAL if pin is not from Port B, G or H. + * + ****************************************************************************/ + +int a64_pio_irqenable(pio_pinset_t pinset) +{ + return a64_pio_irq(pinset, true); +} + +/**************************************************************************** + * Name: a64_pio_irqdisable + * + * Description: + * Disable the interrupt for specified PIO pin. Only Ports B, G and H are + * supported for interrupts. + * + * Input Parameters: + * cfgset - Bit-encoded description of a pin. Port should be B, G or H. + * + * Returned Value: + * Zero (OK) on success; -EINVAL if pin is not from Port B, G or H. + * + ****************************************************************************/ + +int a64_pio_irqdisable(pio_pinset_t pinset) +{ + return a64_pio_irq(pinset, false); +} diff --git a/arch/arm64/src/a64/a64_pio.h b/arch/arm64/src/a64/a64_pio.h index 1a4ff7f1cd2..1a454c4842a 100644 --- a/arch/arm64/src/a64/a64_pio.h +++ b/arch/arm64/src/a64/a64_pio.h @@ -278,6 +278,40 @@ void a64_pio_write(pio_pinset_t pinset, bool value); bool a64_pio_read(pio_pinset_t pinset); +/**************************************************************************** + * Name: a64_pio_irqenable + * + * Description: + * Enable the interrupt for specified PIO pin. Only Ports B, G and H are + * supported for interrupts. + * + * Input Parameters: + * pinset - Bit-encoded description of a pin. Port should be B, G or H. + * + * Returned Value: + * Zero (OK) on success; -EINVAL if pin is not from Port B, G or H. + * + ****************************************************************************/ + +int a64_pio_irqenable(pio_pinset_t pinset); + +/**************************************************************************** + * Name: a64_pio_irqdisable + * + * Description: + * Disable the interrupt for specified PIO pin. Only Ports B, G and H are + * supported for interrupts. + * + * Input Parameters: + * pinset - Bit-encoded description of a pin. Port should be B, G or H. + * + * Returned Value: + * Zero (OK) on success; -EINVAL if pin is not from Port B, G or H. + * + ****************************************************************************/ + +int a64_pio_irqdisable(pio_pinset_t pinset); + #undef EXTERN #if defined(__cplusplus) } diff --git a/arch/arm64/src/a64/hardware/a64_pio.h b/arch/arm64/src/a64/hardware/a64_pio.h index 21260129328..a05e1080ce6 100644 --- a/arch/arm64/src/a64/hardware/a64_pio.h +++ b/arch/arm64/src/a64/hardware/a64_pio.h @@ -70,13 +70,14 @@ #define A64_PIO_DRV1_OFFSET(n) (0x0018 + (n)*0x24) /* Port Multi-Driving Register 1, n=0-7 */ #define A64_PIO_PUL0_OFFSET(n) (0x001c + (n)*0x24) /* Port Pull Register 0, n=0-7 */ #define A64_PIO_PUL1_OFFSET(n) (0x0020 + (n)*0x24) /* Port Pull Register 1, n=0-7 */ -#define A64_PIO_INT_CFG0_OFFSET 0x0200 /* PIO Interrupt Configure Register 0 */ -#define A64_PIO_INT_CFG1_OFFSET 0x0204 /* PIO Interrupt Configure Register 1 */ -#define A64_PIO_INT_CFG2_OFFSET 0x0208 /* PIO Interrupt Configure Register 2 */ -#define A64_PIO_INT_CFG3_OFFSET 0x020c /* PIO Interrupt Configure Register 3 */ -#define A64_PIO_INT_CTL_OFFSET 0x0210 /* PIO Interrupt Control Register */ -#define A64_PIO_INT_STA_OFFSET 0x0214 /* PIO Interrupt Status Register */ -#define A64_PIO_INT_DEB_OFFSET 0x0218 /* PIO Interrupt Debounce Register */ + +#define A64_PIO_INT_CFG0_OFFSET(n) (0x0200 + (n)*0x20) /* PIO Interrupt Configure Register 0, n=0-2 */ +#define A64_PIO_INT_CFG1_OFFSET(n) (0x0204 + (n)*0x20) /* PIO Interrupt Configure Register 1, n=0-2 */ +#define A64_PIO_INT_CFG2_OFFSET(n) (0x0208 + (n)*0x20) /* PIO Interrupt Configure Register 2, n=0-2 */ +#define A64_PIO_INT_CFG3_OFFSET(n) (0x020c + (n)*0x20) /* PIO Interrupt Configure Register 3, n=0-2 */ +#define A64_PIO_INT_CTL_OFFSET(n) (0x0210 + (n)*0x20) /* PIO Interrupt Control Register, n=0-2 */ +#define A64_PIO_INT_STA_OFFSET(n) (0x0214 + (n)*0x20) /* PIO Interrupt Status Register, n=0-2 */ +#define A64_PIO_INT_DEB_OFFSET(n) (0x0218 + (n)*0x20) /* PIO Interrupt Debounce Register, n=0-2 */ /* Register Addresses *******************************************************/ @@ -89,13 +90,13 @@ #define A64_PIO_DRV1(n) (A64_PIO_ADDR+A64_PIO_DRV1_OFFSET(n)) #define A64_PIO_PUL0(n) (A64_PIO_ADDR+A64_PIO_PUL0_OFFSET(n)) #define A64_PIO_PUL1(n) (A64_PIO_ADDR+A64_PIO_PUL1_OFFSET(n)) -#define A64_PIO_INT_CFG0 (A64_PIO_ADDR+A64_PIO_INT_CFG0_OFFSET) -#define A64_PIO_INT_CFG1 (A64_PIO_ADDR+A64_PIO_INT_CFG1_OFFSET) -#define A64_PIO_INT_CFG2 (A64_PIO_ADDR+A64_PIO_INT_CFG2_OFFSET) -#define A64_PIO_INT_CFG3 (A64_PIO_ADDR+A64_PIO_INT_CFG3_OFFSET) -#define A64_PIO_INT_CTL (A64_PIO_ADDR+A64_PIO_INT_CTL_OFFSET) -#define A64_PIO_INT_STA (A64_PIO_ADDR+A64_PIO_INT_STA_OFFSET) -#define A64_PIO_INT_DEB (A64_PIO_ADDR+A64_PIO_INT_DEB_OFFSET) +#define A64_PIO_INT_CFG0(n) (A64_PIO_ADDR+A64_PIO_INT_CFG0_OFFSET(n)) +#define A64_PIO_INT_CFG1(n) (A64_PIO_ADDR+A64_PIO_INT_CFG1_OFFSET(n)) +#define A64_PIO_INT_CFG2(n) (A64_PIO_ADDR+A64_PIO_INT_CFG2_OFFSET(n)) +#define A64_PIO_INT_CFG3(n) (A64_PIO_ADDR+A64_PIO_INT_CFG3_OFFSET(n)) +#define A64_PIO_INT_CTL(n) (A64_PIO_ADDR+A64_PIO_INT_CTL_OFFSET(n)) +#define A64_PIO_INT_STA(n) (A64_PIO_ADDR+A64_PIO_INT_STA_OFFSET(n)) +#define A64_PIO_INT_DEB(n) (A64_PIO_ADDR+A64_PIO_INT_DEB_OFFSET(n)) #define A64_RPIO_CFG0 (A64_RPIO_ADDR+A64_PIO_CFG0_OFFSET(0)) #define A64_RPIO_CFG1 (A64_RPIO_ADDR+A64_PIO_CFG1_OFFSET(0)) @@ -106,13 +107,13 @@ #define A64_RPIO_DRV1 (A64_RPIO_ADDR+A64_PIO_DRV1_OFFSET(0)) #define A64_RPIO_PUL0 (A64_RPIO_ADDR+A64_PIO_PUL0_OFFSET(0)) #define A64_RPIO_PUL1 (A64_RPIO_ADDR+A64_PIO_PUL1_OFFSET(0)) -#define A64_RPIO_INT_CFG0 (A64_RPIO_ADDR+A64_PIO_INT_CFG0_OFFSET) -#define A64_RPIO_INT_CFG1 (A64_RPIO_ADDR+A64_PIO_INT_CFG1_OFFSET) -#define A64_RPIO_INT_CFG2 (A64_RPIO_ADDR+A64_PIO_INT_CFG2_OFFSET) -#define A64_RPIO_INT_CFG3 (A64_RPIO_ADDR+A64_PIO_INT_CFG3_OFFSET) -#define A64_RPIO_INT_CTL (A64_RPIO_ADDR+A64_PIO_INT_CTL_OFFSET) -#define A64_RPIO_INT_STA (A64_RPIO_ADDR+A64_PIO_INT_STA_OFFSET) -#define A64_RPIO_INT_DEB (A64_RPIO_ADDR+A64_PIO_INT_DEB_OFFSET) +#define A64_RPIO_INT_CFG0 (A64_RPIO_ADDR+A64_PIO_INT_CFG0_OFFSET(0)) +#define A64_RPIO_INT_CFG1 (A64_RPIO_ADDR+A64_PIO_INT_CFG1_OFFSET(0)) +#define A64_RPIO_INT_CFG2 (A64_RPIO_ADDR+A64_PIO_INT_CFG2_OFFSET(0)) +#define A64_RPIO_INT_CFG3 (A64_RPIO_ADDR+A64_PIO_INT_CFG3_OFFSET(0)) +#define A64_RPIO_INT_CTL (A64_RPIO_ADDR+A64_PIO_INT_CTL_OFFSET(0)) +#define A64_RPIO_INT_STA (A64_RPIO_ADDR+A64_PIO_INT_STA_OFFSET(0)) +#define A64_RPIO_INT_DEB (A64_RPIO_ADDR+A64_PIO_INT_DEB_OFFSET(0)) /* Register Bit Field Definitions *******************************************/