pcit.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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 struct resource sni_mem_resource = {
  118. .start = 0x18000000UL,
  119. .end = 0x1fbfffffUL,
  120. .name = "PCIT PCI MEM",
  121. .flags = IORESOURCE_MEM
  122. };
  123. static void __init sni_pcit_resource_init(void)
  124. {
  125. int i;
  126. /* request I/O space for devices used on all i[345]86 PCs */
  127. for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++)
  128. request_resource(&sni_io_resource, pcit_io_resources + i);
  129. }
  130. extern struct pci_ops sni_pcit_ops;
  131. static struct pci_controller sni_pcit_controller = {
  132. .pci_ops = &sni_pcit_ops,
  133. .mem_resource = &sni_mem_resource,
  134. .mem_offset = 0x00000000UL,
  135. .io_resource = &sni_io_resource,
  136. .io_offset = 0x00000000UL,
  137. .io_map_base = SNI_PORT_BASE
  138. };
  139. static void enable_pcit_irq(struct irq_data *d)
  140. {
  141. u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24);
  142. *(volatile u32 *)SNI_PCIT_INT_REG |= mask;
  143. }
  144. void disable_pcit_irq(struct irq_data *d)
  145. {
  146. u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24);
  147. *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask;
  148. }
  149. static struct irq_chip pcit_irq_type = {
  150. .name = "PCIT",
  151. .irq_mask = disable_pcit_irq,
  152. .irq_unmask = enable_pcit_irq,
  153. };
  154. static void pcit_hwint1(void)
  155. {
  156. u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
  157. int irq;
  158. clear_c0_status(IE_IRQ1);
  159. irq = ffs((pending >> 16) & 0x7f);
  160. if (likely(irq > 0))
  161. do_IRQ(irq + SNI_PCIT_INT_START - 1);
  162. set_c0_status(IE_IRQ1);
  163. }
  164. static void pcit_hwint0(void)
  165. {
  166. u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
  167. int irq;
  168. clear_c0_status(IE_IRQ0);
  169. irq = ffs((pending >> 16) & 0x3f);
  170. if (likely(irq > 0))
  171. do_IRQ(irq + SNI_PCIT_INT_START - 1);
  172. set_c0_status(IE_IRQ0);
  173. }
  174. static void sni_pcit_hwint(void)
  175. {
  176. u32 pending = read_c0_cause() & read_c0_status();
  177. if (pending & C_IRQ1)
  178. pcit_hwint1();
  179. else if (pending & C_IRQ2)
  180. do_IRQ(MIPS_CPU_IRQ_BASE + 4);
  181. else if (pending & C_IRQ3)
  182. do_IRQ(MIPS_CPU_IRQ_BASE + 5);
  183. else if (pending & C_IRQ5)
  184. do_IRQ(MIPS_CPU_IRQ_BASE + 7);
  185. }
  186. static void sni_pcit_hwint_cplus(void)
  187. {
  188. u32 pending = read_c0_cause() & read_c0_status();
  189. if (pending & C_IRQ0)
  190. pcit_hwint0();
  191. else if (pending & C_IRQ1)
  192. do_IRQ(MIPS_CPU_IRQ_BASE + 3);
  193. else if (pending & C_IRQ2)
  194. do_IRQ(MIPS_CPU_IRQ_BASE + 4);
  195. else if (pending & C_IRQ3)
  196. do_IRQ(MIPS_CPU_IRQ_BASE + 5);
  197. else if (pending & C_IRQ5)
  198. do_IRQ(MIPS_CPU_IRQ_BASE + 7);
  199. }
  200. void __init sni_pcit_irq_init(void)
  201. {
  202. int i;
  203. mips_cpu_irq_init();
  204. for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
  205. irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
  206. *(volatile u32 *)SNI_PCIT_INT_REG = 0;
  207. sni_hwint = sni_pcit_hwint;
  208. change_c0_status(ST0_IM, IE_IRQ1);
  209. setup_irq(SNI_PCIT_INT_START + 6, &sni_isa_irq);
  210. }
  211. void __init sni_pcit_cplus_irq_init(void)
  212. {
  213. int i;
  214. mips_cpu_irq_init();
  215. for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
  216. irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
  217. *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000;
  218. sni_hwint = sni_pcit_hwint_cplus;
  219. change_c0_status(ST0_IM, IE_IRQ0);
  220. setup_irq(MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq);
  221. }
  222. void __init sni_pcit_init(void)
  223. {
  224. ioport_resource.end = sni_io_resource.end;
  225. #ifdef CONFIG_PCI
  226. PCIBIOS_MIN_IO = 0x9000;
  227. register_pci_controller(&sni_pcit_controller);
  228. #endif
  229. sni_pcit_resource_init();
  230. }
  231. static int __init snirm_pcit_setup_devinit(void)
  232. {
  233. switch (sni_brd_type) {
  234. case SNI_BRD_PCI_TOWER:
  235. platform_device_register(&pcit_serial8250_device);
  236. platform_device_register(&pcit_cmos_device);
  237. platform_device_register(&pcit_pcspeaker_pdev);
  238. break;
  239. case SNI_BRD_PCI_TOWER_CPLUS:
  240. platform_device_register(&pcit_cplus_serial8250_device);
  241. platform_device_register(&pcit_cmos_device);
  242. platform_device_register(&pcit_pcspeaker_pdev);
  243. break;
  244. }
  245. return 0;
  246. }
  247. device_initcall(snirm_pcit_setup_devinit);