cim_init.c revision f29dbc25
1/* 2 * Copyright (c) 2006 Advanced Micro Devices, Inc. 3 * 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: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 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. 21 * 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. 25 */ 26 27 /* 28 * Cimarron initialization routines. These routines detect a Geode LX and 29 * read all hardware base addresses. 30 */ 31 32CIMARRON_STATIC unsigned long init_video_base = 0x80000900; 33 34/*--------------------------------------------------------------------------- 35 * init_detect_cpu 36 * 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 39 * processor. 40 * bits[24:16] = minor version 41 * bits[15:8] = major version 42 * bits[7:0] = type (1 = Geode GX, 2 = Geode LX) 43 *---------------------------------------------------------------------------*/ 44 45int 46init_detect_cpu(unsigned long *cpu_revision, 47 unsigned long *companion_revision) 48{ 49 unsigned long bus, device, i; 50 unsigned long cpu_bus = 0, cpu_device = 0; 51 unsigned long address, data; 52 unsigned long num_bars, function; 53 int cpu_found, sb_found; 54 Q_WORD msr_value; 55 56 /* SEARCH THROUGH PCI BUS */ 57 /* We search the PCI bus for the Geode LX or Geode GX northbridge. */ 58 /* We then verify that one of its functions is the graphics */ 59 /* controller and that all bars are filled in. */ 60 61 cpu_found = sb_found = 0; 62 for (bus = 0; bus < 256; bus++) { 63 for (device = 0; device < 21; device++) { 64 address = 0x80000000 | (bus << 16) | (device << 11); 65 66 data = init_read_pci(address); 67 68 if (data == PCI_VENDOR_DEVICE_GEODEGX 69 || data == PCI_VENDOR_DEVICE_GEODELX) { 70 cpu_found = 1; 71 cpu_device = device; 72 cpu_bus = bus; 73 if (data == PCI_VENDOR_DEVICE_GEODEGX) 74 *cpu_revision = CIM_CPU_GEODEGX; 75 else 76 *cpu_revision = CIM_CPU_GEODELX; 77 } else if (data == PCI_VENDOR_5535 || data == PCI_VENDOR_5536) { 78 sb_found = 1; 79 if (data == PCI_VENDOR_5535) 80 *companion_revision = CIM_SB_5535; 81 else 82 *companion_revision = CIM_SB_5536; 83 } 84 85 if (cpu_found && sb_found) 86 break; 87 } 88 if (device != 21) 89 break; 90 } 91 92 if (bus == 256) { 93 *cpu_revision = 0; 94 return CIM_STATUS_CPUNOTFOUND; 95 } 96 97 msr_init_table(); 98 99 if (msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_REVID, 100 &msr_value) != CIM_STATUS_OK) { 101 *cpu_revision = 0; 102 return CIM_STATUS_CPUNOTFOUND; 103 } 104 105 *cpu_revision |= ((msr_value.low & 0xF0) << 4) | 106 ((msr_value.low & 0x0F) << 16); 107 108 if (msr_read64(MSR_DEVICE_5535_GLCP, GLCP_REVID, 109 &msr_value) != CIM_STATUS_OK) { 110 *cpu_revision = 0; 111 return CIM_STATUS_CPUNOTFOUND; 112 } 113 114 *companion_revision |= ((msr_value.low & 0xF0) << 4) | 115 ((msr_value.low & 0x0F) << 16); 116 117 /* SEARCH ALL FUNCTIONS FOR INTEGRATED GRAPHICS */ 118 119 num_bars = 0; 120 for (function = 0; function < 7; function++) { 121 address = 0x80000000 | (cpu_bus << 16) | (cpu_device << 11) | 122 (function << 8); 123 data = init_read_pci(address); 124 125 if (data == PCI_VENDOR_DEVICE_GEODEGX_VIDEO) { 126 num_bars = 4; 127 break; 128 } else if (data == PCI_VENDOR_DEVICE_GEODELX_VIDEO) { 129 num_bars = 5; 130 break; 131 } 132 } 133 134 /* VERIFY THAT ALL BARS ARE PRESENT */ 135 136 if (function == 7) 137 return CIM_STATUS_DISPLAYUNAVAILABLE; 138 139 for (i = 0; i < num_bars; i++) { 140 data = init_read_pci(address + 0x10 + (i << 2)); 141 142 if (data == 0 || data == 0xFFFFFFFF) 143 break; 144 } 145 146 if (i != num_bars) 147 return CIM_STATUS_DISPLAYUNAVAILABLE; 148 149 /* SAVE VIDEO BASE ADDRESS FOR FUTURE CALLS */ 150 151 init_video_base = address; 152 153 return CIM_STATUS_OK; 154} 155 156/*--------------------------------------------------------------------------- 157 * init_read_pci 158 * 159 * This routine reads an unsigned long value from a PCI address. 160 *---------------------------------------------------------------------------*/ 161 162unsigned long 163init_read_pci(unsigned long address) 164{ 165 OUTD(0xCF8, address); 166 return IND(0xCFC); 167} 168 169/*--------------------------------------------------------------------------- 170 * init_read_base_addresses 171 * 172 * This routine reads all base addresses for the peripherals from the PCI 173 * BARs. 174 *---------------------------------------------------------------------------*/ 175 176int 177init_read_base_addresses(INIT_BASE_ADDRESSES * base_addresses) 178{ 179 unsigned long value; 180 181 /* READ ALL BASE ADDRESSES */ 182 183 base_addresses->framebuffer_base = init_read_pci(init_video_base + 0x10); 184 base_addresses->gp_register_base = init_read_pci(init_video_base + 0x14); 185 base_addresses->vg_register_base = init_read_pci(init_video_base + 0x18); 186 base_addresses->df_register_base = init_read_pci(init_video_base + 0x1C); 187 base_addresses->vip_register_base = init_read_pci(init_video_base + 0x20); 188 189 /* READ FRAME BUFFER SIZE */ 190 /* The frame buffer size is reported by a VSM in VSA II */ 191 /* Virtual Register Class = 0x02 */ 192 /* VG_MEM_SIZE (1MB units) = 0x00 */ 193 194 OUTW(0xAC1C, 0xFC53); 195 OUTW(0xAC1C, 0x0200); 196 197 value = (unsigned long)(INW(0xAC1E)) & 0xFE; 198 199 base_addresses->framebuffer_size = value << 20; 200 201 return CIM_STATUS_OK; 202} 203 204/*--------------------------------------------------------------------------- 205 * init_read_cpu_frequency 206 * 207 * This routine returns the current CPU core frequency, in MHz. 208 *---------------------------------------------------------------------------*/ 209 210int 211init_read_cpu_frequency(unsigned long *cpu_frequency) 212{ 213 /* CPU SPEED IS REPORTED BY A VSM IN VSA II */ 214 /* Virtual Register Class = 0x12 (Sysinfo) */ 215 /* CPU Speed Register = 0x01 */ 216 217 OUTW(0xAC1C, 0xFC53); 218 OUTW(0xAC1C, 0x1201); 219 220 *cpu_frequency = (unsigned long)(INW(0xAC1E)); 221 222 return CIM_STATUS_OK; 223} 224