cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

starfire.c (2636B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * starfire.c: Starfire/E10000 support.
      4 *
      5 * Copyright (C) 1998 David S. Miller (davem@redhat.com)
      6 * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
      7 */
      8
      9#include <linux/kernel.h>
     10#include <linux/slab.h>
     11
     12#include <asm/page.h>
     13#include <asm/oplib.h>
     14#include <asm/smp.h>
     15#include <asm/upa.h>
     16#include <asm/starfire.h>
     17
     18/*
     19 * A few places around the kernel check this to see if
     20 * they need to call us to do things in a Starfire specific
     21 * way.
     22 */
     23int this_is_starfire = 0;
     24
     25void check_if_starfire(void)
     26{
     27	phandle ssnode = prom_finddevice("/ssp-serial");
     28	if (ssnode != 0 && (s32)ssnode != -1)
     29		this_is_starfire = 1;
     30}
     31
     32/*
     33 * Each Starfire board has 32 registers which perform translation
     34 * and delivery of traditional interrupt packets into the extended
     35 * Starfire hardware format.  Essentially UPAID's now have 2 more
     36 * bits than in all previous Sun5 systems.
     37 */
     38struct starfire_irqinfo {
     39	unsigned long imap_slots[32];
     40	unsigned long tregs[32];
     41	struct starfire_irqinfo *next;
     42	int upaid, hwmid;
     43};
     44
     45static struct starfire_irqinfo *sflist = NULL;
     46
     47/* Beam me up Scott(McNeil)y... */
     48void starfire_hookup(int upaid)
     49{
     50	struct starfire_irqinfo *p;
     51	unsigned long treg_base, hwmid, i;
     52
     53	p = kmalloc(sizeof(*p), GFP_KERNEL);
     54	if (!p) {
     55		prom_printf("starfire_hookup: No memory, this is insane.\n");
     56		prom_halt();
     57	}
     58	treg_base = 0x100fc000000UL;
     59	hwmid = ((upaid & 0x3c) << 1) |
     60		((upaid & 0x40) >> 4) |
     61		(upaid & 0x3);
     62	p->hwmid = hwmid;
     63	treg_base += (hwmid << 33UL);
     64	treg_base += 0x200UL;
     65	for (i = 0; i < 32; i++) {
     66		p->imap_slots[i] = 0UL;
     67		p->tregs[i] = treg_base + (i * 0x10UL);
     68		/* Lets play it safe and not overwrite existing mappings */
     69		if (upa_readl(p->tregs[i]) != 0)
     70			p->imap_slots[i] = 0xdeadbeaf;
     71	}
     72	p->upaid = upaid;
     73	p->next = sflist;
     74	sflist = p;
     75}
     76
     77unsigned int starfire_translate(unsigned long imap,
     78				unsigned int upaid)
     79{
     80	struct starfire_irqinfo *p;
     81	unsigned int bus_hwmid;
     82	unsigned int i;
     83
     84	bus_hwmid = (((unsigned long)imap) >> 33) & 0x7f;
     85	for (p = sflist; p != NULL; p = p->next)
     86		if (p->hwmid == bus_hwmid)
     87			break;
     88	if (p == NULL) {
     89		prom_printf("XFIRE: Cannot find irqinfo for imap %016lx\n",
     90			    ((unsigned long)imap));
     91		prom_halt();
     92	}
     93	for (i = 0; i < 32; i++) {
     94		if (p->imap_slots[i] == imap ||
     95		    p->imap_slots[i] == 0UL)
     96			break;
     97	}
     98	if (i == 32) {
     99		printk("starfire_translate: Are you kidding me?\n");
    100		panic("Lucy in the sky....");
    101	}
    102	p->imap_slots[i] = imap;
    103
    104	/* map to real upaid */
    105	upaid = (((upaid & 0x3c) << 1) |
    106		 ((upaid & 0x40) >> 4) |
    107		 (upaid & 0x3));
    108
    109	upa_writel(upaid, p->tregs[i]);
    110
    111	return i;
    112}