162 lines
5.5 KiB
C
162 lines
5.5 KiB
C
/*
|
|
* Kneron Power Base driver
|
|
*
|
|
* Copyright (C) 2019 Kneron, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
#include "kdrv_power.h"
|
|
#include "kdrv_scu.h"
|
|
#include "kdrv_scu_ext.h"
|
|
#include "kdrv_system.h"
|
|
#include "kdrv_clock.h" // for kdrv_delay_us()
|
|
#include "kdrv_ddr.h"
|
|
//#include "kmdw_console.h"
|
|
|
|
/************************************************************************
|
|
* Power Register Releated Macros
|
|
************************************************************************/
|
|
#define POWER_DOMAIN_WORKING_NONE 0x00000000
|
|
#define POWER_DOMAIN_WORKING_DEFAULT 0x00000001
|
|
#define POWER_DOMAIN_WORKING_NPU 0x00000002
|
|
#define POWER_DOMAIN_WORKING_DDR 0x00000004
|
|
#define POWER_DOMAIN_WORKING_ALL (POWER_DOMAIN_WORKING_DEFAULT | POWER_DOMAIN_WORKING_NPU | POWER_DOMAIN_WORKING_DDR)
|
|
|
|
#define POWER_DOMAIN_SOFTOFF_DEFAULT 0x00000010
|
|
#define POWER_DOMAIN_SOFTOFF_NPU 0x00000020
|
|
#define POWER_DOMAIN_SOFTOFF_DDR 0x00000040
|
|
|
|
#define POWER_DOMAIN_SOFTOFF_MASK (POWER_DOMAIN_SOFTOFF_DEFAULT | \
|
|
POWER_DOMAIN_SOFTOFF_NPU | \
|
|
POWER_DOMAIN_SOFTOFF_DDR)
|
|
|
|
#define PWR_CTRL_SOFTOFF_MASK (SCU_REG_PWR_CTRL_PWRUP_UPDATE | \
|
|
SCU_REG_PWR_CTRL_PWRUP_CTRL_MASK | \
|
|
SCU_REG_PWR_CTRL_PWRDN_CTRL_MASK)
|
|
|
|
#define PWR_CTRL_SOFTOFF_DEEP_RETENTION (SCU_REG_PWR_CTRL_PWRUP_UPDATE | \
|
|
SCU_REG_PWR_CTRL_PWRUP_CTRL_DOMAIN_DDRCK | \
|
|
SCU_REG_PWR_CTRL_PWRUP_CTRL_DOMAIN_DEFAULT | \
|
|
SCU_REG_PWR_CTRL_PWRDN_CTRL_DOMAIN_DDRCK)
|
|
|
|
#define PWR_CTRL_SOFTOFF_RTC_MODE (SCU_REG_PWR_CTRL_PWRUP_UPDATE | \
|
|
SCU_REG_PWR_CTRL_PWRUP_CTRL_DOMAIN_DEFAULT)
|
|
|
|
kdrv_power_mode_t __power_mgr_mode = POWER_MODE_RTC;
|
|
|
|
/************************************************************************
|
|
* Private API
|
|
************************************************************************/
|
|
static void _power_mgr_ops_fcs()
|
|
{
|
|
masked_outw(SCU_REG_PWR_MOD,
|
|
SCU_REG_PWR_MOD_SELFR_CMD_OFF | //scu will NOT issue the self-refresh command to DDR/SDR (in FCS)
|
|
SCU_REG_PWR_MOD_FCS_PLL_RSTn | //Keep PLL active in FCS
|
|
SCU_REG_PWR_MOD_FCS, //enter FCS
|
|
|
|
SCU_REG_PWR_MOD_SELFR_CMD_OFF | SCU_REG_PWR_MOD_FCS_PLL2_RSTn |
|
|
SCU_REG_PWR_MOD_FCS_DLL_RSTn | SCU_REG_PWR_MOD_FCS_PLL_RSTn |
|
|
SCU_REG_PWR_MOD_FCS | SCU_REG_PWR_MOD_BUS_SPEED);
|
|
}
|
|
|
|
/************************************************************************
|
|
* Public API
|
|
************************************************************************/
|
|
void kdrv_power_sw_reset(void)
|
|
{
|
|
//err_msg("Set watchdog reset\n");
|
|
|
|
outw(WDT_FTWDT010_PA_BASE+0x0C, 0);
|
|
outw(WDT_FTWDT010_PA_BASE+0x04, 1000);
|
|
outw(WDT_FTWDT010_PA_BASE+0x0C, 0x03); // system reset
|
|
outw(WDT_FTWDT010_PA_BASE+0x08, 0x5AB9);
|
|
|
|
__WFI();
|
|
}
|
|
|
|
kdrv_status_t kdrv_power_set_domain(kdrv_power_domain_t domain, int enable)
|
|
{
|
|
uint32_t val, mask, vcc_ready, misc_pwr, wait_state;
|
|
|
|
switch (domain) {
|
|
case POWER_DOMAIN_DDRCK:
|
|
mask = SCU_REG_PWR_CTRL_PWRUP_CTRL_DOMAIN_DDRCK;
|
|
vcc_ready = SCU_REG_PWR_VCCSTS_PWR_READY_DOMAIN_DDRCK;
|
|
misc_pwr = SCU_EXTREG_MISC_PWR_RESET_RELEASE_DOMAIN_DDRCK;
|
|
break;
|
|
case POWER_DOMAIN_NPU:
|
|
mask = SCU_REG_PWR_CTRL_PWRUP_CTRL_DOMAIN_NPU;
|
|
vcc_ready = SCU_REG_PWR_VCCSTS_PWR_READY_DOMAIN_NPU;
|
|
misc_pwr = SCU_EXTREG_MISC_PWR_RESET_RELEASE_DOMAIN_NPU;
|
|
break;
|
|
case POWER_DOMAIN_DEFAULT:
|
|
mask = SCU_REG_PWR_CTRL_PWRUP_CTRL_DOMAIN_DEFAULT;
|
|
vcc_ready = SCU_REG_PWR_VCCSTS_PWR_READY_DOMAIN_DEFAULT;
|
|
misc_pwr = SCU_EXTREG_MISC_PWR_RESET_RELEASE_DOMAIN_DEFAULT;
|
|
break;
|
|
default:
|
|
return KDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
val = enable? mask : 0;
|
|
val |= SCU_REG_PWR_CTRL_PWRUP_UPDATE;
|
|
mask |= SCU_REG_PWR_CTRL_PWRUP_UPDATE;
|
|
|
|
masked_outw(SCU_REG_PWR_CTRL, val, mask);
|
|
kdrv_delay_us(500);
|
|
|
|
/* Wait for VCC change */
|
|
wait_state = enable? vcc_ready : 0;
|
|
do {
|
|
val = inw(SCU_REG_PWR_VCCSTS);
|
|
} while((val & vcc_ready) != wait_state);
|
|
|
|
/* Wait for power reset change */
|
|
wait_state = enable? misc_pwr : 0;
|
|
do {
|
|
val = inw(SCU_EXTREG_MISC);
|
|
} while((val & misc_pwr) != wait_state);
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_power_softoff(kdrv_power_mode_t mode)
|
|
{
|
|
uint32_t val;
|
|
|
|
switch (mode) {
|
|
case POWER_MODE_DEEP_RETENTION:
|
|
val = PWR_CTRL_SOFTOFF_DEEP_RETENTION;
|
|
break;
|
|
case POWER_MODE_RTC:
|
|
val = PWR_CTRL_SOFTOFF_RTC_MODE;
|
|
break;
|
|
default:
|
|
return KDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
masked_outw(SCU_REG_PWR_CTRL, val, PWR_CTRL_SOFTOFF_MASK);
|
|
SCU_REG_PWR_MOD_SET_SOFTOFF(1);
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_power_ops(kdrv_power_ops_t ops)
|
|
{
|
|
switch (ops) {
|
|
case POWER_OPS_FCS:
|
|
_power_mgr_ops_fcs();
|
|
break;
|
|
case POWER_OPS_CHANGE_BUS_SPEED:
|
|
break;
|
|
case POWER_OPS_PLL_UPDATE:
|
|
break;
|
|
case POWER_OPS_SLEEPING:
|
|
//stop cpu
|
|
//stop ddr
|
|
//send self-refresh command to ddr
|
|
//wait ack
|
|
break;
|
|
default:
|
|
return KDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
return KDRV_STATUS_OK;
|
|
}
|