Merge branch 'master' of git://git.denx.de/u-boot-x86
authorTom Rini <trini@ti.com>
Mon, 26 Jan 2015 22:44:49 +0000 (17:44 -0500)
committerTom Rini <trini@ti.com>
Mon, 26 Jan 2015 22:44:49 +0000 (17:44 -0500)
46 files changed:
arch/x86/cpu/coreboot/Makefile
arch/x86/cpu/coreboot/coreboot.c
arch/x86/cpu/coreboot/ipchecksum.c [deleted file]
arch/x86/cpu/coreboot/tables.c
arch/x86/cpu/cpu.c
arch/x86/cpu/ivybridge/Kconfig
arch/x86/cpu/ivybridge/Makefile
arch/x86/cpu/ivybridge/mrccache.c [new file with mode: 0644]
arch/x86/cpu/ivybridge/sdram.c
arch/x86/cpu/mtrr.c
arch/x86/cpu/start16.S
arch/x86/dts/chromebook_link.dts
arch/x86/include/asm/arch-coreboot/ipchecksum.h [deleted file]
arch/x86/include/asm/arch-ivybridge/mrccache.h [new file with mode: 0644]
arch/x86/include/asm/global_data.h
arch/x86/include/asm/mtrr.h
arch/x86/include/asm/u-boot-x86.h
arch/x86/lib/init_helpers.c
arch/x86/lib/interrupts.c
common/board_f.c
configs/chromebook_link_defconfig
drivers/bios_emulator/atibios.c
drivers/bios_emulator/include/x86emu/debug.h
drivers/bios_emulator/x86emu/ops.c
drivers/block/ahci.c
drivers/pci/pci_auto.c
drivers/pci/pci_rom.c
drivers/pci/pci_tegra.c
drivers/rtc/mc146818.c
drivers/spi/ich.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/cfb_console.c
drivers/video/vesa_fb.c [new file with mode: 0644]
drivers/video/x86_fb.c [deleted file]
include/configs/chromebook_link.h
include/configs/x86-common.h
include/fdtdec.h
include/net.h
include/pci.h
include/pci_rom.h
include/rtc.h
include/vbe.h
lib/fdtdec.c
net/Makefile
net/checksum.c [new file with mode: 0644]

index 35e6cdd..b6e870a 100644 (file)
@@ -16,7 +16,6 @@
 obj-y += car.o
 obj-y += coreboot.o
 obj-y += tables.o
-obj-y += ipchecksum.o
 obj-y += sdram.o
 obj-y += timestamp.o
 obj-$(CONFIG_PCI) += pci.o
index 6d06d5a..4cdd0d4 100644 (file)
@@ -99,3 +99,8 @@ void panic_puts(const char *str)
        while (*str)
                NS16550_putc(port, *str++);
 }
+
+int misc_init_r(void)
+{
+       return 0;
+}
diff --git a/arch/x86/cpu/coreboot/ipchecksum.c b/arch/x86/cpu/coreboot/ipchecksum.c
deleted file mode 100644 (file)
index 3340872..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * This file is part of the libpayload project.
- *
- * It has originally been taken from the FreeBSD project.
- *
- * Copyright (c) 2001 Charles Mott <cm@linktel.net>
- * Copyright (c) 2008 coresystems GmbH
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-#include <asm/arch/ipchecksum.h>
-
-unsigned short ipchksum(const void *vptr, unsigned long nbytes)
-{
-       int sum, oddbyte;
-       const unsigned short *ptr = vptr;
-
-       sum = 0;
-       while (nbytes > 1) {
-               sum += *ptr++;
-               nbytes -= 2;
-       }
-       if (nbytes == 1) {
-               oddbyte = 0;
-               ((u8 *)&oddbyte)[0] = *(u8 *) ptr;
-               ((u8 *)&oddbyte)[1] = 0;
-               sum += oddbyte;
-       }
-       sum = (sum >> 16) + (sum & 0xffff);
-       sum += (sum >> 16);
-       return ~sum;
-}
index 92b7528..2b12b19 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 #include <common.h>
-#include <asm/arch/ipchecksum.h>
+#include <net.h>
 #include <asm/arch/sysinfo.h>
 #include <asm/arch/tables.h>
 
@@ -131,11 +131,11 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
                return 0;
 
        /* Make sure the checksums match. */
-       if (ipchksum((u16 *) header, sizeof(*header)) != 0)
+       if (!ip_checksum_ok(header, sizeof(*header)))
                return -1;
 
-       if (ipchksum((u16 *) (ptr + sizeof(*header)),
-                    header->table_bytes) != header->table_checksum)
+       if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) !=
+           header->table_checksum)
                return -1;
 
        /* Now, walk the tables. */
index 30e5069..ed7905c 100644 (file)
@@ -223,6 +223,11 @@ static bool has_cpuid(void)
        return flag_is_changeable_p(X86_EFLAGS_ID);
 }
 
+static bool has_mtrr(void)
+{
+       return cpuid_edx(0x00000001) & (1 << 12) ? true : false;
+}
+
 static int build_vendor_name(char *vendor_name)
 {
        struct cpuid_result result;
@@ -318,6 +323,8 @@ int x86_cpu_init_f(void)
                gd->arch.x86_model = c.x86_model;
                gd->arch.x86_mask = c.x86_mask;
                gd->arch.x86_device = cpu.device;
+
+               gd->arch.has_mtrr = has_mtrr();
        }
 
        return 0;
index afca957..e4595be 100644 (file)
@@ -26,20 +26,6 @@ config CACHE_MRC_SIZE_KB
        int
        default 256
 
-config MRC_CACHE_BASE
-       hex
-       default 0xff800000
-
-config MRC_CACHE_LOCATION
-       hex
-       depends on !CHROMEOS
-       default 0x1ec000
-
-config MRC_CACHE_SIZE
-       hex
-       depends on !CHROMEOS
-       default 0x10000
-
 config DCACHE_RAM_BASE
        hex
        default 0xff7f0000
@@ -64,20 +50,6 @@ config CACHE_MRC_SIZE_KB
        int
        default 512
 
-config MRC_CACHE_BASE
-       hex
-       default 0xff800000
-
-config MRC_CACHE_LOCATION
-       hex
-       depends on !CHROMEOS
-       default 0x370000
-
-config MRC_CACHE_SIZE
-       hex
-       depends on !CHROMEOS
-       default 0x10000
-
 config DCACHE_RAM_BASE
        hex
        default 0xff7e0000
index 0c7efae..3576b83 100644 (file)
@@ -14,6 +14,7 @@ obj-y += lpc.o
 obj-y += me_status.o
 obj-y += model_206ax.o
 obj-y += microcode_intel.o
+obj-y += mrccache.o
 obj-y += northbridge.o
 obj-y += pch.o
 obj-y += pci.o
