pmac_feature.c
来自「底层驱动开发」· C语言 代码 · 共 768 行 · 第 1/2 页
C
768 行
PMAC_TYPE_POWERMAC_G5_U3L, g5_features, 0, }, { "RackMac3,1", "XServe G5", PMAC_TYPE_XSERVE_G5, g5_features, 0, },};/* * The toplevel feature_call callback */long __pmac pmac_do_feature_call(unsigned int selector, ...){ struct device_node* node; long param, value; int i; feature_call func = NULL; va_list args; if (pmac_mb.features) for (i=0; pmac_mb.features[i].function; i++) if (pmac_mb.features[i].selector == selector) { func = pmac_mb.features[i].function; break; } if (!func) for (i=0; any_features[i].function; i++) if (any_features[i].selector == selector) { func = any_features[i].function; break; } if (!func) return -ENODEV; va_start(args, selector); node = (struct device_node*)va_arg(args, void*); param = va_arg(args, long); value = va_arg(args, long); va_end(args); return func(node, param, value);}static int __init probe_motherboard(void){ int i; struct macio_chip* macio = &macio_chips[0]; const char* model = NULL; struct device_node *dt; /* Lookup known motherboard type in device-tree. First try an * exact match on the "model" property, then try a "compatible" * match is none is found. */ dt = find_devices("device-tree"); if (dt != NULL) model = (const char *) get_property(dt, "model", NULL); for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { pmac_mb = pmac_mb_defs[i]; goto found; } } for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { if (machine_is_compatible(pmac_mb_defs[i].model_string)) { pmac_mb = pmac_mb_defs[i]; goto found; } } /* Fallback to selection depending on mac-io chip type */ switch(macio->type) { case macio_keylargo2: pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; pmac_mb.model_name = "Unknown K2-based"; pmac_mb.features = g5_features; default: return -ENODEV; }found: /* Check for "mobile" machine */ if (model && (strncmp(model, "PowerBook", 9) == 0 || strncmp(model, "iBook", 5) == 0)) pmac_mb.board_flags |= PMAC_MB_MOBILE; printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); return 0;}/* Initialize the Core99 UniNorth host bridge and memory controller */static void __init probe_uninorth(void){ uninorth_node = of_find_node_by_name(NULL, "u3"); if (uninorth_node && uninorth_node->n_addrs > 0) { /* Small hack until I figure out if parsing in prom.c is correct. I should * get rid of those pre-parsed junk anyway */ unsigned long address = uninorth_node->addrs[0].address; uninorth_base = ioremap(address, 0x40000); uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); } else uninorth_node = NULL; if (!uninorth_node) return; printk(KERN_INFO "Found U3 memory controller & host bridge, revision: %d\n", uninorth_rev); printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);}static void __init probe_one_macio(const char* name, const char* compat, int type){ struct device_node* node; int i; volatile u32* base; u32* revp; node = find_devices(name); if (!node || !node->n_addrs) return; if (compat) do { if (device_is_compatible(node, compat)) break; node = node->next; } while (node); if (!node) return; for(i=0; i<MAX_MACIO_CHIPS; i++) { if (!macio_chips[i].of_node) break; if (macio_chips[i].of_node == node) return; } if (i >= MAX_MACIO_CHIPS) { printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); return; } base = (volatile u32*)ioremap(node->addrs[0].address, node->addrs[0].size); if (!base) { printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n"); return; } if (type == macio_keylargo) { u32* did = (u32 *)get_property(node, "device-id", NULL); if (*did == 0x00000025) type = macio_pangea; if (*did == 0x0000003e) type = macio_intrepid; } macio_chips[i].of_node = node; macio_chips[i].type = type; macio_chips[i].base = base; macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; macio_chips[i].name = macio_names[type]; revp = (u32 *)get_property(node, "revision-id", NULL); if (revp) macio_chips[i].rev = *revp; printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", macio_names[type], macio_chips[i].rev, macio_chips[i].base);}static int __initprobe_macios(void){ probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2); macio_chips[0].lbus.index = 0; macio_chips[1].lbus.index = 1; return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;}static void __initset_initial_features(void){ struct device_node *np; if (macio_chips[0].type == macio_keylargo2) {#ifndef CONFIG_SMP /* On SMP machines running UP, we have the second CPU eating * bus cycles. We need to take it off the bus. This is done * from pmac_smp for SMP kernels running on one CPU */ np = of_find_node_by_type(NULL, "cpu"); if (np != NULL) np = of_find_node_by_type(np, "cpu"); if (np != NULL) { g5_phy_disable_cpu1(); of_node_put(np); }#endif /* CONFIG_SMP */ /* Enable GMAC for now for PCI probing. It will be disabled * later on after PCI probe */ np = of_find_node_by_name(NULL, "ethernet"); while(np) { if (device_is_compatible(np, "K2-GMAC")) g5_gmac_enable(np, 0, 1); np = of_find_node_by_name(np, "ethernet"); } /* Enable FW before PCI probe. Will be disabled later on * Note: We should have a batter way to check that we are * dealing with uninorth internal cell and not a PCI cell * on the external PCI. The code below works though. */ np = of_find_node_by_name(NULL, "firewire"); while(np) { if (device_is_compatible(np, "pci106b,5811")) { macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; g5_fw_enable(np, 0, 1); } np = of_find_node_by_name(np, "firewire"); } }}void __initpmac_feature_init(void){ /* Detect the UniNorth memory controller */ probe_uninorth(); /* Probe mac-io controllers */ if (probe_macios()) { printk(KERN_WARNING "No mac-io chip found\n"); return; } /* Setup low-level i2c stuffs */ pmac_init_low_i2c(); /* Probe machine type */ if (probe_motherboard()) printk(KERN_WARNING "Unknown PowerMac !\n"); /* Set some initial features (turn off some chips that will * be later turned on) */ set_initial_features();}int __init pmac_feature_late_init(void){#if 0 struct device_node* np; /* Request some resources late */ if (uninorth_node) request_OF_resource(uninorth_node, 0, NULL); np = find_devices("hammerhead"); if (np) request_OF_resource(np, 0, NULL); np = find_devices("interrupt-controller"); if (np) request_OF_resource(np, 0, NULL);#endif return 0;}device_initcall(pmac_feature_late_init);#if 0static void dump_HT_speeds(char *name, u32 cfg, u32 frq){ int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; int bits[8] = { 8,16,0,32,2,4,0,0 }; int freq = (frq >> 8) & 0xf; if (freqs[freq] == 0) printk("%s: Unknown HT link frequency %x\n", name, freq); else printk("%s: %d MHz on main link, (%d in / %d out) bits width\n", name, freqs[freq], bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);}#endifvoid __init pmac_check_ht_link(void){#if 0 /* Disabled for now */ u32 ufreq, freq, ucfg, cfg; struct device_node *pcix_node; struct pci_dn *pdn; u8 px_bus, px_devfn; struct pci_controller *px_hose; (void)in_be32(u3_ht + U3_HT_LINK_COMMAND); ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG); ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ); dump_HT_speeds("U3 HyperTransport", cfg, freq); pcix_node = of_find_compatible_node(NULL, "pci", "pci-x"); if (pcix_node == NULL) { printk("No PCI-X bridge found\n"); return; } pdn = pcix_node->data; px_hose = pdn->phb; px_bus = pdn->busno; px_devfn = pdn->devfn; early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); dump_HT_speeds("PCI-X HT Uplink", cfg, freq); early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg); early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq); dump_HT_speeds("PCI-X HT Downlink", cfg, freq);#endif}/* * Early video resume hook */static void (*pmac_early_vresume_proc)(void *data) __pmacdata;static void *pmac_early_vresume_data __pmacdata;void pmac_set_early_video_resume(void (*proc)(void *data), void *data){ if (_machine != _MACH_Pmac) return; preempt_disable(); pmac_early_vresume_proc = proc; pmac_early_vresume_data = data; preempt_enable();}EXPORT_SYMBOL(pmac_set_early_video_resume);/* * AGP related suspend/resume code */static struct pci_dev *pmac_agp_bridge __pmacdata;static int (*pmac_agp_suspend)(struct pci_dev *bridge) __pmacdata;static int (*pmac_agp_resume)(struct pci_dev *bridge) __pmacdata;void __pmac pmac_register_agp_pm(struct pci_dev *bridge, int (*suspend)(struct pci_dev *bridge), int (*resume)(struct pci_dev *bridge)){ if (suspend || resume) { pmac_agp_bridge = bridge; pmac_agp_suspend = suspend; pmac_agp_resume = resume; return; } if (bridge != pmac_agp_bridge) return; pmac_agp_suspend = pmac_agp_resume = NULL; return;}EXPORT_SYMBOL(pmac_register_agp_pm);void __pmac pmac_suspend_agp_for_card(struct pci_dev *dev){ if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL) return; if (pmac_agp_bridge->bus != dev->bus) return; pmac_agp_suspend(pmac_agp_bridge);}EXPORT_SYMBOL(pmac_suspend_agp_for_card);void __pmac pmac_resume_agp_for_card(struct pci_dev *dev){ if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL) return; if (pmac_agp_bridge->bus != dev->bus) return; pmac_agp_resume(pmac_agp_bridge);}EXPORT_SYMBOL(pmac_resume_agp_for_card);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?