added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / lib / cimarron / cim / cim_msr.c
blob459dd39ad46277b8942ad793f108fbb16f20e376
1 /*
2 * <LIC_AMD_STD>
3 * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
4 * </LIC_AMD_STD>
6 * <CTL_AMD_STD>
7 * </CTL_AMD_STD>
9 * <DOC_AMD_STD>
10 * Cimarron MSR access routines. These routines allow the user to query the
11 * state of the GeodeLink Bus and read and write model-specfic registers.
12 * </DOC_AMD_STD>
16 /*--------------------------------------------------------------*/
17 /* MSR GLOBALS */
18 /* These variables hold a local copy of the GeodeLink mapping */
19 /* as well as a lookup table for easy device addressing. */
20 /*--------------------------------------------------------------*/
22 GEODELINK_NODE gliu_nodes[24];
23 GEODELINK_NODE msr_dev_lookup[MSR_DEVICE_EMPTY];
25 #define GET_DEVICE_ID(macrohigh, macrolow) ((macrolow >> 12) & 0xFF)
27 /*---------------------------------------------------------------------------
28 * msr_init_table
30 * This routine intializes the internal MSR table in Cimarron. This table is
31 * used for any MSR device accesses.
32 *---------------------------------------------------------------------------*/
34 int msr_init_table (void)
36 Q_WORD msr_value;
37 unsigned int i, j;
38 int return_value = CIM_STATUS_OK;
40 /* CHECK FOR VALID GEODELINK CONFIGURATION */
41 /* The CPU and the three GLIUs are assumed to be at known static addresses, so */
42 /* we will check the device IDs at these addresses as proof of a valid */
43 /* GeodeLink configuration */
45 MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_VAIL, &msr_value);
46 if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_VAIL)
47 return_value = CIM_STATUS_ERROR;
49 MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU0, &msr_value);
50 if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU)
51 return_value = CIM_STATUS_ERROR;
53 MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU1, &msr_value);
54 if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU)
55 return_value = CIM_STATUS_ERROR;
57 MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU2, &msr_value);
58 if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU)
59 return_value = CIM_STATUS_ERROR;
61 if (return_value == CIM_STATUS_OK)
63 /* BUILD LOCAL COPY OF THE GEODELINK BUS */
65 msr_create_geodelink_table (gliu_nodes);
67 /* CLEAR TABLE STATUS */
69 for (i = 0; i < MSR_DEVICE_EMPTY; i++)
70 msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND;
72 /* CREATE EASY LOOKUP TABLE FOR FUTURE HARDWARE ACCESS */
73 /* Note that MSR_DEVICE_EMPTY is the index after the last */
74 /* available device. Also note that we fill in known */
75 /* devices before filling in the rest of the table. */
77 msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].address_from_cpu = MSR_ADDRESS_GLIU0;
78 msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].device_id = MSR_DEVICE_PRESENT;
79 msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].address_from_cpu = MSR_ADDRESS_GLIU1;
80 msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].device_id = MSR_DEVICE_PRESENT;
81 msr_dev_lookup[MSR_DEVICE_5535_GLIU].address_from_cpu = MSR_ADDRESS_GLIU2;
82 msr_dev_lookup[MSR_DEVICE_5535_GLIU].device_id = MSR_DEVICE_PRESENT;
83 msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].address_from_cpu = MSR_ADDRESS_VAIL;
84 msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].device_id = MSR_DEVICE_PRESENT;
86 for (i = 0; i < MSR_DEVICE_EMPTY; i++)
88 if (msr_dev_lookup[i].device_id == MSR_DEVICE_NOTFOUND)
90 for (j = 0; j < 24; j++)
92 if (gliu_nodes[j].device_id == i)
93 break;
96 if (j == 24)
97 msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND;
98 else
100 msr_dev_lookup[i].device_id = MSR_DEVICE_PRESENT;
101 msr_dev_lookup[i].address_from_cpu = gliu_nodes[j].address_from_cpu;
106 else
108 /* ERROR OUT THE GEODELINK TABLES */
110 for (i = 0; i < 24; i++)
112 gliu_nodes[i].address_from_cpu = 0xFFFFFFFF;
113 gliu_nodes[i].device_id = MSR_DEVICE_EMPTY;
116 for (i = 0; i < MSR_DEVICE_EMPTY; i++)
118 msr_dev_lookup[i].address_from_cpu = 0xFFFFFFFF;
119 msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND;
122 return return_value;
125 /*---------------------------------------------------------------------------
126 * msr_create_geodelink_table
128 * This routine dumps the contents of the GeodeLink bus into an array of
129 * 24 GEODELINK_NODE structures. Indexes 0-7 represent ports 0-7 of GLIU0,
130 * indexes 8-15 represent ports 0-7 of GLIU1 and indexes 16-23 represent
131 * ports 0-7 of GLIU2 (5535).
132 *---------------------------------------------------------------------------*/
134 int msr_create_geodelink_table (GEODELINK_NODE *gliu_nodes)
136 unsigned long mbiu_port_count, reflective;
137 unsigned long port, index;
138 unsigned long gliu_count = 0;
139 int glcp_count = 0;
140 int usb_count = 0;
141 int mpci_count = 0;
142 Q_WORD msr_value;
144 /* ALL THREE GLIUS ARE IN ONE ARRAY */
145 /* Entries 0-7 contain the port information for GLIU0, entries */
146 /* 8-15 contain GLIU1 and 15-23 contain GLIU2. We perform the */
147 /* enumeration in two passes. The first simply fills in the */
148 /* addresses and class codes at each node. The second pass */
149 /* translates the class codes into indexes into Cimarron's device */
150 /* lookup table. */
152 /* COUNT GLIU0 PORTS */
154 MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU0, &msr_value);
155 mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7;
157 /* FIND REFLECTIVE PORT */
158 /* Query the GLIU for the port through which we are communicating. */
159 /* We will avoid accesses to this port to avoid a self-reference. */
161 MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU0, &msr_value);
162 reflective = msr_value.low & WHOAMI_MASK;
164 /* SPECIAL CASE FOR PORT 0 */
165 /* GLIU0 port 0 is a special case, as it points back to GLIU0. GLIU0 */
166 /* responds at address 0x10000xxx, which does not equal 0 << 29. */
168 gliu_nodes[0].address_from_cpu = MSR_ADDRESS_GLIU0;
169 gliu_nodes[0].device_id = MSR_CLASS_CODE_GLIU;
171 /* ENUMERATE ALL PORTS */
173 for (port = 1; port < 8; port++)
175 /* FILL IN ADDRESS */
177 gliu_nodes[port].address_from_cpu = port << 29;
179 if (port == reflective)
180 gliu_nodes[port].device_id = MSR_CLASS_CODE_REFLECTIVE;
181 else if (port > mbiu_port_count)
182 gliu_nodes[port].device_id = MSR_CLASS_CODE_UNPOPULATED;
183 else
185 MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[port].address_from_cpu, &msr_value);
186 gliu_nodes[port].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low);
190 /* COUNT GLIU1 PORTS */
192 MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU1, &msr_value);
193 mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7;
195 /* FIND REFLECTIVE PORT */
197 MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU1, &msr_value);
198 reflective = msr_value.low & WHOAMI_MASK;
200 /* ENUMERATE ALL PORTS */
202 for (port = 0; port < 8; port++)
204 index = port + 8;
206 /* FILL IN ADDRESS */
208 gliu_nodes[index].address_from_cpu = (0x02l << 29) + (port << 26);
210 if (port == reflective)
211 gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE;
212 else if (port > mbiu_port_count)
213 gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED;
214 else
216 MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, &msr_value);
217 gliu_nodes[index].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low);
221 /* COUNT GLIU2 PORTS */
223 MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU2, &msr_value);
224 mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7;
226 /* FIND REFLECTIVE PORT */
228 MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU2, &msr_value);
229 reflective = msr_value.low & WHOAMI_MASK;
231 /* FILL IN PORT 0 AND 1 */
232 /* Port 0 on 5535 is MBIU2. Port 1 is MPCI, but it is referenced at */
233 /* a special address. */
235 gliu_nodes[16].address_from_cpu = MSR_ADDRESS_GLIU2;
236 gliu_nodes[16].device_id = MSR_CLASS_CODE_GLIU;
238 gliu_nodes[17].address_from_cpu = MSR_ADDRESS_5535MPCI;
239 gliu_nodes[17].device_id = MSR_CLASS_CODE_MPCI;
241 /* ENUMERATE ALL PORTS */
243 for (port = 2; port < 8; port++)
245 index = port + 16;
247 /* FILL IN ADDRESS */
249 gliu_nodes[index].address_from_cpu =
250 (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20);
252 if (port == reflective)
253 gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE;
254 else if (port > mbiu_port_count)
255 gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED;
256 else
258 MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, &msr_value);
259 gliu_nodes[index].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low);
263 /* SECOND PASS - TRANSLATION */
264 /* Now that the class codes for each device are stored in the */
265 /* array, we walk through the array and translate the class */
266 /* codes to table indexes. For class codes that have multiple */
267 /* instances, the table indexes are sequential. */
269 for (port = 0; port < 24; port++)
271 /* SPECIAL CASE FOR GLIU UNITS */
272 /* A GLIU can be both on another port and on its own port. These */
273 /* end up as the same address, but are shown as duplicate nodes in */
274 /* the GeodeLink table. */
276 if ((port & 7) == 0)
277 gliu_count = port >> 3;
279 switch (gliu_nodes[port].device_id)
281 /* UNPOPULATED OR REFLECTIVE NODES */
283 case MSR_CLASS_CODE_UNPOPULATED: index = MSR_DEVICE_EMPTY; break;
284 case MSR_CLASS_CODE_REFLECTIVE: index = MSR_DEVICE_REFLECTIVE; break;
286 /* KNOWN CLASS CODES */
288 case MSR_CLASS_CODE_GLIU: index = MSR_DEVICE_GEODELX_GLIU0 + gliu_count++; break;
289 case MSR_CLASS_CODE_GLCP: index = MSR_DEVICE_GEODELX_GLCP + glcp_count++; break;
290 case MSR_CLASS_CODE_MPCI: index = MSR_DEVICE_GEODELX_MPCI + mpci_count++; break;
291 case MSR_CLASS_CODE_USB: index = MSR_DEVICE_5535_USB2 + usb_count++; break;
292 case MSR_CLASS_CODE_USB2: index = MSR_DEVICE_5536_USB_2_0; break;
293 case MSR_CLASS_CODE_ATAC: index = MSR_DEVICE_5535_ATAC; break;
294 case MSR_CLASS_CODE_MDD: index = MSR_DEVICE_5535_MDD; break;
295 case MSR_CLASS_CODE_ACC: index = MSR_DEVICE_5535_ACC; break;
296 case MSR_CLASS_CODE_MC: index = MSR_DEVICE_GEODELX_MC; break;
297 case MSR_CLASS_CODE_GP: index = MSR_DEVICE_GEODELX_GP; break;
298 case MSR_CLASS_CODE_VG: index = MSR_DEVICE_GEODELX_VG; break;
299 case MSR_CLASS_CODE_DF: index = MSR_DEVICE_GEODELX_DF; break;
300 case MSR_CLASS_CODE_FG: index = MSR_DEVICE_GEODELX_FG; break;
301 case MSR_CLASS_CODE_VIP: index = MSR_DEVICE_GEODELX_VIP; break;
302 case MSR_CLASS_CODE_AES: index = MSR_DEVICE_GEODELX_AES; break;
303 case MSR_CLASS_CODE_VAIL: index = MSR_DEVICE_GEODELX_VAIL; break;
304 default: index = MSR_DEVICE_EMPTY; break;
307 gliu_nodes[port].device_id = index;
310 return CIM_STATUS_OK;
313 /*---------------------------------------------------------------------------
314 * msr_create_device_list
316 * This routine dumps a list of all known GeodeLX/5535 devices as well as their
317 * respective status and address.
318 *---------------------------------------------------------------------------*/
320 int msr_create_device_list (GEODELINK_NODE *gliu_nodes, int max_devices)
322 int i, count;
324 if (max_devices < MSR_DEVICE_EMPTY) count = max_devices;
325 else count = MSR_DEVICE_EMPTY;
327 for (i = 0; i < count; i++)
329 gliu_nodes[i].address_from_cpu = msr_dev_lookup[i].address_from_cpu;
330 gliu_nodes[i].device_id = msr_dev_lookup[i].device_id;
333 return CIM_STATUS_OK;
336 /*--------------------------------------------------------------------
337 * msr_read64
339 * Performs a 64-bit read from 'msr_register' in device 'device'. 'device' is
340 * an index into Cimarron's table of known GeodeLink devices.
341 *-------------------------------------------------------------------*/
343 int msr_read64 (unsigned long device, unsigned long msr_register,
344 Q_WORD *msr_value)
346 if (device < MSR_DEVICE_EMPTY)
348 if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT)
350 MSR_READ (msr_register, msr_dev_lookup[device].address_from_cpu, msr_value);
351 return CIM_STATUS_OK;
355 msr_value->low = msr_value->high = 0;
356 return CIM_STATUS_DEVNOTFOUND;
359 /*--------------------------------------------------------------------
360 * msr_write64
362 * Performs a 64-bit write to 'msr_register' in device 'device'. 'device' is
363 * an index into Cimarron's table of known GeodeLink devices.
364 *-------------------------------------------------------------------*/
366 int msr_write64 (unsigned long device, unsigned long msr_register,
367 Q_WORD *msr_value)
369 if (device < MSR_DEVICE_EMPTY)
371 if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT)
373 MSR_WRITE (msr_register, msr_dev_lookup[device].address_from_cpu, msr_value);
374 return CIM_STATUS_OK;
377 return CIM_STATUS_DEVNOTFOUND;