Merge branch 'master' of git://git.denx.de/u-boot-x86
authorTom Rini <trini@konsulko.com>
Thu, 28 Jan 2016 15:07:22 +0000 (10:07 -0500)
committerTom Rini <trini@konsulko.com>
Thu, 28 Jan 2016 15:07:22 +0000 (10:07 -0500)
27 files changed:
arch/x86/Kconfig
arch/x86/cpu/baytrail/early_uart.c
arch/x86/cpu/qemu/Kconfig
arch/x86/cpu/qemu/Makefile
arch/x86/cpu/qemu/fw_cfg.c
arch/x86/cpu/qemu/qemu.c
arch/x86/dts/bayleybay.dts
arch/x86/dts/broadwell_som-6896.dts
arch/x86/dts/chromebook_link.dts
arch/x86/dts/chromebox_panther.dts
arch/x86/dts/crownbay.dts
arch/x86/dts/galileo.dts
arch/x86/dts/minnowmax.dts
arch/x86/include/asm/arch-qemu/device.h
arch/x86/include/asm/arch-qemu/qemu.h
arch/x86/include/asm/fw_cfg.h
arch/x86/include/asm/u-boot-x86.h
arch/x86/lib/Makefile
arch/x86/lib/acpi_table.c
arch/x86/lib/fsp/fsp_support.c
doc/README.x86
doc/device-tree-bindings/misc/intel,baytrail-fsp.txt
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/winbond_w83627.c [new file with mode: 0644]
include/configs/x86-common.h
include/winbond_w83627.h [new file with mode: 0644]

index f07567c81ac4374c46349cf892c5420179841369..a995e32bb98cfc3dd1f5dc2a9efb4ed3b044516f 100644 (file)
@@ -358,6 +358,15 @@ config GENERATE_ACPI_TABLE
          by the operating system. It defines platform-independent interfaces
          for configuration and power management monitoring.
 
+config QEMU_ACPI_TABLE
+       bool "Load ACPI table from QEMU fw_cfg interface"
+       depends on GENERATE_ACPI_TABLE && QEMU
+       default y
+       help
+         By default, U-Boot generates its own ACPI tables. This option, if
+         enabled, disables U-Boot's version and loads ACPI tables generated
+         by QEMU.
+
 config GENERATE_SMBIOS_TABLE
        bool "Generate an SMBIOS (System Management BIOS) table"
        default y
index b64a3a90db4ab7e1d10b9a20e3a0867a38031bab..471d592b49fddb45ed215bcf177311fdcec73a13 100644 (file)
@@ -59,11 +59,15 @@ static void x86_pci_write_config32(int dev, unsigned int where, u32 value)
 }
 
 /* This can be called after memory-mapped PCI is working */
-int setup_early_uart(void)
+int setup_internal_uart(int enable)
 {
-       /* Enable the legacy UART hardware. */
+       /* Enable or disable the legacy UART hardware */
        x86_pci_write_config32(PCI_DEV_CONFIG(0, LPC_DEV, LPC_FUNC), UART_CONT,
-                              1);
+                              enable);
+
+       /* All done for the disable part, so just return */
+       if (!enable)
+               return 0;
 
        /*
         * Set up the pads to the UART function. This allows the signals to
index 4f9862194a97e094b9cabee0439828453a1b4e28..6808c9a6b9a262b5ce67b2708e396902505d8b0c 100644 (file)
@@ -17,4 +17,11 @@ config SYS_CAR_SIZE
        hex
        default 0x10000
 
+config ACPI_PM1_BASE
+       hex
+       default 0xe400
+       help
+         ACPI Power Managment 1 (PM1) i/o-mapped base address.
+         This device is defined in ACPI specification, with 16 bytes in size.
+
 endif
index 176ea54ae4ef831b6d5b93661ab67d99e837503a..801413a1cb1478f49fb2caa4094793556a8625e0 100644 (file)
@@ -8,4 +8,6 @@ ifndef CONFIG_EFI_STUB
 obj-y += car.o dram.o
 endif
 obj-y += cpu.o fw_cfg.o qemu.o
+ifndef CONFIG_QEMU_ACPI_TABLE
 obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o dsdt.o
+endif
index 05992145cf0cbe1a2c0a60c2064c6e5f02bfe5bb..5ea7a6e2e539c53b15801969b84ed908d80f1c31 100644 (file)
 #include <malloc.h>
 #include <asm/io.h>
 #include <asm/fw_cfg.h>
+#include <asm/tables.h>
+#include <asm/e820.h>
+#include <linux/list.h>
+#include <memalign.h>
 
 static bool fwcfg_present;
 static bool fwcfg_dma_present;
 
+static LIST_HEAD(fw_list);
+
 /* Read configuration item using fw_cfg PIO interface */
 static void qemu_fwcfg_read_entry_pio(uint16_t entry,
                uint32_t size, void *address)
