^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * arch/arm/plat-iop/pci.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * PCI support for the Intel IOP32X and IOP33X processors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Rory Bolt <rorybolt@pacbell.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2002 Rory Bolt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/mach/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "hardware.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "iop3xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) // #define DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define DBG(x...) printk(x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DBG(x...) do { } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * This routine builds either a type0 or type1 configuration command. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * bus is on the 803xx then a type0 made, else a type1 is created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static u32 iop3xx_cfg_address(struct pci_bus *bus, int devfn, int where)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct pci_sys_data *sys = bus->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (sys->busnr == bus->number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) addr |= PCI_FUNC(devfn) << 8 | (where & ~3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * This routine checks the status of the last configuration cycle. If an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * was detected it returns a 1, else it returns a 0. The errors being checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * are parity, master abort, target abort (master and target). These types of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * errors occur during a config cycle where there is no device, like during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * the discovery stage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int iop3xx_pci_status(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * Check the status registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) status = *IOP3XX_ATUSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (status & 0xf900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *IOP3XX_ATUSR = status & 0xf900;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) status = *IOP3XX_ATUISR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (status & 0x679f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *IOP3XX_ATUISR = status & 0x679f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Simply write the address register and read the configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * data. Note that the 4 nops ensure that we are able to handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * a delayed abort (in theory.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static u32 iop3xx_read(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) "str %1, [%2]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) "ldr %0, [%3]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) : "=r" (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) : "r" (addr), "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * The read routines must check the error status of the last configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * cycle. If there was an error, the routine returns all hex f's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) iop3xx_read_config(struct pci_bus *bus, unsigned int devfn, int where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int size, u32 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned long addr = iop3xx_cfg_address(bus, devfn, where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u32 val = iop3xx_read(addr) >> ((where & 3) * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (iop3xx_pci_status())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) val = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return PCIBIOS_SUCCESSFUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) iop3xx_write_config(struct pci_bus *bus, unsigned int devfn, int where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int size, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned long addr = iop3xx_cfg_address(bus, devfn, where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (size != 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) val = iop3xx_read(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (iop3xx_pci_status())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return PCIBIOS_SUCCESSFUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) where = (where & 3) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (size == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) val &= ~(0xff << where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) val &= ~(0xffff << where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) *IOP3XX_OCCDR = val | value << where;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) "str %1, [%2]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "str %0, [%3]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) : "r" (value), "r" (addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return PCIBIOS_SUCCESSFUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct pci_ops iop3xx_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .read = iop3xx_read_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .write = iop3xx_write_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * When a PCI device does not exist during config cycles, the 80200 gets a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * bus error instead of returning 0xffffffff. This handler simply returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) iop3xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) addr, fsr, regs->ARM_pc, regs->ARM_lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * If it was an imprecise abort, then we need to correct the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * return address to be _after_ the instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (fsr & (1 << 10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) regs->ARM_pc += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (nr != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) res = kzalloc(sizeof(struct resource), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) panic("PCI: unable to alloc resources");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) res->start = IOP3XX_PCI_LOWER_MEM_PA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) res->end = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) res->name = "IOP3XX PCI Memory Space";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) res->flags = IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) request_resource(&iomem_resource, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * Use whatever translation is already setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) pci_add_resource_offset(&sys->resources, res, sys->mem_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) pci_ioremap_io(0, IOP3XX_PCI_LOWER_IO_PA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) void __init iop3xx_atu_setup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* BAR 0 ( Disabled ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *IOP3XX_IAUBAR0 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *IOP3XX_IABAR0 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *IOP3XX_IATVR0 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) *IOP3XX_IALR0 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* BAR 1 ( Disabled ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) *IOP3XX_IAUBAR1 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *IOP3XX_IABAR1 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) *IOP3XX_IALR1 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* BAR 2 (1:1 mapping with Physical RAM) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* Set limit and enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) *IOP3XX_IALR2 = ~((u32)IOP3XX_MAX_RAM_SIZE - 1) & ~0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) *IOP3XX_IAUBAR2 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* Align the inbound bar with the base of memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) *IOP3XX_IABAR2 = PHYS_OFFSET |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) PCI_BASE_ADDRESS_MEM_TYPE_64 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) PCI_BASE_ADDRESS_MEM_PREFETCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *IOP3XX_IATVR2 = PHYS_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* Outbound window 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) *IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_BA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *IOP3XX_OUMWTVR0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* Outbound window 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) *IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_BA +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) IOP3XX_PCI_MEM_WINDOW_SIZE / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) *IOP3XX_OUMWTVR1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* BAR 3 ( Disabled ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *IOP3XX_IAUBAR3 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) *IOP3XX_IABAR3 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) *IOP3XX_IATVR3 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) *IOP3XX_IALR3 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /* Setup the I/O Bar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_BA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* Enable inbound and outbound cycles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *IOP3XX_ATUCMD |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) *IOP3XX_ATUCR |= IOP3XX_ATUCR_OUT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) void __init iop3xx_atu_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *IOP3XX_ATUCMD = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) *IOP3XX_ATUCR = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* wait for cycles to quiesce */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) while (*IOP3XX_PCSR & (IOP3XX_PCSR_OUT_Q_BUSY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) IOP3XX_PCSR_IN_Q_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* BAR 0 ( Disabled ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *IOP3XX_IAUBAR0 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) *IOP3XX_IABAR0 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) *IOP3XX_IATVR0 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) *IOP3XX_IALR0 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* BAR 1 ( Disabled ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) *IOP3XX_IAUBAR1 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *IOP3XX_IABAR1 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *IOP3XX_IALR1 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* BAR 2 ( Disabled ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) *IOP3XX_IAUBAR2 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *IOP3XX_IABAR2 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) *IOP3XX_IATVR2 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) *IOP3XX_IALR2 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* BAR 3 ( Disabled ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *IOP3XX_IAUBAR3 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) *IOP3XX_IABAR3 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) *IOP3XX_IATVR3 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) *IOP3XX_IALR3 = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* Clear the outbound windows */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) *IOP3XX_OIOWTVR = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* Outbound window 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *IOP3XX_OMWTVR0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) *IOP3XX_OUMWTVR0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* Outbound window 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *IOP3XX_OMWTVR1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) *IOP3XX_OUMWTVR1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* Flag to determine whether the ATU is initialized and the PCI bus scanned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) int init_atu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int iop3xx_get_init_atu(void) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* check if default has been overridden */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (init_atu != IOP3XX_INIT_ATU_DEFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return init_atu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return IOP3XX_INIT_ATU_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static void __init iop3xx_atu_debug(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) DBG("PCI: Intel IOP3xx PCI init.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) DBG("PCI: Outbound memory window 0: PCI 0x%08x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *IOP3XX_OUMWTVR0, *IOP3XX_OMWTVR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) DBG("PCI: Outbound memory window 1: PCI 0x%08x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) *IOP3XX_OUMWTVR1, *IOP3XX_OMWTVR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) DBG("PCI: Outbound IO window: PCI 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) *IOP3XX_OIOWTVR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) DBG("PCI: Inbound memory window 0: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) *IOP3XX_IAUBAR0, *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) DBG("PCI: Inbound memory window 1: PCI 0x%08x%08x 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) *IOP3XX_IAUBAR1, *IOP3XX_IABAR1, *IOP3XX_IALR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) DBG("PCI: Inbound memory window 2: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) *IOP3XX_IAUBAR2, *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) DBG("PCI: Inbound memory window 3: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) *IOP3XX_IAUBAR3, *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) DBG("PCI: Expansion ROM window: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 0, *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) DBG("ATU: IOP3XX_ATUCR=0x%08x\n", *IOP3XX_ATUCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, 0, "imprecise external abort");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* for platforms that might be host-bus-adapters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) void __init iop3xx_pci_preinit_cond(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) iop3xx_atu_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) iop3xx_atu_setup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) iop3xx_atu_debug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) void __init iop3xx_pci_preinit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) pcibios_min_mem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) iop3xx_atu_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) iop3xx_atu_setup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) iop3xx_atu_debug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* allow init_atu to be user overridden */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static int __init iop3xx_init_atu_setup(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) init_atu = IOP3XX_INIT_ATU_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) while (*str != '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) switch (*str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case 'y':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case 'Y':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) init_atu = IOP3XX_INIT_ATU_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) case 'N':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) init_atu = IOP3XX_INIT_ATU_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) case ',':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case '=':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) printk(KERN_DEBUG "\"%s\" malformed at "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) "character: \'%c\'",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) *str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) *(str + 1) = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) __setup("iop3xx_init_atu", iop3xx_init_atu_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)