rt-thread-official/bsp/x1000/drivers/drv_pmu.c

253 lines
6.7 KiB
C
Raw Blame History

/*
* File : drv_pmu.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2016-03-29 Urey the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <stdint.h>
#include "board.h"
#include "drv_clock.h"
#include "drv_gpio.h"
#include "drv_ost.h"
#include "drv_rtc.h"
struct sleep_save_register
{
unsigned int lcr;
unsigned int opcr;
unsigned int sleep_voice_enable;
unsigned int ddr_training_space[20];
};
static struct sleep_save_register s_reg;
static void write_aic_register(unsigned int addr,unsigned char val)
{
while(REG_ICDC_RGADW & (1 << 16));
REG_ICDC_RGADW = (1 << 16) | (addr << 8) | val;
}
static void _delay_us(rt_uint32_t ns)
{
volatile rt_uint16_t delay;
while(ns--)
{
delay = 200;
while(delay--);
}
}
static void _delay_ms(rt_uint32_t ms)
{
volatile rt_uint16_t delay;
while(ms--)
{
_delay_us(1000);
}
}
#if 0
static int jz_pm_do_sleep(void)
{
unsigned int div;
unsigned long opcr = REG_CPM_OPCR;
unsigned long icmr0 = REG_INTC_IMCR(0);
unsigned long icmr1 = REG_INTC_IMCR(1);
unsigned long sleep_gpio_save[5*(GPIO_NR_PORTS)];
unsigned long cpuflags;
unsigned long msc0cdr = REG_CPM_MSC0CDR;
void (*resume_addr)(void);
unsigned int val;
unsigned int gint_mask = REG_GINT_MASK;
unsigned int level = rt_hw_interrupt_disable();
unsigned int clkgr0 = REG_CPM_CLKGR0;
/* set SLEEP mode */
//CMSREG32(CPM_LCR, LCR_LPM_SLEEP, LCR_LPM_MASK);
REG_CPM_CLKGR0 &= ~(1 << 11);
write_aic_register(0x13, 0x10);
write_aic_register(0xd, 0xb1);
write_aic_register(0xe, 0xb5);
*(volatile unsigned int *)0xb000003c |= (1 << 25) | (1 << 21) | (1 << 20);
REG_CPM_CLKGR0 = 0x0fdefff7;
/* Mask all interrupts */
REG_INTC_IMCR(0) = 0xffffffff;
REG_INTC_IMCR(1) = 0xffffffff;
REG_GINT_MASK = 0;
REG_GINT_MASK = 1 << 31;
*((volatile unsigned int *)(0xb2000038)) = 1;
/* OUTREG32(INTC_ICMCR(0), 0xffffffff); */
/* /\* unmask rtc interrupts *\/ */
/* OUTREG32(INTC_ICMCR(1), 0x1); */
/* Sleep on-board modules */
jzsoc_do_sleep(sleep_gpio_save);
/* config_irq_wakeup(); */
load_pm_firmware_new(SLEEP_TCSM_SPACE);
sleep_param = (struct sleep_param *)SLEEP_TCSM_SPACE;
sleep_param->post_resume_pc = (unsigned int)restore_goto;
sleep_param->uart_id = 2;
memcpy(&s_reg.ddr_training_space,(void*)0x80000000,sizeof(s_reg.ddr_training_space));
s_reg.opcr = INREG32(CPM_OPCR);
s_reg.lcr = INREG32(CPM_LCR);
/*
* set OPCR.
*/
val = s_reg.opcr;
#if 0
val &= ~((1 << 25) | (1 << 22) | (0xfff << 8) | (1 << 7) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 2));
val |= (1 << 31) | (1 << 30) | (1 << 25) | (1 << 23) | (0xfff << 8) | (1 << 4) | (1 << 3) | (1 << 2);
#else
val &= ~((1 << 31)|(1 << 30)| (1 << 25) | (1 << 22) | (0xfff << 8) | (1 << 7) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 2));
val |= (1 << 25) | (1 << 23) | (0xfff << 8) | (1 << 3) | (1 << 2) | (1 << 4);
#endif
REG_CPM_OPCR = val;
*(volatile unsigned int *)0xb000003c &= ~(1 << 31);
*(volatile unsigned int *)0xb000003c |= (1 << 20);
val = s_reg.lcr;
val &= ~3;
//val |= 1;
val |= 0xff << 8; /* power stable time */
REG_CPM_LCR = val;
// *(volatile unsigned int *)0xb0000010 &= ~(1 << 8);
// *(volatile unsigned int *)0xb0000014 &= ~(1 << 7);
printf("clkgr = 0x%08x\n", *(volatile unsigned int *)0xb0000020);
printf("opcr = 0x%08x\n", *(volatile unsigned int *)0xb0000024);
printf("otg phy = 0x%08x\n", *(volatile unsigned int *)0xb0000048);
printf("otg = 0x%08x\n", *(volatile unsigned int *)0xb0000050);
mb();
save_goto((unsigned int)sleep_param->pm_core_enter);
mb();
memcpy((void*)0x80000000,&s_reg.ddr_training_space,sizeof(s_reg.ddr_training_space));
dma_cache_wback_inv(0x80000000,sizeof(s_reg.ddr_training_space));
OUTREG32(CPM_LCR, s_reg.lcr);
OUTREG32(CPM_OPCR, s_reg.opcr);
spin_unlock_irqrestore(sr);
REG_GINT_MASK = gint_mask;
/* Restore interrupts */
//*((volatile unsigned int *)(0xb2000008)) = 1;
REG_CPM_CLKGR0 = clkgr0;
*((volatile unsigned int *)(0xb2000034)) = 1;
OUTREG32(INTC_ICMR(0), icmr0);
OUTREG32(INTC_ICMR(1), icmr1);
/* Resume on-board modules */
jzsoc_do_resume(sleep_gpio_save);
/* Restore Oscillator and Power Control Register */
/* OUTREG32(CPM_OPCR, opcr); */
return 0;
}
#endif
/*
* Function: Keep power for CPU core when reset.
* So that EPC, tcsm and so on can maintain it's status after reset-key pressed.
*/
int reset_keep_power(void)
{
rtc_write_reg(RTC_BASE + RTC_PWRONCR, rtc_read_reg(RTC_BASE + RTC_PWRONCR) & ~(1 << 0));
return 0;
}
int drv_pmu_get_keypwr(void)
{
int level = 0;
#ifdef BOARD_CANNA_OVC
level = gpio_get_value(DET_PWR_PORT,DET_PWR_PIN);
do
{
_delay_ms(5); //ȥ<><C8A5>
}while(level != gpio_get_value(DET_PWR_PORT,DET_PWR_PIN));
#endif
return level;
}
void drv_pmu_power_down(void)
{
#ifdef BOARD_CANNA_OVC
rt_kprintf("SET STB down...\n");
gpio_set_value(EXT_DEV_RST_PORT, EXT_DEV_RST_PIN, 0);
gpio_direction_output(CTR_STB_PORT, CTR_STB_PIN, 0);
_delay_ms(100);
gpio_direction_output(CTR_LOCK_PORT, CTR_LOCK_PIN, 1);
_delay_ms(100);
rt_hw_led_off(LED_GREEN);
rt_hw_led_off(LED_RED);
rt_hw_led_off(LED_BLUE);
#endif
}
void drv_pmu_power_up(void)
{
}
int drv_pmu_init(void)
{
volatile unsigned int lcr, opcr;
/* init opcr and lcr for idle */
lcr = cpm_inl(CPM_LCR);
lcr &= ~(0x3); /* LCR.SLEEP.DS=0'b0,LCR.LPM=1'b00*/
lcr |= 0xff << 8; /* power stable time */
cpm_outl(lcr, CPM_LCR);
opcr = cpm_inl(CPM_OPCR);
opcr |= 0xff << 8; /* EXCLK stable time */
opcr &= ~(1 << 4); /* EXCLK stable time */
cpm_outl(opcr, CPM_OPCR);
return 0;
}