From 77ee62d882adc9041711933786230b6cd284d079 Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Fri, 16 May 2014 13:59:46 +0900 Subject: arm: exynos: pinmux: add sdmmc4 gpio configratuion For use dwmmc controller at exynos4, add SDMMC4 gpio configuration. Signed-off-by: Beomho Seo Signed-off-by: Jaehoon Chung Tested-by: Piotr Wilczek Cc: Lukasz Majewski Cc: Piotr Wilczek Cc: Minkyu Kang Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/pinmux.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index ee7c2e5..86a0c75 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -573,15 +573,26 @@ static void exynos4_i2c_config(int peripheral, int flags) static int exynos4_mmc_config(int peripheral, int flags) { int i, start = 0, start_ext = 0; + unsigned int func, ext_func; switch (peripheral) { case PERIPH_ID_SDMMC0: start = EXYNOS4_GPIO_K00; start_ext = EXYNOS4_GPIO_K13; + func = S5P_GPIO_FUNC(0x2); + ext_func = S5P_GPIO_FUNC(0x3); break; case PERIPH_ID_SDMMC2: start = EXYNOS4_GPIO_K20; start_ext = EXYNOS4_GPIO_K33; + func = S5P_GPIO_FUNC(0x2); + ext_func = S5P_GPIO_FUNC(0x3); + break; + case PERIPH_ID_SDMMC4: + start = EXYNOS4_GPIO_K00; + start_ext = EXYNOS4_GPIO_K13; + func = S5P_GPIO_FUNC(0x3); + ext_func = S5P_GPIO_FUNC(0x4); break; default: return -1; @@ -589,13 +600,14 @@ static int exynos4_mmc_config(int peripheral, int flags) for (i = start; i < (start + 7); i++) { if (i == (start + 2)) continue; - gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2)); + gpio_cfg_pin(i, func); gpio_set_pull(i, S5P_GPIO_PULL_NONE); gpio_set_drv(i, S5P_GPIO_DRV_4X); } + /* SDMMC2 do not use 8bit mode at exynos4 */ if (flags & PINMUX_FLAG_8BIT_MODE) { for (i = start_ext; i < (start_ext + 4); i++) { - gpio_cfg_pin(i, S5P_GPIO_FUNC(0x3)); + gpio_cfg_pin(i, ext_func); gpio_set_pull(i, S5P_GPIO_PULL_NONE); gpio_set_drv(i, S5P_GPIO_DRV_4X); } @@ -676,15 +688,26 @@ static void exynos4x12_i2c_config(int peripheral, int flags) static int exynos4x12_mmc_config(int peripheral, int flags) { int i, start = 0, start_ext = 0; + unsigned int func, ext_func; switch (peripheral) { case PERIPH_ID_SDMMC0: start = EXYNOS4X12_GPIO_K00; start_ext = EXYNOS4X12_GPIO_K13; + func = S5P_GPIO_FUNC(0x2); + ext_func = S5P_GPIO_FUNC(0x3); break; case PERIPH_ID_SDMMC2: start = EXYNOS4X12_GPIO_K20; start_ext = EXYNOS4X12_GPIO_K33; + func = S5P_GPIO_FUNC(0x2); + ext_func = S5P_GPIO_FUNC(0x3); + break; + case PERIPH_ID_SDMMC4: + start = EXYNOS4_GPIO_K00; + start_ext = EXYNOS4_GPIO_K13; + func = S5P_GPIO_FUNC(0x3); + ext_func = S5P_GPIO_FUNC(0x4); break; default: return -1; @@ -692,13 +715,13 @@ static int exynos4x12_mmc_config(int peripheral, int flags) for (i = start; i < (start + 7); i++) { if (i == (start + 2)) continue; - gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2)); + gpio_cfg_pin(i, func); gpio_set_pull(i, S5P_GPIO_PULL_NONE); gpio_set_drv(i, S5P_GPIO_DRV_4X); } if (flags & PINMUX_FLAG_8BIT_MODE) { for (i = start_ext; i < (start_ext + 4); i++) { - gpio_cfg_pin(i, S5P_GPIO_FUNC(0x3)); + gpio_cfg_pin(i, ext_func); gpio_set_pull(i, S5P_GPIO_PULL_NONE); gpio_set_drv(i, S5P_GPIO_DRV_4X); } @@ -759,10 +782,10 @@ static int exynos4_pinmux_config(int peripheral, int flags) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC2: + case PERIPH_ID_SDMMC4: return exynos4_mmc_config(peripheral, flags); case PERIPH_ID_SDMMC1: case PERIPH_ID_SDMMC3: - case PERIPH_ID_SDMMC4: debug("SDMMC device %d not implemented\n", peripheral); return -1; default: @@ -794,10 +817,10 @@ static int exynos4x12_pinmux_config(int peripheral, int flags) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC2: + case PERIPH_ID_SDMMC4: return exynos4x12_mmc_config(peripheral, flags); case PERIPH_ID_SDMMC1: case PERIPH_ID_SDMMC3: - case PERIPH_ID_SDMMC4: debug("SDMMC device %d not implemented\n", peripheral); return -1; default: -- cgit v1.1 From 00ee81300f29a25c1e4f0175b93fad6d59df43d9 Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Fri, 16 May 2014 13:59:47 +0900 Subject: arm: exynos: clock: Remove exynos4x12_set_mmc_clk function exynos4x12_set_mmc_clk function have been removed. Because, exynos4x12_clock and exynos4_clock return same div_fsys* value. Signed-off-by: Beomho Seo Signed-off-by: Jaehoon Chung Tested-by: Piotr Wilczek Cc: Lukasz Majewski Cc: Piotr Wilczek Cc: Minkyu Kang Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/clock.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 1fea4d6..2c2029a 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -893,30 +893,6 @@ static void exynos4_set_mmc_clk(int dev_index, unsigned int div) (div & 0xff) << ((dev_index << 4) + 8)); } -/* exynos4x12: set the mmc clock */ -static void exynos4x12_set_mmc_clk(int dev_index, unsigned int div) -{ - struct exynos4x12_clock *clk = - (struct exynos4x12_clock *)samsung_get_base_clock(); - unsigned int addr; - - /* - * CLK_DIV_FSYS1 - * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24] - * CLK_DIV_FSYS2 - * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24] - */ - if (dev_index < 2) { - addr = (unsigned int)&clk->div_fsys1; - } else { - addr = (unsigned int)&clk->div_fsys2; - dev_index -= 2; - } - - clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8), - (div & 0xff) << ((dev_index << 4) + 8)); -} - /* exynos5: set the mmc clock */ static void exynos5_set_mmc_clk(int dev_index, unsigned int div) { @@ -1612,10 +1588,7 @@ void set_mmc_clk(int dev_index, unsigned int div) else exynos5_set_mmc_clk(dev_index, div); } else { - if (proid_is_exynos4412()) - exynos4x12_set_mmc_clk(dev_index, div); - else - exynos4_set_mmc_clk(dev_index, div); + exynos4_set_mmc_clk(dev_index, div); } } -- cgit v1.1 From 39c49756221b53f2672452bef1f4b00a8dbad49c Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 16 May 2014 13:59:50 +0900 Subject: ARM: exynos: clock: modify the set_mmc_clk for exynos4 Modified the mmc_set_clock for eynos4. The goal of this patch is that fsys-div register should be reset. And retore the div-value, not using the value of lowlevel_init. (For using SDMMC4, this patch is needs) Signed-off-by: Jaehoon Chung Tested-by: Lukasz Majewski Acked-by: Lukasz Majewski Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/clock.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 2c2029a..400d134 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -869,7 +869,7 @@ static void exynos4_set_mmc_clk(int dev_index, unsigned int div) { struct exynos4_clock *clk = (struct exynos4_clock *)samsung_get_base_clock(); - unsigned int addr; + unsigned int addr, clear_bit, set_bit; /* * CLK_DIV_FSYS1 @@ -877,20 +877,26 @@ static void exynos4_set_mmc_clk(int dev_index, unsigned int div) * CLK_DIV_FSYS2 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24] * CLK_DIV_FSYS3 - * MMC4_PRE_RATIO [15:8] + * MMC4_RATIO [3:0] */ if (dev_index < 2) { addr = (unsigned int)&clk->div_fsys1; - } else if (dev_index == 4) { + clear_bit = MASK_PRE_RATIO(dev_index); + set_bit = SET_PRE_RATIO(dev_index, div); + } else if (dev_index == 4) { addr = (unsigned int)&clk->div_fsys3; dev_index -= 4; + /* MMC4 is controlled with the MMC4_RATIO value */ + clear_bit = MASK_RATIO(dev_index); + set_bit = SET_RATIO(dev_index, div); } else { addr = (unsigned int)&clk->div_fsys2; dev_index -= 2; + clear_bit = MASK_PRE_RATIO(dev_index); + set_bit = SET_PRE_RATIO(dev_index, div); } - clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8), - (div & 0xff) << ((dev_index << 4) + 8)); + clrsetbits_le32(addr, clear_bit, set_bit); } /* exynos5: set the mmc clock */ -- cgit v1.1 From 12bbc0ba813463fd3c7b433c37abcd3f67b37ff3 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Wed, 19 Mar 2014 14:48:44 +0800 Subject: ARM: atmel: switch to main crystal osc for SPL boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If without switch to main crystal oscillator, the sama5d3 SoC will use internal on chip RC oscillator. In order to get better accuracy, switch to main crystal oscillator. Signed-off-by: Bo Shen Signed-off-by: Andreas Bießmann --- arch/arm/cpu/at91-common/spl.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/at91-common/spl.c b/arch/arm/cpu/at91-common/spl.c index 7f4debb..cbb5a52 100644 --- a/arch/arm/cpu/at91-common/spl.c +++ b/arch/arm/cpu/at91-common/spl.c @@ -20,6 +20,43 @@ static void at91_disable_wdt(void) writel(AT91_WDT_MR_WDDIS, &wdt->mr); } +static void switch_to_main_crystal_osc(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + u32 tmp; + + tmp = readl(&pmc->mor); + tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff); + tmp &= ~AT91_PMC_MOR_KEY(0xff); + tmp |= AT91_PMC_MOR_MOSCEN; + tmp |= AT91_PMC_MOR_OSCOUNT(8); + tmp |= AT91_PMC_MOR_KEY(0x37); + writel(tmp, &pmc->mor); + while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS)) + ; + + tmp = readl(&pmc->mor); + tmp &= ~AT91_PMC_MOR_OSCBYPASS; + tmp &= ~AT91_PMC_MOR_KEY(0xff); + tmp |= AT91_PMC_MOR_KEY(0x37); + writel(tmp, &pmc->mor); + + tmp = readl(&pmc->mor); + tmp |= AT91_PMC_MOR_MOSCSEL; + tmp &= ~AT91_PMC_MOR_KEY(0xff); + tmp |= AT91_PMC_MOR_KEY(0x37); + writel(tmp, &pmc->mor); + + while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS)) + ; + + tmp = readl(&pmc->mor); + tmp &= ~AT91_PMC_MOR_MOSCRCEN; + tmp &= ~AT91_PMC_MOR_KEY(0xff); + tmp |= AT91_PMC_MOR_KEY(0x37); + writel(tmp, &pmc->mor); +} + void at91_plla_init(u32 pllar) { struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; @@ -76,6 +113,8 @@ u32 spl_boot_mode(void) void s_init(void) { + switch_to_main_crystal_osc(); + /* disable watchdog */ at91_disable_wdt(); -- cgit v1.1 From 5c390a5b26ce53a6534b99c22bb762484e6b3497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= Date: Mon, 19 May 2014 14:23:40 +0200 Subject: arm:at91: enable ROM loadable atmel image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For sama5d3xek we need to modify the SPL image for correct detection by ROM code. Signed-off-by: Andreas Bießmann Tested-by: Bo Shen --- arch/arm/cpu/armv7/at91/config.mk | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 arch/arm/cpu/armv7/at91/config.mk (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/at91/config.mk b/arch/arm/cpu/armv7/at91/config.mk new file mode 100644 index 0000000..09eab70 --- /dev/null +++ b/arch/arm/cpu/armv7/at91/config.mk @@ -0,0 +1,10 @@ +# +# Copyright (C) 2014, Andreas Bießmann +# +# SPDX-License-Identifier: GPL-2.0+ +# +ifdef CONFIG_SPL_BUILD +ALL-y += boot.bin +else +ALL-y += u-boot.img +endif -- cgit v1.1 From cf874c190e1796a77be6661cacc43aebb94c7a57 Mon Sep 17 00:00:00 2001 From: "Wu, Josh" Date: Wed, 21 May 2014 10:42:15 +0800 Subject: ARM: at91sam9m10g45ek: enable mci0 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also we enable the mmc command in configuration file. As both CONFIG_CMD_MMC and CONFIG_CMD_USB use the CONFIG_DOS_PARTITION, so remove the redundant CONFIG_DOS_PARTITION definition. Signed-off-by: Josh Wu Signed-off-by: Andreas Bießmann --- arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c b/arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c index 7d7725c..0e6c0da 100644 --- a/arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c +++ b/arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c @@ -165,3 +165,20 @@ void at91_macb_hw_init(void) #endif } #endif + +#ifdef CONFIG_GENERIC_ATMEL_MCI +void at91_mci_hw_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + at91_set_a_periph(AT91_PIO_PORTA, 0, 0); /* MCI0 CLK */ + at91_set_a_periph(AT91_PIO_PORTA, 1, 0); /* MCI0 CDA */ + at91_set_a_periph(AT91_PIO_PORTA, 2, 0); /* MCI0 DA0 */ + at91_set_a_periph(AT91_PIO_PORTA, 3, 0); /* MCI0 DA1 */ + at91_set_a_periph(AT91_PIO_PORTA, 4, 0); /* MCI0 DA2 */ + at91_set_a_periph(AT91_PIO_PORTA, 5, 0); /* MCI0 DA3 */ + + /* Enable clock */ + writel(1 << ATMEL_ID_MCI0, &pmc->pcer); +} +#endif -- cgit v1.1 From eb0dd9986c3883820ff888c3738b013c0a7d918c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 20 May 2014 06:01:40 -0600 Subject: exynos: Enable PSHOLD in SPL There is quite a tight deadline in enabling PSHOLD, less than a second. In some cases (e.g. with USB download), U-Boot takes longer than that to load, so the board powers off before U-Boot starts. Add a call in SPL to enable PSHOLD. Signed-off-by: Simon Glass Reviewed-by: Lukasz Majewski Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 11fe5b8..48b5511 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -48,6 +48,8 @@ int do_lowlevel_init(void) arch_cpu_init(); + set_ps_hold_ctrl(); + reset_status = get_reset_status(); switch (reset_status) { -- cgit v1.1 From ae4223f4444d7e673ff6b4a066c8584858629025 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 10 Apr 2014 20:01:23 -0600 Subject: Remove unnecessary use of hush header file Some files include hush.h but don't actually use it. Remove this where possible. Signed-off-by: Simon Glass --- arch/arm/cpu/arm926ejs/kirkwood/cpu.c | 1 - arch/arm/cpu/arm926ejs/orion5x/cpu.c | 1 - 2 files changed, 2 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c index d4711c0..0937506 100644 --- a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c +++ b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c @@ -13,7 +13,6 @@ #include #include #include -#include #define BUFLEN 16 diff --git a/arch/arm/cpu/arm926ejs/orion5x/cpu.c b/arch/arm/cpu/arm926ejs/orion5x/cpu.c index b55c5f0..f88db3b 100644 --- a/arch/arm/cpu/arm926ejs/orion5x/cpu.c +++ b/arch/arm/cpu/arm926ejs/orion5x/cpu.c @@ -15,7 +15,6 @@ #include #include #include -#include #define BUFLEN 16 -- cgit v1.1 From 567802bbd6bf1c809d37fef9244fc8a692244e73 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Thu, 29 May 2014 21:40:54 +0530 Subject: Exynos: Make sure ps_hold gets set in the SPL Setting ps_hold ought to be one of the first things we do when we first boot up. If we wait until the main u-boot runs we won't set it in time and the PMIC may power us back off. Signed-off-by: Doug Anderson Signed-off-by: Akshay Saraswat Acked-by: Simon Glass Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 6 +++++- arch/arm/cpu/armv7/exynos/power.c | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 48b5511..dcc270f 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -39,6 +39,7 @@ enum { DO_CLOCKS = 1 << 1, DO_MEM_RESET = 1 << 2, DO_UART = 1 << 3, + DO_POWER = 1 << 4, }; int do_lowlevel_init(void) @@ -62,9 +63,12 @@ int do_lowlevel_init(void) break; default: /* This is a normal boot (not a wake from sleep) */ - actions = DO_CLOCKS | DO_MEM_RESET; + actions = DO_CLOCKS | DO_MEM_RESET | DO_POWER; } + if (actions & DO_POWER) + set_ps_hold_ctrl(); + if (actions & DO_CLOCKS) { system_clock_init(); mem_ctrl_init(actions & DO_MEM_RESET); diff --git a/arch/arm/cpu/armv7/exynos/power.c b/arch/arm/cpu/armv7/exynos/power.c index 563abd7..638ee0b 100644 --- a/arch/arm/cpu/armv7/exynos/power.c +++ b/arch/arm/cpu/armv7/exynos/power.c @@ -112,6 +112,12 @@ static void exynos5_set_ps_hold_ctrl(void) EXYNOS_PS_HOLD_CONTROL_DATA_HIGH); } +/* + * Set ps_hold data driving value high + * This enables the machine to stay powered on + * after the initial power-on condition goes away + * (e.g. power button). + */ void set_ps_hold_ctrl(void) { if (cpu_is_exynos5()) -- cgit v1.1 From 68128e0a86810c9ea9bebcb69451aeabfd44c491 Mon Sep 17 00:00:00 2001 From: pekon gupta Date: Tue, 6 May 2014 00:46:20 +0530 Subject: omap3: remove remnant macros GPMC_NAND_ECC_LP_x8_LAYOUT and GPMC_NAND_ECC_LP_x16_LAYOUT OMAP3 used GPMC_NAND_ECC_LP_x8_LAYOUT and GPMC_NAND_ECC_LP_x16_LAYOUT macros to configure GPMC controller for x7 or x8 bit device connected to its interface. Now this information is encoded in CONFIG_SYS_NAND_DEVICE_WIDTH macro, so above macros can be completely removed. Signed-off-by: Pekon Gupta --- arch/arm/cpu/armv7/omap3/mem.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap3/mem.c b/arch/arm/cpu/armv7/omap3/mem.c index e649409..1832aff 100644 --- a/arch/arm/cpu/armv7/omap3/mem.c +++ b/arch/arm/cpu/armv7/omap3/mem.c @@ -21,17 +21,6 @@ struct gpmc *gpmc_cfg; #if defined(CONFIG_CMD_NAND) -#if defined(GPMC_NAND_ECC_SP_x8_LAYOUT) || defined(GPMC_NAND_ECC_LP_x8_LAYOUT) -static const u32 gpmc_m_nand[GPMC_MAX_REG] = { - SMNAND_GPMC_CONFIG1, - SMNAND_GPMC_CONFIG2, - SMNAND_GPMC_CONFIG3, - SMNAND_GPMC_CONFIG4, - SMNAND_GPMC_CONFIG5, - SMNAND_GPMC_CONFIG6, - 0, -}; -#else static const u32 gpmc_m_nand[GPMC_MAX_REG] = { M_NAND_GPMC_CONFIG1, M_NAND_GPMC_CONFIG2, @@ -40,7 +29,6 @@ static const u32 gpmc_m_nand[GPMC_MAX_REG] = { M_NAND_GPMC_CONFIG5, M_NAND_GPMC_CONFIG6, 0 }; -#endif #endif /* CONFIG_CMD_NAND */ #if defined(CONFIG_CMD_ONENAND) -- cgit v1.1 From 7a5f71bc4056591574ea122ba58c55d14145eeb0 Mon Sep 17 00:00:00 2001 From: Sourav Poddar Date: Mon, 19 May 2014 16:53:37 -0400 Subject: am43xx_evm: Add qspiboot target The ePOS EVM and EVM SK have QSPI as an option to boot. Add a qspiboot target that utilizes QSPI for env and so forth as an example of best practices. As QSPI is booted from directly we need to chang CONFIG_SYS_TEXT_BASE. Note that on ePOS EVM the QSPI and NAND are mutually exclusive choices we need to handle that elsewhere, once NAND support is also added. Signed-off-by: Sourav Poddar Signed-off-by: Tom Rini --- arch/arm/cpu/armv7/am33xx/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c index 28c16f8..e5c922a 100644 --- a/arch/arm/cpu/armv7/am33xx/board.c +++ b/arch/arm/cpu/armv7/am33xx/board.c @@ -224,7 +224,7 @@ void s_init(void) set_uart_mux_conf(); setup_clocks_for_console(); uart_soft_reset(); -#ifdef CONFIG_NOR_BOOT +#if defined(CONFIG_NOR_BOOT) || defined(CONFIG_QSPI_BOOT) gd->baudrate = CONFIG_BAUDRATE; serial_init(); gd->have_console = 1; -- cgit v1.1 From 87acf194a298f65a40c659036a5e413613d458e6 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 21 May 2014 12:57:21 -0400 Subject: arm:am33xx: Make dram_init call sdram_init() in some contexts We have two contexts for booting these platforms. One is SPL which is roughly: reset, cpu_init_crit, lowlevel_init, s_init, sdram_init, _main, board_init_f from SPL, ... then U-Boot loads. The other is a memory-mapped XIP case (NOR or QSPI) where we do not run an SPL. In this case we go, roughly: reset, cpu_init_crit, lowlevel_init, s_init, _main, regular board_init_f. In the first case s_init will set a valid gd and then be able to call sdram_init which in many cases will need i2c (which needs a valid gd for gd->cur_i2c_bus). In this second case we must (and are able to and should) defer sdram_init() into dram_init() called by board_init_f as gd will have been set in _main and cleared in board_init_f. Signed-off-by: Tom Rini --- arch/arm/cpu/armv7/am33xx/board.c | 2 ++ arch/arm/cpu/armv7/am33xx/emif4.c | 4 ++++ 2 files changed, 6 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c index e5c922a..9a69b6c 100644 --- a/arch/arm/cpu/armv7/am33xx/board.c +++ b/arch/arm/cpu/armv7/am33xx/board.c @@ -238,7 +238,9 @@ void s_init(void) /* Enable RTC32K clock */ rtc32k_enable(); #endif +#ifdef CONFIG_SPL_BUILD sdram_init(); +#endif } #endif diff --git a/arch/arm/cpu/armv7/am33xx/emif4.c b/arch/arm/cpu/armv7/am33xx/emif4.c index 2c67c32..a7a3e88 100644 --- a/arch/arm/cpu/armv7/am33xx/emif4.c +++ b/arch/arm/cpu/armv7/am33xx/emif4.c @@ -21,6 +21,10 @@ DECLARE_GLOBAL_DATA_PTR; int dram_init(void) { +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + sdram_init(); +#endif + /* dram_init must store complete ramsize in gd->ram_size */ gd->ram_size = get_ram_size( (void *)CONFIG_SYS_SDRAM_BASE, -- cgit v1.1 From 196311dc728bbb9484356547b9daa731ca2feb8d Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 21 May 2014 12:57:22 -0400 Subject: arm:am33xx: Rework s_init and add board_early_init_f With the changes to the i2c framework (and adopting the omap24xx_i2c driver to them) we can no longer call i2c functions prior to gd having been set and cleared. When SPL booting, this is handled by setting gd to point to SRAM in s_init. However in the cases where we are loaded directly by ROM (memory mapped NOR or QSPI) we need to make use of the normal hooks to slightly delay these calls. Signed-off-by: Tom Rini --- arch/arm/cpu/armv7/am33xx/board.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c index 9a69b6c..7fe049e 100644 --- a/arch/arm/cpu/armv7/am33xx/board.c +++ b/arch/arm/cpu/armv7/am33xx/board.c @@ -144,6 +144,19 @@ int arch_misc_init(void) #ifndef CONFIG_SKIP_LOWLEVEL_INIT /* + * In the case of non-SPL based booting we'll want to call these + * functions a tiny bit later as it will require gd to be set and cleared + * and that's not true in s_init in this case so we cannot do it there. + */ +int board_early_init_f(void) +{ + prcm_init(); + set_mux_conf_regs(); + + return 0; +} + +/* * This function is the place to do per-board things such as ramp up the * MPU clock frequency. */ @@ -232,13 +245,12 @@ void s_init(void) gd = &gdata; preloader_console_init(); #endif - prcm_init(); - set_mux_conf_regs(); #if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC) /* Enable RTC32K clock */ rtc32k_enable(); #endif #ifdef CONFIG_SPL_BUILD + board_early_init_f(); sdram_init(); #endif } -- cgit v1.1 From afee59cd49449e7b7d538d919b6e8ab5184e5b93 Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Thu, 29 May 2014 18:57:12 +0300 Subject: keystone: init: enable UART1 to be able use it from kernel Currently PWREMU_MGMT is not configured in the Linux generic UART driver as this register seems to be specific TI UART IP. So this needs to be enabled in u-boot to use UART1 from kernel space. Acked-By: Vitaly Andrianov Signed-off-by: Murali Karicheri Signed-off-by: Ivan Khoronzhuk --- arch/arm/cpu/armv7/keystone/init.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/keystone/init.c b/arch/arm/cpu/armv7/keystone/init.c index 044015a..4df5ae1 100644 --- a/arch/arm/cpu/armv7/keystone/init.c +++ b/arch/arm/cpu/armv7/keystone/init.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -30,6 +31,14 @@ int arch_cpu_init(void) share_all_segments(11); /* PCIE */ #endif + /* + * just initialise the COM2 port so that TI specific + * UART register PWREMU_MGMT is initialized. Linux UART + * driver doesn't handle this. + */ + NS16550_init((NS16550_t)(CONFIG_SYS_NS16550_COM2), + CONFIG_SYS_NS16550_CLK / 16 / CONFIG_BAUDRATE); + return 0; } -- cgit v1.1 From ccd2f8db814b88bf4f7a7d418048051d259014a4 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Mon, 2 Jun 2014 10:49:03 +0530 Subject: ARM: AM43xx: Fix UART clocks enabling After enabling a module, SW has to wait on IDLEST bit until it is Fully functional. This wait is missing for UART module and there is a immediate access of UART registers after this. So there is a chance of hang on this module( This can happen when we are running from MPU SRAM). So waiting for IDLEST bit. Signed-off-by: Lokesh Vutla --- arch/arm/cpu/armv7/am33xx/clock_am43xx.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/clock_am43xx.c b/arch/arm/cpu/armv7/am33xx/clock_am43xx.c index d0bc234..31188c8 100644 --- a/arch/arm/cpu/armv7/am33xx/clock_am43xx.c +++ b/arch/arm/cpu/armv7/am33xx/clock_am43xx.c @@ -53,6 +53,8 @@ const struct dpll_regs dpll_ddr_regs = { void setup_clocks_for_console(void) { + u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED; + /* Do not add any spl_debug prints in this function */ clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, CD_CLKCTRL_CLKTRCTRL_SW_WKUP << @@ -63,6 +65,13 @@ void setup_clocks_for_console(void) MODULE_CLKCTRL_MODULEMODE_MASK, MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << MODULE_CLKCTRL_MODULEMODE_SHIFT); + + while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) || + (idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) { + clkctrl = readl(&cmwkup->wkup_uart0ctrl); + idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >> + MODULE_CLKCTRL_IDLEST_SHIFT; + } } void enable_basic_clocks(void) -- cgit v1.1 From 64ce2fbd6c9ebb68e274ae1b3c449e1cae86c5b6 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 5 Jun 2014 11:15:28 -0400 Subject: arm:am33xx: Add a scale_vcores() hook Similar to OMAP4/5 we need to scale the voltage up prior to changing the clock frequencies up higher. Add a similar hook to start with. Signed-off-by: Tom Rini --- arch/arm/cpu/armv7/am33xx/clock.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/clock.c b/arch/arm/cpu/armv7/am33xx/clock.c index 0672798..ec7d468 100644 --- a/arch/arm/cpu/armv7/am33xx/clock.c +++ b/arch/arm/cpu/armv7/am33xx/clock.c @@ -170,8 +170,19 @@ void do_enable_clocks(u32 *const *clk_domains, }; } +/* + * Before scaling up the clocks we need to have the PMIC scale up the + * voltages first. This will be dependent on which PMIC is in use + * and in some cases we may not be scaling things up at all and thus not + * need to do anything here. + */ +__weak void scale_vcores(void) +{ +} + void prcm_init() { enable_basic_clocks(); + scale_vcores(); setup_dplls(); } -- cgit v1.1 From b924d586d70bd52c3648870d3313b2ea7081c83d Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 21 May 2014 14:29:23 +0100 Subject: arm64: zero cntvoff_el2 Currently cntvoff_el2 is initialised with an arbitrary bag of bits derived from the initial value of cnthctl_el2 on the current CPU. This is somewhat odd and problematic as some of these bits are UNKNOWN at reset and may differ across CPUs (which may cause an OS at EL1 to observe time going backwards across CPUs). This patch instead initialises cntvoff_el2 with xzr, giving the register a consistent value of zero on all CPUs. Signed-off-by: Mark Rutland Acked-by: Marc Zyngier Acked-by: Catalin Marinas Cc: Scott Wood Cc: David Feng Cc: Tom Rini Acked-by: David.Feng --- arch/arm/cpu/armv8/transition.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S index e0a5946..38dea5c 100644 --- a/arch/arm/cpu/armv8/transition.S +++ b/arch/arm/cpu/armv8/transition.S @@ -43,7 +43,7 @@ ENTRY(armv8_switch_to_el1) mrs x0, cnthctl_el2 orr x0, x0, #0x3 /* Enable EL1 access to timers */ msr cnthctl_el2, x0 - msr cntvoff_el2, x0 + msr cntvoff_el2, xzr mrs x0, cntkctl_el1 orr x0, x0, #0x3 /* Enable EL0 access to timers */ msr cntkctl_el1, x0 -- cgit v1.1 From 7e4154a553c56ccbf877ac830e15b9c23815eb4d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 2 Jun 2014 22:04:48 -0600 Subject: am33xx/omap: Allow cache enable for all Sitara/OMAP Enable the cache for all devices, unless CONFIG_SYS_DCACHE_OFF is defined. This speeds up the Beaglebone Black boot considerable. (Tested only on Beaglebone Black with SD card boot) Signed-off-by: Simon Glass --- arch/arm/cpu/armv7/am33xx/board.c | 8 ---- arch/arm/cpu/armv7/omap-common/Makefile | 4 ++ arch/arm/cpu/armv7/omap-common/hwinit-common.c | 42 ------------------- arch/arm/cpu/armv7/omap-common/omap-cache.c | 56 ++++++++++++++++++++++++++ arch/arm/cpu/armv7/omap3/board.c | 8 ---- 5 files changed, 60 insertions(+), 58 deletions(-) create mode 100644 arch/arm/cpu/armv7/omap-common/omap-cache.c (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c index 7fe049e..828d10b 100644 --- a/arch/arm/cpu/armv7/am33xx/board.c +++ b/arch/arm/cpu/armv7/am33xx/board.c @@ -255,11 +255,3 @@ void s_init(void) #endif } #endif - -#ifndef CONFIG_SYS_DCACHE_OFF -void enable_caches(void) -{ - /* Enable D-cache. I-cache is already enabled in start.S */ - dcache_enable(); -} -#endif /* !CONFIG_SYS_DCACHE_OFF */ diff --git a/arch/arm/cpu/armv7/omap-common/Makefile b/arch/arm/cpu/armv7/omap-common/Makefile index 5f5132f..7695e16 100644 --- a/arch/arm/cpu/armv7/omap-common/Makefile +++ b/arch/arm/cpu/armv7/omap-common/Makefile @@ -22,6 +22,10 @@ obj-y += pipe3-phy.o obj-$(CONFIG_SCSI_AHCI_PLAT) += sata.o endif +ifeq ($(CONFIG_SYS_DCACHE_OFF),) +obj-y += omap-cache.o +endif + ifeq ($(CONFIG_OMAP34XX),) obj-y += boot-common.o obj-y += lowlevel_init.o diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c index ba97d9e..5f50a19 100644 --- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c +++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c @@ -18,13 +18,8 @@ #include #include #include -#include #include -#define ARMV7_DCACHE_WRITEBACK 0xe -#define ARMV7_DOMAIN_CLIENT 1 -#define ARMV7_DOMAIN_MASK (0x3 << 0) - DECLARE_GLOBAL_DATA_PTR; void do_set_mux(u32 base, struct pad_conf_entry const *array, int size) @@ -263,40 +258,3 @@ int print_cpuinfo(void) return 0; } #endif - -#ifndef CONFIG_SYS_DCACHE_OFF -void enable_caches(void) -{ - /* Enable D-cache. I-cache is already enabled in start.S */ - dcache_enable(); -} - -void dram_bank_mmu_setup(int bank) -{ - bd_t *bd = gd->bd; - int i; - - u32 start = bd->bi_dram[bank].start >> 20; - u32 size = bd->bi_dram[bank].size >> 20; - u32 end = start + size; - - debug("%s: bank: %d\n", __func__, bank); - for (i = start; i < end; i++) - set_section_dcache(i, ARMV7_DCACHE_WRITEBACK); - -} - -void arm_init_domains(void) -{ - u32 reg; - - reg = get_dacr(); - /* - * Set DOMAIN to client access so that all permissions - * set in pagetables are validated by the mmu. - */ - reg &= ~ARMV7_DOMAIN_MASK; - reg |= ARMV7_DOMAIN_CLIENT; - set_dacr(reg); -} -#endif diff --git a/arch/arm/cpu/armv7/omap-common/omap-cache.c b/arch/arm/cpu/armv7/omap-common/omap-cache.c new file mode 100644 index 0000000..579bebf --- /dev/null +++ b/arch/arm/cpu/armv7/omap-common/omap-cache.c @@ -0,0 +1,56 @@ +/* + * + * Common functions for OMAP4/5 based boards + * + * (C) Copyright 2010 + * Texas Instruments, + * + * Author : + * Aneesh V + * Steve Sakoman + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define ARMV7_DCACHE_WRITEBACK 0xe +#define ARMV7_DOMAIN_CLIENT 1 +#define ARMV7_DOMAIN_MASK (0x3 << 0) + +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} + +void dram_bank_mmu_setup(int bank) +{ + bd_t *bd = gd->bd; + int i; + + u32 start = bd->bi_dram[bank].start >> 20; + u32 size = bd->bi_dram[bank].size >> 20; + u32 end = start + size; + + debug("%s: bank: %d\n", __func__, bank); + for (i = start; i < end; i++) + set_section_dcache(i, ARMV7_DCACHE_WRITEBACK); +} + +void arm_init_domains(void) +{ + u32 reg; + + reg = get_dacr(); + /* + * Set DOMAIN to client access so that all permissions + * set in pagetables are validated by the mmu. + */ + reg &= ~ARMV7_DOMAIN_MASK; + reg |= ARMV7_DOMAIN_CLIENT; + set_dacr(reg); +} diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c index 9bb1a1c..e252e7f 100644 --- a/arch/arm/cpu/armv7/omap3/board.c +++ b/arch/arm/cpu/armv7/omap3/board.c @@ -478,11 +478,3 @@ void omap3_outer_cache_disable(void) omap3_update_aux_cr(0, 0x2); } #endif /* !CONFIG_SYS_L2CACHE_OFF */ - -#ifndef CONFIG_SYS_DCACHE_OFF -void enable_caches(void) -{ - /* Enable D-cache. I-cache is already enabled in start.S */ - dcache_enable(); -} -#endif /* !CONFIG_SYS_DCACHE_OFF */ -- cgit v1.1 From 73671dad49bf2368959b7bf0e30ba931ea95565c Mon Sep 17 00:00:00 2001 From: Thomas Betker Date: Thu, 5 Jun 2014 20:07:56 +0200 Subject: Check run_command() return code properly run_command() returns 0 for success, 1 for failure. Fix places which assume that failure is indicated by a negative return code. Signed-off-by: Thomas Betker Acked-by: Simon Glass Tested-by: Simon Glass Tested-by: Stefan Roese --- arch/arm/cpu/arm926ejs/kirkwood/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c index 0937506..da80240 100644 --- a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c +++ b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c @@ -210,7 +210,7 @@ static void kw_sysrst_action(void) debug("Starting %s process...\n", __FUNCTION__); ret = run_command(s, 0); - if (ret < 0) + if (ret != 0) debug("Error.. %s failed\n", __FUNCTION__); else debug("%s process finished\n", __FUNCTION__); -- cgit v1.1 From 4b9ca09399c6b5105d2bd1860f183d7a95e05f5c Mon Sep 17 00:00:00 2001 From: Vasili Galka Date: Tue, 10 Jun 2014 16:06:52 +0300 Subject: cosmetic: Whitespace fix Signed-off-by: Vasili Galka --- arch/arm/cpu/armv7/exynos/spl_boot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c index ade45fd..7916630 100644 --- a/arch/arm/cpu/armv7/exynos/spl_boot.c +++ b/arch/arm/cpu/armv7/exynos/spl_boot.c @@ -4,8 +4,8 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include -#include +#include +#include #include #include -- cgit v1.1 From 7922a2d479b6cdce853b853b80d94675b955a66a Mon Sep 17 00:00:00 2001 From: Minkyu Kang Date: Fri, 13 Jun 2014 17:00:56 +0900 Subject: Revert "exynos: Enable PSHOLD in SPL" This reverts commit eb0dd9986c3883820ff888c3738b013c0a7d918c. --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index dcc270f..83e1dcf 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -49,8 +49,6 @@ int do_lowlevel_init(void) arch_cpu_init(); - set_ps_hold_ctrl(); - reset_status = get_reset_status(); switch (reset_status) { -- cgit v1.1 From cfde7588d8ad22560e2328574a4f415642170b92 Mon Sep 17 00:00:00 2001 From: Akshay Saraswat Date: Mon, 26 May 2014 19:17:03 +0530 Subject: Exynos5: DMC: Modify the definition of ddr3_mem_ctrl_init Passing fewer arguments is better and mem_iv_size is never used. Let's keep only one argument and make it cleaner. Signed-off-by: Hatim Ali Signed-off-by: Akshay Saraswat Acked-by: Simon Glass Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/dmc_common.c | 2 +- arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 7 ++----- arch/arm/cpu/armv7/exynos/exynos5_setup.h | 9 ++------- 3 files changed, 5 insertions(+), 13 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c b/arch/arm/cpu/armv7/exynos/dmc_common.c index cca925e..9b6ee69 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_common.c +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c @@ -162,7 +162,7 @@ void mem_ctrl_init(int reset) /* If there are any other memory variant, add their init call below */ if (param->mem_type == DDR_MODE_DDR3) { - ret = ddr3_mem_ctrl_init(mem, param->mem_iv_size, reset); + ret = ddr3_mem_ctrl_init(mem, reset); if (ret) { /* will hang if failed to init memory control */ while (1) diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c index 487e6f4..4481ab4 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -28,8 +28,7 @@ static void reset_phy_ctrl(void) writel(DDR3PHY_CTRL_PHY_RESET, &clk->lpddr3phy_ctrl); } -int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, - int reset) +int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) { unsigned int val; struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl; @@ -221,8 +220,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, #endif #ifdef CONFIG_EXYNOS5420 -int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, - int reset) +int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) { struct exynos5420_clock *clk = (struct exynos5420_clock *)samsung_get_base_clock(); @@ -244,7 +242,6 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, tzasc0 = (struct exynos5420_tzasc *)samsung_get_base_dmc_tzasc(); tzasc1 = (struct exynos5420_tzasc *)(samsung_get_base_dmc_tzasc() + DMC_OFFSET); - /* Enable PAUSE for DREX */ setbits_le32(&clk->pause, ENABLE_BIT); diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index 53b0ace..314d6f4 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -890,16 +890,11 @@ enum { /* * Memory variant specific initialization code for DDR3 * - * @param mem Memory timings for this memory type. - * @param mem_iv_size Memory interleaving size is a configurable parameter - * which the DMC uses to decide how to split a memory - * chunk into smaller chunks to support concurrent - * accesses; may vary across boards. + * @param mem Memory timings for this memory type. * @param reset Reset DDR PHY during initialization. * @return 0 if ok, SETUP_ERR_... if there is a problem */ -int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, - int reset); +int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset); /* Memory variant specific initialization code for LPDDR3 */ void lpddr3_mem_ctrl_init(void); -- cgit v1.1 From aacdd79095b0a7c258a76e4fdfc133af16b07dc0 Mon Sep 17 00:00:00 2001 From: Akshay Saraswat Date: Mon, 26 May 2014 19:18:06 +0530 Subject: Exynos5420: Remove code for enabling read leveling This patch intends to remove all code which enables hardware read leveling. All characterization environments may not cope up with h/w read leveling enabled, so we must disable this. Also, disabling h/w read leveling improves the MIF LVcc value (LVcc value is the value at which DDR will fail to work properly). Improving LVcc means we have enough voltage margin for MIF. When h/w leveling is enabled, we have almost zero volatge margin. Signed-off-by: Alim Akhtar Signed-off-by: Akshay Saraswat Acked-by: Simon Glass Tested-by: Simon Glass Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 71 ------------------------------- 1 file changed, 71 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c index 4481ab4..1d6048c 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -519,77 +519,6 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) &drex1->directcmd); } - if (mem->read_leveling_enable) { - /* Set Read DQ Calibration */ - val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4; - for (chip = 0; chip < mem->chips_to_configure; chip++) { - writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), - &drex0->directcmd); - writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), - &drex1->directcmd); - } - - val = readl(&phy0_ctrl->phy_con1); - val |= READ_LEVELLING_DDR3; - writel(val, &phy0_ctrl->phy_con1); - val = readl(&phy1_ctrl->phy_con1); - val |= READ_LEVELLING_DDR3; - writel(val, &phy1_ctrl->phy_con1); - - val = readl(&phy0_ctrl->phy_con2); - val |= (RDLVL_EN | RDLVL_INCR_ADJ); - writel(val, &phy0_ctrl->phy_con2); - val = readl(&phy1_ctrl->phy_con2); - val |= (RDLVL_EN | RDLVL_INCR_ADJ); - writel(val, &phy1_ctrl->phy_con2); - - setbits_le32(&drex0->rdlvl_config, - CTRL_RDLVL_DATA_ENABLE); - i = TIMEOUT; - while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) - != RDLVL_COMPLETE_CHO) && (i > 0)) { - /* - * TODO(waihong): Comment on how long this take - * to timeout - */ - sdelay(100); - i--; - } - if (!i) - return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; - - clrbits_le32(&drex0->rdlvl_config, - CTRL_RDLVL_DATA_ENABLE); - setbits_le32(&drex1->rdlvl_config, - CTRL_RDLVL_DATA_ENABLE); - i = TIMEOUT; - while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) - != RDLVL_COMPLETE_CHO) && (i > 0)) { - /* - * TODO(waihong): Comment on how long this take - * to timeout - */ - sdelay(100); - i--; - } - if (!i) - return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; - - clrbits_le32(&drex1->rdlvl_config, - CTRL_RDLVL_DATA_ENABLE); - - val = (0x3 << DIRECT_CMD_BANK_SHIFT); - for (chip = 0; chip < mem->chips_to_configure; chip++) { - writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), - &drex0->directcmd); - writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), - &drex1->directcmd); - } - - update_reset_dll(&drex0->phycontrol0, DDR_MODE_DDR3); - update_reset_dll(&drex1->phycontrol0, DDR_MODE_DDR3); - } - /* Common Settings for Leveling */ val = PHY_CON12_RESET_VAL; writel((val + n_lock_w_phy0), &phy0_ctrl->phy_con12); -- cgit v1.1 From c9334fcda90652e2f8c49f4517b728ebc6f5f623 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Mon, 26 May 2014 19:19:05 +0530 Subject: DMC: exynos5420: Gate CLKM to when reading PHY_CON13 when CLKM is running. If we stop CLKM when sampling it the glitches all go away, so we'll do that as per Samsung suggestion. We also check the "is it locked" bits of PHY_CON13 and loop until they show the the value sampled actually represents a locked value. It doesn't appear that the glitching and "is it locked" are related, but it seems wise to wait until the PHY tells us the value is good before we use it. In practice we will not loop more than a couple times (and usually won't loop at all). Signed-off-by: Doug Anderson Signed-off-by: Akshay Saraswat Acked-by: Simon Glass Tested-by: Simon Glass Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 43 +++++++++++++++++++++++++++---- arch/arm/cpu/armv7/exynos/exynos5_setup.h | 1 + 2 files changed, 39 insertions(+), 5 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c index 1d6048c..13003b8 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -230,6 +230,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) struct exynos5420_dmc *drex0, *drex1; struct exynos5420_tzasc *tzasc0, *tzasc1; uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1; + uint32_t lock0_info, lock1_info; int chip; int i; @@ -391,7 +392,41 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) */ dmc_config_mrs(mem, &drex0->directcmd); dmc_config_mrs(mem, &drex1->directcmd); - } else { + } + + /* + * Get PHY_CON13 from both phys. Gate CLKM around reading since + * PHY_CON13 is glitchy when CLKM is running. We're paranoid and + * wait until we get a "fine lock", though a coarse lock is probably + * OK (we only use the coarse numbers below). We try to gate the + * clock for as short a time as possible in case SDRAM is somehow + * sensitive. sdelay(10) in the loop is arbitrary to make sure + * there is some time for PHY_CON13 to get updated. In practice + * no delay appears to be needed. + */ + val = readl(&clk->gate_bus_cdrex); + while (true) { + writel(val & ~0x1, &clk->gate_bus_cdrex); + lock0_info = readl(&phy0_ctrl->phy_con13); + writel(val, &clk->gate_bus_cdrex); + + if ((lock0_info & CTRL_FINE_LOCKED) == CTRL_FINE_LOCKED) + break; + + sdelay(10); + } + while (true) { + writel(val & ~0x2, &clk->gate_bus_cdrex); + lock1_info = readl(&phy1_ctrl->phy_con13); + writel(val, &clk->gate_bus_cdrex); + + if ((lock1_info & CTRL_FINE_LOCKED) == CTRL_FINE_LOCKED) + break; + + sdelay(10); + } + + if (!reset) { /* * During Suspend-Resume & S/W-Reset, as soon as PMU releases * pad retention, CKE goes high. This causes memory contents @@ -442,15 +477,13 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET); writel(val, &phy1_ctrl->phy_con1); - n_lock_r = readl(&phy0_ctrl->phy_con13); - n_lock_w_phy0 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2; + n_lock_w_phy0 = (lock0_info & CTRL_LOCK_COARSE_MASK) >> 2; n_lock_r = readl(&phy0_ctrl->phy_con12); n_lock_r &= ~CTRL_DLL_ON; n_lock_r |= n_lock_w_phy0; writel(n_lock_r, &phy0_ctrl->phy_con12); - n_lock_r = readl(&phy1_ctrl->phy_con13); - n_lock_w_phy1 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2; + n_lock_w_phy1 = (lock1_info & CTRL_LOCK_COARSE_MASK) >> 2; n_lock_r = readl(&phy1_ctrl->phy_con12); n_lock_r &= ~CTRL_DLL_ON; n_lock_r |= n_lock_w_phy1; diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index 314d6f4..d415c91 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -284,6 +284,7 @@ #define CTRL_DLL_ON (1 << 5) #define CTRL_FORCE_MASK (0x7F << 8) #define CTRL_LOCK_COARSE_MASK (0x7F << 10) +#define CTRL_FINE_LOCKED 0x7 #define CTRL_OFFSETD_RESET_VAL 0x8 #define CTRL_OFFSETD_VAL 0x7F -- cgit v1.1 From ed32522fe048f9edcb3269c8d5af79c6e8c6daea Mon Sep 17 00:00:00 2001 From: Akshay Saraswat Date: Mon, 26 May 2014 19:20:08 +0530 Subject: Exynos5420: DMC: Add software read leveling Sometimes Read DQ and DQS are not in phase. Since, this phase shift differs from board to board, we need to calibrate it at DRAM init phase, that's read DQ calibration. This patch adds SW Read DQ calibration routine to compensate this skew. Signed-off-by: Alim Akhtar Signed-off-by: Akshay Saraswat Acked-by: Simon Glass Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 250 +++++++++++++++++++++++++++++- arch/arm/cpu/armv7/exynos/exynos5_setup.h | 5 +- 2 files changed, 250 insertions(+), 5 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c index 13003b8..b86dd2d 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -6,6 +6,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include #include #include #include @@ -16,7 +17,11 @@ #include "exynos5_setup.h" #include "clock_init.h" -#define TIMEOUT 10000 +#define TIMEOUT_US 10000 +#define NUM_BYTE_LANES 4 +#define DEFAULT_DQS 8 +#define DEFAULT_DQS_X4 (DEFAULT_DQS << 24) || (DEFAULT_DQS << 16) \ + || (DEFAULT_DQS << 8) || (DEFAULT_DQS << 0) #ifdef CONFIG_EXYNOS5250 static void reset_phy_ctrl(void) @@ -176,7 +181,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) writel(val, &phy1_ctrl->phy_con1); writel(CTRL_RDLVL_GATE_ENABLE, &dmc->rdlvl_config); - i = TIMEOUT; + i = TIMEOUT_US; while ((readl(&dmc->phystatus) & (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) != (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i > 0) { @@ -220,6 +225,219 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) #endif #ifdef CONFIG_EXYNOS5420 +/** + * RAM address to use in the test. + * + * We'll use 4 words at this address and 4 at this address + 0x80 (Ares + * interleaves channels every 128 bytes). This will allow us to evaluate all of + * the chips in a 1 chip per channel (2GB) system and half the chips in a 2 + * chip per channel (4GB) system. We can't test the 2nd chip since we need to + * do tests before the 2nd chip is enabled. Looking at the 2nd chip isn't + * critical because the 1st and 2nd chip have very similar timings (they'd + * better have similar timings, since there's only a single adjustment that is + * shared by both chips). + */ +const unsigned int test_addr = CONFIG_SYS_SDRAM_BASE; + +/* Test pattern with which RAM will be tested */ +static const unsigned int test_pattern[] = { + 0x5a5a5a5a, + 0xa5a5a5a5, + 0xf0f0f0f0, + 0x0f0f0f0f, +}; + +/** + * This function is a test vector for sw read leveling, + * it compares the read data with the written data. + * + * @param ch DMC channel number + * @param byte_lane which DQS byte offset, + * possible values are 0,1,2,3 + * @return TRUE if memory was good, FALSE if not. + */ +static bool dmc_valid_window_test_vector(int ch, int byte_lane) +{ + unsigned int read_data; + unsigned int mask; + int i; + + mask = 0xFF << (8 * byte_lane); + + for (i = 0; i < ARRAY_SIZE(test_pattern); i++) { + read_data = readl(test_addr + i * 4 + ch * 0x80); + if ((read_data & mask) != (test_pattern[i] & mask)) + return false; + } + + return true; +} + +/** + * This function returns current read offset value. + * + * @param phy_ctrl pointer to the current phy controller + */ +static unsigned int dmc_get_read_offset_value(struct exynos5420_phy_control + *phy_ctrl) +{ + return readl(&phy_ctrl->phy_con4); +} + +/** + * This function performs resync, so that slave DLL is updated. + * + * @param phy_ctrl pointer to the current phy controller + */ +static void ddr_phy_set_do_resync(struct exynos5420_phy_control *phy_ctrl) +{ + setbits_le32(&phy_ctrl->phy_con10, PHY_CON10_CTRL_OFFSETR3); + clrbits_le32(&phy_ctrl->phy_con10, PHY_CON10_CTRL_OFFSETR3); +} + +/** + * This function sets read offset value register with 'offset'. + * + * ...we also call call ddr_phy_set_do_resync(). + * + * @param phy_ctrl pointer to the current phy controller + * @param offset offset to read DQS + */ +static void dmc_set_read_offset_value(struct exynos5420_phy_control *phy_ctrl, + unsigned int offset) +{ + writel(offset, &phy_ctrl->phy_con4); + ddr_phy_set_do_resync(phy_ctrl); +} + +/** + * Convert a 2s complement byte to a byte with a sign bit. + * + * NOTE: you shouldn't use normal math on the number returned by this function. + * As an example, -10 = 0xf6. After this function -10 = 0x8a. If you wanted + * to do math and get the average of 10 and -10 (should be 0): + * 0x8a + 0xa = 0x94 (-108) + * 0x94 / 2 = 0xca (-54) + * ...and 0xca = sign bit plus 0x4a, or -74 + * + * Also note that you lose the ability to represent -128 since there are two + * representations of 0. + * + * @param b The byte to convert in two's complement. + * @return The 7-bit value + sign bit. + */ + +unsigned char make_signed_byte(signed char b) +{ + if (b < 0) + return 0x80 | -b; + else + return b; +} + +/** + * Test various shifts starting at 'start' and going to 'end'. + * + * For each byte lane, we'll walk through shift starting at 'start' and going + * to 'end' (inclusive). When we are finally able to read the test pattern + * we'll store the value in the results array. + * + * @param phy_ctrl pointer to the current phy controller + * @param ch channel number + * @param start the start shift. -127 to 127 + * @param end the end shift. -127 to 127 + * @param results we'll store results for each byte lane. + */ + +void test_shifts(struct exynos5420_phy_control *phy_ctrl, int ch, + int start, int end, int results[NUM_BYTE_LANES]) +{ + int incr = (start < end) ? 1 : -1; + int byte_lane; + + for (byte_lane = 0; byte_lane < NUM_BYTE_LANES; byte_lane++) { + int shift; + + dmc_set_read_offset_value(phy_ctrl, DEFAULT_DQS_X4); + results[byte_lane] = DEFAULT_DQS; + + for (shift = start; shift != (end + incr); shift += incr) { + unsigned int byte_offsetr; + unsigned int offsetr; + + byte_offsetr = make_signed_byte(shift); + + offsetr = dmc_get_read_offset_value(phy_ctrl); + offsetr &= ~(0xFF << (8 * byte_lane)); + offsetr |= (byte_offsetr << (8 * byte_lane)); + dmc_set_read_offset_value(phy_ctrl, offsetr); + + if (dmc_valid_window_test_vector(ch, byte_lane)) { + results[byte_lane] = shift; + break; + } + } + } +} + +/** + * This function performs SW read leveling to compensate DQ-DQS skew at + * receiver it first finds the optimal read offset value on each DQS + * then applies the value to PHY. + * + * Read offset value has its min margin and max margin. If read offset + * value exceeds its min or max margin, read data will have corruption. + * To avoid this we are doing sw read leveling. + * + * SW read leveling is: + * 1> Finding offset value's left_limit and right_limit + * 2> and calculate its center value + * 3> finally programs that center value to PHY + * 4> then PHY gets its optimal offset value. + * + * @param phy_ctrl pointer to the current phy controller + * @param ch channel number + * @param coarse_lock_val The coarse lock value read from PHY_CON13. + * (0 - 0x7f) + */ +static void software_find_read_offset(struct exynos5420_phy_control *phy_ctrl, + int ch, unsigned int coarse_lock_val) +{ + unsigned int offsetr_cent; + int byte_lane; + int left_limit; + int right_limit; + int left[NUM_BYTE_LANES]; + int right[NUM_BYTE_LANES]; + int i; + + /* Fill the memory with test patterns */ + for (i = 0; i < ARRAY_SIZE(test_pattern); i++) + writel(test_pattern[i], test_addr + i * 4 + ch * 0x80); + + /* Figure out the limits we'll test with; keep -127 < limit < 127 */ + left_limit = DEFAULT_DQS - coarse_lock_val; + right_limit = DEFAULT_DQS + coarse_lock_val; + if (right_limit > 127) + right_limit = 127; + + /* Fill in the location where reads were OK from left and right */ + test_shifts(phy_ctrl, ch, left_limit, right_limit, left); + test_shifts(phy_ctrl, ch, right_limit, left_limit, right); + + /* Make a final value by taking the center between the left and right */ + offsetr_cent = 0; + for (byte_lane = 0; byte_lane < NUM_BYTE_LANES; byte_lane++) { + int temp_center; + unsigned int vmwc; + + temp_center = (left[byte_lane] + right[byte_lane]) / 2; + vmwc = make_signed_byte(temp_center); + offsetr_cent |= vmwc << (8 * byte_lane); + } + dmc_set_read_offset_value(phy_ctrl, offsetr_cent); +} + int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) { struct exynos5420_clock *clk = @@ -229,6 +447,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) struct exynos5420_phy_control *phy0_ctrl, *phy1_ctrl; struct exynos5420_dmc *drex0, *drex1; struct exynos5420_tzasc *tzasc0, *tzasc1; + struct exynos5_power *pmu; uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1; uint32_t lock0_info, lock1_info; int chip; @@ -243,6 +462,8 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) tzasc0 = (struct exynos5420_tzasc *)samsung_get_base_dmc_tzasc(); tzasc1 = (struct exynos5420_tzasc *)(samsung_get_base_dmc_tzasc() + DMC_OFFSET); + pmu = (struct exynos5_power *)EXYNOS5420_POWER_BASE; + /* Enable PAUSE for DREX */ setbits_le32(&clk->pause, ENABLE_BIT); @@ -512,7 +733,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) writel(val, &phy1_ctrl->phy_con1); writel(CTRL_RDLVL_GATE_ENABLE, &drex0->rdlvl_config); - i = TIMEOUT; + i = TIMEOUT_US; while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) != RDLVL_COMPLETE_CHO) && (i > 0)) { /* @@ -527,7 +748,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) writel(CTRL_RDLVL_GATE_DISABLE, &drex0->rdlvl_config); writel(CTRL_RDLVL_GATE_ENABLE, &drex1->rdlvl_config); - i = TIMEOUT; + i = TIMEOUT_US; while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) != RDLVL_COMPLETE_CHO) && (i > 0)) { /* @@ -561,6 +782,27 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset) setbits_le32(&phy1_ctrl->phy_con2, DLL_DESKEW_EN); } + /* + * Do software read leveling + * + * Do this before we turn on auto refresh since the auto refresh can + * be in conflict with the resync operation that's part of setting + * read leveling. + */ + if (!reset) { + /* restore calibrated value after resume */ + dmc_set_read_offset_value(phy0_ctrl, readl(&pmu->pmu_spare1)); + dmc_set_read_offset_value(phy1_ctrl, readl(&pmu->pmu_spare2)); + } else { + software_find_read_offset(phy0_ctrl, 0, + CTRL_LOCK_COARSE(lock0_info)); + software_find_read_offset(phy1_ctrl, 1, + CTRL_LOCK_COARSE(lock1_info)); + /* save calibrated value to restore after resume */ + writel(dmc_get_read_offset_value(phy0_ctrl), &pmu->pmu_spare1); + writel(dmc_get_read_offset_value(phy1_ctrl), &pmu->pmu_spare2); + } + /* Send PALL command */ dmc_config_prech(mem, &drex0->directcmd); dmc_config_prech(mem, &drex1->directcmd); diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index d415c91..d91e585 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -282,8 +282,11 @@ #define PHY_CON12_VAL 0x10107F50 #define CTRL_START (1 << 6) #define CTRL_DLL_ON (1 << 5) +#define CTRL_LOCK_COARSE_OFFSET 10 +#define CTRL_LOCK_COARSE_MASK (0x7F << CTRL_LOCK_COARSE_OFFSET) +#define CTRL_LOCK_COARSE(x) (((x) & CTRL_LOCK_COARSE_MASK) >> \ + CTRL_LOCK_COARSE_OFFSET) #define CTRL_FORCE_MASK (0x7F << 8) -#define CTRL_LOCK_COARSE_MASK (0x7F << 10) #define CTRL_FINE_LOCKED 0x7 #define CTRL_OFFSETD_RESET_VAL 0x8 -- cgit v1.1 From d337a09c30a04d14e2c35b7517105c6b2e3e48dd Mon Sep 17 00:00:00 2001 From: "Wu, Josh" Date: Mon, 19 May 2014 19:51:28 +0800 Subject: ARMv7: at91: enable ICache and DCache. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For at91 armv7 SoC (SAMA5D3x), only LCD and macb used DMA. Now as the lcd and macb driver already support dcache. So we can enable dcache now. Also we can enable icache without any problem. Signed-off-by: Josh Wu Signed-off-by: Andreas Bießmann --- arch/arm/cpu/armv7/at91/cpu.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/at91/cpu.c b/arch/arm/cpu/armv7/at91/cpu.c index 2fbf60d..8d86f97 100644 --- a/arch/arm/cpu/armv7/at91/cpu.c +++ b/arch/arm/cpu/armv7/at91/cpu.c @@ -61,6 +61,8 @@ int print_cpuinfo(void) void enable_caches(void) { + icache_enable(); + dcache_enable(); } unsigned int get_chip_id(void) -- cgit v1.1 From a811db5a8c557138e4d22000aca4ce7f6c3b25b5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 5 Jun 2014 19:47:45 +0900 Subject: arm: zynq: fix a bug in Zynq linker script Commit 41623c91 moved exception handlers to ".vectores" section but it missed to adjust Zynq linker script. Zynq boards hang up after relocation because "_start" symbol does not point to the correct address and gd->relocaddr gets insane. Signed-off-by: Masahiro Yamada Cc: Albert ARIBAUD Cc: Michal Simek Tested-by: Michal Simek Signed-off-by: Michal Simek --- arch/arm/cpu/armv7/zynq/u-boot.lds | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/zynq/u-boot.lds b/arch/arm/cpu/armv7/zynq/u-boot.lds index 69500a6..4dc9bb0 100644 --- a/arch/arm/cpu/armv7/zynq/u-boot.lds +++ b/arch/arm/cpu/armv7/zynq/u-boot.lds @@ -18,6 +18,7 @@ SECTIONS .text : { *(.__image_copy_start) + *(.vectors) CPUDIR/start.o (.text*) *(.text*) } -- cgit v1.1 From c42ff090e41d4b9e50faa727bac490ee790f82f4 Mon Sep 17 00:00:00 2001 From: Jeroen Hofstee Date: Wed, 11 Jun 2014 23:12:28 +0200 Subject: tegra20: display: fix checking of return value The calling code seems a bit in doubt about the return value of fdtdec_lookup_phandle. Since it returns a negative value on error (and fdt_node_offset_by_phandle as well), check for that. cc: Wei Ni Signed-off-by: Jeroen Hofstee Tested-by: Stephen Warren Signed-off-by: Tom Warren --- arch/arm/cpu/armv7/tegra20/display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/tegra20/display.c b/arch/arm/cpu/armv7/tegra20/display.c index 488f0c6..fd77f3f 100644 --- a/arch/arm/cpu/armv7/tegra20/display.c +++ b/arch/arm/cpu/armv7/tegra20/display.c @@ -328,7 +328,7 @@ static int tegra_display_decode_config(const void *blob, rgb = fdt_subnode_offset(blob, node, "rgb"); config->panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); - if (!config->panel_node < 0) { + if (config->panel_node < 0) { debug("%s: Cannot find panel information\n", __func__); return -1; } -- cgit v1.1 From 2868a5dff373f6d173ba2d060bbe910c38254cbf Mon Sep 17 00:00:00 2001 From: Ash Charles Date: Fri, 6 Jun 2014 11:27:28 -0700 Subject: omap: Don't enable GPMC CS0 with nothing attached If CONFIG_(NAND|NOR|ONENAND) is not defined, no configuration is set for GPMC on chip select #0---size is 0. In this case, the GPMC configuration should be reset but not enabled. Enabling causes the Gumstix DuoVero board to hang when entering Linux. Signed-off-by: Ash Charles [trini: Switch to testing base as GPMC_SIZE_256M is 0x0] Signed-off-by: Tom Rini --- arch/arm/cpu/armv7/omap-common/mem-common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap-common/mem-common.c b/arch/arm/cpu/armv7/omap-common/mem-common.c index 944ef84..11be480 100644 --- a/arch/arm/cpu/armv7/omap-common/mem-common.c +++ b/arch/arm/cpu/armv7/omap-common/mem-common.c @@ -133,5 +133,6 @@ void gpmc_init(void) writel(0, &gpmc_cfg->cs[0].config7); sdelay(1000); /* enable chip-select specific configurations */ - enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg->cs[0], base, size); + if (base != 0) + enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg->cs[0], base, size); } -- cgit v1.1 From 3e01ed00da98a29fe2b71c6d60309d5b09adc0de Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Sat, 7 Jun 2014 04:22:52 +0300 Subject: mtd: nand: davinci: add header file for driver definitions The definitions inside emif_defs.h concern davinci nand driver and should be in it's header. So create header file for davinci nand driver and move definitions from emif_defs.h and nand_defs.h to it. Acked-by: Vitaly Andrianov Signed-off-by: Ivan Khoronzhuk [trini: Fixup more davinci breakage] Signed-off-by: Tom Rini --- arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c | 2 +- arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c | 1 + arch/arm/cpu/armv7/keystone/aemif.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c b/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c index b91e948..19730ce 100644 --- a/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c +++ b/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include void davinci_enable_uart0(void) diff --git a/arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c b/arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c index ee096fe..c8b4498 100644 --- a/arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c +++ b/arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/cpu/armv7/keystone/aemif.c b/arch/arm/cpu/armv7/keystone/aemif.c index 9b26886..bcbb95a 100644 --- a/arch/arm/cpu/armv7/keystone/aemif.c +++ b/arch/arm/cpu/armv7/keystone/aemif.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #define AEMIF_CFG_SELECT_STROBE(v) ((v) ? 1 << 31 : 0) #define AEMIF_CFG_EXTEND_WAIT(v) ((v) ? 1 << 30 : 0) -- cgit v1.1 From 909ea9aa264423c99cd3039475c98f4a069cb7a4 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Sat, 7 Jun 2014 05:10:49 +0300 Subject: ARM: keystone: aemif: move aemif driver to drivers/memory/ti-aemif.c Move AEMIF driver to drivers/memory/ti-aemif.c along with AEMIF definitions collected in arch/arm/include/asm/ti-common/ti-aemif.h Acked-by: Vitaly Andrianov Signed-off-by: Ivan Khoronzhuk --- arch/arm/cpu/armv7/keystone/Makefile | 1 - arch/arm/cpu/armv7/keystone/aemif.c | 71 ------------------------------------ 2 files changed, 72 deletions(-) delete mode 100644 arch/arm/cpu/armv7/keystone/aemif.c (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/keystone/Makefile b/arch/arm/cpu/armv7/keystone/Makefile index b1bd022..c4af252 100644 --- a/arch/arm/cpu/armv7/keystone/Makefile +++ b/arch/arm/cpu/armv7/keystone/Makefile @@ -5,7 +5,6 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y += aemif.o obj-y += init.o obj-y += psc.o obj-y += clock.o diff --git a/arch/arm/cpu/armv7/keystone/aemif.c b/arch/arm/cpu/armv7/keystone/aemif.c deleted file mode 100644 index bcbb95a..0000000 --- a/arch/arm/cpu/armv7/keystone/aemif.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Keystone2: Asynchronous EMIF Configuration - * - * (C) Copyright 2012-2014 - * Texas Instruments Incorporated, - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -#define AEMIF_CFG_SELECT_STROBE(v) ((v) ? 1 << 31 : 0) -#define AEMIF_CFG_EXTEND_WAIT(v) ((v) ? 1 << 30 : 0) -#define AEMIF_CFG_WR_SETUP(v) (((v) & 0x0f) << 26) -#define AEMIF_CFG_WR_STROBE(v) (((v) & 0x3f) << 20) -#define AEMIF_CFG_WR_HOLD(v) (((v) & 0x07) << 17) -#define AEMIF_CFG_RD_SETUP(v) (((v) & 0x0f) << 13) -#define AEMIF_CFG_RD_STROBE(v) (((v) & 0x3f) << 7) -#define AEMIF_CFG_RD_HOLD(v) (((v) & 0x07) << 4) -#define AEMIF_CFG_TURN_AROUND(v) (((v) & 0x03) << 2) -#define AEMIF_CFG_WIDTH(v) (((v) & 0x03) << 0) - -#define set_config_field(reg, field, val) \ - do { \ - if (val != -1) { \ - reg &= ~AEMIF_CFG_##field(0xffffffff); \ - reg |= AEMIF_CFG_##field(val); \ - } \ - } while (0) - -void configure_async_emif(int cs, struct async_emif_config *cfg) -{ - unsigned long tmp; - - if (cfg->mode == ASYNC_EMIF_MODE_NAND) { - tmp = __raw_readl(&davinci_emif_regs->nandfcr); - tmp |= (1 << cs); - __raw_writel(tmp, &davinci_emif_regs->nandfcr); - - } else if (cfg->mode == ASYNC_EMIF_MODE_ONENAND) { - tmp = __raw_readl(&davinci_emif_regs->one_nand_cr); - tmp |= (1 << cs); - __raw_writel(tmp, &davinci_emif_regs->one_nand_cr); - } - - tmp = __raw_readl(&davinci_emif_regs->abncr[cs]); - - set_config_field(tmp, SELECT_STROBE, cfg->select_strobe); - set_config_field(tmp, EXTEND_WAIT, cfg->extend_wait); - set_config_field(tmp, WR_SETUP, cfg->wr_setup); - set_config_field(tmp, WR_STROBE, cfg->wr_strobe); - set_config_field(tmp, WR_HOLD, cfg->wr_hold); - set_config_field(tmp, RD_SETUP, cfg->rd_setup); - set_config_field(tmp, RD_STROBE, cfg->rd_strobe); - set_config_field(tmp, RD_HOLD, cfg->rd_hold); - set_config_field(tmp, TURN_AROUND, cfg->turn_around); - set_config_field(tmp, WIDTH, cfg->width); - - __raw_writel(tmp, &davinci_emif_regs->abncr[cs]); -} - -void init_async_emif(int num_cs, struct async_emif_config *config) -{ - int cs; - - for (cs = 0; cs < num_cs; cs++) - configure_async_emif(cs, config + cs); -} -- cgit v1.1 From 9f1220a9ca9f583fbb6e85cf43674c4258c85d24 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 10 Jun 2014 15:01:19 -0500 Subject: cpu: armv7: am33x: ddr: write emif ref_ctrl_shadow register Signed-off-by: Felipe Balbi --- arch/arm/cpu/armv7/am33xx/ddr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c index 9a625c4..bbe9d1a 100644 --- a/arch/arm/cpu/armv7/am33xx/ddr.c +++ b/arch/arm/cpu/armv7/am33xx/ddr.c @@ -95,6 +95,7 @@ void config_sdram_emif4d5(const struct emif_regs *regs, int nr) &emif_reg[nr]->emif_rd_wr_exec_thresh); writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw); writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); writel(regs->sdram_config, &cstat->secure_emif_sdram_config); -- cgit v1.1 From fd3f401bc14340db38f98a99824367e2287aa01a Mon Sep 17 00:00:00 2001 From: Jeroen Hofstee Date: Mon, 16 Jun 2014 23:22:23 +0200 Subject: omap3: board: trivial: add void for no args Signed-off-by: Jeroen Hofstee --- arch/arm/cpu/armv7/omap3/board.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c index 9bb1a1c..2f9c939 100644 --- a/arch/arm/cpu/armv7/omap3/board.c +++ b/arch/arm/cpu/armv7/omap3/board.c @@ -147,7 +147,7 @@ void secure_unlock_mem(void) * configure secure registers and exit secure world * general use. *****************************************************************************/ -void secureworld_exit() +void secureworld_exit(void) { unsigned long i; @@ -178,7 +178,7 @@ void secureworld_exit() * Description: If chip is GP/EMU(special) type, unlock the SRAM for * general use. *****************************************************************************/ -void try_unlock_memory() +void try_unlock_memory(void) { int mode; int in_sdram = is_running_in_sdram(); -- cgit v1.1 From 734af242c20b10b6fc690836123c5d0389b7e2a0 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Tue, 17 Jun 2014 16:47:40 +0200 Subject: OMAP: disable gpmc timeout safely for reenabling gpmc timeout is disabled and the reset counter is set to 0. However, if later a driver activates the timeout setting the reset to a valid value, the old reset value with zero is still valid for the first access. In fact, the timeout block loads the reset counter after a successful access. Found on a am335x board with a FPGA connected to the GPMC bus together with the NAND. When the FPGA driver in kernel activates the timeout, the system hangs at the first access by the NAND driver. Signed-off-by: Stefano Babic --- arch/arm/cpu/armv7/omap-common/mem-common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/omap-common/mem-common.c b/arch/arm/cpu/armv7/omap-common/mem-common.c index 11be480..5bc7e1f 100644 --- a/arch/arm/cpu/armv7/omap-common/mem-common.c +++ b/arch/arm/cpu/armv7/omap-common/mem-common.c @@ -121,7 +121,8 @@ void gpmc_init(void) writel(0x00000008, &gpmc_cfg->sysconfig); writel(0x00000000, &gpmc_cfg->irqstatus); writel(0x00000000, &gpmc_cfg->irqenable); - writel(0x00000000, &gpmc_cfg->timeout_control); + /* disable timeout, set a safe reset value */ + writel(0x00001ff0, &gpmc_cfg->timeout_control); #ifdef CONFIG_NOR writel(0x00000200, &gpmc_cfg->config); #else -- cgit v1.1 From eacf46d340db182a4068772ec43e2586e9eaf80b Mon Sep 17 00:00:00 2001 From: Akshay Saraswat Date: Wed, 18 Jun 2014 17:53:57 +0530 Subject: Exynos5420: Let macros be used for exynos5420 Macros defined in exynos5_setup.h specific to SMDK5420 are required for Peach-Pit too. Hence, replacing CONFIG_SMDK5420 with CONFIG_EXYNOS5420 to enable these macros for all the boards based on Exynos5420. Signed-off-by: Akshay Saraswat Acked-by: Simon Glass Tested-by: Simon Glass Signed-off-by: Minkyu Kang --- arch/arm/cpu/armv7/exynos/exynos5_setup.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index d91e585..3242093 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -435,10 +435,10 @@ /* * Definitions that differ with SoC's. - * Below is the part defining macros for smdk5250. - * Else part introduces macros for smdk5420. + * Below is the part defining macros for Exynos5250. + * Else part introduces macros for Exynos5420. */ -#ifndef CONFIG_SMDK5420 +#ifndef CONFIG_EXYNOS5420 /* APLL_CON1 */ #define APLL_CON1_VAL (0x00203800) -- cgit v1.1 From 22932ffc03e521130cfd33cae1fc2531eb42604a Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 23 Jun 2014 15:15:53 -0700 Subject: ARMv8: Adjust MMU setup Make MMU function reusable. Platform code can setup its own MMU tables. Signed-off-by: York Sun CC: David Feng --- arch/arm/cpu/armv8/cache_v8.c | 50 +++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 30 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index a96ecda..af3c494 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -12,15 +12,14 @@ DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SYS_DCACHE_OFF - -static void set_pgtable_section(u64 section, u64 memory_type) +void set_pgtable_section(u64 *page_table, u64 index, u64 section, + u64 memory_type) { - u64 *page_table = (u64 *)gd->arch.tlb_addr; u64 value; - value = (section << SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; + value = section | PMD_TYPE_SECT | PMD_SECT_AF; value |= PMD_ATTRINDX(memory_type); - page_table[section] = value; + page_table[index] = value; } /* to activate the MMU we need to set up virtual memory */ @@ -28,10 +27,13 @@ static void mmu_setup(void) { int i, j, el; bd_t *bd = gd->bd; + u64 *page_table = (u64 *)gd->arch.tlb_addr; /* Setup an identity-mapping for all spaces */ - for (i = 0; i < (PGTABLE_SIZE >> 3); i++) - set_pgtable_section(i, MT_DEVICE_NGNRNE); + for (i = 0; i < (PGTABLE_SIZE >> 3); i++) { + set_pgtable_section(page_table, i, i << SECTION_SHIFT, + MT_DEVICE_NGNRNE); + } /* Setup an identity-mapping for all RAM space */ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { @@ -39,38 +41,26 @@ static void mmu_setup(void) ulong end = bd->bi_dram[i].start + bd->bi_dram[i].size; for (j = start >> SECTION_SHIFT; j < end >> SECTION_SHIFT; j++) { - set_pgtable_section(j, MT_NORMAL); + set_pgtable_section(page_table, j, j << SECTION_SHIFT, + MT_NORMAL); } } /* load TTBR0 */ el = current_el(); if (el == 1) { - asm volatile("msr ttbr0_el1, %0" - : : "r" (gd->arch.tlb_addr) : "memory"); - asm volatile("msr tcr_el1, %0" - : : "r" (TCR_FLAGS | TCR_EL1_IPS_BITS) - : "memory"); - asm volatile("msr mair_el1, %0" - : : "r" (MEMORY_ATTRIBUTES) : "memory"); + set_ttbr_tcr_mair(el, gd->arch.tlb_addr, + TCR_FLAGS | TCR_EL1_IPS_BITS, + MEMORY_ATTRIBUTES); } else if (el == 2) { - asm volatile("msr ttbr0_el2, %0" - : : "r" (gd->arch.tlb_addr) : "memory"); - asm volatile("msr tcr_el2, %0" - : : "r" (TCR_FLAGS | TCR_EL2_IPS_BITS) - : "memory"); - asm volatile("msr mair_el2, %0" - : : "r" (MEMORY_ATTRIBUTES) : "memory"); + set_ttbr_tcr_mair(el, gd->arch.tlb_addr, + TCR_FLAGS | TCR_EL2_IPS_BITS, + MEMORY_ATTRIBUTES); } else { - asm volatile("msr ttbr0_el3, %0" - : : "r" (gd->arch.tlb_addr) : "memory"); - asm volatile("msr tcr_el3, %0" - : : "r" (TCR_FLAGS | TCR_EL2_IPS_BITS) - : "memory"); - asm volatile("msr mair_el3, %0" - : : "r" (MEMORY_ATTRIBUTES) : "memory"); + set_ttbr_tcr_mair(el, gd->arch.tlb_addr, + TCR_FLAGS | TCR_EL3_IPS_BITS, + MEMORY_ATTRIBUTES); } - /* enable the mmu */ set_sctlr(get_sctlr() | CR_M); } -- cgit v1.1 From 2f78eae5064728d6cd907148cfeaf8ba3e63b0ef Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 23 Jun 2014 15:15:54 -0700 Subject: ARMv8/FSL_LSCH3: Add FSL_LSCH3 SoC Freescale LayerScape with Chassis Generation 3 is a set of SoCs with ARMv8 cores and 3rd generation of Chassis. We use different MMU setup to support memory map and cache attribute for these SoCs. MMU and cache are enabled very early to bootst performance, especially for early development on emulators. After u-boot relocates to DDR, a new MMU table with QBMan cache access is created in DDR. SMMU pagesize is set in SMMU_sACR register. Both DDR3 and DDR4 are supported. Signed-off-by: York Sun Signed-off-by: Varun Sethi Signed-off-by: Arnab Basu --- arch/arm/cpu/armv8/cache_v8.c | 7 +- arch/arm/cpu/armv8/fsl-lsch3/Makefile | 9 + arch/arm/cpu/armv8/fsl-lsch3/README | 10 + arch/arm/cpu/armv8/fsl-lsch3/cpu.c | 425 ++++++++++++++++++++++++++++++++ arch/arm/cpu/armv8/fsl-lsch3/cpu.h | 7 + arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S | 65 +++++ arch/arm/cpu/armv8/fsl-lsch3/speed.c | 176 +++++++++++++ arch/arm/cpu/armv8/fsl-lsch3/speed.h | 7 + 8 files changed, 705 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/Makefile create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/README create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/cpu.c create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/cpu.h create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/speed.c create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/speed.h (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index af3c494..9dbcdf2 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -73,12 +73,17 @@ void invalidate_dcache_all(void) __asm_invalidate_dcache_all(); } +void __weak flush_l3_cache(void) +{ +} + /* * Performs a clean & invalidation of the entire data cache at all levels */ void flush_dcache_all(void) { __asm_flush_dcache_all(); + flush_l3_cache(); } /* @@ -211,7 +216,7 @@ void invalidate_icache_all(void) * Enable dCache & iCache, whether cache is actually enabled * depend on CONFIG_SYS_DCACHE_OFF and CONFIG_SYS_ICACHE_OFF */ -void enable_caches(void) +void __weak enable_caches(void) { icache_enable(); dcache_enable(); diff --git a/arch/arm/cpu/armv8/fsl-lsch3/Makefile b/arch/arm/cpu/armv8/fsl-lsch3/Makefile new file mode 100644 index 0000000..9249537 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/Makefile @@ -0,0 +1,9 @@ +# +# Copyright 2014, Freescale Semiconductor +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cpu.o +obj-y += lowlevel.o +obj-y += speed.o diff --git a/arch/arm/cpu/armv8/fsl-lsch3/README b/arch/arm/cpu/armv8/fsl-lsch3/README new file mode 100644 index 0000000..de34a91 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/README @@ -0,0 +1,10 @@ +# +# Copyright 2014 Freescale Semiconductor +# +# SPDX-License-Identifier: GPL-2.0+ +# + +Freescale LayerScape with Chassis Generation 3 + +This architecture supports Freescale ARMv8 SoCs with Chassis generation 3, +for example LS2100A. diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c new file mode 100644 index 0000000..46965f0 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c @@ -0,0 +1,425 @@ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include "cpu.h" +#include "speed.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_DCACHE_OFF +/* + * To start MMU before DDR is available, we create MMU table in SRAM. + * The base address of SRAM is CONFIG_SYS_FSL_OCRAM_BASE. We use three + * levels of translation tables here to cover 40-bit address space. + * We use 4KB granule size, with 40 bits physical address, T0SZ=24 + * Level 0 IA[39], table address @0 + * Level 1 IA[31:30], table address @01000, 0x2000 + * Level 2 IA[29:21], table address @0x3000 + */ + +#define SECTION_SHIFT_L0 39UL +#define SECTION_SHIFT_L1 30UL +#define SECTION_SHIFT_L2 21UL +#define BLOCK_SIZE_L0 0x8000000000UL +#define BLOCK_SIZE_L1 (1 << SECTION_SHIFT_L1) +#define BLOCK_SIZE_L2 (1 << SECTION_SHIFT_L2) +#define CONFIG_SYS_IFC_BASE 0x30000000 +#define CONFIG_SYS_IFC_SIZE 0x10000000 +#define CONFIG_SYS_IFC_BASE2 0x500000000 +#define CONFIG_SYS_IFC_SIZE2 0x100000000 +#define TCR_EL2_PS_40BIT (2 << 16) +#define LSCH3_VA_BITS (40) +#define LSCH3_TCR (TCR_TG0_4K | \ + TCR_EL2_PS_40BIT | \ + TCR_SHARED_NON | \ + TCR_ORGN_NC | \ + TCR_IRGN_NC | \ + TCR_T0SZ(LSCH3_VA_BITS)) + +/* + * Final MMU + * Let's start from the same layout as early MMU and modify as needed. + * IFC regions will be cache-inhibit. + */ +#define FINAL_QBMAN_CACHED_MEM 0x818000000UL +#define FINAL_QBMAN_CACHED_SIZE 0x4000000 + + +static inline void early_mmu_setup(void) +{ + int el; + u64 i; + u64 section_l1t0, section_l1t1, section_l2; + u64 *level0_table = (u64 *)CONFIG_SYS_FSL_OCRAM_BASE; + u64 *level1_table_0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x1000); + u64 *level1_table_1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x2000); + u64 *level2_table = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x3000); + + + level0_table[0] = + (u64)level1_table_0 | PMD_TYPE_TABLE; + level0_table[1] = + (u64)level1_table_1 | PMD_TYPE_TABLE; + + /* + * set level 1 table 0 to cache_inhibit, covering 0 to 512GB + * set level 1 table 1 to cache enabled, covering 512GB to 1TB + * set level 2 table to cache-inhibit, covering 0 to 1GB + */ + section_l1t0 = 0; + section_l1t1 = BLOCK_SIZE_L0; + section_l2 = 0; + for (i = 0; i < 512; i++) { + set_pgtable_section(level1_table_0, i, section_l1t0, + MT_DEVICE_NGNRNE); + set_pgtable_section(level1_table_1, i, section_l1t1, + MT_NORMAL); + set_pgtable_section(level2_table, i, section_l2, + MT_DEVICE_NGNRNE); + section_l1t0 += BLOCK_SIZE_L1; + section_l1t1 += BLOCK_SIZE_L1; + section_l2 += BLOCK_SIZE_L2; + } + + level1_table_0[0] = + (u64)level2_table | PMD_TYPE_TABLE; + level1_table_0[1] = + 0x40000000 | PMD_SECT_AF | PMD_TYPE_SECT | + PMD_ATTRINDX(MT_DEVICE_NGNRNE); + level1_table_0[2] = + 0x80000000 | PMD_SECT_AF | PMD_TYPE_SECT | + PMD_ATTRINDX(MT_NORMAL); + level1_table_0[3] = + 0xc0000000 | PMD_SECT_AF | PMD_TYPE_SECT | + PMD_ATTRINDX(MT_NORMAL); + + /* Rewrite table to enable cache */ + set_pgtable_section(level2_table, + CONFIG_SYS_FSL_OCRAM_BASE >> SECTION_SHIFT_L2, + CONFIG_SYS_FSL_OCRAM_BASE, + MT_NORMAL); + for (i = CONFIG_SYS_IFC_BASE >> SECTION_SHIFT_L2; + i < (CONFIG_SYS_IFC_BASE + CONFIG_SYS_IFC_SIZE) + >> SECTION_SHIFT_L2; i++) { + section_l2 = i << SECTION_SHIFT_L2; + set_pgtable_section(level2_table, i, + section_l2, MT_NORMAL); + } + + el = current_el(); + set_ttbr_tcr_mair(el, (u64)level0_table, LSCH3_TCR, MEMORY_ATTRIBUTES); + set_sctlr(get_sctlr() | CR_M); +} + +/* + * This final tale looks similar to early table, but different in detail. + * These tables are in regular memory. Cache on IFC is disabled. One sub table + * is added to enable cache for QBMan. + */ +static inline void final_mmu_setup(void) +{ + int el; + u64 i, tbl_base, tbl_limit, section_base; + u64 section_l1t0, section_l1t1, section_l2; + u64 *level0_table = (u64 *)gd->arch.tlb_addr; + u64 *level1_table_0 = (u64 *)(gd->arch.tlb_addr + 0x1000); + u64 *level1_table_1 = (u64 *)(gd->arch.tlb_addr + 0x2000); + u64 *level2_table_0 = (u64 *)(gd->arch.tlb_addr + 0x3000); + u64 *level2_table_1 = (u64 *)(gd->arch.tlb_addr + 0x4000); + + + level0_table[0] = + (u64)level1_table_0 | PMD_TYPE_TABLE; + level0_table[1] = + (u64)level1_table_1 | PMD_TYPE_TABLE; + + /* + * set level 1 table 0 to cache_inhibit, covering 0 to 512GB + * set level 1 table 1 to cache enabled, covering 512GB to 1TB + * set level 2 table 0 to cache-inhibit, covering 0 to 1GB + */ + section_l1t0 = 0; + section_l1t1 = BLOCK_SIZE_L0; + section_l2 = 0; + for (i = 0; i < 512; i++) { + set_pgtable_section(level1_table_0, i, section_l1t0, + MT_DEVICE_NGNRNE); + set_pgtable_section(level1_table_1, i, section_l1t1, + MT_NORMAL); + set_pgtable_section(level2_table_0, i, section_l2, + MT_DEVICE_NGNRNE); + section_l1t0 += BLOCK_SIZE_L1; + section_l1t1 += BLOCK_SIZE_L1; + section_l2 += BLOCK_SIZE_L2; + } + + level1_table_0[0] = + (u64)level2_table_0 | PMD_TYPE_TABLE; + level1_table_0[2] = + 0x80000000 | PMD_SECT_AF | PMD_TYPE_SECT | + PMD_ATTRINDX(MT_NORMAL); + level1_table_0[3] = + 0xc0000000 | PMD_SECT_AF | PMD_TYPE_SECT | + PMD_ATTRINDX(MT_NORMAL); + + /* Rewrite table to enable cache */ + set_pgtable_section(level2_table_0, + CONFIG_SYS_FSL_OCRAM_BASE >> SECTION_SHIFT_L2, + CONFIG_SYS_FSL_OCRAM_BASE, + MT_NORMAL); + + /* + * Fill in other part of tables if cache is needed + * If finer granularity than 1GB is needed, sub table + * should be created. + */ + section_base = FINAL_QBMAN_CACHED_MEM & ~(BLOCK_SIZE_L1 - 1); + i = section_base >> SECTION_SHIFT_L1; + level1_table_0[i] = (u64)level2_table_1 | PMD_TYPE_TABLE; + section_l2 = section_base; + for (i = 0; i < 512; i++) { + set_pgtable_section(level2_table_1, i, section_l2, + MT_DEVICE_NGNRNE); + section_l2 += BLOCK_SIZE_L2; + } + tbl_base = FINAL_QBMAN_CACHED_MEM & (BLOCK_SIZE_L1 - 1); + tbl_limit = (FINAL_QBMAN_CACHED_MEM + FINAL_QBMAN_CACHED_SIZE) & + (BLOCK_SIZE_L1 - 1); + for (i = tbl_base >> SECTION_SHIFT_L2; + i < tbl_limit >> SECTION_SHIFT_L2; i++) { + section_l2 = section_base + (i << SECTION_SHIFT_L2); + set_pgtable_section(level2_table_1, i, + section_l2, MT_NORMAL); + } + + /* flush new MMU table */ + flush_dcache_range(gd->arch.tlb_addr, + gd->arch.tlb_addr + gd->arch.tlb_size); + + /* point TTBR to the new table */ + el = current_el(); + asm volatile("dsb sy"); + if (el == 1) { + asm volatile("msr ttbr0_el1, %0" + : : "r" ((u64)level0_table) : "memory"); + } else if (el == 2) { + asm volatile("msr ttbr0_el2, %0" + : : "r" ((u64)level0_table) : "memory"); + } else if (el == 3) { + asm volatile("msr ttbr0_el3, %0" + : : "r" ((u64)level0_table) : "memory"); + } else { + hang(); + } + asm volatile("isb"); + + /* + * MMU is already enabled, just need to invalidate TLB to load the + * new table. The new table is compatible with the current table, if + * MMU somehow walks through the new table before invalidation TLB, + * it still works. So we don't need to turn off MMU here. + */ +} + +int arch_cpu_init(void) +{ + icache_enable(); + __asm_invalidate_dcache_all(); + __asm_invalidate_tlb_all(); + early_mmu_setup(); + set_sctlr(get_sctlr() | CR_C); + return 0; +} + +/* + * flush_l3_cache + * Dickens L3 cache can be flushed by transitioning from FAM to SFONLY power + * state, by writing to HP-F P-state request register. + * Fixme: This function should moved to a common file if other SoCs also use + * the same Dickens. + */ +#define HNF0_PSTATE_REQ 0x04200010 +#define HNF1_PSTATE_REQ 0x04210010 +#define HNF2_PSTATE_REQ 0x04220010 +#define HNF3_PSTATE_REQ 0x04230010 +#define HNF4_PSTATE_REQ 0x04240010 +#define HNF5_PSTATE_REQ 0x04250010 +#define HNF6_PSTATE_REQ 0x04260010 +#define HNF7_PSTATE_REQ 0x04270010 +#define HNFPSTAT_MASK (0xFFFFFFFFFFFFFFFC) +#define HNFPSTAT_FAM 0x3 +#define HNFPSTAT_SFONLY 0x01 + +static void hnf_pstate_req(u64 *ptr, u64 state) +{ + int timeout = 1000; + out_le64(ptr, (in_le64(ptr) & HNFPSTAT_MASK) | (state & 0x3)); + ptr++; + /* checking if the transition is completed */ + while (timeout > 0) { + if (((in_le64(ptr) & 0x0c) >> 2) == (state & 0x3)) + break; + udelay(100); + timeout--; + } +} + +void flush_l3_cache(void) +{ + hnf_pstate_req((u64 *)HNF0_PSTATE_REQ, HNFPSTAT_SFONLY); + hnf_pstate_req((u64 *)HNF1_PSTATE_REQ, HNFPSTAT_SFONLY); + hnf_pstate_req((u64 *)HNF2_PSTATE_REQ, HNFPSTAT_SFONLY); + hnf_pstate_req((u64 *)HNF3_PSTATE_REQ, HNFPSTAT_SFONLY); + hnf_pstate_req((u64 *)HNF4_PSTATE_REQ, HNFPSTAT_SFONLY); + hnf_pstate_req((u64 *)HNF5_PSTATE_REQ, HNFPSTAT_SFONLY); + hnf_pstate_req((u64 *)HNF6_PSTATE_REQ, HNFPSTAT_SFONLY); + hnf_pstate_req((u64 *)HNF7_PSTATE_REQ, HNFPSTAT_SFONLY); + hnf_pstate_req((u64 *)HNF0_PSTATE_REQ, HNFPSTAT_FAM); + hnf_pstate_req((u64 *)HNF1_PSTATE_REQ, HNFPSTAT_FAM); + hnf_pstate_req((u64 *)HNF2_PSTATE_REQ, HNFPSTAT_FAM); + hnf_pstate_req((u64 *)HNF3_PSTATE_REQ, HNFPSTAT_FAM); + hnf_pstate_req((u64 *)HNF4_PSTATE_REQ, HNFPSTAT_FAM); + hnf_pstate_req((u64 *)HNF5_PSTATE_REQ, HNFPSTAT_FAM); + hnf_pstate_req((u64 *)HNF6_PSTATE_REQ, HNFPSTAT_FAM); + hnf_pstate_req((u64 *)HNF7_PSTATE_REQ, HNFPSTAT_FAM); +} + +/* + * This function is called from lib/board.c. + * It recreates MMU table in main memory. MMU and d-cache are enabled earlier. + * There is no need to disable d-cache for this operation. + */ +void enable_caches(void) +{ + final_mmu_setup(); + __asm_invalidate_tlb_all(); +} +#endif + +static inline u32 initiator_type(u32 cluster, int init_id) +{ + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 idx = (cluster >> (init_id * 8)) & TP_CLUSTER_INIT_MASK; + u32 type = in_le32(&gur->tp_ityp[idx]); + + if (type & TP_ITYP_AV) + return type; + + return 0; +} + +u32 cpu_mask(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster, type, mask = 0; + + do { + int j; + cluster = in_le32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + type = initiator_type(cluster, j); + if (type) { + if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM) + mask |= 1 << count; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + + return mask; +} + +/* + * Return the number of cores on this SOC. + */ +int cpu_numcores(void) +{ + return hweight32(cpu_mask()); +} + +int fsl_qoriq_core_to_cluster(unsigned int core) +{ + struct ccsr_gur __iomem *gur = + (void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster; + + do { + int j; + cluster = in_le32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + if (initiator_type(cluster, j)) { + if (count == core) + return i; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + + return -1; /* cannot identify the cluster */ +} + +u32 fsl_qoriq_core_to_type(unsigned int core) +{ + struct ccsr_gur __iomem *gur = + (void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster, type; + + do { + int j; + cluster = in_le32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + type = initiator_type(cluster, j); + if (type) { + if (count == core) + return type; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + + return -1; /* cannot identify the cluster */ +} + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + struct sys_info sysinfo; + char buf[32]; + unsigned int i, core; + u32 type; + + get_sys_info(&sysinfo); + puts("Clock Configuration:"); + for_each_cpu(i, core, cpu_numcores(), cpu_mask()) { + if (!(i % 3)) + puts("\n "); + type = TP_ITYP_VER(fsl_qoriq_core_to_type(core)); + printf("CPU%d(%s):%-4s MHz ", core, + type == TY_ITYP_VER_A7 ? "A7 " : + (type == TY_ITYP_VER_A53 ? "A53" : + (type == TY_ITYP_VER_A57 ? "A57" : " ")), + strmhz(buf, sysinfo.freq_processor[core])); + } + printf("\n Bus: %-4s MHz ", + strmhz(buf, sysinfo.freq_systembus)); + printf("DDR: %-4s MHz", strmhz(buf, sysinfo.freq_ddrbus)); + puts("\n"); + + return 0; +} +#endif diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.h b/arch/arm/cpu/armv8/fsl-lsch3/cpu.h new file mode 100644 index 0000000..28544d7 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.h @@ -0,0 +1,7 @@ +/* + * Copyright 2014, Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +int fsl_qoriq_core_to_cluster(unsigned int core); diff --git a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S new file mode 100644 index 0000000..ad32b6c --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S @@ -0,0 +1,65 @@ +/* + * (C) Copyright 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Extracted from armv8/start.S + */ + +#include +#include +#include + +ENTRY(lowlevel_init) + mov x29, lr /* Save LR */ + + /* Set the SMMU page size in the sACR register */ + ldr x1, =SMMU_BASE + ldr w0, [x1, #0x10] + orr w0, w0, #1 << 16 /* set sACR.pagesize to indicate 64K page */ + str w0, [x1, #0x10] + + /* Initialize GIC Secure Bank Status */ +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) + branch_if_slave x0, 1f + ldr x0, =GICD_BASE + bl gic_init_secure +1: +#ifdef CONFIG_GICV3 + ldr x0, =GICR_BASE + bl gic_init_secure_percpu +#elif defined(CONFIG_GICV2) + ldr x0, =GICD_BASE + ldr x1, =GICC_BASE + bl gic_init_secure_percpu +#endif +#endif + + branch_if_master x0, x1, 1f + + /* + * Slave should wait for master clearing spin table. + * This sync prevent salves observing incorrect + * value of spin table and jumping to wrong place. + */ +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) +#ifdef CONFIG_GICV2 + ldr x0, =GICC_BASE +#endif + bl gic_wait_for_interrupt +#endif + + /* + * All processors will enter EL2 and optionally EL1. + */ + bl armv8_switch_to_el2 +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + bl armv8_switch_to_el1 +#endif + b 2f + +1: +2: + mov lr, x29 /* Restore LR */ + ret +ENDPROC(lowlevel_init) diff --git a/arch/arm/cpu/armv8/fsl-lsch3/speed.c b/arch/arm/cpu/armv8/fsl-lsch3/speed.c new file mode 100644 index 0000000..dc4a34b --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/speed.c @@ -0,0 +1,176 @@ +/* + * Copyright 2014, Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Derived from arch/power/cpu/mpc85xx/speed.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cpu.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS +#define CONFIG_SYS_FSL_NUM_CC_PLLS 6 +#endif + + +void get_sys_info(struct sys_info *sys_info) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); +#ifdef CONFIG_FSL_IFC + struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR; + u32 ccr; +#endif + struct ccsr_clk_cluster_group __iomem *clk_grp[2] = { + (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR), + (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR) + }; + struct ccsr_clk_ctrl __iomem *clk_ctrl = + (void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR); + unsigned int cpu; + const u8 core_cplx_pll[16] = { + [0] = 0, /* CC1 PPL / 1 */ + [1] = 0, /* CC1 PPL / 2 */ + [2] = 0, /* CC1 PPL / 4 */ + [4] = 1, /* CC2 PPL / 1 */ + [5] = 1, /* CC2 PPL / 2 */ + [6] = 1, /* CC2 PPL / 4 */ + [8] = 2, /* CC3 PPL / 1 */ + [9] = 2, /* CC3 PPL / 2 */ + [10] = 2, /* CC3 PPL / 4 */ + [12] = 3, /* CC4 PPL / 1 */ + [13] = 3, /* CC4 PPL / 2 */ + [14] = 3, /* CC4 PPL / 4 */ + }; + + const u8 core_cplx_pll_div[16] = { + [0] = 1, /* CC1 PPL / 1 */ + [1] = 2, /* CC1 PPL / 2 */ + [2] = 4, /* CC1 PPL / 4 */ + [4] = 1, /* CC2 PPL / 1 */ + [5] = 2, /* CC2 PPL / 2 */ + [6] = 4, /* CC2 PPL / 4 */ + [8] = 1, /* CC3 PPL / 1 */ + [9] = 2, /* CC3 PPL / 2 */ + [10] = 4, /* CC3 PPL / 4 */ + [12] = 1, /* CC4 PPL / 1 */ + [13] = 2, /* CC4 PPL / 2 */ + [14] = 4, /* CC4 PPL / 4 */ + }; + + uint i, cluster; + uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS]; + uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS]; + unsigned long sysclk = CONFIG_SYS_CLK_FREQ; + int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS; + u32 c_pll_sel, cplx_pll; + void *offset; + + sys_info->freq_systembus = sysclk; +#ifdef CONFIG_DDR_CLK_FREQ + sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ; +#else + sys_info->freq_ddrbus = sysclk; +#endif + + sys_info->freq_systembus *= (in_le32(&gur->rcwsr[0]) >> + FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) & + FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK; + sys_info->freq_ddrbus *= (in_le32(&gur->rcwsr[0]) >> + FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) & + FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK; + + for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) { + /* + * fixme: prefer to combine the following into one line, but + * cannot pass compiling without warning about in_le32. + */ + offset = (void *)((size_t)clk_grp[i/3] + + offsetof(struct ccsr_clk_cluster_group, + pllngsr[i%3].gsr)); + ratio[i] = (in_le32(offset) >> 1) & 0x3f; + if (ratio[i] > 4) + freq_c_pll[i] = sysclk * ratio[i]; + else + freq_c_pll[i] = sys_info->freq_systembus * ratio[i]; + } + + for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) { + cluster = fsl_qoriq_core_to_cluster(cpu); + c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27) + & 0xf; + cplx_pll = core_cplx_pll[c_pll_sel]; + cplx_pll += cc_group[cluster] - 1; + sys_info->freq_processor[cpu] = + freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel]; + } + +#if defined(CONFIG_FSL_IFC) + ccr = in_le32(&ifc_regs->ifc_ccr); + ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1; + + sys_info->freq_localbus = sys_info->freq_systembus / ccr; +#endif +} + + +int get_clocks(void) +{ + struct sys_info sys_info; + get_sys_info(&sys_info); + gd->cpu_clk = sys_info.freq_processor[0]; + gd->bus_clk = sys_info.freq_systembus; + gd->mem_clk = sys_info.freq_ddrbus; + +#if defined(CONFIG_FSL_ESDHC) + gd->arch.sdhc_clk = gd->bus_clk / 2; +#endif /* defined(CONFIG_FSL_ESDHC) */ + + if (gd->cpu_clk != 0) + return 0; + else + return 1; +} + +/******************************************** + * get_bus_freq + * return system bus freq in Hz + *********************************************/ +ulong get_bus_freq(ulong dummy) +{ + if (!gd->bus_clk) + get_clocks(); + + return gd->bus_clk; +} + +/******************************************** + * get_ddr_freq + * return ddr bus freq in Hz + *********************************************/ +ulong get_ddr_freq(ulong dummy) +{ + if (!gd->mem_clk) + get_clocks(); + + return gd->mem_clk; +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_I2C_CLK: + return get_bus_freq(0) / 2; + default: + printf("Unsupported clock\n"); + } + return 0; +} diff --git a/arch/arm/cpu/armv8/fsl-lsch3/speed.h b/arch/arm/cpu/armv8/fsl-lsch3/speed.h new file mode 100644 index 0000000..15af5b9 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/speed.h @@ -0,0 +1,7 @@ +/* + * Copyright 2014, Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +void get_sys_info(struct sys_info *sys_info); -- cgit v1.1 From b940ca64b22ba8980fd4ec8dda028f6b1a2ed79d Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Mon, 23 Jun 2014 15:15:55 -0700 Subject: armv8/fsl-lsch3: Add support to load and start MC Firmware Adding support to load and start the Layerscape Management Complex (MC) firmware. First, the MC GCR register is set to 0 to reset all cores. MC firmware and DPL images are copied from their location in NOR flash to DDR. MC registers are updated with the location of these images. Deasserting the reset bit of MC GCR register releases core 0 to run. Core 1 will be released by MC firmware. Stop bits are not touched for this step. U-boot waits for MC until it boots up. In case of a failure, device tree is updated accordingly. The MC firmware image uses FIT format. Signed-off-by: J. German Rivera Signed-off-by: York Sun Signed-off-by: Lijun Pan Signed-off-by: Shruti Kanetkar --- arch/arm/cpu/armv8/fsl-lsch3/cpu.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c index 46965f0..c129d03 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c @@ -12,6 +12,7 @@ #include #include "cpu.h" #include "speed.h" +#include DECLARE_GLOBAL_DATA_PTR; @@ -423,3 +424,13 @@ int print_cpuinfo(void) return 0; } #endif + +int cpu_eth_init(bd_t *bis) +{ + int error = 0; + +#ifdef CONFIG_FSL_MC_ENET + error = mc_init(bis); +#endif + return error; +} -- cgit v1.1 From f749db3a75ec483692d7bb6d46a1fbecb65c38ba Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 23 Jun 2014 15:15:56 -0700 Subject: ARMv8/ls2085a_emu: Add LS2085A emulator and simulator board support LS2085A is an ARMv8 implementation. This adds board support for emulator and simulator: Two DDR controllers UART2 is used as the console IFC timing is tightened for speedy booting Support DDR3 and DDR4 as separated targets Management Complex (MC) is enabled Support for GIC 500 (based on GICv3 arch) Signed-off-by: York Sun Signed-off-by: Arnab Basu Signed-off-by: J. German Rivera Signed-off-by: Bhupesh Sharma --- arch/arm/cpu/armv8/fsl-lsch3/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv8/fsl-lsch3/README b/arch/arm/cpu/armv8/fsl-lsch3/README index de34a91..cc47466 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/README +++ b/arch/arm/cpu/armv8/fsl-lsch3/README @@ -7,4 +7,4 @@ Freescale LayerScape with Chassis Generation 3 This architecture supports Freescale ARMv8 SoCs with Chassis generation 3, -for example LS2100A. +for example LS2085A. -- cgit v1.1 From fcfddfd50472d7ce84ef4e2853242bbeb7b37325 Mon Sep 17 00:00:00 2001 From: Jeroen Hofstee Date: Mon, 23 Jun 2014 22:07:04 +0200 Subject: ARM: cache_v7: use __weak This is not only more readable but also prevents a warning about a missing prototype. The prototypes which are actually missing are added. cc: Albert Aribaud Signed-off-by: Jeroen Hofstee Reviewed-by: Tom Rini --- arch/arm/cpu/armv7/cache_v7.c | 45 +++++++------------------------------------ 1 file changed, 7 insertions(+), 38 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c index bc5fc42..a2c4032 100644 --- a/arch/arm/cpu/armv7/cache_v7.c +++ b/arch/arm/cpu/armv7/cache_v7.c @@ -354,41 +354,10 @@ void invalidate_icache_all(void) } #endif -/* - * Stub implementations for outer cache operations - */ -void __v7_outer_cache_enable(void) -{ -} -void v7_outer_cache_enable(void) - __attribute__((weak, alias("__v7_outer_cache_enable"))); - -void __v7_outer_cache_disable(void) -{ -} -void v7_outer_cache_disable(void) - __attribute__((weak, alias("__v7_outer_cache_disable"))); - -void __v7_outer_cache_flush_all(void) -{ -} -void v7_outer_cache_flush_all(void) - __attribute__((weak, alias("__v7_outer_cache_flush_all"))); - -void __v7_outer_cache_inval_all(void) -{ -} -void v7_outer_cache_inval_all(void) - __attribute__((weak, alias("__v7_outer_cache_inval_all"))); - -void __v7_outer_cache_flush_range(u32 start, u32 end) -{ -} -void v7_outer_cache_flush_range(u32 start, u32 end) - __attribute__((weak, alias("__v7_outer_cache_flush_range"))); - -void __v7_outer_cache_inval_range(u32 start, u32 end) -{ -} -void v7_outer_cache_inval_range(u32 start, u32 end) - __attribute__((weak, alias("__v7_outer_cache_inval_range"))); +/* Stub implementations for outer cache operations */ +__weak void v7_outer_cache_enable(void) {} +__weak void v7_outer_cache_disable(void) {} +__weak void v7_outer_cache_flush_all(void) {} +__weak void v7_outer_cache_inval_all(void) {} +__weak void v7_outer_cache_flush_range(u32 start, u32 end) {} +__weak void v7_outer_cache_inval_range(u32 start, u32 end) {} -- cgit v1.1 From 7237d22baac9ebeffc946dfd30b9f61aaf0bfdbc Mon Sep 17 00:00:00 2001 From: Sergey Kostanbaev Date: Wed, 25 Jun 2014 23:44:29 +0400 Subject: arm: ep9315: Return back Cirrus Logic EDB9315A board support This patch returns back support for old ep93xx processors family Signed-off-by: Sergey Kostanbaev Cc: albert.u.boot@aribaud.net --- arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S | 463 ++++++++++++++++++++++++++-- 1 file changed, 436 insertions(+), 27 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S b/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S index bf2fa2a..cfad206 100644 --- a/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S +++ b/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S @@ -2,48 +2,457 @@ * Low-level initialization for EP93xx * * Copyright (C) 2009 Matthias Kaehlcke + * Copyright (C) 2013 + * Sergey Kostanabev fairwaves.ru> * * Copyright (C) 2006 Dominic Rath + * Copyright (C) 2006 Cirrus Logic Inc. + * + * See file CREDITS for list of people who contributed to this + * project. * * SPDX-License-Identifier: GPL-2.0+ */ -#include -#include +#include +#include + +/* +/* Configure the SDRAM based on the supplied settings. + * + * Input: r0 - SDRAM DEVCFG register + * r2 - configuration for SDRAM chips + * Output: none + * Modifies: r3, r4 + */ +ep93xx_sdram_config: + /* Program the SDRAM device configuration register. */ + ldr r3, =SDRAM_BASE +#ifdef CONFIG_EDB93XX_SDCS0 + str r0, [r3, #SDRAM_OFF_DEVCFG0] +#endif +#ifdef CONFIG_EDB93XX_SDCS1 + str r0, [r3, #SDRAM_OFF_DEVCFG1] +#endif +#ifdef CONFIG_EDB93XX_SDCS2 + str r0, [r3, #SDRAM_OFF_DEVCFG2] +#endif +#ifdef CONFIG_EDB93XX_SDCS3 + str r0, [r3, #SDRAM_OFF_DEVCFG3] +#endif + + /* Set the Initialize and MRS bits (issue continuous NOP commands + * (INIT & MRS set)) + */ + ldr r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_INIT | \ + EP93XX_SDRAMCTRL_GLOBALCFG_MRS | \ + EP93XX_SDRAMCTRL_GLOBALCFG_CKE) + str r4, [r3, #SDRAM_OFF_GLCONFIG] + + /* Delay for 200us. */ + mov r4, #0x3000 +delay1: + subs r4, r4, #1 + bne delay1 + + /* Clear the MRS bit to issue a precharge all. */ + ldr r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_INIT | \ + EP93XX_SDRAMCTRL_GLOBALCFG_CKE) + str r4, [r3, #SDRAM_OFF_GLCONFIG] + + /* Temporarily set the refresh timer to 0x10. Make it really low so + * that refresh cycles are generated. + */ + ldr r4, =0x10 + str r4, [r3, #SDRAM_OFF_REFRSHTIMR] + + /* Delay for at least 80 SDRAM clock cycles. */ + mov r4, #80 +delay2: + subs r4, r4, #1 + bne delay2 + + /* Set the refresh timer to the fastest required for any device + * that might be used. Set 9.6 ms refresh time. + */ + ldr r4, =0x01e0 + str r4, [r3, #SDRAM_OFF_REFRSHTIMR] + + /* Select mode register update mode. */ + ldr r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_CKE | \ + EP93XX_SDRAMCTRL_GLOBALCFG_MRS) + str r4, [r3, #SDRAM_OFF_GLCONFIG] + + /* Program the mode register on the SDRAM by performing fake read */ + ldr r4, [r2] + + /* Select normal operating mode. */ + ldr r4, =EP93XX_SDRAMCTRL_GLOBALCFG_CKE + str r4, [r3, #SDRAM_OFF_GLCONFIG] + + /* Return to the caller. */ + mov pc, lr + +/* + * Test to see if the SDRAM has been configured in a usable mode. + * + * Input: r0 - Test address of SDRAM + * Output: r0 - 0 -- Test OK, -1 -- Failed + * Modifies: r0-r5 + */ +ep93xx_sdram_test: + /* Load the test patterns to be written to SDRAM. */ + ldr r1, =0xf00dface + ldr r2, =0xdeadbeef + ldr r3, =0x08675309 + ldr r4, =0xdeafc0ed + + /* Store the test patterns to SDRAM. */ + stmia r0, {r1-r4} + + /* Load the test patterns from SDRAM one at a time and compare them + * to the actual pattern. + */ + ldr r5, [r0] + cmp r5, r1 + ldreq r5, [r0, #0x0004] + cmpeq r5, r2 + ldreq r5, [r0, #0x0008] + cmpeq r5, r3 + ldreq r5, [r0, #0x000c] + cmpeq r5, r4 + + /* Return -1 if a mismatch was encountered, 0 otherwise. */ + mvnne r0, #0xffffffff + moveq r0, #0x00000000 + + /* Return to the caller. */ + mov pc, lr + +/* + * Determine the size of the SDRAM. Use data=address for the scan. + * + * Input: r0 - Start SDRAM address + * Return: r0 - Single block size + * r1 - Valid block mask + * r2 - Total block count + * Modifies: r0-r5 + */ +ep93xx_sdram_size: + /* Store zero at offset zero. */ + str r0, [r0] + + /* Start checking for an alias at 1MB into SDRAM. */ + ldr r1, =0x00100000 + + /* Store the offset at the current offset. */ +check_block_size: + str r1, [r0, r1] + + /* Read back from zero. */ + ldr r2, [r0] + + /* Stop searching of an alias was found. */ + cmp r1, r2 + beq found_block_size + + /* Advance to the next power of two boundary. */ + mov r1, r1, lsl #1 + + /* Loop back if the size has not reached 256MB. */ + cmp r1, #0x10000000 + bne check_block_size + + /* A full 256MB of memory was found, so return it now. */ + ldr r0, =0x10000000 + ldr r1, =0x00000000 + ldr r2, =0x00000001 + mov pc, lr + + /* An alias was found. See if the first block is 128MB in size. */ +found_block_size: + cmp r1, #0x08000000 + + /* The first block is 128MB, so there is no further memory. Return it + * now. + */ + ldreq r0, =0x08000000 + ldreq r1, =0x00000000 + ldreq r2, =0x00000001 + moveq pc, lr + + /* Save the block size, set the block address bits to zero, and + * initialize the block count to one. + */ + mov r3, r1 + ldr r4, =0x00000000 + ldr r5, =0x00000001 + + /* Look for additional blocks of memory by searching for non-aliases. */ +find_blocks: + /* Store zero back to address zero. It may be overwritten. */ + str r0, [r0] + + /* Advance to the next power of two boundary. */ + mov r1, r1, lsl #1 + + /* Store the offset at the current offset. */ + str r1, [r0, r1] + + /* Read back from zero. */ + ldr r2, [r0] + + /* See if a non-alias was found. */ + cmp r1, r2 + + /* If a non-alias was found, then or in the block address bit and + * multiply the block count by two (since there are two unique + * blocks, one with this bit zero and one with it one). + */ + orrne r4, r4, r1 + movne r5, r5, lsl #1 + + /* Continue searching if there are more address bits to check. */ + cmp r1, #0x08000000 + bne find_blocks + + /* Return the block size, address mask, and count. */ + mov r0, r3 + mov r1, r4 + mov r2, r5 + + /* Return to the caller. */ + mov pc, lr + .globl lowlevel_init lowlevel_init: - /* backup return address */ - ldr r1, =SYSCON_SCRATCH0 - str lr, [r1] - /* Turn on both LEDs */ - bl red_led_on - bl green_led_on + mov r6, lr + + /* Make sure caches are off and invalidated. */ + ldr r0, =0x00000000 + mcr p15, 0, r0, c1, c0, 0 + nop + nop + nop + nop + nop + + /* Turn off the green LED and turn on the red LED. If the red LED + * is left on for too long, the external reset circuit described + * by application note AN258 will cause the system to reset. + */ + ldr r1, =EP93XX_LED_DATA + ldr r0, [r1] + bic r0, r0, #EP93XX_LED_GREEN_ON + orr r0, r0, #EP93XX_LED_RED_ON + str r0, [r1] + + /* Undo the silly static memory controller programming performed + * by the boot rom. + */ + ldr r0, =SMC_BASE + + /* Set WST1 and WST2 to 31 HCLK cycles (slowest access) */ + ldr r1, =0x0000fbe0 + + /* Reset EP93XX_OFF_SMCBCR0 */ + ldr r2, [r0] + orr r2, r2, r1 + str r2, [r0] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR1] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR1] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR2] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR2] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR3] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR3] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR6] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR6] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR7] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR7] + + /* Set the PLL1 and processor clock. */ + ldr r0, =SYSCON_BASE +#ifdef CONFIG_EDB9301 + /* 332MHz, giving a 166MHz processor clock. */ + ldr r1, = 0x02b49907 +#else + +#ifdef CONFIG_EDB93XX_INDUSTRIAL + /* 384MHz, giving a 196MHz processor clock. */ + ldr r1, =0x02a4bb38 +#else + /* 400MHz, giving a 200MHz processor clock. */ + ldr r1, =0x02a4e39e +#endif +#endif + str r1, [r0, #SYSCON_OFF_CLKSET1] + + nop + nop + nop + nop + nop + + /* Need to make sure that SDRAM is configured correctly before + * coping the code into it. + */ + +#ifdef CONFIG_EDB93XX_SDCS0 + mov r11, #SDRAM_DEVCFG0_BASE +#endif +#ifdef CONFIG_EDB93XX_SDCS1 + mov r11, #SDRAM_DEVCFG1_BASE +#endif +#ifdef CONFIG_EDB93XX_SDCS2 + mov r11, #SDRAM_DEVCFG2_BASE +#endif +#ifdef CONFIG_EDB93XX_SDCS3 + ldr r0, =SYSCON_BASE + ldr r0, [r0, #SYSCON_OFF_SYSCFG] + ands r0, r0, #SYSCON_SYSCFG_LASDO + moveq r11, #SDRAM_DEVCFG3_ASD0_BASE + movne r11, #SDRAM_DEVCFG3_ASD1_BASE +#endif + /* See Table 13-5 in EP93xx datasheet for more info about DRAM + * register mapping */ + + /* Try a 32-bit wide configuration of SDRAM. */ + ldr r0, =(EP93XX_SDRAMCTRL_DEVCFG_BANKCOUNT | \ + EP93XX_SDRAMCTRL_DEVCFG_SROMLL | \ + EP93XX_SDRAMCTRL_DEVCFG_CASLAT_2 | \ + EP93XX_SDRAMCTRL_DEVCFG_RASTOCAS_2) + + /* Set burst count: 4 and CAS: 2 + * Burst mode [A11:A10]; CAS [A16:A14] + */ + orr r2, r11, #0x00008800 + bl ep93xx_sdram_config + + /* Test the SDRAM. */ + mov r0, r11 + bl ep93xx_sdram_test + cmp r0, #0x00000000 + beq ep93xx_sdram_done + + /* Try a 16-bit wide configuration of SDRAM. */ + ldr r0, =(EP93XX_SDRAMCTRL_DEVCFG_BANKCOUNT | \ + EP93XX_SDRAMCTRL_DEVCFG_SROMLL | \ + EP93XX_SDRAMCTRL_DEVCFG_CASLAT_2 | \ + EP93XX_SDRAMCTRL_DEVCFG_RASTOCAS_2 | \ + EP93XX_SDRAMCTRL_DEVCFG_EXTBUSWIDTH) + + /* Set burst count: 8, CAS: 2, sequential burst + * Accoring to Table 13-3 for 16bit operations mapping must be shifted. + * Burst mode [A10:A9]; CAS [A15:A13] + */ + orr r2, r11, #0x00004600 + bl ep93xx_sdram_config + + /* Test the SDRAM. */ + mov r0, r11 + bl ep93xx_sdram_test + cmp r0, #0x00000000 + beq ep93xx_sdram_done + + /* Turn off the red LED. */ + ldr r0, =EP93XX_LED_DATA + ldr r1, [r0] + bic r1, r1, #EP93XX_LED_RED_ON + str r1, [r0] + + /* There is no SDRAM so flash the green LED. */ +flash_green: + orr r1, r1, #EP93XX_LED_GREEN_ON + str r1, [r0] + ldr r2, =0x00010000 +flash_green_delay_1: + subs r2, r2, #1 + bne flash_green_delay_1 + bic r1, r1, #EP93XX_LED_GREEN_ON + str r1, [r0] + ldr r2, =0x00010000 +flash_green_delay_2: + subs r2, r2, #1 + bne flash_green_delay_2 + orr r1, r1, #EP93XX_LED_GREEN_ON + str r1, [r0] + ldr r2, =0x00010000 +flash_green_delay_3: + subs r2, r2, #1 + bne flash_green_delay_3 + bic r1, r1, #EP93XX_LED_GREEN_ON + str r1, [r0] + ldr r2, =0x00050000 +flash_green_delay_4: + subs r2, r2, #1 + bne flash_green_delay_4 + b flash_green + - /* Configure flash wait states before we switch to the PLL */ - bl flash_cfg +ep93xx_sdram_done: + ldr r1, =EP93XX_LED_DATA + ldr r0, [r1] + bic r0, r0, #EP93XX_LED_RED_ON + str r0, [r1] - /* Set up PLL */ - bl pll_cfg + /* Determine the size of the SDRAM. */ + mov r0, r11 + bl ep93xx_sdram_size - /* Turn off the Green LED and leave the Red LED on */ - bl green_led_off + /* Save the SDRAM characteristics. */ + mov r8, r0 + mov r9, r1 + mov r10, r2 - /* Setup SDRAM */ - bl sdram_cfg + /* Compute total memory size into r1 */ + mul r1, r8, r10 +#ifdef CONFIG_EDB93XX_SDCS0 + ldr r2, [r0, #SDRAM_OFF_DEVCFG0] +#endif +#ifdef CONFIG_EDB93XX_SDCS1 + ldr r2, [r0, #SDRAM_OFF_DEVCFG1] +#endif +#ifdef CONFIG_EDB93XX_SDCS2 + ldr r2, [r0, #SDRAM_OFF_DEVCFG2] +#endif +#ifdef CONFIG_EDB93XX_SDCS3 + ldr r2, [r0, #SDRAM_OFF_DEVCFG3] +#endif - /* Turn on Green LED, Turn off the Red LED */ - bl green_led_on - bl red_led_off + /* Consider small DRAM size as: + * < 32Mb for 32bit bus + * < 64Mb for 16bit bus + */ + tst r2, #EP93XX_SDRAMCTRL_DEVCFG_EXTBUSWIDTH + moveq r1, r1, lsr #1 + cmp r1, #0x02000000 - /* FIXME: we use async mode for now */ - mrc p15, 0, r0, c1, c0, 0 - orr r0, r0, #0xc0000000 - mcr p15, 0, r0, c1, c0, 0 +#if defined(CONFIG_EDB9301) + /* Set refresh counter to 20ms for small DRAM size, otherwise 9.6ms */ + movlt r1, #0x03f0 + movge r1, #0x01e0 +#else + /* Set refresh counter to 30.7ms for small DRAM size, otherwise 15ms */ + movlt r1, #0x0600 + movge r1, #0x2f0 +#endif + str r1, [r0, #SDRAM_OFF_REFRSHTIMR] - /* restore return address */ - ldr r1, =SYSCON_SCRATCH0 - ldr lr, [r1] + /* Save the memory configuration information. */ + orr r0, r11, #UBOOT_MEMORYCNF_BANK_SIZE + stmia r0, {r8-r11} - mov pc, lr + mov lr, r6 + mov pc, lr -- cgit v1.1 From dc4d4aa14be278eaf7354c2916da6c5e7a538828 Mon Sep 17 00:00:00 2001 From: Chin Liang See Date: Tue, 10 Jun 2014 01:17:42 -0500 Subject: socfpga: Adding Scan Manager driver Scan Manager driver will be called to configure the IOCSR scan chain. This configuration will setup the IO buffer settings Signed-off-by: Chin Liang See Cc: Dinh Nguyen Cc: Wolfgang Denk CC: Pavel Machek Cc: Tom Rini Cc: Albert Aribaud --- arch/arm/cpu/armv7/socfpga/Makefile | 2 +- arch/arm/cpu/armv7/socfpga/scan_manager.c | 209 ++++++++++++++++++++++++++++++ arch/arm/cpu/armv7/socfpga/spl.c | 4 + 3 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/socfpga/scan_manager.c (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/socfpga/Makefile b/arch/arm/cpu/armv7/socfpga/Makefile index cbe1d40..eb33f2c 100644 --- a/arch/arm/cpu/armv7/socfpga/Makefile +++ b/arch/arm/cpu/armv7/socfpga/Makefile @@ -9,4 +9,4 @@ obj-y := lowlevel_init.o obj-y += misc.o timer.o reset_manager.o system_manager.o clock_manager.o -obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o +obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o scan_manager.o diff --git a/arch/arm/cpu/armv7/socfpga/scan_manager.c b/arch/arm/cpu/armv7/socfpga/scan_manager.c new file mode 100644 index 0000000..a820b1b --- /dev/null +++ b/arch/arm/cpu/armv7/socfpga/scan_manager.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2013 Altera Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static const struct socfpga_scan_manager *scan_manager_base = + (void *)(SOCFPGA_SCANMGR_ADDRESS); +static const struct socfpga_freeze_controller *freeze_controller_base = + (void *)(SOCFPGA_SYSMGR_ADDRESS + SYSMGR_FRZCTRL_ADDRESS); + +/* + * Function to check IO scan chain engine status and wait if the engine is + * is active. Poll the IO scan chain engine till maximum iteration reached. + */ +static inline uint32_t scan_chain_engine_is_idle(uint32_t max_iter) +{ + uint32_t scanmgr_status; + + scanmgr_status = readl(&scan_manager_base->stat); + + /* Poll the engine until the scan engine is inactive */ + while (SCANMGR_STAT_ACTIVE_GET(scanmgr_status) || + (SCANMGR_STAT_WFIFOCNT_GET(scanmgr_status) > 0)) { + max_iter--; + if (max_iter > 0) + scanmgr_status = readl(&scan_manager_base->stat); + else + return 0; + } + return 1; +} + +/* Program HPS IO Scan Chain */ +uint32_t scan_mgr_io_scan_chain_prg( + uint32_t io_scan_chain_id, + uint32_t io_scan_chain_len_in_bits, + const uint32_t *iocsr_scan_chain) +{ + uint16_t tdi_tdo_header; + uint32_t io_program_iter; + uint32_t io_scan_chain_data_residual; + uint32_t residual; + uint32_t i; + uint32_t index = 0; + + /* + * De-assert reinit if the IO scan chain is intended for HIO. In + * this, its the chain 3. + */ + if (io_scan_chain_id == 3) + clrbits_le32(&freeze_controller_base->hioctrl, + SYSMGR_FRZCTRL_HIOCTRL_DLLRST_MASK); + + /* + * Check if the scan chain engine is inactive and the + * WFIFO is empty before enabling the IO scan chain + */ + if (!scan_chain_engine_is_idle(SCAN_MAX_DELAY)) + return 1; + + /* + * Enable IO Scan chain based on scan chain id + * Note: only one chain can be enabled at a time + */ + setbits_le32(&scan_manager_base->en, 1 << io_scan_chain_id); + + /* + * Calculate number of iteration needed for full 128-bit (4 x32-bits) + * bits shifting. Each TDI_TDO packet can shift in maximum 128-bits + */ + io_program_iter = io_scan_chain_len_in_bits >> + IO_SCAN_CHAIN_128BIT_SHIFT; + io_scan_chain_data_residual = io_scan_chain_len_in_bits & + IO_SCAN_CHAIN_128BIT_MASK; + + /* Construct TDI_TDO packet for 128-bit IO scan chain (2 bytes) */ + tdi_tdo_header = TDI_TDO_HEADER_FIRST_BYTE | + (TDI_TDO_MAX_PAYLOAD << TDI_TDO_HEADER_SECOND_BYTE_SHIFT); + + /* Program IO scan chain in 128-bit iteration */ + for (i = 0; i < io_program_iter; i++) { + /* write TDI_TDO packet header to scan manager */ + writel(tdi_tdo_header, &scan_manager_base->fifo_double_byte); + + /* calculate array index. Multiply by 4 as write 4 x 32bits */ + index = i * 4; + + /* write 4 successive 32-bit IO scan chain data into WFIFO */ + writel(iocsr_scan_chain[index], + &scan_manager_base->fifo_quad_byte); + writel(iocsr_scan_chain[index + 1], + &scan_manager_base->fifo_quad_byte); + writel(iocsr_scan_chain[index + 2], + &scan_manager_base->fifo_quad_byte); + writel(iocsr_scan_chain[index + 3], + &scan_manager_base->fifo_quad_byte); + + /* + * Check if the scan chain engine has completed the + * IO scan chain data shifting + */ + if (!scan_chain_engine_is_idle(SCAN_MAX_DELAY)) + goto error; + } + + /* Calculate array index for final TDI_TDO packet */ + index = io_program_iter * 4; + + /* Final TDI_TDO packet if any */ + if (io_scan_chain_data_residual) { + /* + * Calculate number of quad bytes FIFO write + * needed for the final TDI_TDO packet + */ + io_program_iter = io_scan_chain_data_residual >> + IO_SCAN_CHAIN_32BIT_SHIFT; + + /* + * Construct TDI_TDO packet for remaining IO + * scan chain (2 bytes) + */ + tdi_tdo_header = TDI_TDO_HEADER_FIRST_BYTE | + ((io_scan_chain_data_residual - 1) << + TDI_TDO_HEADER_SECOND_BYTE_SHIFT); + + /* + * Program the last part of IO scan chain write TDI_TDO packet + * header (2 bytes) to scan manager + */ + writel(tdi_tdo_header, &scan_manager_base->fifo_double_byte); + + for (i = 0; i < io_program_iter; i++) { + /* + * write remaining scan chain data into scan + * manager WFIFO with 4 bytes write + */ + writel(iocsr_scan_chain[index + i], + &scan_manager_base->fifo_quad_byte); + } + + index += io_program_iter; + residual = io_scan_chain_data_residual & + IO_SCAN_CHAIN_32BIT_MASK; + + if (IO_SCAN_CHAIN_PAYLOAD_24BIT < residual) { + /* + * write the last 4B scan chain data + * into scan manager WFIFO + */ + writel(iocsr_scan_chain[index], + &scan_manager_base->fifo_quad_byte); + } else { + /* + * write the remaining 1 - 3 bytes scan chain + * data into scan manager WFIFO byte by byte + * to prevent JTAG engine shifting unused data + * from the FIFO and mistaken the data as a + * valid command (even though unused bits are + * set to 0, but just to prevent hardware + * glitch) + */ + for (i = 0; i < residual; i += 8) { + writel(((iocsr_scan_chain[index] >> i) + & IO_SCAN_CHAIN_BYTE_MASK), + &scan_manager_base->fifo_single_byte); + } + } + + /* + * Check if the scan chain engine has completed the + * IO scan chain data shifting + */ + if (!scan_chain_engine_is_idle(SCAN_MAX_DELAY)) + goto error; + } + + /* Disable IO Scan chain when configuration done*/ + clrbits_le32(&scan_manager_base->en, 1 << io_scan_chain_id); + return 0; + +error: + /* Disable IO Scan chain when error detected */ + clrbits_le32(&scan_manager_base->en, 1 << io_scan_chain_id); + return 1; +} + +int scan_mgr_configure_iocsr(void) +{ + int status = 0; + + /* configure the IOCSR through scan chain */ + status |= scan_mgr_io_scan_chain_prg(0, + CONFIG_HPS_IOCSR_SCANCHAIN0_LENGTH, iocsr_scan_chain0_table); + status |= scan_mgr_io_scan_chain_prg(1, + CONFIG_HPS_IOCSR_SCANCHAIN1_LENGTH, iocsr_scan_chain1_table); + status |= scan_mgr_io_scan_chain_prg(2, + CONFIG_HPS_IOCSR_SCANCHAIN2_LENGTH, iocsr_scan_chain2_table); + status |= scan_mgr_io_scan_chain_prg(3, + CONFIG_HPS_IOCSR_SCANCHAIN3_LENGTH, iocsr_scan_chain3_table); + return status; +} diff --git a/arch/arm/cpu/armv7/socfpga/spl.c b/arch/arm/cpu/armv7/socfpga/spl.c index 2ae88bb..4bed19d 100644 --- a/arch/arm/cpu/armv7/socfpga/spl.c +++ b/arch/arm/cpu/armv7/socfpga/spl.c @@ -121,6 +121,10 @@ void spl_board_init(void) /* reconfigure the PLLs */ cm_basic_init(&cm_default_cfg); + /* configure the IOCSR / IO buffer settings */ + if (scan_mgr_configure_iocsr()) + hang(); + /* configure the pin muxing through system manager */ sysmgr_pinmux_init(); #endif /* CONFIG_SOCFPGA_VIRTUAL_TARGET */ -- cgit v1.1 From 23f23f23d509e8e873797884456070c8a47d72b2 Mon Sep 17 00:00:00 2001 From: Chin Liang See Date: Tue, 10 Jun 2014 02:23:45 -0500 Subject: socfpga: Relocate arch common functions away from board To move the arch common function away from board folder to arch/arm/cpu/armv7/socfpga folder. Its to avoid code duplication for other non Altera dev kit which is using socfpga device. Signed-off-by: Chin Liang See Cc: Wolfgang Denk Cc: Detlev Zundel Cc: Pavel Machek Cc: Dinh Nguyen Acked-by: Detlev Zundel --- arch/arm/cpu/armv7/socfpga/misc.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/socfpga/misc.c b/arch/arm/cpu/armv7/socfpga/misc.c index 2f1c716..5268f2c 100644 --- a/arch/arm/cpu/armv7/socfpga/misc.c +++ b/arch/arm/cpu/armv7/socfpga/misc.c @@ -14,3 +14,27 @@ int dram_init(void) gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); return 0; } + +#if defined(CONFIG_DISPLAY_CPUINFO) +/* + * Print CPU information + */ +int print_cpuinfo(void) +{ + puts("CPU : Altera SOCFPGA Platform\n"); + return 0; +} +#endif + +#if defined(CONFIG_SYS_CONSOLE_IS_IN_ENV) && \ +defined(CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE) +int overwrite_console(void) +{ + return 0; +} +#endif + +int misc_init_r(void) +{ + return 0; +} -- cgit v1.1 From 878cae6b0263576317fcd77bf903cb9e503e6cc7 Mon Sep 17 00:00:00 2001 From: Jeroen Hofstee Date: Wed, 18 Jun 2014 21:22:35 +0200 Subject: ARM: emif4: wait for CM_DLL_READYST to be set The code intends for the CM_DLL_READYST to be set, but actually polls till any bit is set since the logical AND is used instead of the bitwise one is used. Fix it. cc: Lokesh Vutla Signed-off-by: Jeroen Hofstee --- arch/arm/cpu/armv7/am33xx/emif4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/emif4.c b/arch/arm/cpu/armv7/am33xx/emif4.c index a7a3e88..8b7527c 100644 --- a/arch/arm/cpu/armv7/am33xx/emif4.c +++ b/arch/arm/cpu/armv7/am33xx/emif4.c @@ -115,7 +115,7 @@ void config_ddr(unsigned int pll, const struct ctrl_ioregs *ioregs, #endif #ifdef CONFIG_AM43XX writel(readl(&cm_device->cm_dll_ctrl) & ~0x1, &cm_device->cm_dll_ctrl); - while ((readl(&cm_device->cm_dll_ctrl) && CM_DLL_READYST) == 0) + while ((readl(&cm_device->cm_dll_ctrl) & CM_DLL_READYST) == 0) ; writel(0x80000000, &ddrctrl->ddrioctrl); -- cgit v1.1 From 8038b497e742af2845523ed09b560bfc8cb42089 Mon Sep 17 00:00:00 2001 From: "Cooper Jr., Franklin" Date: Fri, 27 Jun 2014 13:31:15 -0500 Subject: am43xx: Tune the system to avoid DSS underflows * This is done by limiting the ARM's bandwidth and setting DSS priority in the EMIF controller to ensure underflows do not occur. --- arch/arm/cpu/armv7/am33xx/ddr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c index bbe9d1a..fc66872 100644 --- a/arch/arm/cpu/armv7/am33xx/ddr.c +++ b/arch/arm/cpu/armv7/am33xx/ddr.c @@ -94,6 +94,18 @@ void config_sdram_emif4d5(const struct emif_regs *regs, int nr) writel(regs->emif_rd_wr_exec_thresh, &emif_reg[nr]->emif_rd_wr_exec_thresh); + /* + * for most SOCs these registers won't need to be changed so only + * write to these registers if someone explicitly has set the + * register's value. + */ + if(regs->emif_cos_config) { + writel(regs->emif_prio_class_serv_map, &emif_reg[nr]->emif_prio_class_serv_map); + writel(regs->emif_connect_id_serv_1_map, &emif_reg[nr]->emif_connect_id_serv_1_map); + writel(regs->emif_connect_id_serv_2_map, &emif_reg[nr]->emif_connect_id_serv_2_map); + writel(regs->emif_cos_config, &emif_reg[nr]->emif_cos_config); + } + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw); writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); -- cgit v1.1