Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  linux/arch/alpha/kernel/sys_nautilus.c
0004  *
0005  *  Copyright (C) 1995 David A Rusling
0006  *  Copyright (C) 1998 Richard Henderson
0007  *  Copyright (C) 1999 Alpha Processor, Inc.,
0008  *      (David Daniel, Stig Telfer, Soohoon Lee)
0009  *
0010  * Code supporting NAUTILUS systems.
0011  *
0012  *
0013  * NAUTILUS has the following I/O features:
0014  *
0015  * a) Driven by AMD 751 aka IRONGATE (northbridge):
0016  *     4 PCI slots
0017  *     1 AGP slot
0018  *
0019  * b) Driven by ALI M1543C (southbridge)
0020  *     2 ISA slots
0021  *     2 IDE connectors
0022  *     1 dual drive capable FDD controller
0023  *     2 serial ports
0024  *     1 ECP/EPP/SP parallel port
0025  *     2 USB ports
0026  */
0027 
0028 #include <linux/kernel.h>
0029 #include <linux/types.h>
0030 #include <linux/mm.h>
0031 #include <linux/sched.h>
0032 #include <linux/pci.h>
0033 #include <linux/init.h>
0034 #include <linux/reboot.h>
0035 #include <linux/memblock.h>
0036 #include <linux/bitops.h>
0037 
0038 #include <asm/ptrace.h>
0039 #include <asm/dma.h>
0040 #include <asm/irq.h>
0041 #include <asm/mmu_context.h>
0042 #include <asm/io.h>
0043 #include <asm/core_irongate.h>
0044 #include <asm/hwrpb.h>
0045 #include <asm/tlbflush.h>
0046 
0047 #include "proto.h"
0048 #include "err_impl.h"
0049 #include "irq_impl.h"
0050 #include "pci_impl.h"
0051 #include "machvec_impl.h"
0052 
0053 
0054 static void __init
0055 nautilus_init_irq(void)
0056 {
0057     if (alpha_using_srm) {
0058         alpha_mv.device_interrupt = srm_device_interrupt;
0059     }
0060 
0061     init_i8259a_irqs();
0062     common_init_isa_dma();
0063 }
0064 
0065 static int
0066 nautilus_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
0067 {
0068     /* Preserve the IRQ set up by the console.  */
0069 
0070     u8 irq;
0071     /* UP1500: AGP INTA is actually routed to IRQ 5, not IRQ 10 as
0072        console reports. Check the device id of AGP bridge to distinguish
0073        UP1500 from UP1000/1100. Note: 'pin' is 2 due to bridge swizzle. */
0074     if (slot == 1 && pin == 2 &&
0075         dev->bus->self && dev->bus->self->device == 0x700f)
0076         return 5;
0077     pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
0078     return irq;
0079 }
0080 
0081 void
0082 nautilus_kill_arch(int mode)
0083 {
0084     struct pci_bus *bus = pci_isa_hose->bus;
0085     u32 pmuport;
0086     int off;
0087 
0088     switch (mode) {
0089     case LINUX_REBOOT_CMD_RESTART:
0090         if (! alpha_using_srm) {
0091             u8 t8;
0092             pci_bus_read_config_byte(bus, 0x38, 0x43, &t8);
0093             pci_bus_write_config_byte(bus, 0x38, 0x43, t8 | 0x80);
0094             outb(1, 0x92);
0095             outb(0, 0x92);
0096             /* NOTREACHED */
0097         }
0098         break;
0099 
0100     case LINUX_REBOOT_CMD_POWER_OFF:
0101         /* Assume M1543C */
0102         off = 0x2000;       /* SLP_TYPE = 0, SLP_EN = 1 */
0103         pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
0104         if (!pmuport) {
0105             /* M1535D/D+ */
0106             off = 0x3400;   /* SLP_TYPE = 5, SLP_EN = 1 */
0107             pci_bus_read_config_dword(bus, 0x88, 0xe0, &pmuport);
0108         }
0109         pmuport &= 0xfffe;
0110         outw(0xffff, pmuport);  /* Clear pending events. */
0111         outw(off, pmuport + 4);
0112         /* NOTREACHED */
0113         break;
0114     }
0115 }
0116 
0117 /* Perform analysis of a machine check that arrived from the system (NMI) */
0118 
0119 static void
0120 naut_sys_machine_check(unsigned long vector, unsigned long la_ptr,
0121                struct pt_regs *regs)
0122 {
0123     printk("PC %lx RA %lx\n", regs->pc, regs->r26);
0124     irongate_pci_clr_err();
0125 }
0126 
0127 /* Machine checks can come from two sources - those on the CPU and those
0128    in the system.  They are analysed separately but all starts here.  */
0129 
0130 void
0131 nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
0132 {
0133     char *mchk_class;
0134 
0135     /* Now for some analysis.  Machine checks fall into two classes --
0136        those picked up by the system, and those picked up by the CPU.
0137        Add to that the two levels of severity - correctable or not.  */
0138 
0139     if (vector == SCB_Q_SYSMCHK
0140         && ((IRONGATE0->dramms & 0x300) == 0x300)) {
0141         unsigned long nmi_ctl;
0142 
0143         /* Clear ALI NMI */
0144         nmi_ctl = inb(0x61);
0145         nmi_ctl |= 0x0c;
0146         outb(nmi_ctl, 0x61);
0147         nmi_ctl &= ~0x0c;
0148         outb(nmi_ctl, 0x61);
0149 
0150         /* Write again clears error bits.  */
0151         IRONGATE0->stat_cmd = IRONGATE0->stat_cmd & ~0x100;
0152         mb();
0153         IRONGATE0->stat_cmd;
0154 
0155         /* Write again clears error bits.  */
0156         IRONGATE0->dramms = IRONGATE0->dramms;
0157         mb();
0158         IRONGATE0->dramms;
0159 
0160         draina();
0161         wrmces(0x7);
0162         mb();
0163         return;
0164     }
0165 
0166     if (vector == SCB_Q_SYSERR)
0167         mchk_class = "Correctable";
0168     else if (vector == SCB_Q_SYSMCHK)
0169         mchk_class = "Fatal";
0170     else {
0171         ev6_machine_check(vector, la_ptr);
0172         return;
0173     }
0174 
0175     printk(KERN_CRIT "NAUTILUS Machine check 0x%lx "
0176              "[%s System Machine Check (NMI)]\n",
0177            vector, mchk_class);
0178 
0179     naut_sys_machine_check(vector, la_ptr, get_irq_regs());
0180 
0181     /* Tell the PALcode to clear the machine check */
0182     draina();
0183     wrmces(0x7);
0184     mb();
0185 }
0186 
0187 extern void pcibios_claim_one_bus(struct pci_bus *);
0188 
0189 static struct resource irongate_mem = {
0190     .name   = "Irongate PCI MEM",
0191     .flags  = IORESOURCE_MEM,
0192 };
0193 static struct resource busn_resource = {
0194     .name   = "PCI busn",
0195     .start  = 0,
0196     .end    = 255,
0197     .flags  = IORESOURCE_BUS,
0198 };
0199 
0200 void __init
0201 nautilus_init_pci(void)
0202 {
0203     struct pci_controller *hose = hose_head;
0204     struct pci_host_bridge *bridge;
0205     struct pci_bus *bus;
0206     unsigned long bus_align, bus_size, pci_mem;
0207     unsigned long memtop = max_low_pfn << PAGE_SHIFT;
0208 
0209     bridge = pci_alloc_host_bridge(0);
0210     if (!bridge)
0211         return;
0212 
0213     /* Use default IO. */
0214     pci_add_resource(&bridge->windows, &ioport_resource);
0215     /* Irongate PCI memory aperture, calculate required size before
0216        setting it up. */
0217     pci_add_resource(&bridge->windows, &irongate_mem);
0218 
0219     pci_add_resource(&bridge->windows, &busn_resource);
0220     bridge->dev.parent = NULL;
0221     bridge->sysdata = hose;
0222     bridge->busnr = 0;
0223     bridge->ops = alpha_mv.pci_ops;
0224     bridge->swizzle_irq = alpha_mv.pci_swizzle;
0225     bridge->map_irq = alpha_mv.pci_map_irq;
0226     bridge->size_windows = 1;
0227 
0228     /* Scan our single hose.  */
0229     if (pci_scan_root_bus_bridge(bridge)) {
0230         pci_free_host_bridge(bridge);
0231         return;
0232     }
0233     bus = hose->bus = bridge->bus;
0234     pcibios_claim_one_bus(bus);
0235 
0236     pci_bus_size_bridges(bus);
0237 
0238     /* Now we've got the size and alignment of PCI memory resources
0239        stored in irongate_mem. Set up the PCI memory range: limit is
0240        hardwired to 0xffffffff, base must be aligned to 16Mb. */
0241     bus_align = irongate_mem.start;
0242     bus_size = irongate_mem.end + 1 - bus_align;
0243     if (bus_align < 0x1000000UL)
0244         bus_align = 0x1000000UL;
0245 
0246     pci_mem = (0x100000000UL - bus_size) & -bus_align;
0247     irongate_mem.start = pci_mem;
0248     irongate_mem.end = 0xffffffffUL;
0249 
0250     /* Register our newly calculated PCI memory window in the resource
0251        tree. */
0252     if (request_resource(&iomem_resource, &irongate_mem) < 0)
0253         printk(KERN_ERR "Failed to request MEM on hose 0\n");
0254 
0255     printk(KERN_INFO "Irongate pci_mem %pR\n", &irongate_mem);
0256 
0257     if (pci_mem < memtop)
0258         memtop = pci_mem;
0259     if (memtop > alpha_mv.min_mem_address) {
0260         free_reserved_area(__va(alpha_mv.min_mem_address),
0261                    __va(memtop), -1, NULL);
0262         printk(KERN_INFO "nautilus_init_pci: %ldk freed\n",
0263             (memtop - alpha_mv.min_mem_address) >> 10);
0264     }
0265     if ((IRONGATE0->dev_vendor >> 16) > 0x7006) /* Albacore? */
0266         IRONGATE0->pci_mem = pci_mem;
0267 
0268     pci_bus_assign_resources(bus);
0269     pci_bus_add_devices(bus);
0270 }
0271 
0272 /*
0273  * The System Vectors
0274  */
0275 
0276 struct alpha_machine_vector nautilus_mv __initmv = {
0277     .vector_name        = "Nautilus",
0278     DO_EV6_MMU,
0279     DO_DEFAULT_RTC,
0280     DO_IRONGATE_IO,
0281     .machine_check      = nautilus_machine_check,
0282     .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
0283     .min_io_address     = DEFAULT_IO_BASE,
0284     .min_mem_address    = IRONGATE_DEFAULT_MEM_BASE,
0285 
0286     .nr_irqs        = 16,
0287     .device_interrupt   = isa_device_interrupt,
0288 
0289     .init_arch      = irongate_init_arch,
0290     .init_irq       = nautilus_init_irq,
0291     .init_rtc       = common_init_rtc,
0292     .init_pci       = nautilus_init_pci,
0293     .kill_arch      = nautilus_kill_arch,
0294     .pci_map_irq        = nautilus_map_irq,
0295     .pci_swizzle        = common_swizzle,
0296 };
0297 ALIAS_MV(nautilus)