⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * Note: the caller has already checked that offset is	 * suitably aligned and that len is 1, 2 or 4.	 */	switch (len) {	case 1:		out_8(addr, val);		break;	case 2:		out_le16(addr, val);		break;	default:		out_le32((u32 __iomem *)addr, val);		break;	}	return PCIBIOS_SUCCESSFUL;}static struct pci_ops u3_ht_pci_ops ={	.read = u3_ht_read_config,	.write = u3_ht_write_config,};#define U4_PCIE_CFA0(devfn, off)	\	((1 << ((unsigned int)PCI_SLOT(dev_fn)))	\	 | (((unsigned int)PCI_FUNC(dev_fn)) << 8)	\	 | ((((unsigned int)(off)) >> 8) << 28) \	 | (((unsigned int)(off)) & 0xfcU))#define U4_PCIE_CFA1(bus, devfn, off)	\	((((unsigned int)(bus)) << 16) \	 |(((unsigned int)(devfn)) << 8)	\	 | ((((unsigned int)(off)) >> 8) << 28) \	 |(((unsigned int)(off)) & 0xfcU)	\	 |1UL)static volatile void __iomem *u4_pcie_cfg_access(struct pci_controller* hose,					u8 bus, u8 dev_fn, int offset){	unsigned int caddr;	if (bus == hose->first_busno) {		caddr = U4_PCIE_CFA0(dev_fn, offset);	} else		caddr = U4_PCIE_CFA1(bus, dev_fn, offset);	/* Uninorth will return garbage if we don't read back the value ! */	do {		out_le32(hose->cfg_addr, caddr);	} while (in_le32(hose->cfg_addr) != caddr);	offset &= 0x03;	return hose->cfg_data + offset;}static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn,			       int offset, int len, u32 *val){	struct pci_controller *hose;	volatile void __iomem *addr;	hose = pci_bus_to_host(bus);	if (hose == NULL)		return PCIBIOS_DEVICE_NOT_FOUND;	if (offset >= 0x1000)		return  PCIBIOS_BAD_REGISTER_NUMBER;	addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);	if (!addr)		return PCIBIOS_DEVICE_NOT_FOUND;	/*	 * Note: the caller has already checked that offset is	 * suitably aligned and that len is 1, 2 or 4.	 */	switch (len) {	case 1:		*val = in_8(addr);		break;	case 2:		*val = in_le16(addr);		break;	default:		*val = in_le32(addr);		break;	}	return PCIBIOS_SUCCESSFUL;}static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn,				int offset, int len, u32 val){	struct pci_controller *hose;	volatile void __iomem *addr;	hose = pci_bus_to_host(bus);	if (hose == NULL)		return PCIBIOS_DEVICE_NOT_FOUND;	if (offset >= 0x1000)		return  PCIBIOS_BAD_REGISTER_NUMBER;	addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);	if (!addr)		return PCIBIOS_DEVICE_NOT_FOUND;	/*	 * Note: the caller has already checked that offset is	 * suitably aligned and that len is 1, 2 or 4.	 */	switch (len) {	case 1:		out_8(addr, val);		break;	case 2:		out_le16(addr, val);		break;	default:		out_le32(addr, val);		break;	}	return PCIBIOS_SUCCESSFUL;}static struct pci_ops u4_pcie_pci_ops ={	.read = u4_pcie_read_config,	.write = u4_pcie_write_config,};#endif /* CONFIG_PPC64 */#ifdef CONFIG_PPC32/* * For a bandit bridge, turn on cache coherency if necessary. * N.B. we could clean this up using the hose ops directly. */static void __init init_bandit(struct pci_controller *bp){	unsigned int vendev, magic;	int rev;	/* read the word at offset 0 in config space for device 11 */	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);	udelay(2);	vendev = in_le32(bp->cfg_data);	if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) +			PCI_VENDOR_ID_APPLE) {		/* read the revision id */		out_le32(bp->cfg_addr,			 (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);		udelay(2);		rev = in_8(bp->cfg_data);		if (rev != BANDIT_REVID)			printk(KERN_WARNING			       "Unknown revision %d for bandit\n", rev);	} else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);		return;	}	/* read the word at offset 0x50 */	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);	udelay(2);	magic = in_le32(bp->cfg_data);	if ((magic & BANDIT_COHERENT) != 0)		return;	magic |= BANDIT_COHERENT;	udelay(2);	out_le32(bp->cfg_data, magic);	printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");}/* * Tweak the PCI-PCI bridge chip on the blue & white G3s. */static void __init init_p2pbridge(void){	struct device_node *p2pbridge;	struct pci_controller* hose;	u8 bus, devfn;	u16 val;	/* XXX it would be better here to identify the specific	   PCI-PCI bridge chip we have. */	p2pbridge = of_find_node_by_name(NULL, "pci-bridge");	if (p2pbridge == NULL	    || p2pbridge->parent == NULL	    || strcmp(p2pbridge->parent->name, "pci") != 0)		goto done;	if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {		DBG("Can't find PCI infos for PCI<->PCI bridge\n");		goto done;	}	/* Warning: At this point, we have not yet renumbered all busses.	 * So we must use OF walking to find out hose	 */	hose = pci_find_hose_for_OF_device(p2pbridge);	if (!hose) {		DBG("Can't find hose for PCI<->PCI bridge\n");		goto done;	}	if (early_read_config_word(hose, bus, devfn,				   PCI_BRIDGE_CONTROL, &val) < 0) {		printk(KERN_ERR "init_p2pbridge: couldn't read bridge"		       " control\n");		goto done;	}	val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;	early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);done:	of_node_put(p2pbridge);}static void __init init_second_ohare(void){	struct device_node *np = of_find_node_by_name(NULL, "pci106b,7");	unsigned char bus, devfn;	unsigned short cmd;	if (np == NULL)		return;	/* This must run before we initialize the PICs since the second	 * ohare hosts a PIC that will be accessed there.	 */	if (pci_device_from_OF_node(np, &bus, &devfn) == 0) {		struct pci_controller* hose =			pci_find_hose_for_OF_device(np);		if (!hose) {			printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");			return;		}		early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);		cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;		cmd &= ~PCI_COMMAND_IO;		early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);	}	has_second_ohare = 1;}/* * Some Apple desktop machines have a NEC PD720100A USB2 controller * on the motherboard. Open Firmware, on these, will disable the * EHCI part of it so it behaves like a pair of OHCI's. This fixup * code re-enables it ;) */static void __init fixup_nec_usb2(void){	struct device_node *nec;	for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {		struct pci_controller *hose;		u32 data;		const u32 *prop;		u8 bus, devfn;		prop = of_get_property(nec, "vendor-id", NULL);		if (prop == NULL)			continue;		if (0x1033 != *prop)			continue;		prop = of_get_property(nec, "device-id", NULL);		if (prop == NULL)			continue;		if (0x0035 != *prop)			continue;		prop = of_get_property(nec, "reg", NULL);		if (prop == NULL)			continue;		devfn = (prop[0] >> 8) & 0xff;		bus = (prop[0] >> 16) & 0xff;		if (PCI_FUNC(devfn) != 0)			continue;		hose = pci_find_hose_for_OF_device(nec);		if (!hose)			continue;		early_read_config_dword(hose, bus, devfn, 0xe4, &data);		if (data & 1UL) {			printk("Found NEC PD720100A USB2 chip with disabled"			       " EHCI, fixing up...\n");			data &= ~1UL;			early_write_config_dword(hose, bus, devfn, 0xe4, data);		}	}}static void __init setup_bandit(struct pci_controller *hose,				struct resource *addr){	hose->ops = &macrisc_pci_ops;	hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);	hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000);	init_bandit(hose);}static int __init setup_uninorth(struct pci_controller *hose,				 struct resource *addr){	pci_assign_all_buses = 1;	has_uninorth = 1;	hose->ops = &macrisc_pci_ops;	hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);	hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000);	/* We "know" that the bridge at f2000000 has the PCI slots. */	return addr->start == 0xf2000000;}#endif /* CONFIG_PPC32 */#ifdef CONFIG_PPC64static void __init setup_u3_agp(struct pci_controller* hose){	/* On G5, we move AGP up to high bus number so we don't need	 * to reassign bus numbers for HT. If we ever have P2P bridges	 * on AGP, we'll have to move pci_assign_all_busses to the	 * pci_controller structure so we enable it for AGP and not for	 * HT childs.	 * We hard code the address because of the different size of	 * the reg address cell, we shall fix that by killing struct	 * reg_property and using some accessor functions instead	 */	hose->first_busno = 0xf0;	hose->last_busno = 0xff;	has_uninorth = 1;	hose->ops = &macrisc_pci_ops;	hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);	hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);	u3_agp = hose;}static void __init setup_u4_pcie(struct pci_controller* hose){	/* We currently only implement the "non-atomic" config space, to	 * be optimised later.	 */	hose->ops = &u4_pcie_pci_ops;	hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);	hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);	/* The bus contains a bridge from root -> device, we need to	 * make it visible on bus 0 so that we pick the right type	 * of config cycles. If we didn't, we would have to force all	 * config cycles to be type 1. So we override the "bus-range"	 * property here	 */	hose->first_busno = 0x00;	hose->last_busno = 0xff;	u4_pcie = hose;}static void __init setup_u3_ht(struct pci_controller* hose){	struct device_node *np = (struct device_node *)hose->arch_data;	struct pci_controller *other = NULL;	int i, cur;	hose->ops = &u3_ht_pci_ops;	/* We hard code the address because of the different size of	 * the reg address cell, we shall fix that by killing struct	 * reg_property and using some accessor functions instead	 */	hose->cfg_data = ioremap(0xf2000000, 0x02000000);	/*	 * /ht node doesn't expose a "ranges" property, so we "remove"	 * regions that have been allocated to AGP. So far, this version of	 * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions	 * to /ht. We need to fix that sooner or later by either parsing all	 * child "ranges" properties or figuring out the U3 address space	 * decoding logic and then read its configuration register (if any).	 */	hose->io_base_phys = 0xf4000000;	hose->pci_io_size = 0x00400000;	hose->io_resource.name = np->full_name;	hose->io_resource.start = 0;	hose->io_resource.end = 0x003fffff;	hose->io_resource.flags = IORESOURCE_IO;	hose->pci_mem_offset = 0;	hose->first_busno = 0;	hose->last_busno = 0xef;	hose->mem_resources[0].name = np->full_name;	hose->mem_resources[0].start = 0x80000000;	hose->mem_resources[0].end = 0xefffffff;	hose->mem_resources[0].flags = IORESOURCE_MEM;	u3_ht = hose;	if (u3_agp != NULL)		other = u3_agp;	else if (u4_pcie != NULL)		other = u4_pcie;	if (other == NULL) {		DBG("U3/4 has no AGP/PCIE, using full resource range\n");		return;	}	/* Fixup bus range vs. PCIE */	if (u4_pcie)		hose->last_busno = u4_pcie->first_busno - 1;	/* We "remove" the AGP resources from the resources allocated to HT,	 * that is we create "holes". However, that code does assumptions	 * that so far happen to be true (cross fingers...), typically that	 * resources in the AGP node are properly ordered	 */	cur = 0;	for (i=0; i<3; i++) {		struct resource *res = &other->mem_resources[i];		if (res->flags != IORESOURCE_MEM)			continue;		/* We don't care about "fine" resources */		if (res->start >= 0xf0000000)			continue;		/* Check if it's just a matter of "shrinking" us in one		 * direction		 */		if (hose->mem_resources[cur].start == res->start) {			DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",			    cur, hose->mem_resources[cur].start,			    res->end + 1);			hose->mem_resources[cur].start = res->end + 1;			continue;		}		if (hose->mem_resources[cur].end == res->end) {			DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",			    cur, hose->mem_resources[cur].end,			    res->start - 1);			hose->mem_resources[cur].end = res->start - 1;			continue;		}		/* No, it's not the case, we need a hole */		if (cur == 2) {			/* not enough resources for a hole, we drop part			 * of the range			 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -