mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 21:07:02 +09:00
rk3026: add reset support
This commit is contained in:
@@ -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
|
||||
|
||||
163
arch/arm/mach-rk3026/reset.c
Normal file
163
arch/arm/mach-rk3026/reset.c
Normal 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;
|
||||
Reference in New Issue
Block a user