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 + -
显示快捷键?