blob: d9879baec6ab04211bd9b7de2cda416e88c16380 [file] [log] [blame]
Angel Pons5f249e62020-04-04 18:51:01 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Angel Pons5f249e62020-04-04 18:51:01 +02002
David Hendricks8cbd5692017-12-01 20:49:48 -08003/*
David Hendricks8cbd5692017-12-01 20:49:48 -08004 * Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
5 */
6
Elyes HAOUASbf0970e2019-03-21 11:10:03 +01007#include <delay.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02008#include <device/mmio.h>
Julius Werner73be9dd2018-08-07 14:02:55 -07009#include <arch/lib_helpers.h>
David Hendricks8cbd5692017-12-01 20:49:48 -080010#include <console/console.h>
David Hendricks8cbd5692017-12-01 20:49:48 -080011#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 */
19struct 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
49check_member(cn81xx_timer, cc_imp_ctl, 0x100);
50check_member(cn81xx_timer, ctl_cntacr0, 0x20040);
51check_member(cn81xx_timer, cwd_wdog[0], 0x40000);
52check_member(cn81xx_timer, cwd_poke[0], 0x50000);
53
David Hendricks8cbd5692017-12-01 20:49:48 -080054#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
72static 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 */
83void timer_monotonic_get(struct mono_time *mt)
84{
85 mono_time_set_usecs(mt, timer_raw_value());
86}
87
Patrick Rudolphae15fec2018-03-29 11:41:01 +020088/* Setup counter to operate at 1MHz */
89static const size_t tickrate = 1000000;
90
David Hendricks8cbd5692017-12-01 20:49:48 -080091/**
92 * Init Global System Timers Unit (GTI).
93 * Configure timer to run at 1MHz tick-rate.
94 */
95void 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
David Hendricks8cbd5692017-12-01 20:49:48 -0800108 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 */
Julius Werner55009af2019-12-02 22:03:27 -0800113 setbits32(&gti->cc_cntcr, GTI_CC_CNTCR_EN);
David Hendricks8cbd5692017-12-01 20:49:48 -0800114
115 //u32 u = (CNTPS_CTL_EL1_IMASK | CNTPS_CTL_EL1_EN);
116 //BDK_MSR(CNTPS_CTL_EL1, u);
117}
118
Patrick Rudolphae15fec2018-03-29 11:41:01 +0200119void soc_timer_init(void)
120{
Julius Werner73be9dd2018-08-07 14:02:55 -0700121 raw_write_cntfrq_el0(tickrate);
Patrick Rudolphae15fec2018-03-29 11:41:01 +0200122}
123
David Hendricks8cbd5692017-12-01 20:49:48 -0800124/**
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 */
137void 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);
Julius Werner55009af2019-12-02 22:03:27 -0800162 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));
David Hendricks8cbd5692017-12-01 20:49:48 -0800167}
168
169/**
170 * Signal the watchdog that we are still running.
171 *
172 * @param index Index of watchdog to configure.
173 */
174void 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 */
190void 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 */
209int 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}