Skip to content

Commit 01394aa

Browse files
Avinash95francois-berder
authored andcommitted
pistachio: add watchdog support
Change-Id: I5859d15e6c114734f1813d1e67d86aed587cdb63 Signed-off-by: Avinash Tahakik <[email protected]>
1 parent 46b1d3b commit 01394aa

File tree

8 files changed

+360
-1
lines changed

8 files changed

+360
-1
lines changed

board/imgtec/pistachio_bub/clocks.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@
128128
#define USB_TIMEOUT_VALUE_US 200000
129129
#define SYS_CLK_LOCK_DELAY 3
130130

131+
/* Definitions for Watchdog setup */
132+
#define WDCLKDIV1_CTRL_ADDR (0x18144800 + 0x0124)
133+
#define WDCLKDIV1_MASK 0x0000007F
134+
#define WDCLKOUT_CTRL_ADDR (0x18144800 + 0x0128)
135+
#define WDCLKOUT_MASK 0x0000007F
131136

132137
#ifdef CONFIG_SPL_BUILD
133138
struct pll_parameters {
@@ -517,4 +522,32 @@ void i2c_clk_setup(u8 divider1, u16 divider2, u8 interface)
517522
reg |= divider2 & I2CCLKOUT_MASK;
518523
writel(reg, I2CCLKOUT_CTRL_ADDR(interface));
519524
}
525+
526+
/*
527+
* wd_clk_setup: sets up clocks for pistachio watchdog
528+
* divider1: 7-bit divider value
529+
* divider2: 7-bit divider value
530+
*/
531+
#ifdef CONFIG_PISTACHIO_WATCHDOG
532+
void wd_clk_setup(u8 divider1, u16 divider2)
533+
{
534+
u32 reg;
535+
536+
/* Check input parameters */
537+
assert(!(divider1 & ~(WDCLKDIV1_MASK)));
538+
assert(!(divider2 & ~(WDCLKOUT_MASK)));
539+
540+
/* Set divider 1 */
541+
reg = readl(WDCLKDIV1_CTRL_ADDR);
542+
reg &= ~WDCLKDIV1_MASK;
543+
reg |= divider1 & WDCLKDIV1_MASK;
544+
writel(reg, WDCLKDIV1_CTRL_ADDR);
545+
546+
/* Set divider 2 */
547+
reg = readl(WDCLKOUT_CTRL_ADDR);
548+
reg &= ~WDCLKOUT_MASK;
549+
reg |= divider2 & WDCLKOUT_MASK;
550+
writel(reg, WDCLKOUT_CTRL_ADDR);
551+
}
552+
#endif /*CONFIG_PISTACHIO_WATCHDOG*/
520553
#endif

board/imgtec/pistachio_bub/clocks.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ int usb_clk_setup(u8 divider, u8 refclksel, u8 fsel);
2525
void rom_clk_setup(u8 divider);
2626
void eth_clk_setup(u8 mux, u8 divider);
2727
void setup_clk_gate_defaults(void);
28+
#ifdef CONFIG_PISTACHIO_WATCHDOG
29+
void wd_clk_setup(u8 divider1, u16 divider2);
30+
#endif /*CONFIG_PISTACHIO_WATCHDOG*/
2831

2932
enum {
3033
CLOCKS_OK = 0,

board/imgtec/pistachio_bub/pistachio.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <asm/mipsregs.h>
2020
#include <asm/pistachio.h>
2121
#include <asm-generic/sections.h>
22+
#include <watchdog.h>
2223

2324
#include "mfio.h"
2425

@@ -169,6 +170,14 @@ int board_early_init_f(void)
169170
return 0;
170171
}
171172

