realtek: Whitespace and codestyle cleanup
[openwrt/staging/jow.git] / target / linux / realtek / files-5.15 / 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
63 return IRQ_HANDLED;
64 }
65
66 static void rtl9300_clock_stop(void __iomem *base)
67 {
68 u32 v;
69
70 writel(0, base + RTL9300_TC_CTRL);
71
72 // Acknowledge possibly pending IRQ
73 v = readl(base + RTL9300_TC_INT);
74 writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
75 }
76
77 static void rtl9300_timer_start(void __iomem *base, bool periodic)
78 {
79 u32 v = (periodic ? RTL9300_TC_CTRL_MODE : 0) | RTL9300_TC_CTRL_EN | DIVISOR_RTL9300;
80
81 writel(0, base + RTL9300_TC_CNT);
82 pr_debug("------------- starting timer base %08x\n", (u32)base);
83 writel(v, base + RTL9300_TC_CTRL);
84 }
85
86 static int rtl9300_next_event(unsigned long delta, struct clock_event_device *clk)
87 {
88 void __iomem *base = rtl9300_tc_base(clk);
89
90 rtl9300_clock_stop(base);
91 writel(delta, base + RTL9300_TC_DATA);
92 rtl9300_timer_start(base, TIMER_MODE_ONCE);
93
94 return 0;
95 }
96
97 static int rtl9300_state_periodic(struct clock_event_device *clk)
98 {
99 void __iomem *base = rtl9300_tc_base(clk);
100
101 pr_debug("------------- rtl9300_state_periodic %08x\n", (u32)base);
102 rtl9300_clock_stop(base);
103 writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
104 rtl9300_timer_start(base, TIMER_MODE_REPEAT);
105
106 return 0;
107 }
108
109 static int rtl9300_state_oneshot(struct clock_event_device *clk)
110 {
111 void __iomem *base = rtl9300_tc_base(clk);
112
113 pr_debug("------------- rtl9300_state_oneshot %08x\n", (u32)base);
114 rtl9300_clock_stop(base);
115 writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
116 rtl9300_timer_start(base, TIMER_MODE_ONCE);
117
118 return 0;
119 }
120
121 static int rtl9300_shutdown(struct clock_event_device *clk)
122 {
123 void __iomem *base = rtl9300_tc_base(clk);
124
125 pr_debug("------------- rtl9300_shutdown %08x\n", (u32)base);
126 rtl9300_clock_stop(base);
127
128 return 0;
129 }
130
131 static void rtl9300_clock_setup(void __iomem *base)
132 {
133 u32 v;
134
135 // Disable timer
136 writel(0, base + RTL9300_TC_CTRL);
137
138 // Acknowledge possibly pending IRQ
139 v = readl(base + RTL9300_TC_INT);
140 writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
141
142 // Setup maximum period (for use as clock-source)
143 writel(0x0fffffff, base + RTL9300_TC_DATA);
144 }
145
146 static DEFINE_PER_CPU(struct rtl9300_clk_dev, rtl9300_clockevent);
147 static DEFINE_PER_CPU(char [18], rtl9300_clock_name);
148
149 void rtl9300_clockevent_init(void)
150 {
151 int cpu = smp_processor_id();
152 int irq;
153 struct rtl9300_clk_dev *rtl_clk = &per_cpu(rtl9300_clockevent, cpu);
154 struct clock_event_device *cd = &rtl_clk->clkdev;
155 unsigned char *name = per_cpu(rtl9300_clock_name, cpu);
156 unsigned long flags = IRQF_PERCPU | IRQF_TIMER;
157 struct device_node *node;
158
159 pr_info("%s called for cpu%d\n", __func__, cpu);
160 BUG_ON(cpu > 3); /* Only have 4 general purpose timers */
161
162 node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300clock");
163 if (!node) {
164 pr_err("No DT entry found for realtek,rtl9300clock\n");
165 return;
166 }
167
168 irq = irq_of_parse_and_map(node, cpu);
169 pr_info("%s using IRQ %d\n", __func__, irq);
170
171 rtl_clk->base = of_iomap(node, cpu);
172 if (!rtl_clk->base) {
173 pr_err("cannot map timer for cpu %d", cpu);
174 return;
175 }
176
177 rtl9300_clock_setup(rtl_clk->base);
178
179 sprintf(name, "rtl9300-counter-%d", cpu);
180 cd->name = name;
181 cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
182
183 clockevent_set_clock(cd, RTL9300_CLOCK_RATE);
184
185 cd->max_delta_ns = clockevent_delta2ns(0x0fffffff, cd);
186 cd->max_delta_ticks = 0x0fffffff;
187 cd->min_delta_ns = clockevent_delta2ns(0x20, cd);
188 cd->min_delta_ticks = 0x20;
189 cd->rating = 300;
190 cd->irq = irq;
191 cd->cpumask = cpumask_of(cpu);
192 cd->set_next_event = rtl9300_next_event;
193 cd->set_state_shutdown = rtl9300_shutdown;
194 cd->set_state_periodic = rtl9300_state_periodic;
195 cd->set_state_oneshot = rtl9300_state_oneshot;
196 clockevents_register_device(cd);
197
198 irq_set_affinity(irq, cd->cpumask);
199
200 if (request_irq(irq, rtl9300_timer_interrupt, flags, name, rtl_clk))
201 pr_err("Failed to request irq %d (%s)\n", irq, name);
202
203 writel(RTL9300_TC_INT_IE, rtl_clk->base + RTL9300_TC_INT);
204 }