pcit.c 6.1 KB

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