cim_init.c revision 04007eba
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, unsigned long *companion_revision) 47{ 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; 53 Q_WORD msr_value; 54 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. */ 59 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); 64 65 data = init_read_pci(address); 66 67 if (data == PCI_VENDOR_DEVICE_GEODEGX 68 || data == PCI_VENDOR_DEVICE_GEODELX) { 69 cpu_found = 1; 70 cpu_device = device; 71 cpu_bus = bus; 72 if (data == PCI_VENDOR_DEVICE_GEODEGX) 73 *cpu_revision = CIM_CPU_GEODEGX; 74 else 75 *cpu_revision = CIM_CPU_GEODELX; 76 } 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 } 129 else if (data == PCI_VENDOR_DEVICE_GEODELX_VIDEO) { 130 num_bars = 5; 131 break; 132 } 133 } 134 135 /* VERIFY THAT ALL BARS ARE PRESENT */ 136 137 if (function == 7) 138 return CIM_STATUS_DISPLAYUNAVAILABLE; 139 140 for (i = 0; i < num_bars; i++) { 141 data = init_read_pci(address + 0x10 + (i << 2)); 142 143 if (data == 0 || data == 0xFFFFFFFF) 144 break; 145 } 146 147 if (i != num_bars) 148 return CIM_STATUS_DISPLAYUNAVAILABLE; 149 150 /* SAVE VIDEO BASE ADDRESS FOR FUTURE CALLS */ 151 152 init_video_base = address; 153 154 return CIM_STATUS_OK; 155} 156 157/*--------------------------------------------------------------------------- 158 * init_read_pci 159 * 160 * This routine reads an unsigned long value from a PCI address. 161 *---------------------------------------------------------------------------*/ 162 163unsigned long 164init_read_pci(unsigned long address) 165{ 166 OUTD(0xCF8, address); 167 return IND(0xCFC); 168} 169 170/*--------------------------------------------------------------------------- 171 * init_read_base_addresses 172 * 173 * This routine reads all base addresses for the peripherals from the PCI 174 * BARs. 175 *---------------------------------------------------------------------------*/ 176 177int 178init_read_base_addresses(INIT_BASE_ADDRESSES * base_addresses) 179{ 180 unsigned long value; 181 182 /* READ ALL BASE ADDRESSES */ 183 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); 189 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 */ 194 195 OUTW(0xAC1C, 0xFC53); 196 OUTW(0xAC1C, 0x0200); 197 198 value = (unsigned long) (INW(0xAC1E)) & 0xFE; 199 200 base_addresses->framebuffer_size = value << 20; 201 202 return CIM_STATUS_OK; 203} 204 205/*--------------------------------------------------------------------------- 206 * init_read_cpu_frequency 207 * 208 * This routine returns the current CPU core frequency, in MHz. 209 *---------------------------------------------------------------------------*/ 210 211int 212init_read_cpu_frequency(unsigned long *cpu_frequency) 213{ 214 /* CPU SPEED IS REPORTED BY A VSM IN VSA II */ 215 /* Virtual Register Class = 0x12 (Sysinfo) */ 216 /* CPU Speed Register = 0x01 */ 217 218 OUTW(0xAC1C, 0xFC53); 219 OUTW(0xAC1C, 0x1201); 220 221 *cpu_frequency = (unsigned long) (INW(0xAC1E)); 222 223 return CIM_STATUS_OK; 224} 225