diff --git a/arch/x86/cpu/ivybridge/mrccache.c b/arch/x86/cpu/ivybridge/mrccache.c
new file mode 100644 (file)
index 0000000..0f1a64b
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/mrccache.c
+ *
+ * Copyright (C) 2014 Google Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <net.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <asm/arch/mrccache.h>
+#include <asm/arch/sandybridge.h>
+
+static struct mrc_data_container *next_mrc_block(
+       struct mrc_data_container *mrc_cache)
+{
+       /* MRC data blocks are aligned within the region */
+       u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->data_size;
+       if (mrc_size & (MRC_DATA_ALIGN - 1UL)) {
+               mrc_size &= ~(MRC_DATA_ALIGN - 1UL);
+               mrc_size += MRC_DATA_ALIGN;
+       }
+
+       u8 *region_ptr = (u8 *)mrc_cache;
+       region_ptr += mrc_size;
+       return (struct mrc_data_container *)region_ptr;
+}
+
+static int is_mrc_cache(struct mrc_data_container *cache)
+{
+       return cache && (cache->signature == MRC_DATA_SIGNATURE);
+}
+
+/*
+ * Find the largest index block in the MRC cache. Return NULL if none is
+ * found.
+ */
+struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry)
+{
+       struct mrc_data_container *cache, *next;
+       ulong base_addr, end_addr;
+       uint id;
+
+       base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
+       end_addr = base_addr + entry->length;
+       cache = NULL;
+
+       /* Search for the last filled entry in the region */
+       for (id = 0, next = (struct mrc_data_container *)base_addr;
+            is_mrc_cache(next);
+            id++) {
+               cache = next;
+               next = next_mrc_block(next);
+               if ((ulong)next >= end_addr)
+                       break;
+       }
+
+       if (id-- == 0) {
+               debug("%s: No valid MRC cache found.\n", __func__);
+               return NULL;
+       }
+
+       /* Verify checksum */
+       if (cache->checksum != compute_ip_checksum(cache->data,
+                                                  cache->data_size)) {
+               printf("%s: MRC cache checksum mismatch\n", __func__);
+               return NULL;
+       }
+
+       debug("%s: picked entry %u from cache block\n", __func__, id);
+
+       return cache;
+}
+
+/**
+ * find_next_mrc_cache() - get next cache entry
+ *
+ * @entry:     MRC cache flash area
+ * @cache:     Entry to start from
+ *
+ * @return next cache entry if found, NULL if we got to the end
+ */
+static struct mrc_data_container *find_next_mrc_cache(struct fmap_entry *entry,
+               struct mrc_data_container *cache)
+{
+       ulong base_addr, end_addr;
+
+       base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
+       end_addr = base_addr + entry->length;
+
+       cache = next_mrc_block(cache);
+       if ((ulong)cache >= end_addr) {
+               /* Crossed the boundary */
+               cache = NULL;
+               debug("%s: no available entries found\n", __func__);
+       } else {
+               debug("%s: picked next entry from cache block at %p\n",
+                     __func__, cache);
+       }
+
+       return cache;
+}
+
+int mrccache_update(struct spi_flash *sf, struct fmap_entry *entry,
+                   struct mrc_data_container *cur)
+{
+       struct mrc_data_container *cache;
+       ulong offset;
+       ulong base_addr;
+       int ret;
+
+       /* Find the last used block */
+       base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
+       debug("Updating MRC cache data\n");
+       cache = mrccache_find_current(entry);
+       if (cache && (cache->data_size == cur->data_size) &&
+           (!memcmp(cache, cur, cache->data_size + sizeof(*cur)))) {
+               debug("MRC data in flash is up to date. No update\n");
+               return -EEXIST;
+       }
+
+       /* Move to the next block, which will be the first unused block */
+       if (cache)
+               cache = find_next_mrc_cache(entry, cache);
+
+       /*
+        * If we have got to the end, erase the entire mrc-cache area and start
+        * again at block 0.
+        */
+       if (!cache) {
+               debug("Erasing the MRC cache region of %x bytes at %x\n",
+                     entry->length, entry->offset);
+
+               ret = spi_flash_erase(sf, entry->offset, entry->length);
+               if (ret) {
+                       debug("Failed to erase flash region\n");
+                       return ret;
+               }
+               cache = (struct mrc_data_container *)base_addr;
+       }
+
+       /* Write the data out */
+       offset = (ulong)cache - base_addr + entry->offset;
+       debug("Write MRC cache update to flash at %lx\n", offset);
+       ret = spi_flash_write(sf, offset, cur->data_size + sizeof(*cur), cur);
+       if (ret) {
+               debug("Failed to write to SPI flash\n");
+               return ret;
+       }
+
+       return 0;
+}
index 9504735..4963448 100644 (file)
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
+#include <net.h>
+#include <rtc.h>
+#include <spi.h>
+#include <spi_flash.h>
 #include <asm/processor.h>
 #include <asm/gpio.h>
 #include <asm/global_data.h>
 #include <asm/mtrr.h>
 #include <asm/pci.h>
 #include <asm/arch/me.h>
+#include <asm/arch/mrccache.h>
 #include <asm/arch/pei_data.h>
 #include <asm/arch/pch.h>
 #include <asm/post.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define CMOS_OFFSET_MRC_SEED           152
+#define CMOS_OFFSET_MRC_SEED_S3                156
+#define CMOS_OFFSET_MRC_SEED_CHK       160
+
 /*
  * This function looks for the highest region of memory lower than 4GB which
  * has enough space for U-Boot where U-Boot is aligned on a page boundary.
@@ -80,6 +89,202 @@ void dram_init_banksize(void)
        }
 }
 
+static int get_mrc_entry(struct spi_flash **sfp, struct fmap_entry *entry)
+{
+       const void *blob = gd->fdt_blob;
+       int node, spi_node, mrc_node;
+       int upto;
+
+       /* Find the flash chip within the SPI controller node */
+       upto = 0;
+       spi_node = fdtdec_next_alias(blob, "spi", COMPAT_INTEL_ICH_SPI, &upto);
+       if (spi_node < 0)
+               return -ENOENT;
+       node = fdt_first_subnode(blob, spi_node);
+       if (node < 0)
+               return -ECHILD;
+
+       /* Find the place where we put the MRC cache */
+       mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
+       if (mrc_node < 0)
+               return -EPERM;
+
+       if (fdtdec_read_fmap_entry(blob, mrc_node, "rm-mrc-cache", entry))
+               return -EINVAL;
+
+       if (sfp) {
+               *sfp = spi_flash_probe_fdt(blob, node, spi_node);
+               if (!*sfp)
+                       return -EBADF;
+       }
+
+       return 0;
+}
+
+static int read_seed_from_cmos(struct pei_data *pei_data)
+{
+       u16 c1, c2, checksum, seed_checksum;
+
+       /*
+        * Read scrambler seeds from CMOS RAM. We don't want to store them in
+        * SPI flash since they change on every boot and that would wear down
+        * the flash too much. So we store these in CMOS and the large MRC
+        * data in SPI flash.
+        */
+       pei_data->scrambler_seed = rtc_read32(CMOS_OFFSET_MRC_SEED);
+       debug("Read scrambler seed    0x%08x from CMOS 0x%02x\n",
+             pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED);
+
+       pei_data->scrambler_seed_s3 = rtc_read32(CMOS_OFFSET_MRC_SEED_S3);
+       debug("Read S3 scrambler seed 0x%08x from CMOS 0x%02x\n",
+             pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3);
+
+       /* Compute seed checksum and compare */
+       c1 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed,
+                                sizeof(u32));
+       c2 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed_s3,
+                                sizeof(u32));
+       checksum = add_ip_checksums(sizeof(u32), c1, c2);
+
+       seed_checksum = rtc_read8(CMOS_OFFSET_MRC_SEED_CHK);
+       seed_checksum |= rtc_read8(CMOS_OFFSET_MRC_SEED_CHK + 1) << 8;
+
+       if (checksum != seed_checksum) {
+               debug("%s: invalid seed checksum\n", __func__);
+               pei_data->scrambler_seed = 0;
+               pei_data->scrambler_seed_s3 = 0;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int prepare_mrc_cache(struct pei_data *pei_data)
+{
+       struct mrc_data_container *mrc_cache;
+       struct fmap_entry entry;
+       int ret;
+
+       ret = read_seed_from_cmos(pei_data);
+       if (ret)
+               return ret;
+       ret = get_mrc_entry(NULL, &entry);
+       if (ret)
+               return ret;
+       mrc_cache = mrccache_find_current(&entry);
+       if (!mrc_cache)
+               return -ENOENT;
+
+       /*
+        * TODO(sjg@chromium.org): Skip this for now as it causes boot
+        * problems
+        */
+       if (0) {
+               pei_data->mrc_input = mrc_cache->data;
+               pei_data->mrc_input_len = mrc_cache->data_size;
+       }
+       debug("%s: at %p, size %x checksum %04x\n", __func__,
+             pei_data->mrc_input, pei_data->mrc_input_len,
+             mrc_cache->checksum);
+
+       return 0;
+}
+
+static int build_mrc_data(struct mrc_data_container **datap)
+{
+       struct mrc_data_container *data;
+       int orig_len;
+       int output_len;
+
+       orig_len = gd->arch.mrc_output_len;
+       output_len = ALIGN(orig_len, 16);
+       data = malloc(output_len + sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+       data->signature = MRC_DATA_SIGNATURE;
+       data->data_size = output_len;
+       data->reserved = 0;
+       memcpy(data->data, gd->arch.mrc_output, orig_len);
+
+       /* Zero the unused space in aligned buffer. */
+       if (output_len > orig_len)
+               memset(data->data + orig_len, 0, output_len - orig_len);
+
+       data->checksum = compute_ip_checksum(data->data, output_len);
+       *datap = data;
+
+       return 0;
+}
+
+static int write_seeds_to_cmos(struct pei_data *pei_data)
+{
+       u16 c1, c2, checksum;
+
+       /* Save the MRC seed values to CMOS */
+       rtc_write32(CMOS_OFFSET_MRC_SEED, pei_data->scrambler_seed);
+       debug("Save scrambler seed    0x%08x to CMOS 0x%02x\n",
+             pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED);
+
+       rtc_write32(CMOS_OFFSET_MRC_SEED_S3, pei_data->scrambler_seed_s3);
+       debug("Save s3 scrambler seed 0x%08x to CMOS 0x%02x\n",
+             pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3);
+
+       /* Save a simple checksum of the seed values */
+       c1 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed,
+                                sizeof(u32));
+       c2 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed_s3,
+                                sizeof(u32));
+       checksum = add_ip_checksums(sizeof(u32), c1, c2);
+
+       rtc_write8(CMOS_OFFSET_MRC_SEED_CHK, checksum & 0xff);
+       rtc_write8(CMOS_OFFSET_MRC_SEED_CHK + 1, (checksum >> 8) & 0xff);
+
+       return 0;
+}
+
+static int sdram_save_mrc_data(void)
+{
+       struct mrc_data_container *data;
+       struct fmap_entry entry;
+       struct spi_flash *sf;
+       int ret;
+
+       if (!gd->arch.mrc_output_len)
+               return 0;
+       debug("Saving %d bytes of MRC output data to SPI flash\n",
+             gd->arch.mrc_output_len);
+
+       ret = get_mrc_entry(&sf, &entry);
+       if (ret)
+               goto err_entry;
+       ret = build_mrc_data(&data);
+       if (ret)
+               goto err_data;
+       ret = mrccache_update(sf, &entry, data);
+       if (!ret)
+               debug("Saved MRC data with checksum %04x\n", data->checksum);
+
+       free(data);
+err_data:
+       spi_flash_free(sf);
+err_entry:
+       if (ret)
+               debug("%s: Failed: %d\n", __func__, ret);
+       return ret;
+}
+
+/* Use this hook to save our SDRAM parameters */
+int misc_init_r(void)
+{
+       int ret;
+
+       ret = sdram_save_mrc_data();
+       if (ret)
+               printf("Unable to save MRC data: %d\n", ret);
+
+       return 0;
+}
+
 static const char *const ecc_decoder[] = {
        "inactive",
        "active on IO",
@@ -142,6 +347,11 @@ static asmlinkage void console_tx_byte(unsigned char byte)
 #endif
 }
 
