summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorStefano Babic <sbabic@denx.de>2015-07-17 11:22:56 +0200
committerStefano Babic <sbabic@denx.de>2015-07-17 11:22:56 +0200
commitf448c5d3200372fa73f340144d013fdecf4e2f1f (patch)
treeb17b66f67a22b553f66bcb22e69d62cb2a5bbe7e /arch
parent425640256a7c5e9259f7583ee4eca1f3b70f8032 (diff)
parent605e15db2b54302364a2528d3c6604fbc57be846 (diff)
Merge branch 'master' of git://git.denx.de/u-boot
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/cpu/armv7/stv0991/clock.c4
-rw-r--r--arch/arm/cpu/armv7/stv0991/pinmux.c5
-rw-r--r--arch/arm/dts/socfpga.dtsi1
-rw-r--r--arch/arm/dts/stv0991.dts30
-rw-r--r--arch/arm/include/asm/arch-stv0991/stv0991_cgu.h15
-rw-r--r--arch/arm/include/asm/arch-stv0991/stv0991_creg.h9
-rw-r--r--arch/arm/include/asm/arch-stv0991/stv0991_periph.h2
-rw-r--r--arch/arm/mach-mvebu/cpu.c66
-rw-r--r--arch/arm/mach-mvebu/include/mach/cpu.h2
-rw-r--r--arch/arm/mach-mvebu/include/mach/gpio.h10
-rw-r--r--arch/arm/mach-mvebu/include/mach/soc.h3
-rw-r--r--arch/mips/include/asm/cacheops.h2
-rw-r--r--arch/mips/include/asm/io.h12
-rw-r--r--arch/mips/include/asm/system.h6
-rw-r--r--arch/x86/Kconfig78
-rw-r--r--arch/x86/cpu/Makefile4
-rw-r--r--arch/x86/cpu/baytrail/Makefile1
-rw-r--r--arch/x86/cpu/baytrail/cpu.c101
-rw-r--r--arch/x86/cpu/baytrail/pci.c46
-rw-r--r--arch/x86/cpu/config.mk6
-rw-r--r--arch/x86/cpu/coreboot/pci.c22
-rw-r--r--arch/x86/cpu/cpu.c108
-rw-r--r--arch/x86/cpu/cpu_x86.c76
-rw-r--r--arch/x86/cpu/ioapic.c21
-rw-r--r--arch/x86/cpu/irq.c68
-rw-r--r--arch/x86/cpu/ivybridge/Kconfig1
-rw-r--r--arch/x86/cpu/ivybridge/model_206ax.c2
-rw-r--r--arch/x86/cpu/lapic.c153
-rw-r--r--arch/x86/cpu/mp_init.c47
-rw-r--r--arch/x86/cpu/queensbay/Kconfig4
-rw-r--r--arch/x86/cpu/queensbay/tnc.c13
-rw-r--r--arch/x86/cpu/start.S6
-rw-r--r--arch/x86/cpu/start16.S5
-rw-r--r--arch/x86/dts/crownbay.dts65
-rw-r--r--arch/x86/dts/minnowmax.dts10
-rw-r--r--arch/x86/dts/rtc.dtsi6
-rw-r--r--arch/x86/include/asm/arch-ivybridge/bd82x6x.h14
-rw-r--r--arch/x86/include/asm/cpu.h14
-rw-r--r--arch/x86/include/asm/cpu_x86.h34
-rw-r--r--arch/x86/include/asm/ioapic.h46
-rw-r--r--arch/x86/include/asm/lapic.h229
-rw-r--r--arch/x86/include/asm/lapic_def.h101
-rw-r--r--arch/x86/include/asm/mp.h1
-rw-r--r--arch/x86/include/asm/mpspec.h444
-rw-r--r--arch/x86/include/asm/mtrr.h27
-rw-r--r--arch/x86/include/asm/tables.h14
-rw-r--r--arch/x86/include/asm/u-boot-x86.h10
-rw-r--r--arch/x86/include/asm/zimage.h1
-rw-r--r--arch/x86/lib/Makefile1
-rw-r--r--arch/x86/lib/bios_asm.S23
-rw-r--r--arch/x86/lib/bios_interrupts.c10
-rw-r--r--arch/x86/lib/cmd_mtrr.c3
-rw-r--r--arch/x86/lib/fsp/fsp_car.S26
-rw-r--r--arch/x86/lib/fsp/fsp_common.c8
-rw-r--r--arch/x86/lib/fsp/fsp_support.c3
-rw-r--r--arch/x86/lib/mpspec.c382
-rw-r--r--arch/x86/lib/tables.c19
-rw-r--r--arch/x86/lib/zimage.c2
59 files changed, 1798 insertions, 627 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9908b430d6..506463c12c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -227,6 +227,9 @@ config TARGET_STV0991
select CPU_V7
select DM
select DM_SERIAL
+ select DM_SPI
+ select DM_SPI_FLASH
+ select SPI_FLASH
config TARGET_X600
bool "Support x600"
diff --git a/arch/arm/cpu/armv7/stv0991/clock.c b/arch/arm/cpu/armv7/stv0991/clock.c
index 70b8a8d984..26c0d3637d 100644
--- a/arch/arm/cpu/armv7/stv0991/clock.c
+++ b/arch/arm/cpu/armv7/stv0991/clock.c
@@ -33,7 +33,9 @@ void clock_setup(int peripheral)
/* Clock selection for ethernet tx_clk & rx_clk*/
writel((readl(&stv0991_cgu_regs->eth_ctrl) & ETH_CLK_MASK)
| ETH_CLK_CTRL, &stv0991_cgu_regs->eth_ctrl);
-
+ break;
+ case QSPI_CLOCK_CFG:
+ writel(QSPI_CLK_CTRL, &stv0991_cgu_regs->qspi_freq);
break;
default:
break;
diff --git a/arch/arm/cpu/armv7/stv0991/pinmux.c b/arch/arm/cpu/armv7/stv0991/pinmux.c
index 1d086a235d..24c67faaea 100644
--- a/arch/arm/cpu/armv7/stv0991/pinmux.c
+++ b/arch/arm/cpu/armv7/stv0991/pinmux.c
@@ -55,6 +55,11 @@ int stv0991_pinmux_config(int peripheral)
ETH_M_VDD_CFG, &stv0991_creg->vdd_pad1);
break;
+ case QSPI_CS_CLK_PAD:
+ writel((readl(&stv0991_creg->mux13) & FLASH_CS_NC_MASK) |
+ CFG_FLASH_CS_NC, &stv0991_creg->mux13);
+ writel((readl(&stv0991_creg->mux13) & FLASH_CLK_MASK) |
+ CFG_FLASH_CLK, &stv0991_creg->mux13);
default:
break;
}
diff --git a/arch/arm/dts/socfpga.dtsi b/arch/arm/dts/socfpga.dtsi
index bf791c5dde..9b1242025d 100644
--- a/arch/arm/dts/socfpga.dtsi
+++ b/arch/arm/dts/socfpga.dtsi
@@ -639,6 +639,7 @@
ext-decoder = <0>; /* external decoder */
num-cs = <4>;
fifo-depth = <128>;
+ sram-size = <128>;
bus-num = <2>;
status = "disabled";
};
diff --git a/arch/arm/dts/stv0991.dts b/arch/arm/dts/stv0991.dts
index b25c48bcec..fa3fd641b2 100644
--- a/arch/arm/dts/stv0991.dts
+++ b/arch/arm/dts/stv0991.dts
@@ -20,4 +20,34 @@
reg = <0x80406000 0x1000>;
clock = <2700000>;
};
+
+ aliases {
+ spi0 = "/spi@80203000"; /* QSPI */
+ };
+
+ qspi: spi@80203000 {
+ compatible = "cadence,qspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x80203000 0x100>,
+ <0x40000000 0x1000000>;
+ clocks = <3750000>;
+ sram-size = <256>;
+ status = "okay";
+
+ flash0: n25q32@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-flash";
+ reg = <0>; /* chip select */
+ spi-max-frequency = <50000000>;
+ m25p,fast-read;
+ page-size = <256>;
+ block-size = <16>; /* 2^16, 64KB */
+ tshsl-ns = <50>;
+ tsd2d-ns = <50>;
+ tchsh-ns = <4>;
+ tslch-ns = <4>;
+ };
+ };
};
diff --git a/arch/arm/include/asm/arch-stv0991/stv0991_cgu.h b/arch/arm/include/asm/arch-stv0991/stv0991_cgu.h
index ddcbb57a92..f0045f3e04 100644
--- a/arch/arm/include/asm/arch-stv0991/stv0991_cgu.h
+++ b/arch/arm/include/asm/arch-stv0991/stv0991_cgu.h
@@ -113,4 +113,19 @@ struct stv0991_cgu_regs {
#define ETH_CLK_CTRL (ETH_CLK_RX_EXT_PHY << RX_CLK_SHIFT \
| ETH_CLK_TX_EXT_PHY)
+/* CGU qspi clock */
+#define DIV_HCLK1_SHIFT 9
+#define DIV_CRYP_SHIFT 6
+#define MDIV_QSPI_SHIFT 3
+
+#define CLK_QSPI_OSC 0
+#define CLK_QSPI_MCLK 1
+#define CLK_QSPI_PLL1 2
+#define CLK_QSPI_PLL2 3
+
+#define QSPI_CLK_CTRL (3 << DIV_HCLK1_SHIFT \
+ | 1 << DIV_CRYP_SHIFT \
+ | 0 << MDIV_QSPI_SHIFT \
+ | CLK_QSPI_OSC)
+
#endif
diff --git a/arch/arm/include/asm/arch-stv0991/stv0991_creg.h b/arch/arm/include/asm/arch-stv0991/stv0991_creg.h
index c804eb5e4c..737c95253b 100644
--- a/arch/arm/include/asm/arch-stv0991/stv0991_creg.h
+++ b/arch/arm/include/asm/arch-stv0991/stv0991_creg.h
@@ -49,6 +49,15 @@ struct stv0991_creg {
u32 vdd_comp1; /* offset 0x400 */
};
+/* CREG MUX 13 register */
+#define FLASH_CS_NC_SHIFT 4
+#define FLASH_CS_NC_MASK ~(7 << FLASH_CS_NC_SHIFT)
+#define CFG_FLASH_CS_NC (0 << FLASH_CS_NC_SHIFT)
+
+#define FLASH_CLK_SHIFT 0
+#define FLASH_CLK_MASK ~(7 << FLASH_CLK_SHIFT)
+#define CFG_FLASH_CLK (0 << FLASH_CLK_SHIFT)
+
/* CREG MUX 12 register */
#define GPIOC_30_MUX_SHIFT 24
#define GPIOC_30_MUX_MASK ~(1 << GPIOC_30_MUX_SHIFT)
diff --git a/arch/arm/include/asm/arch-stv0991/stv0991_periph.h b/arch/arm/include/asm/arch-stv0991/stv0991_periph.h
index f728c83cb7..725da838b8 100644
--- a/arch/arm/include/asm/arch-stv0991/stv0991_periph.h
+++ b/arch/arm/include/asm/arch-stv0991/stv0991_periph.h
@@ -18,6 +18,7 @@ enum periph_id {
UART_GPIOC_30_31 = 0,
UART_GPIOB_16_17,
ETH_GPIOB_10_31_C_0_4,
+ QSPI_CS_CLK_PAD,
PERIPH_ID_I2C0,
PERIPH_ID_I2C1,
PERIPH_ID_I2C2,
@@ -39,6 +40,7 @@ enum periph_id {
enum periph_clock {
UART_CLOCK_CFG = 0,
ETH_CLOCK_CFG,
+ QSPI_CLOCK_CFG,
};
#endif /* __ASM_ARM_ARCH_PERIPH_H */
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 0121db8bb5..9bc9f002d8 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -6,10 +6,13 @@
#include <common.h>
#include <netdev.h>
+#include <ahci.h>
+#include <linux/mbus.h>
#include <asm/io.h>
#include <asm/pl310.h>
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
+#include <sdhci.h>
#define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3))
#define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3))
@@ -245,6 +248,69 @@ int cpu_eth_init(bd_t *bis)
}
#endif
+#ifdef CONFIG_MV_SDHCI
+int board_mmc_init(bd_t *bis)
+{
+ mv_sdh_init(MVEBU_SDIO_BASE, 0, 0,
+ SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_SCSI_AHCI_PLAT
+#define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0
+#define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4
+
+#define AHCI_WINDOW_CTRL(win) (0x60 + ((win) << 4))
+#define AHCI_WINDOW_BASE(win) (0x64 + ((win) << 4))
+#define AHCI_WINDOW_SIZE(win) (0x68 + ((win) << 4))
+
+static void ahci_mvebu_mbus_config(void __iomem *base)
+{
+ const struct mbus_dram_target_info *dram;
+ int i;
+
+ dram = mvebu_mbus_dram_info();
+
+ for (i = 0; i < 4; i++) {
+ writel(0, base + AHCI_WINDOW_CTRL(i));
+ writel(0, base + AHCI_WINDOW_BASE(i));
+ writel(0, base + AHCI_WINDOW_SIZE(i));
+ }
+
+ for (i = 0; i < dram->num_cs; i++) {
+ const struct mbus_dram_window *cs = dram->cs + i;
+
+ writel((cs->mbus_attr << 8) |
+ (dram->mbus_dram_target_id << 4) | 1,
+ base + AHCI_WINDOW_CTRL(i));
+ writel(cs->base >> 16, base + AHCI_WINDOW_BASE(i));
+ writel(((cs->size - 1) & 0xffff0000),
+ base + AHCI_WINDOW_SIZE(i));
+ }
+}
+
+static void ahci_mvebu_regret_option(void __iomem *base)
+{
+ /*
+ * Enable the regret bit to allow the SATA unit to regret a
+ * request that didn't receive an acknowlegde and avoid a
+ * deadlock
+ */
+ writel(0x4, base + AHCI_VENDOR_SPECIFIC_0_ADDR);
+ writel(0x80, base + AHCI_VENDOR_SPECIFIC_0_DATA);
+}
+
+void scsi_init(void)
+{
+ printf("MVEBU SATA INIT\n");
+ ahci_mvebu_mbus_config((void __iomem *)MVEBU_SATA0_BASE);
+ ahci_mvebu_regret_option((void __iomem *)MVEBU_SATA0_BASE);
+ ahci_init((void __iomem *)MVEBU_SATA0_BASE);
+}
+#endif
+
#ifndef CONFIG_SYS_DCACHE_OFF
void enable_caches(void)
{
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index 3b48460a0b..4bdb6331e1 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -114,6 +114,8 @@ void mvebu_sdram_size_adjust(enum memory_bank bank);
int mvebu_mbus_probe(struct mbus_win windows[], int count);
int mvebu_soc_family(void);
+int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks);
+
/*
* Highspeed SERDES PHY config init, ported from bin_hdr
* to mainline U-Boot
diff --git a/arch/arm/mach-mvebu/include/mach/gpio.h b/arch/arm/mach-mvebu/include/mach/gpio.h
new file mode 100644
index 0000000000..09e3c503dd
--- /dev/null
+++ b/arch/arm/mach-mvebu/include/mach/gpio.h
@@ -0,0 +1,10 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __MACH_MVEBU_GPIO_H
+#define __MACH_MVEBU_GPIO_H
+
+/* Empty file - sdhci requires this. */
+
+#endif
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 0a9307c8ce..1aaea672ee 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -49,8 +49,11 @@
#define MVEBU_EGIGA2_BASE (MVEBU_REGISTER(0x30000))
#define MVEBU_EGIGA3_BASE (MVEBU_REGISTER(0x34000))
#define MVEBU_REG_PCIE_BASE (MVEBU_REGISTER(0x40000))
+#define MVEBU_USB20_BASE (MVEBU_REGISTER(0x58000))
#define MVEBU_EGIGA0_BASE (MVEBU_REGISTER(0x70000))
#define MVEBU_EGIGA1_BASE (MVEBU_REGISTER(0x74000))
+#define MVEBU_SATA0_BASE (MVEBU_REGISTER(0xa8000))
+#define MVEBU_SDIO_BASE (MVEBU_REGISTER(0xd8000))
#define SDRAM_MAX_CS 4
#define SDRAM_ADDR_MASK 0xFF000000
diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h
index 75ec380980..af2adc701e 100644
--- a/arch/mips/include/asm/cacheops.h
+++ b/arch/mips/include/asm/cacheops.h
@@ -18,7 +18,7 @@ static inline void mips_cache(int op, const volatile void *addr)
#ifdef __GCC_HAVE_BUILTIN_MIPS_CACHE
__builtin_mips_cache(op, addr);
#else
- __asm__ __volatile__("cache %0, %1" : : "i"(op), "R"(addr))
+ __asm__ __volatile__("cache %0, %1" : : "i"(op), "R"(addr));
#endif
}
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 3fa37f5dd2..a7ab087c0d 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -117,7 +117,7 @@ static inline void set_io_port_base(unsigned long base)
* Change virtual addresses to physical addresses and vv.
* These are trivial on the 1:1 Linux/MIPS mapping
*/
-extern inline phys_addr_t virt_to_phys(volatile void * address)
+static inline phys_addr_t virt_to_phys(volatile void * address)
{
#ifndef CONFIG_64BIT
return CPHYSADDR(address);
@@ -126,7 +126,7 @@ extern inline phys_addr_t virt_to_phys(volatile void * address)
#endif
}
-extern inline void * phys_to_virt(unsigned long address)
+static inline void * phys_to_virt(unsigned long address)
{
#ifndef CONFIG_64BIT
return (void *)KSEG0ADDR(address);
@@ -138,7 +138,7 @@ extern inline void * phys_to_virt(unsigned long address)
/*
* IO bus memory addresses are also 1:1 with the physical address
*/
-extern inline unsigned long virt_to_bus(volatile void * address)
+static inline unsigned long virt_to_bus(volatile void * address)
{
#ifndef CONFIG_64BIT
return CPHYSADDR(address);
@@ -147,7 +147,7 @@ extern inline unsigned long virt_to_bus(volatile void * address)
#endif
}
-extern inline void * bus_to_virt(unsigned long address)
+static inline void * bus_to_virt(unsigned long address)
{
#ifndef CONFIG_64BIT
return (void *)KSEG0ADDR(address);
@@ -165,12 +165,12 @@ extern unsigned long isa_slot_offset;
extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
#if 0
-extern inline void *ioremap(unsigned long offset, unsigned long size)
+static inline void *ioremap(unsigned long offset, unsigned long size)
{
return __ioremap(offset, size, _CACHE_UNCACHED);
}
-extern inline void *ioremap_nocache(unsigned long offset, unsigned long size)
+static inline void *ioremap_nocache(unsigned long offset, unsigned long size)
{
return __ioremap(offset, size, _CACHE_UNCACHED);
}
diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h
index 7a2895284e..d56f73b8b8 100644
--- a/arch/mips/include/asm/system.h
+++ b/arch/mips/include/asm/system.h
@@ -22,7 +22,7 @@
#include <linux/kernel.h>
#endif
-extern __inline__ void
+static __inline__ void
__sti(void)
{
__asm__ __volatile__(
@@ -46,7 +46,7 @@ __sti(void)
* R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
* no nops at all.
*/
-extern __inline__ void
+static __inline__ void
__cli(void)
{
__asm__ __volatile__(
@@ -207,7 +207,7 @@ do { \
* For 32 and 64 bit operands we can take advantage of ll and sc.
* FIXME: This doesn't work for R3000 machines.
*/
-extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
+static __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
{
#ifdef CONFIG_CPU_HAS_LLSC
unsigned long dummy;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 20083e68c3..cbbaa4f2ce 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -69,6 +69,21 @@ config X86_RESET_VECTOR
bool
default n
+config RESET_SEG_START
+ hex
+ depends on X86_RESET_VECTOR
+ default 0xffff0000
+
+config RESET_SEG_SIZE
+ hex
+ depends on X86_RESET_VECTOR
+ default 0x10000
+
+config RESET_VEC_LOC
+ hex
+ depends on X86_RESET_VECTOR
+ default 0xfffffff0
+
config SYS_X86_START16
hex
depends on X86_RESET_VECTOR
@@ -173,14 +188,6 @@ config X86_RAMTEST
to work correctly. It is not exhaustive but can save time by
detecting obvious failures.
-config MARK_GRAPHICS_MEM_WRCOMB
- bool "Mark graphics memory as write-combining"
- default n
- help
- The graphics performance may increase if the graphics
- memory is set as write-combining cache type. This option
- enables marking the graphics memory as write-combining.
-
config HAVE_FSP
bool "Add an Firmware Support Package binary"
help
@@ -220,17 +227,6 @@ config FSP_TEMP_RAM_ADDR
Stack top address which is used in FspInit after DRAM is ready and
CAR is disabled.
-config MAX_CPUS
- int "Maximum number of CPUs permitted"
- default 4
- help
- When using multi-CPU chips it is possible for U-Boot to start up
- more than one CPU. The stack memory used by all of these CPUs is
- pre-allocated so at present U-Boot wants to know the maximum
- number of CPUs that may be present. Set this to at least as high
- as the number of CPUs in your system (it uses about 4KB of RAM for
- each CPU).
-
config SMP
bool "Enable Symmetric Multiprocessing"
default n
@@ -241,8 +237,21 @@ config SMP
only one CPU will be enabled regardless of the number of CPUs
available.
+config MAX_CPUS
+ int "Maximum number of CPUs permitted"
+ depends on SMP
+ default 4
+ help
+ When using multi-CPU chips it is possible for U-Boot to start up
+ more than one CPU. The stack memory used by all of these CPUs is
+ pre-allocated so at present U-Boot wants to know the maximum
+ number of CPUs that may be present. Set this to at least as high
+ as the number of CPUs in your system (it uses about 4KB of RAM for
+ each CPU).
+
config AP_STACK_SIZE
hex
+ depends on SMP
default 0x1000
help
Each additional CPU started by U-Boot requires its own stack. This
@@ -270,6 +279,28 @@ config TSC_FREQ_IN_MHZ
help
The running frequency in MHz of Time-Stamp Counter (TSC).
+config HAVE_VGA_BIOS
+ bool "Add a VGA BIOS image"
+ help
+ Select this option if you have a VGA BIOS image that you would
+ like to add to your ROM.
+
+config VGA_BIOS_FILE
+ string "VGA BIOS image filename"
+ depends on HAVE_VGA_BIOS
+ default "vga.bin"
+ help
+ The filename of the VGA BIOS image in the board directory.
+
+config VGA_BIOS_ADDR
+ hex "VGA BIOS image location"
+ depends on HAVE_VGA_BIOS
+ default 0xfff90000
+ help
+ The location of VGA BIOS image in the SPI flash. For example, base
+ address of 0xfff90000 indicates that the image will be put at offset
+ 0x90000 from the beginning of a 1MB flash device.
+
menu "System tables"
config GENERATE_PIRQ_TABLE
@@ -296,6 +327,15 @@ config GENERATE_SFI_TABLE
For more information, see http://simplefirmware.org
+config GENERATE_MP_TABLE
+ bool "Generate an MP (Multi-Processor) table"
+ default n
+ help
+ Generate an MP (Multi-Processor) table for this board. The MP table
+ provides a way for the operating system to support for symmetric
+ multiprocessing as well as symmetric I/O interrupt handling with
+ the local APIC and I/O APIC.
+
endmenu
config MAX_PIRQ_LINKS
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 7ff05e6628..8a8e63e1d3 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -10,7 +10,7 @@
extra-y = start.o
obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
-obj-y += interrupts.o cpu.o call64.o
+obj-y += interrupts.o cpu.o cpu_x86.o call64.o
obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
obj-$(CONFIG_SYS_COREBOOT) += coreboot/
@@ -19,7 +19,7 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
obj-$(CONFIG_INTEL_QUARK) += quark/
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
-obj-y += irq.o lapic.o
+obj-y += irq.o lapic.o ioapic.o
obj-$(CONFIG_SMP) += mp_init.o
obj-y += mtrr.o
obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/x86/cpu/baytrail/Makefile b/arch/x86/cpu/baytrail/Makefile
index c78b644eb7..5be5491643 100644
--- a/arch/x86/cpu/baytrail/Makefile
+++ b/arch/x86/cpu/baytrail/Makefile
@@ -7,5 +7,4 @@
obj-y += cpu.o
obj-y += early_uart.o
obj-y += fsp_configs.o
-obj-y += pci.o
obj-y += valleyview.o
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index 1d482064b2..a0117308ae 100644
--- a/arch/x86/cpu/baytrail/cpu.c
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -10,79 +10,11 @@
#include <cpu.h>
#include <dm.h>
#include <asm/cpu.h>
+#include <asm/cpu_x86.h>
#include <asm/lapic.h>
-#include <asm/mp.h>
#include <asm/msr.h>
#include <asm/turbo.h>
-#ifdef CONFIG_SMP
-static int enable_smis(struct udevice *cpu, void *unused)
-{
- return 0;
-}
-
-static struct mp_flight_record mp_steps[] = {
- MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
- /* Wait for APs to finish initialization before proceeding. */
- MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
-};
-
-static int detect_num_cpus(void)
-{
- int ecx = 0;
-
- /*
- * Use the algorithm described in Intel 64 and IA-32 Architectures
- * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
- * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
- * of CPUID Extended Topology Leaf.
- */
- while (1) {
- struct cpuid_result leaf_b;
-
- leaf_b = cpuid_ext(0xb, ecx);
-
- /*
- * Bay Trail doesn't have hyperthreading so just determine the
- * number of cores by from level type (ecx[15:8] == * 2)
- */
- if ((leaf_b.ecx & 0xff00) == 0x0200)
- return leaf_b.ebx & 0xffff;
- ecx++;
- }
-}
-
-static int baytrail_init_cpus(void)
-{
- struct mp_params mp_params;
-
- lapic_setup();
-
- mp_params.num_cpus = detect_num_cpus();
- mp_params.parallel_microcode_load = 0,
- mp_params.flight_plan = &mp_steps[0];
- mp_params.num_records = ARRAY_SIZE(mp_steps);
- mp_params.microcode_pointer = 0;
-
- if (mp_init(&mp_params)) {
- printf("Warning: MP init failure\n");
- return -EIO;
- }
-
- return 0;
-}
-#endif
-
-int x86_init_cpus(void)
-{
-#ifdef CONFIG_SMP
- debug("Init additional CPUs\n");
- baytrail_init_cpus();
-#endif
-
- return 0;
-}
-
static void set_max_freq(void)
{
msr_t perf_ctl;
@@ -175,19 +107,38 @@ static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
return 0;
}
-static int cpu_x86_baytrail_bind(struct udevice *dev)
+static int baytrail_get_count(struct udevice *dev)
{
- struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+ int ecx = 0;
+
+ /*
+ * Use the algorithm described in Intel 64 and IA-32 Architectures
+ * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
+ * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
+ * of CPUID Extended Topology Leaf.
+ */
+ while (1) {
+ struct cpuid_result leaf_b;
+
+ leaf_b = cpuid_ext(0xb, ecx);
+
+ /*
+ * Bay Trail doesn't have hyperthreading so just determine the
+ * number of cores by from level type (ecx[15:8] == * 2)
+ */
+ if ((leaf_b.ecx & 0xff00) == 0x0200)
+ return leaf_b.ebx & 0xffff;
- plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
- "intel,apic-id", -1);
+ ecx++;
+ }
return 0;
}
static const struct cpu_ops cpu_x86_baytrail_ops = {
- .get_desc = x86_cpu_get_desc,
+ .get_desc = cpu_x86_get_desc,
.get_info = baytrail_get_info,
+ .get_count = baytrail_get_count,
};
static const struct udevice_id cpu_x86_baytrail_ids[] = {
@@ -199,7 +150,7 @@ U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
.name = "cpu_x86_baytrail",
.id = UCLASS_CPU,
.of_match = cpu_x86_baytrail_ids,
- .bind = cpu_x86_baytrail_bind,
+ .bind = cpu_x86_bind,
.probe = cpu_x86_baytrail_probe,
.ops = &cpu_x86_baytrail_ops,
};
diff --git a/arch/x86/cpu/baytrail/pci.c b/arch/x86/cpu/baytrail/pci.c
deleted file mode 100644
index 48409de5c4..0000000000
--- a/arch/x86/cpu/baytrail/pci.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <pci.h>
-#include <asm/pci.h>
-#include <asm/fsp/fsp_support.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-void board_pci_setup_hose(struct pci_controller *hose)
-{
- hose->first_busno = 0;
- hose->last_busno = 0;
-
- /* PCI memory space */
- pci_set_region(hose->regions + 0,
- CONFIG_PCI_MEM_BUS,
- CONFIG_PCI_MEM_PHYS,
- CONFIG_PCI_MEM_SIZE,
- PCI_REGION_MEM);
-
- /* PCI IO space */
- pci_set_region(hose->regions + 1,
- CONFIG_PCI_IO_BUS,
- CONFIG_PCI_IO_PHYS,
- CONFIG_PCI_IO_SIZE,
- PCI_REGION_IO);
-
- pci_set_region(hose->regions + 2,
- CONFIG_PCI_PREF_BUS,
- CONFIG_PCI_PREF_PHYS,
- CONFIG_PCI_PREF_SIZE,
- PCI_REGION_PREFETCH);
-
- pci_set_region(hose->regions + 3,
- 0,
- 0,
- gd->ram_size < 0x80000000 ? gd->ram_size : 0x80000000,
- PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
-
- hose->region_count = 4;
-}
diff --git a/arch/x86/cpu/config.mk b/arch/x86/cpu/config.mk
index 4c4d0c7cd2..1263221e69 100644
--- a/arch/x86/cpu/config.mk
+++ b/arch/x86/cpu/config.mk
@@ -10,8 +10,8 @@ CROSS_COMPILE ?= i386-linux-
PLATFORM_CPPFLAGS += -D__I386__
# DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
-LDPPFLAGS += -DRESET_SEG_START=0xffff0000
-LDPPFLAGS += -DRESET_SEG_SIZE=0x10000
-LDPPFLAGS += -DRESET_VEC_LOC=0xfffffff0
+LDPPFLAGS += -DRESET_SEG_START=$(CONFIG_RESET_SEG_START)
+LDPPFLAGS += -DRESET_SEG_SIZE=$(CONFIG_RESET_SEG_SIZE)
+LDPPFLAGS += -DRESET_VEC_LOC=$(CONFIG_RESET_VEC_LOC)
LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16)
LDPPFLAGS += -DRESET_BASE="CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE)"
diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c
index 67eb14ce99..41e29a6086 100644
--- a/arch/x86/cpu/coreboot/pci.c
+++ b/arch/x86/cpu/coreboot/pci.c
@@ -11,29 +11,7 @@
#include <common.h>
#include <dm.h>
-#include <errno.h>
#include <pci.h>
-#include <asm/io.h>
-#include <asm/pci.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static const struct dm_pci_ops pci_x86_ops = {
- .read_config = pci_x86_read_config,
- .write_config = pci_x86_write_config,
-};
-
-static const struct udevice_id pci_x86_ids[] = {
- { .compatible = "pci-x86" },
- { }
-};
-
-U_BOOT_DRIVER(pci_x86_drv) = {
- .name = "pci_x86",
- .id = UCLASS_PCI,
- .of_match = pci_x86_ids,
- .ops = &pci_x86_ops,
-};
static const struct udevice_id generic_pch_ids[] = {
{ .compatible = "intel,pch" },
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index bb4a110c00..af927b94e0 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -21,12 +21,15 @@
#include <common.h>
#include <command.h>
-#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <asm/control_regs.h>
#include <asm/cpu.h>
+#include <asm/lapic.h>
+#include <asm/mp.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/processor.h>
#include <asm/processor-flags.h>
@@ -164,6 +167,26 @@ void setup_gdt(gd_t *id, u64 *gdt_addr)
load_fs(X86_GDT_ENTRY_32BIT_FS);
}
+#ifdef CONFIG_HAVE_FSP
+/*
+ * Setup FSP execution environment GDT
+ *
+ * Per Intel FSP external architecture specification, before calling any FSP
+ * APIs, we need make sure the system is in flat 32-bit mode and both the code
+ * and data selectors should have full 4GB access range. Here we reuse the one
+ * we used in arch/x86/cpu/start16.S, and reload the segement registers.
+ */
+void setup_fsp_gdt(void)
+{
+ load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4);
+ load_ds(X86_GDT_ENTRY_32BIT_DS);
+ load_ss(X86_GDT_ENTRY_32BIT_DS);
+ load_es(X86_GDT_ENTRY_32BIT_DS);
+ load_fs(X86_GDT_ENTRY_32BIT_DS);
+ load_gs(X86_GDT_ENTRY_32BIT_DS);
+}
+#endif
+
int __weak x86_cleanup_before_linux(void)
{
#ifdef CONFIG_BOOTSTAGE_STASH
@@ -330,6 +353,28 @@ int x86_cpu_init_f(void)
gd->arch.has_mtrr = has_mtrr();
}
+ /* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
+ gd->pci_ram_top = 0x80000000U;
+
+ /* Configure fixed range MTRRs for some legacy regions */
+ if (gd->arch.has_mtrr) {
+ u64 mtrr_cap;
+
+ mtrr_cap = native_read_msr(MTRR_CAP_MSR);
+ if (mtrr_cap & MTRR_CAP_FIX) {
+ /* Mark the VGA RAM area as uncacheable */
+ native_write_msr(MTRR_FIX_16K_A0000_MSR, 0, 0);
+
+ /* Mark the PCI ROM area as uncacheable */
+ native_write_msr(MTRR_FIX_4K_C0000_MSR, 0, 0);
+ native_write_msr(MTRR_FIX_4K_C8000_MSR, 0, 0);
+ native_write_msr(MTRR_FIX_4K_D0000_MSR, 0, 0);
+ native_write_msr(MTRR_FIX_4K_D8000_MSR, 0, 0);
+
+ /* Enable the fixed range MTRRs */
+ msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
+ }
+ }
return 0;
}
@@ -520,16 +565,6 @@ char *cpu_get_name(char *name)
return ptr;
}
-int x86_cpu_get_desc(struct udevice *dev, char *buf, int size)
-{
- if (size < CPU_MAX_NAME_LEN)
- return -ENOSPC;
-
- cpu_get_name(buf);
-
- return 0;
-}
-
int default_print_cpuinfo(void)
{
printf("CPU: %s, vendor %s, device %xh\n",
@@ -613,28 +648,47 @@ int last_stage_init(void)
}
#endif
-__weak int x86_init_cpus(void)
+#ifdef CONFIG_SMP
+static int enable_smis(struct udevice *cpu, void *unused)
{
return 0;
}
-int cpu_init_r(void)
+static struct mp_flight_record mp_steps[] = {
+ MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
+ /* Wait for APs to finish initialization before proceeding */
+ MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
+};
+
+static int x86_mp_init(void)
{
- return x86_init_cpus();
+ struct mp_params mp_params;
+
+ mp_params.parallel_microcode_load = 0,
+ mp_params.flight_plan = &mp_steps[0];
+ mp_params.num_records = ARRAY_SIZE(mp_steps);
+ mp_params.microcode_pointer = 0;
+
+ if (mp_init(&mp_params)) {
+ printf("Warning: MP init failure\n");
+ return -EIO;
+ }
+
+ return 0;
}
+#endif
-static const struct cpu_ops cpu_x86_ops = {
- .get_desc = x86_cpu_get_desc,
-};
+__weak int x86_init_cpus(void)
+{
+#ifdef CONFIG_SMP
+ debug("Init additional CPUs\n");
+ x86_mp_init();
+#endif
-static const struct udevice_id cpu_x86_ids[] = {
- { .compatible = "cpu-x86" },
- { }
-};
+ return 0;
+}
-U_BOOT_DRIVER(cpu_x86_drv) = {
- .name = "cpu_x86",
- .id = UCLASS_CPU,
- .of_match = cpu_x86_ids,
- .ops = &cpu_x86_ops,
-};
+int cpu_init_r(void)
+{
+ return x86_init_cpus();
+}
diff --git a/arch/x86/cpu/cpu_x86.c b/arch/x86/cpu/cpu_x86.c
new file mode 100644
index 0000000000..09410416a1
--- /dev/null
+++ b/arch/x86/cpu/cpu_x86.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/cpu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int cpu_x86_bind(struct udevice *dev)
+{
+ struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+
+ plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "intel,apic-id", -1);
+
+ return 0;
+}
+
+int cpu_x86_get_desc(struct udevice *dev, char *buf, int size)
+{
+ if (size < CPU_MAX_NAME_LEN)
+ return -ENOSPC;
+
+ cpu_get_name(buf);
+
+ return 0;
+}
+
+static int cpu_x86_get_count(struct udevice *dev)
+{
+ int node, cpu;
+ int num = 0;
+
+ node = fdt_path_offset(gd->fdt_blob, "/cpus");
+ if (node < 0)
+ return -ENOENT;
+
+ for (cpu = fdt_first_subnode(gd->fdt_blob, node);
+ cpu >= 0;
+ cpu = fdt_next_subnode(gd->fdt_blob, cpu)) {
+ const char *device_type;
+
+ device_type = fdt_getprop(gd->fdt_blob, cpu,
+ "device_type", NULL);
+ if (!device_type)
+ continue;
+ if (strcmp(device_type, "cpu") == 0)
+ num++;
+ }
+
+ return num;
+}
+
+static const struct cpu_ops cpu_x86_ops = {
+ .get_desc = cpu_x86_get_desc,
+ .get_count = cpu_x86_get_count,
+};
+
+static const struct udevice_id cpu_x86_ids[] = {
+ { .compatible = "cpu-x86" },
+ { }
+};
+
+U_BOOT_DRIVER(cpu_x86_drv) = {
+ .name = "cpu_x86",
+ .id = UCLASS_CPU,
+ .of_match = cpu_x86_ids,
+ .bind = cpu_x86_bind,
+ .ops = &cpu_x86_ops,
+};
diff --git a/arch/x86/cpu/ioapic.c b/arch/x86/cpu/ioapic.c
new file mode 100644
index 0000000000..112a9c63b4
--- /dev/null
+++ b/arch/x86/cpu/ioapic.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ioapic.h>
+
+u32 io_apic_read(u32 reg)
+{
+ writel(reg, IO_APIC_INDEX);
+ return readl(IO_APIC_DATA);
+}
+
+void io_apic_write(u32 reg, u32 val)
+{
+ writel(reg, IO_APIC_INDEX);
+ writel(val, IO_APIC_DATA);
+}
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c
index 74b89ad2ff..97dd000039 100644
--- a/arch/x86/cpu/irq.c
+++ b/arch/x86/cpu/irq.c
@@ -58,17 +58,28 @@ void pirq_assign_irq(int link, u8 irq)
writeb(irq, irq_router.ibase + LINK_N2V(link, base));
}
-static inline void fill_irq_info(struct irq_info **slotp, int *entries, u8 bus,
- u8 device, u8 func, u8 pin, u8 pirq)
+static struct irq_info *check_dup_entry(struct irq_info *slot_base,
+ int entry_num, int bus, int device)
{
- struct irq_info *slot = *slotp;
+ struct irq_info *slot = slot_base;
+ int i;
+
+ for (i = 0; i < entry_num; i++) {
+ if (slot->bus == bus && slot->devfn == (device << 3))
+ break;
+ slot++;
+ }
+ return (i == entry_num) ? NULL : slot;
+}
+
+static inline void fill_irq_info(struct irq_info *slot, int bus, int device,
+ int pin, int pirq)
+{
slot->bus = bus;
- slot->devfn = (device << 3) | func;
+ slot->devfn = (device << 3) | 0;
slot->irq[pin - 1].link = LINK_N2V(pirq, irq_router.link_base);
slot->irq[pin - 1].bitmap = irq_router.irq_mask;
- (*entries)++;
- (*slotp)++;
}
__weak void cpu_irq_init(void)
@@ -84,7 +95,7 @@ static int create_pirq_routing_table(void)
int len, count;
const u32 *cell;
struct irq_routing_table *rt;
- struct irq_info *slot;
+ struct irq_info *slot, *slot_base;
int irq_entries = 0;
int i;
int ret;
@@ -161,13 +172,13 @@ static int create_pirq_routing_table(void)
/* Populate the PIRQ table fields */
rt->signature = PIRQ_SIGNATURE;
rt->version = PIRQ_VERSION;
- rt->rtr_bus = 0;
+ rt->rtr_bus = PCI_BUS(irq_router.bdf);
rt->rtr_devfn = (PCI_DEV(irq_router.bdf) << 3) |
PCI_FUNC(irq_router.bdf);
rt->rtr_vendor = PCI_VENDOR_ID_INTEL;
rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31;
- slot = rt->slots;
+ slot_base = rt->slots;
/* Now fill in the irq_info entries in the PIRQ table */
for (i = 0; i < count; i++) {
@@ -181,9 +192,44 @@ static int create_pirq_routing_table(void)
i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
PCI_FUNC(pr.bdf), 'A' + pr.pin - 1,
'A' + pr.pirq);
- fill_irq_info(&slot, &irq_entries, PCI_BUS(pr.bdf),
- PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf),
+
+ slot = check_dup_entry(slot_base, irq_entries,
+ PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
+ if (slot) {
+ debug("found entry for bus %d device %d, ",
+ PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
+
+ if (slot->irq[pr.pin - 1].link) {
+ debug("skipping\n");
+
+ /*
+ * Sanity test on the routed PIRQ pin
+ *
+ * If they don't match, show a warning to tell
+ * there might be something wrong with the PIRQ
+ * routing information in the device tree.
+ */
+ if (slot->irq[pr.pin - 1].link !=
+ LINK_N2V(pr.pirq, irq_router.link_base))
+ debug("WARNING: Inconsistent PIRQ routing information\n");
+
+ cell += sizeof(struct pirq_routing) /
+ sizeof(u32);
+ continue;
+ } else {
+ debug("writing INT%c\n", 'A' + pr.pin - 1);
+ fill_irq_info(slot, PCI_BUS(pr.bdf),
+ PCI_DEV(pr.bdf), pr.pin, pr.pirq);
+ cell += sizeof(struct pirq_routing) /
+ sizeof(u32);
+ continue;
+ }
+ }
+
+ slot = slot_base + irq_entries;
+ fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
pr.pin, pr.pirq);
+ irq_entries++;
cell += sizeof(struct pirq_routing) / sizeof(u32);
}
diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig
index e4595be3ae..0e249a40a6 100644
--- a/arch/x86/cpu/ivybridge/Kconfig
+++ b/arch/x86/cpu/ivybridge/Kconfig
@@ -95,7 +95,6 @@ config CPU_SPECIFIC_OPTIONS
select ARCH_BOOTBLOCK_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
- select SMP
select SSE2
select UDELAY_LAPIC
select CPU_MICROCODE_IN_CBFS
diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c
index 8b08c40bcb..fd7db97cbd 100644
--- a/arch/x86/cpu/ivybridge/model_206ax.c
+++ b/arch/x86/cpu/ivybridge/model_206ax.c
@@ -13,12 +13,12 @@
#include <asm/acpi.h>
#include <asm/cpu.h>
#include <asm/lapic.h>
-#include <asm/lapic_def.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
#include <asm/processor.h>
#include <asm/speedstep.h>
#include <asm/turbo.h>
+#include <asm/arch/bd82x6x.h>
#include <asm/arch/model_206ax.h>
static void enable_vmx(void)
diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c
index 4690603c75..30d23130eb 100644
--- a/arch/x86/cpu/lapic.c
+++ b/arch/x86/cpu/lapic.c
@@ -8,50 +8,153 @@
*/
#include <common.h>
-#include <asm/msr.h>
#include <asm/io.h>
#include <asm/lapic.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
#include <asm/post.h>
+unsigned long lapic_read(unsigned long reg)
+{
+ return readl(LAPIC_DEFAULT_BASE + reg);
+}
+
+#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
+ sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+/*
+ * Note: no "lock" prefix even on SMP. xchg always implies lock anyway.
+ *
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ * but generally the primitive is invalid, *ptr is output argument.
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+ int size)
+{
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("xchgb %b0,%1"
+ : "=q" (x)
+ : "m" (*__xg(ptr)), "0" (x)
+ : "memory");
+ break;
+ case 2:
+ __asm__ __volatile__("xchgw %w0,%1"
+ : "=r" (x)
+ : "m" (*__xg(ptr)), "0" (x)
+ : "memory");
+ break;
+ case 4:
+ __asm__ __volatile__("xchgl %0,%1"
+ : "=r" (x)
+ : "m" (*__xg(ptr)), "0" (x)
+ : "memory");
+ break;
+ }
+
+ return x;
+}
+
+void lapic_write(unsigned long reg, unsigned long v)
+{
+ (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
+}
+
+void enable_lapic(void)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_IA32_APICBASE);
+ msr.hi &= 0xffffff00;
+ msr.lo |= MSR_IA32_APICBASE_ENABLE;
+ msr.lo &= ~MSR_IA32_APICBASE_BASE;
+ msr.lo |= LAPIC_DEFAULT_BASE;
+ msr_write(MSR_IA32_APICBASE, msr);
+}
+
+void disable_lapic(void)
+{
+ msr_t msr;
+
+ msr = msr_read(MSR_IA32_APICBASE);
+ msr.lo &= ~MSR_IA32_APICBASE_ENABLE;
+ msr_write(MSR_IA32_APICBASE, msr);
+}
+
+unsigned long lapicid(void)
+{
+ return lapic_read(LAPIC_ID) >> 24;
+}
+
+static void lapic_wait_icr_idle(void)
+{
+ do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
+}
+
+int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
+{
+ int timeout;
+ unsigned long status;
+ int result;
+
+ lapic_wait_icr_idle();
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
+ lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
+
+ timeout = 0;
+ do {
+ status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
+ } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
+
+ result = -1;
+ if (status == LAPIC_ICR_RR_VALID) {
+ *pvalue = lapic_read(LAPIC_RRR);
+ result = 0;
+ }
+
+ return result;
+}
+
void lapic_setup(void)
{
-#if NEED_LAPIC == 1
+#ifdef CONFIG_SMP
/* Only Pentium Pro and later have those MSR stuff */
debug("Setting up local apic: ");
/* Enable the local apic */
enable_lapic();
- /*
- * Set Task Priority to 'accept all'.
- */
- lapic_write_around(LAPIC_TASKPRI,
- lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
+ /* Set Task Priority to 'accept all' */
+ lapic_write(LAPIC_TASKPRI,
+ lapic_read(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Put the local apic in virtual wire mode */
- lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
- ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
- lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
- ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
- LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
- LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
- LAPIC_DELIVERY_MODE_MASK)) |
- (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
- LAPIC_DELIVERY_MODE_EXTINT));
- lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
- ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
- LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
- LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
- LAPIC_DELIVERY_MODE_MASK)) |
- (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
- LAPIC_DELIVERY_MODE_NMI));
+ lapic_write(LAPIC_SPIV, (lapic_read(LAPIC_SPIV) &
+ ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
+ lapic_write(LAPIC_LVT0, (lapic_read(LAPIC_LVT0) &
+ ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
+ LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
+ LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
+ LAPIC_DELIVERY_MODE_MASK)) |
+ (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
+ LAPIC_DELIVERY_MODE_EXTINT));
+ lapic_write(LAPIC_LVT1, (lapic_read(LAPIC_LVT1) &
+ ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
+ LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
+ LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
+ LAPIC_DELIVERY_MODE_MASK)) |
+ (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
+ LAPIC_DELIVERY_MODE_NMI));
debug("apic_id: 0x%02lx, ", lapicid());
-#else /* !NEED_LLAPIC */
+#else /* !CONFIG_SMP */
/* Only Pentium Pro and later have those MSR stuff */
debug("Disabling local apic: ");
disable_lapic();
-#endif /* !NEED_LAPIC */
+#endif /* CONFIG_SMP */
debug("done.\n");
post_code(POST_LAPIC);
}
diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c
index ac5753a1fd..e686b28c9c 100644
--- a/arch/x86/cpu/mp_init.c
+++ b/arch/x86/cpu/mp_init.c
@@ -16,12 +16,17 @@
#include <asm/interrupt.h>
#include <asm/lapic.h>
#include <asm/mp.h>
+#include <asm/msr.h>
#include <asm/mtrr.h>
+#include <asm/processor.h>
#include <asm/sipi.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
#include <linux/linkage.h>
+/* Total CPUs include BSP */
+static int num_cpus;
+
/* This also needs to match the sipi.S assembly code for saved MSR encoding */
struct saved_msr {
uint32_t index;
@@ -56,6 +61,13 @@ static inline void release_barrier(atomic_t *b)
atomic_set(b, 1);
}
+static inline void stop_this_cpu(void)
+{
+ /* Called by an AP when it is ready to halt and wait for a new task */
+ for (;;)
+ cpu_hlt();
+}
+
/* Returns 1 if timeout waiting for APs. 0 if target APs found */
static int wait_for_aps(atomic_t *val, int target, int total_delay,
int delay_step)
@@ -314,9 +326,9 @@ static int start_aps(int ap_count, atomic_t *num_aps)
}
/* Send INIT IPI to all but self */
- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
- lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
- LAPIC_DM_INIT);
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+ lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+ LAPIC_DM_INIT);
debug("Waiting for 10ms after sending INIT.\n");
mdelay(10);
@@ -331,9 +343,9 @@ static int start_aps(int ap_count, atomic_t *num_aps)
}
}
- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
- lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
- LAPIC_DM_STARTUP | sipi_vector);
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+ lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+ LAPIC_DM_STARTUP | sipi_vector);
debug("Waiting for 1st SIPI to complete...");
if (apic_wait_timeout(10000, 50)) {
debug("timed out.\n");
@@ -356,9 +368,9 @@ static int start_aps(int ap_count, atomic_t *num_aps)
}
}
- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
- lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
- LAPIC_DM_STARTUP | sipi_vector);
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+ lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+ LAPIC_DM_STARTUP | sipi_vector);
debug("Waiting for 2nd SIPI to complete...");
if (apic_wait_timeout(10000, 50)) {
debug("timed out.\n");
@@ -383,7 +395,7 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params)
int ret = 0;
const int timeout_us = 100000;
const int step_us = 100;
- int num_aps = mp_params->num_cpus - 1;
+ int num_aps = num_cpus - 1;
for (i = 0; i < mp_params->num_records; i++) {
struct mp_flight_record *rec = &mp_params->flight_plan[i];
@@ -415,7 +427,7 @@ static int init_bsp(struct udevice **devp)
cpu_get_name(processor_name);
debug("CPU: %s.\n", processor_name);
- enable_lapic();
+ lapic_setup();
apic_id = lapicid();
ret = find_cpu_by_apid_id(apic_id, devp);
@@ -451,7 +463,16 @@ int mp_init(struct mp_params *p)
return -1;
}
- ret = check_cpu_devices(p->num_cpus);
+ num_cpus = cpu_get_count(cpu);
+ if (num_cpus < 0) {
+ debug("Cannot get number of CPUs: err=%d\n", num_cpus);
+ return num_cpus;
+ }
+
+ if (num_cpus < 2)
+ debug("Warning: Only 1 CPU is detected\n");
+
+ ret = check_cpu_devices(num_cpus);
if (ret)
debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n");
@@ -471,7 +492,7 @@ int mp_init(struct mp_params *p)
wbinvd();
/* Start the APs providing number of APs and the cpus_entered field */
- num_aps = p->num_cpus - 1;
+ num_aps = num_cpus - 1;
ret = start_aps(num_aps, ap_count);
if (ret) {
mdelay(1000);
diff --git a/arch/x86/cpu/queensbay/Kconfig b/arch/x86/cpu/queensbay/Kconfig
index 397e599f93..fbf85f233f 100644
--- a/arch/x86/cpu/queensbay/Kconfig
+++ b/arch/x86/cpu/queensbay/Kconfig
@@ -38,4 +38,8 @@ config CMC_ADDR
The default base address of 0xfffb0000 indicates that the binary must
be located at offset 0xb0000 from the beginning of a 1MB flash device.
+config CPU_ADDR_BITS
+ int
+ default 32
+
endif
diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c
index 873de7be9d..d27b2d9ec6 100644
--- a/arch/x86/cpu/queensbay/tnc.c
+++ b/arch/x86/cpu/queensbay/tnc.c
@@ -69,17 +69,18 @@ void cpu_irq_init(void)
* Route TunnelCreek PCI device interrupt pin to PIRQ
*
* Since PCIe downstream ports received INTx are routed to PIRQ
- * A/B/C/D directly and not configurable, we route internal PCI
- * device's INTx to PIRQ E/F/G/H.
+ * A/B/C/D directly and not configurable, we have to route PCIe
+ * root ports' INTx to PIRQ A/B/C/D as well. For other devices
+ * on TunneCreek, route them to PIRQ E/F/G/H.
*/
writew(PIRQE, &rcba->d02ir);
writew(PIRQF, &rcba->d03ir);
writew(PIRQG, &rcba->d27ir);
writew(PIRQH, &rcba->d31ir);
- writew(PIRQE, &rcba->d23ir);
- writew(PIRQF, &rcba->d24ir);
- writew(PIRQG, &rcba->d25ir);
- writew(PIRQH, &rcba->d26ir);
+ writew(PIRQA, &rcba->d23ir);
+ writew(PIRQB, &rcba->d24ir);
+ writew(PIRQC, &rcba->d25ir);
+ writew(PIRQD, &rcba->d26ir);
}
int arch_misc_init(void)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 2e5f9da756..00e585e19b 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -116,12 +116,16 @@ car_init_ret:
rep stosb
#ifdef CONFIG_HAVE_FSP
+ test %esi, %esi
+ jz skip_hob
+
/* Store HOB list */
movl %esp, %edx
addl $GD_HOB_LIST, %edx
movl %esi, (%edx)
-#endif
+skip_hob:
+#endif
/* Setup first parameter to setup_gdt, pointer to global_data */
movl %esp, %eax
diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S
index 826e2b4361..5eb17f15c9 100644
--- a/arch/x86/cpu/start16.S
+++ b/arch/x86/cpu/start16.S
@@ -71,11 +71,12 @@ idt_ptr:
*/
gdt_ptr:
.word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */
- .long BOOT_SEG + gdt /* base */
+ .long BOOT_SEG + gdt_rom /* base */
/* Some CPUs are picky about GDT alignment... */
.align 16
-gdt:
+.globl gdt_rom
+gdt_rom:
/*
* The GDT table ...
*
diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts
index d68efda8df..60da1f544b 100644
--- a/arch/x86/dts/crownbay.dts
+++ b/arch/x86/dts/crownbay.dts
@@ -10,6 +10,7 @@
/include/ "skeleton.dtsi"
/include/ "serial.dtsi"
+/include/ "rtc.dtsi"
/ {
model = "Intel Crown Bay";
@@ -23,6 +24,26 @@
silent_console = <0>;
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "cpu-x86";
+ reg = <0>;
+ intel,apic-id = <0>;
+ };
+
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "cpu-x86";
+ reg = <1>;
+ intel,apic-id = <1>;
+ };
+
+ };
+
gpioa {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
@@ -148,10 +169,22 @@
/* TunnelCreek PCI devices */
PCI_BDF(0, 2, 0) INTA PIRQE
PCI_BDF(0, 3, 0) INTA PIRQF
- PCI_BDF(0, 23, 0) INTA PIRQE
- PCI_BDF(0, 24, 0) INTA PIRQF
- PCI_BDF(0, 25, 0) INTA PIRQG
- PCI_BDF(0, 26, 0) INTA PIRQH
+ PCI_BDF(0, 23, 0) INTA PIRQA
+ PCI_BDF(0, 23, 0) INTB PIRQB
+ PCI_BDF(0, 23, 0) INTC PIRQC
+ PCI_BDF(0, 23, 0) INTD PIRQD
+ PCI_BDF(0, 24, 0) INTA PIRQB
+ PCI_BDF(0, 24, 0) INTB PIRQC
+ PCI_BDF(0, 24, 0) INTC PIRQD
+ PCI_BDF(0, 24, 0) INTD PIRQA
+ PCI_BDF(0, 25, 0) INTA PIRQC
+ PCI_BDF(0, 25, 0) INTB PIRQD
+ PCI_BDF(0, 25, 0) INTC PIRQA
+ PCI_BDF(0, 25, 0) INTD PIRQB
+ PCI_BDF(0, 26, 0) INTA PIRQD
+ PCI_BDF(0, 26, 0) INTB PIRQA
+ PCI_BDF(0, 26, 0) INTC PIRQB
+ PCI_BDF(0, 26, 0) INTD PIRQC
PCI_BDF(0, 27, 0) INTA PIRQG
/*
* Topcliff PCI devices
@@ -159,29 +192,29 @@
* Note on the Crown Bay board, Topcliff chipset
* is connected to TunnelCreek PCIe port 0, so
* its bus number is 1 for its PCIe port and 2
- * for its PCI devices per U-Boot currnet PCI
+ * for its PCI devices per U-Boot current PCI
* bus enumeration algorithm.
*/
PCI_BDF(1, 0, 0) INTA PIRQA
PCI_BDF(2, 0, 1) INTA PIRQA
PCI_BDF(2, 0, 2) INTA PIRQA
- PCI_BDF(2, 2, 0) INTB PIRQB
- PCI_BDF(2, 2, 1) INTB PIRQB
- PCI_BDF(2, 2, 2) INTB PIRQB
- PCI_BDF(2, 2, 3) INTB PIRQB
- PCI_BDF(2, 2, 4) INTB PIRQB
+ PCI_BDF(2, 2, 0) INTB PIRQD
+ PCI_BDF(2, 2, 1) INTB PIRQD
+ PCI_BDF(2, 2, 2) INTB PIRQD
+ PCI_BDF(2, 2, 3) INTB PIRQD
+ PCI_BDF(2, 2, 4) INTB PIRQD
PCI_BDF(2, 4, 0) INTC PIRQC
PCI_BDF(2, 4, 1) INTC PIRQC
- PCI_BDF(2, 6, 0) INTD PIRQD
+ PCI_BDF(2, 6, 0) INTD PIRQB
PCI_BDF(2, 8, 0) INTA PIRQA
PCI_BDF(2, 8, 1) INTA PIRQA
PCI_BDF(2, 8, 2) INTA PIRQA
PCI_BDF(2, 8, 3) INTA PIRQA
- PCI_BDF(2, 10, 0) INTB PIRQB
- PCI_BDF(2, 10, 1) INTB PIRQB
- PCI_BDF(2, 10, 2) INTB PIRQB
- PCI_BDF(2, 10, 3) INTB PIRQB
- PCI_BDF(2, 10, 4) INTB PIRQB
+ PCI_BDF(2, 10, 0) INTB PIRQD
+ PCI_BDF(2, 10, 1) INTB PIRQD
+ PCI_BDF(2, 10, 2) INTB PIRQD
+ PCI_BDF(2, 10, 3) INTB PIRQD
+ PCI_BDF(2, 10, 4) INTB PIRQD
PCI_BDF(2, 12, 0) INTC PIRQC
PCI_BDF(2, 12, 1) INTC PIRQC
PCI_BDF(2, 12, 2) INTC PIRQC
diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index bd21bfb0b4..0e59b18d34 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -111,6 +111,16 @@
};
+ pci {
+ compatible = "intel,pci-baytrail", "pci-x86";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ u-boot,dm-pre-reloc;
+ ranges = <0x02000000 0x0 0xd0000000 0xd0000000 0 0x10000000
+ 0x42000000 0x0 0xc0000000 0xc0000000 0 0x10000000
+ 0x01000000 0x0 0x2000 0x2000 0 0xe000>;
+ };
+
spi {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/x86/dts/rtc.dtsi b/arch/x86/dts/rtc.dtsi
new file mode 100644
index 0000000000..93dacd7307
--- /dev/null
+++ b/arch/x86/dts/rtc.dtsi
@@ -0,0 +1,6 @@
+/ {
+ rtc {
+ compatible = "motorola,mc146818";
+ reg = <0x70 2>;
+ };
+};
diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h
index 5ae32f7883..7786493be7 100644
--- a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h
+++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h
@@ -16,7 +16,19 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
const void *blob, int node);
int bd82x6x_init(void);
-struct x86_cpu_priv;
+/**
+ * struct x86_cpu_priv - Information about a single CPU
+ *
+ * @apic_id: Advanced Programmable Interrupt Controller Identifier, which is
+ * just a number representing the CPU core
+ *
+ * TODO: Move this to driver model once lifecycle is understood
+ */
+struct x86_cpu_priv {
+ int apic_id;
+ int start_err;
+};
+
int model_206ax_init(struct x86_cpu_priv *cpu);
#endif
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index ebc74adbc3..08284ee295 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -197,20 +197,6 @@ const char *cpu_vendor_name(int vendor);
char *cpu_get_name(char *name);
/**
- *
-* x86_cpu_get_desc() - Get a description string for an x86 CPU
-*
-* This uses cpu_get_name() and is suitable to use as the get_desc() method for
-* the CPU uclass.
-*
-* @dev: Device to check (UCLASS_CPU)
-* @buf: Buffer to place string
-* @size: Size of string space
-* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
-*/
-int x86_cpu_get_desc(struct udevice *dev, char *buf, int size);
-
-/**
* cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
*
* The kernel is uncompressed and the 64-bit entry point is expected to be
diff --git a/arch/x86/include/asm/cpu_x86.h b/arch/x86/include/asm/cpu_x86.h
new file mode 100644
index 0000000000..19404805c5
--- /dev/null
+++ b/arch/x86/include/asm/cpu_x86.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _ASM_CPU_X86_H
+#define _ASM_CPU_X86_H
+
+/**
+ * cpu_x86_bind() - Bind an x86 CPU with the driver
+ *
+ * This updates cpu device's platform data with information from device tree,
+ * like the processor local apic id.
+ *
+ * @dev: Device to check (UCLASS_CPU)
+ * @return 0 always
+ */
+int cpu_x86_bind(struct udevice *dev);
+
+/**
+ * cpu_x86_get_desc() - Get a description string for an x86 CPU
+ *
+ * This uses cpu_get_name() and is suitable to use as the get_desc() method for
+ * the CPU uclass.
+ *
+ * @dev: Device to check (UCLASS_CPU)
+ * @buf: Buffer to place string
+ * @size: Size of string space
+ * @return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+int cpu_x86_get_desc(struct udevice *dev, char *buf, int size);
+
+#endif /* _ASM_CPU_X86_H */
diff --git a/arch/x86/include/asm/ioapic.h b/arch/x86/include/asm/ioapic.h
index 699160f9f7..77c443e9f5 100644
--- a/arch/x86/include/asm/ioapic.h
+++ b/arch/x86/include/asm/ioapic.h
@@ -10,29 +10,33 @@
#define __ASM_IOAPIC_H
#define IO_APIC_ADDR 0xfec00000
-#define IO_APIC_INDEX IO_APIC_ADDR
+
+/* Direct addressed register */
+#define IO_APIC_INDEX (IO_APIC_ADDR + 0x00)
#define IO_APIC_DATA (IO_APIC_ADDR + 0x10)
-#define IO_APIC_INTERRUPTS 24
-#define ALL (0xff << 24)
-#define NONE 0
-#define DISABLED (1 << 16)
-#define ENABLED (0 << 16)
-#define TRIGGER_EDGE (0 << 15)
-#define TRIGGER_LEVEL (1 << 15)
-#define POLARITY_HIGH (0 << 13)
-#define POLARITY_LOW (1 << 13)
-#define PHYSICAL_DEST (0 << 11)
-#define LOGICAL_DEST (1 << 11)
-#define ExtINT (7 << 8)
-#define NMI (4 << 8)
-#define SMI (2 << 8)
-#define INT (1 << 8)
+/* Indirect addressed register offset */
+#define IO_APIC_ID 0x00
+#define IO_APIC_VER 0x01
+
+/**
+ * io_apic_read() - Read I/O APIC register
+ *
+ * This routine reads I/O APIC indirect addressed register.
+ *
+ * @reg: address of indirect addressed register
+ * @return: register value to read
+ */
+u32 io_apic_read(u32 reg);
-u32 io_apic_read(u32 ioapic_base, u32 reg);
-void io_apic_write(u32 ioapic_base, u32 reg, u32 value);
-void set_ioapic_id(u32 ioapic_base, u8 ioapic_id);
-void setup_ioapic(u32 ioapic_base, u8 ioapic_id);
-void clear_ioapic(u32 ioapic_base);
+/**
+ * io_apic_write() - Write I/O APIC register
+ *
+ * This routine writes I/O APIC indirect addressed register.
+ *
+ * @reg: address of indirect addressed register
+ * @val: register value to write
+ */
+void io_apic_write(u32 reg, u32 val);
#endif
diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h
index 0a7f443195..bc2b2d1520 100644
--- a/arch/x86/include/asm/lapic.h
+++ b/arch/x86/include/asm/lapic.h
@@ -1,5 +1,5 @@
/*
- * From Coreboot file of same name
+ * From coreboot file of same name
*
* Copyright (C) 2014 Google, Inc
*
@@ -9,171 +9,70 @@
#ifndef _ARCH_ASM_LAPIC_H
#define _ARCH_ASM_LAPIC_H
-#include <asm/io.h>
-#include <asm/lapic_def.h>
-#include <asm/msr.h>
-#include <asm/processor.h>
-
-/* See if I need to initialize the local apic */
-#if CONFIG_SMP || CONFIG_IOAPIC
-# define NEED_LAPIC 1
-#else
-# define NEED_LAPIC 0
-#endif
-
-static inline __attribute__((always_inline))
- unsigned long lapic_read(unsigned long reg)
-{
- return readl(LAPIC_DEFAULT_BASE + reg);
-}
-
-static inline __attribute__((always_inline))
- void lapic_write(unsigned long reg, unsigned long val)
-{
- writel(val, LAPIC_DEFAULT_BASE + reg);
-}
-
-static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void)
-{
- do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
-}
-
-static inline void enable_lapic(void)
-{
- msr_t msr;
-
- msr = msr_read(LAPIC_BASE_MSR);
- msr.hi &= 0xffffff00;
- msr.lo |= LAPIC_BASE_MSR_ENABLE;
- msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
- msr.lo |= LAPIC_DEFAULT_BASE;
- msr_write(LAPIC_BASE_MSR, msr);
-}
-
-static inline void disable_lapic(void)
-{
- msr_t msr;
-
- msr = msr_read(LAPIC_BASE_MSR);
- msr.lo &= ~(1 << 11);
- msr_write(LAPIC_BASE_MSR, msr);
-}
-
-static inline __attribute__((always_inline)) unsigned long lapicid(void)
-{
- return lapic_read(LAPIC_ID) >> 24;
-}
-
-#if !CONFIG_AP_IN_SIPI_WAIT
-/* If we need to go back to sipi wait, we use the long non-inlined version of
- * this function in lapic_cpu_init.c
- */
-static inline __attribute__((always_inline)) void stop_this_cpu(void)
-{
- /* Called by an AP when it is ready to halt and wait for a new task */
- for (;;)
- cpu_hlt();
-}
-#else
-void stop_this_cpu(void);
-#endif
-
-#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
- sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
- * Note 2: xchg has side effect, so that attribute volatile is necessary,
- * but generally the primitive is invalid, *ptr is output argument. --ANK
- */
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
- int size)
-{
- switch (size) {
- case 1:
- __asm__ __volatile__("xchgb %b0,%1"
- : "=q" (x)
- : "m" (*__xg(ptr)), "0" (x)
- : "memory");
- break;
- case 2:
- __asm__ __volatile__("xchgw %w0,%1"
- : "=r" (x)
- : "m" (*__xg(ptr)), "0" (x)
- : "memory");
- break;
- case 4:
- __asm__ __volatile__("xchgl %0,%1"
- : "=r" (x)
- : "m" (*__xg(ptr)), "0" (x)
- : "memory");
- break;
- }
-
- return x;
-}
-
-static inline void lapic_write_atomic(unsigned long reg, unsigned long v)
-{
- (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
-}
-
-
-#ifdef X86_GOOD_APIC
-# define FORCE_READ_AROUND_WRITE 0
-# define lapic_read_around(x) lapic_read(x)
-# define lapic_write_around(x, y) lapic_write((x), (y))
-#else
-# define FORCE_READ_AROUND_WRITE 1
-# define lapic_read_around(x) lapic_read(x)
-# define lapic_write_around(x, y) lapic_write_atomic((x), (y))
-#endif
-
-static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
-{
- int timeout;
- unsigned long status;
- int result;
- lapic_wait_icr_idle();
- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
- lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
- timeout = 0;
- do {
- status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
- } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
-
- result = -1;
- if (status == LAPIC_ICR_RR_VALID) {
- *pvalue = lapic_read(LAPIC_RRR);
- result = 0;
- }
- return result;
-}
-
+#define LAPIC_DEFAULT_BASE 0xfee00000
+
+#define LAPIC_ID 0x020
+#define LAPIC_LVR 0x030
+
+#define LAPIC_TASKPRI 0x080
+#define LAPIC_TPRI_MASK 0xff
+
+#define LAPIC_RRR 0x0c0
+
+#define LAPIC_SPIV 0x0f0
+#define LAPIC_SPIV_ENABLE 0x100
+
+#define LAPIC_ICR 0x300
+#define LAPIC_DEST_SELF 0x40000
+#define LAPIC_DEST_ALLINC 0x80000
+#define LAPIC_DEST_ALLBUT 0xc0000
+#define LAPIC_ICR_RR_MASK 0x30000
+#define LAPIC_ICR_RR_INVALID 0x00000
+#define LAPIC_ICR_RR_INPROG 0x10000
+#define LAPIC_ICR_RR_VALID 0x20000
+#define LAPIC_INT_LEVELTRIG 0x08000
+#define LAPIC_INT_ASSERT 0x04000
+#define LAPIC_ICR_BUSY 0x01000
+#define LAPIC_DEST_LOGICAL 0x00800
+#define LAPIC_DM_FIXED 0x00000
+#define LAPIC_DM_LOWEST 0x00100
+#define LAPIC_DM_SMI 0x00200
+#define LAPIC_DM_REMRD 0x00300
+#define LAPIC_DM_NMI 0x00400
+#define LAPIC_DM_INIT 0x00500
+#define LAPIC_DM_STARTUP 0x00600
+#define LAPIC_DM_EXTINT 0x00700
+#define LAPIC_VECTOR_MASK 0x000ff
+
+#define LAPIC_ICR2 0x310
+#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xff)
+#define SET_LAPIC_DEST_FIELD(x) ((x) << 24)
+
+#define LAPIC_LVT0 0x350
+#define LAPIC_LVT1 0x360
+#define LAPIC_LVT_MASKED (1 << 16)
+#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15)
+#define LAPIC_LVT_REMOTE_IRR (1 << 14)
+#define LAPIC_INPUT_POLARITY (1 << 13)
+#define LAPIC_SEND_PENDING (1 << 12)
+#define LAPIC_LVT_RESERVED_1 (1 << 11)
+#define LAPIC_DELIVERY_MODE_MASK (7 << 8)
+#define LAPIC_DELIVERY_MODE_FIXED (0 << 8)
+#define LAPIC_DELIVERY_MODE_NMI (4 << 8)
+#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8)
+
+unsigned long lapic_read(unsigned long reg);
+
+void lapic_write(unsigned long reg, unsigned long v);
+
+void enable_lapic(void);
+
+void disable_lapic(void);
+
+unsigned long lapicid(void);
+
+int lapic_remote_read(int apicid, int reg, unsigned long *pvalue);
void lapic_setup(void);
-#if CONFIG_SMP
-struct device;
-int start_cpu(struct device *cpu);
-#endif /* CONFIG_SMP */
-
-int boot_cpu(void);
-
-/**
- * struct x86_cpu_priv - Information about a single CPU
- *
- * @apic_id: Advanced Programmable Interrupt Controller Identifier, which is
- * just a number representing the CPU core
- *
- * TODO: Move this to driver model once lifecycle is understood
- */
-struct x86_cpu_priv {
- int apic_id;
- int start_err;
-};
-
#endif
diff --git a/arch/x86/include/asm/lapic_def.h b/arch/x86/include/asm/lapic_def.h
deleted file mode 100644
index 722ceadaa4..0000000000
--- a/arch/x86/include/asm/lapic_def.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Taken from the Coreboot file of the same name
- *
- * (C) Copyright 2014 Google, Inc
- *
- * SPDX-License-Identifier: GPL-2.0
- */
-
-#ifndef _ASM_LAPIC_DEF_H
-#define _ASM_LAPIC_DEF_H
-
-#define LAPIC_BASE_MSR 0x1B
-#define LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR (1 << 8)
-#define LAPIC_BASE_MSR_ENABLE (1 << 11)
-#define LAPIC_BASE_MSR_ADDR_MASK 0xFFFFF000
-
-#define LOCAL_APIC_ADDR 0xfee00000
-#define LAPIC_DEFAULT_BASE LOCAL_APIC_ADDR
-
-#define LAPIC_ID 0x020
-#define LAPIC_LVR 0x030
-#define LAPIC_TASKPRI 0x80
-#define LAPIC_TPRI_MASK 0xFF
-#define LAPIC_ARBID 0x090
-#define LAPIC_RRR 0x0C0
-#define LAPIC_SVR 0x0f0
-#define LAPIC_SPIV 0x0f0
-#define LAPIC_SPIV_ENABLE 0x100
-#define LAPIC_ESR 0x280
-#define LAPIC_ESR_SEND_CS 0x00001
-#define LAPIC_ESR_RECV_CS 0x00002
-#define LAPIC_ESR_SEND_ACC 0x00004
-#define LAPIC_ESR_RECV_ACC 0x00008
-#define LAPIC_ESR_SENDILL 0x00020
-#define LAPIC_ESR_RECVILL 0x00040
-#define LAPIC_ESR_ILLREGA 0x00080
-#define LAPIC_ICR 0x300
-#define LAPIC_DEST_SELF 0x40000
-#define LAPIC_DEST_ALLINC 0x80000
-#define LAPIC_DEST_ALLBUT 0xC0000
-#define LAPIC_ICR_RR_MASK 0x30000
-#define LAPIC_ICR_RR_INVALID 0x00000
-#define LAPIC_ICR_RR_INPROG 0x10000
-#define LAPIC_ICR_RR_VALID 0x20000
-#define LAPIC_INT_LEVELTRIG 0x08000
-#define LAPIC_INT_ASSERT 0x04000
-#define LAPIC_ICR_BUSY 0x01000
-#define LAPIC_DEST_LOGICAL 0x00800
-#define LAPIC_DM_FIXED 0x00000
-#define LAPIC_DM_LOWEST 0x00100
-#define LAPIC_DM_SMI 0x00200
-#define LAPIC_DM_REMRD 0x00300
-#define LAPIC_DM_NMI 0x00400
-#define LAPIC_DM_INIT 0x00500
-#define LAPIC_DM_STARTUP 0x00600
-#define LAPIC_DM_EXTINT 0x00700
-#define LAPIC_VECTOR_MASK 0x000FF
-#define LAPIC_ICR2 0x310
-#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
-#define SET_LAPIC_DEST_FIELD(x) ((x) << 24)
-#define LAPIC_LVTT 0x320
-#define LAPIC_LVTPC 0x340
-#define LAPIC_LVT0 0x350
-#define LAPIC_LVT_TIMER_BASE_MASK (0x3 << 18)
-#define GET_LAPIC_TIMER_BASE(x) (((x) >> 18) & 0x3)
-#define SET_LAPIC_TIMER_BASE(x) (((x) << 18))
-#define LAPIC_TIMER_BASE_CLKIN 0x0
-#define LAPIC_TIMER_BASE_TMBASE 0x1
-#define LAPIC_TIMER_BASE_DIV 0x2
-#define LAPIC_LVT_TIMER_PERIODIC (1 << 17)
-#define LAPIC_LVT_MASKED (1 << 16)
-#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15)
-#define LAPIC_LVT_REMOTE_IRR (1 << 14)
-#define LAPIC_INPUT_POLARITY (1 << 13)
-#define LAPIC_SEND_PENDING (1 << 12)
-#define LAPIC_LVT_RESERVED_1 (1 << 11)
-#define LAPIC_DELIVERY_MODE_MASK (7 << 8)
-#define LAPIC_DELIVERY_MODE_FIXED (0 << 8)
-#define LAPIC_DELIVERY_MODE_NMI (4 << 8)
-#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8)
-#define GET_LAPIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7)
-#define SET_LAPIC_DELIVERY_MODE(x, y) (((x) & ~0x700)|((y) << 8))
-#define LAPIC_MODE_FIXED 0x0
-#define LAPIC_MODE_NMI 0x4
-#define LAPIC_MODE_EXINT 0x7
-#define LAPIC_LVT1 0x360
-#define LAPIC_LVTERR 0x370
-#define LAPIC_TMICT 0x380
-#define LAPIC_TMCCT 0x390
-#define LAPIC_TDCR 0x3E0
-#define LAPIC_TDR_DIV_TMBASE (1 << 2)
-#define LAPIC_TDR_DIV_1 0xB
-#define LAPIC_TDR_DIV_2 0x0
-#define LAPIC_TDR_DIV_4 0x1
-#define LAPIC_TDR_DIV_8 0x2
-#define LAPIC_TDR_DIV_16 0x3
-#define LAPIC_TDR_DIV_32 0x8
-#define LAPIC_TDR_DIV_64 0x9
-#define LAPIC_TDR_DIV_128 0xA
-
-#endif
diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h
index c0930fd0c6..2e6c3120c7 100644
--- a/arch/x86/include/asm/mp.h
+++ b/arch/x86/include/asm/mp.h
@@ -59,7 +59,6 @@ struct mp_flight_record {
* SMM support.
*/
struct mp_params {
- int num_cpus; /* Total cpus include BSP */
int parallel_microcode_load;
const void *microcode_pointer;
/* Flight plan for APs and BSP */
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
new file mode 100644
index 0000000000..efa9231f92
--- /dev/null
+++ b/arch/x86/include/asm/mpspec.h
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Adapted from coreboot src/arch/x86/include/arch/smp/mpspec.h
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __ASM_MPSPEC_H
+#define __ASM_MPSPEC_H
+
+/*
+ * Structure definitions for SMP machines following the
+ * Intel MultiProcessor Specification 1.4
+ */
+
+#define MPSPEC_V14 4
+
+#define MPF_SIGNATURE "_MP_"
+
+struct mp_floating_table {
+ char mpf_signature[4]; /* "_MP_" */
+ u32 mpf_physptr; /* Configuration table address */
+ u8 mpf_length; /* Our length (paragraphs) */
+ u8 mpf_spec; /* Specification version */
+ u8 mpf_checksum; /* Checksum (makes sum 0) */
+ u8 mpf_feature1; /* Predefined or Unique configuration? */
+ u8 mpf_feature2; /* Bit7 set for IMCR/PIC */
+ u8 mpf_feature3; /* Unused (0) */
+ u8 mpf_feature4; /* Unused (0) */
+ u8 mpf_feature5; /* Unused (0) */
+};
+
+#define MPC_SIGNATURE "PCMP"
+
+struct mp_config_table {
+ char mpc_signature[4]; /* "PCMP" */
+ u16 mpc_length; /* Size of table */
+ u8 mpc_spec; /* Specification version */
+ u8 mpc_checksum; /* Checksum (makes sum 0) */
+ char mpc_oem[8]; /* OEM ID */
+ char mpc_product[12]; /* Product ID */
+ u32 mpc_oemptr; /* OEM table address */
+ u16 mpc_oemsize; /* OEM table size */
+ u16 mpc_entry_count; /* Number of entries in the table */
+ u32 mpc_lapic; /* Local APIC address */
+ u16 mpe_length; /* Extended table size */
+ u8 mpe_checksum; /* Extended table checksum */
+ u8 reserved;
+};
+
+/* Base MP configuration table entry types */
+
+enum mp_base_config_entry_type {
+ MP_PROCESSOR,
+ MP_BUS,
+ MP_IOAPIC,
+ MP_INTSRC,
+ MP_LINTSRC
+};
+
+#define MPC_CPU_EN (1 << 0)
+#define MPC_CPU_BP (1 << 1)
+
+struct mpc_config_processor {
+ u8 mpc_type;
+ u8 mpc_apicid;
+ u8 mpc_apicver;
+ u8 mpc_cpuflag;
+ u32 mpc_cpusignature;
+ u32 mpc_cpufeature;
+ u32 mpc_reserved[2];
+};
+
+#define BUSTYPE_CBUS "CBUS "
+#define BUSTYPE_CBUSII "CBUSII"
+#define BUSTYPE_EISA "EISA "
+#define BUSTYPE_FUTURE "FUTURE"
+#define BUSTYPE_INTERN "INTERN"
+#define BUSTYPE_ISA "ISA "
+#define BUSTYPE_MBI "MBI "
+#define BUSTYPE_MBII "MBII "
+#define BUSTYPE_MCA "MCA "
+#define BUSTYPE_MPI "MPI "
+#define BUSTYPE_MPSA "MPSA "
+#define BUSTYPE_NUBUS "NUBUS "
+#define BUSTYPE_PCI "PCI "
+#define BUSTYPE_PCMCIA "PCMCIA"
+#define BUSTYPE_TC "TC "
+#define BUSTYPE_VL "VL "
+#define BUSTYPE_VME "VME "
+#define BUSTYPE_XPRESS "XPRESS"
+
+struct mpc_config_bus {
+ u8 mpc_type;
+ u8 mpc_busid;
+ u8 mpc_bustype[6];
+};
+
+#define MPC_APIC_USABLE (1 << 0)
+
+struct mpc_config_ioapic {
+ u8 mpc_type;
+ u8 mpc_apicid;
+ u8 mpc_apicver;
+ u8 mpc_flags;
+ u32 mpc_apicaddr;
+};
+
+enum mp_irq_source_types {
+ MP_INT,
+ MP_NMI,
+ MP_SMI,
+ MP_EXTINT
+};
+
+#define MP_IRQ_POLARITY_DEFAULT 0x0
+#define MP_IRQ_POLARITY_HIGH 0x1
+#define MP_IRQ_POLARITY_LOW 0x3
+#define MP_IRQ_POLARITY_MASK 0x3
+#define MP_IRQ_TRIGGER_DEFAULT 0x0
+#define MP_IRQ_TRIGGER_EDGE 0x4
+#define MP_IRQ_TRIGGER_LEVEL 0xc
+#define MP_IRQ_TRIGGER_MASK 0xc
+
+#define MP_APIC_ALL 0xff
+
+struct mpc_config_intsrc {
+ u8 mpc_type;
+ u8 mpc_irqtype;
+ u16 mpc_irqflag;
+ u8 mpc_srcbus;
+ u8 mpc_srcbusirq;
+ u8 mpc_dstapic;
+ u8 mpc_dstirq;
+};
+
+struct mpc_config_lintsrc {
+ u8 mpc_type;
+ u8 mpc_irqtype;
+ u16 mpc_irqflag;
+ u8 mpc_srcbusid;
+ u8 mpc_srcbusirq;
+ u8 mpc_destapic;
+ u8 mpc_destlint;
+};
+
+/* Extended MP configuration table entry types */
+
+enum mp_ext_config_entry_type {
+ MPE_SYSTEM_ADDRESS_SPACE = 128,
+ MPE_BUS_HIERARCHY,
+ MPE_COMPAT_ADDRESS_SPACE
+};
+
+struct mp_ext_config {
+ u8 mpe_type;
+ u8 mpe_length;
+};
+
+#define ADDRESS_TYPE_IO 0
+#define ADDRESS_TYPE_MEM 1
+#define ADDRESS_TYPE_PREFETCH 2
+
+struct mp_ext_system_address_space {
+ u8 mpe_type;
+ u8 mpe_length;
+ u8 mpe_busid;
+ u8 mpe_addr_type;
+ u32 mpe_addr_base_low;
+ u32 mpe_addr_base_high;
+ u32 mpe_addr_length_low;
+ u32 mpe_addr_length_high;
+};
+
+#define BUS_SUBTRACTIVE_DECODE (1 << 0)
+
+struct mp_ext_bus_hierarchy {
+ u8 mpe_type;
+ u8 mpe_length;
+ u8 mpe_busid;
+ u8 mpe_bus_info;
+ u8 mpe_parent_busid;
+ u8 reserved[3];
+};
+
+#define ADDRESS_RANGE_ADD 0
+#define ADDRESS_RANGE_SUBTRACT 1
+
+/*
+ * X100 - X3FF
+ * X500 - X7FF
+ * X900 - XBFF
+ * XD00 - XFFF
+ */
+#define RANGE_LIST_IO_ISA 0
+/*
+ * X3B0 - X3BB
+ * X3C0 - X3DF
+ * X7B0 - X7BB
+ * X7C0 - X7DF
+ * XBB0 - XBBB
+ * XBC0 - XBDF
+ * XFB0 - XFBB
+ * XFC0 - XCDF
+ */
+#define RANGE_LIST_IO_VGA 1
+
+struct mp_ext_compat_address_space {
+ u8 mpe_type;
+ u8 mpe_length;
+ u8 mpe_busid;
+ u8 mpe_addr_modifier;
+ u32 mpe_range_list;
+};
+
+/**
+ * mp_next_mpc_entry() - Compute MP configuration table end to be used as
+ * next base table entry start address
+ *
+ * This computes the end address of current MP configuration table, without
+ * counting any extended configuration table entry.
+ *
+ * @mc: configuration table header address
+ * @return: configuration table end address
+ */
+static inline u32 mp_next_mpc_entry(struct mp_config_table *mc)
+{
+ return (u32)mc + mc->mpc_length;
+}
+
+/**
+ * mp_add_mpc_entry() - Add a base MP configuration table entry
+ *
+ * This adds the base MP configuration table entry size with
+ * added base table entry length and increases entry count by 1.
+ *
+ * @mc: configuration table header address
+ * @length: length of the added table entry
+ */
+static inline void mp_add_mpc_entry(struct mp_config_table *mc, uint length)
+{
+ mc->mpc_length += length;
+ mc->mpc_entry_count++;
+}
+
+/**
+ * mp_next_mpe_entry() - Compute MP configuration table end to be used as
+ * next extended table entry start address
+ *
+ * This computes the end address of current MP configuration table,
+ * including any extended configuration table entry.
+ *
+ * @mc: configuration table header address
+ * @return: configuration table end address
+ */
+static inline u32 mp_next_mpe_entry(struct mp_config_table *mc)
+{
+ return (u32)mc + mc->mpc_length + mc->mpe_length;
+}
+
+/**
+ * mp_add_mpe_entry() - Add an extended MP configuration table entry
+ *
+ * This adds the extended MP configuration table entry size with
+ * added extended table entry length.
+ *
+ * @mc: configuration table header address
+ * @mpe: extended table entry base address
+ */
+static inline void mp_add_mpe_entry(struct mp_config_table *mc,
+ struct mp_ext_config *mpe)
+{
+ mc->mpe_length += mpe->mpe_length;
+}
+
+/**
+ * mp_write_floating_table() - Write the MP floating table
+ *
+ * This writes the MP floating table, and points MP configuration table
+ * to its end address so that MP configuration table follows immediately
+ * after the floating table.
+ *
+ * @mf: MP floating table base address
+ * @return: MP configuration table header address
+ */
+struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf);
+
+/**
+ * mp_config_table_init() - Initialize the MP configuration table header
+ *
+ * This populates the MP configuration table header with valid bits.
+ *
+ * @mc: MP configuration table header address
+ */
+void mp_config_table_init(struct mp_config_table *mc);
+
+/**
+ * mp_write_processor() - Write a processor entry
+ *
+ * This writes a processor entry to the configuration table.
+ *
+ * @mc: MP configuration table header address
+ */
+void mp_write_processor(struct mp_config_table *mc);
+
+/**
+ * mp_write_bus() - Write a bus entry
+ *
+ * This writes a bus entry to the configuration table.
+ *
+ * @mc: MP configuration table header address
+ * @id: bus id
+ * @bustype: bus type name
+ */
+void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype);
+
+/**
+ * mp_write_ioapic() - Write an I/O APIC entry
+ *
+ * This writes an I/O APIC entry to the configuration table.
+ *
+ * @mc: MP configuration table header address
+ * @id: I/O APIC id
+ * @ver: I/O APIC version
+ * @apicaddr: I/O APIC address
+ */
+void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr);
+
+/**
+ * mp_write_intsrc() - Write an I/O interrupt assignment entry
+ *
+ * This writes an I/O interrupt assignment entry to the configuration table.
+ *
+ * @mc: MP configuration table header address
+ * @irqtype: IRQ type (INT/NMI/SMI/ExtINT)
+ * @irqflag: IRQ flag (level/trigger)
+ * @srcbus: source bus id where the interrupt comes from
+ * @srcbusirq: IRQ number mapped on the source bus
+ * @dstapic: destination I/O APIC id where the interrupt goes to
+ * @dstirq: destination I/O APIC pin where the interrupt goes to
+ */
+void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag,
+ int srcbus, int srcbusirq, int dstapic, int dstirq);
+
+/**
+ * mp_write_pci_intsrc() - Write a PCI interrupt assignment entry
+ *
+ * This writes a PCI interrupt assignment entry to the configuration table.
+ *
+ * @mc: MP configuration table header address
+ * @irqtype: IRQ type (INT/NMI/SMI/ExtINT)
+ * @srcbus: PCI bus number where the interrupt comes from
+ * @dev: device number on the PCI bus
+ * @pin: PCI interrupt pin (INT A/B/C/D)
+ * @dstapic: destination I/O APIC id where the interrupt goes to
+ * @dstirq: destination I/O APIC pin where the interrupt goes to
+ */
+void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype,
+ int srcbus, int dev, int pin, int dstapic, int dstirq);
+
+/**
+ * mp_write_lintsrc() - Write a local interrupt assignment entry
+ *
+ * This writes a local interrupt assignment entry to the configuration table.
+ *
+ * @mc: MP configuration table header address
+ * @irqtype: IRQ type (INT/NMI/SMI/ExtINT)
+ * @irqflag: IRQ flag (level/trigger)
+ * @srcbus: PCI bus number where the interrupt comes from
+ * @srcbusirq: IRQ number mapped on the source bus
+ * @dstapic: destination local APIC id where the interrupt goes to
+ * @destlint: destination local APIC pin where the interrupt goes to
+ */
+void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag,
+ int srcbus, int srcbusirq, int destapic, int destlint);
+
+
+/**
+ * mp_write_address_space() - Write a system address space entry
+ *
+ * This writes a system address space entry to the configuration table.
+ *
+ * @mc: MP configuration table header address
+ * @busid: bus id for the bus where system address space is mapped
+ * @addr_type: system address type
+ * @addr_base_low: starting address low
+ * @addr_base_high: starting address high
+ * @addr_length_low: address length low
+ * @addr_length_high: address length high
+ */
+void mp_write_address_space(struct mp_config_table *mc,
+ int busid, int addr_type,
+ u32 addr_base_low, u32 addr_base_high,
+ u32 addr_length_low, u32 addr_length_high);
+
+/**
+ * mp_write_bus_hierarchy() - Write a bus hierarchy descriptor entry
+ *
+ * This writes a bus hierarchy descriptor entry to the configuration table.
+ *
+ * @mc: MP configuration table header address
+ * @busid: bus id
+ * @bus_info: bit0 indicates if the bus is a subtractive decode bus
+ * @parent_busid: parent bus id
+ */
+void mp_write_bus_hierarchy(struct mp_config_table *mc,
+ int busid, int bus_info, int parent_busid);
+
+/**
+ * mp_write_compat_address_space() - Write a compat bus address space entry
+ *
+ * This writes a compatibility bus address space modifier entry to the
+ * configuration table.
+ *
+ * @mc: MP configuration table header address
+ * @busid: bus id
+ * @addr_modifier: add or subtract to predefined address range list
+ * @range_list: list of predefined address space ranges
+ */
+void mp_write_compat_address_space(struct mp_config_table *mc, int busid,
+ int addr_modifier, u32 range_list);
+
+/**
+ * mptable_finalize() - Finalize the MP table
+ *
+ * This finalizes the MP table by calculating required checksums.
+ *
+ * @mc: MP configuration table header address
+ * @return: MP table end address
+ */
+u32 mptable_finalize(struct mp_config_table *mc);
+
+/**
+ * write_mp_table() - Write MP table
+ *
+ * This writes MP table at a given address.
+ *
+ * @addr: start address to write MP table
+ * @return: end address of MP table
+ */
+u32 write_mp_table(u32 addr);
+
+#endif /* __ASM_MPSPEC_H */
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 3ad617cb4a..70762eed10 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -21,6 +21,11 @@
#define MTRR_CAP_MSR 0x0fe
#define MTRR_DEF_TYPE_MSR 0x2ff
+#define MTRR_CAP_SMRR (1 << 11)
+#define MTRR_CAP_WC (1 << 10)
+#define MTRR_CAP_FIX (1 << 8)
+#define MTRR_CAP_VCNT_MASK 0xff
+
#define MTRR_DEF_TYPE_EN (1 << 11)
#define MTRR_DEF_TYPE_FIX_EN (1 << 10)
@@ -38,17 +43,17 @@
#define RANGES_PER_FIXED_MTRR 8
#define NUM_FIXED_RANGES (NUM_FIXED_MTRRS * RANGES_PER_FIXED_MTRR)
-#define MTRR_FIX_64K_00000_MSR 0x250
-#define MTRR_FIX_16K_80000_MSR 0x258
-#define MTRR_FIX_16K_A0000_MSR 0x259
-#define MTRR_FIX_4K_C0000_MSR 0x268
-#define MTRR_FIX_4K_C8000_MSR 0x269
-#define MTRR_FIX_4K_D0000_MSR 0x26a
-#define MTRR_FIX_4K_D8000_MSR 0x26b
-#define MTRR_FIX_4K_E0000_MSR 0x26c
-#define MTRR_FIX_4K_E8000_MSR 0x26d
-#define MTRR_FIX_4K_F0000_MSR 0x26e
-#define MTRR_FIX_4K_F8000_MSR 0x26f
+#define MTRR_FIX_64K_00000_MSR 0x250
+#define MTRR_FIX_16K_80000_MSR 0x258
+#define MTRR_FIX_16K_A0000_MSR 0x259
+#define MTRR_FIX_4K_C0000_MSR 0x268
+#define MTRR_FIX_4K_C8000_MSR 0x269
+#define MTRR_FIX_4K_D0000_MSR 0x26a
+#define MTRR_FIX_4K_D8000_MSR 0x26b
+#define MTRR_FIX_4K_E0000_MSR 0x26c
+#define MTRR_FIX_4K_E8000_MSR 0x26d
+#define MTRR_FIX_4K_F0000_MSR 0x26e
+#define MTRR_FIX_4K_F8000_MSR 0x26f
#if !defined(__ASSEMBLER__)
diff --git a/arch/x86/include/asm/tables.h b/arch/x86/include/asm/tables.h
index 8146ba39b2..0aa6d9b33e 100644
--- a/arch/x86/include/asm/tables.h
+++ b/arch/x86/include/asm/tables.h
@@ -28,6 +28,20 @@
u8 table_compute_checksum(void *v, int len);
/**
+ * table_fill_string() - Fill a string with pad in the configuration table
+ *
+ * This fills a string in the configuration table. It copies number of bytes
+ * from the source string, and if source string length is shorter than the
+ * required size to copy, pad the table string with the given pad character.
+ *
+ * @dest: where to fill a string
+ * @src: where to copy from
+ * @n: number of bytes to copy
+ * @pad: character to pad the remaining bytes
+ */
+void table_fill_string(char *dest, const char *src, size_t n, char pad);
+
+/**
* write_tables() - Write x86 configuration tables
*
* This writes x86 configuration tables, including PIRQ routing table,
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index d1d21ed660..4dae365a12 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -8,12 +8,19 @@
#ifndef _U_BOOT_I386_H_
#define _U_BOOT_I386_H_ 1
+extern char gdt_rom[];
+
/* cpu/.../cpu.c */
int arch_cpu_init(void);
int x86_cpu_init_f(void);
int cpu_init_f(void);
void init_gd(gd_t *id, u64 *gdt_addr);
void setup_gdt(gd_t *id, u64 *gdt_addr);
+/*
+ * Setup FSP execution environment GDT to use the one we used in
+ * arch/x86/cpu/start16.S and reload the segment registers.
+ */
+void setup_fsp_gdt(void);
int init_cache(void);
int cleanup_before_linux(void);
@@ -49,6 +56,9 @@ u32 isa_map_rom(u32 bus_addr, int size);
/* arch/x86/lib/... */
int video_bios_init(void);
+/* arch/x86/lib/fsp/... */
+int x86_fsp_init(void);
+
void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
void board_init_f_r(void) __attribute__ ((noreturn));
diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h
index 8e7dd424ca..bf351ed3b6 100644
--- a/arch/x86/include/asm/zimage.h
+++ b/arch/x86/include/asm/zimage.h
@@ -38,5 +38,6 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
ulong *load_addressp);
int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
unsigned long initrd_addr, unsigned long initrd_size);
+void setup_video(struct screen_info *screen_info);
#endif
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 70ad19b263..43489fdc1f 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -15,6 +15,7 @@ obj-y += gcc.o
obj-y += init_helpers.o
obj-y += interrupts.o
obj-y += lpc-uclass.o
+obj-y += mpspec.o
obj-y += cmd_mtrr.o
obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o
diff --git a/arch/x86/lib/bios_asm.S b/arch/x86/lib/bios_asm.S
index 4faa70e314..9dbf969373 100644
--- a/arch/x86/lib/bios_asm.S
+++ b/arch/x86/lib/bios_asm.S
@@ -246,6 +246,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
push %fs
push %gs
+ /* Save real mode SS */
+ movw %ss, %cs:__realmode_ss
+
/* Clear DF to not break ABI assumptions */
cld
@@ -258,12 +261,29 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
enter_protected_mode
+ /*
+ * Now we are in protected mode. We need compute the right ESP based
+ * on saved real mode SS otherwise interrupt_handler() won't get
+ * correct parameters from the stack.
+ */
+ movzwl %cs:__realmode_ss, %ecx
+ shll $4, %ecx
+ addl %ecx, %esp
+
/* Call the C interrupt handler */
movl $interrupt_handler, %eax
call *%eax
+ /* Restore real mode ESP based on saved SS */
+ movzwl %cs:__realmode_ss, %ecx
+ shll $4, %ecx
+ subl %ecx, %esp
+
enter_real_mode
+ /* Restore real mode SS */
+ movw %cs:__realmode_ss, %ss
+
/*
* Restore all registers, including those manipulated by the C
* handler
@@ -276,6 +296,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
popal
iret
+__realmode_ss = PTR_TO_REAL_MODE(.)
+ .word 0
+
.globl asm_realmode_code_size
asm_realmode_code_size:
.long . - asm_realmode_code
diff --git a/arch/x86/lib/bios_interrupts.c b/arch/x86/lib/bios_interrupts.c
index 290990a8bd..47d9f599a3 100644
--- a/arch/x86/lib/bios_interrupts.c
+++ b/arch/x86/lib/bios_interrupts.c
@@ -161,15 +161,7 @@ int int1a_handler(void)
bus = M.x86.R_EBX >> 8;
reg = M.x86.R_EDI;
dev = PCI_BDF(bus, devfn >> 3, devfn & 7);
- if (!dev) {
- debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func,
- bus, devfn);
- /* Or are we supposed to return PCIBIOS_NODEV? */
- M.x86.R_EAX &= 0xffff00ff; /* Clear AH */
- M.x86.R_EAX |= PCIBIOS_BADREG;
- retval = 0;
- return retval;
- }
+
switch (func) {
case 0xb108: /* Read Config Byte */
byte = x86_pci_read_config8(dev, reg);
diff --git a/arch/x86/lib/cmd_mtrr.c b/arch/x86/lib/cmd_mtrr.c
index 7e0506b75d..f632f495ed 100644
--- a/arch/x86/lib/cmd_mtrr.c
+++ b/arch/x86/lib/cmd_mtrr.c
@@ -37,7 +37,8 @@ static int do_mtrr_list(void)
valid = mask & MTRR_PHYS_MASK_VALID;
type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
printf("%d %-5s %-12s %016llx %016llx %016llx\n", i,
- valid ? "Y" : "N", type, base, mask, size);
+ valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
+ mask & ~MTRR_PHYS_MASK_VALID, size);
}
return 0;
diff --git a/arch/x86/lib/fsp/fsp_car.S b/arch/x86/lib/fsp/fsp_car.S
index 5e09568b85..afbf3f9baa 100644
--- a/arch/x86/lib/fsp/fsp_car.S
+++ b/arch/x86/lib/fsp/fsp_car.S
@@ -56,28 +56,10 @@ temp_ram_init_ret:
/* stack grows down from top of CAR */
movl %edx, %esp
+ subl $4, %esp
- /*
- * TODO:
- *
- * According to FSP architecture spec, the fsp_init() will not return
- * to its caller, instead it requires the bootloader to provide a
- * so-called continuation function to pass into the FSP as a parameter
- * of fsp_init, and fsp_init() will call that continuation function
- * directly.
- *
- * The call to fsp_init() may need to be moved out of the car_init()
- * to cpu_init_f() with the help of some inline assembly codes.
- * Note there is another issue that fsp_init() will setup another stack
- * using the fsp_init parameter stack_top after DRAM is initialized,
- * which means any data on the previous stack (on the CAR) gets lost
- * (ie: U-Boot global_data). FSP is supposed to support such scenario,
- * however it does not work. This should be revisited in the future.
- */
- movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax
- xorl %edx, %edx
- xorl %ecx, %ecx
- call fsp_init
+ xor %esi, %esi
+ jmp car_init_done
.global fsp_init_done
fsp_init_done:
@@ -86,6 +68,8 @@ fsp_init_done:
* Save eax to esi temporarily.
*/
movl %eax, %esi
+
+car_init_done:
/*
* Re-initialize the ebp (BIST) to zero, as we already reach here
* which means we passed BIST testing before.
diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c
index 001494d97d..5b256324e1 100644
--- a/arch/x86/lib/fsp/fsp_common.c
+++ b/arch/x86/lib/fsp/fsp_common.c
@@ -46,3 +46,11 @@ void board_final_cleanup(void)
return;
}
+
+int x86_fsp_init(void)
+{
+ if (!gd->arch.hob_list)
+ fsp_init(CONFIG_FSP_TEMP_RAM_ADDR, BOOT_FULL_CONFIG, NULL);
+
+ return 0;
+}
diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c
index 5809235b10..4585166083 100644
--- a/arch/x86/lib/fsp/fsp_support.c
+++ b/arch/x86/lib/fsp/fsp_support.c
@@ -173,6 +173,9 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
post_code(POST_PRE_MRC);
+ /* Load GDT for FSP */
+ setup_fsp_gdt();
+
/*
* Use ASM code to ensure the register value in EAX & ECX
* will be passed into BlContinuationFunc
diff --git a/arch/x86/lib/mpspec.c b/arch/x86/lib/mpspec.c
new file mode 100644
index 0000000000..f16fbcbb0d
--- /dev/null
+++ b/arch/x86/lib/mpspec.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Adapted from coreboot src/arch/x86/boot/mpspec.c
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <asm/cpu.h>
+#include <asm/irq.h>
+#include <asm/ioapic.h>
+#include <asm/lapic.h>
+#include <asm/mpspec.h>
+#include <asm/tables.h>
+#include <dm/uclass-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf)
+{
+ u32 mc;
+
+ memcpy(mf->mpf_signature, MPF_SIGNATURE, 4);
+ mf->mpf_physptr = (u32)mf + sizeof(struct mp_floating_table);
+ mf->mpf_length = 1;
+ mf->mpf_spec = MPSPEC_V14;
+ mf->mpf_checksum = 0;
+ /* We don't use the default configuration table */
+ mf->mpf_feature1 = 0;
+ /* Indicate that virtual wire mode is always implemented */
+ mf->mpf_feature2 = 0;
+ mf->mpf_feature3 = 0;
+ mf->mpf_feature4 = 0;
+ mf->mpf_feature5 = 0;
+ mf->mpf_checksum = table_compute_checksum(mf, mf->mpf_length * 16);
+
+ mc = (u32)mf + sizeof(struct mp_floating_table);
+ return (struct mp_config_table *)mc;
+}
+
+void mp_config_table_init(struct mp_config_table *mc)
+{
+ memcpy(mc->mpc_signature, MPC_SIGNATURE, 4);
+ mc->mpc_length = sizeof(struct mp_config_table);
+ mc->mpc_spec = MPSPEC_V14;
+ mc->mpc_checksum = 0;
+ mc->mpc_oemptr = 0;
+ mc->mpc_oemsize = 0;
+ mc->mpc_entry_count = 0;
+ mc->mpc_lapic = LAPIC_DEFAULT_BASE;
+ mc->mpe_length = 0;
+ mc->mpe_checksum = 0;
+ mc->reserved = 0;
+
+ /* The oem/product id fields are exactly 8/12 bytes long */
+ table_fill_string(mc->mpc_oem, CONFIG_SYS_VENDOR, 8, ' ');
+ table_fill_string(mc->mpc_product, CONFIG_SYS_BOARD, 12, ' ');
+}
+
+void mp_write_processor(struct mp_config_table *mc)
+{
+ struct mpc_config_processor *mpc;
+ struct udevice *dev;
+ u8 boot_apicid, apicver;
+ u32 cpusignature, cpufeature;
+ struct cpuid_result result;
+
+ boot_apicid = lapicid();
+ apicver = lapic_read(LAPIC_LVR) & 0xff;
+ result = cpuid(1);
+ cpusignature = result.eax;
+ cpufeature = result.edx;
+
+ for (uclass_find_first_device(UCLASS_CPU, &dev);
+ dev;
+ uclass_find_next_device(&dev)) {
+ struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+ u8 cpuflag = MPC_CPU_EN;
+
+ if (!device_active(dev))
+ continue;
+
+ mpc = (struct mpc_config_processor *)mp_next_mpc_entry(mc);
+ mpc->mpc_type = MP_PROCESSOR;
+ mpc->mpc_apicid = plat->cpu_id;
+ mpc->mpc_apicver = apicver;
+ if (boot_apicid == plat->cpu_id)
+ cpuflag |= MPC_CPU_BP;
+ mpc->mpc_cpuflag = cpuflag;
+ mpc->mpc_cpusignature = cpusignature;
+ mpc->mpc_cpufeature = cpufeature;
+ mpc->mpc_reserved[0] = 0;
+ mpc->mpc_reserved[1] = 0;
+ mp_add_mpc_entry(mc, sizeof(*mpc));
+ }
+}
+
+void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype)
+{
+ struct mpc_config_bus *mpc;
+
+ mpc = (struct mpc_config_bus *)mp_next_mpc_entry(mc);
+ mpc->mpc_type = MP_BUS;
+ mpc->mpc_busid = id;
+ memcpy(mpc->mpc_bustype, bustype, 6);
+ mp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr)
+{
+ struct mpc_config_ioapic *mpc;
+
+ mpc = (struct mpc_config_ioapic *)mp_next_mpc_entry(mc);
+ mpc->mpc_type = MP_IOAPIC;
+ mpc->mpc_apicid = id;
+ mpc->mpc_apicver = ver;
+ mpc->mpc_flags = MPC_APIC_USABLE;
+ mpc->mpc_apicaddr = apicaddr;
+ mp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag,
+ int srcbus, int srcbusirq, int dstapic, int dstirq)
+{
+ struct mpc_config_intsrc *mpc;
+
+ mpc = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc);
+ mpc->mpc_type = MP_INTSRC;
+ mpc->mpc_irqtype = irqtype;
+ mpc->mpc_irqflag = irqflag;
+ mpc->mpc_srcbus = srcbus;
+ mpc->mpc_srcbusirq = srcbusirq;
+ mpc->mpc_dstapic = dstapic;
+ mpc->mpc_dstirq = dstirq;
+ mp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype,
+ int srcbus, int dev, int pin, int dstapic, int dstirq)
+{
+ u8 srcbusirq = (dev << 2) | (pin - 1);
+
+ mp_write_intsrc(mc, irqtype, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW,
+ srcbus, srcbusirq, dstapic, dstirq);
+}
+
+void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag,
+ int srcbus, int srcbusirq, int destapic, int destlint)
+{
+ struct mpc_config_lintsrc *mpc;
+
+ mpc = (struct mpc_config_lintsrc *)mp_next_mpc_entry(mc);
+ mpc->mpc_type = MP_LINTSRC;
+ mpc->mpc_irqtype = irqtype;
+ mpc->mpc_irqflag = irqflag;
+ mpc->mpc_srcbusid = srcbus;
+ mpc->mpc_srcbusirq = srcbusirq;
+ mpc->mpc_destapic = destapic;
+ mpc->mpc_destlint = destlint;
+ mp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+void mp_write_address_space(struct mp_config_table *mc,
+ int busid, int addr_type,
+ u32 addr_base_low, u32 addr_base_high,
+ u32 addr_length_low, u32 addr_length_high)
+{
+ struct mp_ext_system_address_space *mpe;
+
+ mpe = (struct mp_ext_system_address_space *)mp_next_mpe_entry(mc);
+ mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE;
+ mpe->mpe_length = sizeof(*mpe);
+ mpe->mpe_busid = busid;
+ mpe->mpe_addr_type = addr_type;
+ mpe->mpe_addr_base_low = addr_base_low;
+ mpe->mpe_addr_base_high = addr_base_high;
+ mpe->mpe_addr_length_low = addr_length_low;
+ mpe->mpe_addr_length_high = addr_length_high;
+ mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
+}
+
+void mp_write_bus_hierarchy(struct mp_config_table *mc,
+ int busid, int bus_info, int parent_busid)
+{
+ struct mp_ext_bus_hierarchy *mpe;
+
+ mpe = (struct mp_ext_bus_hierarchy *)mp_next_mpe_entry(mc);
+ mpe->mpe_type = MPE_BUS_HIERARCHY;
+ mpe->mpe_length = sizeof(*mpe);
+ mpe->mpe_busid = busid;
+ mpe->mpe_bus_info = bus_info;
+ mpe->mpe_parent_busid = parent_busid;
+ mpe->reserved[0] = 0;
+ mpe->reserved[1] = 0;
+ mpe->reserved[2] = 0;
+ mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
+}
+
+void mp_write_compat_address_space(struct mp_config_table *mc, int busid,
+ int addr_modifier, u32 range_list)
+{
+ struct mp_ext_compat_address_space *mpe;
+
+ mpe = (struct mp_ext_compat_address_space *)mp_next_mpe_entry(mc);
+ mpe->mpe_type = MPE_COMPAT_ADDRESS_SPACE;
+ mpe->mpe_length = sizeof(*mpe);
+ mpe->mpe_busid = busid;
+ mpe->mpe_addr_modifier = addr_modifier;
+ mpe->mpe_range_list = range_list;
+ mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
+}
+
+u32 mptable_finalize(struct mp_config_table *mc)
+{
+ u32 end;
+
+ mc->mpe_checksum = table_compute_checksum((void *)mp_next_mpc_entry(mc),
+ mc->mpe_length);
+ mc->mpc_checksum = table_compute_checksum(mc, mc->mpc_length);
+ end = mp_next_mpe_entry(mc);
+
+ debug("Write the MP table at: %x - %x\n", (u32)mc, end);
+
+ return end;
+}
+
+static void mptable_add_isa_interrupts(struct mp_config_table *mc, int bus_isa,
+ int apicid, int external_int2)
+{
+ int i;
+
+ mp_write_intsrc(mc, external_int2 ? MP_INT : MP_EXTINT,
+ MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+ bus_isa, 0, apicid, 0);
+ mp_write_intsrc(mc, MP_INT, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+ bus_isa, 1, apicid, 1);
+ mp_write_intsrc(mc, external_int2 ? MP_EXTINT : MP_INT,
+ MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+ bus_isa, 0, apicid, 2);
+
+ for (i = 3; i < 16; i++)
+ mp_write_intsrc(mc, MP_INT,
+ MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+ bus_isa, i, apicid, i);
+}
+
+/*
+ * Check duplicated I/O interrupt assignment table entry, to make sure
+ * there is only one entry with the given bus, device and interrupt pin.
+ */
+static bool check_dup_entry(struct mpc_config_intsrc *intsrc_base,
+ int entry_num, int bus, int device, int pin)
+{
+ struct mpc_config_intsrc *intsrc = intsrc_base;
+ int i;
+
+ for (i = 0; i < entry_num; i++) {
+ if (intsrc->mpc_srcbus == bus &&
+ intsrc->mpc_srcbusirq == ((device << 2) | (pin - 1)))
+ break;
+ intsrc++;
+ }
+
+ return (i == entry_num) ? false : true;
+}
+
+static int mptable_add_intsrc(struct mp_config_table *mc,
+ int bus_isa, int apicid)
+{
+ struct mpc_config_intsrc *intsrc_base;
+ int intsrc_entries = 0;
+ const void *blob = gd->fdt_blob;
+ int node;
+ int len, count;
+ const u32 *cell;
+ int i;
+
+ /* Legacy Interrupts */
+ debug("Writing ISA IRQs\n");
+ mptable_add_isa_interrupts(mc, bus_isa, apicid, 0);
+
+ /* Get I/O interrupt information from device tree */
+ node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER);
+ if (node < 0) {
+ debug("%s: Cannot find irq router node\n", __func__);
+ return -ENOENT;
+ }
+
+ cell = fdt_getprop(blob, node, "intel,pirq-routing", &len);
+ if (!cell)
+ return -ENOENT;
+
+ if ((len % sizeof(struct pirq_routing)) == 0)
+ count = len / sizeof(struct pirq_routing);
+ else
+ return -EINVAL;
+
+ intsrc_base = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc);
+
+ for (i = 0; i < count; i++) {
+ struct pirq_routing pr;
+
+ pr.bdf = fdt_addr_to_cpu(cell[0]);
+ pr.pin = fdt_addr_to_cpu(cell[1]);
+ pr.pirq = fdt_addr_to_cpu(cell[2]);
+
+ if (check_dup_entry(intsrc_base, intsrc_entries,
+ PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin)) {
+ debug("found entry for bus %d device %d INT%c, skipping\n",
+ PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
+ 'A' + pr.pin - 1);
+ cell += sizeof(struct pirq_routing) / sizeof(u32);
+ continue;
+ }
+
+ /* PIRQ[A-H] are always connected to I/O APIC INTPIN#16-23 */
+ mp_write_pci_intsrc(mc, MP_INT, PCI_BUS(pr.bdf),
+ PCI_DEV(pr.bdf), pr.pin, apicid,
+ pr.pirq + 16);
+ intsrc_entries++;
+ cell += sizeof(struct pirq_routing) / sizeof(u32);
+ }
+
+ return 0;
+}
+
+static void mptable_add_lintsrc(struct mp_config_table *mc, int bus_isa)
+{
+ mp_write_lintsrc(mc, MP_EXTINT,
+ MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+ bus_isa, 0, MP_APIC_ALL, 0);
+ mp_write_lintsrc(mc, MP_NMI,
+ MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+ bus_isa, 0, MP_APIC_ALL, 1);
+}
+
+u32 write_mp_table(u32 addr)
+{
+ struct mp_config_table *mc;
+ int ioapic_id, ioapic_ver;
+ int bus_isa = 0xff;
+ int ret;
+ u32 end;
+
+ /* 16 byte align the table address */
+ addr = ALIGN(addr, 16);
+
+ /* Write floating table */
+ mc = mp_write_floating_table((struct mp_floating_table *)addr);
+
+ /* Write configuration table header */
+ mp_config_table_init(mc);
+
+ /* Write processor entry */
+ mp_write_processor(mc);
+
+ /* Write bus entry */
+ mp_write_bus(mc, bus_isa, BUSTYPE_ISA);
+
+ /* Write I/O APIC entry */
+ ioapic_id = io_apic_read(IO_APIC_ID) >> 24;
+ ioapic_ver = io_apic_read(IO_APIC_VER) & 0xff;
+ mp_write_ioapic(mc, ioapic_id, ioapic_ver, IO_APIC_ADDR);
+
+ /* Write I/O interrupt assignment entry */
+ ret = mptable_add_intsrc(mc, bus_isa, ioapic_id);
+ if (ret)
+ debug("Failed to write I/O interrupt assignment table\n");
+
+ /* Write local interrupt assignment entry */
+ mptable_add_lintsrc(mc, bus_isa);
+
+ /* Finalize the MP table */
+ end = mptable_finalize(mc);
+
+ return end;
+}
diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c
index 8031201a49..75ffbc1b22 100644
--- a/arch/x86/lib/tables.c
+++ b/arch/x86/lib/tables.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <asm/sfi.h>
+#include <asm/mpspec.h>
#include <asm/tables.h>
u8 table_compute_checksum(void *v, int len)
@@ -20,6 +21,20 @@ u8 table_compute_checksum(void *v, int len)
return checksum;
}
+void table_fill_string(char *dest, const char *src, size_t n, char pad)
+{
+ int start, len;
+ int i;
+
+ strncpy(dest, src, n);
+
+ /* Fill the remaining bytes with pad */
+ len = strlen(src);
+ start = len < n ? len : n;
+ for (i = start; i < n; i++)
+ dest[i] = pad;
+}
+
void write_tables(void)
{
u32 __maybe_unused rom_table_end = ROM_TABLE_ADDR;
@@ -32,4 +47,8 @@ void write_tables(void)
rom_table_end = write_sfi_table(rom_table_end);
rom_table_end = ALIGN(rom_table_end, 1024);
#endif
+#ifdef CONFIG_GENERATE_MP_TABLE
+ rom_table_end = write_mp_table(rom_table_end);
+ rom_table_end = ALIGN(rom_table_end, 1024);
+#endif
}
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index c3f8a7308f..144471c5bb 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -273,6 +273,8 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
build_command_line(cmd_line, auto_boot);
}
+ setup_video(&setup_base->screen_info);
+
return 0;
}