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

prom.c

Linux Kernel 2.6.9 for OMAP1710
C
第 1 页 / 共 4 页
字号:
/* *  * * Procedures for interfacing to Open Firmware. * * Paul Mackerras	August 1996. * Copyright (C) 1996 Paul Mackerras. *  *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. *    {engebret|bergner}@us.ibm.com  * *      This program is free software; you can redistribute it and/or *      modify it under the terms of the GNU General Public License *      as published by the Free Software Foundation; either version *      2 of the License, or (at your option) any later version. */#undef DEBUG#include <stdarg.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/init.h>#include <linux/version.h>#include <linux/threads.h>#include <linux/spinlock.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/proc_fs.h>#include <linux/stringify.h>#include <linux/delay.h>#include <linux/initrd.h>#include <asm/prom.h>#include <asm/rtas.h>#include <asm/lmb.h>#include <asm/abs_addr.h>#include <asm/page.h>#include <asm/processor.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/smp.h>#include <asm/system.h>#include <asm/mmu.h>#include <asm/pgtable.h>#include <asm/bitops.h>#include <asm/naca.h>#include <asm/pci.h>#include <asm/iommu.h>#include <asm/bootinfo.h>#include <asm/ppcdebug.h>#include <asm/btext.h>#include <asm/sections.h>#include <asm/machdep.h>#include "open_pic.h"#ifdef DEBUG#define DBG(fmt...) udbg_printf(fmt)#else#define DBG(fmt...)#endifstruct pci_reg_property {	struct pci_address addr;	u32 size_hi;	u32 size_lo;};struct isa_reg_property {	u32 space;	u32 address;	u32 size;};typedef unsigned long interpret_func(struct device_node *, unsigned long,				     int, int, int);extern struct rtas_t rtas;extern struct lmb lmb;extern unsigned long klimit;static int __initdata dt_root_addr_cells;static int __initdata dt_root_size_cells;static int __initdata iommu_is_off;int __initdata iommu_force_on;typedef u32 cell_t;#if 0static struct boot_param_header *initial_boot_params __initdata;#elsestruct boot_param_header *initial_boot_params;#endifstatic struct device_node *allnodes = NULL;/* use when traversing tree through the allnext, child, sibling, * or parent members of struct device_node. */static rwlock_t devtree_lock = RW_LOCK_UNLOCKED;/* export that to outside world */struct device_node *of_chosen;/* * Find the device_node with a given phandle. */static struct device_node * find_phandle(phandle ph){	struct device_node *np;	for (np = allnodes; np != 0; np = np->allnext)		if (np->linux_phandle == ph)			return np;	return NULL;}/* * Find the interrupt parent of a node. */static struct device_node * __devinit intr_parent(struct device_node *p){	phandle *parp;	parp = (phandle *) get_property(p, "interrupt-parent", NULL);	if (parp == NULL)		return p->parent;	return find_phandle(*parp);}/* * Find out the size of each entry of the interrupts property * for a node. */int __devinit prom_n_intr_cells(struct device_node *np){	struct device_node *p;	unsigned int *icp;	for (p = np; (p = intr_parent(p)) != NULL; ) {		icp = (unsigned int *)			get_property(p, "#interrupt-cells", NULL);		if (icp != NULL)			return *icp;		if (get_property(p, "interrupt-controller", NULL) != NULL		    || get_property(p, "interrupt-map", NULL) != NULL) {			printk("oops, node %s doesn't have #interrupt-cells\n",			       p->full_name);			return 1;		}	}#ifdef DEBUG_IRQ	printk("prom_n_intr_cells failed for %s\n", np->full_name);#endif	return 1;}/* * Map an interrupt from a device up to the platform interrupt * descriptor. */static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler,				   struct device_node *np, unsigned int *ints,				   int nintrc){	struct device_node *p, *ipar;	unsigned int *imap, *imask, *ip;	int i, imaplen, match;	int newintrc = 0, newaddrc = 0;	unsigned int *reg;	int naddrc;	reg = (unsigned int *) get_property(np, "reg", NULL);	naddrc = prom_n_addr_cells(np);	p = intr_parent(np);	while (p != NULL) {		if (get_property(p, "interrupt-controller", NULL) != NULL)			/* this node is an interrupt controller, stop here */			break;		imap = (unsigned int *)			get_property(p, "interrupt-map", &imaplen);		if (imap == NULL) {			p = intr_parent(p);			continue;		}		imask = (unsigned int *)			get_property(p, "interrupt-map-mask", NULL);		if (imask == NULL) {			printk("oops, %s has interrupt-map but no mask\n",			       p->full_name);			return 0;		}		imaplen /= sizeof(unsigned int);		match = 0;		ipar = NULL;		while (imaplen > 0 && !match) {			/* check the child-interrupt field */			match = 1;			for (i = 0; i < naddrc && match; ++i)				match = ((reg[i] ^ imap[i]) & imask[i]) == 0;			for (; i < naddrc + nintrc && match; ++i)				match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;			imap += naddrc + nintrc;			imaplen -= naddrc + nintrc;			/* grab the interrupt parent */			ipar = find_phandle((phandle) *imap++);			--imaplen;			if (ipar == NULL) {				printk("oops, no int parent %x in map of %s\n",				       imap[-1], p->full_name);				return 0;			}			/* find the parent's # addr and intr cells */			ip = (unsigned int *)				get_property(ipar, "#interrupt-cells", NULL);			if (ip == NULL) {				printk("oops, no #interrupt-cells on %s\n",				       ipar->full_name);				return 0;			}			newintrc = *ip;			ip = (unsigned int *)				get_property(ipar, "#address-cells", NULL);			newaddrc = (ip == NULL)? 0: *ip;			imap += newaddrc + newintrc;			imaplen -= newaddrc + newintrc;		}		if (imaplen < 0) {			printk("oops, error decoding int-map on %s, len=%d\n",			       p->full_name, imaplen);			return 0;		}		if (!match) {#ifdef DEBUG_IRQ			printk("oops, no match in %s int-map for %s\n",			       p->full_name, np->full_name);#endif			return 0;		}		p = ipar;		naddrc = newaddrc;		nintrc = newintrc;		ints = imap - nintrc;		reg = ints - naddrc;	}	if (p == NULL) {#ifdef DEBUG_IRQ		printk("hmmm, int tree for %s doesn't have ctrler\n",		       np->full_name);#endif		return 0;	}	*irq = ints;	*ictrler = p;	return nintrc;}static unsigned long __init finish_node_interrupts(struct device_node *np,						   unsigned long mem_start,						   int measure_only){	unsigned int *ints;	int intlen, intrcells, intrcount;	int i, j, n;	unsigned int *irq, virq;	struct device_node *ic;	ints = (unsigned int *) get_property(np, "interrupts", &intlen);	if (ints == NULL)		return mem_start;	intrcells = prom_n_intr_cells(np);	intlen /= intrcells * sizeof(unsigned int);	np->intrs = (struct interrupt_info *) mem_start;	mem_start += intlen * sizeof(struct interrupt_info);	if (measure_only)		return mem_start;	intrcount = 0;	for (i = 0; i < intlen; ++i, ints += intrcells) {		n = map_interrupt(&irq, &ic, np, ints, intrcells);		if (n <= 0)			continue;		/* don't map IRQ numbers under a cascaded 8259 controller */		if (ic && device_is_compatible(ic, "chrp,iic")) {			np->intrs[intrcount].line = irq[0];		} else {			virq = virt_irq_create_mapping(irq[0]);			if (virq == NO_IRQ) {				printk(KERN_CRIT "Could not allocate interrupt"				       " number for %s\n", np->full_name);				continue;			}			np->intrs[intrcount].line = irq_offset_up(virq);		}		/* We offset irq numbers for the u3 MPIC by 128 in PowerMac */		if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) {			char *name = get_property(ic->parent, "name", NULL);			if (name && !strcmp(name, "u3"))				np->intrs[intrcount].line += 128;		}		np->intrs[intrcount].sense = 1;		if (n > 1)			np->intrs[intrcount].sense = irq[1];		if (n > 2) {			printk("hmmm, got %d intr cells for %s:", n,			       np->full_name);			for (j = 0; j < n; ++j)				printk(" %d", irq[j]);			printk("\n");		}		++intrcount;	}	np->n_intrs = intrcount;	return mem_start;}static unsigned long __init interpret_pci_props(struct device_node *np,						unsigned long mem_start,						int naddrc, int nsizec,						int measure_only){	struct address_range *adr;	struct pci_reg_property *pci_addrs;	int i, l;	pci_addrs = (struct pci_reg_property *)		get_property(np, "assigned-addresses", &l);	if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {		i = 0;		adr = (struct address_range *) mem_start;		while ((l -= sizeof(struct pci_reg_property)) >= 0) {			if (!measure_only) {				adr[i].space = pci_addrs[i].addr.a_hi;				adr[i].address = pci_addrs[i].addr.a_lo;				adr[i].size = pci_addrs[i].size_lo;			}			++i;		}		np->addrs = adr;		np->n_addrs = i;		mem_start += i * sizeof(struct address_range);	}	return mem_start;}static unsigned long __init interpret_dbdma_props(struct device_node *np,						  unsigned long mem_start,						  int naddrc, int nsizec,						  int measure_only){	struct reg_property32 *rp;	struct address_range *adr;	unsigned long base_address;	int i, l;	struct device_node *db;	base_address = 0;	if (!measure_only) {		for (db = np->parent; db != NULL; db = db->parent) {			if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {				base_address = db->addrs[0].address;				break;			}		}	}	rp = (struct reg_property32 *) get_property(np, "reg", &l);	if (rp != 0 && l >= sizeof(struct reg_property32)) {		i = 0;		adr = (struct address_range *) mem_start;		while ((l -= sizeof(struct reg_property32)) >= 0) {			if (!measure_only) {				adr[i].space = 2;				adr[i].address = rp[i].address + base_address;				adr[i].size = rp[i].size;			}			++i;		}		np->addrs = adr;		np->n_addrs = i;		mem_start += i * sizeof(struct address_range);	}	return mem_start;}static unsigned long __init interpret_macio_props(struct device_node *np,						  unsigned long mem_start,						  int naddrc, int nsizec,						  int measure_only){	struct reg_property32 *rp;	struct address_range *adr;	unsigned long base_address;	int i, l;	struct device_node *db;	base_address = 0;	if (!measure_only) {		for (db = np->parent; db != NULL; db = db->parent) {			if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {				base_address = db->addrs[0].address;				break;			}		}	}	rp = (struct reg_property32 *) get_property(np, "reg", &l);	if (rp != 0 && l >= sizeof(struct reg_property32)) {		i = 0;		adr = (struct address_range *) mem_start;		while ((l -= sizeof(struct reg_property32)) >= 0) {			if (!measure_only) {				adr[i].space = 2;				adr[i].address = rp[i].address + base_address;				adr[i].size = rp[i].size;			}			++i;		}		np->addrs = adr;		np->n_addrs = i;		mem_start += i * sizeof(struct address_range);	}	return mem_start;}static unsigned long __init interpret_isa_props(struct device_node *np,						unsigned long mem_start,						int naddrc, int nsizec,						int measure_only){	struct isa_reg_property *rp;	struct address_range *adr;	int i, l;	rp = (struct isa_reg_property *) get_property(np, "reg", &l);	if (rp != 0 && l >= sizeof(struct isa_reg_property)) {		i = 0;		adr = (struct address_range *) mem_start;		while ((l -= sizeof(struct reg_property)) >= 0) {			if (!measure_only) {				adr[i].space = rp[i].space;				adr[i].address = rp[i].address;				adr[i].size = rp[i].size;			}			++i;		}		np->addrs = adr;		np->n_addrs = i;		mem_start += i * sizeof(struct address_range);	}	return mem_start;}static unsigned long __init interpret_root_props(struct device_node *np,						 unsigned long mem_start,						 int naddrc, int nsizec,						 int measure_only){	struct address_range *adr;	int i, l;	unsigned int *rp;	int rpsize = (naddrc + nsizec) * sizeof(unsigned int);	rp = (unsigned int *) get_property(np, "reg", &l);	if (rp != 0 && l >= rpsize) {		i = 0;		adr = (struct address_range *) mem_start;		while ((l -= rpsize) >= 0) {			if (!measure_only) {				adr[i].space = 0;				adr[i].address = rp[naddrc - 1];				adr[i].size = rp[naddrc + nsizec - 1];			}			++i;			rp += naddrc + nsizec;		}		np->addrs = adr;		np->n_addrs = i;		mem_start += i * sizeof(struct address_range);

⌨️ 快捷键说明

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