+static int recovery_mode_enabled(void)
+{
+       return false;
+}
+
 /**
  * Find the PEI executable in the ROM and execute it.
  *
@@ -166,6 +376,17 @@ int sdram_initialise(struct pei_data *pei_data)
 
        debug("Starting UEFI PEI System Agent\n");
 
+       /*
+        * Do not pass MRC data in for recovery mode boot,
+        * Always pass it in for S3 resume.
+        */
+       if (!recovery_mode_enabled() ||
+           pei_data->boot_mode == PEI_BOOT_RESUME) {
+               ret = prepare_mrc_cache(pei_data);
+               if (ret)
+                       debug("prepare_mrc_cache failed: %d\n", ret);
+       }
+
        /* If MRC data is not found we cannot continue S3 resume. */
        if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) {
                debug("Giving up in sdram_initialize: No MRC data\n");
@@ -216,6 +437,8 @@ int sdram_initialise(struct pei_data *pei_data)
        debug("System Agent Version %d.%d.%d Build %d\n",
              version >> 24 , (version >> 16) & 0xff,
              (version >> 8) & 0xff, version & 0xff);
+       debug("MCR output data length %#x at %p\n", pei_data->mrc_output_len,
+             pei_data->mrc_output);
 
        /*
         * Send ME init done for SandyBridge here.  This is done inside the
@@ -231,6 +454,36 @@ int sdram_initialise(struct pei_data *pei_data)
        post_system_agent_init(pei_data);
        report_memory_config();
 
+       /* S3 resume: don't save scrambler seed or MRC data */
+       if (pei_data->boot_mode != PEI_BOOT_RESUME) {
+               /*
+                * This will be copied to SDRAM in reserve_arch(), then written
+                * to SPI flash in sdram_save_mrc_data()
+                */
+               gd->arch.mrc_output = (char *)pei_data->mrc_output;
+               gd->arch.mrc_output_len = pei_data->mrc_output_len;
+               ret = write_seeds_to_cmos(pei_data);
+               if (ret)
+                       debug("Failed to write seeds to CMOS: %d\n", ret);
+       }
+
+       return 0;
+}
+
+int reserve_arch(void)
+{
+       u16 checksum;
+
+       checksum = compute_ip_checksum(gd->arch.mrc_output,
+                                      gd->arch.mrc_output_len);
+       debug("Saving %d bytes for MRC output data, checksum %04x\n",
+             gd->arch.mrc_output_len, checksum);
+       gd->start_addr_sp -= gd->arch.mrc_output_len;
+       memcpy((void *)gd->start_addr_sp, gd->arch.mrc_output,
+              gd->arch.mrc_output_len);
+       gd->arch.mrc_output = (char *)gd->start_addr_sp;
+       gd->start_addr_sp &= ~0xf;
+
        return 0;
 }
 
index d5a825d..5d36b3e 100644 (file)
 #include <asm/msr.h>
 #include <asm/mtrr.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* Prepare to adjust MTRRs */
 void mtrr_open(struct mtrr_state *state)
 {
+       if (!gd->arch.has_mtrr)
+               return;
+
        state->enable_cache = dcache_status();
 
        if (state->enable_cache)
@@ -31,6 +36,9 @@ void mtrr_open(struct mtrr_state *state)
 /* Clean up after adjusting MTRRs, and enable them */
 void mtrr_close(struct mtrr_state *state)
 {
+       if (!gd->arch.has_mtrr)
+               return;
+
        wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
        if (state->enable_cache)
                enable_caches();
@@ -43,6 +51,9 @@ int mtrr_commit(bool do_caches)
        uint64_t mask;
        int i;
 
+       if (!gd->arch.has_mtrr)
+               return -ENOSYS;
+
        mtrr_open(&state);
        for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) {
                mask = ~(req->size - 1);
@@ -64,6 +75,9 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size)
        struct mtrr_request *req;
        uint64_t mask;
 
+       if (!gd->arch.has_mtrr)
+               return -ENOSYS;
+
        if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
                return -ENOSPC;
        req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
index 9550502..826e2b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  U-boot - x86 Startup Code
+ *  U-Boot - x86 Startup Code
  *
  * (C) Copyright 2008-2011
  * Graeme Russ, <graeme.russ@gmail.com>
@@ -28,7 +28,7 @@ start16:
        movl    $GD_FLG_COLD_BOOT, %ebx
 
        xorl    %eax, %eax
-       movl    %eax, %cr3    /* Invalidate TLB */
+       movl    %eax, %cr3      /* Invalidate TLB */
 
        /* Turn off cache (this might require a 486-class CPU) */
        movl    %cr0, %eax
@@ -49,7 +49,7 @@ o32 cs        lgdt    gdt_ptr
        jmp     ff
 ff:
 
-       /* Finally restore BIST and jump to the 32bit initialization code */
+       /* Finally restore BIST and jump to the 32-bit initialization code */
        movw    $code32start, %ax
        movw    %ax, %bp
        movl    %ecx, %eax
@@ -64,17 +64,17 @@ idt_ptr:
        .word   0               /* limit */
        .long   0               /* base */
 
-/*
- * The following Global Descriptor Table is just enough to get us into
- * 'Flat Protected Mode' - It will be discarded as soon as the final
- * GDT is setup in a safe location in RAM
- */
+       /*
       * The following Global Descriptor Table is just enough to get us into
       * 'Flat Protected Mode' - It will be discarded as soon as the final
       * GDT is setup in a safe location in RAM
       */
 gdt_ptr:
        .word   0x1f            /* limit (31 bytes = 4 GDT entries - 1) */
        .long   BOOT_SEG + gdt  /* base */
 
-/* Some CPUs are picky about GDT alignment... */
-.align 16
+       /* Some CPUs are picky about GDT alignment... */
+       .align  16
 gdt:
        /*
         * The GDT table ...
index 9490b16..45ada61 100644 (file)
@@ -7,6 +7,10 @@
        model = "Google Link";
        compatible = "google,link", "intel,celeron-ivybridge";
 
+       aliases {
+               spi0 = "/spi";
+       };
+
        config {
               silent_console = <0>;
        };
        spi {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "intel,ich9";
+               compatible = "intel,ich-spi";
                spi-flash@0 {
+                       #size-cells = <1>;
+                       #address-cells = <1>;
                        reg = <0>;
                        compatible = "winbond,w25q64", "spi-flash";
                        memory-map = <0xff800000 0x00800000>;
+                       rw-mrc-cache {
+                               label = "rw-mrc-cache";
+                               /* Alignment: 4k (for updating) */
+                               reg = <0x003e0000 0x00010000>;
+                               type = "wiped";
+                               wipe-value = [ff];
+                       };
                };
        };
 
