diff options
author | Patrick Georgi <patrick.georgi@secunet.com> | 2012-11-06 11:05:38 +0100 |
---|---|---|
committer | Patrick Georgi <patrick@georgi-clan.de> | 2012-11-27 09:17:05 +0100 |
commit | 021b7033fb578258844bf8ecad9f2d34b16b674b (patch) | |
tree | 836aea10485b00d3e93a8af99e73ba25f85a2aec /src/mainboard/roda/rk9/romstage.c | |
parent | e72a8a3047c535bda03aecce2eca134608d1a93c (diff) | |
download | coreboot-021b7033fb578258844bf8ecad9f2d34b16b674b.tar.xz |
roda/rk9: New mainboard
Roda RK9 is a notebook based on the GM45/ICH9 platform using DDR3 memory.
http://roda-computer.com/products/notebooks/rk9/
Tested with various Linux versions, known to work:
- 2x4GB RAM
- IGD
- HD Audio
- UHCI, EHCI
- AHCI
- NIC
- PCI
- PS/2 keyboard
- serial console
- ACPI lid switch
- ACPI battery/AC events
- power off, reboot
Change-Id: I7299dccbff2eea3544363fdd4f49f05aa3dae7bc
Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com>
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: http://review.coreboot.org/1691
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Diffstat (limited to 'src/mainboard/roda/rk9/romstage.c')
-rw-r--r-- | src/mainboard/roda/rk9/romstage.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/mainboard/roda/rk9/romstage.c b/src/mainboard/roda/rk9/romstage.c new file mode 100644 index 0000000000..c6ca078dc1 --- /dev/null +++ b/src/mainboard/roda/rk9/romstage.c @@ -0,0 +1,211 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 secunet Security Networks AG + * + * 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 + */ + +// __PRE_RAM__ means: use "unsigned" for device, not a struct. + +#include <stdint.h> +#include <string.h> +#include <arch/io.h> +#include <arch/romcc_io.h> +#include <cpu/x86/lapic.h> +#include <cpu/x86/msr.h> +#include <cpu/x86/tsc.h> +#include <cbmem.h> +#include <lib.h> +#include <pc80/mc146818rtc.h> +#include <console/console.h> +#include <southbridge/intel/i82801ix/i82801ix.h> +#include <northbridge/intel/gm45/gm45.h> +#include <superio/smsc/lpc47n227/early_serial.c> + +#define LPC_DEV PCI_DEV(0, 0x1f, 0) +#define SERIAL_DEV PNP_DEV(0x2e, LPC47N227_SP1) + +static void default_southbridge_gpio_setup(void) +{ + /* Enable GPIOs [31:0]. */ + outl(0x197e7dfe, DEFAULT_GPIOBASE + 0x00); + /* Set input/output mode [31:0] (0 == out, 1 == in). */ + outl(0xe0ea43fe, DEFAULT_GPIOBASE + 0x04); + /* Set gpio levels [31:0]. orig: 0x01140800 (~SATA0, ~SATA1, GSM, BT, + WLAN, ~ANTMUX, ~GPIO12, + ~SUSPWR, SMBALERT) */ + outl(0x00000800, DEFAULT_GPIOBASE + 0x0c); + + /* Disable blink [31:0]. */ + outl(0x00000000, DEFAULT_GPIOBASE + 0x18); + /* Set input inversion [31:0]. */ + outl(0x00000182, DEFAULT_GPIOBASE + 0x2c); + + /* Enable GPIOs [60:32]. */ + outl(0x130300fe, DEFAULT_GPIOBASE + 0x30); + /* Set input/output mode [60:32] (0 == out, 1 == in). */ + outl(0x0e55ffb0, DEFAULT_GPIOBASE + 0x34); + /* Set gpio levels [60:32]. orig: 0x10020046 (LNKALERT, ~ATAIO, + DMITERM, TXT, ~CLKSATA, + GPS, AUDIO) */ + outl(0x10020042, DEFAULT_GPIOBASE + 0x38); +} + +static void early_lpc_setup(void) +{ + /* Set up SuperIO LPC forwards */ + + /* Configure serial IRQs.*/ + pci_write_config8(LPC_DEV, D31F0_SERIRQ_CNTL, 0xd0); + /* Map COMa on 0x3f8, COMb on 0x2f8. */ + pci_write_config16(LPC_DEV, D31F0_LPC_IODEC, 0x0010); + /* Enable COMa, COMb, Kbd, SuperIO at 0x2e, MCs at 0x4e and 0x62/66. */ + pci_write_config16(LPC_DEV, D31F0_LPC_EN, 0x3c03); +} + +static void default_superio_gpio_setup(void) +{ + /* Original settings: + idx 30 31 32 33 34 35 36 37 38 39 + val 60 00 00 40 00 ff 00 e0 00 80 + def 00 00 00 00 00 00 00 00 00 80 + + Values: + GP1 GP2 GP3 GP4 + fd 17 88 14 + */ + const device_t sio = PNP_DEV(0x2e, 0); + + /* Enter super-io's configuration state. */ + pnp_enter_conf_state(sio); + + /* Set lpc47n227's runtime register block's base address. */ + pnp_write_config(sio, 0x30, 0x600 >> 4); + + /* Set GP23 to alternate function. */ + pnp_write_config(sio, 0x33, 0x40); + + /* Set GP30 - GP37 to output mode: COM control */ + pnp_write_config(sio, 0x35, 0xff); + + /* Set GP45 - GP47 to output mode. */ + pnp_write_config(sio, 0x37, 0xe0); + + /* Set nIO_PME to open drain. */ + pnp_write_config(sio, 0x39, 0x80); + + /* Exit configuration state. */ + pnp_exit_conf_state(sio); + + + /* Enable decoding of 0x600-0x60f through lpc. */ + pci_write_config32(LPC_DEV, D31F0_GEN1_DEC, 0x000c0601); + + /* Set GPIO output values: */ + outb(0x88, 0x600 + 0xb + 3); /* GP30 - GP37 */ + outb(0x10, 0x600 + 0xb + 4); /* GP40 - GP47 */ +} + +void main(unsigned long bist) +{ + sysinfo_t sysinfo; + int s3resume = 0; + u16 reg16; + + /* basic northbridge setup, including MMCONF BAR */ + gm45_early_init(); + + if (bist == 0) + enable_lapic(); + + /* First, run everything needed for console output. */ + i82801ix_early_init(); + early_lpc_setup(); + default_superio_gpio_setup(); + lpc47n227_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); + console_init(); + printk(BIOS_DEBUG, "running main(bist = %lu)\n", bist); + + reg16 = pci_read_config16(LPC_DEV, D31F0_GEN_PMCON_3); + pci_write_config16(LPC_DEV, D31F0_GEN_PMCON_3, reg16); + if ((MCHBAR16(SSKPD_MCHBAR) == 0xCAFE) && !(reg16 & (1 << 9))) { + printk(BIOS_DEBUG, "soft reset detected, rebooting properly\n"); + gm45_early_reset(); + } + + default_southbridge_gpio_setup(); + + /* ASPM related setting, set early by original BIOS. */ + DMIBAR16(0x204) &= ~(3 << 10); + + /* Check for S3 resume. */ + const u32 pm1_cnt = inl(DEFAULT_PMBASE + 0x04); + if (((pm1_cnt >> 10) & 7) == 5) { +#if CONFIG_HAVE_ACPI_RESUME + printk(BIOS_DEBUG, "Resume from S3 detected.\n"); + s3resume = 1; + /* Clear SLP_TYPE. This will break stage2 but + * we care for that when we get there. + */ + outl(pm1_cnt & ~(7 << 10), DEFAULT_PMBASE + 0x04); +#else + printk(BIOS_DEBUG, "Resume from S3 detected, but disabled.\n"); +#endif + } + + /* RAM initialization */ + enter_raminit_or_reset(); + get_gmch_info(&sysinfo); + raminit(&sysinfo, s3resume); + + raminit_thermal(&sysinfo); + init_igd(&sysinfo, 0, 1); /* Enable IGD, disable PEG. */ + init_pm(&sysinfo); + + i82801ix_dmi_setup(); + gm45_late_init(sysinfo.stepping); + i82801ix_dmi_poll_vc1(); + + MCHBAR16(SSKPD_MCHBAR) = 0xCAFE; + + init_iommu(); + +#if CONFIG_HAVE_ACPI_RESUME + /* Start address of high memory tables */ + unsigned long high_ram_base = get_top_of_ram() - HIGH_MEMORY_SIZE; + + /* If there is no high memory area, we didn't boot before, so + * this is not a resume. In that case we just create the cbmem toc. + */ + if (s3resume && cbmem_reinit((u64)high_ram_base)) { + void *resume_backup_memory = cbmem_find(CBMEM_ID_RESUME); + + /* copy 1MB - 64K to high tables ram_base to prevent memory corruption + * through stage 2. We could keep stuff like stack and heap in high tables + * memory completely, but that's a wonderful clean up task for another + * day. + */ + if (resume_backup_memory) + memcpy(resume_backup_memory, (void *)CONFIG_RAMBASE, HIGH_MEMORY_SAVE); + + /* Magic for S3 resume */ + pci_write_config32(PCI_DEV(0, 0, 0), D0F0_SKPD, SKPAD_ACPI_S3_MAGIC); + } +#endif + printk(BIOS_SPEW, "exit main()\n"); +} + |