diff options
author | David Daney <david.daney@cavium.com> | 2017-08-29 11:40:37 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2017-09-04 15:19:03 -0400 |
commit | 0cd4e7a918863a332eddd3d57d778fe93697053e (patch) | |
tree | a91b37a9074eceab6343beaefaa1deb8f6271487 /drivers/watchdog | |
parent | 381cec022e46f51268f3e33c9c60764fb56f73df (diff) |
watchdog: octeon-wdt: Add support for cn68XX SOCs.
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>
Cc: linux-mips@linux-mips.org
Cc: linux-watchdog@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/17213/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/octeon-wdt-main.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 73b510231169..410800f8432a 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c | |||
@@ -69,6 +69,9 @@ | |||
69 | 69 | ||
70 | #include <asm/octeon/octeon.h> | 70 | #include <asm/octeon/octeon.h> |
71 | #include <asm/octeon/cvmx-boot-vector.h> | 71 | #include <asm/octeon/cvmx-boot-vector.h> |
72 | #include <asm/octeon/cvmx-ciu2-defs.h> | ||
73 | |||
74 | static int divisor; | ||
72 | 75 | ||
73 | /* The count needed to achieve timeout_sec. */ | 76 | /* The count needed to achieve timeout_sec. */ |
74 | static unsigned int timeout_cnt; | 77 | static unsigned int timeout_cnt; |
@@ -227,10 +230,10 @@ void octeon_wdt_nmi_stage3(u64 reg[32]) | |||
227 | u64 cp0_epc = read_c0_epc(); | 230 | u64 cp0_epc = read_c0_epc(); |
228 | 231 | ||
229 | /* Delay so output from all cores output is not jumbled together. */ | 232 | /* Delay so output from all cores output is not jumbled together. */ |
230 | __delay(100000000ull * coreid); | 233 | udelay(85000 * coreid); |
231 | 234 | ||
232 | octeon_wdt_write_string("\r\n*** NMI Watchdog interrupt on Core 0x"); | 235 | octeon_wdt_write_string("\r\n*** NMI Watchdog interrupt on Core 0x"); |
233 | octeon_wdt_write_hex(coreid, 1); | 236 | octeon_wdt_write_hex(coreid, 2); |
234 | octeon_wdt_write_string(" ***\r\n"); | 237 | octeon_wdt_write_string(" ***\r\n"); |
235 | for (i = 0; i < 32; i++) { | 238 | for (i = 0; i < 32; i++) { |
236 | octeon_wdt_write_string("\t"); | 239 | octeon_wdt_write_string("\t"); |
@@ -253,11 +256,28 @@ void octeon_wdt_nmi_stage3(u64 reg[32]) | |||
253 | octeon_wdt_write_hex(cp0_cause, 16); | 256 | octeon_wdt_write_hex(cp0_cause, 16); |
254 | octeon_wdt_write_string("\r\n"); | 257 | octeon_wdt_write_string("\r\n"); |
255 | 258 | ||
256 | octeon_wdt_write_string("\tsum0\t0x"); | 259 | /* The CIU register is different for each Octeon model. */ |
257 | octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16); | 260 | if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { |
258 | octeon_wdt_write_string("\ten0\t0x"); | 261 | octeon_wdt_write_string("\tsrc_wd\t0x"); |
259 | octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16); | 262 | octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SRC_PPX_IP2_WDOG(coreid)), 16); |
260 | octeon_wdt_write_string("\r\n"); | 263 | octeon_wdt_write_string("\ten_wd\t0x"); |
264 | octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_EN_PPX_IP2_WDOG(coreid)), 16); | ||
265 | octeon_wdt_write_string("\r\n"); | ||
266 | octeon_wdt_write_string("\tsrc_rml\t0x"); | ||
267 | octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SRC_PPX_IP2_RML(coreid)), 16); | ||
268 | octeon_wdt_write_string("\ten_rml\t0x"); | ||
269 | octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_EN_PPX_IP2_RML(coreid)), 16); | ||
270 | octeon_wdt_write_string("\r\n"); | ||
271 | octeon_wdt_write_string("\tsum\t0x"); | ||
272 | octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU2_SUM_PPX_IP2(coreid)), 16); | ||
273 | octeon_wdt_write_string("\r\n"); | ||
274 | } else if (!octeon_has_feature(OCTEON_FEATURE_CIU3)) { | ||
275 | octeon_wdt_write_string("\tsum0\t0x"); | ||
276 | octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16); | ||
277 | octeon_wdt_write_string("\ten0\t0x"); | ||
278 | octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16); | ||
279 | octeon_wdt_write_string("\r\n"); | ||
280 | } | ||
261 | 281 | ||
262 | octeon_wdt_write_string("*** Chip soft reset soon ***\r\n"); | 282 | octeon_wdt_write_string("*** Chip soft reset soon ***\r\n"); |
263 | } | 283 | } |
@@ -366,7 +386,7 @@ static void octeon_wdt_calc_parameters(int t) | |||
366 | 386 | ||
367 | countdown_reset = periods > 2 ? periods - 2 : 0; | 387 | countdown_reset = periods > 2 ? periods - 2 : 0; |
368 | heartbeat = t; | 388 | heartbeat = t; |
369 | timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8; | 389 | timeout_cnt = ((octeon_get_io_clock_rate() / divisor) * timeout_sec) >> 8; |
370 | } | 390 | } |
371 | 391 | ||
372 | static int octeon_wdt_set_timeout(struct watchdog_device *wdog, | 392 | static int octeon_wdt_set_timeout(struct watchdog_device *wdog, |
@@ -437,9 +457,7 @@ static enum cpuhp_state octeon_wdt_online; | |||
437 | */ | 457 | */ |
438 | static int __init octeon_wdt_init(void) | 458 | static int __init octeon_wdt_init(void) |
439 | { | 459 | { |
440 | int i; | ||
441 | int ret; | 460 | int ret; |
442 | u64 *ptr; | ||
443 | 461 | ||
444 | octeon_wdt_bootvector = cvmx_boot_vector_get(); | 462 | octeon_wdt_bootvector = cvmx_boot_vector_get(); |
445 | if (!octeon_wdt_bootvector) { | 463 | if (!octeon_wdt_bootvector) { |
@@ -447,10 +465,15 @@ static int __init octeon_wdt_init(void) | |||
447 | return -ENOMEM; | 465 | return -ENOMEM; |
448 | } | 466 | } |
449 | 467 | ||
468 | if (OCTEON_IS_MODEL(OCTEON_CN68XX)) | ||
469 | divisor = 0x200; | ||
470 | else | ||
471 | divisor = 0x100; | ||
472 | |||
450 | /* | 473 | /* |
451 | * Watchdog time expiration length = The 16 bits of LEN | 474 | * Watchdog time expiration length = The 16 bits of LEN |
452 | * represent the most significant bits of a 24 bit decrementer | 475 | * represent the most significant bits of a 24 bit decrementer |
453 | * that decrements every 256 cycles. | 476 | * that decrements every divisor cycle. |
454 | * | 477 | * |
455 | * Try for a timeout of 5 sec, if that fails a smaller number | 478 | * Try for a timeout of 5 sec, if that fails a smaller number |
456 | * of even seconds, | 479 | * of even seconds, |
@@ -458,8 +481,7 @@ static int __init octeon_wdt_init(void) | |||
458 | max_timeout_sec = 6; | 481 | max_timeout_sec = 6; |
459 | do { | 482 | do { |
460 | max_timeout_sec--; | 483 | max_timeout_sec--; |
461 | timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * | 484 | timeout_cnt = ((octeon_get_io_clock_rate() / divisor) * max_timeout_sec) >> 8; |
462 | max_timeout_sec) >> 8; | ||
463 | } while (timeout_cnt > 65535); | 485 | } while (timeout_cnt > 65535); |
464 | 486 | ||
465 | BUG_ON(timeout_cnt == 0); | 487 | BUG_ON(timeout_cnt == 0); |