diff options
Diffstat (limited to 'src/northbridge/amd/lx/chipsetinit.c')
-rw-r--r-- | src/northbridge/amd/lx/chipsetinit.c | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/src/northbridge/amd/lx/chipsetinit.c b/src/northbridge/amd/lx/chipsetinit.c new file mode 100644 index 0000000000..0178079795 --- /dev/null +++ b/src/northbridge/amd/lx/chipsetinit.c @@ -0,0 +1,384 @@ +#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 "chip.h" +#include "northbridge.h" +#include <cpu/amd/lxdef.h> +#include <cpu/x86/msr.h> +#include <cpu/x86/cache.h> + + +/* the structs in this file only set msr.lo. But ... that may not always be true */ + +struct msrinit { + unsigned long msrnum; + msr_t msr; +}; + +/* Master Configuration Register for Bus Masters.*/ +struct msrinit SB_MASTER_CONF_TABLE[] = { + {USB1_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00008f000}}, /* NOTE: Must be 1st entry in table*/ + {USB2_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00008f000}}, + {ATA_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00048f000}}, + {AC97_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00008f000}}, + {MDD_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00000f000}}, +/* GLPCI_SB_GLD_MSR_CONF, 0x0FFFFFFFF*/ +/* GLCP_SB_GLD_MSR_CONF, 0x0FFFFFFFF*/ +/* GLIU_SB_GLD_MSR_CONF, 0x0*/ + {0,{0,0}} +}; + +/* 5535_A3 Clock Gating*/ +struct msrinit CS5535_CLOCK_GATING_TABLE[] = { + { USB1_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + { USB2_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + { GLIU_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, + { GLPCI_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + { GLCP_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, + { MDD_SB_GLD_MSR_PM, {.hi=0,.lo=0x050554111}}, + { ATA_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + { AC97_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + {0,{0,0}} +}; + +/* 5536 Clock Gating*/ +struct msrinit CS5536_CLOCK_GATING_TABLE[] = { +/* MSR Setting*/ + { GLIU_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, + { GLPCI_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + { GLCP_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, + { MDD_SB_GLD_MSR_PM, {.hi=0,.lo=0x050554111}}, /* SMBus clock gating errata (PBZ 2226 & SiBZ 3977)*/ + { ATA_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + { AC97_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + {0,{0,0}} +}; + +struct acpiinit { + unsigned short ioreg; + unsigned long regdata; + unsigned short iolen; +}; + +struct acpiinit acpi_init_table[] = { + {ACPI_BASE+0x00, 0x01000000, 4}, + {ACPI_BASE+0x08, 0, 4}, + {ACPI_BASE+0x0C, 0, 4}, + {ACPI_BASE+0x1C, 0, 4}, + {ACPI_BASE+0x18, 0x0FFFFFFFF, 4}, + {ACPI_BASE+0x00, 0x0000FFFF, 4}, + + {PM_SCLK, 0x000000E00, 4}, + {PM_SED, 0x000004601, 4}, + {PM_SIDD, 0x000008C02, 4}, + {PM_WKD, 0x0000000A0, 4}, + {PM_WKXD, 0x0000000A0, 4}, + {0,0,0} +}; + +/* return 1 if we are a 5536-based system */ +static int is_5536(void){ + msr_t msr; + msr = rdmsr(GLIU_SB_GLD_MSR_CAP); + msr.lo >>= 20; + printk_debug("is_5536: msr.lo is 0x%x(==5 means 5536)\n", msr.lo&0xf); + return ((msr.lo&0xf) == 5); +} +/* ***************************************************************************/ +/* **/ +/* * pmChipsetInit*/ +/* **/ +/* * Program ACPI LBAR and initialize ACPI registers.*/ +/* * */ +/* **/ +/* * Entry:*/ +/* * None*/ +/* **/ +/* * Exit:*/ +/* * None*/ +/* **/ +/* * Destroys:*/ +/* * None*/ +/* **/ +/* ***************************************************************************/ +static void +pmChipsetInit(void) { + unsigned long val = 0; + unsigned short port; + + port = (PMLogic_BASE + 0x010); + val = 0x0E00 ; /* 1ms*/ + outl(val, port); + + /* PM_WKXD*/ + /* Make sure bits[3:0]=0000b to clear the*/ + /* saved Sx state*/ + port = (PMLogic_BASE + 0x034); + val = 0x0A0 ; /* 5ms*/ + outl(val, port); + + /* PM_WKD*/ + port = (PMLogic_BASE + 0x030); + outl(val, port); + + /* PM_SED*/ + port = (PMLogic_BASE + 0x014); +/* mov eax, 0x057642 ; 100ms, works*/ + val = 0x04601 ; /* 5ms*/ + outl(val, port); + + /* PM_SIDD*/ + port = (PMLogic_BASE + 0x020); +/* mov eax, 0x0AEC84 ; 200ms, works*/ + val = 0x08C02 ; /* 10ms*/ + outl(val, port); + + /* GPIO24 OUT_AUX1 function is the external signal for 5535's vsb_working_aux*/ + /* which is de-asserted when 5535 enters Standby(S3 or S5) state.*/ + /* On Hawk, GPIO24 controls all voltage rails except Vmem and Vstandby. This means*/ + /* GX2 will be fully de-powered if this control de-asserts in S3/S5.*/ + /* */ + /* GPIO24 is setup in preChipsetInit for two reasons*/ + /* 1. GPIO24 at reset defaults to disabled, since this signal is vsb_work_aux on*/ + /* Hawk it controls the FET's for all voltage rails except Vstanby & Vmem.*/ + /* BIOS needs to enable GPIO24 as OUT_AUX1 & OUTPUT_EN early so it is driven*/ + /* by 5535.*/ + /* 2. Non-PM builds will require GPIO24 enabled for instant-off power button*/ + /* */ + + /* GPIO11 OUT_AUX1 function is the external signal for 5535's slp_clk_n which is asserted*/ + /* when 5535 enters Sleep(S1) state.*/ + /* On Hawk, GPIO11 is connected to control input of external clock generator*/ + /* for 14MHz, PCI, USB & LPC clocks.*/ + /* Programming of GPIO11 will be done by VSA PM code. During VSA Init. BIOS writes*/ + /* PM Core Virual Register indicating if S1 Clocks should be On or Off. This is based*/ + /* on a Setup item. We do not want to leave GPIO11 enabled because of a Hawk board*/ + /* problem. With GPIO11 enabled in S3, something is back-driving GPIO11 causing it to*/ + /* float to 1.6-1.7V.*/ + +} + +struct FLASH_DEVICE { + unsigned char fType; /* Flash type: NOR or NAND */ + unsigned char fInterface; /* Flash interface: I/O or Memory */ + unsigned long fMask; /* Flash size/mask */ +}; + +struct FLASH_DEVICE FlashInitTable[] = { + { FLASH_TYPE_NAND, FLASH_IF_MEM, FLASH_MEM_4K }, /* CS0, or Flash Device 0 */ + { FLASH_TYPE_NONE, 0, 0 }, /* CS1, or Flash Device 1 */ + { FLASH_TYPE_NONE, 0, 0 }, /* CS2, or Flash Device 2 */ + { FLASH_TYPE_NONE, 0, 0 }, /* CS3, or Flash Device 3 */ +}; + +#define FlashInitTableLen (sizeof(FlashInitTable)/sizeof(FlashInitTable[0])) + +uint32_t FlashPort[] = { + MDD_LBAR_FLSH0, + MDD_LBAR_FLSH1, + MDD_LBAR_FLSH2, + MDD_LBAR_FLSH3 + }; + +/*************************************************************************** + * + * ChipsetFlashSetup + * + * Flash LBARs need to be setup before VSA init so the PCI BARs have + * correct size info. Call this routine only if flash needs to be + * configured (don't call it if you want IDE). + * + * Entry: + * Exit: + * Destroys: + * + **************************************************************************/ +static void ChipsetFlashSetup(void) +{ + msr_t msr; + int i; + int numEnabled = 0; + + printk_debug("ChipsetFlashSetup++\n"); + for (i = 0; i < FlashInitTableLen; i++) { + if (FlashInitTable[i].fType != FLASH_TYPE_NONE) { + printk_debug("Enable CS%d\n", i); + /* we need to configure the memory/IO mask */ + msr = rdmsr(FlashPort[i]); + msr.hi = 0; /* start with the "enabled" bit clear */ + if (FlashInitTable[i].fType == FLASH_TYPE_NAND) + msr.hi |= 0x00000002; + else + msr.hi &= ~0x00000002; + if (FlashInitTable[i].fInterface == FLASH_IF_MEM) + msr.hi |= 0x00000004; + else + msr.hi &= ~0x00000004; + msr.hi |= FlashInitTable[i].fMask; + printk_debug("WRMSR(0x%08X, %08X_%08X)\n", FlashPort[i], msr.hi, msr.lo); + wrmsr(FlashPort[i], msr); + + /* now write-enable the device */ + msr = rdmsr(MDD_NORF_CNTRL); + msr.lo |= (1 << i); + printk_debug("WRMSR(0x%08X, %08X_%08X)\n", MDD_NORF_CNTRL, msr.hi, msr.lo); + wrmsr(MDD_NORF_CNTRL, msr); + + /* update the number enabled */ + numEnabled++; + } + } + + /* enable the flash */ + if (0 != numEnabled) { + msr = rdmsr(MDD_PIN_OPT); + msr.lo &= ~1; /* PIN_OPT_IDE */ + printk_debug("WRMSR(0x%08X, %08X_%08X)\n", MDD_PIN_OPT, msr.hi, msr.lo); + wrmsr(MDD_PIN_OPT, msr); + } + printk_debug("ChipsetFlashSetup--\n"); + +} + + + +/* ***************************************************************************/ +/* **/ +/* * ChipsetGeodeLinkInit*/ +/* * Handle chipset specific GeodeLink settings here. */ +/* * Called from GeodeLink init code.*/ +/* **/ +/* * Entry:*/ +/* * Exit:*/ +/* * Destroys: GS*/ +/* **/ +/* ***************************************************************************/ +static void +ChipsetGeodeLinkInit(void){ + msr_t msr; + unsigned long msrnum; + unsigned long totalmem; + + if (is_5536()) + return; + /* SWASIF for A1 DMA */ + /* Set all memory to "just above systop" PCI so DMA will work*/ + /* check A1*/ + msrnum = MSR_SB_GLCP + 0x17; + msr = rdmsr(msrnum); + if ((msr.lo&0xff) == 0x11) + return; + + totalmem = sizeram() << 20 - 1; + totalmem >>= 12; + totalmem = ~totalmem; + totalmem &= 0xfffff; + msr.lo = totalmem; + msr.hi = 0x20000000; /* Port 1 (PCI)*/ + msrnum = MSR_SB_GLIU + 0x20; /* */; + wrmsr(msrnum, msr); +} + +void +chipsetinit (struct northbridge_amd_lx_config *nb){ + msr_t msr; + struct msrinit *csi; + int i; + unsigned long msrnum; + + outb( P80_CHIPSET_INIT, 0x80); + ChipsetGeodeLinkInit(); +#if 0 + /* we hope NEVER to be in linuxbios when S3 resumes + if (! IsS3Resume()) */ + { + struct acpiinit *aci = acpi_init_table; + while (aci->ioreg){ + if (aci->iolen == 2) { + outw(aci->regdata, aci->ioreg); + inw(aci->ioreg); + } else { + outl(aci->regdata, aci->ioreg); + inl(aci->ioreg); + } + } + + pmChipsetInit(); + } +#endif + + + if (!is_5536()) { + /* Setup USB. Need more details. #118.18*/ + msrnum = MSR_SB_USB1 + 8; + msr.lo = 0x00012090; + msr.hi = 0; + wrmsr(msrnum, msr); + msrnum = MSR_SB_USB2 + 8; + wrmsr(msrnum, msr); + } + + /* set hd IRQ */ + outl (GPIOL_2_SET, GPIOL_INPUT_ENABLE); + outl (GPIOL_2_SET, GPIOL_IN_AUX1_SELECT); + + /* Allow IO read and writes during a ATA DMA operation.*/ + /* This could be done in the HD rom but do it here for easier debugging.*/ + + msrnum = ATA_SB_GLD_MSR_ERR; + msr = rdmsr(msrnum); + msr.lo &= ~0x100; + wrmsr(msrnum, msr); + + /* Enable Post Primary IDE.*/ + msrnum = GLPCI_SB_CTRL; + msr = rdmsr(msrnum); + msr.lo |= GLPCI_CRTL_PPIDE_SET; + wrmsr(msrnum, msr); + + + /* Set up Master Configuration Register*/ + /* If 5536, use same master config settings as 5535, except for OHCI MSRs*/ + if (is_5536()) + i = 2; + else + i = 0; + + csi = &SB_MASTER_CONF_TABLE[i]; + for(; csi->msrnum; csi++){ + msr.lo = csi->msr.lo; + msr.hi = csi->msr.hi; + wrmsr(csi->msrnum, msr); // MSR - see table above + } + + + /* Flash Setup*/ + printk_err("%sDOING ChipsetFlashSetup()!!!!!!!!!!!!!!!!!!\n", nb->setupflash? " " : "NOT"); + if (nb->setupflash) + ChipsetFlashSetup(); + + + + /* */ + /* Set up Hardware Clock Gating*/ + /* */ + /* if (getnvram(TOKEN_SB_CLK_GATE) != TVALUE_DISABLE) */ + { + if (is_5536()) + csi = CS5536_CLOCK_GATING_TABLE; + else + csi = CS5535_CLOCK_GATING_TABLE; + + for(; csi->msrnum; csi++){ + msr.lo = csi->msr.lo; + msr.hi = csi->msr.hi; + wrmsr(csi->msrnum, msr); // MSR - see table above + } + } + +} |