diff options
Diffstat (limited to 'arch')
78 files changed, 2715 insertions, 3236 deletions
diff --git a/arch/arm/cpu/arm926ejs/kirkwood/Kconfig b/arch/arm/cpu/arm926ejs/kirkwood/Kconfig index 6c037a1..45c6687 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 3b6ae47..1720f7d 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 9b3e80c..bc98c56 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 8e949c6..d7a7040 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 41b9add..b6cb9de 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 ec8aaa7..c736fa3 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 699173c..5dbbf61 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, ¶); - mctl_dll_init(1, ¶); + setbits_le32(&mctl_com->ccr, MCTL_CCR_CH0_CLK_EN); + + if (para.chan == 2) { + mctl_dll_init(1, ¶); + 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, ¶); - mctl_channel_init(1, ¶); + if (para.chan == 2) + mctl_channel_init(1, ¶); + mctl_com_init(¶); 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 0000000..3d7964d --- /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 48613bd..26a9cfc 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 b9ea78b..5be497b 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 0000000..b72bb9d --- /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 0000000..14de9f9 --- /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 4b3ee6e..9c6e824 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 64acff3..505c363 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 eb88969..84a9a2b 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 3599054..4711260 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 2c92b5c..82b3d46 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 ddb71c1..2ac8a87 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 9072e68..7ff43e6 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 0000000..06adee2 --- /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 366c0dc..71cc879 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 88de1ff..82ed541 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 0000000..95a595a --- /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 0000000..8d20973 --- /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 5374b4d..78c98ed 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/Kconfig b/arch/powerpc/Kconfig index 7a50301..8e5a3e2 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -7,9 +7,6 @@ config SYS_ARCH choice prompt "CPU select" -config 74xx_7xx - bool "74xx" - config MPC512X bool "MPC512X" @@ -39,7 +36,6 @@ config 4xx endchoice -source "arch/powerpc/cpu/74xx_7xx/Kconfig" source "arch/powerpc/cpu/mpc512x/Kconfig" source "arch/powerpc/cpu/mpc5xx/Kconfig" source "arch/powerpc/cpu/mpc5xxx/Kconfig" diff --git a/arch/powerpc/cpu/74xx_7xx/Kconfig b/arch/powerpc/cpu/74xx_7xx/Kconfig deleted file mode 100644 index b2f1a59..0000000 --- a/arch/powerpc/cpu/74xx_7xx/Kconfig +++ /dev/null @@ -1,32 +0,0 @@ -menu "74xx_7xx CPU" - depends on 74xx_7xx - -config SYS_CPU - default "74xx_7xx" - -choice - prompt "Target select" - -config TARGET_P3G4 - bool "Support P3G4" - -config TARGET_ZUMA - bool "Support ZUMA" - -config TARGET_PPMC7XX - bool "Support ppmc7xx" - -config TARGET_ELPPC - bool "Support ELPPC" - -config TARGET_MPC7448HPC2 - bool "Support mpc7448hpc2" - -endchoice - -source "board/eltec/elppc/Kconfig" -source "board/evb64260/Kconfig" -source "board/freescale/mpc7448hpc2/Kconfig" -source "board/ppmc7xx/Kconfig" - -endmenu diff --git a/arch/powerpc/cpu/74xx_7xx/Makefile b/arch/powerpc/cpu/74xx_7xx/Makefile deleted file mode 100644 index f31fe75..0000000 --- a/arch/powerpc/cpu/74xx_7xx/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# (C) Copyright 2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# (C) Copyright 2001 -# Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -extra-y = start.o -obj-y = cache.o kgdb.o io.o -obj-y += traps.o cpu.o cpu_init.o speed.o interrupts.o diff --git a/arch/powerpc/cpu/74xx_7xx/cache.S b/arch/powerpc/cpu/74xx_7xx/cache.S deleted file mode 100644 index 66c7298..0000000 --- a/arch/powerpc/cpu/74xx_7xx/cache.S +++ /dev/null @@ -1,404 +0,0 @@ -#include <config.h> -#include <74xx_7xx.h> -#include <version.h> - -#include <ppc_asm.tmpl> -#include <ppc_defs.h> - -#include <asm/cache.h> -#include <asm/mmu.h> - -#ifndef CACHE_LINE_SIZE -# define CACHE_LINE_SIZE L1_CACHE_BYTES -#endif - -#if CACHE_LINE_SIZE == 128 -#define LG_CACHE_LINE_SIZE 7 -#elif CACHE_LINE_SIZE == 32 -#define LG_CACHE_LINE_SIZE 5 -#elif CACHE_LINE_SIZE == 16 -#define LG_CACHE_LINE_SIZE 4 -#elif CACHE_LINE_SIZE == 8 -#define LG_CACHE_LINE_SIZE 3 -#else -# error "Invalid cache line size!" -#endif - -/* - * Invalidate L1 instruction cache. - */ -_GLOBAL(invalidate_l1_instruction_cache) - mfspr r3,PVR - rlwinm r3,r3,16,16,31 - cmpi 0,r3,1 - beqlr /* for 601, do nothing */ - /* 603/604 processor - use invalidate-all bit in HID0 */ - mfspr r3,HID0 - ori r3,r3,HID0_ICFI - mtspr HID0,r3 - isync - blr - -/* - * Invalidate L1 data cache. - */ -_GLOBAL(invalidate_l1_data_cache) - mfspr r3,HID0 - ori r3,r3,HID0_DCFI - mtspr HID0,r3 - isync - blr - -/* - * Flush data cache. - */ -_GLOBAL(flush_dcache) - lis r3,0 - lis r5,CACHE_LINE_SIZE -flush: - cmp 0,1,r3,r5 - bge done - lwz r5,0(r3) - lis r5,CACHE_LINE_SIZE - addi r3,r3,0x4 - b flush -done: - blr -/* - * Write any modified data cache blocks out to memory - * and invalidate the corresponding instruction cache blocks. - * This is a no-op on the 601. - * - * flush_icache_range(unsigned long start, unsigned long stop) - */ -_GLOBAL(flush_icache_range) - mfspr r5,PVR - rlwinm r5,r5,16,16,31 - cmpi 0,r5,1 - beqlr /* for 601, do nothing */ - li r5,CACHE_LINE_SIZE-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,LG_CACHE_LINE_SIZE - beqlr - mtctr r4 - mr r6,r3 -1: dcbst 0,r3 - addi r3,r3,CACHE_LINE_SIZE - bdnz 1b - sync /* wait for dcbst's to get to ram */ - mtctr r4 -2: icbi 0,r6 - addi r6,r6,CACHE_LINE_SIZE - bdnz 2b - sync /* additional sync needed on g4 */ - isync - blr -/* - * Write any modified data cache blocks out to memory. - * Does not invalidate the corresponding cache lines (especially for - * any corresponding instruction cache). - * - * clean_dcache_range(unsigned long start, unsigned long stop) - */ -_GLOBAL(clean_dcache_range) - li r5,CACHE_LINE_SIZE-1 - andc r3,r3,r5 /* align r3 down to cache line */ - subf r4,r3,r4 /* r4 = offset of stop from start of cache line */ - add r4,r4,r5 /* r4 += cache_line_size-1 */ - srwi. r4,r4,LG_CACHE_LINE_SIZE /* r4 = number of cache lines to flush */ - beqlr /* if r4 == 0 return */ - mtctr r4 /* ctr = r4 */ - - sync -1: dcbst 0,r3 - addi r3,r3,CACHE_LINE_SIZE - bdnz 1b - sync /* wait for dcbst's to get to ram */ - blr - -/* - * Write any modified data cache blocks out to memory - * and invalidate the corresponding instruction cache blocks. - * - * flush_dcache_range(unsigned long start, unsigned long stop) - */ -_GLOBAL(flush_dcache_range) - li r5,CACHE_LINE_SIZE-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,LG_CACHE_LINE_SIZE - beqlr - mtctr r4 - - sync -1: dcbf 0,r3 - addi r3,r3,CACHE_LINE_SIZE - bdnz 1b - sync /* wait for dcbf's to get to ram */ - blr - -/* - * Like above, but invalidate the D-cache. This is used by the 8xx - * to invalidate the cache so the PPC core doesn't get stale data - * from the CPM (no cache snooping here :-). - * - * invalidate_dcache_range(unsigned long start, unsigned long stop) - */ -_GLOBAL(invalidate_dcache_range) - li r5,CACHE_LINE_SIZE-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,LG_CACHE_LINE_SIZE - beqlr - mtctr r4 - - sync -1: dcbi 0,r3 - addi r3,r3,CACHE_LINE_SIZE - bdnz 1b - sync /* wait for dcbi's to get to ram */ - blr - -/* - * Flush a particular page from the data cache to RAM. - * Note: this is necessary because the instruction cache does *not* - * snoop from the data cache. - * This is a no-op on the 601 which has a unified cache. - * - * void __flush_page_to_ram(void *page) - */ -_GLOBAL(__flush_page_to_ram) - mfspr r5,PVR - rlwinm r5,r5,16,16,31 - cmpi 0,r5,1 - beqlr /* for 601, do nothing */ - rlwinm r3,r3,0,0,19 /* Get page base address */ - li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */ - mtctr r4 - mr r6,r3 -0: dcbst 0,r3 /* Write line to ram */ - addi r3,r3,CACHE_LINE_SIZE - bdnz 0b - sync - mtctr r4 -1: icbi 0,r6 - addi r6,r6,CACHE_LINE_SIZE - bdnz 1b - sync - isync - blr - -/* - * Flush a particular page from the instruction cache. - * Note: this is necessary because the instruction cache does *not* - * snoop from the data cache. - * This is a no-op on the 601 which has a unified cache. - * - * void __flush_icache_page(void *page) - */ -_GLOBAL(__flush_icache_page) - mfspr r5,PVR - rlwinm r5,r5,16,16,31 - cmpi 0,r5,1 - beqlr /* for 601, do nothing */ - li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */ - mtctr r4 -1: icbi 0,r3 - addi r3,r3,CACHE_LINE_SIZE - bdnz 1b - sync - isync - blr - -/* - * Clear a page using the dcbz instruction, which doesn't cause any - * memory traffic (except to write out any cache lines which get - * displaced). This only works on cacheable memory. - */ -_GLOBAL(clear_page) - li r0,4096/CACHE_LINE_SIZE - mtctr r0 -1: dcbz 0,r3 - addi r3,r3,CACHE_LINE_SIZE - bdnz 1b - blr - -/* - * Enable L1 Instruction cache - */ -_GLOBAL(icache_enable) - mfspr r3, HID0 - li r5, HID0_ICFI|HID0_ILOCK - andc r3, r3, r5 - ori r3, r3, HID0_ICE - ori r5, r3, HID0_ICFI - mtspr HID0, r5 - mtspr HID0, r3 - isync - blr - -/* - * Disable L1 Instruction cache - */ -_GLOBAL(icache_disable) - mflr r4 - bl invalidate_l1_instruction_cache /* uses r3 */ - sync - mtlr r4 - mfspr r3, HID0 - li r5, 0 - ori r5, r5, HID0_ICE - andc r3, r3, r5 - mtspr HID0, r3 - isync - blr - -/* - * Is instruction cache enabled? - */ -_GLOBAL(icache_status) - mfspr r3, HID0 - andi. r3, r3, HID0_ICE - blr - - -_GLOBAL(l1dcache_enable) - mfspr r3, HID0 - li r5, HID0_DCFI|HID0_DLOCK - andc r3, r3, r5 - mtspr HID0, r3 /* no invalidate, unlock */ - ori r3, r3, HID0_DCE - ori r5, r3, HID0_DCFI - mtspr HID0, r5 /* enable + invalidate */ - mtspr HID0, r3 /* enable */ - sync - blr - -/* - * Enable data cache(s) - L1 and optionally L2 - * Calls l2cache_enable. LR saved in r5 - */ -_GLOBAL(dcache_enable) - mfspr r3, HID0 - li r5, HID0_DCFI|HID0_DLOCK - andc r3, r3, r5 - mtspr HID0, r3 /* no invalidate, unlock */ - ori r3, r3, HID0_DCE - ori r5, r3, HID0_DCFI - mtspr HID0, r5 /* enable + invalidate */ - mtspr HID0, r3 /* enable */ - sync -#ifdef CONFIG_SYS_L2 - mflr r5 - bl l2cache_enable /* uses r3 and r4 */ - sync - mtlr r5 -#endif - blr - - -/* - * Disable data cache(s) - L1 and optionally L2 - * Calls flush_dcache and l2cache_disable_no_flush. - * LR saved in r4 - */ -_GLOBAL(dcache_disable) - mflr r4 /* save link register */ - bl flush_dcache /* uses r3 and r5 */ - sync - mfspr r3, HID0 - li r5, HID0_DCFI|HID0_DLOCK - andc r3, r3, r5 - mtspr HID0, r3 /* no invalidate, unlock */ - li r5, HID0_DCE|HID0_DCFI - andc r3, r3, r5 /* no enable, no invalidate */ - mtspr HID0, r3 - sync -#ifdef CONFIG_SYS_L2 - bl l2cache_disable_no_flush /* uses r3 */ -#endif - mtlr r4 /* restore link register */ - blr - -/* - * Is data cache enabled? - */ -_GLOBAL(dcache_status) - mfspr r3, HID0 - andi. r3, r3, HID0_DCE - blr - -/* - * Invalidate L2 cache using L2I and polling L2IP or L2I - */ -_GLOBAL(l2cache_invalidate) - sync - mfspr r3, l2cr - oris r3, r3, L2CR_L2I@h - sync - mtspr l2cr, r3 - sync - mfspr r3, PVR - sync - rlwinm r3, r3, 16,16,31 - cmpli 0,r3,0x8000 /* 7451, 7441 */ - beq 0,inv_7450 - cmpli 0,r3,0x8001 /* 7455, 7445 */ - beq 0,inv_7450 - cmpli 0,r3,0x8002 /* 7457, 7447 */ - beq 0,inv_7450 - cmpli 0,r3,0x8003 /* 7447A */ - beq 0,inv_7450 - cmpli 0,r3,0x8004 /* 7448 */ - beq 0,inv_7450 -invl2: - mfspr r3, l2cr - andi. r3, r3, L2CR_L2IP - bne invl2 - /* turn off the global invalidate bit */ - mfspr r3, l2cr - rlwinm r3, r3, 0, 11, 9 - sync - mtspr l2cr, r3 - sync - blr -inv_7450: - mfspr r3, l2cr - andis. r3, r3, L2CR_L2I@h - bne inv_7450 - blr - -/* - * Enable L2 cache - * Calls l2cache_invalidate. LR is saved in r4 - */ -_GLOBAL(l2cache_enable) - mflr r4 /* save link register */ - bl l2cache_invalidate /* uses r3 */ - sync - lis r3, L2_ENABLE@h - ori r3, r3, L2_ENABLE@l - mtspr l2cr, r3 - isync - mtlr r4 /* restore link register */ - blr - -/* - * Disable L2 cache - * Calls flush_dcache. LR is saved in r4 - */ -_GLOBAL(l2cache_disable) - mflr r4 /* save link register */ - bl flush_dcache /* uses r3 and r5 */ - sync - mtlr r4 /* restore link register */ -l2cache_disable_no_flush: /* provide way to disable L2 w/o flushing */ - lis r3, L2_INIT@h - ori r3, r3, L2_INIT@l - mtspr l2cr, r3 - isync - blr diff --git a/arch/powerpc/cpu/74xx_7xx/config.mk b/arch/powerpc/cpu/74xx_7xx/config.mk deleted file mode 100644 index 4cd1a26..0000000 --- a/arch/powerpc/cpu/74xx_7xx/config.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -# (C) Copyright 2001 -# Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -PLATFORM_CPPFLAGS += -mstring diff --git a/arch/powerpc/cpu/74xx_7xx/cpu.c b/arch/powerpc/cpu/74xx_7xx/cpu.c deleted file mode 100644 index 6cd54bf..0000000 --- a/arch/powerpc/cpu/74xx_7xx/cpu.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * (C) Copyright 2001 - * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * cpu.c - * - * CPU specific code - * - * written or collected and sometimes rewritten by - * Magnus Damm <damm@bitsmart.com> - * - * minor modifications by - * Wolfgang Denk <wd@denx.de> - * - * more modifications by - * Josh Huber <huber@mclx.com> - * added support for the 74xx series of cpus - * added support for the 7xx series of cpus - * made the code a little less hard-coded, and more auto-detectish - */ - -#include <common.h> -#include <command.h> -#include <74xx_7xx.h> -#include <asm/cache.h> - -#if defined(CONFIG_OF_LIBFDT) -#include <libfdt.h> -#include <fdt_support.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -cpu_t -get_cpu_type(void) -{ - uint pvr = get_pvr(); - cpu_t type; - - type = CPU_UNKNOWN; - - switch (PVR_VER(pvr)) { - case 0x000c: - type = CPU_7400; - break; - case 0x0008: - type = CPU_750; - - if (((pvr >> 8) & 0xff) == 0x01) { - type = CPU_750CX; /* old CX (80100 and 8010x?)*/ - } else if (((pvr >> 8) & 0xff) == 0x22) { - type = CPU_750CX; /* CX (82201,82202) and CXe (82214) */ - } else if (((pvr >> 8) & 0xff) == 0x33) { - type = CPU_750CX; /* CXe (83311) */ - } else if (((pvr >> 12) & 0xF) == 0x3) { - type = CPU_755; - } - break; - - case 0x7000: - type = CPU_750FX; - break; - - case 0x7002: - type = CPU_750GX; - break; - - case 0x800C: - type = CPU_7410; - break; - - case 0x8000: - type = CPU_7450; - break; - - case 0x8001: - type = CPU_7455; - break; - - case 0x8002: - type = CPU_7457; - break; - - case 0x8003: - type = CPU_7447A; - break; - - case 0x8004: - type = CPU_7448; - break; - - default: - break; - } - - return type; -} - -/* ------------------------------------------------------------------------- */ - -#if !defined(CONFIG_BAB7xx) -int checkcpu (void) -{ - uint type = get_cpu_type(); - uint pvr = get_pvr(); - ulong clock = gd->cpu_clk; - char buf[32]; - char *str; - - puts ("CPU: "); - - switch (type) { - case CPU_750CX: - printf ("750CX%s v%d.%d", (pvr&0xf0)?"e":"", - (pvr>>8) & 0xf, - pvr & 0xf); - goto PR_CLK; - - case CPU_750: - str = "750"; - break; - - case CPU_750FX: - str = "750FX"; - break; - - case CPU_750GX: - str = "750GX"; - break; - - case CPU_755: - str = "755"; - break; - - case CPU_7400: - str = "MPC7400"; - break; - - case CPU_7410: - str = "MPC7410"; - break; - - case CPU_7447A: - str = "MPC7447A"; - break; - - case CPU_7448: - str = "MPC7448"; - break; - - case CPU_7450: - str = "MPC7450"; - break; - - case CPU_7455: - str = "MPC7455"; - break; - - case CPU_7457: - str = "MPC7457"; - break; - - default: - printf("Unknown CPU -- PVR: 0x%08x\n", pvr); - return -1; - } - - printf ("%s v%d.%d", str, (pvr >> 8) & 0xFF, pvr & 0xFF); -PR_CLK: - printf (" @ %s MHz\n", strmhz(buf, clock)); - - return (0); -} -#endif -/* these two functions are unimplemented currently [josh] */ - -/* -------------------------------------------------------------------- */ -/* L1 i-cache */ - -int -checkicache(void) -{ - return 0; /* XXX */ -} - -/* -------------------------------------------------------------------- */ -/* L1 d-cache */ - -int -checkdcache(void) -{ - return 0; /* XXX */ -} - -/* -------------------------------------------------------------------- */ - -static inline void -soft_restart(unsigned long addr) -{ - /* SRR0 has system reset vector, SRR1 has default MSR value */ - /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ - - __asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr)); - __asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4"); - __asm__ __volatile__ ("mtspr 27, 4"); - __asm__ __volatile__ ("rfi"); - - while(1); /* not reached */ -} - - -#if !defined(CONFIG_BAB7xx) && \ - !defined(CONFIG_ELPPC) && \ - !defined(CONFIG_PPMC7XX) -/* no generic way to do board reset. simply call soft_reset. */ -int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - ulong addr; - /* flush and disable I/D cache */ - __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3"); - __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5"); - __asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4"); - __asm__ __volatile__ ("andc 5, 3, 5" ::: "r5"); - __asm__ __volatile__ ("sync"); - __asm__ __volatile__ ("mtspr 1008, 4"); - __asm__ __volatile__ ("isync"); - __asm__ __volatile__ ("sync"); - __asm__ __volatile__ ("mtspr 1008, 5"); - __asm__ __volatile__ ("isync"); - __asm__ __volatile__ ("sync"); - -#ifdef CONFIG_SYS_RESET_ADDRESS - addr = CONFIG_SYS_RESET_ADDRESS; -#else - /* - * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, - * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid - * address. Better pick an address known to be invalid on your - * system and assign it to CONFIG_SYS_RESET_ADDRESS. - */ - addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong); -#endif - soft_restart(addr); - - /* not reached */ - while(1) - ; - - return 1; -} -#endif - -/* ------------------------------------------------------------------------- */ - -/* - * For the 7400 the TB clock runs at 1/4 the cpu bus speed. - */ -#ifndef CONFIG_SYS_BUS_CLK -#define CONFIG_SYS_BUS_CLK gd->bus_clk -#endif - -unsigned long get_tbclk(void) -{ - return CONFIG_SYS_BUS_CLK / 4; -} - -/* ------------------------------------------------------------------------- */ - -#if defined(CONFIG_WATCHDOG) -#if !defined(CONFIG_BAB7xx) -void -watchdog_reset(void) -{ - -} -#endif /* !CONFIG_BAB7xx */ -#endif /* CONFIG_WATCHDOG */ - -/* ------------------------------------------------------------------------- */ - -#ifdef CONFIG_OF_LIBFDT -void ft_cpu_setup(void *blob, bd_t *bd) -{ - do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, - "timebase-frequency", bd->bi_busfreq / 4, 1); - do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, - "bus-frequency", bd->bi_busfreq, 1); - do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, - "clock-frequency", bd->bi_intfreq, 1); - - fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); - - fdt_fixup_ethernet(blob); -} -#endif -/* ------------------------------------------------------------------------- */ diff --git a/arch/powerpc/cpu/74xx_7xx/cpu_init.c b/arch/powerpc/cpu/74xx_7xx/cpu_init.c deleted file mode 100644 index a6a8788..0000000 --- a/arch/powerpc/cpu/74xx_7xx/cpu_init.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * (C) Copyright 2001 - * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * cpu_init.c - low level cpu init - * - * there's really nothing going on here yet. future work area? - */ - -#include <common.h> -#include <74xx_7xx.h> - -/* - * Breath some life into the CPU... - * - * there's basically nothing to do here since the memory controller - * isn't on the CPU in this case. - */ -void -cpu_init_f (void) -{ - switch (get_cpu_type()) { - case CPU_7450: - case CPU_7455: - case CPU_7457: - case CPU_7447A: - case CPU_7448: - /* enable the timebase bit in HID0 */ - set_hid0(get_hid0() | 0x4000000); - break; - default: - /* do nothing */ - break; - } -} - -/* - * initialize higher level parts of CPU like timers - */ -int cpu_init_r (void) -{ - return (0); -} diff --git a/arch/powerpc/cpu/74xx_7xx/interrupts.c b/arch/powerpc/cpu/74xx_7xx/interrupts.c deleted file mode 100644 index a906243..0000000 --- a/arch/powerpc/cpu/74xx_7xx/interrupts.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * (C) Copyright 2001 - * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * interrupts.c - just enough support for the decrementer/timer - */ - -#include <common.h> -#include <mpc8xx.h> -#include <mpc8xx_irq.h> -#include <asm/processor.h> -#include <commproc.h> -#include <command.h> - -int interrupt_init_cpu (unsigned *decrementer_count) -{ - debug("interrupt_init: GT main cause reg: %08x:%08x\n", - GTREGREAD(LOW_INTERRUPT_CAUSE_REGISTER), - GTREGREAD(HIGH_INTERRUPT_CAUSE_REGISTER)); - debug("interrupt_init: ethernet cause regs: %08x %08x %08x\n", - GTREGREAD(ETHERNET0_INTERRUPT_CAUSE_REGISTER), - GTREGREAD(ETHERNET1_INTERRUPT_CAUSE_REGISTER), - GTREGREAD(ETHERNET2_INTERRUPT_CAUSE_REGISTER)); - debug("interrupt_init: ethernet mask regs: %08x %08x %08x\n", - GTREGREAD(ETHERNET0_INTERRUPT_MASK_REGISTER), - GTREGREAD(ETHERNET1_INTERRUPT_MASK_REGISTER), - GTREGREAD(ETHERNET2_INTERRUPT_MASK_REGISTER)); - debug("interrupt_init: setting decrementer_count\n"); - - *decrementer_count = get_tbclk() / CONFIG_SYS_HZ; - - return (0); -} - -/****************************************************************************/ - -/* - * Handle external interrupts - */ -void -external_interrupt(struct pt_regs *regs) -{ - puts("external_interrupt (oops!)\n"); -} - -volatile ulong timestamp = 0; - -/* - * timer_interrupt - gets called when the decrementer overflows, - * with interrupts disabled. - * Trivial implementation - no need to be really accurate. - */ -void -timer_interrupt_cpu (struct pt_regs *regs) -{ - /* nothing to do here */ - return; -} - -/****************************************************************************/ - -/* - * Install and free a interrupt handler. - */ - -void -irq_install_handler(int vec, interrupt_handler_t *handler, void *arg) -{ - -} - -void -irq_free_handler(int vec) -{ - -} - -/****************************************************************************/ - -void -do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char * const argv[]) -{ - puts("IRQ related functions are unimplemented currently.\n"); -} diff --git a/arch/powerpc/cpu/74xx_7xx/io.S b/arch/powerpc/cpu/74xx_7xx/io.S deleted file mode 100644 index 3b4b08a..0000000 --- a/arch/powerpc/cpu/74xx_7xx/io.S +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> - * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> - * Copyright (C) 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Andreas Heppel <aheppel@sysgo.de> - * Copyright (C) 2002 Wolfgang Denk <wd@denx.de> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <config.h> -#include <ppc_asm.tmpl> - -/* ------------------------------------------------------------------------------- */ -/* Function: in8 */ -/* Description: Input 8 bits */ -/* ------------------------------------------------------------------------------- */ - .globl in8 -in8: - lbz r3,0(r3) - sync - blr - -/* ------------------------------------------------------------------------------- */ -/* Function: in16 */ -/* Description: Input 16 bits */ -/* ------------------------------------------------------------------------------- */ - .globl in16 -in16: - lhz r3,0(r3) - sync - blr - -/* ------------------------------------------------------------------------------- */ -/* Function: in16r */ -/* Description: Input 16 bits and byte reverse */ -/* ------------------------------------------------------------------------------- */ - .globl in16r -in16r: - lhbrx r3,0,r3 - sync - blr - -/* ------------------------------------------------------------------------------- */ -/* Function: in32 */ -/* Description: Input 32 bits */ -/* ------------------------------------------------------------------------------- */ - .globl in32 -in32: - lwz 3,0(3) - sync - blr - -/* ------------------------------------------------------------------------------- */ -/* Function: in32r */ -/* Description: Input 32 bits and byte reverse */ -/* ------------------------------------------------------------------------------- */ - .globl in32r -in32r: - lwbrx r3,0,r3 - sync - blr - -/* ------------------------------------------------------------------------------- */ -/* Function: out8 */ -/* Description: Output 8 bits */ -/* ------------------------------------------------------------------------------- */ - .globl out8 -out8: - stb r4,0(r3) - sync - blr - -/* ------------------------------------------------------------------------------- */ -/* Function: out16 */ -/* Description: Output 16 bits */ -/* ------------------------------------------------------------------------------- */ - .globl out16 -out16: - sth r4,0(r3) - sync - blr - -/* ------------------------------------------------------------------------------- */ -/* Function: out16r */ -/* Description: Byte reverse and output 16 bits */ -/* ------------------------------------------------------------------------------- */ - .globl out16r -out16r: - sthbrx r4,0,r3 - sync - blr - -/* ------------------------------------------------------------------------------- */ -/* Function: out32 */ -/* Description: Output 32 bits */ -/* ------------------------------------------------------------------------------- */ - .globl out32 -out32: - stw r4,0(r3) - sync - blr - -/* ------------------------------------------------------------------------------- */ -/* Function: out32r */ -/* Description: Byte reverse and output 32 bits */ -/* ------------------------------------------------------------------------------- */ - .globl out32r -out32r: - stwbrx r4,0,r3 - sync - blr diff --git a/arch/powerpc/cpu/74xx_7xx/kgdb.S b/arch/powerpc/cpu/74xx_7xx/kgdb.S deleted file mode 100644 index 42b3a76..0000000 --- a/arch/powerpc/cpu/74xx_7xx/kgdb.S +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2000 Murray Jensen <Murray.Jensen@cmst.csiro.au> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <config.h> -#include <command.h> -#include <74xx_7xx.h> -#include <version.h> - -#include <ppc_asm.tmpl> -#include <ppc_defs.h> - -#include <asm/cache.h> -#include <asm/mmu.h> - -#if defined(CONFIG_CMD_KGDB) - - /* - * cache flushing routines for kgdb - */ - - .globl kgdb_flush_cache_all -kgdb_flush_cache_all: - lis r3,0 - addis r4,r0,0x0040 -kgdb_flush_loop: - lwz r5,0(r3) - addi r3,r3,CONFIG_SYS_CACHELINE_SIZE - cmp 0,0,r3,r4 - bne kgdb_flush_loop - SYNC - mfspr r3,1008 - ori r3,r3,0x8800 - mtspr 1008,r3 - sync - blr - - .globl kgdb_flush_cache_range -kgdb_flush_cache_range: - li r5,CONFIG_SYS_CACHELINE_SIZE-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,CONFIG_SYS_CACHELINE_SHIFT - beqlr - mtctr r4 - mr r6,r3 -1: dcbst 0,r3 - addi r3,r3,CONFIG_SYS_CACHELINE_SIZE - bdnz 1b - sync /* wait for dcbst's to get to ram */ - mtctr r4 -2: icbi 0,r6 - addi r6,r6,CONFIG_SYS_CACHELINE_SIZE - bdnz 2b - SYNC - blr - -#endif diff --git a/arch/powerpc/cpu/74xx_7xx/speed.c b/arch/powerpc/cpu/74xx_7xx/speed.c deleted file mode 100644 index 5ffa41c..0000000 --- a/arch/powerpc/cpu/74xx_7xx/speed.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * (C) Copyright 2000-2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <74xx_7xx.h> -#include <asm/processor.h> - -DECLARE_GLOBAL_DATA_PTR; - -extern unsigned long get_board_bus_clk (void); - -static const int hid1_multipliers_x_10[] = { - 25, /* 0000 - 2.5x */ - 75, /* 0001 - 7.5x */ - 70, /* 0010 - 7x */ - 10, /* 0011 - bypass */ - 20, /* 0100 - 2x */ - 65, /* 0101 - 6.5x */ - 100, /* 0110 - 10x */ - 45, /* 0111 - 4.5x */ - 30, /* 1000 - 3x */ - 55, /* 1001 - 5.5x */ - 40, /* 1010 - 4x */ - 50, /* 1011 - 5x */ - 80, /* 1100 - 8x */ - 60, /* 1101 - 6x */ - 35, /* 1110 - 3.5x */ - 0 /* 1111 - off */ -}; - -/* PLL_CFG[0:4] table for cpu 7448/7447A/7455/7457 */ -static const int hid1_74xx_multipliers_x_10[] = { - 115, /* 00000 - 11.5x */ - 170, /* 00001 - 17x */ - 75, /* 00010 - 7.5x */ - 150, /* 00011 - 15x */ - 70, /* 00100 - 7x */ - 180, /* 00101 - 18x */ - 10, /* 00110 - bypass */ - 200, /* 00111 - 20x */ - 20, /* 01000 - 2x */ - 210, /* 01001 - 21x */ - 65, /* 01010 - 6.5x */ - 130, /* 01011 - 13x */ - 85, /* 01100 - 8.5x */ - 240, /* 01101 - 24x */ - 95, /* 01110 - 9.5x */ - 90, /* 01111 - 9x */ - 30, /* 10000 - 3x */ - 105, /* 10001 - 10.5x */ - 55, /* 10010 - 5.5x */ - 110, /* 10011 - 11x */ - 40, /* 10100 - 4x */ - 100, /* 10101 - 10x */ - 50, /* 10110 - 5x */ - 120, /* 10111 - 12x */ - 80, /* 11000 - 8x */ - 140, /* 11001 - 14x */ - 60, /* 11010 - 6x */ - 160, /* 11011 - 16x */ - 135, /* 11100 - 13.5x */ - 280, /* 11101 - 28x */ - 0, /* 11110 - off */ - 125 /* 11111 - 12.5x */ -}; - -static const int hid1_fx_multipliers_x_10[] = { - 00, /* 0000 - off */ - 00, /* 0001 - off */ - 10, /* 0010 - bypass */ - 10, /* 0011 - bypass */ - 20, /* 0100 - 2x */ - 25, /* 0101 - 2.5x */ - 30, /* 0110 - 3x */ - 35, /* 0111 - 3.5x */ - 40, /* 1000 - 4x */ - 45, /* 1001 - 4.5x */ - 50, /* 1010 - 5x */ - 55, /* 1011 - 5.5x */ - 60, /* 1100 - 6x */ - 65, /* 1101 - 6.5x */ - 70, /* 1110 - 7x */ - 75, /* 1111 - 7.5 */ - 80, /* 10000 - 8x */ - 85, /* 10001 - 8.5x */ - 90, /* 10010 - 9x */ - 95, /* 10011 - 9.5x */ - 100, /* 10100 - 10x */ - 110, /* 10101 - 11x */ - 120, /* 10110 - 12x */ -}; - - -/* ------------------------------------------------------------------------- */ - -/* - * Measure CPU clock speed (core clock GCLK1, GCLK2) - * - * (Approx. GCLK frequency in Hz) - */ - -int get_clocks (void) -{ - ulong clock = 0; - -#ifdef CONFIG_SYS_BUS_CLK - gd->bus_clk = CONFIG_SYS_BUS_CLK; /* bus clock is a fixed frequency */ -#else - gd->bus_clk = get_board_bus_clk (); /* bus clock is configurable */ -#endif - - /* calculate the clock frequency based upon the CPU type */ - switch (get_cpu_type()) { - case CPU_7447A: - case CPU_7448: - case CPU_7455: - case CPU_7457: - /* - * Make sure division is done before multiplication to prevent 32-bit - * arithmetic overflows which will cause a negative number - */ - clock = (gd->bus_clk / 10) * - hid1_74xx_multipliers_x_10[(get_hid1 () >> 12) & 0x1F]; - break; - - case CPU_750GX: - case CPU_750FX: - clock = (gd->bus_clk / 10) * - hid1_fx_multipliers_x_10[get_hid1 () >> 27]; - break; - - case CPU_7450: - case CPU_740: - case CPU_740P: - case CPU_745: - case CPU_750CX: - case CPU_750: - case CPU_750P: - case CPU_755: - case CPU_7400: - case CPU_7410: - /* - * Make sure division is done before multiplication to prevent 32-bit - * arithmetic overflows which will cause a negative number - */ - clock = (gd->bus_clk / 10) * - hid1_multipliers_x_10[get_hid1 () >> 28]; - break; - - case CPU_UNKNOWN: - printf ("get_gclk_freq(): unknown CPU type\n"); - clock = 0; - return (1); - } - - gd->cpu_clk = clock; - - return (0); -} - -/* ------------------------------------------------------------------------- */ diff --git a/arch/powerpc/cpu/74xx_7xx/start.S b/arch/powerpc/cpu/74xx_7xx/start.S deleted file mode 100644 index 8393781..0000000 --- a/arch/powerpc/cpu/74xx_7xx/start.S +++ /dev/null @@ -1,829 +0,0 @@ -/* - * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> - * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> - * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de> - * Copyright (C) 2001 Josh Huber <huber@mclx.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* U-Boot - Startup Code for PowerPC based Embedded Boards - * - * - * The processor starts at 0xfff00100 and the code is executed - * from flash. The code is organized to be at an other address - * in memory, but as long we don't jump around before relocating. - * board_init lies at a quite high address and when the cpu has - * jumped there, everything is ok. - */ -#include <asm-offsets.h> -#include <config.h> -#include <74xx_7xx.h> -#include <version.h> - -#include <ppc_asm.tmpl> -#include <ppc_defs.h> - -#include <asm/cache.h> -#include <asm/mmu.h> -#include <asm/u-boot.h> - -/* We don't want the MMU yet. -*/ -#undef MSR_KERNEL -/* Machine Check and Recoverable Interr. */ -#define MSR_KERNEL ( MSR_ME | MSR_RI ) - -/* - * Set up GOT: Global Offset Table - * - * Use r12 to access the GOT - */ - START_GOT - GOT_ENTRY(_GOT2_TABLE_) - GOT_ENTRY(_FIXUP_TABLE_) - - GOT_ENTRY(_start) - GOT_ENTRY(_start_of_vectors) - GOT_ENTRY(_end_of_vectors) - GOT_ENTRY(transfer_to_handler) - - GOT_ENTRY(__init_end) - GOT_ENTRY(__bss_end) - GOT_ENTRY(__bss_start) - END_GOT - -/* - * r3 - 1st arg to board_init(): IMMP pointer - * r4 - 2nd arg to board_init(): boot flag - */ - .text - .long 0x27051956 /* U-Boot Magic Number */ - .globl version_string -version_string: - .ascii U_BOOT_VERSION_STRING, "\0" - - . = EXC_OFF_SYS_RESET - .globl _start -_start: - b boot_cold - - /* the boot code is located below the exception table */ - - .globl _start_of_vectors -_start_of_vectors: - -/* Machine check */ - STD_EXCEPTION(0x200, MachineCheck, MachineCheckException) - -/* Data Storage exception. "Never" generated on the 860. */ - STD_EXCEPTION(0x300, DataStorage, UnknownException) - -/* Instruction Storage exception. "Never" generated on the 860. */ - STD_EXCEPTION(0x400, InstStorage, UnknownException) - -/* External Interrupt exception. */ - STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt) - -/* Alignment exception. */ - . = 0x600 -Alignment: - EXCEPTION_PROLOG(SRR0, SRR1) - mfspr r4,DAR - stw r4,_DAR(r21) - mfspr r5,DSISR - stw r5,_DSISR(r21) - addi r3,r1,STACK_FRAME_OVERHEAD - EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE) - -/* Program check exception */ - . = 0x700 -ProgramCheck: - EXCEPTION_PROLOG(SRR0, SRR1) - addi r3,r1,STACK_FRAME_OVERHEAD - EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException, - MSR_KERNEL, COPY_EE) - - /* No FPU on MPC8xx. This exception is not supposed to happen. - */ - STD_EXCEPTION(0x800, FPUnavailable, UnknownException) - - /* I guess we could implement decrementer, and may have - * to someday for timekeeping. - */ - STD_EXCEPTION(0x900, Decrementer, timer_interrupt) - STD_EXCEPTION(0xa00, Trap_0a, UnknownException) - STD_EXCEPTION(0xb00, Trap_0b, UnknownException) - STD_EXCEPTION(0xc00, SystemCall, UnknownException) - STD_EXCEPTION(0xd00, SingleStep, UnknownException) - - STD_EXCEPTION(0xe00, Trap_0e, UnknownException) - STD_EXCEPTION(0xf00, Trap_0f, UnknownException) - - /* - * On the MPC8xx, this is a software emulation interrupt. It - * occurs for all unimplemented and illegal instructions. - */ - STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException) - - STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException) - STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException) - STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException) - STD_EXCEPTION(0x1400, DataTLBError, UnknownException) - - STD_EXCEPTION(0x1500, Reserved5, UnknownException) - STD_EXCEPTION(0x1600, Reserved6, UnknownException) - STD_EXCEPTION(0x1700, Reserved7, UnknownException) - STD_EXCEPTION(0x1800, Reserved8, UnknownException) - STD_EXCEPTION(0x1900, Reserved9, UnknownException) - STD_EXCEPTION(0x1a00, ReservedA, UnknownException) - STD_EXCEPTION(0x1b00, ReservedB, UnknownException) - - STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException) - STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException) - STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException) - STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException) - - .globl _end_of_vectors -_end_of_vectors: - - . = 0x2000 - -boot_cold: - /* disable everything */ - li r0, 0 - mtspr HID0, r0 - sync - mtmsr 0 - bl invalidate_bats - sync - -#ifdef CONFIG_SYS_L2 - /* init the L2 cache */ - addis r3, r0, L2_INIT@h - ori r3, r3, L2_INIT@l - sync - mtspr l2cr, r3 -#endif -#if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx) - .long 0x7e00066c - /* - * dssall instruction, gas doesn't have it yet - * ...for altivec, data stream stop all this probably - * isn't needed unless we warm (software) reboot U-Boot - */ -#endif - -#ifdef CONFIG_SYS_L2 - /* invalidate the L2 cache */ - bl l2cache_invalidate - sync -#endif -#ifdef CONFIG_SYS_BOARD_ASM_INIT - /* do early init */ - bl board_asm_init -#endif - - /* - * Calculate absolute address in FLASH and jump there - *------------------------------------------------------*/ - lis r3, CONFIG_SYS_MONITOR_BASE@h - ori r3, r3, CONFIG_SYS_MONITOR_BASE@l - addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET - mtlr r3 - blr - -in_flash: - /* let the C-code set up the rest */ - /* */ - /* Be careful to keep code relocatable ! */ - /*------------------------------------------------------*/ - - /* perform low-level init */ - /* sdram init, galileo init, etc */ - /* r3: NHR bit from HID0 */ - - /* setup the bats */ - bl setup_bats - sync - - /* - * Cache must be enabled here for stack-in-cache trick. - * This means we need to enable the BATS. - * This means: - * 1) for the EVB, original gt regs need to be mapped - * 2) need to have an IBAT for the 0xf region, - * we are running there! - * Cache should be turned on after BATs, since by default - * everything is write-through. - * The init-mem BAT can be reused after reloc. The old - * gt-regs BAT can be reused after board_init_f calls - * board_early_init_f (EVB only). - */ -#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC) && !defined(CONFIG_P3Mx) - /* enable address translation */ - bl enable_addr_trans - sync - - /* enable and invalidate the data cache */ - bl l1dcache_enable - sync -#endif -#ifdef CONFIG_SYS_INIT_RAM_LOCK - bl lock_ram_in_cache - sync -#endif - - /* set up the stack pointer in our newly created - * cache-ram (r1) */ - lis r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h - ori r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l - - li r0, 0 /* Make room for stack frame header and */ - stwu r0, -4(r1) /* clear final stack frame so that */ - stwu r0, -4(r1) /* stack backtraces terminate cleanly */ - - GET_GOT /* initialize GOT access */ - - /* run low-level CPU init code (from Flash) */ - bl cpu_init_f - sync - - /* run 1st part of board init code (from Flash) */ - bl board_init_f - sync - - /* NOTREACHED - board_init_f() does not return */ - - .globl invalidate_bats -invalidate_bats: - /* invalidate BATs */ - mtspr IBAT0U, r0 - mtspr IBAT1U, r0 - mtspr IBAT2U, r0 - mtspr IBAT3U, r0 -#ifdef CONFIG_HIGH_BATS - mtspr IBAT4U, r0 - mtspr IBAT5U, r0 - mtspr IBAT6U, r0 - mtspr IBAT7U, r0 -#endif - isync - mtspr DBAT0U, r0 - mtspr DBAT1U, r0 - mtspr DBAT2U, r0 - mtspr DBAT3U, r0 -#ifdef CONFIG_HIGH_BATS - mtspr DBAT4U, r0 - mtspr DBAT5U, r0 - mtspr DBAT6U, r0 - mtspr DBAT7U, r0 -#endif - isync - sync - blr - - /* setup_bats - set them up to some initial state */ - .globl setup_bats -setup_bats: - addis r0, r0, 0x0000 - - /* IBAT 0 */ - addis r4, r0, CONFIG_SYS_IBAT0L@h - ori r4, r4, CONFIG_SYS_IBAT0L@l - addis r3, r0, CONFIG_SYS_IBAT0U@h - ori r3, r3, CONFIG_SYS_IBAT0U@l - mtspr IBAT0L, r4 - mtspr IBAT0U, r3 - isync - - /* DBAT 0 */ - addis r4, r0, CONFIG_SYS_DBAT0L@h - ori r4, r4, CONFIG_SYS_DBAT0L@l - addis r3, r0, CONFIG_SYS_DBAT0U@h - ori r3, r3, CONFIG_SYS_DBAT0U@l - mtspr DBAT0L, r4 - mtspr DBAT0U, r3 - isync - - /* IBAT 1 */ - addis r4, r0, CONFIG_SYS_IBAT1L@h - ori r4, r4, CONFIG_SYS_IBAT1L@l - addis r3, r0, CONFIG_SYS_IBAT1U@h - ori r3, r3, CONFIG_SYS_IBAT1U@l - mtspr IBAT1L, r4 - mtspr IBAT1U, r3 - isync - - /* DBAT 1 */ - addis r4, r0, CONFIG_SYS_DBAT1L@h - ori r4, r4, CONFIG_SYS_DBAT1L@l - addis r3, r0, CONFIG_SYS_DBAT1U@h - ori r3, r3, CONFIG_SYS_DBAT1U@l - mtspr DBAT1L, r4 - mtspr DBAT1U, r3 - isync - - /* IBAT 2 */ - addis r4, r0, CONFIG_SYS_IBAT2L@h - ori r4, r4, CONFIG_SYS_IBAT2L@l - addis r3, r0, CONFIG_SYS_IBAT2U@h - ori r3, r3, CONFIG_SYS_IBAT2U@l - mtspr IBAT2L, r4 - mtspr IBAT2U, r3 - isync - - /* DBAT 2 */ - addis r4, r0, CONFIG_SYS_DBAT2L@h - ori r4, r4, CONFIG_SYS_DBAT2L@l - addis r3, r0, CONFIG_SYS_DBAT2U@h - ori r3, r3, CONFIG_SYS_DBAT2U@l - mtspr DBAT2L, r4 - mtspr DBAT2U, r3 - isync - - /* IBAT 3 */ - addis r4, r0, CONFIG_SYS_IBAT3L@h - ori r4, r4, CONFIG_SYS_IBAT3L@l - addis r3, r0, CONFIG_SYS_IBAT3U@h - ori r3, r3, CONFIG_SYS_IBAT3U@l - mtspr IBAT3L, r4 - mtspr IBAT3U, r3 - isync - - /* DBAT 3 */ - addis r4, r0, CONFIG_SYS_DBAT3L@h - ori r4, r4, CONFIG_SYS_DBAT3L@l - addis r3, r0, CONFIG_SYS_DBAT3U@h - ori r3, r3, CONFIG_SYS_DBAT3U@l - mtspr DBAT3L, r4 - mtspr DBAT3U, r3 - isync - -#ifdef CONFIG_HIGH_BATS - /* IBAT 4 */ - addis r4, r0, CONFIG_SYS_IBAT4L@h - ori r4, r4, CONFIG_SYS_IBAT4L@l - addis r3, r0, CONFIG_SYS_IBAT4U@h - ori r3, r3, CONFIG_SYS_IBAT4U@l - mtspr IBAT4L, r4 - mtspr IBAT4U, r3 - isync - - /* DBAT 4 */ - addis r4, r0, CONFIG_SYS_DBAT4L@h - ori r4, r4, CONFIG_SYS_DBAT4L@l - addis r3, r0, CONFIG_SYS_DBAT4U@h - ori r3, r3, CONFIG_SYS_DBAT4U@l - mtspr DBAT4L, r4 - mtspr DBAT4U, r3 - isync - - /* IBAT 5 */ - addis r4, r0, CONFIG_SYS_IBAT5L@h - ori r4, r4, CONFIG_SYS_IBAT5L@l - addis r3, r0, CONFIG_SYS_IBAT5U@h - ori r3, r3, CONFIG_SYS_IBAT5U@l - mtspr IBAT5L, r4 - mtspr IBAT5U, r3 - isync - - /* DBAT 5 */ - addis r4, r0, CONFIG_SYS_DBAT5L@h - ori r4, r4, CONFIG_SYS_DBAT5L@l - addis r3, r0, CONFIG_SYS_DBAT5U@h - ori r3, r3, CONFIG_SYS_DBAT5U@l - mtspr DBAT5L, r4 - mtspr DBAT5U, r3 - isync - - /* IBAT 6 */ - addis r4, r0, CONFIG_SYS_IBAT6L@h - ori r4, r4, CONFIG_SYS_IBAT6L@l - addis r3, r0, CONFIG_SYS_IBAT6U@h - ori r3, r3, CONFIG_SYS_IBAT6U@l - mtspr IBAT6L, r4 - mtspr IBAT6U, r3 - isync - - /* DBAT 6 */ - addis r4, r0, CONFIG_SYS_DBAT6L@h - ori r4, r4, CONFIG_SYS_DBAT6L@l - addis r3, r0, CONFIG_SYS_DBAT6U@h - ori r3, r3, CONFIG_SYS_DBAT6U@l - mtspr DBAT6L, r4 - mtspr DBAT6U, r3 - isync - - /* IBAT 7 */ - addis r4, r0, CONFIG_SYS_IBAT7L@h - ori r4, r4, CONFIG_SYS_IBAT7L@l - addis r3, r0, CONFIG_SYS_IBAT7U@h - ori r3, r3, CONFIG_SYS_IBAT7U@l - mtspr IBAT7L, r4 - mtspr IBAT7U, r3 - isync - - /* DBAT 7 */ - addis r4, r0, CONFIG_SYS_DBAT7L@h - ori r4, r4, CONFIG_SYS_DBAT7L@l - addis r3, r0, CONFIG_SYS_DBAT7U@h - ori r3, r3, CONFIG_SYS_DBAT7U@l - mtspr DBAT7L, r4 - mtspr DBAT7U, r3 - isync -#endif - - /* bats are done, now invalidate the TLBs */ - - addis r3, 0, 0x0000 - addis r5, 0, 0x4 /* upper bound of 0x00040000 for 7400/750 */ - - isync - -tlblp: - tlbie r3 - sync - addi r3, r3, 0x1000 - cmp 0, 0, r3, r5 - blt tlblp - - blr - - .globl enable_addr_trans -enable_addr_trans: - /* enable address translation */ - mfmsr r5 - ori r5, r5, (MSR_IR | MSR_DR) - mtmsr r5 - isync - blr - - .globl disable_addr_trans -disable_addr_trans: - /* disable address translation */ - mflr r4 - mfmsr r3 - andi. r0, r3, (MSR_IR | MSR_DR) - beqlr - andc r3, r3, r0 - mtspr SRR0, r4 - mtspr SRR1, r3 - rfi - -/* - * This code finishes saving the registers to the exception frame - * and jumps to the appropriate handler for the exception. - * Register r21 is pointer into trap frame, r1 has new stack pointer. - */ - .globl transfer_to_handler -transfer_to_handler: - stw r22,_NIP(r21) - lis r22,MSR_POW@h - andc r23,r23,r22 - stw r23,_MSR(r21) - SAVE_GPR(7, r21) - SAVE_4GPRS(8, r21) - SAVE_8GPRS(12, r21) - SAVE_8GPRS(24, r21) - mflr r23 - andi. r24,r23,0x3f00 /* get vector offset */ - stw r24,TRAP(r21) - li r22,0 - stw r22,RESULT(r21) - mtspr SPRG2,r22 /* r1 is now kernel sp */ - lwz r24,0(r23) /* virtual address of handler */ - lwz r23,4(r23) /* where to go when done */ - mtspr SRR0,r24 - mtspr SRR1,r20 - mtlr r23 - SYNC - rfi /* jump to handler, enable MMU */ - -int_return: - mfmsr r28 /* Disable interrupts */ - li r4,0 - ori r4,r4,MSR_EE - andc r28,r28,r4 - SYNC /* Some chip revs need this... */ - mtmsr r28 - SYNC - lwz r2,_CTR(r1) - lwz r0,_LINK(r1) - mtctr r2 - mtlr r0 - lwz r2,_XER(r1) - lwz r0,_CCR(r1) - mtspr XER,r2 - mtcrf 0xFF,r0 - REST_10GPRS(3, r1) - REST_10GPRS(13, r1) - REST_8GPRS(23, r1) - REST_GPR(31, r1) - lwz r2,_NIP(r1) /* Restore environment */ - lwz r0,_MSR(r1) - mtspr SRR0,r2 - mtspr SRR1,r0 - lwz r0,GPR0(r1) - lwz r2,GPR2(r1) - lwz r1,GPR1(r1) - SYNC - rfi - - .globl dc_read -dc_read: - blr - - .globl get_pvr -get_pvr: - mfspr r3, PVR - blr - -/*-----------------------------------------------------------------------*/ -/* - * void relocate_code (addr_sp, gd, addr_moni) - * - * This "function" does not return, instead it continues in RAM - * after relocating the monitor code. - * - * r3 = dest - * r4 = src - * r5 = length in bytes - * r6 = cachelinesize - */ - .globl relocate_code -relocate_code: - mr r1, r3 /* Set new stack pointer */ - mr r9, r4 /* Save copy of Global Data pointer */ - mr r10, r5 /* Save copy of Destination Address */ - - GET_GOT - mr r3, r5 /* Destination Address */ - lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */ - ori r4, r4, CONFIG_SYS_MONITOR_BASE@l - lwz r5, GOT(__init_end) - sub r5, r5, r4 - li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */ - - /* - * Fix GOT pointer: - * - * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address - * - * Offset: - */ - sub r15, r10, r4 - - /* First our own GOT */ - add r12, r12, r15 - /* then the one used by the C code */ - add r30, r30, r15 - - /* - * Now relocate code - */ -#ifdef CONFIG_ECC - bl board_relocate_rom - sync - mr r3, r10 /* Destination Address */ - lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */ - ori r4, r4, CONFIG_SYS_MONITOR_BASE@l - lwz r5, GOT(__init_end) - sub r5, r5, r4 - li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */ -#else - cmplw cr1,r3,r4 - addi r0,r5,3 - srwi. r0,r0,2 - beq cr1,4f /* In place copy is not necessary */ - beq 7f /* Protect against 0 count */ - mtctr r0 - bge cr1,2f - - la r8,-4(r4) - la r7,-4(r3) -1: lwzu r0,4(r8) - stwu r0,4(r7) - bdnz 1b - b 4f - -2: slwi r0,r0,2 - add r8,r4,r0 - add r7,r3,r0 -3: lwzu r0,-4(r8) - stwu r0,-4(r7) - bdnz 3b -#endif -/* - * Now flush the cache: note that we must start from a cache aligned - * address. Otherwise we might miss one cache line. - */ -4: cmpwi r6,0 - add r5,r3,r5 - beq 7f /* Always flush prefetch queue in any case */ - subi r0,r6,1 - andc r3,r3,r0 - mr r4,r3 -5: dcbst 0,r4 - add r4,r4,r6 - cmplw r4,r5 - blt 5b - sync /* Wait for all dcbst to complete on bus */ - mr r4,r3 -6: icbi 0,r4 - add r4,r4,r6 - cmplw r4,r5 - blt 6b -7: sync /* Wait for all icbi to complete on bus */ - isync - -/* - * We are done. Do not return, instead branch to second part of board - * initialization, now running from RAM. - */ - addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET - mtlr r0 - blr - -in_ram: -#ifdef CONFIG_ECC - bl board_init_ecc -#endif - /* - * Relocation Function, r12 point to got2+0x8000 - * - * Adjust got2 pointers, no need to check for 0, this code - * already puts a few entries in the table. - */ - li r0,__got2_entries@sectoff@l - la r3,GOT(_GOT2_TABLE_) - lwz r11,GOT(_GOT2_TABLE_) - mtctr r0 - sub r11,r3,r11 - addi r3,r3,-4 -1: lwzu r0,4(r3) - cmpwi r0,0 - beq- 2f - add r0,r0,r11 - stw r0,0(r3) -2: bdnz 1b - - /* - * Now adjust the fixups and the pointers to the fixups - * in case we need to move ourselves again. - */ - li r0,__fixup_entries@sectoff@l - lwz r3,GOT(_FIXUP_TABLE_) - cmpwi r0,0 - mtctr r0 - addi r3,r3,-4 - beq 4f -3: lwzu r4,4(r3) - lwzux r0,r4,r11 - cmpwi r0,0 - add r0,r0,r11 - stw r4,0(r3) - beq- 5f - stw r0,0(r4) -5: bdnz 3b -4: -/* clear_bss: */ - /* - * Now clear BSS segment - */ - lwz r3,GOT(__bss_start) - lwz r4,GOT(__bss_end) - - cmplw 0, r3, r4 - beq 6f - - li r0, 0 -5: - stw r0, 0(r3) - addi r3, r3, 4 - cmplw 0, r3, r4 - bne 5b -6: - mr r3, r10 /* Destination Address */ -#if defined(CONFIG_PPMC7XX) - mr r4, r9 /* Use RAM copy of the global data */ -#endif - bl after_reloc - - /* not reached - end relocate_code */ -/*-----------------------------------------------------------------------*/ - - /* - * Copy exception vector code to low memory - * - * r3: dest_addr - * r7: source address, r8: end address, r9: target address - */ - .globl trap_init -trap_init: - mflr r4 /* save link register */ - GET_GOT - lwz r7, GOT(_start) - lwz r8, GOT(_end_of_vectors) - - li r9, 0x100 /* reset vector always at 0x100 */ - - cmplw 0, r7, r8 - bgelr /* return if r7>=r8 - just in case */ -1: - lwz r0, 0(r7) - stw r0, 0(r9) - addi r7, r7, 4 - addi r9, r9, 4 - cmplw 0, r7, r8 - bne 1b - - /* - * relocate `hdlr' and `int_return' entries - */ - li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET - li r8, Alignment - _start + EXC_OFF_SYS_RESET -2: - bl trap_reloc - addi r7, r7, 0x100 /* next exception vector */ - cmplw 0, r7, r8 - blt 2b - - li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET - bl trap_reloc - - li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET - bl trap_reloc - - li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET - li r8, SystemCall - _start + EXC_OFF_SYS_RESET -3: - bl trap_reloc - addi r7, r7, 0x100 /* next exception vector */ - cmplw 0, r7, r8 - blt 3b - - li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET - li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET -4: - bl trap_reloc - addi r7, r7, 0x100 /* next exception vector */ - cmplw 0, r7, r8 - blt 4b - - /* enable execptions from RAM vectors */ - mfmsr r7 - li r8,MSR_IP - andc r7,r7,r8 - mtmsr r7 - - mtlr r4 /* restore link register */ - blr - -#ifdef CONFIG_SYS_INIT_RAM_LOCK -lock_ram_in_cache: - /* Allocate Initial RAM in data cache. - */ - lis r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h - ori r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l - li r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \ - (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32 - mtctr r4 -1: - dcbz r0, r3 - addi r3, r3, 32 - bdnz 1b - - /* Lock the data cache */ - mfspr r0, HID0 - ori r0, r0, 0x1000 - sync - mtspr HID0, r0 - sync - blr - -.globl unlock_ram_in_cache -unlock_ram_in_cache: - /* invalidate the INIT_RAM section */ - lis r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h - ori r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l - li r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \ - (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32 - mtctr r4 -1: icbi r0, r3 - addi r3, r3, 32 - bdnz 1b - sync /* Wait for all icbi to complete on bus */ - isync - - /* Unlock the data cache and invalidate it */ - mfspr r0, HID0 - li r3,0x1000 - andc r0,r0,r3 - li r3,0x0400 - or r0,r0,r3 - sync - mtspr HID0, r0 - sync - blr -#endif diff --git a/arch/powerpc/cpu/74xx_7xx/traps.c b/arch/powerpc/cpu/74xx_7xx/traps.c deleted file mode 100644 index 111c86c..0000000 --- a/arch/powerpc/cpu/74xx_7xx/traps.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * linux/arch/powerpc/kernel/traps.c - * - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * - * Modified by Cort Dougan (cort@cs.nmt.edu) - * and Paul Mackerras (paulus@cs.anu.edu.au) - * - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * This file handles the architecture-dependent parts of hardware exceptions - */ - -#include <common.h> -#include <command.h> -#include <kgdb.h> -#include <asm/processor.h> - -/* Returns 0 if exception not found and fixup otherwise. */ -extern unsigned long search_exception_table(unsigned long); - -/* THIS NEEDS CHANGING to use the board info structure. -*/ -#define END_OF_MEM 0x02000000 - -/* - * Trap & Exception support - */ - -static void print_backtrace(unsigned long *sp) -{ - int cnt = 0; - unsigned long i; - - printf("Call backtrace: "); - while (sp) { - if ((uint)sp > END_OF_MEM) - break; - - i = sp[1]; - if (cnt++ % 7 == 0) - printf("\n"); - printf("%08lX ", i); - if (cnt > 32) break; - sp = (unsigned long *)*sp; - } - printf("\n"); -} - -void show_regs(struct pt_regs *regs) -{ - int i; - - printf("NIP: %08lX XER: %08lX LR: %08lX REGS:" - " %p TRAP: %04lx DAR: %08lX\n", - regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); - printf("MSR: %08lx EE: %01x PR: %01x FP:" - " %01x ME: %01x IR/DR: %01x%01x\n", - regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, - regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, - regs->msr&MSR_IR ? 1 : 0, - regs->msr&MSR_DR ? 1 : 0); - - printf("\n"); - for (i = 0; i < 32; i++) { - if ((i % 8) == 0) - { - printf("GPR%02d: ", i); - } - - printf("%08lX ", regs->gpr[i]); - if ((i % 8) == 7) - { - printf("\n"); - } - } -} - - -static void _exception(int signr, struct pt_regs *regs) -{ - show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Exception in kernel pc %lx signal %d",regs->nip,signr); -} - -void MachineCheckException(struct pt_regs *regs) -{ - unsigned long fixup; - - /* Probing PCI using config cycles cause this exception - * when a device is not present. Catch it and return to - * the PCI exception handler. - */ - if ((fixup = search_exception_table(regs->nip)) != 0) { - regs->nip = fixup; - return; - } - -#if defined(CONFIG_CMD_KGDB) - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - return; -#endif - - printf("Machine check in kernel mode.\n"); - printf("Caused by (from msr): "); - printf("regs %p ",regs); - switch( regs->msr & 0x000F0000) { - case (0x80000000>>12): - printf("Machine check signal - probably due to mm fault\n" - "with mmu off\n"); - break; - case (0x80000000>>13): - printf("Transfer error ack signal\n"); - break; - case (0x80000000>>14): - printf("Data parity signal\n"); - break; - case (0x80000000>>15): - printf("Address parity signal\n"); - break; - default: - printf("Unknown values in msr\n"); - } - show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); - panic("machine check"); -} - -void AlignmentException(struct pt_regs *regs) -{ -#if defined(CONFIG_CMD_KGDB) - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - return; -#endif - show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Alignment Exception"); -} - -void ProgramCheckException(struct pt_regs *regs) -{ - unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL; - int i, j; - -#if defined(CONFIG_CMD_KGDB) - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - return; -#endif - show_regs(regs); - - p = (unsigned char *) ((unsigned long)p & 0xFFFFFFE0); - p -= 32; - for (i = 0; i < 256; i+=16) { - printf("%08x: ", (unsigned int)p+i); - for (j = 0; j < 16; j++) { - printf("%02x ", p[i+j]); - } - printf("\n"); - } - - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Program Check Exception"); -} - -void SoftEmuException(struct pt_regs *regs) -{ -#if defined(CONFIG_CMD_KGDB) - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - return; -#endif - show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Software Emulation Exception"); -} - -void UnknownException(struct pt_regs *regs) -{ -#if defined(CONFIG_CMD_KGDB) - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - return; -#endif - printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", - regs->nip, regs->msr, regs->trap); - _exception(0, regs); -} - -/* Probe an address by reading. If not present, return -1, otherwise - * return 0. - */ -int addr_probe(uint *addr) -{ -#if 0 - int retval; - - __asm__ __volatile__( \ - "1: lwz %0,0(%1)\n" \ - " eieio\n" \ - " li %0,0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,-1\n" \ - " b 2b\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 2\n" \ - " .long 1b,3b\n" \ - ".text" \ - : "=r" (retval) : "r"(addr)); - - return (retval); -#endif - return 0; -} diff --git a/arch/powerpc/cpu/74xx_7xx/u-boot.lds b/arch/powerpc/cpu/74xx_7xx/u-boot.lds deleted file mode 100644 index c099849..0000000 --- a/arch/powerpc/cpu/74xx_7xx/u-boot.lds +++ /dev/null @@ -1,78 +0,0 @@ -/* - * (C) Copyright 2010 Wolfgang Denk <wd@denx.de> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -OUTPUT_ARCH(powerpc) - -SECTIONS -{ - .text : - { - arch/powerpc/cpu/74xx_7xx/start.o (.text*) - - *(.text*) - } - _etext = .; - PROVIDE (etext = .); - .rodata : - { - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) - } - - /* Read-write section, merged into data segment: */ - . = (. + 0x00FF) & 0xFFFFFF00; - _erotext = .; - PROVIDE (erotext = .); - .reloc : - { - _GOT2_TABLE_ = .; - KEEP(*(.got2)) - KEEP(*(.got)) - PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4); - _FIXUP_TABLE_ = .; - KEEP(*(.fixup)) - } - __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1; - __fixup_entries = (. - _FIXUP_TABLE_)>>2; - - .data : - { - *(.data*) - *(.sdata*) - } - _edata = .; - PROVIDE (edata = .); - - . = .; - - . = ALIGN(4); - .u_boot_list : { - KEEP(*(SORT(.u_boot_list*))); - } - - - . = .; - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - . = ALIGN(256); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(256); - __init_end = .; - - __bss_start = .; - .bss (NOLOAD) : - { - *(.bss*) - *(.sbss*) - *(COMMON) - . = ALIGN(4); - } - __bss_end = . ; - PROVIDE (end = .); -} diff --git a/arch/powerpc/cpu/mpc8xx/u-boot.lds b/arch/powerpc/cpu/mpc8xx/u-boot.lds deleted file mode 100644 index 0eb2fba..0000000 --- a/arch/powerpc/cpu/mpc8xx/u-boot.lds +++ /dev/null @@ -1,82 +0,0 @@ -/* - * (C) Copyright 2000-2010 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -OUTPUT_ARCH(powerpc) - -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = + SIZEOF_HEADERS; - .text : - { - arch/powerpc/cpu/mpc8xx/start.o (.text*) - arch/powerpc/cpu/mpc8xx/traps.o (.text*) - - *(.text*) - } - _etext = .; - PROVIDE (etext = .); - .rodata : - { - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) - } - - /* Read-write section, merged into data segment: */ - . = (. + 0x00FF) & 0xFFFFFF00; - _erotext = .; - PROVIDE (erotext = .); - .reloc : - { - _GOT2_TABLE_ = .; - KEEP(*(.got2)) - KEEP(*(.got)) - PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4); - _FIXUP_TABLE_ = .; - KEEP(*(.fixup)) - } - __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1; - __fixup_entries = (. - _FIXUP_TABLE_)>>2; - - .data : - { - *(.data*) - *(.sdata*) - } - _edata = .; - PROVIDE (edata = .); - - . = .; - - . = ALIGN(4); - .u_boot_list : { - KEEP(*(SORT(.u_boot_list*))); - } - - - . = .; - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - . = ALIGN(256); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(256); - __init_end = .; - - __bss_start = .; - .bss (NOLOAD) : - { - *(.bss*) - *(.sbss*) - *(COMMON) - . = ALIGN(4); - } - __bss_end = . ; - PROVIDE (end = .); -} diff --git a/arch/powerpc/cpu/ppc4xx/4xx_pci.c b/arch/powerpc/cpu/ppc4xx/4xx_pci.c index 33dc725..b26ec2a 100644 --- a/arch/powerpc/cpu/ppc4xx/4xx_pci.c +++ b/arch/powerpc/cpu/ppc4xx/4xx_pci.c @@ -63,10 +63,6 @@ DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_405GP) || defined(CONFIG_405EP) -#if defined(CONFIG_PMC405) -ushort pmc405_pci_subsys_deviceid(void); -#endif - /*#define DEBUG*/ /* diff --git a/arch/powerpc/cpu/ppc4xx/Kconfig b/arch/powerpc/cpu/ppc4xx/Kconfig index 8f88601..a40ae3b 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/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h index 4430477..c57d9c0 100644 --- a/arch/powerpc/include/asm/global_data.h +++ b/arch/powerpc/include/asm/global_data.h @@ -100,9 +100,6 @@ struct arch_global_data { #if defined(CONFIG_4xx) u32 uart_clk; #endif /* CONFIG_4xx */ -#if defined(CONFIG_SYS_GT_6426x) - unsigned int mirror_hack[16]; -#endif #ifdef CONFIG_SYS_FPGA_COUNT unsigned fpga_state[CONFIG_SYS_FPGA_COUNT]; #endif diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ebf72b3..90e828a 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 5033d2b..62e43c0 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 0000000..e0e3c64 --- /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 cfacc05..6d06d5a 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 6a3dd93..c9983f1 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 bd3558a..0edee6b 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 dca68e4..9441666 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 969b07b..e925310 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 3d7f740..6cf9654 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 0817751..2440a97 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 b95e781..9504735 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 0000000..d5a825d --- /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 f3492c3..ab1aaaa 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 ef1916b..aed3e2b 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 8e97c9b..df79a39 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 125782c..f51f112 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 3b5d6da..97ed884 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 2f13544..0000000 --- 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 6f8c5cd..9490b16 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 65a93ac..0000000 --- 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 3f43f3c..e81054e 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 a739080..0000000 --- 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 0000000..9b097f4 --- /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 bc9b87c..b868283 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 380b64e..6cca7f5 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 3ae1b66..ebdbd03 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 03d491a..24e3052 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 5f05a48..3c11740 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 ac1a808..c30dd4c 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 73262d7..32d7b98 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 d1f8933..1d75cfc 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 b552fe6..a0ef037 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 0000000..7e0506b --- /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 be4eb12..fc211d9 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 fb9afed..7f5ba2c 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; |