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