2
* Copyright (c) 2006 Advanced Micro Devices, Inc.
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
* DEALINGS IN THE SOFTWARE.
22
* Neither the name of the Advanced Micro Devices, Inc. nor the names of its
23
* contributors may be used to endorse or promote products derived from this
24
* software without specific prior written permission.
28
* Cimarron initialization routines. These routines detect a Geode LX and
29
* read all hardware base addresses.
32
CIMARRON_STATIC unsigned long init_video_base = 0x80000900;
34
/*---------------------------------------------------------------------------
37
* This routine verifies that a Geode LX is present and returns the processor
38
* revision ID. For compatibility, this routine can also detect a Redcloud
40
* bits[24:16] = minor version
41
* bits[15:8] = major version
42
* bits[7:0] = type (1 = Geode GX, 2 = Geode LX)
43
*---------------------------------------------------------------------------*/
46
init_detect_cpu(unsigned long *cpu_revision, unsigned long *companion_revision)
48
unsigned long bus, device, i;
49
unsigned long cpu_bus = 0, cpu_device = 0;
50
unsigned long address, data;
51
unsigned long num_bars, function;
52
int cpu_found, sb_found;
55
/* SEARCH THROUGH PCI BUS */
56
/* We search the PCI bus for the Geode LX or Geode GX northbridge. */
57
/* We then verify that one of its functions is the graphics */
58
/* controller and that all bars are filled in. */
60
cpu_found = sb_found = 0;
61
for (bus = 0; bus < 256; bus++) {
62
for (device = 0; device < 21; device++) {
63
address = 0x80000000 | (bus << 16) | (device << 11);
65
data = init_read_pci(address);
67
if (data == PCI_VENDOR_DEVICE_GEODEGX
68
|| data == PCI_VENDOR_DEVICE_GEODELX) {
72
if (data == PCI_VENDOR_DEVICE_GEODEGX)
73
*cpu_revision = CIM_CPU_GEODEGX;
75
*cpu_revision = CIM_CPU_GEODELX;
77
else if (data == PCI_VENDOR_5535 || data == PCI_VENDOR_5536) {
79
if (data == PCI_VENDOR_5535)
80
*companion_revision = CIM_SB_5535;
82
*companion_revision = CIM_SB_5536;
85
if (cpu_found && sb_found)
94
return CIM_STATUS_CPUNOTFOUND;
99
if (msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_REVID,
100
&msr_value) != CIM_STATUS_OK) {
102
return CIM_STATUS_CPUNOTFOUND;
105
*cpu_revision |= ((msr_value.low & 0xF0) << 4) |
106
((msr_value.low & 0x0F) << 16);
108
if (msr_read64(MSR_DEVICE_5535_GLCP, GLCP_REVID,
109
&msr_value) != CIM_STATUS_OK) {
111
return CIM_STATUS_CPUNOTFOUND;
114
*companion_revision |= ((msr_value.low & 0xF0) << 4) |
115
((msr_value.low & 0x0F) << 16);
117
/* SEARCH ALL FUNCTIONS FOR INTEGRATED GRAPHICS */
120
for (function = 0; function < 7; function++) {
121
address = 0x80000000 | (cpu_bus << 16) | (cpu_device << 11) |
123
data = init_read_pci(address);
125
if (data == PCI_VENDOR_DEVICE_GEODEGX_VIDEO) {
129
else if (data == PCI_VENDOR_DEVICE_GEODELX_VIDEO) {
135
/* VERIFY THAT ALL BARS ARE PRESENT */
138
return CIM_STATUS_DISPLAYUNAVAILABLE;
140
for (i = 0; i < num_bars; i++) {
141
data = init_read_pci(address + 0x10 + (i << 2));
143
if (data == 0 || data == 0xFFFFFFFF)
148
return CIM_STATUS_DISPLAYUNAVAILABLE;
150
/* SAVE VIDEO BASE ADDRESS FOR FUTURE CALLS */
152
init_video_base = address;
154
return CIM_STATUS_OK;
157
/*---------------------------------------------------------------------------
160
* This routine reads an unsigned long value from a PCI address.
161
*---------------------------------------------------------------------------*/
164
init_read_pci(unsigned long address)
166
OUTD(0xCF8, address);
170
/*---------------------------------------------------------------------------
171
* init_read_base_addresses
173
* This routine reads all base addresses for the peripherals from the PCI
175
*---------------------------------------------------------------------------*/
178
init_read_base_addresses(INIT_BASE_ADDRESSES * base_addresses)
182
/* READ ALL BASE ADDRESSES */
184
base_addresses->framebuffer_base = init_read_pci(init_video_base + 0x10);
185
base_addresses->gp_register_base = init_read_pci(init_video_base + 0x14);
186
base_addresses->vg_register_base = init_read_pci(init_video_base + 0x18);
187
base_addresses->df_register_base = init_read_pci(init_video_base + 0x1C);
188
base_addresses->vip_register_base = init_read_pci(init_video_base + 0x20);
190
/* READ FRAME BUFFER SIZE */
191
/* The frame buffer size is reported by a VSM in VSA II */
192
/* Virtual Register Class = 0x02 */
193
/* VG_MEM_SIZE (1MB units) = 0x00 */
195
OUTW(0xAC1C, 0xFC53);
196
OUTW(0xAC1C, 0x0200);
198
value = (unsigned long) (INW(0xAC1E)) & 0xFE;
200
base_addresses->framebuffer_size = value << 20;
202
return CIM_STATUS_OK;
205
/*---------------------------------------------------------------------------
206
* init_read_cpu_frequency
208
* This routine returns the current CPU core frequency, in MHz.
209
*---------------------------------------------------------------------------*/
212
init_read_cpu_frequency(unsigned long *cpu_frequency)
214
/* CPU SPEED IS REPORTED BY A VSM IN VSA II */
215
/* Virtual Register Class = 0x12 (Sysinfo) */
216
/* CPU Speed Register = 0x01 */
218
OUTW(0xAC1C, 0xFC53);
219
OUTW(0xAC1C, 0x1201);
221
*cpu_frequency = (unsigned long) (INW(0xAC1E));
223
return CIM_STATUS_OK;