diff --git a/arch/x86/include/asm/arch-coreboot/ipchecksum.h b/arch/x86/include/asm/arch-coreboot/ipchecksum.h
deleted file mode 100644 (file)
index 1d73b4d..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * This file is part of the libpayload project.
- *
- * It has originally been taken from the FreeBSD project.
- *
- * Copyright (c) 2001 Charles Mott <cm@linktel.net>
- * Copyright (c) 2008 coresystems GmbH
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _COREBOOT_IPCHECKSUM_H
-#define _COREBOOT_IPCHECKSUM_H
-
-unsigned short ipchksum(const void *vptr, unsigned long nbytes);
-
-#endif
diff --git a/arch/x86/include/asm/arch-ivybridge/mrccache.h b/arch/x86/include/asm/arch-ivybridge/mrccache.h
new file mode 100644 (file)
index 0000000..968b2ef
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_MRCCACHE_H
+#define _ASM_ARCH_MRCCACHE_H
+
+#define MRC_DATA_ALIGN         0x1000
+#define MRC_DATA_SIGNATURE     (('M' << 0) | ('R' << 8) | ('C' << 16) | \
+                                       ('D'<<24))
+
+__packed struct mrc_data_container {
+       u32     signature;      /* "MRCD" */
+       u32     data_size;      /* Size of the 'data' field */
+       u32     checksum;       /* IP style checksum */
+       u32     reserved;       /* For header alignment */
+       u8      data[0];        /* Variable size, platform/run time dependent */
+};
+
+struct fmap_entry;
+struct spi_flash;
+
+/**
+ * mrccache_find_current() - find the latest MRC cache record
+ *
+ * This searches the MRC cache region looking for the latest record to use
+ * for setting up SDRAM
+ *
+ * @entry:     Information about the position and size of the MRC cache
+ * @return pointer to latest record, or NULL if none
+ */
+struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry);
+
+/**
+ * mrccache_update() - update the MRC cache with a new record
+ *
+ * This writes a new record to the end of the MRC cache. If the new record is
+ * the same as the latest record then the write is skipped
+ *
+ * @sf:                SPI flash to write to
+ * @entry:     Position and size of MRC cache in SPI flash
+ * @cur:       Record to write
+ * @return 0 if updated, -EEXIST if the record is the same as the latest
+ * record, other error if SPI write failed
+ */
+int mrccache_update(struct spi_flash *sf, struct fmap_entry *entry,
+                   struct mrc_data_container *cur);
+
+#endif
index 24e3052..5ee06eb 100644 (file)
@@ -44,11 +44,11 @@ struct mtrr_request {
 
 /* Architecture-specific global data */
 struct arch_global_data {
-       struct global_data *gd_addr;            /* Location of Global Data */
-       uint8_t  x86;                   /* CPU family */
-       uint8_t  x86_vendor;            /* CPU vendor */
-       uint8_t  x86_model;
-       uint8_t  x86_mask;
+       struct global_data *gd_addr;    /* Location of Global Data */
+       uint8_t x86;                    /* CPU family */
+       uint8_t x86_vendor;             /* CPU vendor */
+       uint8_t x86_model;
+       uint8_t x86_mask;
        uint32_t x86_device;
        uint64_t tsc_base;              /* Initial value returned by rdtsc() */
        uint32_t tsc_base_kclocks;      /* Initial tsc as a kclocks value */
@@ -60,10 +60,14 @@ struct arch_global_data {
        const struct pch_gpio_map *gpio_map;    /* board GPIO map */
        struct memory_info meminfo;     /* Memory information */
 #ifdef CONFIG_HAVE_FSP
-       void    *hob_list;              /* FSP HOB list */
+       void *hob_list;                 /* FSP HOB list */
 #endif
        struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
        int mtrr_req_count;
+       int has_mtrr;
+       /* MRC training data to save for the next boot */
+       char *mrc_output;
+       unsigned int mrc_output_len;
 };
 
 #endif
index 3c11740..fda4eae 100644 (file)
@@ -65,7 +65,6 @@ void mtrr_open(struct mtrr_state *state);
  *
  * @state:     Structure from mtrr_open()
  */
-/*  */
 void mtrr_close(struct mtrr_state *state);
 
 /**
@@ -76,6 +75,8 @@ void mtrr_close(struct mtrr_state *state);
  * @type:      Requested type (MTRR_TYPE_)
  * @start:     Start address
  * @size:      Size
+ *
+ * @return:    0 on success, non-zero on failure
  */
 int mtrr_add_request(int type, uint64_t start, uint64_t size);
 
@@ -86,6 +87,8 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size);
  * It must be called with caches disabled.
  *
  * @do_caches: true if caches are currently on
+ *
+ * @return:    0 on success, non-zero on failure
  */
 int mtrr_commit(bool do_caches);
 
index 36145cb..b98afa8 100644 (file)
@@ -70,4 +70,6 @@ uint64_t timer_get_tsc(void);
 
 void quick_ram_check(void);
 
+#define PCI_VGA_RAM_IMAGE_START                0xc0000
+
 #endif /* _U_BOOT_I386_H_ */
index fc211d9..5097ca2 100644 (file)
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <fdtdec.h>
 #include <spi.h>
+#include <asm/errno.h>
 #include <asm/mtrr.h>
 #include <asm/sections.h>
 
@@ -71,7 +72,8 @@ int init_cache_f_r(void)
        int ret;
 
        ret = mtrr_commit(false);
-       if (ret)
+       /* If MTRR MSR is not implemented by the processor, just ignore it */
+       if (ret && ret != -ENOSYS)
                return ret;
 #endif
        /* Initialise the CPU cache(s) */
index 6bb22d2..146ad11 100644 (file)
@@ -130,7 +130,7 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        printf("Interrupt-Information:\n");
        printf("Nr  Routine   Arg       Count\n");
 
-       for (irq = 0; irq <= CONFIG_SYS_NUM_IRQS; irq++) {
+       for (irq = 0; irq < CONFIG_SYS_NUM_IRQS; irq++) {
                if (irq_handlers[irq].handler != NULL) {
                        printf("%02d  %08lx  %08lx  %d\n",
                                        irq,
index 3a4b32c..215108b 100644 (file)
@@ -807,6 +807,12 @@ static int initf_dm(void)
        return 0;
 }
 
+/* Architecture-specific memory reservation */
+__weak int reserve_arch(void)
+{
+       return 0;
+}
+
 static init_fnc_t init_sequence_f[] = {
 #ifdef CONFIG_SANDBOX
        setup_ram_buf,
@@ -970,6 +976,7 @@ static init_fnc_t init_sequence_f[] = {
        setup_machine,
        reserve_global_data,
        reserve_fdt,
+       reserve_arch,
        reserve_stacks,
        setup_dram_config,
        show_dram_config,
index e956835..2f0c714 100644 (file)
@@ -6,6 +6,6 @@ CONFIG_OF_SEPARATE=y
 CONFIG_DEFAULT_DEVICE_TREE="chromebook_link"
 CONFIG_HAVE_MRC=y
 CONFIG_SMM_TSEG_SIZE=0x800000
-CONFIG_VIDEO_X86=y
+CONFIG_VIDEO_VESA=y
 CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
 CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
index 93b815c..7ea5fa6 100644 (file)
@@ -62,40 +62,158 @@ static u32 saveBaseAddress14;
 static u32 saveBaseAddress18;
 static u32 saveBaseAddress20;
 
-static void atibios_set_vesa_mode(RMREGS *regs, int vesa_mode,
-                                 struct vbe_mode_info *mode_info)
+/* Addres im memory of VBE region */
+const int vbe_offset = 0x2000;
+
+static const void *bios_ptr(const void *buf, BE_VGAInfo *vga_info,
+                           u32 x86_dword_ptr)
+{
+       u32 seg_ofs, flat;
+
+       seg_ofs = le32_to_cpu(x86_dword_ptr);
+       flat = ((seg_ofs & 0xffff0000) >> 12) | (seg_ofs & 0xffff);
+       if (flat >= 0xc0000)
+               return vga_info->BIOSImage + flat - 0xc0000;
+       else
+               return buf + (flat - vbe_offset);
+}
+
+static int atibios_debug_mode(BE_VGAInfo *vga_info, RMREGS *regs,
+                             int vesa_mode, struct vbe_mode_info *mode_info)
+{
+       void *buffer = (void *)(M.mem_base + vbe_offset);
+       u16 buffer_seg = (((unsigned long)vbe_offset) >> 4) & 0xff00;
+       u16 buffer_adr = ((unsigned long)vbe_offset) & 0xffff;
+       struct vesa_mode_info *vm;
+       struct vbe_info *info;
+       const u16 *modes_bios, *ptr;
+       u16 *modes;
+       int size;
+
+       debug("VBE: Getting information\n");
+       regs->e.eax = VESA_GET_INFO;
+       regs->e.esi = buffer_seg;
+       regs->e.edi = buffer_adr;
+       info = buffer;
+       memset(info, '\0', sizeof(*info));
+       strcpy(info->signature, "VBE2");
+       BE_int86(0x10, regs, regs);
+       if (regs->e.eax != 0x4f) {
+               debug("VESA_GET_INFO: error %x\n", regs->e.eax);
+               return -ENOSYS;
+       }
+       debug("version %x\n", le16_to_cpu(info->version));
+       debug("oem '%s'\n", (char *)bios_ptr(buffer, vga_info,
+                                            info->oem_string_ptr));
+       debug("vendor '%s'\n", (char *)bios_ptr(buffer, vga_info,
+                                               info->vendor_name_ptr));
+       debug("product '%s'\n", (char *)bios_ptr(buffer, vga_info,
+                                                info->product_name_ptr));
+       debug("rev '%s'\n", (char *)bios_ptr(buffer, vga_info,
+                                            info->product_rev_ptr));
+       modes_bios = bios_ptr(buffer, vga_info, info->modes_ptr);
+       debug("Modes: ");
+       for (ptr = modes_bios; *ptr != 0xffff; ptr++)
+               debug("%x ", le16_to_cpu(*ptr));
+       debug("\nmemory %dMB\n", le16_to_cpu(info->total_memory) >> 4);
+       size = (ptr - modes_bios) * sizeof(u16) + 2;
+       modes = malloc(size);
+       if (!modes)
+               return -ENOMEM;
+       memcpy(modes, modes_bios, size);
+
+       regs->e.eax = VESA_GET_CUR_MODE;
+       BE_int86(0x10, regs, regs);
+       if (regs->e.eax != 0x4f) {
+               debug("VESA_GET_CUR_MODE: error %x\n", regs->e.eax);
+               return -ENOSYS;
+       }
+       debug("Current mode %x\n", regs->e.ebx);
+
+       for (ptr = modes; *ptr != 0xffff; ptr++) {
+               int mode = le16_to_cpu(*ptr);
+               bool linear_ok;
+               int attr;
+
+               break;
+               debug("Mode %x: ", mode);
+               memset(buffer, '\0', sizeof(struct vbe_mode_info));
+               regs->e.eax = VESA_GET_MODE_INFO;
+               regs->e.ebx = 0;
+               regs->e.ecx = mode;
+               regs->e.edx = 0;
+               regs->e.esi = buffer_seg;
+               regs->e.edi = buffer_adr;
+               BE_int86(0x10, regs, regs);
+               if (regs->e.eax != 0x4f) {
+                       debug("VESA_GET_MODE_INFO: error %x\n", regs->e.eax);
+                       continue;
+               }
+               memcpy(mode_info->mode_info_block, buffer,
+                      sizeof(struct vesa_mode_info));
+               mode_info->valid = true;
+               vm = &mode_info->vesa;
+               attr = le16_to_cpu(vm->mode_attributes);
+               linear_ok = attr & 0x80;
+               debug("res %d x %d, %d bpp, mm %d, (Linear %s, attr %02x)\n",
+                     le16_to_cpu(vm->x_resolution),
+                     le16_to_cpu(vm->y_resolution),
+                     vm->bits_per_pixel, vm->memory_model,
+                     linear_ok ? "OK" : "not available",
+                     attr);
+               debug("\tRGB pos=%d,%d,%d, size=%d,%d,%d\n",
+                     vm->red_mask_pos, vm->green_mask_pos, vm->blue_mask_pos,
+                     vm->red_mask_size, vm->green_mask_size,
+                     vm->blue_mask_size);
+       }
+
+       return 0;
+}
+
+static int atibios_set_vesa_mode(RMREGS *regs, int vesa_mode,
+                                struct vbe_mode_info *mode_info)
 {
+       void *buffer = (void *)(M.mem_base + vbe_offset);
+       u16 buffer_seg = (((unsigned long)vbe_offset) >> 4) & 0xff00;
+       u16 buffer_adr = ((unsigned long)vbe_offset) & 0xffff;
+       struct vesa_mode_info *vm;
+
        debug("VBE: Setting VESA mode %#04x\n", vesa_mode);
-       /* request linear framebuffer mode */
-       vesa_mode |= (1 << 14);
-       /* request clearing of framebuffer */
-       vesa_mode &= ~(1 << 15);
        regs->e.eax = VESA_SET_MODE;
        regs->e.ebx = vesa_mode;
+       /* request linear framebuffer mode and don't clear display */
+       regs->e.ebx |= (1 << 14) | (1 << 15);
        BE_int86(0x10, regs, regs);
+       if (regs->e.eax != 0x4f) {
+               debug("VESA_SET_MODE: error %x\n", regs->e.eax);
+               return -ENOSYS;
+       }
 
-       int offset = 0x2000;
-       void *buffer = (void *)(M.mem_base + offset);
-
-       u16 buffer_seg = (((unsigned long)offset) >> 4) & 0xff00;
-       u16 buffer_adr = ((unsigned long)offset) & 0xffff;
+       memset(buffer, '\0', sizeof(struct vbe_mode_info));
+       debug("VBE: Geting info for VESA mode %#04x\n", vesa_mode);
        regs->e.eax = VESA_GET_MODE_INFO;
-       regs->e.ebx = 0;
        regs->e.ecx = vesa_mode;
-       regs->e.edx = 0;
        regs->e.esi = buffer_seg;
        regs->e.edi = buffer_adr;
        BE_int86(0x10, regs, regs);
+       if (regs->e.eax != 0x4f) {
+               debug("VESA_GET_MODE_INFO: error %x\n", regs->e.eax);
+               return -ENOSYS;
+       }
+
        memcpy(mode_info->mode_info_block, buffer,
-              sizeof(struct vbe_mode_info));
+               sizeof(struct vesa_mode_info));
        mode_info->valid = true;
+       mode_info->video_mode = vesa_mode;
+       vm = &mode_info->vesa;
+       vm->x_resolution = le16_to_cpu(vm->x_resolution);
+       vm->y_resolution = le16_to_cpu(vm->y_resolution);
+       vm->bytes_per_scanline = le16_to_cpu(vm->bytes_per_scanline);
+       vm->phys_base_ptr = le32_to_cpu(vm->phys_base_ptr);
+       vm->mode_attributes = le16_to_cpu(vm->mode_attributes);
+       debug("VBE: Init complete\n");
 
-       vesa_mode |= (1 << 14);
-       /* request clearing of framebuffer */
-       vesa_mode &= ~(1 << 15);
-       regs->e.eax = VESA_SET_MODE;
-       regs->e.ebx = vesa_mode;
-       BE_int86(0x10, regs, regs);
+       return 0;
 }
 
 /****************************************************************************
@@ -132,6 +250,9 @@ static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo *vga_info,
        /*Cleanup and exit*/
        BE_getVGA(vga_info);
 
+       /* Useful for debugging */
+       if (0)
+               atibios_debug_mode(vga_info, &regs, vesa_mode, mode_info);
        if (vesa_mode != -1)
                atibios_set_vesa_mode(&regs, vesa_mode, mode_info);
 }
index 304b2bf..4962a2a 100644 (file)
 # define ERR_PRINTF(x)         printf(x)
 # define ERR_PRINTF2(x, y)     printf(x, y)
 
-#ifdef CONFIG_X86EMU_DEBUG103
+#ifdef CONFIG_X86EMU_DEBUG
 
 
 # define DECODE_PRINTF(x)      if (DEBUG_DECODE()) \
index 2bb5e2d..5752fee 100644 (file)
@@ -179,7 +179,7 @@ void x86emuOp_illegal_op(
 {
     START_OF_INSTR();
     if (M.x86.R_SP != 0) {
-       ERR_PRINTF("ILLEGAL X86 OPCODE\n");
+       DB(printf("ILLEGAL X86 OPCODE\n"));
        TRACE_REGS();
        DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
            M.x86.R_CS, M.x86.R_IP-1,op1));
index 37d2d2a..c908fab 100644 (file)
@@ -513,6 +513,20 @@ static void ahci_set_feature(u8 port)
 }
 #endif
 
+static int wait_spinup(volatile u8 *port_mmio)
+{
+       ulong start;
+       u32 tf_data;
+
+       start = get_timer(0);
+       do {
+               tf_data = readl(port_mmio + PORT_TFDATA);
+               if (!(tf_data & ATA_BUSY))
+                       return 0;
+       } while (get_timer(start) < WAIT_MS_SPINUP);
+
+       return -ETIMEDOUT;
+}
 
 static int ahci_port_start(u8 port)
 {
@@ -579,7 +593,11 @@ static int ahci_port_start(u8 port)
 
        debug("Exit start port %d\n", port);
 
-       return 0;
+       /*
+        * Make sure interface is not busy based on error and status
+        * information from task file data register before proceeding
+        */
+       return wait_spinup(port_mmio);
 }
 
 
index 44470fa..ed92857 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #include <common.h>
-
+#include <errno.h>
 #include <pci.h>
 
 #undef DEBUG
@@ -191,6 +191,32 @@ void pciauto_setup_device(struct pci_controller *hose,
        pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
 }
 
+int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev)
+{
+       pci_addr_t bar_value;
+       pci_size_t bar_size;
+       u32 bar_response;
+       u16 cmdstat = 0;
+
+       pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, 0xfffffffe);
+       pci_hose_read_config_dword(hose, dev, PCI_ROM_ADDRESS, &bar_response);
+       if (!bar_response)
+               return -ENOENT;
+
+       bar_size = -(bar_response & ~1);
+       DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size);
+       if (pciauto_region_allocate(hose->pci_mem, bar_size, &bar_value) == 0) {
+               pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS,
+                                           bar_value);
+       }
+       DEBUGF("\n");
+       pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
+       cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+       pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
+
+       return 0;
+}
+
 void pciauto_prescan_setup_bridge(struct pci_controller *hose,
                                         pci_dev_t dev, int sub_bus)
 {
index 7d25cc9..eb76591 100644 (file)
@@ -66,6 +66,7 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
        struct pci_rom_header *rom_header;
        struct pci_rom_data *rom_data;
        u16 vendor, device;
+       u16 rom_vendor, rom_device;
        u32 vendev;
        u32 mapped_vendev;
        u32 rom_address;
@@ -80,7 +81,12 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
 #ifdef CONFIG_X86_OPTION_ROM_ADDR
        rom_address = CONFIG_X86_OPTION_ROM_ADDR;
 #else
-       pci_write_config_dword(dev, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK);
+
+       if (pciauto_setup_rom(pci_bus_to_hose(PCI_BUS(dev)), dev)) {
+               debug("Cannot find option ROM\n");
+               return -ENOENT;
+       }
+
        pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_address);
        if (rom_address == 0x00000000 || rom_address == 0xffffffff) {
                debug("%s: rom_address=%x\n", __func__, rom_address);
@@ -95,26 +101,28 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
        rom_header = (struct pci_rom_header *)rom_address;
 
        debug("PCI expansion ROM, signature %#04x, INIT size %#04x, data ptr %#04x\n",
-             le32_to_cpu(rom_header->signature),
-             rom_header->size * 512, le32_to_cpu(rom_header->data));
+             le16_to_cpu(rom_header->signature),
+             rom_header->size * 512, le16_to_cpu(rom_header->data));
 
