2 Copyright © 2015, The AROS Development Team. All rights reserved.
6 #include <aros/kernel.h>
7 #include <aros/symbolsets.h>
9 #include <proto/exec.h>
12 #include <hardware/intbits.h>
14 #include "kernel_intern.h"
15 #include "kernel_base.h"
16 #include "kernel_cpu.h"
17 #include "kernel_interrupts.h"
18 #include "kernel_intr.h"
20 static void bcm2708_init(void)
25 static void bcm2708_toggle_led(int LED
, int state
)
27 if (__arm_periiobase
== BCM2836_PERIPHYSBASE
)
30 IPTR gpiofunc
= GPCLR1
;
32 if (LED
== ARM_LED_ACTIVITY
)
35 if (state
== ARM_LED_ON
)
38 *(volatile unsigned int *)gpiofunc
= (1 << (pin
-32));
42 // RasPi 1 only allows us to toggle the activity LED
44 *(volatile unsigned int *)GPCLR0
= (1 << 16);
46 *(volatile unsigned int *)GPSET0
= (1 << 16);
50 static void bcm2708_gputimer_handler(unsigned int timerno
, void *unused1
)
54 D(bug("[KRN:BCM2708] %s(%d)\n", __PRETTY_FUNCTION__
, timerno
));
56 /* Aknowledge our timer interrupt */
57 cs
= *((volatile unsigned int *)(SYSTIMER_CS
));
58 cs
&= ~ (1 << timerno
);
59 *((volatile unsigned int *)(SYSTIMER_CS
)) = cs
;
61 /* Signal the Exec VBlankServer */
62 if (SysBase
&& (SysBase
->IDNestCnt
< 0)) {
63 core_Cause(INTB_VERTB
, 1L << INTB_VERTB
);
66 /* Refresh our timer interrupt */
67 stc
= *((volatile unsigned int *)(SYSTIMER_CLO
));
68 stc
+= VBLANK_INTERVAL
;
69 *((volatile unsigned int *)(SYSTIMER_CS
)) = cs
| (1 << timerno
);
70 *((volatile unsigned int *)(SYSTIMER_C0
+ (timerno
* 4))) = stc
;
72 D(bug("[BCM2708] %s: Done..\n", __PRETTY_FUNCTION__
));
75 static bcm2708_init_gputimer(struct KernelBase
*KernelBase
)
77 struct IntrNode
*GPUTimerHandle
;
80 D(bug("[KRN:BCM2708] %s(%012p)\n", __PRETTY_FUNCTION__
, KernelBase
));
82 if ((GPUTimerHandle
= AllocMem(sizeof(struct IntrNode
), MEMF_PUBLIC
|MEMF_CLEAR
)) != NULL
)
84 D(bug("[KRN:BCM2708] %s: IntrNode @ 0x%p:\n", __PRETTY_FUNCTION__
, GPUTimerHandle
));
85 D(bug("[KRN:BCM2708] %s: Using GPUTimer %d for VBlank\n", __PRETTY_FUNCTION__
, VBLANK_TIMER
));
87 GPUTimerHandle
->in_Handler
= bcm2708_gputimer_handler
;
88 GPUTimerHandle
->in_HandlerData
= VBLANK_TIMER
;
89 GPUTimerHandle
->in_HandlerData2
= KernelBase
;
90 GPUTimerHandle
->in_type
= it_interrupt
;
91 GPUTimerHandle
->in_nr
= IRQ_TIMER0
+ VBLANK_TIMER
;
93 ADDHEAD(&KernelBase
->kb_Interrupts
[IRQ_TIMER0
+ VBLANK_TIMER
], &GPUTimerHandle
->in_Node
);
95 D(bug("[KRN:BCM2708] %s: Enabling Hardware IRQ.. \n", __PRETTY_FUNCTION__
));
97 stc
= *((volatile unsigned int *)(SYSTIMER_CLO
));
98 stc
+= VBLANK_INTERVAL
;
99 *((volatile unsigned int *)(SYSTIMER_CS
)) = (1 << VBLANK_TIMER
);
100 *((volatile unsigned int *)(SYSTIMER_C0
+ (VBLANK_TIMER
* 4))) = stc
;
102 ictl_enable_irq(IRQ_TIMER0
+ VBLANK_TIMER
, KernelBase
);
105 D(bug("[KRN:BCM2708] %s: Done.. \n", __PRETTY_FUNCTION__
));
107 return GPUTimerHandle
;
111 static IPTR
bcm2708_probe(struct ARM_Implementation
*krnARMImpl
, struct TagItem
*msg
)
113 //TODO: really detect if we are running on a broadcom 2835/2836
114 if (krnARMImpl
->ARMI_Family
== 7) /* bcm2836 uses armv7 */
115 __arm_periiobase
= BCM2836_PERIPHYSBASE
;
117 __arm_periiobase
= BCM2835_PERIPHYSBASE
;
119 krnARMImpl
->ARMI_InitTimer
= &bcm2708_init_gputimer
;
120 krnARMImpl
->ARMI_LED_Toggle
= &bcm2708_toggle_led
;
125 ADD2SET(bcm2708_probe
, ARMPLATFORMS
, 0);