rk3026: add reset support

This commit is contained in:
黄涛
2013-08-08 16:22:16 +08:00
parent 803063762a
commit 20ff870b3c
2 changed files with 164 additions and 1 deletions

View File

@@ -2,7 +2,7 @@ ifneq ($(CONFIG_RK_FPGA),y)
obj-y += ../plat-rk/clock.o
obj-y += clock_data.o
obj-y += ../mach-rk2928/ddr.o
obj-y += ../mach-rk30/reset.o
obj-y += reset.o
obj-$(CONFIG_PM) += ../mach-rk2928/pm.o
endif
obj-y += common.o

View File

@@ -0,0 +1,163 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <mach/system.h>
#include <linux/string.h>
#include <mach/cru.h>
#include <mach/grf.h>
#include <mach/loader.h>
#include <mach/board.h>
//#define DEBUG // for jtag debug
#define cru_readl(offset) readl_relaxed(RK30_CRU_BASE + offset)
#define cru_writel(v, offset) do { writel_relaxed(v, RK30_CRU_BASE + offset); dsb(); } while (0)
#define grf_readl(offset) readl_relaxed(RK30_GRF_BASE + offset)
#define grf_writel(v, offset) do { writel_relaxed(v, RK30_GRF_BASE + offset); dsb(); } while (0)
static bool is_panic = false;
static int panic_event(struct notifier_block *this, unsigned long event, void *ptr)
{
is_panic = true;
return NOTIFY_DONE;
}
static struct notifier_block panic_block = {
.notifier_call = panic_event,
};
static int __init arch_reset_init(void)
{
atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
return 0;
}
core_initcall(arch_reset_init);
#ifdef DEBUG
__sramdata volatile int reset_loop = 1;
#endif
static void __sramfunc __noreturn soft_reset(void)
{
/* pll enter slow mode */
cru_writel(0xffff0000, CRU_MODE_CON);
/* restore clock select and divide */
cru_writel(0xffff0200, CRU_CLKSELS_CON(0));
cru_writel(0xffff3113, CRU_CLKSELS_CON(1));
cru_writel(0xfff00000, CRU_CLKSELS_CON(2)); // 3:0 reserved
cru_writel(0xffff0200, CRU_CLKSELS_CON(3));
cru_writel(0x003f0000, CRU_CLKSELS_CON(4)); // 15:6 reserved
cru_writel(0x003f0000, CRU_CLKSELS_CON(5)); // 15:6 reserved
cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(6));
cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(7));
cru_writel(0xffff2100, CRU_CLKSELS_CON(10));
cru_writel(0x007f0017, CRU_CLKSELS_CON(11)); // 15:7 reserved
cru_writel(0xffff1717, CRU_CLKSELS_CON(12));
cru_writel(0xffff0200, CRU_CLKSELS_CON(13));
cru_writel(0xffff0200, CRU_CLKSELS_CON(14));
cru_writel(0xffff0200, CRU_CLKSELS_CON(15));
cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(17));
cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(18));
cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(19));
cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(23));
cru_writel(0xffff1700, CRU_CLKSELS_CON(24));
cru_writel(0x017f0107, CRU_CLKSELS_CON(25)); // 15:9 7 reserved
cru_writel(0xffff0000, CRU_CLKSELS_CON(26));
cru_writel(0xffff0700, CRU_CLKSELS_CON(27));
cru_writel(0xffff0700, CRU_CLKSELS_CON(28));
cru_writel(0xffff0012, CRU_CLKSELS_CON(29));
cru_writel(0xffff0300, CRU_CLKSELS_CON(30));
cru_writel(0xffff0001, CRU_CLKSELS_CON(31));
cru_writel(0xffff0303, CRU_CLKSELS_CON(32));
cru_writel(0xffff0003, CRU_CLKSELS_CON(34));
/* idle request PERI/VIO/VPU/GPU */
grf_writel(0x1e00ffff, GRF_SOC_CON2);
while ((grf_readl(GRF_SOC_STATUS0) & (0x1e << 16)) != (0x1e << 16))
;
while ((grf_readl(GRF_SOC_STATUS0) & (0x1e << 22)) != (0x1e << 22))
;
/* software reset modules */
#ifdef DEBUG
cru_writel(0xfff3ffff, CRU_SOFTRSTS_CON(8)); // CORE_DBG/DBG_APB
#else
cru_writel(0xffffffff, CRU_SOFTRSTS_CON(8));
#endif
cru_writel(0xffffffff, CRU_SOFTRSTS_CON(7));
cru_writel(0xffffffff, CRU_SOFTRSTS_CON(6));
cru_writel(0xffffffff, CRU_SOFTRSTS_CON(5));
cru_writel(0x7fffffff, CRU_SOFTRSTS_CON(4)); // DDRMSCH
#ifdef DEBUG
cru_writel(0xff63ffff, CRU_SOFTRSTS_CON(3)); // DAP_PO/DAP/DAP_SYS
#else
cru_writel(0xff7fffff, CRU_SOFTRSTS_CON(3)); // GRF
#endif
cru_writel(0xfff0ffff, CRU_SOFTRSTS_CON(2)); // GPIO0/1/2/3
cru_writel(0xffdfffff, CRU_SOFTRSTS_CON(1)); // INTMEM
#ifdef DEBUG
cru_writel(0x1e60ffff, CRU_SOFTRSTS_CON(0)); // MCORE_DBG/CORE0_DBG
#else
cru_writel(0x1fe0ffff, CRU_SOFTRSTS_CON(0)); // CORE_SRST_WDT_SEL/MCORE/CORE0/CORE1/ACLK_CORE/STRC_SYS_AXI/L2C
#endif
sram_udelay(1000);
cru_writel(0xffff0000, CRU_SOFTRSTS_CON(0));
cru_writel(0xffff0000, CRU_SOFTRSTS_CON(1));
cru_writel(0xffff0000, CRU_SOFTRSTS_CON(2));
cru_writel(0xffff0000, CRU_SOFTRSTS_CON(3));
cru_writel(0xffff0000, CRU_SOFTRSTS_CON(4));
cru_writel(0xffff0000, CRU_SOFTRSTS_CON(5));
cru_writel(0xffff0000, CRU_SOFTRSTS_CON(6));
cru_writel(0xffff0000, CRU_SOFTRSTS_CON(7));
cru_writel(0xffff0000, CRU_SOFTRSTS_CON(8));
/* disable idle request */
grf_writel(0x3f000000, GRF_SOC_CON2);
while (grf_readl(GRF_SOC_STATUS0) & (0x3f << 16))
;
while (grf_readl(GRF_SOC_STATUS0) & (0x3f << 22))
;
#ifdef DEBUG
// while (reset_loop);
#endif
cru_writel(0x801cffff, CRU_SOFTRSTS_CON(0)); // MCORE/CORE0/CORE1/L2C
while (1);
}
static void rk30_arch_reset(char mode, const char *cmd)
{
unsigned i;
u32 boot_flag = 0;
u32 boot_mode = BOOT_MODE_REBOOT;
if (cmd) {
if (!strcmp(cmd, "loader") || !strcmp(cmd, "bootloader"))
boot_flag = SYS_LOADER_REBOOT_FLAG + BOOT_LOADER;
else if(!strcmp(cmd, "recovery"))
boot_flag = SYS_LOADER_REBOOT_FLAG + BOOT_RECOVER;
else if (!strcmp(cmd, "charge"))
boot_mode = BOOT_MODE_CHARGE;
} else {
if (is_panic)
boot_mode = BOOT_MODE_PANIC;
}
grf_writel(boot_flag, GRF_OS_REG4); // for loader
grf_writel(boot_mode, GRF_OS_REG5); // for linux
/* enable all clock */
for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
cru_writel(0xffff0000, CRU_CLKGATES_CON(i));
/* disable remap */
grf_writel(1 << (12 + 16), GRF_SOC_CON0);
((void(*)(void))((u32)soft_reset - (u32)RK30_IMEM_BASE + (u32)RK30_IMEM_NONCACHED))();
}
void (*arch_reset)(char, const char *) = rk30_arch_reset;