* [PATCH 1/8] MIPS: Octeon: Add support for accessing the boot vector.
2017-08-29 15:40 [PATCH 0/8] Update Octeon watchdog driver Steven J. Hill
@ 2017-08-29 15:40 ` Steven J. Hill
2017-08-29 15:40 ` [PATCH 2/8] watchdog: octeon-wdt: Remove old boot vector code Steven J. Hill
` (6 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Steven J. Hill @ 2017-08-29 15:40 UTC (permalink / raw)
To: linux-mips, linux-watchdog, ralf
Used by the Octeon watchdog driver to get the address of the
firmware boot vector.
Signed-off-by: Steven J. Hill <steven.hill@cavium.com>
Acked-by: David Daney <david.daney@cavium.com>
---
arch/mips/cavium-octeon/executive/Makefile | 2 +-
.../cavium-octeon/executive/cvmx-boot-vector.c | 167 +++++++++++++++++++++
arch/mips/cavium-octeon/executive/cvmx-bootmem.c | 85 +++++++++++
arch/mips/include/asm/octeon/cvmx-boot-vector.h | 53 +++++++
arch/mips/include/asm/octeon/cvmx-bootmem.h | 28 ++++
5 files changed, 334 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-boot-vector.c
create mode 100644 arch/mips/include/asm/octeon/cvmx-boot-vector.h
diff --git a/arch/mips/cavium-octeon/executive/Makefile b/arch/mips/cavium-octeon/executive/Makefile
index b6d6e84..50b4278 100644
--- a/arch/mips/cavium-octeon/executive/Makefile
+++ b/arch/mips/cavium-octeon/executive/Makefile
@@ -16,4 +16,4 @@ obj-y += cvmx-pko.o cvmx-spi.o cvmx-cmd-queue.o \
cvmx-helper-loop.o cvmx-helper-spi.o cvmx-helper-util.o \
cvmx-interrupt-decodes.o cvmx-interrupt-rsl.o
-obj-y += cvmx-helper-errata.o cvmx-helper-jtag.o
+obj-y += cvmx-helper-errata.o cvmx-helper-jtag.o cvmx-boot-vector.o
diff --git a/arch/mips/cavium-octeon/executive/cvmx-boot-vector.c b/arch/mips/cavium-octeon/executive/cvmx-boot-vector.c
new file mode 100644
index 0000000..b7019d2
--- /dev/null
+++ b/arch/mips/cavium-octeon/executive/cvmx-boot-vector.c
@@ -0,0 +1,167 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004-2017 Cavium, Inc.
+ */
+
+
+/*
+ We install this program at the bootvector:
+------------------------------------
+ .set noreorder
+ .set nomacro
+ .set noat
+reset_vector:
+ dmtc0 $k0, $31, 0 # Save $k0 to DESAVE
+ dmtc0 $k1, $31, 3 # Save $k1 to KScratch2
+
+ mfc0 $k0, $12, 0 # Status
+ mfc0 $k1, $15, 1 # Ebase
+
+ ori $k0, 0x84 # Enable 64-bit addressing, set
+ # ERL (should already be set)
+ andi $k1, 0x3ff # mask out core ID
+
+ mtc0 $k0, $12, 0 # Status
+ sll $k1, 5
+
+ lui $k0, 0xbfc0
+ cache 17, 0($0) # Core-14345, clear L1 Dcache virtual
+ # tags if the core hit an NMI
+
+ ld $k0, 0x78($k0) # k0 <- (bfc00078) pointer to the reset vector
+ synci 0($0) # Invalidate ICache to get coherent
+ # view of target code.
+
+ daddu $k0, $k0, $k1
+ nop
+
+ ld $k0, 0($k0) # k0 <- core specific target address
+ dmfc0 $k1, $31, 3 # Restore $k1 from KScratch2
+
+ beqz $k0, wait_loop # Spin in wait loop
+ nop
+
+ jr $k0
+ nop
+
+ nop # NOPs needed here to fill delay slots
+ nop # on endian reversal of previous instructions
+
+wait_loop:
+ wait
+ nop
+
+ b wait_loop
+ nop
+
+ nop
+ nop
+------------------------------------
+
+0000000000000000 <reset_vector>:
+ 0: 40baf800 dmtc0 k0,c0_desave
+ 4: 40bbf803 dmtc0 k1,c0_kscratch2
+
+ 8: 401a6000 mfc0 k0,c0_status
+ c: 401b7801 mfc0 k1,c0_ebase
+
+ 10: 375a0084 ori k0,k0,0x84
+ 14: 337b03ff andi k1,k1,0x3ff
+
+ 18: 409a6000 mtc0 k0,c0_status
+ 1c: 001bd940 sll k1,k1,0x5
+
+ 20: 3c1abfc0 lui k0,0xbfc0
+ 24: bc110000 cache 0x11,0(zero)
+
+ 28: df5a0078 ld k0,120(k0)
+ 2c: 041f0000 synci 0(zero)
+
+ 30: 035bd02d daddu k0,k0,k1
+ 34: 00000000 nop
+
+ 38: df5a0000 ld k0,0(k0)
+ 3c: 403bf803 dmfc0 k1,c0_kscratch2
+
+ 40: 13400005 beqz k0,58 <wait_loop>
+ 44: 00000000 nop
+
+ 48: 03400008 jr k0
+ 4c: 00000000 nop
+
+ 50: 00000000 nop
+ 54: 00000000 nop
+
+0000000000000058 <wait_loop>:
+ 58: 42000020 wait
+ 5c: 00000000 nop
+
+ 60: 1000fffd b 58 <wait_loop>
+ 64: 00000000 nop
+
+ 68: 00000000 nop
+ 6c: 00000000 nop
+
+ */
+
+#include <asm/octeon/cvmx-boot-vector.h>
+
+static unsigned long long _cvmx_bootvector_data[16] = {
+ 0x40baf80040bbf803ull, /* patch low order 8-bits if no KScratch*/
+ 0x401a6000401b7801ull,
+ 0x375a0084337b03ffull,
+ 0x409a6000001bd940ull,
+ 0x3c1abfc0bc110000ull,
+ 0xdf5a0078041f0000ull,
+ 0x035bd02d00000000ull,
+ 0xdf5a0000403bf803ull, /* patch low order 8-bits if no KScratch*/
+ 0x1340000500000000ull,
+ 0x0340000800000000ull,
+ 0x0000000000000000ull,
+ 0x4200002000000000ull,
+ 0x1000fffd00000000ull,
+ 0x0000000000000000ull,
+ OCTEON_BOOT_MOVEABLE_MAGIC1,
+ 0 /* To be filled in with address of vector block*/
+};
+
+/* 2^10 CPUs */
+#define VECTOR_TABLE_SIZE (1024 * sizeof(struct cvmx_boot_vector_element))
+
+static void cvmx_boot_vector_init(void *mem)
+{
+ uint64_t kseg0_mem;
+ int i;
+
+ memset(mem, 0, VECTOR_TABLE_SIZE);
+ kseg0_mem = cvmx_ptr_to_phys(mem) | 0x8000000000000000ull;
+
+ for (i = 0; i < 15; i++) {
+ uint64_t v = _cvmx_bootvector_data[i];
+
+ if (OCTEON_IS_OCTEON1PLUS() && (i == 0 || i == 7))
+ v &= 0xffffffff00000000ull; /* KScratch not availble. */
+ cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8);
+ cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, v);
+ }
+ cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, 15 * 8);
+ cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, kseg0_mem);
+ cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000);
+}
+
+/**
+ * Get a pointer to the per-core table of reset vector pointers
+ *
+ */
+struct cvmx_boot_vector_element *cvmx_boot_vector_get(void)
+{
+ struct cvmx_boot_vector_element *ret;
+
+ ret = cvmx_bootmem_alloc_named_range_once(VECTOR_TABLE_SIZE, 0,
+ (1ull << 32) - 1, 8, "__boot_vector1__", cvmx_boot_vector_init);
+ return ret;
+}
+EXPORT_SYMBOL(cvmx_boot_vector_get);
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
index 8d54d77..94d97eb 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
@@ -44,6 +44,55 @@ static struct cvmx_bootmem_desc *cvmx_bootmem_desc;
/* See header file for descriptions of functions */
+/**
+ * This macro returns the size of a member of a structure.
+ * Logically it is the same as "sizeof(s::field)" in C++, but
+ * C lacks the "::" operator.
+ */
+#define SIZEOF_FIELD(s, field) sizeof(((s *)NULL)->field)
+
+/**
+ * This macro returns a member of the
+ * cvmx_bootmem_named_block_desc_t structure. These members can't
+ * be directly addressed as they might be in memory not directly
+ * reachable. In the case where bootmem is compiled with
+ * LINUX_HOST, the structure itself might be located on a remote
+ * Octeon. The argument "field" is the member name of the
+ * cvmx_bootmem_named_block_desc_t to read. Regardless of the type
+ * of the field, the return type is always a uint64_t. The "addr"
+ * parameter is the physical address of the structure.
+ */
+#define CVMX_BOOTMEM_NAMED_GET_FIELD(addr, field) \
+ __cvmx_bootmem_desc_get(addr, \
+ offsetof(struct cvmx_bootmem_named_block_desc, field), \
+ SIZEOF_FIELD(struct cvmx_bootmem_named_block_desc, field))
+
+/**
+ * This function is the implementation of the get macros defined
+ * for individual structure members. The argument are generated
+ * by the macros inorder to read only the needed memory.
+ *
+ * @param base 64bit physical address of the complete structure
+ * @param offset Offset from the beginning of the structure to the member being
+ * accessed.
+ * @param size Size of the structure member.
+ *
+ * @return Value of the structure member promoted into a uint64_t.
+ */
+static inline uint64_t __cvmx_bootmem_desc_get(uint64_t base, int offset,
+ int size)
+{
+ base = (1ull << 63) | (base + offset);
+ switch (size) {
+ case 4:
+ return cvmx_read64_uint32(base);
+ case 8:
+ return cvmx_read64_uint64(base);
+ default:
+ return 0;
+ }
+}
+
/*
* Wrapper functions are provided for reading/writing the size and
* next block values as these may not be directly addressible (in 32
@@ -98,6 +147,42 @@ void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment)
return cvmx_bootmem_alloc_range(size, alignment, 0, 0);
}
+void *cvmx_bootmem_alloc_named_range_once(uint64_t size, uint64_t min_addr,
+ uint64_t max_addr, uint64_t align,
+ char *name,
+ void (*init) (void *))
+{
+ int64_t addr;
+ void *ptr;
+ uint64_t named_block_desc_addr;
+
+ named_block_desc_addr = (uint64_t)
+ cvmx_bootmem_phy_named_block_find(name,
+ (uint32_t)CVMX_BOOTMEM_FLAG_NO_LOCKING);
+
+ if (named_block_desc_addr) {
+ addr = CVMX_BOOTMEM_NAMED_GET_FIELD(named_block_desc_addr,
+ base_addr);
+ return cvmx_phys_to_ptr(addr);
+ }
+
+ addr = cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr,
+ align, name,
+ (uint32_t)CVMX_BOOTMEM_FLAG_NO_LOCKING);
+
+ if (addr < 0)
+ return NULL;
+ ptr = cvmx_phys_to_ptr(addr);
+
+ if (init)
+ init(ptr);
+ else
+ memset(ptr, 0, size);
+
+ return ptr;
+}
+EXPORT_SYMBOL(cvmx_bootmem_alloc_named_range_once);
+
void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr,
uint64_t max_addr, uint64_t align,
char *name)
diff --git a/arch/mips/include/asm/octeon/cvmx-boot-vector.h b/arch/mips/include/asm/octeon/cvmx-boot-vector.h
new file mode 100644
index 0000000..8db0824
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-boot-vector.h
@@ -0,0 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003-2017 Cavium, Inc.
+ */
+
+#ifndef __CVMX_BOOT_VECTOR_H__
+#define __CVMX_BOOT_VECTOR_H__
+
+#include <asm/octeon/octeon.h>
+
+/*
+ * The boot vector table is made up of an array of 1024 elements of
+ * struct cvmx_boot_vector_element. There is one entry for each
+ * possible MIPS CPUNum, indexed by the CPUNum.
+ *
+ * Once cvmx_boot_vector_get() returns a non-NULL value (indicating
+ * success), NMI to a core will cause execution to transfer to the
+ * target_ptr location for that core's entry in the vector table.
+ *
+ * The struct cvmx_boot_vector_element fields app0, app1, and app2 can
+ * be used by the application that has set the target_ptr in any
+ * application specific manner, they are not touched by the vectoring
+ * code.
+ *
+ * The boot vector code clobbers the CP0_DESAVE register, and on
+ * OCTEON II and later CPUs also clobbers CP0_KScratch2. All GP
+ * registers are preserved, except on pre-OCTEON II CPUs, where k1 is
+ * clobbered.
+ *
+ */
+
+
+/*
+ * Applications install the boot bus code in cvmx-boot-vector.c, which
+ * uses this magic:
+ */
+#define OCTEON_BOOT_MOVEABLE_MAGIC1 0xdb00110ad358eacdull
+
+struct cvmx_boot_vector_element {
+ /* kseg0 or xkphys address of target code. */
+ uint64_t target_ptr;
+ /* Three application specific arguments. */
+ uint64_t app0;
+ uint64_t app1;
+ uint64_t app2;
+};
+
+struct cvmx_boot_vector_element *cvmx_boot_vector_get(void);
+
+#endif /* __CVMX_BOOT_VECTOR_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-bootmem.h b/arch/mips/include/asm/octeon/cvmx-bootmem.h
index 3745625..72d2e40 100644
--- a/arch/mips/include/asm/octeon/cvmx-bootmem.h
+++ b/arch/mips/include/asm/octeon/cvmx-bootmem.h
@@ -255,6 +255,34 @@ extern void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr,
uint64_t max_addr, uint64_t align,
char *name);
+/**
+ * Allocate if needed a block of memory from a specific range of the
+ * free list that was passed to the application by the bootloader, and
+ * assign it a name in the global named block table. (part of the
+ * cvmx_bootmem_descriptor_t structure) Named blocks can later be
+ * freed. If the requested name block is already allocated, return
+ * the pointer to block of memory. If request cannot be satisfied
+ * within the address range specified, NULL is returned
+ *
+ * @param size Size in bytes of block to allocate
+ * @param min_addr minimum address of range
+ * @param max_addr maximum address of range
+ * @param align Alignment of memory to be allocated. (must be a power of 2)
+ * @param name name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes
+ * @param init Initialization function
+ *
+ * The initialization function is optional, if omitted the named block
+ * is initialized to all zeros when it is created, i.e. once.
+ *
+ * @return pointer to block of memory, NULL on error
+ */
+void *cvmx_bootmem_alloc_named_range_once(uint64_t size,
+ uint64_t min_addr,
+ uint64_t max_addr,
+ uint64_t align,
+ char *name,
+ void (*init) (void *));
+
extern int cvmx_bootmem_free_named(char *name);
/**
--
2.1.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/8] watchdog: octeon-wdt: Remove old boot vector code.
2017-08-29 15:40 [PATCH 0/8] Update Octeon watchdog driver Steven J. Hill
2017-08-29 15:40 ` [PATCH 1/8] MIPS: Octeon: Add support for accessing the boot vector Steven J. Hill
@ 2017-08-29 15:40 ` Steven J. Hill
2017-08-30 4:33 ` Guenter Roeck
2017-08-29 15:40 ` [PATCH 3/8] MIPS: Octeon: Watchdog registers for 70xx, 73xx, 78xx, F75xx Steven J. Hill
` (5 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Steven J. Hill @ 2017-08-29 15:40 UTC (permalink / raw)
To: linux-mips, linux-watchdog, ralf
Signed-off-by: Steven J. Hill <steven.hill@cavium.com>
Acked-by: David Daney <david.daney@cavium.com>
---
drivers/watchdog/octeon-wdt-main.c | 134 +++----------------------------------
drivers/watchdog/octeon-wdt-nmi.S | 42 +++++++++---
2 files changed, 44 insertions(+), 132 deletions(-)
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index b5cdceb..fbdd484 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -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",
diff --git a/drivers/watchdog/octeon-wdt-nmi.S b/drivers/watchdog/octeon-wdt-nmi.S
index 8a900a5..97f6eb7 100644
--- a/drivers/watchdog/octeon-wdt-nmi.S
+++ b/drivers/watchdog/octeon-wdt-nmi.S
@@ -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)
--
2.1.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 2/8] watchdog: octeon-wdt: Remove old boot vector code.
2017-08-29 15:40 ` [PATCH 2/8] watchdog: octeon-wdt: Remove old boot vector code Steven J. Hill
@ 2017-08-30 4:33 ` Guenter Roeck
2017-08-30 14:16 ` Steven J. Hill
0 siblings, 1 reply; 14+ messages in thread
From: Guenter Roeck @ 2017-08-30 4:33 UTC (permalink / raw)
To: Steven J. Hill; +Cc: linux-mips, linux-watchdog, ralf
On Tue, Aug 29, 2017 at 10:40:32AM -0500, Steven J. Hill wrote:
> 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>
I assume this series will go through the mips tree.
Guenter
> ---
> drivers/watchdog/octeon-wdt-main.c | 134 +++----------------------------------
> drivers/watchdog/octeon-wdt-nmi.S | 42 +++++++++---
> 2 files changed, 44 insertions(+), 132 deletions(-)
>
> diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
> index b5cdceb..fbdd484 100644
> --- a/drivers/watchdog/octeon-wdt-main.c
> +++ b/drivers/watchdog/octeon-wdt-main.c
> @@ -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",
> diff --git a/drivers/watchdog/octeon-wdt-nmi.S b/drivers/watchdog/octeon-wdt-nmi.S
> index 8a900a5..97f6eb7 100644
> --- a/drivers/watchdog/octeon-wdt-nmi.S
> +++ b/drivers/watchdog/octeon-wdt-nmi.S
> @@ -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)
> --
> 2.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/8] watchdog: octeon-wdt: Remove old boot vector code.
2017-08-30 4:33 ` Guenter Roeck
@ 2017-08-30 14:16 ` Steven J. Hill
0 siblings, 0 replies; 14+ messages in thread
From: Steven J. Hill @ 2017-08-30 14:16 UTC (permalink / raw)
To: Guenter Roeck; +Cc: linux-mips, linux-watchdog, ralf
On 08/29/2017 11:33 PM, Guenter Roeck wrote:
> On Tue, Aug 29, 2017 at 10:40:32AM -0500, Steven J. Hill wrote:
>> 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>
>
> I assume this series will go through the mips tree.
>
Hello Guenter.
Yes, we will have Ralf or James take this driver with the next MIPS
push upstream. Thanks for your Ack.
Steve
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/8] MIPS: Octeon: Watchdog registers for 70xx, 73xx, 78xx, F75xx.
2017-08-29 15:40 [PATCH 0/8] Update Octeon watchdog driver Steven J. Hill
2017-08-29 15:40 ` [PATCH 1/8] MIPS: Octeon: Add support for accessing the boot vector Steven J. Hill
2017-08-29 15:40 ` [PATCH 2/8] watchdog: octeon-wdt: Remove old boot vector code Steven J. Hill
@ 2017-08-29 15:40 ` Steven J. Hill
2017-08-29 15:40 ` [PATCH 4/8] MIPS: Octeon: Make CSR functions node aware Steven J. Hill
` (4 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Steven J. Hill @ 2017-08-29 15:40 UTC (permalink / raw)
To: linux-mips, linux-watchdog, ralf
From: "Steven J. Hill" <Steven.Hill@cavium.com>
Signed-off-by: Steven J. Hill <steven.hill@cavium.com>
Acked-by: David Daney <david.daney@cavium.com>
---
arch/mips/include/asm/octeon/cvmx-ciu-defs.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/mips/include/asm/octeon/cvmx-ciu-defs.h b/arch/mips/include/asm/octeon/cvmx-ciu-defs.h
index 0dd0e40..6e61792 100644
--- a/arch/mips/include/asm/octeon/cvmx-ciu-defs.h
+++ b/arch/mips/include/asm/octeon/cvmx-ciu-defs.h
@@ -128,6 +128,7 @@ static inline uint64_t CVMX_CIU_PP_POKEX(unsigned long offset)
case OCTEON_CN52XX & OCTEON_FAMILY_MASK:
case OCTEON_CNF71XX & OCTEON_FAMILY_MASK:
case OCTEON_CN61XX & OCTEON_FAMILY_MASK:
+ case OCTEON_CN70XX & OCTEON_FAMILY_MASK:
return CVMX_ADD_IO_SEG(0x0001070000000580ull) + (offset) * 8;
case OCTEON_CN31XX & OCTEON_FAMILY_MASK:
case OCTEON_CN50XX & OCTEON_FAMILY_MASK:
@@ -143,6 +144,10 @@ static inline uint64_t CVMX_CIU_PP_POKEX(unsigned long offset)
return CVMX_ADD_IO_SEG(0x0001070000000580ull) + (offset) * 8;
case OCTEON_CN68XX & OCTEON_FAMILY_MASK:
return CVMX_ADD_IO_SEG(0x0001070100100200ull) + (offset) * 8;
+ case OCTEON_CNF75XX & OCTEON_FAMILY_MASK:
+ case OCTEON_CN73XX & OCTEON_FAMILY_MASK:
+ case OCTEON_CN78XX & OCTEON_FAMILY_MASK:
+ return CVMX_ADD_IO_SEG(0x0001010000030000ull) + (offset) * 8;
}
return CVMX_ADD_IO_SEG(0x0001070000000580ull) + (offset) * 8;
}
@@ -180,6 +185,7 @@ static inline uint64_t CVMX_CIU_WDOGX(unsigned long offset)
case OCTEON_CN52XX & OCTEON_FAMILY_MASK:
case OCTEON_CNF71XX & OCTEON_FAMILY_MASK:
case OCTEON_CN61XX & OCTEON_FAMILY_MASK:
+ case OCTEON_CN70XX & OCTEON_FAMILY_MASK:
return CVMX_ADD_IO_SEG(0x0001070000000500ull) + (offset) * 8;
case OCTEON_CN31XX & OCTEON_FAMILY_MASK:
case OCTEON_CN50XX & OCTEON_FAMILY_MASK:
@@ -195,6 +201,10 @@ static inline uint64_t CVMX_CIU_WDOGX(unsigned long offset)
return CVMX_ADD_IO_SEG(0x0001070000000500ull) + (offset) * 8;
case OCTEON_CN68XX & OCTEON_FAMILY_MASK:
return CVMX_ADD_IO_SEG(0x0001070100100000ull) + (offset) * 8;
+ case OCTEON_CNF75XX & OCTEON_FAMILY_MASK:
+ case OCTEON_CN73XX & OCTEON_FAMILY_MASK:
+ case OCTEON_CN78XX & OCTEON_FAMILY_MASK:
+ return CVMX_ADD_IO_SEG(0x0001010000020000ull) + (offset) * 8;
}
return CVMX_ADD_IO_SEG(0x0001070000000500ull) + (offset) * 8;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/8] MIPS: Octeon: Make CSR functions node aware.
2017-08-29 15:40 [PATCH 0/8] Update Octeon watchdog driver Steven J. Hill
` (2 preceding siblings ...)
2017-08-29 15:40 ` [PATCH 3/8] MIPS: Octeon: Watchdog registers for 70xx, 73xx, 78xx, F75xx Steven J. Hill
@ 2017-08-29 15:40 ` Steven J. Hill
2017-08-29 15:40 ` [PATCH 5/8] MIPS: Octeon: Allow access to CIU3 IRQ domains Steven J. Hill
` (3 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Steven J. Hill @ 2017-08-29 15:40 UTC (permalink / raw)
To: linux-mips, linux-watchdog, ralf
From: "Steven J. Hill" <Steven.Hill@cavium.com>
Updates CSR read/write functions to be aware of nodes present in
systems with CIU3 support.
Signed-off-by: Steven J. Hill <Steven.Hill@cavium.com>
Acked-by: David Daney <david.daney@cavium.com>
---
arch/mips/include/asm/octeon/cvmx.h | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h
index e638735..205ab2c 100644
--- a/arch/mips/include/asm/octeon/cvmx.h
+++ b/arch/mips/include/asm/octeon/cvmx.h
@@ -357,6 +357,34 @@ static inline unsigned int cvmx_get_local_core_num(void)
return cvmx_get_core_num() & ((1 << CVMX_NODE_NO_SHIFT) - 1);
}
+#define CVMX_NODE_BITS (2) /* Number of bits to define a node */
+#define CVMX_MAX_NODES (1 << CVMX_NODE_BITS)
+#define CVMX_NODE_IO_SHIFT (36)
+#define CVMX_NODE_MEM_SHIFT (40)
+#define CVMX_NODE_IO_MASK ((uint64_t)CVMX_NODE_MASK << CVMX_NODE_IO_SHIFT)
+
+static inline void cvmx_write_csr_node(uint64_t node, uint64_t csr_addr,
+ uint64_t val)
+{
+ uint64_t composite_csr_addr, node_addr;
+
+ node_addr = (node & CVMX_NODE_MASK) << CVMX_NODE_IO_SHIFT;
+ composite_csr_addr = (csr_addr & ~CVMX_NODE_IO_MASK) | node_addr;
+
+ cvmx_write64_uint64(composite_csr_addr, val);
+ if (((csr_addr >> 40) & 0x7ffff) == (0x118))
+ cvmx_read64_uint64(CVMX_MIO_BOOT_BIST_STAT | node_addr);
+}
+
+static inline uint64_t cvmx_read_csr_node(uint64_t node, uint64_t csr_addr)
+{
+ uint64_t node_addr;
+
+ node_addr = (csr_addr & ~CVMX_NODE_IO_MASK) |
+ (node & CVMX_NODE_MASK) << CVMX_NODE_IO_SHIFT;
+ return cvmx_read_csr(node_addr);
+}
+
/**
* Returns the number of bits set in the provided value.
* Simple wrapper for POP instruction.
--
2.1.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 5/8] MIPS: Octeon: Allow access to CIU3 IRQ domains.
2017-08-29 15:40 [PATCH 0/8] Update Octeon watchdog driver Steven J. Hill
` (3 preceding siblings ...)
2017-08-29 15:40 ` [PATCH 4/8] MIPS: Octeon: Make CSR functions node aware Steven J. Hill
@ 2017-08-29 15:40 ` Steven J. Hill
2017-08-29 15:40 ` [PATCH 6/8] watchdog: octeon-wdt: File cleaning Steven J. Hill
` (2 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Steven J. Hill @ 2017-08-29 15:40 UTC (permalink / raw)
To: linux-mips, linux-watchdog, ralf
From: "Steven J. Hill" <Steven.Hill@cavium.com>
Add accessor function octeon_irq_get_block_domain() for cores
with a CIU3.
Signed-off-by: Steven J. Hill <steven.hill@cavium.com>
Acked-by: David Daney <david.daney@cavium.com>
---
arch/mips/cavium-octeon/octeon-irq.c | 9 +++++++++
arch/mips/include/asm/octeon/octeon.h | 2 ++
2 files changed, 11 insertions(+)
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index c1eb1ff..5b3a3f6 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -2963,3 +2963,12 @@ void octeon_fixup_irqs(void)
}
#endif /* CONFIG_HOTPLUG_CPU */
+
+struct irq_domain *octeon_irq_get_block_domain(int node, uint8_t block)
+{
+ struct octeon_ciu3_info *ciu3_info;
+
+ ciu3_info = octeon_ciu3_info_per_node[node & CVMX_NODE_MASK];
+ return ciu3_info->domain[block];
+}
+EXPORT_SYMBOL(octeon_irq_get_block_domain);
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index 07c0516..c99c4b6 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -362,4 +362,6 @@ extern void octeon_fixup_irqs(void);
extern struct semaphore octeon_bootbus_sem;
+struct irq_domain *octeon_irq_get_block_domain(int node, uint8_t block);
+
#endif /* __ASM_OCTEON_OCTEON_H */
--
2.1.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 6/8] watchdog: octeon-wdt: File cleaning.
2017-08-29 15:40 [PATCH 0/8] Update Octeon watchdog driver Steven J. Hill
` (4 preceding siblings ...)
2017-08-29 15:40 ` [PATCH 5/8] MIPS: Octeon: Allow access to CIU3 IRQ domains Steven J. Hill
@ 2017-08-29 15:40 ` Steven J. Hill
2017-08-30 4:33 ` Guenter Roeck
2017-08-29 15:40 ` [PATCH 7/8] watchdog: octeon-wdt: Add support for cn68XX SOCs Steven J. Hill
2017-08-29 15:40 ` [PATCH 8/8] watchdog: octeon-wdt: Add support for 78XX SOCs Steven J. Hill
7 siblings, 1 reply; 14+ messages in thread
From: Steven J. Hill @ 2017-08-29 15:40 UTC (permalink / raw)
To: linux-mips, linux-watchdog, ralf
From: "Steven J. Hill" <Steven.Hill@cavium.com>
* Update copyright and company name.
* Remove unused headers.
* Fix variable spelling and data type.
* Use octal values for module parameters.
Signed-off-by: Steven J. Hill <steven.hill@cavium.com>
Acked-by: David Daney <david.daney@cavium.com>
---
drivers/watchdog/octeon-wdt-main.c | 45 +++++++++++++++++++++++++-------------
1 file changed, 30 insertions(+), 15 deletions(-)
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index fbdd484..73b5102 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -1,7 +1,7 @@
/*
* Octeon Watchdog driver
*
- * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks
+ * Copyright (C) 2007-2017 Cavium, Inc.
*
* Converted to use WATCHDOG_CORE by Aaro Koskinen <aaro.koskinen@iki.fi>.
*
@@ -59,14 +59,9 @@
#include <linux/interrupt.h>
#include <linux/watchdog.h>
#include <linux/cpumask.h>
-#include <linux/bitops.h>
-#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/string.h>
#include <linux/delay.h>
#include <linux/cpu.h>
-#include <linux/smp.h>
-#include <linux/fs.h>
#include <linux/irq.h>
#include <asm/mipsregs.h>
@@ -85,7 +80,7 @@ static unsigned int max_timeout_sec;
static unsigned int timeout_sec;
/* Set to non-zero when userspace countdown mode active */
-static int do_coundown;
+static bool do_countdown;
static unsigned int countdown_reset;
static unsigned int per_cpu_countdown[NR_CPUS];
@@ -94,17 +89,22 @@ static cpumask_t irq_enabled_cpus;
#define WD_TIMO 60 /* Default heartbeat = 60 seconds */
static int heartbeat = WD_TIMO;
-module_param(heartbeat, int, S_IRUGO);
+module_param(heartbeat, int, 0444);
MODULE_PARM_DESC(heartbeat,
"Watchdog heartbeat in seconds. (0 < heartbeat, default="
__MODULE_STRING(WD_TIMO) ")");
static bool nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, bool, S_IRUGO);
+module_param(nowayout, bool, 0444);
MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+static int disable;
+module_param(disable, int, 0444);
+MODULE_PARM_DESC(disable,
+ "Disable the watchdog entirely (default=0)");
+
static struct cvmx_boot_vector_element *octeon_wdt_bootvector;
void octeon_wdt_nmi_stage2(void);
@@ -140,7 +140,7 @@ static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
unsigned int core = cvmx_get_core_num();
int cpu = core2cpu(core);
- if (do_coundown) {
+ if (do_countdown) {
if (per_cpu_countdown[cpu] > 0) {
/* We're alive, poke the watchdog */
cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
@@ -324,11 +324,14 @@ static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog)
int cpu;
int coreid;
+ if (disable)
+ return 0;
+
for_each_online_cpu(cpu) {
coreid = cpu2core(cpu);
cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
per_cpu_countdown[cpu] = countdown_reset;
- if ((countdown_reset || !do_coundown) &&
+ if ((countdown_reset || !do_countdown) &&
!cpumask_test_cpu(cpu, &irq_enabled_cpus)) {
/* We have to enable the irq */
int irq = OCTEON_IRQ_WDOG0 + coreid;
@@ -378,6 +381,9 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
octeon_wdt_calc_parameters(t);
+ if (disable)
+ return 0;
+
for_each_online_cpu(cpu) {
coreid = cpu2core(cpu);
cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
@@ -394,13 +400,13 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
static int octeon_wdt_start(struct watchdog_device *wdog)
{
octeon_wdt_ping(wdog);
- do_coundown = 1;
+ do_countdown = 1;
return 0;
}
static int octeon_wdt_stop(struct watchdog_device *wdog)
{
- do_coundown = 0;
+ do_countdown = 0;
octeon_wdt_ping(wdog);
return 0;
}
@@ -473,6 +479,11 @@ static int __init octeon_wdt_init(void)
return ret;
}
+ if (disable) {
+ pr_notice("disabled\n");
+ return 0;
+ }
+
cpumask_clear(&irq_enabled_cpus);
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "watchdog/octeon:online",
@@ -493,6 +504,10 @@ static int __init octeon_wdt_init(void)
static void __exit octeon_wdt_cleanup(void)
{
watchdog_unregister_device(&octeon_wdt);
+
+ if (disable)
+ return;
+
cpuhp_remove_state(octeon_wdt_online);
/*
@@ -503,7 +518,7 @@ static void __exit octeon_wdt_cleanup(void)
}
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
-MODULE_DESCRIPTION("Cavium Networks Octeon Watchdog driver.");
+MODULE_AUTHOR("Cavium Inc. <support@cavium.com>");
+MODULE_DESCRIPTION("Cavium Inc. OCTEON Watchdog driver.");
module_init(octeon_wdt_init);
module_exit(octeon_wdt_cleanup);
--
2.1.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 6/8] watchdog: octeon-wdt: File cleaning.
2017-08-29 15:40 ` [PATCH 6/8] watchdog: octeon-wdt: File cleaning Steven J. Hill
@ 2017-08-30 4:33 ` Guenter Roeck
0 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2017-08-30 4:33 UTC (permalink / raw)
To: Steven J. Hill; +Cc: linux-mips, linux-watchdog, ralf
On Tue, Aug 29, 2017 at 10:40:36AM -0500, Steven J. Hill wrote:
> From: "Steven J. Hill" <Steven.Hill@cavium.com>
>
> * Update copyright and company name.
> * Remove unused headers.
> * Fix variable spelling and data type.
> * Use octal values for module parameters.
>
> 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>
> ---
> drivers/watchdog/octeon-wdt-main.c | 45 +++++++++++++++++++++++++-------------
> 1 file changed, 30 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
> index fbdd484..73b5102 100644
> --- a/drivers/watchdog/octeon-wdt-main.c
> +++ b/drivers/watchdog/octeon-wdt-main.c
> @@ -1,7 +1,7 @@
> /*
> * Octeon Watchdog driver
> *
> - * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks
> + * Copyright (C) 2007-2017 Cavium, Inc.
> *
> * Converted to use WATCHDOG_CORE by Aaro Koskinen <aaro.koskinen@iki.fi>.
> *
> @@ -59,14 +59,9 @@
> #include <linux/interrupt.h>
> #include <linux/watchdog.h>
> #include <linux/cpumask.h>
> -#include <linux/bitops.h>
> -#include <linux/kernel.h>
> #include <linux/module.h>
> -#include <linux/string.h>
> #include <linux/delay.h>
> #include <linux/cpu.h>
> -#include <linux/smp.h>
> -#include <linux/fs.h>
> #include <linux/irq.h>
>
> #include <asm/mipsregs.h>
> @@ -85,7 +80,7 @@ static unsigned int max_timeout_sec;
> static unsigned int timeout_sec;
>
> /* Set to non-zero when userspace countdown mode active */
> -static int do_coundown;
> +static bool do_countdown;
> static unsigned int countdown_reset;
> static unsigned int per_cpu_countdown[NR_CPUS];
>
> @@ -94,17 +89,22 @@ static cpumask_t irq_enabled_cpus;
> #define WD_TIMO 60 /* Default heartbeat = 60 seconds */
>
> static int heartbeat = WD_TIMO;
> -module_param(heartbeat, int, S_IRUGO);
> +module_param(heartbeat, int, 0444);
> MODULE_PARM_DESC(heartbeat,
> "Watchdog heartbeat in seconds. (0 < heartbeat, default="
> __MODULE_STRING(WD_TIMO) ")");
>
> static bool nowayout = WATCHDOG_NOWAYOUT;
> -module_param(nowayout, bool, S_IRUGO);
> +module_param(nowayout, bool, 0444);
> MODULE_PARM_DESC(nowayout,
> "Watchdog cannot be stopped once started (default="
> __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
>
> +static int disable;
> +module_param(disable, int, 0444);
> +MODULE_PARM_DESC(disable,
> + "Disable the watchdog entirely (default=0)");
> +
> static struct cvmx_boot_vector_element *octeon_wdt_bootvector;
>
> void octeon_wdt_nmi_stage2(void);
> @@ -140,7 +140,7 @@ static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
> unsigned int core = cvmx_get_core_num();
> int cpu = core2cpu(core);
>
> - if (do_coundown) {
> + if (do_countdown) {
> if (per_cpu_countdown[cpu] > 0) {
> /* We're alive, poke the watchdog */
> cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
> @@ -324,11 +324,14 @@ static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog)
> int cpu;
> int coreid;
>
> + if (disable)
> + return 0;
> +
> for_each_online_cpu(cpu) {
> coreid = cpu2core(cpu);
> cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
> per_cpu_countdown[cpu] = countdown_reset;
> - if ((countdown_reset || !do_coundown) &&
> + if ((countdown_reset || !do_countdown) &&
> !cpumask_test_cpu(cpu, &irq_enabled_cpus)) {
> /* We have to enable the irq */
> int irq = OCTEON_IRQ_WDOG0 + coreid;
> @@ -378,6 +381,9 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
>
> octeon_wdt_calc_parameters(t);
>
> + if (disable)
> + return 0;
> +
> for_each_online_cpu(cpu) {
> coreid = cpu2core(cpu);
> cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
> @@ -394,13 +400,13 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
> static int octeon_wdt_start(struct watchdog_device *wdog)
> {
> octeon_wdt_ping(wdog);
> - do_coundown = 1;
> + do_countdown = 1;
> return 0;
> }
>
> static int octeon_wdt_stop(struct watchdog_device *wdog)
> {
> - do_coundown = 0;
> + do_countdown = 0;
> octeon_wdt_ping(wdog);
> return 0;
> }
> @@ -473,6 +479,11 @@ static int __init octeon_wdt_init(void)
> return ret;
> }
>
> + if (disable) {
> + pr_notice("disabled\n");
> + return 0;
> + }
> +
> cpumask_clear(&irq_enabled_cpus);
>
> ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "watchdog/octeon:online",
> @@ -493,6 +504,10 @@ static int __init octeon_wdt_init(void)
> static void __exit octeon_wdt_cleanup(void)
> {
> watchdog_unregister_device(&octeon_wdt);
> +
> + if (disable)
> + return;
> +
> cpuhp_remove_state(octeon_wdt_online);
>
> /*
> @@ -503,7 +518,7 @@ static void __exit octeon_wdt_cleanup(void)
> }
>
> MODULE_LICENSE("GPL");
> -MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
> -MODULE_DESCRIPTION("Cavium Networks Octeon Watchdog driver.");
> +MODULE_AUTHOR("Cavium Inc. <support@cavium.com>");
> +MODULE_DESCRIPTION("Cavium Inc. OCTEON Watchdog driver.");
> module_init(octeon_wdt_init);
> module_exit(octeon_wdt_cleanup);
> --
> 2.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 7/8] watchdog: octeon-wdt: Add support for cn68XX SOCs.
2017-08-29 15:40 [PATCH 0/8] Update Octeon watchdog driver Steven J. Hill
` (5 preceding siblings ...)
2017-08-29 15:40 ` [PATCH 6/8] watchdog: octeon-wdt: File cleaning Steven J. Hill
@ 2017-08-29 15:40 ` Steven J. Hill
2017-08-30 4:34 ` Guenter Roeck
2017-08-29 15:40 ` [PATCH 8/8] watchdog: octeon-wdt: Add support for 78XX SOCs Steven J. Hill
7 siblings, 1 reply; 14+ messages in thread
From: Steven J. Hill @ 2017-08-29 15:40 UTC (permalink / raw)
To: linux-mips, linux-watchdog, ralf
From: David Daney <david.daney@cavium.com>
Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Carlos Munoz <cmunoz@caviumnetworks.com>
Signed-off-by: Chandrakala Chavva <cchavva@caviumnetworks.com>
---
drivers/watchdog/octeon-wdt-main.c | 48 +++++++++++++++++++++++++++-----------
1 file changed, 35 insertions(+), 13 deletions(-)
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index 73b5102..410800f 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -69,6 +69,9 @@
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-boot-vector.h>
+#include <asm/octeon/cvmx-ciu2-defs.h>
+
+static int divisor;
/* The count needed to achieve timeout_sec. */
static unsigned int timeout_cnt;
@@ -227,10 +230,10 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
u64 cp0_epc = read_c0_epc();
/* Delay so output from all cores output is not jumbled together. */
- __delay(100000000ull * coreid);
+ udelay(85000 * coreid);
octeon_wdt_write_string("\r\n*** NMI Watchdog interrupt on Core 0x");
- octeon_wdt_write_hex(coreid, 1);
+ octeon_wdt_write_hex(coreid, 2);
octeon_wdt_write_string(" ***\r\n");
for (i = 0; i < 32; i++) {
octeon_wdt_write_string("\t");
@@ -253,11 +256,28 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
octeon_wdt_write_hex(cp0_cause, 16);
octeon_wdt_write_string("\r\n");
- octeon_wdt_write_string("\tsum0\t0x");
- octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16);
- octeon_wdt_write_string("\ten0\t0x");
- octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16);
- octeon_wdt_write_string("\r\n");
+ /* The CIU register is different for each Octeon model. */
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+ octeon_wdt_write_string("\tsrc_wd\t0x");
+ octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SRC_PPX_IP2_WDOG(coreid)), 16);
+ octeon_wdt_write_string("\ten_wd\t0x");
+ octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_EN_PPX_IP2_WDOG(coreid)), 16);
+ octeon_wdt_write_string("\r\n");
+ octeon_wdt_write_string("\tsrc_rml\t0x");
+ octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SRC_PPX_IP2_RML(coreid)), 16);
+ octeon_wdt_write_string("\ten_rml\t0x");
+ octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_EN_PPX_IP2_RML(coreid)), 16);
+ octeon_wdt_write_string("\r\n");
+ octeon_wdt_write_string("\tsum\t0x");
+ octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SUM_PPX_IP2(coreid)), 16);
+ octeon_wdt_write_string("\r\n");
+ } else if (!octeon_has_feature(OCTEON_FEATURE_CIU3)) {
+ octeon_wdt_write_string("\tsum0\t0x");
+ octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16);
+ octeon_wdt_write_string("\ten0\t0x");
+ octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16);
+ octeon_wdt_write_string("\r\n");
+ }
octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");
}
@@ -366,7 +386,7 @@ static void octeon_wdt_calc_parameters(int t)
countdown_reset = periods > 2 ? periods - 2 : 0;
heartbeat = t;
- timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8;
+ timeout_cnt = ((octeon_get_io_clock_rate() / divisor) * timeout_sec) >> 8;
}
static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
@@ -437,9 +457,7 @@ static enum cpuhp_state octeon_wdt_online;
*/
static int __init octeon_wdt_init(void)
{
- int i;
int ret;
- u64 *ptr;
octeon_wdt_bootvector = cvmx_boot_vector_get();
if (!octeon_wdt_bootvector) {
@@ -447,10 +465,15 @@ static int __init octeon_wdt_init(void)
return -ENOMEM;
}
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ divisor = 0x200;
+ else
+ divisor = 0x100;
+
/*
* Watchdog time expiration length = The 16 bits of LEN
* represent the most significant bits of a 24 bit decrementer
- * that decrements every 256 cycles.
+ * that decrements every divisor cycle.
*
* Try for a timeout of 5 sec, if that fails a smaller number
* of even seconds,
@@ -458,8 +481,7 @@ static int __init octeon_wdt_init(void)
max_timeout_sec = 6;
do {
max_timeout_sec--;
- timeout_cnt = ((octeon_get_io_clock_rate() >> 8) *
- max_timeout_sec) >> 8;
+ timeout_cnt = ((octeon_get_io_clock_rate() / divisor) * max_timeout_sec) >> 8;
} while (timeout_cnt > 65535);
BUG_ON(timeout_cnt == 0);
--
2.1.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 7/8] watchdog: octeon-wdt: Add support for cn68XX SOCs.
2017-08-29 15:40 ` [PATCH 7/8] watchdog: octeon-wdt: Add support for cn68XX SOCs Steven J. Hill
@ 2017-08-30 4:34 ` Guenter Roeck
0 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2017-08-30 4:34 UTC (permalink / raw)
To: Steven J. Hill; +Cc: linux-mips, linux-watchdog, ralf
On Tue, Aug 29, 2017 at 10:40:37AM -0500, Steven J. Hill wrote:
> From: David Daney <david.daney@cavium.com>
>
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Carlos Munoz <cmunoz@caviumnetworks.com>
> Signed-off-by: Chandrakala Chavva <cchavva@caviumnetworks.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
> ---
> drivers/watchdog/octeon-wdt-main.c | 48 +++++++++++++++++++++++++++-----------
> 1 file changed, 35 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
> index 73b5102..410800f 100644
> --- a/drivers/watchdog/octeon-wdt-main.c
> +++ b/drivers/watchdog/octeon-wdt-main.c
> @@ -69,6 +69,9 @@
>
> #include <asm/octeon/octeon.h>
> #include <asm/octeon/cvmx-boot-vector.h>
> +#include <asm/octeon/cvmx-ciu2-defs.h>
> +
> +static int divisor;
>
> /* The count needed to achieve timeout_sec. */
> static unsigned int timeout_cnt;
> @@ -227,10 +230,10 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
> u64 cp0_epc = read_c0_epc();
>
> /* Delay so output from all cores output is not jumbled together. */
> - __delay(100000000ull * coreid);
> + udelay(85000 * coreid);
>
> octeon_wdt_write_string("\r\n*** NMI Watchdog interrupt on Core 0x");
> - octeon_wdt_write_hex(coreid, 1);
> + octeon_wdt_write_hex(coreid, 2);
> octeon_wdt_write_string(" ***\r\n");
> for (i = 0; i < 32; i++) {
> octeon_wdt_write_string("\t");
> @@ -253,11 +256,28 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
> octeon_wdt_write_hex(cp0_cause, 16);
> octeon_wdt_write_string("\r\n");
>
> - octeon_wdt_write_string("\tsum0\t0x");
> - octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16);
> - octeon_wdt_write_string("\ten0\t0x");
> - octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16);
> - octeon_wdt_write_string("\r\n");
> + /* The CIU register is different for each Octeon model. */
> + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
> + octeon_wdt_write_string("\tsrc_wd\t0x");
> + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SRC_PPX_IP2_WDOG(coreid)), 16);
> + octeon_wdt_write_string("\ten_wd\t0x");
> + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_EN_PPX_IP2_WDOG(coreid)), 16);
> + octeon_wdt_write_string("\r\n");
> + octeon_wdt_write_string("\tsrc_rml\t0x");
> + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SRC_PPX_IP2_RML(coreid)), 16);
> + octeon_wdt_write_string("\ten_rml\t0x");
> + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_EN_PPX_IP2_RML(coreid)), 16);
> + octeon_wdt_write_string("\r\n");
> + octeon_wdt_write_string("\tsum\t0x");
> + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SUM_PPX_IP2(coreid)), 16);
> + octeon_wdt_write_string("\r\n");
> + } else if (!octeon_has_feature(OCTEON_FEATURE_CIU3)) {
> + octeon_wdt_write_string("\tsum0\t0x");
> + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16);
> + octeon_wdt_write_string("\ten0\t0x");
> + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16);
> + octeon_wdt_write_string("\r\n");
> + }
>
> octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");
> }
> @@ -366,7 +386,7 @@ static void octeon_wdt_calc_parameters(int t)
>
> countdown_reset = periods > 2 ? periods - 2 : 0;
> heartbeat = t;
> - timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8;
> + timeout_cnt = ((octeon_get_io_clock_rate() / divisor) * timeout_sec) >> 8;
> }
>
> static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
> @@ -437,9 +457,7 @@ static enum cpuhp_state octeon_wdt_online;
> */
> static int __init octeon_wdt_init(void)
> {
> - int i;
> int ret;
> - u64 *ptr;
>
> octeon_wdt_bootvector = cvmx_boot_vector_get();
> if (!octeon_wdt_bootvector) {
> @@ -447,10 +465,15 @@ static int __init octeon_wdt_init(void)
> return -ENOMEM;
> }
>
> + if (OCTEON_IS_MODEL(OCTEON_CN68XX))
> + divisor = 0x200;
> + else
> + divisor = 0x100;
> +
> /*
> * Watchdog time expiration length = The 16 bits of LEN
> * represent the most significant bits of a 24 bit decrementer
> - * that decrements every 256 cycles.
> + * that decrements every divisor cycle.
> *
> * Try for a timeout of 5 sec, if that fails a smaller number
> * of even seconds,
> @@ -458,8 +481,7 @@ static int __init octeon_wdt_init(void)
> max_timeout_sec = 6;
> do {
> max_timeout_sec--;
> - timeout_cnt = ((octeon_get_io_clock_rate() >> 8) *
> - max_timeout_sec) >> 8;
> + timeout_cnt = ((octeon_get_io_clock_rate() / divisor) * max_timeout_sec) >> 8;
> } while (timeout_cnt > 65535);
>
> BUG_ON(timeout_cnt == 0);
> --
> 2.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 8/8] watchdog: octeon-wdt: Add support for 78XX SOCs.
2017-08-29 15:40 [PATCH 0/8] Update Octeon watchdog driver Steven J. Hill
` (6 preceding siblings ...)
2017-08-29 15:40 ` [PATCH 7/8] watchdog: octeon-wdt: Add support for cn68XX SOCs Steven J. Hill
@ 2017-08-29 15:40 ` Steven J. Hill
2017-08-30 4:34 ` Guenter Roeck
7 siblings, 1 reply; 14+ messages in thread
From: Steven J. Hill @ 2017-08-29 15:40 UTC (permalink / raw)
To: linux-mips, linux-watchdog, ralf
From: Carlos Munoz <carlos.munoz@caviumnetworks.com>
Signed-off-by: Carlos Munoz <carlos.munoz@caviumnetworks.com>
Signed-off-by: Steven J. Hill <steven.hill@cavium.com>
Acked-by: David Daney <david.daney@cavium.com>
---
drivers/watchdog/octeon-wdt-main.c | 133 ++++++++++++++++++++++++++++---------
1 file changed, 103 insertions(+), 30 deletions(-)
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index 410800f..0ec419a 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -70,6 +70,10 @@
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-boot-vector.h>
#include <asm/octeon/cvmx-ciu2-defs.h>
+#include <asm/octeon/cvmx-rst-defs.h>
+
+/* Watchdog interrupt major block number (8 MSBs of intsn) */
+#define WD_BLOCK_NUMBER 0x01
static int divisor;
@@ -91,6 +95,8 @@ static cpumask_t irq_enabled_cpus;
#define WD_TIMO 60 /* Default heartbeat = 60 seconds */
+#define CVMX_GSERX_SCRATCH(offset) (CVMX_ADD_IO_SEG(0x0001180090000020ull) + ((offset) & 15) * 0x1000000ull)
+
static int heartbeat = WD_TIMO;
module_param(heartbeat, int, 0444);
MODULE_PARM_DESC(heartbeat,
@@ -115,21 +121,12 @@ void octeon_wdt_nmi_stage2(void);
static int cpu2core(int cpu)
{
#ifdef CONFIG_SMP
- return cpu_logical_map(cpu);
+ return cpu_logical_map(cpu) & 0x3f;
#else
return cvmx_get_core_num();
#endif
}
-static int core2cpu(int coreid)
-{
-#ifdef CONFIG_SMP
- return cpu_number_map(coreid);
-#else
- return 0;
-#endif
-}
-
/**
* Poke the watchdog when an interrupt is received
*
@@ -140,13 +137,14 @@ static int core2cpu(int coreid)
*/
static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
{
- unsigned int core = cvmx_get_core_num();
- int cpu = core2cpu(core);
+ int cpu = raw_smp_processor_id();
+ unsigned int core = cpu2core(cpu);
+ int node = cpu_to_node(cpu);
if (do_countdown) {
if (per_cpu_countdown[cpu] > 0) {
/* We're alive, poke the watchdog */
- cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
+ cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
per_cpu_countdown[cpu]--;
} else {
/* Bad news, you are about to reboot. */
@@ -155,7 +153,7 @@ static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
}
} else {
/* Not open, just ping away... */
- cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
+ cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
}
return IRQ_HANDLED;
}
@@ -280,26 +278,74 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
}
octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");
+
+ /*
+ * G-30204: We must trigger a soft reset before watchdog
+ * does an incomplete job of doing it.
+ */
+ if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX)) {
+ u64 scr;
+ unsigned int node = cvmx_get_node_num();
+ unsigned int lcore = cvmx_get_local_core_num();
+ union cvmx_ciu_wdogx ciu_wdog;
+
+ /*
+ * Wait for other cores to print out information, but
+ * not too long. Do the soft reset before watchdog
+ * can trigger it.
+ */
+ do {
+ ciu_wdog.u64 = cvmx_read_csr_node(node, CVMX_CIU_WDOGX(lcore));
+ } while (ciu_wdog.s.cnt > 0x10000);
+
+ scr = cvmx_read_csr_node(0, CVMX_GSERX_SCRATCH(0));
+ scr |= 1 << 11; /* Indicate watchdog in bit 11 */
+ cvmx_write_csr_node(0, CVMX_GSERX_SCRATCH(0), scr);
+ cvmx_write_csr_node(0, CVMX_RST_SOFT_RST, 1);
+ }
+}
+
+static int octeon_wdt_cpu_to_irq(int cpu)
+{
+ unsigned int coreid;
+ int node;
+ int irq;
+
+ coreid = cpu2core(cpu);
+ node = cpu_to_node(cpu);
+
+ if (octeon_has_feature(OCTEON_FEATURE_CIU3)) {
+ struct irq_domain *domain;
+ int hwirq;
+
+ domain = octeon_irq_get_block_domain(node,
+ WD_BLOCK_NUMBER);
+ hwirq = WD_BLOCK_NUMBER << 12 | 0x200 | coreid;
+ irq = irq_find_mapping(domain, hwirq);
+ } else {
+ irq = OCTEON_IRQ_WDOG0 + coreid;
+ }
+ return irq;
}
static int octeon_wdt_cpu_pre_down(unsigned int cpu)
{
unsigned int core;
- unsigned int irq;
+ int node;
union cvmx_ciu_wdogx ciu_wdog;
core = cpu2core(cpu);
- irq = OCTEON_IRQ_WDOG0 + core;
+ node = cpu_to_node(cpu);
/* Poke the watchdog to clear out its state */
- cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
+ cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
/* Disable the hardware. */
ciu_wdog.u64 = 0;
- cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
+ cvmx_write_csr_node(node, CVMX_CIU_WDOGX(core), ciu_wdog.u64);
- free_irq(irq, octeon_wdt_poke_irq);
+ free_irq(octeon_wdt_cpu_to_irq(cpu), octeon_wdt_poke_irq);
return 0;
}
@@ -308,33 +354,56 @@ static int octeon_wdt_cpu_online(unsigned int cpu)
unsigned int core;
unsigned int irq;
union cvmx_ciu_wdogx ciu_wdog;
+ int node;
+ struct irq_domain *domain;
+ int hwirq;
core = cpu2core(cpu);
+ node = cpu_to_node(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);
+ cvmx_write_csr_node(node, CVMX_CIU_WDOGX(core), ciu_wdog.u64);
per_cpu_countdown[cpu] = countdown_reset;
- irq = OCTEON_IRQ_WDOG0 + core;
+ if (octeon_has_feature(OCTEON_FEATURE_CIU3)) {
+ /* Must get the domain for the watchdog block */
+ domain = octeon_irq_get_block_domain(node, WD_BLOCK_NUMBER);
+
+ /* Get a irq for the wd intsn (hardware interrupt) */
+ hwirq = WD_BLOCK_NUMBER << 12 | 0x200 | core;
+ irq = irq_create_mapping(domain, hwirq);
+ irqd_set_trigger_type(irq_get_irq_data(irq),
+ IRQ_TYPE_EDGE_RISING);
+ } else
+ irq = OCTEON_IRQ_WDOG0 + core;
if (request_irq(irq, octeon_wdt_poke_irq,
IRQF_NO_THREAD, "octeon_wdt", octeon_wdt_poke_irq))
panic("octeon_wdt: Couldn't obtain irq %d", irq);
+ /* Must set the irq affinity here */
+ if (octeon_has_feature(OCTEON_FEATURE_CIU3)) {
+ cpumask_t mask;
+
+ cpumask_clear(&mask);
+ cpumask_set_cpu(cpu, &mask);
+ irq_set_affinity(irq, &mask);
+ }
+
cpumask_set_cpu(cpu, &irq_enabled_cpus);
/* Poke the watchdog to clear out its state */
- cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
+ cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
/* Finally enable the watchdog now that all handlers are installed */
ciu_wdog.u64 = 0;
ciu_wdog.s.len = timeout_cnt;
ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */
- cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
+ cvmx_write_csr_node(node, CVMX_CIU_WDOGX(core), ciu_wdog.u64);
return 0;
}
@@ -343,20 +412,20 @@ static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog)
{
int cpu;
int coreid;
+ int node;
if (disable)
return 0;
for_each_online_cpu(cpu) {
coreid = cpu2core(cpu);
- cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
+ node = cpu_to_node(cpu);
+ cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(coreid), 1);
per_cpu_countdown[cpu] = countdown_reset;
if ((countdown_reset || !do_countdown) &&
!cpumask_test_cpu(cpu, &irq_enabled_cpus)) {
/* We have to enable the irq */
- int irq = OCTEON_IRQ_WDOG0 + coreid;
-
- enable_irq(irq);
+ enable_irq(octeon_wdt_cpu_to_irq(cpu));
cpumask_set_cpu(cpu, &irq_enabled_cpus);
}
}
@@ -395,6 +464,7 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
int cpu;
int coreid;
union cvmx_ciu_wdogx ciu_wdog;
+ int node;
if (t <= 0)
return -1;
@@ -406,12 +476,13 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
for_each_online_cpu(cpu) {
coreid = cpu2core(cpu);
- cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
+ node = cpu_to_node(cpu);
+ cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(coreid), 1);
ciu_wdog.u64 = 0;
ciu_wdog.s.len = timeout_cnt;
ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */
- cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64);
- cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
+ cvmx_write_csr_node(node, CVMX_CIU_WDOGX(coreid), ciu_wdog.u64);
+ cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(coreid), 1);
}
octeon_wdt_ping(wdog); /* Get the irqs back on. */
return 0;
@@ -467,6 +538,8 @@ static int __init octeon_wdt_init(void)
if (OCTEON_IS_MODEL(OCTEON_CN68XX))
divisor = 0x200;
+ else if (OCTEON_IS_MODEL(OCTEON_CN78XX))
+ divisor = 0x400;
else
divisor = 0x100;
--
2.1.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 8/8] watchdog: octeon-wdt: Add support for 78XX SOCs.
2017-08-29 15:40 ` [PATCH 8/8] watchdog: octeon-wdt: Add support for 78XX SOCs Steven J. Hill
@ 2017-08-30 4:34 ` Guenter Roeck
0 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2017-08-30 4:34 UTC (permalink / raw)
To: Steven J. Hill; +Cc: linux-mips, linux-watchdog, ralf
On Tue, Aug 29, 2017 at 10:40:38AM -0500, Steven J. Hill wrote:
> From: Carlos Munoz <carlos.munoz@caviumnetworks.com>
>
> Signed-off-by: Carlos Munoz <carlos.munoz@caviumnetworks.com>
> 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>
> ---
> drivers/watchdog/octeon-wdt-main.c | 133 ++++++++++++++++++++++++++++---------
> 1 file changed, 103 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
> index 410800f..0ec419a 100644
> --- a/drivers/watchdog/octeon-wdt-main.c
> +++ b/drivers/watchdog/octeon-wdt-main.c
> @@ -70,6 +70,10 @@
> #include <asm/octeon/octeon.h>
> #include <asm/octeon/cvmx-boot-vector.h>
> #include <asm/octeon/cvmx-ciu2-defs.h>
> +#include <asm/octeon/cvmx-rst-defs.h>
> +
> +/* Watchdog interrupt major block number (8 MSBs of intsn) */
> +#define WD_BLOCK_NUMBER 0x01
>
> static int divisor;
>
> @@ -91,6 +95,8 @@ static cpumask_t irq_enabled_cpus;
>
> #define WD_TIMO 60 /* Default heartbeat = 60 seconds */
>
> +#define CVMX_GSERX_SCRATCH(offset) (CVMX_ADD_IO_SEG(0x0001180090000020ull) + ((offset) & 15) * 0x1000000ull)
> +
> static int heartbeat = WD_TIMO;
> module_param(heartbeat, int, 0444);
> MODULE_PARM_DESC(heartbeat,
> @@ -115,21 +121,12 @@ void octeon_wdt_nmi_stage2(void);
> static int cpu2core(int cpu)
> {
> #ifdef CONFIG_SMP
> - return cpu_logical_map(cpu);
> + return cpu_logical_map(cpu) & 0x3f;
> #else
> return cvmx_get_core_num();
> #endif
> }
>
> -static int core2cpu(int coreid)
> -{
> -#ifdef CONFIG_SMP
> - return cpu_number_map(coreid);
> -#else
> - return 0;
> -#endif
> -}
> -
> /**
> * Poke the watchdog when an interrupt is received
> *
> @@ -140,13 +137,14 @@ static int core2cpu(int coreid)
> */
> static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
> {
> - unsigned int core = cvmx_get_core_num();
> - int cpu = core2cpu(core);
> + int cpu = raw_smp_processor_id();
> + unsigned int core = cpu2core(cpu);
> + int node = cpu_to_node(cpu);
>
> if (do_countdown) {
> if (per_cpu_countdown[cpu] > 0) {
> /* We're alive, poke the watchdog */
> - cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
> + cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
> per_cpu_countdown[cpu]--;
> } else {
> /* Bad news, you are about to reboot. */
> @@ -155,7 +153,7 @@ static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
> }
> } else {
> /* Not open, just ping away... */
> - cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
> + cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
> }
> return IRQ_HANDLED;
> }
> @@ -280,26 +278,74 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
> }
>
> octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");
> +
> + /*
> + * G-30204: We must trigger a soft reset before watchdog
> + * does an incomplete job of doing it.
> + */
> + if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX)) {
> + u64 scr;
> + unsigned int node = cvmx_get_node_num();
> + unsigned int lcore = cvmx_get_local_core_num();
> + union cvmx_ciu_wdogx ciu_wdog;
> +
> + /*
> + * Wait for other cores to print out information, but
> + * not too long. Do the soft reset before watchdog
> + * can trigger it.
> + */
> + do {
> + ciu_wdog.u64 = cvmx_read_csr_node(node, CVMX_CIU_WDOGX(lcore));
> + } while (ciu_wdog.s.cnt > 0x10000);
> +
> + scr = cvmx_read_csr_node(0, CVMX_GSERX_SCRATCH(0));
> + scr |= 1 << 11; /* Indicate watchdog in bit 11 */
> + cvmx_write_csr_node(0, CVMX_GSERX_SCRATCH(0), scr);
> + cvmx_write_csr_node(0, CVMX_RST_SOFT_RST, 1);
> + }
> +}
> +
> +static int octeon_wdt_cpu_to_irq(int cpu)
> +{
> + unsigned int coreid;
> + int node;
> + int irq;
> +
> + coreid = cpu2core(cpu);
> + node = cpu_to_node(cpu);
> +
> + if (octeon_has_feature(OCTEON_FEATURE_CIU3)) {
> + struct irq_domain *domain;
> + int hwirq;
> +
> + domain = octeon_irq_get_block_domain(node,
> + WD_BLOCK_NUMBER);
> + hwirq = WD_BLOCK_NUMBER << 12 | 0x200 | coreid;
> + irq = irq_find_mapping(domain, hwirq);
> + } else {
> + irq = OCTEON_IRQ_WDOG0 + coreid;
> + }
> + return irq;
> }
>
> static int octeon_wdt_cpu_pre_down(unsigned int cpu)
> {
> unsigned int core;
> - unsigned int irq;
> + int node;
> union cvmx_ciu_wdogx ciu_wdog;
>
> core = cpu2core(cpu);
>
> - irq = OCTEON_IRQ_WDOG0 + core;
> + node = cpu_to_node(cpu);
>
> /* Poke the watchdog to clear out its state */
> - cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
> + cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
>
> /* Disable the hardware. */
> ciu_wdog.u64 = 0;
> - cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
> + cvmx_write_csr_node(node, CVMX_CIU_WDOGX(core), ciu_wdog.u64);
>
> - free_irq(irq, octeon_wdt_poke_irq);
> + free_irq(octeon_wdt_cpu_to_irq(cpu), octeon_wdt_poke_irq);
> return 0;
> }
>
> @@ -308,33 +354,56 @@ static int octeon_wdt_cpu_online(unsigned int cpu)
> unsigned int core;
> unsigned int irq;
> union cvmx_ciu_wdogx ciu_wdog;
> + int node;
> + struct irq_domain *domain;
> + int hwirq;
>
> core = cpu2core(cpu);
> + node = cpu_to_node(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);
> + cvmx_write_csr_node(node, CVMX_CIU_WDOGX(core), ciu_wdog.u64);
>
> per_cpu_countdown[cpu] = countdown_reset;
>
> - irq = OCTEON_IRQ_WDOG0 + core;
> + if (octeon_has_feature(OCTEON_FEATURE_CIU3)) {
> + /* Must get the domain for the watchdog block */
> + domain = octeon_irq_get_block_domain(node, WD_BLOCK_NUMBER);
> +
> + /* Get a irq for the wd intsn (hardware interrupt) */
> + hwirq = WD_BLOCK_NUMBER << 12 | 0x200 | core;
> + irq = irq_create_mapping(domain, hwirq);
> + irqd_set_trigger_type(irq_get_irq_data(irq),
> + IRQ_TYPE_EDGE_RISING);
> + } else
> + irq = OCTEON_IRQ_WDOG0 + core;
>
> if (request_irq(irq, octeon_wdt_poke_irq,
> IRQF_NO_THREAD, "octeon_wdt", octeon_wdt_poke_irq))
> panic("octeon_wdt: Couldn't obtain irq %d", irq);
>
> + /* Must set the irq affinity here */
> + if (octeon_has_feature(OCTEON_FEATURE_CIU3)) {
> + cpumask_t mask;
> +
> + cpumask_clear(&mask);
> + cpumask_set_cpu(cpu, &mask);
> + irq_set_affinity(irq, &mask);
> + }
> +
> cpumask_set_cpu(cpu, &irq_enabled_cpus);
>
> /* Poke the watchdog to clear out its state */
> - cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
> + cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
>
> /* Finally enable the watchdog now that all handlers are installed */
> ciu_wdog.u64 = 0;
> ciu_wdog.s.len = timeout_cnt;
> ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */
> - cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
> + cvmx_write_csr_node(node, CVMX_CIU_WDOGX(core), ciu_wdog.u64);
>
> return 0;
> }
> @@ -343,20 +412,20 @@ static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog)
> {
> int cpu;
> int coreid;
> + int node;
>
> if (disable)
> return 0;
>
> for_each_online_cpu(cpu) {
> coreid = cpu2core(cpu);
> - cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
> + node = cpu_to_node(cpu);
> + cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(coreid), 1);
> per_cpu_countdown[cpu] = countdown_reset;
> if ((countdown_reset || !do_countdown) &&
> !cpumask_test_cpu(cpu, &irq_enabled_cpus)) {
> /* We have to enable the irq */
> - int irq = OCTEON_IRQ_WDOG0 + coreid;
> -
> - enable_irq(irq);
> + enable_irq(octeon_wdt_cpu_to_irq(cpu));
> cpumask_set_cpu(cpu, &irq_enabled_cpus);
> }
> }
> @@ -395,6 +464,7 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
> int cpu;
> int coreid;
> union cvmx_ciu_wdogx ciu_wdog;
> + int node;
>
> if (t <= 0)
> return -1;
> @@ -406,12 +476,13 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
>
> for_each_online_cpu(cpu) {
> coreid = cpu2core(cpu);
> - cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
> + node = cpu_to_node(cpu);
> + cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(coreid), 1);
> ciu_wdog.u64 = 0;
> ciu_wdog.s.len = timeout_cnt;
> ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */
> - cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64);
> - cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
> + cvmx_write_csr_node(node, CVMX_CIU_WDOGX(coreid), ciu_wdog.u64);
> + cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(coreid), 1);
> }
> octeon_wdt_ping(wdog); /* Get the irqs back on. */
> return 0;
> @@ -467,6 +538,8 @@ static int __init octeon_wdt_init(void)
>
> if (OCTEON_IS_MODEL(OCTEON_CN68XX))
> divisor = 0x200;
> + else if (OCTEON_IS_MODEL(OCTEON_CN78XX))
> + divisor = 0x400;
> else
> divisor = 0x100;
>
> --
> 2.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread