diff --git a/boards/arm/efr32_slwstk6061a/efr32_slwstk6061a.dts b/boards/arm/efr32_slwstk6061a/efr32_slwstk6061a.dts index 121383c3a88..78e3d25e904 100644 --- a/boards/arm/efr32_slwstk6061a/efr32_slwstk6061a.dts +++ b/boards/arm/efr32_slwstk6061a/efr32_slwstk6061a.dts @@ -60,6 +60,11 @@ status = "ok"; }; +&gpio { + location-swo = <0>; + status = "ok"; +}; + &flash0 { /* * If the chosen node has no zephyr,code-partition property, the diff --git a/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.dts b/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.dts index 4752bd99e21..ca7c0460c42 100644 --- a/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.dts +++ b/boards/arm/efr32mg_sltb004a/efr32mg_sltb004a.dts @@ -73,3 +73,8 @@ location = <17>; status = "ok"; }; + +&gpio { + location-swo = <0>; + status = "ok"; +}; diff --git a/drivers/gpio/gpio_gecko.c b/drivers/gpio/gpio_gecko.c index 473979c91f4..4ec1e44b17e 100644 --- a/drivers/gpio/gpio_gecko.c +++ b/drivers/gpio/gpio_gecko.c @@ -285,6 +285,24 @@ DEVICE_AND_API_INIT(gpio_gecko_common, DT_GPIO_GECKO_COMMON_NAME, static int gpio_gecko_common_init(struct device *dev) { + /* Serial Wire Output (SWO) pin is controlled by GPIO module, configure + * if enabled. + */ +#if defined(DT_GPIO_GECKO_SWO_LOCATION) + struct soc_gpio_pin pin_swo = PIN_SWO; + +#if defined(_GPIO_ROUTEPEN_MASK) + /* Enable Serial wire output pin */ + GPIO->ROUTEPEN |= GPIO_ROUTEPEN_SWVPEN; + /* Set SWO location */ + GPIO->ROUTELOC0 = + DT_GPIO_GECKO_SWO_LOCATION << _GPIO_ROUTELOC0_SWVLOC_SHIFT; +#else + GPIO->ROUTE = GPIO_ROUTE_SWOPEN | (DT_GPIO_GECKO_SWO_LOCATION << 8); +#endif + soc_gpio_configure(&pin_swo); +#endif /* defined(DT_GPIO_GECKO_SWO_LOCATION) */ + gpio_gecko_common_data.count = 0; IRQ_CONNECT(GPIO_EVEN_IRQn, DT_GPIO_GECKO_COMMON_EVEN_PRI, gpio_gecko_common_isr, DEVICE_GET(gpio_gecko_common), 0); diff --git a/dts/arm/silabs/efr32fg1p.dtsi b/dts/arm/silabs/efr32fg1p.dtsi index 9810243c94e..9eecb8d31d6 100644 --- a/dts/arm/silabs/efr32fg1p.dtsi +++ b/dts/arm/silabs/efr32fg1p.dtsi @@ -57,7 +57,7 @@ label = "USART_1"; }; - gpio@4000a400 { + gpio: gpio@4000a400 { compatible = "silabs,efr32xg1-gpio"; reg = <0x4000a400 0xc00>; interrupts = <9 2 17 2>; diff --git a/dts/arm/silabs/efr32mg.dtsi b/dts/arm/silabs/efr32mg.dtsi index ad96aef9e5a..a5c8c02ed08 100644 --- a/dts/arm/silabs/efr32mg.dtsi +++ b/dts/arm/silabs/efr32mg.dtsi @@ -111,7 +111,7 @@ status = "disabled"; }; - gpio@4000a400 { + gpio: gpio@4000a400 { compatible = "silabs,efr32mg-gpio"; reg = <0x4000a400 0xc00>; interrupts = <9 2 17 2>; diff --git a/dts/bindings/gpio/silabs,efr32mg12-gpio.yaml b/dts/bindings/gpio/silabs,efr32mg12-gpio.yaml index feef52d069a..f9e2f7690b7 100644 --- a/dts/bindings/gpio/silabs,efr32mg12-gpio.yaml +++ b/dts/bindings/gpio/silabs,efr32mg12-gpio.yaml @@ -31,4 +31,9 @@ properties: description: Human readable string describing the device (used by Zephyr for API name) generation: define + location-swo: + type: int + category: optional + description: Serial Wire Output (SWO) PIN location + generation: define ... diff --git a/dts/bindings/gpio/silabs,efr32xg1-gpio.yaml b/dts/bindings/gpio/silabs,efr32xg1-gpio.yaml index bdf9c04c40f..246a338a653 100644 --- a/dts/bindings/gpio/silabs,efr32xg1-gpio.yaml +++ b/dts/bindings/gpio/silabs,efr32xg1-gpio.yaml @@ -31,4 +31,9 @@ properties: description: Human readable string describing the device (used by Zephyr for API name) generation: define + location-swo: + type: int + category: optional + description: Serial Wire Output (SWO) PIN location + generation: define ... diff --git a/soc/arm/silabs_exx32/common/soc.c b/soc/arm/silabs_exx32/common/soc.c index 0ac6165c9dd..b3f7f1c22d0 100644 --- a/soc/arm/silabs_exx32/common/soc.c +++ b/soc/arm/silabs_exx32/common/soc.c @@ -66,6 +66,11 @@ static ALWAYS_INLINE void clkInit(void) /* Enable the High Frequency Peripheral Clock */ CMU_ClockEnable(cmuClock_HFPER, true); +#ifdef CONFIG_LOG_BACKEND_SWO + /* Select HFCLK as the debug trace clock */ + CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_HFCLK; +#endif + #ifdef CONFIG_GPIO_GECKO CMU_ClockEnable(cmuClock_GPIO, true); #endif diff --git a/soc/arm/silabs_exx32/efr32fg1p/Kconfig.defconfig.efr32fg1p b/soc/arm/silabs_exx32/efr32fg1p/Kconfig.defconfig.efr32fg1p index 41630e7523e..657c4be789a 100644 --- a/soc/arm/silabs_exx32/efr32fg1p/Kconfig.defconfig.efr32fg1p +++ b/soc/arm/silabs_exx32/efr32fg1p/Kconfig.defconfig.efr32fg1p @@ -8,12 +8,12 @@ if SOC_SERIES_EFR32FG1P -if GPIO +if GPIO || LOG_BACKEND_SWO config GPIO_GECKO default y -endif # GPIO +endif # GPIO || LOG_BACKEND_SWO if SERIAL diff --git a/soc/arm/silabs_exx32/efr32fg1p/Kconfig.series b/soc/arm/silabs_exx32/efr32fg1p/Kconfig.series index 0d6068d862e..2d36c347a00 100644 --- a/soc/arm/silabs_exx32/efr32fg1p/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32fg1p/Kconfig.series @@ -8,6 +8,7 @@ config SOC_SERIES_EFR32FG1P bool "EFR32FG1P Series MCU" select HAS_SILABS_GECKO + select HAS_SWO select CPU_CORTEX_M4 select CPU_HAS_FPU select SOC_FAMILY_EXX32 diff --git a/soc/arm/silabs_exx32/efr32fg1p/dts_fixup.h b/soc/arm/silabs_exx32/efr32fg1p/dts_fixup.h index 9f24a15667d..19fc24a7765 100644 --- a/soc/arm/silabs_exx32/efr32fg1p/dts_fixup.h +++ b/soc/arm/silabs_exx32/efr32fg1p/dts_fixup.h @@ -16,6 +16,7 @@ #define DT_GPIO_GECKO_COMMON_EVEN_PRI DT_SILABS_EFR32XG1_GPIO_4000A400_IRQ_GPIO_EVEN_PRIORITY #define DT_GPIO_GECKO_COMMON_ODD_IRQ DT_SILABS_EFR32XG1_GPIO_4000A400_IRQ_GPIO_ODD #define DT_GPIO_GECKO_COMMON_ODD_PRI DT_SILABS_EFR32XG1_GPIO_4000A400_IRQ_GPIO_ODD_PRIORITY +#define DT_GPIO_GECKO_SWO_LOCATION DT_SILABS_EFR32XG1_GPIO_4000A400_LOCATION_SWO #define DT_GPIO_GECKO_PORTA_NAME DT_SILABS_EFR32XG1_GPIO_PORT_4000A000_LABEL #define DT_GPIO_GECKO_PORTB_NAME DT_SILABS_EFR32XG1_GPIO_PORT_4000A030_LABEL diff --git a/soc/arm/silabs_exx32/efr32fg1p/soc_pinmap.h b/soc/arm/silabs_exx32/efr32fg1p/soc_pinmap.h index b2cca5b90af..eec98a064df 100644 --- a/soc/arm/silabs_exx32/efr32fg1p/soc_pinmap.h +++ b/soc/arm/silabs_exx32/efr32fg1p/soc_pinmap.h @@ -16,6 +16,21 @@ #include #include +#ifdef CONFIG_GPIO_GECKO +/* Serial Wire Output (SWO) */ +#if (DT_GPIO_GECKO_SWO_LOCATION == 0) +#define PIN_SWO {gpioPortF, 2, gpioModePushPull, 1} +#elif (DT_GPIO_GECKO_SWO_LOCATION == 1) +#define PIN_SWO {gpioPortB, 13, gpioModePushPull, 1} +#elif (DT_GPIO_GECKO_SWO_LOCATION == 2) +#define PIN_SWO {gpioPortD, 15, gpioModePushPull, 1} +#elif (DT_GPIO_GECKO_SWO_LOCATION == 3) +#define PIN_SWO {gpioPortC, 11, gpioModePushPull, 1} +#elif (DT_GPIO_GECKO_SWO_LOCATION >= 4) +#error ("Invalid SWO pin location") +#endif +#endif /* CONFIG_GPIO_GECKO */ + #ifdef CONFIG_USART_GECKO_0 #if (DT_SILABS_GECKO_USART_USART_0_LOCATION == 0) #define PIN_USART0_TXD {gpioPortA, 0, gpioModePushPull, 1} diff --git a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.defconfig.efr32mg12p b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.defconfig.efr32mg12p index aa1cc1dfc95..549960e815e 100644 --- a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.defconfig.efr32mg12p +++ b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.defconfig.efr32mg12p @@ -8,12 +8,12 @@ if SOC_SERIES_EFR32MG12P -if GPIO +if GPIO || LOG_BACKEND_SWO config GPIO_GECKO default y -endif # GPIO +endif # GPIO || LOG_BACKEND_SWO if SERIAL diff --git a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.series b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.series index d6256a6b797..877ebfa52a5 100644 --- a/soc/arm/silabs_exx32/efr32mg12p/Kconfig.series +++ b/soc/arm/silabs_exx32/efr32mg12p/Kconfig.series @@ -13,6 +13,7 @@ config SOC_SERIES_EFR32MG12P select SYS_POWER_LOW_POWER_STATE_SUPPORTED select CPU_HAS_SYSTICK select HAS_SILABS_GECKO + select HAS_SWO select SOC_GECKO_CMU select SOC_GECKO_EMU select SOC_GECKO_GPIO diff --git a/soc/arm/silabs_exx32/efr32mg12p/dts_fixup.h b/soc/arm/silabs_exx32/efr32mg12p/dts_fixup.h index 26f2c55adda..728853bc699 100644 --- a/soc/arm/silabs_exx32/efr32mg12p/dts_fixup.h +++ b/soc/arm/silabs_exx32/efr32mg12p/dts_fixup.h @@ -16,6 +16,7 @@ #define DT_GPIO_GECKO_COMMON_EVEN_PRI DT_SILABS_EFR32MG_GPIO_4000A400_IRQ_GPIO_EVEN_PRIORITY #define DT_GPIO_GECKO_COMMON_ODD_IRQ DT_SILABS_EFR32MG_GPIO_4000A400_IRQ_GPIO_ODD #define DT_GPIO_GECKO_COMMON_ODD_PRI DT_SILABS_EFR32MG_GPIO_4000A400_IRQ_GPIO_ODD_PRIORITY +#define DT_GPIO_GECKO_SWO_LOCATION DT_SILABS_EFR32MG_GPIO_4000A400_LOCATION_SWO #define DT_GPIO_GECKO_PORTA_NAME DT_SILABS_EFR32MG_GPIO_PORT_4000A000_LABEL #define DT_GPIO_GECKO_PORTB_NAME DT_SILABS_EFR32MG_GPIO_PORT_4000A030_LABEL diff --git a/soc/arm/silabs_exx32/efr32mg12p/soc_pinmap.h b/soc/arm/silabs_exx32/efr32mg12p/soc_pinmap.h index 75d5abb6155..5b5af41a849 100644 --- a/soc/arm/silabs_exx32/efr32mg12p/soc_pinmap.h +++ b/soc/arm/silabs_exx32/efr32mg12p/soc_pinmap.h @@ -15,6 +15,21 @@ #include +#ifdef CONFIG_GPIO_GECKO +/* Serial Wire Output (SWO) */ +#if (DT_GPIO_GECKO_SWO_LOCATION == 0) +#define PIN_SWO {gpioPortF, 2, gpioModePushPull, 1} +#elif (DT_GPIO_GECKO_SWO_LOCATION == 1) +#define PIN_SWO {gpioPortB, 13, gpioModePushPull, 1} +#elif (DT_GPIO_GECKO_SWO_LOCATION == 2) +#define PIN_SWO {gpioPortD, 15, gpioModePushPull, 1} +#elif (DT_GPIO_GECKO_SWO_LOCATION == 3) +#define PIN_SWO {gpioPortC, 11, gpioModePushPull, 1} +#elif (DT_GPIO_GECKO_SWO_LOCATION >= 4) +#error ("Invalid SWO pin location") +#endif +#endif /* CONFIG_GPIO_GECKO */ + #ifdef CONFIG_UART_GECKO #ifdef CONFIG_USART_GECKO_0 #if (DT_SILABS_GECKO_USART_USART_0_LOCATION == 0)