Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)