Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * starfire.c: Starfire/E10000 support.
0004  *
0005  * Copyright (C) 1998 David S. Miller (davem@redhat.com)
0006  * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/slab.h>
0011 
0012 #include <asm/page.h>
0013 #include <asm/oplib.h>
0014 #include <asm/smp.h>
0015 #include <asm/upa.h>
0016 #include <asm/starfire.h>
0017 
0018 /*
0019  * A few places around the kernel check this to see if
0020  * they need to call us to do things in a Starfire specific
0021  * way.
0022  */
0023 int this_is_starfire = 0;
0024 
0025 void check_if_starfire(void)
0026 {
0027     phandle ssnode = prom_finddevice("/ssp-serial");
0028     if (ssnode != 0 && (s32)ssnode != -1)
0029         this_is_starfire = 1;
0030 }
0031 
0032 /*
0033  * Each Starfire board has 32 registers which perform translation
0034  * and delivery of traditional interrupt packets into the extended
0035  * Starfire hardware format.  Essentially UPAID's now have 2 more
0036  * bits than in all previous Sun5 systems.
0037  */
0038 struct starfire_irqinfo {
0039     unsigned long imap_slots[32];
0040     unsigned long tregs[32];
0041     struct starfire_irqinfo *next;
0042     int upaid, hwmid;
0043 };
0044 
0045 static struct starfire_irqinfo *sflist = NULL;
0046 
0047 /* Beam me up Scott(McNeil)y... */
0048 void starfire_hookup(int upaid)
0049 {
0050     struct starfire_irqinfo *p;
0051     unsigned long treg_base, hwmid, i;
0052 
0053     p = kmalloc(sizeof(*p), GFP_KERNEL);
0054     if (!p) {
0055         prom_printf("starfire_hookup: No memory, this is insane.\n");
0056         prom_halt();
0057     }
0058     treg_base = 0x100fc000000UL;
0059     hwmid = ((upaid & 0x3c) << 1) |
0060         ((upaid & 0x40) >> 4) |
0061         (upaid & 0x3);
0062     p->hwmid = hwmid;
0063     treg_base += (hwmid << 33UL);
0064     treg_base += 0x200UL;
0065     for (i = 0; i < 32; i++) {
0066         p->imap_slots[i] = 0UL;
0067         p->tregs[i] = treg_base + (i * 0x10UL);
0068         /* Lets play it safe and not overwrite existing mappings */
0069         if (upa_readl(p->tregs[i]) != 0)
0070             p->imap_slots[i] = 0xdeadbeaf;
0071     }
0072     p->upaid = upaid;
0073     p->next = sflist;
0074     sflist = p;
0075 }
0076 
0077 unsigned int starfire_translate(unsigned long imap,
0078                 unsigned int upaid)
0079 {
0080     struct starfire_irqinfo *p;
0081     unsigned int bus_hwmid;
0082     unsigned int i;
0083 
0084     bus_hwmid = (((unsigned long)imap) >> 33) & 0x7f;
0085     for (p = sflist; p != NULL; p = p->next)
0086         if (p->hwmid == bus_hwmid)
0087             break;
0088     if (p == NULL) {
0089         prom_printf("XFIRE: Cannot find irqinfo for imap %016lx\n",
0090                 ((unsigned long)imap));
0091         prom_halt();
0092     }
0093     for (i = 0; i < 32; i++) {
0094         if (p->imap_slots[i] == imap ||
0095             p->imap_slots[i] == 0UL)
0096             break;
0097     }
0098     if (i == 32) {
0099         printk("starfire_translate: Are you kidding me?\n");
0100         panic("Lucy in the sky....");
0101     }
0102     p->imap_slots[i] = imap;
0103 
0104     /* map to real upaid */
0105     upaid = (((upaid & 0x3c) << 1) |
0106          ((upaid & 0x40) >> 4) |
0107          (upaid & 0x3));
0108 
0109     upa_writel(upaid, p->tregs[i]);
0110 
0111     return i;
0112 }