@@ -162,29 +168,311 @@ static int qemu_fwcfg_setup_kernel(void *load_addr, void *initrd_addr)
        return 0;
 }
 
-static int qemu_fwcfg_list_firmware(void)
+static int qemu_fwcfg_read_firmware_list(void)
 {
        int i;
        uint32_t count;
-       struct fw_cfg_files *files;
+       struct fw_file *file;
+       struct list_head *entry;
+
+       /* don't read it twice */
+       if (!list_empty(&fw_list))
+               return 0;
 
        qemu_fwcfg_read_entry(FW_CFG_FILE_DIR, 4, &count);
        if (!count)
                return 0;
 
        count = be32_to_cpu(count);
-       files = malloc(count * sizeof(struct fw_cfg_file));
-       if (!files)
-               return -ENOMEM;
-
-       files->count = count;
-       qemu_fwcfg_read_entry(FW_CFG_INVALID,
-                             count * sizeof(struct fw_cfg_file),
-                             files->files);
-
-       for (i = 0; i < files->count; i++)
-               printf("%-56s\n", files->files[i].name);
-       free(files);
+       for (i = 0; i < count; i++) {
+               file = malloc(sizeof(*file));
+               if (!file) {
+                       printf("error: allocating resource\n");
+                       goto err;
+               }
+               qemu_fwcfg_read_entry(FW_CFG_INVALID,
+                                     sizeof(struct fw_cfg_file), &file->cfg);
+               file->addr = 0;
+               list_add_tail(&file->list, &fw_list);
+       }
+
+       return 0;
+
+err:
+       list_for_each(entry, &fw_list) {
+               file = list_entry(entry, struct fw_file, list);
+               free(file);
+       }
+
+       return -ENOMEM;
+}
+
+#ifdef CONFIG_QEMU_ACPI_TABLE
+static struct fw_file *qemu_fwcfg_find_file(const char *name)
+{
+       struct list_head *entry;
+       struct fw_file *file;
+
+       list_for_each(entry, &fw_list) {
+               file = list_entry(entry, struct fw_file, list);
+               if (!strcmp(file->cfg.name, name))
+                       return file;
+       }
+
+       return NULL;
+}
+
+/*
+ * This function allocates memory for ACPI tables
+ *
+ * @entry : BIOS linker command entry which tells where to allocate memory
+ *          (either high memory or low memory)
+ * @addr  : The address that should be used for low memory allcation. If the
+ *          memory allocation request is 'ZONE_HIGH' then this parameter will
+ *          be ignored.
+ * @return: 0 on success, or negative value on failure
+ */
+static int bios_linker_allocate(struct bios_linker_entry *entry,
+                          unsigned long *addr)
+{
+       uint32_t size, align;
+       struct fw_file *file;
+       unsigned long aligned_addr;
+
+       align = le32_to_cpu(entry->alloc.align);
+       /* align must be power of 2 */
+       if (align & (align - 1)) {
+               printf("error: wrong alignment %u\n", align);
+               return -EINVAL;
+       }
+
+       file = qemu_fwcfg_find_file(entry->alloc.file);
+       if (!file) {
+               printf("error: can't find file %s\n", entry->alloc.file);
+               return -ENOENT;
+       }
+
+       size = be32_to_cpu(file->cfg.size);
+
+       /*
+        * ZONE_HIGH means we need to allocate from high memory, since
+        * malloc space is already at the end of RAM, so we directly use it.
+        * If allocation zone is ZONE_FSEG, then we use the 'addr' passed
+        * in which is low memory
+        */
+       if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
+               aligned_addr = (unsigned long)memalign(align, size);
+               if (!aligned_addr) {
+                       printf("error: allocating resource\n");
+                       return -ENOMEM;
+               }
+       } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) {
+               aligned_addr = ALIGN(*addr, align);
+       } else {
+               printf("error: invalid allocation zone\n");
+               return -EINVAL;
+       }
+
+       debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n",
+             file->cfg.name, size, entry->alloc.zone, align, aligned_addr);
+
+       qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select),
+                             size, (void *)aligned_addr);
+       file->addr = aligned_addr;
+
+       /* adjust address for low memory allocation */
+       if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
+               *addr = (aligned_addr + size);
+
+       return 0;
+}
+
+/*
+ * This function patches ACPI tables previously loaded
+ * by bios_linker_allocate()
+ *
+ * @entry : BIOS linker command entry which tells how to patch
+ *          ACPI tables
+ * @return: 0 on success, or negative value on failure
+ */
+static int bios_linker_add_pointer(struct bios_linker_entry *entry)
+{
+       struct fw_file *dest, *src;
+       uint32_t offset = le32_to_cpu(entry->pointer.offset);
+       uint64_t pointer = 0;
+
+       dest = qemu_fwcfg_find_file(entry->pointer.dest_file);
+       if (!dest || !dest->addr)
+               return -ENOENT;
+       src = qemu_fwcfg_find_file(entry->pointer.src_file);
+       if (!src || !src->addr)
+               return -ENOENT;
+
+       debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n",
+             dest->addr, src->addr, offset, entry->pointer.size, pointer);
+
+       memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size);
+       pointer = le64_to_cpu(pointer);
+       pointer += (unsigned long)src->addr;
+       pointer = cpu_to_le64(pointer);
+       memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size);
+
+       return 0;
+}
+
+/*
+ * This function updates checksum fields of ACPI tables previously loaded
+ * by bios_linker_allocate()
+ *
+ * @entry : BIOS linker command entry which tells where to update ACPI table
+ *          checksums
+ * @return: 0 on success, or negative value on failure
+ */
+static int bios_linker_add_checksum(struct bios_linker_entry *entry)
+{
+       struct fw_file *file;
+       uint8_t *data, cksum = 0;
+       uint8_t *cksum_start;
+
+       file = qemu_fwcfg_find_file(entry->cksum.file);
+       if (!file || !file->addr)
+               return -ENOENT;
+
+       data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset));
+       cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start));
+       cksum = table_compute_checksum(cksum_start,
+                                      le32_to_cpu(entry->cksum.length));
+       *data = cksum;
+
+       return 0;
+}
+
+unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
+{
+       entries[0].addr = 0;
+       entries[0].size = ISA_START_ADDRESS;
+       entries[0].type = E820_RAM;
+
+       entries[1].addr = ISA_START_ADDRESS;
+       entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
+       entries[1].type = E820_RESERVED;
+
+       /*
+        * since we use memalign(malloc) to allocate high memory for
+        * storing ACPI tables, we need to reserve them in e820 tables,
+        * otherwise kernel will reclaim them and data will be corrupted
+        */
+       entries[2].addr = ISA_END_ADDRESS;
+       entries[2].size = gd->relocaddr - TOTAL_MALLOC_LEN - ISA_END_ADDRESS;
+       entries[2].type = E820_RAM;
+
+       /* for simplicity, reserve entire malloc space */
+       entries[3].addr = gd->relocaddr - TOTAL_MALLOC_LEN;
+       entries[3].size = TOTAL_MALLOC_LEN;
+       entries[3].type = E820_RESERVED;
+
+       entries[4].addr = gd->relocaddr;
+       entries[4].size = gd->ram_size - gd->relocaddr;
+       entries[4].type = E820_RESERVED;
+
+       entries[5].addr = CONFIG_PCIE_ECAM_BASE;
+       entries[5].size = CONFIG_PCIE_ECAM_SIZE;
+       entries[5].type = E820_RESERVED;
+
+       return 6;
+}
+
+/* This function loads and patches ACPI tables provided by QEMU */
+unsigned long write_acpi_tables(unsigned long addr)
+{
+       int i, ret = 0;
+       struct fw_file *file;
+       struct bios_linker_entry *table_loader;
+       struct bios_linker_entry *entry;
+       uint32_t size;
+       struct list_head *list;
+
+       /* make sure fw_list is loaded */
+       ret = qemu_fwcfg_read_firmware_list();
+       if (ret) {
+               printf("error: can't read firmware file list\n");
+               return addr;
+       }
+
+       file = qemu_fwcfg_find_file("etc/table-loader");
+       if (!file) {
+               printf("error: can't find etc/table-loader\n");
+               return addr;
+       }
+
+       size = be32_to_cpu(file->cfg.size);
+       if ((size % sizeof(*entry)) != 0) {
+               printf("error: table-loader maybe corrupted\n");
+               return addr;
+       }
+
+       table_loader = malloc(size);
+       if (!table_loader) {
+               printf("error: no memory for table-loader\n");
+               return addr;
+       }
+
+       qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select),
+                             size, table_loader);
+
+       for (i = 0; i < (size / sizeof(*entry)); i++) {
+               entry = table_loader + i;
+               switch (le32_to_cpu(entry->command)) {
+               case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
+                       ret = bios_linker_allocate(entry, &addr);
+                       if (ret)
+                               goto out;
+                       break;
+               case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
+                       ret = bios_linker_add_pointer(entry);
+                       if (ret)
+                               goto out;
+                       break;
+               case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
+                       ret = bios_linker_add_checksum(entry);
+                       if (ret)
+                               goto out;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+out:
+       if (ret) {
+               list_for_each(list, &fw_list) {
+                       file = list_entry(list, struct fw_file, list);
+                       if (file->addr)
+                               free((void *)file->addr);
+               }
+       }
+
+       free(table_loader);
+       return addr;
+}
+#endif
+
+static int qemu_fwcfg_list_firmware(void)
+{
+       int ret;
+       struct list_head *entry;
+       struct fw_file *file;
+
+       /* make sure fw_list is loaded */
+       ret = qemu_fwcfg_read_firmware_list();
+       if (ret)
+               return ret;
+
+       list_for_each(entry, &fw_list) {
+               file = list_entry(entry, struct fw_file, list);
+               printf("%-56s\n", file->cfg.name);
+       }
+
        return 0;
 }
 
index 5a7b92944a21501edd10b99824cb2eab337e0da1..f8af566deae80d714e2516aa04c370b6eed20c9a 100644 (file)
 
 static bool i440fx;
 
+static void enable_pm_piix(void)
+{
+       u8 en;
+       u16 cmd;
+
+       /* Set the PM I/O base */
+       x86_pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
+
+       /* Enable access to the PM I/O space */
+       cmd = x86_pci_read_config16(PIIX_PM, PCI_COMMAND);
+       cmd |= PCI_COMMAND_IO;
+       x86_pci_write_config16(PIIX_PM, PCI_COMMAND, cmd);
+
+       /* PM I/O Space Enable (PMIOSE) */
+       en = x86_pci_read_config8(PIIX_PM, PMREGMISC);
+       en |= PMIOSE;
+       x86_pci_write_config8(PIIX_PM, PMREGMISC, en);
+}
+
+static void enable_pm_ich9(void)
+{
+       /* Set the PM I/O base */
+       x86_pci_write_config32(ICH9_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
+}
+
 static void qemu_chipset_init(void)
 {
        u16 device, xbcs;
@@ -53,10 +78,14 @@ static void qemu_chipset_init(void)
                xbcs = x86_pci_read_config16(PIIX_ISA, XBCS);
                xbcs |= APIC_EN;
                x86_pci_write_config16(PIIX_ISA, XBCS, xbcs);
+
+               enable_pm_piix();
        } else {
                /* Configure PCIe ECAM base address */
                x86_pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR,
                                       CONFIG_PCIE_ECAM_BASE | BAR_EN);
+
+               enable_pm_ich9();
        }
 
        qemu_fwcfg_init();
index 9bf707bf0e84bdd43c05d7f97d8fbafddcd2b5d7..fbca46762c55149ae601e41fc4edadbd4f3d37b8 100644 (file)
@@ -21,7 +21,7 @@
 
        aliases {
                serial0 = &serial;
-               spi0 = "/spi";
+               spi0 = &spi;
        };
 
        config {
                                >;
                        };
 
-                       spi {
+                       spi: spi {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "intel,ich-spi";
index 4e9e410b706aac85ea31ad99e4f28904bc6a64f7..7b2c51504b1a9694289359c94a94414a42799af9 100644 (file)
@@ -10,7 +10,7 @@
        compatible = "advantech,som-6896", "intel,broadwell";
 
        aliases {
-               spi0 = "/spi";
+               spi0 = &spi;
        };
 
        config {
@@ -34,7 +34,7 @@
                        reg = <0x0000f800 0 0 0 0>;
                        compatible = "intel,pch9";
 
-                       spi {
+                       spi: spi {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "intel,ich-spi";
index d148d6e349cd87f0d8c06395834aca3f52909e5e..58072031df88e7c2fd536b1bb6fa6ac686d84d72 100644 (file)
@@ -11,7 +11,7 @@
        compatible = "google,link", "intel,celeron-ivybridge";
 
        aliases {
-               spi0 = "/pci/pch/spi";
+               spi0 = &spi;
                usb0 = &usb_0;
                usb1 = &usb_1;
        };
                        /* Enable EC SMI source */
                        intel,alt-gp-smi-enable = <0x0100>;
 
-                       spi {
+                       spi: spi {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "intel,ich-spi";
index 23027016e5746a51768974a2629f06ea906ceecc..48f0c77d45894b3efc2d7e3111426c62a11e574c 100644 (file)
@@ -10,7 +10,7 @@
        compatible = "google,panther", "intel,haswell";
 
        aliases {
-               spi0 = "/spi";
+               spi0 = &spi;
        };
 
        config {
@@ -56,7 +56,7 @@
                        reg = <0x0000f800 0 0 0 0>;
                        compatible = "intel,pch9";
 
-                       spi {
+                       spi: spi {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "intel,ich-spi";
index d6dd0b49f0fac3a64f9ec4192c3a2ed431d2610f..47fab0fda6758710d0cba172268f10a93c2790de 100644 (file)
@@ -19,7 +19,7 @@
        compatible = "intel,crownbay", "intel,queensbay";
 
        aliases {
-               spi0 = "/spi";
+               spi0 = &spi;
        };
 
        config {
                                >;
                        };
 
-                       spi {
+                       spi: spi {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "intel,ich-spi";
index a2f5a1f223427508c447225df87bdce965b91b4a..dd75fc4dc968725f627b7a89efa3d6cde77ce11f 100644 (file)
@@ -18,7 +18,7 @@
        compatible = "intel,galileo", "intel,quark";
 
        aliases {
-               spi0 = "/spi";
+               spi0 = &spi;
        };
 
        config {
                                >;
                        };
 
-                       spi {
+                       spi: spi {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "intel,ich-spi";
index e7ef7c987b6226b525a1d40be3299ec5787a0d6e..7afdf6c30ba015f134a12a55b0784daf0f188d19 100644 (file)
@@ -20,7 +20,7 @@
 
        aliases {
                serial0 = &serial;
-               spi0 = "/spi";
+               spi0 = &spi;
        };
 
        config {
                                >;
                        };
 
-                       spi {
+                       spi: spi {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "intel,ich-spi";
index 75a435e67b9ff294e33035b0cfaf83b811ef40f2..38ab798994f00e36d26d4e6e8148810eb8be0b42 100644 (file)
@@ -13,6 +13,8 @@
 #define PIIX_ISA       PCI_BDF(0, 1, 0)
 #define PIIX_IDE       PCI_BDF(0, 1, 1)
 #define PIIX_USB       PCI_BDF(0, 1, 2)
+#define PIIX_PM        PCI_BDF(0, 1, 3)
+#define ICH9_PM        PCI_BDF(0, 0x1f, 0)
 #define I440FX_VGA     PCI_BDF(0, 2, 0)
 
 #define QEMU_Q35       PCI_BDF(0, 0, 0)
index b67d3428ee69711f5e469aa70ebd13146e073fa7..a85eee8ec6d13bd6078b45a6c74cf9bcab50026b 100644 (file)
@@ -33,4 +33,9 @@
 #define LOW_RAM_ADDR           0x34
 #define HIGH_RAM_ADDR          0x35
 
+/* PM registers */
+#define PMBA           0x40
+#define PMREGMISC      0x80
+#define PMIOSE         (1 << 0)
+
 #endif /* _ARCH_QEMU_H_ */
index fb110fa8e786314e6ffcfd3c59721a5e3a362cc5..e9450c619687f246fdb5f6d2d46305ab06751cb2 100644 (file)
@@ -12,6 +12,8 @@
 #define FW_DMA_PORT_LOW        0x514
 #define FW_DMA_PORT_HIGH       0x518
 
+#include <linux/list.h>
+
 enum qemu_fwcfg_items {
        FW_CFG_SIGNATURE        = 0x00,
        FW_CFG_ID               = 0x01,
@@ -45,11 +47,23 @@ enum qemu_fwcfg_items {
        FW_CFG_INVALID          = 0xffff,
 };
 
+enum {
+       BIOS_LINKER_LOADER_COMMAND_ALLOCATE     = 0x1,
+       BIOS_LINKER_LOADER_COMMAND_ADD_POINTER  = 0x2,
+       BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3,
+};
+
+enum {
+       BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH = 0x1,
+       BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG = 0x2,
+};
+
 #define FW_CFG_FILE_SLOTS      0x10
 #define FW_CFG_MAX_ENTRY       (FW_CFG_FILE_FIRST + FW_CFG_FILE_SLOTS)
 #define FW_CFG_ENTRY_MASK       ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)
 
 #define FW_CFG_MAX_FILE_PATH   56
+#define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH
 
 #define QEMU_FW_CFG_SIGNATURE  (('Q' << 24) | ('E' << 16) | ('M' << 8) | 'U')
 
@@ -67,9 +81,10 @@ struct fw_cfg_file {
        char name[FW_CFG_MAX_FILE_PATH];
 };
 
-struct fw_cfg_files {
-       __be32 count;
-       struct fw_cfg_file files[];
+struct fw_file {
+       struct fw_cfg_file cfg; /* firmware file information */
+       unsigned long addr;     /* firmware file in-memory address */
+       struct list_head list;  /* list node to link to fw_list */
 };
 
 struct fw_cfg_dma_access {
@@ -78,6 +93,55 @@ struct fw_cfg_dma_access {
        __be64 address;
 };
 
+struct bios_linker_entry {
+       __le32 command;
+       union {
+               /*
+                * COMMAND_ALLOCATE - allocate a table from @alloc.file
+                * subject to @alloc.align alignment (must be power of 2)
+                * and @alloc.zone (can be HIGH or FSEG) requirements.
+                *
+                * Must appear exactly once for each file, and before
+                * this file is referenced by any other command.
+                */
+               struct {
+                       char file[BIOS_LINKER_LOADER_FILESZ];
+                       __le32 align;
+                       uint8_t zone;
+               } alloc;
+
+               /*
+                * COMMAND_ADD_POINTER - patch the table (originating from
+                * @dest_file) at @pointer.offset, by adding a pointer to the
+                * table originating from @src_file. 1,2,4 or 8 byte unsigned
+                * addition is used depending on @pointer.size.
+                */
+               struct {
+                       char dest_file[BIOS_LINKER_LOADER_FILESZ];
+                       char src_file[BIOS_LINKER_LOADER_FILESZ];
+                       __le32 offset;
+                       uint8_t size;
+               } pointer;
+
+               /*
+                * COMMAND_ADD_CHECKSUM - calculate checksum of the range
+                * specified by @cksum_start and @cksum_length fields,
+                * and then add the value at @cksum.offset.
+                * Checksum simply sums -X for each byte X in the range
+                * using 8-bit math.
+                */
+               struct {
+                       char file[BIOS_LINKER_LOADER_FILESZ];
+                       __le32 offset;
+                       __le32 start;
+                       __le32 length;
+               } cksum;
+
+               /* padding */
+               char pad[124];
+       };
+} __packed;
+
 /**
  * Initialize QEMU fw_cfg interface
  */
index 9c143caf670b84653d14eda57bf70b936b965c35..031740b708a8f5d660801f816db421af77e0a8fd 100644 (file)
@@ -45,7 +45,7 @@ void dram_init_banksize(void);
 int default_print_cpuinfo(void);
 
 /* Set up a UART which can be used with printch(), printhex8(), etc. */
-int setup_early_uart(void);
+int setup_internal_uart(int enable);
 
 void setup_pcat_compatibility(void);
 
index d9fc296b6e4877a1a3b3a8766fe7d54f6ac54d67..50bc69a659f078ad8a0ec022d0083bcab9d4444d 100644 (file)
@@ -32,7 +32,9 @@ obj-$(CONFIG_X86_RAMTEST) += ramtest.o
 obj-y += sfi.o
 obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
 obj-y  += string.o
+ifndef CONFIG_QEMU_ACPI_TABLE
 obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
+endif
 obj-y  += tables.o
 obj-$(CONFIG_CMD_ZBOOT)        += zimage.o
 obj-$(CONFIG_HAVE_FSP) += fsp/
index ab1db7ec26eee8e08aabf101aa4add678415e5da..2ec5ad2fa4a0d11f7b56984036d739c50ccb63c3 100644 (file)
@@ -331,6 +331,10 @@ static void acpi_create_ssdt_generator(acpi_header_t *ssdt,
        ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
 }
 
+/*
+ * QEMU's version of write_acpi_tables is defined in
+ * arch/x86/cpu/qemu/fw_cfg.c
+ */
 unsigned long write_acpi_tables(unsigned long start)
 {
        unsigned long current;
index 875c96a8f19a47961b366d2f1ea400e3270ac347..29fa06098d1afb30f61e38683538ff62ce119b9f 100644 (file)
@@ -111,7 +111,7 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
 #endif
 
 #ifdef CONFIG_DEBUG_UART
-       setup_early_uart();
+       setup_internal_uart(1);
 #endif
 
        fsp_hdr = find_fsp_header();
index 36aaef011de9956dc6f3a6921024f8458b8b1448..6d9cb10edc85233bf25536ba971eadcdb19474ba 100644 (file)
@@ -706,7 +706,7 @@ the board, then you can use post_code() calls from C or assembler to monitor
 boot progress. This can be good for debugging.
 
 If not, you can try to get serial working as early as possible. The early
-debug serial port may be useful here. See setup_early_uart() for an example.
+debug serial port may be useful here. See setup_internal_uart() for an example.
 
 During the U-Boot porting, one of the important steps is to write correct PIRQ
 routing information in the board device tree. Without it, device drivers in the
index b44b5b5431f8e65cf7652832314959dc23b8576b..07fa46ef7ef557b095da01cd86b1a255d1160745 100644 (file)
@@ -74,12 +74,41 @@ discovered by the FSP and used to setup main memory.
 
        # Integer properties:
 
-       - fsp,dram-speed
+       - fsp,dram-speed:
+         0x0: "800 MHz"
+         0x1: "1066 MHz"
+         0x2: "1333 MHz"
+         0x3: "1600 MHz"
+
        - fsp,dram-type
+         0x0: "DDR3"
+         0x1: "DDR3L"
+         0x2: "DDR3U"
+         0x4: "LPDDR2"
+         0x5: "LPDDR3"
+         0x6: "DDR4"
+
        - fsp,dimm-width
+         0x0: "x8"
+         0x1: "x16"
+         0x2: "x32"
+
        - fsp,dimm-density
+         0x0: "1 Gbit"
+         0x1: "2 Gbit"
+         0x2: "4 Gbit"
+         0x3: "8 Gbit"
+
        - fsp,dimm-bus-width
+         0x0: "8 bits"
+         0x1: "16 bits"
+         0x2: "32 bits"
+         0x3: "64 bits"
+
        - fsp,dimm-sides
+         0x0: "1 rank"
+         0x1: "2 ranks"
+
        - fsp,dimm-tcl
        - fsp,dimm-trpt-rcd
        - fsp,dimm-twr
index cba236334c0e400101ff53c31ea1e8c57568b655..af8667f030c52c4f266351714df15401a301d372 100644 (file)
@@ -130,4 +130,12 @@ config RESET
          effect a reset. The uclass will try all available drivers when
          reset_walk() is called.
 
+config WINBOND_W83627
+       bool "Enable Winbond Super I/O driver"
+       help
+         If you say Y here, you will get support for the Winbond
+         W83627 Super I/O driver. This can be used to enable the
+         legacy UART or other devices in the Winbond Super IO chips
+         on X86 platforms.
+
 endmenu
index cd4846b4a8e93794990eb21e4b7cf8297997458d..e1e3c6b70fc047d746882e28cc40c38223e47438 100644 (file)
@@ -41,3 +41,4 @@ obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
 obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
 obj-$(CONFIG_RESET) += reset-uclass.o
 obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o
+obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
diff --git a/drivers/misc/winbond_w83627.c b/drivers/misc/winbond_w83627.c
new file mode 100644 (file)
index 0000000..59db7d9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/pnp_def.h>
+
+#define WINBOND_ENTRY_KEY      0x87
+#define WINBOND_EXIT_KEY       0xaa
+
+/* Enable configuration: pass entry key '0x87' into index port dev twice */
+static void pnp_enter_conf_state(u16 dev)
+{
+       u16 port = dev >> 8;
+
+       outb(WINBOND_ENTRY_KEY, port);
+       outb(WINBOND_ENTRY_KEY, port);
+}
+
+/* Disable configuration: pass exit key '0xAA' into index port dev */
+static void pnp_exit_conf_state(u16 dev)
+{
+       u16 port = dev >> 8;
+
+       outb(WINBOND_EXIT_KEY, port);
+}
+
+/* Bring up early serial debugging output before the RAM is initialized */
+void winbond_enable_serial(uint dev, uint iobase, uint irq)
+{
+       pnp_enter_conf_state(dev);
+       pnp_set_logical_device(dev);
+       pnp_set_enable(dev, 0);
+       pnp_set_iobase(dev, PNP_IDX_IO0, iobase);
+       pnp_set_irq(dev, PNP_IDX_IRQ0, irq);
+       pnp_set_enable(dev, 1);
+       pnp_exit_conf_state(dev);
+}
index 4182a3bf6314a5ee2dbf596fce5c780598d8f46c..dc7b227d25c41e3061a521a2ad196237a666e362 100644 (file)
  * Command line configuration.
  */
 #define CONFIG_CMD_DATE
+#define CONFIG_CMD_FS_GENERIC
 #define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_IO
 #define CONFIG_CMD_IRQ
diff --git a/include/winbond_w83627.h b/include/winbond_w83627.h
new file mode 100644 (file)
index 0000000..ac3bec6
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _WINBOND_W83627_H_
+#define _WINBOND_W83627_H_
+
+/* I/O address of Winbond Super IO chip */
+#define WINBOND_IO_PORT                0x2e
+
+/* Logical device number */
+#define W83627DHG_FDC          0       /* Floppy */
+#define W83627DHG_PP           1       /* Parallel port */
+#define W83627DHG_SP1          2       /* Com1 */
+#define W83627DHG_SP2          3       /* Com2 */
+#define W83627DHG_KBC          5       /* PS/2 keyboard & mouse */
+#define W83627DHG_SPI          6       /* Serial peripheral interface */
+#define W83627DHG_WDTO_PLED    8       /* WDTO#, PLED */
+#define W83627DHG_ACPI         10      /* ACPI */
+#define W83627DHG_HWM          11      /* Hardware monitor */
+#define W83627DHG_PECI_SST     12      /* PECI, SST */
+
+/**
+ * Configure the base I/O port of the specified serial device and enable the
+ * serial device.
+ *
+ * @dev: high 8 bits = super I/O port, low 8 bits = logical device number
+ * @iobase: processor I/O port address to assign to this serial device
+ * @irq: processor IRQ number to assign to this serial device
+ */
+void winbond_enable_serial(uint dev, uint iobase, uint irq);
+
+#endif /* _WINBOND_W83627_H_ */