From 8bed2d5e273e1353d1fa1b0ba521c1c6e9bcd0a9 Mon Sep 17 00:00:00 2001 From: Piotr Mienkowski Date: Thu, 27 Dec 2018 08:12:05 +0100 Subject: [PATCH] soc: silabs_exx32: Add SWO logger support By default, after reset SWO signal is not connected to GPIO pin. This commit adds required initialization code to enable support for SWO logger. Not all SoC series support the feature. Signed-off-by: Piotr Mienkowski --- .../efr32_slwstk6061a/efr32_slwstk6061a.dts | 5 +++++ .../arm/efr32mg_sltb004a/efr32mg_sltb004a.dts | 5 +++++ drivers/gpio/gpio_gecko.c | 18 ++++++++++++++++++ dts/arm/silabs/efr32fg1p.dtsi | 2 +- dts/arm/silabs/efr32mg.dtsi | 2 +- dts/bindings/gpio/silabs,efr32mg12-gpio.yaml | 5 +++++ dts/bindings/gpio/silabs,efr32xg1-gpio.yaml | 5 +++++ soc/arm/silabs_exx32/common/soc.c | 5 +++++ .../efr32fg1p/Kconfig.defconfig.efr32fg1p | 4 ++-- soc/arm/silabs_exx32/efr32fg1p/Kconfig.series | 1 + soc/arm/silabs_exx32/efr32fg1p/dts_fixup.h | 1 + soc/arm/silabs_exx32/efr32fg1p/soc_pinmap.h | 15 +++++++++++++++ .../efr32mg12p/Kconfig.defconfig.efr32mg12p | 4 ++-- soc/arm/silabs_exx32/efr32mg12p/Kconfig.series | 1 + soc/arm/silabs_exx32/efr32mg12p/dts_fixup.h | 1 + soc/arm/silabs_exx32/efr32mg12p/soc_pinmap.h | 15 +++++++++++++++ 16 files changed, 83 insertions(+), 6 deletions(-) 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)