| Paul Mundt | 85b59f5 | 2010-02-01 13:01:42 +0900 | [diff] [blame^] | 1 | #include <linux/pci.h> | 
 | 2 | #include <linux/kernel.h> | 
 | 3 |  | 
 | 4 | static int __init | 
 | 5 | early_read_config_word(struct pci_channel *hose, | 
 | 6 | 		       int top_bus, int bus, int devfn, int offset, u16 *value) | 
 | 7 | { | 
 | 8 | 	struct pci_dev fake_dev; | 
 | 9 | 	struct pci_bus fake_bus; | 
 | 10 |  | 
 | 11 | 	fake_dev.bus = &fake_bus; | 
 | 12 | 	fake_dev.sysdata = hose; | 
 | 13 | 	fake_dev.devfn = devfn; | 
 | 14 | 	fake_bus.number = bus; | 
 | 15 | 	fake_bus.sysdata = hose; | 
 | 16 | 	fake_bus.ops = hose->pci_ops; | 
 | 17 |  | 
 | 18 | 	if (bus != top_bus) | 
 | 19 | 		/* Fake a parent bus structure. */ | 
 | 20 | 		fake_bus.parent = &fake_bus; | 
 | 21 | 	else | 
 | 22 | 		fake_bus.parent = NULL; | 
 | 23 |  | 
 | 24 | 	return pci_read_config_word(&fake_dev, offset, value); | 
 | 25 | } | 
 | 26 |  | 
 | 27 | int __init pci_is_66mhz_capable(struct pci_channel *hose, | 
 | 28 | 				int top_bus, int current_bus) | 
 | 29 | { | 
 | 30 | 	u32 pci_devfn; | 
 | 31 | 	unsigned short vid; | 
 | 32 | 	int cap66 = -1; | 
 | 33 | 	u16 stat; | 
 | 34 |  | 
 | 35 | 	printk(KERN_INFO "PCI: Checking 66MHz capabilities...\n"); | 
 | 36 |  | 
 | 37 | 	for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) { | 
 | 38 | 		if (PCI_FUNC(pci_devfn)) | 
 | 39 | 			continue; | 
 | 40 | 		if (early_read_config_word(hose, top_bus, current_bus, | 
 | 41 | 					   pci_devfn, PCI_VENDOR_ID, &vid) != | 
 | 42 | 		    PCIBIOS_SUCCESSFUL) | 
 | 43 | 			continue; | 
 | 44 | 		if (vid == 0xffff) | 
 | 45 | 			continue; | 
 | 46 |  | 
 | 47 | 		/* check 66MHz capability */ | 
 | 48 | 		if (cap66 < 0) | 
 | 49 | 			cap66 = 1; | 
 | 50 | 		if (cap66) { | 
 | 51 | 			early_read_config_word(hose, top_bus, current_bus, | 
 | 52 | 					       pci_devfn, PCI_STATUS, &stat); | 
 | 53 | 			if (!(stat & PCI_STATUS_66MHZ)) { | 
 | 54 | 				printk(KERN_DEBUG | 
 | 55 | 				       "PCI: %02x:%02x not 66MHz capable.\n", | 
 | 56 | 				       current_bus, pci_devfn); | 
 | 57 | 				cap66 = 0; | 
 | 58 | 				break; | 
 | 59 | 			} | 
 | 60 | 		} | 
 | 61 | 	} | 
 | 62 |  | 
 | 63 | 	return cap66 > 0; | 
 | 64 | } |