Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 20 additions & 39 deletions drivers/gpio/gpio_mspm0.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
/* Driverlib includes */
#include <ti/driverlib/dl_gpio.h>

#include <soc.h>

/* GPIO defines */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay)
#define GPIOA_NODE DT_NODELABEL(gpioa)
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 = \
{ \
Expand Down
2 changes: 2 additions & 0 deletions dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions dts/bindings/gpio/ti,mspm0-gpio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
100 changes: 100 additions & 0 deletions soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,103 @@

#include <zephyr/init.h>
#include <ti/driverlib/m0p/dl_core.h>
#include <ti/driverlib/m0p/dl_interrupt.h>
#include <soc.h>

#include <zephyr/irq.h>
#include <errno.h>

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 */
Expand All @@ -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;
}

Expand Down
14 changes: 14 additions & 0 deletions soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down