-       if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
+       if (le16_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
                printf("Incorrect expansion ROM header signature %04x\n",
-                      le32_to_cpu(rom_header->signature));
+                      le16_to_cpu(rom_header->signature));
                return -EINVAL;
        }
 
-       rom_data = (((void *)rom_header) + le32_to_cpu(rom_header->data));
+       rom_data = (((void *)rom_header) + le16_to_cpu(rom_header->data));
+       rom_vendor = le16_to_cpu(rom_data->vendor);
+       rom_device = le16_to_cpu(rom_data->device);
 
        debug("PCI ROM image, vendor ID %04x, device ID %04x,\n",
-             rom_data->vendor, rom_data->device);
+             rom_vendor, rom_device);
 
        /* If the device id is mapped, a mismatch is expected */
-       if ((vendor != rom_data->vendor || device != rom_data->device) &&
+       if ((vendor != rom_vendor || device != rom_device) &&
            (vendev == mapped_vendev)) {
                printf("ID mismatch: vendor ID %04x, device ID %04x\n",
-                      rom_data->vendor, rom_data->device);
-               return -EPERM;
+                      rom_vendor, rom_device);
+               /* Continue anyway */
        }
 
        debug("PCI ROM image, Class Code %04x%02x, Code Type %02x\n",
@@ -144,17 +152,23 @@ int pci_rom_load(uint16_t class, struct pci_rom_header *rom_header,
                                                            image_size);
 
                rom_data = (struct pci_rom_data *)((void *)rom_header +
-                               le32_to_cpu(rom_header->data));
+                               le16_to_cpu(rom_header->data));
 
