cim_init.c revision 04007eba
1f29dbc25Smrg/* 2f29dbc25Smrg * Copyright (c) 2006 Advanced Micro Devices, Inc. 3f29dbc25Smrg * 4f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5f29dbc25Smrg * copy of this software and associated documentation files (the "Software"), 6f29dbc25Smrg * to deal in the Software without restriction, including without limitation 7f29dbc25Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f29dbc25Smrg * and/or sell copies of the Software, and to permit persons to whom the 9f29dbc25Smrg * Software is furnished to do so, subject to the following conditions: 10f29dbc25Smrg * 11f29dbc25Smrg * The above copyright notice and this permission notice shall be included in 12f29dbc25Smrg * all copies or substantial portions of the Software. 13f29dbc25Smrg * 14f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20f29dbc25Smrg * DEALINGS IN THE SOFTWARE. 21f29dbc25Smrg * 22f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 23f29dbc25Smrg * contributors may be used to endorse or promote products derived from this 24f29dbc25Smrg * software without specific prior written permission. 25f29dbc25Smrg */ 26f29dbc25Smrg 27f29dbc25Smrg /* 28f29dbc25Smrg * Cimarron initialization routines. These routines detect a Geode LX and 29f29dbc25Smrg * read all hardware base addresses. 30f29dbc25Smrg */ 31f29dbc25Smrg 32f29dbc25SmrgCIMARRON_STATIC unsigned long init_video_base = 0x80000900; 33f29dbc25Smrg 34f29dbc25Smrg/*--------------------------------------------------------------------------- 35f29dbc25Smrg * init_detect_cpu 36f29dbc25Smrg * 37f29dbc25Smrg * This routine verifies that a Geode LX is present and returns the processor 38f29dbc25Smrg * revision ID. For compatibility, this routine can also detect a Redcloud 39f29dbc25Smrg * processor. 40f29dbc25Smrg * bits[24:16] = minor version 41f29dbc25Smrg * bits[15:8] = major version 42f29dbc25Smrg * bits[7:0] = type (1 = Geode GX, 2 = Geode LX) 43f29dbc25Smrg *---------------------------------------------------------------------------*/ 44f29dbc25Smrg 45f29dbc25Smrgint 4604007ebaSmrginit_detect_cpu(unsigned long *cpu_revision, unsigned long *companion_revision) 47f29dbc25Smrg{ 48f29dbc25Smrg unsigned long bus, device, i; 49f29dbc25Smrg unsigned long cpu_bus = 0, cpu_device = 0; 50f29dbc25Smrg unsigned long address, data; 51f29dbc25Smrg unsigned long num_bars, function; 52f29dbc25Smrg int cpu_found, sb_found; 53f29dbc25Smrg Q_WORD msr_value; 54f29dbc25Smrg 55f29dbc25Smrg /* SEARCH THROUGH PCI BUS */ 56f29dbc25Smrg /* We search the PCI bus for the Geode LX or Geode GX northbridge. */ 57f29dbc25Smrg /* We then verify that one of its functions is the graphics */ 58f29dbc25Smrg /* controller and that all bars are filled in. */ 59f29dbc25Smrg 60f29dbc25Smrg cpu_found = sb_found = 0; 61f29dbc25Smrg for (bus = 0; bus < 256; bus++) { 62f29dbc25Smrg for (device = 0; device < 21; device++) { 63f29dbc25Smrg address = 0x80000000 | (bus << 16) | (device << 11); 64f29dbc25Smrg 65f29dbc25Smrg data = init_read_pci(address); 66f29dbc25Smrg 67f29dbc25Smrg if (data == PCI_VENDOR_DEVICE_GEODEGX 68f29dbc25Smrg || data == PCI_VENDOR_DEVICE_GEODELX) { 69f29dbc25Smrg cpu_found = 1; 70f29dbc25Smrg cpu_device = device; 71f29dbc25Smrg cpu_bus = bus; 72f29dbc25Smrg if (data == PCI_VENDOR_DEVICE_GEODEGX) 73f29dbc25Smrg *cpu_revision = CIM_CPU_GEODEGX; 74f29dbc25Smrg else 75f29dbc25Smrg *cpu_revision = CIM_CPU_GEODELX; 7604007ebaSmrg } 7704007ebaSmrg else if (data == PCI_VENDOR_5535 || data == PCI_VENDOR_5536) { 78f29dbc25Smrg sb_found = 1; 79f29dbc25Smrg if (data == PCI_VENDOR_5535) 80f29dbc25Smrg *companion_revision = CIM_SB_5535; 81f29dbc25Smrg else 82f29dbc25Smrg *companion_revision = CIM_SB_5536; 83f29dbc25Smrg } 84f29dbc25Smrg 85f29dbc25Smrg if (cpu_found && sb_found) 86f29dbc25Smrg break; 87f29dbc25Smrg } 88f29dbc25Smrg if (device != 21) 89f29dbc25Smrg break; 90f29dbc25Smrg } 91f29dbc25Smrg 92f29dbc25Smrg if (bus == 256) { 93f29dbc25Smrg *cpu_revision = 0; 94f29dbc25Smrg return CIM_STATUS_CPUNOTFOUND; 95f29dbc25Smrg } 96f29dbc25Smrg 97f29dbc25Smrg msr_init_table(); 98f29dbc25Smrg 99f29dbc25Smrg if (msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_REVID, 10004007ebaSmrg &msr_value) != CIM_STATUS_OK) { 101f29dbc25Smrg *cpu_revision = 0; 102f29dbc25Smrg return CIM_STATUS_CPUNOTFOUND; 103f29dbc25Smrg } 104f29dbc25Smrg 105f29dbc25Smrg *cpu_revision |= ((msr_value.low & 0xF0) << 4) | 106f29dbc25Smrg ((msr_value.low & 0x0F) << 16); 107f29dbc25Smrg 108f29dbc25Smrg if (msr_read64(MSR_DEVICE_5535_GLCP, GLCP_REVID, 10904007ebaSmrg &msr_value) != CIM_STATUS_OK) { 110f29dbc25Smrg *cpu_revision = 0; 111f29dbc25Smrg return CIM_STATUS_CPUNOTFOUND; 112f29dbc25Smrg } 113f29dbc25Smrg 114f29dbc25Smrg *companion_revision |= ((msr_value.low & 0xF0) << 4) | 115f29dbc25Smrg ((msr_value.low & 0x0F) << 16); 116f29dbc25Smrg 117f29dbc25Smrg /* SEARCH ALL FUNCTIONS FOR INTEGRATED GRAPHICS */ 118f29dbc25Smrg 119f29dbc25Smrg num_bars = 0; 120f29dbc25Smrg for (function = 0; function < 7; function++) { 121f29dbc25Smrg address = 0x80000000 | (cpu_bus << 16) | (cpu_device << 11) | 122f29dbc25Smrg (function << 8); 123f29dbc25Smrg data = init_read_pci(address); 124f29dbc25Smrg 125f29dbc25Smrg if (data == PCI_VENDOR_DEVICE_GEODEGX_VIDEO) { 126f29dbc25Smrg num_bars = 4; 127f29dbc25Smrg break; 12804007ebaSmrg } 12904007ebaSmrg else if (data == PCI_VENDOR_DEVICE_GEODELX_VIDEO) { 130f29dbc25Smrg num_bars = 5; 131f29dbc25Smrg break; 132f29dbc25Smrg } 133f29dbc25Smrg } 134f29dbc25Smrg 135f29dbc25Smrg /* VERIFY THAT ALL BARS ARE PRESENT */ 136f29dbc25Smrg 137f29dbc25Smrg if (function == 7) 138f29dbc25Smrg return CIM_STATUS_DISPLAYUNAVAILABLE; 139f29dbc25Smrg 140f29dbc25Smrg for (i = 0; i < num_bars; i++) { 141f29dbc25Smrg data = init_read_pci(address + 0x10 + (i << 2)); 142f29dbc25Smrg 143f29dbc25Smrg if (data == 0 || data == 0xFFFFFFFF) 144f29dbc25Smrg break; 145f29dbc25Smrg } 146f29dbc25Smrg 147f29dbc25Smrg if (i != num_bars) 148f29dbc25Smrg return CIM_STATUS_DISPLAYUNAVAILABLE; 149f29dbc25Smrg 150f29dbc25Smrg /* SAVE VIDEO BASE ADDRESS FOR FUTURE CALLS */ 151f29dbc25Smrg 152f29dbc25Smrg init_video_base = address; 153f29dbc25Smrg 154f29dbc25Smrg return CIM_STATUS_OK; 155f29dbc25Smrg} 156f29dbc25Smrg 157f29dbc25Smrg/*--------------------------------------------------------------------------- 158f29dbc25Smrg * init_read_pci 159f29dbc25Smrg * 160f29dbc25Smrg * This routine reads an unsigned long value from a PCI address. 161f29dbc25Smrg *---------------------------------------------------------------------------*/ 162f29dbc25Smrg 163f29dbc25Smrgunsigned long 164f29dbc25Smrginit_read_pci(unsigned long address) 165f29dbc25Smrg{ 166f29dbc25Smrg OUTD(0xCF8, address); 167f29dbc25Smrg return IND(0xCFC); 168f29dbc25Smrg} 169f29dbc25Smrg 170f29dbc25Smrg/*--------------------------------------------------------------------------- 171f29dbc25Smrg * init_read_base_addresses 172f29dbc25Smrg * 173f29dbc25Smrg * This routine reads all base addresses for the peripherals from the PCI 174f29dbc25Smrg * BARs. 175f29dbc25Smrg *---------------------------------------------------------------------------*/ 176f29dbc25Smrg 177f29dbc25Smrgint 178f29dbc25Smrginit_read_base_addresses(INIT_BASE_ADDRESSES * base_addresses) 179f29dbc25Smrg{ 180f29dbc25Smrg unsigned long value; 181f29dbc25Smrg 182f29dbc25Smrg /* READ ALL BASE ADDRESSES */ 183f29dbc25Smrg 184f29dbc25Smrg base_addresses->framebuffer_base = init_read_pci(init_video_base + 0x10); 185f29dbc25Smrg base_addresses->gp_register_base = init_read_pci(init_video_base + 0x14); 186f29dbc25Smrg base_addresses->vg_register_base = init_read_pci(init_video_base + 0x18); 187f29dbc25Smrg base_addresses->df_register_base = init_read_pci(init_video_base + 0x1C); 188f29dbc25Smrg base_addresses->vip_register_base = init_read_pci(init_video_base + 0x20); 189f29dbc25Smrg 190f29dbc25Smrg /* READ FRAME BUFFER SIZE */ 191f29dbc25Smrg /* The frame buffer size is reported by a VSM in VSA II */ 192f29dbc25Smrg /* Virtual Register Class = 0x02 */ 193f29dbc25Smrg /* VG_MEM_SIZE (1MB units) = 0x00 */ 194f29dbc25Smrg 195f29dbc25Smrg OUTW(0xAC1C, 0xFC53); 196f29dbc25Smrg OUTW(0xAC1C, 0x0200); 197f29dbc25Smrg 19804007ebaSmrg value = (unsigned long) (INW(0xAC1E)) & 0xFE; 199f29dbc25Smrg 200f29dbc25Smrg base_addresses->framebuffer_size = value << 20; 201f29dbc25Smrg 202f29dbc25Smrg return CIM_STATUS_OK; 203f29dbc25Smrg} 204f29dbc25Smrg 205f29dbc25Smrg/*--------------------------------------------------------------------------- 206f29dbc25Smrg * init_read_cpu_frequency 207f29dbc25Smrg * 208f29dbc25Smrg * This routine returns the current CPU core frequency, in MHz. 209f29dbc25Smrg *---------------------------------------------------------------------------*/ 210f29dbc25Smrg 211f29dbc25Smrgint 212f29dbc25Smrginit_read_cpu_frequency(unsigned long *cpu_frequency) 213f29dbc25Smrg{ 214f29dbc25Smrg /* CPU SPEED IS REPORTED BY A VSM IN VSA II */ 215f29dbc25Smrg /* Virtual Register Class = 0x12 (Sysinfo) */ 216f29dbc25Smrg /* CPU Speed Register = 0x01 */ 217f29dbc25Smrg 218f29dbc25Smrg OUTW(0xAC1C, 0xFC53); 219f29dbc25Smrg OUTW(0xAC1C, 0x1201); 220f29dbc25Smrg 22104007ebaSmrg *cpu_frequency = (unsigned long) (INW(0xAC1E)); 222f29dbc25Smrg 223f29dbc25Smrg return CIM_STATUS_OK; 224f29dbc25Smrg} 225