欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

prom.c

Linux Kernel 2.6.9 for OMAP1710
C
第 1 页 / 共 4 页
字号:
	}	return mem_start;}static unsigned long __init finish_node(struct device_node *np,					unsigned long mem_start,					interpret_func *ifunc,					int naddrc, int nsizec,					int measure_only){	struct device_node *child;	int *ip;	/* get the device addresses and interrupts */	if (ifunc != NULL)		mem_start = ifunc(np, mem_start, naddrc, nsizec, measure_only);	mem_start = finish_node_interrupts(np, mem_start, measure_only);	/* Look for #address-cells and #size-cells properties. */	ip = (int *) get_property(np, "#address-cells", NULL);	if (ip != NULL)		naddrc = *ip;	ip = (int *) get_property(np, "#size-cells", NULL);	if (ip != NULL)		nsizec = *ip;	/* the f50 sets the name to 'display' and 'compatible' to what we	 * expect for the name -- Cort	 */	if (!strcmp(np->name, "display"))		np->name = get_property(np, "compatible", NULL);	if (!strcmp(np->name, "device-tree") || np->parent == NULL)		ifunc = interpret_root_props;	else if (np->type == 0)		ifunc = NULL;	else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))		ifunc = interpret_pci_props;	else if (!strcmp(np->type, "dbdma"))		ifunc = interpret_dbdma_props;	else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props)		ifunc = interpret_macio_props;	else if (!strcmp(np->type, "isa"))		ifunc = interpret_isa_props;	else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))		ifunc = interpret_root_props;	else if (!((ifunc == interpret_dbdma_props		    || ifunc == interpret_macio_props)		   && (!strcmp(np->type, "escc")		       || !strcmp(np->type, "media-bay"))))		ifunc = NULL;	for (child = np->child; child != NULL; child = child->sibling)		mem_start = finish_node(child, mem_start, ifunc,					naddrc, nsizec, measure_only);	return mem_start;}/** * finish_device_tree is called once things are running normally * (i.e. with text and data mapped to the address they were linked at). * It traverses the device tree and fills in some of the additional, * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt * mapping is also initialized at this point. */void __init finish_device_tree(void){	unsigned long mem, size;	DBG(" -> finish_device_tree\n");	if (naca->interrupt_controller == IC_INVALID) {		DBG("failed to configure interrupt controller type\n");		panic("failed to configure interrupt controller type\n");	}		/* Initialize virtual IRQ map */	virt_irq_init();	/* Finish device-tree (pre-parsing some properties etc...) */	size = finish_node(allnodes, 0, NULL, 0, 0, 1);	mem = (unsigned long)abs_to_virt(lmb_alloc(size, 128));	if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + size)		BUG();	DBG(" <- finish_device_tree\n");}#ifdef DEBUG#define printk udbg_printf#endifstatic inline char *find_flat_dt_string(u32 offset){	return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings		+ offset;}/** * This function is used to scan the flattened device-tree, it is * used to extract the memory informations at boot before we can * unflatten the tree */static int __init scan_flat_dt(int (*it)(unsigned long node,					 const char *full_path, void *data),			       void *data){	unsigned long p = ((unsigned long)initial_boot_params) +		initial_boot_params->off_dt_struct;	int rc = 0;	do {		u32 tag = *((u32 *)p);		char *pathp;				p += 4;		if (tag == OF_DT_END_NODE)			continue;		if (tag == OF_DT_END)			break;		if (tag == OF_DT_PROP) {			u32 sz = *((u32 *)p);			p += 8;			p = _ALIGN(p, sz >= 8 ? 8 : 4);			p += sz;			p = _ALIGN(p, 4);			continue;		}		if (tag != OF_DT_BEGIN_NODE) {			printk(KERN_WARNING "Invalid tag %x scanning flattened"			       " device tree !\n", tag);			return -EINVAL;		}		pathp = (char *)p;		p = _ALIGN(p + strlen(pathp) + 1, 4);		rc = it(p, pathp, data);		if (rc != 0)			break;			} while(1);	return rc;}/** * This  function can be used within scan_flattened_dt callback to get * access to properties */static void* __init get_flat_dt_prop(unsigned long node, const char *name,				     unsigned long *size){	unsigned long p = node;	do {		u32 tag = *((u32 *)p);		u32 sz, noff;		const char *nstr;		p += 4;		if (tag != OF_DT_PROP)			return NULL;		sz = *((u32 *)p);		noff = *((u32 *)(p + 4));		p += 8;		p = _ALIGN(p, sz >= 8 ? 8 : 4);		nstr = find_flat_dt_string(noff);		if (nstr == NULL) {			printk(KERN_WARNING "Can't find property index name !\n");			return NULL;		}		if (strcmp(name, nstr) == 0) {			if (size)				*size = sz;			return (void *)p;		}		p += sz;		p = _ALIGN(p, 4);	} while(1);}static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,					       unsigned long align){	void *res;	*mem = _ALIGN(*mem, align);	res = (void *)*mem;	*mem += size;	return res;}static unsigned long __init unflatten_dt_node(unsigned long mem,					      unsigned long *p,					      struct device_node *dad,					      struct device_node ***allnextpp){	struct device_node *np;	struct property *pp, **prev_pp = NULL;	char *pathp;	u32 tag;	unsigned int l;	tag = *((u32 *)(*p));	if (tag != OF_DT_BEGIN_NODE) {		printk("Weird tag at start of node: %x\n", tag);		return mem;	}	*p += 4;	pathp = (char *)*p;	l = strlen(pathp) + 1;	*p = _ALIGN(*p + l, 4);	np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l,				__alignof__(struct device_node));	if (allnextpp) {		memset(np, 0, sizeof(*np));		np->full_name = ((char*)np) + sizeof(struct device_node);		memcpy(np->full_name, pathp, l);		prev_pp = &np->properties;		**allnextpp = np;		*allnextpp = &np->allnext;		if (dad != NULL) {			np->parent = dad;			/* we temporarily use the `next' field as `last_child'. */			if (dad->next == 0)				dad->child = np;			else				dad->next->sibling = np;			dad->next = np;		}	}	while(1) {		u32 sz, noff;		char *pname;		tag = *((u32 *)(*p));		if (tag != OF_DT_PROP)			break;		*p += 4;		sz = *((u32 *)(*p));		noff = *((u32 *)((*p) + 4));		*p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4);		pname = find_flat_dt_string(noff);		if (pname == NULL) {			printk("Can't find property name in list !\n");			break;		}		l = strlen(pname) + 1;		pp = unflatten_dt_alloc(&mem, sizeof(struct property),					__alignof__(struct property));		if (allnextpp) {			if (strcmp(pname, "linux,phandle") == 0) {				np->node = *((u32 *)*p);				if (np->linux_phandle == 0)					np->linux_phandle = np->node;			}			if (strcmp(pname, "ibm,phandle") == 0)				np->linux_phandle = *((u32 *)*p);			pp->name = pname;			pp->length = sz;			pp->value = (void *)*p;			*prev_pp = pp;			prev_pp = &pp->next;		}		*p = _ALIGN((*p) + sz, 4);	}	if (allnextpp) {		*prev_pp = NULL;		np->name = get_property(np, "name", NULL);		np->type = get_property(np, "device_type", NULL);		if (!np->name)			np->name = "<NULL>";		if (!np->type)			np->type = "<NULL>";	}	while (tag == OF_DT_BEGIN_NODE) {		mem = unflatten_dt_node(mem, p, np, allnextpp);		tag = *((u32 *)(*p));	}	if (tag != OF_DT_END_NODE) {		printk("Weird tag at start of node: %x\n", tag);		return mem;	}	*p += 4;	return mem;}/** * unflattens the device-tree passed by the firmware, creating the * tree of struct device_node. It also fills the "name" and "type" * pointers of the nodes so the normal device-tree walking functions * can be used (this used to be done by finish_device_tree) */void __init unflatten_device_tree(void){	unsigned long start, mem, size;	struct device_node **allnextp = &allnodes;	char *p;	int l = 0;	DBG(" -> unflatten_device_tree()\n");	/* First pass, scan for size */	start = ((unsigned long)initial_boot_params) +		initial_boot_params->off_dt_struct;	size = unflatten_dt_node(0, &start, NULL, NULL);	DBG("  size is %lx, allocating...\n", size);	/* Allocate memory for the expanded device tree */	mem = (unsigned long)abs_to_virt(lmb_alloc(size,						   __alignof__(struct device_node)));	DBG("  unflattening...\n", mem);	/* Second pass, do actual unflattening */	start = ((unsigned long)initial_boot_params) +		initial_boot_params->off_dt_struct;	unflatten_dt_node(mem, &start, NULL, &allnextp);	if (*((u32 *)start) != OF_DT_END)		printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start));	*allnextp = NULL;	/* Get pointer to OF "/chosen" node for use everywhere */	of_chosen = of_find_node_by_path("/chosen");	/* Retreive command line */	if (of_chosen != NULL) {		p = (char *)get_property(of_chosen, "bootargs", &l);		if (p != NULL && l > 0)			strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE));	}#ifdef CONFIG_CMDLINE	if (l == 0) /* dbl check */		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);#endif /* CONFIG_CMDLINE */	DBG("Command line is: %s\n", cmd_line);	DBG(" <- unflatten_device_tree()\n");}static int __init early_init_dt_scan_cpus(unsigned long node,					  const char *full_path, void *data){	char *type = get_flat_dt_prop(node, "device_type", NULL);	/* We are scanning "cpu" nodes only */	if (type == NULL || strcmp(type, "cpu") != 0)		return 0;	/* On LPAR, look for the first ibm,pft-size property for the  hash table size	 */	if (systemcfg->platform == PLATFORM_PSERIES_LPAR && naca->pftSize == 0) {		u32 *pft_size;		pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL);		if (pft_size != NULL) {			/* pft_size[0] is the NUMA CEC cookie */			naca->pftSize = pft_size[1];		}	}	/* Check if it's the boot-cpu, set it's hw index in paca now */	if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) {		u32 *prop = get_flat_dt_prop(node, "reg", NULL);		paca[0].hw_cpu_id = prop == NULL ? 0 : *prop;	}	return 0;}static int __init early_init_dt_scan_chosen(unsigned long node,					    const char *full_path, void *data){	u32 *prop;	if (strcmp(full_path, "/chosen") != 0)		return 0;	/* get platform type */	prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL);	if (prop == NULL)		return 0;	systemcfg->platform = *prop;	/* check if iommu is forced on or off */	if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)		iommu_is_off = 1;	if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)		iommu_force_on = 1;#ifdef CONFIG_PPC_PSERIES	/* To help early debugging via the front panel, we retreive a minimal	 * set of RTAS infos now if available	 */	{		u64 *basep, *entryp;		basep = (u64*)get_flat_dt_prop(node, "linux,rtas-base", NULL);		entryp = (u64*)get_flat_dt_prop(node, "linux,rtas-entry", NULL);		prop = (u32*)get_flat_dt_prop(node, "linux,rtas-size", NULL);		if (basep && entryp && prop) {			rtas.base = *basep;			rtas.entry = *entryp;			rtas.size = *prop;		}	}#endif /* CONFIG_PPC_PSERIES */	/* break now */	return 1;}static int __init early_init_dt_scan_root(unsigned long node,					  const char *full_path, void *data){	u32 *prop;	if (strcmp(full_path, "/") != 0)		return 0;	prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);	dt_root_size_cells = (prop == NULL) ? 1 : *prop;			prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);	dt_root_addr_cells = (prop == NULL) ? 2 : *prop;		/* break now */	return 1;}static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp){	cell_t *p = *cellp;	unsigned long r = 0;	/* Ignore more than 2 cells */	while (s > 2) {		p++;		s--;	}	while (s) {		r <<= 32;		r |= *(p++);		s--;	}	*cellp = p;	return r;}static int __init early_init_dt_scan_memory(unsigned long node,					    const char *full_path, void *data){	char *type = get_flat_dt_prop(node, "device_type", NULL);	cell_t *reg, *endp;	unsigned long l;	/* We are scanning "memory" nodes only */	if (type == NULL || strcmp(type, "memory") != 0)		return 0;	reg = (cell_t *)get_flat_dt_prop(node, "reg", &l);	if (reg == NULL)		return 0;	endp = reg + (l / sizeof(cell_t));	DBG("memory scan node %s ...\n", full_path);	while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {		unsigned long base, size;		base = dt_mem_next_cell(dt_root_addr_cells, &reg);		size = dt_mem_next_cell(dt_root_size_cells, &reg);		if (size == 0)			continue;

⌨️ 快捷键说明

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