1*c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2217dd11eSRalf Baechle /*
3217dd11eSRalf Baechle * Copyright (C) 2000, 2001 Broadcom Corporation
4217dd11eSRalf Baechle */
5217dd11eSRalf Baechle #include <linux/clocksource.h>
6262f1c92SDeng-Cheng Zhu #include <linux/sched_clock.h>
7217dd11eSRalf Baechle
8217dd11eSRalf Baechle #include <asm/addrspace.h>
9217dd11eSRalf Baechle #include <asm/io.h>
10217dd11eSRalf Baechle #include <asm/time.h>
11217dd11eSRalf Baechle
12217dd11eSRalf Baechle #include <asm/sibyte/sb1250.h>
13217dd11eSRalf Baechle #include <asm/sibyte/sb1250_regs.h>
14217dd11eSRalf Baechle #include <asm/sibyte/sb1250_int.h>
15217dd11eSRalf Baechle #include <asm/sibyte/sb1250_scd.h>
16217dd11eSRalf Baechle
17217dd11eSRalf Baechle #define SB1250_HPT_NUM 3
18217dd11eSRalf Baechle #define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */
19217dd11eSRalf Baechle
20217dd11eSRalf Baechle /*
21217dd11eSRalf Baechle * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
22217dd11eSRalf Baechle * again.
23217dd11eSRalf Baechle */
sb1250_hpt_get_cycles(void)24a5a1d1c2SThomas Gleixner static inline u64 sb1250_hpt_get_cycles(void)
25217dd11eSRalf Baechle {
26217dd11eSRalf Baechle unsigned int count;
2702710fc8SDeng-Cheng Zhu void __iomem *addr;
28217dd11eSRalf Baechle
2902710fc8SDeng-Cheng Zhu addr = IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT));
3002710fc8SDeng-Cheng Zhu count = G_SCD_TIMER_CNT(__raw_readq(addr));
31217dd11eSRalf Baechle
32217dd11eSRalf Baechle return SB1250_HPT_VALUE - count;
33217dd11eSRalf Baechle }
34217dd11eSRalf Baechle
sb1250_hpt_read(struct clocksource * cs)35a5a1d1c2SThomas Gleixner static u64 sb1250_hpt_read(struct clocksource *cs)
3602710fc8SDeng-Cheng Zhu {
3702710fc8SDeng-Cheng Zhu return sb1250_hpt_get_cycles();
3802710fc8SDeng-Cheng Zhu }
3902710fc8SDeng-Cheng Zhu
40217dd11eSRalf Baechle struct clocksource bcm1250_clocksource = {
41f99f2cc9SRalf Baechle .name = "bcm1250-counter-3",
42217dd11eSRalf Baechle .rating = 200,
43217dd11eSRalf Baechle .read = sb1250_hpt_read,
44217dd11eSRalf Baechle .mask = CLOCKSOURCE_MASK(23),
45217dd11eSRalf Baechle .flags = CLOCK_SOURCE_IS_CONTINUOUS,
46217dd11eSRalf Baechle };
47217dd11eSRalf Baechle
sb1250_read_sched_clock(void)48262f1c92SDeng-Cheng Zhu static u64 notrace sb1250_read_sched_clock(void)
49262f1c92SDeng-Cheng Zhu {
50262f1c92SDeng-Cheng Zhu return sb1250_hpt_get_cycles();
51262f1c92SDeng-Cheng Zhu }
52262f1c92SDeng-Cheng Zhu
sb1250_clocksource_init(void)53217dd11eSRalf Baechle void __init sb1250_clocksource_init(void)
54217dd11eSRalf Baechle {
55217dd11eSRalf Baechle struct clocksource *cs = &bcm1250_clocksource;
56217dd11eSRalf Baechle
57217dd11eSRalf Baechle /* Setup hpt using timer #3 but do not enable irq for it */
58217dd11eSRalf Baechle __raw_writeq(0,
59217dd11eSRalf Baechle IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
60217dd11eSRalf Baechle R_SCD_TIMER_CFG)));
61217dd11eSRalf Baechle __raw_writeq(SB1250_HPT_VALUE,
62217dd11eSRalf Baechle IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
63217dd11eSRalf Baechle R_SCD_TIMER_INIT)));
64217dd11eSRalf Baechle __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
65217dd11eSRalf Baechle IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
66217dd11eSRalf Baechle R_SCD_TIMER_CFG)));
67217dd11eSRalf Baechle
6875c4fd8cSJohn Stultz clocksource_register_hz(cs, V_SCD_TIMER_FREQ);
69262f1c92SDeng-Cheng Zhu
70262f1c92SDeng-Cheng Zhu sched_clock_register(sb1250_read_sched_clock, 23, V_SCD_TIMER_FREQ);
71217dd11eSRalf Baechle }
72