patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / ia64 / sn / io / platform_init / sgi_io_init.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
7  */
8
9 #include <linux/types.h>
10 #include <linux/config.h>
11 #include <linux/slab.h>
12 #include <linux/smp.h>
13 #include <asm/sn/sgi.h>
14 #include <asm/sn/io.h>
15 #include <asm/sn/sn_cpuid.h>
16 #include <asm/sn/klconfig.h>
17 #include <asm/sn/sn_private.h>
18 #include <asm/sn/pda.h>
19
20 extern void init_all_devices(void);
21 extern void klhwg_add_all_modules(vertex_hdl_t);
22 extern void klhwg_add_all_nodes(vertex_hdl_t);
23
24 extern int init_hcl(void);
25 extern vertex_hdl_t hwgraph_root;
26 extern void io_module_init(void);
27 extern int pci_bus_to_hcl_cvlink(void);
28
29 nasid_t console_nasid = (nasid_t) - 1;
30 char master_baseio_wid;
31
32 nasid_t master_baseio_nasid;
33 nasid_t master_nasid = INVALID_NASID;   /* This is the partition master nasid */
34
35 /*
36  * per_hub_init
37  *
38  *      This code is executed once for each Hub chip.
39  */
40 static void
41 per_hub_init(cnodeid_t cnode)
42 {
43         nasid_t nasid;
44         nodepda_t *npdap;
45         ii_icmr_u_t ii_icmr;
46         ii_ibcr_u_t ii_ibcr;
47         ii_ilcsr_u_t ii_ilcsr;
48
49         nasid = cnodeid_to_nasid(cnode);
50
51         ASSERT(nasid != INVALID_NASID);
52         ASSERT(nasid_to_cnodeid(nasid) == cnode);
53
54         npdap = NODEPDA(cnode);
55
56         /* Disable the request and reply errors. */
57         REMOTE_HUB_S(nasid, IIO_IWEIM, 0xC000);
58
59         /*
60          * Set the total number of CRBs that can be used.
61          */
62         ii_icmr.ii_icmr_regval = 0x0;
63         ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf;
64         if (enable_shub_wars_1_1()) {
65                 // Set bit one of ICMR to prevent II from sending interrupt for II bug.
66                 ii_icmr.ii_icmr_regval |= 0x1;
67         }
68         REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval);
69
70         /*
71          * Set the number of CRBs that both of the BTEs combined
72          * can use minus 1.
73          */
74         ii_ibcr.ii_ibcr_regval = 0x0;
75         ii_ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
76         if (ii_ilcsr.ii_ilcsr_fld_s.i_llp_stat & LNK_STAT_WORKING) {
77                 ii_ibcr.ii_ibcr_fld_s.i_count = 0x8;
78         } else {
79                 /*
80                  * if the LLP is down, there is no attached I/O, so
81                  * give BTE all the CRBs.
82                  */
83                 ii_ibcr.ii_ibcr_fld_s.i_count = 0x14;
84         }
85         REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval);
86
87         /*
88          * Set CRB timeout to be 10ms.
89          */
90         REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff);
91         REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
92
93         /* Initialize error interrupts for this hub. */
94         hub_error_init(cnode);
95 }
96
97 /*
98  * This routine is responsible for the setup of all the IRIX hwgraph style
99  * stuff that's been pulled into linux.  It's called by sn_pci_find_bios which
100  * is called just before the generic Linux PCI layer does its probing (by 
101  * platform_pci_fixup aka sn_pci_fixup).
102  *
103  * It is very IMPORTANT that this call is only made by the Master CPU!
104  *
105  */
106
107 void __init
108 sgi_master_io_infr_init(void)
109 {
110         cnodeid_t cnode;
111
112         if (init_hcl() < 0) {   /* Sets up the hwgraph compatibility layer */
113                 printk("sgi_master_io_infr_init: Cannot init hcl\n");
114                 return;
115         }
116
117         /*
118          * Initialize platform-dependent vertices in the hwgraph:
119          *      module
120          *      node
121          *      cpu
122          *      memory
123          *      slot
124          *      hub
125          *      router
126          *      xbow
127          */
128
129         io_module_init();       /* Use to be called module_init() .. */
130         klhwg_add_all_modules(hwgraph_root);
131         klhwg_add_all_nodes(hwgraph_root);
132
133         for (cnode = 0; cnode < numionodes; cnode++) {
134                 extern void per_hub_init(cnodeid_t);
135                 per_hub_init(cnode);
136         }
137
138         /*
139          *
140          * Our IO Infrastructure drivers are in place .. 
141          * Initialize the whole IO Infrastructure .. xwidget/device probes.
142          *
143          */
144         init_all_devices();
145         pci_bus_to_hcl_cvlink();
146 }
147
148 inline int
149 check_nasid_equiv(nasid_t nasida, nasid_t nasidb)
150 {
151         if ((nasida == nasidb)
152             || (nasida == NODEPDA(nasid_to_cnodeid(nasidb))->xbow_peer))
153                 return 1;
154         else
155                 return 0;
156 }
157
158 int
159 is_master_baseio_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid)
160 {
161         /*
162          * If the widget numbers are different, we're not the master.
163          */
164         if (test_wid != (xwidgetnum_t) master_baseio_wid) {
165                 return 0;
166         }
167
168         /*
169          * If the NASIDs are the same or equivalent, we're the master.
170          */
171         if (check_nasid_equiv(test_nasid, master_baseio_nasid)) {
172                 return 1;
173         } else {
174                 return 0;
175         }
176 }