1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/arch/alpha/kernel/core_irongate.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Copyright (C) 1999 Alpha Processor, Inc.,
81da177e4SLinus Torvalds * (David Daniel, Stig Telfer, Soohoon Lee)
91da177e4SLinus Torvalds *
101da177e4SLinus Torvalds * Code common to all IRONGATE core logic chips.
111da177e4SLinus Torvalds */
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds #define __EXTERN_INLINE inline
141da177e4SLinus Torvalds #include <asm/io.h>
151da177e4SLinus Torvalds #include <asm/core_irongate.h>
161da177e4SLinus Torvalds #undef __EXTERN_INLINE
171da177e4SLinus Torvalds
181da177e4SLinus Torvalds #include <linux/types.h>
191da177e4SLinus Torvalds #include <linux/pci.h>
201da177e4SLinus Torvalds #include <linux/sched.h>
211da177e4SLinus Torvalds #include <linux/init.h>
221da177e4SLinus Torvalds #include <linux/initrd.h>
236471f52aSMike Rapoport #include <linux/memblock.h>
241da177e4SLinus Torvalds
251da177e4SLinus Torvalds #include <asm/ptrace.h>
261da177e4SLinus Torvalds #include <asm/cacheflush.h>
271da177e4SLinus Torvalds #include <asm/tlbflush.h>
281da177e4SLinus Torvalds
291da177e4SLinus Torvalds #include "proto.h"
301da177e4SLinus Torvalds #include "pci_impl.h"
311da177e4SLinus Torvalds
321da177e4SLinus Torvalds /*
331da177e4SLinus Torvalds * BIOS32-style PCI interface:
341da177e4SLinus Torvalds */
351da177e4SLinus Torvalds
361da177e4SLinus Torvalds #define DEBUG_CONFIG 0
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds #if DEBUG_CONFIG
391da177e4SLinus Torvalds # define DBG_CFG(args) printk args
401da177e4SLinus Torvalds #else
411da177e4SLinus Torvalds # define DBG_CFG(args)
421da177e4SLinus Torvalds #endif
431da177e4SLinus Torvalds
441da177e4SLinus Torvalds igcsr32 *IronECC;
451da177e4SLinus Torvalds
461da177e4SLinus Torvalds /*
471da177e4SLinus Torvalds * Given a bus, device, and function number, compute resulting
481da177e4SLinus Torvalds * configuration space address accordingly. It is therefore not safe
491da177e4SLinus Torvalds * to have concurrent invocations to configuration space access
501da177e4SLinus Torvalds * routines, but there really shouldn't be any need for this.
511da177e4SLinus Torvalds *
521da177e4SLinus Torvalds * addr[31:24] reserved
531da177e4SLinus Torvalds * addr[23:16] bus number (8 bits = 128 possible buses)
541da177e4SLinus Torvalds * addr[15:11] Device number (5 bits)
551da177e4SLinus Torvalds * addr[10: 8] function number
561da177e4SLinus Torvalds * addr[ 7: 2] register number
571da177e4SLinus Torvalds *
581da177e4SLinus Torvalds * For IRONGATE:
591da177e4SLinus Torvalds * if (bus = addr[23:16]) == 0
601da177e4SLinus Torvalds * then
611da177e4SLinus Torvalds * type 0 config cycle:
621da177e4SLinus Torvalds * addr_on_pci[31:11] = id selection for device = addr[15:11]
631da177e4SLinus Torvalds * addr_on_pci[10: 2] = addr[10: 2] ???
641da177e4SLinus Torvalds * addr_on_pci[ 1: 0] = 00
651da177e4SLinus Torvalds * else
661da177e4SLinus Torvalds * type 1 config cycle (pass on with no decoding):
671da177e4SLinus Torvalds * addr_on_pci[31:24] = 0
681da177e4SLinus Torvalds * addr_on_pci[23: 2] = addr[23: 2]
691da177e4SLinus Torvalds * addr_on_pci[ 1: 0] = 01
701da177e4SLinus Torvalds * fi
711da177e4SLinus Torvalds *
721da177e4SLinus Torvalds * Notes:
731da177e4SLinus Torvalds * The function number selects which function of a multi-function device
741da177e4SLinus Torvalds * (e.g., SCSI and Ethernet).
751da177e4SLinus Torvalds *
761da177e4SLinus Torvalds * The register selects a DWORD (32 bit) register offset. Hence it
771da177e4SLinus Torvalds * doesn't get shifted by 2 bits as we want to "drop" the bottom two
781da177e4SLinus Torvalds * bits.
791da177e4SLinus Torvalds */
801da177e4SLinus Torvalds
811da177e4SLinus Torvalds static int
mk_conf_addr(struct pci_bus * pbus,unsigned int device_fn,int where,unsigned long * pci_addr,unsigned char * type1)821da177e4SLinus Torvalds mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
831da177e4SLinus Torvalds unsigned long *pci_addr, unsigned char *type1)
841da177e4SLinus Torvalds {
851da177e4SLinus Torvalds unsigned long addr;
861da177e4SLinus Torvalds u8 bus = pbus->number;
871da177e4SLinus Torvalds
881da177e4SLinus Torvalds DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
891da177e4SLinus Torvalds "pci_addr=0x%p, type1=0x%p)\n",
901da177e4SLinus Torvalds bus, device_fn, where, pci_addr, type1));
911da177e4SLinus Torvalds
921da177e4SLinus Torvalds *type1 = (bus != 0);
931da177e4SLinus Torvalds
941da177e4SLinus Torvalds addr = (bus << 16) | (device_fn << 8) | where;
951da177e4SLinus Torvalds addr |= IRONGATE_CONF;
961da177e4SLinus Torvalds
971da177e4SLinus Torvalds *pci_addr = addr;
981da177e4SLinus Torvalds DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
991da177e4SLinus Torvalds return 0;
1001da177e4SLinus Torvalds }
1011da177e4SLinus Torvalds
1021da177e4SLinus Torvalds static int
irongate_read_config(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 * value)1031da177e4SLinus Torvalds irongate_read_config(struct pci_bus *bus, unsigned int devfn, int where,
1041da177e4SLinus Torvalds int size, u32 *value)
1051da177e4SLinus Torvalds {
1061da177e4SLinus Torvalds unsigned long addr;
1071da177e4SLinus Torvalds unsigned char type1;
1081da177e4SLinus Torvalds
1091da177e4SLinus Torvalds if (mk_conf_addr(bus, devfn, where, &addr, &type1))
1101da177e4SLinus Torvalds return PCIBIOS_DEVICE_NOT_FOUND;
1111da177e4SLinus Torvalds
1121da177e4SLinus Torvalds switch (size) {
1131da177e4SLinus Torvalds case 1:
1141da177e4SLinus Torvalds *value = __kernel_ldbu(*(vucp)addr);
1151da177e4SLinus Torvalds break;
1161da177e4SLinus Torvalds case 2:
1171da177e4SLinus Torvalds *value = __kernel_ldwu(*(vusp)addr);
1181da177e4SLinus Torvalds break;
1191da177e4SLinus Torvalds case 4:
1201da177e4SLinus Torvalds *value = *(vuip)addr;
1211da177e4SLinus Torvalds break;
1221da177e4SLinus Torvalds }
1231da177e4SLinus Torvalds
1241da177e4SLinus Torvalds return PCIBIOS_SUCCESSFUL;
1251da177e4SLinus Torvalds }
1261da177e4SLinus Torvalds
1271da177e4SLinus Torvalds static int
irongate_write_config(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 value)1281da177e4SLinus Torvalds irongate_write_config(struct pci_bus *bus, unsigned int devfn, int where,
1291da177e4SLinus Torvalds int size, u32 value)
1301da177e4SLinus Torvalds {
1311da177e4SLinus Torvalds unsigned long addr;
1321da177e4SLinus Torvalds unsigned char type1;
1331da177e4SLinus Torvalds
1341da177e4SLinus Torvalds if (mk_conf_addr(bus, devfn, where, &addr, &type1))
1351da177e4SLinus Torvalds return PCIBIOS_DEVICE_NOT_FOUND;
1361da177e4SLinus Torvalds
1371da177e4SLinus Torvalds switch (size) {
1381da177e4SLinus Torvalds case 1:
1391da177e4SLinus Torvalds __kernel_stb(value, *(vucp)addr);
1401da177e4SLinus Torvalds mb();
1411da177e4SLinus Torvalds __kernel_ldbu(*(vucp)addr);
1421da177e4SLinus Torvalds break;
1431da177e4SLinus Torvalds case 2:
1441da177e4SLinus Torvalds __kernel_stw(value, *(vusp)addr);
1451da177e4SLinus Torvalds mb();
1461da177e4SLinus Torvalds __kernel_ldwu(*(vusp)addr);
1471da177e4SLinus Torvalds break;
1481da177e4SLinus Torvalds case 4:
1491da177e4SLinus Torvalds *(vuip)addr = value;
1501da177e4SLinus Torvalds mb();
1511da177e4SLinus Torvalds *(vuip)addr;
1521da177e4SLinus Torvalds break;
1531da177e4SLinus Torvalds }
1541da177e4SLinus Torvalds
1551da177e4SLinus Torvalds return PCIBIOS_SUCCESSFUL;
1561da177e4SLinus Torvalds }
1571da177e4SLinus Torvalds
1581da177e4SLinus Torvalds struct pci_ops irongate_pci_ops =
1591da177e4SLinus Torvalds {
1601da177e4SLinus Torvalds .read = irongate_read_config,
1611da177e4SLinus Torvalds .write = irongate_write_config,
1621da177e4SLinus Torvalds };
1631da177e4SLinus Torvalds
1641da177e4SLinus Torvalds int
irongate_pci_clr_err(void)1651da177e4SLinus Torvalds irongate_pci_clr_err(void)
1661da177e4SLinus Torvalds {
1671da177e4SLinus Torvalds unsigned int nmi_ctl=0;
1681da177e4SLinus Torvalds unsigned int IRONGATE_jd;
1691da177e4SLinus Torvalds
1701da177e4SLinus Torvalds again:
1711da177e4SLinus Torvalds IRONGATE_jd = IRONGATE0->stat_cmd;
1721da177e4SLinus Torvalds printk("Iron stat_cmd %x\n", IRONGATE_jd);
1731da177e4SLinus Torvalds IRONGATE0->stat_cmd = IRONGATE_jd; /* write again clears error bits */
1741da177e4SLinus Torvalds mb();
1751da177e4SLinus Torvalds IRONGATE_jd = IRONGATE0->stat_cmd; /* re-read to force write */
1761da177e4SLinus Torvalds
1771da177e4SLinus Torvalds IRONGATE_jd = *IronECC;
1781da177e4SLinus Torvalds printk("Iron ECC %x\n", IRONGATE_jd);
1791da177e4SLinus Torvalds *IronECC = IRONGATE_jd; /* write again clears error bits */
1801da177e4SLinus Torvalds mb();
1811da177e4SLinus Torvalds IRONGATE_jd = *IronECC; /* re-read to force write */
1821da177e4SLinus Torvalds
1831da177e4SLinus Torvalds /* Clear ALI NMI */
1841da177e4SLinus Torvalds nmi_ctl = inb(0x61);
1851da177e4SLinus Torvalds nmi_ctl |= 0x0c;
1861da177e4SLinus Torvalds outb(nmi_ctl, 0x61);
1871da177e4SLinus Torvalds nmi_ctl &= ~0x0c;
1881da177e4SLinus Torvalds outb(nmi_ctl, 0x61);
1891da177e4SLinus Torvalds
1901da177e4SLinus Torvalds IRONGATE_jd = *IronECC;
1911da177e4SLinus Torvalds if (IRONGATE_jd & 0x300) goto again;
1921da177e4SLinus Torvalds
1931da177e4SLinus Torvalds return 0;
1941da177e4SLinus Torvalds }
1951da177e4SLinus Torvalds
1961da177e4SLinus Torvalds #define IRONGATE_3GB 0xc0000000UL
1971da177e4SLinus Torvalds
1981da177e4SLinus Torvalds /* On Albacore (aka UP1500) with 4Gb of RAM we have to reserve some
1991da177e4SLinus Torvalds memory for PCI. At this point we just reserve memory above 3Gb. Most
2001da177e4SLinus Torvalds of this memory will be freed after PCI setup is done. */
2011da177e4SLinus Torvalds static void __init
albacore_init_arch(void)2021da177e4SLinus Torvalds albacore_init_arch(void)
2031da177e4SLinus Torvalds {
2041da177e4SLinus Torvalds unsigned long memtop = max_low_pfn << PAGE_SHIFT;
2051da177e4SLinus Torvalds unsigned long pci_mem = (memtop + 0x1000000UL) & ~0xffffffUL;
2061da177e4SLinus Torvalds struct percpu_struct *cpu;
2071da177e4SLinus Torvalds int pal_rev, pal_var;
2081da177e4SLinus Torvalds
2091da177e4SLinus Torvalds cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
2101da177e4SLinus Torvalds pal_rev = cpu->pal_revision & 0xffff;
2111da177e4SLinus Torvalds pal_var = (cpu->pal_revision >> 16) & 0xff;
2121da177e4SLinus Torvalds
2131da177e4SLinus Torvalds /* Consoles earlier than A5.6-18 (OSF PALcode v1.62-2) set up
2141da177e4SLinus Torvalds the CPU incorrectly (leave speculative stores enabled),
2151da177e4SLinus Torvalds which causes memory corruption under certain conditions.
2161da177e4SLinus Torvalds Issue a warning for such consoles. */
2171da177e4SLinus Torvalds if (alpha_using_srm &&
2181da177e4SLinus Torvalds (pal_rev < 0x13e || (pal_rev == 0x13e && pal_var < 2)))
2191da177e4SLinus Torvalds printk(KERN_WARNING "WARNING! Upgrade to SRM A5.6-19 "
2201da177e4SLinus Torvalds "or later\n");
2211da177e4SLinus Torvalds
2221da177e4SLinus Torvalds if (pci_mem > IRONGATE_3GB)
2231da177e4SLinus Torvalds pci_mem = IRONGATE_3GB;
2241da177e4SLinus Torvalds IRONGATE0->pci_mem = pci_mem;
2251da177e4SLinus Torvalds alpha_mv.min_mem_address = pci_mem;
2261da177e4SLinus Torvalds if (memtop > pci_mem) {
2271da177e4SLinus Torvalds #ifdef CONFIG_BLK_DEV_INITRD
2281da177e4SLinus Torvalds extern unsigned long initrd_start, initrd_end;
2291da177e4SLinus Torvalds extern void *move_initrd(unsigned long);
2301da177e4SLinus Torvalds
2311da177e4SLinus Torvalds /* Move the initrd out of the way. */
2321da177e4SLinus Torvalds if (initrd_end && __pa(initrd_end) > pci_mem) {
2331da177e4SLinus Torvalds unsigned long size;
2341da177e4SLinus Torvalds
2351da177e4SLinus Torvalds size = initrd_end - initrd_start;
236*4421cca0SMike Rapoport memblock_free((void *)initrd_start, PAGE_ALIGN(size));
2371da177e4SLinus Torvalds if (!move_initrd(pci_mem))
2381da177e4SLinus Torvalds printk("irongate_init_arch: initrd too big "
2391da177e4SLinus Torvalds "(%ldK)\ndisabling initrd\n",
2401da177e4SLinus Torvalds size / 1024);
2411da177e4SLinus Torvalds }
2421da177e4SLinus Torvalds #endif
2436471f52aSMike Rapoport memblock_reserve(pci_mem, memtop - pci_mem);
2441da177e4SLinus Torvalds printk("irongate_init_arch: temporarily reserving "
2451da177e4SLinus Torvalds "region %08lx-%08lx for PCI\n", pci_mem, memtop - 1);
2461da177e4SLinus Torvalds }
2471da177e4SLinus Torvalds }
2481da177e4SLinus Torvalds
2491da177e4SLinus Torvalds static void __init
irongate_setup_agp(void)2501da177e4SLinus Torvalds irongate_setup_agp(void)
2511da177e4SLinus Torvalds {
2521da177e4SLinus Torvalds /* Disable the GART window. AGPGART doesn't work due to yet
2531da177e4SLinus Torvalds unresolved memory coherency issues... */
2541da177e4SLinus Torvalds IRONGATE0->agpva = IRONGATE0->agpva & ~0xf;
2551da177e4SLinus Torvalds alpha_agpgart_size = 0;
2561da177e4SLinus Torvalds }
2571da177e4SLinus Torvalds
2581da177e4SLinus Torvalds void __init
irongate_init_arch(void)2591da177e4SLinus Torvalds irongate_init_arch(void)
2601da177e4SLinus Torvalds {
2611da177e4SLinus Torvalds struct pci_controller *hose;
2621da177e4SLinus Torvalds int amd761 = (IRONGATE0->dev_vendor >> 16) > 0x7006; /* Albacore? */
2631da177e4SLinus Torvalds
2641da177e4SLinus Torvalds IronECC = amd761 ? &IRONGATE0->bacsr54_eccms761 : &IRONGATE0->dramms;
2651da177e4SLinus Torvalds
2661da177e4SLinus Torvalds irongate_pci_clr_err();
2671da177e4SLinus Torvalds
2681da177e4SLinus Torvalds if (amd761)
2691da177e4SLinus Torvalds albacore_init_arch();
2701da177e4SLinus Torvalds
2711da177e4SLinus Torvalds irongate_setup_agp();
2721da177e4SLinus Torvalds
2731da177e4SLinus Torvalds /*
2741da177e4SLinus Torvalds * Create our single hose.
2751da177e4SLinus Torvalds */
2761da177e4SLinus Torvalds
2771da177e4SLinus Torvalds pci_isa_hose = hose = alloc_pci_controller();
2781da177e4SLinus Torvalds hose->io_space = &ioport_resource;
2791da177e4SLinus Torvalds hose->mem_space = &iomem_resource;
2801da177e4SLinus Torvalds hose->index = 0;
2811da177e4SLinus Torvalds
2821da177e4SLinus Torvalds /* This is for userland consumption. For some reason, the 40-bit
2831da177e4SLinus Torvalds PIO bias that we use in the kernel through KSEG didn't work for
2841da177e4SLinus Torvalds the page table based user mappings. So make sure we get the
2851da177e4SLinus Torvalds 43-bit PIO bias. */
2861da177e4SLinus Torvalds hose->sparse_mem_base = 0;
2871da177e4SLinus Torvalds hose->sparse_io_base = 0;
2881da177e4SLinus Torvalds hose->dense_mem_base
2891da177e4SLinus Torvalds = (IRONGATE_MEM & 0xffffffffffUL) | 0x80000000000UL;
2901da177e4SLinus Torvalds hose->dense_io_base
2911da177e4SLinus Torvalds = (IRONGATE_IO & 0xffffffffffUL) | 0x80000000000UL;
2921da177e4SLinus Torvalds
2931da177e4SLinus Torvalds hose->sg_isa = hose->sg_pci = NULL;
2941da177e4SLinus Torvalds __direct_map_base = 0;
2951da177e4SLinus Torvalds __direct_map_size = 0xffffffff;
2961da177e4SLinus Torvalds }
2971da177e4SLinus Torvalds
2981da177e4SLinus Torvalds /*
2991da177e4SLinus Torvalds * IO map and AGP support
3001da177e4SLinus Torvalds */
3011da177e4SLinus Torvalds #include <linux/vmalloc.h>
3021da177e4SLinus Torvalds #include <linux/agp_backend.h>
3031da177e4SLinus Torvalds #include <linux/agpgart.h>
30400cd1176SPaul Gortmaker #include <linux/export.h>
3051da177e4SLinus Torvalds
3061da177e4SLinus Torvalds #define GET_PAGE_DIR_OFF(addr) (addr >> 22)
3071da177e4SLinus Torvalds #define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr))
3081da177e4SLinus Torvalds
3091da177e4SLinus Torvalds #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
3101da177e4SLinus Torvalds #define GET_GATT(addr) (gatt_pages[GET_PAGE_DIR_IDX(addr)])
3111da177e4SLinus Torvalds
3121da177e4SLinus Torvalds void __iomem *
irongate_ioremap(unsigned long addr,unsigned long size)3131da177e4SLinus Torvalds irongate_ioremap(unsigned long addr, unsigned long size)
3141da177e4SLinus Torvalds {
3151da177e4SLinus Torvalds struct vm_struct *area;
3161da177e4SLinus Torvalds unsigned long vaddr;
3171da177e4SLinus Torvalds unsigned long baddr, last;
3181da177e4SLinus Torvalds u32 *mmio_regs, *gatt_pages, *cur_gatt, pte;
3191da177e4SLinus Torvalds unsigned long gart_bus_addr;
3201da177e4SLinus Torvalds
3211da177e4SLinus Torvalds if (!alpha_agpgart_size)
3221da177e4SLinus Torvalds return (void __iomem *)(addr + IRONGATE_MEM);
3231da177e4SLinus Torvalds
3241da177e4SLinus Torvalds gart_bus_addr = (unsigned long)IRONGATE0->bar0 &
3251da177e4SLinus Torvalds PCI_BASE_ADDRESS_MEM_MASK;
3261da177e4SLinus Torvalds
3271da177e4SLinus Torvalds /*
3281da177e4SLinus Torvalds * Check for within the AGP aperture...
3291da177e4SLinus Torvalds */
3301da177e4SLinus Torvalds do {
3311da177e4SLinus Torvalds /*
3321da177e4SLinus Torvalds * Check the AGP area
3331da177e4SLinus Torvalds */
3341da177e4SLinus Torvalds if (addr >= gart_bus_addr && addr + size - 1 <
3351da177e4SLinus Torvalds gart_bus_addr + alpha_agpgart_size)
3361da177e4SLinus Torvalds break;
3371da177e4SLinus Torvalds
3381da177e4SLinus Torvalds /*
3391da177e4SLinus Torvalds * Not found - assume legacy ioremap
3401da177e4SLinus Torvalds */
3411da177e4SLinus Torvalds return (void __iomem *)(addr + IRONGATE_MEM);
3421da177e4SLinus Torvalds } while(0);
3431da177e4SLinus Torvalds
3441da177e4SLinus Torvalds mmio_regs = (u32 *)(((unsigned long)IRONGATE0->bar1 &
3451da177e4SLinus Torvalds PCI_BASE_ADDRESS_MEM_MASK) + IRONGATE_MEM);
3461da177e4SLinus Torvalds
3471da177e4SLinus Torvalds gatt_pages = (u32 *)(phys_to_virt(mmio_regs[1])); /* FIXME */
3481da177e4SLinus Torvalds
3491da177e4SLinus Torvalds /*
3501da177e4SLinus Torvalds * Adjust the limits (mappings must be page aligned)
3511da177e4SLinus Torvalds */
3521da177e4SLinus Torvalds if (addr & ~PAGE_MASK) {
3531da177e4SLinus Torvalds printk("AGP ioremap failed... addr not page aligned (0x%lx)\n",
3541da177e4SLinus Torvalds addr);
3551da177e4SLinus Torvalds return (void __iomem *)(addr + IRONGATE_MEM);
3561da177e4SLinus Torvalds }
3571da177e4SLinus Torvalds last = addr + size - 1;
3581da177e4SLinus Torvalds size = PAGE_ALIGN(last) - addr;
3591da177e4SLinus Torvalds
3601da177e4SLinus Torvalds #if 0
3611da177e4SLinus Torvalds printk("irongate_ioremap(0x%lx, 0x%lx)\n", addr, size);
3621da177e4SLinus Torvalds printk("irongate_ioremap: gart_bus_addr 0x%lx\n", gart_bus_addr);
3631da177e4SLinus Torvalds printk("irongate_ioremap: gart_aper_size 0x%lx\n", gart_aper_size);
3641da177e4SLinus Torvalds printk("irongate_ioremap: mmio_regs %p\n", mmio_regs);
3651da177e4SLinus Torvalds printk("irongate_ioremap: gatt_pages %p\n", gatt_pages);
3661da177e4SLinus Torvalds
3671da177e4SLinus Torvalds for(baddr = addr; baddr <= last; baddr += PAGE_SIZE)
3681da177e4SLinus Torvalds {
3691da177e4SLinus Torvalds cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
3701da177e4SLinus Torvalds pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
3711da177e4SLinus Torvalds printk("irongate_ioremap: cur_gatt %p pte 0x%x\n",
3721da177e4SLinus Torvalds cur_gatt, pte);
3731da177e4SLinus Torvalds }
3741da177e4SLinus Torvalds #endif
3751da177e4SLinus Torvalds
3761da177e4SLinus Torvalds /*
3771da177e4SLinus Torvalds * Map it
3781da177e4SLinus Torvalds */
3791da177e4SLinus Torvalds area = get_vm_area(size, VM_IOREMAP);
3801da177e4SLinus Torvalds if (!area) return NULL;
3811da177e4SLinus Torvalds
3821da177e4SLinus Torvalds for(baddr = addr, vaddr = (unsigned long)area->addr;
3831da177e4SLinus Torvalds baddr <= last;
3841da177e4SLinus Torvalds baddr += PAGE_SIZE, vaddr += PAGE_SIZE)
3851da177e4SLinus Torvalds {
3861da177e4SLinus Torvalds cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
3871da177e4SLinus Torvalds pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
3881da177e4SLinus Torvalds
3891da177e4SLinus Torvalds if (__alpha_remap_area_pages(vaddr,
3901da177e4SLinus Torvalds pte, PAGE_SIZE, 0)) {
3911da177e4SLinus Torvalds printk("AGP ioremap: FAILED to map...\n");
3921da177e4SLinus Torvalds vfree(area->addr);
3931da177e4SLinus Torvalds return NULL;
3941da177e4SLinus Torvalds }
3951da177e4SLinus Torvalds }
3961da177e4SLinus Torvalds
3971da177e4SLinus Torvalds flush_tlb_all();
3981da177e4SLinus Torvalds
3991da177e4SLinus Torvalds vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
4001da177e4SLinus Torvalds #if 0
4011da177e4SLinus Torvalds printk("irongate_ioremap(0x%lx, 0x%lx) returning 0x%lx\n",
4021da177e4SLinus Torvalds addr, size, vaddr);
4031da177e4SLinus Torvalds #endif
4041da177e4SLinus Torvalds return (void __iomem *)vaddr;
4051da177e4SLinus Torvalds }
406cff52dafSAl Viro EXPORT_SYMBOL(irongate_ioremap);
4071da177e4SLinus Torvalds
4081da177e4SLinus Torvalds void
irongate_iounmap(volatile void __iomem * xaddr)4091da177e4SLinus Torvalds irongate_iounmap(volatile void __iomem *xaddr)
4101da177e4SLinus Torvalds {
4111da177e4SLinus Torvalds unsigned long addr = (unsigned long) xaddr;
4121da177e4SLinus Torvalds if (((long)addr >> 41) == -2)
4131da177e4SLinus Torvalds return; /* kseg map, nothing to do */
4141da177e4SLinus Torvalds if (addr)
4151da177e4SLinus Torvalds return vfree((void *)(PAGE_MASK & addr));
4161da177e4SLinus Torvalds }
417cff52dafSAl Viro EXPORT_SYMBOL(irongate_iounmap);
418