diff options
Diffstat (limited to 'src/southbridge/amd/cs5535/chipsetinit.c')
-rw-r--r-- | src/southbridge/amd/cs5535/chipsetinit.c | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/src/southbridge/amd/cs5535/chipsetinit.c b/src/southbridge/amd/cs5535/chipsetinit.c new file mode 100644 index 0000000000..d31efd3e52 --- /dev/null +++ b/src/southbridge/amd/cs5535/chipsetinit.c @@ -0,0 +1,360 @@ +#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/amd/gx2/northbridge.h" +#include <cpu/amd/gx2def.h> +#include <cpu/x86/msr.h> +#include <cpu/x86/cache.h> +#include "southbridge/amd/cs5535/cs5535.h" +// This code uses some cs5536 includes because cs5535 includes are empty: +#include "southbridge/amd/cs5536/cs5536.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. */ +static 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*/ +static 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, {.hi=0, .lo=0x000000000} } +}; + +#ifdef UNUSED_CODE +struct acpiinit { + unsigned short ioreg; + unsigned long regdata; + unsigned short iolen; +}; + +static 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} +}; + +/***************************************************************************** + * + * pmChipsetInit + * + * Program ACPI LBAR and initialize ACPI registers. + * + *****************************************************************************/ +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); + val = 0x04601 ; /* 5ms*/ + outl(val, port); + + /* PM_SIDD*/ + port = (PMLogic_BASE + 0x020); + 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. + */ +} +#endif + +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 */ +}; + +static 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 (ARRAY_SIZE(FlashInitTable)) + +static 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). + * + **************************************************************************/ +static void ChipsetFlashSetup(void) +{ + msr_t msr; + int i; + int numEnabled = 0; + + printk(BIOS_DEBUG, "ChipsetFlashSetup++\n"); + for (i = 0; i < FlashInitTableLen; i++) { + if (FlashInitTable[i].fType != FLASH_TYPE_NONE) { + printk(BIOS_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(BIOS_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(BIOS_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(BIOS_DEBUG, "WRMSR(0x%08X, %08X_%08X)\n", MDD_PIN_OPT, msr.hi, msr.lo); + wrmsr(MDD_PIN_OPT, msr); + } + + printk(BIOS_DEBUG, "ChipsetFlashSetup--\n"); +} + + + +/**************************************************************************** + * + * ChipsetGeodeLinkInit + * + * Handle chipset specific GeodeLink settings here. + * Called from GeodeLink init code. + * + ****************************************************************************/ +static void +ChipsetGeodeLinkInit(void) +{ + msr_t msr; + unsigned long msrnum; + unsigned long totalmem; + + /* 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; // highest address + 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(void) +{ + device_t dev; + struct southbridge_amd_cs5535_config *sb; + msr_t msr; + struct msrinit *csi; + int i; + unsigned long msrnum; + + dev = dev_find_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_NS_CS5535_ISA, 0); + + if (!dev) { + printk(BIOS_ERR, "CS5535 not found.\n"); + return; + } + + sb = (struct southbridge_amd_cs5535_config *)dev->chip_info; + + if (!sb) { + printk(BIOS_ERR, "CS5535 configuration not found.\n"); + return; + } + + outb( P80_CHIPSET_INIT, 0x80); + ChipsetGeodeLinkInit(); + +#ifdef UNUSED_CODE + /* we hope NEVER to be in coreboot 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 + + /* 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 */ + 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(BIOS_INFO, "%sDOING ChipsetFlashSetup()!\n", + sb->setupflash ? "" : "NOT "); + + if (sb->setupflash) + ChipsetFlashSetup(); + + /* Set up Hardware Clock Gating */ + + /* if (getnvram(TOKEN_SB_CLK_GATE) != TVALUE_DISABLE) */ + { + 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 + } + } +} + |