remove duplicate const
[AROS.git] / arch / arm-raspi / timer / timer_init.c
blobf187984384e5e4f28298bf2c16e64544c228c20e
1 /*
2 Copyright © 2013-2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /*
7 * RasPi timer driver.
9 * We use the GPU Timer #1 to handle EClock updates, since GPU Timer #3 is used for VBlank,
10 * and Timers #0 and #2 are used by the GPU itself.
14 #define DEBUG 0
16 #include <aros/bootloader.h>
17 #include <aros/debug.h>
18 #include <aros/symbolsets.h>
19 #include <exec/execbase.h>
20 #include <exec/interrupts.h>
21 #include <hardware/intbits.h>
22 #include <proto/arossupport.h>
23 #include <proto/bootloader.h>
24 #include <proto/exec.h>
25 #include <proto/kernel.h>
28 #include "timer_intern.h"
29 #include "timer_macros.h"
31 #include <stdlib.h>
32 #include <string.h>
34 /* Timer 1 (EClock) interrupt handler */
35 static void Timer1Tick(struct TimerBase *TimerBase, struct ExecBase *SysBase)
37 unsigned int last_CLO, last_CHI;
39 D(bug("[Timer] Timer1Tick()\n"));
41 if (!(TimerBase) || !(SysBase))
43 bug("[Timer] Timer1Tick: Bad Params!\n");
44 return;
47 last_CHI = TimerBase->tb_Platform.tbp_CHI;
48 last_CLO = TimerBase->tb_Platform.tbp_CLO;
50 /* Aknowledge and update our timer interrupt */
51 *((volatile unsigned int *)(SYSTIMER_CS)) = (1 << TICK_TIMER); //TimerBase->tb_Platform.tbp_cs;
52 TimerBase->tb_Platform.tbp_CHI = *((volatile unsigned int *)(SYSTIMER_CHI));
53 TimerBase->tb_Platform.tbp_CLO = *((volatile unsigned int *)(SYSTIMER_CLO));
55 D(bug("[Timer] Timer1Tick: Updating EClock..\n"));
56 D(bug("[Timer] Timer1Tick: diff_CHI = %d\n", (TimerBase->tb_Platform.tbp_CHI - last_CHI)));
57 D(bug("[Timer] Timer1Tick: diff_CLO = %d\n", (TimerBase->tb_Platform.tbp_CLO - last_CLO)));
59 TimerBase->tb_Platform.tbp_TickRate.tv_secs = 0;
60 if ((TimerBase->tb_Platform.tbp_CLO - last_CLO) > 0)
61 TimerBase->tb_Platform.tbp_TickRate.tv_micro = TimerBase->tb_Platform.tbp_CLO - last_CLO;
62 else
63 TimerBase->tb_Platform.tbp_TickRate.tv_micro = ((1000000 - last_CLO) + TimerBase->tb_Platform.tbp_CLO);
65 /* Increment EClock value and process microhz requests */
66 ADDTIME(&TimerBase->tb_CurrentTime, &TimerBase->tb_Platform.tbp_TickRate);
67 ADDTIME(&TimerBase->tb_Elapsed, &TimerBase->tb_Platform.tbp_TickRate);
68 TimerBase->tb_ticks_total++;
70 D(bug("[Timer] Timer1Tick: Processing events.. \n"));
72 handleMicroHZ(TimerBase, SysBase);
73 // handleEClock(TimerBase, SysBase);
75 D(bug("[Timer] Timer1Tick: Reconfiguring interrupt..\n"));
77 TimerBase->tb_Platform.tbp_CLO = *((volatile unsigned int *)(SYSTIMER_CLO));
78 *((volatile unsigned int *)(SYSTIMER_C0 + (TICK_TIMER * 4))) = (TimerBase->tb_Platform.tbp_CLO + (1000000 / TimerBase->tb_eclock_rate));
80 D(bug("[Timer] Timer1Tick: Done..\n"));
83 /****************************************************************************************/
84 int vblank_Init(struct TimerBase *LIBBASE);
86 static int Timer_Init(struct TimerBase *TimerBase)
88 D(bug("[Timer] Timer_Init: kernel.resource @ 0x%p\n", KernelBase));
90 TimerBase->tb_Platform.tbp_periiobase = KrnGetSystemAttr(KATTR_PeripheralBase);
92 /* Install timer IRQ handler */
93 TimerBase->tb_TimerIRQHandle = KrnAddIRQHandler(IRQ_TIMER0 + TICK_TIMER, Timer1Tick, TimerBase, SysBase);
94 if (!TimerBase->tb_TimerIRQHandle)
95 return FALSE;
97 D(bug("[Timer] Timer_Init: TimerIRQHandle @ 0x%p\n", TimerBase->tb_TimerIRQHandle));
99 /* By default we want 100 Hz EClock */
100 TimerBase->tb_eclock_rate = 100;
103 * Since we are software-driven, we can just ask the user which
104 * frequencies he wishes to use.
106 BootLoaderBase = OpenResource("bootloader.resource");
107 if (BootLoaderBase)
109 struct List *args = GetBootInfo(BL_Args);
111 if (args)
113 struct Node *node;
115 for (node = args->lh_Head; node->ln_Succ; node = node->ln_Succ)
117 if (strncasecmp(node->ln_Name, "eclock=", 7) == 0)
119 TimerBase->tb_eclock_rate = atoi(&node->ln_Name[7]);
120 break;
126 /* Set ExecBase public field. */
127 SysBase->ex_EClockFrequency = TimerBase->tb_eclock_rate;
128 D(bug("[Timer] Timer frequency is %d\n", TimerBase->tb_eclock_rate));
130 /* Calculate timer period in us */
131 TimerBase->tb_Platform.tbp_TickRate.tv_secs = 0;
132 TimerBase->tb_Platform.tbp_TickRate.tv_micro = 1000000 / TimerBase->tb_eclock_rate;
134 /* Start up GPU timer #TICK_TIMER */
135 Forbid();
136 TimerBase->tb_Platform.tbp_CHI = *((volatile unsigned int *)(SYSTIMER_CHI));
137 TimerBase->tb_Platform.tbp_CLO = *((volatile unsigned int *)(SYSTIMER_CLO));
138 *((volatile unsigned int *)(SYSTIMER_C0 + (TICK_TIMER * 4))) = (TimerBase->tb_Platform.tbp_CLO + TimerBase->tb_Platform.tbp_TickRate.tv_micro);
139 Permit();
141 vblank_Init(TimerBase);
143 D(bug("[Timer] Timer_Init: configured GPU timer %d\n", TICK_TIMER));
145 return TRUE;
148 static int Timer_Expunge(struct TimerBase *TimerBase)
150 D(bug("[Timer] Timer_Expunge()\n"));
152 if (TimerBase->tb_TimerIRQHandle)
153 KrnRemIRQHandler(TimerBase->tb_TimerIRQHandle);
155 return TRUE;
158 ADD2INITLIB(Timer_Init, 0)
159 ADD2EXPUNGELIB(Timer_Expunge, 0)