Commit 5f20cc02b0b10525843813e81603e1dc82033e76

Authored by Breno Lima
Committed by Ye Li
1 parent a49a064fba

MLK-22743 mx7ulp: Update unlock and refresh sequences in sWDOG driver

According to i.MX7ULP Reference Manual the second word write for both
UNLOCK and REFRESH operations must occur in maximum 16 bus clock.

The current code is using writel() function which has a DMB barrier to
order the memory access. The DMB between two words write may introduce
some delay in certain circumstance, causing a WDOG timeout due to 16 bus
clock window requirement.

Replace writel() function by __raw_writel() to achieve a faster memory
access and avoid such issue.

Signed-off-by: Breno Lima <breno.lima@nxp.com>
Reviewed-by: Ye Li <ye.li@nxp.com>
(cherry picked from commit 5dd8c46d68d3267e989f980598a4e3e2ed04d4f9)

Showing 1 changed file with 12 additions and 6 deletions Inline Diff

drivers/watchdog/ulp_wdog.c
1 // SPDX-License-Identifier: GPL-2.0+ 1 // SPDX-License-Identifier: GPL-2.0+
2 /* 2 /*
3 * Copyright (C) 2016 Freescale Semiconductor, Inc. 3 * Copyright (C) 2016 Freescale Semiconductor, Inc.
4 */ 4 */
5 5
6 #include <common.h> 6 #include <common.h>
7 #include <asm/io.h> 7 #include <asm/io.h>
8 #include <asm/arch/imx-regs.h> 8 #include <asm/arch/imx-regs.h>
9 9
10 /* 10 /*
11 * MX7ULP WDOG Register Map 11 * MX7ULP WDOG Register Map
12 */ 12 */
13 struct wdog_regs { 13 struct wdog_regs {
14 u8 cs1; 14 u8 cs1;
15 u8 cs2; 15 u8 cs2;
16 u16 reserve0; 16 u16 reserve0;
17 u32 cnt; 17 u32 cnt;
18 u32 toval; 18 u32 toval;
19 u32 win; 19 u32 win;
20 }; 20 };
21 21
22 #ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS 22 #ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS
23 #define CONFIG_WATCHDOG_TIMEOUT_MSECS 0x1500 23 #define CONFIG_WATCHDOG_TIMEOUT_MSECS 0x1500
24 #endif 24 #endif
25 25
26 #define REFRESH_WORD0 0xA602 /* 1st refresh word */ 26 #define REFRESH_WORD0 0xA602 /* 1st refresh word */
27 #define REFRESH_WORD1 0xB480 /* 2nd refresh word */ 27 #define REFRESH_WORD1 0xB480 /* 2nd refresh word */
28 28
29 #define UNLOCK_WORD0 0xC520 /* 1st unlock word */ 29 #define UNLOCK_WORD0 0xC520 /* 1st unlock word */
30 #define UNLOCK_WORD1 0xD928 /* 2nd unlock word */ 30 #define UNLOCK_WORD1 0xD928 /* 2nd unlock word */
31 31
32 #define WDGCS1_WDGE (1<<7) 32 #define WDGCS1_WDGE (1<<7)
33 #define WDGCS1_WDGUPDATE (1<<5) 33 #define WDGCS1_WDGUPDATE (1<<5)
34 34
35 #define WDGCS2_FLG (1<<6) 35 #define WDGCS2_FLG (1<<6)
36 36
37 #define WDG_BUS_CLK (0x0) 37 #define WDG_BUS_CLK (0x0)
38 #define WDG_LPO_CLK (0x1) 38 #define WDG_LPO_CLK (0x1)
39 #define WDG_32KHZ_CLK (0x2) 39 #define WDG_32KHZ_CLK (0x2)
40 #define WDG_EXT_CLK (0x3) 40 #define WDG_EXT_CLK (0x3)
41 41
42 void hw_watchdog_set_timeout(u16 val) 42 void hw_watchdog_set_timeout(u16 val)
43 { 43 {
44 /* setting timeout value */ 44 /* setting timeout value */
45 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; 45 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
46 46
47 writel(val, &wdog->toval); 47 writel(val, &wdog->toval);
48 } 48 }
49 49
50 void hw_watchdog_reset(void) 50 void hw_watchdog_reset(void)
51 { 51 {
52 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; 52 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
53 53
54 writel(REFRESH_WORD0, &wdog->cnt); 54 dmb();
55 writel(REFRESH_WORD1, &wdog->cnt); 55 __raw_writel(REFRESH_WORD0, &wdog->cnt);
56 __raw_writel(REFRESH_WORD1, &wdog->cnt);
57 dmb();
56 } 58 }
57 59
58 void hw_watchdog_init(void) 60 void hw_watchdog_init(void)
59 { 61 {
60 u8 val; 62 u8 val;
61 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; 63 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
62 64
63 writel(UNLOCK_WORD0, &wdog->cnt); 65 dmb();
64 writel(UNLOCK_WORD1, &wdog->cnt); 66 __raw_writel(UNLOCK_WORD0, &wdog->cnt);
67 __raw_writel(UNLOCK_WORD1, &wdog->cnt);
68 dmb();
65 69
66 val = readb(&wdog->cs2); 70 val = readb(&wdog->cs2);
67 val |= WDGCS2_FLG; 71 val |= WDGCS2_FLG;
68 writeb(val, &wdog->cs2); 72 writeb(val, &wdog->cs2);
69 73
70 hw_watchdog_set_timeout(CONFIG_WATCHDOG_TIMEOUT_MSECS); 74 hw_watchdog_set_timeout(CONFIG_WATCHDOG_TIMEOUT_MSECS);
71 writel(0, &wdog->win); 75 writel(0, &wdog->win);
72 76
73 writeb(WDG_LPO_CLK, &wdog->cs2);/* setting 1-kHz clock source */ 77 writeb(WDG_LPO_CLK, &wdog->cs2);/* setting 1-kHz clock source */
74 writeb((WDGCS1_WDGE | WDGCS1_WDGUPDATE), &wdog->cs1);/* enable counter running */ 78 writeb((WDGCS1_WDGE | WDGCS1_WDGUPDATE), &wdog->cs1);/* enable counter running */
75 79
76 hw_watchdog_reset(); 80 hw_watchdog_reset();
77 } 81 }
78 82
79 void reset_cpu(ulong addr) 83 void reset_cpu(ulong addr)
80 { 84 {
81 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; 85 struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
82 86
83 writel(UNLOCK_WORD0, &wdog->cnt); 87 dmb();
84 writel(UNLOCK_WORD1, &wdog->cnt); 88 __raw_writel(UNLOCK_WORD0, &wdog->cnt);
89 __raw_writel(UNLOCK_WORD1, &wdog->cnt);
90 dmb();
85 91
86 hw_watchdog_set_timeout(5); /* 5ms timeout */ 92 hw_watchdog_set_timeout(5); /* 5ms timeout */
87 writel(0, &wdog->win); 93 writel(0, &wdog->win);
88 94
89 writeb(WDG_LPO_CLK, &wdog->cs2);/* setting 1-kHz clock source */ 95 writeb(WDG_LPO_CLK, &wdog->cs2);/* setting 1-kHz clock source */
90 writeb(WDGCS1_WDGE, &wdog->cs1);/* enable counter running */ 96 writeb(WDGCS1_WDGE, &wdog->cs1);/* enable counter running */
91 97
92 hw_watchdog_reset(); 98 hw_watchdog_reset();
93 99
94 while (1); 100 while (1);
95 } 101 }
96 102