From 2220a4b695f2f5ac9fe212de4bcfa5365318136f Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sat, 28 Jan 2017 14:43:35 -0500 Subject: Improve imx31 interrupt code for PMIC and GPIO Fix stuff that was bugging me about the way I did it at first. While messing around I found RDS code wasn't masking its GPIO ISR as it should, which might lead to two different interrupts messing with the static data. Change-Id: I54626809ea3039a842af0cc9e3e42853326c4193 --- firmware/target/arm/imx31/gpio-imx31.h | 209 +++++++++++++++++++++++++++------ 1 file changed, 170 insertions(+), 39 deletions(-) (limited to 'firmware/target/arm/imx31/gpio-imx31.h') diff --git a/firmware/target/arm/imx31/gpio-imx31.h b/firmware/target/arm/imx31/gpio-imx31.h index a1358672e8..86ca964f94 100644 --- a/firmware/target/arm/imx31/gpio-imx31.h +++ b/firmware/target/arm/imx31/gpio-imx31.h @@ -26,62 +26,193 @@ #define USE_GPIO2_EVENTS (1 << 1) #define USE_GPIO3_EVENTS (1 << 2) -/* Module indexes defined by which GPIO modules are used */ +/* Module logical indexes */ enum gpio_module_number { - __GPIO_NUM_START = -1, -#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) - GPIO1_NUM, -#endif -#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) - GPIO2_NUM, -#endif -#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) - GPIO3_NUM, -#endif + GPIO1_NUM, /* ID 0..31 */ + GPIO2_NUM, /* ID 32..63 */ + GPIO3_NUM, /* ID 64..95 */ GPIO_NUM_GPIO, }; -/* Possible values for gpio interrupt line config */ -enum gpio_int_sense_enum +enum gpio_id { - GPIO_SENSE_LOW_LEVEL = 0, /* High-level sensitive */ - GPIO_SENSE_HIGH_LEVEL, /* Low-level sensitive */ - GPIO_SENSE_RISING, /* Rising-edge sensitive */ - GPIO_SENSE_FALLING, /* Falling-edge sensitive */ + /* GPIO1 */ + GPIO1_0_ID = 0, + GPIO1_1_ID, + GPIO1_2_ID, + GPIO1_3_ID, + GPIO1_4_ID, + GPIO1_5_ID, + GPIO1_6_ID, + GPIO1_7_ID, + GPIO1_8_ID, + GPIO1_9_ID, + GPIO1_10_ID, + GPIO1_11_ID, + GPIO1_12_ID, + GPIO1_13_ID, + GPIO1_14_ID, + GPIO1_15_ID, + GPIO1_16_ID, + GPIO1_17_ID, + GPIO1_18_ID, + GPIO1_19_ID, + GPIO1_20_ID, + GPIO1_21_ID, + GPIO1_22_ID, + GPIO1_23_ID, + GPIO1_24_ID, + GPIO1_25_ID, + GPIO1_26_ID, + GPIO1_27_ID, + GPIO1_28_ID, + GPIO1_29_ID, + GPIO1_30_ID, + GPIO1_31_ID, + /* GPIO2 */ + GPIO2_0_ID = 32, + GPIO2_1_ID, + GPIO2_2_ID, + GPIO2_3_ID, + GPIO2_4_ID, + GPIO2_5_ID, + GPIO2_6_ID, + GPIO2_7_ID, + GPIO2_8_ID, + GPIO2_9_ID, + GPIO2_10_ID, + GPIO2_11_ID, + GPIO2_12_ID, + GPIO2_13_ID, + GPIO2_14_ID, + GPIO2_15_ID, + GPIO2_16_ID, + GPIO2_17_ID, + GPIO2_18_ID, + GPIO2_19_ID, + GPIO2_20_ID, + GPIO2_21_ID, + GPIO2_22_ID, + GPIO2_23_ID, + GPIO2_24_ID, + GPIO2_25_ID, + GPIO2_26_ID, + GPIO2_27_ID, + GPIO2_28_ID, + GPIO2_29_ID, + GPIO2_30_ID, + GPIO2_31_ID, + /* GPIO3 */ + GPIO3_0_ID = 64, + GPIO3_1_ID, + GPIO3_2_ID, + GPIO3_3_ID, + GPIO3_4_ID, + GPIO3_5_ID, + GPIO3_6_ID, + GPIO3_7_ID, + GPIO3_8_ID, + GPIO3_9_ID, + GPIO3_10_ID, + GPIO3_11_ID, + GPIO3_12_ID, + GPIO3_13_ID, + GPIO3_14_ID, + GPIO3_15_ID, + GPIO3_16_ID, + GPIO3_17_ID, + GPIO3_18_ID, + GPIO3_19_ID, + GPIO3_20_ID, + GPIO3_21_ID, + GPIO3_22_ID, + GPIO3_23_ID, + GPIO3_24_ID, + GPIO3_25_ID, + GPIO3_26_ID, + GPIO3_27_ID, + GPIO3_28_ID, + GPIO3_29_ID, + GPIO3_30_ID, + GPIO3_31_ID, }; -#define GPIO_SENSE_CONFIG_MASK 0x3 +/* Possible values for gpio interrupt line config */ +enum gpio_int_sense +{ + GPIO_SENSE_LOW_LEVEL, /* High-level sensitive */ + GPIO_SENSE_HIGH_LEVEL, /* Low-level sensitive */ + GPIO_SENSE_RISING, /* Rising-edge sensitive */ + GPIO_SENSE_FALLING, /* Falling-edge sensitive */ + GPIO_SENSE_EDGE_SEL, /* Detect any edge */ +}; -/* Pending events will be called in array order which allows easy - * pioritization */ +/* Handlers will be called in declared order for a given module + Handlers of same module should be grouped together; module order + doesn't matter */ +#ifdef DEFINE_GPIO_VECTOR_TABLE /* Describes a single event for a pin */ struct gpio_event { - unsigned long mask; /* mask: 1 << (0...31) */ - enum gpio_int_sense_enum sense; /* Type of sense */ - void (*callback)(void); /* Callback function */ + uint8_t id; /* GPIOx_y_ID */ + uint8_t sense; /* GPIO_SENSE_x */ + void (*callback)(void); /* GPIOx_y_EVENT_CB */ }; -/* Module corresponding to the event ID is identified by range */ -enum gpio_event_bases -{ -#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) - GPIO1_EVENT_FIRST = 32*GPIO1_NUM, -#endif -#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) - GPIO2_EVENT_FIRST = 32*GPIO2_NUM, -#endif -#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) - GPIO3_EVENT_FIRST = 32*GPIO3_NUM, -#endif -}; +#define GPIO_VECTOR_TBL_START() \ + static FORCE_INLINE uintptr_t __gpio_event_vector_tbl(int __what) \ + { \ + static const struct gpio_event __tbl[] = { + +#define GPIO_EVENT_VECTOR(__name, __sense) \ + { .id = (__name##_ID), \ + .sense = (__sense), \ + .callback = ({ void __name##_EVENT_CB(void); \ + __name##_EVENT_CB; }) }, + +#define GPIO_VECTOR_TBL_END() \ + }; \ + switch (__what) \ + { \ + default: return (uintptr_t)__tbl; \ + case 1: return (uintptr_t)ARRAYLEN(__tbl); \ + } \ + } -#include "gpio-target.h" +#define gpio_event_vector_tbl \ + ((const struct gpio_event *)__gpio_event_vector_tbl(0)) + +#define gpio_event_vector_tbl_len \ + ((unsigned int)__gpio_event_vector_tbl(1)) + +#endif /* DEFINE_GPIO_VECTOR_TABLE */ + +#define GPIO_BASE_ADDR \ + (volatile unsigned long * const [GPIO_NUM_GPIO]) { \ + (volatile unsigned long *)GPIO1_BASE_ADDR, \ + (volatile unsigned long *)GPIO2_BASE_ADDR, \ + (volatile unsigned long *)GPIO3_BASE_ADDR } + +#define GPIO_DR (0x00 / sizeof (unsigned long)) /* 00h */ +#define GPIO_GDIR (0x04 / sizeof (unsigned long)) /* 04h */ +#define GPIO_PSR (0x08 / sizeof (unsigned long)) /* 08h */ +#define GPIO_ICR (0x0C / sizeof (unsigned long)) /* 0Ch ICR1,2 */ +#define GPIO_IMR (0x14 / sizeof (unsigned long)) /* 14h */ +#define GPIO_ISR (0x18 / sizeof (unsigned long)) /* 18h */ +#define GPIO_EDGE_SEL (0x1C / sizeof (unsigned long)) /* 1Ch */ void gpio_init(void); -bool gpio_enable_event(enum gpio_event_ids id); -void gpio_disable_event(enum gpio_event_ids id); +bool gpio_enable_event(enum gpio_id id, bool enable); + +static FORCE_INLINE void gpio_int_clear(enum gpio_id id) + { GPIO_BASE_ADDR[id / 32][GPIO_ISR] = 1ul << (id % 32); } + +static FORCE_INLINE void gpio_int_enable(enum gpio_id id) + { bitset32(&GPIO_BASE_ADDR[id / 32][GPIO_IMR], 1ul << (id % 32)); } + +static FORCE_INLINE void gpio_int_disable(enum gpio_id id) + { bitclr32(&GPIO_BASE_ADDR[id / 32][GPIO_IMR], 1ul << (id % 32)); } #endif /* GPIO_IMX31_H */ -- cgit v1.2.3