summaryrefslogtreecommitdiff
path: root/src/cpu/amd/geode_gx2
diff options
context:
space:
mode:
authorKyösti Mälkki <kyosti.malkki@gmail.com>2012-02-09 16:07:41 +0200
committerStefan Reinauer <stefan.reinauer@coreboot.org>2012-02-13 21:56:38 +0100
commit7916f4cef62bf032af86368a9df45db833d09b79 (patch)
treeab2a85208db187624f8615c135acf605777fc7d8 /src/cpu/amd/geode_gx2
parent50759ed4ff438db6f3b093984fbb79d6445ebcb3 (diff)
AMD Geode cpus: apply un-written naming rules
Kconfig directives to select chip drivers for compile literally match the chip directory names capitalized and underscored. Rename directories and Kconfig as follows: model_lx -> geode_lx model_gx1 -> geode_gx1 model_gx2 -> geode_gx2 Change-Id: Ib8bf1e758b88f9efed1cf8b11c76b796388e7147 Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: http://review.coreboot.org/613 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/cpu/amd/geode_gx2')
-rw-r--r--src/cpu/amd/geode_gx2/Kconfig58
-rw-r--r--src/cpu/amd/geode_gx2/Makefile.inc9
-rw-r--r--src/cpu/amd/geode_gx2/cache_as_ram.inc208
-rw-r--r--src/cpu/amd/geode_gx2/cpubug.c349
-rw-r--r--src/cpu/amd/geode_gx2/cpureginit.c129
-rw-r--r--src/cpu/amd/geode_gx2/geode_gx2_init.c46
-rw-r--r--src/cpu/amd/geode_gx2/syspreinit.c20
7 files changed, 819 insertions, 0 deletions
diff --git a/src/cpu/amd/geode_gx2/Kconfig b/src/cpu/amd/geode_gx2/Kconfig
new file mode 100644
index 0000000000..0e25542582
--- /dev/null
+++ b/src/cpu/amd/geode_gx2/Kconfig
@@ -0,0 +1,58 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2010 coresystems GmbH
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; version 2 of the License.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+config CPU_AMD_GEODE_GX2
+ bool
+
+if CPU_AMD_GEODE_GX2
+
+config CPU_SPECIFIC_OPTIONS
+ def_bool y
+ select CACHE_AS_RAM
+
+config DCACHE_RAM_BASE
+ hex
+ default 0xc8000
+
+config DCACHE_RAM_SIZE
+ hex
+ default 0x04000
+
+config GEODE_VSA
+ bool
+ default y
+ select PCI_OPTION_ROM_RUN_REALMODE
+
+config GEODE_VSA_FILE
+ bool "Add a VSA image"
+ help
+ Select this option if you have an AMD Geode GX2 vsa that you would
+ like to add to your ROM.
+
+ You will be able to specify the location and file name of the
+ image later.
+
+config VSA_FILENAME
+ string "AMD Geode GX2 VSA path and filename"
+ depends on GEODE_VSA_FILE
+ default "gpl_vsa_gx_102.bin"
+ help
+ The path and filename of the file to use as VSA.
+
+endif # CPU_AMD_GEODE_GX2
diff --git a/src/cpu/amd/geode_gx2/Makefile.inc b/src/cpu/amd/geode_gx2/Makefile.inc
new file mode 100644
index 0000000000..b70537accf
--- /dev/null
+++ b/src/cpu/amd/geode_gx2/Makefile.inc
@@ -0,0 +1,9 @@
+subdirs-y += ../../x86/tsc
+subdirs-y += ../../x86/lapic
+subdirs-y += ../../x86/cache
+subdirs-y += ../../x86/smm
+
+driver-y += geode_gx2_init.c
+ramstage-y += cpubug.c
+
+cpu_incs += $(src)/cpu/amd/geode_gx2/cache_as_ram.inc
diff --git a/src/cpu/amd/geode_gx2/cache_as_ram.inc b/src/cpu/amd/geode_gx2/cache_as_ram.inc
new file mode 100644
index 0000000000..0af2fdf488
--- /dev/null
+++ b/src/cpu/amd/geode_gx2/cache_as_ram.inc
@@ -0,0 +1,208 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Copyright (C) 2010 Nils Jacobs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define GX2_STACK_BASE CONFIG_DCACHE_RAM_BASE /* this is where the DCache will be mapped and be used as stack, It would be cool if it was the same base as coreboot normal stack */
+#define GX2_STACK_END GX2_STACK_BASE+(CONFIG_DCACHE_RAM_SIZE-1)
+
+#define GX2_NUM_CACHELINES 0x080 /* there are 128lines per way */
+#define GX2_CACHELINE_SIZE 0x020 /* there are 32bytes per line */
+#define GX2_CACHEWAY_SIZE (GX2_NUM_CACHELINES * GX2_CACHELINE_SIZE)
+#define CR0_CD 0x40000000 /* bit 30 = Cache Disable */
+#define CR0_NW 0x20000000 /* bit 29 = Not Write Through */
+#include <cpu/amd/gx2def.h>
+#include <cpu/x86/post_code.h>
+/***************************************************************************
+/**
+/** DCacheSetup
+/**
+/** Setup data cache for use as RAM for a stack.
+/**
+/** Max. size data cache =0x4000 (16KB)
+/**
+/***************************************************************************/
+DCacheSetup:
+ /* Save the BIST result */
+ movl %eax, %ebx
+
+ invd
+ /* set cache properties */
+ movl $CPU_RCONF_DEFAULT, %ecx
+ rdmsr
+ movl $0x010010000, %eax /*1MB system memory in write back 1|00100|00 */
+ wrmsr
+
+ /* in GX2 DCDIS is set after POR which disables the cache..., clear this bit */
+ movl $CPU_DM_CONFIG0, %ecx
+ rdmsr
+ andl $(~(DM_CONFIG0_LOWER_DCDIS_SET)), %eax /* TODO: make consistent with i$ init, either whole reg = 0, or just this bit... */
+ wrmsr
+
+ /* Get cleaned up. */
+ xorl %edi, %edi
+ xorl %esi, %esi
+ xorl %ebp, %ebp
+
+ /* DCache Ways0 through Ways3 will be tagged for GX2_STACK_BASE + CONFIG_DCACHE_RAM_SIZE for holding stack */
+ /* remember, there is NO stack yet... */
+
+ /* Tell cache we want to fill WAY 0 starting at the top */
+ xorl %edx, %edx
+ xorl %eax, %eax
+ movl $CPU_DC_INDEX, %ecx
+ wrmsr
+
+ /* startaddress for tag of Way0: ebp will hold the incrementing address. dont destroy! */
+ movl $GX2_STACK_BASE, %ebp /* init to start address */
+ orl $1, %ebp /* set valid bit and tag for this Way (B[31:12] : Cache tag value for line/way curr. selected by CPU_DC_INDEX */
+
+ /* start tag Ways 0 with 128 lines with 32bytes each: edi will hold the line counter. dont destroy! */
+ movl $GX2_NUM_CACHELINES, %edi
+DCacheSetupFillWay:
+
+ /* fill with dummy data: zero it so we can tell it from PCI memory space (returns FFs). */
+ /* We will now store a line (32 bytes = 4 x 8bytes = 4 quadWords) */
+ movw $0x04, %si
+ xorl %edx, %edx
+ xorl %eax, %eax
+ movl $CPU_DC_DATA, %ecx
+DCacheSetup_quadWordLoop:
+ wrmsr
+ decw %si
+ jnz DCacheSetup_quadWordLoop
+
+ /* Set the tag for this line,need to do this for every new cache line to validate it! */
+ /* accessing CPU_DC_TAG_I makes the LINE field in CPU_DC_INDEX increment and thus cont. in the next cache line... */
+ xorl %edx, %edx
+ movl %ebp, %eax
+ movl $CPU_DC_TAG, %ecx
+ wrmsr
+
+ /* switch to next line */
+ /* lines are in Bits8:2 */
+ /* when index is crossing 0x7F -> 0x80 writing a RSVD bit as 0x80 is not a valid CL anymore! */
+ movl $CPU_DC_INDEX, %ecx
+ rdmsr
+ addl $0x04, %eax /* inc DC_LINE. TODO: prob. would be more elegant to calc. this from counter var edi... */
+ wrmsr
+
+ decl %edi
+ jnz DCacheSetupFillWay
+
+ /* 1 Way has been filled, forward start address for next Way, terminate if we have reached end of desired address range */
+ addl $GX2_CACHEWAY_SIZE, %ebp
+ cmpl $GX2_STACK_END, %ebp
+ jge leave_DCacheSetup
+ movl $GX2_NUM_CACHELINES, %edi
+
+ /* switch to next way */
+ movl $CPU_DC_INDEX, %ecx
+ rdmsr
+ addl $0x01, %eax
+ andl $0xFFFFFE03, %eax /* lets be sure: reset line index Bits8:2 */
+ wrmsr
+
+ jmp DCacheSetupFillWay
+
+leave_DCacheSetup:
+ xorl %edi, %edi
+ xorl %esi, %esi
+ xorl %ebp, %ebp
+
+ /* Disable the cache, but ... DO NOT INVALIDATE the tags. */
+ /* Memory reads and writes will all hit in the cache. */
+ /* Cache updates and memory write-backs will not occur ! */
+ movl %cr0, %eax
+ orl $(CR0_CD + CR0_NW), %eax /* set the CD and NW bits */
+ movl %eax, %cr0
+
+ /* Now point sp to the cached stack. */
+ /* The stack will be fully functional at this location. No system memory is required at all ! */
+ /* set up the stack pointer */
+ movl $GX2_STACK_END, %eax
+ movl %eax, %esp
+
+ /* test the stack*/
+ movl $0x0F0F05A5A, %edx
+ pushl %edx
+ popl %ecx
+ cmpl %ecx, %edx
+ je DCacheSetupGood
+
+ post_code(0xc5)
+DCacheSetupBad:
+ hlt /* issues */
+ jmp DCacheSetupBad
+DCacheSetupGood:
+ /* Go do early init and memory setup */
+
+ /* Restore the BIST result */
+ movl %ebx, %eax
+ movl %esp, %ebp
+ pushl %eax
+
+ post_code(0x23)
+
+ /* Call romstage.c main function */
+ call main
+done_cache_as_ram_main:
+
+ /* We now run over the stack-in-cache, copying it back to itself to invalidate the cache */
+
+ push %edi
+ mov $(CONFIG_DCACHE_RAM_SIZE/4),%ecx
+ push %esi
+ mov $(CONFIG_DCACHE_RAM_BASE),%edi
+ mov %edi,%esi
+ cld
+ rep movsl %ds:(%esi),%es:(%edi)
+ pop %esi
+ pop %edi
+
+ /* Clear the cache out to ram */
+ wbinvd
+ /* re-enable the cache */
+ movl %cr0, %eax
+ xorl $(CR0_CD + CR0_NW), %eax /* clear the CD and NW bits */
+ movl %eax, %cr0
+
+ /* clear boot_complete flag */
+ xorl %ebp, %ebp
+__main:
+ post_code(POST_PREPARE_RAMSTAGE)
+
+ /* TODO For suspend/resume the cache will have to live between
+ * CONFIG_RAMBASE and CONFIG_RAMTOP
+ */
+
+ cld /* clear direction flag */
+
+ /* copy coreboot from it's initial load location to
+ * the location it is compiled to run at.
+ * Normally this is copying from FLASH ROM to RAM.
+ */
+ movl %ebp, %esi
+ pushl %esi
+ call copy_and_run
+
+.Lhlt:
+ post_code(POST_DEAD_CODE)
+ hlt
+ jmp .Lhlt
+
diff --git a/src/cpu/amd/geode_gx2/cpubug.c b/src/cpu/amd/geode_gx2/cpubug.c
new file mode 100644
index 0000000000..473766c8a4
--- /dev/null
+++ b/src/cpu/amd/geode_gx2/cpubug.c
@@ -0,0 +1,349 @@
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/amd/gx2def.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/cache.h>
+
+#if 0
+void bug645(void)
+{
+ msr_t msr;
+ rdmsr(CPU_ID_CONFIG);
+ msr.whatever |= ID_CONFIG_SERIAL_SET;
+ wrmsr(msr);
+}
+
+void bug573(void)
+{
+ msr_t msr;
+ msr = rdmsr(MC_GLD_MSR_PM);
+ msr.eax &= 0xfff3;
+ wrmsr(MC_GLD_MSR_PM);
+}
+#endif
+
+/* pcideadlock
+ *
+ * Bugtool #465 and #609
+ * PCI cache deadlock
+ * There is also fix code in cache and PCI functions. This bug is very is pervasive.
+ */
+static void pcideadlock(void)
+{
+ msr_t msr;
+
+ /* forces serialization of all load misses. Setting this bit prevents the
+ * DM pipe from backing up if a read request has to be held up waiting
+ * for PCI writes to complete.
+ */
+ msr = rdmsr(CPU_DM_CONFIG0);
+ msr.hi &= ~(7<<DM_CONFIG0_UPPER_WSREQ_SHIFT);
+ msr.hi |= (2<<DM_CONFIG0_UPPER_WSREQ_SHIFT);
+ msr.lo |= DM_CONFIG0_LOWER_MISSER_SET;
+ wrmsr(CPU_DM_CONFIG0, msr);
+
+ /* interlock instruction fetches to WS regions with data accesses.
+ * This prevents an instruction fetch from going out to PCI if the
+ * data side is about to make a request.
+ */
+ msr = rdmsr(CPU_IM_CONFIG);
+ msr.lo |= IM_CONFIG_LOWER_QWT_SET;
+ wrmsr(CPU_IM_CONFIG, msr);
+
+ /* write serialize memory hole to PCI. Need to unWS when something is
+ * shadowed regardless of cachablility.
+ */
+ msr.lo = 0x021212121;
+ msr.hi = 0x021212121;
+ wrmsr( CPU_RCONF_A0_BF, msr);
+ wrmsr( CPU_RCONF_C0_DF, msr);
+ wrmsr( CPU_RCONF_E0_FF, msr);
+}
+
+/* CPUbug784
+ *
+ * Bugtool #784 + #792
+ *
+ * Fix CPUID instructions for < 3.0 CPUs
+ */
+static void bug784(void)
+{
+ msr_t msr;
+ //static char *name = "Geode by NSC";
+
+ /* we'll do this the stupid way, for now, but that's the string they want. NO ONE KNOWS why you
+ * would do this -- the OS can figure this type of stuff out!
+ */
+ msr = rdmsr(0x3006);
+ msr.hi = 0x646f6547;
+ wrmsr(0x3006, msr);
+
+ msr = rdmsr(0x3007);
+ msr.hi = 0x79622065;
+ msr.lo = 0x43534e20;
+ wrmsr(0x3007, msr);
+
+ msr = rdmsr(0x3002);
+ wrmsr(0x3008, msr);
+
+ /* More CPUID to match AMD better. #792*/
+ msr = rdmsr(0x3009);
+ msr.hi = 0x0C0C0A13D;
+ msr.lo = 0x00000000;
+ wrmsr(0x3009, msr);
+}
+
+/* cpubug 1398: enable MC if we KNOW we have DDR*/
+
+/* CPUbugIAENG1398
+ *
+ * ClearQuest #IAENG1398
+ * The MC can not be enabled with SDR memory but can for DDR. Enable for
+ * DDR here if the setup token is "Default"
+ * Add this back to core by default once 2.0 CPUs are not supported.
+ */
+static void eng1398(void)
+{
+ msr_t msr;
+
+ msr = rdmsr(MSR_GLCP+0x17);
+ if ((msr.lo & 0xff) <= CPU_REV_2_0) {
+ msr = rdmsr(GLCP_SYS_RSTPLL);
+ if (msr.lo & (1<<RSTPPL_LOWER_SDRMODE_SHIFT))
+ return;
+ }
+
+ /* no CMOS/NVRAM to check, so enable MC Clock Gating */
+ msr = rdmsr(MC_GLD_MSR_PM);
+ msr.lo |= 3; /* enable MC clock gating.*/
+ wrmsr(MC_GLD_MSR_PM, msr);
+}
+
+/* CPUbugIAENG2900
+ *
+ * Clear Quest IAENG00002900, VSS 118.150
+ *
+ * BTB issue causes blue screen in windows, but the fix is required
+ * for all operating systems.
+ */
+static void eng2900(void)
+{
+ msr_t msr;
+
+ printk(BIOS_DEBUG, "CPU_BUG:%s\n", __func__);
+ /* Clear bit 43, disables the sysenter/sysexit in CPUID3 */
+ msr = rdmsr(0x3003);
+ msr.hi &= 0xFFFFF7FF;
+ wrmsr(0x3003, msr);
+
+ /* change this value to zero if you need to disable this BTB SWAPSiF. */
+ if (1) {
+
+ /* Disable enable_actions in DIAGCTL while setting up GLCP */
+ msr.hi = 0;
+ msr.lo = 0;
+ wrmsr(MSR_GLCP + 0x005f, msr);
+
+ /* Changing DBGCLKCTL register to GeodeLink */
+ msr.hi = 0;
+ msr.lo = 0;
+ wrmsr(MSR_GLCP + 0x0016, msr);
+
+ msr.hi = 0;
+ msr.lo = 2;
+ wrmsr(MSR_GLCP + 0x0016, msr);
+
+ /* The code below sets up the CPU to stall for 4 GeodeLink
+ * clocks when CPU is snooped. Because setting XSTATE to 0
+ * overrides any other XSTATE action, the code will always
+ * stall for 4 GeodeLink clocks after a snoop request goes
+ * away even if it occured a clock or two later than a
+ * different snoop; the stall signal will never 'glitch high'
+ * for only one or two CPU clocks with this code.
+ */
+
+ /* Send mb0 port 3 requests to upper GeodeLink diag bits
+ [63:32] */
+ msr.hi = 0;
+ msr.lo = 0x80338041;
+ wrmsr(MSR_GLIU0 + 0x2005, msr);
+
+ /* set5m watches request ready from mb0 to CPU (snoop) */
+ msr.hi = 0x5ad68000;
+ msr.lo = 0;
+ wrmsr(MSR_GLCP + 0x0045, msr);
+
+ /* SET4M will be high when state is idle (XSTATE=11) */
+ msr.hi = 0;
+ msr.lo = 0x0140;
+ wrmsr(MSR_GLCP + 0x0044, msr);
+
+ /* SET5n to watch for processor stalled state */
+ msr.hi = 0x2000;
+ msr.lo = 0;
+ wrmsr(MSR_GLCP + 0x004D, msr);
+
+ /* Writing action number 13: XSTATE=0 to occur when CPU is
+ snooped unless we're stalled */
+ msr.hi = 0;
+ msr.lo = 0x00400000;
+ wrmsr(MSR_GLCP + 0x0075, msr);
+
+ /* Writing action number 11: inc XSTATE every GeodeLink clock
+ unless we're idle */
+ msr.hi = 0;
+ msr.lo = 0x30000;
+ wrmsr(MSR_GLCP + 0x0073, msr);
+
+ /* Writing action number 5: STALL_CPU_PIPE when exitting idle
+ state or not in idle state */
+ msr.hi = 0;
+ msr.lo = 0x00430000;
+ wrmsr(MSR_GLCP + 0x006D, msr);
+
+ /* Writing DIAGCTL Register to enable the stall action and to
+ let set5m watch the upper GeodeLink diag bits. */
+ msr.hi = 0;
+ msr.lo = 0x80004000;
+ wrmsr(MSR_GLCP + 0x005f, msr);
+ }
+}
+
+static void bug118253(void)
+{
+ /* GLPCI PIO Post Control shouldn't be enabled */
+ msr_t msr;
+
+ msr = rdmsr(GLPCI_SPARE);
+ msr.lo &= ~GLPCI_SPARE_LOWER_PPC_SET;
+ wrmsr(GLPCI_SPARE, msr);
+}
+
+static void bug118339(void)
+{
+ /* per AMD, do this always */
+ msr_t msr = {0,0};
+ int msrnum;
+
+ /* Disable enable_actions in DIAGCTL while setting up GLCP */
+ wrmsr(MSR_GLCP + 0x005f, msr);
+
+ /* SET2M fires if VG pri is odd (3, not 2) and Ystate=0 */
+ msrnum = MSR_GLCP + 0x042;
+ /* msr.hi = 2d6b8000h */;
+ msr.hi = 0x596b8000;
+ msr.lo = 0x00000a00;
+ wrmsr(msrnum, msr);
+
+ /* SET3M fires if MBUS changed and VG pri is odd */
+ msrnum = MSR_GLCP + 0x043;
+ msr.hi = 0x596b8040;
+ msr.lo = 0;
+ wrmsr(msrnum, msr);
+
+ /* Put VG request data on lower diag bus */
+ msrnum = MSR_GLIU0 + 0x2005;
+ msr.hi = 0;
+ msr.lo = 0x80338041;
+ wrmsr(msrnum, msr);
+
+ /* Increment Y state if SET3M if true */
+ msrnum = MSR_GLCP + 0x074;
+ msr.hi = 0;
+ msr.lo = 0x0000c000;
+ wrmsr(msrnum, msr);
+
+ /* Set up MBUS action to PRI=3 read of MBIU */
+ msrnum = MSR_GLCP + 0x020;
+ msr.hi = 0x0000d863;
+ msr.lo = 0x20002000;
+ wrmsr(msrnum, msr);
+
+ /* Trigger MBUS action if VG=pri3 and Y=0, this blocks most PCI */
+ msrnum = MSR_GLCP + 0x071;
+ msr.hi = 0;
+ msr.lo = 0x00000c00;
+ wrmsr(msrnum, msr);
+
+ /* Writing DIAGCTL */
+ msrnum = MSR_GLCP + 0x005f;
+ msr.hi = 0;
+ msr.lo = 0x80004000;
+ wrmsr(msrnum, msr);
+
+ /* Code to enable FS2 even when BTB and VGTEAR SWAPSiFs are enabled
+ * As per Todd Roberts in PBz1094 and PBz1095
+ * Moved from CPUREG to CPUBUG per Tom Sylla
+ */
+ msrnum = 0x04C000042; /* GLCP SETMCTL Register */
+ msr = rdmsr(msrnum);
+ msr.hi |= 8; /* Bit 35 = MCP_IN */
+ wrmsr(msrnum, msr);
+}
+
+
+
+/* DisableMemoryReorder
+ *
+ * PBZ 3659:
+ * The MC reordered transactions incorrectly and breaks coherency.
+ * Disable reording and take a potential performance hit.
+ * This is safe to do here and not in MC init since there is nothing
+ * to maintain coherency with and the cache is not enabled yet.
+ */
+static void disablememoryreadorder(void)
+{
+ msr_t msr;
+
+ msr = rdmsr(MC_CF8F_DATA);
+ msr.hi |= CF8F_UPPER_REORDER_DIS_SET;
+ wrmsr(MC_CF8F_DATA, msr);
+}
+
+void cpubug(void)
+{
+ msr_t msr;
+ int rev;
+
+ msr = rdmsr(GLCP_CHIP_REVID);
+
+ rev = msr.lo & 0xff;
+ if (rev < 0x20) {
+ printk(BIOS_ERR, "%s: rev < 0x20! bailing!\n", __func__);
+ return;
+ }
+ printk(BIOS_DEBUG, "Doing cpubug fixes for rev 0x%x\n", rev);
+ switch(rev)
+ {
+ case 0x20:
+ pcideadlock();
+ eng1398();
+ /* cs 5530 bug; ignore
+ bug752();
+ */
+ break;
+ case 0x21:
+ pcideadlock();
+ eng1398();
+ eng2900();
+ bug118339();
+ break;
+ case 0x22:
+ case 0x30:
+ break;
+ default:
+ printk(BIOS_ERR, "unknown rev %x, bailing\n", rev);
+ return;
+ }
+ bug784();
+ bug118253();
+ disablememoryreadorder();
+ printk(BIOS_DEBUG, "Done cpubug fixes \n");
+}
diff --git a/src/cpu/amd/geode_gx2/cpureginit.c b/src/cpu/amd/geode_gx2/cpureginit.c
new file mode 100644
index 0000000000..0fc852d531
--- /dev/null
+++ b/src/cpu/amd/geode_gx2/cpureginit.c
@@ -0,0 +1,129 @@
+
+/* cpuRegInit */
+void cpuRegInit (void)
+{
+ int msrnum;
+ msr_t msr;
+ /* The following is only for diagnostics mode; do not use for OLPC */
+ if (0) {
+ /* Set Diagnostic Mode */
+ msrnum = CPU_GLD_MSR_DIAG;
+ msr.hi = 0;
+ msr.lo = DIAG_SEL1_SET | DIAG_SET0_SET;
+ wrmsr(msrnum, msr);
+
+ /* Set up GLCP to grab BTM data. */
+ msrnum = GLCP_DBGOUT; /* GLCP_DBGOUT MSR */
+ msr.hi = 0x0;
+ msr.lo = 0x08; /* reset value (SCOPE_SEL = 0) causes FIFO toshift out, */
+ wrmsr(msrnum, msr); /* exchange it to anything else to prevent this */
+
+ /* Turn off debug clock */
+ msrnum = GLCP_DBGCLKCTL; /* DBG_CLK_CTL */
+ msr.lo = 0x00; /* No clock */
+ msr.hi = 0x00;
+ wrmsr(msrnum, msr);
+
+ /* Set debug clock to CPU */
+ msrnum = GLCP_DBGCLKCTL; /* DBG_CLK_CTL */
+ msr.lo = 0x01; /* CPU CLOCK */
+ msr.hi = 0x00;
+ wrmsr(msrnum, msr);
+
+ /* Set fifo ctl to BTM bits wide */
+ msrnum = GLCP_FIFOCTL; /* FIFO_CTL */
+ msr.lo = 0x003880000; /* Bit [25:24] are size (11=BTM, 10 = 64 bit, 01= 32 bit, 00 = 16bit) */
+ wrmsr(msrnum, msr); /* Bit [23:21] are position (100 = CPU downto0) */
+ /* Bit [19] sets it up in slow data mode. */
+
+ /* enable fifo loading - BTM sizing will constrain */
+ /* only valid BTM packets to load - this action should always be on */
+ msrnum = 0x04C00006F; /* GLCP ACTION7 - load fifo */
+ msr.lo = 0x00000F000; /* Any nibble all 1's will always trigger */
+ msr.hi = 0x000000000;
+ wrmsr(msrnum, msr);
+
+ /* start storing diag data in the fifo */
+ msrnum = 0x04C00005F; /* DIAG CTL */
+ msr.lo = 0x080000000; /* enable actions */
+ msr.hi = 0x000000000;
+ wrmsr(msrnum, msr);
+
+ /* Set up delay on data lines, so that the hold time */
+ /* is 1 ns. */
+ msrnum = GLCP_PROCSTAT; /* GLCP IO DELAY CONTROLS */
+ msr.lo = 0x082b5ad68;
+ msr.hi = 0x080ad6b57; /* RGB delay = 0x07 */
+ wrmsr(msrnum, msr);
+
+ /* Set up DF to output diag information on DF pins. */
+ msrnum = DF_GLD_MSR_MASTER_CONF;
+ msr.lo = 0x0220;
+ msr.hi = 0;
+ wrmsr(msrnum, msr);
+
+ msrnum = GLCP_DBGOUT; /* GLCP_DBGOUT MSR */
+ msr.hi = 0x0;
+ msr.lo = 0x0; /* reset value (SCOPE_SEL = 0) causes FIFO to shift out, */
+ wrmsr(msrnum, msr);
+ /* end of code for BTM */
+ }
+
+ /* Enable Suspend on Halt */
+ msrnum = CPU_XC_CONFIG;
+ msr = rdmsr(msrnum);
+ msr.lo |= XC_CONFIG_SUSP_ON_HLT;
+ wrmsr(msrnum, msr);
+
+ /* ENable SUSP and allow TSC to run in Suspend */
+ /* to keep speed detection happy */
+ msrnum = CPU_BC_CONF_0;
+ msr = rdmsr(msrnum);
+ msr.lo |= TSC_SUSP_SET | SUSP_EN_SET;
+ wrmsr(msrnum, msr);
+
+ /* Setup throttling to proper mode if it is ever enabled. */
+ msrnum = GLCP_TH_OD;
+ msr.hi = 0x000000000;
+ msr.lo = 0x00000603C;
+ wrmsr(msrnum, msr);
+
+/* FooGlue Setup */
+ /* Set CS5535/CS5536 mode in FooGlue */
+ msrnum = FG_GIO_MSR_SEL;
+ msr = rdmsr(msrnum);
+ msr.lo &= ~3;
+ msr.lo |= 2; /* IIOC mode CS5535/CS5536 enable. (according to Jordan Crouse the databook is wrong bits 1:0 have to be 2 instead of 1) */
+ wrmsr(msrnum, msr);
+
+/* Disable DOT PLL. Graphics init will enable it if needed. */
+ msrnum = GLCP_DOTPLL;
+ msr = rdmsr(msrnum);
+ msr.lo |= DOTPPL_LOWER_PD_SET;
+ wrmsr(msrnum, msr);
+
+/* Enable RSDC */
+ msrnum = CPU_AC_SMM_CTL;
+ msr = rdmsr(msrnum);
+ msr.lo |= 0x08;
+ wrmsr(msrnum, msr);
+
+/* Enable BTB */
+ /* I hate to put this check here but it doesn't really work in cpubug.asm */
+ msrnum = GLCP_CHIP_REVID;
+ msr = rdmsr(msrnum);
+ if (msr.lo >= CPU_REV_2_1){
+ msrnum = CPU_PF_BTB_CONF;
+ msr = rdmsr(msrnum);
+ msr.lo |= BTB_ENABLE_SET | RETURN_STACK_ENABLE_SET;
+ wrmsr(msrnum, msr);
+ }
+
+/* FPU impercise exceptions bit */
+ {
+ msrnum = CPU_FPU_MSR_MODE;
+ msr = rdmsr(msrnum);
+ msr.lo |= FPU_IE_SET;
+ wrmsr(msrnum, msr);
+ }
+}
diff --git a/src/cpu/amd/geode_gx2/geode_gx2_init.c b/src/cpu/amd/geode_gx2/geode_gx2_init.c
new file mode 100644
index 0000000000..7e481b5390
--- /dev/null
+++ b/src/cpu/amd/geode_gx2/geode_gx2_init.c
@@ -0,0 +1,46 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <string.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/lapic.h>
+#include <cpu/x86/cache.h>
+
+static void vsm_end_post_smi(void)
+{
+ __asm__ volatile (
+ "push %ax\n"
+ "mov $0x5000, %ax\n"
+ ".byte 0x0f, 0x38\n"
+ "pop %ax\n"
+ );
+}
+
+static void geode_gx2_init(device_t dev)
+{
+ printk(BIOS_DEBUG, "geode_gx2_init\n");
+
+ /* Turn on caching if we haven't already */
+ x86_enable_cache();
+
+ /* Enable the local cpu apics */
+ //setup_lapic();
+
+ vsm_end_post_smi();
+
+ printk(BIOS_DEBUG, "geode_gx2_init DONE\n");
+};
+
+static struct device_operations cpu_dev_ops = {
+ .init = geode_gx2_init,
+};
+
+static struct cpu_device_id cpu_table[] = {
+ { X86_VENDOR_NSC, 0x0552 },
+ { 0, 0 },
+};
+
+static const struct cpu_driver driver __cpu_driver = {
+ .ops = &cpu_dev_ops,
+ .id_table = cpu_table,
+};
diff --git a/src/cpu/amd/geode_gx2/syspreinit.c b/src/cpu/amd/geode_gx2/syspreinit.c
new file mode 100644
index 0000000000..814034823c
--- /dev/null
+++ b/src/cpu/amd/geode_gx2/syspreinit.c
@@ -0,0 +1,20 @@
+/* StartTimer1
+ *
+ * Entry: none
+ * Exit: Starts Timer 1 for port 61 use
+ * Destroys: Al,
+ */
+static void StartTimer1(void)
+{
+ outb(0x56, 0x43);
+ outb(0x12, 0x41);
+}
+
+void SystemPreInit(void)
+{
+ /* they want a jump ... */
+#if !CONFIG_CACHE_AS_RAM
+ __asm__ __volatile__("jmp .+2\ninvd\njmp .+2\n");
+#endif
+ StartTimer1();
+}