xref: /haiku/src/system/kernel/arch/arm/soc_pxa.cpp (revision f638102196d8255c37eb0f6727c13e42cefa8a88)
1 #include "soc_pxa.h"
2 
3 /* PXA Interrupt Controller Registers */
4 #define PXA_ICIP	0x00
5 #define PXA_ICMR	0x01
6 #define PXA_ICFP	0x03
7 #define PXA_ICMR2	0x28
8 
9 void
10 PXAInterruptController::EnableInterrupt(int irq)
11 {
12 	if (irq <= 31) {
13 		fRegBase[PXA_ICMR] |= 1 << irq;
14 		return;
15 	}
16 
17 	fRegBase[PXA_ICMR2] |= 1 << (irq - 32);
18 }
19 
20 
21 void
22 PXAInterruptController::DisableInterrupt(int irq)
23 {
24 	if (irq <= 31) {
25 		fRegBase[PXA_ICMR] &= ~(1 << irq);
26 		return;
27 	}
28 
29 	fRegBase[PXA_ICMR2] &= ~(1 << (irq - 32));
30 }
31 
32 
33 void
34 PXAInterruptController::HandleInterrupt()
35 {
36 	for (int i=0; i < 32; i++) {
37 		if (fRegBase[PXA_ICIP] & (1 << i))
38 			int_io_interrupt_handler(i, true);
39 	}
40 }
41 
42 
43 #if 0
44 PXAInterruptController::PXAInterruptController(fdt_module_info *fdt, fdt_device_node node)
45 	: InterruptController(fdt, node) {
46 	fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase);
47 	if (fRegArea < 0)
48 		panic("PXAInterruptController: cannot map registers!");
49 
50 	fRegBase[PXA_ICMR] = 0;
51 	fRegBase[PXA_ICMR2] = 0;
52 }
53 #endif
54 
55 #define PXA_TIMERS_INTERRUPT	7 /* OST_4_11 */
56 
57 #define PXA_OSSR	0x05
58 #define PXA_OIER	0x07
59 #define PXA_OSCR4	0x10
60 #define PXA_OSCR5	0x11
61 #define PXA_OSMR4	0x20
62 #define PXA_OSMR5	0x21
63 #define PXA_OMCR4	0x30
64 #define PXA_OMCR5	0x31
65 
66 #define PXA_RES_S	(3 << 0)
67 #define PXA_RES_MS	(1 << 1)
68 #define PXA_RES_US	(1 << 2)
69 
70 #define US2S(bt)	((bt) / 1000000ULL)
71 #define US2MS(bt)	((bt) / 1000ULL)
72 
73 void
74 PXATimer::SetTimeout(bigtime_t timeout)
75 {
76 	uint32 val = timeout & UINT_MAX;
77 	uint32 res = PXA_RES_US;
78 
79 	if (timeout & ~UINT_MAX) {
80 		// Does not fit, so scale resolution down to milliseconds
81 		if (US2MS(timeout) & ~UINT_MAX) {
82 			// Still does not fit, scale down to seconds as last ditch attempt
83 			val = US2S(timeout) & UINT_MAX;
84 			res = PXA_RES_S;
85 		} else {
86 			// Fits in millisecond resolution
87 			val = US2MS(timeout) & UINT_MAX;
88 			res = PXA_RES_MS;
89 		}
90 	}
91 
92 	dprintf("arch_timer_set_hardware_timer(val=%lu, res=%lu)\n", val, res);
93 	fRegBase[PXA_OIER] |= (1 << 4);
94 	fRegBase[PXA_OMCR4] = res;
95 	fRegBase[PXA_OSMR4] = val;
96 	fRegBase[PXA_OSCR4] = 0; // start counting from 0 again
97 }
98 
99 void
100 PXATimer::Clear()
101 {
102 	fRegBase[PXA_OMCR4] = 0; // disable our timer
103 	fRegBase[PXA_OIER] &= ~(1 << 4);
104 }
105 
106 
107 bigtime_t
108 PXATimer::Time()
109 {
110 	if (fRegArea < 0)
111 		return 0;
112 
113 	return (fRegBase != NULL) ?
114 		fSystemTime + fRegBase[PXA_OSCR5] :
115 		0ULL;
116 }
117 
118 
119 int32
120 PXATimer::_InterruptWrapper(void *data)
121 {
122 	return ((PXATimer*)data)->HandleInterrupt();
123 }
124 
125 
126 int32
127 PXATimer::HandleInterrupt()
128 {
129 	if (fRegBase[PXA_OSSR] & (1 << 4)) {
130 		fRegBase[PXA_OSSR] |= (1 << 4);
131 		return timer_interrupt();
132 	}
133 
134 	if (fRegBase[PXA_OSSR]  & (1 << 5)) {
135 		fRegBase[PXA_OSSR] |= (1 << 5);
136 		fSystemTime += UINT_MAX + 1ULL;
137 	}
138 
139 	return B_HANDLED_INTERRUPT;
140 }
141 
142 
143 #if 0
144 PXATimer::PXATimer(fdt_module_info *fdt, fdt_device_node node)
145 	: HardwareTimer(fdt, node)
146 {
147 	fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase);
148 	if (fRegArea < 0)
149 		panic("Cannot map PXATimer registers!");
150 
151 	fRegBase[PXA_OIER] |= (1 << 5); // enable timekeeping timer
152 	fRegBase[PXA_OMCR5] = PXA_RES_US | (1 << 7);
153 	fRegBase[PXA_OSMR5] = UINT_MAX;
154 	fRegBase[PXA_OSCR5] = 0;
155 
156 	install_io_interrupt_handler(PXA_TIMERS_INTERRUPT, &PXATimer::_InterruptWrapper, NULL, 0);
157 }
158 #endif
159