Merge branch 'master' of git://git.denx.de/u-boot-x86
This commit is contained in:
commit
4b5a4a0535
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10,10 +10,16 @@
|
|||
#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;
|
||||
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);
|
||||
}
|
||||
|
||||
files->count = count;
|
||||
qemu_fwcfg_read_entry(FW_CFG_INVALID,
|
||||
count * sizeof(struct fw_cfg_file),
|
||||
files->files);
|
||||
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);
|
||||
}
|
||||
|
||||
for (i = 0; i < files->count; i++)
|
||||
printf("%-56s\n", files->files[i].name);
|
||||
free(files);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,31 @@
|
|||
|
||||
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();
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
aliases {
|
||||
serial0 = &serial;
|
||||
spi0 = "/spi";
|
||||
spi0 = &spi;
|
||||
};
|
||||
|
||||
config {
|
||||
|
@ -184,7 +184,7 @@
|
|||
>;
|
||||
};
|
||||
|
||||
spi {
|
||||
spi: spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "intel,ich-spi";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
compatible = "google,link", "intel,celeron-ivybridge";
|
||||
|
||||
aliases {
|
||||
spi0 = "/pci/pch/spi";
|
||||
spi0 = &spi;
|
||||
usb0 = &usb_0;
|
||||
usb1 = &usb_1;
|
||||
};
|
||||
|
@ -252,7 +252,7 @@
|
|||
/* Enable EC SMI source */
|
||||
intel,alt-gp-smi-enable = <0x0100>;
|
||||
|
||||
spi {
|
||||
spi: spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "intel,ich-spi";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
compatible = "intel,crownbay", "intel,queensbay";
|
||||
|
||||
aliases {
|
||||
spi0 = "/spi";
|
||||
spi0 = &spi;
|
||||
};
|
||||
|
||||
config {
|
||||
|
@ -227,7 +227,7 @@
|
|||
>;
|
||||
};
|
||||
|
||||
spi {
|
||||
spi: spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "intel,ich-spi";
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
compatible = "intel,galileo", "intel,quark";
|
||||
|
||||
aliases {
|
||||
spi0 = "/spi";
|
||||
spi0 = &spi;
|
||||
};
|
||||
|
||||
config {
|
||||
|
@ -115,7 +115,7 @@
|
|||
>;
|
||||
};
|
||||
|
||||
spi {
|
||||
spi: spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "intel,ich-spi";
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
aliases {
|
||||
serial0 = &serial;
|
||||
spi0 = "/spi";
|
||||
spi0 = &spi;
|
||||
};
|
||||
|
||||
config {
|
||||
|
@ -218,7 +218,7 @@
|
|||
>;
|
||||
};
|
||||
|
||||
spi {
|
||||
spi: spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "intel,ich-spi";
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -100,6 +100,7 @@
|
|||
* 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
|
||||
|
|
|
@ -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_ */
|
Loading…
Reference in New Issue