xref: /haiku/src/system/kernel/arch/arm/arch_timer.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
1 /*
2  * Copyright 2007-2012, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  * 		François Revol <revol@free.fr>
7  *              Ithamar R. Adema <ithamar@upgrade-android.com>
8  *
9  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
10  * Distributed under the terms of the NewOS License.
11  */
12 
13 
14 #include <boot/stage2.h>
15 #include <kernel.h>
16 #include <debug.h>
17 
18 #include <timer.h>
19 #include <arch/timer.h>
20 #include <arch/cpu.h>
21 
22 
23 //#define TRACE_ARCH_TIMER
24 #ifdef TRACE_ARCH_TIMER
25 #	define TRACE(x) dprintf x
26 #else
27 #	define TRACE(x) ;
28 #endif
29 
30 
31 #define PXA_TIMERS_PHYS_BASE	0x40A00000
32 #define PXA_TIMERS_SIZE		0x000000C0
33 #define PXA_TIMERS_INTERRUPT	7 /* OST_4_11 */
34 
35 #define PXA_OSSR		0x05
36 #define PXA_OIER		0x07
37 #define PXA_OSCR4		0x10
38 #define PXA_OSMR4		0x20
39 #define PXA_OMCR4		0x30
40 
41 
42 static area_id sPxaTimersArea;
43 static uint32 *sPxaTimersBase;
44 
45 
46 static int32
47 pxa_timer_interrupt(void *data)
48 {
49 	int32 ret = timer_interrupt();
50         sPxaTimersBase[PXA_OSSR] |= (1 << 4);
51 
52         return ret;
53 }
54 
55 
56 void
57 arch_timer_set_hardware_timer(bigtime_t timeout)
58 {
59 	TRACE(("arch_timer_set_hardware_timer(%lld)\n", timeout));
60 
61 	if (sPxaTimersBase) {
62 		sPxaTimersBase[PXA_OIER] |= (1 << 4);
63 		sPxaTimersBase[PXA_OMCR4] = 4; // set to exactly single milisecond resolution
64 		sPxaTimersBase[PXA_OSMR4] = timeout;
65 		sPxaTimersBase[PXA_OSCR4] = 0; // start counting from 0 again
66 	}
67 }
68 
69 
70 void
71 arch_timer_clear_hardware_timer()
72 {
73 	TRACE(("arch_timer_clear_hardware_timer\n"));
74 
75 	if (sPxaTimersBase) {
76 		sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
77 		sPxaTimersBase[PXA_OIER] &= ~(4 << 1);
78 	}
79 }
80 
81 
82 int
83 arch_init_timer(kernel_args *args)
84 {
85 	sPxaTimersArea = map_physical_memory("pxa_timers", PXA_TIMERS_PHYS_BASE,
86 		PXA_TIMERS_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaTimersBase);
87 
88 	if (sPxaTimersArea < 0)
89 		return sPxaTimersArea;
90 
91 	sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
92 
93 	install_io_interrupt_handler(PXA_TIMERS_INTERRUPT, &pxa_timer_interrupt, NULL, 0);
94 
95 	return B_OK;
96 }
97