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

📄 prom_init.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		*mem_start = _ALIGN(*mem_start, 4);	}	/* Add a "linux,phandle" property. */	soff = dt_find_string(RELOC("linux,phandle"));	if (soff == 0)		prom_printf("WARNING: Can't find string index for"			    " <linux-phandle> node %s\n", path);	else {		dt_push_token(OF_DT_PROP, mem_start, mem_end);		dt_push_token(4, mem_start, mem_end);		dt_push_token(soff, mem_start, mem_end);		valp = make_room(mem_start, mem_end, 4, 4);		*(u32 *)valp = node;	}	/* do all our children */	child = call_prom("child", 1, 1, node);	while (child != 0) {		scan_dt_build_struct(child, mem_start, mem_end);		child = call_prom("peer", 1, 1, child);	}	dt_push_token(OF_DT_END_NODE, mem_start, mem_end);}static void __init flatten_device_tree(void){	phandle root;	unsigned long mem_start, mem_end, room;	struct boot_param_header *hdr;	struct prom_t *_prom = &RELOC(prom);	char *namep;	u64 *rsvmap;	/*	 * Check how much room we have between alloc top & bottom (+/- a	 * few pages), crop to 4Mb, as this is our "chuck" size	 */	room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000;	if (room > DEVTREE_CHUNK_SIZE)		room = DEVTREE_CHUNK_SIZE;	prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom));	/* Now try to claim that */	mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);	if (mem_start == 0)		prom_panic("Can't allocate initial device-tree chunk\n");	mem_end = RELOC(alloc_top);	/* Get root of tree */	root = call_prom("peer", 1, 1, (phandle)0);	if (root == (phandle)0)		prom_panic ("couldn't get device tree root\n");	/* Build header and make room for mem rsv map */ 	mem_start = _ALIGN(mem_start, 4);	hdr = make_room(&mem_start, &mem_end,			sizeof(struct boot_param_header), 4);	RELOC(dt_header_start) = (unsigned long)hdr;	rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);	/* Start of strings */	mem_start = PAGE_ALIGN(mem_start);	RELOC(dt_string_start) = mem_start;	mem_start += 4; /* hole */	/* Add "linux,phandle" in there, we'll need it */	namep = make_room(&mem_start, &mem_end, 16, 1);	strcpy(namep, RELOC("linux,phandle"));	mem_start = (unsigned long)namep + strlen(namep) + 1;	/* Build string array */	prom_printf("Building dt strings...\n"); 	scan_dt_build_strings(root, &mem_start, &mem_end);	RELOC(dt_string_end) = mem_start;	/* Build structure */	mem_start = PAGE_ALIGN(mem_start);	RELOC(dt_struct_start) = mem_start;	prom_printf("Building dt structure...\n"); 	scan_dt_build_struct(root, &mem_start, &mem_end);	dt_push_token(OF_DT_END, &mem_start, &mem_end);	RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);	/* Finish header */	hdr->boot_cpuid_phys = _prom->cpu;	hdr->magic = OF_DT_HEADER;	hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);	hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);	hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);	hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);	hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);	hdr->version = OF_DT_VERSION;	/* Version 16 is not backward compatible */	hdr->last_comp_version = 0x10;	/* Copy the reserve map in */	memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));#ifdef DEBUG_PROM	{		int i;		prom_printf("reserved memory map:\n");		for (i = 0; i < RELOC(mem_reserve_cnt); i++)			prom_printf("  %x - %x\n",				    RELOC(mem_reserve_map)[i].base,				    RELOC(mem_reserve_map)[i].size);	}#endif	/* Bump mem_reserve_cnt to cause further reservations to fail	 * since it's too late.	 */	RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;	prom_printf("Device tree strings 0x%x -> 0x%x\n",		    RELOC(dt_string_start), RELOC(dt_string_end)); 	prom_printf("Device tree struct  0x%x -> 0x%x\n",		    RELOC(dt_struct_start), RELOC(dt_struct_end));}#ifdef CONFIG_PPC_MAPLE/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property. * The values are bad, and it doesn't even have the right number of cells. */static void __init fixup_device_tree_maple(void){	phandle isa;	u32 rloc = 0x01002000; /* IO space; PCI device = 4 */	u32 isa_ranges[6];	char *name;	name = "/ht@0/isa@4";	isa = call_prom("finddevice", 1, 1, ADDR(name));	if (!PHANDLE_VALID(isa)) {		name = "/ht@0/isa@6";		isa = call_prom("finddevice", 1, 1, ADDR(name));		rloc = 0x01003000; /* IO space; PCI device = 6 */	}	if (!PHANDLE_VALID(isa))		return;	if (prom_getproplen(isa, "ranges") != 12)		return;	if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))		== PROM_ERROR)		return;	if (isa_ranges[0] != 0x1 ||		isa_ranges[1] != 0xf4000000 ||		isa_ranges[2] != 0x00010000)		return;	prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");	isa_ranges[0] = 0x1;	isa_ranges[1] = 0x0;	isa_ranges[2] = rloc;	isa_ranges[3] = 0x0;	isa_ranges[4] = 0x0;	isa_ranges[5] = 0x00010000;	prom_setprop(isa, name, "ranges",			isa_ranges, sizeof(isa_ranges));}#else#define fixup_device_tree_maple()#endif#ifdef CONFIG_PPC_CHRP/* * Pegasos and BriQ lacks the "ranges" property in the isa node * Pegasos needs decimal IRQ 14/15, not hexadecimal * Pegasos has the IDE configured in legacy mode, but advertised as native */static void __init fixup_device_tree_chrp(void){	phandle ph;	u32 prop[6];	u32 rloc = 0x01006000; /* IO space; PCI device = 12 */	char *name;	int rc;	name = "/pci@80000000/isa@c";	ph = call_prom("finddevice", 1, 1, ADDR(name));	if (!PHANDLE_VALID(ph)) {		name = "/pci@ff500000/isa@6";		ph = call_prom("finddevice", 1, 1, ADDR(name));		rloc = 0x01003000; /* IO space; PCI device = 6 */	}	if (PHANDLE_VALID(ph)) {		rc = prom_getproplen(ph, "ranges");		if (rc == 0 || rc == PROM_ERROR) {			prom_printf("Fixing up missing ISA range on Pegasos...\n");			prop[0] = 0x1;			prop[1] = 0x0;			prop[2] = rloc;			prop[3] = 0x0;			prop[4] = 0x0;			prop[5] = 0x00010000;			prom_setprop(ph, name, "ranges", prop, sizeof(prop));		}	}	name = "/pci@80000000/ide@C,1";	ph = call_prom("finddevice", 1, 1, ADDR(name));	if (PHANDLE_VALID(ph)) {		prom_printf("Fixing up IDE interrupt on Pegasos...\n");		prop[0] = 14;		prop[1] = 0x0;		prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));		prom_printf("Fixing up IDE class-code on Pegasos...\n");		rc = prom_getprop(ph, "class-code", prop, sizeof(u32));		if (rc == sizeof(u32)) {			prop[0] &= ~0x5;			prom_setprop(ph, name, "class-code", prop, sizeof(u32));		}	}}#else#define fixup_device_tree_chrp()#endif#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)static void __init fixup_device_tree_pmac(void){	phandle u3, i2c, mpic;	u32 u3_rev;	u32 interrupts[2];	u32 parent;	/* Some G5s have a missing interrupt definition, fix it up here */	u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));	if (!PHANDLE_VALID(u3))		return;	i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));	if (!PHANDLE_VALID(i2c))		return;	mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));	if (!PHANDLE_VALID(mpic))		return;	/* check if proper rev of u3 */	if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))	    == PROM_ERROR)		return;	if (u3_rev < 0x35 || u3_rev > 0x39)		return;	/* does it need fixup ? */	if (prom_getproplen(i2c, "interrupts") > 0)		return;	prom_printf("fixing up bogus interrupts for u3 i2c...\n");	/* interrupt on this revision of u3 is number 0 and level */	interrupts[0] = 0;	interrupts[1] = 1;	prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",		     &interrupts, sizeof(interrupts));	parent = (u32)mpic;	prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",		     &parent, sizeof(parent));}#else#define fixup_device_tree_pmac()#endif#ifdef CONFIG_PPC_EFIKA/* The current fw of the Efika has a device tree needs quite a few * fixups to be compliant with the mpc52xx bindings. It's currently * unknown if it will ever be compliant (come on bPlan ...) so we do fixups. * NOTE that we (barely) tolerate it because the EFIKA was out before * the bindings were finished, for any new boards -> RTFM ! */struct subst_entry {	char *path;	char *property;	void *value;	int value_len;};static void __init fixup_device_tree_efika(void){	/* Substitution table */	#define prop_cstr(x) x, sizeof(x)	int prop_sound_irq[3] = { 2, 2, 0 };	int prop_bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,	                             3,4,0, 3,5,0, 3,6,0, 3,7,0,	                             3,8,0, 3,9,0, 3,10,0, 3,11,0,	                             3,12,0, 3,13,0, 3,14,0, 3,15,0 };	struct subst_entry efika_subst_table[] = {		{ "/",			"device_type",	prop_cstr("efika") },		{ "/builtin",		"device_type",	prop_cstr("soc") },		{ "/builtin/ata",	"compatible",	prop_cstr("mpc5200b-ata\0mpc5200-ata"), },		{ "/builtin/bestcomm",	"compatible",	prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") },		{ "/builtin/bestcomm",	"interrupts",	prop_bcomm_irq, sizeof(prop_bcomm_irq) },		{ "/builtin/ethernet",	"compatible",	prop_cstr("mpc5200b-fec\0mpc5200-fec") },		{ "/builtin/pic",	"compatible",	prop_cstr("mpc5200b-pic\0mpc5200-pic") },		{ "/builtin/serial",	"compatible",	prop_cstr("mpc5200b-psc-uart\0mpc5200-psc-uart") },		{ "/builtin/sound",	"compatible",	prop_cstr("mpc5200b-psc-ac97\0mpc5200-psc-ac97") },		{ "/builtin/sound",	"interrupts",	prop_sound_irq, sizeof(prop_sound_irq) },		{ "/builtin/sram",	"compatible",	prop_cstr("mpc5200b-sram\0mpc5200-sram") },		{ "/builtin/sram",	"device_type",	prop_cstr("sram") },		{}	};	#undef prop_cstr	/* Vars */	u32 node;	char prop[64];	int rv, i;	/* Check if we're really running on a EFIKA */	node = call_prom("finddevice", 1, 1, ADDR("/"));	if (!PHANDLE_VALID(node))		return;	rv = prom_getprop(node, "model", prop, sizeof(prop));	if (rv == PROM_ERROR)		return;	if (strcmp(prop, "EFIKA5K2"))		return;	prom_printf("Applying EFIKA device tree fixups\n");	/* Process substitution table */	for (i=0; efika_subst_table[i].path; i++) {		struct subst_entry *se = &efika_subst_table[i];		node = call_prom("finddevice", 1, 1, ADDR(se->path));		if (!PHANDLE_VALID(node)) {			prom_printf("fixup_device_tree_efika: ",				"skipped entry %x - not found\n", i);			continue;		}		rv = prom_setprop(node, se->path, se->property,					se->value, se->value_len );		if (rv == PROM_ERROR)			prom_printf("fixup_device_tree_efika: ",				"skipped entry %x - setprop error\n", i);	}	/* Make sure ethernet mdio bus node exists */	node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));	if (!PHANDLE_VALID(node)) {		prom_printf("Adding Ethernet MDIO node\n");		call_prom("interpret", 1, 1,			" s\" /builtin\" find-device"			" new-device"				" 1 encode-int s\" #address-cells\" property"				" 0 encode-int s\" #size-cells\" property"				" s\" mdio\" 2dup device-name device-type"				" s\" mpc5200b-fec-phy\" encode-string"				" s\" compatible\" property"				" 0xf0003000 0x400 reg"				" 0x2 encode-int"				" 0x5 encode-int encode+"				" 0x3 encode-int encode+"				" s\" interrupts\" property"			" finish-device");	};	/* Make sure ethernet phy device node exist */	node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio/ethernet-phy"));	if (!PHANDLE_VALID(node)) {		prom_printf("Adding Ethernet PHY node\n");		call_prom("interpret", 1, 1,			" s\" /builtin/mdio\" find-device"			" new-device"				" s\" ethernet-phy\" device-name"				" 0x10 encode-int s\" reg\" property"				" my-self"				" ihandle>phandle"			" finish-device"			" s\" /builtin/ethernet\" find-device"				" encode-int"				" s\" phy-handle\" property"			" device-end");	}}#else#define fixup_device_tree_efika()#endifstatic void __init fixup_device_tree(void){	fixup_device_tree_maple();	fixup_device_tree_chrp();	fixup_device_tree_pmac();	fixup_device_tree_efika();}static void __init prom_find_boot_cpu(void){	struct prom_t *_prom = &RELOC(prom);	u32 getprop_rval;	ihandle prom_cpu;	phandle cpu_pkg;	_prom->cpu = 0;	if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)		return;	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);	prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));	_prom->cpu = getprop_rval;	prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);}static void __init prom_check_initrd(unsigned long r3, unsigned long r4){#ifdef CONFIG_BLK_DEV_INITRD	struct prom_t *_prom = &RELOC(prom);	if (r3 && r4 && r4 != 0xdeadbeef) {		unsigned long val;		RELOC(prom_initrd_start) = is_kernel_addr(r3) ? __pa(r3) : r3;		RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;		val = RELOC(prom_initrd_start);		prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start",			     &val, sizeof(val));		val = RELOC(prom_initrd_end);		prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end",			     &val, sizeof(val));		reserve_mem(RELOC(prom_initrd_start),			    RELOC(prom_initrd_end) - RELOC(prom_initrd_start));		prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start));		prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end));	}#endif /* CONFIG_BLK_DEV_INITRD */}/* * We enter here early on, when the Open Firmware prom is still * handling exceptions and the MMU hash table for us. */unsigned long __init prom_init(unsigned long r3, unsigned long r4,			       unsigned long pp,			       unsigned long r6, unsigned long r7){		struct prom_t *_prom;	unsigned long hdr;	unsigned long offset = reloc_offset();#ifdef CONFIG_PPC32	reloc_got2(offset);#endif	_prom = &RELOC(prom);	/*	 * First zero the BSS	 */	memset(&RELOC(__bss_start), 0, __bss_stop - __bss_start);	/*	 * Init interface to Open Firmware, get some node references

⌨️ 快捷键说明

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