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 extern void cpu_Register(void);
22 static void bcm2708_init(void)
27 static void bcm2708_toggle_led(int LED
, int state
)
29 if (__arm_periiobase
== BCM2836_PERIPHYSBASE
)
32 IPTR gpiofunc
= GPCLR1
;
34 if (LED
== ARM_LED_ACTIVITY
)
37 if (state
== ARM_LED_ON
)
40 *(volatile unsigned int *)gpiofunc
= (1 << (pin
-32));
44 // RasPi 1 only allows us to toggle the activity LED
46 *(volatile unsigned int *)GPCLR0
= (1 << 16);
48 *(volatile unsigned int *)GPSET0
= (1 << 16);
52 static void bcm2708_gputimer_handler(unsigned int timerno
, void *unused1
)
56 D(bug("[KRN:BCM2708] %s(%d)\n", __PRETTY_FUNCTION__
, timerno
));
58 /* Aknowledge our timer interrupt */
59 cs
= *((volatile unsigned int *)(SYSTIMER_CS
));
60 cs
&= ~ (1 << timerno
);
61 *((volatile unsigned int *)(SYSTIMER_CS
)) = cs
;
63 /* Signal the Exec VBlankServer */
64 if (SysBase
&& (SysBase
->IDNestCnt
< 0)) {
65 core_Cause(INTB_VERTB
, 1L << INTB_VERTB
);
68 /* Refresh our timer interrupt */
69 stc
= *((volatile unsigned int *)(SYSTIMER_CLO
));
70 stc
+= VBLANK_INTERVAL
;
71 *((volatile unsigned int *)(SYSTIMER_CS
)) = cs
| (1 << timerno
);
72 *((volatile unsigned int *)(SYSTIMER_C0
+ (timerno
* 4))) = stc
;
74 D(bug("[BCM2708] %s: Done..\n", __PRETTY_FUNCTION__
));
77 static bcm2708_init_gputimer(struct KernelBase
*KernelBase
)
79 struct IntrNode
*GPUTimerHandle
;
82 D(bug("[KRN:BCM2708] %s(%012p)\n", __PRETTY_FUNCTION__
, KernelBase
));
84 if ((GPUTimerHandle
= AllocMem(sizeof(struct IntrNode
), MEMF_PUBLIC
|MEMF_CLEAR
)) != NULL
)
86 D(bug("[KRN:BCM2708] %s: IntrNode @ 0x%p:\n", __PRETTY_FUNCTION__
, GPUTimerHandle
));
87 D(bug("[KRN:BCM2708] %s: Using GPUTimer %d for VBlank\n", __PRETTY_FUNCTION__
, VBLANK_TIMER
));
89 GPUTimerHandle
->in_Handler
= bcm2708_gputimer_handler
;
90 GPUTimerHandle
->in_HandlerData
= VBLANK_TIMER
;
91 GPUTimerHandle
->in_HandlerData2
= KernelBase
;
92 GPUTimerHandle
->in_type
= it_interrupt
;
93 GPUTimerHandle
->in_nr
= IRQ_TIMER0
+ VBLANK_TIMER
;
95 ADDHEAD(&KernelBase
->kb_Interrupts
[IRQ_TIMER0
+ VBLANK_TIMER
], &GPUTimerHandle
->in_Node
);
97 D(bug("[KRN:BCM2708] %s: Enabling Hardware IRQ.. \n", __PRETTY_FUNCTION__
));
99 stc
= *((volatile unsigned int *)(SYSTIMER_CLO
));
100 stc
+= VBLANK_INTERVAL
;
101 *((volatile unsigned int *)(SYSTIMER_CS
)) = (1 << VBLANK_TIMER
);
102 *((volatile unsigned int *)(SYSTIMER_C0
+ (VBLANK_TIMER
* 4))) = stc
;
104 ictl_enable_irq(IRQ_TIMER0
+ VBLANK_TIMER
, KernelBase
);
107 D(bug("[KRN:BCM2708] %s: Done.. \n", __PRETTY_FUNCTION__
));
109 return GPUTimerHandle
;
113 static IPTR
bcm2708_probe(struct ARM_Implementation
*krnARMImpl
, struct TagItem
*msg
)
115 //TODO: really detect if we are running on a broadcom 2835/2836
116 if (krnARMImpl
->ARMI_Family
== 7) /* bcm2836 uses armv7 */
117 __arm_periiobase
= BCM2836_PERIPHYSBASE
;
119 __arm_periiobase
= BCM2835_PERIPHYSBASE
;
121 krnARMImpl
->ARMI_InitTimer
= &bcm2708_init_gputimer
;
122 krnARMImpl
->ARMI_LED_Toggle
= &bcm2708_toggle_led
;
124 if (__arm_periiobase
== BCM2836_PERIPHYSBASE
)
127 for (core
= 1; core
< 3; core
++)
129 *((volatile unsigned int *)(0x4000008C + (0x10 * core
))) = cpu_Register
;
132 if (krnARMImpl
->ARMI_Delay
)
133 krnARMImpl
->ARMI_Delay(1500);
139 ADD2SET(bcm2708_probe
, ARMPLATFORMS
, 0);