xref: /aosp_15_r20/external/coreboot/src/soc/cavium/cn81xx/timer.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /*
4  * Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
5  */
6 
7 #include <delay.h>
8 #include <device/mmio.h>
9 #include <arch/lib_helpers.h>
10 #include <console/console.h>
11 #include <soc/clock.h>
12 #include <soc/timer.h>
13 #include <stdint.h>
14 #include <timer.h>
15 #include <soc/addressmap.h>
16 #include <assert.h>
17 
18 /* Global System Timers Unit (GTI) registers */
19 struct cn81xx_timer {
20 	u32 cc_cntcr;
21 	u32 cc_cntsr;
22 	u64 cc_cntcv;
23 	u8 rsvd[0x10];
24 	u32 cc_cntfid0;
25 	u32 cc_cntfid1;
26 	u8 rsvd2[0x98];
27 	u32 cc_cntrate;
28 	u32 cc_cntracc;
29 	u64 cc_cntadd;
30 	u64 cc_cntmb;
31 	u64 cc_cntmbts;
32 	u64 cc_cntmb_int;
33 	u64 cc_cntmb_int_set;
34 	u64 cc_cntmb_int_ena_clr;
35 	u64 cc_cntmb_int_ena_set;
36 	u64 cc_imp_ctl;
37 	u8 skip[0x1fef8];
38 	u32 ctl_cntfrq;
39 	u32 ctl_cntnsar;
40 	u32 ctl_cnttidr;
41 	u8 rsvd3[0x34];
42 	u32 ctl_cntacr0;
43 	u8 skip2[0x1ffb8];
44 	u64 cwd_wdog[48]; /* Offset 0x40000 */
45 	u8 skip3[0xfe80];
46 	u64 cwd_poke[48]; /* Offset 0x50000 */
47 };
48 
49 check_member(cn81xx_timer, cc_imp_ctl, 0x100);
50 check_member(cn81xx_timer, ctl_cntacr0, 0x20040);
51 check_member(cn81xx_timer, cwd_wdog[0], 0x40000);
52 check_member(cn81xx_timer, cwd_poke[0], 0x50000);
53 
54 #define GTI_CC_CNTCR_EN			(1 << 0)
55 #define GTI_CC_CNTCR_HDBG		(1 << 1)
56 #define GTI_CC_CNTCR_FCREQ		(1 << 8)
57 
58 #define GTI_CC_CNTSR_DBGH		(1 << 1)
59 #define GTI_CC_CNTSR_FCACK		(1 << 8)
60 
61 #define GTI_CWD_WDOG_MODE_SHIFT		0
62 #define GTI_CWD_WDOG_MODE_MASK		0x3
63 #define GTI_CWD_WDOG_STATE_SHIFT	2
64 #define GTI_CWD_WDOG_STATE_MASK		0x3
65 #define GTI_CWD_WDOG_LEN_SHIFT		4
66 #define GTI_CWD_WDOG_LEN_MASK		0xffff
67 #define GTI_CWD_WDOG_CNT_SHIFT		20
68 #define GTI_CWD_WDOG_CNT_MASK		0xffffff
69 #define GTI_CWD_WDOC_DSTOP		(1 << 44)
70 #define GTI_CWD_WDOC_GSTOP		(1 << 45)
71 
timer_raw_value(void)72 static uint64_t timer_raw_value(void)
73 {
74 	struct cn81xx_timer *timer = (void *)GTI_PF_BAR0;
75 
76 	return read64(&timer->cc_cntcv);
77 }
78 
79 /**
80  * Get GTI counter value.
81  * @param mt      Structure to fill
82  */
timer_monotonic_get(struct mono_time * mt)83 void timer_monotonic_get(struct mono_time *mt)
84 {
85 	mono_time_set_usecs(mt, timer_raw_value());
86 }
87 
88 /* Setup counter to operate at 1MHz */
89 static const size_t tickrate = 1000000;
90 
91 /**
92  * Init Global System Timers Unit (GTI).
93  * Configure timer to run at 1MHz tick-rate.
94  */
init_timer(void)95 void init_timer(void)
96 {
97 	struct cn81xx_timer *gti = (struct cn81xx_timer *)GTI_PF_BAR0;
98 
99 	/* Check if the counter was already setup */
100 	if (gti->cc_cntcr & GTI_CC_CNTCR_EN)
101 		return;
102 
103 	u64 sclk = thunderx_get_io_clock();
104 
105 	/* Use coprocessor clock source */
106 	write32(&gti->cc_imp_ctl, 0);
107 
108 	write32(&gti->cc_cntfid0, tickrate);
109 	write32(&gti->ctl_cntfrq, tickrate);
110 	write32(&gti->cc_cntrate, ((1ULL << 32) * tickrate) / sclk);
111 
112 	/* Enable the counter */
113 	setbits32(&gti->cc_cntcr, GTI_CC_CNTCR_EN);
114 
115 	//u32 u = (CNTPS_CTL_EL1_IMASK | CNTPS_CTL_EL1_EN);
116 	//BDK_MSR(CNTPS_CTL_EL1, u);
117 }
118 
soc_timer_init(void)119 void soc_timer_init(void)
120 {
121 	raw_write_cntfrq_el0(tickrate);
122 }
123 
124 /**
125  * Setup the watchdog to expire in timeout_ms milliseconds. When the watchdog
126  * expires, the chip three things happen:
127  * 1) Expire 1: interrupt that is ignored by the BDK
128  * 2) Expire 2: DEL3T interrupt, which is disabled and ignored
129  * 3) Expire 3: Soft reset of the chip
130  *
131  * Since we want a soft reset, we actually program the watchdog to expire at
132  * the timeout / 3.
133  *
134  * @param index      Index of watchdog to configure
135  * @param timeout_ms Timeout in milliseconds.
136  */
watchdog_set(const size_t index,unsigned int timeout_ms)137 void watchdog_set(const size_t index, unsigned int timeout_ms)
138 {
139 	uint64_t sclk = thunderx_get_io_clock();
140 	uint64_t timeout_sclk = sclk * timeout_ms / 1000;
141 	struct cn81xx_timer *timer = (struct cn81xx_timer *)GTI_PF_BAR0;
142 
143 	assert(index < ARRAY_SIZE(timer->cwd_wdog));
144 	if (index >= ARRAY_SIZE(timer->cwd_wdog))
145 		return;
146 
147 	/*
148 	 * Per comment above, we want the watchdog to expire at 3x the rate
149 	 * specified
150 	 */
151 	timeout_sclk /= 3;
152 	/* Watchdog counts in 1024 cycle steps */
153 	uint64_t timeout_wdog = timeout_sclk >> 10;
154 	/* We can only specify the upper 16 bits of a 24 bit value. Round up */
155 	timeout_wdog = (timeout_wdog + 0xff) >> 8;
156 	/* If the timeout overflows the hardware limit, set max */
157 	if (timeout_wdog >= 0x10000)
158 		timeout_wdog = 0xffff;
159 
160 	printk(BIOS_DEBUG, "Watchdog: Set to expire %llu SCLK cycles\n",
161 	       timeout_wdog << 18);
162 	clrsetbits64(&timer->cwd_wdog[index],
163 		     (GTI_CWD_WDOG_LEN_MASK << GTI_CWD_WDOG_LEN_SHIFT) |
164 		     (GTI_CWD_WDOG_MODE_MASK << GTI_CWD_WDOG_MODE_SHIFT),
165 		     (timeout_wdog << GTI_CWD_WDOG_LEN_SHIFT) |
166 		     (3 << GTI_CWD_WDOG_MODE_SHIFT));
167 }
168 
169 /**
170  * Signal the watchdog that we are still running.
171  *
172  * @param index      Index of watchdog to configure.
173  */
watchdog_poke(const size_t index)174 void watchdog_poke(const size_t index)
175 {
176 	struct cn81xx_timer *timer = (struct cn81xx_timer *)GTI_PF_BAR0;
177 
178 	assert(index < ARRAY_SIZE(timer->cwd_poke));
179 	if (index >= ARRAY_SIZE(timer->cwd_poke))
180 		return;
181 
182 	write64(&timer->cwd_poke[0], 0);
183 }
184 
185 /**
186  * Disable the hardware watchdog
187  *
188  * @param index      Index of watchdog to configure.
189  */
watchdog_disable(const size_t index)190 void watchdog_disable(const size_t index)
191 {
192 	struct cn81xx_timer *timer = (struct cn81xx_timer *)GTI_PF_BAR0;
193 
194 	assert(index < ARRAY_SIZE(timer->cwd_wdog));
195 	if (index >= ARRAY_SIZE(timer->cwd_wdog))
196 		return;
197 
198 	write64(&timer->cwd_wdog[index], 0);
199 	printk(BIOS_DEBUG, "Watchdog: Disabled\n");
200 }
201 
202 /**
203  * Return true if the watchdog is configured and running
204  *
205  * @param index      Index of watchdog to configure.
206  *
207  * @return           Non-zero if watchdog is running.
208  */
watchdog_is_running(const size_t index)209 int watchdog_is_running(const size_t index)
210 {
211 	struct cn81xx_timer *timer = (struct cn81xx_timer *)GTI_PF_BAR0;
212 
213 	assert(index < ARRAY_SIZE(timer->cwd_wdog));
214 	if (index >= ARRAY_SIZE(timer->cwd_wdog))
215 		return 0;
216 
217 	uint64_t val = read64(&timer->cwd_wdog[index]);
218 
219 	return !!(val & (GTI_CWD_WDOG_MODE_MASK << GTI_CWD_WDOG_MODE_SHIFT));
220 }
221