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

📄 pmac_pci.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (k2_skiplist[i] && k2_skiplist[i]->bus == bus &&		    k2_skiplist[i]->devfn == devfn)			return PCIBIOS_SUCCESSFUL;	addr = u3_ht_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((u8 *)addr, val);		(void) in_8((u8 *)addr);		break;	case 2:		out_le16((u16 *)addr, val);		(void) in_le16((u16 *)addr);		break;	default:		out_le32((u32 *)addr, val);		(void) in_le32((u32 *)addr);		break;	}	return PCIBIOS_SUCCESSFUL;}static struct pci_ops u3_ht_pci_ops ={	u3_ht_read_config,	u3_ht_write_config};#endif /* CONFIG_POWER4 *//* * For a bandit bridge, turn on cache coherency if necessary. * N.B. we could clean this up using the hose ops directly. */static void __initinit_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((volatile unsigned int *)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((volatile unsigned int *)bp->cfg_data);	if ((magic & BANDIT_COHERENT) != 0)		return;	magic |= BANDIT_COHERENT;	udelay(2);	out_le32((volatile unsigned int *)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 __initinit_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. */	if ((p2pbridge = find_devices("pci-bridge")) == 0	    || p2pbridge->parent == NULL	    || strcmp(p2pbridge->parent->name, "pci") != 0)		return;	if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {		DBG("Can't find PCI infos for PCI<->PCI bridge\n");		return;	}	/* 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");		return;	}	if (early_read_config_word(hose, bus, devfn,				   PCI_BRIDGE_CONTROL, &val) < 0) {		printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");		return;	}	val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;	early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);}/* * 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 __initfixup_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, *prop;		u8 bus, devfn;				prop = (u32 *)get_property(nec, "vendor-id", NULL);		if (prop == NULL)			continue;		if (0x1033 != *prop)			continue;		prop = (u32 *)get_property(nec, "device-id", NULL);		if (prop == NULL)			continue;		if (0x0035 != *prop)			continue;		prop = (u32 *)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);			early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE,				nec->intrs[0].line);		}	}}void __initpmac_find_bridges(void){	struct device_node *np, *root;	struct device_node *ht = NULL;	root = of_find_node_by_path("/");	if (root == NULL) {		printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n");		return;	}	for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {		if (np->name == NULL)			continue;		if (strcmp(np->name, "bandit") == 0		    || strcmp(np->name, "chaos") == 0		    || strcmp(np->name, "pci") == 0) {			if (add_bridge(np) == 0)				of_node_get(np);		}		if (strcmp(np->name, "ht") == 0) {			of_node_get(np);			ht = np;		}	}	of_node_put(root);	/* Probe HT last as it relies on the agp resources to be already	 * setup	 */	if (ht && add_bridge(ht) != 0)		of_node_put(ht);	init_p2pbridge();	fixup_nec_usb2();#ifdef CONFIG_POWER4 	/* There is something wrong with DMA on U3/HT. I haven't figured out	 * the details yet, but if I set the cache line size to 128 bytes like	 * it should, I'm getting memory corruption caused by devices like	 * sungem (even without the MWI bit set, but maybe sungem doesn't	 * care). Right now, it appears that setting up a 64 bytes line size	 * works properly, 64 bytes beeing the max transfer size of HT, I	 * suppose this is related the way HT/PCI are hooked together. I still	 * need to dive into more specs though to be really sure of what's	 * going on. --BenH.	 *	 * Ok, apparently, it's just that HT can't do more than 64 bytes	 * transactions. MWI seem to be meaningless there as well, it may	 * be worth nop'ing out pci_set_mwi too though I haven't done that	 * yet.	 *	 * Note that it's a bit different for whatever is in the AGP slot.	 * For now, I don't care, but this can become a real issue, we	 * should probably hook pci_set_mwi anyway to make sure it sets	 * the real cache line size in there.	 */	if (machine_is_compatible("MacRISC4"))		pci_cache_line_size = 16; /* 64 bytes */	pmac_check_ht_link();#endif /* CONFIG_POWER4 */}#define GRACKLE_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \				 | (((o) & ~3) << 24))#define GRACKLE_PICR1_STG		0x00000040#define GRACKLE_PICR1_LOOPSNOOP		0x00000010/* N.B. this is called before bridges is initialized, so we can't   use grackle_pcibios_{read,write}_config_dword. */static inline void grackle_set_stg(struct pci_controller* bp, int enable){	unsigned int val;	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));	val = in_le32((volatile unsigned int *)bp->cfg_data);	val = enable? (val | GRACKLE_PICR1_STG) :		(val & ~GRACKLE_PICR1_STG);	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));	out_le32((volatile unsigned int *)bp->cfg_data, val);	(void)in_le32((volatile unsigned int *)bp->cfg_data);}static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable){	unsigned int val;	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));	val = in_le32((volatile unsigned int *)bp->cfg_data);	val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :		(val & ~GRACKLE_PICR1_LOOPSNOOP);	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));	out_le32((volatile unsigned int *)bp->cfg_data, val);	(void)in_le32((volatile unsigned int *)bp->cfg_data);}static int __initsetup_uninorth(struct pci_controller* hose, struct reg_property* addr){	pci_assign_all_busses = 1;	has_uninorth = 1;	hose->ops = &macrisc_pci_ops;	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);	/* We "know" that the bridge at f2000000 has the PCI slots. */	return addr->address == 0xf2000000;}static void __initsetup_bandit(struct pci_controller* hose, struct reg_property* addr){	hose->ops = &macrisc_pci_ops;	hose->cfg_addr = (volatile unsigned int *)		ioremap(addr->address + 0x800000, 0x1000);	hose->cfg_data = (volatile unsigned char *)		ioremap(addr->address + 0xc00000, 0x1000);	init_bandit(hose);}static void __initsetup_chaos(struct pci_controller* hose, struct reg_property* addr){	/* assume a `chaos' bridge */	hose->ops = &chaos_pci_ops;	hose->cfg_addr = (volatile unsigned int *)		ioremap(addr->address + 0x800000, 0x1000);	hose->cfg_data = (volatile unsigned char *)		ioremap(addr->address + 0xc00000, 0x1000);}#ifdef CONFIG_POWER4static void __initsetup_u3_agp(struct pci_controller* hose, struct reg_property* addr){	/* 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 __initsetup_u3_ht(struct pci_controller* hose, struct reg_property *addr){	struct device_node *np = (struct device_node *)hose->arch_data;	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 = (volatile unsigned char *)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 + 0x00400000;	hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);	isa_io_base = (unsigned long) hose->io_base_virt;	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;	if (u3_agp == NULL) {		DBG("U3 has no AGP, using full resource range\n");		return;	}	/* 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 = &u3_agp->mem_resources[i];		if (res->flags != IORESOURCE_MEM)

⌨️ 快捷键说明

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