IRQ support fixed.
[AROS.git] / arch / arm-native / kernel / platform_bcm2708.c
blob376a3fb32a72f0402fa25b40725e5eeec1e5b5b9
1 /*
2 Copyright © 2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/kernel.h>
7 #include <aros/symbolsets.h>
9 #include "kernel_base.h"
11 #include <proto/kernel.h>
12 #include <proto/exec.h>
14 #include <inttypes.h>
15 #include <hardware/intbits.h>
17 #include "kernel_intern.h"
18 #include "kernel_cpu.h"
19 #include "kernel_interrupts.h"
20 #include "kernel_intr.h"
21 #include "kernel_fb.h"
23 #define ARM_PERIIOBASE __arm_arosintern.ARMI_PeripheralBase
24 #include <hardware/bcm2708.h>
25 #include <hardware/pl011uart.h>
27 #define IRQBANK_POINTER(bank) ((bank == 0) ? GPUIRQ_ENBL0 : (bank == 1) ? GPUIRQ_ENBL1 : ARMIRQ_ENBL)
29 #define IRQ_BANK1 0x00000100
30 #define IRQ_BANK2 0x00000200
32 #define DIRQ(x)
34 extern void cpu_Register(void);
36 static void bcm2708_init(APTR _kernelBase)
38 struct KernelBase *KernelBase = (struct KernelBase *)_kernelBase;
39 if (__arm_arosintern.ARMI_PeripheralBase == (APTR)BCM2836_PERIPHYSBASE)
41 int core;
42 for (core = 1; core < 4; core ++)
44 *((volatile unsigned int *)(0x4000008C + (0x10 * core))) = (unsigned int)KrnVirtualToPhysical(cpu_Register);
47 if (__arm_arosintern.ARMI_Delay)
48 __arm_arosintern.ARMI_Delay(1500);
52 static unsigned int bcm2807_get_time(void)
54 return *((volatile unsigned int *)(SYSTIMER_CLO));
57 static void bcm2807_irq_init(void)
59 // disable IRQ's
60 *(volatile unsigned int *)ARMIRQ_DIBL = ~0;
61 *(volatile unsigned int *)GPUIRQ_DIBL0 = ~0;
62 *(volatile unsigned int *)GPUIRQ_DIBL1 = ~0;
65 static void bcm2807_irq_enable(int irq)
67 int bank = IRQ_BANK(irq);
68 unsigned int reg;
70 reg = (unsigned int)IRQBANK_POINTER(bank);
72 (bug("[KRN:BCM2708] Enabling irq %d [bank %d, reg 0x%p]\n", irq, bank, reg));
74 *((volatile unsigned int *)reg) = IRQ_MASK(irq);
76 (bug("[KRN:BCM2708] irqmask=%08x\n", *((volatile unsigned int *)reg)));
79 static void bcm2807_irq_disable(int irq)
81 int bank = IRQ_BANK(irq);
82 unsigned int reg;
84 reg = (unsigned int)IRQBANK_POINTER(bank) + 0x0c;
86 (bug("[KRN:BCM2708] Disabling irq %d [bank %d, reg 0x%p]\n", irq, bank, reg));
88 *((volatile unsigned int *)reg) = IRQ_MASK(irq);
90 (bug("[KRN:BCM2708] irqmask=%08x\n", *((volatile unsigned int *)reg)));
93 static void bcm2807_irq_process()
95 unsigned int pendingarm, pending0, pending1, irq;
97 for(;;)
99 pendingarm = *((volatile unsigned int *)(ARMIRQ_PEND));
100 pending0 = *((volatile unsigned int *)(GPUIRQ_PEND0));
101 pending1 = *((volatile unsigned int *)(GPUIRQ_PEND1));
103 if (!(pendingarm || pending0 || pending1))
104 break;
106 DIRQ(bug("[KRN] PendingARM %08x\n", pendingarm));
107 DIRQ(bug("[KRN] Pending0 %08x\n", pending0));
108 DIRQ(bug("[KRN] Pending1 %08x\n", pending1));
110 if (pendingarm & ~(IRQ_BANK1 | IRQ_BANK2))
112 for (irq = (2 << 5); irq < ((2 << 5) + 8); irq++)
114 if (pendingarm & (1 << (irq - (2 << 5))))
116 DIRQ(bug("[KRN] Handling IRQ %d ..\n", irq));
117 krnRunIRQHandlers(KernelBase, irq);
122 if (pending0)
124 for (irq = (0 << 5); irq < ((0 << 5) + 32); irq++)
126 if (pending0 & (1 << (irq - (0 << 5))))
128 DIRQ(bug("[KRN] Handling IRQ %d ..\n", irq));
129 krnRunIRQHandlers(KernelBase, irq);
134 if (pending1)
136 for (irq = (1 << 5); irq < ((1 << 5) + 32); irq++)
138 if (pending1 & (1 << (irq - (1 << 5))))
140 DIRQ(bug("[KRN] Handling IRQ %d ..\n", irq));
141 krnRunIRQHandlers(KernelBase, irq);
149 static void bcm2708_toggle_led(int LED, int state)
151 if (__arm_arosintern.ARMI_PeripheralBase == (APTR)BCM2836_PERIPHYSBASE)
153 int pin = 35;
154 APTR gpiofunc = GPCLR1;
156 if (LED == ARM_LED_ACTIVITY)
157 pin = 47;
159 if (state == ARM_LED_ON)
160 gpiofunc = GPSET1;
162 *(volatile unsigned int *)gpiofunc = (1 << (pin-32));
164 else
166 // RasPi 1 only allows us to toggle the activity LED
167 if (state)
168 *(volatile unsigned int *)GPCLR0 = (1 << 16);
169 else
170 *(volatile unsigned int *)GPSET0 = (1 << 16);
174 static void bcm2708_gputimer_handler(unsigned int timerno, void *unused1)
176 unsigned int stc;
178 D(bug("[KRN:BCM2708] %s(%d)\n", __PRETTY_FUNCTION__, timerno));
180 /* Aknowledge our timer interrupt */
181 *((volatile unsigned int *)(SYSTIMER_CS)) = 1 << timerno;
183 /* Signal the Exec VBlankServer */
184 if (SysBase && (SysBase->IDNestCnt < 0)) {
185 core_Cause(INTB_VERTB, 1L << INTB_VERTB);
188 /* Refresh our timer interrupt */
189 stc = *((volatile unsigned int *)(SYSTIMER_CLO));
190 stc += VBLANK_INTERVAL;
191 *((volatile unsigned int *)(SYSTIMER_C0 + (timerno * 4))) = stc;
193 D(bug("[BCM2708] %s: Done..\n", __PRETTY_FUNCTION__));
196 static APTR bcm2708_init_gputimer(APTR _kernelBase)
198 struct KernelBase *KernelBase = (struct KernelBase *)_kernelBase;
199 struct IntrNode *GPUTimerHandle;
200 unsigned int stc;
202 D(bug("[KRN:BCM2708] %s(%012p)\n", __PRETTY_FUNCTION__, KernelBase));
204 if ((GPUTimerHandle = AllocMem(sizeof(struct IntrNode), MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
206 D(bug("[KRN:BCM2708] %s: IntrNode @ 0x%p:\n", __PRETTY_FUNCTION__, GPUTimerHandle));
207 D(bug("[KRN:BCM2708] %s: Using GPUTimer %d for VBlank\n", __PRETTY_FUNCTION__, VBLANK_TIMER));
209 GPUTimerHandle->in_Handler = bcm2708_gputimer_handler;
210 GPUTimerHandle->in_HandlerData = VBLANK_TIMER;
211 GPUTimerHandle->in_HandlerData2 = KernelBase;
212 GPUTimerHandle->in_type = it_interrupt;
213 GPUTimerHandle->in_nr = IRQ_TIMER0 + VBLANK_TIMER;
215 ADDHEAD(&KernelBase->kb_Interrupts[IRQ_TIMER0 + VBLANK_TIMER], &GPUTimerHandle->in_Node);
217 D(bug("[KRN:BCM2708] %s: Enabling Hardware IRQ.. \n", __PRETTY_FUNCTION__));
219 stc = *((volatile unsigned int *)(SYSTIMER_CLO));
220 stc += VBLANK_INTERVAL;
221 *((volatile unsigned int *)(SYSTIMER_CS)) = (1 << VBLANK_TIMER);
222 *((volatile unsigned int *)(SYSTIMER_C0 + (VBLANK_TIMER * 4))) = stc;
224 ictl_enable_irq(IRQ_TIMER0 + VBLANK_TIMER, KernelBase);
227 D(bug("[KRN:BCM2708] %s: Done.. \n", __PRETTY_FUNCTION__));
229 return GPUTimerHandle;
232 static inline void bcm2708_ser_waitout()
234 while(1)
236 if ((*(volatile uint32_t *)(PL011_0_BASE + PL011_FR) & PL011_FR_TXFF) == 0) break;
240 static void bcm2708_ser_putc(uint8_t chr)
242 bcm2708_ser_waitout();
244 if (chr == '\n')
246 *(volatile uint32_t *)(PL011_0_BASE + PL011_DR) = '\r';
247 bcm2708_ser_waitout();
249 *(volatile uint32_t *)(PL011_0_BASE + PL011_DR) = chr;
252 static int bcm2708_ser_getc(void)
254 if ((*(volatile uint32_t *)(PL011_0_BASE + PL011_FR) & PL011_FR_RXFE) == 0)
255 return (int)*(volatile uint32_t *)(PL011_0_BASE + PL011_DR);
257 return -1;
260 static IPTR bcm2708_probe(struct ARM_Implementation *krnARMImpl, struct TagItem *msg)
262 BOOL bcm2708found = FALSE;
263 void *bootPutC = NULL;
265 while(msg->ti_Tag != TAG_DONE)
267 switch (msg->ti_Tag)
269 case KRN_Platform:
270 if (msg->ti_Data == 0xc42)
271 bcm2708found = TRUE;
272 break;
273 case KRN_FuncPutC:
274 bootPutC = (void *)msg->ti_Data;
275 break;
277 msg++;
280 if (!bcm2708found)
281 return FALSE;
283 if (krnARMImpl->ARMI_Family == 7) /* bcm2836 uses armv7 */
284 krnARMImpl->ARMI_PeripheralBase = (APTR)BCM2836_PERIPHYSBASE;
285 else
286 krnARMImpl->ARMI_PeripheralBase = (APTR)BCM2835_PERIPHYSBASE;
288 krnARMImpl->ARMI_GetTime = &bcm2807_get_time;
289 krnARMImpl->ARMI_InitTimer = &bcm2708_init_gputimer;
290 krnARMImpl->ARMI_LED_Toggle = &bcm2708_toggle_led;
292 krnARMImpl->ARMI_SerPutChar = &bcm2708_ser_putc;
293 krnARMImpl->ARMI_SerGetChar = &bcm2708_ser_getc;
294 if ((krnARMImpl->ARMI_PutChar = bootPutC) != NULL)
295 krnARMImpl->ARMI_PutChar(0xFF); // Clear the display
297 krnARMImpl->ARMI_IRQInit = &bcm2807_irq_init;
298 krnARMImpl->ARMI_IRQEnable = &bcm2807_irq_enable;
299 krnARMImpl->ARMI_IRQDisable = &bcm2807_irq_disable;
300 krnARMImpl->ARMI_IRQProcess = &bcm2807_irq_process;
302 krnARMImpl->ARMI_Init = &bcm2708_init;
304 return TRUE;
307 ADD2SET(bcm2708_probe, ARMPLATFORMS, 0);