sys_sable.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * linux/arch/alpha/kernel/sys_sable.c
  4. *
  5. * Copyright (C) 1995 David A Rusling
  6. * Copyright (C) 1996 Jay A Estabrook
  7. * Copyright (C) 1998, 1999 Richard Henderson
  8. *
  9. * Code supporting the Sable, Sable-Gamma, and Lynx systems.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/types.h>
  13. #include <linux/mm.h>
  14. #include <linux/sched.h>
  15. #include <linux/pci.h>
  16. #include <linux/init.h>
  17. #include <asm/ptrace.h>
  18. #include <asm/dma.h>
  19. #include <asm/irq.h>
  20. #include <asm/mmu_context.h>
  21. #include <asm/io.h>
  22. #include <asm/core_t2.h>
  23. #include <asm/tlbflush.h>
  24. #include "proto.h"
  25. #include "irq_impl.h"
  26. #include "pci_impl.h"
  27. #include "machvec_impl.h"
  28. DEFINE_SPINLOCK(sable_lynx_irq_lock);
  29. typedef struct irq_swizzle_struct
  30. {
  31. char irq_to_mask[64];
  32. char mask_to_irq[64];
  33. /* Note mask bit is true for DISABLED irqs. */
  34. unsigned long shadow_mask;
  35. void (*update_irq_hw)(unsigned long bit, unsigned long mask);
  36. void (*ack_irq_hw)(unsigned long bit);
  37. } irq_swizzle_t;
  38. static irq_swizzle_t *sable_lynx_irq_swizzle;
  39. static void sable_lynx_init_irq(int nr_of_irqs);
  40. #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE)
  41. /***********************************************************************/
  42. /*
  43. * For SABLE, which is really baroque, we manage 40 IRQ's, but the
  44. * hardware really only supports 24, not via normal ISA PIC,
  45. * but cascaded custom 8259's, etc.
  46. * 0-7 (char at 536)
  47. * 8-15 (char at 53a)
  48. * 16-23 (char at 53c)
  49. *
  50. * Summary Registers (536/53a/53c):
  51. *
  52. * Bit Meaning Kernel IRQ
  53. *------------------------------------------
  54. * 0 PCI slot 0 34
  55. * 1 NCR810 (builtin) 33
  56. * 2 TULIP (builtin) 32
  57. * 3 mouse 12
  58. * 4 PCI slot 1 35
  59. * 5 PCI slot 2 36
  60. * 6 keyboard 1
  61. * 7 floppy 6
  62. * 8 COM2 3
  63. * 9 parallel port 7
  64. *10 EISA irq 3 -
  65. *11 EISA irq 4 -
  66. *12 EISA irq 5 5
  67. *13 EISA irq 6 -
  68. *14 EISA irq 7 -
  69. *15 COM1 4
  70. *16 EISA irq 9 9
  71. *17 EISA irq 10 10
  72. *18 EISA irq 11 11
  73. *19 EISA irq 12 -
  74. *20 EISA irq 13 -
  75. *21 EISA irq 14 14
  76. *22 NC 15
  77. *23 IIC -
  78. */
  79. static void
  80. sable_update_irq_hw(unsigned long bit, unsigned long mask)
  81. {
  82. int port = 0x537;
  83. if (bit >= 16) {
  84. port = 0x53d;
  85. mask >>= 16;
  86. } else if (bit >= 8) {
  87. port = 0x53b;
  88. mask >>= 8;
  89. }
  90. outb(mask, port);
  91. }
  92. static void
  93. sable_ack_irq_hw(unsigned long bit)
  94. {
  95. int port, val1, val2;
  96. if (bit >= 16) {
  97. port = 0x53c;
  98. val1 = 0xE0 | (bit - 16);
  99. val2 = 0xE0 | 4;
  100. } else if (bit >= 8) {
  101. port = 0x53a;
  102. val1 = 0xE0 | (bit - 8);
  103. val2 = 0xE0 | 3;
  104. } else {
  105. port = 0x536;
  106. val1 = 0xE0 | (bit - 0);
  107. val2 = 0xE0 | 1;
  108. }
  109. outb(val1, port); /* ack the slave */
  110. outb(val2, 0x534); /* ack the master */
  111. }
  112. static irq_swizzle_t sable_irq_swizzle = {
  113. {
  114. -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
  115. -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
  116. -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */
  117. -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
  118. 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
  119. -1, -1, -1, -1, -1, -1, -1, -1, /* */
  120. -1, -1, -1, -1, -1, -1, -1, -1, /* */
  121. -1, -1, -1, -1, -1, -1, -1, -1 /* */
  122. },
  123. {
  124. 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */
  125. 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
  126. 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
  127. -1, -1, -1, -1, -1, -1, -1, -1, /* */
  128. -1, -1, -1, -1, -1, -1, -1, -1, /* */
  129. -1, -1, -1, -1, -1, -1, -1, -1, /* */
  130. -1, -1, -1, -1, -1, -1, -1, -1, /* */
  131. -1, -1, -1, -1, -1, -1, -1, -1 /* */
  132. },
  133. -1,
  134. sable_update_irq_hw,
  135. sable_ack_irq_hw
  136. };
  137. static void __init
  138. sable_init_irq(void)
  139. {
  140. outb(-1, 0x537); /* slave 0 */
  141. outb(-1, 0x53b); /* slave 1 */
  142. outb(-1, 0x53d); /* slave 2 */
  143. outb(0x44, 0x535); /* enable cascades in master */
  144. sable_lynx_irq_swizzle = &sable_irq_swizzle;
  145. sable_lynx_init_irq(40);
  146. }
  147. /*
  148. * PCI Fixup configuration for ALPHA SABLE (2100).
  149. *
  150. * The device to slot mapping looks like:
  151. *
  152. * Slot Device
  153. * 0 TULIP
  154. * 1 SCSI
  155. * 2 PCI-EISA bridge
  156. * 3 none
  157. * 4 none
  158. * 5 none
  159. * 6 PCI on board slot 0
  160. * 7 PCI on board slot 1
  161. * 8 PCI on board slot 2
  162. *
  163. *
  164. * This two layered interrupt approach means that we allocate IRQ 16 and
  165. * above for PCI interrupts. The IRQ relates to which bit the interrupt
  166. * comes in on. This makes interrupt processing much easier.
  167. */
  168. /*
  169. * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
  170. * with the values in the irq swizzling tables above.
  171. */
  172. static int
  173. sable_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
  174. {
  175. static char irq_tab[9][5] = {
  176. /*INT INTA INTB INTC INTD */
  177. { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
  178. { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
  179. { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */
  180. { -1, -1, -1, -1, -1}, /* IdSel 3, none */
  181. { -1, -1, -1, -1, -1}, /* IdSel 4, none */
  182. { -1, -1, -1, -1, -1}, /* IdSel 5, none */
  183. { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */
  184. { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */
  185. { 32+4, 32+4, 32+4, 32+4, 32+4} /* IdSel 8, slot 2 */
  186. };
  187. long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;
  188. return COMMON_TABLE_LOOKUP;
  189. }
  190. #endif /* defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE) */
  191. /***********************************************************************/
  192. /* GENERIC irq routines */
  193. static inline void
  194. sable_lynx_enable_irq(struct irq_data *d)
  195. {
  196. unsigned long bit, mask;
  197. bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];
  198. spin_lock(&sable_lynx_irq_lock);
  199. mask = sable_lynx_irq_swizzle->shadow_mask &= ~(1UL << bit);
  200. sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
  201. spin_unlock(&sable_lynx_irq_lock);
  202. #if 0
  203. printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n",
  204. __func__, mask, bit, irq);
  205. #endif
  206. }
  207. static void
  208. sable_lynx_disable_irq(struct irq_data *d)
  209. {
  210. unsigned long bit, mask;
  211. bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];
  212. spin_lock(&sable_lynx_irq_lock);
  213. mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
  214. sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
  215. spin_unlock(&sable_lynx_irq_lock);
  216. #if 0
  217. printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n",
  218. __func__, mask, bit, irq);
  219. #endif
  220. }
  221. static void
  222. sable_lynx_mask_and_ack_irq(struct irq_data *d)
  223. {
  224. unsigned long bit, mask;
  225. bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];
  226. spin_lock(&sable_lynx_irq_lock);
  227. mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
  228. sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
  229. sable_lynx_irq_swizzle->ack_irq_hw(bit);
  230. spin_unlock(&sable_lynx_irq_lock);
  231. }
  232. static struct irq_chip sable_lynx_irq_type = {
  233. .name = "SABLE/LYNX",
  234. .irq_unmask = sable_lynx_enable_irq,
  235. .irq_mask = sable_lynx_disable_irq,
  236. .irq_mask_ack = sable_lynx_mask_and_ack_irq,
  237. };
  238. static void
  239. sable_lynx_srm_device_interrupt(unsigned long vector)
  240. {
  241. /* Note that the vector reported by the SRM PALcode corresponds
  242. to the interrupt mask bits, but we have to manage via the
  243. so-called legacy IRQs for many common devices. */
  244. int bit, irq;
  245. bit = (vector - 0x800) >> 4;
  246. irq = sable_lynx_irq_swizzle->mask_to_irq[bit];
  247. #if 0
  248. printk("%s: vector 0x%lx bit 0x%x irq 0x%x\n",
  249. __func__, vector, bit, irq);
  250. #endif
  251. handle_irq(irq);
  252. }
  253. static void __init
  254. sable_lynx_init_irq(int nr_of_irqs)
  255. {
  256. long i;
  257. for (i = 0; i < nr_of_irqs; ++i) {
  258. irq_set_chip_and_handler(i, &sable_lynx_irq_type,
  259. handle_level_irq);
  260. irq_set_status_flags(i, IRQ_LEVEL);
  261. }
  262. common_init_isa_dma();
  263. }
  264. static void __init
  265. sable_lynx_init_pci(void)
  266. {
  267. common_init_pci();
  268. }
  269. /*****************************************************************/
  270. /*
  271. * The System Vectors
  272. *
  273. * In order that T2_HAE_ADDRESS should be a constant, we play
  274. * these games with GAMMA_BIAS.
  275. */
  276. #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE)
  277. #undef GAMMA_BIAS
  278. #define GAMMA_BIAS _GAMMA_BIAS
  279. struct alpha_machine_vector sable_gamma_mv __initmv = {
  280. .vector_name = "Sable-Gamma",
  281. DO_EV5_MMU,
  282. DO_DEFAULT_RTC,
  283. DO_T2_IO,
  284. .machine_check = t2_machine_check,
  285. .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
  286. .min_io_address = EISA_DEFAULT_IO_BASE,
  287. .min_mem_address = T2_DEFAULT_MEM_BASE,
  288. .nr_irqs = 40,
  289. .device_interrupt = sable_lynx_srm_device_interrupt,
  290. .init_arch = t2_init_arch,
  291. .init_irq = sable_init_irq,
  292. .init_rtc = common_init_rtc,
  293. .init_pci = sable_lynx_init_pci,
  294. .kill_arch = t2_kill_arch,
  295. .pci_map_irq = sable_map_irq,
  296. .pci_swizzle = common_swizzle,
  297. .sys = { .t2 = {
  298. .gamma_bias = _GAMMA_BIAS
  299. } }
  300. };
  301. ALIAS_MV(sable_gamma)
  302. #endif /* GENERIC || SABLE */