Skip to content

Commit dee5a06

Browse files
ssekar15kartben
authored andcommitted
drivers: gpio: mspm0: Add a gpio support for MSPM0 family
Add a GPIO driver support for TI MSPM0 SoC family. Signed-off-by: Saravanan Sekar <[email protected]> Signed-off-by: Jackson Farley <[email protected]>
1 parent 258cc7e commit dee5a06

File tree

5 files changed

+350
-0
lines changed

5 files changed

+350
-0
lines changed

drivers/gpio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_MCUX_LPC gpio_mcux_lpc.c)
6161
zephyr_library_sources_ifdef(CONFIG_GPIO_MCUX_RGPIO gpio_mcux_rgpio.c)
6262
zephyr_library_sources_ifdef(CONFIG_GPIO_MFXSTM32L152 gpio_mfxstm32l152.c)
6363
zephyr_library_sources_ifdef(CONFIG_GPIO_MMIO32 gpio_mmio32.c)
64+
zephyr_library_sources_ifdef(CONFIG_GPIO_MSPM0 gpio_mspm0.c)
6465
zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX gpio_nct38xx.c)
6566
zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX gpio_nct38xx_port.c)
6667
zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX_ALERT gpio_nct38xx_alert.c)

drivers/gpio/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ source "drivers/gpio/Kconfig.mcux_rgpio"
149149
source "drivers/gpio/Kconfig.mec5"
150150
source "drivers/gpio/Kconfig.mfxstm32l152"
151151
source "drivers/gpio/Kconfig.mmio32"
152+
source "drivers/gpio/Kconfig.mspm0"
152153
source "drivers/gpio/Kconfig.nct38xx"
153154
source "drivers/gpio/Kconfig.neorv32"
154155
source "drivers/gpio/Kconfig.npcx"

drivers/gpio/Kconfig.mspm0

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# TI MSPM0 GPIO configuration options
2+
3+
# Copyright (c) 2025 Texas Instruments
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
config GPIO_MSPM0
7+
bool "TI MSPM0 GPIO driver"
8+
default y
9+
depends on DT_HAS_TI_MSPM0_GPIO_ENABLED
10+
select USE_MSPM0_DL_GPIO
11+
help
12+
Enable the TI MSPM0 GPIO driver.

drivers/gpio/gpio_mspm0.c

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
/*
2+
* Copyright (c) 2025 Texas Instruments
3+
* Copyright (c) 2025 Linumiz
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#define DT_DRV_COMPAT ti_mspm0_gpio
9+
10+
/* Zephyr includes */
11+
#include <zephyr/drivers/gpio.h>
12+
#include <zephyr/drivers/gpio/gpio_utils.h>
13+
#include <zephyr/irq.h>
14+
15+
/* Driverlib includes */
16+
#include <ti/driverlib/dl_gpio.h>
17+
18+
struct gpio_mspm0_config {
19+
/* gpio_mspm0_config needs to be first (doesn't actually get used) */
20+
struct gpio_driver_config common;
21+
/* port base address */
22+
GPIO_Regs *base;
23+
/* port pincm lookup table */
24+
uint32_t *pincm_lut;
25+
};
26+
27+
struct gpio_mspm0_data {
28+
/* gpio_driver_data needs to be first */
29+
struct gpio_driver_data common;
30+
sys_slist_t callbacks; /* List of interrupt callbacks */
31+
};
32+
33+
/* Two polarity registers and HAL api used for pins (0-15) and pins (16-32) */
34+
#define MSPM0_PINS_LOW_GROUP 16
35+
36+
/* GPIO defines */
37+
#define GPIOA_NODE DT_NODELABEL(gpioa)
38+
#if DT_NODE_HAS_STATUS(GPIOA_NODE, okay)
39+
#if CONFIG_SOC_SERIES_MSPM0G
40+
#define NUM_GPIOA_PIN 32
41+
#define gpioa_pins NUM_GPIOA_PIN
42+
static uint32_t gpioa_pincm_lut[NUM_GPIOA_PIN] = {
43+
IOMUX_PINCM1, IOMUX_PINCM2, IOMUX_PINCM7, IOMUX_PINCM8, IOMUX_PINCM9, IOMUX_PINCM10,
44+
IOMUX_PINCM11, IOMUX_PINCM14, IOMUX_PINCM19, IOMUX_PINCM20, IOMUX_PINCM21, IOMUX_PINCM22,
45+
IOMUX_PINCM34, IOMUX_PINCM35, IOMUX_PINCM36, IOMUX_PINCM37, IOMUX_PINCM38, IOMUX_PINCM39,
46+
IOMUX_PINCM40, IOMUX_PINCM41, IOMUX_PINCM42, IOMUX_PINCM46, IOMUX_PINCM47, IOMUX_PINCM53,
47+
IOMUX_PINCM54, IOMUX_PINCM55, IOMUX_PINCM59, IOMUX_PINCM60, IOMUX_PINCM3, IOMUX_PINCM4,
48+
IOMUX_PINCM5, IOMUX_PINCM6,
49+
};
50+
#else
51+
#error "Series lookup table not supported"
52+
#endif /* if CONFIG_SOC_SERIES_MSPM0G */
53+
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) */
54+
55+
#define GPIOB_NODE DT_NODELABEL(gpiob)
56+
#if DT_NODE_HAS_STATUS(GPIOB_NODE, okay)
57+
#ifdef CONFIG_SOC_SERIES_MSPM0G
58+
#define NUM_GPIOB_PIN 28
59+
#define gpiob_pins NUM_GPIOB_PIN
60+
static uint32_t gpiob_pincm_lut[NUM_GPIOB_PIN] = {
61+
IOMUX_PINCM12, IOMUX_PINCM13, IOMUX_PINCM15, IOMUX_PINCM16, IOMUX_PINCM17, IOMUX_PINCM18,
62+
IOMUX_PINCM23, IOMUX_PINCM24, IOMUX_PINCM25, IOMUX_PINCM26, IOMUX_PINCM27, IOMUX_PINCM28,
63+
IOMUX_PINCM29, IOMUX_PINCM30, IOMUX_PINCM31, IOMUX_PINCM32, IOMUX_PINCM33, IOMUX_PINCM43,
64+
IOMUX_PINCM44, IOMUX_PINCM45, IOMUX_PINCM48, IOMUX_PINCM49, IOMUX_PINCM50, IOMUX_PINCM51,
65+
IOMUX_PINCM52, IOMUX_PINCM56, IOMUX_PINCM57, IOMUX_PINCM58,
66+
};
67+
#endif /* CONFIG_SOC_SERIES_MSPM0G */
68+
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) */
69+
70+
static int gpio_mspm0_port_get_raw(const struct device *port, uint32_t *value)
71+
{
72+
const struct gpio_mspm0_config *config = port->config;
73+
74+
/* Read entire port */
75+
*value = DL_GPIO_readPins(config->base, UINT32_MAX);
76+
77+
return 0;
78+
}
79+
80+
static int gpio_mspm0_port_set_masked_raw(const struct device *port,
81+
uint32_t mask, uint32_t value)
82+
{
83+
const struct gpio_mspm0_config *config = port->config;
84+
85+
DL_GPIO_writePinsVal(config->base, mask, value);
86+
87+
return 0;
88+
}
89+
90+
static int gpio_mspm0_port_set_bits_raw(const struct device *port,
91+
uint32_t mask)
92+
{
93+
const struct gpio_mspm0_config *config = port->config;
94+
95+
DL_GPIO_setPins(config->base, mask);
96+
97+
return 0;
98+
}
99+
100+
static int gpio_mspm0_port_clear_bits_raw(const struct device *port,
101+
uint32_t mask)
102+
{
103+
const struct gpio_mspm0_config *config = port->config;
104+
105+
DL_GPIO_clearPins(config->base, mask);
106+
107+
return 0;
108+
}
109+
110+
static int gpio_mspm0_port_toggle_bits(const struct device *port,
111+
uint32_t mask)
112+
{
113+
const struct gpio_mspm0_config *config = port->config;
114+
115+
DL_GPIO_togglePins(config->base, mask);
116+
117+
return 0;
118+
}
119+
120+
static int gpio_mspm0_pin_configure(const struct device *port,
121+
gpio_pin_t pin,
122+
gpio_flags_t flags)
123+
{
124+
const struct gpio_mspm0_config *config = port->config;
125+
/* determine pull up resistor value based on flags */
126+
DL_GPIO_RESISTOR pull_res;
127+
128+
if (flags & GPIO_PULL_UP) {
129+
pull_res = DL_GPIO_RESISTOR_PULL_UP;
130+
} else if (flags & GPIO_PULL_DOWN) {
131+
pull_res = DL_GPIO_RESISTOR_PULL_DOWN;
132+
} else {
133+
pull_res = DL_GPIO_RESISTOR_NONE;
134+
}
135+
136+
/* Config pin based on flags */
137+
switch (flags & (GPIO_INPUT | GPIO_OUTPUT)) {
138+
case GPIO_INPUT:
139+
DL_GPIO_initDigitalInputFeatures(config->pincm_lut[pin],
140+
DL_GPIO_INVERSION_DISABLE,
141+
pull_res,
142+
DL_GPIO_HYSTERESIS_DISABLE,
143+
DL_GPIO_WAKEUP_DISABLE);
144+
break;
145+
case GPIO_OUTPUT:
146+
DL_GPIO_initDigitalOutputFeatures(config->pincm_lut[pin],
147+
DL_GPIO_INVERSION_DISABLE,
148+
pull_res,
149+
DL_GPIO_DRIVE_STRENGTH_LOW,
150+
DL_GPIO_HIZ_DISABLE);
151+
152+
/* Set initial state */
153+
if (flags & GPIO_OUTPUT_INIT_HIGH) {
154+
gpio_mspm0_port_set_bits_raw(port, BIT(pin));
155+
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
156+
gpio_mspm0_port_clear_bits_raw(port, BIT(pin));
157+
}
158+
/* Enable output */
159+
DL_GPIO_enableOutput(config->base, BIT(pin));
160+
break;
161+
case GPIO_DISCONNECTED:
162+
DL_GPIO_disableOutput(config->base, BIT(pin));
163+
break;
164+
default:
165+
return -ENOTSUP;
166+
}
167+
168+
return 0;
169+
}
170+
171+
static int gpio_mspm0_pin_interrupt_configure(const struct device *port,
172+
gpio_pin_t pin,
173+
enum gpio_int_mode mode,
174+
enum gpio_int_trig trig)
175+
{
176+
const struct gpio_mspm0_config *config = port->config;
177+
178+
/* Config interrupt */
179+
switch (mode) {
180+
case GPIO_INT_MODE_DISABLED:
181+
DL_GPIO_clearInterruptStatus(config->base, BIT(pin));
182+
DL_GPIO_disableInterrupt(config->base, BIT(pin));
183+
break;
184+
case GPIO_INT_MODE_EDGE:
185+
uint32_t polarity = 0x00;
186+
187+
if (trig & GPIO_INT_TRIG_LOW) {
188+
polarity |= BIT(0);
189+
}
190+
191+
if (trig & GPIO_INT_TRIG_HIGH) {
192+
polarity |= BIT(1);
193+
}
194+
195+
if (pin < MSPM0_PINS_LOW_GROUP) {
196+
DL_GPIO_setLowerPinsPolarity(config->base,
197+
polarity << (2 * pin));
198+
} else {
199+
DL_GPIO_setUpperPinsPolarity(config->base,
200+
polarity << (2 * (pin - MSPM0_PINS_LOW_GROUP)));
201+
}
202+
203+
DL_GPIO_clearInterruptStatus(config->base, BIT(pin));
204+
DL_GPIO_enableInterrupt(config->base, BIT(pin));
205+
break;
206+
case GPIO_INT_MODE_LEVEL:
207+
return -ENOTSUP;
208+
}
209+
210+
return 0;
211+
}
212+
213+
static int gpio_mspm0_manage_callback(const struct device *port,
214+
struct gpio_callback *callback,
215+
bool set)
216+
{
217+
struct gpio_mspm0_data *data = port->data;
218+
219+
return gpio_manage_callback(&data->callbacks, callback, set);
220+
}
221+
222+
static uint32_t gpio_mspm0_get_pending_int(const struct device *port)
223+
{
224+
const struct gpio_mspm0_config *config = port->config;
225+
226+
return DL_GPIO_getPendingInterrupt(config->base);
227+
}
228+
229+
static void gpio_mspm0_isr(const struct device *port)
230+
{
231+
struct gpio_mspm0_data *data;
232+
const struct gpio_mspm0_config *config;
233+
const struct device *dev_list[] = {
234+
DEVICE_DT_GET_OR_NULL(GPIOA_NODE),
235+
DEVICE_DT_GET_OR_NULL(GPIOB_NODE),
236+
};
237+
238+
for (uint8_t i = 0; i < ARRAY_SIZE(dev_list); i++) {
239+
uint32_t status;
240+
241+
if (dev_list[i] == NULL) {
242+
continue;
243+
}
244+
245+
data = dev_list[i]->data;
246+
config = dev_list[i]->config;
247+
248+
status = DL_GPIO_getRawInterruptStatus(config->base,
249+
0xFFFFFFFF);
250+
251+
DL_GPIO_clearInterruptStatus(config->base, status);
252+
if (status != 0) {
253+
gpio_fire_callbacks(&data->callbacks,
254+
dev_list[i], status);
255+
}
256+
}
257+
}
258+
259+
static int gpio_mspm0_init(const struct device *dev)
260+
{
261+
const struct gpio_mspm0_config *cfg = dev->config;
262+
static bool init_irq = true;
263+
264+
/* Reset and enable GPIO banks */
265+
DL_GPIO_reset(cfg->base);
266+
DL_GPIO_enablePower(cfg->base);
267+
268+
/* All the interrupt port share the same irq number, do it once */
269+
if (init_irq) {
270+
init_irq = false;
271+
272+
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
273+
gpio_mspm0_isr, DEVICE_DT_INST_GET(0), 0);
274+
irq_enable(DT_INST_IRQN(0));
275+
}
276+
277+
return 0;
278+
}
279+
280+
static const struct gpio_driver_api gpio_mspm0_driver_api = {
281+
.pin_configure = gpio_mspm0_pin_configure,
282+
.port_get_raw = gpio_mspm0_port_get_raw,
283+
.port_set_masked_raw = gpio_mspm0_port_set_masked_raw,
284+
.port_set_bits_raw = gpio_mspm0_port_set_bits_raw,
285+
.port_clear_bits_raw = gpio_mspm0_port_clear_bits_raw,
286+
.port_toggle_bits = gpio_mspm0_port_toggle_bits,
287+
.pin_interrupt_configure = gpio_mspm0_pin_interrupt_configure,
288+
.manage_callback = gpio_mspm0_manage_callback,
289+
.get_pending_int = gpio_mspm0_get_pending_int,
290+
};
291+
292+
#define GPIO_DEVICE_INIT(n, __suffix, __base_addr) \
293+
static const struct gpio_mspm0_config gpio_mspm0_cfg_##__suffix = { \
294+
.common = { .port_pin_mask = \
295+
GPIO_PORT_PIN_MASK_FROM_NGPIOS(gpio##__suffix##_pins), \
296+
}, \
297+
.base = (GPIO_Regs *)__base_addr, \
298+
.pincm_lut = gpio##__suffix##_pincm_lut, \
299+
}; \
300+
static struct gpio_mspm0_data gpio_mspm0_data_##__suffix; \
301+
DEVICE_DT_DEFINE(n, gpio_mspm0_init, NULL, &gpio_mspm0_data_##__suffix, \
302+
&gpio_mspm0_cfg_##__suffix, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \
303+
&gpio_mspm0_driver_api)
304+
305+
#define GPIO_DEVICE_INIT_MSPM0(__suffix) \
306+
GPIO_DEVICE_INIT(DT_NODELABEL(gpio##__suffix), __suffix, \
307+
DT_REG_ADDR(DT_NODELABEL(gpio##__suffix)))
308+
309+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay)
310+
GPIO_DEVICE_INIT_MSPM0(a);
311+
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) */
312+
313+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay)
314+
GPIO_DEVICE_INIT_MSPM0(b);
315+
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) */

dts/bindings/gpio/ti,mspm0-gpio.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
description: TI MSPM0 GPIO
4+
5+
compatible: "ti,mspm0-gpio"
6+
7+
include: [gpio-controller.yaml, base.yaml]
8+
9+
properties:
10+
reg:
11+
required: true
12+
13+
interrupts:
14+
required: true
15+
16+
"#gpio-cells":
17+
const: 2
18+
19+
gpio-cells:
20+
- pin
21+
- flags

0 commit comments

Comments
 (0)