1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ARM Specific GTDT table Support |
4 | * |
5 | * Copyright (C) 2016, Linaro Ltd. |
6 | * Author: Daniel Lezcano <daniel.lezcano@linaro.org> |
7 | * Fu Wei <fu.wei@linaro.org> |
8 | * Hanjun Guo <hanjun.guo@linaro.org> |
9 | */ |
10 | |
11 | #include <linux/acpi.h> |
12 | #include <linux/init.h> |
13 | #include <linux/irqdomain.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/platform_device.h> |
16 | |
17 | #include <clocksource/arm_arch_timer.h> |
18 | |
19 | #undef pr_fmt |
20 | #define pr_fmt(fmt) "ACPI GTDT: " fmt |
21 | |
22 | /** |
23 | * struct acpi_gtdt_descriptor - Store the key info of GTDT for all functions |
24 | * @gtdt: The pointer to the struct acpi_table_gtdt of GTDT table. |
25 | * @gtdt_end: The pointer to the end of GTDT table. |
26 | * @platform_timer: The pointer to the start of Platform Timer Structure |
27 | * |
28 | * The struct store the key info of GTDT table, it should be initialized by |
29 | * acpi_gtdt_init. |
30 | */ |
31 | struct acpi_gtdt_descriptor { |
32 | struct acpi_table_gtdt *gtdt; |
33 | void *gtdt_end; |
34 | void *platform_timer; |
35 | }; |
36 | |
37 | static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata; |
38 | |
39 | static inline __init void *next_platform_timer(void *platform_timer) |
40 | { |
41 | struct acpi_gtdt_header *gh = platform_timer; |
42 | |
43 | platform_timer += gh->length; |
44 | if (platform_timer < acpi_gtdt_desc.gtdt_end) |
45 | return platform_timer; |
46 | |
47 | return NULL; |
48 | } |
49 | |
50 | #define for_each_platform_timer(_g) \ |
51 | for (_g = acpi_gtdt_desc.platform_timer; _g; \ |
52 | _g = next_platform_timer(_g)) |
53 | |
54 | static inline bool is_timer_block(void *platform_timer) |
55 | { |
56 | struct acpi_gtdt_header *gh = platform_timer; |
57 | |
58 | return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK; |
59 | } |
60 | |
61 | static inline bool is_non_secure_watchdog(void *platform_timer) |
62 | { |
63 | struct acpi_gtdt_header *gh = platform_timer; |
64 | struct acpi_gtdt_watchdog *wd = platform_timer; |
65 | |
66 | if (gh->type != ACPI_GTDT_TYPE_WATCHDOG) |
67 | return false; |
68 | |
69 | return !(wd->timer_flags & ACPI_GTDT_WATCHDOG_SECURE); |
70 | } |
71 | |
72 | static int __init map_gt_gsi(u32 interrupt, u32 flags) |
73 | { |
74 | int trigger, polarity; |
75 | |
76 | trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE |
77 | : ACPI_LEVEL_SENSITIVE; |
78 | |
79 | polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW |
80 | : ACPI_ACTIVE_HIGH; |
81 | |
82 | return acpi_register_gsi(NULL, gsi: interrupt, triggering: trigger, polarity); |
83 | } |
84 | |
85 | /** |
86 | * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer. |
87 | * @type: the type of PPI. |
88 | * |
89 | * Note: Secure state is not managed by the kernel on ARM64 systems. |
90 | * So we only handle the non-secure timer PPIs, |
91 | * ARCH_TIMER_PHYS_SECURE_PPI is treated as invalid type. |
92 | * |
93 | * Return: the mapped PPI value, 0 if error. |
94 | */ |
95 | int __init acpi_gtdt_map_ppi(int type) |
96 | { |
97 | struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt; |
98 | |
99 | switch (type) { |
100 | case ARCH_TIMER_PHYS_NONSECURE_PPI: |
101 | return map_gt_gsi(interrupt: gtdt->non_secure_el1_interrupt, |
102 | flags: gtdt->non_secure_el1_flags); |
103 | case ARCH_TIMER_VIRT_PPI: |
104 | return map_gt_gsi(interrupt: gtdt->virtual_timer_interrupt, |
105 | flags: gtdt->virtual_timer_flags); |
106 | |
107 | case ARCH_TIMER_HYP_PPI: |
108 | return map_gt_gsi(interrupt: gtdt->non_secure_el2_interrupt, |
109 | flags: gtdt->non_secure_el2_flags); |
110 | default: |
111 | pr_err("Failed to map timer interrupt: invalid type.\n" ); |
112 | } |
113 | |
114 | return 0; |
115 | } |
116 | |
117 | /** |
118 | * acpi_gtdt_c3stop() - Got c3stop info from GTDT according to the type of PPI. |
119 | * @type: the type of PPI. |
120 | * |
121 | * Return: true if the timer HW state is lost when a CPU enters an idle state, |
122 | * false otherwise |
123 | */ |
124 | bool __init acpi_gtdt_c3stop(int type) |
125 | { |
126 | struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt; |
127 | |
128 | switch (type) { |
129 | case ARCH_TIMER_PHYS_NONSECURE_PPI: |
130 | return !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); |
131 | |
132 | case ARCH_TIMER_VIRT_PPI: |
133 | return !(gtdt->virtual_timer_flags & ACPI_GTDT_ALWAYS_ON); |
134 | |
135 | case ARCH_TIMER_HYP_PPI: |
136 | return !(gtdt->non_secure_el2_flags & ACPI_GTDT_ALWAYS_ON); |
137 | |
138 | default: |
139 | pr_err("Failed to get c3stop info: invalid type.\n" ); |
140 | } |
141 | |
142 | return false; |
143 | } |
144 | |
145 | /** |
146 | * acpi_gtdt_init() - Get the info of GTDT table to prepare for further init. |
147 | * @table: The pointer to GTDT table. |
148 | * @platform_timer_count: It points to a integer variable which is used |
149 | * for storing the number of platform timers. |
150 | * This pointer could be NULL, if the caller |
151 | * doesn't need this info. |
152 | * |
153 | * Return: 0 if success, -EINVAL if error. |
154 | */ |
155 | int __init acpi_gtdt_init(struct acpi_table_header *table, |
156 | int *platform_timer_count) |
157 | { |
158 | void *platform_timer; |
159 | struct acpi_table_gtdt *gtdt; |
160 | |
161 | gtdt = container_of(table, struct acpi_table_gtdt, header); |
162 | acpi_gtdt_desc.gtdt = gtdt; |
163 | acpi_gtdt_desc.gtdt_end = (void *)table + table->length; |
164 | acpi_gtdt_desc.platform_timer = NULL; |
165 | if (platform_timer_count) |
166 | *platform_timer_count = 0; |
167 | |
168 | if (table->revision < 2) { |
169 | pr_warn("Revision:%d doesn't support Platform Timers.\n" , |
170 | table->revision); |
171 | return 0; |
172 | } |
173 | |
174 | if (!gtdt->platform_timer_count) { |
175 | pr_debug("No Platform Timer.\n" ); |
176 | return 0; |
177 | } |
178 | |
179 | platform_timer = (void *)gtdt + gtdt->platform_timer_offset; |
180 | if (platform_timer < (void *)table + sizeof(struct acpi_table_gtdt)) { |
181 | pr_err(FW_BUG "invalid timer data.\n" ); |
182 | return -EINVAL; |
183 | } |
184 | acpi_gtdt_desc.platform_timer = platform_timer; |
185 | if (platform_timer_count) |
186 | *platform_timer_count = gtdt->platform_timer_count; |
187 | |
188 | return 0; |
189 | } |
190 | |
191 | static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block, |
192 | struct arch_timer_mem *timer_mem) |
193 | { |
194 | int i; |
195 | struct arch_timer_mem_frame *frame; |
196 | struct acpi_gtdt_timer_entry *gtdt_frame; |
197 | |
198 | if (!block->timer_count) { |
199 | pr_err(FW_BUG "GT block present, but frame count is zero.\n" ); |
200 | return -ENODEV; |
201 | } |
202 | |
203 | if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) { |
204 | pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 8\n" , |
205 | block->timer_count); |
206 | return -EINVAL; |
207 | } |
208 | |
209 | timer_mem->cntctlbase = (phys_addr_t)block->block_address; |
210 | /* |
211 | * The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC). |
212 | * See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3 |
213 | * "CNTCTLBase memory map". |
214 | */ |
215 | timer_mem->size = SZ_4K; |
216 | |
217 | gtdt_frame = (void *)block + block->timer_offset; |
218 | if (gtdt_frame + block->timer_count != (void *)block + block->header.length) |
219 | return -EINVAL; |
220 | |
221 | /* |
222 | * Get the GT timer Frame data for every GT Block Timer |
223 | */ |
224 | for (i = 0; i < block->timer_count; i++, gtdt_frame++) { |
225 | if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER) |
226 | continue; |
227 | if (gtdt_frame->frame_number >= ARCH_TIMER_MEM_MAX_FRAMES || |
228 | !gtdt_frame->base_address || !gtdt_frame->timer_interrupt) |
229 | goto error; |
230 | |
231 | frame = &timer_mem->frame[gtdt_frame->frame_number]; |
232 | |
233 | /* duplicate frame */ |
234 | if (frame->valid) |
235 | goto error; |
236 | |
237 | frame->phys_irq = map_gt_gsi(interrupt: gtdt_frame->timer_interrupt, |
238 | flags: gtdt_frame->timer_flags); |
239 | if (frame->phys_irq <= 0) { |
240 | pr_warn("failed to map physical timer irq in frame %d.\n" , |
241 | gtdt_frame->frame_number); |
242 | goto error; |
243 | } |
244 | |
245 | if (gtdt_frame->virtual_timer_interrupt) { |
246 | frame->virt_irq = |
247 | map_gt_gsi(interrupt: gtdt_frame->virtual_timer_interrupt, |
248 | flags: gtdt_frame->virtual_timer_flags); |
249 | if (frame->virt_irq <= 0) { |
250 | pr_warn("failed to map virtual timer irq in frame %d.\n" , |
251 | gtdt_frame->frame_number); |
252 | goto error; |
253 | } |
254 | } else { |
255 | pr_debug("virtual timer in frame %d not implemented.\n" , |
256 | gtdt_frame->frame_number); |
257 | } |
258 | |
259 | frame->cntbase = gtdt_frame->base_address; |
260 | /* |
261 | * The CNTBaseN frame is 4KB (register offsets 0x000 - 0xFFC). |
262 | * See ARM DDI 0487A.k_iss10775, page I1-5130, Table I1-4 |
263 | * "CNTBaseN memory map". |
264 | */ |
265 | frame->size = SZ_4K; |
266 | frame->valid = true; |
267 | } |
268 | |
269 | return 0; |
270 | |
271 | error: |
272 | do { |
273 | if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER || |
274 | gtdt_frame->frame_number >= ARCH_TIMER_MEM_MAX_FRAMES) |
275 | continue; |
276 | |
277 | frame = &timer_mem->frame[gtdt_frame->frame_number]; |
278 | |
279 | if (frame->phys_irq > 0) |
280 | acpi_unregister_gsi(gsi: gtdt_frame->timer_interrupt); |
281 | frame->phys_irq = 0; |
282 | |
283 | if (frame->virt_irq > 0) |
284 | acpi_unregister_gsi(gsi: gtdt_frame->virtual_timer_interrupt); |
285 | frame->virt_irq = 0; |
286 | } while (i-- >= 0 && gtdt_frame--); |
287 | |
288 | return -EINVAL; |
289 | } |
290 | |
291 | /** |
292 | * acpi_arch_timer_mem_init() - Get the info of all GT blocks in GTDT table. |
293 | * @timer_mem: The pointer to the array of struct arch_timer_mem for returning |
294 | * the result of parsing. The element number of this array should |
295 | * be platform_timer_count(the total number of platform timers). |
296 | * @timer_count: It points to a integer variable which is used for storing the |
297 | * number of GT blocks we have parsed. |
298 | * |
299 | * Return: 0 if success, -EINVAL/-ENODEV if error. |
300 | */ |
301 | int __init acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, |
302 | int *timer_count) |
303 | { |
304 | int ret; |
305 | void *platform_timer; |
306 | |
307 | *timer_count = 0; |
308 | for_each_platform_timer(platform_timer) { |
309 | if (is_timer_block(platform_timer)) { |
310 | ret = gtdt_parse_timer_block(block: platform_timer, timer_mem); |
311 | if (ret) |
312 | return ret; |
313 | timer_mem++; |
314 | (*timer_count)++; |
315 | } |
316 | } |
317 | |
318 | if (*timer_count) |
319 | pr_info("found %d memory-mapped timer block(s).\n" , |
320 | *timer_count); |
321 | |
322 | return 0; |
323 | } |
324 | |
325 | /* |
326 | * Initialize a SBSA generic Watchdog platform device info from GTDT |
327 | */ |
328 | static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd, |
329 | int index) |
330 | { |
331 | struct platform_device *pdev; |
332 | int irq; |
333 | |
334 | /* |
335 | * According to SBSA specification the size of refresh and control |
336 | * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF). |
337 | */ |
338 | struct resource res[] = { |
339 | DEFINE_RES_MEM(wd->control_frame_address, SZ_4K), |
340 | DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K), |
341 | {}, |
342 | }; |
343 | int nr_res = ARRAY_SIZE(res); |
344 | |
345 | pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n" , |
346 | wd->refresh_frame_address, wd->control_frame_address, |
347 | wd->timer_interrupt, wd->timer_flags); |
348 | |
349 | if (!(wd->refresh_frame_address && wd->control_frame_address)) { |
350 | pr_err(FW_BUG "failed to get the Watchdog base address.\n" ); |
351 | return -EINVAL; |
352 | } |
353 | |
354 | irq = map_gt_gsi(interrupt: wd->timer_interrupt, flags: wd->timer_flags); |
355 | res[2] = (struct resource)DEFINE_RES_IRQ(irq); |
356 | if (irq <= 0) { |
357 | pr_warn("failed to map the Watchdog interrupt.\n" ); |
358 | nr_res--; |
359 | } |
360 | |
361 | /* |
362 | * Add a platform device named "sbsa-gwdt" to match the platform driver. |
363 | * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog |
364 | * The platform driver can get device info below by matching this name. |
365 | */ |
366 | pdev = platform_device_register_simple(name: "sbsa-gwdt" , id: index, res, num: nr_res); |
367 | if (IS_ERR(ptr: pdev)) { |
368 | if (irq > 0) |
369 | acpi_unregister_gsi(gsi: wd->timer_interrupt); |
370 | return PTR_ERR(ptr: pdev); |
371 | } |
372 | |
373 | return 0; |
374 | } |
375 | |
376 | static int __init gtdt_sbsa_gwdt_init(void) |
377 | { |
378 | void *platform_timer; |
379 | struct acpi_table_header *table; |
380 | int ret, timer_count, gwdt_count = 0; |
381 | |
382 | if (acpi_disabled) |
383 | return 0; |
384 | |
385 | if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_GTDT, 0, &table))) |
386 | return -EINVAL; |
387 | |
388 | /* |
389 | * Note: Even though the global variable acpi_gtdt_desc has been |
390 | * initialized by acpi_gtdt_init() while initializing the arch timers, |
391 | * when we call this function to get SBSA watchdogs info from GTDT, the |
392 | * pointers stashed in it are stale (since they are early temporary |
393 | * mappings carried out before acpi_permanent_mmap is set) and we need |
394 | * to re-initialize them with permanent mapped pointer values to let the |
395 | * GTDT parsing possible. |
396 | */ |
397 | ret = acpi_gtdt_init(table, platform_timer_count: &timer_count); |
398 | if (ret || !timer_count) |
399 | goto out_put_gtdt; |
400 | |
401 | for_each_platform_timer(platform_timer) { |
402 | if (is_non_secure_watchdog(platform_timer)) { |
403 | ret = gtdt_import_sbsa_gwdt(wd: platform_timer, index: gwdt_count); |
404 | if (ret) |
405 | break; |
406 | gwdt_count++; |
407 | } |
408 | } |
409 | |
410 | if (gwdt_count) |
411 | pr_info("found %d SBSA generic Watchdog(s).\n" , gwdt_count); |
412 | |
413 | out_put_gtdt: |
414 | acpi_put_table(table); |
415 | return ret; |
416 | } |
417 | |
418 | device_initcall(gtdt_sbsa_gwdt_init); |
419 | |