173+
int board_late_init(void)
174+
{
175+
#ifdef CONFIG_PISTACHIO_WATCHDOG
176+
hw_watchdog_init();
177+
#endif
178+
return 0;
179+
}
180+
172181
int misc_init_r(void)
173182
{
174183
return 0;

board/imgtec/pistachio_bub/spl_pistachio.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <common.h>
1212
#include <linux/sizes.h>
1313
#include <spl.h>
14-
1514
#include "clocks.h"
1615
#include "ddr_init.h"
1716
#include "mfio.h"
@@ -78,6 +77,9 @@ void spl_lowlevel_init(void) {
7877
eth_clk_setup(0, 6);
7978
rom_clk_setup(1);
8079
usb_clk_setup(6, 2, 7);
80+
#ifdef CONFIG_PISTACHIO_WATCHDOG
81+
wd_clk_setup(87, 120);
82+
#endif
8183
#if defined(CONFIG_TARGET_PISTACHIO_MARDUK) || \
8284
defined(CONFIG_TARGET_PISTACHIO_BEETLE)
8385
mfio_setup_usb_pwr();

doc/README.watchdog

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,15 @@ CONFIG_XILINX_TB_WATCHDOG
3333

3434
CONFIG_BFIN_WATCHDOG
3535
Available for bf5xx and bf6xx to service the watchdog.
36+
37+
CONFIG_PISTACHIO_WATCHDOG
38+
Available for pistachio to service the watchdog.
39+
one needs to define following configs to have full watchdog support
40+
CONFIG_HW_WATCHDOG
41+
CONFIG_PISTACHIO_WATCHDOG
42+
CONFIG_SPL_WATCHDOG_SUPPORT
43+
CONFIG_BOARD_LATE_INIT
44+
45+
CONFIG_PISTACHIO_WATCHDOG_TIMEOUT_SEC
46+
Can be used to change the timeout for pistachio watchdog.
47+
Actual timeout may vary please check comment header in drivers/watchdog/pistachio_wdt.c

drivers/watchdog/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
1515
obj-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o
1616
obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
1717
obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
18+
obj-$(CONFIG_PISTACHIO_WATCHDOG) += pistachio_wdt.o

drivers/watchdog/pistachio_wdt.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (C) 2016 Imagination Technologies
3+
* Author: Avinash Tahakik <[email protected]>
4+
*
5+
* SPDX-License-Identifier: GPL-2.0+
6+
*
7+
* Notes
8+
* -----
9+
* The timeout value is rounded to the next power of two clock cycles.
10+
* This is configured using the PDC_WDT_CONFIG register, according to this
11+
* formula:
12+
*
13+
* timeout = 2^(delay + 1) clock cycles
14+
*
15+
* Where 'delay' is the value written in PDC_WDT_CONFIG register.
16+
*
17+
* Therefore, the hardware only allows to program watchdog timeouts, expressed
18+
* as a power of two number of watchdog clock cycles. The current implementation
19+
* guarantees that the actual watchdog timeout will be _at least_ the value
20+
* programmed in the imgpdg_wdt driver.
21+
*
22+
* The following table shows how the user-configured timeout relates
23+
* to the actual hardware timeout (watchdog clock @ 40000 Hz):
24+
*
25+
* input timeout | WD_DELAY | actual timeout
26+
* -----------------------------------
27+
* 10 | 18 | 13 seconds
28+
* 20 | 19 | 26 seconds
29+
* 30 | 20 | 52 seconds
30+
* 60 | 21 | 104 seconds
31+
*
32+
* Albeit coarse, this granularity would suffice most watchdog uses.
33+
* If the platform allows it, the user should be able to change the watchdog
34+
* clock rate and achieve a finer timeout granularity.
35+
*/
36+
37+
#include <common.h>
38+
#include <watchdog.h>
39+
#include <asm/io.h>
40+
#include <linux/log2.h>
41+
42+
/* registers */
43+
44+
#define PDC_WDT_BASE 0x18102100
45+
#define PDC_WDT_SOFT_RESET 0x00
46+
#define PDC_WDT_SOFT_RESET_VALUE 0X1
47+
#define PDC_WDT_CONFIG 0x04
48+
#define PDC_WDT_CONFIG_ENABLE (1 << 31)
49+
#define PDC_WDT_CONFIG_DELAY_MASK 0x1f
50+
51+
#define PDC_WDT_TICKLE1 0x08
52+
#define PDC_WDT_TICKLE1_MAGIC 0xabcd1234
53+
#define PDC_WDT_TICKLE2 0x0c
54+
#define PDC_WDT_TICKLE2_MAGIC 0x4321dcba
55+
56+
#define CLOCK_RATE 32871
57+
58+
#ifndef CONFIG_PISTACHIO_WATCHDOG_TIMEOUT_SEC
59+
#define CONFIG_PISTACHIO_WATCHDOG_TIMEOUT_SEC 60
60+
#endif
61+
62+
static void wdt_keepalive(void)
63+
{
64+
writel(PDC_WDT_TICKLE1_MAGIC, PDC_WDT_BASE + PDC_WDT_TICKLE1);
65+
writel(PDC_WDT_TICKLE2_MAGIC, PDC_WDT_BASE + PDC_WDT_TICKLE2);
66+
}
67+
68+
static void wdt_set_timeout(unsigned int timeout)
69+
{
70+
unsigned int val;
71+
72+
val = readl(PDC_WDT_BASE + PDC_WDT_CONFIG) & ~PDC_WDT_CONFIG_DELAY_MASK;
73+
val |= order_base_2(timeout * CLOCK_RATE) - 1;
74+
writel(val, PDC_WDT_BASE + PDC_WDT_CONFIG);
75+
}
76+
77+
void hw_watchdog_reset(void)
78+
{
79+
wdt_keepalive();
80+
}
81+
82+
void hw_watchdog_init(void)
83+
{
84+
unsigned int val;
85+
86+
wdt_set_timeout(CONFIG_PISTACHIO_WATCHDOG_TIMEOUT_SEC);
87+
88+
val = readl(PDC_WDT_BASE + PDC_WDT_CONFIG);
89+
val |= PDC_WDT_CONFIG_ENABLE;
90+
writel(val, PDC_WDT_BASE + PDC_WDT_CONFIG);
91+
}

0 commit comments

Comments
 (0)