mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-15 19:08:54 +00:00
V1.0.5
This commit is contained in:
@@ -17,6 +17,11 @@
|
||||
uint64_t sleep_counter;
|
||||
uint64_t resume_counter;
|
||||
|
||||
#define AIC_SRAM_BASE 0x00100000
|
||||
static void (*aic_suspend_resume_fn)();
|
||||
extern void aic_suspend_resume();
|
||||
extern u32 aic_suspend_resume_size;
|
||||
|
||||
void aic_pm_enter_idle(void)
|
||||
{
|
||||
__WFI();
|
||||
@@ -86,7 +91,12 @@ void aic_pm_enter_deep_sleep(void)
|
||||
hal_clk_disable(CLK_PLL_INT0);
|
||||
/* reset all pins */
|
||||
//TO DO
|
||||
__WFI();
|
||||
|
||||
rt_memcpy((void *)AIC_SRAM_BASE, aic_suspend_resume, aic_suspend_resume_size);
|
||||
aic_suspend_resume_fn = (void *)AIC_SRAM_BASE;
|
||||
aicos_icache_invalid();
|
||||
aicos_dcache_clean_invalid();
|
||||
aic_suspend_resume_fn();
|
||||
|
||||
/* wakeup flow */
|
||||
/* enable PLL_INT0: cpu pll */
|
||||
|
||||
237
bsp/artinchip/drv/pm/drv_pm_v12.c
Normal file
237
bsp/artinchip/drv/pm/drv_pm_v12.c
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, ArtInChip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Authors: dwj <weijie.ding@artinchip.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <rtdevice.h>
|
||||
#include <rtthread.h>
|
||||
#include <aic_core.h>
|
||||
#include <aic_drv.h>
|
||||
#include <string.h>
|
||||
#include <aic_osal.h>
|
||||
|
||||
uint64_t sleep_counter;
|
||||
uint64_t resume_counter;
|
||||
|
||||
extern void aic_suspend_resume();
|
||||
extern u32 aic_suspend_resume_size;
|
||||
static void (*aic_suspend_resume_fn)();
|
||||
extern size_t __sram_start;
|
||||
|
||||
#define PRCM_SW_VDD11_CTL 0x88000070
|
||||
#define PRCM_C908_VDD11_CTL 0x88000074
|
||||
#define PRCM_DDR_WAKEUP_STATUS 0x88000108
|
||||
#define CMU_APB0_REG 0x98020120
|
||||
#define CMU_APB2_REG 0x98020128
|
||||
|
||||
void aic_pm_enter_idle(void)
|
||||
{
|
||||
__WFI();
|
||||
}
|
||||
|
||||
#ifndef AIC_USING_SRAM
|
||||
void aic_ddr_sr_code_on_ddr(void)
|
||||
{
|
||||
rt_kprintf("aic_suspend_resume_size: %d\n", aic_suspend_resume_size);
|
||||
rt_kprintf("__sram_start: %x\n", (uint32_t)&__sram_start);
|
||||
|
||||
rt_memcpy((void *)&__sram_start, aic_suspend_resume, aic_suspend_resume_size);
|
||||
aic_suspend_resume_fn = (void *)&__sram_start;
|
||||
aicos_icache_invalid();
|
||||
aicos_dcache_clean_invalid();
|
||||
aic_suspend_resume_fn();
|
||||
}
|
||||
#else
|
||||
void aic_ddr_sr_code_on_sram(void)
|
||||
{
|
||||
rt_kprintf("aic_suspend_resume_size: %d\n", aic_suspend_resume_size);
|
||||
aic_suspend_resume_fn = aic_suspend_resume;
|
||||
aic_suspend_resume_fn();
|
||||
}
|
||||
#endif
|
||||
|
||||
void aic_pm_enter_deep_sleep(void)
|
||||
{
|
||||
rt_base_t level;
|
||||
uint32_t i, reg_val;
|
||||
uint8_t save_sp_clic_ie[MAX_IRQn] = {0};
|
||||
uint32_t cmu_pll_freq[8];
|
||||
uint32_t cmu_pll8_freq, cmu_apb0_freq, cmu_apb2_freq;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
/*
|
||||
* After VDD1.1 power domain reset, the CMU will also reset.
|
||||
* So save the CMU pll and bus register value before the VDD1.1 domain
|
||||
* power down.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(cmu_pll_freq); i++)
|
||||
cmu_pll_freq[i] = hal_clk_get_freq(CLK_CS_PLL_FRA0 + i);
|
||||
|
||||
/* TO DO */
|
||||
RT_UNUSED(cmu_pll8_freq);
|
||||
|
||||
cmu_apb0_freq = readl(CMU_APB0_REG);
|
||||
cmu_apb2_freq = readl(CMU_APB2_REG);
|
||||
|
||||
/* change PRCM bus frequency to 24M */
|
||||
hal_clk_set_parent(CLK_AHB, CLK_24M);
|
||||
hal_clk_set_parent(CLK_APB0, CLK_24M);
|
||||
hal_clk_set_parent(CLK_AXI, CLK_24M);
|
||||
/* change SP cpu frequency to 24M */
|
||||
hal_clk_set_parent(CLK_CPU, CLK_24M);
|
||||
/* save the interrupt status of each peripheral */
|
||||
for (i = 0; i < MAX_IRQn; i++)
|
||||
{
|
||||
save_sp_clic_ie[i] = (uint8_t)csi_vic_get_enabled_irq(i);
|
||||
if (save_sp_clic_ie[i])
|
||||
aicos_irq_disable(i);
|
||||
}
|
||||
|
||||
/* Indicate DDR will enter self-refresh */
|
||||
reg_val = readl(PRCM_DDR_WAKEUP_STATUS);
|
||||
reg_val |= 1;
|
||||
writel(reg_val, PRCM_DDR_WAKEUP_STATUS);
|
||||
#ifdef FPGA_BOARD_ARTINCHIP
|
||||
#define CMU_SC_CLK_CPU 0x980201f0
|
||||
#define CMU_CSYS_CLK_CPU 0x98020200
|
||||
//reset SC CPU
|
||||
writel(0xac000000, CMU_SC_CLK_CPU);
|
||||
//reset CSYS CPU, release by non-secure se brom
|
||||
writel(0xac000000, CMU_CSYS_CLK_CPU);
|
||||
#endif
|
||||
aicos_irq_enable(GMAC0_IRQn);
|
||||
aicos_irq_enable(RTC_IRQn);
|
||||
/* reset all pins */
|
||||
//TO DO
|
||||
#ifndef AIC_USING_SRAM
|
||||
aic_ddr_sr_code_on_ddr();
|
||||
#else
|
||||
aic_ddr_sr_code_on_sram();
|
||||
#endif
|
||||
|
||||
/* wakeup flow */
|
||||
aicos_irq_disable(GMAC0_IRQn);
|
||||
aicos_irq_disable(RTC_IRQn);
|
||||
/* restore CMU pll and bus freqency */
|
||||
for (i = 0; i < ARRAY_SIZE(cmu_pll_freq); i++)
|
||||
hal_clk_set_freq(CLK_CS_PLL_FRA0 + i, cmu_pll_freq[i]);
|
||||
|
||||
writel(cmu_apb0_freq, CMU_APB0_REG);
|
||||
writel(cmu_apb2_freq, CMU_APB2_REG);
|
||||
|
||||
/* indicate DDR has exited self-refresh and is ready */
|
||||
reg_val = readl(PRCM_DDR_WAKEUP_STATUS);
|
||||
reg_val &= ~1;
|
||||
writel(reg_val, PRCM_DDR_WAKEUP_STATUS);
|
||||
/* restore the interrupt status of each peripheral */
|
||||
for (i = 0; i < MAX_IRQn; i++)
|
||||
{
|
||||
if (save_sp_clic_ie[i])
|
||||
aicos_irq_enable(i);
|
||||
}
|
||||
//release SC CPU, CSYS CPU is released by se brom
|
||||
writel(0xac003100, CMU_SC_CLK_CPU);
|
||||
/* change cpu frequency to pll */
|
||||
hal_clk_set_parent(CLK_CPU, CLK_PLL_FRA0);
|
||||
/* enable PLL_INT1: bus pll */
|
||||
hal_clk_set_parent(CLK_APB0, CLK_PLL_FRA0);
|
||||
hal_clk_set_parent(CLK_AHB, CLK_PLL_FRA0);
|
||||
rt_pm_request(PM_SLEEP_MODE_NONE);
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
|
||||
|
||||
static void aic_sleep(struct rt_pm *pm, uint8_t mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case PM_SLEEP_MODE_NONE:
|
||||
break;
|
||||
|
||||
case PM_SLEEP_MODE_IDLE:
|
||||
aic_pm_enter_idle();
|
||||
break;
|
||||
case PM_SLEEP_MODE_LIGHT:
|
||||
break;
|
||||
case PM_SLEEP_MODE_DEEP:
|
||||
aic_pm_enter_deep_sleep();
|
||||
break;
|
||||
case PM_SLEEP_MODE_STANDBY:
|
||||
//TO DO
|
||||
break;
|
||||
case PM_SLEEP_MODE_SHUTDOWN:
|
||||
break;
|
||||
default:
|
||||
RT_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* timeout unit is rt_tick_t, but MTIMECMPH/L unit is HZ
|
||||
* one tick is 4000 counter
|
||||
*/
|
||||
static void aic_timer_start(struct rt_pm *pm, rt_uint32_t timeout)
|
||||
{
|
||||
uint64_t tmp_counter;
|
||||
uint32_t tick_resolution = drv_get_sys_freq() / CONFIG_SYSTICK_HZ;
|
||||
|
||||
sleep_counter = ((uint64_t)csi_coret_get_valueh() << 32) |
|
||||
csi_coret_get_value();
|
||||
tmp_counter = (uint64_t)timeout * tick_resolution;
|
||||
|
||||
csi_coret_set_load(tmp_counter + sleep_counter);
|
||||
}
|
||||
|
||||
static void aic_timer_stop(struct rt_pm *pm)
|
||||
{
|
||||
uint64_t tmp_counter = ((uint64_t)csi_coret_get_valueh() << 32) |
|
||||
csi_coret_get_value();
|
||||
|
||||
uint32_t tick_resolution = drv_get_sys_freq() / CONFIG_SYSTICK_HZ;
|
||||
|
||||
csi_coret_set_load(tmp_counter + tick_resolution);
|
||||
}
|
||||
|
||||
static rt_tick_t aic_timer_get_tick(struct rt_pm *pm)
|
||||
{
|
||||
rt_tick_t delta_tick;
|
||||
uint64_t delta_counter;
|
||||
uint32_t tick_resolution = drv_get_sys_freq() / CONFIG_SYSTICK_HZ;
|
||||
|
||||
resume_counter = ((uint64_t)csi_coret_get_valueh() << 32) |
|
||||
csi_coret_get_value();
|
||||
delta_counter = resume_counter - sleep_counter;
|
||||
|
||||
delta_tick = delta_counter / tick_resolution;
|
||||
|
||||
return delta_tick;
|
||||
}
|
||||
|
||||
static const struct rt_pm_ops aic_pm_ops =
|
||||
{
|
||||
aic_sleep,
|
||||
NULL,
|
||||
aic_timer_start,
|
||||
aic_timer_stop,
|
||||
aic_timer_get_tick,
|
||||
};
|
||||
|
||||
/**
|
||||
* This function initialize the power manager
|
||||
*/
|
||||
|
||||
int aic_pm_hw_init(void)
|
||||
{
|
||||
rt_uint8_t timer_mask = 0;
|
||||
|
||||
timer_mask = 1UL << PM_SLEEP_MODE_DEEP;
|
||||
/* initialize system pm module */
|
||||
rt_system_pm_init(&aic_pm_ops, timer_mask, RT_NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
INIT_BOARD_EXPORT(aic_pm_hw_init);
|
||||
@@ -17,115 +17,53 @@
|
||||
uint64_t sleep_counter;
|
||||
uint64_t resume_counter;
|
||||
|
||||
extern void aic_suspend_resume();
|
||||
extern u32 aic_suspend_resume_size;
|
||||
static void (*aic_suspend_resume_fn)();
|
||||
extern size_t __sram_start;
|
||||
|
||||
#define PRCM_SW_VDD11_CTL 0x88000070
|
||||
#define PRCM_C908_VDD11_CTL 0x88000074
|
||||
#define PRCM_DDR_WAKEUP_STATUS 0x88000108
|
||||
#define CMU_APB0_REG 0x98020120
|
||||
#define CMU_APB2_REG 0x98020128
|
||||
extern void sc_save_context_and_suspend();
|
||||
extern void sc_restore_context_and_resume();
|
||||
extern u32 sc_restore_context_and_resume_size;
|
||||
|
||||
void aic_pm_enter_idle(void)
|
||||
{
|
||||
__WFI();
|
||||
}
|
||||
|
||||
#ifndef AIC_USING_SRAM
|
||||
void aic_ddr_sr_code_on_ddr(void)
|
||||
{
|
||||
rt_kprintf("aic_suspend_resume_size: %d\n", aic_suspend_resume_size);
|
||||
rt_kprintf("__sram_start: %x\n", (uint32_t)&__sram_start);
|
||||
|
||||
rt_memcpy((void *)&__sram_start, aic_suspend_resume, aic_suspend_resume_size);
|
||||
aic_suspend_resume_fn = (void *)&__sram_start;
|
||||
aicos_icache_invalid();
|
||||
aicos_dcache_clean_invalid();
|
||||
aic_suspend_resume_fn();
|
||||
}
|
||||
#else
|
||||
void aic_ddr_sr_code_on_sram(void)
|
||||
{
|
||||
rt_kprintf("aic_suspend_resume_size: %d\n", aic_suspend_resume_size);
|
||||
aic_suspend_resume_fn = aic_suspend_resume;
|
||||
aic_suspend_resume_fn();
|
||||
}
|
||||
#endif
|
||||
|
||||
void aic_pm_enter_deep_sleep(void)
|
||||
{
|
||||
rt_base_t level;
|
||||
uint32_t i;
|
||||
uint8_t save_sp_clic_ie[MAX_IRQn] = {0};
|
||||
uint32_t cmu_pll_freq[8];
|
||||
uint32_t cmu_pll8_freq, cmu_apb0_freq, cmu_apb2_freq;
|
||||
uint8_t save_sc_clic_ie[MAX_IRQn] = {0};
|
||||
uint32_t save_sc_context[36] = {0};
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
/*
|
||||
* After VDD1.1 power domain reset, the CMU will also reset.
|
||||
* So save the CMU pll and bus register value before the VDD1.1 domain
|
||||
* power down.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(cmu_pll_freq); i++)
|
||||
cmu_pll_freq[i] = hal_clk_get_freq(CLK_CS_PLL_FRA0 + i);
|
||||
rt_memcpy((void *)0x80050000, sc_restore_context_and_resume,
|
||||
sc_restore_context_and_resume_size);
|
||||
|
||||
/* TO DO */
|
||||
RT_UNUSED(cmu_pll8_freq);
|
||||
|
||||
cmu_apb0_freq = readl(CMU_APB0_REG);
|
||||
cmu_apb2_freq = readl(CMU_APB2_REG);
|
||||
|
||||
/* change PRCM bus frequency to 24M */
|
||||
hal_clk_set_parent(CLK_AHB, CLK_24M);
|
||||
hal_clk_set_parent(CLK_APB0, CLK_24M);
|
||||
hal_clk_set_parent(CLK_AXI, CLK_24M);
|
||||
/* change SP cpu frequency to 24M */
|
||||
hal_clk_set_parent(CLK_CPU, CLK_24M);
|
||||
/* save the interrupt status of each peripheral */
|
||||
for (i = 0; i < MAX_IRQn; i++)
|
||||
{
|
||||
save_sp_clic_ie[i] = (uint8_t)csi_vic_get_enabled_irq(i);
|
||||
if (save_sp_clic_ie[i])
|
||||
save_sc_clic_ie[i] = (uint8_t)csi_vic_get_enabled_irq(i);
|
||||
if (save_sc_clic_ie[i])
|
||||
aicos_irq_disable(i);
|
||||
}
|
||||
|
||||
/* Indicate DDR will enter self-refresh */
|
||||
writel(1, PRCM_DDR_WAKEUP_STATUS);
|
||||
/* reset all pins */
|
||||
//TO DO
|
||||
#ifndef AIC_USING_SRAM
|
||||
aic_ddr_sr_code_on_ddr();
|
||||
#else
|
||||
aic_ddr_sr_code_on_sram();
|
||||
#endif
|
||||
/* save context and wait power down */
|
||||
sc_save_context_and_suspend(&save_sc_context);
|
||||
|
||||
/* wakeup flow */
|
||||
/* restore CMU pll and bus freqency */
|
||||
for (i = 0; i < ARRAY_SIZE(cmu_pll_freq); i++)
|
||||
hal_clk_set_freq(CLK_CS_PLL_FRA0 + i, cmu_pll_freq[i]);
|
||||
/* SC power up and resume flow */
|
||||
CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >>
|
||||
CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos);
|
||||
/* config CLIC attribute to use vector interrupt */
|
||||
for (i = 0; i < MAX_IRQn; i++)
|
||||
CLIC->CLICINT[i].ATTR = 1;
|
||||
|
||||
writel(cmu_apb0_freq, CMU_APB0_REG);
|
||||
writel(cmu_apb2_freq, CMU_APB2_REG);
|
||||
CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3;
|
||||
|
||||
/* indicate DDR has exited self-refresh and is ready */
|
||||
writel(0, PRCM_DDR_WAKEUP_STATUS);
|
||||
/* restore the interrupt status of each peripheral */
|
||||
for (i = 0; i < MAX_IRQn; i++)
|
||||
{
|
||||
if (save_sp_clic_ie[i])
|
||||
if (save_sc_clic_ie[i])
|
||||
aicos_irq_enable(i);
|
||||
}
|
||||
/* change cpu frequency to pll */
|
||||
hal_clk_set_parent(CLK_CPU, CLK_PLL_FRA0);
|
||||
/* enable PLL_INT1: bus pll */
|
||||
hal_clk_set_parent(CLK_APB0, CLK_PLL_FRA0);
|
||||
hal_clk_set_parent(CLK_AHB, CLK_PLL_FRA0);
|
||||
rt_pm_request(PM_SLEEP_MODE_NONE);
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
|
||||
rt_pm_request(PM_SLEEP_MODE_NONE);
|
||||
}
|
||||
|
||||
static void aic_sleep(struct rt_pm *pm, uint8_t mode)
|
||||
{
|
||||
@@ -187,8 +125,6 @@ static rt_tick_t aic_timer_get_tick(struct rt_pm *pm)
|
||||
resume_counter = ((uint64_t)csi_coret_get_valueh() << 32) |
|
||||
csi_coret_get_value();
|
||||
delta_counter = resume_counter - sleep_counter;
|
||||
if (delta_counter > 400)
|
||||
return 1;
|
||||
|
||||
delta_tick = delta_counter / tick_resolution;
|
||||
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, ArtInChip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Authors: dwj <weijie.ding@artinchip.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <rtdevice.h>
|
||||
#include <rtthread.h>
|
||||
#include <aic_core.h>
|
||||
#include <aic_drv.h>
|
||||
#include <string.h>
|
||||
#include <aic_osal.h>
|
||||
|
||||
uint64_t sleep_counter;
|
||||
uint64_t resume_counter;
|
||||
|
||||
extern void sc_save_context_and_suspend();
|
||||
extern void sc_restore_context_and_resume();
|
||||
extern u32 sc_restore_context_and_resume_size;
|
||||
|
||||
void aic_pm_enter_idle(void)
|
||||
{
|
||||
__WFI();
|
||||
}
|
||||
|
||||
void aic_pm_enter_deep_sleep(void)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t save_sc_clic_ie[MAX_IRQn] = {0};
|
||||
uint32_t save_sc_context[36] = {0};
|
||||
|
||||
rt_memcpy((void *)0x80050000, sc_restore_context_and_resume,
|
||||
sc_restore_context_and_resume_size);
|
||||
|
||||
/* save the interrupt status of each peripheral */
|
||||
for (i = 0; i < MAX_IRQn; i++)
|
||||
{
|
||||
save_sc_clic_ie[i] = (uint8_t)csi_vic_get_enabled_irq(i);
|
||||
if (save_sc_clic_ie[i])
|
||||
aicos_irq_disable(i);
|
||||
}
|
||||
|
||||
/* save context and wait power down */
|
||||
sc_save_context_and_suspend(&save_sc_context);
|
||||
|
||||
/* SC power up and resume flow */
|
||||
CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >>
|
||||
CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos);
|
||||
/* config CLIC attribute to use vector interrupt */
|
||||
for (i = 0; i < MAX_IRQn; i++)
|
||||
CLIC->CLICINT[i].ATTR = 1;
|
||||
|
||||
CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3;
|
||||
|
||||
/* restore the interrupt status of each peripheral */
|
||||
for (i = 0; i < MAX_IRQn; i++)
|
||||
{
|
||||
if (save_sc_clic_ie[i])
|
||||
aicos_irq_enable(i);
|
||||
}
|
||||
|
||||
rt_pm_request(PM_SLEEP_MODE_NONE);
|
||||
}
|
||||
|
||||
static void aic_sleep(struct rt_pm *pm, uint8_t mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case PM_SLEEP_MODE_NONE:
|
||||
break;
|
||||
|
||||
case PM_SLEEP_MODE_IDLE:
|
||||
aic_pm_enter_idle();
|
||||
break;
|
||||
case PM_SLEEP_MODE_LIGHT:
|
||||
break;
|
||||
case PM_SLEEP_MODE_DEEP:
|
||||
aic_pm_enter_deep_sleep();
|
||||
break;
|
||||
case PM_SLEEP_MODE_STANDBY:
|
||||
//TO DO
|
||||
break;
|
||||
case PM_SLEEP_MODE_SHUTDOWN:
|
||||
break;
|
||||
default:
|
||||
RT_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* timeout unit is rt_tick_t, but MTIMECMPH/L unit is HZ
|
||||
* one tick is 4000 counter
|
||||
*/
|
||||
static void aic_timer_start(struct rt_pm *pm, rt_uint32_t timeout)
|
||||
{
|
||||
uint64_t tmp_counter;
|
||||
uint32_t tick_resolution = drv_get_sys_freq() / CONFIG_SYSTICK_HZ;
|
||||
|
||||
sleep_counter = ((uint64_t)csi_coret_get_valueh() << 32) |
|
||||
csi_coret_get_value();
|
||||
tmp_counter = (uint64_t)timeout * tick_resolution;
|
||||
|
||||
csi_coret_set_load(tmp_counter + sleep_counter);
|
||||
}
|
||||
|
||||
static void aic_timer_stop(struct rt_pm *pm)
|
||||
{
|
||||
uint64_t tmp_counter = ((uint64_t)csi_coret_get_valueh() << 32) |
|
||||
csi_coret_get_value();
|
||||
|
||||
uint32_t tick_resolution = drv_get_sys_freq() / CONFIG_SYSTICK_HZ;
|
||||
|
||||
csi_coret_set_load(tmp_counter + tick_resolution);
|
||||
}
|
||||
|
||||
static rt_tick_t aic_timer_get_tick(struct rt_pm *pm)
|
||||
{
|
||||
rt_tick_t delta_tick;
|
||||
uint64_t delta_counter;
|
||||
uint32_t tick_resolution = drv_get_sys_freq() / CONFIG_SYSTICK_HZ;
|
||||
|
||||
resume_counter = ((uint64_t)csi_coret_get_valueh() << 32) |
|
||||
csi_coret_get_value();
|
||||
delta_counter = resume_counter - sleep_counter;
|
||||
|
||||
delta_tick = delta_counter / tick_resolution;
|
||||
|
||||
return delta_tick;
|
||||
}
|
||||
|
||||
static const struct rt_pm_ops aic_pm_ops =
|
||||
{
|
||||
aic_sleep,
|
||||
NULL,
|
||||
aic_timer_start,
|
||||
aic_timer_stop,
|
||||
aic_timer_get_tick,
|
||||
};
|
||||
|
||||
/**
|
||||
* This function initialize the power manager
|
||||
*/
|
||||
|
||||
int aic_pm_hw_init(void)
|
||||
{
|
||||
rt_uint8_t timer_mask = 0;
|
||||
|
||||
timer_mask = 1UL << PM_SLEEP_MODE_DEEP;
|
||||
/* initialize system pm module */
|
||||
rt_system_pm_init(&aic_pm_ops, timer_mask, RT_NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
INIT_BOARD_EXPORT(aic_pm_hw_init);
|
||||
257
bsp/artinchip/drv/pm/suspend_v10.S
Normal file
257
bsp/artinchip/drv/pm/suspend_v10.S
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2023-2024, ArtInChip Technology Co., Ltd
|
||||
*
|
||||
* Authors:
|
||||
* dwj <weijie.ding@artinchip.com>
|
||||
*/
|
||||
//# include <sbi/riscv_asm.h>
|
||||
|
||||
#define DDRC_BASE 0x18400000
|
||||
#define DDR_PHY_BASE 0x18500000
|
||||
#define GTC_CNTV 0x19050008
|
||||
#define CMU_DDR_REG 0x18020210
|
||||
#define CMU_PLL_FRA0_REG 0x18020020
|
||||
#define CMU_PLL_INT1_REG 0x18020004
|
||||
|
||||
.macro delay_200us
|
||||
li a0, GTC_CNTV
|
||||
ld a1, (a0) //start value 64bit
|
||||
1:
|
||||
ld a2, (a0) //current value 64bit
|
||||
sub a3, a2, a1 //t3 <--- t2 - t1
|
||||
li a4, 800 //GTC frequency is 4000000Hz, 200us counter 800
|
||||
bltu a3, a4, 1b
|
||||
2:
|
||||
.endm
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.option pic
|
||||
.global aic_suspend_resume
|
||||
aic_suspend_resume:
|
||||
//ddr self-refresh flow
|
||||
li t0, DDRC_BASE
|
||||
li t1, DDR_PHY_BASE
|
||||
|
||||
//check port status
|
||||
check_port_status:
|
||||
lw t2, 0x3fc(t0)
|
||||
bne t2, zero, check_port_status
|
||||
|
||||
//disable DDR port
|
||||
li t2, 0
|
||||
li t3, 0
|
||||
li t5, 5
|
||||
addi t0, t0, 0x490
|
||||
port_close_loop:
|
||||
add t0, t0, t2
|
||||
sw zero, (t0)
|
||||
addi t2, t2, 0xb0
|
||||
addi t3, t3, 1
|
||||
bltu t3, t5, port_close_loop
|
||||
|
||||
delay_200us
|
||||
|
||||
//enter self refresh
|
||||
li t0, DDRC_BASE
|
||||
lw t2, 0x30(t0)
|
||||
ori t2, t2, 0x21
|
||||
sw t2, 0x30(t0)
|
||||
check_ddr_enter_sr_status:
|
||||
lw t2, 0x4(t0)
|
||||
andi t2, t2, 0x3
|
||||
li t3, 0x3
|
||||
bne t2, t3, check_ddr_enter_sr_status
|
||||
|
||||
delay_200us
|
||||
|
||||
//en_dfi_dram_clk_disable
|
||||
lw t2, 0x30(t0)
|
||||
ori t2, t2, 0x8
|
||||
sw t2, 0x30(t0)
|
||||
|
||||
//disable PGCR0 reg CKEN bitfiled
|
||||
lw t2, 0x8(t1)
|
||||
li t3, 0x3ffffff
|
||||
and t2, t2, t3
|
||||
sw t2, 0x8(t1)
|
||||
|
||||
delay_200us
|
||||
|
||||
//disable DX0GCR reg DQ, DM, DQS
|
||||
lw t2, 0x1C0(t1)
|
||||
ori t2, t2, 0x30
|
||||
li t3, 0xffff3fff
|
||||
and t2, t2, t3
|
||||
li t3, 0x8000
|
||||
or t2, t2, t3
|
||||
sw t2, 0x1C0(t1)
|
||||
|
||||
//disable DX1GCR reg DQ, DM, DQS
|
||||
lw t2, 0x200(t1)
|
||||
ori t2, t2, 0x30
|
||||
li t3, 0xffff3fff
|
||||
and t2, t2, t3
|
||||
li t3, 0x8000
|
||||
or t2, t2, t3
|
||||
sw t2, 0x200(t1)
|
||||
|
||||
//disable DDR phy/bus clock
|
||||
li t1, CMU_DDR_REG
|
||||
lw t2, (t1)
|
||||
li t3, 0xfffaabff
|
||||
and t2, t2, t3
|
||||
sw t2, (t1)
|
||||
|
||||
delay_200us
|
||||
|
||||
//disable DDR phy update request
|
||||
li t1, DDR_PHY_BASE
|
||||
lw t2, 0x40(t1)
|
||||
li t3, 0xfffffffe
|
||||
and t2, t2, t3
|
||||
sw t2, 0x40(t1)
|
||||
|
||||
//disable DDR core controller clock
|
||||
li t1, CMU_DDR_REG
|
||||
lw t2, (t1)
|
||||
li t3, 0xfffffeff
|
||||
and t2, t2, t3
|
||||
sw t2, (t1)
|
||||
|
||||
delay_200us
|
||||
|
||||
//disable PLL_FRA0
|
||||
li t1, CMU_PLL_FRA0_REG
|
||||
lw t2, (t1)
|
||||
li t3, 0xfffaffff
|
||||
and t2, t2, t3
|
||||
sw t2, (t1)
|
||||
|
||||
//disable PLL_INT1
|
||||
li t1, CMU_PLL_INT1_REG
|
||||
lw t2, (t1)
|
||||
li t3, 0xfffaffff
|
||||
and t2, t2, t3
|
||||
sw t2, (t1)
|
||||
|
||||
wfi
|
||||
|
||||
//wakeup flow
|
||||
//enable PLL_INT1
|
||||
li t3, 0x50000
|
||||
or t2, t2, t3
|
||||
sw t2, (t1)
|
||||
|
||||
//enable PLL_FRA0
|
||||
li t1, CMU_PLL_FRA0_REG
|
||||
lw t2, (t1)
|
||||
li t3, 0x50000
|
||||
or t2, t2, t3
|
||||
sw t2, (t1)
|
||||
|
||||
delay_200us
|
||||
|
||||
//enable DDR phy/bus clock
|
||||
li t1, CMU_DDR_REG
|
||||
lw t2, (t1)
|
||||
li t3, 0x55400
|
||||
or t2, t2, t3
|
||||
sw t2, (t1)
|
||||
|
||||
delay_200us
|
||||
|
||||
//enable DDR phy update request
|
||||
li t1, DDR_PHY_BASE
|
||||
lw t2, 0x40(t1)
|
||||
ori t2, t2, 0x1
|
||||
sw t2, 0x40(t1)
|
||||
|
||||
//enable DDR core controller clock
|
||||
li t1, CMU_DDR_REG
|
||||
lw t2, (t1)
|
||||
ori t2, t2, 0x100
|
||||
sw t2, (t1)
|
||||
|
||||
//must reset PLL if the DDR core clock disabled in self-refresh state
|
||||
li t0, DDRC_BASE
|
||||
li t1, DDR_PHY_BASE
|
||||
|
||||
lw t2, 0x18(t1)
|
||||
li t3, 0x40000000
|
||||
or t2, t2, t3
|
||||
sw t2, 0x18(t1)
|
||||
|
||||
delay_200us
|
||||
|
||||
li t3, 0xbfffffff
|
||||
and t2, t2, t3
|
||||
sw t2, 0x18(t1)
|
||||
|
||||
delay_200us
|
||||
|
||||
//enable dfi_dram_clk
|
||||
lw t2, 0x30(t0)
|
||||
li t3, 0xFFFFFFF7
|
||||
and t2, t2, t3
|
||||
sw t2, 0x30(t0)
|
||||
|
||||
//enable PGCR0 reg CKEN bitfiled
|
||||
lw t2, 0x8(t1)
|
||||
li t3, 0x3ffffff
|
||||
and t2, t2, t3
|
||||
li t3, 0x8000000
|
||||
or t2, t2, t3
|
||||
sw t2, 0x8(t1)
|
||||
|
||||
delay_200us
|
||||
|
||||
//enable DX0GCR reg DQ, DM, DQS
|
||||
lw t2, 0x1C0(t1)
|
||||
li t3, 0xFFFF3FCF
|
||||
and t2, t2, t3
|
||||
sw t2, 0x1C0(t1)
|
||||
|
||||
//enable DX1GCR reg DQ, DM, DQS
|
||||
lw t2, 0x200(t1)
|
||||
li t3, 0xFFFF3FCF
|
||||
and t2, t2, t3
|
||||
sw t2, 0x200(t1)
|
||||
|
||||
delay_200us
|
||||
|
||||
//DDR exit self-refresh
|
||||
lw t2, 0x30(t0)
|
||||
li t3, 0xDE
|
||||
and t2, t2, t3
|
||||
sw t2, 0x30(t0) //exit self-refresh
|
||||
check_ddr_exit_sr_status:
|
||||
lw t2, 0x4(t0)
|
||||
andi t2, t2, 0x3
|
||||
li t3, 0x1
|
||||
bne t2, t3, check_ddr_exit_sr_status
|
||||
|
||||
delay_200us
|
||||
|
||||
li t2, 0
|
||||
li t3, 0
|
||||
li t4, 1
|
||||
li t5, 5
|
||||
addi t0, t0, 0x490
|
||||
port_open_loop:
|
||||
add t0, t0, t2
|
||||
sw t4, (t0)
|
||||
addi t2, t2, 0xb0
|
||||
addi t3, t3, 1
|
||||
bltu t3, t5, port_open_loop
|
||||
|
||||
ret
|
||||
aic_suspend_resume_end:
|
||||
|
||||
.data
|
||||
.align 3
|
||||
.global aic_suspend_resume_size
|
||||
aic_suspend_resume_size:
|
||||
.word aic_suspend_resume_end - aic_suspend_resume
|
||||
@@ -6,12 +6,15 @@
|
||||
* Authors:
|
||||
* dwj <weijie.ding@aic.com>
|
||||
*/
|
||||
#include <rtconfig.h>
|
||||
|
||||
#define DDRC_BASE 0x98400000
|
||||
#define DDR_PHY_BASE 0x98500000
|
||||
#define GTC_CNTVL 0x89050008
|
||||
#define GTC_CNTVH 0x8905000C
|
||||
#define PRCM_SW_VDD11_CTL 0x88000070
|
||||
#define PRCM_C908_VDD11_CTL 0x88000074
|
||||
#define PRCM_DDR_WAKEUP_STATUS 0x88000108
|
||||
|
||||
.macro delay_200us
|
||||
li s0, GTC_CNTVL
|
||||
@@ -58,7 +61,7 @@ port_close_loop:
|
||||
lw t1, 0x30(t0)
|
||||
ori t1, t1, 0x21
|
||||
sw t1, 0x30(t0)
|
||||
|
||||
#ifndef FPGA_BOARD_ARTINCHIP
|
||||
delay_200us
|
||||
|
||||
//step2: C908 VDD11 power down
|
||||
@@ -149,10 +152,11 @@ PD_PSA_check:
|
||||
and t1, t1, t2
|
||||
sw t1, (t0) //clear POWER_SWITCH_EN[7:0] bit0
|
||||
delay_200us
|
||||
|
||||
#endif
|
||||
//enter wfi
|
||||
wfi
|
||||
|
||||
#ifndef FPGA_BOARD_ARTINCHIP
|
||||
//step1: VDD11 SW power up
|
||||
li t0, PRCM_SW_VDD11_CTL
|
||||
lw t1, (t0)
|
||||
@@ -217,7 +221,7 @@ PU_PSD_check:
|
||||
delay_200us
|
||||
li t2, 0x10000
|
||||
or t1, t1, t2
|
||||
j .
|
||||
// set PMU_RESET, SESS will boot
|
||||
sw t1, (t0) //set PMU_RESET
|
||||
delay_200us
|
||||
|
||||
@@ -237,6 +241,7 @@ PU_C908_check:
|
||||
or t1, t1, t2
|
||||
sw t1, (t0) //set PMU_RESET
|
||||
delay_200us
|
||||
#endif
|
||||
|
||||
//step3: DDR exit self-refresh
|
||||
li t0, DDRC_BASE
|
||||
@@ -259,6 +264,8 @@ port_open_loop:
|
||||
addi t3, t3, 1
|
||||
bltu t3, t5, port_open_loop
|
||||
|
||||
.long 0x0100000b //icache.iall
|
||||
.long 0x0010000b //dcache.call
|
||||
ret
|
||||
aic_suspend_resume_end:
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
* dwj <weijie.ding@aic.com>
|
||||
*/
|
||||
|
||||
#define PRCM_CPU_STATUS 0x8800010C
|
||||
#define PRCM_SC_CONTEXT_ADDR 0x88000110
|
||||
#define PRCM_SCSS_CPU_STATUS 0x88000110
|
||||
#define PRCM_SC_CONTEXT_ADDR 0x8800011c
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
@@ -65,14 +65,13 @@ sc_save_context_and_suspend:
|
||||
csrr t0, mexstatus
|
||||
sw t0, 0x88(a0)
|
||||
|
||||
/* save sc context addr to 0x88000110 */
|
||||
/* save sc context addr to PRCM_SC_CONTEXT_ADDR */
|
||||
li t0, PRCM_SC_CONTEXT_ADDR
|
||||
sw a0, (t0)
|
||||
|
||||
/* Update CPU status to PRCM bank register */
|
||||
li t0, PRCM_CPU_STATUS
|
||||
lw t1, (t0)
|
||||
ori t1, t1, 0x2
|
||||
li t0, PRCM_SCSS_CPU_STATUS
|
||||
li t1, 1
|
||||
sw t1, (t0)
|
||||
|
||||
fence.i
|
||||
@@ -148,16 +147,13 @@ sc_restore_context_and_resume:
|
||||
lw t0, 0x88(a0)
|
||||
csrw mexstatus, t0
|
||||
|
||||
/* clear sc context addr to 0 in 0x88000110 */
|
||||
/* clear sc context addr to 0 in PRCM_SC_CONTEXT_ADDR */
|
||||
li t0, PRCM_SC_CONTEXT_ADDR
|
||||
sw zero, (t0)
|
||||
|
||||
/* clear CPU status to PRCM bank register */
|
||||
li t0, PRCM_CPU_STATUS
|
||||
lw t1, (t0)
|
||||
li t2, 0xFFFFFFFD
|
||||
and t1, t1, t2
|
||||
sw t1, (t0)
|
||||
li t0, PRCM_SCSS_CPU_STATUS
|
||||
sw zero, (t0)
|
||||
|
||||
ret
|
||||
sc_restore_context_and_resume_end:
|
||||
Reference in New Issue
Block a user