soc: silabs: siwx91x: Add siwx91x Power Manager driver
This commit enables the Power Manager driver support for the siwx91x device. Signed-off-by: S Mohamed Fiaz <fiaz.mohamed@silabs.com>
This commit is contained in:
parent
c891ace488
commit
132247e2cd
8 changed files with 185 additions and 5 deletions
|
@ -24,6 +24,20 @@
|
||||||
cpu0: cpu@0 {
|
cpu0: cpu@0 {
|
||||||
compatible = "arm,cortex-m4f";
|
compatible = "arm,cortex-m4f";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
|
cpu-power-states = <&pstate_ps4_standby &pstate_ps4_sleep>;
|
||||||
|
};
|
||||||
|
|
||||||
|
power-states {
|
||||||
|
pstate_ps4_standby: ps4_standby {
|
||||||
|
compatible = "zephyr,power-state";
|
||||||
|
power-state-name = "runtime-idle";
|
||||||
|
};
|
||||||
|
pstate_ps4_sleep: ps4_sleep {
|
||||||
|
compatible = "zephyr,power-state";
|
||||||
|
power-state-name = "suspend-to-idle";
|
||||||
|
min-residency-us = <100000>;
|
||||||
|
exit-latency-us = <3000>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
set(SISDK_DIR ${ZEPHYR_HAL_SILABS_MODULE_DIR}/simplicity_sdk)
|
set(SISDK_DIR ${ZEPHYR_HAL_SILABS_MODULE_DIR}/simplicity_sdk)
|
||||||
set(WISECONNECT_DIR ${ZEPHYR_HAL_SILABS_MODULE_DIR}/wiseconnect)
|
set(WISECONNECT_DIR ${ZEPHYR_HAL_SILABS_MODULE_DIR}/wiseconnect)
|
||||||
|
set(COMMON_DIR ${ZEPHYR_HAL_SILABS_MODULE_DIR}/simplicity_sdk/platform/common)
|
||||||
|
|
||||||
# Keep these values sync with
|
# Keep these values sync with
|
||||||
# components/device/silabs/si91x/mcu/core/chip/component/siwg917*.slcc
|
# components/device/silabs/si91x/mcu/core/chip/component/siwg917*.slcc
|
||||||
|
@ -23,16 +24,25 @@ zephyr_include_directories(
|
||||||
${SISDK_DIR}/platform/common/inc
|
${SISDK_DIR}/platform/common/inc
|
||||||
${SISDK_DIR}/platform/common/config
|
${SISDK_DIR}/platform/common/config
|
||||||
${SISDK_DIR}/platform/service/mem_pool/inc
|
${SISDK_DIR}/platform/service/mem_pool/inc
|
||||||
${WISECONNECT_DIR}/components/board/silabs/inc
|
# Wiseconnect do not provide generic RTE_Device_917.h. However, all the boards
|
||||||
|
# share more-or-less the same definitions. So we could take any of them.
|
||||||
|
# In addtion, this file is only required for the compilation, but none the
|
||||||
|
# symbols are normally used by Zephyr (it is required to compile CMSIS API
|
||||||
|
# which is not not used).
|
||||||
|
${WISECONNECT_DIR}/components/board/silabs/config/brd4342a
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/config
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/config
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/inc
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/inc
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/config
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/config
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/common/inc
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/rom_driver/inc
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/rom_driver/inc
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/inc
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/inc
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/clock_manager/inc
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/clock_manager/inc
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/inc
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/config
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/systemlevel/inc
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/systemlevel/inc
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_api/inc
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_api/inc
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_api/config
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_api/config
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_api/config/sl_i2s_config
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_peripheral_drivers/inc
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_peripheral_drivers/inc
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver/config
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver/config
|
||||||
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver
|
||||||
|
@ -141,7 +151,7 @@ endif() # CONFIG_BT_SILABS_SIWX91X
|
||||||
if(CONFIG_WISECONNECT_NETWORK_STACK)
|
if(CONFIG_WISECONNECT_NETWORK_STACK)
|
||||||
zephyr_compile_definitions(
|
zephyr_compile_definitions(
|
||||||
SLI_SI91X_ENABLE_OS
|
SLI_SI91X_ENABLE_OS
|
||||||
SL_SI91X_SI917_RAM_MEM_CONFIG=1
|
SL_SI91X_SI917_RAM_MEM_CONFIG=2
|
||||||
SL_WIFI_COMPONENT_INCLUDED # Depite de the name, required for everything
|
SL_WIFI_COMPONENT_INCLUDED # Depite de the name, required for everything
|
||||||
)
|
)
|
||||||
zephyr_include_directories(
|
zephyr_include_directories(
|
||||||
|
@ -198,5 +208,49 @@ if(CONFIG_SOC_SILABS_SLEEPTIMER)
|
||||||
)
|
)
|
||||||
endif() # CONFIG_SOC_SILABS_SLEEPTIMER
|
endif() # CONFIG_SOC_SILABS_SLEEPTIMER
|
||||||
|
|
||||||
|
if(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR)
|
||||||
|
zephyr_library_sources(
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/common/src/rsi_debug.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/src/rsi_ps_ram_func.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver/USART.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver/UDMA.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver/SAI.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/sl_si91x_m4_ps.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/rsi_usart.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/rsi_udma_wrapper.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/rsi_udma.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sl_si91x_power_manager.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sli_si91x_power_manager.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/clock_manager/src/sli_si91x_clock_manager.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/systemlevel/src/rsi_temp_sensor.c
|
||||||
|
${COMMON_DIR}/src/sl_slist.c
|
||||||
|
)
|
||||||
|
zephyr_include_directories(
|
||||||
|
${COMMON_DIR}/inc
|
||||||
|
)
|
||||||
|
zephyr_compile_definitions(
|
||||||
|
SL_CODE_COMPONENT_POWER_MANAGER=power_manager
|
||||||
|
SL_SI91X_TICKLESS_MODE
|
||||||
|
SL_SLEEP_TIMER
|
||||||
|
SL_SI91X_SI917_RAM_MEM_CONFIG=2
|
||||||
|
SL_CODE_COMPONENT_CORE=core
|
||||||
|
DEBUG_ENABLE
|
||||||
|
DEBUG_UART
|
||||||
|
SLI_WIRELESS_COMPONENT_PRESENT
|
||||||
|
)
|
||||||
|
zephyr_code_relocate(FILES
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/src/rsi_deepsleep_soc.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sl_si91x_power_manager.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sli_si91x_power_manager.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/sleeptimer/src/sl_sleeptimer_hal_si91x_sysrtc.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/rsi_sysrtc.c
|
||||||
|
${SISDK_DIR}/platform/service/sleeptimer/src/sl_sleeptimer.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/wireless/ahb_interface/src/rsi_hal_mcu_m4_ram.c
|
||||||
|
${WISECONNECT_DIR}/components/device/silabs/si91x/wireless/ahb_interface/src/rsi_hal_mcu_m4_rom.c
|
||||||
|
${ZEPHYR_BASE}/drivers/gpio/*.c
|
||||||
|
LOCATION RAM
|
||||||
|
)
|
||||||
|
endif() # CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR
|
||||||
|
|
||||||
zephyr_linker_sources(ROM_SECTIONS linker/code_classification_text.ld)
|
zephyr_linker_sources(ROM_SECTIONS linker/code_classification_text.ld)
|
||||||
zephyr_linker_sources(RAMFUNC_SECTION linker/code_classification_ramfunc.ld)
|
zephyr_linker_sources(RAMFUNC_SECTION linker/code_classification_ramfunc.ld)
|
||||||
|
|
|
@ -9,6 +9,7 @@ config SOC_FAMILY_SILABS_SIWX91X
|
||||||
select CPU_HAS_ARM_MPU
|
select CPU_HAS_ARM_MPU
|
||||||
select HAS_SILABS_WISECONNECT
|
select HAS_SILABS_WISECONNECT
|
||||||
select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE
|
select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE
|
||||||
|
select HAS_PM
|
||||||
|
|
||||||
if SOC_FAMILY_SILABS_SIWX91X
|
if SOC_FAMILY_SILABS_SIWX91X
|
||||||
|
|
||||||
|
@ -19,6 +20,16 @@ config SOC_SILABS_SLEEPTIMER
|
||||||
help
|
help
|
||||||
The Sleeptimer HAL module is used for SIWX91X.
|
The Sleeptimer HAL module is used for SIWX91X.
|
||||||
|
|
||||||
|
config SOC_SIWX91X_PM_BACKEND_PMGR
|
||||||
|
bool
|
||||||
|
select WISECONNECT_NETWORK_STACK
|
||||||
|
select SILABS_SLEEPTIMER_TIMER
|
||||||
|
select SRAM_VECTOR_TABLE
|
||||||
|
select CODE_DATA_RELOCATION_SRAM
|
||||||
|
default y if PM
|
||||||
|
help
|
||||||
|
Implement PM using sl_power_manager service from Gecko SDK
|
||||||
|
|
||||||
config SIWX91X_NWP_INIT_PRIORITY
|
config SIWX91X_NWP_INIT_PRIORITY
|
||||||
int "SiWx91x Network Processor init priority"
|
int "SiWx91x Network Processor init priority"
|
||||||
default 39
|
default 39
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
|
|
||||||
if SOC_FAMILY_SILABS_SIWX91X
|
if SOC_FAMILY_SILABS_SIWX91X
|
||||||
|
|
||||||
configdefault SILABS_SLEEPTIMER_TIMER
|
|
||||||
default y if PM
|
|
||||||
|
|
||||||
configdefault CORTEX_M_SYSTICK
|
configdefault CORTEX_M_SYSTICK
|
||||||
default n if SILABS_SLEEPTIMER_TIMER
|
default n if SILABS_SLEEPTIMER_TIMER
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,6 @@
|
||||||
|
|
||||||
zephyr_sources_ifdef(CONFIG_SOC_SERIES_SIWG917 soc.c)
|
zephyr_sources_ifdef(CONFIG_SOC_SERIES_SIWG917 soc.c)
|
||||||
zephyr_sources_ifdef(CONFIG_WISECONNECT_NETWORK_STACK nwp.c)
|
zephyr_sources_ifdef(CONFIG_WISECONNECT_NETWORK_STACK nwp.c)
|
||||||
|
zephyr_sources_ifdef(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR soc_siwx91x_power_pmgr.c)
|
||||||
|
|
||||||
set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "")
|
set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "")
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifdef CONFIG_BT_SILABS_SIWX91X
|
#ifdef CONFIG_BT_SILABS_SIWX91X
|
||||||
#include "rsi_ble_common_config.h"
|
#include "rsi_ble_common_config.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "sl_si91x_power_manager.h"
|
||||||
|
|
||||||
#define AP_MAX_NUM_STA 4
|
#define AP_MAX_NUM_STA 4
|
||||||
|
|
||||||
|
@ -243,6 +244,8 @@ static int siwg917_nwp_init(void)
|
||||||
{
|
{
|
||||||
sl_wifi_device_configuration_t network_config;
|
sl_wifi_device_configuration_t network_config;
|
||||||
sl_status_t status;
|
sl_status_t status;
|
||||||
|
__maybe_unused sl_wifi_performance_profile_t performance_profile = {
|
||||||
|
.profile = DEEP_SLEEP_WITH_RAM_RETENTION};
|
||||||
|
|
||||||
siwx91x_get_nwp_config(&network_config, WIFI_STA_MODE, false, 0);
|
siwx91x_get_nwp_config(&network_config, WIFI_STA_MODE, false, 0);
|
||||||
/* TODO: If sl_net_*_profile() functions will be needed for WiFi then call
|
/* TODO: If sl_net_*_profile() functions will be needed for WiFi then call
|
||||||
|
@ -253,6 +256,14 @@ static int siwg917_nwp_init(void)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR)) {
|
||||||
|
status = sl_wifi_set_performance_profile(&performance_profile);
|
||||||
|
if (status != SL_STATUS_OK) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
/* Remove the previously added PS4 power state requirement */
|
||||||
|
sl_si91x_power_manager_remove_ps_requirement(SL_SI91X_POWER_MANAGER_PS4);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#if defined(CONFIG_MBEDTLS_INIT)
|
#if defined(CONFIG_MBEDTLS_INIT)
|
||||||
|
|
|
@ -10,10 +10,28 @@
|
||||||
#include <zephyr/sw_isr_table.h>
|
#include <zephyr/sw_isr_table.h>
|
||||||
|
|
||||||
#include "em_device.h"
|
#include "em_device.h"
|
||||||
|
#ifdef CONFIG_WISECONNECT_NETWORK_STACK
|
||||||
|
#include "sli_siwx917_soc.h"
|
||||||
|
#endif
|
||||||
|
#include "sl_si91x_power_manager.h"
|
||||||
|
|
||||||
void soc_early_init_hook(void)
|
void soc_early_init_hook(void)
|
||||||
{
|
{
|
||||||
|
__maybe_unused sl_power_peripheral_t peripheral_config = {};
|
||||||
|
__maybe_unused sl_power_ram_retention_config_t ram_configuration = {
|
||||||
|
.configure_ram_banks = false,
|
||||||
|
.m4ss_ram_size_kb = (DT_REG_SIZE(DT_NODELABEL(sram0)) / 1024),
|
||||||
|
.ulpss_ram_size_kb = 4,
|
||||||
|
};
|
||||||
SystemInit();
|
SystemInit();
|
||||||
|
#if IS_ENABLED(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR)
|
||||||
|
sli_si91x_platform_init();
|
||||||
|
sl_si91x_power_manager_init();
|
||||||
|
sl_si91x_power_manager_remove_peripheral_requirement(&peripheral_config);
|
||||||
|
sl_si91x_power_manager_configure_ram_retention(&ram_configuration);
|
||||||
|
sl_si91x_power_manager_add_ps_requirement(SL_SI91X_POWER_MANAGER_PS4);
|
||||||
|
sl_si91x_power_manager_set_clock_scaling(SL_SI91X_POWER_MANAGER_PERFORMANCE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SiWx917's bootloader requires IRQn 32 to hold payload's entry point address. */
|
/* SiWx917's bootloader requires IRQn 32 to hold payload's entry point address. */
|
||||||
|
|
74
soc/silabs/silabs_siwx91x/siwg917/soc_siwx91x_power_pmgr.c
Normal file
74
soc/silabs/silabs_siwx91x/siwg917/soc_siwx91x_power_pmgr.c
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2025 Silicon Laboratories Inc.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/pm/pm.h>
|
||||||
|
#include "sl_si91x_power_manager.h"
|
||||||
|
#include "sli_si91x_clock_manager.h"
|
||||||
|
#include "sl_rsi_utility.h"
|
||||||
|
#include "sl_si91x_m4_ps.h"
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(siwx91x_pm);
|
||||||
|
|
||||||
|
extern uint32_t frontend_switch_control;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Power state map:
|
||||||
|
* PM_STATE_RUNTIME_IDLE: SL_SI91X_POWER_MANAGER_STANDBY (PS4)
|
||||||
|
* PM_STATE_SUSPEND_TO_IDLE: SL_SI91X_POWER_MANAGER_SLEEP (PS4 Sleep)
|
||||||
|
*/
|
||||||
|
void pm_state_set(enum pm_state state, uint8_t substate_id)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(substate_id);
|
||||||
|
|
||||||
|
/* Set PRIMASK */
|
||||||
|
__disable_irq();
|
||||||
|
/* Set BASEPRI to 0. */
|
||||||
|
irq_unlock(0);
|
||||||
|
|
||||||
|
if (!sl_si91x_power_manager_is_ok_to_sleep()) {
|
||||||
|
/* Device is not ready to sleep; perform necessary actions if required. */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == PM_STATE_RUNTIME_IDLE) {
|
||||||
|
sl_si91x_power_manager_standby();
|
||||||
|
} else {
|
||||||
|
if (sli_si91x_config_clocks_to_mhz_rc() != 0) {
|
||||||
|
LOG_ERR("Failed to configure clocks for sleep mode");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (IS_ENABLED(CONFIG_WISECONNECT_NETWORK_STACK)) {
|
||||||
|
if (!(M4_ULP_SLP_STATUS_REG & ULP_MODE_SWITCHED_NPSS)) {
|
||||||
|
if (!sl_si91x_is_device_initialized()) {
|
||||||
|
LOG_ERR("Device is not initialized");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
sli_si91x_xtal_turn_off_request_from_m4_to_TA();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sl_si91x_power_manager_sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(M4_ULP_SLP_STATUS_REG & ULP_MODE_SWITCHED_NPSS)) {
|
||||||
|
if (frontend_switch_control != 0) {
|
||||||
|
sli_si91x_configure_wireless_frontend_controls(frontend_switch_control);
|
||||||
|
}
|
||||||
|
|
||||||
|
sl_si91x_host_clear_sleep_indicator();
|
||||||
|
sli_si91x_m4_ta_wakeup_configurations();
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
/* Clear PRIMASK */
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(state);
|
||||||
|
ARG_UNUSED(substate_id);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue