1 /*
2  * Copyright 2023 The Hafnium Authors.
3  *
4  * Use of this source code is governed by a BSD-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/BSD-3-Clause.
7  */
8 
9 #include "sp805.h"
10 
11 #include "hf/mmio.h"
12 
13 #include "test/hftest.h"
14 
sp805_write_wdog_load(void * base,uint32_t value)15 static inline void sp805_write_wdog_load(void *base, uint32_t value)
16 {
17 	mmio_write32_offset(base, SP805_WDOG_LOAD_OFF, value);
18 }
19 
sp805_write_wdog_ctrl(void * base,uint32_t value)20 static inline void sp805_write_wdog_ctrl(void *base, uint32_t value)
21 {
22 	/* Not setting reserved bits. */
23 	ASSERT_FALSE((value & ~SP805_WDOG_CTRL_MASK));
24 	mmio_write32_offset(base, SP805_WDOG_CTRL_OFF, value);
25 }
26 
sp805_write_wdog_int_clr(void * base,uint32_t value)27 static inline void sp805_write_wdog_int_clr(void *base, uint32_t value)
28 {
29 	mmio_write32_offset(base, SP805_WDOG_INT_CLR_OFF, value);
30 }
31 
sp805_write_wdog_lock(void * base,uint32_t value)32 static inline void sp805_write_wdog_lock(void *base, uint32_t value)
33 {
34 	mmio_write32_offset(base, SP805_WDOG_LOCK_OFF, value);
35 }
36 
sp805_wdog_start_(void * base,uint32_t wdog_cycles)37 static void sp805_wdog_start_(void *base, uint32_t wdog_cycles)
38 {
39 	/* Unlock to access the watchdog registers. */
40 	sp805_write_wdog_lock(base, SP805_WDOG_UNLOCK_ACCESS);
41 
42 	/* Write the number of cycles needed. */
43 	sp805_write_wdog_load(base, wdog_cycles);
44 
45 	/* Enable reset interrupt and watchdog interrupt on expiry. */
46 	sp805_write_wdog_ctrl(base,
47 			      SP805_WDOG_CTRL_RESEN | SP805_WDOG_CTRL_INTEN);
48 
49 	/* Lock registers so that they can't be accidently overwritten. */
50 	sp805_write_wdog_lock(base, 0x0);
51 }
52 
sp805_wdog_stop_(void * base)53 static void sp805_wdog_stop_(void *base)
54 {
55 	/* Unlock to access the watchdog registers. */
56 	sp805_write_wdog_lock(base, SP805_WDOG_UNLOCK_ACCESS);
57 
58 	/* Clearing INTEN bit stops the counter. */
59 	sp805_write_wdog_ctrl(base, 0x00);
60 
61 	/* Lock registers so that they can't be accidently overwritten. */
62 	sp805_write_wdog_lock(base, 0x0);
63 }
64 
sp805_wdog_refresh_(void * base)65 static void sp805_wdog_refresh_(void *base)
66 {
67 	/* Unlock to access the watchdog registers. */
68 	sp805_write_wdog_lock(base, SP805_WDOG_UNLOCK_ACCESS);
69 
70 	/*
71 	 * Write of any value to WdogIntClr clears interrupt and reloads
72 	 * the counter from the value in WdogLoad Register.
73 	 */
74 	sp805_write_wdog_int_clr(base, 1);
75 
76 	/* Lock registers so that they can't be accidently overwritten. */
77 	sp805_write_wdog_lock(base, 0x0);
78 }
79 
sp805_twdog_start(uint32_t wdog_cycles)80 void sp805_twdog_start(uint32_t wdog_cycles)
81 {
82 	sp805_wdog_start_((void *)SP805_TWDOG_BASE, wdog_cycles);
83 }
84 
sp805_twdog_stop(void)85 void sp805_twdog_stop(void)
86 {
87 	sp805_wdog_stop_((void *)SP805_TWDOG_BASE);
88 }
89 
sp805_twdog_refresh(void)90 void sp805_twdog_refresh(void)
91 {
92 	sp805_wdog_refresh_((void *)SP805_TWDOG_BASE);
93 }
94