-               image_size = le32_to_cpu(rom_data->ilen) * 512;
-       } while ((rom_data->type != 0) && (rom_data->indicator != 0));
+               image_size = le16_to_cpu(rom_data->ilen) * 512;
+       } while ((rom_data->type != 0) && (rom_data->indicator == 0));
 
        if (rom_data->type != 0)
                return -EACCES;
 
        rom_size = rom_header->size * 512;
 
+#ifdef PCI_VGA_RAM_IMAGE_START
        target = (void *)PCI_VGA_RAM_IMAGE_START;
+#else
+       target = (void *)malloc(rom_size);
+       if (!target)
+               return -ENOMEM;
+#endif
        if (target != rom_header) {
                ulong start = get_timer(0);
 
index f9e05ad..67b5fdf 100644 (file)
@@ -459,7 +459,6 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node,
                                      unsigned int *lanes)
 {
        struct fdt_pci_addr addr;
-       pci_dev_t bdf;
        int err;
 
        err = fdtdec_get_int(fdt, node, "nvidia,num-lanes", 0);
@@ -470,13 +469,13 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node,
 
        *lanes = err;
 
-       err = fdtdec_get_pci_bdf(fdt, node, &addr, &bdf);
+       err = fdtdec_get_pci_addr(fdt, node, 0, "reg", &addr);
        if (err < 0) {
                error("failed to parse \"reg\" property");
                return err;
        }
 
-       *index = PCI_DEV(bdf) - 1;
+       *index = PCI_DEV(addr.phys_hi) - 1;
 
        return 0;
 }
index 39e6041..c9d318c 100644 (file)
@@ -27,9 +27,6 @@
 /* Set this to 1 to clear the CMOS RAM */
 #define CLEAR_CMOS 0
 
-static uchar rtc_read  (uchar reg);
-static void  rtc_write (uchar reg, uchar val);
-
 #define RTC_PORT_MC146818      CONFIG_SYS_ISA_IO_BASE_ADDRESS +  0x70
 #define RTC_SECONDS            0x00
 #define RTC_SECONDS_ALARM      0x01
@@ -60,24 +57,24 @@ int rtc_get (struct rtc_time *tmp)
 {
        uchar sec, min, hour, mday, wday, mon, year;
   /* here check if rtc can be accessed */
-       while((rtc_read(RTC_CONFIG_A)&0x80)==0x80);
-       sec     = rtc_read (RTC_SECONDS);
-       min     = rtc_read (RTC_MINUTES);
-       hour    = rtc_read (RTC_HOURS);
-       mday    = rtc_read (RTC_DATE_OF_MONTH);
-       wday    = rtc_read (RTC_DAY_OF_WEEK);
-       mon     = rtc_read (RTC_MONTH);
-       year    = rtc_read (RTC_YEAR);
+       while ((rtc_read8(RTC_CONFIG_A) & 0x80) == 0x80);
+       sec     = rtc_read8(RTC_SECONDS);
+       min     = rtc_read8(RTC_MINUTES);
+       hour    = rtc_read8(RTC_HOURS);
+       mday    = rtc_read8(RTC_DATE_OF_MONTH);
+       wday    = rtc_read8(RTC_DAY_OF_WEEK);
+       mon     = rtc_read8(RTC_MONTH);
+       year    = rtc_read8(RTC_YEAR);
 #ifdef RTC_DEBUG
        printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
                "hr: %02x min: %02x sec: %02x\n",
                year, mon, mday, wday,
                hour, min, sec );
        printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n",
-               rtc_read (RTC_CONFIG_D) & 0x3F,
-               rtc_read (RTC_HOURS_ALARM),
-               rtc_read (RTC_MINUTES_ALARM),
-               rtc_read (RTC_SECONDS_ALARM) );
+               rtc_read8(RTC_CONFIG_D) & 0x3F,
+               rtc_read8(RTC_HOURS_ALARM),
+               rtc_read8(RTC_MINUTES_ALARM),
+               rtc_read8(RTC_SECONDS_ALARM));
 #endif
        tmp->tm_sec  = bcd2bin (sec  & 0x7F);
        tmp->tm_min  = bcd2bin (min  & 0x7F);
@@ -108,80 +105,108 @@ int rtc_set (struct rtc_time *tmp)
                tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 #endif
-       rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */
+       rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
 
-       rtc_write (RTC_YEAR, bin2bcd(tmp->tm_year % 100));
-       rtc_write (RTC_MONTH, bin2bcd(tmp->tm_mon));
-       rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
-       rtc_write (RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
-       rtc_write (RTC_HOURS, bin2bcd(tmp->tm_hour));
-       rtc_write (RTC_MINUTES, bin2bcd(tmp->tm_min ));
-       rtc_write (RTC_SECONDS, bin2bcd(tmp->tm_sec ));
-       rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */
+       rtc_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100));
+       rtc_write8(RTC_MONTH, bin2bcd(tmp->tm_mon));
+       rtc_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
+       rtc_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
+       rtc_write8(RTC_HOURS, bin2bcd(tmp->tm_hour));
+       rtc_write8(RTC_MINUTES, bin2bcd(tmp->tm_min));
+       rtc_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec));
+       rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
 
        return 0;
 }
 
 void rtc_reset (void)
 {
-       rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */
-       rtc_write(RTC_CONFIG_A,0x20); /* Normal OP */
-       rtc_write(RTC_CONFIG_B,0x00);
-       rtc_write(RTC_CONFIG_B,0x00);
-       rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */
+       rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
+       rtc_write8(RTC_CONFIG_A, 0x20); /* Normal OP */
+       rtc_write8(RTC_CONFIG_B, 0x00);
+       rtc_write8(RTC_CONFIG_B, 0x00);
+       rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
 }
 
 /* ------------------------------------------------------------------------- */
 
-#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
 /*
  * use direct memory access
  */
-static uchar rtc_read (uchar reg)
+int rtc_read8(int reg)
 {
+#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
        return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg);
+#else
+       int ofs = 0;
+
+       if (reg >= 128) {
+               ofs = 2;
+               reg -= 128;
+       }
+       out8(RTC_PORT_MC146818 + ofs, reg);
+
+       return in8(RTC_PORT_MC146818 + ofs + 1);
+#endif
 }
 
