forked from luck/tmp_suning_uos_patched
watchdog: octeon-wdt: Remove old boot vector code.
Signed-off-by: Steven J. Hill <steven.hill@cavium.com> Acked-by: David Daney <david.daney@cavium.com> Acked-by: Guenter Roeck <linux@roeck-us.net> Cc: linux-mips@linux-mips.org Cc: linux-watchdog@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/17209/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
9438a86a07
commit
49d148b4e5
|
@ -73,6 +73,7 @@
|
|||
#include <asm/uasm.h>
|
||||
|
||||
#include <asm/octeon/octeon.h>
|
||||
#include <asm/octeon/cvmx-boot-vector.h>
|
||||
|
||||
/* The count needed to achieve timeout_sec. */
|
||||
static unsigned int timeout_cnt;
|
||||
|
@ -104,122 +105,10 @@ MODULE_PARM_DESC(nowayout,
|
|||
"Watchdog cannot be stopped once started (default="
|
||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
static u32 nmi_stage1_insns[64] __initdata;
|
||||
/* We need one branch and therefore one relocation per target label. */
|
||||
static struct uasm_label labels[5] __initdata;
|
||||
static struct uasm_reloc relocs[5] __initdata;
|
||||
|
||||
enum lable_id {
|
||||
label_enter_bootloader = 1
|
||||
};
|
||||
|
||||
/* Some CP0 registers */
|
||||
#define K0 26
|
||||
#define C0_CVMMEMCTL 11, 7
|
||||
#define C0_STATUS 12, 0
|
||||
#define C0_EBASE 15, 1
|
||||
#define C0_DESAVE 31, 0
|
||||
static struct cvmx_boot_vector_element *octeon_wdt_bootvector;
|
||||
|
||||
void octeon_wdt_nmi_stage2(void);
|
||||
|
||||
static void __init octeon_wdt_build_stage1(void)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
u32 *p = nmi_stage1_insns;
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
struct uasm_label *l = labels;
|
||||
struct uasm_reloc *r = relocs;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For the next few instructions running the debugger may
|
||||
* cause corruption of k0 in the saved registers. Since we're
|
||||
* about to crash, nobody probably cares.
|
||||
*
|
||||
* Save K0 into the debug scratch register
|
||||
*/
|
||||
uasm_i_dmtc0(&p, K0, C0_DESAVE);
|
||||
|
||||
uasm_i_mfc0(&p, K0, C0_STATUS);
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
if (octeon_bootloader_entry_addr)
|
||||
uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI),
|
||||
label_enter_bootloader);
|
||||
#endif
|
||||
/* Force 64-bit addressing enabled */
|
||||
uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX);
|
||||
uasm_i_mtc0(&p, K0, C0_STATUS);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
if (octeon_bootloader_entry_addr) {
|
||||
uasm_i_mfc0(&p, K0, C0_EBASE);
|
||||
/* Coreid number in K0 */
|
||||
uasm_i_andi(&p, K0, K0, 0xf);
|
||||
/* 8 * coreid in bits 16-31 */
|
||||
uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
|
||||
uasm_i_ori(&p, K0, K0, 0x8001);
|
||||
uasm_i_dsll_safe(&p, K0, K0, 16);
|
||||
uasm_i_ori(&p, K0, K0, 0x0700);
|
||||
uasm_i_drotr_safe(&p, K0, K0, 32);
|
||||
/*
|
||||
* Should result in: 0x8001,0700,0000,8*coreid which is
|
||||
* CVMX_CIU_WDOGX(coreid) - 0x0500
|
||||
*
|
||||
* Now ld K0, CVMX_CIU_WDOGX(coreid)
|
||||
*/
|
||||
uasm_i_ld(&p, K0, 0x500, K0);
|
||||
/*
|
||||
* If bit one set handle the NMI as a watchdog event.
|
||||
* otherwise transfer control to bootloader.
|
||||
*/
|
||||
uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
|
||||
uasm_i_nop(&p);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Clear Dcache so cvmseg works right. */
|
||||
uasm_i_cache(&p, 1, 0, 0);
|
||||
|
||||
/* Use K0 to do a read/modify/write of CVMMEMCTL */
|
||||
uasm_i_dmfc0(&p, K0, C0_CVMMEMCTL);
|
||||
/* Clear out the size of CVMSEG */
|
||||
uasm_i_dins(&p, K0, 0, 0, 6);
|
||||
/* Set CVMSEG to its largest value */
|
||||
uasm_i_ori(&p, K0, K0, 0x1c0 | 54);
|
||||
/* Store the CVMMEMCTL value */
|
||||
uasm_i_dmtc0(&p, K0, C0_CVMMEMCTL);
|
||||
|
||||
/* Load the address of the second stage handler */
|
||||
UASM_i_LA(&p, K0, (long)octeon_wdt_nmi_stage2);
|
||||
uasm_i_jr(&p, K0);
|
||||
uasm_i_dmfc0(&p, K0, C0_DESAVE);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
if (octeon_bootloader_entry_addr) {
|
||||
uasm_build_label(&l, p, label_enter_bootloader);
|
||||
/* Jump to the bootloader and restore K0 */
|
||||
UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
|
||||
uasm_i_jr(&p, K0);
|
||||
uasm_i_dmfc0(&p, K0, C0_DESAVE);
|
||||
}
|
||||
#endif
|
||||
uasm_resolve_relocs(relocs, labels);
|
||||
|
||||
len = (int)(p - nmi_stage1_insns);
|
||||
pr_debug("Synthesized NMI stage 1 handler (%d instructions)\n", len);
|
||||
|
||||
pr_debug("\t.set push\n");
|
||||
pr_debug("\t.set noreorder\n");
|
||||
for (i = 0; i < len; i++)
|
||||
pr_debug("\t.word 0x%08x\n", nmi_stage1_insns[i]);
|
||||
pr_debug("\t.set pop\n");
|
||||
|
||||
if (len > 32)
|
||||
panic("NMI stage 1 handler exceeds 32 instructions, was %d\n",
|
||||
len);
|
||||
}
|
||||
|
||||
static int cpu2core(int cpu)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -402,6 +291,8 @@ static int octeon_wdt_cpu_online(unsigned int cpu)
|
|||
|
||||
core = cpu2core(cpu);
|
||||
|
||||
octeon_wdt_bootvector[core].target_ptr = (u64)octeon_wdt_nmi_stage2;
|
||||
|
||||
/* Disable it before doing anything with the interrupts. */
|
||||
ciu_wdog.u64 = 0;
|
||||
cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
|
||||
|
@ -544,6 +435,12 @@ static int __init octeon_wdt_init(void)
|
|||
int ret;
|
||||
u64 *ptr;
|
||||
|
||||
octeon_wdt_bootvector = cvmx_boot_vector_get();
|
||||
if (!octeon_wdt_bootvector) {
|
||||
pr_err("Error: Cannot allocate boot vector.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Watchdog time expiration length = The 16 bits of LEN
|
||||
* represent the most significant bits of a 24 bit decrementer
|
||||
|
@ -576,17 +473,6 @@ static int __init octeon_wdt_init(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Build the NMI handler ... */
|
||||
octeon_wdt_build_stage1();
|
||||
|
||||
/* ... and install it. */
|
||||
ptr = (u64 *) nmi_stage1_insns;
|
||||
for (i = 0; i < 16; i++) {
|
||||
cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8);
|
||||
cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, ptr[i]);
|
||||
}
|
||||
cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000);
|
||||
|
||||
cpumask_clear(&irq_enabled_cpus);
|
||||
|
||||
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "watchdog/octeon:online",
|
||||
|
|
|
@ -3,20 +3,40 @@
|
|||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2007 Cavium Networks
|
||||
* Copyright (C) 2007-2017 Cavium, Inc.
|
||||
*/
|
||||
#include <asm/asm.h>
|
||||
#include <asm/regdef.h>
|
||||
|
||||
#define SAVE_REG(r) sd $r, -32768+6912-(32-r)*8($0)
|
||||
#define CVMSEG_BASE -32768
|
||||
#define CVMSEG_SIZE 6912
|
||||
#define SAVE_REG(r) sd $r, CVMSEG_BASE + CVMSEG_SIZE - ((32 - r) * 8)($0)
|
||||
|
||||
NESTED(octeon_wdt_nmi_stage2, 0, sp)
|
||||
.set push
|
||||
.set noreorder
|
||||
.set noat
|
||||
/* Save all registers to the top CVMSEG. This shouldn't
|
||||
/* Clear Dcache so cvmseg works right. */
|
||||
cache 1,0($0)
|
||||
/* Use K0 to do a read/modify/write of CVMMEMCTL */
|
||||
dmfc0 k0, $11, 7
|
||||
/* Clear out the size of CVMSEG */
|
||||
dins k0, $0, 0, 6
|
||||
/* Set CVMSEG to its largest value */
|
||||
ori k0, k0, 0x1c0 | 54
|
||||
/* Store the CVMMEMCTL value */
|
||||
dmtc0 k0, $11, 7
|
||||
/*
|
||||
* Restore K0 from the debug scratch register, it was saved in
|
||||
* the boot-vector code.
|
||||
*/
|
||||
dmfc0 k0, $31
|
||||
|
||||
/*
|
||||
* Save all registers to the top CVMSEG. This shouldn't
|
||||
* corrupt any state used by the kernel. Also all registers
|
||||
* should have the value right before the NMI. */
|
||||
* should have the value right before the NMI.
|
||||
*/
|
||||
SAVE_REG(0)
|
||||
SAVE_REG(1)
|
||||
SAVE_REG(2)
|
||||
|
@ -49,16 +69,22 @@
|
|||
SAVE_REG(29)
|
||||
SAVE_REG(30)
|
||||
SAVE_REG(31)
|
||||
/* Write zero to all CVMSEG locations per Core-15169 */
|
||||
dli a0, CVMSEG_SIZE - (33 * 8)
|
||||
1: sd zero, CVMSEG_BASE(a0)
|
||||
daddiu a0, a0, -8
|
||||
bgez a0, 1b
|
||||
nop
|
||||
/* Set the stack to begin right below the registers */
|
||||
li sp, -32768+6912-32*8
|
||||
dli sp, CVMSEG_BASE + CVMSEG_SIZE - (32 * 8)
|
||||
/* Load the address of the third stage handler */
|
||||
dla a0, octeon_wdt_nmi_stage3
|
||||
dla $25, octeon_wdt_nmi_stage3
|
||||
/* Call the third stage handler */
|
||||
jal a0
|
||||
jal $25
|
||||
/* a0 is the address of the saved registers */
|
||||
move a0, sp
|
||||
/* Loop forvever if we get here. */
|
||||
1: b 1b
|
||||
2: b 2b
|
||||
nop
|
||||
.set pop
|
||||
END(octeon_wdt_nmi_stage2)
|
||||
|
|
Loading…
Reference in New Issue
Block a user