From 87cec561549df816828186f474c80b4e2b4de8bb Mon Sep 17 00:00:00 2001 From: Philippe Leduc Date: Fri, 1 Sep 2023 15:23:10 +0200 Subject: [PATCH] Handle GPIO IRQs Add board buttons --- arch/arm/include/mx8mp/mx8mp_irq.h | 192 ++++++++++++- arch/arm/src/mx8mp/hardware/mx8mp_gpio.h | 6 - arch/arm/src/mx8mp/hardware/mx8mp_pinmux.h | 51 ++-- arch/arm/src/mx8mp/mx8mp_config.h | 2 +- arch/arm/src/mx8mp/mx8mp_gpio.c | 272 +++++++++++++++--- arch/arm/src/mx8mp/mx8mp_gpio.h | 37 ++- arch/arm/src/mx8mp/mx8mp_irq.c | 10 +- arch/arm/src/mx8mp/mx8mp_lowputc.h | 4 +- arch/arm/src/mx8mp/mx8mp_serial.c | 4 - arch/arm/src/mx8mp/mx8mp_timerisr.c | 2 +- boards/Kconfig | 2 + boards/arm/mx8mp/verdin-mx8mp/README.txt | 9 + .../mx8mp/verdin-mx8mp/configs/nsh/defconfig | 14 +- boards/arm/mx8mp/verdin-mx8mp/include/board.h | 35 ++- boards/arm/mx8mp/verdin-mx8mp/src/Makefile | 8 +- .../mx8mp/verdin-mx8mp/src/mx8mp_autoleds.c | 129 +++++++++ .../mx8mp/verdin-mx8mp/src/mx8mp_bringup.c | 39 ++- .../mx8mp/verdin-mx8mp/src/mx8mp_buttons.c | 168 +++++++++++ .../mx8mp/verdin-mx8mp/src/mx8mp_userleds.c | 12 +- .../arm/mx8mp/verdin-mx8mp/src/verdin-mx8mp.h | 16 +- 20 files changed, 874 insertions(+), 138 deletions(-) create mode 100644 boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_autoleds.c create mode 100644 boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_buttons.c diff --git a/arch/arm/include/mx8mp/mx8mp_irq.h b/arch/arm/include/mx8mp/mx8mp_irq.h index ebf1093c500..19f4a0bc8d1 100644 --- a/arch/arm/include/mx8mp/mx8mp_irq.h +++ b/arch/arm/include/mx8mp/mx8mp_irq.h @@ -201,8 +201,196 @@ #define MX8MP_IRQ_NVECTORS (MX8MP_IRQ_FIRST + MX8MP_IRQ_NEXTINTS) -/* GPIO IRQ interrupts -- To be provided */ +/* GPIO second level interrupt **********************************************/ -#define NR_IRQS MX8MP_IRQ_NVECTORS +#define MX8MP_IRQ_SOFT_GPIO_START MX8MP_IRQ_NVECTORS + +/* GPIO1 has dedicated interrupts for pins 0-7, however theses pin are also + * connected to the multiplexed IRQ and both can be triggered together is + * enabled. Here we choose to no use the dedicated IRQ. + * REVISIT: add an option to choose the strategy: + * - both IRQ + * - only dedicated (and losst of GPIO1 8-15 IRQs) + * - only multiplexed + */ + +#define MX8MP_IRQ_SOFT_GPIO1_START MX8MP_IRQ_SOFT_GPIO_START + +#define MX8MP_IRQ_SOFT_GPIO1_0 (MX8MP_IRQ_SOFT_GPIO1_START + 1) +#define MX8MP_IRQ_SOFT_GPIO1_1 (MX8MP_IRQ_SOFT_GPIO1_START + 2) +#define MX8MP_IRQ_SOFT_GPIO1_2 (MX8MP_IRQ_SOFT_GPIO1_START + 3) +#define MX8MP_IRQ_SOFT_GPIO1_3 (MX8MP_IRQ_SOFT_GPIO1_START + 4) +#define MX8MP_IRQ_SOFT_GPIO1_4 (MX8MP_IRQ_SOFT_GPIO1_START + 5) +#define MX8MP_IRQ_SOFT_GPIO1_5 (MX8MP_IRQ_SOFT_GPIO1_START + 6) +#define MX8MP_IRQ_SOFT_GPIO1_6 (MX8MP_IRQ_SOFT_GPIO1_START + 7) +#define MX8MP_IRQ_SOFT_GPIO1_7 (MX8MP_IRQ_SOFT_GPIO1_START + 8) +#define MX8MP_IRQ_SOFT_GPIO1_8 (MX8MP_IRQ_SOFT_GPIO1_START + 9) +#define MX8MP_IRQ_SOFT_GPIO1_9 (MX8MP_IRQ_SOFT_GPIO1_START + 10) +#define MX8MP_IRQ_SOFT_GPIO1_10 (MX8MP_IRQ_SOFT_GPIO1_START + 11) +#define MX8MP_IRQ_SOFT_GPIO1_11 (MX8MP_IRQ_SOFT_GPIO1_START + 12) +#define MX8MP_IRQ_SOFT_GPIO1_12 (MX8MP_IRQ_SOFT_GPIO1_START + 13) +#define MX8MP_IRQ_SOFT_GPIO1_13 (MX8MP_IRQ_SOFT_GPIO1_START + 14) +#define MX8MP_IRQ_SOFT_GPIO1_14 (MX8MP_IRQ_SOFT_GPIO1_START + 15) +#define MX8MP_IRQ_SOFT_GPIO1_15 (MX8MP_IRQ_SOFT_GPIO1_START + 16) +#define MX8MP_IRQ_SOFT_GPIO1_16 (MX8MP_IRQ_SOFT_GPIO1_START + 17) +#define MX8MP_IRQ_SOFT_GPIO1_17 (MX8MP_IRQ_SOFT_GPIO1_START + 18) +#define MX8MP_IRQ_SOFT_GPIO1_18 (MX8MP_IRQ_SOFT_GPIO1_START + 19) +#define MX8MP_IRQ_SOFT_GPIO1_19 (MX8MP_IRQ_SOFT_GPIO1_START + 20) +#define MX8MP_IRQ_SOFT_GPIO1_20 (MX8MP_IRQ_SOFT_GPIO1_START + 21) +#define MX8MP_IRQ_SOFT_GPIO1_21 (MX8MP_IRQ_SOFT_GPIO1_START + 22) +#define MX8MP_IRQ_SOFT_GPIO1_22 (MX8MP_IRQ_SOFT_GPIO1_START + 23) +#define MX8MP_IRQ_SOFT_GPIO1_23 (MX8MP_IRQ_SOFT_GPIO1_START + 24) +#define MX8MP_IRQ_SOFT_GPIO1_24 (MX8MP_IRQ_SOFT_GPIO1_START + 25) +#define MX8MP_IRQ_SOFT_GPIO1_25 (MX8MP_IRQ_SOFT_GPIO1_START + 26) +#define MX8MP_IRQ_SOFT_GPIO1_26 (MX8MP_IRQ_SOFT_GPIO1_START + 27) +#define MX8MP_IRQ_SOFT_GPIO1_27 (MX8MP_IRQ_SOFT_GPIO1_START + 28) +#define MX8MP_IRQ_SOFT_GPIO1_28 (MX8MP_IRQ_SOFT_GPIO1_START + 29) +#define MX8MP_IRQ_SOFT_GPIO1_29 (MX8MP_IRQ_SOFT_GPIO1_START + 30) +#define MX8MP_IRQ_SOFT_GPIO1_30 (MX8MP_IRQ_SOFT_GPIO1_START + 31) +#define MX8MP_IRQ_SOFT_GPIO1_31 (MX8MP_IRQ_SOFT_GPIO1_START + 32) + +#define MX8MP_IRQ_SOFT_GPIO2_START MX8MP_IRQ_SOFT_GPIO1_31 + +#define MX8MP_IRQ_SOFT_GPIO2_0 (MX8MP_IRQ_SOFT_GPIO2_START + 1) +#define MX8MP_IRQ_SOFT_GPIO2_1 (MX8MP_IRQ_SOFT_GPIO2_START + 2) +#define MX8MP_IRQ_SOFT_GPIO2_2 (MX8MP_IRQ_SOFT_GPIO2_START + 3) +#define MX8MP_IRQ_SOFT_GPIO2_3 (MX8MP_IRQ_SOFT_GPIO2_START + 4) +#define MX8MP_IRQ_SOFT_GPIO2_4 (MX8MP_IRQ_SOFT_GPIO2_START + 5) +#define MX8MP_IRQ_SOFT_GPIO2_5 (MX8MP_IRQ_SOFT_GPIO2_START + 6) +#define MX8MP_IRQ_SOFT_GPIO2_6 (MX8MP_IRQ_SOFT_GPIO2_START + 7) +#define MX8MP_IRQ_SOFT_GPIO2_7 (MX8MP_IRQ_SOFT_GPIO2_START + 8) +#define MX8MP_IRQ_SOFT_GPIO2_8 (MX8MP_IRQ_SOFT_GPIO2_START + 9) +#define MX8MP_IRQ_SOFT_GPIO2_9 (MX8MP_IRQ_SOFT_GPIO2_START + 10) +#define MX8MP_IRQ_SOFT_GPIO2_10 (MX8MP_IRQ_SOFT_GPIO2_START + 11) +#define MX8MP_IRQ_SOFT_GPIO2_11 (MX8MP_IRQ_SOFT_GPIO2_START + 12) +#define MX8MP_IRQ_SOFT_GPIO2_12 (MX8MP_IRQ_SOFT_GPIO2_START + 13) +#define MX8MP_IRQ_SOFT_GPIO2_13 (MX8MP_IRQ_SOFT_GPIO2_START + 14) +#define MX8MP_IRQ_SOFT_GPIO2_14 (MX8MP_IRQ_SOFT_GPIO2_START + 15) +#define MX8MP_IRQ_SOFT_GPIO2_15 (MX8MP_IRQ_SOFT_GPIO2_START + 16) +#define MX8MP_IRQ_SOFT_GPIO2_16 (MX8MP_IRQ_SOFT_GPIO2_START + 17) +#define MX8MP_IRQ_SOFT_GPIO2_17 (MX8MP_IRQ_SOFT_GPIO2_START + 18) +#define MX8MP_IRQ_SOFT_GPIO2_18 (MX8MP_IRQ_SOFT_GPIO2_START + 19) +#define MX8MP_IRQ_SOFT_GPIO2_19 (MX8MP_IRQ_SOFT_GPIO2_START + 20) +#define MX8MP_IRQ_SOFT_GPIO2_20 (MX8MP_IRQ_SOFT_GPIO2_START + 21) +#define MX8MP_IRQ_SOFT_GPIO2_21 (MX8MP_IRQ_SOFT_GPIO2_START + 22) +#define MX8MP_IRQ_SOFT_GPIO2_22 (MX8MP_IRQ_SOFT_GPIO2_START + 23) +#define MX8MP_IRQ_SOFT_GPIO2_23 (MX8MP_IRQ_SOFT_GPIO2_START + 24) +#define MX8MP_IRQ_SOFT_GPIO2_24 (MX8MP_IRQ_SOFT_GPIO2_START + 25) +#define MX8MP_IRQ_SOFT_GPIO2_25 (MX8MP_IRQ_SOFT_GPIO2_START + 26) +#define MX8MP_IRQ_SOFT_GPIO2_26 (MX8MP_IRQ_SOFT_GPIO2_START + 27) +#define MX8MP_IRQ_SOFT_GPIO2_27 (MX8MP_IRQ_SOFT_GPIO2_START + 28) +#define MX8MP_IRQ_SOFT_GPIO2_28 (MX8MP_IRQ_SOFT_GPIO2_START + 29) +#define MX8MP_IRQ_SOFT_GPIO2_29 (MX8MP_IRQ_SOFT_GPIO2_START + 30) +#define MX8MP_IRQ_SOFT_GPIO2_30 (MX8MP_IRQ_SOFT_GPIO2_START + 31) +#define MX8MP_IRQ_SOFT_GPIO2_31 (MX8MP_IRQ_SOFT_GPIO2_START + 32) + +#define MX8MP_IRQ_SOFT_GPIO3_START MX8MP_IRQ_SOFT_GPIO2_31 + +#define MX8MP_IRQ_SOFT_GPIO3_0 (MX8MP_IRQ_SOFT_GPIO3_START + 1) +#define MX8MP_IRQ_SOFT_GPIO3_1 (MX8MP_IRQ_SOFT_GPIO3_START + 2) +#define MX8MP_IRQ_SOFT_GPIO3_2 (MX8MP_IRQ_SOFT_GPIO3_START + 3) +#define MX8MP_IRQ_SOFT_GPIO3_3 (MX8MP_IRQ_SOFT_GPIO3_START + 4) +#define MX8MP_IRQ_SOFT_GPIO3_4 (MX8MP_IRQ_SOFT_GPIO3_START + 5) +#define MX8MP_IRQ_SOFT_GPIO3_5 (MX8MP_IRQ_SOFT_GPIO3_START + 6) +#define MX8MP_IRQ_SOFT_GPIO3_6 (MX8MP_IRQ_SOFT_GPIO3_START + 7) +#define MX8MP_IRQ_SOFT_GPIO3_7 (MX8MP_IRQ_SOFT_GPIO3_START + 8) +#define MX8MP_IRQ_SOFT_GPIO3_8 (MX8MP_IRQ_SOFT_GPIO3_START + 9) +#define MX8MP_IRQ_SOFT_GPIO3_9 (MX8MP_IRQ_SOFT_GPIO3_START + 10) +#define MX8MP_IRQ_SOFT_GPIO3_10 (MX8MP_IRQ_SOFT_GPIO3_START + 11) +#define MX8MP_IRQ_SOFT_GPIO3_11 (MX8MP_IRQ_SOFT_GPIO3_START + 12) +#define MX8MP_IRQ_SOFT_GPIO3_12 (MX8MP_IRQ_SOFT_GPIO3_START + 13) +#define MX8MP_IRQ_SOFT_GPIO3_13 (MX8MP_IRQ_SOFT_GPIO3_START + 14) +#define MX8MP_IRQ_SOFT_GPIO3_14 (MX8MP_IRQ_SOFT_GPIO3_START + 15) +#define MX8MP_IRQ_SOFT_GPIO3_15 (MX8MP_IRQ_SOFT_GPIO3_START + 16) +#define MX8MP_IRQ_SOFT_GPIO3_16 (MX8MP_IRQ_SOFT_GPIO3_START + 17) +#define MX8MP_IRQ_SOFT_GPIO3_17 (MX8MP_IRQ_SOFT_GPIO3_START + 18) +#define MX8MP_IRQ_SOFT_GPIO3_18 (MX8MP_IRQ_SOFT_GPIO3_START + 19) +#define MX8MP_IRQ_SOFT_GPIO3_19 (MX8MP_IRQ_SOFT_GPIO3_START + 20) +#define MX8MP_IRQ_SOFT_GPIO3_20 (MX8MP_IRQ_SOFT_GPIO3_START + 21) +#define MX8MP_IRQ_SOFT_GPIO3_21 (MX8MP_IRQ_SOFT_GPIO3_START + 22) +#define MX8MP_IRQ_SOFT_GPIO3_22 (MX8MP_IRQ_SOFT_GPIO3_START + 23) +#define MX8MP_IRQ_SOFT_GPIO3_23 (MX8MP_IRQ_SOFT_GPIO3_START + 24) +#define MX8MP_IRQ_SOFT_GPIO3_24 (MX8MP_IRQ_SOFT_GPIO3_START + 25) +#define MX8MP_IRQ_SOFT_GPIO3_25 (MX8MP_IRQ_SOFT_GPIO3_START + 26) +#define MX8MP_IRQ_SOFT_GPIO3_26 (MX8MP_IRQ_SOFT_GPIO3_START + 27) +#define MX8MP_IRQ_SOFT_GPIO3_27 (MX8MP_IRQ_SOFT_GPIO3_START + 28) +#define MX8MP_IRQ_SOFT_GPIO3_28 (MX8MP_IRQ_SOFT_GPIO3_START + 29) +#define MX8MP_IRQ_SOFT_GPIO3_29 (MX8MP_IRQ_SOFT_GPIO3_START + 30) +#define MX8MP_IRQ_SOFT_GPIO3_30 (MX8MP_IRQ_SOFT_GPIO3_START + 31) +#define MX8MP_IRQ_SOFT_GPIO3_31 (MX8MP_IRQ_SOFT_GPIO3_START + 32) + +#define MX8MP_IRQ_SOFT_GPIO4_START MX8MP_IRQ_SOFT_GPIO3_31 + +#define MX8MP_IRQ_SOFT_GPIO4_0 (MX8MP_IRQ_SOFT_GPIO4_START + 1) +#define MX8MP_IRQ_SOFT_GPIO4_1 (MX8MP_IRQ_SOFT_GPIO4_START + 2) +#define MX8MP_IRQ_SOFT_GPIO4_2 (MX8MP_IRQ_SOFT_GPIO4_START + 3) +#define MX8MP_IRQ_SOFT_GPIO4_3 (MX8MP_IRQ_SOFT_GPIO4_START + 4) +#define MX8MP_IRQ_SOFT_GPIO4_4 (MX8MP_IRQ_SOFT_GPIO4_START + 5) +#define MX8MP_IRQ_SOFT_GPIO4_5 (MX8MP_IRQ_SOFT_GPIO4_START + 6) +#define MX8MP_IRQ_SOFT_GPIO4_6 (MX8MP_IRQ_SOFT_GPIO4_START + 7) +#define MX8MP_IRQ_SOFT_GPIO4_7 (MX8MP_IRQ_SOFT_GPIO4_START + 8) +#define MX8MP_IRQ_SOFT_GPIO4_8 (MX8MP_IRQ_SOFT_GPIO4_START + 9) +#define MX8MP_IRQ_SOFT_GPIO4_9 (MX8MP_IRQ_SOFT_GPIO4_START + 10) +#define MX8MP_IRQ_SOFT_GPIO4_10 (MX8MP_IRQ_SOFT_GPIO4_START + 11) +#define MX8MP_IRQ_SOFT_GPIO4_11 (MX8MP_IRQ_SOFT_GPIO4_START + 12) +#define MX8MP_IRQ_SOFT_GPIO4_12 (MX8MP_IRQ_SOFT_GPIO4_START + 13) +#define MX8MP_IRQ_SOFT_GPIO4_13 (MX8MP_IRQ_SOFT_GPIO4_START + 14) +#define MX8MP_IRQ_SOFT_GPIO4_14 (MX8MP_IRQ_SOFT_GPIO4_START + 15) +#define MX8MP_IRQ_SOFT_GPIO4_15 (MX8MP_IRQ_SOFT_GPIO4_START + 16) +#define MX8MP_IRQ_SOFT_GPIO4_16 (MX8MP_IRQ_SOFT_GPIO4_START + 17) +#define MX8MP_IRQ_SOFT_GPIO4_17 (MX8MP_IRQ_SOFT_GPIO4_START + 18) +#define MX8MP_IRQ_SOFT_GPIO4_18 (MX8MP_IRQ_SOFT_GPIO4_START + 19) +#define MX8MP_IRQ_SOFT_GPIO4_19 (MX8MP_IRQ_SOFT_GPIO4_START + 20) +#define MX8MP_IRQ_SOFT_GPIO4_20 (MX8MP_IRQ_SOFT_GPIO4_START + 21) +#define MX8MP_IRQ_SOFT_GPIO4_21 (MX8MP_IRQ_SOFT_GPIO4_START + 22) +#define MX8MP_IRQ_SOFT_GPIO4_22 (MX8MP_IRQ_SOFT_GPIO4_START + 23) +#define MX8MP_IRQ_SOFT_GPIO4_23 (MX8MP_IRQ_SOFT_GPIO4_START + 24) +#define MX8MP_IRQ_SOFT_GPIO4_24 (MX8MP_IRQ_SOFT_GPIO4_START + 25) +#define MX8MP_IRQ_SOFT_GPIO4_25 (MX8MP_IRQ_SOFT_GPIO4_START + 26) +#define MX8MP_IRQ_SOFT_GPIO4_26 (MX8MP_IRQ_SOFT_GPIO4_START + 27) +#define MX8MP_IRQ_SOFT_GPIO4_27 (MX8MP_IRQ_SOFT_GPIO4_START + 28) +#define MX8MP_IRQ_SOFT_GPIO4_28 (MX8MP_IRQ_SOFT_GPIO4_START + 29) +#define MX8MP_IRQ_SOFT_GPIO4_29 (MX8MP_IRQ_SOFT_GPIO4_START + 30) +#define MX8MP_IRQ_SOFT_GPIO4_30 (MX8MP_IRQ_SOFT_GPIO4_START + 31) +#define MX8MP_IRQ_SOFT_GPIO4_31 (MX8MP_IRQ_SOFT_GPIO4_START + 32) + +#define MX8MP_IRQ_SOFT_GPIO5_START MX8MP_IRQ_SOFT_GPIO4_31 + +#define MX8MP_IRQ_SOFT_GPIO5_0 (MX8MP_IRQ_SOFT_GPIO5_START + 1) +#define MX8MP_IRQ_SOFT_GPIO5_1 (MX8MP_IRQ_SOFT_GPIO5_START + 2) +#define MX8MP_IRQ_SOFT_GPIO5_2 (MX8MP_IRQ_SOFT_GPIO5_START + 3) +#define MX8MP_IRQ_SOFT_GPIO5_3 (MX8MP_IRQ_SOFT_GPIO5_START + 4) +#define MX8MP_IRQ_SOFT_GPIO5_4 (MX8MP_IRQ_SOFT_GPIO5_START + 5) +#define MX8MP_IRQ_SOFT_GPIO5_5 (MX8MP_IRQ_SOFT_GPIO5_START + 6) +#define MX8MP_IRQ_SOFT_GPIO5_6 (MX8MP_IRQ_SOFT_GPIO5_START + 7) +#define MX8MP_IRQ_SOFT_GPIO5_7 (MX8MP_IRQ_SOFT_GPIO5_START + 8) +#define MX8MP_IRQ_SOFT_GPIO5_8 (MX8MP_IRQ_SOFT_GPIO5_START + 9) +#define MX8MP_IRQ_SOFT_GPIO5_9 (MX8MP_IRQ_SOFT_GPIO5_START + 10) +#define MX8MP_IRQ_SOFT_GPIO5_10 (MX8MP_IRQ_SOFT_GPIO5_START + 11) +#define MX8MP_IRQ_SOFT_GPIO5_11 (MX8MP_IRQ_SOFT_GPIO5_START + 12) +#define MX8MP_IRQ_SOFT_GPIO5_12 (MX8MP_IRQ_SOFT_GPIO5_START + 13) +#define MX8MP_IRQ_SOFT_GPIO5_13 (MX8MP_IRQ_SOFT_GPIO5_START + 14) +#define MX8MP_IRQ_SOFT_GPIO5_14 (MX8MP_IRQ_SOFT_GPIO5_START + 15) +#define MX8MP_IRQ_SOFT_GPIO5_15 (MX8MP_IRQ_SOFT_GPIO5_START + 16) +#define MX8MP_IRQ_SOFT_GPIO5_16 (MX8MP_IRQ_SOFT_GPIO5_START + 17) +#define MX8MP_IRQ_SOFT_GPIO5_17 (MX8MP_IRQ_SOFT_GPIO5_START + 18) +#define MX8MP_IRQ_SOFT_GPIO5_18 (MX8MP_IRQ_SOFT_GPIO5_START + 19) +#define MX8MP_IRQ_SOFT_GPIO5_19 (MX8MP_IRQ_SOFT_GPIO5_START + 20) +#define MX8MP_IRQ_SOFT_GPIO5_20 (MX8MP_IRQ_SOFT_GPIO5_START + 21) +#define MX8MP_IRQ_SOFT_GPIO5_21 (MX8MP_IRQ_SOFT_GPIO5_START + 22) +#define MX8MP_IRQ_SOFT_GPIO5_22 (MX8MP_IRQ_SOFT_GPIO5_START + 23) +#define MX8MP_IRQ_SOFT_GPIO5_23 (MX8MP_IRQ_SOFT_GPIO5_START + 24) +#define MX8MP_IRQ_SOFT_GPIO5_24 (MX8MP_IRQ_SOFT_GPIO5_START + 25) +#define MX8MP_IRQ_SOFT_GPIO5_25 (MX8MP_IRQ_SOFT_GPIO5_START + 26) +#define MX8MP_IRQ_SOFT_GPIO5_26 (MX8MP_IRQ_SOFT_GPIO5_START + 27) +#define MX8MP_IRQ_SOFT_GPIO5_27 (MX8MP_IRQ_SOFT_GPIO5_START + 28) +#define MX8MP_IRQ_SOFT_GPIO5_28 (MX8MP_IRQ_SOFT_GPIO5_START + 29) +#define MX8MP_IRQ_SOFT_GPIO5_29 (MX8MP_IRQ_SOFT_GPIO5_START + 30) +#define MX8MP_IRQ_SOFT_GPIO5_30 (MX8MP_IRQ_SOFT_GPIO5_START + 31) +#define MX8MP_IRQ_SOFT_GPIO5_31 (MX8MP_IRQ_SOFT_GPIO5_START + 32) + +#define MX8MP_IRQ_SOFT_GPIO_END MX8MP_IRQ_SOFT_GPIO5_31 + +#define NR_IRQS (MX8MP_IRQ_NVECTORS + MX8MP_IRQ_SOFT_GPIO_END) #endif /* ARCH_ARM_INCLUDE_MX8MP_IRQ_H */ diff --git a/arch/arm/src/mx8mp/hardware/mx8mp_gpio.h b/arch/arm/src/mx8mp/hardware/mx8mp_gpio.h index 3ab131ae763..ea65f64e464 100644 --- a/arch/arm/src/mx8mp/hardware/mx8mp_gpio.h +++ b/arch/arm/src/mx8mp/hardware/mx8mp_gpio.h @@ -37,12 +37,6 @@ * Pre-processor Definitions ****************************************************************************/ -#define GPIO1 0 /* Port 1 index */ -#define GPIO2 1 /* Port 2 index */ -#define GPIO3 2 /* Port 3 index */ -#define GPIO4 3 /* Port 4 index */ -#define GPIO5 4 /* Port 5 index */ - #define GPIO_NPORTS 5 /* Seven total ports */ #define GPIO_NPINS 32 /* Up to 32 pins per port */ diff --git a/arch/arm/src/mx8mp/hardware/mx8mp_pinmux.h b/arch/arm/src/mx8mp/hardware/mx8mp_pinmux.h index a3c218091a1..0b30817341f 100644 --- a/arch/arm/src/mx8mp/hardware/mx8mp_pinmux.h +++ b/arch/arm/src/mx8mp/hardware/mx8mp_pinmux.h @@ -40,31 +40,31 @@ /* General Purpose Registers */ -#define IMX_IOMUXC_GPR0_OFFSET 0x0000 -#define IMX_IOMUXC_GPR1_OFFSET 0x0004 -#define IMX_IOMUXC_GPR2_OFFSET 0x0008 -#define IMX_IOMUXC_GPR3_OFFSET 0x000c -#define IMX_IOMUXC_GPR4_OFFSET 0x0010 -#define IMX_IOMUXC_GPR5_OFFSET 0x0014 -#define IMX_IOMUXC_GPR6_OFFSET 0x0018 -#define IMX_IOMUXC_GPR7_OFFSET 0x001c -#define IMX_IOMUXC_GPR8_OFFSET 0x0020 -#define IMX_IOMUXC_GPR9_OFFSET 0x0024 -#define IMX_IOMUXC_GPR10_OFFSET 0x0028 -#define IMX_IOMUXC_GPR11_OFFSET 0x002c -#define IMX_IOMUXC_GPR12_OFFSET 0x0030 -#define IMX_IOMUXC_GPR13_OFFSET 0x0034 -#define IMX_IOMUXC_GPR14_OFFSET 0x0038 -#define IMX_IOMUXC_GPR15_OFFSET 0x003c -#define IMX_IOMUXC_GPR16_OFFSET 0x0040 -#define IMX_IOMUXC_GPR17_OFFSET 0x0044 -#define IMX_IOMUXC_GPR18_OFFSET 0x0048 -#define IMX_IOMUXC_GPR19_OFFSET 0x004c -#define IMX_IOMUXC_GPR20_OFFSET 0x0050 -#define IMX_IOMUXC_GPR21_OFFSET 0x0054 -#define IMX_IOMUXC_GPR22_OFFSET 0x0058 -#define IMX_IOMUXC_GPR23_OFFSET 0x005c -#define IMX_IOMUXC_GPR24_OFFSET 0x0060 +#define IOMUXC_GPR0_OFFSET 0x0000 +#define IOMUXC_GPR1_OFFSET 0x0004 +#define IOMUXC_GPR2_OFFSET 0x0008 +#define IOMUXC_GPR3_OFFSET 0x000c +#define IOMUXC_GPR4_OFFSET 0x0010 +#define IOMUXC_GPR5_OFFSET 0x0014 +#define IOMUXC_GPR6_OFFSET 0x0018 +#define IOMUXC_GPR7_OFFSET 0x001c +#define IOMUXC_GPR8_OFFSET 0x0020 +#define IOMUXC_GPR9_OFFSET 0x0024 +#define IOMUXC_GPR10_OFFSET 0x0028 +#define IOMUXC_GPR11_OFFSET 0x002c +#define IOMUXC_GPR12_OFFSET 0x0030 +#define IOMUXC_GPR13_OFFSET 0x0034 +#define IOMUXC_GPR14_OFFSET 0x0038 +#define IOMUXC_GPR15_OFFSET 0x003c +#define IOMUXC_GPR16_OFFSET 0x0040 +#define IOMUXC_GPR17_OFFSET 0x0044 +#define IOMUXC_GPR18_OFFSET 0x0048 +#define IOMUXC_GPR19_OFFSET 0x004c +#define IOMUXC_GPR20_OFFSET 0x0050 +#define IOMUXC_GPR21_OFFSET 0x0054 +#define IOMUXC_GPR22_OFFSET 0x0058 +#define IOMUXC_GPR23_OFFSET 0x005c +#define IOMUXC_GPR24_OFFSET 0x0060 /* The pin function ID is a tuple that contains in order: * mux_register @@ -879,7 +879,6 @@ #define IOMUXC_HDMI_HPD_CAN2_RX 0x3033024C, 0x4, 0x30330550, 0x3, 0x303304AC #define IOMUXC_HDMI_HPD_GPIO3_IO29 0x3033024C, 0x5, 0x00000000, 0x0, 0x303304AC - /* DSE - Drive Strength Field * 00 x1 * 10 x2 diff --git a/arch/arm/src/mx8mp/mx8mp_config.h b/arch/arm/src/mx8mp/mx8mp_config.h index 48443213034..096d43d7590 100644 --- a/arch/arm/src/mx8mp/mx8mp_config.h +++ b/arch/arm/src/mx8mp/mx8mp_config.h @@ -70,4 +70,4 @@ #error "MPU is requiered for proper behavior" #endif -#endif /* __ARCH_ARM_SRC_MX8MP_IMX_CONFIG_H */ +#endif /* __ARCH_ARM_SRC_MX8MP_MX8MP_CONFIG_H */ diff --git a/arch/arm/src/mx8mp/mx8mp_gpio.c b/arch/arm/src/mx8mp/mx8mp_gpio.c index 60a5a182472..a48d1cdcee9 100644 --- a/arch/arm/src/mx8mp/mx8mp_gpio.c +++ b/arch/arm/src/mx8mp/mx8mp_gpio.c @@ -38,14 +38,151 @@ * Pre-processor Definitions ****************************************************************************/ +/**************************************************************************** + * Private Type + ****************************************************************************/ + +/* GPIO context for IRQ management */ + +struct mx8mp_gpio_s +{ + const uint32_t isr; + const uint32_t imr; + const uint16_t irq_start; + const uint16_t bit; + const uint32_t mask; +}; + /**************************************************************************** * Private Data ****************************************************************************/ +static struct mx8mp_gpio_s g_gpio1_l = +{ + .isr = GPIO_ISR(1), + .imr = GPIO_IMR(1), + .irq_start = MX8MP_IRQ_SOFT_GPIO1_0, + .bit = 0, + .mask = 0x0000ffff +}; + +static struct mx8mp_gpio_s g_gpio1_h = +{ + .isr = GPIO_ISR(1), + .imr = GPIO_IMR(1), + .irq_start = MX8MP_IRQ_SOFT_GPIO1_16, + .bit = 16, + .mask = 0xffff0000 +}; + +static struct mx8mp_gpio_s g_gpio2_l = +{ + .isr = GPIO_ISR(2), + .imr = GPIO_IMR(2), + .irq_start = MX8MP_IRQ_SOFT_GPIO2_0, + .bit = 0, + .mask = 0x0000ffff +}; + +static struct mx8mp_gpio_s g_gpio2_h = +{ + .isr = GPIO_ISR(2), + .imr = GPIO_IMR(2), + .irq_start = MX8MP_IRQ_SOFT_GPIO2_16, + .bit = 16, + .mask = 0xffff0000 +}; + +static struct mx8mp_gpio_s g_gpio3_l = +{ + .isr = GPIO_ISR(3), + .imr = GPIO_IMR(3), + .irq_start = MX8MP_IRQ_SOFT_GPIO3_0, + .bit = 0, + .mask = 0x0000ffff +}; + +static struct mx8mp_gpio_s g_gpio3_h = +{ + .isr = GPIO_ISR(3), + .imr = GPIO_IMR(3), + .irq_start = MX8MP_IRQ_SOFT_GPIO3_16, + .bit = 16, + .mask = 0xffff0000 +}; + +static struct mx8mp_gpio_s g_gpio4_l = +{ + .isr = GPIO_ISR(4), + .imr = GPIO_IMR(4), + .irq_start = MX8MP_IRQ_SOFT_GPIO4_0, + .bit = 0, + .mask = 0x0000ffff +}; + +static struct mx8mp_gpio_s g_gpio4_h = +{ + .isr = GPIO_ISR(4), + .imr = GPIO_IMR(4), + .irq_start = MX8MP_IRQ_SOFT_GPIO4_16, + .bit = 16, + .mask = 0xffff0000 +}; + +static struct mx8mp_gpio_s g_gpio5_l = +{ + .isr = GPIO_ISR(5), + .imr = GPIO_IMR(5), + .irq_start = MX8MP_IRQ_SOFT_GPIO5_0, + .bit = 0, + .mask = 0x0000ffff +}; + +static struct mx8mp_gpio_s g_gpio5_h = +{ + .isr = GPIO_ISR(5), + .imr = GPIO_IMR(5), + .irq_start = MX8MP_IRQ_SOFT_GPIO5_16, + .bit = 16, + .mask = 0xffff0000 +}; + /**************************************************************************** * Private Functions ****************************************************************************/ +static int mx8mp_gpio_interrupt(int irq, void *context, void *arg) +{ + struct mx8mp_gpio_s *cfg = (struct mx8mp_gpio_s *)(arg); + + uint32_t status; + int i; + + /* Get the pending interrupt indications */ + + status = getreg32(cfg->isr) & getreg32(cfg->imr) & cfg->mask; + + /* Decode the pending interrupts */ + + for (i = 0; (i < 16) && (status != 0); ++i) + { + /* Is the IRQ associate with this pin pending? */ + + uint32_t mask = (1 << (cfg->bit + i)); + if ((status & mask) != 0) + { + /* Yes, clear the status bit and dispatch the interrupt */ + + putreg32(mask, cfg->isr); + status &= ~mask; + + irq_dispatch(cfg->irq_start + i, context); + } + } + + return OK; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -98,7 +235,6 @@ int mx8mp_gpio_config(gpio_pinset_t pinset) /* Convert the configured input GPIO to an output */ modreg32(GPIO_PIN(pin), GPIO_PIN(pin), GPIO_GDIR(port)); - printf("output %lx -> %lx (%lu) (%lu)\n", GPIO_GDIR(port), getreg32(GPIO_GDIR(port)), port, pin); } break; @@ -121,6 +257,70 @@ int mx8mp_gpio_config(gpio_pinset_t pinset) return ret; } +/**************************************************************************** + * Name: mx8mp_gpio_irq_initialize + * + * Description: + * Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + * + ****************************************************************************/ + +void mx8mp_gpio_irq_initialize(void) +{ + /* Disable all GPIO interrupts at the source */ + + putreg32(0, GPIO_IMR(1)); + putreg32(0, GPIO_IMR(2)); + putreg32(0, GPIO_IMR(3)); + putreg32(0, GPIO_IMR(4)); + putreg32(0, GPIO_IMR(5)); + + /* Disable all GPIO interrupts at the NVIC */ + + up_disable_irq(MX8MP_IRQ_GPIO1_0_15); + up_disable_irq(MX8MP_IRQ_GPIO1_16_31); + + up_disable_irq(MX8MP_IRQ_GPIO2_0_15); + up_disable_irq(MX8MP_IRQ_GPIO2_16_31); + + up_disable_irq(MX8MP_IRQ_GPIO3_0_15); + up_disable_irq(MX8MP_IRQ_GPIO3_16_31); + + up_disable_irq(MX8MP_IRQ_GPIO4_0_15); + up_disable_irq(MX8MP_IRQ_GPIO4_16_31); + + up_disable_irq(MX8MP_IRQ_GPIO5_0_15); + up_disable_irq(MX8MP_IRQ_GPIO5_16_31); + + /* Attach all GPIO interrupts and enable the interrupt at the NVIC */ + + irq_attach(MX8MP_IRQ_GPIO1_0_15, mx8mp_gpio_interrupt, &g_gpio1_l); + up_enable_irq(MX8MP_IRQ_GPIO1_0_15); + irq_attach(MX8MP_IRQ_GPIO1_16_31, mx8mp_gpio_interrupt, &g_gpio1_h); + up_enable_irq(MX8MP_IRQ_GPIO1_16_31); + + irq_attach(MX8MP_IRQ_GPIO2_0_15, mx8mp_gpio_interrupt, &g_gpio2_l); + up_enable_irq(MX8MP_IRQ_GPIO2_0_15); + irq_attach(MX8MP_IRQ_GPIO2_16_31, mx8mp_gpio_interrupt, &g_gpio2_h); + up_enable_irq(MX8MP_IRQ_GPIO2_16_31); + + irq_attach(MX8MP_IRQ_GPIO3_0_15, mx8mp_gpio_interrupt, &g_gpio3_l); + up_enable_irq(MX8MP_IRQ_GPIO3_0_15); + irq_attach(MX8MP_IRQ_GPIO3_16_31, mx8mp_gpio_interrupt, &g_gpio3_h); + up_enable_irq(MX8MP_IRQ_GPIO3_16_31); + + irq_attach(MX8MP_IRQ_GPIO4_0_15, mx8mp_gpio_interrupt, &g_gpio4_l); + up_enable_irq(MX8MP_IRQ_GPIO4_0_15); + irq_attach(MX8MP_IRQ_GPIO4_16_31, mx8mp_gpio_interrupt, &g_gpio4_h); + up_enable_irq(MX8MP_IRQ_GPIO4_16_31); + + irq_attach(MX8MP_IRQ_GPIO5_0_15, mx8mp_gpio_interrupt, &g_gpio5_l); + up_enable_irq(MX8MP_IRQ_GPIO5_0_15); + irq_attach(MX8MP_IRQ_GPIO5_16_31, mx8mp_gpio_interrupt, &g_gpio5_h); + up_enable_irq(MX8MP_IRQ_GPIO5_16_31); +} + /**************************************************************************** * Name: mx8mp_gpio_write * @@ -133,10 +333,12 @@ void mx8mp_gpio_write(gpio_pinset_t pinset, bool value) { uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; - uint32_t regaddr = GPIO_DR(port); uint32_t regval; + irqstate_t flags; - regval = getreg32(regaddr); + flags = enter_critical_section(); + + regval = getreg32(GPIO_DR(port)); if (value) { regval |= GPIO_PIN(pin); @@ -146,9 +348,10 @@ void mx8mp_gpio_write(gpio_pinset_t pinset, bool value) regval &= ~GPIO_PIN(pin); } - putreg32(regval, regaddr); -} + putreg32(regval, GPIO_DR(port)); + leave_critical_section(flags); +} /**************************************************************************** * Name: mx8mp_gpio_read @@ -162,8 +365,21 @@ bool mx8mp_gpio_read(gpio_pinset_t pinset) { uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + uint32_t regval; + irqstate_t flags; - uint32_t regval = getreg32(GPIO_DR(port)); + flags = enter_critical_section(); + + if ((pinset & (GPIO_OUTPUT)) == (GPIO_OUTPUT)) + { + regval = getreg32(GPIO_PSR(port)); + } + else + { + regval = getreg32(GPIO_DR(port)); + } + + leave_critical_section(flags); return ((regval & GPIO_PIN(pin)) != 0); } @@ -187,6 +403,7 @@ void mx8mp_gpio_configure_irq(gpio_pinset_t pinset) uint32_t regval; /* Set the right field in the right ICR register */ + regaddr = pin < 16 ? GPIO_ICR1(port) : GPIO_ICR2(port); regval = getreg32(regaddr); regval &= ~ICR_MASK(pin); @@ -203,52 +420,33 @@ void mx8mp_gpio_configure_irq(gpio_pinset_t pinset) } /**************************************************************************** - * Name: mx8mp_gpio_enable_irq + * Name: mx8mp_gpio_irq_enable * * Description: - * Enable the interrupt for specified GPIO IRQ + * Enable the interrupt for specified GPIO * ****************************************************************************/ -int mx8mp_gpio_enable_irq(int irq) +void mx8mp_gpio_irq_enable(gpio_pinset_t pinset) { -#if 0 - uintptr_t regaddr; - unsigned int pin; - int ret; + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; - ret = imxrt_gpio_info(irq, ®addr, &pin); - if (ret >= 0) - { - modifyreg32(regaddr, 0, 1 << pin); - } - - return ret; -#endif - return OK; + modifyreg32(GPIO_IMR(port), 0, GPIO_PIN(pin)); } /**************************************************************************** - * Name: mx8mp_gpio_disable_irq + * Name: mx8mp_gpio_irq_disable * * Description: - * Disable the interrupt for specified GPIO IRQ + * Disable the interrupt for specified GPIO * ****************************************************************************/ -int mx8mp_gpio_disable_irq(int irq) +void mx8mp_gpio_irq_disable(gpio_pinset_t pinset) { -#if 0 - uintptr_t regaddr; - unsigned int pin; - int ret; - ret = imxrt_gpio_info(irq, ®addr, &pin); - if (ret >= 0) - { - modifyreg32(regaddr, 1 << pin, 0); - } + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; - return ret; - #endif - return OK; + modifyreg32(GPIO_IMR(port), GPIO_PIN(pin), 0); } diff --git a/arch/arm/src/mx8mp/mx8mp_gpio.h b/arch/arm/src/mx8mp/mx8mp_gpio.h index da92d32554e..08916baa5bd 100644 --- a/arch/arm/src/mx8mp/mx8mp_gpio.h +++ b/arch/arm/src/mx8mp/mx8mp_gpio.h @@ -84,7 +84,6 @@ #define GPIO_INTBOTHCFG_MASK (1 << GPIO_INTBOTHCFG_SHIFT) # define GPIO_INTBOTH_EDGES (1 << GPIO_INTBOTHCFG_SHIFT) - /* GPIO Port Number * * GPIO INPUT 00.. .... GGG. .... .... .... .... .... @@ -176,7 +175,7 @@ extern "C" int mx8mp_gpio_config(gpio_pinset_t pinset); /**************************************************************************** - * Name: imx_gpio_write + * Name: mx8mp_gpio_write * * Description: * Write one or zero to the selected GPIO pin @@ -195,6 +194,17 @@ void mx8mp_gpio_write(gpio_pinset_t pinset, bool value); bool mx8mp_gpio_read(gpio_pinset_t pinset); +/**************************************************************************** + * Name: mx8mp_gpio_irq_initialize + * + * Description: + * Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + * + ****************************************************************************/ + +void mx8mp_gpio_irq_initialize(void); + /**************************************************************************** * Name: mx8mp_gpio_configure_irq * @@ -206,39 +216,24 @@ bool mx8mp_gpio_read(gpio_pinset_t pinset); void mx8mp_gpio_configure_irq(gpio_pinset_t pinset); /**************************************************************************** - * Name: imx_gpioirq_enable + * Name: mx8mp_gpio_irq_enable * * Description: * Enable the interrupt for specified GPIO IRQ * ****************************************************************************/ -int mx8mp_gpio_enable_irq(int irq); +void mx8mp_gpio_irq_enable(gpio_pinset_t pinset); /**************************************************************************** - * Name: imx_gpioirq_disable + * Name: mx8mp_gpio_irq_disable * * Description: * Disable the interrupt for specified GPIO IRQ * ****************************************************************************/ -int mx8mp_gpio_disable_irq(int irq); - -/**************************************************************************** - * Function: imx_dump_gpio - * - * Description: - * Dump all GPIO registers associated with the base address of the provided - * pinset. - * - ****************************************************************************/ - -#ifdef CONFIG_DEBUG_GPIO_INFO -int mx8mp_dump_gpio(gpio_pinset_t pinset, const char *msg); -#else -# define mx8mp_dump_gpio(p,m) -#endif +void mx8mp_gpio_irq_disable(gpio_pinset_t pinset); #undef EXTERN #if defined(__cplusplus) diff --git a/arch/arm/src/mx8mp/mx8mp_irq.c b/arch/arm/src/mx8mp/mx8mp_irq.c index 47fe11d74e6..f224597d38b 100644 --- a/arch/arm/src/mx8mp/mx8mp_irq.c +++ b/arch/arm/src/mx8mp/mx8mp_irq.c @@ -37,6 +37,8 @@ #include "ram_vectors.h" #include "arm_internal.h" +#include "mx8mp_gpio.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -420,9 +422,15 @@ void up_irqinitialize(void) putreg32(regval, NVIC_DEMCR); #endif +#ifndef CONFIG_SUPPRESS_INTERRUPTS + /* Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + */ + + mx8mp_gpio_irq_initialize(); + /* And finally, enable interrupts */ -#ifndef CONFIG_SUPPRESS_INTERRUPTS up_irq_enable(); #endif } diff --git a/arch/arm/src/mx8mp/mx8mp_lowputc.h b/arch/arm/src/mx8mp/mx8mp_lowputc.h index fdaf7e16ca6..2f0cdf233bd 100644 --- a/arch/arm/src/mx8mp/mx8mp_lowputc.h +++ b/arch/arm/src/mx8mp/mx8mp_lowputc.h @@ -54,7 +54,7 @@ struct uart_config_s ****************************************************************************/ /**************************************************************************** - * Name: imx_uart_configure + * Name: mx8mp_uart_configure * * Description: * Configure a UART for non-interrupt driven operation @@ -66,7 +66,7 @@ int mx8mp_uart_configure(uint32_t base, const struct uart_config_s *config); /**************************************************************************** - * Name: imx_lowsetup + * Name: mx8mp_lowsetup * * Description: * Called at the very beginning of _start. Performs low level diff --git a/arch/arm/src/mx8mp/mx8mp_serial.c b/arch/arm/src/mx8mp/mx8mp_serial.c index 88cf405e6b4..782eea68acf 100644 --- a/arch/arm/src/mx8mp/mx8mp_serial.c +++ b/arch/arm/src/mx8mp/mx8mp_serial.c @@ -250,8 +250,6 @@ static char g_uart4rxbuffer[CONFIG_UART4_RXBUFSIZE]; static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE]; #endif -/* This describes the state of the IMX uart1 port. */ - #ifdef CONFIG_MX8MP_UART1 static struct mx8mp_uart_s g_uart1priv = { @@ -281,8 +279,6 @@ static struct uart_dev_s g_uart1port = }; #endif -/* This describes the state of the IMX uart2 port. */ - #ifdef CONFIG_MX8MP_UART2 static struct mx8mp_uart_s g_uart2priv = { diff --git a/arch/arm/src/mx8mp/mx8mp_timerisr.c b/arch/arm/src/mx8mp/mx8mp_timerisr.c index debe37c93a0..1b7caedcc29 100644 --- a/arch/arm/src/mx8mp/mx8mp_timerisr.c +++ b/arch/arm/src/mx8mp/mx8mp_timerisr.c @@ -62,7 +62,7 @@ static int mx8mp_timerisr(int irq, uint32_t *regs, void *arg); ****************************************************************************/ /**************************************************************************** - * Function: imxrt_timerisr + * Function: mx8mp_timerisr * * Description: * The timer ISR will perform a variety of services for various portions diff --git a/boards/Kconfig b/boards/Kconfig index f319212d653..fc7d9900da3 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -2758,6 +2758,8 @@ config ARCH_BOARD_VERDIN_MX8MP bool "Toradex Verdin i.MX8MP" depends on ARCH_CHIP_MX8MP select ARCH_HAVE_LEDS + select ARCH_HAVE_BUTTONS + select ARCH_HAVE_IRQBUTTONS ---help--- Toradex Verdin i.MX8MP diff --git a/boards/arm/mx8mp/verdin-mx8mp/README.txt b/boards/arm/mx8mp/verdin-mx8mp/README.txt index b536017ac82..50d4305bb40 100644 --- a/boards/arm/mx8mp/verdin-mx8mp/README.txt +++ b/boards/arm/mx8mp/verdin-mx8mp/README.txt @@ -4,7 +4,16 @@ README for the verdin-mx8mp Relax The directory provides board support for the Toradex Verdin mx8mp. Note: this port works on the internal Cortex-M7 auxiliary core, NOT the main Cortex-53 complex! + LEDs and buttons shall be connected to header pins like this: + - LED21 on GPIO_4 + - LED22 on GPIO_3 + - LED23 on GPIO_2 + - LED24 on GPIO_1 + - SW11 on GPIO_5_CSI + You can adjust this pinout in verdin_mx8mp.h + Status ====== 2023-08-23: The Verdin mx8mp boots into NSH, provides the NSH prompt. + 2023-09-04: gpio support, i2c support (tested with on-board ina219 sensor) diff --git a/boards/arm/mx8mp/verdin-mx8mp/configs/nsh/defconfig b/boards/arm/mx8mp/verdin-mx8mp/configs/nsh/defconfig index d3de7fd2692..4880b2065f8 100644 --- a/boards/arm/mx8mp/verdin-mx8mp/configs/nsh/defconfig +++ b/boards/arm/mx8mp/verdin-mx8mp/configs/nsh/defconfig @@ -5,27 +5,30 @@ # You can then do "make savedefconfig" to generate a new defconfig file that includes your # modifications. # +# CONFIG_ARCH_LEDS is not set # CONFIG_ARCH_RAMFUNCS is not set # CONFIG_STANDARD_SERIAL is not set CONFIG_ARCH="arm" CONFIG_ARCH_BOARD="verdin-mx8mp" CONFIG_ARCH_BOARD_VERDIN_MX8MP=y +CONFIG_ARCH_BUTTONS=y CONFIG_ARCH_CHIP="mx8mp" CONFIG_ARCH_CHIP_MX8MP=y CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_IRQBUTTONS=y CONFIG_ARCH_STACKDUMP=y CONFIG_ARMV7M_DCACHE=y CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y CONFIG_ARMV7M_ICACHE=y CONFIG_ARM_MPU=y -CONFIG_BOARD_LOOPSPERMSEC=8000 +CONFIG_BOARD_LOOPSPERMSEC=159972 CONFIG_BUILTIN=y CONFIG_CXX_EXCEPTION=y CONFIG_CXX_RTTI=y -CONFIG_EXAMPLES_CALIB_UDELAY=y -CONFIG_EXAMPLES_CALIB_UDELAY_NUM_MEASUREMENTS=6 -CONFIG_EXAMPLES_CALIB_UDELAY_NUM_RESULTS=60 +CONFIG_EXAMPLES_BUTTONS=y +CONFIG_EXAMPLES_HELLOXX=y CONFIG_EXAMPLES_INA219=y +CONFIG_EXAMPLES_LEDS=y CONFIG_HAVE_CXX=y CONFIG_I2CTOOL_MAXADDR=0x7f CONFIG_I2CTOOL_MAXBUS=6 @@ -33,6 +36,8 @@ CONFIG_I2CTOOL_MINADDR=0x00 CONFIG_I2CTOOL_MINBUS=1 CONFIG_I2C_RESET=y CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INPUT=y +CONFIG_INPUT_BUTTONS_LOWER=y CONFIG_INTELHEX_BINARY=y CONFIG_LIBCXX=y CONFIG_MX8MP_I2C4=y @@ -60,5 +65,6 @@ CONFIG_SYSTEM_I2CTOOL=y CONFIG_SYSTEM_NSH=y CONFIG_SYSTEM_RAMTEST=y CONFIG_UART4_SERIAL_CONSOLE=y +CONFIG_UINPUT_BUTTONS=y CONFIG_USERLED=y CONFIG_USERLED_LOWER=y diff --git a/boards/arm/mx8mp/verdin-mx8mp/include/board.h b/boards/arm/mx8mp/verdin-mx8mp/include/board.h index d46b557999e..38d348cb253 100644 --- a/boards/arm/mx8mp/verdin-mx8mp/include/board.h +++ b/boards/arm/mx8mp/verdin-mx8mp/include/board.h @@ -43,8 +43,6 @@ /* LED definitions **********************************************************/ -/* The Freedom K66F has a single RGB LED driven by the K66F as follows: - /* LED index values for use with board_userled() */ #define BOARD_LED_1 0 @@ -68,15 +66,30 @@ * ------------------- ---------------------------- -------------------- */ -#define LED_STARTED 1 /* NuttX has been started None */ -#define LED_HEAPALLOCATE 2 /* Heap has been allocated ON(1) */ -#define LED_IRQSENABLED 0 /* Interrupts enabled ON(1) */ -#define LED_STACKCREATED 3 /* Idle stack created ON(2) */ -#define LED_INIRQ 0 /* In an interrupt (no change) */ -#define LED_SIGNAL 0 /* In a signal handler (no change) */ -#define LED_ASSERTION 0 /* An assertion failed (no change) */ -#define LED_PANIC 5 /* The system has crashed FLASH(3) */ -#undef LED_IDLE 4 /* idle loop FLASH(4) */ +#define LED_STARTED 0 /* NuttX has been started None */ +#define LED_HEAPALLOCATE 1 /* Heap has been allocated ON(1), OFF(2) */ +#define LED_IRQSENABLED 2 /* Interrupts enabled OFF(1), ON(2) */ +#define LED_STACKCREATED 3 /* Idle stack created ON(1), ON(2) */ +#define LED_INIRQ 4 /* In an interrupt (no change) */ +#define LED_SIGNAL 5 /* In a signal handler (no change) */ +#define LED_ASSERTION 6 /* An assertion failed ON(3) */ +#define LED_PANIC 7 /* The system has crashed FLASH(1,2) */ +#define LED_IDLE 8 /* idle loop FLASH(4) */ + +/* Button definitions *******************************************************/ + +/* The Verdin board has four switch buttons and four on/off buttons. + * They are not connected to the board by default: it is up to the user to + * connect them to one of the multiple available headers pins. + * Here we choose (arbitrary) to connect SW11 to GPIO_5_CSI header pin + * + * 1. SW11 GPIO1_7 (= GPIO_5_CSI) + */ + +#define BUTTON_1 0 +#define NUM_BUTTONS 1 + +#define BUTTON_1_BIT (1 << BUTTON_1) /**************************************************************************** * Public Data diff --git a/boards/arm/mx8mp/verdin-mx8mp/src/Makefile b/boards/arm/mx8mp/verdin-mx8mp/src/Makefile index 9688dde45ea..205bb0cfdba 100644 --- a/boards/arm/mx8mp/verdin-mx8mp/src/Makefile +++ b/boards/arm/mx8mp/verdin-mx8mp/src/Makefile @@ -35,9 +35,13 @@ ifeq ($(CONFIG_MX8MP_I2C_DRIVER),y) endif ifeq ($(CONFIG_ARCH_LEDS),y) -#CSRCS += mx8mp_autoleds.c + CSRCS += mx8mp_autoleds.c else -CSRCS += mx8mp_userleds.c + CSRCS += mx8mp_userleds.c +endif + +ifeq ($(CONFIG_ARCH_BUTTONS),y) + CSRCS += mx8mp_buttons.c endif diff --git a/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_autoleds.c b/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_autoleds.c new file mode 100644 index 00000000000..f7e817663c8 --- /dev/null +++ b/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_autoleds.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_autoleds.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "mx8mp_gpio.h" +#include "verdin-mx8mp.h" + +#ifdef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_autoled_initialize + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + mx8mp_iomuxc_config(IOMUX_LED_1); + mx8mp_iomuxc_config(IOMUX_LED_2); + mx8mp_iomuxc_config(IOMUX_LED_3); + mx8mp_iomuxc_config(IOMUX_LED_4); + + mx8mp_gpio_config(GPIO_LED_1); + mx8mp_gpio_config(GPIO_LED_2); + mx8mp_gpio_config(GPIO_LED_3); + mx8mp_gpio_config(GPIO_LED_4); +} + +/**************************************************************************** + * Name: board_autoled_on + ****************************************************************************/ + +void board_autoled_on(int led) +{ + switch (led) + { + case LED_HEAPALLOCATE: + { + mx8mp_gpio_write(GPIO_LED_1, true); + mx8mp_gpio_write(GPIO_LED_2, false); + } + break; + + case LED_IRQSENABLED: + { + mx8mp_gpio_write(GPIO_LED_1, false); + mx8mp_gpio_write(GPIO_LED_2, true); + } + break; + + case LED_STACKCREATED: + { + mx8mp_gpio_write(GPIO_LED_1, true); + mx8mp_gpio_write(GPIO_LED_2, true); + } + break; + + case LED_ASSERTION: + { + mx8mp_gpio_write(GPIO_LED_3, true); + } + break; + + case LED_PANIC: + { + mx8mp_gpio_write(GPIO_LED_1, true); + mx8mp_gpio_write(GPIO_LED_2, true); + } + break; + + case LED_IDLE: + { + mx8mp_gpio_write(GPIO_LED_4, true); + } + break; + } +} + +/**************************************************************************** + * Name: board_autoled_off + ****************************************************************************/ + +void board_autoled_off(int led) +{ + switch (led) + { + case LED_PANIC: + { + mx8mp_gpio_write(GPIO_LED_1, false); + mx8mp_gpio_write(GPIO_LED_2, false); + } + break; + + case LED_IDLE: + { + mx8mp_gpio_write(GPIO_LED_4, false); + } + break; + } +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_bringup.c b/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_bringup.c index 7b35f0a05d4..87e01244162 100644 --- a/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_bringup.c +++ b/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_bringup.c @@ -23,16 +23,13 @@ ****************************************************************************/ #include +#include +#include #include -#include -#include #include "verdin-mx8mp.h" - -#ifdef CONFIG_USERLED -# include -#endif +#include "mx8mp_gpio.h" #ifdef CONFIG_SENSORS_INA219 # include "mx8mp_ina219.h" @@ -54,15 +51,39 @@ int mx8mp_bringup(void) { int ret = OK; -#if !defined(CONFIG_ARCH_LEDS) && defined(CONFIG_USERLED_LOWER) +#if defined(CONFIG_USERLED) && !defined(CONFIG_ARCH_LEDS) +#ifdef CONFIG_USERLED_LOWER /* Register the LED driver */ ret = userled_lower_initialize("/dev/userleds"); - if (ret < 0) + if (ret != OK) { syslog(LOG_ERR, "ERROR: userled_lower_initialize() failed: %d\n", ret); + return ret; } -#endif +#else + /* Enable USER LED support for some other purpose */ + + board_userled_initialize(); +#endif /* CONFIG_USERLED_LOWER */ +#endif /* CONFIG_USERLED && !CONFIG_ARCH_LEDS */ + +#ifdef CONFIG_INPUT_BUTTONS +#ifdef CONFIG_INPUT_BUTTONS_LOWER + /* Register the BUTTON driver */ + + ret = btn_lower_initialize("/dev/buttons"); + if (ret != OK) + { + syslog(LOG_ERR, "ERROR: btn_lower_initialize() failed: %d\n", ret); + return ret; + } +#else + /* Enable BUTTON support for some other purpose */ + + board_button_initialize(); +#endif /* CONFIG_INPUT_BUTTONS_LOWER */ +#endif /* CONFIG_INPUT_BUTTONS */ #ifdef CONFIG_FS_PROCFS /* Mount the procfs file system */ diff --git a/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_buttons.c b/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_buttons.c new file mode 100644 index 00000000000..ee7e4ccaaf8 --- /dev/null +++ b/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_buttons.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_buttons.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "arm_internal.h" +#include "mx8mp_gpio.h" +#include "verdin-mx8mp.h" + +#ifdef CONFIG_ARCH_BUTTONS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_button_irqx + * + * Description: + * This function implements the core of the board_button_irq() logic. + * + ****************************************************************************/ + +static int board_button_irqx(gpio_pinset_t pinset, int irq, + xcpt_t irqhandler, void *arg) +{ + irqstate_t flags; + + /* Disable interrupts until we are done. This guarantees that the + * following operations are atomic. + */ + + flags = enter_critical_section(); + + /* Are we attaching or detaching? */ + + if (irqhandler != NULL) + { + /* Configure the interrupt */ + + irq_attach(irq, irqhandler, arg); + mx8mp_gpio_irq_enable (pinset); + + /* Then make sure that interrupts are enabled on the pin */ + + up_enable_irq(irq); + } + else + { + /* Detach and disable the interrupt */ + + irq_detach(irq); + mx8mp_gpio_irq_disable(pinset); + } + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_button_initialize + * + * Description: + * board_button_initialize() must be called to initialize button resources. + * After that, board_buttons() may be called to collect the current state + * of all buttons or board_button_irq() may be called to register button + * interrupt handlers. + * + ****************************************************************************/ + +uint32_t board_button_initialize(void) +{ + /* Configure the buttons as input */ + + mx8mp_iomuxc_config(BUTTON_1_IOMUX); + mx8mp_gpio_config(BUTTON_1_GPIO); + + return NUM_BUTTONS; +} + +/**************************************************************************** + * Name: board_buttons + * + * Description: + * After board_button_initialize() has been called, board_buttons() may be + * called to collect the state of all buttons. board_buttons() returns an + * 8-bit bit set with each bit associated with a button. See the + * BUTTON_*_BIT definitions in board.h for the meaning of each bit. + * + ****************************************************************************/ + +uint8_t board_buttons(void) +{ + uint8_t ret = 0; + + if (!mx8mp_gpio_read(BUTTON_1_GPIO)) + { + ret |= BUTTON_1_BIT; + } + + return ret; +} + +/**************************************************************************** + * Name: board_button_irq + * + * Description: + * board_button_irq() may be called to register an interrupt handler that + * will be called when a button is depressed or released. The ID value is + * a button enumeration value that uniquely identifies a button resource. + * See the BUTTON_* definitions in board.h for the meaning of enumeration + * value. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQBUTTONS +int board_button_irq(int id, xcpt_t irqhandler, void *arg) +{ + /* The button has already been configured as an interrupting input (by + * board_button_initialize() above). + * + * Attach the new button handler. + */ + + switch (id) + { + case BUTTON_1: + return board_button_irqx(BUTTON_1_GPIO, BUTTON_1_IRQ, + irqhandler, arg); + + default: + return -EINVAL; + } +} +#endif +#endif /* CONFIG_ARCH_BUTTONS */ diff --git a/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_userleds.c b/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_userleds.c index e647c932ab0..943e29b4074 100644 --- a/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_userleds.c +++ b/boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_userleds.c @@ -1,5 +1,5 @@ /**************************************************************************** - * boards/arm/nrf53/nrf5340-dk/src/nrf53_userleds.c + * boards/arm/mx8mp/verdin-mx8mp/src/mx8mp_userleds.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -52,8 +52,7 @@ #ifdef LED_VERBOSE static void led_dumppins(const char *msg) { - nrf53_pin_dump(PINCONFIG_LED, msg); - nrf53_gpio_dump(GPIO_LED, msg); + #warning Missing logic } #else # define led_dumppins(m) @@ -70,9 +69,9 @@ static void led_dumppins(const char *msg) uint32_t board_userled_initialize(void) { mx8mp_iomuxc_config(IOMUX_LED_1); - mx8mp_iomuxc_config(IOMUX_LED_1); - mx8mp_iomuxc_config(IOMUX_LED_1); - mx8mp_iomuxc_config(IOMUX_LED_1); + mx8mp_iomuxc_config(IOMUX_LED_2); + mx8mp_iomuxc_config(IOMUX_LED_3); + mx8mp_iomuxc_config(IOMUX_LED_4); mx8mp_gpio_config(GPIO_LED_1); mx8mp_gpio_config(GPIO_LED_2); @@ -119,6 +118,7 @@ void board_userled(int led, bool on) default: return; } + mx8mp_gpio_write(gpio, on); } diff --git a/boards/arm/mx8mp/verdin-mx8mp/src/verdin-mx8mp.h b/boards/arm/mx8mp/verdin-mx8mp/src/verdin-mx8mp.h index b5169442c85..6fa68195aa6 100644 --- a/boards/arm/mx8mp/verdin-mx8mp/src/verdin-mx8mp.h +++ b/boards/arm/mx8mp/verdin-mx8mp/src/verdin-mx8mp.h @@ -33,18 +33,24 @@ * Pre-processor Definitions ****************************************************************************/ -/* Board LEDs*/ +/* Board LEDs */ -#define GPIO_LED_1 (GPIO_OUTPUT | GPIO_OUTPUT_ONE | GPIO_PORT1 | GPIO_PIN0) -#define GPIO_LED_2 (GPIO_OUTPUT | GPIO_OUTPUT_ONE | GPIO_PORT1 | GPIO_PIN1) -#define GPIO_LED_3 (GPIO_OUTPUT | GPIO_OUTPUT_ONE | GPIO_PORT1 | GPIO_PIN5) -#define GPIO_LED_4 (GPIO_OUTPUT | GPIO_OUTPUT_ONE | GPIO_PORT1 | GPIO_PIN6) +#define GPIO_LED_1 (GPIO_OUTPUT | GPIO_PORT1 | GPIO_PIN0) +#define GPIO_LED_2 (GPIO_OUTPUT | GPIO_PORT1 | GPIO_PIN1) +#define GPIO_LED_3 (GPIO_OUTPUT | GPIO_PORT1 | GPIO_PIN5) +#define GPIO_LED_4 (GPIO_OUTPUT | GPIO_PORT1 | GPIO_PIN6) #define IOMUX_LED_1 IOMUXC_GPIO1_IO00_GPIO1_IO00, 0, GPIO_PAD_CTRL #define IOMUX_LED_2 IOMUXC_GPIO1_IO01_GPIO1_IO01, 0, GPIO_PAD_CTRL #define IOMUX_LED_3 IOMUXC_GPIO1_IO05_GPIO1_IO05, 0, GPIO_PAD_CTRL #define IOMUX_LED_4 IOMUXC_GPIO1_IO06_GPIO1_IO06, 0, GPIO_PAD_CTRL +/* Board buttons */ + +#define BUTTON_1_GPIO (GPIO_INTERRUPT | GPIO_INTBOTH_EDGES | GPIO_PORT1 | GPIO_PIN7) +#define BUTTON_1_IRQ MX8MP_IRQ_SOFT_GPIO1_7 +#define BUTTON_1_IOMUX IOMUXC_GPIO1_IO07_GPIO1_IO07, 0, GPIO_PAD_CTRL + /**************************************************************************** * Public Types ****************************************************************************/