ath25: switch default kernel to 5.15
[openwrt/staging/wigyori.git] / target / linux / realtek / files-5.10 / arch / mips / kernel / cevt-rtl9300.c
1 // SPDX-License-Identifier: GPL-2.0-only
2
3 #include <linux/clockchips.h>
4 #include <linux/init.h>
5 #include <asm/time.h>
6 #include <asm/idle.h>
7 #include <linux/interrupt.h>
8 #include <linux/of_address.h>
9 #include <linux/of_irq.h>
10 #include <linux/sched_clock.h>
11
12 #include <mach-rtl83xx.h>
13
14 /*
15 * Timer registers
16 * the RTL9300/9310 SoCs have 6 timers, each register block 0x10 apart
17 */
18 #define RTL9300_TC_DATA 0x0
19 #define RTL9300_TC_CNT 0x4
20 #define RTL9300_TC_CTRL 0x8
21 #define RTL9300_TC_CTRL_MODE BIT(24)
22 #define RTL9300_TC_CTRL_EN BIT(28)
23 #define RTL9300_TC_INT 0xc
24 #define RTL9300_TC_INT_IP BIT(16)
25 #define RTL9300_TC_INT_IE BIT(20)
26
27 // Timer modes
28 #define TIMER_MODE_REPEAT 1
29 #define TIMER_MODE_ONCE 0
30
31 // Minimum divider is 2
32 #define DIVISOR_RTL9300 2
33
34 #define N_BITS 28
35
36 #define RTL9300_CLOCK_RATE 87500000
37
38 struct rtl9300_clk_dev {
39 struct clock_event_device clkdev;
40 void __iomem *base;
41 };
42
43 static void __iomem *rtl9300_tc_base(struct clock_event_device *clk)
44 {
45 struct rtl9300_clk_dev *rtl_clk = container_of(clk, struct rtl9300_clk_dev, clkdev);
46
47 return rtl_clk->base;
48 }
49
50 static irqreturn_t rtl9300_timer_interrupt(int irq, void *dev_id)
51 {
52 struct rtl9300_clk_dev *rtl_clk = dev_id;
53 struct clock_event_device *clk = &rtl_clk->clkdev;
54
55 u32 v = readl(rtl_clk->base + RTL9300_TC_INT);
56
57 // Acknowledge the IRQ
58 v |= RTL9300_TC_INT_IP;
59 writel(v, rtl_clk->base + RTL9300_TC_INT);
60
61 clk->event_handler(clk);
62 return IRQ_HANDLED;
63 }
64
65 static void rtl9300_clock_stop(void __iomem *base)
66 {
67 u32 v;
68
69 writel(0, base + RTL9300_TC_CTRL);
70
71 // Acknowledge possibly pending IRQ
72 v = readl(base + RTL9300_TC_INT);
73 writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
74 }
75
76 static void rtl9300_timer_start(void __iomem *base, bool periodic)
77 {
78 u32 v = (periodic ? RTL9300_TC_CTRL_MODE : 0) | RTL9300_TC_CTRL_EN | DIVISOR_RTL9300;
79
80 writel(0, base + RTL9300_TC_CNT);
81 pr_debug("------------- starting timer base %08x\n", (u32)base);
82 writel(v, base + RTL9300_TC_CTRL);
83 }
84
85 static int rtl9300_next_event(unsigned long delta, struct clock_event_device *clk)
86 {
87 void __iomem *base = rtl9300_tc_base(clk);
88
89 rtl9300_clock_stop(base);
90 writel(delta, base + RTL9300_TC_DATA);
91 rtl9300_timer_start(base, TIMER_MODE_ONCE);
92
93 return 0;
94 }
95
96 static int rtl9300_state_periodic(struct clock_event_device *clk)
97 {
98 void __iomem *base = rtl9300_tc_base(clk);
99
100 pr_debug("------------- rtl9300_state_periodic %08x\n", (u32)base);
101 rtl9300_clock_stop(base);
102 writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
103 rtl9300_timer_start(base, TIMER_MODE_REPEAT);
104 return 0;
105 }
106
107 static int rtl9300_state_oneshot(struct clock_event_device *clk)
108 {
109 void __iomem *base = rtl9300_tc_base(clk);
110
111 pr_debug("------------- rtl9300_state_oneshot %08x\n", (u32)base);
112 rtl9300_clock_stop(base);
113 writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
114 rtl9300_timer_start(base, TIMER_MODE_ONCE);
115 return 0;
116 }
117
118 static int rtl9300_shutdown(struct clock_event_device *clk)
119 {
120 void __iomem *base = rtl9300_tc_base(clk);
121
122 pr_debug("------------- rtl9300_shutdown %08x\n", (u32)base);
123 rtl9300_clock_stop(base);
124 return 0;
125 }
126
127 static void rtl9300_clock_setup(void __iomem *base)
128 {
129 u32 v;
130
131 // Disable timer
132 writel(0, base + RTL9300_TC_CTRL);
133
134 // Acknowledge possibly pending IRQ
135 v = readl(base + RTL9300_TC_INT);
136 writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
137
138 // Setup maximum period (for use as clock-source)
139 writel(0x0fffffff, base + RTL9300_TC_DATA);
140 }
141
142 static DEFINE_PER_CPU(struct rtl9300_clk_dev, rtl9300_clockevent);
143 static DEFINE_PER_CPU(char [18], rtl9300_clock_name);
144
145 void rtl9300_clockevent_init(void)
146 {
147 int cpu = smp_processor_id();
148 int irq;
149 struct rtl9300_clk_dev *rtl_clk = &per_cpu(rtl9300_clockevent, cpu);
150 struct clock_event_device *cd = &rtl_clk->clkdev;
151 unsigned char *name = per_cpu(rtl9300_clock_name, cpu);
152 unsigned long flags = IRQF_PERCPU | IRQF_TIMER;
153 struct device_node *node;
154
155 pr_info("%s called for cpu%d\n", __func__, cpu);
156 BUG_ON(cpu > 3); /* Only have 4 general purpose timers */
157
158 node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300clock");
159 if (!node) {
160 pr_err("No DT entry found for realtek,rtl9300clock\n");
161 return;
162 }
163
164 irq = irq_of_parse_and_map(node, cpu);
165 pr_info("%s using IRQ %d\n", __func__, irq);
166
167 rtl_clk->base = of_iomap(node, cpu);
168 if (!rtl_clk->base) {
169 pr_err("cannot map timer for cpu %d", cpu);
170 return;
171 }
172
173 rtl9300_clock_setup(rtl_clk->base);
174
175 sprintf(name, "rtl9300-counter-%d", cpu);
176 cd->name = name;
177 cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
178
179 clockevent_set_clock(cd, RTL9300_CLOCK_RATE);
180
181 cd->max_delta_ns = clockevent_delta2ns(0x0fffffff, cd);
182 cd->max_delta_ticks = 0x0fffffff;
183 cd->min_delta_ns = clockevent_delta2ns(0x20, cd);
184 cd->min_delta_ticks = 0x20;
185 cd->rating = 300;
186 cd->irq = irq;
187 cd->cpumask = cpumask_of(cpu);
188 cd->set_next_event = rtl9300_next_event;
189 cd->set_state_shutdown = rtl9300_shutdown;
190 cd->set_state_periodic = rtl9300_state_periodic;
191 cd->set_state_oneshot = rtl9300_state_oneshot;
192 clockevents_register_device(cd);
193
194 irq_set_affinity(irq, cd->cpumask);
195
196 if (request_irq(irq, rtl9300_timer_interrupt, flags, name, rtl_clk))
197 pr_err("Failed to request irq %d (%s)\n", irq, name);
198
199 writel(RTL9300_TC_INT_IE, rtl_clk->base + RTL9300_TC_INT);
200 }