18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *	linux/arch/alpha/kernel/sys_miata.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *	Copyright (C) 1995 David A Rusling
68c2ecf20Sopenharmony_ci *	Copyright (C) 1996 Jay A Estabrook
78c2ecf20Sopenharmony_ci *	Copyright (C) 1998, 1999, 2000 Richard Henderson
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Code supporting the MIATA (EV56+PYXIS).
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/types.h>
148c2ecf20Sopenharmony_ci#include <linux/mm.h>
158c2ecf20Sopenharmony_ci#include <linux/sched.h>
168c2ecf20Sopenharmony_ci#include <linux/pci.h>
178c2ecf20Sopenharmony_ci#include <linux/init.h>
188c2ecf20Sopenharmony_ci#include <linux/reboot.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <asm/ptrace.h>
218c2ecf20Sopenharmony_ci#include <asm/dma.h>
228c2ecf20Sopenharmony_ci#include <asm/irq.h>
238c2ecf20Sopenharmony_ci#include <asm/mmu_context.h>
248c2ecf20Sopenharmony_ci#include <asm/io.h>
258c2ecf20Sopenharmony_ci#include <asm/core_cia.h>
268c2ecf20Sopenharmony_ci#include <asm/tlbflush.h>
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include "proto.h"
298c2ecf20Sopenharmony_ci#include "irq_impl.h"
308c2ecf20Sopenharmony_ci#include "pci_impl.h"
318c2ecf20Sopenharmony_ci#include "machvec_impl.h"
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic void
358c2ecf20Sopenharmony_cimiata_srm_device_interrupt(unsigned long vector)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	int irq;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	irq = (vector - 0x800) >> 4;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	/*
428c2ecf20Sopenharmony_ci	 * I really hate to do this, but the MIATA SRM console ignores the
438c2ecf20Sopenharmony_ci	 *  low 8 bits in the interrupt summary register, and reports the
448c2ecf20Sopenharmony_ci	 *  vector 0x80 *lower* than I expected from the bit numbering in
458c2ecf20Sopenharmony_ci	 *  the documentation.
468c2ecf20Sopenharmony_ci	 * This was done because the low 8 summary bits really aren't used
478c2ecf20Sopenharmony_ci	 *  for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
488c2ecf20Sopenharmony_ci	 *  used for this purpose, as PIC interrupts are delivered as the
498c2ecf20Sopenharmony_ci	 *  vectors 0x800-0x8f0).
508c2ecf20Sopenharmony_ci	 * But I really don't want to change the fixup code for allocation
518c2ecf20Sopenharmony_ci	 *  of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
528c2ecf20Sopenharmony_ci	 *  look nice and clean now.
538c2ecf20Sopenharmony_ci	 * So, here's this grotty hack... :-(
548c2ecf20Sopenharmony_ci	 */
558c2ecf20Sopenharmony_ci	if (irq >= 16)
568c2ecf20Sopenharmony_ci		irq = irq + 8;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	handle_irq(irq);
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic void __init
628c2ecf20Sopenharmony_cimiata_init_irq(void)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	if (alpha_using_srm)
658c2ecf20Sopenharmony_ci		alpha_mv.device_interrupt = miata_srm_device_interrupt;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#if 0
688c2ecf20Sopenharmony_ci	/* These break on MiataGL so we'll try not to do it at all.  */
698c2ecf20Sopenharmony_ci	*(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb();	/* ISA/NMI HI */
708c2ecf20Sopenharmony_ci	*(vulp)PYXIS_RT_COUNT = 0UL; mb();		/* clear count */
718c2ecf20Sopenharmony_ci#endif
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	init_i8259a_irqs();
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	/* Not interested in the bogus interrupts (3,10), Fan Fault (0),
768c2ecf20Sopenharmony_ci           NMI (1), or EIDE (9).
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	   We also disable the risers (4,5), since we don't know how to
798c2ecf20Sopenharmony_ci	   route the interrupts behind the bridge.  */
808c2ecf20Sopenharmony_ci	init_pyxis_irqs(0x63b0000);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	common_init_isa_dma();
838c2ecf20Sopenharmony_ci	if (request_irq(16 + 2, no_action, 0, "halt-switch", NULL))
848c2ecf20Sopenharmony_ci		pr_err("Failed to register halt-switch interrupt\n");
858c2ecf20Sopenharmony_ci	if (request_irq(16 + 6, no_action, 0, "timer-cascade", NULL))
868c2ecf20Sopenharmony_ci		pr_err("Failed to register timer-cascade interrupt\n");
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/*
918c2ecf20Sopenharmony_ci * PCI Fixup configuration.
928c2ecf20Sopenharmony_ci *
938c2ecf20Sopenharmony_ci * Summary @ PYXIS_INT_REQ:
948c2ecf20Sopenharmony_ci * Bit      Meaning
958c2ecf20Sopenharmony_ci * 0        Fan Fault
968c2ecf20Sopenharmony_ci * 1        NMI
978c2ecf20Sopenharmony_ci * 2        Halt/Reset switch
988c2ecf20Sopenharmony_ci * 3        none
998c2ecf20Sopenharmony_ci * 4        CID0 (Riser ID)
1008c2ecf20Sopenharmony_ci * 5        CID1 (Riser ID)
1018c2ecf20Sopenharmony_ci * 6        Interval timer
1028c2ecf20Sopenharmony_ci * 7        PCI-ISA Bridge
1038c2ecf20Sopenharmony_ci * 8        Ethernet
1048c2ecf20Sopenharmony_ci * 9        EIDE (deprecated, ISA 14/15 used)
1058c2ecf20Sopenharmony_ci *10        none
1068c2ecf20Sopenharmony_ci *11        USB
1078c2ecf20Sopenharmony_ci *12        Interrupt Line A from slot 4
1088c2ecf20Sopenharmony_ci *13        Interrupt Line B from slot 4
1098c2ecf20Sopenharmony_ci *14        Interrupt Line C from slot 4
1108c2ecf20Sopenharmony_ci *15        Interrupt Line D from slot 4
1118c2ecf20Sopenharmony_ci *16        Interrupt Line A from slot 5
1128c2ecf20Sopenharmony_ci *17        Interrupt line B from slot 5
1138c2ecf20Sopenharmony_ci *18        Interrupt Line C from slot 5
1148c2ecf20Sopenharmony_ci *19        Interrupt Line D from slot 5
1158c2ecf20Sopenharmony_ci *20        Interrupt Line A from slot 1
1168c2ecf20Sopenharmony_ci *21        Interrupt Line B from slot 1
1178c2ecf20Sopenharmony_ci *22        Interrupt Line C from slot 1
1188c2ecf20Sopenharmony_ci *23        Interrupt Line D from slot 1
1198c2ecf20Sopenharmony_ci *24        Interrupt Line A from slot 2
1208c2ecf20Sopenharmony_ci *25        Interrupt Line B from slot 2
1218c2ecf20Sopenharmony_ci *26        Interrupt Line C from slot 2
1228c2ecf20Sopenharmony_ci *27        Interrupt Line D from slot 2
1238c2ecf20Sopenharmony_ci *27        Interrupt Line A from slot 3
1248c2ecf20Sopenharmony_ci *29        Interrupt Line B from slot 3
1258c2ecf20Sopenharmony_ci *30        Interrupt Line C from slot 3
1268c2ecf20Sopenharmony_ci *31        Interrupt Line D from slot 3
1278c2ecf20Sopenharmony_ci *
1288c2ecf20Sopenharmony_ci * The device to slot mapping looks like:
1298c2ecf20Sopenharmony_ci *
1308c2ecf20Sopenharmony_ci * Slot     Device
1318c2ecf20Sopenharmony_ci *  3       DC21142 Ethernet
1328c2ecf20Sopenharmony_ci *  4       EIDE CMD646
1338c2ecf20Sopenharmony_ci *  5       none
1348c2ecf20Sopenharmony_ci *  6       USB
1358c2ecf20Sopenharmony_ci *  7       PCI-ISA bridge
1368c2ecf20Sopenharmony_ci *  8       PCI-PCI Bridge      (SBU Riser)
1378c2ecf20Sopenharmony_ci *  9       none
1388c2ecf20Sopenharmony_ci * 10       none
1398c2ecf20Sopenharmony_ci * 11       PCI on board slot 4 (SBU Riser)
1408c2ecf20Sopenharmony_ci * 12       PCI on board slot 5 (SBU Riser)
1418c2ecf20Sopenharmony_ci *
1428c2ecf20Sopenharmony_ci *  These are behind the bridge, so I'm not sure what to do...
1438c2ecf20Sopenharmony_ci *
1448c2ecf20Sopenharmony_ci * 13       PCI on board slot 1 (SBU Riser)
1458c2ecf20Sopenharmony_ci * 14       PCI on board slot 2 (SBU Riser)
1468c2ecf20Sopenharmony_ci * 15       PCI on board slot 3 (SBU Riser)
1478c2ecf20Sopenharmony_ci *
1488c2ecf20Sopenharmony_ci *
1498c2ecf20Sopenharmony_ci * This two layered interrupt approach means that we allocate IRQ 16 and
1508c2ecf20Sopenharmony_ci * above for PCI interrupts.  The IRQ relates to which bit the interrupt
1518c2ecf20Sopenharmony_ci * comes in on.  This makes interrupt processing much easier.
1528c2ecf20Sopenharmony_ci */
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_cistatic int
1558c2ecf20Sopenharmony_cimiata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci        static char irq_tab[18][5] = {
1588c2ecf20Sopenharmony_ci		/*INT    INTA   INTB   INTC   INTD */
1598c2ecf20Sopenharmony_ci		{16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8},  /* IdSel 14,  DC21142 */
1608c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 15,  EIDE    */
1618c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 16,  none    */
1628c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 17,  none    */
1638c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 18,  PCI-ISA */
1648c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 19,  PCI-PCI */
1658c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 20,  none    */
1668c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 21,  none    */
1678c2ecf20Sopenharmony_ci		{16+12, 16+12, 16+13, 16+14, 16+15},  /* IdSel 22,  slot 4  */
1688c2ecf20Sopenharmony_ci		{16+16, 16+16, 16+17, 16+18, 16+19},  /* IdSel 23,  slot 5  */
1698c2ecf20Sopenharmony_ci		/* the next 7 are actually on PCI bus 1, across the bridge */
1708c2ecf20Sopenharmony_ci		{16+11, 16+11, 16+11, 16+11, 16+11},  /* IdSel 24,  QLISP/GL*/
1718c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 25,  none    */
1728c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 26,  none    */
1738c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 27,  none    */
1748c2ecf20Sopenharmony_ci		{16+20, 16+20, 16+21, 16+22, 16+23},  /* IdSel 28,  slot 1  */
1758c2ecf20Sopenharmony_ci		{16+24, 16+24, 16+25, 16+26, 16+27},  /* IdSel 29,  slot 2  */
1768c2ecf20Sopenharmony_ci		{16+28, 16+28, 16+29, 16+30, 16+31},  /* IdSel 30,  slot 3  */
1778c2ecf20Sopenharmony_ci		/* This bridge is on the main bus of the later orig MIATA */
1788c2ecf20Sopenharmony_ci		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 31,  PCI-PCI */
1798c2ecf20Sopenharmony_ci        };
1808c2ecf20Sopenharmony_ci	const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	/* the USB function of the 82c693 has it's interrupt connected to
1838c2ecf20Sopenharmony_ci           the 2nd 8259 controller. So we have to check for it first. */
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if((slot == 7) && (PCI_FUNC(dev->devfn) == 3)) {
1868c2ecf20Sopenharmony_ci		u8 irq=0;
1878c2ecf20Sopenharmony_ci		struct pci_dev *pdev = pci_get_slot(dev->bus, dev->devfn & ~7);
1888c2ecf20Sopenharmony_ci		if(pdev == NULL || pci_read_config_byte(pdev, 0x40,&irq) != PCIBIOS_SUCCESSFUL) {
1898c2ecf20Sopenharmony_ci			pci_dev_put(pdev);
1908c2ecf20Sopenharmony_ci			return -1;
1918c2ecf20Sopenharmony_ci		}
1928c2ecf20Sopenharmony_ci		else	{
1938c2ecf20Sopenharmony_ci			pci_dev_put(pdev);
1948c2ecf20Sopenharmony_ci			return irq;
1958c2ecf20Sopenharmony_ci		}
1968c2ecf20Sopenharmony_ci	}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	return COMMON_TABLE_LOOKUP;
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_cistatic u8
2028c2ecf20Sopenharmony_cimiata_swizzle(struct pci_dev *dev, u8 *pinp)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	int slot, pin = *pinp;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	if (dev->bus->number == 0) {
2078c2ecf20Sopenharmony_ci		slot = PCI_SLOT(dev->devfn);
2088c2ecf20Sopenharmony_ci	}
2098c2ecf20Sopenharmony_ci	/* Check for the built-in bridge.  */
2108c2ecf20Sopenharmony_ci	else if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
2118c2ecf20Sopenharmony_ci		 (PCI_SLOT(dev->bus->self->devfn) == 20)) {
2128c2ecf20Sopenharmony_ci		slot = PCI_SLOT(dev->devfn) + 9;
2138c2ecf20Sopenharmony_ci	}
2148c2ecf20Sopenharmony_ci	else
2158c2ecf20Sopenharmony_ci	{
2168c2ecf20Sopenharmony_ci		/* Must be a card-based bridge.  */
2178c2ecf20Sopenharmony_ci		do {
2188c2ecf20Sopenharmony_ci			if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
2198c2ecf20Sopenharmony_ci			    (PCI_SLOT(dev->bus->self->devfn) == 20)) {
2208c2ecf20Sopenharmony_ci				slot = PCI_SLOT(dev->devfn) + 9;
2218c2ecf20Sopenharmony_ci				break;
2228c2ecf20Sopenharmony_ci			}
2238c2ecf20Sopenharmony_ci			pin = pci_swizzle_interrupt_pin(dev, pin);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci			/* Move up the chain of bridges.  */
2268c2ecf20Sopenharmony_ci			dev = dev->bus->self;
2278c2ecf20Sopenharmony_ci			/* Slot of the next bridge.  */
2288c2ecf20Sopenharmony_ci			slot = PCI_SLOT(dev->devfn);
2298c2ecf20Sopenharmony_ci		} while (dev->bus->self);
2308c2ecf20Sopenharmony_ci	}
2318c2ecf20Sopenharmony_ci	*pinp = pin;
2328c2ecf20Sopenharmony_ci	return slot;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic void __init
2368c2ecf20Sopenharmony_cimiata_init_pci(void)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	cia_init_pci();
2398c2ecf20Sopenharmony_ci	SMC669_Init(0); /* it might be a GL (fails harmlessly if not) */
2408c2ecf20Sopenharmony_ci	es1888_init();
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistatic void
2448c2ecf20Sopenharmony_cimiata_kill_arch(int mode)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	cia_kill_arch(mode);
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci#ifndef ALPHA_RESTORE_SRM_SETUP
2498c2ecf20Sopenharmony_ci	switch(mode) {
2508c2ecf20Sopenharmony_ci	case LINUX_REBOOT_CMD_RESTART:
2518c2ecf20Sopenharmony_ci		/* Who said DEC engineers have no sense of humor? ;-)  */
2528c2ecf20Sopenharmony_ci		if (alpha_using_srm) {
2538c2ecf20Sopenharmony_ci			*(vuip) PYXIS_RESET = 0x0000dead;
2548c2ecf20Sopenharmony_ci			mb();
2558c2ecf20Sopenharmony_ci		}
2568c2ecf20Sopenharmony_ci		break;
2578c2ecf20Sopenharmony_ci	case LINUX_REBOOT_CMD_HALT:
2588c2ecf20Sopenharmony_ci		break;
2598c2ecf20Sopenharmony_ci	case LINUX_REBOOT_CMD_POWER_OFF:
2608c2ecf20Sopenharmony_ci		break;
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	halt();
2648c2ecf20Sopenharmony_ci#endif
2658c2ecf20Sopenharmony_ci}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci/*
2698c2ecf20Sopenharmony_ci * The System Vector
2708c2ecf20Sopenharmony_ci */
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistruct alpha_machine_vector miata_mv __initmv = {
2738c2ecf20Sopenharmony_ci	.vector_name		= "Miata",
2748c2ecf20Sopenharmony_ci	DO_EV5_MMU,
2758c2ecf20Sopenharmony_ci	DO_DEFAULT_RTC,
2768c2ecf20Sopenharmony_ci	DO_PYXIS_IO,
2778c2ecf20Sopenharmony_ci	.machine_check		= cia_machine_check,
2788c2ecf20Sopenharmony_ci	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
2798c2ecf20Sopenharmony_ci	.min_io_address		= DEFAULT_IO_BASE,
2808c2ecf20Sopenharmony_ci	.min_mem_address	= DEFAULT_MEM_BASE,
2818c2ecf20Sopenharmony_ci	.pci_dac_offset		= PYXIS_DAC_OFFSET,
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	.nr_irqs		= 48,
2848c2ecf20Sopenharmony_ci	.device_interrupt	= pyxis_device_interrupt,
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	.init_arch		= pyxis_init_arch,
2878c2ecf20Sopenharmony_ci	.init_irq		= miata_init_irq,
2888c2ecf20Sopenharmony_ci	.init_rtc		= common_init_rtc,
2898c2ecf20Sopenharmony_ci	.init_pci		= miata_init_pci,
2908c2ecf20Sopenharmony_ci	.kill_arch		= miata_kill_arch,
2918c2ecf20Sopenharmony_ci	.pci_map_irq		= miata_map_irq,
2928c2ecf20Sopenharmony_ci	.pci_swizzle		= miata_swizzle,
2938c2ecf20Sopenharmony_ci};
2948c2ecf20Sopenharmony_ciALIAS_MV(miata)
295