-static void rtc_write (uchar reg, uchar val)
+void rtc_write8(int reg, uchar val)
 {
+#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
        out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val);
-}
 #else
-static uchar rtc_read (uchar reg)
+       int ofs = 0;
+
+       if (reg >= 128) {
+               ofs = 2;
+               reg -= 128;
+       }
+       out8(RTC_PORT_MC146818 + ofs, reg);
+       out8(RTC_PORT_MC146818 + ofs + 1, val);
+#endif
+}
+
+u32 rtc_read32(int reg)
 {
-       out8(RTC_PORT_MC146818,reg);
-       return in8(RTC_PORT_MC146818 + 1);
+       u32 value = 0;
+       int i;
+
+       for (i = 0; i < sizeof(value); i++)
+               value |= rtc_read8(reg + i) << (i << 3);
+
+       return value;
 }
 
-static void rtc_write (uchar reg, uchar val)
+void rtc_write32(int reg, u32 value)
 {
-       out8(RTC_PORT_MC146818,reg);
-       out8(RTC_PORT_MC146818+1, val);
+       int i;
+
+       for (i = 0; i < sizeof(value); i++)
+               rtc_write8(reg + i, (value >> (i << 3)) & 0xff);
 }
-#endif
 
 void rtc_init(void)
 {
 #if CLEAR_CMOS
        int i;
 
-       rtc_write(RTC_SECONDS_ALARM, 0);
-       rtc_write(RTC_MINUTES_ALARM, 0);
-       rtc_write(RTC_HOURS_ALARM, 0);
+       rtc_write8(RTC_SECONDS_ALARM, 0);
+       rtc_write8(RTC_MINUTES_ALARM, 0);
+       rtc_write8(RTC_HOURS_ALARM, 0);
        for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++)
-               rtc_write(i, 0);
+               rtc_write8(i, 0);
        printf("RTC: zeroing CMOS RAM\n");
 #endif
 
        /* Setup the real time clock */
-       rtc_write(RTC_CONFIG_B, RTC_CONFIG_B_24H);
+       rtc_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H);
        /* Setup the frequency it operates at */
-       rtc_write(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
+       rtc_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
                  RTC_CONFIG_A_RATE_1024HZ);
        /* Ensure all reserved bits are 0 in register D */
-       rtc_write(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
+       rtc_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
 
        /* Clear any pending interrupts */
-       rtc_read(RTC_CONFIG_C);
+       rtc_read8(RTC_CONFIG_C);
 }
 #endif
index 0379444..fdff158 100644 (file)
@@ -153,6 +153,13 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
        return &ich->slave;
 }
 
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
+                                     int spi_node)
+{
+       /* We only support a single SPI at present */
+       return spi_setup_slave(0, 0, 20000000, 0);
+}
+
 void spi_free_slave(struct spi_slave *slave)
 {
        struct ich_spi_slave *ich = to_ich_spi(slave);
index ccbd7e2..51728b3 100644 (file)
@@ -1,11 +1,12 @@
-config VIDEO_X86
-       bool "Enable x86 video driver support"
+config VIDEO_VESA
+       bool "Enable VESA video driver support"
        depends on X86
        default n
        help
          Turn on this option to enable a very simple driver which uses vesa
          to discover the video mode and then provides a frame buffer for use
-         by U-Boot.
+         by U-Boot. This can in principle be used with any platform that
+         supports PCI and video cards that support VESA BIOS Extension (VBE).
 
 config VIDEO_LCD_SSD2828
        bool "SSD2828 bridge chip"
index c3fcf45..af2d47b 100644 (file)
@@ -44,7 +44,7 @@ obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o
 obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o videomodes.o
 obj-$(CONFIG_VIDEO_TEGRA) += tegra.o
 obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
-obj-$(CONFIG_VIDEO_X86) += x86_fb.o
+obj-$(CONFIG_VIDEO_VESA) += vesa_fb.o
 obj-$(CONFIG_FORMIKE) += formike.o
 obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
 obj-$(CONFIG_VIDEO_PARADE) += parade.o
index d4226e3..a81affa 100644 (file)
@@ -299,7 +299,11 @@ void console_cursor(int state);
 #define CONSOLE_ROW_SECOND     (video_console_address + CONSOLE_ROW_SIZE)
 #define CONSOLE_ROW_LAST       (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
 #define CONSOLE_SIZE           (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
-#define CONSOLE_SCROLL_SIZE    (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+
+/* By default we scroll by a single line */
+#ifndef CONFIG_CONSOLE_SCROLL_LINES
+#define CONFIG_CONSOLE_SCROLL_LINES 1
+#endif
 
 /* Macros */
 #ifdef VIDEO_FB_LITTLE_ENDIAN
@@ -740,26 +744,33 @@ static void console_clear_line(int line, int begin, int end)
 
 static void console_scrollup(void)
 {
+       const int rows = CONFIG_CONSOLE_SCROLL_LINES;
+       int i;
+
        /* copy up rows ignoring the first one */
 
 #ifdef VIDEO_HW_BITBLT
        video_hw_bitblt(VIDEO_PIXEL_SIZE,       /* bytes per pixel */
                        0,                      /* source pos x */
                        video_logo_height +
-                               VIDEO_FONT_HEIGHT, /* source pos y */
+                               VIDEO_FONT_HEIGHT * rows, /* source pos y */
                        0,                      /* dest pos x */
                        video_logo_height,      /* dest pos y */
                        VIDEO_VISIBLE_COLS,     /* frame width */
                        VIDEO_VISIBLE_ROWS
                        - video_logo_height
-                       - VIDEO_FONT_HEIGHT     /* frame height */
+                       - VIDEO_FONT_HEIGHT * rows      /* frame height */
                );
 #else
-       memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
-               CONSOLE_SCROLL_SIZE >> 2);
+       memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_FIRST + rows * CONSOLE_ROW_SIZE,
+               (CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows) >> 2);
 #endif
        /* clear the last one */
-       console_clear_line(CONSOLE_ROWS - 1, 0, CONSOLE_COLS - 1);
+       for (i = 1; i <= rows; i++)
+               console_clear_line(CONSOLE_ROWS - i, 0, CONSOLE_COLS - 1);
+
+       /* Decrement row number */
+       console_row -= rows;
 }
 
 static void console_back(void)
@@ -871,9 +882,6 @@ static void console_newline(int n)
        if (console_row >= CONSOLE_ROWS) {
                /* Scroll everything up */
                console_scrollup();
-
-               /* Decrement row number */
-               console_row = CONSOLE_ROWS - 1;
        }
 }
 
diff --git a/drivers/video/vesa_fb.c b/drivers/video/vesa_fb.c
new file mode 100644 (file)
index 0000000..3dacafd
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *
+ * Vesa frame buffer driver for x86
+ *
+ * Copyright (C) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <pci_rom.h>
+#include <video_fb.h>
+#include <vbe.h>
+
+/*
+ * The Graphic Device
+ */
+GraphicDevice ctfb;
+
+/* Devices to allow - only the last one works fully */
+struct pci_device_id vesa_video_ids[] = {
+       { .vendor = 0x102b, .device = 0x0525 },
+       { .vendor = 0x1002, .device = 0x5159 },
+       { .vendor = 0x1002, .device = 0x4752 },
+       { .vendor = 0x1002, .device = 0x5452 },
+       {},
+};
+
+void *video_hw_init(void)
+{
+       GraphicDevice *gdev = &ctfb;
+       int bits_per_pixel;
+       pci_dev_t dev;
+       int ret;
+
+       printf("Video: ");
+       if (vbe_get_video_info(gdev)) {
+               /* TODO: Should we look these up by class? */
+               dev = pci_find_devices(vesa_video_ids, 0);
+               if (dev == -1) {
+                       printf("no card detected\n");
+                       return NULL;
+               }
+               printf("bdf %x\n", dev);
+               ret = pci_run_vga_bios(dev, NULL, true);
+               if (ret) {
+                       printf("failed to run video BIOS: %d\n", ret);
+                       return NULL;
+               }
+       }
+
+       if (vbe_get_video_info(gdev)) {
+               printf("No video mode configured\n");
+               return NULL;
+       }
+
+       bits_per_pixel = gdev->gdfBytesPP * 8;
+       sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
+               bits_per_pixel);
+       printf("%s\n", gdev->modeIdent);
+       debug("Framex buffer at %x\n", gdev->pciBase);
+
+       return (void *)gdev;
+}
diff --git a/drivers/video/x86_fb.c b/drivers/video/x86_fb.c
deleted file mode 100644 (file)
index 6641033..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * Vesa frame buffer driver for x86
- *
- * Copyright (C) 2014 Google, Inc
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <video_fb.h>
-#include <vbe.h>
-#include "videomodes.h"
-
-/*
- * The Graphic Device
- */
-GraphicDevice ctfb;
-
-void *video_hw_init(void)
-{
-       GraphicDevice *gdev = &ctfb;
-       int bits_per_pixel;
-
-       printf("Video: ");
-       if (vbe_get_video_info(gdev)) {
-               printf("No video mode configured\n");
-               return NULL;
-       }
-
-       bits_per_pixel = gdev->gdfBytesPP * 8;
-       sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
-               bits_per_pixel);
-       printf("%s\n", gdev->modeIdent);
-       debug("Frame buffer at %x\n", gdev->frameAdrs);
-
-       return (void *)gdev;
-}
index 7e6d239..7b460e8 100644 (file)
@@ -20,6 +20,7 @@
 
 #define CONFIG_DCACHE_RAM_MRC_VAR_SIZE         0x4000
 #define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_MISC_INIT_R
 
 #define CONFIG_NR_DRAM_BANKS                   8
 #define CONFIG_X86_MRC_ADDR                    0xfffa0000
 #define CONFIG_CMD_CROS_EC
 #define CONFIG_ARCH_EARLY_INIT_R
 
