Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Steven J. Hill and committed by
Ralf Baechle
49d148b4 9438a86a

+44 -132
+10 -124
drivers/watchdog/octeon-wdt-main.c
··· 73 73 #include <asm/uasm.h> 74 74 75 75 #include <asm/octeon/octeon.h> 76 + #include <asm/octeon/cvmx-boot-vector.h> 76 77 77 78 /* The count needed to achieve timeout_sec. */ 78 79 static unsigned int timeout_cnt; ··· 105 104 "Watchdog cannot be stopped once started (default=" 106 105 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 107 106 108 - static u32 nmi_stage1_insns[64] __initdata; 109 - /* We need one branch and therefore one relocation per target label. */ 110 - static struct uasm_label labels[5] __initdata; 111 - static struct uasm_reloc relocs[5] __initdata; 112 - 113 - enum lable_id { 114 - label_enter_bootloader = 1 115 - }; 116 - 117 - /* Some CP0 registers */ 118 - #define K0 26 119 - #define C0_CVMMEMCTL 11, 7 120 - #define C0_STATUS 12, 0 121 - #define C0_EBASE 15, 1 122 - #define C0_DESAVE 31, 0 107 + static struct cvmx_boot_vector_element *octeon_wdt_bootvector; 123 108 124 109 void octeon_wdt_nmi_stage2(void); 125 - 126 - static void __init octeon_wdt_build_stage1(void) 127 - { 128 - int i; 129 - int len; 130 - u32 *p = nmi_stage1_insns; 131 - #ifdef CONFIG_HOTPLUG_CPU 132 - struct uasm_label *l = labels; 133 - struct uasm_reloc *r = relocs; 134 - #endif 135 - 136 - /* 137 - * For the next few instructions running the debugger may 138 - * cause corruption of k0 in the saved registers. Since we're 139 - * about to crash, nobody probably cares. 140 - * 141 - * Save K0 into the debug scratch register 142 - */ 143 - uasm_i_dmtc0(&p, K0, C0_DESAVE); 144 - 145 - uasm_i_mfc0(&p, K0, C0_STATUS); 146 - #ifdef CONFIG_HOTPLUG_CPU 147 - if (octeon_bootloader_entry_addr) 148 - uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), 149 - label_enter_bootloader); 150 - #endif 151 - /* Force 64-bit addressing enabled */ 152 - uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX); 153 - uasm_i_mtc0(&p, K0, C0_STATUS); 154 - 155 - #ifdef CONFIG_HOTPLUG_CPU 156 - if (octeon_bootloader_entry_addr) { 157 - uasm_i_mfc0(&p, K0, C0_EBASE); 158 - /* Coreid number in K0 */ 159 - uasm_i_andi(&p, K0, K0, 0xf); 160 - /* 8 * coreid in bits 16-31 */ 161 - uasm_i_dsll_safe(&p, K0, K0, 3 + 16); 162 - uasm_i_ori(&p, K0, K0, 0x8001); 163 - uasm_i_dsll_safe(&p, K0, K0, 16); 164 - uasm_i_ori(&p, K0, K0, 0x0700); 165 - uasm_i_drotr_safe(&p, K0, K0, 32); 166 - /* 167 - * Should result in: 0x8001,0700,0000,8*coreid which is 168 - * CVMX_CIU_WDOGX(coreid) - 0x0500 169 - * 170 - * Now ld K0, CVMX_CIU_WDOGX(coreid) 171 - */ 172 - uasm_i_ld(&p, K0, 0x500, K0); 173 - /* 174 - * If bit one set handle the NMI as a watchdog event. 175 - * otherwise transfer control to bootloader. 176 - */ 177 - uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader); 178 - uasm_i_nop(&p); 179 - } 180 - #endif 181 - 182 - /* Clear Dcache so cvmseg works right. */ 183 - uasm_i_cache(&p, 1, 0, 0); 184 - 185 - /* Use K0 to do a read/modify/write of CVMMEMCTL */ 186 - uasm_i_dmfc0(&p, K0, C0_CVMMEMCTL); 187 - /* Clear out the size of CVMSEG */ 188 - uasm_i_dins(&p, K0, 0, 0, 6); 189 - /* Set CVMSEG to its largest value */ 190 - uasm_i_ori(&p, K0, K0, 0x1c0 | 54); 191 - /* Store the CVMMEMCTL value */ 192 - uasm_i_dmtc0(&p, K0, C0_CVMMEMCTL); 193 - 194 - /* Load the address of the second stage handler */ 195 - UASM_i_LA(&p, K0, (long)octeon_wdt_nmi_stage2); 196 - uasm_i_jr(&p, K0); 197 - uasm_i_dmfc0(&p, K0, C0_DESAVE); 198 - 199 - #ifdef CONFIG_HOTPLUG_CPU 200 - if (octeon_bootloader_entry_addr) { 201 - uasm_build_label(&l, p, label_enter_bootloader); 202 - /* Jump to the bootloader and restore K0 */ 203 - UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr); 204 - uasm_i_jr(&p, K0); 205 - uasm_i_dmfc0(&p, K0, C0_DESAVE); 206 - } 207 - #endif 208 - uasm_resolve_relocs(relocs, labels); 209 - 210 - len = (int)(p - nmi_stage1_insns); 211 - pr_debug("Synthesized NMI stage 1 handler (%d instructions)\n", len); 212 - 213 - pr_debug("\t.set push\n"); 214 - pr_debug("\t.set noreorder\n"); 215 - for (i = 0; i < len; i++) 216 - pr_debug("\t.word 0x%08x\n", nmi_stage1_insns[i]); 217 - pr_debug("\t.set pop\n"); 218 - 219 - if (len > 32) 220 - panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", 221 - len); 222 - } 223 110 224 111 static int cpu2core(int cpu) 225 112 { ··· 291 402 292 403 core = cpu2core(cpu); 293 404 405 + octeon_wdt_bootvector[core].target_ptr = (u64)octeon_wdt_nmi_stage2; 406 + 294 407 /* Disable it before doing anything with the interrupts. */ 295 408 ciu_wdog.u64 = 0; 296 409 cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); ··· 435 544 int ret; 436 545 u64 *ptr; 437 546 547 + octeon_wdt_bootvector = cvmx_boot_vector_get(); 548 + if (!octeon_wdt_bootvector) { 549 + pr_err("Error: Cannot allocate boot vector.\n"); 550 + return -ENOMEM; 551 + } 552 + 438 553 /* 439 554 * Watchdog time expiration length = The 16 bits of LEN 440 555 * represent the most significant bits of a 24 bit decrementer ··· 472 575 pr_err("watchdog_register_device() failed: %d\n", ret); 473 576 return ret; 474 577 } 475 - 476 - /* Build the NMI handler ... */ 477 - octeon_wdt_build_stage1(); 478 - 479 - /* ... and install it. */ 480 - ptr = (u64 *) nmi_stage1_insns; 481 - for (i = 0; i < 16; i++) { 482 - cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8); 483 - cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, ptr[i]); 484 - } 485 - cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000); 486 578 487 579 cpumask_clear(&irq_enabled_cpus); 488 580
+34 -8
drivers/watchdog/octeon-wdt-nmi.S
··· 3 3 * License. See the file "COPYING" in the main directory of this archive 4 4 * for more details. 5 5 * 6 - * Copyright (C) 2007 Cavium Networks 6 + * Copyright (C) 2007-2017 Cavium, Inc. 7 7 */ 8 8 #include <asm/asm.h> 9 9 #include <asm/regdef.h> 10 10 11 - #define SAVE_REG(r) sd $r, -32768+6912-(32-r)*8($0) 11 + #define CVMSEG_BASE -32768 12 + #define CVMSEG_SIZE 6912 13 + #define SAVE_REG(r) sd $r, CVMSEG_BASE + CVMSEG_SIZE - ((32 - r) * 8)($0) 12 14 13 15 NESTED(octeon_wdt_nmi_stage2, 0, sp) 14 16 .set push 15 17 .set noreorder 16 18 .set noat 17 - /* Save all registers to the top CVMSEG. This shouldn't 19 + /* Clear Dcache so cvmseg works right. */ 20 + cache 1,0($0) 21 + /* Use K0 to do a read/modify/write of CVMMEMCTL */ 22 + dmfc0 k0, $11, 7 23 + /* Clear out the size of CVMSEG */ 24 + dins k0, $0, 0, 6 25 + /* Set CVMSEG to its largest value */ 26 + ori k0, k0, 0x1c0 | 54 27 + /* Store the CVMMEMCTL value */ 28 + dmtc0 k0, $11, 7 29 + /* 30 + * Restore K0 from the debug scratch register, it was saved in 31 + * the boot-vector code. 32 + */ 33 + dmfc0 k0, $31 34 + 35 + /* 36 + * Save all registers to the top CVMSEG. This shouldn't 18 37 * corrupt any state used by the kernel. Also all registers 19 - * should have the value right before the NMI. */ 38 + * should have the value right before the NMI. 39 + */ 20 40 SAVE_REG(0) 21 41 SAVE_REG(1) 22 42 SAVE_REG(2) ··· 69 49 SAVE_REG(29) 70 50 SAVE_REG(30) 71 51 SAVE_REG(31) 52 + /* Write zero to all CVMSEG locations per Core-15169 */ 53 + dli a0, CVMSEG_SIZE - (33 * 8) 54 + 1: sd zero, CVMSEG_BASE(a0) 55 + daddiu a0, a0, -8 56 + bgez a0, 1b 57 + nop 72 58 /* Set the stack to begin right below the registers */ 73 - li sp, -32768+6912-32*8 59 + dli sp, CVMSEG_BASE + CVMSEG_SIZE - (32 * 8) 74 60 /* Load the address of the third stage handler */ 75 - dla a0, octeon_wdt_nmi_stage3 61 + dla $25, octeon_wdt_nmi_stage3 76 62 /* Call the third stage handler */ 77 - jal a0 63 + jal $25 78 64 /* a0 is the address of the saved registers */ 79 65 move a0, sp 80 66 /* Loop forvever if we get here. */ 81 - 1: b 1b 67 + 2: b 2b 82 68 nop 83 69 .set pop 84 70 END(octeon_wdt_nmi_stage2)