summaryrefslogtreecommitdiff
path: root/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c')
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c
new file mode 100755
index 0000000..8a7cdf4
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c
@@ -0,0 +1,367 @@
+/*
+* 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
+*/
+
+//******************************************************************************
+//* Routines related to the MBus Diverse Device
+//******************************************************************************
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "GX2.H"
+#include "MDD.H"
+#include "PROTOS.H"
+#include "DESCR.H"
+#include "ACPI.H"
+#include "VPCI.H"
+#include "PCI.H"
+#include "ACPI.H"
+#include "CHIPSET.H"
+
+#define A20_EN (A20_P_EN | A20_K_EN)
+#define INIT_EN (INIT_K_EN | INIT_P_EN)
+
+
+// External function prototypes:
+void Init_MFGPT(void);
+UCHAR pascal ACPI_Trapping(USHORT);
+
+// Local function prototypes:
+void pascal Control_MDD_SMI(USHORT, ULONG);
+
+
+// Local variables:
+ULONG MDD_Base;
+
+// External variables:
+extern PCI_HEADER_ENTRY ISA_Hdr[];
+extern Hardware HardwareInfo;
+
+
+//***********************************************************************
+// Enables/disables KEL SMIs
+//***********************************************************************
+void pascal Control_KEL_SMI(USHORT EnableFlag)
+{
+ Control_MDD_SMI(EnableFlag, KEL_ASMI_EN);
+}
+
+//***********************************************************************
+// Enable/disable keyboard command snooping by KEL
+//***********************************************************************
+void pascal Control_KEL_Snoop(USHORT EnableFlag)
+{ ULONG MsrAddr, MsrData;
+
+ MsrAddr = MDD_Base;
+ (USHORT)MsrAddr = MSR_KEL_CNTRL;
+ MsrData = Read_MSR_LO(MsrAddr);
+
+ if (EnableFlag) {
+ MsrData |= KEL_SNOOP;
+ } else {
+ MsrData &= ~KEL_SNOOP;
+ }
+ Write_MSR_LO(MsrAddr, MsrData);
+
+}
+
+//***********************************************************************
+// Initializes the MBus Diverse Device
+//***********************************************************************
+void Init_MDD(void)
+{ ULONG MsrAddr;
+ USHORT ACPI_Bar;
+ UCHAR i;
+
+
+ // Find address of MBus Diverse Device
+ MsrAddr = MDD_Base = Find_MBus_ID(ID_MDD, 1) & 0xFFFF0000;
+
+ //*********************************************
+ // Record MDD's LBARs in MSRs[]
+ //*********************************************
+ for (i = MSR_LBAR_IRQ; i <= MSR_LBAR_FLSH3; i++) {
+
+ (UCHAR)MsrAddr = i;
+
+ if (Init_Descr(MDD_LBAR, MsrAddr)) {
+ break;
+ }
+ }
+
+ // Clear PM1_STS
+ (UCHAR)MsrAddr = ISA_Hdr[BAR5/4].LBar;
+ ACPI_Bar = (USHORT)Read_MSR_LO(MsrAddr);
+ out_16(ACPI_Bar, in_16(ACPI_Bar));
+
+
+ // Initialize KEL
+
+ // Enable keyboard snooping by KEL
+ Control_KEL_Snoop(1);
+
+ // Enable SMIs from:
+ // - A20 & Init (keyboard and port 92h)
+ // - KEL
+ // - Extended PIC Mapper
+ Control_MDD_SMI(1, A20_EN | INIT_EN | PIC_ASMI_EN | KEL_ASMI_EN);
+
+
+ // Initialize the MFGPT
+ Init_MFGPT();
+
+ // Clear any pending PIC events
+ (USHORT)MsrAddr = MBD_MSR_SMI;
+ Write_MSR_HI(MsrAddr, PIC_ASMI_EN);
+
+}
+
+
+
+
+//***********************************************************************
+// Implements CS5536's F0 Special Cycles.
+// Linked to MDD's MSR_LEG_IO[31].
+//
+// When set, a Shutdown special cycle causes a reset. When the Special
+// Cycles bit is cleared, a Shutdown special cycle is ignored. Before
+// updating MSR_LEG_IO, VSA will check MSR_ERR[15] and MSR_SMI[1]. If
+// either of these MSR bits are set, then no action is taken. It will
+// be assumed that a debugger is in use and VSA will not interfere.
+//***********************************************************************
+void pascal Update_Special_Cycles(USHORT EnableFlag)
+{ ULONG MSR_Addr, MSR_Data;
+
+
+ // If either MSR_ERR[15] and MSR_SMI[1] is set, then bail.
+ if (Read_MSR_LO(MDD_Base + MBD_MSR_SMI) & 2) {
+ return;
+ }
+ if (Read_MSR_LO(MDD_Base + MBD_MSR_ERROR) & 0x8000) {
+ return;
+ }
+
+ // Link MSR_LEG_IO[RESET_SHUT_EN] to COMMAND[3]
+ MSR_Addr = MDD_Base + MSR_LEG_IO;
+ MSR_Data = Read_MSR_LO(MSR_Addr);
+
+ if (EnableFlag) {
+ MSR_Data |= RESET_SHUT_EN;
+ } else {
+ MSR_Data &= ~RESET_SHUT_EN;
+ }
+
+ Write_MSR_LO(MSR_Addr, MSR_Data);
+}
+
+
+//***********************************************************************
+// Enable/disable of MDD ASMI(s)
+//***********************************************************************
+void pascal Control_MDD_SMI(USHORT EnableFlag, ULONG EnableMask)
+{ ULONG MsrAddr, MsrData;
+
+ MsrAddr = MDD_Base;
+ (USHORT)MsrAddr = MBD_MSR_SMI;
+
+ MsrData = Read_MSR_LO(MsrAddr);
+ if (EnableFlag) {
+ MsrData |= EnableMask;
+ } else {
+ MsrData &= ~EnableMask;
+ }
+ Write_MSR_LO(MsrAddr, MsrData);
+}
+
+
+//***********************************************************************
+// Clears the ACPI Status register
+// This routine fills in MsgPacket[0] = ACPI GPE0_STS
+// and MsgPacket[1] bits[15:0] = ACPI PM1_STS
+//***********************************************************************
+USHORT Get_ACPI_Status(ULONG *msgp)
+{ USHORT ACPI_Bar, PM1_Status;
+ ULONG GPE_Status;
+ UCHAR Flag;
+
+ // Disable ACPI trapping
+ Flag = ACPI_Trapping(0);
+
+ // Get ACPI Status
+ ACPI_Bar = ISA_Hdr[BAR5/4].Value_LO;
+
+ (UCHAR)ACPI_Bar = GPE0_STS_OFS;
+ GPE_Status = in_32(ACPI_Bar);
+
+ // Don't clear PIC status
+ GPE_Status &= ~1;
+
+
+ msgp[1] = GPE_Status;
+
+
+ (UCHAR)ACPI_Bar = PM1_STS_OFS;
+ PM1_Status = in_16(ACPI_Bar);
+
+
+ // Enable ACPI trapping
+ if (Flag) {
+ ACPI_Trapping(1);
+ }
+
+ msgp[2] = (ULONG)PM1_Status;
+
+ return (PM1_Status || GPE_Status);
+}
+
+//***********************************************************************
+// Enable PM logic
+//***********************************************************************
+void Enable_PME_Event(UCHAR EnableFlag, UCHAR Pm1Bit, UCHAR PmeBit, USHORT Attributes)
+{ ULONG Gpe, Pm1, bmGPE0;
+ USHORT ACPI_Bar, bmPM1;
+ UCHAR Flag;
+ static UCHAR pme_instance = 0;
+ static UCHAR PM1_Instance[11] = {0,0,0,0,0,0,0,0,0,0,0};
+ static UCHAR PME_Instance[8] = {0,0,0,0,0,0,0,0};
+ static ULONG GPE0_Masks[] = { // Maps PME # to GPE0 bits
+ 0x00010000,
+ 0x00020000,
+ 0x00040000,
+ 0x00080000,
+ 0x00100000,
+ 0x00200000,
+ 0x40000000,
+ 0x80000000,
+ };
+
+ bmPM1 = 0;
+ bmGPE0 = 0L;
+ if (Attributes & PM1) {
+ bmPM1 = 1 << Pm1Bit;
+
+ if (EnableFlag) {
+ PM1_Instance[Pm1Bit]++;
+ } else {
+ if (PM1_Instance[Pm1Bit]) {
+ // If there are still registrations for this PM1 bit...
+ if (--PM1_Instance[Pm1Bit]) {
+ // then don't turn disable it
+ return;
+ }
+ } else {
+ // Error:
+ return;
+ }
+ }
+ }
+ if (Attributes & GPE) {
+ bmGPE0 = GPE0_Masks[PmeBit];
+ if (EnableFlag) {
+ PME_Instance[PmeBit]++;
+ } else {
+ if (PME_Instance[PmeBit]) {
+ // If there are still registrations for this GEP0 bit...
+ if (--PME_Instance[PmeBit]) {
+ // then don't turn disable it
+ return;
+ }
+ } else {
+ // Error:
+ return;
+ }
+ }
+ }
+
+
+ if (!(Attributes & NO_ASMI)) {
+ // Keep a count of PME events.
+ // Once all have been de-registered, turn off PM_ASMI bit.
+ if (EnableFlag) {
+ if (Attributes & PME) {
+ pme_instance++;
+ }
+ // Enable ASMIs from Power Management logic
+ Control_MDD_SMI(EnableFlag, PM_ASMI_EN);
+ } else {
+ if (Attributes & PME) {
+ if (pme_instance != 0) {
+ if (--pme_instance == 0) {
+ // Disable ASMIs from Power Management logic
+ Control_MDD_SMI(0, PM_ASMI_EN);
+ }
+ }
+ }
+ }
+ }
+
+ // See if we want to enable the approriate bits in PM1_EN and GPE0_EN
+ // if set to NO_ENALE we don't enable (Used by ACPI as the OS controls)
+ if (!(Attributes & NO_ENABLE)) {
+ // Disable ACPI trapping
+ Flag = ACPI_Trapping(0);
+
+ // Get ACPI base address
+ ACPI_Bar = ISA_Hdr[BAR5/4].Value_LO;
+
+ if (bmPM1) {
+ // Must do 32-bit I/O to avoid shadow register bug (IAeng00003062)
+ (UCHAR)ACPI_Bar = 0x00;
+ Pm1 = in_32(ACPI_Bar);
+ if (EnableFlag) {
+ Pm1 |= (ULONG)bmPM1 << 16;
+ } else {
+ Pm1 &= ~((ULONG)bmPM1 << 16);
+ }
+ out_32(ACPI_Bar, Pm1);
+
+ // Serialize the previous I/O write
+ in_16(ACPI_Bar);
+
+ // Clear spurious status
+ (UCHAR)ACPI_Bar = PM1_STS_OFS;
+ out_32(ACPI_Bar, (ULONG)Pm1);
+ }
+
+ if (bmGPE0) {
+ (UCHAR)ACPI_Bar = GPE0_EN_OFS;
+ Gpe = in_32(ACPI_Bar);
+ if (EnableFlag) {
+ Gpe |= bmGPE0;
+ } else {
+ Gpe &= ~bmGPE0;
+ }
+ out_32(ACPI_Bar, Gpe);
+ // Serialize the previous I/O write
+ in_32(ACPI_Bar);
+
+ // Clear spurious status
+ (UCHAR)ACPI_Bar = GPE0_STS_OFS;
+ out_32(ACPI_Bar, Gpe);
+ }
+
+ // Serialize the previous I/O write
+ in_32(ACPI_Bar);
+
+ // Re-enable ACPI trapping
+ if (Flag) {
+ ACPI_Trapping(1);
+ }
+ }
+}