summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/cpu/arm926ejs/kirkwood/Kconfig4
-rw-r--r--arch/arm/cpu/armv7/sunxi/Makefile5
-rw-r--r--arch/arm/cpu/armv7/sunxi/board.c3
-rw-r--r--arch/arm/cpu/armv7/sunxi/clock_sun6i.c26
-rw-r--r--arch/arm/cpu/armv7/sunxi/cpu_info.c57
-rw-r--r--arch/arm/cpu/armv7/sunxi/dram_sun4i.c17
-rw-r--r--arch/arm/cpu/armv7/sunxi/dram_sun6i.c77
-rw-r--r--arch/arm/cpu/armv7/sunxi/dram_sun8i.c345
-rw-r--r--arch/arm/cpu/armv7/sunxi/p2wi.c14
-rw-r--r--arch/arm/cpu/armv7/sunxi/psci.S201
-rw-r--r--arch/arm/cpu/armv7/sunxi/rsb.c158
-rw-r--r--arch/arm/cpu/armv7/sunxi/usbc.c272
-rw-r--r--arch/arm/cpu/armv8/cache.S2
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock.h1
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun4i.h23
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun6i.h31
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu.h13
-rw-r--r--arch/arm/include/asm/arch-sunxi/display.h219
-rw-r--r--arch/arm/include/asm/arch-sunxi/dram.h29
-rw-r--r--arch/arm/include/asm/arch-sunxi/dram_sun8i.h266
-rw-r--r--arch/arm/include/asm/arch-sunxi/gpio.h22
-rw-r--r--arch/arm/include/asm/arch-sunxi/prcm.h3
-rw-r--r--arch/arm/include/asm/arch-sunxi/rsb.h55
-rw-r--r--arch/arm/include/asm/arch-sunxi/usbc.h20
-rw-r--r--arch/m68k/Kconfig4
-rw-r--r--arch/powerpc/cpu/ppc4xx/Kconfig73
-rw-r--r--arch/x86/Kconfig39
-rw-r--r--arch/x86/cpu/Makefile1
-rw-r--r--arch/x86/cpu/coreboot/Kconfig15
-rw-r--r--arch/x86/cpu/coreboot/coreboot.c22
-rw-r--r--arch/x86/cpu/coreboot/pci.c30
-rw-r--r--arch/x86/cpu/coreboot/timestamp.c33
-rw-r--r--arch/x86/cpu/ivybridge/car.S74
-rw-r--r--arch/x86/cpu/ivybridge/cpu.c27
-rw-r--r--arch/x86/cpu/ivybridge/gma.c16
-rw-r--r--arch/x86/cpu/ivybridge/microcode_intel.c26
-rw-r--r--arch/x86/cpu/ivybridge/sdram.c10
-rw-r--r--arch/x86/cpu/mtrr.c81
-rw-r--r--arch/x86/cpu/pci.c11
-rw-r--r--arch/x86/cpu/queensbay/fsp_support.c95
-rw-r--r--arch/x86/cpu/queensbay/tnc_dram.c39
-rw-r--r--arch/x86/cpu/start.S8
-rw-r--r--arch/x86/dts/Makefile4
-rw-r--r--arch/x86/dts/alex.dts24
-rw-r--r--[l---------]arch/x86/dts/chromebook_link.dts217
-rw-r--r--arch/x86/dts/coreboot.dtsi17
-rw-r--r--arch/x86/dts/crownbay.dts94
-rw-r--r--arch/x86/dts/link.dts224
-rw-r--r--arch/x86/dts/serial.dtsi9
-rw-r--r--arch/x86/include/asm/arch-ivybridge/microcode.h6
-rw-r--r--arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h68
-rw-r--r--arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h5
-rw-r--r--arch/x86/include/asm/global_data.h16
-rw-r--r--arch/x86/include/asm/mtrr.h163
-rw-r--r--arch/x86/include/asm/pci.h2
-rw-r--r--arch/x86/lib/Makefile1
-rw-r--r--arch/x86/lib/bios.c14
-rw-r--r--arch/x86/lib/cmd_hob.c18
-rw-r--r--arch/x86/lib/cmd_mtrr.c138
-rw-r--r--arch/x86/lib/init_helpers.c8
-rw-r--r--arch/x86/lib/tsc_timer.c8
61 files changed, 2715 insertions, 788 deletions
diff --git a/arch/arm/cpu/arm926ejs/kirkwood/Kconfig b/arch/arm/cpu/arm926ejs/kirkwood/Kconfig
index 6c037a16c9..45c6687d0b 100644
--- a/arch/arm/cpu/arm926ejs/kirkwood/Kconfig
+++ b/arch/arm/cpu/arm926ejs/kirkwood/Kconfig
@@ -57,6 +57,9 @@ config TARGET_DOCKSTAR
config TARGET_GOFLEXHOME
bool "GoFlex Home Board"
+config TARGET_NAS220
+ bool "BlackArmor NAS220"
+
endchoice
config SYS_SOC
@@ -80,5 +83,6 @@ source "board/LaCie/wireless_space/Kconfig"
source "board/raidsonic/ib62x0/Kconfig"
source "board/Seagate/dockstar/Kconfig"
source "board/Seagate/goflexhome/Kconfig"
+source "board/Seagate/nas220/Kconfig"
endif
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 3b6ae47329..1720f7db01 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -10,10 +10,13 @@
obj-y += timer.o
obj-y += board.o
obj-y += clock.o
+obj-y += cpu_info.o
obj-y += pinmux.o
+obj-y += usbc.o
obj-$(CONFIG_MACH_SUN6I) += prcm.o
obj-$(CONFIG_MACH_SUN8I) += prcm.o
obj-$(CONFIG_MACH_SUN6I) += p2wi.o
+obj-$(CONFIG_MACH_SUN8I) += rsb.o
obj-$(CONFIG_MACH_SUN4I) += clock_sun4i.o
obj-$(CONFIG_MACH_SUN5I) += clock_sun4i.o
obj-$(CONFIG_MACH_SUN6I) += clock_sun6i.o
@@ -21,7 +24,6 @@ obj-$(CONFIG_MACH_SUN7I) += clock_sun4i.o
obj-$(CONFIG_MACH_SUN8I) += clock_sun6i.o
ifndef CONFIG_SPL_BUILD
-obj-y += cpu_info.o
ifdef CONFIG_ARMV7_PSCI
obj-y += psci.o
endif
@@ -32,6 +34,7 @@ obj-$(CONFIG_MACH_SUN4I) += dram_sun4i.o
obj-$(CONFIG_MACH_SUN5I) += dram_sun4i.o
obj-$(CONFIG_MACH_SUN6I) += dram_sun6i.o
obj-$(CONFIG_MACH_SUN7I) += dram_sun4i.o
+obj-$(CONFIG_MACH_SUN8I) += dram_sun8i.o
ifdef CONFIG_SPL_FEL
obj-y += start.o
endif
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index 9b3e80c24a..bc98c564f9 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -114,7 +114,8 @@ void reset_cpu(ulong addr)
/* do some early init */
void s_init(void)
{
-#if defined CONFIG_SPL_BUILD && defined CONFIG_MACH_SUN6I
+#if defined CONFIG_SPL_BUILD && \
+ (defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I)
/* Magic (undocmented) value taken from boot0, without this DRAM
* access gets messed up (seems cache related) */
setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
index 8e949c6901..d7a7040b72 100644
--- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
@@ -97,6 +97,7 @@ void clock_set_pll1(unsigned int clk)
{
struct sunxi_ccm_reg * const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ const int p = 0;
int k = 1;
int m = 1;
@@ -113,8 +114,11 @@ void clock_set_pll1(unsigned int clk)
CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
&ccm->cpu_axi_cfg);
- /* PLL1 rate = 24000000 * n * k / m */
- writel(CCM_PLL1_CTRL_EN | CCM_PLL1_CTRL_MAGIC |
+ /*
+ * sun6i: PLL1 rate = ((24000000 * n * k) >> 0) / m (p is ignored)
+ * sun8i: PLL1 rate = ((24000000 * n * k) >> p) / m
+ */
+ writel(CCM_PLL1_CTRL_EN | CCM_PLL1_CTRL_P(p) |
CCM_PLL1_CTRL_N(clk / (24000000 * k / m)) |
CCM_PLL1_CTRL_K(k) | CCM_PLL1_CTRL_M(m), &ccm->pll1_cfg);
sdelay(200);
@@ -144,15 +148,25 @@ void clock_set_pll3(unsigned int clk)
&ccm->pll3_cfg);
}
-void clock_set_pll5(unsigned int clk)
+void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
{
struct sunxi_ccm_reg * const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
- const int k = 2;
- const int m = 1;
+ const int max_n = 32;
+ int k = 1, m = 2;
+
+ if (sigma_delta_enable)
+ writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg);
/* PLL5 rate = 24000000 * n * k / m */
- writel(CCM_PLL5_CTRL_EN | CCM_PLL5_CTRL_UPD |
+ if (clk > 24000000 * k * max_n / m) {
+ m = 1;
+ if (clk > 24000000 * k * max_n / m)
+ k = 2;
+ }
+ writel(CCM_PLL5_CTRL_EN |
+ (sigma_delta_enable ? CCM_PLL5_CTRL_SIGMA_DELTA_EN : 0) |
+ CCM_PLL5_CTRL_UPD |
CCM_PLL5_CTRL_N(clk / (24000000 * k / m)) |
CCM_PLL5_CTRL_K(k) | CCM_PLL5_CTRL_M(m), &ccm->pll5_cfg);
diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c
index 41b9add297..b6cb9dea64 100644
--- a/arch/arm/cpu/armv7/sunxi/cpu_info.c
+++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c
@@ -9,6 +9,33 @@
#include <common.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
+#include <asm/arch/clock.h>
+#include <axp221.h>
+
+#ifdef CONFIG_MACH_SUN6I
+int sunxi_get_ss_bonding_id(void)
+{
+ struct sunxi_ccm_reg * const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ static int bonding_id = -1;
+
+ if (bonding_id != -1)
+ return bonding_id;
+
+ /* Enable Security System */
+ setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_SS);
+ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_SS);
+
+ bonding_id = readl(SUNXI_SS_BASE);
+ bonding_id = (bonding_id >> 16) & 0x7;
+
+ /* Disable Security System again */
+ clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_SS);
+ clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_SS);
+
+ return bonding_id;
+}
+#endif
#ifdef CONFIG_DISPLAY_CPUINFO
int print_cpuinfo(void)
@@ -24,7 +51,17 @@ int print_cpuinfo(void)
default: puts("CPU: Allwinner A1X (SUN5I)\n");
}
#elif defined CONFIG_MACH_SUN6I
- puts("CPU: Allwinner A31 (SUN6I)\n");
+ switch (sunxi_get_ss_bonding_id()) {
+ case SUNXI_SS_BOND_ID_A31:
+ puts("CPU: Allwinner A31 (SUN6I)\n");
+ break;
+ case SUNXI_SS_BOND_ID_A31S:
+ puts("CPU: Allwinner A31s (SUN6I)\n");
+ break;
+ default:
+ printf("CPU: Allwinner A31? (SUN6I, id: %d)\n",
+ sunxi_get_ss_bonding_id());
+ }
#elif defined CONFIG_MACH_SUN7I
puts("CPU: Allwinner A20 (SUN7I)\n");
#elif defined CONFIG_MACH_SUN8I
@@ -36,3 +73,21 @@ int print_cpuinfo(void)
return 0;
}
#endif
+
+int sunxi_get_sid(unsigned int *sid)
+{
+#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
+#ifdef CONFIG_AXP221_POWER
+ return axp221_get_sid(sid);
+#else
+ return -ENODEV;
+#endif
+#else
+ int i;
+
+ for (i = 0; i< 4; i++)
+ sid[i] = readl(SUNXI_SID_BASE + 4 * i);
+
+ return 0;
+#endif
+}
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c b/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
index ec8aaa7d48..c736fa3b47 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
@@ -36,24 +36,11 @@
#define CPU_CFG_CHIP_REV_B 0x3
/*
- * Wait up to 1s for value to be set in given part of reg.
- */
-static void await_completion(u32 *reg, u32 mask, u32 val)
-{
- unsigned long tmo = timer_get_us() + 1000000;
-
- while ((readl(reg) & mask) != val) {
- if (timer_get_us() > tmo)
- panic("Timeout initialising DRAM\n");
- }
-}
-
-/*
* Wait up to 1s for mask to be clear in given reg.
*/
static inline void await_bits_clear(u32 *reg, u32 mask)
{
- await_completion(reg, mask, 0);
+ mctl_await_completion(reg, mask, 0);
}
/*
@@ -61,7 +48,7 @@ static inline void await_bits_clear(u32 *reg, u32 mask)
*/
static inline void await_bits_set(u32 *reg, u32 mask)
{
- await_completion(reg, mask, mask);
+ mctl_await_completion(reg, mask, mask);
}
/*
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
index 699173cf69..5dbbf6186f 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
@@ -17,9 +17,7 @@
#include <asm/arch/dram.h>
#include <asm/arch/prcm.h>
-/* DRAM clk & zq defaults, maybe turn these into Kconfig options ? */
-#define DRAM_CLK_DEFAULT 312000000
-#define DRAM_ZQ_DEFAULT 0x78
+#define DRAM_CLK (CONFIG_DRAM_CLK * 1000000)
struct dram_sun6i_para {
u8 bus_width;
@@ -29,31 +27,18 @@ struct dram_sun6i_para {
u16 page_size;
};
-/*
- * Wait up to 1s for value to be set in given part of reg.
- */
-static void await_completion(u32 *reg, u32 mask, u32 val)
-{
- unsigned long tmo = timer_get_us() + 1000000;
-
- while ((readl(reg) & mask) != val) {
- if (timer_get_us() > tmo)
- panic("Timeout initialising DRAM\n");
- }
-}
-
static void mctl_sys_init(void)
{
struct sunxi_ccm_reg * const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
const int dram_clk_div = 2;
- clock_set_pll5(DRAM_CLK_DEFAULT * dram_clk_div);
+ clock_set_pll5(DRAM_CLK * dram_clk_div, false);
clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK,
CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST |
CCM_DRAMCLK_CFG_UPD);
- await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
+ mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
writel(MDFS_CLK_DEFAULT, &ccm->mdfs_clk_cfg);
@@ -109,8 +94,8 @@ static bool mctl_rank_detect(u32 *gsr0, int rank)
const u32 done = MCTL_DX_GSR0_RANK0_TRAIN_DONE << rank;
const u32 err = MCTL_DX_GSR0_RANK0_TRAIN_ERR << rank;
- await_completion(gsr0, done, done);
- await_completion(gsr0 + 0x10, done, done);
+ mctl_await_completion(gsr0, done, done);
+ mctl_await_completion(gsr0 + 0x10, done, done);
return !(readl(gsr0) & err) && !(readl(gsr0 + 0x10) & err);
}
@@ -131,7 +116,7 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
}
writel(MCTL_MCMD_NOP, &mctl_ctl->mcmd);
- await_completion(&mctl_ctl->mcmd, MCTL_MCMD_BUSY, 0);
+ mctl_await_completion(&mctl_ctl->mcmd, MCTL_MCMD_BUSY, 0);
/* PHY initialization */
writel(MCTL_PGCR, &mctl_phy->pgcr);
@@ -168,14 +153,14 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx2gcr);
writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx3gcr);
- await_completion(&mctl_phy->pgsr, 0x03, 0x03);
+ mctl_await_completion(&mctl_phy->pgsr, 0x03, 0x03);
- writel(DRAM_ZQ_DEFAULT, &mctl_phy->zq0cr1);
+ writel(CONFIG_DRAM_ZQ, &mctl_phy->zq0cr1);
setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS);
writel(MCTL_PIR_STEP1, &mctl_phy->pir);
udelay(10);
- await_completion(&mctl_phy->pgsr, 0x1f, 0x1f);
+ mctl_await_completion(&mctl_phy->pgsr, 0x1f, 0x1f);
/* rank detect */
if (!mctl_rank_detect(&mctl_phy->dx0gsr0, 1)) {
@@ -206,19 +191,19 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS);
writel(MCTL_PIR_STEP2, &mctl_phy->pir);
udelay(10);
- await_completion(&mctl_phy->pgsr, 0x11, 0x11);
+ mctl_await_completion(&mctl_phy->pgsr, 0x11, 0x11);
if (readl(&mctl_phy->pgsr) & MCTL_PGSR_TRAIN_ERR_MASK)
panic("Training error initialising DRAM\n");
/* Move to configure state */
writel(MCTL_SCTL_CONFIG, &mctl_ctl->sctl);
- await_completion(&mctl_ctl->sstat, 0x07, 0x01);
+ mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x01);
/* Set number of clks per micro-second */
- writel(DRAM_CLK_DEFAULT / 1000000, &mctl_ctl->togcnt1u);
+ writel(DRAM_CLK / 1000000, &mctl_ctl->togcnt1u);
/* Set number of clks per 100 nano-seconds */
- writel(DRAM_CLK_DEFAULT / 10000000, &mctl_ctl->togcnt100n);
+ writel(DRAM_CLK / 10000000, &mctl_ctl->togcnt100n);
/* Set memory timing registers */
writel(MCTL_TREFI, &mctl_ctl->trefi);
writel(MCTL_TMRD, &mctl_ctl->tmrd);
@@ -272,7 +257,7 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
/* Move to access state */
writel(MCTL_SCTL_ACCESS, &mctl_ctl->sctl);
- await_completion(&mctl_ctl->sstat, 0x07, 0x03);
+ mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x03);
}
static void mctl_com_init(struct dram_sun6i_para *para)
@@ -341,20 +326,6 @@ static void mctl_port_cfg(void)
writel(0x00000307, &mctl_com->mbagcr[5]);
}
-static bool mctl_mem_matches(u32 offset)
-{
- const int match_count = 64;
- int i, matches = 0;
-
- for (i = 0; i < match_count; i++) {
- if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
- readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
- matches++;
- }
-
- return matches == match_count;
-}
-
unsigned long sunxi_dram_init(void)
{
struct sunxi_mctl_com_reg * const mctl_com =
@@ -371,18 +342,26 @@ unsigned long sunxi_dram_init(void)
.rows = 16,
};
+ /* A31s only has one channel */
+ if (sunxi_get_ss_bonding_id() == SUNXI_SS_BOND_ID_A31S)
+ para.chan = 1;
+
mctl_sys_init();
mctl_dll_init(0, &para);
- mctl_dll_init(1, &para);
+ setbits_le32(&mctl_com->ccr, MCTL_CCR_CH0_CLK_EN);
+
+ if (para.chan == 2) {
+ mctl_dll_init(1, &para);
+ setbits_le32(&mctl_com->ccr, MCTL_CCR_CH1_CLK_EN);
+ }
- setbits_le32(&mctl_com->ccr,
- MCTL_CCR_MASTER_CLK_EN |
- MCTL_CCR_CH0_CLK_EN |
- MCTL_CCR_CH1_CLK_EN);
+ setbits_le32(&mctl_com->ccr, MCTL_CCR_MASTER_CLK_EN);
mctl_channel_init(0, &para);
- mctl_channel_init(1, &para);
+ if (para.chan == 2)
+ mctl_channel_init(1, &para);
+
mctl_com_init(&para);
mctl_port_cfg();
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
new file mode 100644
index 0000000000..3d7964d1af
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
@@ -0,0 +1,345 @@
+/*
+ * Sun8i platform dram controller init.
+ *
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * Note this code uses a lot of magic hex values, that is because this code
+ * simply replays the init sequence as done by the Allwinner boot0 code, so
+ * we do not know what these values mean. There are no symbolic constants for
+ * these magic values, since we do not know how to name them and making up
+ * names for them is not useful.
+ *
+ * The register-layout of the sunxi_mctl_phy_reg-s looks a lot like the one
+ * found in the TI Keystone2 documentation:
+ * http://www.ti.com/lit/ug/spruhn7a/spruhn7a.pdf
+ * "Table4-2 DDR3 PHY Registers"
+ * This may be used as a (possible) reference for future work / cleanups.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/prcm.h>
+
+static const struct dram_para dram_para = {
+ .clock = CONFIG_DRAM_CLK,
+ .type = 3,
+ .zq = CONFIG_DRAM_ZQ,
+ .odt_en = 1,
+ .para1 = 0, /* not used (only used when tpr13 bit 31 is set */
+ .para2 = 0, /* not used (only used when tpr13 bit 31 is set */
+ .mr0 = 6736,
+ .mr1 = 4,
+ .mr2 = 16,
+ .mr3 = 0,
+ /* tpr0 - 10 contain timing constants or-ed together in u32 vals */
+ .tpr0 = 0x2ab83def,
+ .tpr1 = 0x18082356,
+ .tpr2 = 0x00034156,
+ .tpr3 = 0x448c5533,
+ .tpr4 = 0x08010d00,
+ .tpr5 = 0x0340b20f,
+ .tpr6 = 0x20d118cc,
+ .tpr7 = 0x14062485,
+ .tpr8 = 0x220d1d52,
+ .tpr9 = 0x1e078c22,
+ .tpr10 = 0x3c,
+ .tpr11 = 0, /* not used */
+ .tpr12 = 0, /* not used */
+ .tpr13 = 0x30000,
+};
+
+static void mctl_sys_init(void)
+{
+ struct sunxi_ccm_reg * const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+ /* enable pll5, note the divide by 2 is deliberate! */
+ clock_set_pll5(dram_para.clock * 1000000 / 2,
+ dram_para.tpr13 & 0x40000);
+
+ /* deassert ahb mctl reset */
+ setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
+
+ /* enable ahb mctl clock */
+ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
+}
+
+static void mctl_apply_odt_correction(u32 *reg, int correction)
+{
+ int val;
+
+ val = (readl(reg) >> 8) & 0xff;
+ val += correction;
+
+ /* clamp */
+ if (val < 0)
+ val = 0;
+ else if (val > 255)
+ val = 255;
+
+ clrsetbits_le32(reg, 0xff00, val << 8);
+}
+
+static void mctl_init(u32 *bus_width)
+{
+ struct sunxi_ccm_reg * const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ struct sunxi_mctl_com_reg * const mctl_com =
+ (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+ struct sunxi_mctl_ctl_reg * const mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+ struct sunxi_mctl_phy_reg * const mctl_phy =
+ (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+ int correction;
+
+ if (dram_para.tpr13 & 0x20)
+ writel(0x40b, &mctl_phy->dcr);
+ else
+ writel(0x1000040b, &mctl_phy->dcr);
+
+ if (dram_para.clock >= 480)
+ writel(0x5c000, &mctl_phy->dllgcr);
+ else
+ writel(0xdc000, &mctl_phy->dllgcr);
+
+ writel(0x0a003e3f, &mctl_phy->pgcr0);
+ writel(0x03008421, &mctl_phy->pgcr1);
+
+ writel(dram_para.mr0, &mctl_phy->mr0);
+ writel(dram_para.mr1, &mctl_phy->mr1);
+ writel(dram_para.mr2, &mctl_phy->mr2);
+ writel(dram_para.mr3, &mctl_phy->mr3);
+
+ if (!(dram_para.tpr13 & 0x10000)) {
+ clrsetbits_le32(&mctl_phy->dx0gcr, 0x3800, 0x2000);
+ clrsetbits_le32(&mctl_phy->dx1gcr, 0x3800, 0x2000);
+ }
+
+ /*
+ * All the masking and shifting below converts what I assume are DDR
+ * timing constants from Allwinner dram_para tpr format to the actual
+ * timing registers format.
+ */
+
+ writel((dram_para.tpr0 & 0x000fffff), &mctl_phy->ptr2);
+ writel((dram_para.tpr1 & 0x1fffffff), &mctl_phy->ptr3);
+ writel((dram_para.tpr0 & 0x3ff00000) >> 2 |
+ (dram_para.tpr2 & 0x0003ffff), &mctl_phy->ptr4);
+
+ writel(dram_para.tpr3, &mctl_phy->dtpr0);
+ writel(dram_para.tpr4, &mctl_phy->dtpr2);
+
+ writel(0x01000081, &mctl_phy->dtcr);
+
+ if (dram_para.clock <= 240 || !(dram_para.odt_en & 0x01)) {
+ clrbits_le32(&mctl_phy->dx0gcr, 0x600);
+ clrbits_le32(&mctl_phy->dx1gcr, 0x600);
+ }
+ if (dram_para.clock <= 240) {
+ writel(0, &mctl_phy->odtcr);
+ writel(0, &mctl_ctl->odtmap);
+ }
+
+ writel(((dram_para.tpr5 & 0x0f00) << 12) |
+ ((dram_para.tpr5 & 0x00f8) << 9) |
+ ((dram_para.tpr5 & 0x0007) << 8),
+ &mctl_ctl->rfshctl0);
+
+ writel(((dram_para.tpr5 & 0x0003f000) << 12) |
+ ((dram_para.tpr5 & 0x00fc0000) >> 2) |
+ ((dram_para.tpr5 & 0x3f000000) >> 16) |
+ ((dram_para.tpr6 & 0x0000003f) >> 0),
+ &mctl_ctl->dramtmg0);
+
+ writel(((dram_para.tpr6 & 0x000007c0) << 10) |
+ ((dram_para.tpr6 & 0x0000f800) >> 3) |
+ ((dram_para.tpr6 & 0x003f0000) >> 16),
+ &mctl_ctl->dramtmg1);
+
+ writel(((dram_para.tpr6 & 0x0fc00000) << 2) |
+ ((dram_para.tpr7 & 0x0000001f) << 16) |
+ ((dram_para.tpr7 & 0x000003e0) << 3) |
+ ((dram_para.tpr7 & 0x0000fc00) >> 10),
+ &mctl_ctl->dramtmg2);
+
+ writel(((dram_para.tpr7 & 0x03ff0000) >> 16) |
+ ((dram_para.tpr6 & 0xf0000000) >> 16),
+ &mctl_ctl->dramtmg3);
+
+ writel(((dram_para.tpr7 & 0x3c000000) >> 2 ) |
+ ((dram_para.tpr8 & 0x00000007) << 16) |
+ ((dram_para.tpr8 & 0x00000038) << 5) |
+ ((dram_para.tpr8 & 0x000003c0) >> 6),
+ &mctl_ctl->dramtmg4);
+
+ writel(((dram_para.tpr8 & 0x00003c00) << 14) |
+ ((dram_para.tpr8 & 0x0003c000) << 2) |
+ ((dram_para.tpr8 & 0x00fc0000) >> 10) |
+ ((dram_para.tpr8 & 0x0f000000) >> 24),
+ &mctl_ctl->dramtmg5);
+
+ writel(0x00000008, &mctl_ctl->dramtmg8);
+
+ writel(((dram_para.tpr8 & 0xf0000000) >> 4) |
+ ((dram_para.tpr9 & 0x00007c00) << 6) |
+ ((dram_para.tpr9 & 0x000003e0) << 3) |
+ ((dram_para.tpr9 & 0x0000001f) >> 0),
+ &mctl_ctl->pitmg0);
+
+ setbits_le32(&mctl_ctl->pitmg1, 0x80000);
+
+ writel(((dram_para.tpr9 & 0x003f8000) << 9) | 0x2001,
+ &mctl_ctl->sched);
+
+ writel((dram_para.mr0 << 16) | dram_para.mr1, &mctl_ctl->init3);
+ writel((dram_para.mr2 << 16) | dram_para.mr3, &mctl_ctl->init4);
+
+ writel(0x00000000, &mctl_ctl->pimisc);
+ writel(0x80000000, &mctl_ctl->upd0);
+
+ writel(((dram_para.tpr9 & 0xffc00000) >> 22) |
+ ((dram_para.tpr10 & 0x00000fff) << 16),
+ &mctl_ctl->rfshtmg);
+
+ if (dram_para.tpr13 & 0x20)
+ writel(0x01040001, &mctl_ctl->mstr);
+ else
+ writel(0x01040401, &mctl_ctl->mstr);
+
+ if (!(dram_para.tpr13 & 0x20000)) {
+ writel(0x00000002, &mctl_ctl->pwrctl);
+ writel(0x00008001, &mctl_ctl->pwrtmg);
+ }
+
+ writel(0x00000001, &mctl_ctl->rfshctl3);
+ writel(0x00000001, &mctl_ctl->pimisc);
+
+ /* deassert dram_clk_cfg reset */
+ setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
+
+ setbits_le32(&mctl_com->ccr, 0x80000);
+
+ /* zq stuff */
+ writel((dram_para.zq >> 8) & 0xff, &mctl_phy->zqcr1);
+
+ writel(0x00000003, &mctl_phy->pir);
+ udelay(10);
+ mctl_await_completion(&mctl_phy->pgsr0, 0x09, 0x09);
+
+ writel(readl(&mctl_phy->zqsr0) | 0x10000000, &mctl_phy->zqcr2);
+ writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);
+
+ /* A23-v1.0 SDK uses 0xfdf3, A23-v2.0 SDK uses 0x5f3 */
+ writel(0x000005f3, &mctl_phy->pir);
+ udelay(10);
+ mctl_await_completion(&mctl_phy->pgsr0, 0x03, 0x03);
+
+ if (readl(&mctl_phy->dx1gsr0) & 0x1000000) {
+ *bus_width = 8;
+ writel(0, &mctl_phy->dx1gcr);
+ writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);
+ writel(0x5f3, &mctl_phy->pir);
+ udelay(10000);
+ setbits_le32(&mctl_ctl->mstr, 0x1000);
+ } else
+ *bus_width = 16;
+
+ correction = (dram_para.odt_en >> 8) & 0xff;
+ if (correction) {
+ if (dram_para.odt_en & 0x80000000)
+ correction = -correction;
+
+ mctl_apply_odt_correction(&mctl_phy->dx0lcdlr1, correction);
+ mctl_apply_odt_correction(&mctl_phy->dx1lcdlr1, correction);
+ }
+
+ mctl_await_completion(&mctl_ctl->statr, 0x01, 0x01);
+
+ writel(0x08003e3f, &mctl_phy->pgcr0);
+ writel(0x00000000, &mctl_ctl->rfshctl3);
+}
+
+unsigned long sunxi_dram_init(void)
+{
+ struct sunxi_mctl_com_reg * const mctl_com =
+ (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+ const u32 columns = 13;
+ u32 bus, bus_width, offset, page_size, rows;
+
+ mctl_sys_init();
+ mctl_init(&bus_width);
+
+ if (bus_width == 16) {
+ page_size = 8;
+ bus = 1;
+ } else {
+ page_size = 7;
+ bus = 0;
+ }
+
+ if (!(dram_para.tpr13 & 0x80000000)) {
+ /* Detect and set rows */
+ writel(0x000310f4 | MCTL_CR_PAGE_SIZE(page_size),
+ &mctl_com->cr);
+ setbits_le32(&mctl_com->swonr, 0x0003ffff);
+ for (rows = 11; rows < 16; rows++) {
+ offset = 1 << (rows + columns + bus);
+ if (mctl_mem_matches(offset))
+ break;
+ }
+ clrsetbits_le32(&mctl_com->cr, MCTL_CR_ROW_MASK,
+ MCTL_CR_ROW(rows));
+ } else {
+ rows = (dram_para.para1 >> 16) & 0xff;
+ writel(((dram_para.para2 & 0x000000f0) << 11) |
+ ((rows - 1) << 4) |
+ ((dram_para.para1 & 0x0f000000) >> 22) |
+ 0x31000 | MCTL_CR_PAGE_SIZE(page_size),
+ &mctl_com->cr);
+ setbits_le32(&mctl_com->swonr, 0x0003ffff);
+ }
+
+ /* Setup DRAM master priority? If this is left out things still work */
+ writel(0x00000008, &mctl_com->mcr0_0);
+ writel(0x0001000d, &mctl_com->mcr1_0);
+ writel(0x00000004, &mctl_com->mcr0_1);
+ writel(0x00000080, &mctl_com->mcr1_1);
+ writel(0x00000004, &mctl_com->mcr0_2);
+ writel(0x00000019, &mctl_com->mcr1_2);
+ writel(0x00000004, &mctl_com->mcr0_3);
+ writel(0x00000080, &mctl_com->mcr1_3);
+ writel(0x00000004, &mctl_com->mcr0_4);
+ writel(0x01010040, &mctl_com->mcr1_4);
+ writel(0x00000004, &mctl_com->mcr0_5);
+ writel(0x0001002f, &mctl_com->mcr1_5);
+ writel(0x00000004, &mctl_com->mcr0_6);
+ writel(0x00010020, &mctl_com->mcr1_6);
+ writel(0x00000004, &mctl_com->mcr0_7);
+ writel(0x00010020, &mctl_com->mcr1_7);
+ writel(0x00000008, &mctl_com->mcr0_8);
+ writel(0x00000001, &mctl_com->mcr1_8);
+ writel(0x00000008, &mctl_com->mcr0_9);
+ writel(0x00000005, &mctl_com->mcr1_9);
+ writel(0x00000008, &mctl_com->mcr0_10);
+ writel(0x00000003, &mctl_com->mcr1_10);
+ writel(0x00000008, &mctl_com->mcr0_11);
+ writel(0x00000005, &mctl_com->mcr1_11);
+ writel(0x00000008, &mctl_com->mcr0_12);
+ writel(0x00000003, &mctl_com->mcr1_12);
+ writel(0x00000008, &mctl_com->mcr0_13);
+ writel(0x00000004, &mctl_com->mcr1_13);
+ writel(0x00000008, &mctl_com->mcr0_14);
+ writel(0x00000002, &mctl_com->mcr1_14);
+ writel(0x00000008, &mctl_com->mcr0_15);
+ writel(0x00000003, &mctl_com->mcr1_15);
+ writel(0x00010138, &mctl_com->bwcr);
+
+ return 1 << (rows + columns + bus);
+}
diff --git a/arch/arm/cpu/armv7/sunxi/p2wi.c b/arch/arm/cpu/armv7/sunxi/p2wi.c
index 48613bd0ea..26a9cfc68b 100644
--- a/arch/arm/cpu/armv7/sunxi/p2wi.c
+++ b/arch/arm/cpu/armv7/sunxi/p2wi.c
@@ -26,13 +26,13 @@
void p2wi_init(void)
{
- struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUNXI_P2WI_BASE;
+ struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
/* Enable p2wi and PIO clk, and de-assert their resets */
prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI);
- sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUNXI_GPL0_R_P2WI_SCK);
- sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUNXI_GPL1_R_P2WI_SDA);
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK);
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA);
/* Reset p2wi controller and set clock to CLKIN(12)/8 = 1.5 MHz */
writel(P2WI_CTRL_RESET, &p2wi->ctrl);
@@ -43,7 +43,7 @@ void p2wi_init(void)
int p2wi_change_to_p2wi_mode(u8 slave_addr, u8 ctrl_reg, u8 init_data)
{
- struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUNXI_P2WI_BASE;
+ struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
unsigned long tmo = timer_get_us() + 1000000;
writel(P2WI_PM_DEV_ADDR(slave_addr) |
@@ -62,7 +62,7 @@ int p2wi_change_to_p2wi_mode(u8 slave_addr, u8 ctrl_reg, u8 init_data)
static int p2wi_await_trans(void)
{
- struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUNXI_P2WI_BASE;
+ struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
unsigned long tmo = timer_get_us() + 1000000;
int ret;
u8 reg;
@@ -88,7 +88,7 @@ static int p2wi_await_trans(void)
int p2wi_read(const u8 addr, u8 *data)
{
- struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUNXI_P2WI_BASE;
+ struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
int ret;
writel(P2WI_DATADDR_BYTE_1(addr), &p2wi->dataddr0);
@@ -105,7 +105,7 @@ int p2wi_read(const u8 addr, u8 *data)
int p2wi_write(const u8 addr, u8 data)
{
- struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUNXI_P2WI_BASE;
+ struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
writel(P2WI_DATADDR_BYTE_1(addr), &p2wi->dataddr0);
writel(P2WI_DATA_BYTE_1(data), &p2wi->data0);
diff --git a/arch/arm/cpu/armv7/sunxi/psci.S b/arch/arm/cpu/armv7/sunxi/psci.S
index b9ea78b84e..5be497b7be 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.S
+++ b/arch/arm/cpu/armv7/sunxi/psci.S
@@ -18,6 +18,7 @@
*/
#include <config.h>
+#include <asm/gic.h>
#include <asm/psci.h>
#include <asm/arch/cpu.h>
@@ -38,6 +39,8 @@
#define ONE_MS (CONFIG_SYS_CLK_FREQ / 1000)
#define TEN_MS (10 * ONE_MS)
+#define GICD_BASE 0x1c81000
+#define GICC_BASE 0x1c82000
.macro timer_wait reg, ticks
@ Program CNTP_TVAL
@@ -59,25 +62,77 @@
isb
.endm
-.globl psci_arch_init
-psci_arch_init:
- mrc p15, 0, r5, c1, c1, 0 @ Read SCR
- bic r5, r5, #1 @ Secure mode
- mcr p15, 0, r5, c1, c1, 0 @ Write SCR
+.globl psci_fiq_enter
+psci_fiq_enter:
+ push {r0-r12}
+
+ @ Switch to secure
+ mrc p15, 0, r7, c1, c1, 0
+ bic r8, r7, #1
+ mcr p15, 0, r8, c1, c1, 0
isb
- mrc p15, 0, r4, c0, c0, 5 @ MPIDR
- and r4, r4, #3 @ cpu number in cluster
- mov r5, #400 @ 1kB of stack per CPU
- mul r4, r4, r5
+ @ Validate reason based on IAR and acknowledge
+ movw r8, #(GICC_BASE & 0xffff)
+ movt r8, #(GICC_BASE >> 16)
+ ldr r9, [r8, #GICC_IAR]
+ movw r10, #0x3ff
+ movt r10, #0
+ cmp r9, r10 @ skip spurious interrupt 1023
+ beq out
+ movw r10, #0x3fe @ ...and 1022
+ cmp r9, r10
+ beq out
+ str r9, [r8, #GICC_EOIR] @ acknowledge the interrupt
+ dsb
- adr r5, text_end @ end of text
- add r5, r5, #0x2000 @ Skip two pages
- lsr r5, r5, #12 @ Align to start of page
- lsl r5, r5, #12
- sub sp, r5, r4 @ here's our stack!
+ @ Compute CPU number
+ lsr r9, r9, #10
+ and r9, r9, #0xf
- bx lr
+ movw r8, #(SUN7I_CPUCFG_BASE & 0xffff)
+ movt r8, #(SUN7I_CPUCFG_BASE >> 16)
+
+ @ Wait for the core to enter WFI
+ lsl r11, r9, #6 @ x64
+ add r11, r11, r8
+
+1: ldr r10, [r11, #0x48]
+ tst r10, #(1 << 2)
+ bne 2f
+ timer_wait r10, ONE_MS
+ b 1b
+
+ @ Reset CPU
+2: mov r10, #0
+ str r10, [r11, #0x40]
+
+ @ Lock CPU
+ mov r10, #1
+ lsl r9, r10, r9 @ r9 is now CPU mask
+ ldr r10, [r8, #0x1e4]
+ bic r10, r10, r9
+ str r10, [r8, #0x1e4]
+
+ @ Set power gating
+ ldr r10, [r8, #0x1b4]
+ orr r10, r10, #1
+ str r10, [r8, #0x1b4]
+ timer_wait r10, ONE_MS
+
+ @ Activate power clamp
+ mov r10, #1
+1: str r10, [r8, #0x1b0]
+ lsl r10, r10, #1
+ orr r10, r10, #1
+ tst r10, #0x100
+ beq 1b
+
+ @ Restore security level
+out: mcr p15, 0, r7, c1, c1, 0
+
+ pop {r0-r12}
+ subs pc, lr, #4
@ r1 = target CPU
@ r2 = target PC
@@ -144,6 +199,53 @@ psci_cpu_on:
_target_pc:
.word 0
+/* Imported from Linux kernel */
+v7_flush_dcache_all:
+ dmb @ ensure ordering with previous memory accesses
+ mrc p15, 1, r0, c0, c0, 1 @ read clidr
+ ands r3, r0, #0x7000000 @ extract loc from clidr
+ mov r3, r3, lsr #23 @ left align loc bit field
+ beq finished @ if loc is 0, then no need to clean
+ mov r10, #0 @ start clean at cache level 0
+flush_levels:
+ add r2, r10, r10, lsr #1 @ work out 3x current cache level
+ mov r1, r0, lsr r2 @ extract cache type bits from clidr
+ and r1, r1, #7 @ mask of the bits for current cache only
+ cmp r1, #2 @ see what cache we have at this level
+ blt skip @ skip if no cache, or just i-cache
+ mrs r9, cpsr @ make cssr&csidr read atomic
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ isb @ isb to sych the new cssr&csidr
+ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
+ msr cpsr_c, r9
+ and r2, r1, #7 @ extract the length of the cache lines
+ add r2, r2, #4 @ add 4 (line length offset)
+ ldr r4, =0x3ff
+ ands r4, r4, r1, lsr #3 @ find maximum number on the way size
+ clz r5, r4 @ find bit position of way size increment
+ ldr r7, =0x7fff
+ ands r7, r7, r1, lsr #13 @ extract max number of the index size
+loop1:
+ mov r9, r7 @ create working copy of max index
+loop2:
+ orr r11, r10, r4, lsl r5 @ factor way and cache number into r11
+ orr r11, r11, r9, lsl r2 @ factor index number into r11
+ mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
+ subs r9, r9, #1 @ decrement the index
+ bge loop2
+ subs r4, r4, #1 @ decrement the way
+ bge loop1
+skip:
+ add r10, r10, #2 @ increment cache number
+ cmp r3, r10
+ bgt flush_levels
+finished:
+ mov r10, #0 @ swith back to cache level 0
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ dsb st
+ isb
+ bx lr
+
_sunxi_cpu_entry:
@ Set SMP bit
mrc p15, 0, r0, c1, c0, 1
@@ -158,5 +260,74 @@ _sunxi_cpu_entry:
ldr r0, [r0]
b _do_nonsec_entry
+.globl psci_cpu_off
+psci_cpu_off:
+ mrc p15, 0, r0, c1, c0, 0 @ SCTLR
+ bic r0, r0, #(1 << 2) @ Clear C bit
+ mcr p15, 0, r0, c1, c0, 0 @ SCTLR
+ isb
+ dsb
+
+ bl v7_flush_dcache_all
+
+ clrex @ Why???
+
+ mrc p15, 0, r0, c1, c0, 1 @ ACTLR
+ bic r0, r0, #(1 << 6) @ Clear SMP bit
+ mcr p15, 0, r0, c1, c0, 1 @ ACTLR
+ isb
+ dsb
+
+ @ Ask CPU0 to pull the rug...
+ movw r0, #(GICD_BASE & 0xffff)
+ movt r0, #(GICD_BASE >> 16)
+ movw r1, #15 @ SGI15
+ movt r1, #1 @ Target is CPU0
+ str r1, [r0, #GICD_SGIR]
+ dsb
+
+1: wfi
+ b 1b
+
+.globl psci_arch_init
+psci_arch_init:
+ movw r4, #(GICD_BASE & 0xffff)
+ movt r4, #(GICD_BASE >> 16)
+
+ ldr r5, [r4, #GICD_IGROUPRn]
+ bic r5, r5, #(1 << 15) @ SGI15 as Group-0
+ str r5, [r4, #GICD_IGROUPRn]
+
+ mov r5, #0 @ Set SGI15 priority to 0
+ strb r5, [r4, #(GICD_IPRIORITYRn + 15)]
+
+ add r4, r4, #0x1000 @ GICC address
+
+ mov r5, #0xff
+ str r5, [r4, #GICC_PMR] @ Be cool with non-secure
+
+ ldr r5, [r4, #GICC_CTLR]
+ orr r5, r5, #(1 << 3) @ Switch FIQEn on
+ str r5, [r4, #GICC_CTLR]
+
+ mrc p15, 0, r5, c1, c1, 0 @ Read SCR
+ orr r5, r5, #4 @ Enable FIQ in monitor mode
+ bic r5, r5, #1 @ Secure mode
+ mcr p15, 0, r5, c1, c1, 0 @ Write SCR
+ isb
+
+ mrc p15, 0, r4, c0, c0, 5 @ MPIDR
+ and r4, r4, #3 @ cpu number in cluster
+ mov r5, #0x400 @ 1kB of stack per CPU
+ mul r4, r4, r5
+
+ adr r5, text_end @ end of text
+ add r5, r5, #0x2000 @ Skip two pages
+ lsr r5, r5, #12 @ Align to start of page
+ lsl r5, r5, #12
+ sub sp, r5, r4 @ here's our stack!
+
+ bx lr
+
text_end:
.popsection
diff --git a/arch/arm/cpu/armv7/sunxi/rsb.c b/arch/arm/cpu/armv7/sunxi/rsb.c
new file mode 100644
index 0000000000..b72bb9db51
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/rsb.c
@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on allwinner u-boot sources rsb code which is:
+ * (C) Copyright 2007-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * lixiang <lixiang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/prcm.h>
+#include <asm/arch/rsb.h>
+
+static void rsb_cfg_io(void)
+{
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL0_R_RSB_SCK);
+ sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL1_R_RSB_SDA);
+ sunxi_gpio_set_pull(SUNXI_GPL(0), 1);
+ sunxi_gpio_set_pull(SUNXI_GPL(1), 1);
+ sunxi_gpio_set_drv(SUNXI_GPL(0), 2);
+ sunxi_gpio_set_drv(SUNXI_GPL(1), 2);
+}
+
+static void rsb_set_clk(void)
+{
+ struct sunxi_rsb_reg * const rsb =
+ (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+ u32 div = 0;
+ u32 cd_odly = 0;
+
+ /* Source is Hosc24M, set RSB clk to 3Mhz */
+ div = 24000000 / 3000000 / 2 - 1;
+ cd_odly = div >> 1;
+ if (!cd_odly)
+ cd_odly = 1;
+
+ writel((cd_odly << 8) | div, &rsb->ccr);
+}
+
+void rsb_init(void)
+{
+ struct sunxi_rsb_reg * const rsb =
+ (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+
+ rsb_cfg_io();
+
+ /* Enable RSB and PIO clk, and de-assert their resets */
+ prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB);
+
+ writel(RSB_CTRL_SOFT_RST, &rsb->ctrl);
+ rsb_set_clk();
+}
+
+static int rsb_await_trans(void)
+{
+ struct sunxi_rsb_reg * const rsb =
+ (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+ unsigned long tmo = timer_get_us() + 1000000;
+ u32 stat;
+ int ret;
+
+ while (1) {
+ stat = readl(&rsb->stat);
+ if (stat & RSB_STAT_LBSY_INT) {
+ ret = -EBUSY;
+ break;
+ }
+ if (stat & RSB_STAT_TERR_INT) {
+ ret = -EIO;
+ break;
+ }
+ if (stat & RSB_STAT_TOVER_INT) {
+ ret = 0;
+ break;
+ }
+ if (timer_get_us() > tmo) {
+ ret = -ETIME;
+ break;
+ }
+ }
+ writel(stat, &rsb->stat); /* Clear status bits */
+
+ return ret;
+}
+
+int rsb_set_device_mode(u32 device_mode_data)
+{
+ struct sunxi_rsb_reg * const rsb =
+ (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+ unsigned long tmo = timer_get_us() + 1000000;
+
+ writel(RSB_DMCR_DEVICE_MODE_START | device_mode_data, &rsb->dmcr);
+
+ while (readl(&rsb->dmcr) & RSB_DMCR_DEVICE_MODE_START) {
+ if (timer_get_us() > tmo)
+ return -ETIME;
+ }
+
+ return rsb_await_trans();
+}
+
+static int rsb_do_trans(void)
+{
+ struct sunxi_rsb_reg * const rsb =
+ (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+
+ setbits_le32(&rsb->ctrl, RSB_CTRL_START_TRANS);
+ return rsb_await_trans();
+}
+
+int rsb_set_device_address(u16 device_addr, u16 runtime_addr)
+{
+ struct sunxi_rsb_reg * const rsb =
+ (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+
+ writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr) |
+ RSB_DEVADDR_DEVICE_ADDR(device_addr), &rsb->devaddr);
+ writel(RSB_CMD_SET_RTSADDR, &rsb->cmd);
+
+ return rsb_do_trans();
+}
+
+int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data)
+{
+ struct sunxi_rsb_reg * const rsb =
+ (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+
+ writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr);
+ writel(reg_addr, &rsb->addr);
+ writel(data, &rsb->data);
+ writel(RSB_CMD_BYTE_WRITE, &rsb->cmd);
+
+ return rsb_do_trans();
+}
+
+int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data)
+{
+ struct sunxi_rsb_reg * const rsb =
+ (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+ int ret;
+
+ writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr);
+ writel(reg_addr, &rsb->addr);
+ writel(RSB_CMD_BYTE_READ, &rsb->cmd);
+
+ ret = rsb_do_trans();
+ if (ret)
+ return ret;
+
+ *data = readl(&rsb->data) & 0xff;
+
+ return 0;
+}
diff --git a/arch/arm/cpu/armv7/sunxi/usbc.c b/arch/arm/cpu/armv7/sunxi/usbc.c
new file mode 100644
index 0000000000..14de9f98bd
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/usbc.c
@@ -0,0 +1,272 @@
+/*
+ * Sunxi usb-controller code shared between the ehci and musb controllers
+ *
+ * Copyright (C) 2014 Roman Byshko
+ *
+ * Roman Byshko <rbyshko@gmail.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm/arch/clock.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/usbc.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <common.h>
+#ifdef CONFIG_AXP152_POWER
+#include <axp152.h>
+#endif
+#ifdef CONFIG_AXP209_POWER
+#include <axp209.h>
+#endif
+#ifdef CONFIG_AXP221_POWER
+#include <axp221.h>
+#endif
+
+#define SUNXI_USB_PMU_IRQ_ENABLE 0x800
+#define SUNXI_USB_CSR 0x404
+#define SUNXI_USB_PASSBY_EN 1
+
+#define SUNXI_EHCI_AHB_ICHR8_EN (1 << 10)
+#define SUNXI_EHCI_AHB_INCR4_BURST_EN (1 << 9)
+#define SUNXI_EHCI_AHB_INCRX_ALIGN_EN (1 << 8)
+#define SUNXI_EHCI_ULPI_BYPASS_EN (1 << 0)
+
+static struct sunxi_usbc_hcd {
+ struct usb_hcd *hcd;
+ int usb_rst_mask;
+ int ahb_clk_mask;
+ int gpio_vbus;
+ int irq;
+ int id;
+} sunxi_usbc_hcd[] = {
+ {
+ .usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK,
+ .ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB0,
+#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
+ .irq = 71,
+#else
+ .irq = 38,
+#endif
+ .id = 0,
+ },
+ {
+ .usb_rst_mask = CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK,
+ .ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0,
+#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
+ .irq = 72,
+#else
+ .irq = 39,
+#endif
+ .id = 1,
+ },
+#if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1)
+ {
+ .usb_rst_mask = CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK,
+ .ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI1,
+#ifdef CONFIG_MACH_SUN6I
+ .irq = 74,
+#else
+ .irq = 40,
+#endif
+ .id = 2,
+ }
+#endif
+};
+
+static int enabled_hcd_count;
+
+static bool use_axp_drivebus(int index)
+{
+ return index == 0 &&
+ strcmp(CONFIG_USB0_VBUS_PIN, "axp_drivebus") == 0;
+}
+
+void *sunxi_usbc_get_io_base(int index)
+{
+ switch (index) {
+ case 0:
+ return (void *)SUNXI_USB0_BASE;
+ case 1:
+ return (void *)SUNXI_USB1_BASE;
+ case 2:
+ return (void *)SUNXI_USB2_BASE;
+ default:
+ return NULL;
+ }
+}
+
+static int get_vbus_gpio(int index)
+{
+ if (use_axp_drivebus(index))
+ return -1;
+
+ switch (index) {
+ case 0: return sunxi_name_to_gpio(CONFIG_USB0_VBUS_PIN);
+ case 1: return sunxi_name_to_gpio(CONFIG_USB1_VBUS_PIN);
+ case 2: return sunxi_name_to_gpio(CONFIG_USB2_VBUS_PIN);
+ }
+ return -1;
+}
+
+static void usb_phy_write(struct sunxi_usbc_hcd *sunxi_usbc, int addr,
+ int data, int len)
+{
+ int j = 0, usbc_bit = 0;
+ void *dest = sunxi_usbc_get_io_base(0) + SUNXI_USB_CSR;
+
+ usbc_bit = 1 << (sunxi_usbc->id * 2);
+ for (j = 0; j < len; j++) {
+ /* set the bit address to be written */
+ clrbits_le32(dest, 0xff << 8);
+ setbits_le32(dest, (addr + j) << 8);
+
+ clrbits_le32(dest, usbc_bit);
+ /* set data bit */
+ if (data & 0x1)
+ setbits_le32(dest, 1 << 7);
+ else
+ clrbits_le32(dest, 1 << 7);
+
+ setbits_le32(dest, usbc_bit);
+
+ clrbits_le32(dest, usbc_bit);
+
+ data >>= 1;
+ }
+}
+
+static void sunxi_usb_phy_init(struct sunxi_usbc_hcd *sunxi_usbc)
+{
+ /* The following comments are machine
+ * translated from Chinese, you have been warned!
+ */
+
+ /* Regulation 45 ohms */
+ if (sunxi_usbc->id == 0)
+ usb_phy_write(sunxi_usbc, 0x0c, 0x01, 1);
+
+ /* adjust PHY's magnitude and rate */
+ usb_phy_write(sunxi_usbc, 0x20, 0x14, 5);
+
+ /* threshold adjustment disconnect */
+#if defined CONFIG_MACH_SUN4I || defined CONFIG_MACH_SUN6I
+ usb_phy_write(sunxi_usbc, 0x2a, 3, 2);
+#else
+ usb_phy_write(sunxi_usbc, 0x2a, 2, 2);
+#endif
+
+ return;
+}
+
+static void sunxi_usb_passby(struct sunxi_usbc_hcd *sunxi_usbc, int enable)
+{
+ unsigned long bits = 0;
+ void *addr = sunxi_usbc_get_io_base(sunxi_usbc->id) +
+ SUNXI_USB_PMU_IRQ_ENABLE;
+
+ bits = SUNXI_EHCI_AHB_ICHR8_EN |
+ SUNXI_EHCI_AHB_INCR4_BURST_EN |
+ SUNXI_EHCI_AHB_INCRX_ALIGN_EN |
+ SUNXI_EHCI_ULPI_BYPASS_EN;
+
+ if (enable)
+ setbits_le32(addr, bits);
+ else
+ clrbits_le32(addr, bits);
+
+ return;
+}
+
+int sunxi_usbc_request_resources(int index)
+{
+ struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+
+ sunxi_usbc->gpio_vbus = get_vbus_gpio(index);
+ if (sunxi_usbc->gpio_vbus != -1)
+ return gpio_request(sunxi_usbc->gpio_vbus, "usbc_vbus");
+
+ return 0;
+}
+
+int sunxi_usbc_free_resources(int index)
+{
+ struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+
+ if (sunxi_usbc->gpio_vbus != -1)
+ return gpio_free(sunxi_usbc->gpio_vbus);
+
+ return 0;
+}
+
+void sunxi_usbc_enable(int index)
+{
+ struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+ /* enable common PHY only once */
+ if (enabled_hcd_count == 0)
+ setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
+
+ setbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask);
+ setbits_le32(&ccm->ahb_gate0, sunxi_usbc->ahb_clk_mask);
+#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
+ setbits_le32(&ccm->ahb_reset0_cfg, sunxi_usbc->ahb_clk_mask);
+#endif
+
+ sunxi_usb_phy_init(sunxi_usbc);
+
+ if (sunxi_usbc->id != 0)
+ sunxi_usb_passby(sunxi_usbc, SUNXI_USB_PASSBY_EN);
+
+ enabled_hcd_count++;
+}
+
+void sunxi_usbc_disable(int index)
+{
+ struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+ if (sunxi_usbc->id != 0)
+ sunxi_usb_passby(sunxi_usbc, !SUNXI_USB_PASSBY_EN);
+
+#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
+ clrbits_le32(&ccm->ahb_reset0_cfg, sunxi_usbc->ahb_clk_mask);
+#endif
+ clrbits_le32(&ccm->ahb_gate0, sunxi_usbc->ahb_clk_mask);
+ clrbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask);
+
+ /* disable common PHY only once, for the last enabled hcd */
+ if (enabled_hcd_count == 1)
+ clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
+
+ enabled_hcd_count--;
+}
+
+void sunxi_usbc_vbus_enable(int index)
+{
+ struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+
+#ifdef AXP_DRIVEBUS
+ if (use_axp_drivebus(index))
+ axp_drivebus_enable();
+#endif
+ if (sunxi_usbc->gpio_vbus != -1)
+ gpio_direction_output(sunxi_usbc->gpio_vbus, 1);
+}
+
+void sunxi_usbc_vbus_disable(int index)
+{
+ struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+
+#ifdef AXP_DRIVEBUS
+ if (use_axp_drivebus(index))
+ axp_drivebus_disable();
+#endif
+ if (sunxi_usbc->gpio_vbus != -1)
+ gpio_direction_output(sunxi_usbc->gpio_vbus, 0);
+}
diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
index 4b3ee6ed6f..9c6e8243bb 100644
--- a/arch/arm/cpu/armv8/cache.S
+++ b/arch/arm/cpu/armv8/cache.S
@@ -94,7 +94,7 @@ skip:
b.gt loop_level
mov x0, #0
- msr csselr_el1, x0 /* resotre csselr_el1 */
+ msr csselr_el1, x0 /* restore csselr_el1 */
dsb sy
isb
mov lr, x15
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index 64acff3504..505c363e46 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -26,7 +26,6 @@ int clock_init(void);
int clock_twi_onoff(int port, int state);
void clock_set_pll1(unsigned int hz);
void clock_set_pll3(unsigned int hz);
-void clock_set_pll5(unsigned int hz);
unsigned int clock_get_pll5p(void);
unsigned int clock_get_pll6(void);
void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz);
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
index eb889695d9..84a9a2bdbc 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
@@ -182,7 +182,7 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_USB_EHCI1 3
#define AHB_GATE_OFFSET_USB_OHCI0 2
#define AHB_GATE_OFFSET_USB_EHCI0 1
-#define AHB_GATE_OFFSET_USB 0
+#define AHB_GATE_OFFSET_USB0 0
/* ahb clock gate bit offset (second register) */
#define AHB_GATE_OFFSET_GMAC 17
@@ -190,6 +190,8 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_HDMI 11
#define AHB_GATE_OFFSET_LCD1 5
#define AHB_GATE_OFFSET_LCD0 4
+#define AHB_GATE_OFFSET_TVE1 3
+#define AHB_GATE_OFFSET_TVE0 2
#define CCM_AHB_GATE_GPS (0x1 << 26)
#define CCM_AHB_GATE_SDRAM (0x1 << 14)
@@ -255,11 +257,14 @@ struct sunxi_ccm_reg {
#define CCM_MBUS_CTRL_CLK_SRC_PLL5 0x2
#define CCM_MBUS_CTRL_GATE (0x1 << 31)
-#define CCM_MMC_CTRL_OSCM24 (0x0 << 24)
-#define CCM_MMC_CTRL_PLL6 (0x1 << 24)
-#define CCM_MMC_CTRL_PLL5 (0x2 << 24)
-
-#define CCM_MMC_CTRL_ENABLE (0x1 << 31)
+#define CCM_MMC_CTRL_M(x) ((x) - 1)
+#define CCM_MMC_CTRL_OCLK_DLY(x) ((x) << 8)
+#define CCM_MMC_CTRL_N(x) ((x) << 16)
+#define CCM_MMC_CTRL_SCLK_DLY(x) ((x) << 20)
+#define CCM_MMC_CTRL_OSCM24 (0x0 << 24)
+#define CCM_MMC_CTRL_PLL6 (0x1 << 24)
+#define CCM_MMC_CTRL_PLL5 (0x2 << 24)
+#define CCM_MMC_CTRL_ENABLE (0x1 << 31)
#define CCM_DRAM_GATE_OFFSET_DE_BE0 26
@@ -279,6 +284,8 @@ struct sunxi_ccm_reg {
/* Enable / disable both ch1 sclk1 and sclk2 at the same time */
#define CCM_LCD_CH1_CTRL_GATE (0x1 << 31 | 0x1 << 15)
+#define CCM_LVDS_CTRL_RST (1 << 0)
+
#define CCM_HDMI_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
#define CCM_HDMI_CTRL_PLL_MASK (3 << 24)
#define CCM_HDMI_CTRL_PLL3 (0 << 24)
@@ -295,10 +302,12 @@ struct sunxi_ccm_reg {
#define CCM_GMAC_CTRL_GPIT_MII (0x0 << 2)
#define CCM_GMAC_CTRL_GPIT_RGMII (0x1 << 2)
+#define CCM_USB_CTRL_PHY0_RST (0x1 << 0)
#define CCM_USB_CTRL_PHY1_RST (0x1 << 1)
#define CCM_USB_CTRL_PHY2_RST (0x1 << 2)
#define CCM_USB_CTRL_PHYGATE (0x1 << 8)
-/* These 2 are sun6i only, define them as 0 on sun4i */
+/* These 3 are sun6i only, define them as 0 on sun4i */
+#define CCM_USB_CTRL_PHY0_CLK 0
#define CCM_USB_CTRL_PHY1_CLK 0
#define CCM_USB_CTRL_PHY2_CLK 0
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index 359905452c..4711260c1e 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -173,7 +173,7 @@ struct sunxi_ccm_reg {
#define CCM_PLL1_CTRL_M(n) ((((n) - 1) & 0x3) << 0)
#define CCM_PLL1_CTRL_K(n) ((((n) - 1) & 0x3) << 4)
#define CCM_PLL1_CTRL_N(n) ((((n) - 1) & 0x1f) << 8)
-#define CCM_PLL1_CTRL_MAGIC (0x1 << 16)
+#define CCM_PLL1_CTRL_P(n) (((n) & 0x3) << 16)
#define CCM_PLL1_CTRL_EN (0x1 << 31)
#define CCM_PLL3_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
@@ -185,6 +185,7 @@ struct sunxi_ccm_reg {
#define CCM_PLL5_CTRL_K(n) ((((n) - 1) & 0x3) << 4)
#define CCM_PLL5_CTRL_N(n) ((((n) - 1) & 0x1f) << 8)
#define CCM_PLL5_CTRL_UPD (0x1 << 20)
+#define CCM_PLL5_CTRL_SIGMA_DELTA_EN (0x1 << 24)
#define CCM_PLL5_CTRL_EN (0x1 << 31)
#define PLL6_CFG_DEFAULT 0x90041811 /* 600 MHz */
@@ -203,6 +204,7 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_USB_OHCI0 29
#define AHB_GATE_OFFSET_USB_EHCI1 27
#define AHB_GATE_OFFSET_USB_EHCI0 26
+#define AHB_GATE_OFFSET_USB0 24
#define AHB_GATE_OFFSET_MCTL 14
#define AHB_GATE_OFFSET_GMAC 17
#define AHB_GATE_OFFSET_MMC3 11
@@ -210,6 +212,7 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_MMC1 9
#define AHB_GATE_OFFSET_MMC0 8
#define AHB_GATE_OFFSET_MMC(n) (AHB_GATE_OFFSET_MMC0 + (n))
+#define AHB_GATE_OFFSET_SS 5
/* ahb_gate1 offsets */
#define AHB_GATE_OFFSET_DRC0 25
@@ -218,15 +221,20 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_LCD1 5
#define AHB_GATE_OFFSET_LCD0 4
-#define CCM_MMC_CTRL_OSCM24 (0x0 << 24)
-#define CCM_MMC_CTRL_PLL6 (0x1 << 24)
-
-#define CCM_MMC_CTRL_ENABLE (0x1 << 31)
+#define CCM_MMC_CTRL_M(x) ((x) - 1)
+#define CCM_MMC_CTRL_OCLK_DLY(x) ((x) << 8)
+#define CCM_MMC_CTRL_N(x) ((x) << 16)
+#define CCM_MMC_CTRL_SCLK_DLY(x) ((x) << 20)
+#define CCM_MMC_CTRL_OSCM24 (0x0 << 24)
+#define CCM_MMC_CTRL_PLL6 (0x1 << 24)
+#define CCM_MMC_CTRL_ENABLE (0x1 << 31)
+#define CCM_USB_CTRL_PHY0_RST (0x1 << 0)
#define CCM_USB_CTRL_PHY1_RST (0x1 << 1)
#define CCM_USB_CTRL_PHY2_RST (0x1 << 2)
/* There is no global phy clk gate on sun6i, define as 0 */
#define CCM_USB_CTRL_PHYGATE 0
+#define CCM_USB_CTRL_PHY0_CLK (0x1 << 8)
#define CCM_USB_CTRL_PHY1_CLK (0x1 << 9)
#define CCM_USB_CTRL_PHY2_CLK (0x1 << 10)
@@ -250,6 +258,8 @@ struct sunxi_ccm_reg {
#define CCM_LCD_CH0_CTRL_PLL3_2X (2 << 24)
#define CCM_LCD_CH0_CTRL_PLL7_2X (3 << 24)
#define CCM_LCD_CH0_CTRL_MIPI_PLL (4 << 24)
+/* No reset bit in ch0_clk_cfg (reset is controlled through ahb_reset1) */
+#define CCM_LCD_CH0_CTRL_RST 0
#define CCM_LCD_CH0_CTRL_GATE (0x1 << 31)
#define CCM_LCD_CH1_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
@@ -268,7 +278,13 @@ struct sunxi_ccm_reg {
#define CCM_HDMI_CTRL_DDC_GATE (0x1 << 30)
#define CCM_HDMI_CTRL_GATE (0x1 << 31)
+#ifndef CONFIG_MACH_SUN8I
#define MBUS_CLK_DEFAULT 0x81000001 /* PLL6 / 2 */
+#else
+#define MBUS_CLK_DEFAULT 0x81000003 /* PLL6 / 4 */
+#endif
+
+#define CCM_PLL5_PATTERN 0xd1303333
/* ahb_reset0 offsets */
#define AHB_RESET_OFFSET_GMAC 17
@@ -278,8 +294,9 @@ struct sunxi_ccm_reg {
#define AHB_RESET_OFFSET_MMC1 9
#define AHB_RESET_OFFSET_MMC0 8
#define AHB_RESET_OFFSET_MMC(n) (AHB_RESET_OFFSET_MMC0 + (n))
+#define AHB_RESET_OFFSET_SS 5
-/* ahb_reset0 offsets */
+/* ahb_reset1 offsets */
#define AHB_RESET_OFFSET_DRC0 25
#define AHB_RESET_OFFSET_DE_BE0 12
#define AHB_RESET_OFFSET_HDMI 11
@@ -303,4 +320,6 @@ struct sunxi_ccm_reg {
#define CCM_DE_CTRL_PLL10 (5 << 24)
#define CCM_DE_CTRL_GATE (1 << 31)
+void clock_set_pll5(unsigned int clk, bool sigma_delta_enable);
+
#endif /* _SUNXI_CLOCK_SUN6I_H */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index 2c92b5ca56..82b3d4676f 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -37,7 +37,7 @@
#define SUNXI_MMC1_BASE 0x01c10000
#define SUNXI_MMC2_BASE 0x01c11000
#define SUNXI_MMC3_BASE 0x01c12000
-#ifndef CONFIG_MACH_SUN6I
+#if !defined CONFIG_MACH_SUN6I && !defined CONFIG_MACH_SUN8I
#define SUNXI_USB0_BASE 0x01c13000
#define SUNXI_USB1_BASE 0x01c14000
#endif
@@ -45,7 +45,7 @@
#define SUNXI_HDMI_BASE 0x01c16000
#define SUNXI_SPI2_BASE 0x01c17000
#define SUNXI_SATA_BASE 0x01c18000
-#ifndef CONFIG_MACH_SUN6I
+#if !defined CONFIG_MACH_SUN6I && !defined CONFIG_MACH_SUN8I
#define SUNXI_PATA_BASE 0x01c19000
#define SUNXI_ACE_BASE 0x01c1a000
#define SUNXI_TVE1_BASE 0x01c1b000
@@ -128,7 +128,8 @@
#define SUN6I_CPUCFG_BASE 0x01f01c00
#define SUNXI_R_UART_BASE 0x01f02800
#define SUNXI_R_PIO_BASE 0x01f02c00
-#define SUNXI_P2WI_BASE 0x01f03400
+#define SUN6I_P2WI_BASE 0x01f03400
+#define SUNXI_RSB_BASE 0x01f03400
/* CoreSight Debug Module */
#define SUNXI_CSDM_BASE 0x3f500000
@@ -139,9 +140,15 @@
#define SUNXI_CPU_CFG (SUNXI_TIMER_BASE + 0x13c)
+/* SS bonding ids used for cpu identification */
+#define SUNXI_SS_BOND_ID_A31 4
+#define SUNXI_SS_BOND_ID_A31S 5
+
#ifndef __ASSEMBLY__
void sunxi_board_init(void);
void sunxi_reset(void);
+int sunxi_get_ss_bonding_id(void);
+int sunxi_get_sid(unsigned int *sid);
#endif /* __ASSEMBLY__ */
#endif /* _CPU_H */
diff --git a/arch/arm/include/asm/arch-sunxi/display.h b/arch/arm/include/asm/arch-sunxi/display.h
index ddb71c1bbd..2ac8a879df 100644
--- a/arch/arm/include/asm/arch-sunxi/display.h
+++ b/arch/arm/include/asm/arch-sunxi/display.h
@@ -57,14 +57,16 @@ struct sunxi_lcdc_reg {
u32 int0; /* 0x04 */
u32 int1; /* 0x08 */
u8 res0[0x04]; /* 0x0c */
- u32 frame_ctrl; /* 0x10 */
- u8 res1[0x2c]; /* 0x14 */
+ u32 tcon0_frm_ctrl; /* 0x10 */
+ u32 tcon0_frm_seed[6]; /* 0x14 */
+ u32 tcon0_frm_table[4]; /* 0x2c */
+ u8 res1[4]; /* 0x3c */
u32 tcon0_ctrl; /* 0x40 */
u32 tcon0_dclk; /* 0x44 */
- u32 tcon0_basic_timing0; /* 0x48 */
- u32 tcon0_basic_timing1; /* 0x4c */
- u32 tcon0_basic_timing2; /* 0x50 */
- u32 tcon0_basic_timing3; /* 0x54 */
+ u32 tcon0_timing_active; /* 0x48 */
+ u32 tcon0_timing_h; /* 0x4c */
+ u32 tcon0_timing_v; /* 0x50 */
+ u32 tcon0_timing_sync; /* 0x54 */
u32 tcon0_hv_intf; /* 0x58 */
u8 res2[0x04]; /* 0x5c */
u32 tcon0_cpu_intf; /* 0x60 */
@@ -89,6 +91,9 @@ struct sunxi_lcdc_reg {
u8 res3[0x44]; /* 0xac */
u32 tcon1_io_polarity; /* 0xf0 */
u32 tcon1_io_tristate; /* 0xf4 */
+ u8 res4[0x128]; /* 0xf8 */
+ u32 lvds_ana0; /* 0x220 */
+ u32 lvds_ana1; /* 0x224 */
};
struct sunxi_hdmi_reg {
@@ -102,11 +107,106 @@ struct sunxi_hdmi_reg {
u32 video_fp; /* 0x01c */
u32 video_spw; /* 0x020 */
u32 video_polarity; /* 0x024 */
- u8 res0[0x1d8]; /* 0x028 */
+ u8 res0[0x58]; /* 0x028 */
+ u8 avi_info_frame[0x14]; /* 0x080 */
+ u8 res1[0x4c]; /* 0x094 */
+ u32 qcp_packet0; /* 0x0e0 */
+ u32 qcp_packet1; /* 0x0e4 */
+ u8 res2[0x118]; /* 0x0e8 */
u32 pad_ctrl0; /* 0x200 */
u32 pad_ctrl1; /* 0x204 */
u32 pll_ctrl; /* 0x208 */
u32 pll_dbg0; /* 0x20c */
+ u32 pll_dbg1; /* 0x210 */
+ u32 hpd_cec; /* 0x214 */
+ u8 res3[0x28]; /* 0x218 */
+ u8 vendor_info_frame[0x14]; /* 0x240 */
+ u8 res4[0x9c]; /* 0x254 */
+ u32 pkt_ctrl0; /* 0x2f0 */
+ u32 pkt_ctrl1; /* 0x2f4 */
+ u8 res5[0x8]; /* 0x2f8 */
+ u32 unknown; /* 0x300 */
+ u8 res6[0xc]; /* 0x304 */
+ u32 audio_sample_count; /* 0x310 */
+ u8 res7[0xec]; /* 0x314 */
+ u32 audio_tx_fifo; /* 0x400 */
+ u8 res8[0xfc]; /* 0x404 */
+#ifndef CONFIG_MACH_SUN6I
+ u32 ddc_ctrl; /* 0x500 */
+ u32 ddc_addr; /* 0x504 */
+ u32 ddc_int_mask; /* 0x508 */
+ u32 ddc_int_status; /* 0x50c */
+ u32 ddc_fifo_ctrl; /* 0x510 */
+ u32 ddc_fifo_status; /* 0x514 */
+ u32 ddc_fifo_data; /* 0x518 */
+ u32 ddc_byte_count; /* 0x51c */
+ u32 ddc_cmnd; /* 0x520 */
+ u32 ddc_exreg; /* 0x524 */
+ u32 ddc_clock; /* 0x528 */
+ u8 res9[0x14]; /* 0x52c */
+ u32 ddc_line_ctrl; /* 0x540 */
+#else
+ u32 ddc_ctrl; /* 0x500 */
+ u32 ddc_exreg; /* 0x504 */
+ u32 ddc_cmnd; /* 0x508 */
+ u32 ddc_addr; /* 0x50c */
+ u32 ddc_int_mask; /* 0x510 */
+ u32 ddc_int_status; /* 0x514 */
+ u32 ddc_fifo_ctrl; /* 0x518 */
+ u32 ddc_fifo_status; /* 0x51c */
+ u32 ddc_clock; /* 0x520 */
+ u32 ddc_timeout; /* 0x524 */
+ u8 res9[0x18]; /* 0x528 */
+ u32 ddc_dbg; /* 0x540 */
+ u8 res10[0x3c]; /* 0x544 */
+ u32 ddc_fifo_data; /* 0x580 */
+#endif
+};
+
+/*
+ * This is based on the A10s User Manual, and the A10s only supports
+ * composite video and not vga like the A10 / A20 does, still other
+ * than the removed vga out capability the tvencoder seems to be the same.
+ * "unknown#" registers are registers which are used in the A10 kernel code,
+ * but not documented in the A10s User Manual.
+ */
+struct sunxi_tve_reg {
+ u32 gctrl; /* 0x000 */
+ u32 cfg0; /* 0x004 */
+ u32 dac_cfg0; /* 0x008 */
+ u32 filter; /* 0x00c */
+ u32 chroma_freq; /* 0x010 */
+ u32 porch_num; /* 0x014 */
+ u32 unknown0; /* 0x018 */
+ u32 line_num; /* 0x01c */
+ u32 blank_black_level; /* 0x020 */
+ u32 unknown1; /* 0x024, seems to be 1 byte per dac */
+ u8 res0[0x08]; /* 0x028 */
+ u32 auto_detect_en; /* 0x030 */
+ u32 auto_detect_int_status; /* 0x034 */
+ u32 auto_detect_status; /* 0x038 */
+ u32 auto_detect_debounce; /* 0x03c */
+ u32 csc_reg0; /* 0x040 */
+ u32 csc_reg1; /* 0x044 */
+ u32 csc_reg2; /* 0x048 */
+ u32 csc_reg3; /* 0x04c */
+ u8 res1[0xb0]; /* 0x050 */
+ u32 color_burst; /* 0x100 */
+ u32 vsync_num; /* 0x104 */
+ u32 notch_freq; /* 0x108 */
+ u32 cbr_level; /* 0x10c */
+ u32 burst_phase; /* 0x110 */
+ u32 burst_width; /* 0x114 */
+ u8 res2[0x04]; /* 0x118 */
+ u32 sync_vbi_level; /* 0x11c */
+ u32 white_level; /* 0x120 */
+ u32 active_num; /* 0x124 */
+ u32 chroma_bw_gain; /* 0x128 */
+ u32 notch_width; /* 0x12c */
+ u32 resync_num; /* 0x130 */
+ u32 slave_para; /* 0x134 */
+ u32 cfg1; /* 0x138 */
+ u32 cfg2; /* 0x13c */
};
/*
@@ -126,17 +226,42 @@ struct sunxi_hdmi_reg {
*/
#define SUNXI_LCDC_X(x) (((x) - 1) << 16)
#define SUNXI_LCDC_Y(y) (((y) - 1) << 0)
+#define SUNXI_LCDC_TCON_VSYNC_MASK (1 << 24)
+#define SUNXI_LCDC_TCON_HSYNC_MASK (1 << 25)
#define SUNXI_LCDC_CTRL_IO_MAP_MASK (1 << 0)
#define SUNXI_LCDC_CTRL_IO_MAP_TCON0 (0 << 0)
#define SUNXI_LCDC_CTRL_IO_MAP_TCON1 (1 << 0)
#define SUNXI_LCDC_CTRL_TCON_ENABLE (1 << 31)
+#define SUNXI_LCDC_TCON0_FRM_CTRL_RGB666 ((1 << 31) | (0 << 4))
+#define SUNXI_LCDC_TCON0_FRM_CTRL_RGB565 ((1 << 31) | (5 << 4))
+#define SUNXI_LCDC_TCON0_FRM_SEED 0x11111111
+#define SUNXI_LCDC_TCON0_FRM_TAB0 0x01010000
+#define SUNXI_LCDC_TCON0_FRM_TAB1 0x15151111
+#define SUNXI_LCDC_TCON0_FRM_TAB2 0x57575555
+#define SUNXI_LCDC_TCON0_FRM_TAB3 0x7f7f7777
+#define SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(n) (((n) & 0x1f) << 4)
+#define SUNXI_LCDC_TCON0_CTRL_ENABLE (1 << 31)
+#define SUNXI_LCDC_TCON0_DCLK_DIV(n) ((n) << 0)
#define SUNXI_LCDC_TCON0_DCLK_ENABLE (0xf << 28)
+#define SUNXI_LCDC_TCON0_TIMING_H_BP(n) (((n) - 1) << 0)
+#define SUNXI_LCDC_TCON0_TIMING_H_TOTAL(n) (((n) - 1) << 16)
+#define SUNXI_LCDC_TCON0_TIMING_V_BP(n) (((n) - 1) << 0)
+#define SUNXI_LCDC_TCON0_TIMING_V_TOTAL(n) (((n) * 2) << 16)
+#define SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(n) ((n) << 26)
+#define SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE (1 << 31)
+#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE0 (0 << 28)
+#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE60 (1 << 28)
+#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE120 (2 << 28)
#define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(n) (((n) & 0x1f) << 4)
#define SUNXI_LCDC_TCON1_CTRL_ENABLE (1 << 31)
#define SUNXI_LCDC_TCON1_TIMING_H_BP(n) (((n) - 1) << 0)
#define SUNXI_LCDC_TCON1_TIMING_H_TOTAL(n) (((n) - 1) << 16)
#define SUNXI_LCDC_TCON1_TIMING_V_BP(n) (((n) - 1) << 0)
#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n) (((n) * 2) << 16)
+#define SUNXI_LCDC_LVDS_ANA0 0x3f310000
+#define SUNXI_LCDC_LVDS_ANA0_UPDATE (1 << 22)
+#define SUNXI_LCDC_LVDS_ANA1_INIT1 (0x1f << 26 | 0x1f << 10)
+#define SUNXI_LCDC_LVDS_ANA1_INIT2 (0x1f << 16 | 0x1f << 00)
/*
* HDMI register constants.
@@ -149,9 +274,12 @@ struct sunxi_hdmi_reg {
#define SUNXI_HDMI_IRQ_STATUS_BITS 0x73
#define SUNXI_HDMI_HPD_DETECT (1 << 0)
#define SUNXI_HDMI_VIDEO_CTRL_ENABLE (1 << 31)
+#define SUNXI_HDMI_VIDEO_CTRL_HDMI (1 << 30)
#define SUNXI_HDMI_VIDEO_POL_HOR (1 << 0)
#define SUNXI_HDMI_VIDEO_POL_VER (1 << 1)
#define SUNXI_HDMI_VIDEO_POL_TX_CLK (0x3e0 << 16)
+#define SUNXI_HDMI_QCP_PACKET0 3
+#define SUNXI_HDMI_QCP_PACKET1 0
#ifdef CONFIG_MACH_SUN6I
#define SUNXI_HDMI_PAD_CTRL0_HDP 0x7e80000f
@@ -182,6 +310,83 @@ struct sunxi_hdmi_reg {
#define SUNXI_HDMI_PLL_DBG0_PLL3 (0 << 21)
#define SUNXI_HDMI_PLL_DBG0_PLL7 (1 << 21)
+#define SUNXI_HDMI_PKT_CTRL0 0x00000f21
+#define SUNXI_HDMI_PKT_CTRL1 0x0000000f
+#define SUNXI_HDMI_UNKNOWN_INPUT_SYNC 0x08000000
+
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HMDI_DDC_CTRL_ENABLE (1 << 0)
+#define SUNXI_HMDI_DDC_CTRL_SCL_ENABLE (1 << 4)
+#define SUNXI_HMDI_DDC_CTRL_SDA_ENABLE (1 << 6)
+#define SUNXI_HMDI_DDC_CTRL_START (1 << 27)
+#define SUNXI_HMDI_DDC_CTRL_RESET (1 << 31)
+#else
+#define SUNXI_HMDI_DDC_CTRL_RESET (1 << 0)
+/* sun4i / sun5i / sun7i do not have a separate line_ctrl reg */
+#define SUNXI_HMDI_DDC_CTRL_SDA_ENABLE 0
+#define SUNXI_HMDI_DDC_CTRL_SCL_ENABLE 0
+#define SUNXI_HMDI_DDC_CTRL_START (1 << 30)
+#define SUNXI_HMDI_DDC_CTRL_ENABLE (1 << 31)
+#endif
+
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HMDI_DDC_ADDR_SLAVE_ADDR (0xa0 << 0)
+#else
+#define SUNXI_HMDI_DDC_ADDR_SLAVE_ADDR (0x50 << 0)
+#endif
+#define SUNXI_HMDI_DDC_ADDR_OFFSET(n) (((n) & 0xff) << 8)
+#define SUNXI_HMDI_DDC_ADDR_EDDC_ADDR (0x60 << 16)
+#define SUNXI_HMDI_DDC_ADDR_EDDC_SEGMENT(n) ((n) << 24)
+
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HDMI_DDC_FIFO_CTRL_CLEAR (1 << 15)
+#else
+#define SUNXI_HDMI_DDC_FIFO_CTRL_CLEAR (1 << 31)
+#endif
+
+#define SUNXI_HDMI_DDC_CMND_EXPLICIT_EDDC_READ 6
+#define SUNXI_HDMI_DDC_CMND_IMPLICIT_EDDC_READ 7
+
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HDMI_DDC_CLOCK 0x61
+#else
+/* N = 5,M=1 Fscl= Ftmds/2/10/2^N/(M+1) */
+#define SUNXI_HDMI_DDC_CLOCK 0x0d
+#endif
+
+#define SUNXI_HMDI_DDC_LINE_CTRL_SCL_ENABLE (1 << 8)
+#define SUNXI_HMDI_DDC_LINE_CTRL_SDA_ENABLE (1 << 9)
+
+/*
+ * TVE register constants.
+ */
+#define SUNXI_TVE_GCTRL_ENABLE (1 << 0)
+/*
+ * Select input 0 to disable dac, 1 - 4 to feed dac from tve0, 5 - 8 to feed
+ * dac from tve1. When using tve1 the mux value must be written to both tve0's
+ * and tve1's gctrl reg.
+ */
+#define SUNXI_TVE_GCTRL_DAC_INPUT_MASK(dac) (0xf << (((dac) + 1) * 4))
+#define SUNXI_TVE_GCTRL_DAC_INPUT(dac, sel) ((sel) << (((dac) + 1) * 4))
+#define SUNXI_TVE_GCTRL_CFG0_VGA 0x20000000
+#define SUNXI_TVE_GCTRL_DAC_CFG0_VGA 0x403e1ac7
+#define SUNXI_TVE_GCTRL_UNKNOWN1_VGA 0x00000000
+#define SUNXI_TVE_AUTO_DETECT_EN_DET_EN(dac) (1 << ((dac) + 0))
+#define SUNXI_TVE_AUTO_DETECT_EN_INT_EN(dac) (1 << ((dac) + 16))
+#define SUNXI_TVE_AUTO_DETECT_INT_STATUS(dac) (1 << ((dac) + 0))
+#define SUNXI_TVE_AUTO_DETECT_STATUS_SHIFT(dac) ((dac) * 8)
+#define SUNXI_TVE_AUTO_DETECT_STATUS_MASK(dac) (3 << ((dac) * 8))
+#define SUNXI_TVE_AUTO_DETECT_STATUS_NONE 0
+#define SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED 1
+#define SUNXI_TVE_AUTO_DETECT_STATUS_SHORT_GND 3
+#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_SHIFT(d) ((d) * 8)
+#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_MASK(d) (0xf << ((d) * 8))
+#define SUNXI_TVE_CSC_REG0_ENABLE (1 << 31)
+#define SUNXI_TVE_CSC_REG0 0x08440832
+#define SUNXI_TVE_CSC_REG1 0x3b6dace1
+#define SUNXI_TVE_CSC_REG2 0x0e1d13dc
+#define SUNXI_TVE_CSC_REG3 0x00108080
+
int sunxi_simplefb_setup(void *blob);
#endif /* _SUNXI_DISPLAY_H */
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 9072e68229..7ff43e6d3a 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -12,15 +12,44 @@
#ifndef _SUNXI_DRAM_H
#define _SUNXI_DRAM_H
+#include <asm/io.h>
#include <linux/types.h>
/* dram regs definition */
#if defined(CONFIG_MACH_SUN6I)
#include <asm/arch/dram_sun6i.h>
+#elif defined(CONFIG_MACH_SUN8I)
+#include <asm/arch/dram_sun8i.h>
#else
#include <asm/arch/dram_sun4i.h>
#endif
unsigned long sunxi_dram_init(void);
+/*
+ * Wait up to 1s for value to be set in given part of reg.
+ */
+static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
+{
+ unsigned long tmo = timer_get_us() + 1000000;
+
+ while ((readl(reg) & mask) != val) {
+ if (timer_get_us() > tmo)
+ panic("Timeout initialising DRAM\n");
+ }
+}
+
+/*
+ * Test if memory at offset offset matches memory at begin of DRAM
+ */
+static inline bool mctl_mem_matches(u32 offset)
+{
+ /* Try to write different values to RAM at two addresses */
+ writel(0, CONFIG_SYS_SDRAM_BASE);
+ writel(0xaa55aa55, CONFIG_SYS_SDRAM_BASE + offset);
+ /* Check if the same value is actually observed when reading back */
+ return readl(CONFIG_SYS_SDRAM_BASE) ==
+ readl(CONFIG_SYS_SDRAM_BASE + offset);
+}
+
#endif /* _SUNXI_DRAM_H */
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
new file mode 100644
index 0000000000..06adee2723
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
@@ -0,0 +1,266 @@
+/*
+ * Sun8i platform dram controller register and constant defines
+ *
+ * (C) Copyright 2007-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * CPL <cplanxy@allwinnertech.com>
+ * Jerry Wang <wangflord@allwinnertech.com>
+ *
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SUNXI_DRAM_SUN8I_H
+#define _SUNXI_DRAM_SUN8I_H
+
+struct dram_para {
+ u32 clock;
+ u32 type;
+ u32 zq;
+ u32 odt_en;
+ u32 para1;
+ u32 para2;
+ u32 mr0;
+ u32 mr1;
+ u32 mr2;
+ u32 mr3;
+ u32 tpr0;
+ u32 tpr1;
+ u32 tpr2;
+ u32 tpr3;
+ u32 tpr4;
+ u32 tpr5;
+ u32 tpr6;
+ u32 tpr7;
+ u32 tpr8;
+ u32 tpr9;
+ u32 tpr10;
+ u32 tpr11;
+ u32 tpr12;
+ u32 tpr13;
+};
+
+struct sunxi_mctl_com_reg {
+ u32 cr; /* 0x00 */
+ u32 ccr; /* 0x04 controller configuration register */
+ u32 dbgcr; /* 0x08 */
+ u8 res0[0x4]; /* 0x0c */
+ u32 mcr0_0; /* 0x10 */
+ u32 mcr1_0; /* 0x14 */
+ u32 mcr0_1; /* 0x18 */
+ u32 mcr1_1; /* 0x1c */
+ u32 mcr0_2; /* 0x20 */
+ u32 mcr1_2; /* 0x24 */
+ u32 mcr0_3; /* 0x28 */
+ u32 mcr1_3; /* 0x2c */
+ u32 mcr0_4; /* 0x30 */
+ u32 mcr1_4; /* 0x34 */
+ u32 mcr0_5; /* 0x38 */
+ u32 mcr1_5; /* 0x3c */
+ u32 mcr0_6; /* 0x40 */
+ u32 mcr1_6; /* 0x44 */
+ u32 mcr0_7; /* 0x48 */
+ u32 mcr1_7; /* 0x4c */
+ u32 mcr0_8; /* 0x50 */
+ u32 mcr1_8; /* 0x54 */
+ u32 mcr0_9; /* 0x58 */
+ u32 mcr1_9; /* 0x5c */
+ u32 mcr0_10; /* 0x60 */
+ u32 mcr1_10; /* 0x64 */
+ u32 mcr0_11; /* 0x68 */
+ u32 mcr1_11; /* 0x6c */
+ u32 mcr0_12; /* 0x70 */
+ u32 mcr1_12; /* 0x74 */
+ u32 mcr0_13; /* 0x78 */
+ u32 mcr1_13; /* 0x7c */
+ u32 mcr0_14; /* 0x80 */
+ u32 mcr1_14; /* 0x84 */
+ u32 mcr0_15; /* 0x88 */
+ u32 mcr1_15; /* 0x8c */
+ u32 bwcr; /* 0x90 */
+ u32 maer; /* 0x94 */
+ u8 res1[0x4]; /* 0x98 */
+ u32 mcgcr; /* 0x9c */
+ u32 bwctr; /* 0xa0 */
+ u8 res2[0x4]; /* 0xa4 */
+ u32 swonr; /* 0xa8 */
+ u32 swoffr; /* 0xac */
+};
+
+struct sunxi_mctl_ctl_reg {
+ u32 mstr; /* 0x00 */
+ u32 statr; /* 0x04 */
+ u8 res0[0x08]; /* 0x08 */
+ u32 mrctrl0; /* 0x10 */
+ u32 mrctrl1; /* 0x14 */
+ u32 mrstatr; /* 0x18 */
+ u8 res1[0x04]; /* 0x1c */
+ u32 derateen; /* 0x20 */
+ u32 deratenint; /* 0x24 */
+ u8 res2[0x08]; /* 0x28 */
+ u32 pwrctl; /* 0x30 */
+ u32 pwrtmg; /* 0x34 */
+ u8 res3[0x18]; /* 0x38 */
+ u32 rfshctl0; /* 0x50 */
+ u32 rfshctl1; /* 0x54 */
+ u8 res4[0x8]; /* 0x58 */
+ u32 rfshctl3; /* 0x60 */
+ u32 rfshtmg; /* 0x64 */
+ u8 res6[0x68]; /* 0x68 */
+ u32 init0; /* 0xd0 */
+ u32 init1; /* 0xd4 */
+ u32 init2; /* 0xd8 */
+ u32 init3; /* 0xdc */
+ u32 init4; /* 0xe0 */
+ u32 init5; /* 0xe4 */
+ u8 res7[0x0c]; /* 0xe8 */
+ u32 rankctl; /* 0xf4 */
+ u8 res8[0x08]; /* 0xf8 */
+ u32 dramtmg0; /* 0x100 */
+ u32 dramtmg1; /* 0x104 */
+ u32 dramtmg2; /* 0x108 */
+ u32 dramtmg3; /* 0x10c */
+ u32 dramtmg4; /* 0x110 */
+ u32 dramtmg5; /* 0x114 */
+ u32 dramtmg6; /* 0x118 */
+ u32 dramtmg7; /* 0x11c */
+ u32 dramtmg8; /* 0x120 */
+ u8 res9[0x5c]; /* 0x124 */
+ u32 zqctl0; /* 0x180 */
+ u32 zqctl1; /* 0x184 */
+ u32 zqctl2; /* 0x188 */
+ u32 zqstat; /* 0x18c */
+ u32 pitmg0; /* 0x190 */
+ u32 pitmg1; /* 0x194 */
+ u32 plpcfg0; /* 0x198 */
+ u8 res10[0x04]; /* 0x19c */
+ u32 upd0; /* 0x1a0 */
+ u32 upd1; /* 0x1a4 */
+ u32 upd2; /* 0x1a8 */
+ u32 upd3; /* 0x1ac */
+ u32 pimisc; /* 0x1b0 */
+ u8 res11[0x1c]; /* 0x1b4 */
+ u32 trainctl0; /* 0x1d0 */
+ u32 trainctl1; /* 0x1d4 */
+ u32 trainctl2; /* 0x1d8 */
+ u32 trainstat; /* 0x1dc */
+ u8 res12[0x60]; /* 0x1e0 */
+ u32 odtcfg; /* 0x240 */
+ u32 odtmap; /* 0x244 */
+ u8 res13[0x08]; /* 0x248 */
+ u32 sched; /* 0x250 */
+ u8 res14[0x04]; /* 0x254 */
+ u32 perfshpr0; /* 0x258 */
+ u32 perfshpr1; /* 0x25c */
+ u32 perflpr0; /* 0x260 */
+ u32 perflpr1; /* 0x264 */
+ u32 perfwr0; /* 0x268 */
+ u32 perfwr1; /* 0x26c */
+};
+
+struct sunxi_mctl_phy_reg {
+ u8 res0[0x04]; /* 0x00 */
+ u32 pir; /* 0x04 */
+ u32 pgcr0; /* 0x08 phy general configuration register */
+ u32 pgcr1; /* 0x0c phy general configuration register */
+ u32 pgsr0; /* 0x10 */
+ u32 pgsr1; /* 0x14 */
+ u32 dllgcr; /* 0x18 */
+ u32 ptr0; /* 0x1c */
+ u32 ptr1; /* 0x20 */
+ u32 ptr2; /* 0x24 */
+ u32 ptr3; /* 0x28 */
+ u32 ptr4; /* 0x2c */
+ u32 acmdlr; /* 0x30 */
+ u32 acbdlr; /* 0x34 */
+ u32 aciocr; /* 0x38 */
+ u32 dxccr; /* 0x3c DATX8 common configuration register */
+ u32 dsgcr; /* 0x40 dram system general config register */
+ u32 dcr; /* 0x44 */
+ u32 dtpr0; /* 0x48 dram timing parameters register 0 */
+ u32 dtpr1; /* 0x4c dram timing parameters register 1 */
+ u32 dtpr2; /* 0x50 dram timing parameters register 2 */
+ u32 mr0; /* 0x54 mode register 0 */
+ u32 mr1; /* 0x58 mode register 1 */
+ u32 mr2; /* 0x5c mode register 2 */
+ u32 mr3; /* 0x60 mode register 3 */
+ u32 odtcr; /* 0x64 */
+ u32 dtcr; /* 0x68 */
+ u32 dtar0; /* 0x6c data training address register 0 */
+ u32 dtar1; /* 0x70 data training address register 1 */
+ u32 dtar2; /* 0x74 data training address register 2 */
+ u32 dtar3; /* 0x78 data training address register 3 */
+ u32 dtdr0; /* 0x7c */
+ u32 dtdr1; /* 0x80 */
+ u32 dtedr0; /* 0x84 */
+ u32 dtedr1; /* 0x88 */
+ u32 pgcr2; /* 0x8c */
+ u8 res1[0x70]; /* 0x90 */
+ u32 bistrr; /* 0x100 */
+ u32 bistwcr; /* 0x104 */
+ u32 bistmskr0; /* 0x108 */
+ u32 bistmskr1; /* 0x10c */
+ u32 bistmskr2; /* 0x110 */
+ u32 bistlsr; /* 0x114 */
+ u32 bistar0; /* 0x118 */
+ u32 bistar1; /* 0x11c */
+ u32 bistar2; /* 0x120 */
+ u32 bistupdr; /* 0x124 */
+ u32 bistgsr; /* 0x128 */
+ u32 bistwer; /* 0x12c */
+ u32 bistber0; /* 0x130 */
+ u32 bistber1; /* 0x134 */
+ u32 bistber2; /* 0x138 */
+ u32 bistber3; /* 0x13c */
+ u32 bistwcsr; /* 0x140 */
+ u32 bistfwr0; /* 0x144 */
+ u32 bistfwr1; /* 0x148 */
+ u32 bistfwr2; /* 0x14c */
+ u8 res2[0x30]; /* 0x150 */
+ u32 zqcr0; /* 0x180 zq control register 0 */
+ u32 zqcr1; /* 0x184 zq control register 1 */
+ u32 zqsr0; /* 0x188 zq status register 0 */
+ u32 zqsr1; /* 0x18c zq status register 1 */
+ u32 zqcr2; /* 0x190 zq control register 2 */
+ u8 res3[0x2c]; /* 0x194 */
+ u32 dx0gcr; /* 0x1c0 */
+ u32 dx0gsr0; /* 0x1c4 */
+ u32 dx0gsr1; /* 0x1c8 */
+ u32 dx0bdlr0; /* 0x1cc */
+ u32 dx0bdlr1; /* 0x1d0 */
+ u32 dx0bdlr2; /* 0x1d4 */
+ u32 dx0bdlr3; /* 0x1d8 */
+ u32 dx0bdlr4; /* 0x1dc */
+ u32 dx0lcdlr0; /* 0x1e0 */
+ u32 dx0lcdlr1; /* 0x1e4 */
+ u32 dx0lcdlr2; /* 0x1e8 */
+ u32 dx0mdlr; /* 0x1ec */
+ u32 dx0gtr; /* 0x1f0 */
+ u32 dx0gsr2; /* 0x1f4 */
+ u8 res4[0x08]; /* 0x1f8 */
+ u32 dx1gcr; /* 0x200 */
+ u32 dx1gsr0; /* 0x204 */
+ u32 dx1gsr1; /* 0x208 */
+ u32 dx1bdlr0; /* 0x20c */
+ u32 dx1bdlr1; /* 0x210 */
+ u32 dx1bdlr2; /* 0x214 */
+ u32 dx1bdlr3; /* 0x218 */
+ u32 dx1bdlr4; /* 0x21c */
+ u32 dx1lcdlr0; /* 0x220 */
+ u32 dx1lcdlr1; /* 0x224 */
+ u32 dx1lcdlr2; /* 0x228 */
+ u32 dx1mdlr; /* 0x22c */
+ u32 dx1gtr; /* 0x230 */
+ u32 dx1gsr2; /* 0x234 */
+};
+
+/*
+ * DRAM common (sunxi_mctl_com_reg) register constants.
+ */
+#define MCTL_CR_ROW_MASK (0xf << 4)
+#define MCTL_CR_ROW(x) (((x) - 1) << 4)
+#define MCTL_CR_PAGE_SIZE_MASK (0xf << 8)
+#define MCTL_CR_PAGE_SIZE(x) ((x) << 8)
+
+#endif /* _SUNXI_DRAM_SUN8I_H */
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 366c0dc45a..71cc879c2b 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -114,6 +114,7 @@ enum sunxi_gpio_number {
SUNXI_GPIO_I_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_H),
SUNXI_GPIO_L_START = 352,
SUNXI_GPIO_M_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_L),
+ SUNXI_GPIO_AXP0_START = 1024,
};
/* SUNXI GPIO number definitions */
@@ -129,6 +130,8 @@ enum sunxi_gpio_number {
#define SUNXI_GPL(_nr) (SUNXI_GPIO_L_START + (_nr))
#define SUNXI_GPM(_nr) (SUNXI_GPIO_M_START + (_nr))
+#define SUNXI_GPAXP0(_nr) (SUNXI_GPIO_AXP0_START + (_nr))
+
/* GPIO pin function config */
#define SUNXI_GPIO_INPUT 0
#define SUNXI_GPIO_OUTPUT 1
@@ -145,13 +148,11 @@ enum sunxi_gpio_number {
#define SUN5I_GPB19_UART0_TX 2
#define SUN5I_GPB20_UART0_RX 2
-#define SUN5I_GPG3_SDC1 2
-
-#define SUN5I_GPG3_UART1_TX 4
-#define SUN5I_GPG4_UART1_RX 4
-
#define SUNXI_GPC6_SDC2 3
+#define SUNXI_GPD0_LCD0 2
+#define SUNXI_GPD0_LVDS0 3
+
#define SUNXI_GPF0_SDC0 2
#define SUNXI_GPF2_SDC0 2
@@ -166,6 +167,11 @@ enum sunxi_gpio_number {
#define SUN4I_GPG0_SDC1 4
+#define SUN5I_GPG3_SDC1 2
+
+#define SUN5I_GPG3_UART1_TX 4
+#define SUN5I_GPG4_UART1_RX 4
+
#define SUN4I_GPH22_SDC1 5
#define SUN6I_GPH20_UART0_TX 2
@@ -173,9 +179,11 @@ enum sunxi_gpio_number {
#define SUN4I_GPI4_SDC3 2
-#define SUNXI_GPL0_R_P2WI_SCK 3
-#define SUNXI_GPL1_R_P2WI_SDA 3
+#define SUN6I_GPL0_R_P2WI_SCK 3
+#define SUN6I_GPL1_R_P2WI_SDA 3
+#define SUN8I_GPL0_R_RSB_SCK 2
+#define SUN8I_GPL1_R_RSB_SDA 2
#define SUN8I_GPL2_R_UART_TX 2
#define SUN8I_GPL3_R_UART_RX 2
diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
index 88de1ff675..82ed541e91 100644
--- a/arch/arm/include/asm/arch-sunxi/prcm.h
+++ b/arch/arm/include/asm/arch-sunxi/prcm.h
@@ -50,7 +50,8 @@
#define PRCM_APB0_GATE_PIO (0x1 << 0)
#define PRCM_APB0_GATE_IR (0x1 << 1)
#define PRCM_APB0_GATE_TIMER01 (0x1 << 2)
-#define PRCM_APB0_GATE_P2WI (0x1 << 3)
+#define PRCM_APB0_GATE_P2WI (0x1 << 3) /* sun6i */
+#define PRCM_APB0_GATE_RSB (0x1 << 3) /* sun8i */
#define PRCM_APB0_GATE_UART (0x1 << 4)
#define PRCM_APB0_GATE_1WIRE (0x1 << 5)
#define PRCM_APB0_GATE_I2C (0x1 << 6)
diff --git a/arch/arm/include/asm/arch-sunxi/rsb.h b/arch/arm/include/asm/arch-sunxi/rsb.h
new file mode 100644
index 0000000000..95a595ab8d
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/rsb.h
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on allwinner u-boot sources rsb code which is:
+ * (C) Copyright 2007-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * lixiang <lixiang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __SUNXI_RSB_H
+#define __SUNXI_RSB_H
+
+#include <common.h>
+#include <asm/io.h>
+
+struct sunxi_rsb_reg {
+ u32 ctrl; /* 0x00 */
+ u32 ccr; /* 0x04 */
+ u32 inte; /* 0x08 */
+ u32 stat; /* 0x0c */
+ u32 addr; /* 0x10 */
+ u8 res0[8]; /* 0x14 */
+ u32 data; /* 0x1c */
+ u8 res1[4]; /* 0x20 */
+ u32 lcr; /* 0x24 */
+ u32 dmcr; /* 0x28 */
+ u32 cmd; /* 0x2c */
+ u32 devaddr; /* 0x30 */
+};
+
+#define RSB_CTRL_SOFT_RST (1 << 0)
+#define RSB_CTRL_START_TRANS (1 << 7)
+
+#define RSB_STAT_TOVER_INT (1 << 0)
+#define RSB_STAT_TERR_INT (1 << 1)
+#define RSB_STAT_LBSY_INT (1 << 2)
+
+#define RSB_DMCR_DEVICE_MODE_START (1 << 31)
+
+#define RSB_CMD_BYTE_WRITE 0x4e
+#define RSB_CMD_BYTE_READ 0x8b
+#define RSB_CMD_SET_RTSADDR 0xe8
+
+#define RSB_DEVADDR_RUNTIME_ADDR(x) ((x) << 16)
+#define RSB_DEVADDR_DEVICE_ADDR(x) ((x) << 0)
+
+void rsb_init(void);
+int rsb_set_device_mode(u32 device_mode_data);
+int rsb_set_device_address(u16 device_addr, u16 runtime_addr);
+int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data);
+int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data);
+
+#endif
diff --git a/arch/arm/include/asm/arch-sunxi/usbc.h b/arch/arm/include/asm/arch-sunxi/usbc.h
new file mode 100644
index 0000000000..8d2097336c
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/usbc.h
@@ -0,0 +1,20 @@
+/*
+ * Sunxi usb-controller code shared between the ehci and musb controllers
+ *
+ * Copyright (C) 2014 Roman Byshko
+ *
+ * Roman Byshko <rbyshko@gmail.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+void *sunxi_usbc_get_io_base(int index);
+int sunxi_usbc_request_resources(int index);
+int sunxi_usbc_free_resources(int index);
+void sunxi_usbc_enable(int index);
+void sunxi_usbc_disable(int index);
+void sunxi_usbc_vbus_enable(int index);
+void sunxi_usbc_vbus_disable(int index);
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 5374b4d6eb..78c98ed2d0 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -19,9 +19,6 @@ config TARGET_COBRA5272
config TARGET_EB_CPU5282
bool "Support eb_cpu5282"
-config TARGET_TASREG
- bool "Support TASREG"
-
config TARGET_M5208EVBE
bool "Support M5208EVBE"
@@ -75,7 +72,6 @@ endchoice
source "board/BuS/eb_cpu5282/Kconfig"
source "board/astro/mcf5373l/Kconfig"
source "board/cobra5272/Kconfig"
-source "board/esd/tasreg/Kconfig"
source "board/freescale/m5208evbe/Kconfig"
source "board/freescale/m52277evb/Kconfig"
source "board/freescale/m5235evb/Kconfig"
diff --git a/arch/powerpc/cpu/ppc4xx/Kconfig b/arch/powerpc/cpu/ppc4xx/Kconfig
index 8f8860163c..a40ae3b38a 100644
--- a/arch/powerpc/cpu/ppc4xx/Kconfig
+++ b/arch/powerpc/cpu/ppc4xx/Kconfig
@@ -13,9 +13,6 @@ config TARGET_CSB272
config TARGET_CSB472
bool "Support csb472"
-config TARGET_G2000
- bool "Support G2000"
-
config TARGET_JSE
bool "Support JSE"
@@ -110,78 +107,24 @@ config TARGET_CATCENTER
config TARGET_PPCHAMELEONEVB
bool "Support PPChameleonEVB"
-config TARGET_APC405
- bool "Support APC405"
-
-config TARGET_AR405
- bool "Support AR405"
-
-config TARGET_ASH405
- bool "Support ASH405"
-
-config TARGET_CMS700
- bool "Support CMS700"
-
config TARGET_CPCI2DP
bool "Support CPCI2DP"
-config TARGET_CPCI405
- bool "Support CPCI405"
-
config TARGET_CPCI4052
bool "Support CPCI4052"
-config TARGET_CPCI405AB
- bool "Support CPCI405AB"
-
-config TARGET_CPCI405DT
- bool "Support CPCI405DT"
-
-config TARGET_CPCIISER4
- bool "Support CPCIISER4"
-
-config TARGET_DP405
- bool "Support DP405"
-
-config TARGET_DU405
- bool "Support DU405"
-
-config TARGET_DU440
- bool "Support DU440"
-
-config TARGET_HH405
- bool "Support HH405"
-
-config TARGET_HUB405
- bool "Support HUB405"
-
-config TARGET_OCRTC
- bool "Support OCRTC"
-
-config TARGET_PCI405
- bool "Support PCI405"
-
config TARGET_PLU405
bool "Support PLU405"
-config TARGET_PMC405
- bool "Support PMC405"
-
config TARGET_PMC405DE
bool "Support PMC405DE"
config TARGET_PMC440
bool "Support PMC440"
-config TARGET_VOH405
- bool "Support VOH405"
-
config TARGET_VOM405
bool "Support VOM405"
-config TARGET_WUH405
- bool "Support WUH405"
-
config TARGET_DLVISION_10G
bool "Support dlvision-10g"
@@ -257,28 +200,12 @@ source "board/avnet/v5fx30teval/Kconfig"
source "board/csb272/Kconfig"
source "board/csb472/Kconfig"
source "board/dave/PPChameleonEVB/Kconfig"
-source "board/esd/apc405/Kconfig"
-source "board/esd/ar405/Kconfig"
-source "board/esd/ash405/Kconfig"
-source "board/esd/cms700/Kconfig"
source "board/esd/cpci2dp/Kconfig"
source "board/esd/cpci405/Kconfig"
-source "board/esd/cpciiser4/Kconfig"
-source "board/esd/dp405/Kconfig"
-source "board/esd/du405/Kconfig"
-source "board/esd/du440/Kconfig"
-source "board/esd/hh405/Kconfig"
-source "board/esd/hub405/Kconfig"
-source "board/esd/ocrtc/Kconfig"
-source "board/esd/pci405/Kconfig"
source "board/esd/plu405/Kconfig"
-source "board/esd/pmc405/Kconfig"
source "board/esd/pmc405de/Kconfig"
source "board/esd/pmc440/Kconfig"
-source "board/esd/voh405/Kconfig"
source "board/esd/vom405/Kconfig"
-source "board/esd/wuh405/Kconfig"
-source "board/g2000/Kconfig"
source "board/gdsys/405ep/Kconfig"
source "board/gdsys/405ex/Kconfig"
source "board/gdsys/dlvision/Kconfig"
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ebf72b3ee0..90e828a26e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -47,13 +47,10 @@ config RAMBASE
hex
default 0x100000
-config RAMTOP
- hex
- default 0x200000
-
config XIP_ROM_SIZE
hex
- default 0x10000
+ depends on X86_RESET_VECTOR
+ default ROM_SIZE
config CPU_ADDR_BITS
int
@@ -70,6 +67,15 @@ config SMM_TSEG
config SMM_TSEG_SIZE
hex
+config X86_RESET_VECTOR
+ bool
+ default n
+
+config SYS_X86_START16
+ hex
+ depends on X86_RESET_VECTOR
+ default 0xfffff800
+
config BOARD_ROMSIZE_KB_512
bool
config BOARD_ROMSIZE_KB_1024
@@ -85,6 +91,7 @@ config BOARD_ROMSIZE_KB_16384
choice
prompt "ROM chip size"
+ depends on X86_RESET_VECTOR
default UBOOT_ROMSIZE_KB_512 if BOARD_ROMSIZE_KB_512
default UBOOT_ROMSIZE_KB_1024 if BOARD_ROMSIZE_KB_1024
default UBOOT_ROMSIZE_KB_2048 if BOARD_ROMSIZE_KB_2048
@@ -317,6 +324,28 @@ config FRAMEBUFFER_VESA_MODE
endmenu
+config TSC_CALIBRATION_BYPASS
+ bool "Bypass Time-Stamp Counter (TSC) calibration"
+ default n
+ help
+ By default U-Boot automatically calibrates Time-Stamp Counter (TSC)
+ running frequency via Model-Specific Register (MSR) and Programmable
+ Interval Timer (PIT). If the calibration does not work on your board,
+ select this option and provide a hardcoded TSC running frequency with
+ CONFIG_TSC_FREQ_IN_MHZ below.
+
+ Normally this option should be turned on in a simulation environment
+ like qemu.
+
+config TSC_FREQ_IN_MHZ
+ int "Time-Stamp Counter (TSC) running frequency in MHz"
+ depends on TSC_CALIBRATION_BYPASS
+ default 1000
+ help
+ The running frequency in MHz of Time-Stamp Counter (TSC).
+
+source "arch/x86/cpu/coreboot/Kconfig"
+
source "arch/x86/cpu/ivybridge/Kconfig"
source "arch/x86/cpu/queensbay/Kconfig"
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 5033d2b757..62e43c04e5 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -17,5 +17,6 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
obj-y += lapic.o
+obj-y += mtrr.o
obj-$(CONFIG_PCI) += pci.o
obj-y += turbo.o
diff --git a/arch/x86/cpu/coreboot/Kconfig b/arch/x86/cpu/coreboot/Kconfig
new file mode 100644
index 0000000000..e0e3c64506
--- /dev/null
+++ b/arch/x86/cpu/coreboot/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_COREBOOT
+
+config SYS_COREBOOT
+ bool
+ default y
+
+config CBMEM_CONSOLE
+ bool
+ default y
+
+config VIDEO_COREBOOT
+ bool
+ default y
+
+endif
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index cfacc05875..6d06d5af19 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -15,6 +15,7 @@
#include <asm/cache.h>
#include <asm/cpu.h>
#include <asm/io.h>
+#include <asm/mtrr.h>
#include <asm/arch/tables.h>
#include <asm/arch/sysinfo.h>
#include <asm/arch/timestamp.h>
@@ -64,11 +65,6 @@ int board_eth_init(bd_t *bis)
return pci_eth_init(bis);
}
-#define MTRR_TYPE_WP 5
-#define MTRRcap_MSR 0xfe
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
-
void board_final_cleanup(void)
{
/* Un-cache the ROM so the kernel has one
@@ -77,15 +73,17 @@ void board_final_cleanup(void)
* Coreboot should have assigned this to the
* top available variable MTRR.
*/
- u8 top_mtrr = (native_read_msr(MTRRcap_MSR) & 0xff) - 1;
- u8 top_type = native_read_msr(MTRRphysBase_MSR(top_mtrr)) & 0xff;
+ u8 top_mtrr = (native_read_msr(MTRR_CAP_MSR) & 0xff) - 1;
+ u8 top_type = native_read_msr(MTRR_PHYS_BASE_MSR(top_mtrr)) & 0xff;
/* Make sure this MTRR is the correct Write-Protected type */
- if (top_type == MTRR_TYPE_WP) {
- disable_caches();
- wrmsrl(MTRRphysBase_MSR(top_mtrr), 0);
- wrmsrl(MTRRphysMask_MSR(top_mtrr), 0);
- enable_caches();
+ if (top_type == MTRR_TYPE_WRPROT) {
+ struct mtrr_state state;
+
+ mtrr_open(&state);
+ wrmsrl(MTRR_PHYS_BASE_MSR(top_mtrr), 0);
+ wrmsrl(MTRR_PHYS_MASK_MSR(top_mtrr), 0);
+ mtrr_close(&state);
}
/* Issue SMI to Coreboot to lock down ME and registers */
diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c
index 6a3dd93914..c9983f1588 100644
--- a/arch/x86/cpu/coreboot/pci.c
+++ b/arch/x86/cpu/coreboot/pci.c
@@ -13,6 +13,8 @@
#include <pci.h>
#include <asm/pci.h>
+DECLARE_GLOBAL_DATA_PTR;
+
static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev,
struct pci_config_table *table)
{
@@ -35,7 +37,31 @@ void board_pci_setup_hose(struct pci_controller *hose)
hose->first_busno = 0;
hose->last_busno = 0;
- pci_set_region(hose->regions + 0, 0x0, 0x0, 0xffffffff,
+ /* PCI memory space */
+ pci_set_region(hose->regions + 0,
+ CONFIG_PCI_MEM_BUS,
+ CONFIG_PCI_MEM_PHYS,
+ CONFIG_PCI_MEM_SIZE,
PCI_REGION_MEM);
- hose->region_count = 1;
+
+ /* 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,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ hose->region_count = 4;
}
diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c
index bd3558a021..0edee6bd2c 100644
--- a/arch/x86/cpu/coreboot/timestamp.c
+++ b/arch/x86/cpu/coreboot/timestamp.c
@@ -3,18 +3,7 @@
*
* Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
@@ -38,9 +27,27 @@ static struct timestamp_table *ts_table __attribute__((section(".data")));
void timestamp_init(void)
{
+#ifdef CONFIG_SYS_X86_TSC_TIMER
+ uint64_t base_time;
+#endif
+
ts_table = lib_sysinfo.tstamp_table;
#ifdef CONFIG_SYS_X86_TSC_TIMER
- timer_set_base(ts_table->base_time);
+ /*
+ * If coreboot is built with CONFIG_COLLECT_TIMESTAMPS, use the value
+ * of base_time in coreboot's timestamp table as our timer base,
+ * otherwise TSC counter value will be used.
+ *
+ * Sometimes even coreboot is built with CONFIG_COLLECT_TIMESTAMPS,
+ * the value of base_time in the timestamp table is still zero, so
+ * we must exclude this case too (this is currently seen on booting
+ * coreboot in qemu)
+ */
+ if (ts_table && ts_table->base_time)
+ base_time = ts_table->base_time;
+ else
+ base_time = rdtsc();
+ timer_set_base(base_time);
#endif
timestamp_add_now(TS_U_BOOT_INITTED);
}
diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S
index dca68e4144..9441666f5a 100644
--- a/arch/x86/cpu/ivybridge/car.S
+++ b/arch/x86/cpu/ivybridge/car.S
@@ -12,9 +12,11 @@
*/
#include <common.h>
+#include <asm/msr-index.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/processor-flags.h>
+#include <asm/arch/microcode.h>
#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
@@ -45,6 +47,14 @@ car_init:
movl $0xFEE00300, %esi
movl %eax, (%esi)
+ /* TODO: Load microcode later - the 'no eviction' mode breaks this */
+ movl $MSR_IA32_UCODE_WRITE, %ecx
+ xorl %edx, %edx
+ movl $_dt_ucode_base_size, %eax
+ movl (%eax), %eax
+ addl $UCODE_HEADER_LEN, %eax
+ wrmsr
+
post_code(POST_CAR_SIPI)
/* Zero out all fixed range and variable range MTRRs */
movl $mtrr_table, %esi
@@ -61,7 +71,7 @@ clear_mtrrs:
post_code(POST_CAR_MTRR)
/* Configure the default memory type to uncacheable */
- movl $MTRRdefType_MSR, %ecx
+ movl $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
andl $(~0x00000cff), %eax
wrmsr
@@ -76,16 +86,16 @@ clear_mtrrs:
post_code(POST_CAR_BASE_ADDRESS)
/* Set Cache-as-RAM mask */
movl $(MTRR_PHYS_MASK_MSR(0)), %ecx
- movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax
+ movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
post_code(POST_CAR_MASK)
/* Enable MTRR */
- movl $MTRRdefType_MSR, %ecx
+ movl $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
- orl $MTRRdefTypeEn, %eax
+ orl $MTRR_DEF_TYPE_EN, %eax
wrmsr
/* Enable cache (CR0.CD = 0, CR0.NW = 0) */
@@ -130,7 +140,7 @@ clear_mtrrs:
movl $MTRR_PHYS_MASK_MSR(1), %ecx
movl $CPU_PHYSMASK_HI, %edx
- movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax
+ movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
wrmsr
post_code(POST_CAR_ROM_CACHE)
@@ -141,7 +151,7 @@ clear_mtrrs:
xorl %edx, %edx
wrmsr
movl $MTRR_PHYS_MASK_MSR(2), %ecx
- movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax
+ movl $(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
#endif
@@ -163,6 +173,52 @@ wait_for_sipi:
/* return */
jmp car_init_ret
+.globl car_uninit
+car_uninit:
+ /* Disable cache */
+ movl %cr0, %eax
+ orl $X86_CR0_CD, %eax
+ movl %eax, %cr0
+
+ /* Disable MTRRs */
+ movl $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ andl $(~MTRR_DEF_TYPE_EN), %eax
+ wrmsr
+
+ /* Disable the no-eviction run state */
+ movl NOEVICTMOD_MSR, %ecx
+ rdmsr
+ andl $~2, %eax
+ wrmsr
+
+ invd
+
+ /* Disable the no-eviction mode */
+ rdmsr
+ andl $~1, %eax
+ wrmsr
+
+#ifdef CONFIG_CACHE_MRC_BIN
+ /* Clear the MTRR that was used to cache MRC */
+ xorl %eax, %eax
+ xorl %edx, %edx
+ movl $MTRR_PHYS_BASE_MSR(2), %ecx
+ wrmsr
+ movl $MTRR_PHYS_MASK_MSR(2), %ecx
+ wrmsr
+#endif
+
+ /* Enable MTRRs */
+ movl $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ orl $MTRR_DEF_TYPE_EN, %eax
+ wrmsr
+
+ invd
+
+ ret
+
mtrr_table:
/* Fixed MTRRs */
.word 0x250, 0x258, 0x259
@@ -176,3 +232,9 @@ mtrr_table:
.word 0x20C, 0x20D, 0x20E, 0x20F
.word 0x210, 0x211, 0x212, 0x213
mtrr_table_end:
+
+ .align 4
+_dt_ucode_base_size:
+ /* These next two fields are filled in by ifdtool */
+ .long 0 /* microcode base */
+ .long 0 /* microcode size */
diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
index 969b07b059..e9253100f6 100644
--- a/arch/x86/cpu/ivybridge/cpu.c
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -49,27 +49,6 @@ static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev)
pci_hose_write_config_byte(hose, dev, 0xdc, reg8);
}
-static void set_var_mtrr(
- unsigned reg, unsigned base, unsigned size, unsigned type)
-
-{
- /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
- /* FIXME: It only support 4G less range */
- wrmsr(MTRRphysBase_MSR(reg), base | type, 0);
- wrmsr(MTRRphysMask_MSR(reg), ~(size - 1) | MTRRphysMaskValid,
- (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1);
-}
-
-static void enable_rom_caching(void)
-{
- disable_caches();
- set_var_mtrr(1, 0xffc00000, 4 << 20, MTRR_TYPE_WRPROT);
- enable_caches();
-
- /* Enable Variable MTRRs */
- wrmsr(MTRRdefType_MSR, 0x800, 0);
-}
-
static int set_flex_ratio_to_tdp_nominal(void)
{
msr_t flex_ratio, msr;
@@ -165,10 +144,6 @@ int arch_cpu_init(void)
/* This is already done in start.S, but let's do it in C */
enable_port80_on_lpc(hose, PCH_LPC_DEV);
- /* already done in car.S */
- if (false)
- enable_rom_caching();
-
set_spi_speed();
/*
@@ -288,7 +263,7 @@ int print_cpuinfo(void)
enable_lapic();
ret = microcode_update_intel();
- if (ret && ret != -ENOENT && ret != -EEXIST)
+ if (ret)
return ret;
/* Enable upper 128bytes of CMOS */
diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c
index 3d7f740273..6cf9654e02 100644
--- a/arch/x86/cpu/ivybridge/gma.c
+++ b/arch/x86/cpu/ivybridge/gma.c
@@ -12,9 +12,11 @@
#include <fdtdec.h>
#include <pci_rom.h>
#include <asm/io.h>
+#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/arch/pch.h>
#include <asm/arch/sandybridge.h>
+#include <linux/kconfig.h>
struct gt_powermeter {
u16 reg;
@@ -730,7 +732,11 @@ static int int15_handler(void)
int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
const void *blob, int node)
{
+#ifdef CONFIG_VIDEO
+ ulong start;
+#endif
void *gtt_bar;
+ ulong base;
u32 reg32;
int ret;
@@ -739,14 +745,22 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
pci_write_config32(dev, PCI_COMMAND, reg32);
+ /* Use write-combining for the graphics memory, 256MB */
+ base = pci_read_bar32(hose, dev, 2);
+ mtrr_add_request(MTRR_TYPE_WRCOMB, base, 256 << 20);
+ mtrr_commit(true);
+
gtt_bar = (void *)pci_read_bar32(pci_bus_to_hose(0), dev, 0);
debug("GT bar %p\n", gtt_bar);
ret = gma_pm_init_pre_vbios(gtt_bar);
if (ret)
return ret;
+#ifdef CONFIG_VIDEO
+ start = get_timer(0);
ret = pci_run_vga_bios(dev, int15_handler, false);
-
+ debug("BIOS ran in %lums\n", get_timer(start));
+#endif
/* Post VBIOS init */
ret = gma_pm_init_post_vbios(gtt_bar, blob, node);
if (ret)
diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c
index 08177510ab..2440a97c48 100644
--- a/arch/x86/cpu/ivybridge/microcode_intel.c
+++ b/arch/x86/cpu/ivybridge/microcode_intel.c
@@ -13,7 +13,9 @@
#include <libfdt.h>
#include <asm/cpu.h>
#include <asm/msr.h>
+#include <asm/msr-index.h>
#include <asm/processor.h>
+#include <asm/arch/microcode.h>
/**
* struct microcode_update - standard microcode header from Intel
@@ -40,8 +42,8 @@ static int microcode_decode_node(const void *blob, int node,
update->data = fdt_getprop(blob, node, "data", &update->size);
if (!update->data)
return -EINVAL;
- update->data += 48;
- update->size -= 48;
+ update->data += UCODE_HEADER_LEN;
+ update->size -= UCODE_HEADER_LEN;
update->header_version = fdtdec_get_int(blob, node,
"intel,header-version", 0);
@@ -71,15 +73,16 @@ static inline uint32_t microcode_read_rev(void)
asm volatile (
"xorl %%eax, %%eax\n"
"xorl %%edx, %%edx\n"
- "movl $0x8b, %%ecx\n"
+ "movl %2, %%ecx\n"
"wrmsr\n"
"movl $0x01, %%eax\n"
"cpuid\n"
- "movl $0x8b, %%ecx\n"
+ "movl %2, %%ecx\n"
"rdmsr\n"
: /* outputs */
"=a" (low), "=d" (high)
: /* inputs */
+ "i" (MSR_IA32_UCODE_REV)
: /* clobbers */
"ebx", "ecx"
);
@@ -94,9 +97,9 @@ static void microcode_read_cpu(struct microcode_update *cpu)
struct cpuid_result result;
uint32_t low, high;
- wrmsr(0x8b, 0, 0);
+ wrmsr(MSR_IA32_UCODE_REV, 0, 0);
result = cpuid(1);
- rdmsr(0x8b, low, cpu->update_revision);
+ rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision);
x86_model = (result.eax >> 4) & 0x0f;
x86_family = (result.eax >> 8) & 0x0f;
cpu->processor_signature = result.eax;
@@ -120,6 +123,7 @@ int microcode_update_intel(void)
int count;
int node;
int ret;
+ int rev;
microcode_read_cpu(&cpu);
node = 0;
@@ -147,12 +151,16 @@ int microcode_update_intel(void)
skipped++;
continue;
}
- ret = microcode_read_rev();
- wrmsr(0x79, (ulong)update.data, 0);
+ wrmsr(MSR_IA32_UCODE_WRITE, (ulong)update.data, 0);
+ rev = microcode_read_rev();
debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n",
- microcode_read_rev(), update.date_code & 0xffff,
+ rev, update.date_code & 0xffff,
(update.date_code >> 24) & 0xff,
(update.date_code >> 16) & 0xff);
+ if (update.update_revision != rev) {
+ printf("Microcode update failed\n");
+ return -EFAULT;
+ }
count++;
} while (1);
}
diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c
index b95e781bbf..95047359ff 100644
--- a/arch/x86/cpu/ivybridge/sdram.c
+++ b/arch/x86/cpu/ivybridge/sdram.c
@@ -17,6 +17,7 @@
#include <asm/processor.h>
#include <asm/gpio.h>
#include <asm/global_data.h>
+#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/arch/me.h>
#include <asm/arch/pei_data.h>
@@ -430,6 +431,15 @@ static int sdram_find(pci_dev_t dev)
add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28);
add_memory_area(info, (4 << 28) + (2 << 20), tseg_base);
add_memory_area(info, 1ULL << 32, touud);
+
+ /* Add MTRRs for memory */
+ mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30);
+ mtrr_add_request(MTRR_TYPE_WRBACK, 2ULL << 30, 512 << 20);
+ mtrr_add_request(MTRR_TYPE_WRBACK, 0xaULL << 28, 256 << 20);
+ mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base, 16 << 20);
+ mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base + (16 << 20),
+ 32 << 20);
+
/*
* If >= 4GB installed then memory from TOLUD to 4GB
* is remapped above TOM, TOUUD will account for both
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c
new file mode 100644
index 0000000000..d5a825d181
--- /dev/null
+++ b/arch/x86/cpu/mtrr.c
@@ -0,0 +1,81 @@
+/*
+ * (C) Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Memory Type Range Regsters - these are used to tell the CPU whether
+ * memory is cacheable and if so the cache write mode to use.
+ *
+ * These can speed up booting. See the mtrr command.
+ *
+ * Reference: Intel Architecture Software Developer's Manual, Volume 3:
+ * System Programming
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+
+/* Prepare to adjust MTRRs */
+void mtrr_open(struct mtrr_state *state)
+{
+ state->enable_cache = dcache_status();
+
+ if (state->enable_cache)
+ disable_caches();
+ state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR);
+ wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN);
+}
+
+/* Clean up after adjusting MTRRs, and enable them */
+void mtrr_close(struct mtrr_state *state)
+{
+ wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
+ if (state->enable_cache)
+ enable_caches();
+}
+
+int mtrr_commit(bool do_caches)
+{
+ struct mtrr_request *req = gd->arch.mtrr_req;
+ struct mtrr_state state;
+ uint64_t mask;
+ int i;
+
+ mtrr_open(&state);
+ for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) {
+ mask = ~(req->size - 1);
+ mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+ wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type);
+ wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID);
+ }
+
+ /* Clear the ones that are unused */
+ for (; i < MTRR_COUNT; i++)
+ wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
+ mtrr_close(&state);
+
+ return 0;
+}
+
+int mtrr_add_request(int type, uint64_t start, uint64_t size)
+{
+ struct mtrr_request *req;
+ uint64_t mask;
+
+ if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
+ return -ENOSPC;
+ req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
+ req->type = type;
+ req->start = start;
+ req->size = size;
+ debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1,
+ req->type, req->start, req->size);
+ mask = ~(req->size - 1);
+ mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+ mask |= MTRR_PHYS_MASK_VALID;
+ debug(" %016llx %016llx\n", req->start | req->type, mask);
+
+ return 0;
+}
diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c
index f3492c3851..ab1aaaa059 100644
--- a/arch/x86/cpu/pci.c
+++ b/arch/x86/cpu/pci.c
@@ -15,6 +15,8 @@
#include <pci.h>
#include <asm/pci.h>
+DECLARE_GLOBAL_DATA_PTR;
+
static struct pci_controller x86_hose;
int pci_early_init_hose(struct pci_controller **hosep)
@@ -27,7 +29,8 @@ int pci_early_init_hose(struct pci_controller **hosep)
board_pci_setup_hose(hose);
pci_setup_type1(hose);
- gd->arch.hose = hose;
+ hose->last_busno = pci_hose_scan(hose);
+ gd->hose = hose;
*hosep = hose;
return 0;
@@ -48,7 +51,7 @@ void pci_init_board(void)
struct pci_controller *hose = &x86_hose;
/* Stop using the early hose */
- gd->arch.hose = NULL;
+ gd->hose = NULL;
board_pci_setup_hose(hose);
pci_setup_type1(hose);
@@ -61,8 +64,8 @@ void pci_init_board(void)
static struct pci_controller *get_hose(void)
{
- if (gd->arch.hose)
- return gd->arch.hose;
+ if (gd->hose)
+ return gd->hose;
return pci_bus_to_hose(0);
}
diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/cpu/queensbay/fsp_support.c
index ef1916b2e7..aed3e2b300 100644
--- a/arch/x86/cpu/queensbay/fsp_support.c
+++ b/arch/x86/cpu/queensbay/fsp_support.c
@@ -231,26 +231,28 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
u32 fsp_get_usable_lowmem_top(const void *hob_list)
{
- union hob_pointers hob;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
phys_addr_t phys_start;
u32 top;
/* Get the HOB list for processing */
- hob.raw = (void *)hob_list;
+ hdr = hob_list;
/* * Collect memory ranges */
top = FSP_LOWMEM_BASE;
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- if (hob.res_desc->type == RES_SYS_MEM) {
- phys_start = hob.res_desc->phys_start;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ if (res_desc->type == RES_SYS_MEM) {
+ phys_start = res_desc->phys_start;
/* Need memory above 1MB to be collected here */
if (phys_start >= FSP_LOWMEM_BASE &&
phys_start < (phys_addr_t)FSP_HIGHMEM_BASE)
- top += (u32)(hob.res_desc->len);
+ top += (u32)(res_desc->len);
}
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
return top;
@@ -258,25 +260,27 @@ u32 fsp_get_usable_lowmem_top(const void *hob_list)
u64 fsp_get_usable_highmem_top(const void *hob_list)
{
- union hob_pointers hob;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
phys_addr_t phys_start;
u64 top;
/* Get the HOB list for processing */
- hob.raw = (void *)hob_list;
+ hdr = hob_list;
/* Collect memory ranges */
top = FSP_HIGHMEM_BASE;
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- if (hob.res_desc->type == RES_SYS_MEM) {
- phys_start = hob.res_desc->phys_start;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ if (res_desc->type == RES_SYS_MEM) {
+ phys_start = res_desc->phys_start;
/* Need memory above 1MB to be collected here */
if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE)
- top += (u32)(hob.res_desc->len);
+ top += (u32)(res_desc->len);
}
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
return top;
@@ -285,24 +289,26 @@ u64 fsp_get_usable_highmem_top(const void *hob_list)
u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len,
struct efi_guid *guid)
{
- union hob_pointers hob;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
/* Get the HOB list for processing */
- hob.raw = (void *)hob_list;
+ hdr = hob_list;
/* Collect memory ranges */
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- if (hob.res_desc->type == RES_MEM_RESERVED) {
- if (compare_guid(&hob.res_desc->owner, guid)) {
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ if (res_desc->type == RES_MEM_RESERVED) {
+ if (compare_guid(&res_desc->owner, guid)) {
if (len)
- *len = (u32)(hob.res_desc->len);
+ *len = (u32)(res_desc->len);
- return (u64)(hob.res_desc->phys_start);
+ return (u64)(res_desc->phys_start);
}
}
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
return 0;
@@ -336,44 +342,45 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len)
return base;
}
-void *fsp_get_next_hob(u16 type, const void *hob_list)
+const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list)
{
- union hob_pointers hob;
+ const struct hob_header *hdr;
- assert(hob_list != NULL);
-
- hob.raw = (u8 *)hob_list;
+ hdr = hob_list;
/* Parse the HOB list until end of list or matching type is found */
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == type)
- return hob.raw;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == type)
+ return hdr;
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
return NULL;
}
-void *fsp_get_next_guid_hob(const struct efi_guid *guid, const void *hob_list)
+const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
+ const void *hob_list)
{
- union hob_pointers hob;
-
- hob.raw = (u8 *)hob_list;
- while ((hob.raw = fsp_get_next_hob(HOB_TYPE_GUID_EXT,
- hob.raw)) != NULL) {
- if (compare_guid(guid, &hob.guid->name))
+ const struct hob_header *hdr;
+ struct hob_guid *guid_hob;
+
+ hdr = hob_list;
+ while ((hdr = fsp_get_next_hob(HOB_TYPE_GUID_EXT,
+ hdr)) != NULL) {
+ guid_hob = (struct hob_guid *)hdr;
+ if (compare_guid(guid, &(guid_hob->name)))
break;
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
- return hob.raw;
+ return hdr;
}
void *fsp_get_guid_hob_data(const void *hob_list, u32 *len,
struct efi_guid *guid)
{
- u8 *guid_hob;
+ const struct hob_header *guid_hob;
guid_hob = fsp_get_next_guid_hob(guid, hob_list);
if (guid_hob == NULL) {
diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/cpu/queensbay/tnc_dram.c
index 8e97c9b82a..df79a39dd8 100644
--- a/arch/x86/cpu/queensbay/tnc_dram.c
+++ b/arch/x86/cpu/queensbay/tnc_dram.c
@@ -14,17 +14,19 @@ DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
phys_size_t ram_size = 0;
- union hob_pointers hob;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
- hob.raw = gd->arch.hob_list;
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- if (hob.res_desc->type == RES_SYS_MEM ||
- hob.res_desc->type == RES_MEM_RESERVED) {
- ram_size += hob.res_desc->len;
+ hdr = gd->arch.hob_list;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ if (res_desc->type == RES_SYS_MEM ||
+ res_desc->type == RES_MEM_RESERVED) {
+ ram_size += res_desc->len;
}
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
gd->ram_size = ram_size;
@@ -55,22 +57,23 @@ ulong board_get_usable_ram_top(ulong total_size)
unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
{
unsigned num_entries = 0;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
- union hob_pointers hob;
+ hdr = gd->arch.hob_list;
- hob.raw = gd->arch.hob_list;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ entries[num_entries].addr = res_desc->phys_start;
+ entries[num_entries].size = res_desc->len;
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- entries[num_entries].addr = hob.res_desc->phys_start;
- entries[num_entries].size = hob.res_desc->len;
-
- if (hob.res_desc->type == RES_SYS_MEM)
+ if (res_desc->type == RES_SYS_MEM)
entries[num_entries].type = E820_RAM;
- else if (hob.res_desc->type == RES_MEM_RESERVED)
+ else if (res_desc->type == RES_MEM_RESERVED)
entries[num_entries].type = E820_RESERVED;
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
num_entries++;
}
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 125782cf27..f51f1121d0 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -205,6 +205,14 @@ board_init_f_r_trampoline:
/* Setup global descriptor table so gd->xyz works */
call setup_gdt
+ /* Set if we need to disable CAR */
+.weak car_uninit
+ movl $car_uninit, %eax
+ cmpl $0, %eax
+ jz 1f
+
+ call car_uninit
+1:
/* Re-enter U-Boot by calling board_init_f_r */
call board_init_f_r
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index 3b5d6dad46..97ed884288 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -1,6 +1,4 @@
-dtb-y += link.dtb \
- chromebook_link.dtb \
- alex.dtb \
+dtb-y += chromebook_link.dtb \
crownbay.dtb
targets += $(dtb-y)
diff --git a/arch/x86/dts/alex.dts b/arch/x86/dts/alex.dts
deleted file mode 100644
index 2f13544612..0000000000
--- a/arch/x86/dts/alex.dts
+++ /dev/null
@@ -1,24 +0,0 @@
-/dts-v1/;
-
-/include/ "coreboot.dtsi"
-
-/ {
- #address-cells = <1>;
- #size-cells = <1>;
- model = "Google Alex";
- compatible = "google,alex", "intel,atom-pineview";
-
- config {
- silent_console = <0>;
- };
-
- gpio: gpio {};
-
- serial {
- reg = <0x3f8 8>;
- clock-frequency = <115200>;
- };
-
- chosen { };
- memory { device_type = "memory"; reg = <0 0>; };
-};
diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts
index 6f8c5cdba7..9490b169fb 120000..100644
--- a/arch/x86/dts/chromebook_link.dts
+++ b/arch/x86/dts/chromebook_link.dts
@@ -1 +1,216 @@
-link.dts \ No newline at end of file
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+/include/ "serial.dtsi"
+
+/ {
+ model = "Google Link";
+ compatible = "google,link", "intel,celeron-ivybridge";
+
+ config {
+ silent_console = <0>;
+ };
+
+ gpioa {
+ compatible = "intel,ich6-gpio";
+ u-boot,dm-pre-reloc;
+ reg = <0 0x10>;
+ bank-name = "A";
+ };
+
+ gpiob {
+ compatible = "intel,ich6-gpio";
+ u-boot,dm-pre-reloc;
+ reg = <0x30 0x10>;
+ bank-name = "B";
+ };
+
+ gpioc {
+ compatible = "intel,ich6-gpio";
+ u-boot,dm-pre-reloc;
+ reg = <0x40 0x10>;
+ bank-name = "C";
+ };
+
+ chosen {
+ stdout-path = "/serial";
+ };
+
+ spd {
+ compatible = "memory-spd";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ elpida_4Gb_1600_x16 {
+ reg = <0>;
+ data = [92 10 0b 03 04 19 02 02
+ 03 52 01 08 0a 00 fe 00
+ 69 78 69 3c 69 11 18 81
+ 20 08 3c 3c 01 40 83 81
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 0f 11 42 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 02 fe 00
+ 11 52 00 00 00 07 7f 37
+ 45 42 4a 32 30 55 47 36
+ 45 42 55 30 2d 47 4e 2d
+ 46 20 30 20 02 fe 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00];
+ };
+ samsung_4Gb_1600_1.35v_x16 {
+ reg = <1>;
+ data = [92 11 0b 03 04 19 02 02
+ 03 11 01 08 0a 00 fe 00
+ 69 78 69 3c 69 11 18 81
+ f0 0a 3c 3c 01 40 83 01
+ 00 80 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 0f 11 02 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 80 ce 01
+ 00 00 00 00 00 00 6a 04
+ 4d 34 37 31 42 35 36 37
+ 34 42 48 30 2d 59 4b 30
+ 20 20 00 00 80 ce 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00];
+ };
+ micron_4Gb_1600_1.35v_x16 {
+ reg = <2>;
+ data = [92 11 0b 03 04 19 02 02
+ 03 11 01 08 0a 00 fe 00
+ 69 78 69 3c 69 11 18 81
+ 20 08 3c 3c 01 40 83 05
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 0f 01 02 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 80 2c 00
+ 00 00 00 00 00 00 ad 75
+ 34 4b 54 46 32 35 36 36
+ 34 48 5a 2d 31 47 36 45
+ 31 20 45 31 80 2c 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00
+ ff ff ff ff ff ff ff ff
+ ff ff ff ff ff ff ff ff
+ ff ff ff ff ff ff ff ff
+ ff ff ff ff ff ff ff ff
+ ff ff ff ff ff ff ff ff
+ ff ff ff ff ff ff ff ff
+ ff ff ff ff ff ff ff ff
+ ff ff ff ff ff ff ff ff
+ ff ff ff ff ff ff ff ff
+ ff ff ff ff ff ff ff ff];
+ };
+ };
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "intel,ich9";
+ spi-flash@0 {
+ reg = <0>;
+ compatible = "winbond,w25q64", "spi-flash";
+ memory-map = <0xff800000 0x00800000>;
+ };
+ };
+
+ pci {
+ sata {
+ compatible = "intel,pantherpoint-ahci";
+ intel,sata-mode = "ahci";
+ intel,sata-port-map = <1>;
+ intel,sata-port0-gen3-tx = <0x00880a7f>;
+ };
+
+ gma {
+ compatible = "intel,gma";
+ intel,dp_hotplug = <0 0 0x06>;
+ intel,panel-port-select = <1>;
+ intel,panel-power-cycle-delay = <6>;
+ intel,panel-power-up-delay = <2000>;
+ intel,panel-power-down-delay = <500>;
+ intel,panel-power-backlight-on-delay = <2000>;
+ intel,panel-power-backlight-off-delay = <2000>;
+ intel,cpu-backlight = <0x00000200>;
+ intel,pch-backlight = <0x04000000>;
+ };
+
+ lpc {
+ compatible = "intel,lpc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ gen-dec = <0x800 0xfc 0x900 0xfc>;
+ intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
+ intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b
+ 0x80 0x80 0x80 0x80>;
+ intel,gpi-routing = <0 0 0 0 0 0 0 2
+ 1 0 0 0 0 0 0 0>;
+ /* Enable EC SMI source */
+ intel,alt-gp-smi-enable = <0x0100>;
+
+ cros-ec@200 {
+ compatible = "google,cros-ec";
+ reg = <0x204 1 0x200 1 0x880 0x80>;
+
+ /* Describes the flash memory within the EC */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ flash@8000000 {
+ reg = <0x08000000 0x20000>;
+ erase-value = <0xff>;
+ };
+ };
+ };
+ };
+
+ microcode {
+ update@0 {
+#include "microcode/m12306a9_0000001b.dtsi"
+ };
+ };
+
+};
diff --git a/arch/x86/dts/coreboot.dtsi b/arch/x86/dts/coreboot.dtsi
deleted file mode 100644
index 65a93acd3d..0000000000
--- a/arch/x86/dts/coreboot.dtsi
+++ /dev/null
@@ -1,17 +0,0 @@
-/include/ "skeleton.dtsi"
-
-/ {
- chosen {
- stdout-path = "/serial";
- };
-
- serial {
- compatible = "x86-uart";
- reg = <0x3f8 0x10>;
- reg-shift = <0>;
- io-mapped = <1>;
- multiplier = <1>;
- baudrate = <115200>;
- status = "disabled";
- };
-};
diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts
index 3f43f3ca37..e81054ebc5 100644
--- a/arch/x86/dts/crownbay.dts
+++ b/arch/x86/dts/crownbay.dts
@@ -6,11 +6,10 @@
/dts-v1/;
-/include/ "coreboot.dtsi"
+/include/ "skeleton.dtsi"
+/include/ "serial.dtsi"
/ {
- #address-cells = <1>;
- #size-cells = <1>;
model = "Intel Crown Bay";
compatible = "intel,crownbay", "intel,queensbay";
@@ -32,14 +31,18 @@
bank-name = "B";
};
- serial {
- reg = <0x3f8 8>;
- clock-frequency = <115200>;
+ chosen {
+ /*
+ * By default the legacy superio serial port is used as the
+ * U-Boot serial console. If we want to use UART from Topcliff
+ * PCH as the console, change this property to &pciuart#.
+ *
+ * For example, stdout-path = &pciuart0 will use the first
+ * UART on Topcliff PCH.
+ */
+ stdout-path = "/serial";
};
- chosen { };
- memory { device_type = "memory"; reg = <0 0>; };
-
spi {
#address-cells = <1>;
#size-cells = <0>;
@@ -57,4 +60,77 @@
};
};
+ pci {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ compatible = "intel,pci";
+ device_type = "pci";
+
+ pcie@17,0 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ compatible = "intel,pci";
+ device_type = "pci";
+
+ topcliff@0,0 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ compatible = "intel,pci";
+ device_type = "pci";
+
+ pciuart0: uart@a,1 {
+ compatible = "pci8086,8811.00",
+ "pci8086,8811",
+ "pciclass,070002",
+ "pciclass,0700",
+ "x86-uart";
+ reg = <0x00025100 0x0 0x0 0x0 0x0
+ 0x01025110 0x0 0x0 0x0 0x0>;
+ reg-shift = <0>;
+ clock-frequency = <1843200>;
+ current-speed = <115200>;
+ };
+
+ pciuart1: uart@a,2 {
+ compatible = "pci8086,8812.00",
+ "pci8086,8812",
+ "pciclass,070002",
+ "pciclass,0700",
+ "x86-uart";
+ reg = <0x00025200 0x0 0x0 0x0 0x0
+ 0x01025210 0x0 0x0 0x0 0x0>;
+ reg-shift = <0>;
+ clock-frequency = <1843200>;
+ current-speed = <115200>;
+ };
+
+ pciuart2: uart@a,3 {
+ compatible = "pci8086,8813.00",
+ "pci8086,8813",
+ "pciclass,070002",
+ "pciclass,0700",
+ "x86-uart";
+ reg = <0x00025300 0x0 0x0 0x0 0x0
+ 0x01025310 0x0 0x0 0x0 0x0>;
+ reg-shift = <0>;
+ clock-frequency = <1843200>;
+ current-speed = <115200>;
+ };
+
+ pciuart3: uart@a,4 {
+ compatible = "pci8086,8814.00",
+ "pci8086,8814",
+ "pciclass,070002",
+ "pciclass,0700",
+ "x86-uart";
+ reg = <0x00025400 0x0 0x0 0x0 0x0
+ 0x01025410 0x0 0x0 0x0 0x0>;
+ reg-shift = <0>;
+ clock-frequency = <1843200>;
+ current-speed = <115200>;
+ };
+ };
+ };
+ };
+
};
diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts
deleted file mode 100644
index a739080a2f..0000000000
--- a/arch/x86/dts/link.dts
+++ /dev/null
@@ -1,224 +0,0 @@
-/dts-v1/;
-
-/include/ "coreboot.dtsi"
-
-/ {
- #address-cells = <1>;
- #size-cells = <1>;
- model = "Google Link";
- compatible = "google,link", "intel,celeron-ivybridge";
-
- config {
- silent_console = <0>;
- };
-
- gpioa {
- compatible = "intel,ich6-gpio";
- u-boot,dm-pre-reloc;
- reg = <0 0x10>;
- bank-name = "A";
- };
-
- gpiob {
- compatible = "intel,ich6-gpio";
- u-boot,dm-pre-reloc;
- reg = <0x30 0x10>;
- bank-name = "B";
- };
-
- gpioc {
- compatible = "intel,ich6-gpio";
- u-boot,dm-pre-reloc;
- reg = <0x40 0x10>;
- bank-name = "C";
- };
-
- serial {
- reg = <0x3f8 8>;
- clock-frequency = <115200>;
- };
-
- chosen { };
- memory { device_type = "memory"; reg = <0 0>; };
-
- spd {
- compatible = "memory-spd";
- #address-cells = <1>;
- #size-cells = <0>;
- elpida_4Gb_1600_x16 {
- reg = <0>;
- data = [92 10 0b 03 04 19 02 02
- 03 52 01 08 0a 00 fe 00
- 69 78 69 3c 69 11 18 81
- 20 08 3c 3c 01 40 83 81
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 0f 11 42 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 02 fe 00
- 11 52 00 00 00 07 7f 37
- 45 42 4a 32 30 55 47 36
- 45 42 55 30 2d 47 4e 2d
- 46 20 30 20 02 fe 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00];
- };
- samsung_4Gb_1600_1.35v_x16 {
- reg = <1>;
- data = [92 11 0b 03 04 19 02 02
- 03 11 01 08 0a 00 fe 00
- 69 78 69 3c 69 11 18 81
- f0 0a 3c 3c 01 40 83 01
- 00 80 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 0f 11 02 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 80 ce 01
- 00 00 00 00 00 00 6a 04
- 4d 34 37 31 42 35 36 37
- 34 42 48 30 2d 59 4b 30
- 20 20 00 00 80 ce 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00];
- };
- micron_4Gb_1600_1.35v_x16 {
- reg = <2>;
- data = [92 11 0b 03 04 19 02 02
- 03 11 01 08 0a 00 fe 00
- 69 78 69 3c 69 11 18 81
- 20 08 3c 3c 01 40 83 05
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 0f 01 02 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 80 2c 00
- 00 00 00 00 00 00 ad 75
- 34 4b 54 46 32 35 36 36
- 34 48 5a 2d 31 47 36 45
- 31 20 45 31 80 2c 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- ff ff ff ff ff ff ff ff
- ff ff ff ff ff ff ff ff
- ff ff ff ff ff ff ff ff
- ff ff ff ff ff ff ff ff
- ff ff ff ff ff ff ff ff
- ff ff ff ff ff ff ff ff
- ff ff ff ff ff ff ff ff
- ff ff ff ff ff ff ff ff
- ff ff ff ff ff ff ff ff
- ff ff ff ff ff ff ff ff];
- };
- };
-
- spi {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "intel,ich9";
- spi-flash@0 {
- reg = <0>;
- compatible = "winbond,w25q64", "spi-flash";
- memory-map = <0xff800000 0x00800000>;
- };
- };
-
- pci {
- sata {
- compatible = "intel,pantherpoint-ahci";
- intel,sata-mode = "ahci";
- intel,sata-port-map = <1>;
- intel,sata-port0-gen3-tx = <0x00880a7f>;
- };
-
- gma {
- compatible = "intel,gma";
- intel,dp_hotplug = <0 0 0x06>;
- intel,panel-port-select = <1>;
- intel,panel-power-cycle-delay = <6>;
- intel,panel-power-up-delay = <2000>;
- intel,panel-power-down-delay = <500>;
- intel,panel-power-backlight-on-delay = <2000>;
- intel,panel-power-backlight-off-delay = <2000>;
- intel,cpu-backlight = <0x00000200>;
- intel,pch-backlight = <0x04000000>;
- };
-
- lpc {
- compatible = "intel,lpc";
- #address-cells = <1>;
- #size-cells = <1>;
- gen-dec = <0x800 0xfc 0x900 0xfc>;
- intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
- intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b
- 0x80 0x80 0x80 0x80>;
- intel,gpi-routing = <0 0 0 0 0 0 0 2
- 1 0 0 0 0 0 0 0>;
- /* Enable EC SMI source */
- intel,alt-gp-smi-enable = <0x0100>;
-
- cros-ec@200 {
- compatible = "google,cros-ec";
- reg = <0x204 1 0x200 1 0x880 0x80>;
-
- /* Describes the flash memory within the EC */
- #address-cells = <1>;
- #size-cells = <1>;
- flash@8000000 {
- reg = <0x08000000 0x20000>;
- erase-value = <0xff>;
- };
- };
- };
- };
-
- microcode {
- update@0 {
-#include "microcode/m12206a7_00000029.dtsi"
- };
- update@1 {
-#include "microcode/m12306a9_0000001b.dtsi"
- };
- };
-
-};
diff --git a/arch/x86/dts/serial.dtsi b/arch/x86/dts/serial.dtsi
new file mode 100644
index 0000000000..9b097f4f9b
--- /dev/null
+++ b/arch/x86/dts/serial.dtsi
@@ -0,0 +1,9 @@
+/ {
+ serial {
+ compatible = "x86-uart";
+ reg = <0x3f8 8>;
+ reg-shift = <0>;
+ clock-frequency = <1843200>;
+ current-speed = <115200>;
+ };
+};
diff --git a/arch/x86/include/asm/arch-ivybridge/microcode.h b/arch/x86/include/asm/arch-ivybridge/microcode.h
index bc9b87c44c..b868283761 100644
--- a/arch/x86/include/asm/arch-ivybridge/microcode.h
+++ b/arch/x86/include/asm/arch-ivybridge/microcode.h
@@ -7,6 +7,11 @@
#ifndef __ASM_ARCH_MICROCODE_H
#define __ASM_ARCH_MICROCODE_H
+/* Length of the public header on Intel microcode blobs */
+#define UCODE_HEADER_LEN 0x30
+
+#ifndef __ASSEMBLY__
+
/**
* microcode_update_intel() - Apply microcode updates
*
@@ -16,5 +21,6 @@
* not updates were found, -EINVAL if an update was invalid
*/
int microcode_update_intel(void);
+#endif /* __ASSEMBLY__ */
#endif
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h
index 380b64efaa..6cca7f5654 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h
+++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h
@@ -182,58 +182,19 @@ struct hob_guid {
/* GUID specific data goes here */
};
-/* Union of all the possible HOB Types */
-union hob_pointers {
- struct hob_header *hdr;
- struct hob_mem_alloc *mem_alloc;
- struct hob_res_desc *res_desc;
- struct hob_guid *guid;
- u8 *raw;
-};
-
-/**
- * get_hob_type() - return the type of a HOB
- *
- * This macro returns the type field from the HOB header for the
- * HOB specified by hob.
- *
- * @hob: A pointer to a HOB.
- *
- * @return: HOB type.
- */
-static inline u16 get_hob_type(union hob_pointers hob)
-{
- return hob.hdr->type;
-}
-
-/**
- * get_hob_length() - return the length, in bytes, of a HOB
- *
- * This macro returns the len field from the HOB header for the
- * HOB specified by hob.
- *
- * @hob: A pointer to a HOB.
- *
- * @return: HOB length.
- */
-static inline u16 get_hob_length(union hob_pointers hob)
-{
- return hob.hdr->len;
-}
-
/**
* get_next_hob() - return a pointer to the next HOB in the HOB list
*
* This macro returns a pointer to HOB that follows the HOB specified by hob
* in the HOB List.
*
- * @hob: A pointer to a HOB.
+ * @hdr: A pointer to a HOB.
*
* @return: A pointer to the next HOB in the HOB list.
*/
-static inline void *get_next_hob(union hob_pointers hob)
+static inline const struct hob_header *get_next_hob(const struct hob_header *hdr)
{
- return (void *)(*(u8 **)&(hob) + get_hob_length(hob));
+ return (const struct hob_header *)((u32)hdr + hdr->len);
}
/**
@@ -243,14 +204,14 @@ static inline void *get_next_hob(union hob_pointers hob)
* HOB list. If hob is last HOB in the HOB list, then true is returned.
* Otherwise, false is returned.
*
- * @hob: A pointer to a HOB.
+ * @hdr: A pointer to a HOB.
*
- * @retval true: The HOB specified by hob is the last HOB in the HOB list.
- * @retval false: The HOB specified by hob is not the last HOB in the HOB list.
+ * @retval true: The HOB specified by hdr is the last HOB in the HOB list.
+ * @retval false: The HOB specified by hdr is not the last HOB in the HOB list.
*/
-static inline bool end_of_hob(union hob_pointers hob)
+static inline bool end_of_hob(const struct hob_header *hdr)
{
- return get_hob_type(hob) == HOB_TYPE_EOH;
+ return hdr->type == HOB_TYPE_EOH;
}
/**
@@ -260,13 +221,13 @@ static inline bool end_of_hob(union hob_pointers hob)
* This macro returns a pointer to the data buffer in a HOB specified by hob.
* hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
*
- * @hob: A pointer to a HOB.
+ * @hdr: A pointer to a HOB.
*
* @return: A pointer to the data buffer in a HOB.
*/
-static inline void *get_guid_hob_data(u8 *hob)
+static inline void *get_guid_hob_data(const struct hob_header *hdr)
{
- return (void *)(hob + sizeof(struct hob_guid));
+ return (void *)((u32)hdr + sizeof(struct hob_guid));
}
/**
@@ -276,14 +237,13 @@ static inline void *get_guid_hob_data(u8 *hob)
* This macro returns the size, in bytes, of the data buffer in a HOB
* specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
*
- * @hob: A pointer to a HOB.
+ * @hdr: A pointer to a HOB.
*
* @return: The size of the data buffer.
*/
-static inline u16 get_guid_hob_data_size(u8 *hob)
+static inline u16 get_guid_hob_data_size(const struct hob_header *hdr)
{
- union hob_pointers hob_p = *(union hob_pointers *)hob;
- return get_hob_length(hob_p) - sizeof(struct hob_guid);
+ return hdr->len - sizeof(struct hob_guid);
}
/* FSP specific GUID HOB definitions */
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h
index 3ae1b663b9..ebdbd03435 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h
+++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h
@@ -145,7 +145,7 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len);
*
* @retval: A HOB object with matching type; Otherwise NULL.
*/
-void *fsp_get_next_hob(u16 type, const void *hob_list);
+const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list);
/**
* Returns the next instance of the matched GUID HOB from the starting HOB.
@@ -155,7 +155,8 @@ void *fsp_get_next_hob(u16 type, const void *hob_list);
*
* @retval: A HOB object with matching GUID; Otherwise NULL.
*/
-void *fsp_get_next_guid_hob(const struct efi_guid *guid, const void *hob_list);
+const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
+ const void *hob_list);
/**
* This function retrieves a GUID HOB data buffer and size.
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 03d491a17f..24e305239b 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -29,6 +29,19 @@ struct memory_info {
struct memory_area area[CONFIG_NR_DRAM_BANKS];
};
+#define MAX_MTRR_REQUESTS 8
+
+/**
+ * A request for a memory region to be set up in a particular way. These
+ * requests are processed before board_init_r() is called. They are generally
+ * optional and can be ignored with some performance impact.
+ */
+struct mtrr_request {
+ int type; /* MTRR_TYPE_... */
+ uint64_t start;
+ uint64_t size;
+};
+
/* Architecture-specific global data */
struct arch_global_data {
struct global_data *gd_addr; /* Location of Global Data */
@@ -43,13 +56,14 @@ struct arch_global_data {
uint32_t tsc_mhz; /* TSC frequency in MHz */
void *new_fdt; /* Relocated FDT */
uint32_t bist; /* Built-in self test value */
- struct pci_controller *hose; /* PCI hose for early use */
enum pei_boot_mode_t pei_boot_mode;
const struct pch_gpio_map *gpio_map; /* board GPIO map */
struct memory_info meminfo; /* Memory information */
#ifdef CONFIG_HAVE_FSP
void *hob_list; /* FSP HOB list */
#endif
+ struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
+ int mtrr_req_count;
};
#endif
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 5f05a4848f..3c1174043c 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -9,99 +9,86 @@
#ifndef _ASM_MTRR_H
#define _ASM_MTRR_H
-/* These are the region types */
-#define MTRR_TYPE_UNCACHEABLE 0
-#define MTRR_TYPE_WRCOMB 1
-/*#define MTRR_TYPE_ 2*/
-/*#define MTRR_TYPE_ 3*/
-#define MTRR_TYPE_WRTHROUGH 4
-#define MTRR_TYPE_WRPROT 5
-#define MTRR_TYPE_WRBACK 6
-#define MTRR_NUM_TYPES 7
-
-#define MTRRcap_MSR 0x0fe
-#define MTRRdefType_MSR 0x2ff
-
-#define MTRRdefTypeEn (1 << 11)
-#define MTRRdefTypeFixEn (1 << 10)
-
-#define SMRRphysBase_MSR 0x1f2
-#define SMRRphysMask_MSR 0x1f3
-
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
-
-#define MTRRphysMaskValid (1 << 11)
-
-#define NUM_FIXED_RANGES 88
-#define RANGES_PER_FIXED_MTRR 8
-#define MTRRfix64K_00000_MSR 0x250
-#define MTRRfix16K_80000_MSR 0x258
-#define MTRRfix16K_A0000_MSR 0x259
-#define MTRRfix4K_C0000_MSR 0x268
-#define MTRRfix4K_C8000_MSR 0x269
-#define MTRRfix4K_D0000_MSR 0x26a
-#define MTRRfix4K_D8000_MSR 0x26b
-#define MTRRfix4K_E0000_MSR 0x26c
-#define MTRRfix4K_E8000_MSR 0x26d
-#define MTRRfix4K_F0000_MSR 0x26e
-#define MTRRfix4K_F8000_MSR 0x26f
+/* MTRR region types */
+#define MTRR_TYPE_UNCACHEABLE 0
+#define MTRR_TYPE_WRCOMB 1
+#define MTRR_TYPE_WRTHROUGH 4
+#define MTRR_TYPE_WRPROT 5
+#define MTRR_TYPE_WRBACK 6
+
+#define MTRR_TYPE_COUNT 7
+
+#define MTRR_CAP_MSR 0x0fe
+#define MTRR_DEF_TYPE_MSR 0x2ff
+
+#define MTRR_DEF_TYPE_EN (1 << 11)
+#define MTRR_DEF_TYPE_FIX_EN (1 << 10)
+
+#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
+#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+#define MTRR_PHYS_MASK_VALID (1 << 11)
+
+#define MTRR_BASE_TYPE_MASK 0x7
+
+/* Number of MTRRs supported */
+#define MTRR_COUNT 8
#if !defined(__ASSEMBLER__)
-/*
- * The MTRR code has some side effects that the callers should be aware for.
- * 1. The call sequence matters. x86_setup_mtrrs() calls
- * x86_setup_fixed_mtrrs_no_enable() then enable_fixed_mtrrs() (equivalent
- * of x86_setup_fixed_mtrrs()) then x86_setup_var_mtrrs(). If the callers
- * want to call the components of x86_setup_mtrrs() because of other
- * rquirements the ordering should still preserved.
- * 2. enable_fixed_mtrr() will enable both variable and fixed MTRRs because
- * of the nature of the global MTRR enable flag. Therefore, all direct
- * or indirect callers of enable_fixed_mtrr() should ensure that the
- * variable MTRR MSRs do not contain bad ranges.
- * 3. If CONFIG_CACHE_ROM is selected an MTRR is allocated for enabling
- * the caching of the ROM. However, it is set to uncacheable (UC). It
- * is the responsiblity of the caller to enable it by calling
- * x86_mtrr_enable_rom_caching().
+/**
+ * Information about the previous MTRR state, set up by mtrr_open()
+ *
+ * @deftype: Previous value of MTRR_DEF_TYPE_MSR
+ * @enable_cache: true if cache was enabled
*/
-void x86_setup_mtrrs(void);
-/*
- * x86_setup_var_mtrrs() parameters:
- * address_bits - number of physical address bits supported by cpu
- * above4gb - 2 means dynamically detect number of variable MTRRs available.
- * non-zero means handle memory ranges above 4GiB.
- * 0 means ignore memory ranges above 4GiB
+struct mtrr_state {
+ uint64_t deftype;
+ bool enable_cache;
+};
+
+/**
+ * mtrr_open() - Prepare to adjust MTRRs
+ *
+ * Use mtrr_open() passing in a structure - this function will init it. Then
+ * when done, pass the same structure to mtrr_close() to re-enable MTRRs and
+ * possibly the cache.
+ *
+ * @state: Empty structure to pass in to hold settings
*/
-void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb);
-void enable_fixed_mtrr(void);
-void x86_setup_fixed_mtrrs(void);
-/* Set up fixed MTRRs but do not enable them. */
-void x86_setup_fixed_mtrrs_no_enable(void);
-int x86_mtrr_check(void);
-/* ROM caching can be used after variable MTRRs are set up. Beware that
- * enabling CONFIG_CACHE_ROM will eat through quite a few MTRRs based on
- * one's IO hole size and WRCOMB resources. Be sure to check the console
- * log when enabling CONFIG_CACHE_ROM or adding WRCOMB resources. Beware that
- * on CPUs with core-scoped MTRR registers such as hyperthreaded CPUs the
- * rom caching will be disabled if all threads run the MTRR code. Therefore,
- * one needs to call x86_mtrr_enable_rom_caching() after all threads of the
- * same core have run the MTRR code. */
-#if CONFIG_CACHE_ROM
-void x86_mtrr_enable_rom_caching(void);
-void x86_mtrr_disable_rom_caching(void);
-/* Return the variable range MTRR index of the ROM cache. */
-long x86_mtrr_rom_cache_var_index(void);
-#else
-static inline void x86_mtrr_enable_rom_caching(void) {}
-static inline void x86_mtrr_disable_rom_caching(void) {}
-static inline long x86_mtrr_rom_cache_var_index(void) { return -1; }
-#endif /* CONFIG_CACHE_ROM */
+void mtrr_open(struct mtrr_state *state);
-#endif
+/**
+ * mtrr_open() - Clean up after adjusting MTRRs, and enable them
+ *
+ * This uses the structure containing information returned from mtrr_open().
+ *
+ * @state: Structure from mtrr_open()
+ */
+/* */
+void mtrr_close(struct mtrr_state *state);
+
+/**
+ * mtrr_add_request() - Add a new MTRR request
+ *
+ * This adds a request for a memory region to be set up in a particular way.
+ *
+ * @type: Requested type (MTRR_TYPE_)
+ * @start: Start address
+ * @size: Size
+ */
+int mtrr_add_request(int type, uint64_t start, uint64_t size);
+
+/**
+ * mtrr_commit() - set up the MTRR registers based on current requests
+ *
+ * This sets up MTRRs for the available DRAM and the requests received so far.
+ * It must be called with caches disabled.
+ *
+ * @do_caches: true if caches are currently on
+ */
+int mtrr_commit(bool do_caches);
-#if !defined(CONFIG_RAMTOP)
-# error "CONFIG_RAMTOP not defined"
#endif
#if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0)
@@ -114,8 +101,4 @@ static inline long x86_mtrr_rom_cache_var_index(void) { return -1; }
#define CACHE_ROM_BASE (((1 << 20) - (CONFIG_CACHE_ROM_SIZE >> 12)) << 12)
-#if (CONFIG_RAMTOP & (CONFIG_RAMTOP - 1)) != 0
-# error "CONFIG_RAMTOP must be a power of 2"
-#endif
-
#endif
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index ac1a808307..c30dd4c218 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -29,7 +29,7 @@ void board_pci_setup_hose(struct pci_controller *hose);
* pci_early_init_hose() - Set up PCI host before relocation
*
* This allocates memory for, sets up and returns the PCI hose. It can be
- * called before relocation. The hose will be stored in gd->arch.hose for
+ * called before relocation. The hose will be stored in gd->hose for
* later use, but will become invalid one DRAM is available.
*/
int pci_early_init_hose(struct pci_controller **hosep);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 73262d7263..32d7b98fa6 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_HAVE_FSP) += cmd_hob.o
obj-y += gcc.o
obj-y += init_helpers.o
obj-y += interrupts.o
+obj-y += cmd_mtrr.o
obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o
obj-$(CONFIG_PCI) += pci_type1.o
diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c
index d1f8933e12..1d75cfc263 100644
--- a/arch/x86/lib/bios.c
+++ b/arch/x86/lib/bios.c
@@ -207,12 +207,14 @@ static u8 vbe_get_mode_info(struct vbe_mode_info *mi)
static u8 vbe_set_mode(struct vbe_mode_info *mi)
{
- debug("VBE: Setting VESA mode %#04x\n", mi->video_mode);
+ int video_mode = mi->video_mode;
+
+ debug("VBE: Setting VESA mode %#04x\n", video_mode);
/* request linear framebuffer mode */
- mi->video_mode |= (1 << 14);
- /* request clearing of framebuffer */
- mi->video_mode &= ~(1 << 15);
- realmode_interrupt(0x10, VESA_SET_MODE, mi->video_mode,
+ video_mode |= (1 << 14);
+ /* don't clear the framebuffer, we do that later */
+ video_mode |= (1 << 15);
+ realmode_interrupt(0x10, VESA_SET_MODE, video_mode,
0x0000, 0x0000, 0x0000, 0x0000);
return 0;
@@ -236,6 +238,7 @@ static void vbe_set_graphics(int vesa_mode, struct vbe_mode_info *mode_info)
return;
}
+ mode_info->video_mode &= 0x3ff;
vbe_set_mode(mode_info);
}
@@ -262,7 +265,6 @@ void bios_run_on_x86(pci_dev_t pcidev, unsigned long addr, int vesa_mode,
/* Make sure the code is placed. */
setup_realmode_code();
- disable_caches();
debug("Calling Option ROM at %lx, pci device %#x...", addr, num_dev);
/* Option ROM entry point is at OPROM start + 3 */
diff --git a/arch/x86/lib/cmd_hob.c b/arch/x86/lib/cmd_hob.c
index b552fe6c1b..a0ef037da1 100644
--- a/arch/x86/lib/cmd_hob.c
+++ b/arch/x86/lib/cmd_hob.c
@@ -28,20 +28,20 @@ static char *hob_type[] = {
int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- union hob_pointers hob;
- u16 type;
+ const struct hob_header *hdr;
+ uint type;
char *desc;
int i = 0;
- hob.raw = (u8 *)gd->arch.hob_list;
+ hdr = gd->arch.hob_list;
- printf("HOB list address: 0x%08x\n\n", (unsigned int)hob.raw);
+ printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
printf("No. | Address | Type | Length in Bytes\n");
printf("----|----------|---------------------|----------------\n");
- while (!end_of_hob(hob)) {
- printf("%-3d | %08x | ", i, (unsigned int)hob.raw);
- type = get_hob_type(hob);
+ while (!end_of_hob(hdr)) {
+ printf("%-3d | %08x | ", i, (unsigned int)hdr);
+ type = hdr->type;
if (type == HOB_TYPE_UNUSED)
desc = "*Unused*";
else if (type == HOB_TYPE_EOH)
@@ -50,8 +50,8 @@ int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
desc = hob_type[type];
else
desc = "*Invalid Type*";
- printf("%-19s | %-15d\n", desc, get_hob_length(hob));
- hob.raw = get_next_hob(hob);
+ printf("%-19s | %-15d\n", desc, hdr->len);
+ hdr = get_next_hob(hdr);
i++;
}
diff --git a/arch/x86/lib/cmd_mtrr.c b/arch/x86/lib/cmd_mtrr.c
new file mode 100644
index 0000000000..7e0506b75d
--- /dev/null
+++ b/arch/x86/lib/cmd_mtrr.c
@@ -0,0 +1,138 @@
+/*
+ * (C) Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+
+static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
+ "Uncacheable",
+ "Combine",
+ "2",
+ "3",
+ "Through",
+ "Protect",
+ "Back",
+};
+
+static int do_mtrr_list(void)
+{
+ int i;
+
+ printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||",
+ "Mask ||", "Size ||");
+ for (i = 0; i < MTRR_COUNT; i++) {
+ const char *type = "Invalid";
+ uint64_t base, mask, size;
+ bool valid;
+
+ base = native_read_msr(MTRR_PHYS_BASE_MSR(i));
+ mask = native_read_msr(MTRR_PHYS_MASK_MSR(i));
+ size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
+ size |= (1 << 12) - 1;
+ size += 1;
+ 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);
+ }
+
+ return 0;
+}
+
+static int do_mtrr_set(uint reg, int argc, char * const argv[])
+{
+ const char *typename = argv[0];
+ struct mtrr_state state;
+ uint32_t start, size;
+ uint64_t base, mask;
+ int i, type = -1;
+ bool valid;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+ for (i = 0; i < MTRR_TYPE_COUNT; i++) {
+ if (*typename == *mtrr_type_name[i])
+ type = i;
+ }
+ if (type == -1) {
+ printf("Invalid type name %s\n", typename);
+ return CMD_RET_USAGE;
+ }
+ start = simple_strtoul(argv[1], NULL, 16);
+ size = simple_strtoul(argv[2], NULL, 16);
+
+ base = start | type;
+ valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID;
+ mask = ~((uint64_t)size - 1);
+ mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+ if (valid)
+ mask |= MTRR_PHYS_MASK_VALID;
+
+ printf("base=%llx, mask=%llx\n", base, mask);
+ mtrr_open(&state);
+ wrmsrl(MTRR_PHYS_BASE_MSR(reg), base);
+ wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
+ mtrr_close(&state);
+
+ return 0;
+}
+
+static int mtrr_set_valid(int reg, bool valid)
+{
+ struct mtrr_state state;
+ uint64_t mask;
+
+ mtrr_open(&state);
+ mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg));
+ if (valid)
+ mask |= MTRR_PHYS_MASK_VALID;
+ else
+ mask &= ~MTRR_PHYS_MASK_VALID;
+ wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
+ mtrr_close(&state);
+
+ return 0;
+}
+
+static int do_mtrr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ const char *cmd;
+ uint reg;
+
+ cmd = argv[1];
+ if (argc < 2 || *cmd == 'l')
+ return do_mtrr_list();
+ argc -= 2;
+ argv += 2;
+ if (argc <= 0)
+ return CMD_RET_USAGE;
+ reg = simple_strtoul(argv[0], NULL, 16);
+ if (reg >= MTRR_COUNT) {
+ printf("Invalid register number\n");
+ return CMD_RET_USAGE;
+ }
+ if (*cmd == 'e')
+ return mtrr_set_valid(reg, true);
+ else if (*cmd == 'd')
+ return mtrr_set_valid(reg, false);
+ else if (*cmd == 's')
+ return do_mtrr_set(reg, argc - 1, argv + 1);
+ else
+ return CMD_RET_USAGE;
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ mtrr, 6, 1, do_mtrr,
+ "Use x86 memory type range registers (32-bit only)",
+ "[list] - list current registers\n"
+ "set <reg> <type> <start> <size> - set a register\n"
+ "\t<type> is Uncacheable, Combine, Through, Protect, Back\n"
+ "disable <reg> - disable a register\n"
+ "ensable <reg> - enable a register"
+);
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index be4eb12c53..fc211d9d5c 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <fdtdec.h>
#include <spi.h>
+#include <asm/mtrr.h>
#include <asm/sections.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -66,6 +67,13 @@ int calculate_relocation_address(void)
int init_cache_f_r(void)
{
+#if defined(CONFIG_X86_RESET_VECTOR) & !defined(CONFIG_HAVE_FSP)
+ int ret;
+
+ ret = mtrr_commit(false);
+ if (ret)
+ return ret;
+#endif
/* Initialise the CPU cache(s) */
return init_cache();
}
diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c
index fb9afed18f..7f5ba2ca6f 100644
--- a/arch/x86/lib/tsc_timer.c
+++ b/arch/x86/lib/tsc_timer.c
@@ -78,7 +78,7 @@ static int match_cpu(u8 family, u8 model)
*
* Returns the calibration value or 0 if MSR calibration failed.
*/
-static unsigned long try_msr_calibrate_tsc(void)
+static unsigned long __maybe_unused try_msr_calibrate_tsc(void)
{
u32 lo, hi, ratio, freq_id, freq;
unsigned long res;
@@ -199,7 +199,7 @@ static inline int pit_expect_msb(unsigned char val, u64 *tscp,
#define MAX_QUICK_PIT_MS 50
#define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
-static unsigned long quick_pit_calibrate(void)
+static unsigned long __maybe_unused quick_pit_calibrate(void)
{
int i;
u64 tsc, delta;
@@ -306,6 +306,9 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
if (gd->arch.tsc_mhz)
return gd->arch.tsc_mhz;
+#ifdef CONFIG_TSC_CALIBRATION_BYPASS
+ fast_calibrate = CONFIG_TSC_FREQ_IN_MHZ;
+#else
fast_calibrate = try_msr_calibrate_tsc();
if (!fast_calibrate) {
@@ -313,6 +316,7 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
if (!fast_calibrate)
panic("TSC frequency is ZERO");
}
+#endif
gd->arch.tsc_mhz = fast_calibrate;
return fast_calibrate;