extern struct lmb lmb;
extern unsigned long klimit;
-static unsigned long memory_limit;
-
static int __initdata dt_root_addr_cells;
static int __initdata dt_root_size_cells;
#ifdef CONFIG_PPC64
static int __initdata iommu_is_off;
int __initdata iommu_force_on;
-extern unsigned long tce_alloc_start, tce_alloc_end;
+unsigned long tce_alloc_start, tce_alloc_end;
#endif
typedef u32 cell_t;
struct device_node *dflt_interrupt_controller;
int num_interrupt_controllers;
-u32 rtas_data;
-u32 rtas_entry;
-
/*
* Wrapper for allocating memory for various data that needs to be
* attached to device nodes as they are processed at boot or when
return nintrc;
}
+static unsigned char map_isa_senses[4] = {
+ IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
+ IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
+ IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE,
+ IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE
+};
+
+static unsigned char map_mpic_senses[4] = {
+ IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE,
+ IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
+ /* 2 seems to be used for the 8259 cascade... */
+ IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
+ IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE,
+};
+
static int __devinit 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;
+ int i, j, n, sense;
unsigned int *irq, virq;
struct device_node *ic;
+ if (num_interrupt_controllers == 0) {
+ /*
+ * Old machines just have a list of interrupt numbers
+ * and no interrupt-controller nodes.
+ */
+ ints = (unsigned int *) get_property(np, "AAPL,interrupts",
+ &intlen);
+ /* XXX old interpret_pci_props looked in parent too */
+ /* XXX old interpret_macio_props looked for interrupts
+ before AAPL,interrupts */
+ if (ints == NULL)
+ ints = (unsigned int *) get_property(np, "interrupts",
+ &intlen);
+ if (ints == NULL)
+ return 0;
+
+ np->n_intrs = intlen / sizeof(unsigned int);
+ np->intrs = prom_alloc(np->n_intrs * sizeof(np->intrs[0]),
+ mem_start);
+ if (!np->intrs)
+ return -ENOMEM;
+ if (measure_only)
+ return 0;
+
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = *ints++;
+ np->intrs[i].sense = IRQ_SENSE_LEVEL
+ | IRQ_POLARITY_NEGATIVE;
+ }
+ return 0;
+ }
+
ints = (unsigned int *) get_property(np, "interrupts", &intlen);
if (ints == NULL)
return 0;
/* don't map IRQ numbers under a cascaded 8259 controller */
if (ic && device_is_compatible(ic, "chrp,iic")) {
np->intrs[intrcount].line = irq[0];
+ sense = (n > 1)? (irq[1] & 3): 3;
+ np->intrs[intrcount].sense = map_isa_senses[sense];
} else {
-#ifdef CONFIG_PPC64
virq = virt_irq_create_mapping(irq[0]);
+#ifdef CONFIG_PPC64
if (virq == NO_IRQ) {
printk(KERN_CRIT "Could not allocate interrupt"
" number for %s\n", np->full_name);
continue;
}
- virq = irq_offset_up(virq);
-#else
- virq = irq[0];
#endif
- np->intrs[intrcount].line = virq;
+ np->intrs[intrcount].line = irq_offset_up(virq);
+ sense = (n > 1)? (irq[1] & 3): 1;
+ np->intrs[intrcount].sense = map_mpic_senses[sense];
}
#ifdef CONFIG_PPC64
break;
}
#endif
- 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);
* 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 *uname, int depth,
- void *data),
- void *data)
+int __init of_scan_flat_dt(int (*it)(unsigned long node,
+ const char *uname, int depth,
+ void *data),
+ void *data)
{
unsigned long p = ((unsigned long)initial_boot_params) +
initial_boot_params->off_dt_struct;
* 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)
+void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
+ unsigned long *size)
{
unsigned long p = node;
/* Get pointer to OF "/chosen" node for use everywhere */
of_chosen = of_find_node_by_path("/chosen");
+ if (of_chosen == NULL)
+ of_chosen = of_find_node_by_path("/chosen@0");
/* Retreive command line */
if (of_chosen != NULL) {
static int __init early_init_dt_scan_cpus(unsigned long node,
const char *uname, int depth, void *data)
{
- char *type = get_flat_dt_prop(node, "device_type", NULL);
+ char *type = of_get_flat_dt_prop(node, "device_type", NULL);
u32 *prop;
unsigned long size = 0;
if (type == NULL || strcmp(type, "cpu") != 0)
return 0;
-#ifdef CONFIG_PPC_PSERIES
- /* On LPAR, look for the first ibm,pft-size property for the hash table size
- */
- if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) {
- u32 *pft_size;
- pft_size = get_flat_dt_prop(node, "ibm,pft-size", NULL);
- if (pft_size != NULL) {
- /* pft_size[0] is the NUMA CEC cookie */
- ppc64_pft_size = pft_size[1];
- }
- }
-#endif
-
-#ifdef CONFIG_PPC64
+ boot_cpuid = 0;
+ boot_cpuid_phys = 0;
if (initial_boot_params && initial_boot_params->version >= 2) {
/* version 2 of the kexec param format adds the phys cpuid
* of booted proc.
*/
boot_cpuid_phys = initial_boot_params->boot_cpuid_phys;
- boot_cpuid = 0;
} else {
- /* 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) {
- prop = get_flat_dt_prop(node, "reg", NULL);
- set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop);
- boot_cpuid_phys = get_hard_smp_processor_id(0);
+ /* Check if it's the boot-cpu, set it's hw index now */
+ if (of_get_flat_dt_prop(node,
+ "linux,boot-cpu", NULL) != NULL) {
+ prop = of_get_flat_dt_prop(node, "reg", NULL);
+ if (prop != NULL)
+ boot_cpuid_phys = *prop;
}
}
-#endif
+ set_hard_smp_processor_id(0, boot_cpuid_phys);
#ifdef CONFIG_ALTIVEC
/* Check if we have a VMX and eventually update CPU features */
- prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", &size);
+ prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", &size);
if (prop && (*prop) > 0) {
cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
}
/* Same goes for Apple's "altivec" property */
- prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL);
+ prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL);
if (prop) {
cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
* this by looking at the size of the ibm,ppc-interrupt-server#s
* property
*/
- prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
+ prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
&size);
cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
if (prop && ((size / sizeof(u32)) > 1))
DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
- if (depth != 1 || strcmp(uname, "chosen") != 0)
+ if (depth != 1 ||
+ (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
return 0;
/* get platform type */
- prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL);
+ prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL);
if (prop == NULL)
return 0;
#ifdef CONFIG_PPC64
systemcfg->platform = *prop;
#else
+#ifdef CONFIG_PPC_MULTIPLATFORM
_machine = *prop;
#endif
+#endif
#ifdef CONFIG_PPC64
/* check if iommu is forced on or off */
- if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
+ if (of_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)
+ if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
iommu_force_on = 1;
#endif
- lprop = get_flat_dt_prop(node, "linux,memory-limit", NULL);
+ lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
if (lprop)
memory_limit = *lprop;
#ifdef CONFIG_PPC64
- lprop = get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
+ lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
if (lprop)
tce_alloc_start = *lprop;
- lprop = get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
+ lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
if (lprop)
tce_alloc_end = *lprop;
#endif
{
u64 *basep, *entryp;
- basep = get_flat_dt_prop(node, "linux,rtas-base", NULL);
- entryp = get_flat_dt_prop(node, "linux,rtas-entry", NULL);
- prop = get_flat_dt_prop(node, "linux,rtas-size", NULL);
+ basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
+ entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
+ prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
if (basep && entryp && prop) {
rtas.base = *basep;
rtas.entry = *entryp;
if (depth != 0)
return 0;
- prop = get_flat_dt_prop(node, "#size-cells", NULL);
+ prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
dt_root_size_cells = (prop == NULL) ? 1 : *prop;
DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
- prop = get_flat_dt_prop(node, "#address-cells", NULL);
+ prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
static int __init early_init_dt_scan_memory(unsigned long node,
const char *uname, int depth, void *data)
{
- char *type = get_flat_dt_prop(node, "device_type", NULL);
+ char *type = of_get_flat_dt_prop(node, "device_type", NULL);
cell_t *reg, *endp;
unsigned long l;
if (type == NULL || strcmp(type, "memory") != 0)
return 0;
- reg = (cell_t *)get_flat_dt_prop(node, "reg", &l);
+ reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
if (reg == NULL)
return 0;
endp = reg + (l / sizeof(cell_t));
- DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",
+ DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
uname, l, reg[0], reg[1], reg[2], reg[3]);
while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
* device-tree, including the platform type, initrd location and
* size, TCE reserve, and more ...
*/
- scan_flat_dt(early_init_dt_scan_chosen, NULL);
+ of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
/* Scan memory nodes and rebuild LMBs */
lmb_init();
- scan_flat_dt(early_init_dt_scan_root, NULL);
- scan_flat_dt(early_init_dt_scan_memory, NULL);
+ of_scan_flat_dt(early_init_dt_scan_root, NULL);
+ of_scan_flat_dt(early_init_dt_scan_memory, NULL);
lmb_enforce_memory_limit(memory_limit);
lmb_analyze();
#ifdef CONFIG_PPC64
DBG("Scanning CPUs ...\n");
- /* Retreive hash table size from flattened tree plus other
- * CPU related informations (altivec support, boot CPU ID, ...)
+ /* Retreive CPU related informations from the flat tree
+ * (altivec support, boot CPU ID, ...)
*/
- scan_flat_dt(early_init_dt_scan_cpus, NULL);
+ of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
DBG(" <- early_init_devtree()\n");
}
int i, j;
/* default to level-triggered */
- memset(senses, 1, max - off);
+ memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, max - off);
for (np = allnodes; np != 0; np = np->allnext) {
for (j = 0; j < np->n_intrs; j++) {
i = np->intrs[j].line;
if (i >= off && i < max)
- senses[i-off] = np->intrs[j].sense ?
- IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE :
- IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE;
+ senses[i-off] = np->intrs[j].sense;
}
}
}
/*
* Add a property to a node
*/
-void prom_add_property(struct device_node* np, struct property* prop)
+int prom_add_property(struct device_node* np, struct property* prop)
{
- struct property **next = &np->properties;
+ struct property **next;
prop->next = NULL;
- while (*next)
+ write_lock(&devtree_lock);
+ next = &np->properties;
+ while (*next) {
+ if (strcmp(prop->name, (*next)->name) == 0) {
+ /* duplicate ! don't insert it */
+ write_unlock(&devtree_lock);
+ return -1;
+ }
next = &(*next)->next;
+ }
*next = prop;
+ write_unlock(&devtree_lock);
+
+ /* try to add to proc as well if it was initialized */
+ if (np->pde)
+ proc_device_tree_add_prop(np->pde, prop);
+
+ return 0;
}
/* I quickly hacked that one, check against spec ! */
}
}
+#ifdef CONFIG_PCI
static struct resource *find_parent_pci_resource(struct pci_dev* pdev,
struct address_range *range)
{
return 0;
}
EXPORT_SYMBOL(release_OF_resource);
+#endif /* CONFIG_PCI */