revert between 56095 -> 55830 in arch
[AROS.git] / arch / arm-raspi / timer / timer_init.c
blobb8b26324aa1650828675e27a28ad9cd8984f3e03
1 /*
2 Copyright © 2013-2019, 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;
38 D(unsigned int last_CHI);
40 D(bug("[Timer] Timer1Tick()\n"));
42 if (!(TimerBase) || !(SysBase))
44 bug("[Timer] Timer1Tick: Bad Params!\n");
45 return;
48 D(last_CHI = TimerBase->tb_Platform.tbp_CHI);
49 last_CLO = TimerBase->tb_Platform.tbp_CLO;
51 /* Aknowledge and update our timer interrupt */
52 *((volatile unsigned int *)(SYSTIMER_CS)) = (1 << TICK_TIMER); //TimerBase->tb_Platform.tbp_cs;
53 TimerBase->tb_Platform.tbp_CHI = *((volatile unsigned int *)(SYSTIMER_CHI));
54 TimerBase->tb_Platform.tbp_CLO = *((volatile unsigned int *)(SYSTIMER_CLO));
56 D(bug("[Timer] Timer1Tick: Updating EClock..\n"));
57 D(bug("[Timer] Timer1Tick: diff_CHI = %d\n", (TimerBase->tb_Platform.tbp_CHI - last_CHI)));
58 D(bug("[Timer] Timer1Tick: diff_CLO = %d\n", (TimerBase->tb_Platform.tbp_CLO - last_CLO)));
60 TimerBase->tb_Platform.tbp_TickRate.tv_secs = 0;
61 if ((TimerBase->tb_Platform.tbp_CLO - last_CLO) > 0)
62 TimerBase->tb_Platform.tbp_TickRate.tv_micro = TimerBase->tb_Platform.tbp_CLO - last_CLO;
63 else
64 TimerBase->tb_Platform.tbp_TickRate.tv_micro = ((1000000 - last_CLO) + TimerBase->tb_Platform.tbp_CLO);
66 /* Increment EClock value and process microhz requests */
67 ADDTIME(&TimerBase->tb_CurrentTime, &TimerBase->tb_Platform.tbp_TickRate);
68 ADDTIME(&TimerBase->tb_Elapsed, &TimerBase->tb_Platform.tbp_TickRate);
69 TimerBase->tb_ticks_total++;
71 D(bug("[Timer] Timer1Tick: Processing events.. \n"));
73 handleMicroHZ(TimerBase, SysBase);
74 // handleEClock(TimerBase, SysBase);
76 D(bug("[Timer] Timer1Tick: Reconfiguring interrupt..\n"));
78 TimerBase->tb_Platform.tbp_CLO = *((volatile unsigned int *)(SYSTIMER_CLO));
79 *((volatile unsigned int *)(SYSTIMER_C0 + (TICK_TIMER * 4))) = (TimerBase->tb_Platform.tbp_CLO + (1000000 / TimerBase->tb_eclock_rate));
81 D(bug("[Timer] Timer1Tick: Done..\n"));
84 /****************************************************************************************/
85 int vblank_Init(struct TimerBase *LIBBASE);
87 static int Timer_Init(struct TimerBase *TimerBase)
89 D(bug("[Timer] Timer_Init: kernel.resource @ 0x%p\n", KernelBase));
91 TimerBase->tb_Platform.tbp_periiobase = KrnGetSystemAttr(KATTR_PeripheralBase);
93 /* Install timer IRQ handler */
94 TimerBase->tb_TimerIRQHandle = KrnAddIRQHandler(IRQ_TIMER0 + TICK_TIMER, Timer1Tick, TimerBase, SysBase);
95 if (!TimerBase->tb_TimerIRQHandle)
96 return FALSE;
98 D(bug("[Timer] Timer_Init: TimerIRQHandle @ 0x%p\n", TimerBase->tb_TimerIRQHandle));
100 /* By default we want 100 Hz EClock */
101 TimerBase->tb_eclock_rate = 100;
104 * Since we are software-driven, we can just ask the user which
105 * frequencies he wishes to use.
107 BootLoaderBase = OpenResource("bootloader.resource");
108 if (BootLoaderBase)
110 struct List *args = GetBootInfo(BL_Args);
112 if (args)
114 struct Node *node;
116 for (node = args->lh_Head; node->ln_Succ; node = node->ln_Succ)
118 if (strncasecmp(node->ln_Name, "eclock=", 7) == 0)
120 TimerBase->tb_eclock_rate = atoi(&node->ln_Name[7]);
121 break;
127 /* Set ExecBase public field. */
128 SysBase->ex_EClockFrequency = TimerBase->tb_eclock_rate;
129 D(bug("[Timer] Timer frequency is %d\n", TimerBase->tb_eclock_rate));
131 /* Calculate timer period in us */
132 TimerBase->tb_Platform.tbp_TickRate.tv_secs = 0;
133 TimerBase->tb_Platform.tbp_TickRate.tv_micro = 1000000 / TimerBase->tb_eclock_rate;
135 /* Start up GPU timer #TICK_TIMER */
136 Forbid();
137 TimerBase->tb_Platform.tbp_CHI = *((volatile unsigned int *)(SYSTIMER_CHI));
138 TimerBase->tb_Platform.tbp_CLO = *((volatile unsigned int *)(SYSTIMER_CLO));
139 *((volatile unsigned int *)(SYSTIMER_C0 + (TICK_TIMER * 4))) = (TimerBase->tb_Platform.tbp_CLO + TimerBase->tb_Platform.tbp_TickRate.tv_micro);
140 Permit();
142 vblank_Init(TimerBase);
144 D(bug("[Timer] Timer_Init: configured GPU timer %d\n", TICK_TIMER));
146 return TRUE;
149 static int Timer_Expunge(struct TimerBase *TimerBase)
151 D(bug("[Timer] Timer_Expunge()\n"));
153 if (TimerBase->tb_TimerIRQHandle)
154 KrnRemIRQHandler(TimerBase->tb_TimerIRQHandle);
156 return TRUE;
159 ADD2INITLIB(Timer_Init, 0)
160 ADD2EXPUNGELIB(Timer_Expunge, 0)