rt-thread/bsp/allwinner/libraries/sunxi-hal/hal/source/prcm/prcm-sun50iw11/power.c

186 lines
5.2 KiB
C
Raw Normal View History

/*
*********************************************************************************************************
* AR100 SYSTEM
* AR100 Software System Develop Kits
* clock control unit module
*
* (c) Copyright 2012-2016, Sunny China
* All Rights Reserved
*
* File : power.c
* By : Sunny
* Version : v1.0
* Date : 2012-11-22
* Descript: module power manager.
* Update : date auther ver notes
* 2012-11-22 16:44:06 Sunny 1.0 Create this file.
*********************************************************************************************************
*/
#include "ccu_i.h"
#include "cpucfg_regs.h"
#include "hal_prcm.h"
#include "aw_io.h"
#include "aw_io.h"
#include "aw_common.h"
#include "errno.h"
#include "notifier.h"
#include "delay.h"
#include "platform.h"
static u32 hosc_lock;
static u32 pll_ldo_suspend;
/*
*********************************************************************************************************
* SET POWER OFF STATUS OF HWMODULE
*
* Description: set the power off gating status of a specific module.
*
* Arguments : module : the module ID which we want to set power off gating status.
* state : the power off status which we want to set, the detail please
* refer to the status of power-off gating.
*
* Returns : OK if set module power off gating status succeeded, others if failed.
*********************************************************************************************************
*/
s32 ccu_set_poweroff_gating_state(s32 module, s32 state)
{
volatile u32 value;
switch (module) {
case PWRCTL_C0CPU0:
{
value = readl(C0_CPUX_POWEROFF_GATING_REG);
value &= (~(0x1 << 0));
value |= (state & 0x1) << 0;
writel(value, C0_CPUX_POWEROFF_GATING_REG);
return OK;
}
case PWRCTL_C0CPU1:
{
value = readl(C0_CPUX_POWEROFF_GATING_REG);
value &= (~(0x1 << 1));
value |= (state & 0x1) << 1;
writel(value, C0_CPUX_POWEROFF_GATING_REG);
return OK;
}
case PWRCTL_C0CPUX:
{
value = readl(C0_CPUX_POWEROFF_GATING_REG);
value &= (~(0x1 << 4));
value |= (state & 0x1) << 4;
writel(value, C0_CPUX_POWEROFF_GATING_REG);
return OK;
}
case PWRCTL_VDD_CPUS:
{
ccu_reg_addr->sys_pwroff_gate.vdd_cpus_gate = state;
return OK;
}
case PWRCTL_VDD_AVCC_A:
{
ccu_reg_addr->ana_pwroff_gate.avcc_a_gate = state;
return OK;
}
default:
{
pr_warning(
"invaid power control module (%d) when set power-off gating\n",
module);
return -EINVAL;
}
}
/* un-reached */
}
struct notifier *hosc_notifier_list = NULL;
s32 ccu_24mhosc_reg_cb(__pNotifier_t pcb)
{
/* insert call-back to hosc_notifier_list. */
return notifier_insert(&hosc_notifier_list, pcb);
}
#define XO_CTRL_REG (SUNXI_R_RTC_PBASE+0x160)
#define DCXO_EN_SHFIT (1)
s32 ccu_24mhosc_disable(void)
{
u32 value = 0;
hosc_lock = 1;
/* notify 24mhosc will power-off */
pr_info("broadcast 24mhosc will power-off\n");
notifier_notify(&hosc_notifier_list, CCU_HOSC_WILL_OFF_NOTIFY, 0);
/* FIXME: in real board */
/* disable 24mhosc */
value = readl(XO_CTRL_REG);
value &= ~(0x1 << DCXO_EN_SHFIT);
writel(value, XO_CTRL_REG);
/* wait 20 cycles */
udelay(20);
/* save pll voltage */
pll_ldo_suspend = (readl(CCU_PLL_CTRL1) >> 16) & 0x7;
/* power-off pll ldo */
value = (readl(CCU_PLL_CTRL1) | (0xa7 << 24));
writel(value, CCU_PLL_CTRL1);
value = (readl(CCU_PLL_CTRL1) | (0xa7 << 24));
value &= (~(0x1 << 0));
writel(value, CCU_PLL_CTRL1);
return OK;
}
s32 ccu_24mhosc_enable(void)
{
u32 value = 0;
volatile int i = 0;
/* power-on pll ldo */
value = (readl(CCU_PLL_CTRL1) | (0xa7 << 24));
writel(value, CCU_PLL_CTRL1);
value = (readl(CCU_PLL_CTRL1) | (0xa7 << 24));
value |= (0x1 << 0);
writel(value, CCU_PLL_CTRL1);
/* wait 2ms for power-on ready */
for (i = 64; i; i--) ;
/* adjust pll voltage */
value = (readl(CCU_PLL_CTRL1) | (0xa7 << 24));
writel(value, CCU_PLL_CTRL1);
value = (readl(CCU_PLL_CTRL1) | (0xa7 << 24));
value &= (~(0x7 << 16));
value |= (pll_ldo_suspend << 16);
writel(value, CCU_PLL_CTRL1);
/* wait 2ms for voltage ready */
for (i = 64; i; i--) ;
/* FIXME: in real board */
/* enable 24mhosc */
value = readl(XO_CTRL_REG);
value |= (0x1 << DCXO_EN_SHFIT);
writel(value, XO_CTRL_REG);
/* wait 2ms for 24m hosc ready */
for (i = 64; i; i--) ;
/* notify 24mhosc power-on ready */
pr_info("broadcast 24mhosc power-on ready\n");
notifier_notify(&hosc_notifier_list, CCU_HOSC_ON_READY_NOTIFY, 0);
hosc_lock = 0;
return OK;
}
s32 is_hosc_lock(void)
{
return hosc_lock;
}