]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - arch/arm/mach-tegra/sleep-tegra20.S
ARM: tegra: Don't apply CPU erratas in insecure mode
[mirror_ubuntu-hirsute-kernel.git] / arch / arm / mach-tegra / sleep-tegra20.S
CommitLineData
453689e4
JL
1/*
2 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
3 * Copyright (c) 2011, Google, Inc.
4 *
5 * Author: Colin Cross <ccross@android.com>
6 * Gary King <gking@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <linux/linkage.h>
22
7e10cf74
JH
23#include <soc/tegra/flowctrl.h>
24
453689e4 25#include <asm/assembler.h>
5c1350bd
JL
26#include <asm/proc-fns.h>
27#include <asm/cp15.h>
731a9274 28#include <asm/cache.h>
453689e4 29
fddb770d 30#include "irammap.h"
2af6597a 31#include "reset.h"
453689e4 32#include "sleep.h"
453689e4 33
731a9274
JL
34#define EMC_CFG 0xc
35#define EMC_ADR_CFG 0x10
731a9274
JL
36#define EMC_NOP 0xdc
37#define EMC_SELF_REF 0xe0
38#define EMC_REQ_CTRL 0x2b0
39#define EMC_EMC_STATUS 0x2b4
40
41#define CLK_RESET_CCLK_BURST 0x20
42#define CLK_RESET_CCLK_DIVIDER 0x24
43#define CLK_RESET_SCLK_BURST 0x28
44#define CLK_RESET_SCLK_DIVIDER 0x2c
45#define CLK_RESET_PLLC_BASE 0x80
46#define CLK_RESET_PLLM_BASE 0x90
47#define CLK_RESET_PLLP_BASE 0xa0
48
49#define APB_MISC_XM2CFGCPADCTRL 0x8c8
50#define APB_MISC_XM2CFGDPADCTRL 0x8cc
51#define APB_MISC_XM2CLKCFGPADCTRL 0x8d0
52#define APB_MISC_XM2COMPPADCTRL 0x8d4
53#define APB_MISC_XM2VTTGENPADCTRL 0x8d8
54#define APB_MISC_XM2CFGCPADCTRL2 0x8e4
55#define APB_MISC_XM2CFGDPADCTRL2 0x8e8
56
2af6597a
DO
57#define __tegra20_cpu1_resettable_status_offset \
58 (__tegra_cpu_reset_handler_data_offset + RESET_DATA(RESETTABLE_STATUS))
59
731a9274
JL
60.macro pll_enable, rd, r_car_base, pll_base
61 ldr \rd, [\r_car_base, #\pll_base]
62 tst \rd, #(1 << 30)
63 orreq \rd, \rd, #(1 << 30)
64 streq \rd, [\r_car_base, #\pll_base]
65.endm
66
67.macro emc_device_mask, rd, base
68 ldr \rd, [\base, #EMC_ADR_CFG]
69 tst \rd, #(0x3 << 24)
70 moveq \rd, #(0x1 << 8) @ just 1 device
71 movne \rd, #(0x3 << 8) @ 2 devices
72.endm
73
453689e4
JL
74#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
75/*
76 * tegra20_hotplug_shutdown(void)
77 *
78 * puts the current cpu in reset
79 * should never return
80 */
81ENTRY(tegra20_hotplug_shutdown)
453689e4
JL
82 /* Put this CPU down */
83 cpu_id r0
84 bl tegra20_cpu_shutdown
6ebbf2ce 85 ret lr @ should never get here
453689e4
JL
86ENDPROC(tegra20_hotplug_shutdown)
87
88/*
89 * tegra20_cpu_shutdown(int cpu)
90 *
91 * r0 is cpu to reset
92 *
93 * puts the specified CPU in wait-for-event mode on the flow controller
94 * and puts the CPU in reset
95 * can be called on the current cpu or another cpu
96 * if called on the current cpu, does not return
97 * MUST NOT BE CALLED FOR CPU 0.
98 *
99 * corrupts r0-r3, r12
100 */
101ENTRY(tegra20_cpu_shutdown)
102 cmp r0, #0
6ebbf2ce 103 reteq lr @ must not be called for CPU 0
4d48edb3
DO
104 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
105 ldr r2, =__tegra20_cpu1_resettable_status_offset
1d328606 106 mov r12, #CPU_RESETTABLE
4d48edb3 107 strb r12, [r1, r2]
453689e4
JL
108
109 cpu_to_halt_reg r1, r0
110 ldr r3, =TEGRA_FLOW_CTRL_VIRT
111 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
112 str r2, [r3, r1] @ put flow controller in wait event mode
113 ldr r2, [r3, r1]
114 isb
115 dsb
116 movw r1, 0x1011
117 mov r1, r1, lsl r0
118 ldr r3, =TEGRA_CLK_RESET_VIRT
119 str r1, [r3, #0x340] @ put slave CPU in reset
120 isb
121 dsb
122 cpu_id r3
123 cmp r3, r0
124 beq .
6ebbf2ce 125 ret lr
453689e4
JL
126ENDPROC(tegra20_cpu_shutdown)
127#endif
5c1350bd
JL
128
129#ifdef CONFIG_PM_SLEEP
130/*
131 * tegra_pen_lock
132 *
133 * spinlock implementation with no atomic test-and-set and no coherence
134 * using Peterson's algorithm on strongly-ordered registers
135 * used to synchronize a cpu waking up from wfi with entering lp2 on idle
136 *
137 * The reference link of Peterson's algorithm:
138 * http://en.wikipedia.org/wiki/Peterson's_algorithm
139 *
140 * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
141 * on cpu 0:
142 * r2 = flag[0] (in SCRATCH38)
143 * r3 = flag[1] (in SCRATCH39)
144 * on cpu1:
145 * r2 = flag[1] (in SCRATCH39)
146 * r3 = flag[0] (in SCRATCH38)
147 *
148 * must be called with MMU on
149 * corrupts r0-r3, r12
150 */
151ENTRY(tegra_pen_lock)
152 mov32 r3, TEGRA_PMC_VIRT
153 cpu_id r0
154 add r1, r3, #PMC_SCRATCH37
155 cmp r0, #0
156 addeq r2, r3, #PMC_SCRATCH38
157 addeq r3, r3, #PMC_SCRATCH39
158 addne r2, r3, #PMC_SCRATCH39
159 addne r3, r3, #PMC_SCRATCH38
160
161 mov r12, #1
162 str r12, [r2] @ flag[cpu] = 1
163 dsb
164 str r12, [r1] @ !turn = cpu
1651: dsb
166 ldr r12, [r3]
167 cmp r12, #1 @ flag[!cpu] == 1?
168 ldreq r12, [r1]
169 cmpeq r12, r0 @ !turn == cpu?
170 beq 1b @ while !turn == cpu && flag[!cpu] == 1
171
6ebbf2ce 172 ret lr @ locked
5c1350bd
JL
173ENDPROC(tegra_pen_lock)
174
175ENTRY(tegra_pen_unlock)
176 dsb
177 mov32 r3, TEGRA_PMC_VIRT
178 cpu_id r0
179 cmp r0, #0
180 addeq r2, r3, #PMC_SCRATCH38
181 addne r2, r3, #PMC_SCRATCH39
182 mov r12, #0
183 str r12, [r2]
6ebbf2ce 184 ret lr
5c1350bd
JL
185ENDPROC(tegra_pen_unlock)
186
187/*
188 * tegra20_cpu_clear_resettable(void)
189 *
4d48edb3 190 * Called to clear the "resettable soon" flag in IRAM variable when
5c1350bd
JL
191 * it is expected that the secondary CPU will be idle soon.
192 */
193ENTRY(tegra20_cpu_clear_resettable)
4d48edb3
DO
194 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
195 ldr r2, =__tegra20_cpu1_resettable_status_offset
5c1350bd 196 mov r12, #CPU_NOT_RESETTABLE
4d48edb3 197 strb r12, [r1, r2]
6ebbf2ce 198 ret lr
5c1350bd
JL
199ENDPROC(tegra20_cpu_clear_resettable)
200
201/*
202 * tegra20_cpu_set_resettable_soon(void)
203 *
4d48edb3 204 * Called to set the "resettable soon" flag in IRAM variable when
5c1350bd
JL
205 * it is expected that the secondary CPU will be idle soon.
206 */
207ENTRY(tegra20_cpu_set_resettable_soon)
4d48edb3
DO
208 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
209 ldr r2, =__tegra20_cpu1_resettable_status_offset
5c1350bd 210 mov r12, #CPU_RESETTABLE_SOON
4d48edb3 211 strb r12, [r1, r2]
6ebbf2ce 212 ret lr
5c1350bd
JL
213ENDPROC(tegra20_cpu_set_resettable_soon)
214
1d328606
JL
215/*
216 * tegra20_cpu_is_resettable_soon(void)
217 *
4d48edb3 218 * Returns true if the "resettable soon" flag in IRAM variable has been
1d328606
JL
219 * set because it is expected that the secondary CPU will be idle soon.
220 */
221ENTRY(tegra20_cpu_is_resettable_soon)
4d48edb3
DO
222 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
223 ldr r2, =__tegra20_cpu1_resettable_status_offset
224 ldrb r12, [r1, r2]
1d328606
JL
225 cmp r12, #CPU_RESETTABLE_SOON
226 moveq r0, #1
227 movne r0, #0
6ebbf2ce 228 ret lr
1d328606
JL
229ENDPROC(tegra20_cpu_is_resettable_soon)
230
731a9274
JL
231/*
232 * tegra20_sleep_core_finish(unsigned long v2p)
233 *
234 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
235 * tegra20_tear_down_core in IRAM
236 */
237ENTRY(tegra20_sleep_core_finish)
5883ac20 238 mov r4, r0
731a9274 239 /* Flush, disable the L1 data cache and exit SMP */
5883ac20 240 mov r0, #TEGRA_FLUSH_CACHE_ALL
731a9274 241 bl tegra_disable_clean_inv_dcache
5883ac20 242 mov r0, r4
731a9274
JL
243
244 mov32 r3, tegra_shut_off_mmu
245 add r3, r3, r0
246
247 mov32 r0, tegra20_tear_down_core
248 mov32 r1, tegra20_iram_start
249 sub r0, r0, r1
fddb770d 250 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
731a9274
JL
251 add r0, r0, r1
252
6ebbf2ce 253 ret r3
731a9274
JL
254ENDPROC(tegra20_sleep_core_finish)
255
5c1350bd
JL
256/*
257 * tegra20_sleep_cpu_secondary_finish(unsigned long v2p)
258 *
259 * Enters WFI on secondary CPU by exiting coherency.
260 */
261ENTRY(tegra20_sleep_cpu_secondary_finish)
262 stmfd sp!, {r4-r11, lr}
263
264 mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency
265
266 /* Flush and disable the L1 data cache */
ac2527bf 267 mov r0, #TEGRA_FLUSH_CACHE_LOUIS
5c1350bd
JL
268 bl tegra_disable_clean_inv_dcache
269
4d48edb3
DO
270 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
271 ldr r4, =__tegra20_cpu1_resettable_status_offset
5c1350bd 272 mov r3, #CPU_RESETTABLE
4d48edb3 273 strb r3, [r0, r4]
5c1350bd 274
2058842e 275 bl tegra_cpu_do_idle
5c1350bd
JL
276
277 /*
278 * cpu may be reset while in wfi, which will return through
279 * tegra_resume to cpu_resume
280 * or interrupt may wake wfi, which will return here
281 * cpu state is unchanged - MMU is on, cache is on, coherency
282 * is off, and the data cache is off
283 *
284 * r11 contains the original actlr
285 */
286
287 bl tegra_pen_lock
288
4d48edb3
DO
289 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
290 ldr r4, =__tegra20_cpu1_resettable_status_offset
5c1350bd 291 mov r3, #CPU_NOT_RESETTABLE
4d48edb3 292 strb r3, [r0, r4]
5c1350bd
JL
293
294 bl tegra_pen_unlock
295
296 /* Re-enable the data cache */
297 mrc p15, 0, r10, c1, c0, 0
298 orr r10, r10, #CR_C
299 mcr p15, 0, r10, c1, c0, 0
300 isb
301
302 mcr p15, 0, r11, c1, c0, 1 @ reenable coherency
303
304 /* Invalidate the TLBs & BTAC */
305 mov r1, #0
306 mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs
307 mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC
308 dsb
309 isb
310
311 /* the cpu was running with coherency disabled,
312 * caches may be out of date */
313 bl v7_flush_kern_cache_louis
314
315 ldmfd sp!, {r4 - r11, pc}
316ENDPROC(tegra20_sleep_cpu_secondary_finish)
1d328606
JL
317
318/*
319 * tegra20_tear_down_cpu
320 *
321 * Switches the CPU cluster to PLL-P and enters sleep.
322 */
323ENTRY(tegra20_tear_down_cpu)
324 bl tegra_switch_cpu_to_pllp
325 b tegra20_enter_sleep
326ENDPROC(tegra20_tear_down_cpu)
327
731a9274
JL
328/* START OF ROUTINES COPIED TO IRAM */
329 .align L1_CACHE_SHIFT
330 .globl tegra20_iram_start
331tegra20_iram_start:
332
333/*
334 * tegra20_lp1_reset
335 *
336 * reset vector for LP1 restore; copied into IRAM during suspend.
337 * Brings the system back up to a safe staring point (SDRAM out of
338 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
339 * system clock running on the same PLL that it suspended at), and
340 * jumps to tegra_resume to restore virtual addressing and PLLX.
341 * The physical address of tegra_resume expected to be stored in
342 * PMC_SCRATCH41.
343 *
fddb770d 344 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
731a9274
JL
345 */
346ENTRY(tegra20_lp1_reset)
347 /*
348 * The CPU and system bus are running at 32KHz and executing from
349 * IRAM when this code is executed; immediately switch to CLKM and
350 * enable PLLM, PLLP, PLLC.
351 */
352 mov32 r0, TEGRA_CLK_RESET_BASE
353
354 mov r1, #(1 << 28)
355 str r1, [r0, #CLK_RESET_SCLK_BURST]
356 str r1, [r0, #CLK_RESET_CCLK_BURST]
357 mov r1, #0
358 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
359 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
360
361 pll_enable r1, r0, CLK_RESET_PLLM_BASE
362 pll_enable r1, r0, CLK_RESET_PLLP_BASE
363 pll_enable r1, r0, CLK_RESET_PLLC_BASE
364
365 adr r2, tegra20_sdram_pad_address
366 adr r4, tegra20_sdram_pad_save
367 mov r5, #0
368
369 ldr r6, tegra20_sdram_pad_size
370padload:
371 ldr r7, [r2, r5] @ r7 is the addr in the pad_address
372
373 ldr r1, [r4, r5]
374 str r1, [r7] @ restore the value in pad_save
375
376 add r5, r5, #4
377 cmp r6, r5
378 bne padload
379
380padload_done:
381 /* 255uS delay for PLL stabilization */
382 mov32 r7, TEGRA_TMRUS_BASE
383 ldr r1, [r7]
384 add r1, r1, #0xff
385 wait_until r1, r7, r9
386
387 adr r4, tegra20_sclk_save
388 ldr r4, [r4]
389 str r4, [r0, #CLK_RESET_SCLK_BURST]
390 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP
391 str r4, [r0, #CLK_RESET_CCLK_BURST]
392
393 mov32 r0, TEGRA_EMC_BASE
394 ldr r1, [r0, #EMC_CFG]
395 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP
396 str r1, [r0, #EMC_CFG]
397
398 mov r1, #0
399 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
400 mov r1, #1
401 str r1, [r0, #EMC_NOP]
402 str r1, [r0, #EMC_NOP]
731a9274
JL
403
404 emc_device_mask r1, r0
405
406exit_selfrefresh_loop:
407 ldr r2, [r0, #EMC_EMC_STATUS]
408 ands r2, r2, r1
409 bne exit_selfrefresh_loop
410
411 mov r1, #0 @ unstall all transactions
412 str r1, [r0, #EMC_REQ_CTRL]
413
414 mov32 r0, TEGRA_PMC_BASE
415 ldr r0, [r0, #PMC_SCRATCH41]
6ebbf2ce 416 ret r0 @ jump to tegra_resume
731a9274
JL
417ENDPROC(tegra20_lp1_reset)
418
419/*
420 * tegra20_tear_down_core
421 *
422 * copied into and executed from IRAM
423 * puts memory in self-refresh for LP0 and LP1
424 */
425tegra20_tear_down_core:
426 bl tegra20_sdram_self_refresh
427 bl tegra20_switch_cpu_to_clk32k
428 b tegra20_enter_sleep
429
430/*
431 * tegra20_switch_cpu_to_clk32k
432 *
433 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
434 * to the 32KHz clock.
435 */
436tegra20_switch_cpu_to_clk32k:
437 /*
438 * start by switching to CLKM to safely disable PLLs, then switch to
439 * CLKS.
440 */
441 mov r0, #(1 << 28)
442 str r0, [r5, #CLK_RESET_SCLK_BURST]
443 str r0, [r5, #CLK_RESET_CCLK_BURST]
444 mov r0, #0
445 str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
446 str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
447
448 /* 2uS delay delay between changing SCLK and disabling PLLs */
449 mov32 r7, TEGRA_TMRUS_BASE
450 ldr r1, [r7]
451 add r1, r1, #2
452 wait_until r1, r7, r9
453
454 /* disable PLLM, PLLP and PLLC */
455 ldr r0, [r5, #CLK_RESET_PLLM_BASE]
456 bic r0, r0, #(1 << 30)
457 str r0, [r5, #CLK_RESET_PLLM_BASE]
458 ldr r0, [r5, #CLK_RESET_PLLP_BASE]
459 bic r0, r0, #(1 << 30)
460 str r0, [r5, #CLK_RESET_PLLP_BASE]
461 ldr r0, [r5, #CLK_RESET_PLLC_BASE]
462 bic r0, r0, #(1 << 30)
463 str r0, [r5, #CLK_RESET_PLLC_BASE]
464
465 /* switch to CLKS */
466 mov r0, #0 /* brust policy = 32KHz */
467 str r0, [r5, #CLK_RESET_SCLK_BURST]
468
6ebbf2ce 469 ret lr
731a9274 470
1d328606
JL
471/*
472 * tegra20_enter_sleep
473 *
474 * uses flow controller to enter sleep state
475 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
476 * executes from SDRAM with target state is LP2
477 */
478tegra20_enter_sleep:
479 mov32 r6, TEGRA_FLOW_CTRL_BASE
480
481 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
482 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
483 cpu_id r1
484 cpu_to_halt_reg r1, r1
485 str r0, [r6, r1]
486 dsb
487 ldr r0, [r6, r1] /* memory barrier */
488
489halted:
490 dsb
491 wfe /* CPU should be power gated here */
492 isb
493 b halted
494
731a9274
JL
495/*
496 * tegra20_sdram_self_refresh
497 *
498 * called with MMU off and caches disabled
499 * puts sdram in self refresh
500 * must be executed from IRAM
501 */
502tegra20_sdram_self_refresh:
503 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr
504
505 mov r2, #3
506 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
507
508emcidle:
509 ldr r2, [r1, #EMC_EMC_STATUS]
510 tst r2, #4
511 beq emcidle
512
513 mov r2, #1
514 str r2, [r1, #EMC_SELF_REF]
515
516 emc_device_mask r2, r1
517
518emcself:
519 ldr r3, [r1, #EMC_EMC_STATUS]
520 and r3, r3, r2
521 cmp r3, r2
522 bne emcself @ loop until DDR in self-refresh
523
524 adr r2, tegra20_sdram_pad_address
525 adr r3, tegra20_sdram_pad_safe
526 adr r4, tegra20_sdram_pad_save
527 mov r5, #0
528
529 ldr r6, tegra20_sdram_pad_size
530padsave:
531 ldr r0, [r2, r5] @ r0 is the addr in the pad_address
532
533 ldr r1, [r0]
534 str r1, [r4, r5] @ save the content of the addr
535
536 ldr r1, [r3, r5]
537 str r1, [r0] @ set the save val to the addr
538
539 add r5, r5, #4
540 cmp r6, r5
541 bne padsave
542padsave_done:
543
544 mov32 r5, TEGRA_CLK_RESET_BASE
545 ldr r0, [r5, #CLK_RESET_SCLK_BURST]
546 adr r2, tegra20_sclk_save
547 str r0, [r2]
548 dsb
6ebbf2ce 549 ret lr
731a9274
JL
550
551tegra20_sdram_pad_address:
552 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
553 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
554 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
555 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
556 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
557 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
558 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
559
560tegra20_sdram_pad_size:
561 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address
562
563tegra20_sdram_pad_safe:
564 .word 0x8
565 .word 0x8
566 .word 0x0
567 .word 0x8
568 .word 0x5500
569 .word 0x08080040
570 .word 0x0
571
572tegra20_sclk_save:
573 .word 0x0
574
575tegra20_sdram_pad_save:
576 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
577 .long 0
578 .endr
579
580 .ltorg
581/* dummy symbol for end of IRAM */
582 .align L1_CACHE_SHIFT
583 .globl tegra20_iram_end
584tegra20_iram_end:
585 b .
5c1350bd 586#endif