ip27-setup.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
- /*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * SGI IP27 specific setup.
- *
- * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 1999, 2000 Silcon Graphics, Inc.
- */
- #include <linux/config.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/spinlock.h>
- #include <linux/sched.h>
- #include <linux/smp.h>
- #include <asm/io.h>
- #include <asm/sn/types.h>
- #include <asm/sn/sn0/addrs.h>
- #include <asm/sn/sn0/hubni.h>
- #include <asm/sn/sn0/hubio.h>
- #include <asm/sn/klconfig.h>
- #include <asm/sn/ioc3.h>
- #include <asm/mipsregs.h>
- #include <asm/sn/arch.h>
- #include <asm/sn/sn_private.h>
- #include <asm/pci/bridge.h>
- #include <asm/paccess.h>
- #include <asm/sn/sn0/ip27.h>
- /* Check against user dumbness. */
- #ifdef CONFIG_VT
- #error CONFIG_VT not allowed for IP27.
- #endif
- #undef DEBUG_SETUP
- #ifdef DEBUG_SETUP
- #define DBG(x...) printk(x)
- #else
- #define DBG(x...)
- #endif
- unsigned long mips_io_port_base = IO_BASE;
- /*
- * get_nasid() returns the physical node id number of the caller.
- */
- nasid_t
- get_nasid(void)
- {
- return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK)
- >> NSRI_NODEID_SHFT);
- }
- /* Extracted from the IOC3 meta driver. FIXME. */
- static inline void ioc3_sio_init(void)
- {
- struct ioc3 *ioc3;
- nasid_t nid;
- long loops;
- nid = get_nasid();
- ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base;
- ioc3->sscr_a = 0; /* PIO mode for uarta. */
- ioc3->sscr_b = 0; /* PIO mode for uartb. */
- ioc3->sio_iec = ~0;
- ioc3->sio_ies = (SIO_IR_SA_INT | SIO_IR_SB_INT);
- loops=1000000; while(loops--);
- ioc3->sregs.uarta.iu_fcr = 0;
- ioc3->sregs.uartb.iu_fcr = 0;
- loops=1000000; while(loops--);
- }
- static inline void ioc3_eth_init(void)
- {
- struct ioc3 *ioc3;
- nasid_t nid;
- nid = get_nasid();
- ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base;
- ioc3->eier = 0;
- }
- /* Try to catch kernel missconfigurations and give user an indication what
- option to select. */
- static void __init verify_mode(void)
- {
- int n_mode;
- n_mode = LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_MORENODES_MASK;
- printk("Machine is in %c mode.n", n_mode ? 'N' : 'M');
- #ifdef CONFIG_SGI_SN0_N_MODE
- if (!n_mode)
- panic("Kernel compiled for M mode.");
- #else
- if (n_mode)
- panic("Kernel compiled for N mode.");
- #endif
- }
- #define XBOW_WIDGET_PART_NUM 0x0
- #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */
- #define BASE_XBOW_PORT 8 /* Lowest external port */
- unsigned int bus_to_cpu[256];
- unsigned long bus_to_baddr[256];
- 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 bridgen");
- 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 xbown");
- if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid),
- KLTYPE_MIDPLANE8)) == NULL)
- printk("arghn");
- else
- printk("brd = 0x%lxn", (unsigned long) brd);
- if ((xbow_p = (klxbow_t *)
- find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL)
- printk("arghn");
- 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 bridgen", 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 xbridgen");
- 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]= %dn",
- 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 */
- }
- }
- extern void ip27_setup_console(void);
- void __init ip27_setup(void)
- {
- nasid_t nid;
- hubreg_t p, e;
- ip27_setup_console();
- num_bridges = 0;
- /*
- * hub_rtc init and cpu clock intr enabled for later calibrate_delay.
- */
- DBG("ip27_setup(): Entered.n");
- nid = get_nasid();
- printk("IP27: Running on node %d.n", nid);
- p = LOCAL_HUB_L(PI_CPU_PRESENT_A) & 1;
- e = LOCAL_HUB_L(PI_CPU_ENABLE_A) & 1;
- printk("Node %d has %s primary CPU%s.n", nid,
- p ? "a" : "no",
- e ? ", CPU is running" : "");
- p = LOCAL_HUB_L(PI_CPU_PRESENT_B) & 1;
- e = LOCAL_HUB_L(PI_CPU_ENABLE_B) & 1;
- printk("Node %d has %s secondary CPU%s.n", nid,
- p ? "a" : "no",
- e ? ", CPU is running" : "");
- verify_mode();
- ioc3_sio_init();
- ioc3_eth_init();
- per_cpu_init();
- }