Skip to content

Commit bcf274b

Browse files
committed
drivers: added gpio driver for MSPM0 family
Added GPIO driver support for TI MSPM0 family Signed-off-by: Jackson Farley <[email protected]>
1 parent f8c45ac commit bcf274b

File tree

6 files changed

+345
-0
lines changed

6 files changed

+345
-0
lines changed

drivers/gpio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_MCUX_IGPIO gpio_mcux_igpio.c)
5252
zephyr_library_sources_ifdef(CONFIG_GPIO_MCUX_LPC gpio_mcux_lpc.c)
5353
zephyr_library_sources_ifdef(CONFIG_GPIO_MCUX_RGPIO gpio_mcux_rgpio.c)
5454
zephyr_library_sources_ifdef(CONFIG_GPIO_MMIO32 gpio_mmio32.c)
55+
zephyr_library_sources_ifdef(CONFIG_GPIO_MSPM0 gpio_mspm0.c)
5556
zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX gpio_nct38xx.c)
5657
zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX gpio_nct38xx_port.c)
5758
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
@@ -141,6 +141,7 @@ source "drivers/gpio/Kconfig.mcux_igpio"
141141
source "drivers/gpio/Kconfig.mcux_lpc"
142142
source "drivers/gpio/Kconfig.mcux_rgpio"
143143
source "drivers/gpio/Kconfig.mmio32"
144+
source "drivers/gpio/Kconfig.mspm0"
144145
source "drivers/gpio/Kconfig.nct38xx"
145146
source "drivers/gpio/Kconfig.neorv32"
146147
source "drivers/gpio/Kconfig.npcx"

drivers/gpio/Kconfig.mspm0

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

drivers/gpio/Kconfig.mspm0g3xxx

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

drivers/gpio/gpio_mspm0.c

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