summaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorDavid Daney <david.daney@cavium.com>2017-08-29 11:40:37 -0400
committerRalf Baechle <ralf@linux-mips.org>2017-09-04 15:19:03 -0400
commit0cd4e7a918863a332eddd3d57d778fe93697053e (patch)
treea91b37a9074eceab6343beaefaa1deb8f6271487 /drivers/watchdog
parent381cec022e46f51268f3e33c9c60764fb56f73df (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.c48
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
74static int divisor;
72 75
73/* The count needed to achieve timeout_sec. */ 76/* The count needed to achieve timeout_sec. */
74static unsigned int timeout_cnt; 77static 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
372static int octeon_wdt_set_timeout(struct watchdog_device *wdog, 392static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
@@ -437,9 +457,7 @@ static enum cpuhp_state octeon_wdt_online;
437 */ 457 */
438static int __init octeon_wdt_init(void) 458static 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);