Commit 7670a2ca authored by Luis Murta's avatar Luis Murta

Merge branch '42-implement-air_syscall_shutdown_module' into 'dev'

Resolve "Implement air_syscall_shutdown_module()"

Closes #42

See merge request !9

e45b5178 Implements bsp_shutdown_core on the Zynq-7000

    Executes the necessary procedures to enter sleep mode as defined in the
    Zynq-7000 TRM
    Implements all auxiliary procedures to enter sleep mode
    Prints "AIR has been terminated by the application." message

a4603548 Implements air_syscall_shutdown_module

    It now calls bsp_shutdown_core
parent 54795ca2
......@@ -99,5 +99,6 @@ char message[] = {
void entry_point() {
air_syscall_print(message, sizeof(message));
air_syscall_shutdown_module();
for(;;);
}
/*
* Copyright (C) 2018-2019 GMVIS Skysoft S.A.
* Copyright (C) 2018-2020 GMVIS Skysoft S.A.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
......@@ -14,6 +14,7 @@
#include <svc.h>
#include <syscall.h>
#include <configurations.h>
#include <bsp.h>
#ifdef PMK_DEBUG
#include <printk.h>
......@@ -177,7 +178,9 @@ void arm_svc_handler(arm_interrupt_stack_frame_t *frame, pmk_core_ctrl_t *core)
(air_name_ptr_t)frame->r0,
(air_sharedmemory_t *)frame->r1);
break;
// arm_svc_install_handler(AIR_SYSCALL_SHUTDOWN_MODULE)
case AIR_SYSCALL_SHUTDOWN_MODULE:
bsp_shutdown_core(core);
break;
// arm_svc_install_handler(AIR_SYSCALL_GET_EVENT)
// arm_svc_install_handler(AIR_SYSCALL_GET_SYSTEM_STATE)
case AIR_SYSCALL_SET_SYSTEM_STATE:
......
/*
* Copyright (C) 2018-2019 GMVIS Skysoft S.A.
* Copyright (C) 2018-2020 GMVIS Skysoft S.A.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
......@@ -88,6 +88,18 @@ __FORCE_INLINE static void arm_scu_invalidate(air_u32_t cpu_id) {
SCU->inv_reg_ss = ( (0xf) << ( (cpu_id & 0x3) * 4) );
}
__FORCE_INLINE static void arm_scu_standy_enable() {
SCU->ctrl |= CTRL_SCU_STANDBY_EN;
}
__FORCE_INLINE static void arm_cp15_enable_dynamic_clock_gating(void) {
air_u32_t val;
__asm__ volatile ("mrc p15, 0, %0, c15, c0, 0\n":"=r" (val));
val |= 1;
__asm__ volatile ("mcr p15, 0, %0, c15, c0, 0\n"::"r" (val));
}
void arm_a9mpcore_start_hook(air_u32_t cpu_id);
#endif /* A9MPCORE_H_ */
/*
* Copyright (C) 2018-2019 GMVIS Skysoft S.A.
* Copyright (C) 2018-2020 GMVIS Skysoft S.A.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
......@@ -20,10 +20,8 @@
#include <timer.h>
#include <slcr.h>
#include <uart.h>
#ifdef PMK_DEBUG
#include <ddr.h>
#include <printk.h>
#endif
/**
......@@ -137,8 +135,38 @@ void bsp_restart_core(pmk_core_ctrl_t *core_ctx) {
arm_ps_reset();
}
/* TODO possibly go to standby mode */
void bsp_shutdown_core(pmk_core_ctrl_t *core_ctx) {
printk("\nAIR has been terminaded by the application.\n");
/* 1. disable interrupts */
arm_disable_interrupts();
/* 2. configure wake-up device */
/* 3. enable l2 cache dynamic clock gating */
/* 4. enable scu standby mode */
arm_scu_standy_enable();
/* 5. enable topswitch clock stop */
*(air_uptr_t *)(XPAR_PS7_SLCR_0_S_AXI_BASEADDR + 0x16c) |= 1;
/* 6. enable cortex-a9 dynamic clock gating */
arm_cp15_enable_dynamic_clock_gating();
/* 7. put external DDR into self-refresh mode */
arm_ddr_self_refresh();
/* 8. put PLLs into bypass mode */
arm_pll_bypass_mode();
/* 9. shutdown PLLs */
arm_pll_shutdown();
/* 10. increase clock divider (0x3f) and slow down CPU clock */
arm_set_cpu_clock_divisor(0x3f);
__asm__ volatile ("wfi");
return;
}
......
/*
* Copyright (C) 2020 GMVIS Skysoft S.A.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* https://spass-git-ext.gmv.com/AIR/AIR/raw/master/air/LICENSE
*/
/**
* \file ddr.h
* \author lumm
* \brief DDR memory controller access
*/
#ifndef DDR_H_
#define DDR_H_
#include <a9mpcore.h>
#include <parameters.h>
typedef struct {
air_u32_t ddrc_ctrl;
air_u32_t Two_rank_cfg;
air_u32_t HPR_reg;
air_u32_t LPR_reg;
air_u32_t WR_reg;
air_u32_t DRAM_param_reg0;
air_u32_t DRAM_param_reg1;
air_u32_t DRAM_param_reg2;
air_u32_t DRAM_param_reg3;
air_u32_t DRAM_param_reg4;
air_u32_t DRAM_init_param;
air_u32_t DRAM_EMR_reg;
air_u32_t DRAM_EMR_MR_reg;
air_u32_t DRAM_burst8_rdwr;
air_u32_t DRAM_disable_DQ;
air_u32_t DRAM_addr_map_bank;
air_u32_t DRAM_addr_map_col;
air_u32_t DRAM_addr_map_row;
air_u32_t DRAM_ODT_reg;
air_u32_t phy_dbg_reg;
air_u32_t phy_cmd_timeout_rddata_cpt;
air_u32_t mode_sts_reg;
air_u32_t DLL_calib;
air_u32_t ODT_delay_hold;
air_u32_t ctrl_reg1;
air_u32_t ctrl_reg2;
air_u32_t ctrl_reg3;
air_u32_t ctrl_reg4;
air_u32_t ctrl_reg5;
air_u32_t ctrl_reg6;
air_u32_t CHE_REFRESH_TIMER01;
air_u32_t CHE_T_ZQ;
air_u32_t CHE_T_ZQ_Short_Interval_Reg;
air_u32_t deep_pwrdwn_reg;
air_u32_t reg_2c;
air_u32_t reg_2d;
air_u32_t dfi_timing;
air_u32_t CHE_ECC_CONTROL_REG_OFFSET;
air_u32_t CHE_CORR_ECC_LOG_REG_OFFSET;
air_u32_t CHE_CORR_ECC_ADDR_REG_OFFSET;
air_u32_t CHE_CORR_ECC_DATA_31_0_REG_OFFSET;
air_u32_t CHE_CORR_ECC_DATA_63_32_REG_OFFSET;
air_u32_t CHE_CORR_ECC_DATA_71_64_REG_OFFSET;
air_u32_t CHE_UNCORR_ECC_LOG_REG_OFFSET;
air_u32_t CHE_UNCORR_ECC_ADDR_REG_OFFSET;
air_u32_t CHE_UNCORR_ECC_DATA_31_0_REG_OFFSET;
air_u32_t CHE_UNCORR_ECC_DATA_63_32_REG_OFFSET;
air_u32_t CHE_UNCORR_ECC_DATA_71_64_REG_OFFSET;
air_u32_t CHE_ECC_STATS_REG_OFFSET;
air_u32_t ECC_scrub;
air_u32_t CHE_ECC_CORR_BIT_MASK_31_0_REG_OFFSET;
air_u32_t CHE_ECC_CORR_BIT_MASK_63_32_REG_OFFSET;
air_u32_t phy_rcvr_enable;
air_u32_t PHY_Config0;
air_u32_t PHY_Config1;
air_u32_t PHY_Config2;
air_u32_t PHY_Config3;
air_u32_t phy_init_ratio0;
air_u32_t phy_init_ratio1;
air_u32_t phy_init_ratio2;
air_u32_t phy_init_ratio3;
air_u32_t phy_rd_dqs_cfg0;
air_u32_t phy_rd_dqs_cfg1;
air_u32_t phy_rd_dqs_cfg2;
air_u32_t phy_rd_dqs_cfg3;
air_u32_t phy_wr_dqs_cfg0;
air_u32_t phy_wr_dqs_cfg1;
air_u32_t phy_wr_dqs_cfg2;
air_u32_t phy_wr_dqs_cfg3;
air_u32_t phy_we_cfg0;
air_u32_t phy_we_cfg1;
air_u32_t phy_we_cfg2;
air_u32_t phy_we_cfg3;
air_u32_t wr_data_slv0;
air_u32_t wr_data_slv1;
air_u32_t wr_data_slv2;
air_u32_t wr_data_slv3;
air_u32_t reg_64;
air_u32_t reg_65;
air_u32_t reg69_6a0;
air_u32_t reg69_6a1;
air_u32_t reg6c_6d2;
air_u32_t reg6c_6d3;
air_u32_t reg6e_710;
air_u32_t reg6e_711;
air_u32_t reg6e_712;
air_u32_t reg6e_713;
air_u32_t phy_dll_sts0;
air_u32_t phy_dll_sts1;
air_u32_t phy_dll_sts2;
air_u32_t phy_dll_sts3;
air_u32_t dll_lock_sts;
air_u32_t phy_ctrl_sts;
air_u32_t phy_ctrl_sts_reg2;
air_u32_t axi_id;
air_u32_t page_mask;
air_u32_t axi_priority_wr_port0;
air_u32_t axi_priority_wr_port1;
air_u32_t axi_priority_wr_port2;
air_u32_t axi_priority_wr_port3;
air_u32_t axi_priority_rd_port0;
air_u32_t axi_priority_rd_port1;
air_u32_t axi_priority_rd_port2;
air_u32_t axi_priority_rd_port3;
air_u32_t excl_access_cfg0;
air_u32_t excl_access_cfg1;
air_u32_t excl_access_cfg2;
air_u32_t excl_access_cfg3;
air_u32_t mode_reg_read;
air_u32_t lpddr_ctrl0;
air_u32_t lpddr_ctrl1;
air_u32_t lpddr_ctrl2;
air_u32_t lpddr_ctrl3;
} ddrc_t;
#define DDRC ((ddrc_t *)XPAR_PS7_DDRC_0_S_AXI_BASEADDR)
#define DDR_CLK_CTRL (air_uptr_t *)(XPAR_PS7_SLCR_0_S_AXI_BASEADDR + 0x124)
#define DCI_CLK_CTRL (air_uptr_t *)(XPAR_PS7_SLCR_0_S_AXI_BASEADDR + 0x128)
__FORCE_INLINE static void arm_ddr_self_refresh(void) {
air_u32_t timeout = 0;
DDRC->ctrl_reg1 |= (1 << 12);
DDRC->DRAM_param_reg3 |= (1 << 23);
while((DDRC->mode_sts_reg & 0x7) != 3) {
if (++timeout > 1000) return;
};
timeout = 0;
while((DDRC->mode_sts_reg & (0x1f << 16)) ||
(DDRC->mode_sts_reg & (0x3f << 10)) ||
(DDRC->mode_sts_reg & (0x3f << 4))) {
if (++timeout > 1000) return;
};
timeout = 0;
while(++timeout < 1000);
*DDR_CLK_CTRL &= ~3;
*DCI_CLK_CTRL &= ~1;
}
#endif /* DDR_H_ */
/*
* Copyright (C) 2018-2019 GMVIS Skysoft S.A.
* Copyright (C) 2018-2020 GMVIS Skysoft S.A.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
......@@ -55,15 +55,15 @@ typedef struct { /* 0xf800 0000*/
#define SLCR ((slcr_t *)XPAR_PS7_SLCR_0_S_AXI_BASEADDR)
__FORCE_INLINE static void arm_slcr_lock(void){
__FORCE_INLINE static void arm_slcr_lock(void) {
SLCR->slcr_lock = SLCR_LOCK_KEY;
}
__FORCE_INLINE static void arm_slcr_unlock(void){
__FORCE_INLINE static void arm_slcr_unlock(void) {
SLCR->slcr_unlock = SLCR_UNLOCK_KEY;
}
__FORCE_INLINE static air_u32_t arm_slcr_is_locked(void){
__FORCE_INLINE static air_u32_t arm_slcr_is_locked(void) {
return SLCR->slcr_locksta;
}
......@@ -71,5 +71,8 @@ __FORCE_INLINE static air_u32_t arm_slcr_is_locked(void){
void arm_peripheral_soft_reset(void);
void arm_ps_reset(void);
void arm_pll_bypass_mode(void);
void arm_pll_shutdown(void);
void arm_set_cpu_clock_divisor(air_u32_t divisor);
#endif /* SLCR_H_ */
/*
* Copyright (C) 2018-2019 GMVIS Skysoft S.A.
* Copyright (C) 2018-2020 GMVIS Skysoft S.A.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
......@@ -39,3 +39,32 @@ void arm_ps_reset(void) {
/* shouldn't exit from this function */
}
#define ARM_PLL_CTRL (air_uptr_t *)(XPAR_PS7_SLCR_0_S_AXI_BASEADDR + 0x100)
#define DDR_PLL_CTRL (air_uptr_t *)(XPAR_PS7_SLCR_0_S_AXI_BASEADDR + 0x104)
#define IO_PLL_CTRL (air_uptr_t *)(XPAR_PS7_SLCR_0_S_AXI_BASEADDR + 0x108)
void arm_pll_bypass_mode(void) {
*ARM_PLL_CTRL |= (1 << 4);
*DDR_PLL_CTRL |= (1 << 4);
*IO_PLL_CTRL |= (1 << 4);
}
void arm_pll_shutdown(void) {
*ARM_PLL_CTRL |= (1 << 1);
*DDR_PLL_CTRL |= (1 << 1);
*IO_PLL_CTRL |= (1 << 1);
}
#define ARM_CLK_CTRL (air_uptr_t *)(XPAR_PS7_SLCR_0_S_AXI_BASEADDR + 0x120)
void arm_set_cpu_clock_divisor(air_u32_t divisor) {
if (divisor < 0) divisor = 0;
else if (divisor > 0x3f) divisor = 0x3f;
*ARM_CLK_CTRL |= (divisor << 8);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment