haswell platforms: restructure romstage main
There was a mix of setup code sprinkled across the various components: southbridge code in the northbridge, etc. This commit reorganizes the code so that northbridge code doesn't initialize southbridge components. Additionally, the calling dram initialization no longer calls out to ME code. The main() function in the mainboard calls the necessary ME functions before and after dram initialization. The biggest change is the addition of an early_pch_init() function which initializes the BARs, GPIOs, and RCBA configuration. It is also responsible for reporting back to the caller if the board is being woken up from S3. The one sequence difference is that the RCBA config is performed before claling the reference code. Lastly the rcba configuration was changed to be table driven so that different board/configurations can use the same code. It should be possible to have board/configuration specific gpio and rcba configuration while reusing the romstage code. Change-Id: I830e41b426261dd686a2701ce054fc39f296dffa Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/2681 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
parent
218a6864ff
commit
239c2e843f
|
@ -33,7 +33,7 @@
|
||||||
#include "northbridge/intel/haswell/haswell.h"
|
#include "northbridge/intel/haswell/haswell.h"
|
||||||
#include "northbridge/intel/haswell/raminit.h"
|
#include "northbridge/intel/haswell/raminit.h"
|
||||||
#include "southbridge/intel/lynxpoint/pch.h"
|
#include "southbridge/intel/lynxpoint/pch.h"
|
||||||
#include "southbridge/intel/lynxpoint/gpio.h"
|
#include "southbridge/intel/lynxpoint/me.h"
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <cpu/x86/bist.h>
|
#include <cpu/x86/bist.h>
|
||||||
#include <cpu/x86/msr.h>
|
#include <cpu/x86/msr.h>
|
||||||
|
@ -42,22 +42,7 @@
|
||||||
#include <vendorcode/google/chromeos/chromeos.h>
|
#include <vendorcode/google/chromeos/chromeos.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void pch_enable_lpc(void)
|
const struct rcba_config_instruction rcba_config[] = {
|
||||||
{
|
|
||||||
device_t dev = PCH_LPC_DEV;
|
|
||||||
|
|
||||||
/* Set COM1/COM2 decode range */
|
|
||||||
pci_write_config16(dev, LPC_IO_DEC, 0x0010);
|
|
||||||
|
|
||||||
/* Enable SuperIO + COM1 + PS/2 Keyboard/Mouse */
|
|
||||||
u16 lpc_config = CNF1_LPC_EN | CNF2_LPC_EN | COMA_LPC_EN | KBC_LPC_EN;
|
|
||||||
pci_write_config16(dev, LPC_EN, lpc_config);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rcba_config(void)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GFX INTA -> PIRQA (MSI)
|
* GFX INTA -> PIRQA (MSI)
|
||||||
* D28IP_P1IP WLAN INTA -> PIRQB
|
* D28IP_P1IP WLAN INTA -> PIRQB
|
||||||
|
@ -71,55 +56,42 @@ static void rcba_config(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Device interrupt pin register (board specific) */
|
/* Device interrupt pin register (board specific) */
|
||||||
RCBA32(D31IP) = (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) |
|
RCBA_SET_REG_32(D31IP, (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) |
|
||||||
(INTB << D31IP_SMIP) | (INTA << D31IP_SIP);
|
(INTB << D31IP_SMIP) | (INTA << D31IP_SIP)),
|
||||||
RCBA32(D30IP) = (NOINT << D30IP_PIP);
|
RCBA_SET_REG_32(D30IP, (NOINT << D30IP_PIP)),
|
||||||
RCBA32(D29IP) = (INTA << D29IP_E1P);
|
RCBA_SET_REG_32(D29IP, (INTA << D29IP_E1P)),
|
||||||
RCBA32(D28IP) = (INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) |
|
RCBA_SET_REG_32(D28IP, (INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) |
|
||||||
(INTB << D28IP_P4IP);
|
(INTB << D28IP_P4IP)),
|
||||||
RCBA32(D27IP) = (INTA << D27IP_ZIP);
|
RCBA_SET_REG_32(D27IP, (INTA << D27IP_ZIP)),
|
||||||
RCBA32(D26IP) = (INTA << D26IP_E2P);
|
RCBA_SET_REG_32(D26IP, (INTA << D26IP_E2P)),
|
||||||
RCBA32(D25IP) = (NOINT << D25IP_LIP);
|
RCBA_SET_REG_32(D25IP, (NOINT << D25IP_LIP)),
|
||||||
RCBA32(D22IP) = (NOINT << D22IP_MEI1IP);
|
RCBA_SET_REG_32(D22IP, (NOINT << D22IP_MEI1IP)),
|
||||||
|
|
||||||
/* Device interrupt route registers */
|
/* Device interrupt route registers */
|
||||||
DIR_ROUTE(D31IR, PIRQF, PIRQG, PIRQH, PIRQA);
|
RCBA_SET_REG_32(D31IR, DIR_ROUTE(PIRQF, PIRQG, PIRQH, PIRQA)),
|
||||||
DIR_ROUTE(D29IR, PIRQD, PIRQE, PIRQF, PIRQG);
|
RCBA_SET_REG_32(D29IR, DIR_ROUTE(PIRQD, PIRQE, PIRQF, PIRQG)),
|
||||||
DIR_ROUTE(D28IR, PIRQB, PIRQC, PIRQD, PIRQE);
|
RCBA_SET_REG_32(D28IR, DIR_ROUTE(PIRQB, PIRQC, PIRQD, PIRQE)),
|
||||||
DIR_ROUTE(D27IR, PIRQG, PIRQH, PIRQA, PIRQB);
|
RCBA_SET_REG_32(D27IR, DIR_ROUTE(PIRQG, PIRQH, PIRQA, PIRQB)),
|
||||||
DIR_ROUTE(D26IR, PIRQE, PIRQF, PIRQG, PIRQH);
|
RCBA_SET_REG_32(D26IR, DIR_ROUTE(PIRQE, PIRQF, PIRQG, PIRQH)),
|
||||||
DIR_ROUTE(D25IR, PIRQA, PIRQB, PIRQC, PIRQD);
|
RCBA_SET_REG_32(D25IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)),
|
||||||
DIR_ROUTE(D22IR, PIRQA, PIRQB, PIRQC, PIRQD);
|
RCBA_SET_REG_32(D22IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)),
|
||||||
|
|
||||||
/* Enable IOAPIC (generic) */
|
|
||||||
RCBA16(OIC) = 0x0100;
|
|
||||||
/* PCH BWG says to read back the IOAPIC enable register */
|
|
||||||
(void) RCBA16(OIC);
|
|
||||||
|
|
||||||
/* Disable unused devices (board specific) */
|
/* Disable unused devices (board specific) */
|
||||||
reg32 = RCBA32(FD);
|
RCBA_RMW_REG_32(FD, ~0, PCH_DISABLE_ALWAYS),
|
||||||
reg32 |= PCH_DISABLE_ALWAYS;
|
|
||||||
RCBA32(FD) = reg32;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME, this function is generic code that should go to sb/... or
|
/* Enable IOAPIC (generic) */
|
||||||
// nb/../early_init.c
|
RCBA_SET_REG_16(OIC, 0x0100),
|
||||||
static void early_pch_init(void)
|
/* PCH BWG says to read back the IOAPIC enable register */
|
||||||
{
|
RCBA_READ_REG_16(OIC),
|
||||||
u8 reg8;
|
|
||||||
|
|
||||||
// reset rtc power status
|
RCBA_END_CONFIG,
|
||||||
reg8 = pci_read_config8(PCH_LPC_DEV, 0xa4);
|
};
|
||||||
reg8 &= ~(1 << 2);
|
|
||||||
pci_write_config8(PCH_LPC_DEV, 0xa4, reg8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(unsigned long bist)
|
void main(unsigned long bist)
|
||||||
{
|
{
|
||||||
int boot_mode = 0;
|
int boot_mode = 0;
|
||||||
|
int wake_from_s3;
|
||||||
int cbmem_was_initted;
|
int cbmem_was_initted;
|
||||||
u32 pm1_cnt;
|
|
||||||
u16 pm1_sts;
|
|
||||||
|
|
||||||
#if CONFIG_COLLECT_TIMESTAMPS
|
#if CONFIG_COLLECT_TIMESTAMPS
|
||||||
tsc_t start_romstage_time;
|
tsc_t start_romstage_time;
|
||||||
|
@ -180,64 +152,26 @@ void main(unsigned long bist)
|
||||||
if (bist == 0)
|
if (bist == 0)
|
||||||
enable_lapic();
|
enable_lapic();
|
||||||
|
|
||||||
pch_enable_lpc();
|
wake_from_s3 = early_pch_init(&mainboard_gpio_map, &rcba_config[0]);
|
||||||
|
|
||||||
/* Enable GPIOs */
|
|
||||||
pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE|1);
|
|
||||||
pci_write_config8(PCH_LPC_DEV, GPIO_CNTL, 0x10);
|
|
||||||
setup_pch_gpios(&mainboard_gpio_map);
|
|
||||||
|
|
||||||
/* Early Console setup */
|
|
||||||
console_init();
|
|
||||||
|
|
||||||
/* Halt if there was a built in self test failure */
|
/* Halt if there was a built in self test failure */
|
||||||
report_bist_failure(bist);
|
report_bist_failure(bist);
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: MCHBAR isn't setup yet. It's setup in
|
|
||||||
* haswell_early_initialization().
|
|
||||||
*/
|
|
||||||
if (MCHBAR16(SSKPD) == 0xCAFE) {
|
|
||||||
printk(BIOS_DEBUG, "soft reset detected\n");
|
|
||||||
boot_mode = 1;
|
|
||||||
|
|
||||||
/* System is not happy after keyboard reset... */
|
|
||||||
printk(BIOS_DEBUG, "Issuing CF9 warm reset\n");
|
|
||||||
outb(0x6, 0xcf9);
|
|
||||||
while (1) {
|
|
||||||
hlt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform some early chipset initialization required
|
/* Perform some early chipset initialization required
|
||||||
* before RAM initialization can work
|
* before RAM initialization can work
|
||||||
*/
|
*/
|
||||||
haswell_early_initialization(HASWELL_MOBILE);
|
haswell_early_initialization(HASWELL_MOBILE);
|
||||||
printk(BIOS_DEBUG, "Back from haswell_early_initialization()\n");
|
printk(BIOS_DEBUG, "Back from haswell_early_initialization()\n");
|
||||||
|
|
||||||
/* Check PM1_STS[15] to see if we are waking from Sx */
|
if (wake_from_s3) {
|
||||||
pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
|
|
||||||
|
|
||||||
/* Read PM1_CNT[12:10] to determine which Sx state */
|
|
||||||
pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT);
|
|
||||||
|
|
||||||
if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) {
|
|
||||||
#if CONFIG_HAVE_ACPI_RESUME
|
#if CONFIG_HAVE_ACPI_RESUME
|
||||||
printk(BIOS_DEBUG, "Resume from S3 detected.\n");
|
printk(BIOS_DEBUG, "Resume from S3 detected.\n");
|
||||||
boot_mode = 2;
|
boot_mode = 2;
|
||||||
/* Clear SLP_TYPE. This will break stage2 but
|
|
||||||
* we care for that when we get there.
|
|
||||||
*/
|
|
||||||
outl(pm1_cnt & ~(7 << 10), DEFAULT_PMBASE + PM1_CNT);
|
|
||||||
#else
|
#else
|
||||||
printk(BIOS_DEBUG, "Resume from S3 detected, but disabled.\n");
|
printk(BIOS_DEBUG, "Resume from S3 detected, but disabled.\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
post_code(0x38);
|
|
||||||
/* Enable SPD ROMs and DDR-III DRAM */
|
|
||||||
enable_smbus();
|
|
||||||
|
|
||||||
/* Prepare USB controller early in S3 resume */
|
/* Prepare USB controller early in S3 resume */
|
||||||
if (boot_mode == 2)
|
if (boot_mode == 2)
|
||||||
enable_usb_bar();
|
enable_usb_bar();
|
||||||
|
@ -247,21 +181,17 @@ void main(unsigned long bist)
|
||||||
#if CONFIG_COLLECT_TIMESTAMPS
|
#if CONFIG_COLLECT_TIMESTAMPS
|
||||||
before_dram_time = rdtsc();
|
before_dram_time = rdtsc();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
report_platform_info();
|
||||||
|
|
||||||
sdram_initialize(&pei_data);
|
sdram_initialize(&pei_data);
|
||||||
|
|
||||||
#if CONFIG_COLLECT_TIMESTAMPS
|
#if CONFIG_COLLECT_TIMESTAMPS
|
||||||
after_dram_time = rdtsc();
|
after_dram_time = rdtsc();
|
||||||
#endif
|
#endif
|
||||||
post_code(0x3b);
|
post_code(0x3b);
|
||||||
/* Perform some initialization that must run before stage2 */
|
|
||||||
early_pch_init();
|
|
||||||
post_code(0x3c);
|
|
||||||
|
|
||||||
/* This should probably go away. Until now it is required
|
intel_early_me_status();
|
||||||
* and mainboard specific
|
|
||||||
*/
|
|
||||||
rcba_config();
|
|
||||||
post_code(0x3d);
|
|
||||||
|
|
||||||
quick_ram_check();
|
quick_ram_check();
|
||||||
post_code(0x3e);
|
post_code(0x3e);
|
||||||
|
|
|
@ -29,20 +29,6 @@
|
||||||
|
|
||||||
static void haswell_setup_bars(void)
|
static void haswell_setup_bars(void)
|
||||||
{
|
{
|
||||||
/* Setting up Southbridge. In the northbridge code. */
|
|
||||||
printk(BIOS_DEBUG, "Setting up static southbridge registers...");
|
|
||||||
pci_write_config32(PCI_DEV(0, 0x1f, 0), RCBA, DEFAULT_RCBA | 1);
|
|
||||||
|
|
||||||
pci_write_config32(PCI_DEV(0, 0x1f, 0), PMBASE, DEFAULT_PMBASE | 1);
|
|
||||||
pci_write_config8(PCI_DEV(0, 0x1f, 0), 0x44 /* ACPI_CNTL */ , 0x80); /* Enable ACPI BAR */
|
|
||||||
|
|
||||||
printk(BIOS_DEBUG, " done.\n");
|
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Disabling Watchdog reboot...");
|
|
||||||
RCBA32(GCS) = RCBA32(GCS) | (1 << 5); /* No reset */
|
|
||||||
outw((1 << 11), DEFAULT_PMBASE | 0x60 | 0x08); /* halt timer */
|
|
||||||
printk(BIOS_DEBUG, " done.\n");
|
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Setting up static northbridge registers...");
|
printk(BIOS_DEBUG, "Setting up static northbridge registers...");
|
||||||
/* Set up all hardcoded northbridge BARs */
|
/* Set up all hardcoded northbridge BARs */
|
||||||
pci_write_config32(PCI_DEV(0, 0x00, 0), EPBAR, DEFAULT_EPBAR | 1);
|
pci_write_config32(PCI_DEV(0, 0x00, 0), EPBAR, DEFAULT_EPBAR | 1);
|
||||||
|
@ -62,14 +48,6 @@ static void haswell_setup_bars(void)
|
||||||
pci_write_config8(PCI_DEV(0, 0x00, 0), PAM6, 0x33);
|
pci_write_config8(PCI_DEV(0, 0x00, 0), PAM6, 0x33);
|
||||||
|
|
||||||
printk(BIOS_DEBUG, " done.\n");
|
printk(BIOS_DEBUG, " done.\n");
|
||||||
|
|
||||||
#if CONFIG_ELOG_BOOT_COUNT
|
|
||||||
/* Increment Boot Counter except when resuming from S3 */
|
|
||||||
if ((inw(DEFAULT_PMBASE + PM1_STS) & WAK_STS) &&
|
|
||||||
((inl(DEFAULT_PMBASE + PM1_CNT) >> 10) & 7) == SLP_TYP_S3)
|
|
||||||
return;
|
|
||||||
boot_count_increment();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void haswell_setup_graphics(void)
|
static void haswell_setup_graphics(void)
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
#include "pei_data.h"
|
#include "pei_data.h"
|
||||||
#include "haswell.h"
|
#include "haswell.h"
|
||||||
|
|
||||||
/* Management Engine is in the southbridge */
|
|
||||||
#include "southbridge/intel/lynxpoint/me.h"
|
|
||||||
#if CONFIG_CHROMEOS
|
#if CONFIG_CHROMEOS
|
||||||
#include <vendorcode/google/chromeos/chromeos.h>
|
#include <vendorcode/google/chromeos/chromeos.h>
|
||||||
#else
|
#else
|
||||||
|
@ -152,12 +150,6 @@ void sdram_initialize(struct pei_data *pei_data)
|
||||||
struct sys_info sysinfo;
|
struct sys_info sysinfo;
|
||||||
unsigned long entry;
|
unsigned long entry;
|
||||||
|
|
||||||
report_platform_info();
|
|
||||||
|
|
||||||
/* Wait for ME to be ready */
|
|
||||||
intel_early_me_init();
|
|
||||||
intel_early_me_uma_size();
|
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Starting UEFI PEI System Agent\n");
|
printk(BIOS_DEBUG, "Starting UEFI PEI System Agent\n");
|
||||||
|
|
||||||
memset(&sysinfo, 0, sizeof(sysinfo));
|
memset(&sysinfo, 0, sizeof(sysinfo));
|
||||||
|
@ -216,8 +208,6 @@ void sdram_initialize(struct pei_data *pei_data)
|
||||||
version >> 24 , (version >> 16) & 0xff,
|
version >> 24 , (version >> 16) & 0xff,
|
||||||
(version >> 8) & 0xff, version & 0xff);
|
(version >> 8) & 0xff, version & 0xff);
|
||||||
|
|
||||||
intel_early_me_status();
|
|
||||||
|
|
||||||
report_memory_config();
|
report_memory_config();
|
||||||
|
|
||||||
/* S3 resume: don't save scrambler seed or MRC data */
|
/* S3 resume: don't save scrambler seed or MRC data */
|
||||||
|
@ -232,7 +222,10 @@ struct cbmem_entry *get_cbmem_toc(void)
|
||||||
|
|
||||||
unsigned long get_top_of_ram(void)
|
unsigned long get_top_of_ram(void)
|
||||||
{
|
{
|
||||||
/* Base of TSEG is top of usable DRAM */
|
/*
|
||||||
|
* Base of TSEG is top of usable DRAM below 4GiB. The register has
|
||||||
|
* 1 MiB alignement.
|
||||||
|
*/
|
||||||
u32 tom = pci_read_config32(PCI_DEV(0,0,0), TSEG);
|
u32 tom = pci_read_config32(PCI_DEV(0,0,0), TSEG);
|
||||||
return (unsigned long) tom;
|
return (unsigned long) tom & ~((1 << 20) - 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ smm-$(CONFIG_SPI_FLASH_SMM) += spi.c
|
||||||
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c
|
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c
|
||||||
smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c me_9.x.c finalize.c
|
smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c me_9.x.c finalize.c
|
||||||
|
|
||||||
romstage-y += early_usb.c early_smbus.c early_me.c me_status.c
|
romstage-y += early_usb.c early_smbus.c early_me.c me_status.c early_pch.c
|
||||||
romstage-$(CONFIG_USBDEBUG) += usb_debug.c
|
romstage-$(CONFIG_USBDEBUG) += usb_debug.c
|
||||||
romstage-y += reset.c early_spi.c
|
romstage-y += reset.c early_spi.c
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Google Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <arch/io.h>
|
||||||
|
#include <arch/romcc_io.h>
|
||||||
|
#include <device/pci_def.h>
|
||||||
|
#include <elog.h>
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#if CONFIG_INTEL_LYNXPOINT_LP
|
||||||
|
#include "lp_gpio.h"
|
||||||
|
#else
|
||||||
|
#include "gpio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void pch_enable_bars(void)
|
||||||
|
{
|
||||||
|
/* Setting up Southbridge. In the northbridge code. */
|
||||||
|
pci_write_config32(PCH_LPC_DEV, RCBA, DEFAULT_RCBA | 1);
|
||||||
|
|
||||||
|
pci_write_config32(PCH_LPC_DEV, PMBASE, DEFAULT_PMBASE | 1);
|
||||||
|
/* Enable ACPI BAR */
|
||||||
|
pci_write_config8(PCH_LPC_DEV, ACPI_CNTL, 0x80);
|
||||||
|
|
||||||
|
pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE|1);
|
||||||
|
|
||||||
|
/* Enable GPIO functionality. */
|
||||||
|
pci_write_config8(PCH_LPC_DEV, GPIO_CNTL, 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pch_generic_setup(void)
|
||||||
|
{
|
||||||
|
u8 reg8;
|
||||||
|
|
||||||
|
printk(BIOS_DEBUG, "Disabling Watchdog reboot...");
|
||||||
|
RCBA32(GCS) = RCBA32(GCS) | (1 << 5); /* No reset */
|
||||||
|
outw((1 << 11), DEFAULT_PMBASE | 0x60 | 0x08); /* halt timer */
|
||||||
|
printk(BIOS_DEBUG, " done.\n");
|
||||||
|
|
||||||
|
// reset rtc power status
|
||||||
|
reg8 = pci_read_config8(PCH_LPC_DEV, GEN_PMCON_3);
|
||||||
|
reg8 &= ~(1 << 2);
|
||||||
|
pci_write_config8(PCH_LPC_DEV, GEN_PMCON_3, reg8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sleep_type_s3(void)
|
||||||
|
{
|
||||||
|
u32 pm1_cnt;
|
||||||
|
u16 pm1_sts;
|
||||||
|
int is_s3 = 0;
|
||||||
|
|
||||||
|
/* Check PM1_STS[15] to see if we are waking from Sx */
|
||||||
|
pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
|
||||||
|
if (pm1_sts & WAK_STS) {
|
||||||
|
/* Read PM1_CNT[12:10] to determine which Sx state */
|
||||||
|
pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT);
|
||||||
|
if (((pm1_cnt >> 10) & 7) == SLP_TYP_S3) {
|
||||||
|
/* Clear SLP_TYPE. */
|
||||||
|
outl(pm1_cnt & ~(7 << 10), DEFAULT_PMBASE + PM1_CNT);
|
||||||
|
is_s3 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return is_s3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pch_enable_lpc(void)
|
||||||
|
{
|
||||||
|
device_t dev = PCH_LPC_DEV;
|
||||||
|
|
||||||
|
/* Set COM1/COM2 decode range */
|
||||||
|
pci_write_config16(dev, LPC_IO_DEC, 0x0010);
|
||||||
|
|
||||||
|
/* Enable SuperIO + COM1 + PS/2 Keyboard/Mouse */
|
||||||
|
u16 lpc_config = CNF1_LPC_EN | CNF2_LPC_EN | COMA_LPC_EN | KBC_LPC_EN;
|
||||||
|
pci_write_config16(dev, LPC_EN, lpc_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pch_config_rcba(const struct rcba_config_instruction *rcba_config)
|
||||||
|
{
|
||||||
|
const struct rcba_config_instruction *rc;
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
rc = rcba_config;
|
||||||
|
while (rc->command != RCBA_COMMAND_END)
|
||||||
|
{
|
||||||
|
if ((rc->command & RCBA_REG_SIZE_MASK) == RCBA_REG_SIZE_16) {
|
||||||
|
switch (rc->command & RCBA_COMMAND_MASK) {
|
||||||
|
case RCBA_COMMAND_SET:
|
||||||
|
RCBA16(rc->reg) = (u16)rc->or_value;
|
||||||
|
break;
|
||||||
|
case RCBA_COMMAND_READ:
|
||||||
|
(void)RCBA16(rc->reg);
|
||||||
|
break;
|
||||||
|
case RCBA_COMMAND_RMW:
|
||||||
|
value = RCBA16(rc->reg);
|
||||||
|
value &= rc->mask;
|
||||||
|
value |= rc->or_value;
|
||||||
|
RCBA16(rc->reg) = (u16)value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (rc->command & RCBA_COMMAND_MASK) {
|
||||||
|
case RCBA_COMMAND_SET:
|
||||||
|
RCBA32(rc->reg) = rc->or_value;
|
||||||
|
break;
|
||||||
|
case RCBA_COMMAND_READ:
|
||||||
|
(void)RCBA32(rc->reg);
|
||||||
|
break;
|
||||||
|
case RCBA_COMMAND_RMW:
|
||||||
|
value = RCBA32(rc->reg);
|
||||||
|
value &= rc->mask;
|
||||||
|
value |= rc->or_value;
|
||||||
|
RCBA32(rc->reg) = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int early_pch_init(const void *gpio_map,
|
||||||
|
const struct rcba_config_instruction *rcba_config)
|
||||||
|
{
|
||||||
|
int wake_from_s3;
|
||||||
|
|
||||||
|
pch_enable_lpc();
|
||||||
|
|
||||||
|
pch_enable_bars();
|
||||||
|
|
||||||
|
#if CONFIG_INTEL_LYNXPOINT_LP
|
||||||
|
setup_pch_lp_gpios(gpio_map);
|
||||||
|
#else
|
||||||
|
setup_pch_gpios(gpio_map);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
console_init();
|
||||||
|
|
||||||
|
pch_generic_setup();
|
||||||
|
|
||||||
|
/* Enable SMBus for reading SPDs. */
|
||||||
|
enable_smbus();
|
||||||
|
|
||||||
|
pch_config_rcba(rcba_config);
|
||||||
|
|
||||||
|
wake_from_s3 = sleep_type_s3();
|
||||||
|
|
||||||
|
#if CONFIG_ELOG_BOOT_COUNT
|
||||||
|
if (!wake_from_s3)
|
||||||
|
boot_count_increment();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Report if we are waking from s3. */
|
||||||
|
return wake_from_s3;
|
||||||
|
}
|
|
@ -102,6 +102,48 @@ void enable_smbus(void);
|
||||||
void enable_usb_bar(void);
|
void enable_usb_bar(void);
|
||||||
int smbus_read_byte(unsigned device, unsigned address);
|
int smbus_read_byte(unsigned device, unsigned address);
|
||||||
int early_spi_read(u32 offset, u32 size, u8 *buffer);
|
int early_spi_read(u32 offset, u32 size, u8 *buffer);
|
||||||
|
|
||||||
|
/* State Machine configuration. */
|
||||||
|
#define RCBA_REG_SIZE_MASK 0x8000
|
||||||
|
#define RCBA_REG_SIZE_16 0x8000
|
||||||
|
#define RCBA_REG_SIZE_32 0x0000
|
||||||
|
#define RCBA_COMMAND_MASK 0x000f
|
||||||
|
#define RCBA_COMMAND_SET 0x0001
|
||||||
|
#define RCBA_COMMAND_READ 0x0002
|
||||||
|
#define RCBA_COMMAND_RMW 0x0003
|
||||||
|
#define RCBA_COMMAND_END 0x0007
|
||||||
|
|
||||||
|
#define RCBA_ENCODE_COMMAND(command_, reg_, mask_, or_value_) \
|
||||||
|
{ .command = command_, \
|
||||||
|
.reg = reg_, \
|
||||||
|
.mask = mask_, \
|
||||||
|
.or_value = or_value_ \
|
||||||
|
}
|
||||||
|
#define RCBA_SET_REG_32(reg_, value_) \
|
||||||
|
RCBA_ENCODE_COMMAND(RCBA_REG_SIZE_32|RCBA_COMMAND_SET, reg_, 0, value_)
|
||||||
|
#define RCBA_READ_REG_32(reg_) \
|
||||||
|
RCBA_ENCODE_COMMAND(RCBA_REG_SIZE_32|RCBA_COMMAND_READ, reg_, 0, 0)
|
||||||
|
#define RCBA_RMW_REG_32(reg_, mask_, or_) \
|
||||||
|
RCBA_ENCODE_COMMAND(RCBA_REG_SIZE_32|RCBA_COMMAND_RMW, reg_, mask_, or_)
|
||||||
|
#define RCBA_SET_REG_16(reg_, value_) \
|
||||||
|
RCBA_ENCODE_COMMAND(RCBA_REG_SIZE_16|RCBA_COMMAND_SET, reg_, 0, value_)
|
||||||
|
#define RCBA_READ_REG_16(reg_) \
|
||||||
|
RCBA_ENCODE_COMMAND(RCBA_REG_SIZE_16|RCBA_COMMAND_READ, reg_, 0, 0)
|
||||||
|
#define RCBA_RMW_REG_16(reg_, mask_, or_) \
|
||||||
|
RCBA_ENCODE_COMMAND(RCBA_REG_SIZE_16|RCBA_COMMAND_RMW, reg_, mask_, or_)
|
||||||
|
#define RCBA_END_CONFIG \
|
||||||
|
RCBA_ENCODE_COMMAND(RCBA_COMMAND_END, 0, 0, 0)
|
||||||
|
|
||||||
|
struct rcba_config_instruction
|
||||||
|
{
|
||||||
|
u16 command;
|
||||||
|
u16 reg;
|
||||||
|
u32 mask;
|
||||||
|
u32 or_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
int early_pch_init(const void *gpio_map,
|
||||||
|
const struct rcba_config_instruction *rcba_config);
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* get GPIO pin value
|
* get GPIO pin value
|
||||||
|
@ -460,9 +502,9 @@ unsigned get_gpios(const int *gpio_num_array);
|
||||||
#define SOFT_RESET_CTRL 0x38f4
|
#define SOFT_RESET_CTRL 0x38f4
|
||||||
#define SOFT_RESET_DATA 0x38f8
|
#define SOFT_RESET_DATA 0x38f8
|
||||||
|
|
||||||
#define DIR_ROUTE(x,a,b,c,d) \
|
#define DIR_ROUTE(a,b,c,d) \
|
||||||
RCBA32(x) = (((d) << DIR_IDR) | ((c) << DIR_ICR) | \
|
(((d) << DIR_IDR) | ((c) << DIR_ICR) | \
|
||||||
((b) << DIR_IBR) | ((a) << DIR_IAR))
|
((b) << DIR_IBR) | ((a) << DIR_IAR))
|
||||||
|
|
||||||
#define RC 0x3400 /* 32bit */
|
#define RC 0x3400 /* 32bit */
|
||||||
#define HPTC 0x3404 /* 32bit */
|
#define HPTC 0x3404 /* 32bit */
|
||||||
|
|
Loading…
Reference in New Issue