xref: /openbmc/linux/arch/mips/sgi-ip27/ip27-xtalk.c (revision 5b628549)
1 /*
2  * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
3  * Copyright (C) 1999, 2000 Silcon Graphics, Inc.
4  * Copyright (C) 2004 Christoph Hellwig.
5  *	Released under GPL v2.
6  *
7  * Generic XTALK initialization code
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/smp.h>
12 #include <asm/sn/types.h>
13 #include <asm/sn/klconfig.h>
14 #include <asm/sn/hub.h>
15 #include <asm/pci/bridge.h>
16 #include <asm/xtalk/xtalk.h>
17 
18 
19 #define XBOW_WIDGET_PART_NUM	0x0
20 #define XXBOW_WIDGET_PART_NUM	0xd000	/* Xbow in Xbridge */
21 #define BASE_XBOW_PORT		8     /* Lowest external port */
22 
23 extern int bridge_probe(nasid_t nasid, int widget, int masterwid);
24 
25 static int probe_one_port(nasid_t nasid, int widget, int masterwid)
26 {
27 	widgetreg_t		widget_id;
28 	xwidget_part_num_t	partnum;
29 
30 	widget_id = *(volatile widgetreg_t *)
31 		(RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID);
32 	partnum = XWIDGET_PART_NUM(widget_id);
33 
34 	printk(KERN_INFO "Cpu %d, Nasid 0x%x, widget 0x%x (partnum 0x%x) is ",
35 			smp_processor_id(), nasid, widget, partnum);
36 
37 	switch (partnum) {
38 	case BRIDGE_WIDGET_PART_NUM:
39 	case XBRIDGE_WIDGET_PART_NUM:
40 		bridge_probe(nasid, widget, masterwid);
41 		break;
42 	default:
43 		break;
44 	}
45 
46 	return 0;
47 }
48 
49 static int xbow_probe(nasid_t nasid)
50 {
51 	lboard_t *brd;
52 	klxbow_t *xbow_p;
53 	unsigned masterwid, i;
54 
55 	printk("is xbow\n");
56 
57 	/*
58 	 * found xbow, so may have multiple bridges
59 	 * need to probe xbow
60 	 */
61 	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8);
62 	if (!brd)
63 		return -ENODEV;
64 
65 	xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW);
66 	if (!xbow_p)
67 		return -ENODEV;
68 
69 	/*
70 	 * Okay, here's a xbow. Let's arbitrate and find
71 	 * out if we should initialize it. Set enabled
72 	 * hub connected at highest or lowest widget as
73 	 * master.
74 	 */
75 #ifdef WIDGET_A
76 	i = HUB_WIDGET_ID_MAX + 1;
77 	do {
78 		i--;
79 	} while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
80 		 (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
81 #else
82 	i = HUB_WIDGET_ID_MIN - 1;
83 	do {
84 		i++;
85 	} while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
86 		 (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
87 #endif
88 
89 	masterwid = i;
90 	if (nasid != XBOW_PORT_NASID(xbow_p, i))
91 		return 1;
92 
93 	for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) {
94 		if (XBOW_PORT_IS_ENABLED(xbow_p, i) &&
95 		    XBOW_PORT_TYPE_IO(xbow_p, i))
96 			probe_one_port(nasid, i, masterwid);
97 	}
98 
99 	return 0;
100 }
101 
102 static void xtalk_probe_node(cnodeid_t nid)
103 {
104 	volatile u64		hubreg;
105 	nasid_t			nasid;
106 	xwidget_part_num_t	partnum;
107 	widgetreg_t		widget_id;
108 
109 	nasid = COMPACT_TO_NASID_NODEID(nid);
110 	hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
111 
112 	/* check whether the link is up */
113 	if (!(hubreg & IIO_LLP_CSR_IS_UP))
114 		return;
115 
116 	widget_id = *(volatile widgetreg_t *)
117 		       (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
118 	partnum = XWIDGET_PART_NUM(widget_id);
119 
120 	printk(KERN_INFO "Cpu %d, Nasid 0x%x: partnum 0x%x is ",
121 			smp_processor_id(), nasid, partnum);
122 
123 	switch (partnum) {
124 	case BRIDGE_WIDGET_PART_NUM:
125 		bridge_probe(nasid, 0x8, 0xa);
126 		break;
127 	case XBOW_WIDGET_PART_NUM:
128 	case XXBOW_WIDGET_PART_NUM:
129 		xbow_probe(nasid);
130 		break;
131 	default:
132 		printk(" unknown widget??\n");
133 		break;
134 	}
135 }
136 
137 static int __init xtalk_init(void)
138 {
139 	cnodeid_t cnode;
140 
141 	for_each_online_node(cnode)
142 		xtalk_probe_node(cnode);
143 
144 	return 0;
145 }
146 arch_initcall(xtalk_init);
147