baytrail: add initial support
The initial Bay Trail code is intended to support
the mobile and desktop version of Bay Trail. This support
can train memory and execute through ramstage. However,
the resource allocation is not curently handled correctly.
The MRC cache parameters are successfully saved and reused
after the initial cold boot.
BUG=chrome-os-partner:22292
BRANCH=None
TEST=Built and booted on a reference board through ramstage.
Change-Id: I238ede326802aad272c6cca39d7ad4f161d813f5
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/168387
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: http://review.coreboot.org/4847
Tested-by: build bot (Jenkins)
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
diff --git a/src/soc/intel/baytrail/romstage/Makefile.inc b/src/soc/intel/baytrail/romstage/Makefile.inc
new file mode 100644
index 0000000..188ce44
--- /dev/null
+++ b/src/soc/intel/baytrail/romstage/Makefile.inc
@@ -0,0 +1,4 @@
+cpu_incs += $(src)/soc/intel/baytrail/romstage/cache_as_ram.inc
+romstage-y += romstage.c
+romstage-y += raminit.c
+romstage-$(CONFIG_ENABLE_BUILTIN_COM1) += uart.c
diff --git a/src/soc/intel/baytrail/romstage/cache_as_ram.inc b/src/soc/intel/baytrail/romstage/cache_as_ram.inc
new file mode 100644
index 0000000..920fbe4
--- /dev/null
+++ b/src/soc/intel/baytrail/romstage/cache_as_ram.inc
@@ -0,0 +1,280 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2007-2008 coresystems GmbH
+ *
+ * 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 <cpu/x86/stack.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/post_code.h>
+#include <cbmem.h>
+
+/* The full cache-as-ram size includes the cache-as-ram portion from coreboot
+ * and the space used by the reference code. These 2 values combined should
+ * be a power of 2 because the MTRR setup assumes that. */
+#define CACHE_AS_RAM_SIZE \
+ (CONFIG_DCACHE_RAM_SIZE + CONFIG_DCACHE_RAM_MRC_VAR_SIZE)
+#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE
+
+/* Enough room to cache CAR_TILE_SIZE starting at MRC_BIN_ADDRESS */
+#define CACHE_MRC_BASE (CONFIG_MRC_BIN_ADDRESS)
+#define CACHE_MRC_MASK (~(CONFIG_CAR_TILE_SIZE - 1))
+
+#define CPU_PHYSMASK_HI ((1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1)
+
+#define NoEvictMod_MSR 0x2e0
+#define BBL_CR_CTL3_MSR 0x11e
+#define MCG_CAP_MSR 0x179
+
+ /* Save the BIST result. */
+ movl %eax, %ebp
+
+cache_as_ram:
+ post_code(0x20)
+
+ /* Send INIT IPI to all excluding ourself. */
+ movl $0x000C4500, %eax
+ movl $0xFEE00300, %esi
+ movl %eax, (%esi)
+
+ /* All CPUs need to be in Wait for SIPI state */
+wait_for_sipi:
+ movl (%esi), %eax
+ bt $12, %eax
+ jc wait_for_sipi
+
+ post_code(0x21)
+ /* Configure the default memory type to uncacheable as well as disable
+ * fixed and variable range mtrrs. */
+ movl $MTRRdefType_MSR, %ecx
+ rdmsr
+ andl $(~0x00000cff), %eax
+ wrmsr
+
+ post_code(0x22)
+ /* Zero the variable MTRRs. */
+ movl $MCG_CAP_MSR, %ecx
+ rdmsr
+ movzx %al, %ebx
+ /* First variable MTRR. */
+ movl $0x200, %ecx
+ xorl %eax, %eax
+ xorl %edx, %edx
+ 1:
+ wrmsr
+ inc %ecx
+ dec %ebx
+ jnz 1b
+
+ /* Zero out all fixed range and variable range MTRRs. */
+ movl $fixed_mtrr_table, %esi
+ movl $((fixed_mtrr_table_end - fixed_mtrr_table) / 2), %edi
+ xorl %eax, %eax
+ xorl %edx, %edx
+ 1:
+ movw (%esi), %bx
+ movzx %bx, %ecx
+ wrmsr
+ add $2, %esi
+ dec %edi
+ jnz 1b
+
+ post_code(0x23)
+ /* Set Cache-as-RAM base address. */
+ movl $(MTRRphysBase_MSR(0)), %ecx
+ movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
+ xorl %edx, %edx
+ wrmsr
+
+ post_code(0x24)
+ /* Set Cache-as-RAM mask. */
+ movl $(MTRRphysMask_MSR(0)), %ecx
+ movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax
+ movl $CPU_PHYSMASK_HI, %edx
+ wrmsr
+
+ post_code(0x25)
+ /* Set Cache-as-RAM base address. */
+ movl $(MTRRphysBase_MSR(1)), %ecx
+ movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax
+ xorl %edx, %edx
+ wrmsr
+
+ movl $(MTRRphysMask_MSR(1)), %ecx
+ movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax
+ movl $CPU_PHYSMASK_HI, %edx
+ wrmsr
+
+ /* Enable MTRR. */
+ movl $MTRRdefType_MSR, %ecx
+ rdmsr
+ orl $MTRRdefTypeEn, %eax
+ wrmsr
+
+ post_code(0x26)
+
+ /* Enable the L2 cache. */
+ movl $BBL_CR_CTL3_MSR, %ecx
+ rdmsr
+ orl $0x100, %eax
+ wrmsr
+
+ post_code(0x27)
+
+ /* Enable cache (CR0.CD = 0, CR0.NW = 0). */
+ movl %cr0, %eax
+ andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
+ invd
+ movl %eax, %cr0
+
+ /* enable the 'no eviction' mode */
+ movl $NoEvictMod_MSR, %ecx
+ rdmsr
+ orl $1, %eax
+ wrmsr
+
+ post_code(0x28)
+
+ /* Clear the cache memory region. This will also fill up the cache */
+ movl $CACHE_AS_RAM_BASE, %esi
+ movl %esi, %edi
+ movl $(CACHE_AS_RAM_SIZE / 4), %ecx
+ xorl %eax, %eax
+ rep stosl
+
+ /* enable no evict mode */
+ movl $NoEvictMod_MSR, %ecx
+ rdmsr
+ orl $2, %eax
+ wrmsr
+
+ post_code(0x29)
+
+ /* Setup the stack. */
+ movl $(CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE), %eax
+ movl %eax, %esp
+
+ /* Restore the BIST result. */
+ movl %ebp, %eax
+ movl %esp, %ebp
+ pushl %eax
+
+before_romstage:
+ post_code(0x2a)
+ /* Call romstage.c main function. */
+ call romstage_main
+ /* Save return value from romstage_main. It contains the stack to use
+ * after cache-as-ram is torn down. It also contains the information
+ * for setting up MTRRs. */
+ movl %eax, %ebx
+
+ post_code(0x2b)
+
+ /* Disable cache. */
+ movl %cr0, %eax
+ orl $CR0_CacheDisable, %eax
+ movl %eax, %cr0
+
+ post_code(0x2c)
+
+ /* Disable MTRR. */
+ movl $MTRRdefType_MSR, %ecx
+ rdmsr
+ andl $(~MTRRdefTypeEn), %eax
+ wrmsr
+
+ invd
+
+ post_code(0x2d)
+
+ /* Disable the no eviction run state */
+ movl $NoEvictMod_MSR, %ecx
+ rdmsr
+ andl $~2, %eax
+ wrmsr
+
+ /* Disable the no eviction mode */
+ rdmsr
+ andl $~1, %eax
+ wrmsr
+
+ post_code(0x2e)
+
+ /* Setup stack as indicated by return value from ramstage_main(). */
+ movl %ebx, %esp
+
+ /* Get number of MTRRs. */
+ popl %ebx
+ movl $MTRRphysBase_MSR(0), %ecx
+1:
+ testl %ebx, %ebx
+ jz 1f
+
+ /* Low 32 bits of MTRR base. */
+ popl %eax
+ /* Upper 32 bits of MTRR base. */
+ popl %edx
+ /* Write MTRR base. */
+ wrmsr
+ inc %ecx
+ /* Low 32 bits of MTRR mask. */
+ popl %eax
+ /* Upper 32 bits of MTRR mask. */
+ popl %edx
+ /* Write MTRR mask. */
+ wrmsr
+ inc %ecx
+
+ dec %ebx
+ jmp 1b
+1:
+ post_code(0x2f)
+
+ /* And enable cache again after setting MTRRs. */
+ movl %cr0, %eax
+ andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax
+ movl %eax, %cr0
+
+ post_code(0x30)
+
+ /* Enable MTRR. */
+ movl $MTRRdefType_MSR, %ecx
+ rdmsr
+ orl $MTRRdefTypeEn, %eax
+ wrmsr
+
+ post_code(0x31)
+
+__main:
+ post_code(POST_PREPARE_RAMSTAGE)
+ cld /* Clear direction flag. */
+ call romstage_after_car
+
+.Lhlt:
+ post_code(POST_DEAD_CODE)
+ hlt
+ jmp .Lhlt
+
+/* Fixed MTRRs */
+fixed_mtrr_table:
+ .word 0x250, 0x258, 0x259
+ .word 0x268, 0x269, 0x26A
+ .word 0x26B, 0x26C, 0x26D
+ .word 0x26E, 0x26F
+fixed_mtrr_table_end:
+
diff --git a/src/soc/intel/baytrail/romstage/raminit.c b/src/soc/intel/baytrail/romstage/raminit.c
new file mode 100644
index 0000000..68836d3
--- /dev/null
+++ b/src/soc/intel/baytrail/romstage/raminit.c
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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 <stddef.h>
+#include <arch/io.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <device/pci_def.h>
+#include <baytrail/gpio.h>
+#include <baytrail/mrc_cache.h>
+#include <baytrail/iomap.h>
+#include <baytrail/pci_devs.h>
+#include <baytrail/romstage.h>
+
+
+static void enable_smbus(void)
+{
+ uint32_t reg;
+ const uint32_t smbus_dev = PCI_DEV(0, SMBUS_DEV, SMBUS_FUNC);
+
+ /* SMBus I/O BAR */
+ reg = SMBUS_BASE_ADDRESS | 2;
+ pci_write_config32(smbus_dev, PCI_BASE_ADDRESS_4, reg);
+ /* Enable decode of I/O space. */
+ reg = pci_read_config16(smbus_dev, PCI_COMMAND);
+ reg |= 0x1;
+ pci_write_config16(smbus_dev, PCI_COMMAND, reg);
+ /* Enable Host Controller */
+ reg = pci_read_config8(smbus_dev, 0x40);
+ reg |= 1;
+ pci_write_config8(smbus_dev, 0x40, reg);
+
+ /* Configure pads to be used for SMBus */
+ score_select_func(PCU_SMB_CLK_PAD, 1);
+ score_select_func(PCU_SMB_DATA_PAD, 1);
+}
+
+void raminit(struct mrc_params *mp, int prev_sleep_state)
+{
+ int ret;
+ mrc_wrapper_entry_t mrc_entry;
+ const struct mrc_saved_data *cache;
+
+ /* Fill in default entries. */
+ mp->version = MRC_PARAMS_VER;
+ mp->console_out = &console_tx_byte;
+ mp->prev_sleep_state = prev_sleep_state;
+
+ if (!mrc_cache_get_current(&cache)) {
+ mp->saved_data_size = cache->size;
+ mp->saved_data = &cache->data[0];
+ } else {
+ printk(BIOS_DEBUG, "No MRC cache found.\n");
+ }
+
+ mrc_entry = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "mrc.bin", 0xab,
+ NULL);
+
+ if (mrc_entry == NULL) {
+ printk(BIOS_DEBUG, "Couldn't find mrc.bin\n");
+ return;
+ }
+ if (mp->mainboard.dram_info_location == DRAM_INFO_SPD_SMBUS)
+ enable_smbus();
+
+ ret = mrc_entry(mp);
+
+ cbmem_initialize_empty();
+
+ printk(BIOS_DEBUG, "MRC Wrapper returned %d\n", ret);
+ printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", mp->data_to_save,
+ mp->data_to_save_size);
+
+ if (mp->data_to_save != NULL && mp->data_to_save_size > 0)
+ mrc_cache_stash_data(mp->data_to_save, mp->data_to_save_size);
+}
diff --git a/src/soc/intel/baytrail/romstage/romstage.c b/src/soc/intel/baytrail/romstage/romstage.c
new file mode 100644
index 0000000..d353899
--- /dev/null
+++ b/src/soc/intel/baytrail/romstage/romstage.c
@@ -0,0 +1,218 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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 <stddef.h>
+#include <arch/cpu.h>
+#include <arch/io.h>
+#include <arch/cbfs.h>
+#include <arch/stages.h>
+#include <console/console.h>
+#include <cbmem.h>
+#include <cpu/x86/mtrr.h>
+#include <romstage_handoff.h>
+#include <baytrail/gpio.h>
+#include <baytrail/iomap.h>
+#include <baytrail/iosf.h>
+#include <baytrail/lpc.h>
+#include <baytrail/pci_devs.h>
+#include <baytrail/romstage.h>
+
+/* The cache-as-ram assembly file calls romstage_main() after setting up
+ * cache-as-ram. romstage_main() will then call the mainboards's
+ * mainboard_romstage_entry() function. That function then calls
+ * romstage_common() below. The reason for the back and forth is to provide
+ * common entry point from cache-as-ram while still allowing for code sharing.
+ * Because we can't use global variables the stack is used for allocations --
+ * thus the need to call back and forth. */
+
+static void *setup_stack_and_mttrs(void);
+
+static void program_base_addresses(void)
+{
+ uint32_t reg;
+ const uint32_t lpc_dev = PCI_DEV(0, LPC_DEV, LPC_FUNC);
+
+ /* Memory Mapped IO registers. */
+ reg = PMC_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, PBASE, reg);
+ reg = IO_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, IOBASE, reg);
+ reg = ILB_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, IBASE, reg);
+ reg = SPI_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, SBASE, reg);
+ reg = MPHY_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, MPBASE, reg);
+ reg = RCBA_BASE_ADDRESS | 1;
+ pci_write_config32(lpc_dev, RCBA, reg);
+
+ /* IO Port Registers. */
+ reg = ACPI_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, ABASE, reg);
+ reg = GPIO_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, GBASE, reg);
+}
+
+/* Entry from cache-as-ram.inc. */
+void * asmlinkage romstage_main(unsigned long bist)
+{
+ /* Call into mainboard. */
+ mainboard_romstage_entry(bist);
+
+ return setup_stack_and_mttrs();
+}
+
+/* Entry from the mainboard. */
+void romstage_common(const struct romstage_params *params)
+{
+ struct romstage_handoff *handoff;
+
+ program_base_addresses();
+
+ byt_config_com1_and_enable();
+
+ console_init();
+
+ /* Initialize RAM */
+ raminit(params->mrc_params, 5);
+
+ handoff = romstage_handoff_find_or_add();
+ if (handoff != NULL)
+ handoff->s3_resume = 0;
+ else
+ printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
+
+}
+
+static void open_up_spi(void)
+{
+ const uintptr_t sbase = SPI_BASE_ADDRESS;
+
+ /* Disable generating SMI when setting WPD bit. */
+ write32(sbase + 0xf8, read32(sbase + 0xf8) & ~(1 << 7));
+ /* Disable the SMM-only BIOS write and set WPD bit. */
+ write32(sbase + 0xfc, 1 | (read32(sbase + 0xfc) & ~(1 << 5)));
+}
+
+void asmlinkage romstage_after_car(void)
+{
+ /* Allow BIOS to program SPI part. */
+ open_up_spi();
+
+ /* Load the ramstage. */
+ copy_and_run();
+ while (1);
+}
+
+static inline uint32_t *stack_push(u32 *stack, u32 value)
+{
+ stack = &stack[-1];
+ *stack = value;
+ return stack;
+}
+
+/* Romstage needs quite a bit of stack for decompressing images since the lzma
+ * lib keeps its state on the stack during romstage. */
+static unsigned long choose_top_of_stack(void)
+{
+ unsigned long stack_top;
+ const unsigned long romstage_ram_stack_size = 0x5000;
+
+ /* cbmem_add() does a find() before add(). */
+ stack_top = (unsigned long)cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK,
+ romstage_ram_stack_size);
+ stack_top += romstage_ram_stack_size;
+ return stack_top;
+}
+
+/* setup_stack_and_mttrs() determines the stack to use after
+ * cache-as-ram is torn down as well as the MTRR settings to use. */
+static void *setup_stack_and_mttrs(void)
+{
+ unsigned long top_of_stack;
+ int num_mtrrs;
+ uint32_t *slot;
+ uint32_t mtrr_mask_upper;
+ uint32_t top_of_ram;
+
+ /* Top of stack needs to be aligned to a 4-byte boundary. */
+ top_of_stack = choose_top_of_stack() & ~3;
+ slot = (void *)top_of_stack;
+ num_mtrrs = 0;
+
+ /* The upper bits of the MTRR mask need to set according to the number
+ * of physical address bits. */
+ mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1;
+
+ /* The order for each MTRR is value then base with upper 32-bits of
+ * each value coming before the lower 32-bits. The reasoning for
+ * this ordering is to create a stack layout like the following:
+ * +0: Number of MTRRs
+ * +4: MTRR base 0 31:0
+ * +8: MTRR base 0 63:32
+ * +12: MTRR mask 0 31:0
+ * +16: MTRR mask 0 63:32
+ * +20: MTRR base 1 31:0
+ * +24: MTRR base 1 63:32
+ * +28: MTRR mask 1 31:0
+ * +32: MTRR mask 1 63:32
+ */
+
+ /* Cache the ROM as WP just below 4GiB. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRRphysMaskValid);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
+ num_mtrrs++;
+
+ /* Cache RAM as WB from 0 -> CONFIG_RAMTOP. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, 0 | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ top_of_ram = (uint32_t)cbmem_top();
+ /* Cache 8MiB below the top of ram. The top of ram under 4GiB is the
+ * start of the TSEG region. It is required to be 8MiB aligned. Set
+ * this area as cacheable so it can be used later for ramstage before
+ * setting up the entire RAM as cacheable. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, (top_of_ram - (8 << 20)) | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ /* Cache 8MiB at the top of ram. Top of ram is where the TSEG
+ * region resides. However, it is not restricted to SMM mode until
+ * SMM has been relocated. By setting the region to cacheable it
+ * provides faster access when relocating the SMM handler as well
+ * as using the TSEG region for other purposes. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, top_of_ram | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ /* Save the number of MTRRs to setup. Return the stack location
+ * pointing to the number of MTRRs. */
+ slot = stack_push(slot, num_mtrrs);
+
+ return slot;
+}
diff --git a/src/soc/intel/baytrail/romstage/uart.c b/src/soc/intel/baytrail/romstage/uart.c
new file mode 100644
index 0000000..dee3be9
--- /dev/null
+++ b/src/soc/intel/baytrail/romstage/uart.c
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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 <arch/io.h>
+#include <baytrail/gpio.h>
+#include <baytrail/iomap.h>
+#include <baytrail/lpc.h>
+#include <baytrail/pci_devs.h>
+#include <baytrail/romstage.h>
+
+void byt_config_com1_and_enable(void)
+{
+ uint32_t reg;
+
+ /* Enable the UART hardware for COM1. */
+ reg = 1;
+ pci_write_config32(PCI_DEV(0, LPC_DEV, 0), UART_CONT, reg);
+
+ /* Set up the pads to select the UART function. RXD and TXD are
+ * 0x520 and 0x530, respectively. */
+ write32(IO_BASE_ADDRESS + 0x520, read32(IO_BASE_ADDRESS + 0x520) | 1);
+ write32(IO_BASE_ADDRESS + 0x530, read32(IO_BASE_ADDRESS + 0x530) | 1);
+}