diff options
Diffstat (limited to 'zephyr/shim')
-rw-r--r-- | zephyr/shim/src/gpio.c | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/zephyr/shim/src/gpio.c b/zephyr/shim/src/gpio.c index 01faf87fda..2bae272361 100644 --- a/zephyr/shim/src/gpio.c +++ b/zephyr/shim/src/gpio.c @@ -60,12 +60,10 @@ static struct gpio_data data[] = { #endif }; -/* Maps platform/ec gpio callbacks to zephyr gpio callbacks */ +/* Maps platform/ec gpio callback information */ struct gpio_signal_callback { /* The platform/ec gpio_signal */ const enum gpio_signal signal; - /* Zephyr callback */ - struct gpio_callback callback; /* IRQ handler from platform/ec code */ void (*const irq_handler)(enum gpio_signal signal); /* Interrupt-related gpio flags */ @@ -104,31 +102,59 @@ EC_CROS_GPIO_INTERRUPTS #endif #undef GPIO_INT +/* + * Create unique enum values for each GPIO_INT entry, which also sets + * the ZEPHYR_GPIO_INT_COUNT value. + */ +#define ZEPHYR_GPIO_INT_ID(sig) INT_##sig +#define GPIO_INT(sig, f, cb) ZEPHYR_GPIO_INT_ID(sig), +enum zephyr_gpio_int_id { +#ifdef EC_CROS_GPIO_INTERRUPTS + EC_CROS_GPIO_INTERRUPTS +#endif + ZEPHYR_GPIO_INT_COUNT, +}; +#undef GPIO_INT + +/* Create prototypes for each GPIO IRQ handler */ #define GPIO_INT(sig, f, cb) void cb(enum gpio_signal signal); #ifdef EC_CROS_GPIO_INTERRUPTS EC_CROS_GPIO_INTERRUPTS #endif #undef GPIO_INT +/* + * The Zephyr gpio_callback data needs to be updated at runtime, so allocate + * into uninitialized data (BSS). The constant data pulled from + * EC_CROS_GPIO_INTERRUPTS is stored separately in the gpio_interrupts[] array. + */ +static struct gpio_callback zephyr_gpio_callbacks[ZEPHYR_GPIO_INT_COUNT]; + +#define ZEPHYR_GPIO_CALLBACK_TO_INDEX(cb) \ + (int)(((int)(cb) - (int)&zephyr_gpio_callbacks) / \ + sizeof(struct gpio_callback)) + #define GPIO_INT(sig, f, cb) \ { \ .signal = sig, \ .flags = f, \ .irq_handler = cb, \ }, -struct gpio_signal_callback gpio_interrupts[] = { +const static struct gpio_signal_callback + gpio_interrupts[ZEPHYR_GPIO_INT_COUNT] = { #ifdef EC_CROS_GPIO_INTERRUPTS - EC_CROS_GPIO_INTERRUPTS + EC_CROS_GPIO_INTERRUPTS #endif #undef GPIO_INT -}; + }; /* The single zephyr gpio handler that routes to appropriate platform/ec cb */ static void gpio_handler_shim(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins) { + int callback_index = ZEPHYR_GPIO_CALLBACK_TO_INDEX(cb); const struct gpio_signal_callback *const gpio = - CONTAINER_OF(cb, struct gpio_signal_callback, callback); + &gpio_interrupts[callback_index]; /* Call the platform/ec gpio interrupt handler */ gpio->irq_handler(gpio->signal); @@ -143,7 +169,7 @@ static void gpio_handler_shim(const struct device *port, * Return: A pointer to the corresponding entry in gpio_interrupts, or * NULL if one does not exist. */ -static struct gpio_signal_callback * +const static struct gpio_signal_callback * get_interrupt_from_signal(enum gpio_signal signal) { if (!gpio_is_implemented(signal)) @@ -320,10 +346,10 @@ static int init_gpios(const struct device *unused) if (signal == GPIO_UNIMPLEMENTED) continue; - gpio_init_callback(&gpio_interrupts[i].callback, - gpio_handler_shim, BIT(configs[signal].pin)); + gpio_init_callback(&zephyr_gpio_callbacks[i], gpio_handler_shim, + BIT(configs[signal].pin)); rv = gpio_add_callback(data[signal].dev, - &gpio_interrupts[i].callback); + &zephyr_gpio_callbacks[i]); if (rv < 0) { LOG_ERR("Callback reg failed %s (%d)", @@ -352,7 +378,7 @@ SYS_INIT(init_gpios, POST_KERNEL, CONFIG_PLATFORM_EC_GPIO_INIT_PRIORITY); int gpio_enable_interrupt(enum gpio_signal signal) { int rv; - struct gpio_signal_callback *interrupt; + const struct gpio_signal_callback *interrupt; interrupt = get_interrupt_from_signal(signal); |