1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
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>
15 #include <soc/addressmap.h>
18 /* Global System Timers Unit (GTI) registers */
34 u64 cc_cntmb_int_ena_clr
;
35 u64 cc_cntmb_int_ena_set
;
44 u64 cwd_wdog
[48]; /* Offset 0x40000 */
46 u64 cwd_poke
[48]; /* Offset 0x50000 */
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);
54 #define GTI_CC_CNTCR_EN (1 << 0)
55 #define GTI_CC_CNTCR_HDBG (1 << 1)
56 #define GTI_CC_CNTCR_FCREQ (1 << 8)
58 #define GTI_CC_CNTSR_DBGH (1 << 1)
59 #define GTI_CC_CNTSR_FCACK (1 << 8)
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)
72 static uint64_t timer_raw_value(void)
74 struct cn81xx_timer
*timer
= (void *)GTI_PF_BAR0
;
76 return read64(&timer
->cc_cntcv
);
80 * Get GTI counter value.
81 * @param mt Structure to fill
83 void timer_monotonic_get(struct mono_time
*mt
)
85 mono_time_set_usecs(mt
, timer_raw_value());
88 /* Setup counter to operate at 1MHz */
89 static const size_t tickrate
= 1000000;
92 * Init Global System Timers Unit (GTI).
93 * Configure timer to run at 1MHz tick-rate.
97 struct cn81xx_timer
*gti
= (struct cn81xx_timer
*)GTI_PF_BAR0
;
99 /* Check if the counter was already setup */
100 if (gti
->cc_cntcr
& GTI_CC_CNTCR_EN
)
103 u64 sclk
= thunderx_get_io_clock();
105 /* Use coprocessor clock source */
106 write32(>i
->cc_imp_ctl
, 0);
108 write32(>i
->cc_cntfid0
, tickrate
);
109 write32(>i
->ctl_cntfrq
, tickrate
);
110 write32(>i
->cc_cntrate
, ((1ULL << 32) * tickrate
) / sclk
);
112 /* Enable the counter */
113 setbits32(>i
->cc_cntcr
, GTI_CC_CNTCR_EN
);
115 //u32 u = (CNTPS_CTL_EL1_IMASK | CNTPS_CTL_EL1_EN);
116 //BDK_MSR(CNTPS_CTL_EL1, u);
119 void soc_timer_init(void)
121 raw_write_cntfrq_el0(tickrate
);
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
131 * Since we want a soft reset, we actually program the watchdog to expire at
134 * @param index Index of watchdog to configure
135 * @param timeout_ms Timeout in milliseconds.
137 void watchdog_set(const size_t index
, unsigned int timeout_ms
)
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
;
143 assert(index
< ARRAY_SIZE(timer
->cwd_wdog
));
144 if (index
>= ARRAY_SIZE(timer
->cwd_wdog
))
148 * Per comment above, we want the watchdog to expire at 3x the rate
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;
160 printk(BIOS_DEBUG
, "Watchdog: Set to expire %llu SCLK cycles\n",
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
));
170 * Signal the watchdog that we are still running.
172 * @param index Index of watchdog to configure.
174 void watchdog_poke(const size_t index
)
176 struct cn81xx_timer
*timer
= (struct cn81xx_timer
*)GTI_PF_BAR0
;
178 assert(index
< ARRAY_SIZE(timer
->cwd_poke
));
179 if (index
>= ARRAY_SIZE(timer
->cwd_poke
))
182 write64(&timer
->cwd_poke
[0], 0);
186 * Disable the hardware watchdog
188 * @param index Index of watchdog to configure.
190 void watchdog_disable(const size_t index
)
192 struct cn81xx_timer
*timer
= (struct cn81xx_timer
*)GTI_PF_BAR0
;
194 assert(index
< ARRAY_SIZE(timer
->cwd_wdog
));
195 if (index
>= ARRAY_SIZE(timer
->cwd_wdog
))
198 write64(&timer
->cwd_wdog
[index
], 0);
199 printk(BIOS_DEBUG
, "Watchdog: Disabled\n");
203 * Return true if the watchdog is configured and running
205 * @param index Index of watchdog to configure.
207 * @return Non-zero if watchdog is running.
209 int watchdog_is_running(const size_t index
)
211 struct cn81xx_timer
*timer
= (struct cn81xx_timer
*)GTI_PF_BAR0
;
213 assert(index
< ARRAY_SIZE(timer
->cwd_wdog
));
214 if (index
>= ARRAY_SIZE(timer
->cwd_wdog
))
217 uint64_t val
= read64(&timer
->cwd_wdog
[index
]);
219 return !!(val
& (GTI_CWD_WDOG_MODE_MASK
<< GTI_CWD_WDOG_MODE_SHIFT
));