diff --git a/drivers/gpio/gpio_mspm0.c b/drivers/gpio/gpio_mspm0.c index 4cc05da3fc602..b5ddeac979076 100644 --- a/drivers/gpio/gpio_mspm0.c +++ b/drivers/gpio/gpio_mspm0.c @@ -15,6 +15,8 @@ /* Driverlib includes */ #include +#include + /* GPIO defines */ #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) #define GPIOA_NODE DT_NODELABEL(gpioa) @@ -131,6 +133,8 @@ struct gpio_mspm0_config { struct gpio_driver_config common; /* port base address */ GPIO_Regs *base; + /* Interrupt configuration function */ + void (*int_config)(const struct device *); /* port pincm lookup table */ uint32_t *pincm_lut; }; @@ -287,51 +291,21 @@ static uint32_t gpio_mspm0_get_pending_int(const struct device *port) static void gpio_mspm0_isr(const struct device *port) { -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) - const struct device *dev_a = DEVICE_DT_GET(GPIOA_NODE); - struct gpio_mspm0_data *data_a = dev_a->data; - const struct gpio_mspm0_config *config_a = dev_a->config; - - uint32_t status_a = DL_GPIO_getEnabledInterruptStatus(config_a->base, 0xFFFFFFFF); - - DL_GPIO_clearInterruptStatus(config_a->base, status_a); - - gpio_fire_callbacks(&data_a->callbacks, dev_a, status_a); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) - const struct device *dev_b = DEVICE_DT_GET(GPIOB_NODE); - struct gpio_mspm0_data *data_b = dev_b->data; - const struct gpio_mspm0_config *config_b = dev_b->config; - - uint32_t status_b = DL_GPIO_getEnabledInterruptStatus(config_b->base, 0xFFFFFFFF); + struct gpio_mspm0_data *data = port->data; + const struct gpio_mspm0_config *config = port->config; + uint32_t status = DL_GPIO_getEnabledInterruptStatus(config->base, + 0xFFFFFFFF); - DL_GPIO_clearInterruptStatus(config_b->base, status_b); + DL_GPIO_clearInterruptStatus(config->base, status); - gpio_fire_callbacks(&data_b->callbacks, dev_b, status_b); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) */ + if (status != 0) { + gpio_fire_callbacks(&data->callbacks, port, status); + } } -static bool init_irq = true; - static int gpio_mspm0_init(const struct device *port) { - /* Powering up of GPIOs is part of soc.c */ - - if (init_irq) { - - init_irq = false; - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) - IRQ_CONNECT(DT_IRQN(GPIOB_NODE), DT_IRQ(GPIOB_NODE, priority), gpio_mspm0_isr, - DEVICE_DT_GET(GPIOB_NODE), 0); - irq_enable(DT_IRQN(GPIOB_NODE)); -#elif DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) - IRQ_CONNECT(DT_IRQN(GPIOA_NODE), DT_IRQ(GPIOA_NODE, priority), gpio_mspm0_isr, - DEVICE_DT_GET(GPIOA_NODE), 0); - irq_enable(DT_IRQN(GPIOA_NODE)); -#endif - } + cfg->int_config(dev); return 0; } @@ -386,6 +360,13 @@ static const struct gpio_driver_api gpio_mspm0_driver_api = { }; #define GPIO_DEVICE_INIT(__node, __suffix, __base_addr) \ + void gpio_mspm0_int_config_##__suffix(const struct device *dev) \ + { \ + mspm0_register_int_to_group(DT_IRQN(n), \ + DT_PROP(n, ti_int_group_iidx), \ + gpio_mspm0_isr, dev); \ + } \ + \ static const struct gpio_mspm0_config gpio_mspm0_cfg_##__suffix = { \ .common = \ { \ diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi index 92820d17c4b8a..0771bc6da3396 100644 --- a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi @@ -73,6 +73,7 @@ compatible = "ti,mspm0-gpio"; reg = <0x400a0000 0x2000>; interrupts = <1 0>; + ti,int-group-iidx = <1>; status = "disabled"; ngpios = <32>; gpio-controller; @@ -83,6 +84,7 @@ compatible = "ti,mspm0-gpio"; reg = <0x400a2000 0x2000>; interrupts = <1 0>; + ti,int-group-iidx = <2>; status = "disabled"; ngpios = <28>; gpio-controller; diff --git a/dts/bindings/gpio/ti,mspm0-gpio.yaml b/dts/bindings/gpio/ti,mspm0-gpio.yaml index a08a432e4cff5..4cee162473a2c 100644 --- a/dts/bindings/gpio/ti,mspm0-gpio.yaml +++ b/dts/bindings/gpio/ti,mspm0-gpio.yaml @@ -16,6 +16,12 @@ properties: "#gpio-cells": const: 2 + ti,int-group-iidx: + required: true + type: int + enum: [1, 2, 3, 4, 5, 6, 7, 8] + description: Set the interrupt index + gpio-cells: - pin - flags diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c index be97c00770c46..99211c99b4631 100644 --- a/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c @@ -6,8 +6,103 @@ #include #include +#include #include +#include +#include + +struct mspm0_int_grp_iidx { + void (*isr_handler)(const struct device *); + const struct device *dev; +}; + +static struct mspm0_int_grp_iidx mspm0_int_grp0[8] = { 0 }; +static uint32_t mspm0_int_grp0_mask = 0; + +static struct mspm0_int_grp_iidx mspm0_int_grp1[8] = { 0 }; +static uint32_t mspm0_int_grp1_mask = 0; + +static ALWAYS_INLINE void handle_group_isr(int group, uint32_t int_grp_mask, + struct mspm0_int_grp_iidx *int_grp) +{ + uint32_t triggered = DL_Interrupt_getStatusGroup(group, + int_grp_mask) & 0xff; + + DL_Interrupt_clearGroup(group, triggered); + + /* Groups are priority-ordered: the lower the index, + * the higher the priority. + */ + while (triggered) { + if (triggered & 1) { + int_grp->isr_handler(int_grp->dev); + } + + int_grp++; + triggered >>= 1; + } +} + +static void mspm0_int_group_0_isr(const struct device *unused) +{ + ARG_UNUSED(unused); + + handle_group_isr(0, mspm0_int_grp0_mask, mspm0_int_grp0); +} + +static void mspm0_int_group_1_isr(const struct device *unused) +{ + ARG_UNUSED(unused); + + handle_group_isr(1, mspm0_int_grp1_mask, mspm0_int_grp1); +} + +static int register_group_isr(uint8_t int_idx, + uint32_t *int_grp_mask, + struct mspm0_int_grp_iidx int_grp[8], + void (*isr_handler)(const struct device *), + const struct device *dev) +{ + /* IIDX spans from 1 to 8, but it's addressed from 0 to 7 */ + int_idx--; + if (*int_grp_mask & BIT(int_idx)) { + return -EALREADY; + } + + int_grp[int_idx].isr_handler = isr_handler; + int_grp[int_idx].dev = dev; + + *int_grp_mask |= BIT(int_idx); + + return 0; +} + +int mspm0_register_int_to_group(int group, uint8_t int_idx, + void (*isr_handler)(const struct device *), + const struct device *dev) +{ + int ret; + + if (group > 1 || int_idx > 8 || int_idx < 1 || isr_handler == NULL) { + return -EINVAL; + } + + if (group == 0) { + ret = register_group_isr(int_idx, &mspm0_int_grp0_mask, + mspm0_int_grp0, isr_handler, dev); + } else { + ret = register_group_isr(int_idx, &mspm0_int_grp1_mask, + mspm0_int_grp1, isr_handler, dev); + } + + if (ret == 0) { + irq_enable(group); + } + + return ret; +} + static int ti_mspm0g_init(void) { /* Reset and enable GPIO banks */ @@ -23,6 +118,11 @@ static int ti_mspm0g_init(void) /* Low Power Mode is configured to be SLEEP0 */ DL_SYSCTL_setBORThreshold(DL_SYSCTL_BOR_THRESHOLD_LEVEL_0); + /* INT_GRP0 */ + IRQ_CONNECT(0, 0, mspm0_int_group_0_isr, NULL, 0); + /* INT_GRP1 */ + IRQ_CONNECT(1, 0, mspm0_int_group_1_isr, NULL, 0); + return 0; } diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h index 22d79ceada8e3..ee9d0bf2eccce 100644 --- a/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h @@ -21,6 +21,20 @@ extern "C" { #define SOC_MSPM0_HFCLK_FREQ_HZ MHZ(40) #define SOC_MSPM0_SYSPLL_FREQ_HZ MHZ(40) +/** + * @brief Register an isr_handler into an interrupt group + * + * @param group The targeted interrupt group (i.e. the NVIC interrupt). + * @param int_idx The interrupt group index (aka IIDX). + * @param isr_handler Pointer to the ISR function for the device. + * @param dev Pointer to the device that will service the interrupt. + * + * @return 0 on success, a negative errno otherwise. + */ +int mspm0_register_int_to_group(int group, uint8_t int_idx, + void (*isr_handler)(const struct device *), + const struct device *dev); + #ifdef __cplusplus } #endif