static void __init pSeries_setup_mpic(void) { unsigned int *opprop; unsigned long openpic_addr = 0; unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS]; struct device_node *root; int irq_count; /* Find the Open PIC if present */ root = of_find_node_by_path("/"); opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL); if (opprop != 0) { int n = prom_n_addr_cells(root); for (openpic_addr = 0; n > 0; --n) openpic_addr = (openpic_addr << 32) + *opprop++; printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); } of_node_put(root); BUG_ON(openpic_addr == 0); /* Get the sense values from OF */ prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS); /* Setup the openpic driver */ irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY, 16, 16, irq_count, /* isu size, irq offset, irq count */ NR_IRQS - 4, /* ipi offset */ senses, irq_count, /* sense & sense size */ " MPIC "); }
static void __init pSeries_init_mpic(void) { unsigned int *addrp; struct device_node *np; int i; /* All ISUs are setup, complete initialization */ mpic_init(pSeries_mpic); /* Check what kind of cascade ACK we have */ if (!(np = of_find_node_by_name(NULL, "pci")) || !(addrp = (unsigned int *) get_property(np, "8259-interrupt-acknowledge", NULL))) printk(KERN_ERR "Cannot find pci to get ack address\n"); else chrp_int_ack_special = ioremap(addrp[prom_n_addr_cells(np)-1], 1); of_node_put(np); /* Setup the legacy interrupts & controller */ for (i = 0; i < NUM_ISA_INTERRUPTS; i++) irq_desc[i].handler = &i8259_pic; i8259_init(0); /* Hook cascade to mpic */ mpic_setup_cascade(NUM_ISA_INTERRUPTS, pSeries_irq_cascade, NULL); }
unsigned long __devinit get_phb_buid (struct device_node *phb) { int addr_cells; unsigned int *buid_vals; unsigned int len; unsigned long buid; if (ibm_read_pci_config == -1) return 0; /* PHB's will always be children of the root node, * or so it is promised by the current firmware. */ if (phb->parent == NULL) return 0; if (phb->parent->parent) return 0; buid_vals = (unsigned int *) get_property(phb, "reg", &len); if (buid_vals == NULL) return 0; addr_cells = prom_n_addr_cells(phb); if (addr_cells == 1) { buid = (unsigned long) buid_vals[0]; } else { buid = (((unsigned long)buid_vals[0]) << 32UL) | (((unsigned long)buid_vals[1]) & 0xffffffff); } return buid; }
static void of_bus_default_count_cells(struct device_node *dev, int *addrc, int *sizec) { if (addrc) *addrc = prom_n_addr_cells(dev); if (sizec) *sizec = prom_n_size_cells(dev); }
void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, unsigned long *busno, unsigned long *phys, unsigned long *size) { u32 *dma_window, cells; unsigned char *prop; dma_window = (u32 *)dma_window_prop; /* busno is always one cell */ *busno = *(dma_window++); prop = get_property(dn, "ibm,#dma-address-cells", NULL); if (!prop) prop = get_property(dn, "#address-cells", NULL); cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); *phys = of_read_number(dma_window, cells); dma_window += cells; prop = get_property(dn, "ibm,#dma-size-cells", NULL); cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); *size = of_read_number(dma_window, cells); }
static __init void maple_init_IRQ(void) { struct device_node *root; unsigned int *opprop; unsigned long opic_addr; struct mpic *mpic; unsigned char senses[128]; int n; DBG(" -> maple_init_IRQ\n"); /* XXX: Non standard, replace that with a proper openpic/mpic node * in the device-tree. Find the Open PIC if present */ root = of_find_node_by_path("/"); opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL); if (opprop == 0) panic("OpenPIC not found !\n"); n = prom_n_addr_cells(root); for (opic_addr = 0; n > 0; --n) opic_addr = (opic_addr << 32) + *opprop++; of_node_put(root); /* Obtain sense values from device-tree */ prom_get_irq_senses(senses, 0, 128); mpic = mpic_alloc(opic_addr, MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_BROKEN_U3 | MPIC_WANTS_RESET, 0, 0, 128, 128, senses, 128, "U3-MPIC"); BUG_ON(mpic == NULL); mpic_init(mpic); DBG(" <- maple_init_IRQ\n"); }
static void __init pseries_mpic_init_IRQ(void) { struct device_node *np, *old, *cascade = NULL; unsigned int *addrp; unsigned long intack = 0; unsigned int *opprop; unsigned long openpic_addr = 0; unsigned int cascade_irq; int naddr, n, i, opplen; struct mpic *mpic; np = of_find_node_by_path("/"); naddr = prom_n_addr_cells(np); opprop = (unsigned int *) get_property(np, "platform-open-pic", &opplen); if (opprop != 0) { openpic_addr = of_read_number(opprop, naddr); printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); } of_node_put(np); BUG_ON(openpic_addr == 0); /* Setup the openpic driver */ mpic = mpic_alloc(pSeries_mpic_node, openpic_addr, MPIC_PRIMARY, 16, 250, /* isu size, irq count */ " MPIC "); BUG_ON(mpic == NULL); /* Add ISUs */ opplen /= sizeof(u32); for (n = 0, i = naddr; i < opplen; i += naddr, n++) { unsigned long isuaddr = of_read_number(opprop + i, naddr); mpic_assign_isu(mpic, n, isuaddr); } /* All ISUs are setup, complete initialization */ mpic_init(mpic); /* Look for cascade */ for_each_node_by_type(np, "interrupt-controller") if (device_is_compatible(np, "chrp,iic")) { cascade = np; break; } if (cascade == NULL) return; cascade_irq = irq_of_parse_and_map(cascade, 0); if (cascade == NO_IRQ) { printk(KERN_ERR "xics: failed to map cascade interrupt"); return; } /* Check ACK type */ for (old = of_node_get(cascade); old != NULL ; old = np) { np = of_get_parent(old); of_node_put(old); if (np == NULL) break; if (strcmp(np->name, "pci") != 0) continue; addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge", NULL); if (addrp == NULL) continue; naddr = prom_n_addr_cells(np); intack = addrp[naddr-1]; if (naddr > 1) intack |= ((unsigned long)addrp[naddr-2]) << 32; } if (intack) printk(KERN_DEBUG "mpic: PCI 8259 intack at 0x%016lx\n", intack); i8259_init(cascade, intack); of_node_put(cascade); set_irq_chained_handler(cascade_irq, pseries_8259_cascade); }
/** * setup_cpu_maps - initialize the following cpu maps: * cpu_possible_map * cpu_present_map * cpu_sibling_map * * Having the possible map set up early allows us to restrict allocations * of things like irqstacks to num_possible_cpus() rather than NR_CPUS. * * We do not initialize the online map here; cpus set their own bits in * cpu_online_map as they come up. * * This function is valid only for Open Firmware systems. finish_device_tree * must be called before using this. * * While we're here, we may as well set the "physical" cpu ids in the paca. */ static void __init setup_cpu_maps(void) { struct device_node *dn = NULL; int cpu = 0; int swap_cpuid = 0; check_smt_enabled(); while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { u32 *intserv; int j, len = sizeof(u32), nthreads; intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s", &len); if (!intserv) intserv = (u32 *)get_property(dn, "reg", NULL); nthreads = len / sizeof(u32); for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { /* * Only spin up secondary threads if SMT is enabled. * We must leave space in the logical map for the * threads. */ if (j == 0 || smt_enabled_at_boot) { cpu_set(cpu, cpu_present_map); set_hard_smp_processor_id(cpu, intserv[j]); } if (intserv[j] == boot_cpuid_phys) swap_cpuid = cpu; cpu_set(cpu, cpu_possible_map); cpu++; } } /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that * boot cpu is logical 0. */ if (boot_cpuid_phys != get_hard_smp_processor_id(0)) { u32 tmp; tmp = get_hard_smp_processor_id(0); set_hard_smp_processor_id(0, boot_cpuid_phys); set_hard_smp_processor_id(swap_cpuid, tmp); } /* * On pSeries LPAR, we need to know how many cpus * could possibly be added to this partition. */ if (systemcfg->platform == PLATFORM_PSERIES_LPAR && (dn = of_find_node_by_path("/rtas"))) { int num_addr_cell, num_size_cell, maxcpus; unsigned int *ireg; num_addr_cell = prom_n_addr_cells(dn); num_size_cell = prom_n_size_cells(dn); ireg = (unsigned int *) get_property(dn, "ibm,lrdr-capacity", NULL); if (!ireg) goto out; maxcpus = ireg[num_addr_cell + num_size_cell]; /* Double maxcpus for processors which have SMT capability */ if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) maxcpus *= 2; if (maxcpus > NR_CPUS) { printk(KERN_WARNING "Partition configured for %d cpus, " "operating system maximum is %d.\n", maxcpus, NR_CPUS); maxcpus = NR_CPUS; } else printk(KERN_INFO "Partition configured for %d cpus.\n", maxcpus); for (cpu = 0; cpu < maxcpus; cpu++) cpu_set(cpu, cpu_possible_map); out: of_node_put(dn); } /* * Do the sibling map; assume only two threads per processor. */ for_each_cpu(cpu) { cpu_set(cpu, cpu_sibling_map[cpu]); if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); } systemcfg->processorCount = num_present_cpus(); }
void __init chrp_find_bridges(void) { struct device_node *dev; int *bus_range; int len, index = -1; struct pci_controller *hose; volatile unsigned char *cfg; unsigned int *dma; char *model, *machine; int is_longtrail = 0, is_mot = 0; struct device_node *root = find_path_device("/"); #ifdef CONFIG_POWER3 unsigned int *opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL); int i; #endif /* * The PCI host bridge nodes on some machines don't have * properties to adequately identify them, so we have to * look at what sort of machine this is as well. */ machine = get_property(root, "model", NULL); if (machine != NULL) { is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0; is_mot = strncmp(machine, "MOT", 3) == 0; } for (dev = root->child; dev != NULL; dev = dev->sibling) { if (dev->type == NULL || strcmp(dev->type, "pci") != 0) continue; ++index; /* The GG2 bridge on the LongTrail doesn't have an address */ if (dev->n_addrs < 1 && !is_longtrail) { printk(KERN_WARNING "Can't use %s: no address\n", dev->full_name); continue; } bus_range = (int *) get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s\n", dev->full_name); continue; } if (bus_range[1] == bus_range[0]) printk(KERN_INFO "PCI bus %d", bus_range[0]); else printk(KERN_INFO "PCI buses %d..%d", bus_range[0], bus_range[1]); printk(" controlled by %s", dev->type); if (dev->n_addrs > 0) printk(" at %x", dev->addrs[0].address); printk("\n"); hose = pcibios_alloc_controller(); if (!hose) { printk("Can't allocate PCI controller structure for %s\n", dev->full_name); continue; } hose->arch_data = dev; hose->first_busno = bus_range[0]; hose->last_busno = bus_range[1]; model = get_property(dev, "model", NULL); if (model == NULL) model = "<none>"; if (device_is_compatible(dev, "IBM,python")) { hose->ops = &python_pci_ops; cfg = ioremap(dev->addrs[0].address + 0xf8000, 0x20); hose->cfg_addr = (volatile unsigned int *) cfg; hose->cfg_data = cfg + 0x10; } else if (is_mot || strncmp(model, "Motorola, Grackle", 17) == 0) { setup_grackle(hose); } else if (is_longtrail) { hose->ops = &gg2_pci_ops; gg2_pci_config_base = (unsigned long) ioremap(GG2_PCI_CONFIG_BASE, 0x80000); } else { printk("No methods for %s (model %s), using RTAS\n", dev->full_name, model); hose->ops = &rtas_pci_ops; } pci_process_bridge_OF_ranges(hose, dev, index == 0); #ifdef CONFIG_POWER3 if (opprop != NULL) { i = prom_n_addr_cells(root) * (index + 2) - 1; openpic_setup_ISU(index, opprop[i]); } #endif /* CONFIG_POWER3 */ /* check the first bridge for a property that we can use to set pci_dram_offset */ dma = (unsigned int *) get_property(dev, "ibm,dma-ranges", &len); if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) { pci_dram_offset = dma[2] - dma[3]; printk("pci_dram_offset = %lx\n", pci_dram_offset); } } ppc_md.pcibios_fixup = chrp_pcibios_fixup; }
/* * Map an interrupt from a device up to the platform interrupt * descriptor. */ static int __init 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, newaddrc; 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 && num_interrupt_controllers == 1) /* cope with BootX not giving us phandles */ ipar = dflt_interrupt_controller; 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) { printk("oops, no match in %s int-map for %s\n", p->full_name, np->full_name); return 0; } p = ipar; naddrc = newaddrc; nintrc = newintrc; ints = imap - nintrc; reg = ints - naddrc; } if (p == NULL) printk("hmmm, int tree for %s doesn't have ctrler\n", np->full_name); *irq = ints; *ictrler = p; return nintrc; }