rm200.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /*
  2. * RM200 specific code
  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) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  9. *
  10. * i8259 parts ripped out of arch/mips/kernel/i8259.c
  11. */
  12. #include <linux/delay.h>
  13. #include <linux/init.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/irq.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/serial_8250.h>
  18. #include <linux/io.h>
  19. #include <asm/sni.h>
  20. #include <asm/time.h>
  21. #include <asm/irq_cpu.h>
  22. #define RM200_I8259A_IRQ_BASE 32
  23. #define MEMPORT(_base,_irq) \
  24. { \
  25. .mapbase = _base, \
  26. .irq = _irq, \
  27. .uartclk = 1843200, \
  28. .iotype = UPIO_MEM, \
  29. .flags = UPF_BOOT_AUTOCONF|UPF_IOREMAP, \
  30. }
  31. static struct plat_serial8250_port rm200_data[] = {
  32. MEMPORT(0x160003f8, RM200_I8259A_IRQ_BASE + 4),
  33. MEMPORT(0x160002f8, RM200_I8259A_IRQ_BASE + 3),
  34. { },
  35. };
  36. static struct platform_device rm200_serial8250_device = {
  37. .name = "serial8250",
  38. .id = PLAT8250_DEV_PLATFORM,
  39. .dev = {
  40. .platform_data = rm200_data,
  41. },
  42. };
  43. static struct resource rm200_ds1216_rsrc[] = {
  44. {
  45. .start = 0x1cd41ffc,
  46. .end = 0x1cd41fff,
  47. .flags = IORESOURCE_MEM
  48. }
  49. };
  50. static struct platform_device rm200_ds1216_device = {
  51. .name = "rtc-ds1216",
  52. .num_resources = ARRAY_SIZE(rm200_ds1216_rsrc),
  53. .resource = rm200_ds1216_rsrc
  54. };
  55. static struct resource snirm_82596_rm200_rsrc[] = {
  56. {
  57. .start = 0x18000000,
  58. .end = 0x180fffff,
  59. .flags = IORESOURCE_MEM
  60. },
  61. {
  62. .start = 0x1b000000,
  63. .end = 0x1b000004,
  64. .flags = IORESOURCE_MEM
  65. },
  66. {
  67. .start = 0x1ff00000,
  68. .end = 0x1ff00020,
  69. .flags = IORESOURCE_MEM
  70. },
  71. {
  72. .start = 27,
  73. .end = 27,
  74. .flags = IORESOURCE_IRQ
  75. },
  76. {
  77. .flags = 0x00
  78. }
  79. };
  80. static struct platform_device snirm_82596_rm200_pdev = {
  81. .name = "snirm_82596",
  82. .num_resources = ARRAY_SIZE(snirm_82596_rm200_rsrc),
  83. .resource = snirm_82596_rm200_rsrc
  84. };
  85. static struct resource snirm_53c710_rm200_rsrc[] = {
  86. {
  87. .start = 0x19000000,
  88. .end = 0x190fffff,
  89. .flags = IORESOURCE_MEM
  90. },
  91. {
  92. .start = 26,
  93. .end = 26,
  94. .flags = IORESOURCE_IRQ
  95. }
  96. };
  97. static struct platform_device snirm_53c710_rm200_pdev = {
  98. .name = "snirm_53c710",
  99. .num_resources = ARRAY_SIZE(snirm_53c710_rm200_rsrc),
  100. .resource = snirm_53c710_rm200_rsrc
  101. };
  102. static int __init snirm_setup_devinit(void)
  103. {
  104. if (sni_brd_type == SNI_BRD_RM200) {
  105. platform_device_register(&rm200_serial8250_device);
  106. platform_device_register(&rm200_ds1216_device);
  107. platform_device_register(&snirm_82596_rm200_pdev);
  108. platform_device_register(&snirm_53c710_rm200_pdev);
  109. sni_eisa_root_init();
  110. }
  111. return 0;
  112. }
  113. device_initcall(snirm_setup_devinit);
  114. /*
  115. * RM200 has an ISA and an EISA bus. The iSA bus is only used
  116. * for onboard devices and also has twi i8259 PICs. Since these
  117. * PICs are no accessible via inb/outb the following code uses
  118. * readb/writeb to access them
  119. */
  120. static DEFINE_RAW_SPINLOCK(sni_rm200_i8259A_lock);
  121. #define PIC_CMD 0x00
  122. #define PIC_IMR 0x01
  123. #define PIC_ISR PIC_CMD
  124. #define PIC_POLL PIC_ISR
  125. #define PIC_OCW3 PIC_ISR
  126. /* i8259A PIC related value */
  127. #define PIC_CASCADE_IR 2
  128. #define MASTER_ICW4_DEFAULT 0x01
  129. #define SLAVE_ICW4_DEFAULT 0x01
  130. /*
  131. * This contains the irq mask for both 8259A irq controllers,
  132. */
  133. static unsigned int rm200_cached_irq_mask = 0xffff;
  134. static __iomem u8 *rm200_pic_master;
  135. static __iomem u8 *rm200_pic_slave;
  136. #define cached_master_mask (rm200_cached_irq_mask)
  137. #define cached_slave_mask (rm200_cached_irq_mask >> 8)
  138. static void sni_rm200_disable_8259A_irq(unsigned int irq)
  139. {
  140. unsigned int mask;
  141. unsigned long flags;
  142. irq -= RM200_I8259A_IRQ_BASE;
  143. mask = 1 << irq;
  144. raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
  145. rm200_cached_irq_mask |= mask;
  146. if (irq & 8)
  147. writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
  148. else
  149. writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
  150. raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
  151. }
  152. static void sni_rm200_enable_8259A_irq(unsigned int irq)
  153. {
  154. unsigned int mask;
  155. unsigned long flags;
  156. irq -= RM200_I8259A_IRQ_BASE;
  157. mask = ~(1 << irq);
  158. raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
  159. rm200_cached_irq_mask &= mask;
  160. if (irq & 8)
  161. writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
  162. else
  163. writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
  164. raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
  165. }
  166. static inline int sni_rm200_i8259A_irq_real(unsigned int irq)
  167. {
  168. int value;
  169. int irqmask = 1 << irq;
  170. if (irq < 8) {
  171. writeb(0x0B, rm200_pic_master + PIC_CMD);
  172. value = readb(rm200_pic_master + PIC_CMD) & irqmask;
  173. writeb(0x0A, rm200_pic_master + PIC_CMD);
  174. return value;
  175. }
  176. writeb(0x0B, rm200_pic_slave + PIC_CMD); /* ISR register */
  177. value = readb(rm200_pic_slave + PIC_CMD) & (irqmask >> 8);
  178. writeb(0x0A, rm200_pic_slave + PIC_CMD);
  179. return value;
  180. }
  181. /*
  182. * Careful! The 8259A is a fragile beast, it pretty
  183. * much _has_ to be done exactly like this (mask it
  184. * first, _then_ send the EOI, and the order of EOI
  185. * to the two 8259s is important!
  186. */
  187. void sni_rm200_mask_and_ack_8259A(unsigned int irq)
  188. {
  189. unsigned int irqmask;
  190. unsigned long flags;
  191. irq -= RM200_I8259A_IRQ_BASE;
  192. irqmask = 1 << irq;
  193. raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
  194. /*
  195. * Lightweight spurious IRQ detection. We do not want
  196. * to overdo spurious IRQ handling - it's usually a sign
  197. * of hardware problems, so we only do the checks we can
  198. * do without slowing down good hardware unnecessarily.
  199. *
  200. * Note that IRQ7 and IRQ15 (the two spurious IRQs
  201. * usually resulting from the 8259A-1|2 PICs) occur
  202. * even if the IRQ is masked in the 8259A. Thus we
  203. * can check spurious 8259A IRQs without doing the
  204. * quite slow i8259A_irq_real() call for every IRQ.
  205. * This does not cover 100% of spurious interrupts,
  206. * but should be enough to warn the user that there
  207. * is something bad going on ...
  208. */
  209. if (rm200_cached_irq_mask & irqmask)
  210. goto spurious_8259A_irq;
  211. rm200_cached_irq_mask |= irqmask;
  212. handle_real_irq:
  213. if (irq & 8) {
  214. readb(rm200_pic_slave + PIC_IMR);
  215. writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
  216. writeb(0x60+(irq & 7), rm200_pic_slave + PIC_CMD);
  217. writeb(0x60+PIC_CASCADE_IR, rm200_pic_master + PIC_CMD);
  218. } else {
  219. readb(rm200_pic_master + PIC_IMR);
  220. writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
  221. writeb(0x60+irq, rm200_pic_master + PIC_CMD);
  222. }
  223. raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
  224. return;
  225. spurious_8259A_irq:
  226. /*
  227. * this is the slow path - should happen rarely.
  228. */
  229. if (sni_rm200_i8259A_irq_real(irq))
  230. /*
  231. * oops, the IRQ _is_ in service according to the
  232. * 8259A - not spurious, go handle it.
  233. */
  234. goto handle_real_irq;
  235. {
  236. static int spurious_irq_mask;
  237. /*
  238. * At this point we can be sure the IRQ is spurious,
  239. * lets ACK and report it. [once per IRQ]
  240. */
  241. if (!(spurious_irq_mask & irqmask)) {
  242. printk(KERN_DEBUG
  243. "spurious RM200 8259A interrupt: IRQ%d.\n", irq);
  244. spurious_irq_mask |= irqmask;
  245. }
  246. atomic_inc(&irq_err_count);
  247. /*
  248. * Theoretically we do not have to handle this IRQ,
  249. * but in Linux this does not cause problems and is
  250. * simpler for us.
  251. */
  252. goto handle_real_irq;
  253. }
  254. }
  255. static struct irq_chip sni_rm200_i8259A_chip = {
  256. .name = "RM200-XT-PIC",
  257. .mask = sni_rm200_disable_8259A_irq,
  258. .unmask = sni_rm200_enable_8259A_irq,
  259. .mask_ack = sni_rm200_mask_and_ack_8259A,
  260. };
  261. /*
  262. * Do the traditional i8259 interrupt polling thing. This is for the few
  263. * cases where no better interrupt acknowledge method is available and we
  264. * absolutely must touch the i8259.
  265. */
  266. static inline int sni_rm200_i8259_irq(void)
  267. {
  268. int irq;
  269. raw_spin_lock(&sni_rm200_i8259A_lock);
  270. /* Perform an interrupt acknowledge cycle on controller 1. */
  271. writeb(0x0C, rm200_pic_master + PIC_CMD); /* prepare for poll */
  272. irq = readb(rm200_pic_master + PIC_CMD) & 7;
  273. if (irq == PIC_CASCADE_IR) {
  274. /*
  275. * Interrupt is cascaded so perform interrupt
  276. * acknowledge on controller 2.
  277. */
  278. writeb(0x0C, rm200_pic_slave + PIC_CMD); /* prepare for poll */
  279. irq = (readb(rm200_pic_slave + PIC_CMD) & 7) + 8;
  280. }
  281. if (unlikely(irq == 7)) {
  282. /*
  283. * This may be a spurious interrupt.
  284. *
  285. * Read the interrupt status register (ISR). If the most
  286. * significant bit is not set then there is no valid
  287. * interrupt.
  288. */
  289. writeb(0x0B, rm200_pic_master + PIC_ISR); /* ISR register */
  290. if (~readb(rm200_pic_master + PIC_ISR) & 0x80)
  291. irq = -1;
  292. }
  293. raw_spin_unlock(&sni_rm200_i8259A_lock);
  294. return likely(irq >= 0) ? irq + RM200_I8259A_IRQ_BASE : irq;
  295. }
  296. void sni_rm200_init_8259A(void)
  297. {
  298. unsigned long flags;
  299. raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
  300. writeb(0xff, rm200_pic_master + PIC_IMR);
  301. writeb(0xff, rm200_pic_slave + PIC_IMR);
  302. writeb(0x11, rm200_pic_master + PIC_CMD);
  303. writeb(0, rm200_pic_master + PIC_IMR);
  304. writeb(1U << PIC_CASCADE_IR, rm200_pic_master + PIC_IMR);
  305. writeb(MASTER_ICW4_DEFAULT, rm200_pic_master + PIC_IMR);
  306. writeb(0x11, rm200_pic_slave + PIC_CMD);
  307. writeb(8, rm200_pic_slave + PIC_IMR);
  308. writeb(PIC_CASCADE_IR, rm200_pic_slave + PIC_IMR);
  309. writeb(SLAVE_ICW4_DEFAULT, rm200_pic_slave + PIC_IMR);
  310. udelay(100); /* wait for 8259A to initialize */
  311. writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
  312. writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
  313. raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
  314. }
  315. /*
  316. * IRQ2 is cascade interrupt to second interrupt controller
  317. */
  318. static struct irqaction sni_rm200_irq2 = {
  319. .handler = no_action,
  320. .name = "cascade",
  321. };
  322. static struct resource sni_rm200_pic1_resource = {
  323. .name = "onboard ISA pic1",
  324. .start = 0x16000020,
  325. .end = 0x16000023,
  326. .flags = IORESOURCE_BUSY
  327. };
  328. static struct resource sni_rm200_pic2_resource = {
  329. .name = "onboard ISA pic2",
  330. .start = 0x160000a0,
  331. .end = 0x160000a3,
  332. .flags = IORESOURCE_BUSY
  333. };
  334. /* ISA irq handler */
  335. static irqreturn_t sni_rm200_i8259A_irq_handler(int dummy, void *p)
  336. {
  337. int irq;
  338. irq = sni_rm200_i8259_irq();
  339. if (unlikely(irq < 0))
  340. return IRQ_NONE;
  341. do_IRQ(irq);
  342. return IRQ_HANDLED;
  343. }
  344. struct irqaction sni_rm200_i8259A_irq = {
  345. .handler = sni_rm200_i8259A_irq_handler,
  346. .name = "onboard ISA",
  347. .flags = IRQF_SHARED
  348. };
  349. void __init sni_rm200_i8259_irqs(void)
  350. {
  351. int i;
  352. rm200_pic_master = ioremap_nocache(0x16000020, 4);
  353. if (!rm200_pic_master)
  354. return;
  355. rm200_pic_slave = ioremap_nocache(0x160000a0, 4);
  356. if (!rm200_pic_slave) {
  357. iounmap(rm200_pic_master);
  358. return;
  359. }
  360. insert_resource(&iomem_resource, &sni_rm200_pic1_resource);
  361. insert_resource(&iomem_resource, &sni_rm200_pic2_resource);
  362. sni_rm200_init_8259A();
  363. for (i = RM200_I8259A_IRQ_BASE; i < RM200_I8259A_IRQ_BASE + 16; i++)
  364. set_irq_chip_and_handler(i, &sni_rm200_i8259A_chip,
  365. handle_level_irq);
  366. setup_irq(RM200_I8259A_IRQ_BASE + PIC_CASCADE_IR, &sni_rm200_irq2);
  367. }
  368. #define SNI_RM200_INT_STAT_REG CKSEG1ADDR(0xbc000000)
  369. #define SNI_RM200_INT_ENA_REG CKSEG1ADDR(0xbc080000)
  370. #define SNI_RM200_INT_START 24
  371. #define SNI_RM200_INT_END 28
  372. static void enable_rm200_irq(unsigned int irq)
  373. {
  374. unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
  375. *(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask;
  376. }
  377. void disable_rm200_irq(unsigned int irq)
  378. {
  379. unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
  380. *(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask;
  381. }
  382. void end_rm200_irq(unsigned int irq)
  383. {
  384. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  385. enable_rm200_irq(irq);
  386. }
  387. static struct irq_chip rm200_irq_type = {
  388. .name = "RM200",
  389. .ack = disable_rm200_irq,
  390. .mask = disable_rm200_irq,
  391. .mask_ack = disable_rm200_irq,
  392. .unmask = enable_rm200_irq,
  393. .end = end_rm200_irq,
  394. };
  395. static void sni_rm200_hwint(void)
  396. {
  397. u32 pending = read_c0_cause() & read_c0_status();
  398. u8 mask;
  399. u8 stat;
  400. int irq;
  401. if (pending & C_IRQ5)
  402. do_IRQ(MIPS_CPU_IRQ_BASE + 7);
  403. else if (pending & C_IRQ0) {
  404. clear_c0_status(IE_IRQ0);
  405. mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f;
  406. stat = *(volatile u8 *)SNI_RM200_INT_STAT_REG ^ 0x14;
  407. irq = ffs(stat & mask & 0x1f);
  408. if (likely(irq > 0))
  409. do_IRQ(irq + SNI_RM200_INT_START - 1);
  410. set_c0_status(IE_IRQ0);
  411. }
  412. }
  413. void __init sni_rm200_irq_init(void)
  414. {
  415. int i;
  416. * (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f;
  417. sni_rm200_i8259_irqs();
  418. mips_cpu_irq_init();
  419. /* Actually we've got more interrupts to handle ... */
  420. for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
  421. set_irq_chip_and_handler(i, &rm200_irq_type, handle_level_irq);
  422. sni_hwint = sni_rm200_hwint;
  423. change_c0_status(ST0_IM, IE_IRQ0);
  424. setup_irq(SNI_RM200_INT_START + 0, &sni_rm200_i8259A_irq);
  425. setup_irq(SNI_RM200_INT_START + 1, &sni_isa_irq);
  426. }
  427. void __init sni_rm200_init(void)
  428. {
  429. }