Merge tag 'net-6.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux-block.git] / arch / mips / mti-malta / malta-time.c
CommitLineData
41173abc 1// SPDX-License-Identifier: GPL-2.0-only
1da177e4
LT
2/*
3 * Carsten Langgaard, carstenl@mips.com
4 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
5 *
1da177e4
LT
6 * Setting up the clock on the MIPS boards.
7 */
1da177e4 8#include <linux/types.h>
334955ef 9#include <linux/i8253.h>
1da177e4
LT
10#include <linux/init.h>
11#include <linux/kernel_stat.h>
4287adec 12#include <linux/libfdt.h>
24e1df66 13#include <linux/math64.h>
1da177e4
LT
14#include <linux/sched.h>
15#include <linux/spinlock.h>
16#include <linux/interrupt.h>
1da177e4
LT
17#include <linux/timex.h>
18#include <linux/mc146818rtc.h>
19
8ff374b9 20#include <asm/cpu.h>
1da177e4 21#include <asm/mipsregs.h>
41c594ab 22#include <asm/mipsmtregs.h>
e01402b1
RB
23#include <asm/hardirq.h>
24#include <asm/irq.h>
1da177e4 25#include <asm/div64.h>
b81947c6 26#include <asm/setup.h>
1da177e4
LT
27#include <asm/time.h>
28#include <asm/mc146818-time.h>
e01402b1 29#include <asm/msc01_ic.h>
72eb2995 30#include <asm/mips-cps.h>
1da177e4
LT
31
32#include <asm/mips-boards/generic.h>
e01402b1 33#include <asm/mips-boards/maltaint.h>
1da177e4 34
e01402b1 35static int mips_cpu_timer_irq;
39b8d525 36static int mips_cpu_perf_irq;
3b1d4ed5 37extern int cp0_perfcount_irq;
1da177e4 38
b0854514
AB
39static unsigned int gic_frequency;
40
937a8015 41static void mips_timer_dispatch(void)
1da177e4 42{
937a8015 43 do_IRQ(mips_cpu_timer_irq);
e01402b1
RB
44}
45
ffe9ee47
CD
46static void mips_perf_dispatch(void)
47{
39b8d525 48 do_IRQ(mips_cpu_perf_irq);
ffe9ee47
CD
49}
50
778eeb1b
SH
51static unsigned int freqround(unsigned int freq, unsigned int amount)
52{
53 freq += amount;
54 freq -= freq % (amount*2);
55 return freq;
56}
57
1da177e4 58/*
778eeb1b 59 * Estimate CPU and GIC frequencies.
1da177e4 60 */
778eeb1b 61static void __init estimate_frequencies(void)
1da177e4 62{
e79f55a8 63 unsigned long flags;
778eeb1b 64 unsigned int count, start;
24e1df66
JH
65 unsigned char secs1, secs2, ctrl;
66 int secs;
a5a1d1c2 67 u64 giccount = 0, gicstart = 0;
1da177e4
LT
68
69 local_irq_save(flags);
70
72eb2995 71 if (mips_gic_present())
60702867 72 clear_gic_config(GIC_CONFIG_COUNTSTOP);
aab4673b 73
24e1df66
JH
74 /*
75 * Read counters exactly on rising edge of update flag.
76 * This helps get an accurate reading under virtualisation.
77 */
1da177e4
LT
78 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
79 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
70e46f48 80 start = read_c0_count();
72eb2995 81 if (mips_gic_present())
60702867 82 gicstart = read_gic_counter();
1da177e4 83
24e1df66 84 /* Wait for falling edge before reading RTC. */
1da177e4 85 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
24e1df66 86 secs1 = CMOS_READ(RTC_SECONDS);
1da177e4 87
24e1df66
JH
88 /* Read counters again exactly on rising edge of update flag. */
89 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
778eeb1b 90 count = read_c0_count();
72eb2995 91 if (mips_gic_present())
60702867 92 giccount = read_gic_counter();
1da177e4 93
24e1df66
JH
94 /* Wait for falling edge before reading RTC again. */
95 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
96 secs2 = CMOS_READ(RTC_SECONDS);
97
98 ctrl = CMOS_READ(RTC_CONTROL);
99
1da177e4 100 local_irq_restore(flags);
1da177e4 101
24e1df66
JH
102 if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
103 secs1 = bcd2bin(secs1);
104 secs2 = bcd2bin(secs2);
105 }
106 secs = secs2 - secs1;
107 if (secs < 1)
108 secs += 60;
109
778eeb1b 110 count -= start;
24e1df66 111 count /= secs;
778eeb1b 112 mips_hpt_frequency = count;
dfa762e1 113
72eb2995 114 if (mips_gic_present()) {
24e1df66 115 giccount = div_u64(giccount - gicstart, secs);
778eeb1b 116 gic_frequency = giccount;
dfa762e1 117 }
1da177e4
LT
118}
119
09adad17 120void read_persistent_clock64(struct timespec64 *ts)
1da177e4 121{
d4f587c6
MS
122 ts->tv_sec = mc146818_get_cmos_time();
123 ts->tv_nsec = 0;
1da177e4
LT
124}
125
602e8a34
JH
126int get_c0_fdc_int(void)
127{
6249ecbb
JH
128 /*
129 * Some cores claim the FDC is routable through the GIC, but it doesn't
130 * actually seem to be connected for those Malta bitstreams.
131 */
132 switch (current_cpu_type()) {
133 case CPU_INTERAPTIV:
134 case CPU_PROAPTIV:
135 return -1;
3235c5f0 136 }
602e8a34
JH
137
138 if (cpu_has_veic)
6249ecbb 139 return -1;
72eb2995 140 else if (mips_gic_present())
6249ecbb 141 return gic_get_c0_fdc_int();
602e8a34 142 else if (cp0_fdc_irq >= 0)
6249ecbb 143 return MIPS_CPU_IRQ_BASE + cp0_fdc_irq;
602e8a34 144 else
6249ecbb 145 return -1;
602e8a34
JH
146}
147
a669efc4 148int get_c0_perfcount_int(void)
ffe9ee47 149{
e01402b1 150 if (cpu_has_veic) {
49a89efb 151 set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch);
39b8d525 152 mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
72eb2995 153 } else if (mips_gic_present()) {
e9de688d 154 mips_cpu_perf_irq = gic_get_c0_perfcount_int();
a669efc4 155 } else if (cp0_perfcount_irq >= 0) {
39b8d525 156 mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
a669efc4
AB
157 } else {
158 mips_cpu_perf_irq = -1;
e01402b1 159 }
a669efc4
AB
160
161 return mips_cpu_perf_irq;
ffe9ee47 162}
0cb0985f 163EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
e01402b1 164
078a55fc 165unsigned int get_c0_compare_int(void)
ffe9ee47 166{
ffe9ee47 167 if (cpu_has_veic) {
49a89efb 168 set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
ffe9ee47 169 mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
72eb2995 170 } else if (mips_gic_present()) {
e9de688d
AB
171 mips_cpu_timer_irq = gic_get_c0_compare_int();
172 } else {
3b1d4ed5 173 mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
ffe9ee47 174 }
e01402b1 175
38760d40
RB
176 return mips_cpu_timer_irq;
177}
178
a87ea88d
PB
179static void __init init_rtc(void)
180{
106eccb4 181 unsigned char freq, ctrl;
a87ea88d 182
106eccb4
JH
183 /* Set 32KHz time base if not already set */
184 freq = CMOS_READ(RTC_FREQ_SELECT);
185 if ((freq & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ)
186 CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT);
a87ea88d 187
106eccb4
JH
188 /* Ensure SET bit is clear so RTC can run */
189 ctrl = CMOS_READ(RTC_CONTROL);
190 if (ctrl & RTC_SET)
191 CMOS_WRITE(ctrl & ~RTC_SET, RTC_CONTROL);
a87ea88d
PB
192}
193
4287adec
MR
194#ifdef CONFIG_CLKSRC_MIPS_GIC
195static u32 gic_frequency_dt;
196
197static struct property gic_frequency_prop = {
198 .name = "clock-frequency",
199 .length = sizeof(u32),
200 .value = &gic_frequency_dt,
201};
202
203static void update_gic_frequency_dt(void)
204{
205 struct device_node *node;
206
207 gic_frequency_dt = cpu_to_be32(gic_frequency);
208
209 node = of_find_compatible_node(NULL, NULL, "mti,gic-timer");
210 if (!node) {
211 pr_err("mti,gic-timer device node not found\n");
212 return;
213 }
214
215 if (of_update_property(node, &gic_frequency_prop) < 0)
216 pr_err("error updating gic frequency property\n");
608d94cb
LH
217
218 of_node_put(node);
4287adec
MR
219}
220
221#endif
222
38760d40
RB
223void __init plat_time_init(void)
224{
8ff374b9 225 unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
778eeb1b 226 unsigned int freq;
38760d40 227
a87ea88d 228 init_rtc();
778eeb1b 229 estimate_frequencies();
38760d40 230
778eeb1b
SH
231 freq = mips_hpt_frequency;
232 if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
233 (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
234 freq *= 2;
235 freq = freqround(freq, 5000);
dfa762e1 236 printk("CPU frequency %d.%02d MHz\n", freq/1000000,
778eeb1b 237 (freq%1000000)*100/1000000);
778eeb1b 238
778eeb1b
SH
239#ifdef CONFIG_I8253
240 /* Only Malta has a PIT. */
38760d40 241 setup_pit_timer();
340ee4b9 242#endif
ffe9ee47 243
72eb2995 244 if (mips_gic_present()) {
dfa762e1
SH
245 freq = freqround(gic_frequency, 5000);
246 printk("GIC frequency %d.%02d MHz\n", freq/1000000,
247 (freq%1000000)*100/1000000);
fa5635a2 248#ifdef CONFIG_CLKSRC_MIPS_GIC
4287adec 249 update_gic_frequency_dt();
ba5d08c0 250 timer_probe();
dfa762e1
SH
251#endif
252 }
1da177e4 253}