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