2 Copyright © 2015, The AROS Development Team. All rights reserved.
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>
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
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
)
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)
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
);
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
);
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
;
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
))
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
);
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
);
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
)
154 APTR gpiofunc
= GPCLR1
;
156 if (LED
== ARM_LED_ACTIVITY
)
159 if (state
== ARM_LED_ON
)
162 *(volatile unsigned int *)gpiofunc
= (1 << (pin
-32));
166 // RasPi 1 only allows us to toggle the activity LED
168 *(volatile unsigned int *)GPCLR0
= (1 << 16);
170 *(volatile unsigned int *)GPSET0
= (1 << 16);
174 static void bcm2708_gputimer_handler(unsigned int timerno
, void *unused1
)
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
;
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()
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();
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
);
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
)
270 if (msg
->ti_Data
== 0xc42)
274 bootPutC
= (void *)msg
->ti_Data
;
283 if (krnARMImpl
->ARMI_Family
== 7) /* bcm2836 uses armv7 */
284 krnARMImpl
->ARMI_PeripheralBase
= (APTR
)BCM2836_PERIPHYSBASE
;
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
;
307 ADD2SET(bcm2708_probe
, ARMPLATFORMS
, 0);