pcit.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * PCI Tower 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 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  9. */
  10. #include <linux/init.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/pci.h>
  13. #include <linux/serial_8250.h>
  14. #include <asm/sni.h>
  15. #include <asm/time.h>
  16. #include <asm/irq_cpu.h>
  17. #define PORT(_base,_irq) \
  18. { \
  19. .iobase = _base, \
  20. .irq = _irq, \
  21. .uartclk = 1843200, \
  22. .iotype = UPIO_PORT, \
  23. .flags = UPF_BOOT_AUTOCONF, \
  24. }
  25. static struct plat_serial8250_port pcit_data[] = {
  26. PORT(0x3f8, 0),
  27. PORT(0x2f8, 3),
  28. { },
  29. };
  30. static struct platform_device pcit_serial8250_device = {
  31. .name = "serial8250",
  32. .id = PLAT8250_DEV_PLATFORM,
  33. .dev = {
  34. .platform_data = pcit_data,
  35. },
  36. };
  37. static struct plat_serial8250_port pcit_cplus_data[] = {
  38. PORT(0x3f8, 0),
  39. PORT(0x2f8, 3),
  40. PORT(0x3e8, 4),
  41. PORT(0x2e8, 3),
  42. { },
  43. };
  44. static struct platform_device pcit_cplus_serial8250_device = {
  45. .name = "serial8250",
  46. .id = PLAT8250_DEV_PLATFORM,
  47. .dev = {
  48. .platform_data = pcit_cplus_data,
  49. },
  50. };
  51. static struct resource pcit_cmos_rsrc[] = {
  52. {
  53. .start = 0x70,
  54. .end = 0x71,
  55. .flags = IORESOURCE_IO
  56. },
  57. {
  58. .start = 8,
  59. .end = 8,
  60. .flags = IORESOURCE_IRQ
  61. }
  62. };
  63. static struct platform_device pcit_cmos_device = {
  64. .name = "rtc_cmos",
  65. .num_resources = ARRAY_SIZE(pcit_cmos_rsrc),
  66. .resource = pcit_cmos_rsrc
  67. };
  68. static struct platform_device pcit_pcspeaker_pdev = {
  69. .name = "pcspkr",
  70. .id = -1,
  71. };
  72. static struct resource sni_io_resource = {
  73. .start = 0x00000000UL,
  74. .end = 0x03bfffffUL,
  75. .name = "PCIT IO",
  76. .flags = IORESOURCE_IO,
  77. };
  78. static struct resource pcit_io_resources[] = {
  79. {
  80. .start = 0x00,
  81. .end = 0x1f,
  82. .name = "dma1",
  83. .flags = IORESOURCE_BUSY
  84. }, {
  85. .start = 0x40,
  86. .end = 0x5f,
  87. .name = "timer",
  88. .flags = IORESOURCE_BUSY
  89. }, {
  90. .start = 0x60,
  91. .end = 0x6f,
  92. .name = "keyboard",
  93. .flags = IORESOURCE_BUSY
  94. }, {
  95. .start = 0x80,
  96. .end = 0x8f,
  97. .name = "dma page reg",
  98. .flags = IORESOURCE_BUSY
  99. }, {
  100. .start = 0xc0,
  101. .end = 0xdf,
  102. .name = "dma2",
  103. .flags = IORESOURCE_BUSY
  104. }, {
  105. .start = 0xcf8,
  106. .end = 0xcfb,
  107. .name = "PCI config addr",
  108. .flags = IORESOURCE_BUSY
  109. }, {
  110. .start = 0xcfc,
  111. .end = 0xcff,
  112. .name = "PCI config data",
  113. .flags = IORESOURCE_BUSY
  114. }
  115. };
  116. static struct resource sni_mem_resource = {
  117. .start = 0x18000000UL,
  118. .end = 0x1fbfffffUL,
  119. .name = "PCIT PCI MEM",
  120. .flags = IORESOURCE_MEM
  121. };
  122. static void __init sni_pcit_resource_init(void)
  123. {
  124. int i;
  125. /* request I/O space for devices used on all i[345]86 PCs */
  126. for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++)
  127. request_resource(&sni_io_resource, pcit_io_resources + i);
  128. }
  129. extern struct pci_ops sni_pcit_ops;
  130. static struct pci_controller sni_pcit_controller = {
  131. .pci_ops = &sni_pcit_ops,
  132. .mem_resource = &sni_mem_resource,
  133. .mem_offset = 0x00000000UL,
  134. .io_resource = &sni_io_resource,
  135. .io_offset = 0x00000000UL,
  136. .io_map_base = SNI_PORT_BASE
  137. };
  138. static void enable_pcit_irq(unsigned int irq)
  139. {
  140. u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
  141. *(volatile u32 *)SNI_PCIT_INT_REG |= mask;
  142. }
  143. void disable_pcit_irq(unsigned int irq)
  144. {
  145. u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
  146. *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask;
  147. }
  148. void end_pcit_irq(unsigned int irq)
  149. {
  150. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  151. enable_pcit_irq(irq);
  152. }
  153. static struct irq_chip pcit_irq_type = {
  154. .typename = "PCIT",
  155. .ack = disable_pcit_irq,
  156. .mask = disable_pcit_irq,
  157. .mask_ack = disable_pcit_irq,
  158. .unmask = enable_pcit_irq,
  159. .end = end_pcit_irq,
  160. };
  161. static void pcit_hwint1(void)
  162. {
  163. u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
  164. int irq;
  165. clear_c0_status(IE_IRQ1);
  166. irq = ffs((pending >> 16) & 0x7f);
  167. if (likely(irq > 0))
  168. do_IRQ(irq + SNI_PCIT_INT_START - 1);
  169. set_c0_status(IE_IRQ1);
  170. }
  171. static void pcit_hwint0(void)
  172. {
  173. u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
  174. int irq;
  175. clear_c0_status(IE_IRQ0);
  176. irq = ffs((pending >> 16) & 0x3f);
  177. if (likely(irq > 0))
  178. do_IRQ(irq + SNI_PCIT_INT_START - 1);
  179. set_c0_status(IE_IRQ0);
  180. }
  181. static void sni_pcit_hwint(void)
  182. {
  183. u32 pending = read_c0_cause() & read_c0_status();
  184. if (pending & C_IRQ1)
  185. pcit_hwint1();
  186. else if (pending & C_IRQ2)
  187. do_IRQ(MIPS_CPU_IRQ_BASE + 4);
  188. else if (pending & C_IRQ3)
  189. do_IRQ(MIPS_CPU_IRQ_BASE + 5);
  190. else if (pending & C_IRQ5)
  191. do_IRQ(MIPS_CPU_IRQ_BASE + 7);
  192. }
  193. static void sni_pcit_hwint_cplus(void)
  194. {
  195. u32 pending = read_c0_cause() & read_c0_status();
  196. if (pending & C_IRQ0)
  197. pcit_hwint0();
  198. else if (pending & C_IRQ1)
  199. do_IRQ(MIPS_CPU_IRQ_BASE + 3);
  200. else if (pending & C_IRQ2)
  201. do_IRQ(MIPS_CPU_IRQ_BASE + 4);
  202. else if (pending & C_IRQ3)
  203. do_IRQ(MIPS_CPU_IRQ_BASE + 5);
  204. else if (pending & C_IRQ5)
  205. do_IRQ(MIPS_CPU_IRQ_BASE + 7);
  206. }
  207. void __init sni_pcit_irq_init(void)
  208. {
  209. int i;
  210. mips_cpu_irq_init();
  211. for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
  212. set_irq_chip(i, &pcit_irq_type);
  213. *(volatile u32 *)SNI_PCIT_INT_REG = 0;
  214. sni_hwint = sni_pcit_hwint;
  215. change_c0_status(ST0_IM, IE_IRQ1);
  216. setup_irq(SNI_PCIT_INT_START + 6, &sni_isa_irq);
  217. }
  218. void __init sni_pcit_cplus_irq_init(void)
  219. {
  220. int i;
  221. mips_cpu_irq_init();
  222. for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
  223. set_irq_chip(i, &pcit_irq_type);
  224. *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000;
  225. sni_hwint = sni_pcit_hwint_cplus;
  226. change_c0_status(ST0_IM, IE_IRQ0);
  227. setup_irq(MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq);
  228. }
  229. void __init sni_pcit_init(void)
  230. {
  231. ioport_resource.end = sni_io_resource.end;
  232. #ifdef CONFIG_PCI
  233. PCIBIOS_MIN_IO = 0x9000;
  234. register_pci_controller(&sni_pcit_controller);
  235. #endif
  236. sni_pcit_resource_init();
  237. }
  238. static int __init snirm_pcit_setup_devinit(void)
  239. {
  240. switch (sni_brd_type) {
  241. case SNI_BRD_PCI_TOWER:
  242. platform_device_register(&pcit_serial8250_device);
  243. platform_device_register(&pcit_cmos_device);
  244. platform_device_register(&pcit_pcspeaker_pdev);
  245. break;
  246. case SNI_BRD_PCI_TOWER_CPLUS:
  247. platform_device_register(&pcit_cplus_serial8250_device);
  248. platform_device_register(&pcit_cmos_device);
  249. platform_device_register(&pcit_pcspeaker_pdev);
  250. break;
  251. }
  252. return 0;
  253. }
  254. device_initcall(snirm_pcit_setup_devinit);