~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/alpha/kernel/sys_sable.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php