1 #include "soc_omap3.h" 2 3 enum { 4 INTCPS_REVISION = 0, 5 INTCPS_SYSCONFIG = 4, 6 INTCPS_SYSSTATUS, 7 INTCPS_SIR_IRQ = 16, 8 INTCPS_SIR_FIQ = 17, 9 INTCPS_CONTROL = 18, 10 INTCPS_PROTECTION = 19, 11 INTCPS_IDLE = 20, 12 INTCPS_IRQ_PRIORITY = 24, 13 INTCPS_FIQ_PRIORITY = 25, 14 INTCPS_THRESHOLD = 26, 15 INTCPS_ITRn = 32, 16 INTCPS_MIRn = 33, 17 INTCPS_MIR_CLEARn = 34, 18 INTCPS_MIR_SETn = 35, 19 INTCPS_ISR_SETn = 36, 20 INTCPS_ISR_CLEARn = 37, 21 INTCPS_PENDING_IRQn = 38, 22 INTCPS_PENDING_FIQn = 39, 23 INTCPS_ILRm = 40, 24 }; 25 26 27 void 28 OMAP3InterruptController::EnableInterrupt(int irq) 29 { 30 uint32 bit = irq % 32, bank = irq / 32; 31 fRegBase[INTCPS_MIR_CLEARn + (8 * bank)] = 1 << bit; 32 } 33 34 35 void 36 OMAP3InterruptController::DisableInterrupt(int irq) 37 { 38 uint32 bit = irq % 32, bank = irq / 32; 39 fRegBase[INTCPS_MIR_SETn + (8 * bank)] = 1 << bit; 40 } 41 42 43 void 44 OMAP3InterruptController::HandleInterrupt() 45 { 46 bool handledIRQ = false; 47 int irqnr = 0; 48 49 do { 50 for (uint32 i=0; i < fNumPending; i++) { 51 irqnr = fRegBase[INTCPS_PENDING_IRQn + (8 * i)]; 52 if (irqnr) 53 break; 54 } 55 56 if (!irqnr) 57 break; 58 59 irqnr = fRegBase[INTCPS_SIR_IRQ]; 60 irqnr &= 0x7f; /* ACTIVEIRQ */ 61 62 if (irqnr) { 63 int_io_interrupt_handler(irqnr, true); 64 handledIRQ = true; 65 } 66 } while(irqnr); 67 68 // If IRQ got cleared before we could handle it, simply 69 // ack it. 70 if (!handledIRQ) 71 fRegBase[INTCPS_CONTROL] = 1; 72 } 73 74 75 void 76 OMAP3InterruptController::SoftReset() 77 { 78 uint32 tmp = fRegBase[INTCPS_REVISION] & 0xff; 79 80 dprintf("OMAP: INTC found at 0x%p (rev %ld.%ld)\n", 81 fRegBase, tmp >> 4, tmp & 0xf); 82 83 tmp = fRegBase[INTCPS_SYSCONFIG]; 84 tmp |= 1 << 1; /* soft reset */ 85 fRegBase[INTCPS_SYSCONFIG] = tmp; 86 87 while (!(fRegBase[INTCPS_SYSSTATUS] & 0x1)) 88 /* Wait for reset to complete */; 89 90 /* Enable autoidle */ 91 fRegBase[INTCPS_SYSCONFIG] = 1; 92 } 93 94 95 #if 0 96 OMAP3InterruptController::OMAP3InterruptController(fdt_module_info *fdt, fdt_device_node node) 97 : InterruptController(fdt, node), 98 fNumPending(3) 99 { 100 fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase); 101 if (fRegArea < 0) 102 panic("OMAP3InterruptController: cannot map registers!"); 103 104 SoftReset(); 105 106 // Enable protection (MPU registers only available in privileged mode) 107 fRegBase[INTCPS_PROTECTION] |= 1; 108 } 109 #endif 110 111 112 enum { 113 TIDR = 0, 114 TIOCP_CFG = 4, 115 TISTAT, 116 TISR, 117 TIER, 118 TWER, 119 TCLR, 120 TCRR, 121 TLDR, 122 TTGR, 123 TWPS, 124 TMAR, 125 TCAR1, 126 TSICR, 127 TCAR2, 128 TPIR, 129 TNIR, 130 TCVR, 131 TOCR, 132 TOWR, 133 }; 134 135 int32 136 OMAP3Timer::_InterruptWrapper(void *data) 137 { 138 return ((OMAP3Timer*)data)->HandleInterrupt(); 139 } 140 141 142 int32 143 OMAP3Timer::HandleInterrupt() 144 { 145 uint32 ints = fRegBase[TISR] & 7; 146 147 if (ints & 1) { // Match? 148 dprintf("OMAP3Timer: match!\n"); 149 timer_interrupt(); 150 } else if (ints & 2) { // Overflow? 151 dprintf("OMAP3Timer: overflow!\n"); 152 fSystemTime += UINT_MAX +1; 153 } else if (ints & 4) { // Capture? 154 dprintf("OMAP3Timer: capture!\n"); 155 } 156 157 // clear interrupt 158 fRegBase[TISR] = ints; 159 160 return B_HANDLED_INTERRUPT; 161 } 162 163 164 void 165 OMAP3Timer::SetTimeout(bigtime_t timeout) 166 { 167 fRegBase[TMAR] = fRegBase[TCRR] + timeout / 1000ULL; 168 fRegBase[TIER] |= 1; // Enable match interrupt 169 } 170 171 172 bigtime_t 173 OMAP3Timer::Time() 174 { 175 return fSystemTime + fRegBase[TCRR]; 176 } 177 178 179 void 180 OMAP3Timer::Clear() 181 { 182 fRegBase[TIER] &= ~1; // Disable match interrupt 183 } 184 185 186 #if 0 187 OMAP3Timer::OMAP3Timer(fdt_module_info *fdtModule, fdt_device_node node) 188 : HardwareTimer(fdtModule, node), 189 fSystemTime(0) 190 { 191 fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase); 192 if (fRegArea < 0) 193 panic("Cannot map OMAP3Timer registers!"); 194 195 fInterrupt = fFDT->get_interrupt(node, 0); 196 if (fInterrupt < 0) 197 panic("Cannot get OMAP3Timer interrupt!"); 198 199 uint32 rev = fRegBase[TIDR]; 200 dprintf("OMAP: Found timer @ 0x%p, IRQ %d (rev %ld.%ld)\n", fRegBase, fInterrupt, (rev >> 4) & 0xf, rev & 0xf); 201 202 // Let the timer run (so we can use it as clocksource) 203 fRegBase[TCLR] |= 1; 204 fRegBase[TIER] = 2; // Enable overflow interrupt 205 206 install_io_interrupt_handler(fInterrupt, &OMAP3Timer::_InterruptWrapper, this, 0); 207 } 208 #endif 209