Skip to content

Commit 3c67023

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 b1e6204 commit 3c67023

File tree

6 files changed

+358
-0
lines changed

6 files changed

+358
-0
lines changed

drivers/gpio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_AXP192 gpio_axp192.c)
99
zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c)
1010
zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c)
1111
zephyr_library_sources_ifdef(CONFIG_GPIO_CC13XX_CC26XX gpio_cc13xx_cc26xx.c)
12+
zephyr_library_sources_ifdef(CONFIG_GPIO_MSPM0 gpio_mspm0.c)
1213
zephyr_library_sources_ifdef(CONFIG_GPIO_CC32XX gpio_cc32xx.c)
1314
zephyr_library_sources_ifdef(CONFIG_GPIO_CMSDK_AHB gpio_cmsdk_ahb.c)
1415
zephyr_library_sources_ifdef(CONFIG_GPIO_DW gpio_dw.c)

drivers/gpio/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ source "drivers/gpio/Kconfig.cc13xx_cc26xx"
121121

122122
source "drivers/gpio/Kconfig.cc32xx"
123123

124+
source "drivers/gpio/Kconfig.mspm0"
125+
124126
source "drivers/gpio/Kconfig.sifive"
125127

126128
source "drivers/gpio/Kconfig.esp32"

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