ip32-irq.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:14k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Code to handle IP32 IRQs
  3.  *
  4.  * This file is subject to the terms and conditions of the GNU General Public
  5.  * License.  See the file "COPYING" in the main directory of this archive
  6.  * for more details.
  7.  *
  8.  * Copyright (C) 2000 Harald Koerfgen
  9.  * Copyright (C) 2001 Keith M Wesolowski
  10.  */
  11. #include <linux/init.h>
  12. #include <linux/kernel_stat.h>
  13. #include <linux/types.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/irq.h>
  16. #include <linux/bitops.h>
  17. #include <asm/bitops.h>
  18. #include <asm/mipsregs.h>
  19. #include <asm/system.h>
  20. #include <asm/ip32/ip32_ints.h>
  21. #include <asm/ip32/crime.h>
  22. #include <asm/ip32/mace.h>
  23. #include <asm/signal.h>
  24. #undef DEBUG_IRQ
  25. #ifdef DEBUG_IRQ
  26. #define DBG(x...) printk(x)
  27. #else
  28. #define DBG(x...)
  29. #endif
  30. /* O2 irq map
  31.  *
  32.  * IP0 -> software (ignored)
  33.  * IP1 -> software (ignored)
  34.  * IP2 -> (irq0) C crime 1.1 all interrupts; crime 1.5 ???
  35.  * IP3 -> (irq1) X unknown
  36.  * IP4 -> (irq2) X unknown
  37.  * IP5 -> (irq3) X unknown
  38.  * IP6 -> (irq4) X unknown
  39.  * IP7 -> (irq5) 0 CPU count/compare timer (system timer)
  40.  *
  41.  * crime: (C)
  42.  *
  43.  * CRIME_INT_STAT 31:0:
  44.  *
  45.  * 0 -> 1 Video in 1
  46.  * 1 -> 2 Video in 2
  47.  * 2 -> 3 Video out
  48.  * 3 -> 4 Mace ethernet
  49.  * 4 -> S  SuperIO sub-interrupt
  50.  * 5 -> M  Miscellaneous sub-interrupt
  51.  * 6 -> A  Audio sub-interrupt
  52.  * 7 -> 8  PCI bridge errors
  53.  * 8 -> 9  PCI SCSI aic7xxx 0
  54.  * 9 -> 10  PCI SCSI aic7xxx 1
  55.  * 10 -> 11 PCI slot 0
  56.  * 11 -> 12 unused (PCI slot 1)
  57.  * 12 -> 13 unused (PCI slot 2)
  58.  * 13 -> 14 unused (PCI shared 0)
  59.  * 14 -> 15 unused (PCI shared 1)
  60.  * 15 -> 16 unused (PCI shared 2)
  61.  * 16 -> 17 GBE0 (E)
  62.  * 17 -> 18 GBE1 (E)
  63.  * 18 -> 19 GBE2 (E)
  64.  * 19 -> 20 GBE3 (E)
  65.  * 20 -> 21 CPU errors
  66.  * 21 -> 22 Memory errors
  67.  * 22 -> 23 RE empty edge (E)
  68.  * 23 -> 24 RE full edge (E)
  69.  * 24 -> 25 RE idle edge (E)
  70.  * 25 -> 26 RE empty level
  71.  * 26 -> 27 RE full level
  72.  * 27 -> 28 RE idle level
  73.  * 28 -> 29  unused (software 0) (E)
  74.  * 29 -> 30  unused (software 1) (E)
  75.  * 30 -> 31  unused (software 2) - crime 1.5 CPU SysCorError (E)
  76.  * 31 -> 32 VICE
  77.  *
  78.  * S, M, A: Use the MACE ISA interrupt register
  79.  * MACE_ISA_INT_STAT 31:0
  80.  *
  81.  * 0-7 -> 33-40 Audio
  82.  * 8 -> 41 RTC
  83.  * 9 -> 42 Keyboard
  84.  * 10 -> X Keyboard polled
  85.  * 11 -> 44 Mouse
  86.  * 12 -> X Mouse polled
  87.  * 13-15 -> 46-48 Count/compare timers
  88.  * 16-19 -> 49-52 Parallel (16 E)
  89.  * 20-25 -> 53-58 Serial 1 (22 E)
  90.  * 26-31 -> 59-64 Serial 2 (28 E)
  91.  *
  92.  * Note that this means IRQs 5-7, 43, and 45 do not exist.  This is a
  93.  * different IRQ map than IRIX uses, but that's OK as Linux irq handling
  94.  * is quite different anyway.
  95.  */
  96. /* Some initial interrupts to set up */
  97. extern void crime_memerr_intr (unsigned int irq, void *dev_id,
  98.        struct pt_regs *regs);
  99. extern void crime_cpuerr_intr (unsigned int irq, void *dev_id,
  100.        struct pt_regs *regs);
  101. struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT,
  102.        0, "CRIME memory error", NULL,
  103.        NULL };
  104. struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT,
  105.        0, "CRIME CPU error", NULL,
  106.        NULL };
  107. unsigned long spurious_count = 0;
  108. extern void ip32_handle_int (void);
  109. extern void do_IRQ (unsigned int irq, struct pt_regs *regs);
  110. /* For interrupts wired from a single device to the CPU.  Only the clock
  111.  * uses this it seems, which is IRQ 0 and IP7.
  112.  */
  113. static void enable_cpu_irq (unsigned int irq)
  114. {
  115. set_cp0_status (STATUSF_IP7);
  116. }
  117. static unsigned int startup_cpu_irq (unsigned int irq) {
  118. enable_cpu_irq (irq);
  119. return 0;
  120. }
  121. static void disable_cpu_irq (unsigned int irq)
  122. {
  123. clear_cp0_status (STATUSF_IP7);
  124. }
  125. static void end_cpu_irq (unsigned int irq)
  126. {
  127. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  128. enable_cpu_irq (irq);
  129. }
  130. #define shutdown_cpu_irq disable_cpu_irq
  131. #define mask_and_ack_cpu_irq disable_cpu_irq
  132. static struct hw_interrupt_type ip32_cpu_interrupt = {
  133. "IP32 CPU",
  134. startup_cpu_irq,
  135. shutdown_cpu_irq,
  136. enable_cpu_irq,
  137. disable_cpu_irq,
  138. mask_and_ack_cpu_irq,
  139. end_cpu_irq,
  140. NULL
  141. };
  142. /*
  143.  * This is for pure CRIME interrupts - ie not MACE.  The advantage?
  144.  * We get to split the register in half and do faster lookups.
  145.  */
  146. static void enable_crime_irq (unsigned int irq)
  147. {
  148. u64 crime_mask;
  149. unsigned long flags;
  150. save_and_cli (flags);
  151. crime_mask = crime_read_64 (CRIME_INT_MASK);
  152. crime_mask |= 1 << (irq - 1);
  153. crime_write_64 (CRIME_INT_MASK, crime_mask);
  154. restore_flags (flags);
  155. }
  156. static unsigned int startup_crime_irq (unsigned int irq)
  157. {
  158. enable_crime_irq (irq);
  159. return 0; /* This is probably not right; we could have pending irqs */
  160. }
  161. static void disable_crime_irq (unsigned int irq)
  162. {
  163. u64 crime_mask;
  164. unsigned long flags;
  165. save_and_cli (flags);
  166. crime_mask = crime_read_64 (CRIME_INT_MASK);
  167. crime_mask &= ~(1 << (irq - 1));
  168. crime_write_64 (CRIME_INT_MASK, crime_mask);
  169. restore_flags (flags);
  170. }
  171. static void mask_and_ack_crime_irq (unsigned int irq)
  172. {
  173. u64 crime_mask;
  174. unsigned long flags;
  175. /* Edge triggered interrupts must be cleared. */
  176. if ((irq <= CRIME_GBE0_IRQ && irq >= CRIME_GBE3_IRQ)
  177.     || (irq <= CRIME_RE_EMPTY_E_IRQ && irq >= CRIME_RE_IDLE_E_IRQ)
  178.     || (irq <= CRIME_SOFT0_IRQ && irq >= CRIME_SOFT2_IRQ)) {
  179. save_and_cli (flags);
  180. crime_mask = crime_read_64 (CRIME_HARD_INT);
  181. crime_mask &= ~(1 << (irq - 1));
  182. crime_write_64 (CRIME_HARD_INT, crime_mask);
  183. restore_flags (flags);
  184. }
  185. disable_crime_irq (irq);
  186. }
  187. static void end_crime_irq (unsigned int irq)
  188. {
  189. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  190. enable_crime_irq (irq);
  191. }
  192. #define shutdown_crime_irq disable_crime_irq
  193. static struct hw_interrupt_type ip32_crime_interrupt = {
  194. "IP32 CRIME",
  195. startup_crime_irq,
  196. shutdown_crime_irq,
  197. enable_crime_irq,
  198. disable_crime_irq,
  199. mask_and_ack_crime_irq,
  200. end_crime_irq,
  201. NULL
  202. };
  203. /* This is for MACE PCI interrupts.  We can decrease bus traffic by masking
  204.  * as close to the source as possible.  This also means we can take the
  205.  * next chunk of the CRIME register in one piece.
  206.  */
  207. static void enable_macepci_irq (unsigned int irq)
  208. {
  209. u32 mace_mask;
  210. u64 crime_mask;
  211. unsigned long flags;
  212. save_and_cli (flags);
  213. mace_mask = mace_read_32 (MACEPCI_CONTROL);
  214. mace_mask |= MACEPCI_CONTROL_INT (irq - 9);
  215. mace_write_32 (MACEPCI_CONTROL, mace_mask);
  216. /* In case the CRIME interrupt isn't enabled, we must enable it;
  217.  * however, we never disable interrupts at that level.
  218.  */
  219. crime_mask = crime_read_64 (CRIME_INT_MASK);
  220. crime_mask |= 1 << (irq - 1);
  221. crime_write_64 (CRIME_INT_MASK, crime_mask);
  222. restore_flags (flags);
  223. }
  224. static unsigned int startup_macepci_irq (unsigned int irq) {
  225. enable_macepci_irq (irq);
  226. return 0; /* XXX */
  227. }
  228. static void disable_macepci_irq (unsigned int irq)
  229. {
  230. u32 mace_mask;
  231. unsigned long flags;
  232. save_and_cli (flags);
  233. mace_mask = mace_read_32 (MACEPCI_CONTROL);
  234. mace_mask &= ~MACEPCI_CONTROL_INT (irq - 9);
  235. mace_write_32 (MACEPCI_CONTROL, mace_mask);
  236. restore_flags (flags);
  237. }
  238. static void end_macepci_irq (unsigned int irq)
  239. {
  240. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  241. enable_macepci_irq (irq);
  242. }
  243. #define shutdown_macepci_irq disable_macepci_irq
  244. #define mask_and_ack_macepci_irq disable_macepci_irq
  245. static struct hw_interrupt_type ip32_macepci_interrupt = {
  246. "IP32 MACE PCI",
  247. startup_macepci_irq,
  248. shutdown_macepci_irq,
  249. enable_macepci_irq,
  250. disable_macepci_irq,
  251. mask_and_ack_macepci_irq,
  252. end_macepci_irq,
  253. NULL
  254. };
  255. /* This is used for MACE ISA interrupts.  That means bits 4-6 in the
  256.  * CRIME register.
  257.  */
  258. static void enable_maceisa_irq (unsigned int irq)
  259. {
  260. u64 crime_mask;
  261. u32 mace_mask;
  262. unsigned int crime_int = 0;
  263. unsigned long flags;
  264. DBG ("maceisa enable: %un", irq);
  265. switch (irq) {
  266. case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ:
  267. crime_int = MACE_AUDIO_INT;
  268. break;
  269. case MACEISA_RTC_IRQ ... MACEISA_TIMER2_IRQ:
  270. crime_int = MACE_MISC_INT;
  271. break;
  272. case MACEISA_PARALLEL_IRQ ... MACEISA_SERIAL2_RDMAOR_IRQ:
  273. crime_int = MACE_SUPERIO_INT;
  274. break;
  275. }
  276. DBG ("crime_int %016lx enabledn", crime_int);
  277. save_and_cli (flags);
  278. crime_mask = crime_read_64 (CRIME_INT_MASK);
  279. crime_mask |= crime_int;
  280. crime_write_64 (CRIME_INT_MASK, crime_mask);
  281. mace_mask = mace_read_32 (MACEISA_INT_MASK);
  282. mace_mask |= 1 << (irq - 33);
  283. mace_write_32 (MACEISA_INT_MASK, mace_mask);
  284. restore_flags (flags);
  285. }
  286. static unsigned int startup_maceisa_irq (unsigned int irq) {
  287. enable_maceisa_irq (irq);
  288. return 0;
  289. }
  290. static void disable_maceisa_irq (unsigned int irq)
  291. {
  292. u32 mace_mask;
  293. unsigned long flags;
  294. save_and_cli (flags);
  295. mace_mask = mace_read_32 (MACEISA_INT_MASK);
  296. mace_mask &= ~(1 << (irq - 33));
  297. mace_write_32 (MACEISA_INT_MASK, mace_mask);
  298. restore_flags (flags);
  299. }
  300. static void mask_and_ack_maceisa_irq (unsigned int irq)
  301. {
  302. u32 mace_mask;
  303. unsigned long flags;
  304. switch (irq) {
  305. case MACEISA_PARALLEL_IRQ:
  306. case MACEISA_SERIAL1_TDMAPR_IRQ:
  307. case MACEISA_SERIAL2_TDMAPR_IRQ:
  308. save_and_cli (flags);
  309. mace_mask = mace_read_32 (MACEISA_INT_STAT);
  310. mace_mask &= ~(1 << (irq - 33));
  311. mace_write_32 (MACEISA_INT_STAT, mace_mask);
  312. restore_flags (flags);
  313. break;
  314. }
  315. disable_maceisa_irq (irq);
  316. }
  317. static void end_maceisa_irq (unsigned irq)
  318. {
  319. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  320. enable_maceisa_irq (irq);
  321. }
  322. #define shutdown_maceisa_irq disable_maceisa_irq
  323. static struct hw_interrupt_type ip32_maceisa_interrupt = {
  324. "IP32 MACE ISA",
  325. startup_maceisa_irq,
  326. shutdown_maceisa_irq,
  327. enable_maceisa_irq,
  328. disable_maceisa_irq,
  329. mask_and_ack_maceisa_irq,
  330. end_maceisa_irq,
  331. NULL
  332. };
  333. /* This is used for regular non-ISA, non-PCI MACE interrupts.  That means
  334.  * bits 0-3 and 7 in the CRIME register.
  335.  */
  336. static void enable_mace_irq (unsigned int irq)
  337. {
  338. u64 crime_mask;
  339. unsigned long flags;
  340. save_and_cli (flags);
  341. crime_mask = crime_read_64 (CRIME_INT_MASK);
  342. crime_mask |= 1 << (irq - 1);
  343. crime_write_64 (CRIME_INT_MASK, crime_mask);
  344. restore_flags (flags);
  345. }
  346. static unsigned int startup_mace_irq (unsigned int irq)
  347. {
  348. enable_mace_irq (irq);
  349. return 0;
  350. }
  351. static void disable_mace_irq (unsigned int irq)
  352. {
  353. u64 crime_mask;
  354. unsigned long flags;
  355. save_and_cli (flags);
  356. crime_mask = crime_read_64 (CRIME_INT_MASK);
  357. crime_mask &= ~(1 << (irq - 1));
  358. crime_write_64 (CRIME_INT_MASK, crime_mask);
  359. restore_flags (flags);
  360. }
  361. static void end_mace_irq (unsigned int irq)
  362. {
  363. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  364. enable_mace_irq (irq);
  365. }
  366. #define shutdown_mace_irq disable_mace_irq
  367. #define mask_and_ack_mace_irq disable_mace_irq
  368. static struct hw_interrupt_type ip32_mace_interrupt = {
  369. "IP32 MACE",
  370. startup_mace_irq,
  371. shutdown_mace_irq,
  372. enable_mace_irq,
  373. disable_mace_irq,
  374. mask_and_ack_mace_irq,
  375. end_mace_irq,
  376. NULL
  377. };
  378. static void ip32_unknown_interrupt (struct pt_regs *regs)
  379. {
  380. u64 crime;
  381. u32 mace;
  382. printk ("Unknown interrupt occurred!n");
  383. printk ("cp0_status: %08xtcp0_cause: %08xn",
  384. read_32bit_cp0_register (CP0_STATUS),
  385. read_32bit_cp0_register (CP0_CAUSE));
  386. crime = crime_read_64 (CRIME_INT_MASK);
  387. printk ("CRIME interrupt mask: %016lxn", crime);
  388. crime = crime_read_64 (CRIME_INT_STAT);
  389. printk ("CRIME interrupt status: %016lxn", crime);
  390. crime = crime_read_64 (CRIME_HARD_INT);
  391. printk ("CRIME hardware interrupt register: %016lxn", crime);
  392. mace = mace_read_32 (MACEISA_INT_MASK);
  393. printk ("MACE ISA interrupt mask: %08xn", mace);
  394. mace = mace_read_32 (MACEISA_INT_STAT);
  395. printk ("MACE ISA interrupt status: %08xn", mace);
  396. mace = mace_read_32 (MACEPCI_CONTROL);
  397. printk ("MACE PCI control register: %08xn", mace);
  398. printk ("Register dump:n");
  399. show_regs (regs);
  400. printk ("Please mail this report to linux-mips@oss.sgi.comn");
  401. printk ("Spinning...");
  402. while (1) ;
  403. }
  404. void __init ip32_irq_init(void)
  405. {
  406. unsigned int irq;
  407. extern void init_generic_irq (void);
  408. /* Install our interrupt handler, then clear and disable all
  409.  * CRIME and MACE interrupts.
  410.  */
  411. crime_write_64 (CRIME_INT_MASK, 0);
  412. crime_write_64 (CRIME_HARD_INT, 0);
  413. crime_write_64 (CRIME_SOFT_INT, 0);
  414. mace_write_32 (MACEISA_INT_STAT, 0);
  415. mace_write_32 (MACEISA_INT_MASK, 0);
  416. set_except_vector(0, ip32_handle_int);
  417. init_generic_irq ();
  418. for (irq = 0; irq <= IP32_IRQ_MAX; irq++) {
  419. hw_irq_controller *controller;
  420. if (irq == CLOCK_IRQ)
  421. controller = &ip32_cpu_interrupt;
  422. else if (irq <= MACE_PCI_BRIDGE_IRQ && irq >= MACE_VID_IN1_IRQ)
  423. controller = &ip32_mace_interrupt;
  424. else if (irq <= MACEPCI_SHARED2_IRQ && irq >= MACEPCI_SCSI0_IRQ)
  425. controller = &ip32_macepci_interrupt;
  426. else if (irq <= CRIME_VICE_IRQ && irq >= CRIME_GBE0_IRQ)
  427. controller = &ip32_crime_interrupt;
  428. else
  429. controller = &ip32_maceisa_interrupt;
  430. irq_desc[irq].status = IRQ_DISABLED;
  431. irq_desc[irq].action = 0;
  432. irq_desc[irq].depth = 0;
  433. irq_desc[irq].handler = controller;
  434. }
  435. setup_irq (CRIME_MEMERR_IRQ, &memerr_irq);
  436. setup_irq (CRIME_CPUERR_IRQ, &cpuerr_irq);
  437. }
  438. /* CRIME 1.1 appears to deliver all interrupts to this one pin. */
  439. void ip32_irq0 (struct pt_regs *regs)
  440. {
  441. u64 crime_int = crime_read_64 (CRIME_INT_STAT);
  442. int irq = 0;
  443. if (crime_int & CRIME_MACE_INT_MASK) {
  444. crime_int &= CRIME_MACE_INT_MASK;
  445. irq = ffs (crime_int);
  446. } else if (crime_int & CRIME_MACEISA_INT_MASK) {
  447. u32 mace_int;
  448. mace_int = mace_read_32 (MACEISA_INT_STAT);
  449. if (mace_int == 0)
  450. irq = 0;
  451. else
  452. irq = ffs (mace_int) + 32;
  453. } else if (crime_int & CRIME_MACEPCI_INT_MASK) {
  454. crime_int &= CRIME_MACEPCI_INT_MASK;
  455. crime_int >>= 8;
  456. irq = ffs (crime_int) + 8;
  457. } else if (crime_int & 0xffff0000) {
  458. crime_int >>= 16;
  459. irq = ffs (crime_int) + 16;
  460. }
  461. if (irq == 0)
  462. ip32_unknown_interrupt (regs);
  463. DBG ("*irq %u*n", irq);
  464. do_IRQ (irq, regs);
  465. }
  466. void ip32_irq1 (struct pt_regs *regs)
  467. {
  468. ip32_unknown_interrupt (regs);
  469. }
  470. void ip32_irq2 (struct pt_regs *regs)
  471. {
  472. ip32_unknown_interrupt (regs);
  473. }
  474. void ip32_irq3 (struct pt_regs *regs)
  475. {
  476. ip32_unknown_interrupt (regs);
  477. }
  478. void ip32_irq4 (struct pt_regs *regs)
  479. {
  480. ip32_unknown_interrupt (regs);
  481. }
  482. void ip32_irq5 (struct pt_regs *regs)
  483. {
  484. do_IRQ (CLOCK_IRQ, regs);
  485. }