/* * Check that an address is in teh real small window widget 0 space * or else in the big window we're using to emulate small window 0 * in the kernel. */ int hub_check_is_widget0(void *addr) { nasid_t nasid = NASID_GET(addr); if (((__psunsigned_t)addr >= RAW_NODE_SWIN_BASE(nasid, 0)) && ((__psunsigned_t)addr < RAW_NODE_SWIN_BASE(nasid, 1))) return 1; return 0; }
void __cpuinit xtalk_probe_node(cnodeid_t nid) { volatile u64 hubreg; nasid_t nasid; xwidget_part_num_t partnum; widgetreg_t widget_id; nasid = COMPACT_TO_NASID_NODEID(nid); hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); /* check whether the link is up */ if (!(hubreg & IIO_LLP_CSR_IS_UP)) return; widget_id = *(volatile widgetreg_t *) (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); printk(KERN_INFO "Cpu %d, Nasid 0x%x: partnum 0x%x is ", smp_processor_id(), nasid, partnum); switch (partnum) { case BRIDGE_WIDGET_PART_NUM: bridge_probe(nasid, 0x8, 0xa); break; case XBOW_WIDGET_PART_NUM: case XXBOW_WIDGET_PART_NUM: xbow_probe(nasid); break; default: printk(" unknown widget??\n"); break; } }
/* * Probe to see if this hub's xtalk link is active. If so, * return the Crosstalk Identification of the widget that we talk to. * This is called before any of the Crosstalk infrastructure for * this hub is set up. It's usually called on the node that we're * probing, but not always. * * TBD: Prom code should actually do this work, and pass through * hwid for our use. */ static void early_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid) { hubreg_t llp_csr_reg; nasid_t nasid; hubinfo_t hubinfo; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); /* * If link is up, read the widget's part number. * A direct connect widget must respond to widgetnum=0. */ if (llp_csr_reg & IIO_LLP_CSR_IS_UP) { /* TBD: Put hub into "indirect" mode */ /* * We're able to read from a widget because our hub's * WIDGET_ID was set up earlier. */ widgetreg_t widget_id = *(volatile widgetreg_t *) (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); DBG("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id, (volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) ); hwid->part_num = XWIDGET_PART_NUM(widget_id); hwid->rev_num = XWIDGET_REV_NUM(widget_id); hwid->mfg_num = XWIDGET_MFG_NUM(widget_id); /* TBD: link reset */ } else { hwid->part_num = XWIDGET_PART_NUM_NONE; hwid->rev_num = XWIDGET_REV_NUM_NONE; hwid->mfg_num = XWIDGET_MFG_NUM_NONE; } }
/* * Probe to see if this hub's xtalk link is active. If so, * return the Crosstalk Identification of the widget that we talk to. * This is called before any of the Crosstalk infrastructure for * this hub is set up. It's usually called on the node that we're * probing, but not always. * * TBD: Prom code should actually do this work, and pass through * hwid for our use. */ static void early_probe_for_widget(vertex_hdl_t hubv, xwidget_hwid_t hwid) { nasid_t nasid; hubinfo_t hubinfo; hubreg_t llp_csr_reg; widgetreg_t widget_id; int result = 0; hwid->part_num = XWIDGET_PART_NUM_NONE; hwid->rev_num = XWIDGET_REV_NUM_NONE; hwid->mfg_num = XWIDGET_MFG_NUM_NONE; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); if (!(llp_csr_reg & IIO_LLP_CSR_IS_UP)) return; /* Read the Cross-Talk Widget Id on the other end */ result = snia_badaddr_val((volatile void *) (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID), 4, (void *) &widget_id); if (result == 0) { /* Found something connected */ hwid->part_num = XWIDGET_PART_NUM(widget_id); hwid->rev_num = XWIDGET_REV_NUM(widget_id); hwid->mfg_num = XWIDGET_MFG_NUM(widget_id); /* TBD: link reset */ } else { hwid->part_num = XWIDGET_PART_NUM_NONE; hwid->rev_num = XWIDGET_REV_NUM_NONE; hwid->mfg_num = XWIDGET_MFG_NUM_NONE; } }
static int __cpuinit probe_one_port(nasid_t nasid, int widget, int masterwid) { widgetreg_t widget_id; xwidget_part_num_t partnum; widget_id = *(volatile widgetreg_t *) (RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); printk(KERN_INFO "Cpu %d, Nasid 0x%x, widget 0x%x (partnum 0x%x) is ", smp_processor_id(), nasid, widget, partnum); switch (partnum) { case BRIDGE_WIDGET_PART_NUM: case XBRIDGE_WIDGET_PART_NUM: bridge_probe(nasid, widget, masterwid); break; default: break; } return 0; }
int bridge_probe(nasid_t nasid, int widget_id, int masterwid) { unsigned long offset = NODE_OFFSET(nasid); struct bridge_controller *bc; static int num_bridges = 0; bridge_t *bridge; int slot; pci_set_flags(PCI_PROBE_ONLY); printk("a bridge\n"); /* XXX: kludge alert.. */ if (!num_bridges) ioport_resource.end = ~0UL; bc = &bridges[num_bridges]; bc->pc.pci_ops = &bridge_pci_ops; bc->pc.mem_resource = &bc->mem; bc->pc.io_resource = &bc->io; bc->pc.index = num_bridges; bc->mem.name = "Bridge PCI MEM"; bc->pc.mem_offset = offset; bc->mem.start = 0; bc->mem.end = ~0UL; bc->mem.flags = IORESOURCE_MEM; bc->io.name = "Bridge IO MEM"; bc->pc.io_offset = offset; bc->io.start = 0UL; bc->io.end = ~0UL; bc->io.flags = IORESOURCE_IO; bc->irq_cpu = smp_processor_id(); bc->widget_id = widget_id; bc->nasid = nasid; bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR; /* * point to this bridge */ bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); /* * Clear all pending interrupts. */ bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR; /* * Until otherwise set up, assume all interrupts are from slot 0 */ bridge->b_int_device = 0x0; /* * swap pio's to pci mem and io space (big windows) */ bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | BRIDGE_CTRL_MEM_SWAP; #ifdef CONFIG_PAGE_SIZE_4KB bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE; #else /* 16kB or larger */ bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE; #endif /* * Hmm... IRIX sets additional bits in the address which * are documented as reserved in the bridge docs. */ bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ bridge->b_dir_map = (masterwid << 20); /* DMA */ bridge->b_int_enable = 0; for (slot = 0; slot < 8; slot ++) { bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; bc->pci_int[slot] = -1; } bridge->b_wid_tflush; /* wait until Bridge PIO complete */ bc->base = bridge; register_pci_controller(&bc->pc); num_bridges++; return 0; }
int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid) { unsigned long offset = NODE_OFFSET(nasid); struct bridge_controller *bc; static int num_bridges = 0; bridge_t *bridge; int slot; pci_set_flags(PCI_PROBE_ONLY); printk("a bridge\n"); /* */ if (!num_bridges) ioport_resource.end = ~0UL; bc = &bridges[num_bridges]; bc->pc.pci_ops = &bridge_pci_ops; bc->pc.mem_resource = &bc->mem; bc->pc.io_resource = &bc->io; bc->pc.index = num_bridges; bc->mem.name = "Bridge PCI MEM"; bc->pc.mem_offset = offset; bc->mem.start = 0; bc->mem.end = ~0UL; bc->mem.flags = IORESOURCE_MEM; bc->io.name = "Bridge IO MEM"; bc->pc.io_offset = offset; bc->io.start = 0UL; bc->io.end = ~0UL; bc->io.flags = IORESOURCE_IO; bc->irq_cpu = smp_processor_id(); bc->widget_id = widget_id; bc->nasid = nasid; bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR; /* */ bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); /* */ bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR; /* */ bridge->b_int_device = 0x0; /* */ bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | BRIDGE_CTRL_MEM_SWAP; #ifdef CONFIG_PAGE_SIZE_4KB bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE; #else /* */ bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE; #endif /* */ bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); bridge->b_wid_int_lower = 0x01800090; /* */ bridge->b_dir_map = (masterwid << 20); /* */ bridge->b_int_enable = 0; for (slot = 0; slot < 8; slot ++) { bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; bc->pci_int[slot] = -1; } bridge->b_wid_tflush; /* */ bc->base = bridge; register_pci_controller(&bc->pc); num_bridges++; return 0; }
void __init pcibr_setup(cnodeid_t nid) { int i, start, num; unsigned long masterwid; bridge_t *bridge; volatile u64 hubreg; nasid_t nasid, masternasid; xwidget_part_num_t partnum; widgetreg_t widget_id; static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED; /* * If the master is doing this for headless node, nothing to do. * This is because currently we require at least one of the hubs * (master hub) connected to the xbow to have at least one enabled * cpu to receive intrs. Else we need an array bus_to_intrnasid[] * that bridge_startup() needs to use to target intrs. All dma is * routed thru the widget of the master hub. The master hub wid * is selectable by WIDGET_A below. */ if (nid != get_compact_nodeid()) return; /* * find what's on our local node */ spin_lock(&pcibr_setup_lock); start = num_bridges; /* Remember where we start from */ nasid = COMPACT_TO_NASID_NODEID(nid); hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); if (hubreg & IIO_LLP_CSR_IS_UP) { /* link is up */ widget_id = *(volatile widgetreg_t *) (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); printk("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x", smp_processor_id(), nasid, partnum); if (partnum == BRIDGE_WIDGET_PART_NUM) { /* * found direct connected bridge so must be Origin200 */ printk("...is bridge\n"); num_bridges = 1; bus_to_wid[0] = 0x8; bus_to_nid[0] = 0; masterwid = 0xa; bus_to_baddr[0] = 0xa100000000000000UL; } else if (partnum == XBOW_WIDGET_PART_NUM) { lboard_t *brd; klxbow_t *xbow_p; /* * found xbow, so may have multiple bridges * need to probe xbow */ printk("...is xbow\n"); if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8)) == NULL) printk("argh\n"); else printk("brd = 0x%lx\n", (unsigned long) brd); if ((xbow_p = (klxbow_t *) find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL) printk("argh\n"); else { /* * Okay, here's a xbow. Lets arbitrate and find * out if we should initialize it. Set enabled * hub connected at highest or lowest widget as * master. */ #ifdef WIDGET_A i = HUB_WIDGET_ID_MAX + 1; do { i--; } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || (!XBOW_PORT_IS_ENABLED(xbow_p, i))); #else i = HUB_WIDGET_ID_MIN - 1; do { i++; } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || (!XBOW_PORT_IS_ENABLED(xbow_p, i))); #endif masterwid = i; masternasid = XBOW_PORT_NASID(xbow_p, i); if (nasid == masternasid) for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) { if (!XBOW_PORT_IS_ENABLED(xbow_p, i)) continue; if (XBOW_PORT_TYPE_IO(xbow_p, i)) { widget_id = *(volatile widgetreg_t *) (RAW_NODE_SWIN_BASE(nasid, i) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); if (partnum == BRIDGE_WIDGET_PART_NUM) { printk("widget 0x%x is a bridge\n", i); bus_to_wid[num_bridges] = i; bus_to_nid[num_bridges] = nasid; bus_to_baddr[num_bridges] = ((masterwid << 60) | (1UL << 56)); /* Barrier set */ num_bridges++; } } } } } else if (partnum == XXBOW_WIDGET_PART_NUM) { /* * found xbridge, assume ibrick for now */ printk("...is xbridge\n"); bus_to_wid[0] = 0xb; bus_to_wid[1] = 0xe; bus_to_wid[2] = 0xf; bus_to_nid[0] = 0; bus_to_nid[1] = 0; bus_to_nid[2] = 0; bus_to_baddr[0] = 0xa100000000000000UL; bus_to_baddr[1] = 0xa100000000000000UL; bus_to_baddr[2] = 0xa100000000000000UL; masterwid = 0xa; num_bridges = 3; } } num = num_bridges - start; spin_unlock(&pcibr_setup_lock); /* * set bridge registers */ for (i = start; i < (start + num); i++) { DBG("pcibr_setup: bus= %d bus_to_wid[%2d]= %d bus_to_nid[%2d]= %d\n", i, i, bus_to_wid[i], i, bus_to_nid[i]); bus_to_cpu[i] = smp_processor_id(); /* * point to this bridge */ bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[i],bus_to_wid[i]); /* * Clear all pending interrupts. */ bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR); /* * Until otherwise set up, assume all interrupts are from slot 0 */ bridge->b_int_device = (u32) 0x0; /* * swap pio's to pci mem and io space (big windows) */ bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP; bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP; /* * Hmm... IRIX sets additional bits in the address which * are documented as reserved in the bridge docs. */ bridge->b_int_mode = 0x0; /* Don't clear ints */ bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ bridge->b_dir_map = (masterwid << 20); /* DMA */ bridge->b_int_enable = 0; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ } }