1 /*
2 * Copyright (c) 2025 Silicon Laboratories Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/pinctrl.h>
8
9 #include <rail.h>
10
11 #define DT_DRV_COMPAT silabs_pti
12
13 struct silabs_pti_config {
14 const struct pinctrl_dev_config *pcfg;
15 RAIL_PtiMode_t mode;
16 uint32_t baud;
17 };
18
silabs_pti_init(const struct device * dev)19 int silabs_pti_init(const struct device *dev)
20 {
21 const struct silabs_pti_config *config = dev->config;
22 const struct pinctrl_state *state;
23 RAIL_PtiConfig_t pti_config = {
24 .mode = config->mode,
25 .baud = config->baud,
26 };
27 RAIL_Status_t status;
28 int err;
29
30 /* The RAIL API to configure PTI requires GPIO port and pin as part of its configuration
31 * struct, and does the pin configuration itself internally. Create the configuration
32 * struct from the pinctrl node instead of using pinctrl_apply_state().
33 */
34 err = pinctrl_lookup_state(config->pcfg, PINCTRL_STATE_DEFAULT, &state);
35 if (err < 0) {
36 return err;
37 }
38 for (int i = 0; i < state->pin_cnt; i++) {
39 switch (state->pins[i].en_bit) {
40 case _GPIO_FRC_ROUTEEN_DCLKPEN_SHIFT:
41 pti_config.dclkPort = state->pins[i].port;
42 pti_config.dclkPin = state->pins[i].pin;
43 break;
44 case _GPIO_FRC_ROUTEEN_DFRAMEPEN_SHIFT:
45 pti_config.dframePort = state->pins[i].port;
46 pti_config.dframePin = state->pins[i].pin;
47 break;
48 case _GPIO_FRC_ROUTEEN_DOUTPEN_SHIFT:
49 pti_config.doutPort = state->pins[i].port;
50 pti_config.doutPin = state->pins[i].pin;
51 break;
52 default:
53 return -EINVAL;
54 }
55 }
56 status = RAIL_ConfigPti(RAIL_EFR32_HANDLE, &pti_config);
57 if (status != RAIL_STATUS_NO_ERROR) {
58 return -EIO;
59 }
60
61 return 0;
62 }
63
64 #define SILABS_PTI_INIT(idx) \
65 PINCTRL_DT_INST_DEFINE(idx); \
66 \
67 static const struct silabs_pti_config silabs_pti_config_##idx = { \
68 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
69 .mode = DT_INST_ENUM_IDX(idx, mode), \
70 .baud = DT_INST_PROP(idx, clock_frequency), \
71 }; \
72 \
73 DEVICE_DT_INST_DEFINE(idx, &silabs_pti_init, NULL, NULL, &silabs_pti_config_##idx, \
74 POST_KERNEL, CONFIG_DEBUG_DRIVER_INIT_PRIORITY, NULL);
75
76 DT_INST_FOREACH_STATUS_OKAY(SILABS_PTI_INIT)
77