Commit 0cd4e7a9 authored by David Daney's avatar David Daney Committed by Ralf Baechle

watchdog: octeon-wdt: Add support for cn68XX SOCs.

Signed-off-by: default avatarDavid Daney <david.daney@cavium.com>
Signed-off-by: default avatarCarlos Munoz <cmunoz@caviumnetworks.com>
Signed-off-by: default avatarChandrakala Chavva <cchavva@caviumnetworks.com>
Acked-by: default avatarGuenter Roeck <linux@roeck-us.net>
Cc: linux-mips@linux-mips.org
Cc: linux-watchdog@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/17213/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 381cec02
...@@ -69,6 +69,9 @@ ...@@ -69,6 +69,9 @@
#include <asm/octeon/octeon.h> #include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-boot-vector.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. */ /* The count needed to achieve timeout_sec. */
static unsigned int timeout_cnt; static unsigned int timeout_cnt;
...@@ -227,10 +230,10 @@ void octeon_wdt_nmi_stage3(u64 reg[32]) ...@@ -227,10 +230,10 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
u64 cp0_epc = read_c0_epc(); u64 cp0_epc = read_c0_epc();
/* Delay so output from all cores output is not jumbled together. */ /* 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_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"); octeon_wdt_write_string(" ***\r\n");
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
octeon_wdt_write_string("\t"); octeon_wdt_write_string("\t");
...@@ -253,11 +256,28 @@ void octeon_wdt_nmi_stage3(u64 reg[32]) ...@@ -253,11 +256,28 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
octeon_wdt_write_hex(cp0_cause, 16); octeon_wdt_write_hex(cp0_cause, 16);
octeon_wdt_write_string("\r\n"); 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_string("\tsum0\t0x");
octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16); octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16);
octeon_wdt_write_string("\ten0\t0x"); octeon_wdt_write_string("\ten0\t0x");
octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16); octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16);
octeon_wdt_write_string("\r\n"); octeon_wdt_write_string("\r\n");
}
octeon_wdt_write_string("*** Chip soft reset soon ***\r\n"); octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");
} }
...@@ -366,7 +386,7 @@ static void octeon_wdt_calc_parameters(int t) ...@@ -366,7 +386,7 @@ static void octeon_wdt_calc_parameters(int t)
countdown_reset = periods > 2 ? periods - 2 : 0; countdown_reset = periods > 2 ? periods - 2 : 0;
heartbeat = t; 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, static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
...@@ -437,9 +457,7 @@ static enum cpuhp_state octeon_wdt_online; ...@@ -437,9 +457,7 @@ static enum cpuhp_state octeon_wdt_online;
*/ */
static int __init octeon_wdt_init(void) static int __init octeon_wdt_init(void)
{ {
int i;
int ret; int ret;
u64 *ptr;
octeon_wdt_bootvector = cvmx_boot_vector_get(); octeon_wdt_bootvector = cvmx_boot_vector_get();
if (!octeon_wdt_bootvector) { if (!octeon_wdt_bootvector) {
...@@ -447,10 +465,15 @@ static int __init octeon_wdt_init(void) ...@@ -447,10 +465,15 @@ static int __init octeon_wdt_init(void)
return -ENOMEM; return -ENOMEM;
} }
if (OCTEON_IS_MODEL(OCTEON_CN68XX))
divisor = 0x200;
else
divisor = 0x100;
/* /*
* Watchdog time expiration length = The 16 bits of LEN * Watchdog time expiration length = The 16 bits of LEN
* represent the most significant bits of a 24 bit decrementer * 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 * Try for a timeout of 5 sec, if that fails a smaller number
* of even seconds, * of even seconds,
...@@ -458,8 +481,7 @@ static int __init octeon_wdt_init(void) ...@@ -458,8 +481,7 @@ static int __init octeon_wdt_init(void)
max_timeout_sec = 6; max_timeout_sec = 6;
do { do {
max_timeout_sec--; max_timeout_sec--;
timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_cnt = ((octeon_get_io_clock_rate() / divisor) * max_timeout_sec) >> 8;
max_timeout_sec) >> 8;
} while (timeout_cnt > 65535); } while (timeout_cnt > 65535);
BUG_ON(timeout_cnt == 0); BUG_ON(timeout_cnt == 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment