| #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 "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" |
| |
| /* 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 Vstandby & 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 Virtual 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; |
| } |
| |
| post_code(P80_CHIPSET_INIT); |
| 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 |
| } |
| } |
| } |