Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sys_takara.c
Go to the documentation of this file.
1 /*
2  * linux/arch/alpha/kernel/sys_takara.c
3  *
4  * Copyright (C) 1995 David A Rusling
5  * Copyright (C) 1996 Jay A Estabrook
6  * Copyright (C) 1998, 1999 Richard Henderson
7  *
8  * Code supporting the TAKARA.
9  */
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 
18 #include <asm/ptrace.h>
19 #include <asm/dma.h>
20 #include <asm/irq.h>
21 #include <asm/mmu_context.h>
22 #include <asm/io.h>
23 #include <asm/pgtable.h>
24 #include <asm/core_cia.h>
25 #include <asm/tlbflush.h>
26 
27 #include "proto.h"
28 #include "irq_impl.h"
29 #include "pci_impl.h"
30 #include "machvec_impl.h"
31 #include "pc873xx.h"
32 
33 /* Note mask bit is true for DISABLED irqs. */
34 static unsigned long cached_irq_mask[2] = { -1, -1 };
35 
36 static inline void
37 takara_update_irq_hw(unsigned long irq, unsigned long mask)
38 {
39  int regaddr;
40 
41  mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
42  regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
43  outl(mask & 0xffff0000UL, regaddr);
44 }
45 
46 static inline void
47 takara_enable_irq(struct irq_data *d)
48 {
49  unsigned int irq = d->irq;
50  unsigned long mask;
51  mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
52  takara_update_irq_hw(irq, mask);
53 }
54 
55 static void
56 takara_disable_irq(struct irq_data *d)
57 {
58  unsigned int irq = d->irq;
59  unsigned long mask;
60  mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
61  takara_update_irq_hw(irq, mask);
62 }
63 
64 static struct irq_chip takara_irq_type = {
65  .name = "TAKARA",
66  .irq_unmask = takara_enable_irq,
67  .irq_mask = takara_disable_irq,
68  .irq_mask_ack = takara_disable_irq,
69 };
70 
71 static void
72 takara_device_interrupt(unsigned long vector)
73 {
74  unsigned intstatus;
75 
76  /*
77  * The PALcode will have passed us vectors 0x800 or 0x810,
78  * which are fairly arbitrary values and serve only to tell
79  * us whether an interrupt has come in on IRQ0 or IRQ1. If
80  * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
81  * probably ISA, but PCI interrupts can come through IRQ0
82  * as well if the interrupt controller isn't in accelerated
83  * mode.
84  *
85  * OTOH, the accelerator thing doesn't seem to be working
86  * overly well, so what we'll do instead is try directly
87  * examining the Master Interrupt Register to see if it's a
88  * PCI interrupt, and if _not_ then we'll pass it on to the
89  * ISA handler.
90  */
91 
92  intstatus = inw(0x500) & 15;
93  if (intstatus) {
94  /*
95  * This is a PCI interrupt. Check each bit and
96  * despatch an interrupt if it's set.
97  */
98 
99  if (intstatus & 8) handle_irq(16+3);
100  if (intstatus & 4) handle_irq(16+2);
101  if (intstatus & 2) handle_irq(16+1);
102  if (intstatus & 1) handle_irq(16+0);
103  } else {
104  isa_device_interrupt (vector);
105  }
106 }
107 
108 static void
109 takara_srm_device_interrupt(unsigned long vector)
110 {
111  int irq = (vector - 0x800) >> 4;
112  handle_irq(irq);
113 }
114 
115 static void __init
116 takara_init_irq(void)
117 {
118  long i;
119 
121 
122  if (alpha_using_srm) {
123  alpha_mv.device_interrupt = takara_srm_device_interrupt;
124  } else {
125  unsigned int ctlreg = inl(0x500);
126 
127  /* Return to non-accelerated mode. */
128  ctlreg &= ~0x8000;
129  outl(ctlreg, 0x500);
130 
131  /* Enable the PCI interrupt register. */
132  ctlreg = 0x05107c00;
133  outl(ctlreg, 0x500);
134  }
135 
136  for (i = 16; i < 128; i += 16)
137  takara_update_irq_hw(i, -1);
138 
139  for (i = 16; i < 128; ++i) {
140  irq_set_chip_and_handler(i, &takara_irq_type,
142  irq_set_status_flags(i, IRQ_LEVEL);
143  }
144 
146 }
147 
148 
149 /*
150  * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
151  * 19, and 18 respectively, in the default configuration. They can
152  * also be jumpered to slots 8, 7, and 6 respectively, which is fun
153  * because the SIO ISA bridge can also be slot 7. However, the SIO
154  * doesn't explicitly generate PCI-type interrupts, so we can
155  * assign it whatever the hell IRQ we like and it doesn't matter.
156  */
157 
158 static int __init
159 takara_map_irq_srm(const struct pci_dev *dev, u8 slot, u8 pin)
160 {
161  static char irq_tab[15][5] __initdata = {
162  { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
163  { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
164  { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
165  { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
166  { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
167  { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
168  /* These are behind the bridges. */
169  { 12, 12, 13, 14, 15}, /* slot 12 == nothing */
170  { 8, 8, 9, 19, 11}, /* slot 13 == nothing */
171  { 4, 4, 5, 6, 7}, /* slot 14 == nothing */
172  { 0, 0, 1, 2, 3}, /* slot 15 == nothing */
173  { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
174  {64+ 0, 64+0, 64+1, 64+2, 64+3}, /* slot 17= device 4 */
175  {48+ 0, 48+0, 48+1, 48+2, 48+3}, /* slot 18= device 3 */
176  {32+ 0, 32+0, 32+1, 32+2, 32+3}, /* slot 19= device 2 */
177  {16+ 0, 16+0, 16+1, 16+2, 16+3}, /* slot 20= device 1 */
178  };
179  const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
180  int irq = COMMON_TABLE_LOOKUP;
181  if (irq >= 0 && irq < 16) {
182  /* Guess that we are behind a bridge. */
183  unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
184  irq += irq_tab[busslot-min_idsel][0];
185  }
186  return irq;
187 }
188 
189 static int __init
190 takara_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
191 {
192  static char irq_tab[15][5] __initdata = {
193  { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
194  { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
195  { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
196  { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
197  { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
198  { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
199  { -1, -1, -1, -1, -1}, /* slot 12 == nothing */
200  { -1, -1, -1, -1, -1}, /* slot 13 == nothing */
201  { -1, -1, -1, -1, -1}, /* slot 14 == nothing */
202  { -1, -1, -1, -1, -1}, /* slot 15 == nothing */
203  { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
204  { -1, -1, -1, -1, -1}, /* slot 17 == nothing */
205  { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */
206  { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */
207  { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */
208  };
209  const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
210  return COMMON_TABLE_LOOKUP;
211 }
212 
213 static u8 __init
214 takara_swizzle(struct pci_dev *dev, u8 *pinp)
215 {
216  int slot = PCI_SLOT(dev->devfn);
217  int pin = *pinp;
218  unsigned int ctlreg = inl(0x500);
219  unsigned int busslot;
220 
221  if (!dev->bus->self)
222  return slot;
223 
224  busslot = PCI_SLOT(dev->bus->self->devfn);
225  /* Check for built-in bridges. */
226  if (dev->bus->number != 0
227  && busslot > 16
228  && ((1<<(36-busslot)) & ctlreg)) {
229  if (pin == 1)
230  pin += (20 - busslot);
231  else {
232  printk(KERN_WARNING "takara_swizzle: can only "
233  "handle cards with INTA IRQ pin.\n");
234  }
235  } else {
236  /* Must be a card-based bridge. */
237  printk(KERN_WARNING "takara_swizzle: cannot handle "
238  "card-bridge behind builtin bridge yet.\n");
239  }
240 
241  *pinp = pin;
242  return slot;
243 }
244 
245 static void __init
246 takara_init_pci(void)
247 {
248  if (alpha_using_srm)
249  alpha_mv.pci_map_irq = takara_map_irq_srm;
250 
251  cia_init_pci();
252 
253  if (pc873xx_probe() == -1) {
254  printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n");
255  } else {
256  printk(KERN_INFO "Found %s Super IO chip at 0x%x\n",
259  }
260 }
261 
262 
263 /*
264  * The System Vector
265  */
266 
267 struct alpha_machine_vector takara_mv __initmv = {
268  .vector_name = "Takara",
269  DO_EV5_MMU,
271  DO_CIA_IO,
272  .machine_check = cia_machine_check,
273  .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
274  .min_io_address = DEFAULT_IO_BASE,
275  .min_mem_address = CIA_DEFAULT_MEM_BASE,
276 
277  .nr_irqs = 128,
278  .device_interrupt = takara_device_interrupt,
279 
280  .init_arch = cia_init_arch,
281  .init_irq = takara_init_irq,
282  .init_rtc = common_init_rtc,
283  .init_pci = takara_init_pci,
284  .kill_arch = cia_kill_arch,
285  .pci_map_irq = takara_map_irq,
286  .pci_swizzle = takara_swizzle,
287 };
288 ALIAS_MV(takara)