3 * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
10 * Cimarron initialization routines. These routines detect a Geode LX and read
11 * all hardware base addresses.
16 CIMARRON_STATIC
unsigned long init_video_base
= 0x80000900;
18 /*---------------------------------------------------------------------------
21 * This routine verifies that a Geode LX is present and returns the processor revision
22 * ID. For compatibility, this routine can also detect a Redcloud processor.
23 * bits[24:16] = minor version
24 * bits[15:8] = major version
25 * bits[7:0] = type (1 = Geode GX, 2 = Geode LX)
26 *---------------------------------------------------------------------------*/
28 int init_detect_cpu (unsigned long *cpu_revision
, unsigned long *companion_revision
)
30 unsigned long bus
, device
, i
;
31 unsigned long cpu_bus
= 0, cpu_device
= 0;
32 unsigned long address
, data
;
33 unsigned long num_bars
, function
;
34 int cpu_found
, sb_found
;
37 /* SEARCH THROUGH PCI BUS */
38 /* We search the PCI bus for the Geode LX or Geode GX northbridge. */
39 /* We then verify that one of its functions is the graphics */
40 /* controller and that all bars are filled in. */
42 cpu_found
= sb_found
= 0;
43 for (bus
= 0; bus
< 256; bus
++)
45 for (device
= 0; device
< 21; device
++)
47 address
= 0x80000000 | (bus
<< 16) | (device
<< 11);
49 data
= init_read_pci (address
);
51 if (data
== PCI_VENDOR_DEVICE_GEODEGX
|| data
== PCI_VENDOR_DEVICE_GEODELX
)
56 if (data
== PCI_VENDOR_DEVICE_GEODEGX
)
57 *cpu_revision
= CIM_CPU_GEODEGX
;
59 *cpu_revision
= CIM_CPU_GEODELX
;
61 else if (data
== PCI_VENDOR_5535
|| data
== PCI_VENDOR_5536
)
64 if (data
== PCI_VENDOR_5535
)
65 *companion_revision
= CIM_SB_5535
;
67 *companion_revision
= CIM_SB_5536
;
70 if (cpu_found
&& sb_found
)
80 return CIM_STATUS_CPUNOTFOUND
;
85 if (msr_read64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_REVID
, &msr_value
) != CIM_STATUS_OK
)
88 return CIM_STATUS_CPUNOTFOUND
;
91 *cpu_revision
|= ((msr_value
.low
& 0xF0) << 4) |
92 ((msr_value
.low
& 0x0F) << 16);
94 if (msr_read64 (MSR_DEVICE_5535_GLCP
, GLCP_REVID
, &msr_value
) != CIM_STATUS_OK
)
97 return CIM_STATUS_CPUNOTFOUND
;
100 *companion_revision
|= ((msr_value
.low
& 0xF0) << 4) |
101 ((msr_value
.low
& 0x0F) << 16);
103 /* SEARCH ALL FUNCTIONS FOR INTEGRATED GRAPHICS */
106 for (function
= 0; function
< 7; function
++)
108 address
= 0x80000000 | (cpu_bus
<< 16) | (cpu_device
<< 11) | (function
<< 8);
109 data
= init_read_pci (address
);
111 if (data
== PCI_VENDOR_DEVICE_GEODEGX_VIDEO
)
116 else if (data
== PCI_VENDOR_DEVICE_GEODELX_VIDEO
)
123 /* VERIFY THAT ALL BARS ARE PRESENT */
126 return CIM_STATUS_DISPLAYUNAVAILABLE
;
128 for (i
= 0; i
< num_bars
; i
++)
130 data
= init_read_pci (address
+ 0x10 + (i
<< 2));
132 if (data
== 0 || data
== 0xFFFFFFFF)
137 return CIM_STATUS_DISPLAYUNAVAILABLE
;
139 /* SAVE VIDEO BASE ADDRESS FOR FUTURE CALLS */
141 init_video_base
= address
;
143 return CIM_STATUS_OK
;
146 /*---------------------------------------------------------------------------
149 * This routine reads an unsigned long value from a PCI address.
150 *---------------------------------------------------------------------------*/
152 unsigned long init_read_pci (unsigned long address
)
154 OUTD (0xCF8, address
);
158 /*---------------------------------------------------------------------------
159 * init_read_base_addresses
161 * This routine reads all base addresses for the peripherals from the PCI BARs.
162 *---------------------------------------------------------------------------*/
164 int init_read_base_addresses (INIT_BASE_ADDRESSES
*base_addresses
)
168 /* READ ALL BASE ADDRESSES */
170 base_addresses
->framebuffer_base
= init_read_pci (init_video_base
+ 0x10);
171 base_addresses
->gp_register_base
= init_read_pci (init_video_base
+ 0x14);
172 base_addresses
->vg_register_base
= init_read_pci (init_video_base
+ 0x18);
173 base_addresses
->df_register_base
= init_read_pci (init_video_base
+ 0x1C);
174 base_addresses
->vip_register_base
= init_read_pci (init_video_base
+ 0x20);
176 /* READ FRAME BUFFER SIZE */
177 /* The frame buffer size is reported by a VSM in VSA II */
178 /* Virtual Register Class = 0x02 */
179 /* VG_MEM_SIZE (1MB units) = 0x00 */
181 OUTW (0xAC1C, 0xFC53);
182 OUTW (0xAC1C, 0x0200);
184 value
= (unsigned long)(INW (0xAC1E)) & 0xFE;
186 base_addresses
->framebuffer_size
= value
<< 20;
188 return CIM_STATUS_OK
;
191 /*---------------------------------------------------------------------------
192 * init_read_cpu_frequency
194 * This routine returns the current CPU core frequency, in MHz.
195 *---------------------------------------------------------------------------*/
197 int init_read_cpu_frequency (unsigned long *cpu_frequency
)
199 /* CPU SPEED IS REPORTED BY A VSM IN VSA II */
200 /* Virtual Register Class = 0x12 (Sysinfo) */
201 /* CPU Speed Register = 0x01 */
203 OUTW (0xAC1C, 0xFC53);
204 OUTW (0xAC1C, 0x1201);
206 *cpu_frequency
= (unsigned long)(INW (0xAC1E));
208 return CIM_STATUS_OK
;