summaryrefslogtreecommitdiff
path: root/cpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm')
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm221
1 files changed, 221 insertions, 0 deletions
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm
new file mode 100755
index 0000000..a7ec293
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm
@@ -0,0 +1,221 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code 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
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file contains hardware bug fixes.
+
+include VSA2.INC
+include ISA.INC
+include GX2.INC
+include CHIPSET.INC
+
+.model tiny,c
+.586p
+.CODE
+
+externdef Nested_SMI: proc
+externdef SysMgr_Entry: proc
+externdef Restore_IDT: proc
+externdef Install_IDT: proc
+externdef Sample_SMI_Pin: proc
+externdef Clear_SMI_Pin: proc
+externdef Header_Addr: dword
+externdef HC_Status: dword
+externdef SMI_Sources: dword
+externdef HardwareInfo: Hardware
+
+
+;*******************************************************************************
+; Remove the RTC fix if an RTC VSM is installed.
+;*******************************************************************************
+Remove_RTC_Fix proc
+
+ mov word ptr [Fix_RTC], 0C3F8h ; CLC RET
+ ret
+
+Remove_RTC_Fix endp
+
+
+; *******************************************************************************
+; This routine is called upon entry to a non-nested SMI.
+; *******************************************************************************
+VSA_Entry proc
+
+ ; Patch a "jmp Nested_SMI" at Start
+ mov word ptr ds:[1], OFFSET Nested_SMI-3
+
+ ; Install exception handlers
+ call Install_IDT
+ ret
+
+VSA_Entry endp
+
+
+
+
+
+; *******************************************************************************
+; This routine is called upon exit from a non-nested SMI.
+; It performs:
+; 1) RTC fix
+; 2) USB fix
+; 3) IDT restore
+; 4) Re-enable Suspend Modulation
+;
+; If CF=1 is returned, then loop back to SMI handlers.
+; *******************************************************************************
+VSA_Exit proc
+
+ mov eax, [Header_Addr] ; Restore the original SMM header
+ mov ecx, MSR_SMM_HDR
+ wrmsr
+
+ call Fix_RTC
+ jc short Exit ; Don't exit from VSA
+
+ ; Restore "JMP SysMgr_Entry" at Start
+ mov word ptr ds:[1], OFFSET SysMgr_Entry-3
+
+
+ call Restore_IDT ; Restore IDT
+
+ clc
+
+Exit: ret
+
+VSA_Exit endp
+
+
+
+
+
+
+
+
+
+
+; *******************************************************************************
+; Handle the case where the RTC UIP bit was clear, application code was about to
+; read the RTC, but an SMI occurs. When VSA returns, the RTC is updating, so the
+; application reads a bad value.
+;
+; The Solution:
+;
+; The Time Stamp Counter is read upon entry to VSA. On exit, if UIP is low or
+; it is determined that the SMI has taken < 250 us, then just exit. This leaves
+; 44 us for the application to finish reading the RTC safely. If the SMI has
+; taken > 250 us, then spin for 500 us minus the time spent servicing the SMI.
+; This guarantees the RTC has finished updating. Then set the SET bit, wait for
+; UIP to go low, then clear the SET bit.
+;
+; *******************************************************************************
+RTC_TIME equ 250
+
+Fix_RTC proc
+
+ in al, CMOS_INDEX ; Get RTC index
+ cmp al, 9 ; Only RTC indices 0-9 are UIP sensitive
+ ja Exit
+
+ mov bl, al ; Save RTC index
+ push si
+ mov al, CMOS_STATUS_A ; Read RTC Status A
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ test al, UIP
+ jz Restore_RTC_Index
+
+
+ mov al, CMOS_STATUS_B ; Exit if StatusB[SET] = 1
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ test al, SET
+ jz Restore_RTC_Index
+
+
+
+ ASSUME SI: PTR System ; Compute time servicing SMI in us
+ mov si, OFFSET VSM_Header.SysStuff
+ rdtsc
+ sub eax, [si+0].StartTime
+ sbb edx, [si+4].StartTime
+ movzx ecx, [HardwareInfo].CPU_MHz
+ cmp edx, ecx ; If sitting in Dowser or Standby too long,
+ jae Restore_RTC_Index ; the divide could overflow.
+ div ecx
+
+ cmp eax, RTC_TIME ; If < RTC_TIME us, exit
+ jb Restore_RTC_Index
+
+
+ call Clear_SMI_Pin
+WaitForUpdate:
+ call Sample_SMI_Pin
+ stc
+ jnz short SMI_Abort ; Yes, go process it
+
+
+ rdtsc ; Wait for additional 300 us
+ sub eax, [si+0].StartTime
+ sbb edx, [si+4].StartTime
+ div ecx
+ cmp eax, RTC_TIME + 300
+ jb WaitForUpdate
+
+ ASSUME SI: NOTHING
+
+
+ ; StatusB[SET] = 1;
+ mov al, CMOS_STATUS_B ; Read RTC StatusB
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ test al, SET ; If (SET == 1)
+ jnz short Restore_RTC_Index ; bail
+ or al, SET ; else
+ out CMOS_DATA, al ; SET = 1
+
+ ; Wait for StatusA[UIP] to go inactive
+ mov cx, 0FFFFh ; RTC timeout
+SpinUIP:
+ mov al, CMOS_STATUS_A ; Yes, spin until UIP is clear
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ test al, UIP
+ loopnz SpinUIP
+
+ mov al, CMOS_STATUS_B ; SET = 0
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ and al, NOT SET
+ out CMOS_DATA, al
+
+Restore_RTC_Index:
+ clc
+SMI_Abort:
+ pop si
+ mov al, bl ; Restore CMOS index
+ out CMOS_INDEX, al
+Exit: ret
+
+
+Fix_RTC endp
+
+
+
+ END
+