+#undef CONFIG_ENV_IS_NOWHERE
+#undef CONFIG_ENV_SIZE
+#define CONFIG_ENV_SIZE                        0x1000
+#define CONFIG_ENV_SECT_SIZE           0x1000
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_OFFSET              0x003f8000
+
 #define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,vga,serial\0" \
                                        "stdout=vga,serial\0" \
                                        "stderr=vga,serial\0"
index f16ae32..ecedfc3 100644 (file)
 #define VIDEO_FB_16BPP_WORD_SWAP
 #define CONFIG_I8042_KBD
 #define CONFIG_CFB_CONSOLE
+#define CONFIG_CONSOLE_SCROLL_LINES 5
 
 /*-----------------------------------------------------------------------
  * CPU Features
 #define CONFIG_CMD_SF_TEST
 #define CONFIG_CMD_SPI
 #define CONFIG_SPI
+#define CONFIG_OF_SPI_FLASH
 
 /*-----------------------------------------------------------------------
  * Environment configuration
index 75af750..8c2bd21 100644 (file)
@@ -173,6 +173,7 @@ enum fdt_compat_id {
        COMPAT_INTEL_MODEL_206AX,       /* Intel Model 206AX CPU */
        COMPAT_INTEL_GMA,               /* Intel Graphics Media Accelerator */
        COMPAT_AMS_AS3722,              /* AMS AS3722 PMIC */
+       COMPAT_INTEL_ICH_SPI,           /* Intel ICH7/9 SPI controller */
 
        COMPAT_COUNT,
 };
index 3da35fe..73ea88b 100644 (file)
@@ -482,6 +482,36 @@ extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
 extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
                                int sport, int len);
 
+/**
+ * compute_ip_checksum() - Compute IP checksum
+ *
+ * @addr:      Address to check (must be 16-bit aligned)
+ * @nbytes:    Number of bytes to check (normally a multiple of 2)
+ * @return 16-bit IP checksum
+ */
+unsigned compute_ip_checksum(const void *addr, unsigned nbytes);
+
+/**
+ * add_ip_checksums() - add two IP checksums
+ *
+ * @offset:    Offset of first sum (if odd we do a byte-swap)
+ * @sum:       First checksum
+ * @new_sum:   New checksum to add
+ * @return updated 16-bit IP checksum
+ */
+unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
+
+/**
+ * ip_checksum_ok() - check if a checksum is correct
+ *
+ * This works by making sure the checksum sums to 0
+ *
+ * @addr:      Address to check (must be 16-bit aligned)
+ * @nbytes:    Number of bytes to check (normally a multiple of 2)
+ * @return true if the checksum matches, false if not
+ */
+int ip_checksum_ok(const void *addr, unsigned nbytes);
+
 /* Checksum */
 extern int     NetCksumOk(uchar *, int);       /* Return true if cksum OK */
 extern uint    NetCksum(uchar *, int);         /* Calculate the checksum */
index 7f67ca6..4fbb8f6 100644 (file)
@@ -697,5 +697,14 @@ void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
  * */
 u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum);
 
+/**
+ * pciauto_setup_rom() - Set up access to a device ROM
+ *
+ * @hose:      PCI hose to use
+ * @dev:       PCI device to adjust
+ * @return 0 if done, -ve on error
+ */
+int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev);
+
 #endif /* __ASSEMBLY__ */
 #endif /* _PCI_H */
index 8b2674c..4ba36eb 100644 (file)
@@ -8,7 +8,6 @@
 #define _PCI_ROM_H
 
 #define PCI_ROM_HDR                    0xaa55
-#define PCI_VGA_RAM_IMAGE_START                0xc0000
 
 struct pci_rom_header {
        uint16_t signature;
index d11aa8b..54e361e 100644 (file)
@@ -51,6 +51,38 @@ unsigned long mktime (unsigned int, unsigned int, unsigned int,
                      unsigned int, unsigned int, unsigned int);
 
 /**
+ * rtc_read8() - Read an 8-bit register
+ *
+ * @reg:       Register to read
+ * @return value read
+ */
+int rtc_read8(int reg);
+
+/**
+ * rtc_write8() - Write an 8-bit register
+ *
+ * @reg:       Register to write
+ * @value:     Value to write
+ */
+void rtc_write8(int reg, uchar val);
+
+/**
+ * rtc_read32() - Read a 32-bit value from the RTC
+ *
+ * @reg:       Offset to start reading from
+ * @return value read
+ */
+u32 rtc_read32(int reg);
+
+/**
+ * rtc_write32() - Write a 32-bit value to the RTC
+ *
+ * @reg:       Register to start writing to
+ * @value:     Value to write
+ */
+void rtc_write32(int reg, u32 value);
+
+/**
  * rtc_init() - Set up the real time clock ready for use
  */
 void rtc_init(void);
index d405691..c5deee9 100644 (file)
@@ -35,10 +35,14 @@ struct __packed screen_info_input {
 struct __packed vbe_info {
        char signature[4];
        u16 version;
-       u8 *oem_string_ptr;
+       u32 oem_string_ptr;
        u32 capabilities;
-       u16 video_mode_list[256];
+       u32 modes_ptr;
        u16 total_memory;
+       u16 oem_version;
+       u32 vendor_name_ptr;
+       u32 product_name_ptr;
+       u32 product_rev_ptr;
 };
 
 struct __packed vesa_mode_info {
@@ -96,6 +100,7 @@ struct vbe_ddc_info {
 #define VESA_GET_INFO          0x4f00
 #define VESA_GET_MODE_INFO     0x4f01
 #define VESA_SET_MODE          0x4f02
+#define VESA_GET_CUR_MODE      0x4f03
 
 struct graphic_device;
 int vbe_get_video_info(struct graphic_device *gdev);
index 487122e..e989241 100644 (file)
@@ -83,6 +83,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(INTEL_MODEL_206AX, "intel,model-206ax"),
        COMPAT(INTEL_GMA, "intel,gma"),
        COMPAT(AMS_AS3722, "ams,as3722"),
+       COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
index 9425950..e9cc8ad 100644 (file)
@@ -7,6 +7,7 @@
 
 #ccflags-y += -DDEBUG
 
+obj-y += checksum.o
 obj-$(CONFIG_CMD_NET)  += arp.o
 obj-$(CONFIG_CMD_NET)  += bootp.o
 obj-$(CONFIG_CMD_CDP)  += cdp.o
diff --git a/net/checksum.c b/net/checksum.c
new file mode 100644 (file)
index 0000000..a8c9ff5
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * This file was originally taken from the FreeBSD project.
+ *
+ * Copyright (c) 2001 Charles Mott <cm@linktel.net>
+ * Copyright (c) 2008 coresystems GmbH
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:    BSD-2-Clause
+ */
+
+#include <common.h>
+#include <net.h>
+
+unsigned compute_ip_checksum(const void *vptr, unsigned nbytes)
+{
+       int sum, oddbyte;
+       const unsigned short *ptr = vptr;
+
+       sum = 0;
+       while (nbytes > 1) {
+               sum += *ptr++;
+               nbytes -= 2;
+       }
+       if (nbytes == 1) {
+               oddbyte = 0;
+               ((u8 *)&oddbyte)[0] = *(u8 *)ptr;
+               ((u8 *)&oddbyte)[1] = 0;
+               sum += oddbyte;
+       }
+       sum = (sum >> 16) + (sum & 0xffff);
+       sum += (sum >> 16);
+       sum = ~sum & 0xffff;
+
+       return sum;
+}
+
+unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new)
+{
+       unsigned long checksum;
+
+       sum = ~sum & 0xffff;
+       new = ~new & 0xffff;
+       if (offset & 1) {
+               /*
+                * byte-swap the sum if it came from an odd offset; since the
+                * computation is endian independant this works.
+                */
+               new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
+       }
+       checksum = sum + new;
+       if (checksum > 0xffff)
+               checksum -= 0xffff;
+
+       return (~checksum) & 0xffff;
+}
+
+int ip_checksum_ok(const void *addr, unsigned nbytes)
+{
+       return !(compute_ip_checksum(addr, nbytes) & 0xfffe);
+}