Re: [U-Boot] [PATCH v4 03/10] Exynos542x: Add workaround for ARM errata 798870
Hi Kevin, Akshay Saraswat aksha...@samsung.com writes: [...] I don't think it hurts to have a generic function with ARM errata workaround implementation. Whoever wish to use it can call it in their boot path. And it's not even getting executed right now for any SoC other than Exynos542x, so those who don't want it need not bother about it. This was the intention. :) What about exynos542x platforms which also have secure firmware? Are you testing this on any of those (e.g. exynos5422-odroid-xu3?) No, I have not tested this series on exynos5422-odroid-xu3 becuase I don't have it. :) Probably those who are working on exynos5422-odroid-xu3 should comment. I don't know anything about exynos5422-odroid-xu3 and don't have related documents. But as far as I know, from my past experience, for all such features (SMC calls, secondary cores boot path and configuration), there should be a different secure firmware which may not be U-Boot. If true, this whole series of patches would be useless and CONFIG_EXYNOS5420 should not be defined for such a SoC. Kevin Regards, Akshay Saraswat ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH v4 03/10] Exynos542x: Add workaround for ARM errata 798870
Hi Nishanth, On 17:13-20150224, Nishanth Menon wrote: On 13:27-20150220, Akshay Saraswat wrote: This patch adds workaround for ARM errata 798870 which says If back-to-back speculative cache line fills (fill A and fill B) are issued from the L1 data cache of a CPU to the L2 cache, the second request (fill B) is then cancelled, and the second request would have detected a hazard against a recent write or eviction (write B) to the same cache line as fill B then the L2 logic might deadlock. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - Added errata number in comment. - Moved changes to arm generic armv7.h Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. - Added space before */ on line # 40. arch/arm/include/asm/armv7.h | 16 1 file changed, 16 insertions(+) diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h index a13da23..a2040b7 100644 --- a/arch/arm/include/asm/armv7.h +++ b/arch/arm/include/asm/armv7.h @@ -69,6 +69,22 @@ #define CP15DSB asm volatile (mcr p15, 0, %0, c7, c10, 4 : : r (0)) #define CP15DMB asm volatile (mcr p15, 0, %0, c7, c10, 5 : : r (0)) +/* + * Workaround for ARM errata # 798870 + * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been + * stalled for 1024 cycles to verify that its hazard condition still exists. + */ +static inline void v7_enable_l2_hazard_detect(void) +{ + uint32_t val; + + /* L2ACTLR[7]: Enable hazard detect timeout */ + asm volatile (mrc p15, 1, %0, c15, c0, 0\n\t : =r(val)); + val |= (1 7); + asm volatile (mcr p15, 1, %0, c15, c0, 0\n\t : : r(val)); This wont work for us in DRA7/OMAP5 L2ACTLR cannot be modified by u-boot. has to go to secure world using smc call. +} + +void v7_en_l2_hazard_detect(void); void v7_outer_cache_enable(void); void v7_outer_cache_disable(void); void v7_outer_cache_flush_all(void); How about this - using the series: https://patchwork.ozlabs.org/patch/443261/ https://patchwork.ozlabs.org/patch/443264/ https://patchwork.ozlabs.org/patch/443268/ https://patchwork.ozlabs.org/patch/443265/ https://patchwork.ozlabs.org/patch/443263/ https://patchwork.ozlabs.org/patch/443262/ https://patchwork.ozlabs.org/patch/443267/ https://patchwork.ozlabs.org/patch/443266/ https://patchwork.ozlabs.org/patch/443260/ I think the following might work for exynos? Yes, that will probably do and if you look at v3 of this patch, we were doing something similar. But I was convinced with the below mentioned comments I recieved over v3, so updated it. Having the ARM errata number mentioned in the comment here would make the purpose of this code much more clear to anyone looking at it later in the future. Also isn't this a general purpose Cortex-A15 r2pX workaround, also potentially useful for the other non-Exynos SoCs too? I don't think it hurts to have a generic function with ARM errata workaround implementation. Whoever wish to use it can call it in their boot path. And it's not even getting executed right now for any SoC other than Exynos542x, so those who don't want it need not bother about it. This was the intention. :) Please let me know if you still want me to move it from armv7.h to exynos/lowlevel_init.c diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 83e1dcfc1e13..0157105524ca 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -42,6 +42,23 @@ enum { DO_POWER= 1 4, }; +#ifdef CONFIG_ARM_ARCH_CP15_ERRATA +void arch_cp15_errata_workaround(u32 midr, u32 variant, u32 rev, u32 comb) +{ +#ifdef CONFIG_ARM_ERRATA_798870 + if (comb = 0x20 comb 0x30) { + uint32_t l2actlr; + + mrc_l2_aux_ctlr(l2actlr); + /* Disable ACE DVM/CMO message broadcas */ + l2actlr |= (1 7); + mcr_l2_aux_ctlr(l2actlr); + mrc_l2_ctlr(l2actlr); + } +#endif +} +#endif + int do_lowlevel_init(void) { uint32_t reset_status; -- Regards, Nishanth Menon Regards, Akshay Saraswat ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH v4 03/10] Exynos542x: Add workaround for ARM errata 798870
On 13:27-20150220, Akshay Saraswat wrote: This patch adds workaround for ARM errata 798870 which says If back-to-back speculative cache line fills (fill A and fill B) are issued from the L1 data cache of a CPU to the L2 cache, the second request (fill B) is then cancelled, and the second request would have detected a hazard against a recent write or eviction (write B) to the same cache line as fill B then the L2 logic might deadlock. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - Added errata number in comment. - Moved changes to arm generic armv7.h Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. - Added space before */ on line # 40. arch/arm/include/asm/armv7.h | 16 1 file changed, 16 insertions(+) diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h index a13da23..a2040b7 100644 --- a/arch/arm/include/asm/armv7.h +++ b/arch/arm/include/asm/armv7.h @@ -69,6 +69,22 @@ #define CP15DSB asm volatile (mcr p15, 0, %0, c7, c10, 4 : : r (0)) #define CP15DMB asm volatile (mcr p15, 0, %0, c7, c10, 5 : : r (0)) +/* + * Workaround for ARM errata # 798870 + * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been + * stalled for 1024 cycles to verify that its hazard condition still exists. + */ +static inline void v7_enable_l2_hazard_detect(void) +{ +uint32_t val; + +/* L2ACTLR[7]: Enable hazard detect timeout */ +asm volatile (mrc p15, 1, %0, c15, c0, 0\n\t : =r(val)); +val |= (1 7); +asm volatile (mcr p15, 1, %0, c15, c0, 0\n\t : : r(val)); This wont work for us in DRA7/OMAP5 L2ACTLR cannot be modified by u-boot. has to go to secure world using smc call. If you dont want to execute it, don't call it. As simple as that. :) If you want to execute it from secure world, then call it from your SMC handler. Does it make sense? +} + +void v7_en_l2_hazard_detect(void); void v7_outer_cache_enable(void); void v7_outer_cache_disable(void); void v7_outer_cache_flush_all(void); How about this - using the series: https://patchwork.ozlabs.org/patch/443261/ https://patchwork.ozlabs.org/patch/443264/ https://patchwork.ozlabs.org/patch/443268/ https://patchwork.ozlabs.org/patch/443265/ https://patchwork.ozlabs.org/patch/443263/ https://patchwork.ozlabs.org/patch/443262/ https://patchwork.ozlabs.org/patch/443267/ https://patchwork.ozlabs.org/patch/443266/ https://patchwork.ozlabs.org/patch/443260/ -- Regards, Nishanth Menon Regards, Akshay Saraswat ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 10/10] Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800
From: Doug Anderson diand...@chromium.org It was found that the L2 cache timings that we had before could cause freezes and hangs. We should make things more robust with better timings. Currently the production ChromeOS kernel applies these timings, but it's nice to fixup firmware too (and upstream probably won't take our kernel hacks). This also provides a big cleanup of the L2 cache init code avoiding some duplication. The way things used to work: * low_power_start() was installed by the SPL (both at boot and resume time) and left resident in iRAM for the kernel to use when bringing up additional CPUs. It used configure_l2_ctlr() and configure_l2_actlr() when it detected it was on an A15. This was needed (despite the L2 cache registers being shared among all A15s) because we might have been the first man in after the whole A15 cluster was shutdown. * secondary_cores_configure() was called on at boot time and at resume time. Strangely this called configure_l2_ctlr() but not configure_l2_actlr() which was almost certainly wrong. Given that we'll call both (see next bullet) later in the boot process it didn't matter for normal boot, but I guess this is how L2 cache settings got set on 5420/5800 (but not 5250?) at resume time. * exynos5_set_l2cache_params() was called as part of cache enablement. This should happen at boot time (normally in the SPL except for USB boot where it happens in main U-Boot). Note that the old code wasn't setting ECC/parity in the cache enablement code but we happened to get it anyway because we'd call secondary_cores_configure() at boot time. For resume time we'd get it anyway when the 2nd A15 core came up. Let's make this a whole lot simpler. Now we always set these parameters in the same place for all boots and use the same code for setting up secondary CPUs. Intended net effects of this change (other than cleanup): * Timings go from before: data: 0 cycle setup, 3 cycles (0x2) latency tag: 0 cycle setup, 3 cycles (0x2) latency after: data: 1 cycle setup, 4 cycles (0x3) latency tag: 1 cycle setup, 4 cycles (0x3) latency * L2ACTLR is properly initted on 5420/5800 in all cases. One note is that we're still relying on luck to keep low_power_start() working. The compiler is being nice and not storing anything on the stack. Another note is that on its own this patch won't help to fix cache settings in an RW U-Boot update where we still have the RO SPL. The plan for that is: * Have RW U-Boot re-init the cache right before calling the kernel (after it has turned the L2 cache off). This is why the functions are in a header file instead of lowlevel_init.c. * Have the kernel save the L2 cache settings of the boot CPU and apply them to all other CPUs. We get a little lucky here because the old code was using |= to modify the registers and all of the bits that it's setting are also present in the new settings (!). That means that when the 2nd CPU in the A15 cluster comes up it doesn't actually mess up the settings of the 1st CPU in the A15 cluster. An alternative option is to have the kernel write its own low_power_start() code. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v3: - Rebased. Changes since v2: - Removed #ifdef from enum definition. Changes since v1: - Fixed compilation error for snow build. arch/arm/cpu/armv7/exynos/common_setup.h | 62 +++ arch/arm/cpu/armv7/exynos/lowlevel_init.c | 55 --- arch/arm/cpu/armv7/exynos/soc.c | 53 -- arch/arm/include/asm/arch-exynos/system.h | 2 - 4 files changed, 77 insertions(+), 95 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/common_setup.h b/arch/arm/cpu/armv7/exynos/common_setup.h index e6318c0..5235abb 100644 --- a/arch/arm/cpu/armv7/exynos/common_setup.h +++ b/arch/arm/cpu/armv7/exynos/common_setup.h @@ -23,6 +23,8 @@ * MA 02111-1307 USA */ +#include asm/arch/system.h + #define DMC_OFFSET 0x1 /* @@ -43,3 +45,63 @@ void system_clock_init(void); int do_lowlevel_init(void); void sdelay(unsigned long); + +enum l2_cache_params { + CACHE_DATA_RAM_LATENCY_2_CYCLES = (2 0), + CACHE_DATA_RAM_LATENCY_3_CYCLES = (3 0), + CACHE_DISABLE_CLEAN_EVICT = (1 3), + CACHE_DATA_RAM_SETUP = (1 5), + CACHE_TAG_RAM_LATENCY_2_CYCLES = (2 6), + CACHE_TAG_RAM_LATENCY_3_CYCLES = (3 6), + CACHE_ENABLE_HAZARD_DETECT = (1 7), + CACHE_TAG_RAM_SETUP = (1 9), + CACHE_ECC_AND_PARITY = (1 21), + CACHE_ENABLE_FORCE_L2_LOGIC = (1 27) +}; + + +#ifndef CONFIG_SYS_L2CACHE_OFF +/* + * Configure L2CTLR to get timings that keep us from hanging/crashing. + * + * Must be inline here since low_power_start() is called without a + * stack (!). + */ +static inline void configure_l2_ctlr(void) +{ + uint32_t val
[U-Boot] [PATCH v4 09/10] Exynos542x: Make A7s boot with thumb-mode U-Boot on warm reset
On warm reset, all cores jump to the low_power_start function because iRAM data is retained and because while executing iROM code all cores find the jump flag 0x02020028 set. In low_power_start, cores check the reset status and if true they clear the jump flag and jump back to 0x0. The A7 cores do jump to 0x0 but consider following instructions as a Thumb instructions which in turn makes them loop inside the iROM code instead of jumping to power_down_core. This issue is fixed by replacing the mov pc instruction with a bx instruction which switches state along with the jump to make the execution unit consider the branch target as an ARM instruction. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - No change. Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 782ecd1..329ab0c 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -103,7 +103,7 @@ static void low_power_start(void) reg_val = readl(EXYNOS5420_SPARE_BASE); if (reg_val != CPU_RST_FLAG_VAL) { writel(0x0, CONFIG_LOWPOWER_FLAG); - set_pc(0x0); + branch_bx(0x0); } reg_val = readl(CONFIG_PHY_IRAM_BASE + 0x4); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 08/10] Exynos542x: Fix secondary core booting for thumb
When compiled SPL for Thumb secondary cores failed to boot at the kernel boot up. Only one core came up out of 4. This was happening because the code relocated to the address 0x02073000 by the primary core was an ARM asm code which was executed by the secondary cores as if it was a thumb code. This patch fixes the issue of secondary cores considering relocated code as Thumb instructions and not ARM instructions by jumping to the relocated with the help of bx ARM instruction. bx instruction changes the 5th bit of CPSR which allows execution unit to consider the following instructions as ARM instructions. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - No change. Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 +- arch/arm/include/asm/arch-exynos/system.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 0504576..782ecd1 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -89,7 +89,7 @@ static void secondary_cpu_start(void) { v7_enable_smp(EXYNOS5420_INFORM_BASE); svc32_mode_en(); - set_pc(CONFIG_EXYNOS_RELOCATE_CODE_BASE); + branch_bx(CONFIG_EXYNOS_RELOCATE_CODE_BASE); } /* diff --git a/arch/arm/include/asm/arch-exynos/system.h b/arch/arm/include/asm/arch-exynos/system.h index 86903c3..a9fd5e6 100644 --- a/arch/arm/include/asm/arch-exynos/system.h +++ b/arch/arm/include/asm/arch-exynos/system.h @@ -75,6 +75,9 @@ struct exynos5_sysreg { /* Set program counter with the given value */ #define set_pc(x) __asm__ __volatile__ (mov pc, %0\n\t : : r(x)) +/* Branch to the given location */ +#define branch_bx(x) __asm__ __volatile__ (bx %0\n\t : : r(x)) + /* Read Main Id register */ #define mrc_midr(x) __asm__ __volatile__ \ (mrc p15, 0, %0, c0, c0, 0\n\t : =r(x) : ) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 02/10] Exynos542x: CPU: Power down all secondary cores
This patch adds code to shutdown secondary cores. When U-boot comes up, all secondary cores appear powered on, which is undesirable and causes side effects while initializing these cores in kernel. Secondary core power down happens in following steps: Step-1: After Exynos power-on, primary core starts executing first. Step-2: In iROM code every core has to check 2 flags i.e. addresses 0x02020028 0x02020004. Step-3: Initially 0x02020028 is 0 for all cores and 0x02020004 has a jump address for primary core and 0 for all secondary cores. Step-4: Therefore, primary core follows normal iROM execution and jumps to BL1 eventually, whereas all secondary cores enter WFE. Step-5: When primary core comes into function secondary_cores_configure, it puts pointer to function power_down_core into 0x02020004 and provides DSB and SEV for all cores so that they may come out of WFE and jump to power_down_core function. Step-6: And ultimately because of power_down_core all secondary cores shut-down. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v3: - No change. Changes since v2: - No change. Changes since v1: - Removed unnecessary macros. - Changed names of few macros for better understanding. - Added MPIDR bit assignment info comment in power_down_core. arch/arm/cpu/armv7/exynos/exynos5_setup.h | 3 ++ arch/arm/cpu/armv7/exynos/lowlevel_init.c | 69 arch/arm/include/asm/arch-exynos/cpu.h| 5 ++ arch/arm/include/asm/arch-exynos/system.h | 87 +++ 4 files changed, 164 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index 2eea48a..9073f50 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -700,6 +700,9 @@ #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE #else + +#define CPU_CONFIG_STATUS_OFFSET 0x80 +#define CPU_RST_FLAG_VAL 0xFCBA0D10 #define PAD_RETENTION_DRAM_COREBLK_VAL 0x1000 /* APLL_CON1 */ diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 83e1dcf..e36f2fa 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -31,7 +31,9 @@ #include asm/arch/tzpc.h #include asm/arch/periph.h #include asm/arch/pinmux.h +#include asm/arch/system.h #include common_setup.h +#include exynos5_setup.h /* These are the things we can do during low-level init */ enum { @@ -42,6 +44,68 @@ enum { DO_POWER= 1 4, }; +#ifdef CONFIG_EXYNOS5420 +/* + * Pointer to this function is stored in iRam which is used + * for jump and power down of a specific core. + */ +static void power_down_core(void) +{ + uint32_t tmp, core_id, core_config; + + /* Get the unique core id */ + /* +* Multiprocessor Affinity Register +* [11:8] Cluster ID +* [1:0]CPU ID +*/ + mrc_mpafr(core_id); + tmp = core_id 0x3; + core_id = (core_id 6) ~3; + core_id |= tmp; + core_id = 0x3f; + + /* Set the status of the core to low */ + core_config = (core_id * CPU_CONFIG_STATUS_OFFSET); + core_config += EXYNOS5420_CPU_CONFIG_BASE; + writel(0x0, core_config); + + /* Core enter WFI */ + wfi(); +} + +/* + * Configurations for secondary cores are inapt at this stage. + * Reconfigure secondary cores. Shutdown and change the status + * of all cores except the primary core. + */ +static void secondary_cores_configure(void) +{ + uint32_t core_id; + + /* Store jump address for power down of secondary cores */ + writel((uint32_t)power_down_core, CONFIG_PHY_IRAM_BASE + 0x4); + + /* Need all core power down check */ + dsb(); + sev(); + + /* +* Power down all cores(secondary) while primary core must +* wait for all cores to go down. +*/ + for (core_id = 1; core_id != CONFIG_CORE_COUNT; core_id++) { + while ((readl(EXYNOS5420_CPU_STATUS_BASE + + (core_id * CPU_CONFIG_STATUS_OFFSET)) +0xff) != 0x0) { + isb(); + sev(); + } + isb(); + } +} +#endif + int do_lowlevel_init(void) { uint32_t reset_status; @@ -49,6 +113,11 @@ int do_lowlevel_init(void) arch_cpu_init(); +#ifdef CONFIG_EXYNOS5420 + /* Reconfigure secondary cores */ + secondary_cores_configure(); +#endif + reset_status = get_reset_status(); switch (reset_status) { diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index 29674ad..e739520 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include
[U-Boot] [PATCH v4 00/11] Add support for booting multiple cores
This patch series introduces changes for booting secondary CPUs on Exynos5420 and Exynos5800. Changes since v3: - Patch 2 3 : Added errata number in comments. - Patch 2 3 : Moved changes to ARM generic file. - Patch 6 : Removed this patch. Not required anymore. Changes since v2: - Patch 7 8 : Replaced #ifdef and #ifndef - if(proid_is_soc()). - Patch 11 : Removed #ifdef from enum definition. Changes since v1: - Added Reviewed-by Tested-by in the acked patches. - Removed unnecessary CONFIGS and macros. - Changed names of few macros for better understanding in patch 2. - Added MPIDR bit assignment info comment in power_down_core in patch 2. - Changed to SPDX header in sec_boot.S in patch 5. - Fixed compilation error for snow build in patch 11. Akshay Saraswat (9): Exynos542x: Config: Add various configs Exynos542x: CPU: Power down all secondary cores Exynos542x: Add workaround for ARM errata 798870 Exynos542x: Add workaround for ARM errata 799270 Exynos542x: Add workaround for exynos iROM errata Exynos542x: cache: Disable clean/evict push to external Exynos542x: add L2 control register configuration Exynos542x: Fix secondary core booting for thumb Exynos542x: Make A7s boot with thumb-mode U-Boot on warm reset Doug Anderson (1): Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800 arch/arm/cpu/armv7/exynos/Makefile| 2 + arch/arm/cpu/armv7/exynos/common_setup.h | 62 + arch/arm/cpu/armv7/exynos/exynos5_setup.h | 3 + arch/arm/cpu/armv7/exynos/lowlevel_init.c | 147 ++ arch/arm/cpu/armv7/exynos/sec_boot.S | 128 ++ arch/arm/cpu/armv7/exynos/soc.c | 35 --- arch/arm/include/asm/arch-exynos/cpu.h| 5 + arch/arm/include/asm/arch-exynos/system.h | 88 ++ arch/arm/include/asm/armv7.h | 44 + include/configs/exynos5420-common.h | 16 10 files changed, 495 insertions(+), 35 deletions(-) create mode 100644 arch/arm/cpu/armv7/exynos/sec_boot.S -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 01/10] Exynos542x: Config: Add various configs
This patch adds iRAM, CPU state and low power configs which are the addresses acting as flag registers. iROM code checks CONFIG_LOWPOWER_FLAG address. If it is equal to CONFIG_LOWPOWER_EN then it jumps to the address (0x0202+CPUID*4). This is a part of iROM logic. Rest other flags are being used at various places during kernel switching and reset. They are nowhere documented because they are part programming. These configs are serving as flags for us because they are representing the addresses in iRAM which we are using for storing and extracting CPU Status and GIC status. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - No change. Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. - Removed unnecessary CONFIGS. include/configs/exynos5420-common.h | 16 1 file changed, 16 insertions(+) diff --git a/include/configs/exynos5420-common.h b/include/configs/exynos5420-common.h index fe72bd0..b42dab7 100644 --- a/include/configs/exynos5420-common.h +++ b/include/configs/exynos5420-common.h @@ -38,4 +38,20 @@ #define CONFIG_BOARD_REV_GPIO_COUNT2 +#define CONFIG_PHY_IRAM_BASE 0x0202 + +/* Address for relocating helper code (Last 4 KB of IRAM) */ +#define CONFIG_EXYNOS_RELOCATE_CODE_BASE (CONFIG_IRAM_TOP - 0x1000) + +/* + * Low Power settings + */ +#define CONFIG_LOWPOWER_FLAG 0x02020028 +#define CONFIG_LOWPOWER_ADDR 0x0202002C + +/* + * Number of CPUs available + */ +#define CONFIG_CORE_COUNT 0x8 + #endif /* __CONFIG_EXYNOS5420_H */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 05/10] Exynos542x: Add workaround for exynos iROM errata
iROM logic provides undesired jump address for CPU2. This patch adds a programmable susbstitute for a part of iROM logic which wakes up cores and provides jump addresses. This patch creates a logic to make all secondary cores jump to a particular address which evades the possibility of CPU2 jumping to wrong address and create undesired results. Logic of the workaround: Step-1: iROM code checks value at address 0x2020028. Step-2: If value is 0xc9cfcfcf, it jumps to the address (0x202000+CPUid*4), else, it continues executing normally. Step-3: Primary core puts secondary cores in WFE and store 0xc9cfcfcf in 0x2020028 and jump address (pointer to function low_power_start) in (0x202000+CPUid*4). Step-4: When secondary cores recieve event signal they jump to this address and continue execution. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - Included armv7.h in lowlevel_init.c. Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. - Changed to SPDX header in sec_boot.S. arch/arm/cpu/armv7/exynos/Makefile| 2 + arch/arm/cpu/armv7/exynos/lowlevel_init.c | 86 arch/arm/cpu/armv7/exynos/sec_boot.S | 128 ++ 3 files changed, 200 insertions(+), 16 deletions(-) create mode 100644 arch/arm/cpu/armv7/exynos/sec_boot.S diff --git a/arch/arm/cpu/armv7/exynos/Makefile b/arch/arm/cpu/armv7/exynos/Makefile index e207bd6..8542f89 100644 --- a/arch/arm/cpu/armv7/exynos/Makefile +++ b/arch/arm/cpu/armv7/exynos/Makefile @@ -7,6 +7,8 @@ obj-y += clock.o power.o soc.o system.o pinmux.o tzpc.o +obj-$(CONFIG_EXYNOS5420) += sec_boot.o + ifdef CONFIG_SPL_BUILD obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index e36f2fa..b94e49f 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -32,6 +32,7 @@ #include asm/arch/periph.h #include asm/arch/pinmux.h #include asm/arch/system.h +#include asm/armv7.h #include common_setup.h #include exynos5_setup.h @@ -46,6 +47,61 @@ enum { #ifdef CONFIG_EXYNOS5420 /* + * Power up secondary CPUs. + */ +static void secondary_cpu_start(void) +{ + v7_enable_smp(EXYNOS5420_INFORM_BASE); + svc32_mode_en(); + set_pc(CONFIG_EXYNOS_RELOCATE_CODE_BASE); +} + +/* + * This is the entry point of hotplug-in and + * cluster switching. + */ +static void low_power_start(void) +{ + uint32_t val, reg_val; + + reg_val = readl(EXYNOS5420_SPARE_BASE); + if (reg_val != CPU_RST_FLAG_VAL) { + writel(0x0, CONFIG_LOWPOWER_FLAG); + set_pc(0x0); + } + + reg_val = readl(CONFIG_PHY_IRAM_BASE + 0x4); + if (reg_val != (uint32_t)low_power_start) { + /* Store jump address as low_power_start if not present */ + writel((uint32_t)low_power_start, CONFIG_PHY_IRAM_BASE + 0x4); + dsb(); + sev(); + } + + /* Set the CPU to SVC32 mode */ + svc32_mode_en(); + v7_enable_l2_hazard_detect(); + + /* Invalidate L1 TLB */ + val = 0x0; + mcr_tlb(val); + mcr_icache(val); + + /* Disable MMU stuff and caches */ + mrc_sctlr(val); + + val = ~((0x2 12) | 0x7); + val |= ((0x1 12) | (0x8 8) | 0x2); + mcr_sctlr(val); + + /* CPU state is hotplug or reset */ + secondary_cpu_start(); + + /* Core should not enter into WFI here */ + wfi(); +} + +/* * Pointer to this function is stored in iRam which is used * for jump and power down of a specific core. */ @@ -81,29 +137,25 @@ static void power_down_core(void) */ static void secondary_cores_configure(void) { - uint32_t core_id; + /* Setup L2 cache */ + v7_enable_l2_hazard_detect(); - /* Store jump address for power down of secondary cores */ + /* Clear secondary boot iRAM base */ + writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); + + /* set lowpower flag and address */ + writel(CPU_RST_FLAG_VAL, CONFIG_LOWPOWER_FLAG); + writel((uint32_t)low_power_start, CONFIG_LOWPOWER_ADDR); + writel(CPU_RST_FLAG_VAL, EXYNOS5420_SPARE_BASE); + /* Store jump address for power down */ writel((uint32_t)power_down_core, CONFIG_PHY_IRAM_BASE + 0x4); /* Need all core power down check */ dsb(); sev(); - - /* -* Power down all cores(secondary) while primary core must -* wait for all cores to go down. -*/ - for (core_id = 1; core_id != CONFIG_CORE_COUNT; core_id++) { - while ((readl
[U-Boot] [PATCH v4 06/10] Exynos542x: cache: Disable clean/evict push to external
L2 Auxiliary Control Register provides configuration and control options for the L2 memory system. Bit 3 of L2ACTLR stands for clean/evict push to external. Setting bit 3 disables clean/evict which is what this patch intends to do. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - No change. Changes since v2: - Replaced #ifdef with if(proid_id_soc()) check. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/soc.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index 8c7d7d8..427f54c 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -13,7 +13,9 @@ enum l2_cache_params { CACHE_TAG_RAM_SETUP = (1 9), CACHE_DATA_RAM_SETUP = (1 5), CACHE_TAG_RAM_LATENCY = (2 6), - CACHE_DATA_RAM_LATENCY = (2 0) + CACHE_DATA_RAM_LATENCY = (2 0), + CACHE_ENABLE_CLEAN_EVICT = (0 3), + CACHE_DISABLE_CLEAN_EVICT = (1 3) }; void reset_cpu(ulong addr) @@ -37,14 +39,28 @@ static void exynos5_set_l2cache_params(void) { unsigned int val = 0; + /* Read L2CTLR value */ asm volatile(mrc p15, 1, %0, c9, c0, 2\n : =r(val)); + /* Set cache setup and latency cycles */ val |= CACHE_TAG_RAM_SETUP | CACHE_DATA_RAM_SETUP | CACHE_TAG_RAM_LATENCY | CACHE_DATA_RAM_LATENCY; + /* Write new vlaue to L2CTLR */ asm volatile(mcr p15, 1, %0, c9, c0, 2\n : : r(val)); + + if (proid_is_exynos5420() || proid_is_exynos5800()) { + /* Read L2ACTLR value */ + asm volatile(mrc p15, 1, %0, c15, c0, 0 : =r (val)); + + /* Disable clean/evict push to external */ + val |= CACHE_DISABLE_CLEAN_EVICT; + + /* Write new vlaue to L2ACTLR */ + asm volatile(mcr p15, 1, %0, c15, c0, 0 : : r (val)); + } } /* -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 03/10] Exynos542x: Add workaround for ARM errata 798870
This patch adds workaround for ARM errata 798870 which says If back-to-back speculative cache line fills (fill A and fill B) are issued from the L1 data cache of a CPU to the L2 cache, the second request (fill B) is then cancelled, and the second request would have detected a hazard against a recent write or eviction (write B) to the same cache line as fill B then the L2 logic might deadlock. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - Added errata number in comment. - Moved changes to arm generic armv7.h Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. - Added space before */ on line # 40. arch/arm/include/asm/armv7.h | 16 1 file changed, 16 insertions(+) diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h index a13da23..a2040b7 100644 --- a/arch/arm/include/asm/armv7.h +++ b/arch/arm/include/asm/armv7.h @@ -69,6 +69,22 @@ #define CP15DSBasm volatile (mcr p15, 0, %0, c7, c10, 4 : : r (0)) #define CP15DMBasm volatile (mcr p15, 0, %0, c7, c10, 5 : : r (0)) +/* + * Workaround for ARM errata # 798870 + * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been + * stalled for 1024 cycles to verify that its hazard condition still exists. + */ +static inline void v7_enable_l2_hazard_detect(void) +{ + uint32_t val; + + /* L2ACTLR[7]: Enable hazard detect timeout */ + asm volatile (mrc p15, 1, %0, c15, c0, 0\n\t : =r(val)); + val |= (1 7); + asm volatile (mcr p15, 1, %0, c15, c0, 0\n\t : : r(val)); +} + +void v7_en_l2_hazard_detect(void); void v7_outer_cache_enable(void); void v7_outer_cache_disable(void); void v7_outer_cache_flush_all(void); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 04/10] Exynos542x: Add workaround for ARM errata 799270
This patch adds workaround for the ARM errata 799270 which says If the L2 cache logic clock is stopped because of L2 inactivity, setting or clearing the ACTLR.SMP bit might not be effective. The bit is modified in the ACTLR, meaning a read of the register returns the updated value. However the logic that uses that bit retains the previous value. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - Added errata number in comment. - Moved changes to arm generic armv7.h Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/include/asm/armv7.h | 28 1 file changed, 28 insertions(+) diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h index a2040b7..dc9561c 100644 --- a/arch/arm/include/asm/armv7.h +++ b/arch/arm/include/asm/armv7.h @@ -84,6 +84,34 @@ static inline void v7_enable_l2_hazard_detect(void) asm volatile (mcr p15, 1, %0, c15, c0, 0\n\t : : r(val)); } +/* + * Workaround for ARM errata # 799270 + * Ensure that the L2 logic has been used within the previous 256 cycles + * before modifying the ACTLR.SMP bit. This is required during boot before + * MMU has been enabled, or during a specified reset or power down sequence. + */ +static inline void v7_enable_smp(uint32_t address) +{ + uint32_t temp, val; + + /* Read auxiliary control register */ + asm volatile (mrc p15, 0, %0, c1, c0, 1\n\t : =r(val)); + + /* Enable SMP */ + val |= (1 6); + + /* Dummy read to assure L2 access */ + temp = readl(address); + temp = 0; + val |= temp; + + /* Write auxiliary control register */ + asm volatile (mcr p15, 0, %0, c1, c0, 1\n\t : : r(val)); + + CP15DSB; + CP15ISB; +} + void v7_en_l2_hazard_detect(void); void v7_outer_cache_enable(void); void v7_outer_cache_disable(void); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 07/10] Exynos542x: add L2 control register configuration
This patch does 3 things: 1. Enables ECC by setting 21st bit of L2CTLR. 2. Restore data and tag RAM latencies to 3 cycles because iROM sets 0x3000400 L2CTLR value during switching. 3. Disable clean/evict push to external by setting 3rd bit of L2ACTLR. We need to restore this here due to switching. Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - Rebased. Changes since v2: - Replaced #ifndef with if(proid_is_soc()) check. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 51 ++- arch/arm/cpu/armv7/exynos/soc.c | 26 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index b94e49f..0504576 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -47,6 +47,42 @@ enum { #ifdef CONFIG_EXYNOS5420 /* + * Enable ECC by setting L2CTLR[21]. + * Set L2CTLR[7] to make tag ram latency 3 cycles and + * set L2CTLR[1] to make data ram latency 3 cycles. + * We need to make RAM latency of 3 cycles here because cores + * power ON and OFF while switching. And everytime a core powers + * ON, iROM provides it a default L2CTLR value 0x400 which stands + * for TAG RAM setup of 1 cycle. Hence, we face a need of + * restoring data and tag latency values. + */ +static void configure_l2_ctlr(void) +{ + uint32_t val; + + mrc_l2_ctlr(val); + val |= (1 21); + val |= (1 7); + val |= (1 1); + mcr_l2_ctlr(val); +} + +/* + * Set L2ACTLR[27] to prevent the clock generator from stopping + * the L2 logic clock. + * Set L2ACTLR[3] to disable clean/evict push to external. + */ +static void configure_l2_actlr(void) +{ + uint32_t val; + + mrc_l2_aux_ctlr(val); + val |= (1 27); + val |= (1 3); + mcr_l2_aux_ctlr(val); +} + +/* * Power up secondary CPUs. */ static void secondary_cpu_start(void) @@ -80,7 +116,19 @@ static void low_power_start(void) /* Set the CPU to SVC32 mode */ svc32_mode_en(); - v7_enable_l2_hazard_detect(); + +#ifndef CONFIG_SYS_L2CACHE_OFF + /* Read MIDR for Primary Part Number */ + mrc_midr(val); + val = (val 4); + val = 0xf; + + if (val == 0xf) { + configure_l2_ctlr(); + configure_l2_actlr(); + v7_enable_l2_hazard_detect(); + } +#endif /* Invalidate L1 TLB */ val = 0x0; @@ -138,6 +186,7 @@ static void power_down_core(void) static void secondary_cores_configure(void) { /* Setup L2 cache */ + configure_l2_ctlr(); v7_enable_l2_hazard_detect(); /* Clear secondary boot iRAM base */ diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index 427f54c..68eb8e7 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -37,30 +37,32 @@ void enable_caches(void) */ static void exynos5_set_l2cache_params(void) { - unsigned int val = 0; + unsigned int l2ctlr = 0, l2actlr = 0; /* Read L2CTLR value */ - asm volatile(mrc p15, 1, %0, c9, c0, 2\n : =r(val)); + asm volatile(mrc p15, 1, %0, c9, c0, 2\n : =r(l2ctlr)); - /* Set cache setup and latency cycles */ - val |= CACHE_TAG_RAM_SETUP | - CACHE_DATA_RAM_SETUP | - CACHE_TAG_RAM_LATENCY | + /* Set cache latency cycles */ + l2ctlr |= CACHE_TAG_RAM_LATENCY | CACHE_DATA_RAM_LATENCY; - /* Write new vlaue to L2CTLR */ - asm volatile(mcr p15, 1, %0, c9, c0, 2\n : : r(val)); - if (proid_is_exynos5420() || proid_is_exynos5800()) { /* Read L2ACTLR value */ - asm volatile(mrc p15, 1, %0, c15, c0, 0 : =r (val)); + asm volatile(mrc p15, 1, %0, c15, c0, 0 : =r (l2actlr)); /* Disable clean/evict push to external */ - val |= CACHE_DISABLE_CLEAN_EVICT; + l2actlr |= CACHE_DISABLE_CLEAN_EVICT; /* Write new vlaue to L2ACTLR */ - asm volatile(mcr p15, 1, %0, c15, c0, 0 : : r (val)); + asm volatile(mcr p15, 1, %0, c15, c0, 0 : : r (l2actlr)); + } else { + /* Set cache setup cycles */ + l2ctlr |= CACHE_TAG_RAM_SETUP | + CACHE_DATA_RAM_SETUP; } + + /* Write new vlaue to L2CTLR */ + asm volatile(mcr p15, 1, %0, c9, c0, 2\n : : r(l2ctlr)); } /* -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 01/11] Exynos542x: Config: Add various configs
This patch adds iRAM, CPU state and low power configs which are the addresses acting as flag registers. iROM code checks CONFIG_LOWPOWER_FLAG address. If it is equal to CONFIG_LOWPOWER_EN then it jumps to the address (0x0202+CPUID*4). This is a part of iROM logic. Rest other flags are being used at various places during kernel switching and reset. They are nowhere documented because they are part programming. These configs are serving as flags for us because they are representing the addresses in iRAM which we are using for storing and extracting CPU Status and GIC status. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. - Removed unnecessary CONFIGS. include/configs/exynos5420-common.h | 16 1 file changed, 16 insertions(+) diff --git a/include/configs/exynos5420-common.h b/include/configs/exynos5420-common.h index fe72bd0..b42dab7 100644 --- a/include/configs/exynos5420-common.h +++ b/include/configs/exynos5420-common.h @@ -38,4 +38,20 @@ #define CONFIG_BOARD_REV_GPIO_COUNT2 +#define CONFIG_PHY_IRAM_BASE 0x0202 + +/* Address for relocating helper code (Last 4 KB of IRAM) */ +#define CONFIG_EXYNOS_RELOCATE_CODE_BASE (CONFIG_IRAM_TOP - 0x1000) + +/* + * Low Power settings + */ +#define CONFIG_LOWPOWER_FLAG 0x02020028 +#define CONFIG_LOWPOWER_ADDR 0x0202002C + +/* + * Number of CPUs available + */ +#define CONFIG_CORE_COUNT 0x8 + #endif /* __CONFIG_EXYNOS5420_H */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 02/11] Exynos542x: CPU: Power down all secondary cores
This patch adds code to shutdown secondary cores. When U-boot comes up, all secondary cores appear powered on, which is undesirable and causes side effects while initializing these cores in kernel. Secondary core power down happens in following steps: Step-1: After Exynos power-on, primary core starts executing first. Step-2: In iROM code every core has to check 2 flags i.e. addresses 0x02020028 0x02020004. Step-3: Initially 0x02020028 is 0 for all cores and 0x02020004 has a jump address for primary core and 0 for all secondary cores. Step-4: Therefore, primary core follows normal iROM execution and jumps to BL1 eventually, whereas all secondary cores enter WFE. Step-5: When primary core comes into function secondary_cores_configure, it puts pointer to function power_down_core into 0x02020004 and provides DSB and SEV for all cores so that they may come out of WFE and jump to power_down_core function. Step-6: And ultimately because of power_down_core all secondary cores shut-down. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - No change. Changes since v1: - Removed unnecessary macros. - Changed names of few macros for better understanding. - Added MPIDR bit assignment info comment in power_down_core. arch/arm/cpu/armv7/exynos/exynos5_setup.h | 3 ++ arch/arm/cpu/armv7/exynos/lowlevel_init.c | 69 arch/arm/include/asm/arch-exynos/cpu.h| 5 ++ arch/arm/include/asm/arch-exynos/system.h | 87 +++ 4 files changed, 164 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index 2eea48a..9073f50 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -700,6 +700,9 @@ #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE #else + +#define CPU_CONFIG_STATUS_OFFSET 0x80 +#define CPU_RST_FLAG_VAL 0xFCBA0D10 #define PAD_RETENTION_DRAM_COREBLK_VAL 0x1000 /* APLL_CON1 */ diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 83e1dcf..e36f2fa 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -31,7 +31,9 @@ #include asm/arch/tzpc.h #include asm/arch/periph.h #include asm/arch/pinmux.h +#include asm/arch/system.h #include common_setup.h +#include exynos5_setup.h /* These are the things we can do during low-level init */ enum { @@ -42,6 +44,68 @@ enum { DO_POWER= 1 4, }; +#ifdef CONFIG_EXYNOS5420 +/* + * Pointer to this function is stored in iRam which is used + * for jump and power down of a specific core. + */ +static void power_down_core(void) +{ + uint32_t tmp, core_id, core_config; + + /* Get the unique core id */ + /* +* Multiprocessor Affinity Register +* [11:8] Cluster ID +* [1:0]CPU ID +*/ + mrc_mpafr(core_id); + tmp = core_id 0x3; + core_id = (core_id 6) ~3; + core_id |= tmp; + core_id = 0x3f; + + /* Set the status of the core to low */ + core_config = (core_id * CPU_CONFIG_STATUS_OFFSET); + core_config += EXYNOS5420_CPU_CONFIG_BASE; + writel(0x0, core_config); + + /* Core enter WFI */ + wfi(); +} + +/* + * Configurations for secondary cores are inapt at this stage. + * Reconfigure secondary cores. Shutdown and change the status + * of all cores except the primary core. + */ +static void secondary_cores_configure(void) +{ + uint32_t core_id; + + /* Store jump address for power down of secondary cores */ + writel((uint32_t)power_down_core, CONFIG_PHY_IRAM_BASE + 0x4); + + /* Need all core power down check */ + dsb(); + sev(); + + /* +* Power down all cores(secondary) while primary core must +* wait for all cores to go down. +*/ + for (core_id = 1; core_id != CONFIG_CORE_COUNT; core_id++) { + while ((readl(EXYNOS5420_CPU_STATUS_BASE + + (core_id * CPU_CONFIG_STATUS_OFFSET)) +0xff) != 0x0) { + isb(); + sev(); + } + isb(); + } +} +#endif + int do_lowlevel_init(void) { uint32_t reset_status; @@ -49,6 +113,11 @@ int do_lowlevel_init(void) arch_cpu_init(); +#ifdef CONFIG_EXYNOS5420 + /* Reconfigure secondary cores */ + secondary_cores_configure(); +#endif + reset_status = get_reset_status(); switch (reset_status) { diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index 29674ad..e739520 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -153,6 +153,10
[U-Boot] [PATCH v3 00/11] Add support for booting multiple cores
This patch series introduces changes for booting secondary CPUs on Exynos5420 and Exynos5800. Changes since v2: - Patch 7 8 : Replaced #ifdef and #ifndef - if(proid_is_soc()). - Patch 11 : Removed #ifdef from enum definition. Changes since v1: - Added Reviewed-by Tested-by in the acked patches. - Removed unnecessary CONFIGS and macros. - Changed names of few macros for better understanding in patch 2. - Added MPIDR bit assignment info comment in power_down_core in patch 2. - Changed to SPDX header in sec_boot.S in patch 5. - Fixed compilation error for snow build in patch 11. Akshay Saraswat (10): Exynos542x: Config: Add various configs Exynos542x: CPU: Power down all secondary cores Exynos542x: Add workaround for ARM errata 798870 Exynos542x: Add workaround for ARM errata 799270 Exynos542x: Add workaround for exynos iROM errata Exynos542x: Change ambiguous function name set_l2cache Exynos542x: cache: Disable clean/evict push to external Exynos542x: add L2 control register configuration Exynos542x: Fix secondary core booting for thumb Exynos542x: Make A7s boot with thumb-mode U-Boot on warm reset Doug Anderson (1): Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800 arch/arm/cpu/armv7/exynos/Makefile| 2 + arch/arm/cpu/armv7/exynos/common_setup.h | 63 arch/arm/cpu/armv7/exynos/exynos5_setup.h | 3 + arch/arm/cpu/armv7/exynos/lowlevel_init.c | 166 ++ arch/arm/cpu/armv7/exynos/sec_boot.S | 128 +++ arch/arm/cpu/armv7/exynos/soc.c | 35 --- arch/arm/include/asm/arch-exynos/cpu.h| 5 + arch/arm/include/asm/arch-exynos/system.h | 88 include/configs/exynos5420-common.h | 16 +++ 9 files changed, 471 insertions(+), 35 deletions(-) create mode 100644 arch/arm/cpu/armv7/exynos/sec_boot.S -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 04/11] Exynos542x: Add workaround for ARM errata 799270
This patch adds workaround for the ARM errata 799270 which says If the L2 cache logic clock is stopped because of L2 inactivity, setting or clearing the ACTLR.SMP bit might not be effective. The bit is modified in the ACTLR, meaning a read of the register returns the updated value. However the logic that uses that bit retains the previous value. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 7335a1e..bbcae4c 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -46,6 +46,28 @@ enum { #ifdef CONFIG_EXYNOS5420 /* + * Ensure that the L2 logic has been used within the previous 256 cycles + * before modifying the ACTLR.SMP bit. This is required during boot before + * MMU has been enabled, or during a specified reset or power down sequence. + */ +void enable_smp(void) +{ + uint32_t temp, val; + + /* Enable SMP mode */ + mrc_auxr(temp); + temp |= (1 6); + + /* Dummy read to assure L2 access */ + val = readl(EXYNOS5420_INFORM_BASE); + val = 0; + temp |= val; + mcr_auxr(temp); + dsb(); + isb(); +} + +/* * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 05/11] Exynos542x: Add workaround for exynos iROM errata
iROM logic provides undesired jump address for CPU2. This patch adds a programmable susbstitute for a part of iROM logic which wakes up cores and provides jump addresses. This patch creates a logic to make all secondary cores jump to a particular address which evades the possibility of CPU2 jumping to wrong address and create undesired results. Logic of the workaround: Step-1: iROM code checks value at address 0x2020028. Step-2: If value is 0xc9cfcfcf, it jumps to the address (0x202000+CPUid*4), else, it continues executing normally. Step-3: Primary core puts secondary cores in WFE and store 0xc9cfcfcf in 0x2020028 and jump address (pointer to function low_power_start) in (0x202000+CPUid*4). Step-4: When secondary cores recieve event signal they jump to this address and continue execution. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. - Changed to SPDX header in sec_boot.S. arch/arm/cpu/armv7/exynos/Makefile| 2 + arch/arm/cpu/armv7/exynos/lowlevel_init.c | 90 - arch/arm/cpu/armv7/exynos/sec_boot.S | 128 ++ 3 files changed, 202 insertions(+), 18 deletions(-) create mode 100644 arch/arm/cpu/armv7/exynos/sec_boot.S diff --git a/arch/arm/cpu/armv7/exynos/Makefile b/arch/arm/cpu/armv7/exynos/Makefile index e207bd6..8542f89 100644 --- a/arch/arm/cpu/armv7/exynos/Makefile +++ b/arch/arm/cpu/armv7/exynos/Makefile @@ -7,6 +7,8 @@ obj-y += clock.o power.o soc.o system.o pinmux.o tzpc.o +obj-$(CONFIG_EXYNOS5420) += sec_boot.o + ifdef CONFIG_SPL_BUILD obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index bbcae4c..9714af8 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -50,7 +50,7 @@ enum { * before modifying the ACTLR.SMP bit. This is required during boot before * MMU has been enabled, or during a specified reset or power down sequence. */ -void enable_smp(void) +static void enable_smp(void) { uint32_t temp, val; @@ -71,7 +71,7 @@ void enable_smp(void) * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. */ -void set_l2cache(void) +static void set_l2cache(void) { uint32_t val; @@ -90,6 +90,62 @@ void set_l2cache(void) } /* + * Power up secondary CPUs. + */ +static void secondary_cpu_start(void) +{ + enable_smp(); + svc32_mode_en(); + set_pc(CONFIG_EXYNOS_RELOCATE_CODE_BASE); +} + +/* + * This is the entry point of hotplug-in and + * cluster switching. + */ +static void low_power_start(void) +{ + uint32_t val, reg_val; + + reg_val = readl(EXYNOS5420_SPARE_BASE); + if (reg_val != CPU_RST_FLAG_VAL) { + writel(0x0, CONFIG_LOWPOWER_FLAG); + set_pc(0x0); + } + + reg_val = readl(CONFIG_PHY_IRAM_BASE + 0x4); + if (reg_val != (uint32_t)low_power_start) { + /* Store jump address as low_power_start if not present */ + writel((uint32_t)low_power_start, CONFIG_PHY_IRAM_BASE + 0x4); + dsb(); + sev(); + } + + /* Set the CPU to SVC32 mode */ + svc32_mode_en(); + set_l2cache(); + + /* Invalidate L1 TLB */ + val = 0x0; + mcr_tlb(val); + mcr_icache(val); + + /* Disable MMU stuff and caches */ + mrc_sctlr(val); + + val = ~((0x2 12) | 0x7); + val |= ((0x1 12) | (0x8 8) | 0x2); + mcr_sctlr(val); + + /* CPU state is hotplug or reset */ + secondary_cpu_start(); + + /* Core should not enter into WFI here */ + wfi(); + +} + +/* * Pointer to this function is stored in iRam which is used * for jump and power down of a specific core. */ @@ -125,29 +181,25 @@ static void power_down_core(void) */ static void secondary_cores_configure(void) { - uint32_t core_id; + /* Setup L2 cache */ + set_l2cache(); - /* Store jump address for power down of secondary cores */ + /* Clear secondary boot iRAM base */ + writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); + + /* set lowpower flag and address */ + writel(CPU_RST_FLAG_VAL, CONFIG_LOWPOWER_FLAG); + writel((uint32_t)low_power_start, CONFIG_LOWPOWER_ADDR); + writel(CPU_RST_FLAG_VAL, EXYNOS5420_SPARE_BASE); + /* Store jump address for power down */ writel((uint32_t)power_down_core, CONFIG_PHY_IRAM_BASE + 0x4); /* Need all core power down check */ dsb
[U-Boot] [PATCH v3 03/11] Exynos542x: Add workaround for ARM errata 798870
This patch adds workaround for ARM errata 798870 which says If back-to-back speculative cache line fills (fill A and fill B) are issued from the L1 data cache of a CPU to the L2 cache, the second request (fill B) is then cancelled, and the second request would have detected a hazard against a recent write or eviction (write B) to the same cache line as fill B then the L2 logic might deadlock. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. - Added space before */ on line # 40. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index e36f2fa..7335a1e 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -46,6 +46,28 @@ enum { #ifdef CONFIG_EXYNOS5420 /* + * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been + * stalled for 1024 cycles to verify that its hazard condition still exists. + */ +void set_l2cache(void) +{ + uint32_t val; + + /* Read MIDR for Primary Part Number */ + mrc_midr(val); + val = (val 4); + val = 0xf; + + /* L2ACTLR[7]: Enable hazard detect timeout for A15 */ + if (val == 0xf) { + mrc_l2_aux_ctlr(val); + val |= (1 7); + mcr_l2_aux_ctlr(val); + mrc_l2_ctlr(val); + } +} + +/* * Pointer to this function is stored in iRam which is used * for jump and power down of a specific core. */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 09/11] Exynos542x: Fix secondary core booting for thumb
When compiled SPL for Thumb secondary cores failed to boot at the kernel boot up. Only one core came up out of 4. This was happening because the code relocated to the address 0x02073000 by the primary core was an ARM asm code which was executed by the secondary cores as if it was a thumb code. This patch fixes the issue of secondary cores considering relocated code as Thumb instructions and not ARM instructions by jumping to the relocated with the help of bx ARM instruction. bx instruction changes the 5th bit of CPSR which allows execution unit to consider the following instructions as ARM instructions. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 +- arch/arm/include/asm/arch-exynos/system.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index aba6462..fc7e6f5 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -111,7 +111,7 @@ static void secondary_cpu_start(void) { enable_smp(); svc32_mode_en(); - set_pc(CONFIG_EXYNOS_RELOCATE_CODE_BASE); + branch_bx(CONFIG_EXYNOS_RELOCATE_CODE_BASE); } /* diff --git a/arch/arm/include/asm/arch-exynos/system.h b/arch/arm/include/asm/arch-exynos/system.h index 86903c3..a9fd5e6 100644 --- a/arch/arm/include/asm/arch-exynos/system.h +++ b/arch/arm/include/asm/arch-exynos/system.h @@ -75,6 +75,9 @@ struct exynos5_sysreg { /* Set program counter with the given value */ #define set_pc(x) __asm__ __volatile__ (mov pc, %0\n\t : : r(x)) +/* Branch to the given location */ +#define branch_bx(x) __asm__ __volatile__ (bx %0\n\t : : r(x)) + /* Read Main Id register */ #define mrc_midr(x) __asm__ __volatile__ \ (mrc p15, 0, %0, c0, c0, 0\n\t : =r(x) : ) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 07/11] Exynos542x: cache: Disable clean/evict push to external
L2 Auxiliary Control Register provides configuration and control options for the L2 memory system. Bit 3 of L2ACTLR stands for clean/evict push to external. Setting bit 3 disables clean/evict which is what this patch intends to do. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - Replaced #ifdef with if(proid_id_soc()) check. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/soc.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index 8c7d7d8..427f54c 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -13,7 +13,9 @@ enum l2_cache_params { CACHE_TAG_RAM_SETUP = (1 9), CACHE_DATA_RAM_SETUP = (1 5), CACHE_TAG_RAM_LATENCY = (2 6), - CACHE_DATA_RAM_LATENCY = (2 0) + CACHE_DATA_RAM_LATENCY = (2 0), + CACHE_ENABLE_CLEAN_EVICT = (0 3), + CACHE_DISABLE_CLEAN_EVICT = (1 3) }; void reset_cpu(ulong addr) @@ -37,14 +39,28 @@ static void exynos5_set_l2cache_params(void) { unsigned int val = 0; + /* Read L2CTLR value */ asm volatile(mrc p15, 1, %0, c9, c0, 2\n : =r(val)); + /* Set cache setup and latency cycles */ val |= CACHE_TAG_RAM_SETUP | CACHE_DATA_RAM_SETUP | CACHE_TAG_RAM_LATENCY | CACHE_DATA_RAM_LATENCY; + /* Write new vlaue to L2CTLR */ asm volatile(mcr p15, 1, %0, c9, c0, 2\n : : r(val)); + + if (proid_is_exynos5420() || proid_is_exynos5800()) { + /* Read L2ACTLR value */ + asm volatile(mrc p15, 1, %0, c15, c0, 0 : =r (val)); + + /* Disable clean/evict push to external */ + val |= CACHE_DISABLE_CLEAN_EVICT; + + /* Write new vlaue to L2ACTLR */ + asm volatile(mcr p15, 1, %0, c15, c0, 0 : : r (val)); + } } /* -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 11/11] Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800
From: Doug Anderson diand...@chromium.org It was found that the L2 cache timings that we had before could cause freezes and hangs. We should make things more robust with better timings. Currently the production ChromeOS kernel applies these timings, but it's nice to fixup firmware too (and upstream probably won't take our kernel hacks). This also provides a big cleanup of the L2 cache init code avoiding some duplication. The way things used to work: * low_power_start() was installed by the SPL (both at boot and resume time) and left resident in iRAM for the kernel to use when bringing up additional CPUs. It used configure_l2_ctlr() and configure_l2_actlr() when it detected it was on an A15. This was needed (despite the L2 cache registers being shared among all A15s) because we might have been the first man in after the whole A15 cluster was shutdown. * secondary_cores_configure() was called on at boot time and at resume time. Strangely this called configure_l2_ctlr() but not configure_l2_actlr() which was almost certainly wrong. Given that we'll call both (see next bullet) later in the boot process it didn't matter for normal boot, but I guess this is how L2 cache settings got set on 5420/5800 (but not 5250?) at resume time. * exynos5_set_l2cache_params() was called as part of cache enablement. This should happen at boot time (normally in the SPL except for USB boot where it happens in main U-Boot). Note that the old code wasn't setting ECC/parity in the cache enablement code but we happened to get it anyway because we'd call secondary_cores_configure() at boot time. For resume time we'd get it anyway when the 2nd A15 core came up. Let's make this a whole lot simpler. Now we always set these parameters in the same place for all boots and use the same code for setting up secondary CPUs. Intended net effects of this change (other than cleanup): * Timings go from before: data: 0 cycle setup, 3 cycles (0x2) latency tag: 0 cycle setup, 3 cycles (0x2) latency after: data: 1 cycle setup, 4 cycles (0x3) latency tag: 1 cycle setup, 4 cycles (0x3) latency * L2ACTLR is properly initted on 5420/5800 in all cases. One note is that we're still relying on luck to keep low_power_start() working. The compiler is being nice and not storing anything on the stack. Another note is that on its own this patch won't help to fix cache settings in an RW U-Boot update where we still have the RO SPL. The plan for that is: * Have RW U-Boot re-init the cache right before calling the kernel (after it has turned the L2 cache off). This is why the functions are in a header file instead of lowlevel_init.c. * Have the kernel save the L2 cache settings of the boot CPU and apply them to all other CPUs. We get a little lucky here because the old code was using |= to modify the registers and all of the bits that it's setting are also present in the new settings (!). That means that when the 2nd CPU in the A15 cluster comes up it doesn't actually mess up the settings of the 1st CPU in the A15 cluster. An alternative option is to have the kernel write its own low_power_start() code. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - Removed #ifdef from enum definition. Changes since v1: - Fixed compilation error for snow build. arch/arm/cpu/armv7/exynos/common_setup.h | 63 +++ arch/arm/cpu/armv7/exynos/lowlevel_init.c | 55 --- arch/arm/cpu/armv7/exynos/soc.c | 54 -- arch/arm/include/asm/arch-exynos/system.h | 2 - 4 files changed, 78 insertions(+), 96 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/common_setup.h b/arch/arm/cpu/armv7/exynos/common_setup.h index e6318c0..b9fe60b 100644 --- a/arch/arm/cpu/armv7/exynos/common_setup.h +++ b/arch/arm/cpu/armv7/exynos/common_setup.h @@ -23,6 +23,8 @@ * MA 02111-1307 USA */ +#include asm/arch/system.h + #define DMC_OFFSET 0x1 /* @@ -43,3 +45,64 @@ void system_clock_init(void); int do_lowlevel_init(void); void sdelay(unsigned long); + +enum l2_cache_params { + CACHE_DATA_RAM_LATENCY_2_CYCLES = (2 0), + CACHE_DATA_RAM_LATENCY_3_CYCLES = (3 0), + CACHE_DISABLE_CLEAN_EVICT = (1 3), + CACHE_DATA_RAM_SETUP = (1 5), + CACHE_TAG_RAM_LATENCY_2_CYCLES = (2 6), + CACHE_TAG_RAM_LATENCY_3_CYCLES = (3 6), + CACHE_ENABLE_HAZARD_DETECT = (1 7), + CACHE_TAG_RAM_SETUP = (1 9), + CACHE_ECC_AND_PARITY = (1 21), + CACHE_ENABLE_FORCE_L2_LOGIC = (1 27) +}; + + +#ifndef CONFIG_SYS_L2CACHE_OFF +/* + * Configure L2CTLR to get timings that keep us from hanging/crashing. + * + * Must be inline here since low_power_start() is called without a + * stack (!). + */ +static inline void configure_l2_ctlr(void) +{ + uint32_t val; + + mrc_l2_ctlr(val
[U-Boot] [PATCH v3 06/11] Exynos542x: Change ambiguous function name set_l2cache
1. Renaming set_l2cache to configure_l2actlr in order to avoid misleading comprehensions. Apparently this name suggests that L2 cache is being set or initialized which is incorrect as per the code in this function. 2. Cleaning missed mrc for L2 control register. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 9714af8..0893b0b 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -71,7 +71,7 @@ static void enable_smp(void) * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. */ -static void set_l2cache(void) +static void configure_l2actlr(void) { uint32_t val; @@ -85,7 +85,6 @@ static void set_l2cache(void) mrc_l2_aux_ctlr(val); val |= (1 7); mcr_l2_aux_ctlr(val); - mrc_l2_ctlr(val); } } @@ -123,7 +122,7 @@ static void low_power_start(void) /* Set the CPU to SVC32 mode */ svc32_mode_en(); - set_l2cache(); + configure_l2actlr(); /* Invalidate L1 TLB */ val = 0x0; @@ -182,7 +181,7 @@ static void power_down_core(void) static void secondary_cores_configure(void) { /* Setup L2 cache */ - set_l2cache(); + configure_l2actlr(); /* Clear secondary boot iRAM base */ writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 08/11] Exynos542x: add L2 control register configuration
This patch does 3 things: 1. Enables ECC by setting 21st bit of L2CTLR. 2. Restore data and tag RAM latencies to 3 cycles because iROM sets 0x3000400 L2CTLR value during switching. 3. Disable clean/evict push to external by setting 3rd bit of L2ACTLR. We need to restore this here due to switching. Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - Replaced #ifndef with if(proid_is_soc()) check. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 53 +++ arch/arm/cpu/armv7/exynos/soc.c | 27 +--- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 0893b0b..aba6462 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -68,24 +68,40 @@ static void enable_smp(void) } /* + * Enable ECC by setting L2CTLR[21]. + * Set L2CTLR[7] to make tag ram latency 3 cycles and + * set L2CTLR[1] to make data ram latency 3 cycles. + * We need to make RAM latency of 3 cycles here because cores + * power ON and OFF while switching. And everytime a core powers + * ON, iROM provides it a default L2CTLR value 0x400 which stands + * for TAG RAM setup of 1 cycle. Hence, we face a need of + * restoring data and tag latency values. + */ +static void configure_l2_ctlr(void) +{ + uint32_t val; + + mrc_l2_ctlr(val); + val |= (1 21); + val |= (1 7); + val |= (1 1); + mcr_l2_ctlr(val); +} + +/* * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. + * Disable clean/evict push to external by setting L2ACTLR[3]. */ -static void configure_l2actlr(void) +static void configure_l2_actlr(void) { uint32_t val; - /* Read MIDR for Primary Part Number */ - mrc_midr(val); - val = (val 4); - val = 0xf; - - /* L2ACTLR[7]: Enable hazard detect timeout for A15 */ - if (val == 0xf) { - mrc_l2_aux_ctlr(val); - val |= (1 7); - mcr_l2_aux_ctlr(val); - } + mrc_l2_aux_ctlr(val); + val |= (1 27); + val |= (1 7); + val |= (1 3); + mcr_l2_aux_ctlr(val); } /* @@ -122,7 +138,16 @@ static void low_power_start(void) /* Set the CPU to SVC32 mode */ svc32_mode_en(); - configure_l2actlr(); + + /* Read MIDR for Primary Part Number */ + mrc_midr(val); + val = (val 4); + val = 0xf; + + if (val == 0xf) { + configure_l2_ctlr(); + configure_l2_actlr(); + } /* Invalidate L1 TLB */ val = 0x0; @@ -181,7 +206,7 @@ static void power_down_core(void) static void secondary_cores_configure(void) { /* Setup L2 cache */ - configure_l2actlr(); + configure_l2_ctlr(); /* Clear secondary boot iRAM base */ writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index 427f54c..77d3875 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -37,30 +37,33 @@ void enable_caches(void) */ static void exynos5_set_l2cache_params(void) { - unsigned int val = 0; + unsigned int l2ctlr = 0, l2actlr = 0; /* Read L2CTLR value */ - asm volatile(mrc p15, 1, %0, c9, c0, 2\n : =r(val)); + asm volatile(mrc p15, 1, %0, c9, c0, 2\n : =r(l2ctlr)); - /* Set cache setup and latency cycles */ - val |= CACHE_TAG_RAM_SETUP | - CACHE_DATA_RAM_SETUP | - CACHE_TAG_RAM_LATENCY | + /* Set cache latency cycles */ + l2ctlr |= CACHE_TAG_RAM_LATENCY | CACHE_DATA_RAM_LATENCY; - /* Write new vlaue to L2CTLR */ - asm volatile(mcr p15, 1, %0, c9, c0, 2\n : : r(val)); - if (proid_is_exynos5420() || proid_is_exynos5800()) { + /* Read L2ACTLR value */ - asm volatile(mrc p15, 1, %0, c15, c0, 0 : =r (val)); + asm volatile(mrc p15, 1, %0, c15, c0, 0 : =r (l2actlr)); /* Disable clean/evict push to external */ - val |= CACHE_DISABLE_CLEAN_EVICT; + l2actlr |= CACHE_DISABLE_CLEAN_EVICT; /* Write new vlaue to L2ACTLR */ - asm volatile(mcr p15, 1, %0, c15, c0, 0 : : r (val)); + asm volatile(mcr p15, 1, %0, c15, c0, 0 : : r (l2actlr)); + } else { + /* Set cache setup cycles */ + l2ctlr |= CACHE_TAG_RAM_SETUP | + CACHE_DATA_RAM_SETUP
[U-Boot] [PATCH v3 10/11] Exynos542x: Make A7s boot with thumb-mode U-Boot on warm reset
On warm reset, all cores jump to the low_power_start function because iRAM data is retained and because while executing iROM code all cores find the jump flag 0x02020028 set. In low_power_start, cores check the reset status and if true they clear the jump flag and jump back to 0x0. The A7 cores do jump to 0x0 but consider following instructions as a Thumb instructions which in turn makes them loop inside the iROM code instead of jumping to power_down_core. This issue is fixed by replacing the mov pc instruction with a bx instruction which switches state along with the jump to make the execution unit consider the branch target as an ARM instruction. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index fc7e6f5..36a008a 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -125,7 +125,7 @@ static void low_power_start(void) reg_val = readl(EXYNOS5420_SPARE_BASE); if (reg_val != CPU_RST_FLAG_VAL) { writel(0x0, CONFIG_LOWPOWER_FLAG); - set_pc(0x0); + branch_bx(0x0); } reg_val = readl(CONFIG_PHY_IRAM_BASE + 0x4); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH v3 02/11] Exynos542x: CPU: Power down all secondary cores
Hi Lukasz, Hi Akshay, This patch adds code to shutdown secondary cores. When U-boot comes up, all secondary cores appear powered on, which is undesirable and causes side effects while initializing these cores in kernel. Secondary core power down happens in following steps: Step-1: After Exynos power-on, primary core starts executing first. Step-2: In iROM code every core has to check 2 flags i.e. addresses 0x02020028 0x02020004. Could you provide exact names of those registers? I'm familiar with Samsung SoCs but I cannot recall which one those are. As I have written in Step-2, these are addresses (SRAM) and not registers. Our iROM code has a part where it reads 0x02020028 for a specific vlaue FCBA0D10. If CPU finds that value then it extracts jump address from 0x02020004, else it follows normal boot path. It would provide more readability to this commit message. Please fix it globally. Step-3: Initially 0x02020028 is 0 for all cores and 0x02020004 has a jump address for primary core and 0 for all secondary cores. Step-4: Therefore, primary core follows normal iROM execution and jumps to BL1 eventually, whereas all secondary cores enter WFE. Step-5: When primary core comes into function secondary_cores_configure, it puts pointer to function power_down_core into 0x02020004 and provides DSB and SEV for all cores so that they may come out of WFE and jump to power_down_core function. Step-6: And ultimately because of power_down_core all secondary cores shut-down. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - No change. Changes since v1: - Removed unnecessary macros. - Changed names of few macros for better understanding. - Added MPIDR bit assignment info comment in power_down_core. arch/arm/cpu/armv7/exynos/exynos5_setup.h | 3 ++ arch/arm/cpu/armv7/exynos/lowlevel_init.c | 69 arch/arm/include/asm/arch-exynos/cpu.h| 5 ++ arch/arm/include/asm/arch-exynos/system.h | 87 +++ 4 files changed, 164 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index 2eea48a..9073f50 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -700,6 +700,9 @@ #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE #else + +#define CPU_CONFIG_STATUS_OFFSET0x80 +#define CPU_RST_FLAG_VAL0xFCBA0D10 #define PAD_RETENTION_DRAM_COREBLK_VAL 0x1000 /* APLL_CON1 */ diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 83e1dcf..e36f2fa 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -31,7 +31,9 @@ #include asm/arch/tzpc.h #include asm/arch/periph.h #include asm/arch/pinmux.h +#include asm/arch/system.h #include common_setup.h +#include exynos5_setup.h /* These are the things we can do during low-level init */ enum { @@ -42,6 +44,68 @@ enum { DO_POWER= 1 4, }; +#ifdef CONFIG_EXYNOS5420 +/* + * Pointer to this function is stored in iRam which is used + * for jump and power down of a specific core. + */ +static void power_down_core(void) +{ +uint32_t tmp, core_id, core_config; + +/* Get the unique core id */ +/* + * Multiprocessor Affinity Register + * [11:8] Cluster ID + * [1:0]CPU ID + */ +mrc_mpafr(core_id); +tmp = core_id 0x3; +core_id = (core_id 6) ~3; +core_id |= tmp; +core_id = 0x3f; + +/* Set the status of the core to low */ +core_config = (core_id * CPU_CONFIG_STATUS_OFFSET); +core_config += EXYNOS5420_CPU_CONFIG_BASE; +writel(0x0, core_config); + +/* Core enter WFI */ +wfi(); +} + +/* + * Configurations for secondary cores are inapt at this stage. + * Reconfigure secondary cores. Shutdown and change the status + * of all cores except the primary core. + */ +static void secondary_cores_configure(void) +{ +uint32_t core_id; + +/* Store jump address for power down of secondary cores */ +writel((uint32_t)power_down_core, CONFIG_PHY_IRAM_BASE + 0x4); + +/* Need all core power down check */ +dsb(); +sev(); + +/* + * Power down all cores(secondary) while primary core must + * wait for all cores to go down. + */ +for (core_id = 1; core_id != CONFIG_CORE_COUNT; core_id++) { +while ((readl(EXYNOS5420_CPU_STATUS_BASE ++ (core_id * CPU_CONFIG_STATUS_OFFSET)) + 0xff) != 0x0) { +isb(); +sev(); +} +isb(); +} +} +#endif + int do_lowlevel_init(void) { uint32_t reset_status; @@ -49,6 +113,11 @@ int do_lowlevel_init(void
Re: [U-Boot] [PATCH v3 03/11] Exynos542x: Add workaround for ARM errata 798870
Hello, On Wed, 18 Feb 2015 15:16:27 +0530 Akshay Saraswat aksha...@samsung.com wrote: This patch adds workaround for ARM errata 798870 which says If back-to-back speculative cache line fills (fill A and fill B) are issued from the L1 data cache of a CPU to the L2 cache, the second request (fill B) is then cancelled, and the second request would have detected a hazard against a recent write or eviction (write B) to the same cache line as fill B then the L2 logic might deadlock. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v2: - No change. Changes since v1: - Added Reviewed-by Tested-by. - Added space before */ on line # 40. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index e36f2fa..7335a1e 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -46,6 +46,28 @@ enum { #ifdef CONFIG_EXYNOS5420 /* + * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been + * stalled for 1024 cycles to verify that its hazard condition still exists. + */ Having the ARM errata number mentioned in the comment here would make the purpose of this code much more clear to anyone looking at it later in the future. Also isn't this a general purpose Cortex-A15 r2pX workaround, also potentially useful for the other non-Exynos SoCs too? Yes, you are right. I'll mention errata number and will move it to armv7/cpu.c. +void set_l2cache(void) +{ +uint32_t val; + +/* Read MIDR for Primary Part Number */ +mrc_midr(val); +val = (val 4); +val = 0xf; + +/* L2ACTLR[7]: Enable hazard detect timeout for A15 */ +if (val == 0xf) { +mrc_l2_aux_ctlr(val); +val |= (1 7); +mcr_l2_aux_ctlr(val); +mrc_l2_ctlr(val); +} +} + +/* * Pointer to this function is stored in iRam which is used * for jump and power down of a specific core. */ -- Best regards, Siarhei Siamashka Regards, Akshay Saraswat ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH v5 7/7] Exynos: Clock: Cleanup soc_get_periph_rate
Hi, Hi Akshay, On 02/03/2015 05:27 PM, Akshay Saraswat wrote: Cleaning up soc_get_periph_rate to make the logic easy to comprehend. Could you give more detailed description? We did just a cleanup here by removing I2C sepecific calculations because we can now have a generic div and pre-div calculation. Only intention of doing it is making code clean and easily understandable. I don't know what else to write for that. Please suggest. :) Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v4: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 76 +-- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 3884d4b..8724bc7 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -366,8 +366,8 @@ static struct clk_bit_info *get_clk_bit_info(int peripheral) static unsigned long exynos5_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); -unsigned long sclk, sub_clk = 0; -unsigned int src, div, sub_div = 0; +unsigned long sclk = 0; +unsigned int src = 0, div = 0, sub_div = 0; struct exynos5_clock *clk = (struct exynos5_clock *)samsung_get_base_clock(); @@ -389,30 +389,30 @@ static unsigned long exynos5_get_periph_rate(int peripheral) break; case PERIPH_ID_I2S0: src = readl(clk-src_mau); -div = readl(clk-div_mau); +div = sub_div = readl(clk-div_mau); case PERIPH_ID_SPI0: case PERIPH_ID_SPI1: src = readl(clk-src_peric1); -div = readl(clk-div_peric1); +div = sub_div = readl(clk-div_peric1); break; case PERIPH_ID_SPI2: src = readl(clk-src_peric1); -div = readl(clk-div_peric2); +div = sub_div = readl(clk-div_peric2); break; case PERIPH_ID_SPI3: case PERIPH_ID_SPI4: src = readl(clk-sclk_src_isp); -div = readl(clk-sclk_div_isp); +div = sub_div = readl(clk-sclk_div_isp); break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: src = readl(clk-src_fsys); -div = readl(clk-div_fsys1); +div = sub_div = readl(clk-div_fsys1); break; case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: src = readl(clk-src_fsys); -div = readl(clk-div_fsys2); +div = sub_div = readl(clk-div_fsys2); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -422,12 +422,10 @@ static unsigned long exynos5_get_periph_rate(int peripheral) case PERIPH_ID_I2C5: case PERIPH_ID_I2C6: case PERIPH_ID_I2C7: -sclk = exynos5_get_pll_clk(MPLL); -sub_div = ((readl(clk-div_top1) bit_info-div_bit) - bit_info-div_mask) + 1; -div = ((readl(clk-div_top0) bit_info-prediv_bit) - bit_info-prediv_mask) + 1; -return (sclk / sub_div) / div; +src = EXYNOS_SRC_MPLL; +div = readl(clk-div_top0); +sub_div = readl(clk-div_top1); +break; default: debug(%s: invalid peripheral %d, __func__, peripheral); return -1; @@ -446,29 +444,26 @@ static unsigned long exynos5_get_periph_rate(int peripheral) case EXYNOS_SRC_VPLL: sclk = exynos5_get_pll_clk(VPLL); break; -default: -return 0; Why remove? I think it's better to use default label and also how about add debug log? Removing because anyways we are going to calculate return 0 for non-existent src or sclk. I have initialized src and sclk above with value zero. } -/* Ratio clock division for this peripheral */ -if (bit_info-div_bit = 0) { -sub_div = (div bit_info-div_bit) bit_info-div_mask; -sub_clk = sclk / (sub_div + 1); -} +/* Clock divider ratio for this peripheral */ +if (bit_info-div_bit = 0) +div = (div bit_info-div_bit) bit_info-div_mask; -if (bit_info-prediv_bit = 0) { -div = (div bit_info-prediv_bit) bit_info-prediv_mask; -return sub_clk / (div + 1); -} +/* Clock pre-divider ratio for this peripheral */ +if (bit_info-prediv_bit = 0) +sub_div = (sub_div bit_info-prediv_bit) + bit_info-prediv_mask; -return sub_clk; +/* Calculate and return required clock rate */ +return (sclk / (div + 1)) / (sub_div + 1); } static unsigned long exynos542x_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); -unsigned long sclk, sub_clk = 0; -unsigned int src
[U-Boot] [PATCH v6 7/7] Exynos: Clock: Cleanup soc_get_periph_rate
Since we have src, div and pre-div mask bits defined corresponding to peripherals, calculation of clock specific to I2C appears redundant and confusing. Using clk_bit_info struct we can write calculations generic to all peripherals which makes code easy to understand and free from peripheral specific exceptions. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v5: - Elaborated Commit message and fixed a nit. Changes since v4: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 74 ++- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 3884d4b..5777490 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -366,8 +366,8 @@ static struct clk_bit_info *get_clk_bit_info(int peripheral) static unsigned long exynos5_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); - unsigned long sclk, sub_clk = 0; - unsigned int src, div, sub_div = 0; + unsigned long sclk = 0; + unsigned int src = 0, div = 0, sub_div = 0; struct exynos5_clock *clk = (struct exynos5_clock *)samsung_get_base_clock(); @@ -389,30 +389,30 @@ static unsigned long exynos5_get_periph_rate(int peripheral) break; case PERIPH_ID_I2S0: src = readl(clk-src_mau); - div = readl(clk-div_mau); + div = sub_div = readl(clk-div_mau); case PERIPH_ID_SPI0: case PERIPH_ID_SPI1: src = readl(clk-src_peric1); - div = readl(clk-div_peric1); + div = sub_div = readl(clk-div_peric1); break; case PERIPH_ID_SPI2: src = readl(clk-src_peric1); - div = readl(clk-div_peric2); + div = sub_div = readl(clk-div_peric2); break; case PERIPH_ID_SPI3: case PERIPH_ID_SPI4: src = readl(clk-sclk_src_isp); - div = readl(clk-sclk_div_isp); + div = sub_div = readl(clk-sclk_div_isp); break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: src = readl(clk-src_fsys); - div = readl(clk-div_fsys1); + div = sub_div = readl(clk-div_fsys1); break; case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: src = readl(clk-src_fsys); - div = readl(clk-div_fsys2); + div = sub_div = readl(clk-div_fsys2); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -422,12 +422,10 @@ static unsigned long exynos5_get_periph_rate(int peripheral) case PERIPH_ID_I2C5: case PERIPH_ID_I2C6: case PERIPH_ID_I2C7: - sclk = exynos5_get_pll_clk(MPLL); - sub_div = ((readl(clk-div_top1) bit_info-div_bit) -bit_info-div_mask) + 1; - div = ((readl(clk-div_top0) bit_info-prediv_bit) -bit_info-prediv_mask) + 1; - return (sclk / sub_div) / div; + src = EXYNOS_SRC_MPLL; + div = readl(clk-div_top0); + sub_div = readl(clk-div_top1); + break; default: debug(%s: invalid peripheral %d, __func__, peripheral); return -1; @@ -447,28 +445,28 @@ static unsigned long exynos5_get_periph_rate(int peripheral) sclk = exynos5_get_pll_clk(VPLL); break; default: + debug(%s: EXYNOS_SRC %d not supported\n, __func__, src); return 0; } - /* Ratio clock division for this peripheral */ - if (bit_info-div_bit = 0) { - sub_div = (div bit_info-div_bit) bit_info-div_mask; - sub_clk = sclk / (sub_div + 1); - } + /* Clock divider ratio for this peripheral */ + if (bit_info-div_bit = 0) + div = (div bit_info-div_bit) bit_info-div_mask; - if (bit_info-prediv_bit = 0) { - div = (div bit_info-prediv_bit) bit_info-prediv_mask; - return sub_clk / (div + 1); - } + /* Clock pre-divider ratio for this peripheral */ + if (bit_info-prediv_bit = 0) + sub_div = (sub_div bit_info-prediv_bit) + bit_info-prediv_mask; - return sub_clk; + /* Calculate and return required clock rate */ + return (sclk / (div + 1)) / (sub_div + 1); } static unsigned long exynos542x_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); - unsigned long sclk, sub_clk = 0; - unsigned int src, div, sub_div = 0; + unsigned long sclk = 0; + unsigned int src = 0, div = 0, sub_div = 0
[U-Boot] [PATCH v6 5/7] Exynos5: Use clock_get_periph_rate generic API
Replacing SoC and peripheral specific function calls with generic clock_get_periph_rate calls to get the peripheral clocks. Also, removing dead code of peripheral and SoC specific function implementations which was used earlier for fetching peripheral clocks. This code is not being used anymore because of the introduction of generic clock_get_periph_rate function. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org --- Changes since v5: - No Change. Changes since v4: - Added Reviewed-by. Changes since v3: - Merged patches 5 and 6 of version 3 to fix build errors. Changes since v2: - No change. Changes since v1: - Separated exynos5_get_periph_rate fixes into another patch. arch/arm/cpu/armv7/exynos/clock.c | 278 ++ 1 file changed, 43 insertions(+), 235 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 78f784a..f19fb5c 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -689,27 +689,6 @@ static unsigned long exynos4x12_get_pwm_clk(void) return pclk; } -/* exynos5420: return pwm clock frequency */ -static unsigned long exynos5420_get_pwm_clk(void) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long pclk, sclk; - unsigned int ratio; - - /* -* CLK_DIV_PERIC0 -* PWM_RATIO [31:28] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio 28) 0xf; - sclk = get_pll_clk(MPLL); - - pclk = sclk / (ratio + 1); - - return pclk; -} - /* exynos4: return uart clock frequency */ static unsigned long exynos4_get_uart_clk(int dev_index) { @@ -802,100 +781,6 @@ static unsigned long exynos4x12_get_uart_clk(int dev_index) return uclk; } -/* exynos5: return uart clock frequency */ -static unsigned long exynos5_get_uart_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [3:0] -* UART1_SEL [7:4] -* UART2_SEL [8:11] -* UART3_SEL [12:15] -* UART4_SEL [16:19] -* UART5_SEL [23:20] -*/ - sel = readl(clk-src_peric0); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel == 0x7) - sclk = get_pll_clk(EPLL); - else if (sel == 0x8) - sclk = get_pll_clk(VPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [3:0] -* UART1_RATIO [7:4] -* UART2_RATIO [8:11] -* UART3_RATIO [12:15] -* UART4_RATIO [16:19] -* UART5_RATIO [23:20] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio (dev_index 2)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - -/* exynos5420: return uart clock frequency */ -static unsigned long exynos5420_get_uart_clk(int dev_index) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [6:4] -* UART1_SEL [10:8] -* UART2_SEL [14:12] -* UART3_SEL [18:16] -* generalised calculation as follows -* sel = (sel ((dev_index * 4) + 4)) mask; -*/ - sel = readl(clk-src_peric0); - sel = (sel ((dev_index * 4) + 4)) 0x7; - - if (sel == 0x3) - sclk = get_pll_clk(MPLL); - else if (sel == 0x6) - sclk = get_pll_clk(EPLL); - else if (sel == 0x7) - sclk = get_pll_clk(RPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [11:8] -* UART1_RATIO [15:12] -* UART2_RATIO [19:16] -* UART3_RATIO [23:20] -* generalised calculation as follows -* ratio = (ratio ((dev_index * 4) + 8)) mask; -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio ((dev_index * 4) + 8)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - static unsigned long exynos4_get_mmc_clk(int dev_index) { struct exynos4_clock *clk = @@ -945,94 +830,6 @@ static unsigned long exynos4_get_mmc_clk(int dev_index) return uclk; } -static unsigned long exynos5_get_mmc_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel, ratio, pre_ratio; - int shift = 0; - - sel = readl(clk-src_fsys
[U-Boot] [PATCH v6 4/7] Exynos5: Fix exynos5_get_periph_rate calculations
exynos5_get_periph_rate function reads incorrect div for SDMMC2 3. It also reads prediv and does division only for SDMMC0 2 when actually various other peripherals need that. Adding changes to fix these mistakes in periph rate calculation. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v5: - No Change. Changes since v4: - No Change. Changes since v3: - Added Reviewed-by Tested-by. Changes since v2: - Added checks for negative values in exynos5_get_periph_rate. Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 16900cc..78f784a 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -362,8 +362,8 @@ static struct clk_bit_info *get_clk_bit_info(int peripheral) static unsigned long exynos5_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); - unsigned long sclk, sub_clk; - unsigned int src, div, sub_div; + unsigned long sclk, sub_clk = 0; + unsigned int src, div, sub_div = 0; struct exynos5_clock *clk = (struct exynos5_clock *)samsung_get_base_clock(); @@ -402,10 +402,13 @@ static unsigned long exynos5_get_periph_rate(int peripheral) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: + src = readl(clk-src_fsys); + div = readl(clk-div_fsys1); + break; case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: src = readl(clk-src_fsys); - div = readl(clk-div_fsys1); + div = readl(clk-div_fsys2); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -426,7 +429,8 @@ static unsigned long exynos5_get_periph_rate(int peripheral) return -1; }; - src = (src bit_info-src_bit) 0xf; + if (bit_info-src_bit = 0) + src = (src bit_info-src_bit) 0xf; switch (src) { case EXYNOS_SRC_MPLL: @@ -443,11 +447,12 @@ static unsigned long exynos5_get_periph_rate(int peripheral) } /* Ratio clock division for this peripheral */ - sub_div = (div bit_info-div_bit) 0xf; - sub_clk = sclk / (sub_div + 1); + if (bit_info-div_bit = 0) { + sub_div = (div bit_info-div_bit) 0xf; + sub_clk = sclk / (sub_div + 1); + } - /* Pre-ratio clock division for SDMMC0 and 2 */ - if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) { + if (bit_info-prediv_bit = 0) { div = (div bit_info-prediv_bit) 0xff; return sub_clk / (div + 1); } -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v6 6/7] Exynos: clock: change mask bits as per peripheral
We have assumed and kept mask bits for divider and pre-divider as 0xf and 0xff, respectively. But these mask bits change from one peripheral to another, and hence, need to be specified in accordance with the peripherals. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v5: - No Change. Changes since v4: - Isolated maskbit changes. Changes since v3: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 151 -- 1 file changed, 78 insertions(+), 73 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index f19fb5c..3884d4b 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -21,79 +21,83 @@ */ struct clk_bit_info { enum periph_id id; + int32_t src_mask; + int32_t div_mask; + int32_t prediv_mask; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* periph_id src_bit div_bit prediv_bit */ static struct clk_bit_info exynos5_bit_info[] = { - {PERIPH_ID_UART0, 0, 0, -1}, - {PERIPH_ID_UART1, 4, 4, -1}, - {PERIPH_ID_UART2, 8, 8, -1}, - {PERIPH_ID_UART3, 12, 12, -1}, - {PERIPH_ID_I2C0,-1, 24, 0}, - {PERIPH_ID_I2C1,-1, 24, 0}, - {PERIPH_ID_I2C2,-1, 24, 0}, - {PERIPH_ID_I2C3,-1, 24, 0}, - {PERIPH_ID_I2C4,-1, 24, 0}, - {PERIPH_ID_I2C5,-1, 24, 0}, - {PERIPH_ID_I2C6,-1, 24, 0}, - {PERIPH_ID_I2C7,-1, 24, 0}, - {PERIPH_ID_SPI0,16, 0, 8}, - {PERIPH_ID_SPI1,20, 16, 24}, - {PERIPH_ID_SPI2,24, 0, 8}, - {PERIPH_ID_SDMMC0, 0, 0, 8}, - {PERIPH_ID_SDMMC1, 4, 16, 24}, - {PERIPH_ID_SDMMC2, 8, 0, 8}, - {PERIPH_ID_SDMMC3, 12, 16, 24}, - {PERIPH_ID_I2S0,0, 0, 4}, - {PERIPH_ID_I2S1,4, 12, 16}, - {PERIPH_ID_SPI3,0, 0, 4}, - {PERIPH_ID_SPI4,4, 12, 16}, - {PERIPH_ID_SDMMC4, 16, 0, 8}, - {PERIPH_ID_PWM0,24, 0, -1}, - {PERIPH_ID_PWM1,24, 0, -1}, - {PERIPH_ID_PWM2,24, 0, -1}, - {PERIPH_ID_PWM3,24, 0, -1}, - {PERIPH_ID_PWM4,24, 0, -1}, - - {PERIPH_ID_NONE,-1, -1, -1}, + /* periph ids_mask d_mask p_mask s_bit d_bit p_bit */ + {PERIPH_ID_UART0, 0xf,0xf,-1, 0, 0, -1}, + {PERIPH_ID_UART1, 0xf,0xf,-1, 4, 4, -1}, + {PERIPH_ID_UART2, 0xf,0xf,-1, 8, 8, -1}, + {PERIPH_ID_UART3, 0xf,0xf,-1, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_SPI0,0xf,0xf,0xff, 16, 0, 8}, + {PERIPH_ID_SPI1,0xf,0xf,0xff, 20, 16, 24}, + {PERIPH_ID_SPI2,0xf,0xf,0xff, 24, 0, 8}, + {PERIPH_ID_SDMMC0, 0xf,0xf,0xff, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 0xf,0xf,0xff, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 0xf,0xf,0xff, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 0xf,0xf,0xff, 12, 16, 24}, + {PERIPH_ID_I2S0,0xf,0xf,0xff, 0, 0, 4}, + {PERIPH_ID_I2S1,0xf,0xf,0xff, 4, 12, 16}, + {PERIPH_ID_SPI3,0xf,0xf,0xff, 0, 0, 4}, + {PERIPH_ID_SPI4,0xf,0xf,0xff, 4, 12, 16}, + {PERIPH_ID_SDMMC4, 0xf,0xf,0xff, 16, 0, 8}, + {PERIPH_ID_PWM0,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM1,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM2,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM3,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM4,0xf,0xf,-1, 24, 0, -1}, + + {PERIPH_ID_NONE,-1, -1
[U-Boot] [PATCH v6 2/7] Exynos542x: Move exynos5420_get_pll_clk up and rename
Moving exynos5420_get_pll_clk function definition up in the code to keep it together with rest of SoC_get_pll_clk functions. This makes code more legible and also removes the need of declaration when called before the position of definition in code. Also, renaming exynos5420_get_pll_clk to exynos542x_get_pll_clk because it is being used for both Exynos 5420 and 5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v5: - No Change. Changes since v4: - No Change. Changes since v3: - Added Reviewed-by Tested-by. Changes since v2: - Changed exynos5420 - exynos542x in line 33. Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 82 +++ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 6f20c81..5dc9ed2 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -263,6 +263,46 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +/* exynos542x: return pll clock frequency */ +static unsigned long exynos542x_get_pll_clk(int pllreg) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(clk-apll_con0); + break; + case MPLL: + r = readl(clk-mpll_con0); + break; + case EPLL: + r = readl(clk-epll_con0); + k = readl(clk-epll_con1); + break; + case VPLL: + r = readl(clk-vpll_con0); + k = readl(clk-vpll_con1); + break; + case BPLL: + r = readl(clk-bpll_con0); + break; + case RPLL: + r = readl(clk-rpll_con0); + k = readl(clk-rpll_con1); + break; + case SPLL: + r = readl(clk-spll_con0); + break; + default: + printf(Unsupported PLL (%d)\n, pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; @@ -382,46 +422,6 @@ unsigned long clock_get_periph_rate(int peripheral) return 0; } -/* exynos5420: return pll clock frequency */ -static unsigned long exynos5420_get_pll_clk(int pllreg) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long r, k = 0; - - switch (pllreg) { - case APLL: - r = readl(clk-apll_con0); - break; - case MPLL: - r = readl(clk-mpll_con0); - break; - case EPLL: - r = readl(clk-epll_con0); - k = readl(clk-epll_con1); - break; - case VPLL: - r = readl(clk-vpll_con0); - k = readl(clk-vpll_con1); - break; - case BPLL: - r = readl(clk-bpll_con0); - break; - case RPLL: - r = readl(clk-rpll_con0); - k = readl(clk-rpll_con1); - break; - case SPLL: - r = readl(clk-spll_con0); - break; - default: - printf(Unsupported PLL (%d)\n, pllreg); - return 0; - } - - return exynos_get_pll_clk(pllreg, r, k); -} - /* exynos4: return ARM clock frequency */ static unsigned long exynos4_get_arm_clk(void) { @@ -1603,7 +1603,7 @@ unsigned long get_pll_clk(int pllreg) { if (cpu_is_exynos5()) { if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_pll_clk(pllreg); + return exynos542x_get_pll_clk(pllreg); return exynos5_get_pll_clk(pllreg); } else { if (proid_is_exynos4412()) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v6 3/7] Exynos542x: Add and enable get_periph_rate support
We planned to fetch peripheral rate through one generic API per peripheral. These generic peripheral functions are in turn expected to fetch apt values from a function refactored as per SoC versions. This patch adds support for fetching peripheral rates for Exynos5420 and Exynos5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org --- Changes since v5: - No Change. Changes since v4: - Added Reviewed-by. Changes since v3: - Added a case for SPLL in exynos542x_get_periph_rate. - Changed EXYNOS542x - EXYNOS542X. Changes since v2: - Fixed enum and exynos542x_get_periph_rate switch. - Added checks for negative values in exynos542x_get_periph_rate. Changes since v1: - Changes suuport - support in commit message. - Removed position change of exynos5420_get_pll_clk. - Removed #ifdef. arch/arm/cpu/armv7/exynos/clock.c | 153 +++-- arch/arm/include/asm/arch-exynos/clk.h | 4 + 2 files changed, 150 insertions(+), 7 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 5dc9ed2..16900cc 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -27,7 +27,7 @@ struct clk_bit_info { }; /* periph_id src_bit div_bit prediv_bit */ -static struct clk_bit_info clk_bit_info[] = { +static struct clk_bit_info exynos5_bit_info[] = { {PERIPH_ID_UART0, 0, 0, -1}, {PERIPH_ID_UART1, 4, 4, -1}, {PERIPH_ID_UART2, 8, 8, -1}, @@ -61,6 +61,41 @@ static struct clk_bit_info clk_bit_info[] = { {PERIPH_ID_NONE,-1, -1, -1}, }; +static struct clk_bit_info exynos542x_bit_info[] = { + {PERIPH_ID_UART0, 4, 8, -1}, + {PERIPH_ID_UART1, 8, 12, -1}, + {PERIPH_ID_UART2, 12, 16, -1}, + {PERIPH_ID_UART3, 16, 20, -1}, + {PERIPH_ID_I2C0,-1, 8, -1}, + {PERIPH_ID_I2C1,-1, 8, -1}, + {PERIPH_ID_I2C2,-1, 8, -1}, + {PERIPH_ID_I2C3,-1, 8, -1}, + {PERIPH_ID_I2C4,-1, 8, -1}, + {PERIPH_ID_I2C5,-1, 8, -1}, + {PERIPH_ID_I2C6,-1, 8, -1}, + {PERIPH_ID_I2C7,-1, 8, -1}, + {PERIPH_ID_SPI0,20, 20, 8}, + {PERIPH_ID_SPI1,24, 24, 16}, + {PERIPH_ID_SPI2,28, 28, 24}, + {PERIPH_ID_SDMMC0, 8, 0, -1}, + {PERIPH_ID_SDMMC1, 12, 10, -1}, + {PERIPH_ID_SDMMC2, 16, 20, -1}, + {PERIPH_ID_I2C8,-1, 8, -1}, + {PERIPH_ID_I2C9,-1, 8, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SPI3,12, 16, 0}, + {PERIPH_ID_SPI4,16, 20, 8}, + {PERIPH_ID_PWM0,24, 28, -1}, + {PERIPH_ID_PWM1,24, 28, -1}, + {PERIPH_ID_PWM2,24, 28, -1}, + {PERIPH_ID_PWM3,24, 28, -1}, + {PERIPH_ID_PWM4,24, 28, -1}, + {PERIPH_ID_I2C10, -1, 8, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, +}; + /* Epll Clock division values to achive different frequency output */ static struct set_epll_con_val exynos5_epll_div[] = { { 19200, 0, 48, 3, 1, 0 }, @@ -306,16 +341,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg) static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; + struct clk_bit_info *info; + + if (proid_is_exynos5420() || proid_is_exynos5800()) + info = exynos542x_bit_info; + else + info = exynos5_bit_info; - for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { - if (clk_bit_info[i].id == peripheral) + for (i = 0; info[i].id != PERIPH_ID_NONE; i++) { + if (info[i].id == peripheral) break; } - if (clk_bit_info[i].id == PERIPH_ID_NONE) + if (info[i].id == PERIPH_ID_NONE) debug(ERROR: Peripheral ID %d not found\n, peripheral); - return clk_bit_info[i]; + return info[i]; } static unsigned long exynos5_get_periph_rate(int peripheral) @@ -414,12 +455,110 @@ static unsigned long exynos5_get_periph_rate(int peripheral) return sub_clk; } +static unsigned long exynos542x_get_periph_rate(int peripheral) +{ + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); + unsigned long sclk, sub_clk = 0; + unsigned int src, div, sub_div = 0; + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock
[U-Boot] [PATCH v6 0/7] Exynos5: Fix warnings and enrich clock_get_periph_rate
This patch series does following changes - 1. Removing compiler warnings for clock_get_periph_rate. 2. Adding and enabling support for Exynos542x in clock_get_periph_rate. 3. Replacing peripheral specific function calls with clock_get_periph_rate. 4. Remove code from clocks file which became useless due to introduction of clock_get_periph_rate. Changes since v5: - Elaborated commit message and fixed a nit. Changes since v4: - Added Reviewed-by in patches 3 and 5. - Split patch 6 of version 4 into two patches 6 and 7. Changes since v3: - Added Reviewed-by Tested-by in patches 1, 2 and 4. - Patch-3: Handled SPLL case in exynos542x_get_periph_rate. - Patch-3: Changed EXYNOS542x - EXYNOS542X in pll_src_bit enum. - Merged pathces 5 and 6 of version 3. - Patch-6: New patch for dealing with variety of mask bits. Changes since v2: - Patch-1: Added debug message for unknown periph IDs. - Patch-2: Changed exynos5420 - exynos542x in comment. - Patch-3: Fixed enum and soc_get_periph_rate switch. - Patch-3: Added checks for negative values in soc_get_periph_rate. - Patch-4: Added checks for negative values in soc_get_periph_rate. Changes since v1: - Added 2 new patches. Akshay Saraswat (7): Exynos5: Fix compiler warnings due to clock_get_periph_rate Exynos542x: Move exynos5420_get_pll_clk up and rename Exynos542x: Add and enable get_periph_rate support Exynos5: Fix exynos5_get_periph_rate calculations Exynos5: Use clock_get_periph_rate generic API Exynos: clock: change mask bits as per peripheral Exynos: Clock: Cleanup soc_get_periph_rate arch/arm/cpu/armv7/exynos/clock.c | 617 - arch/arm/include/asm/arch-exynos/clk.h | 4 + 2 files changed, 298 insertions(+), 323 deletions(-) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v6 1/7] Exynos5: Fix compiler warnings due to clock_get_periph_rate
Apparently, members of clk_bit_info array do not map correctly to the members of enum periph_id. This mapping got broken after we changed periph_id(s) to reflect interrupt number instead of their position in a sequence. This patch intends to fix above mentioned issue. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v5: - No Change. Changes since v4: - No Change. Changes since v3: - Added Reviewed-by Tested-by. Changes since v2: - Added debug message for unknown periph IDs. Changes since v1: - Removed exynos5_bit_info array name. arch/arm/cpu/armv7/exynos/clock.c | 80 --- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index b31c13b..6f20c81 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -20,42 +20,45 @@ * positions of the peripheral clocks of the src and div registers */ struct clk_bit_info { + enum periph_id id; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* src_bit div_bit prediv_bit */ +/* periph_id src_bit div_bit prediv_bit */ static struct clk_bit_info clk_bit_info[] = { - {0, 0, -1}, - {4, 4, -1}, - {8, 8, -1}, - {12,12, -1}, - {0, 0, 8}, - {4, 16, 24}, - {8, 0, 8}, - {12,16, 24}, - {-1,-1, -1}, - {16,0, 8}, - {20,16, 24}, - {24,0, 8}, - {0, 0, 4}, - {4, 12, 16}, - {-1,-1, -1}, - {-1,-1, -1}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, + {PERIPH_ID_UART0, 0, 0, -1}, + {PERIPH_ID_UART1, 4, 4, -1}, + {PERIPH_ID_UART2, 8, 8, -1}, + {PERIPH_ID_UART3, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 24, 0}, + {PERIPH_ID_SPI0,16, 0, 8}, + {PERIPH_ID_SPI1,20, 16, 24}, + {PERIPH_ID_SPI2,24, 0, 8}, + {PERIPH_ID_SDMMC0, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 12, 16, 24}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SPI3,0, 0, 4}, + {PERIPH_ID_SPI4,4, 12, 16}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 0, -1}, + {PERIPH_ID_PWM1,24, 0, -1}, + {PERIPH_ID_PWM2,24, 0, -1}, + {PERIPH_ID_PWM3,24, 0, -1}, + {PERIPH_ID_PWM4,24, 0, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, }; /* Epll Clock division values to achive different frequency output */ @@ -260,9 +263,24 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +static struct clk_bit_info *get_clk_bit_info(int peripheral) +{ + int i; + + for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { + if (clk_bit_info[i].id == peripheral) + break; + } + + if (clk_bit_info[i].id == PERIPH_ID_NONE) + debug(ERROR: Peripheral ID %d not found\n, peripheral); + + return clk_bit_info[i]; +} + static unsigned long exynos5_get_periph_rate(int peripheral) { - struct clk_bit_info *bit_info = clk_bit_info[peripheral]; + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); unsigned long sclk, sub_clk; unsigned int src, div, sub_div; struct exynos5_clock *clk = -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 02/11] Exynos542x: CPU: Power down all secondary cores
This patch adds code to shutdown secondary cores. When U-boot comes up, all secondary cores appear powered on, which is undesirable and causes side effects while initializing these cores in kernel. Secondary core power down happens in following steps: Step-1: After Exynos power-on, primary core starts executing first. Step-2: In iROM code every core has to check 2 flags i.e. addresses 0x02020028 0x02020004. Step-3: Initially 0x02020028 is 0 for all cores and 0x02020004 has a jump address for primary core and 0 for all secondary cores. Step-4: Therefore, primary core follows normal iROM execution and jumps to BL1 eventually, whereas all secondary cores enter WFE. Step-5: When primary core comes into function secondary_cores_configure, it puts pointer to function power_down_core into 0x02020004 and provides DSB and SEV for all cores so that they may come out of WFE and jump to power_down_core function. Step-6: And ultimately because of power_down_core all secondary cores shut-down. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v1: - Removed unnecessary macros. - Changed names of few macros for better understanding. - Added MPIDR bit assignment info comment in power_down_core. arch/arm/cpu/armv7/exynos/exynos5_setup.h | 3 ++ arch/arm/cpu/armv7/exynos/lowlevel_init.c | 69 arch/arm/include/asm/arch-exynos/cpu.h| 5 ++ arch/arm/include/asm/arch-exynos/system.h | 87 +++ 4 files changed, 164 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index 2eea48a..9073f50 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -700,6 +700,9 @@ #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE #else + +#define CPU_CONFIG_STATUS_OFFSET 0x80 +#define CPU_RST_FLAG_VAL 0xFCBA0D10 #define PAD_RETENTION_DRAM_COREBLK_VAL 0x1000 /* APLL_CON1 */ diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 83e1dcf..e36f2fa 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -31,7 +31,9 @@ #include asm/arch/tzpc.h #include asm/arch/periph.h #include asm/arch/pinmux.h +#include asm/arch/system.h #include common_setup.h +#include exynos5_setup.h /* These are the things we can do during low-level init */ enum { @@ -42,6 +44,68 @@ enum { DO_POWER= 1 4, }; +#ifdef CONFIG_EXYNOS5420 +/* + * Pointer to this function is stored in iRam which is used + * for jump and power down of a specific core. + */ +static void power_down_core(void) +{ + uint32_t tmp, core_id, core_config; + + /* Get the unique core id */ + /* +* Multiprocessor Affinity Register +* [11:8] Cluster ID +* [1:0]CPU ID +*/ + mrc_mpafr(core_id); + tmp = core_id 0x3; + core_id = (core_id 6) ~3; + core_id |= tmp; + core_id = 0x3f; + + /* Set the status of the core to low */ + core_config = (core_id * CPU_CONFIG_STATUS_OFFSET); + core_config += EXYNOS5420_CPU_CONFIG_BASE; + writel(0x0, core_config); + + /* Core enter WFI */ + wfi(); +} + +/* + * Configurations for secondary cores are inapt at this stage. + * Reconfigure secondary cores. Shutdown and change the status + * of all cores except the primary core. + */ +static void secondary_cores_configure(void) +{ + uint32_t core_id; + + /* Store jump address for power down of secondary cores */ + writel((uint32_t)power_down_core, CONFIG_PHY_IRAM_BASE + 0x4); + + /* Need all core power down check */ + dsb(); + sev(); + + /* +* Power down all cores(secondary) while primary core must +* wait for all cores to go down. +*/ + for (core_id = 1; core_id != CONFIG_CORE_COUNT; core_id++) { + while ((readl(EXYNOS5420_CPU_STATUS_BASE + + (core_id * CPU_CONFIG_STATUS_OFFSET)) +0xff) != 0x0) { + isb(); + sev(); + } + isb(); + } +} +#endif + int do_lowlevel_init(void) { uint32_t reset_status; @@ -49,6 +113,11 @@ int do_lowlevel_init(void) arch_cpu_init(); +#ifdef CONFIG_EXYNOS5420 + /* Reconfigure secondary cores */ + secondary_cores_configure(); +#endif + reset_status = get_reset_status(); switch (reset_status) { diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index 29674ad..e739520 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -153,6 +153,10 @@ #define EXYNOS5420_CLOCK_BASE
[U-Boot] [PATCH v2 01/11] Exynos542x: Config: Add various configs
This patch adds iRAM, CPU state and low power configs which are the addresses acting as flag registers. iROM code checks CONFIG_LOWPOWER_FLAG address. If it is equal to CONFIG_LOWPOWER_EN then it jumps to the address (0x0202+CPUID*4). This is a part of iROM logic. Rest other flags are being used at various places during kernel switching and reset. They are nowhere documented because they are part programming. These configs are serving as flags for us because they are representing the addresses in iRAM which we are using for storing and extracting CPU Status and GIC status. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v1: - Added Reviewed-by Tested-by. - Removed unnecessary CONFIGS. include/configs/exynos5420-common.h | 16 1 file changed, 16 insertions(+) diff --git a/include/configs/exynos5420-common.h b/include/configs/exynos5420-common.h index fe72bd0..b42dab7 100644 --- a/include/configs/exynos5420-common.h +++ b/include/configs/exynos5420-common.h @@ -38,4 +38,20 @@ #define CONFIG_BOARD_REV_GPIO_COUNT2 +#define CONFIG_PHY_IRAM_BASE 0x0202 + +/* Address for relocating helper code (Last 4 KB of IRAM) */ +#define CONFIG_EXYNOS_RELOCATE_CODE_BASE (CONFIG_IRAM_TOP - 0x1000) + +/* + * Low Power settings + */ +#define CONFIG_LOWPOWER_FLAG 0x02020028 +#define CONFIG_LOWPOWER_ADDR 0x0202002C + +/* + * Number of CPUs available + */ +#define CONFIG_CORE_COUNT 0x8 + #endif /* __CONFIG_EXYNOS5420_H */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 03/11] Exynos542x: Add workaround for ARM errata 798870
This patch adds workaround for ARM errata 798870 which says If back-to-back speculative cache line fills (fill A and fill B) are issued from the L1 data cache of a CPU to the L2 cache, the second request (fill B) is then cancelled, and the second request would have detected a hazard against a recent write or eviction (write B) to the same cache line as fill B then the L2 logic might deadlock. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v1: - Added Reviewed-by Tested-by. - Added space before */ on line # 40. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index d599bd3..3ad5b78 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -46,6 +46,28 @@ enum { #ifdef CONFIG_EXYNOS5420 /* + * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been + * stalled for 1024 cycles to verify that its hazard condition still exists. + */ +void set_l2cache(void) +{ + uint32_t val; + + /* Read MIDR for Primary Part Number */ + mrc_midr(val); + val = (val 4); + val = 0xf; + + /* L2ACTLR[7]: Enable hazard detect timeout for A15 */ + if (val == 0xf) { + mrc_l2_aux_ctlr(val); + val |= (1 7); + mcr_l2_aux_ctlr(val); + mrc_l2_ctlr(val); + } +} + +/* * Pointer to this function is stored in iRam which is used * for jump and power down of a specific core. */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 04/11] Exynos542x: Add workaround for ARM errata 799270
This patch adds workaround for the ARM errata 799270 which says If the L2 cache logic clock is stopped because of L2 inactivity, setting or clearing the ACTLR.SMP bit might not be effective. The bit is modified in the ACTLR, meaning a read of the register returns the updated value. However the logic that uses that bit retains the previous value. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 3ad5b78..3ebbf84 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -46,6 +46,28 @@ enum { #ifdef CONFIG_EXYNOS5420 /* + * Ensure that the L2 logic has been used within the previous 256 cycles + * before modifying the ACTLR.SMP bit. This is required during boot before + * MMU has been enabled, or during a specified reset or power down sequence. + */ +void enable_smp(void) +{ + uint32_t temp, val; + + /* Enable SMP mode */ + mrc_auxr(temp); + temp |= (1 6); + + /* Dummy read to assure L2 access */ + val = readl(EXYNOS5420_INFORM_BASE); + val = 0; + temp |= val; + mcr_auxr(temp); + dsb(); + isb(); +} + +/* * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 00/11] Add support for booting multiple cores
This patch series introduces changes for booting secondary CPUs on Exynos5420 and Exynos5800. Changes since v1: - Added Reviewed-by Tested-by in the acked patches. - Removed unnecessary CONFIGS and macros. - Changed names of few macros for better understanding in patch 2. - Added MPIDR bit assignment info comment in power_down_core in patch 2. - Changed to SPDX header in sec_boot.S in patch 5. - Fixed compilation error for snow build in patch 11. Akshay Saraswat (10): Exynos542x: Config: Add various configs Exynos542x: CPU: Power down all secondary cores Exynos542x: Add workaround for ARM errata 798870 Exynos542x: Add workaround for ARM errata 799270 Exynos542x: Add workaround for exynos iROM errata Exynos542x: Change ambiguous function name set_l2cache Exynos542x: cache: Disable clean/evict push to external Exynos542x: add L2 control register configuration Exynos542x: Fix secondary core booting for thumb Exynos542x: Make A7s boot with thumb-mode U-Boot on warm reset Doug Anderson (1): Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800 arch/arm/cpu/armv7/exynos/Makefile| 2 + arch/arm/cpu/armv7/exynos/common_setup.h | 55 ++ arch/arm/cpu/armv7/exynos/exynos5_setup.h | 3 + arch/arm/cpu/armv7/exynos/lowlevel_init.c | 166 ++ arch/arm/cpu/armv7/exynos/sec_boot.S | 128 +++ arch/arm/cpu/armv7/exynos/soc.c | 35 --- arch/arm/include/asm/arch-exynos/cpu.h| 5 + arch/arm/include/asm/arch-exynos/system.h | 88 include/configs/exynos5420-common.h | 16 +++ 9 files changed, 463 insertions(+), 35 deletions(-) create mode 100644 arch/arm/cpu/armv7/exynos/sec_boot.S -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v5 0/7] Exynos5: Fix warnings and enrich clock_get_periph_rate
This patch series does following changes - 1. Removing compiler warnings for clock_get_periph_rate. 2. Adding and enabling support for Exynos542x in clock_get_periph_rate. 3. Replacing peripheral specific function calls with clock_get_periph_rate. 4. Remove code from clocks file which became useless due to introduction of clock_get_periph_rate. Changes since v4: - Added Reviewed-by in patches 3 and 5. - Split patch 6 of version 4 into two patches 6 and 7. Changes since v3: - Added Reviewed-by Tested-by in patches 1, 2 and 4. - Patch-3: Handled SPLL case in exynos542x_get_periph_rate. - Patch-3: Changed EXYNOS542x - EXYNOS542X in pll_src_bit enum. - Merged pathces 5 and 6 of version 3. - Patch-6: New patch for dealing with variety of mask bits. Changes since v2: - Patch-1: Added debug message for unknown periph IDs. - Patch-2: Changed exynos5420 - exynos542x in comment. - Patch-3: Fixed enum and soc_get_periph_rate switch. - Patch-3: Added checks for negative values in soc_get_periph_rate. - Patch-4: Added checks for negative values in soc_get_periph_rate. Changes since v1: - Added 2 new patches. Akshay Saraswat (7): Exynos5: Fix compiler warnings due to clock_get_periph_rate Exynos542x: Move exynos5420_get_pll_clk up and rename Exynos542x: Add and enable get_periph_rate support Exynos5: Fix exynos5_get_periph_rate calculations Exynos5: Use clock_get_periph_rate generic API Exynos: clock: change mask bits as per peripheral Exynos: Clock: Cleanup soc_get_periph_rate arch/arm/cpu/armv7/exynos/clock.c | 619 - arch/arm/include/asm/arch-exynos/clk.h | 4 + 2 files changed, 296 insertions(+), 327 deletions(-) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v5 3/7] Exynos542x: Add and enable get_periph_rate support
We planned to fetch peripheral rate through one generic API per peripheral. These generic peripheral functions are in turn expected to fetch apt values from a function refactored as per SoC versions. This patch adds support for fetching peripheral rates for Exynos5420 and Exynos5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org --- Changes since v4: - Added Reviewed-by. Changes since v3: - Added a case for SPLL in exynos542x_get_periph_rate. - Changed EXYNOS542x - EXYNOS542X. Changes since v2: - Fixed enum and exynos542x_get_periph_rate switch. - Added checks for negative values in exynos542x_get_periph_rate. Changes since v1: - Changes suuport - support in commit message. - Removed position change of exynos5420_get_pll_clk. - Removed #ifdef. arch/arm/cpu/armv7/exynos/clock.c | 153 +++-- arch/arm/include/asm/arch-exynos/clk.h | 4 + 2 files changed, 150 insertions(+), 7 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 5dc9ed2..16900cc 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -27,7 +27,7 @@ struct clk_bit_info { }; /* periph_id src_bit div_bit prediv_bit */ -static struct clk_bit_info clk_bit_info[] = { +static struct clk_bit_info exynos5_bit_info[] = { {PERIPH_ID_UART0, 0, 0, -1}, {PERIPH_ID_UART1, 4, 4, -1}, {PERIPH_ID_UART2, 8, 8, -1}, @@ -61,6 +61,41 @@ static struct clk_bit_info clk_bit_info[] = { {PERIPH_ID_NONE,-1, -1, -1}, }; +static struct clk_bit_info exynos542x_bit_info[] = { + {PERIPH_ID_UART0, 4, 8, -1}, + {PERIPH_ID_UART1, 8, 12, -1}, + {PERIPH_ID_UART2, 12, 16, -1}, + {PERIPH_ID_UART3, 16, 20, -1}, + {PERIPH_ID_I2C0,-1, 8, -1}, + {PERIPH_ID_I2C1,-1, 8, -1}, + {PERIPH_ID_I2C2,-1, 8, -1}, + {PERIPH_ID_I2C3,-1, 8, -1}, + {PERIPH_ID_I2C4,-1, 8, -1}, + {PERIPH_ID_I2C5,-1, 8, -1}, + {PERIPH_ID_I2C6,-1, 8, -1}, + {PERIPH_ID_I2C7,-1, 8, -1}, + {PERIPH_ID_SPI0,20, 20, 8}, + {PERIPH_ID_SPI1,24, 24, 16}, + {PERIPH_ID_SPI2,28, 28, 24}, + {PERIPH_ID_SDMMC0, 8, 0, -1}, + {PERIPH_ID_SDMMC1, 12, 10, -1}, + {PERIPH_ID_SDMMC2, 16, 20, -1}, + {PERIPH_ID_I2C8,-1, 8, -1}, + {PERIPH_ID_I2C9,-1, 8, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SPI3,12, 16, 0}, + {PERIPH_ID_SPI4,16, 20, 8}, + {PERIPH_ID_PWM0,24, 28, -1}, + {PERIPH_ID_PWM1,24, 28, -1}, + {PERIPH_ID_PWM2,24, 28, -1}, + {PERIPH_ID_PWM3,24, 28, -1}, + {PERIPH_ID_PWM4,24, 28, -1}, + {PERIPH_ID_I2C10, -1, 8, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, +}; + /* Epll Clock division values to achive different frequency output */ static struct set_epll_con_val exynos5_epll_div[] = { { 19200, 0, 48, 3, 1, 0 }, @@ -306,16 +341,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg) static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; + struct clk_bit_info *info; + + if (proid_is_exynos5420() || proid_is_exynos5800()) + info = exynos542x_bit_info; + else + info = exynos5_bit_info; - for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { - if (clk_bit_info[i].id == peripheral) + for (i = 0; info[i].id != PERIPH_ID_NONE; i++) { + if (info[i].id == peripheral) break; } - if (clk_bit_info[i].id == PERIPH_ID_NONE) + if (info[i].id == PERIPH_ID_NONE) debug(ERROR: Peripheral ID %d not found\n, peripheral); - return clk_bit_info[i]; + return info[i]; } static unsigned long exynos5_get_periph_rate(int peripheral) @@ -414,12 +455,110 @@ static unsigned long exynos5_get_periph_rate(int peripheral) return sub_clk; } +static unsigned long exynos542x_get_periph_rate(int peripheral) +{ + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); + unsigned long sclk, sub_clk = 0; + unsigned int src, div, sub_div = 0; + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + + switch (peripheral) { + case
[U-Boot] [PATCH v5 2/7] Exynos542x: Move exynos5420_get_pll_clk up and rename
Moving exynos5420_get_pll_clk function definition up in the code to keep it together with rest of SoC_get_pll_clk functions. This makes code more legible and also removes the need of declaration when called before the position of definition in code. Also, renaming exynos5420_get_pll_clk to exynos542x_get_pll_clk because it is being used for both Exynos 5420 and 5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v4: - No Change. Changes since v3: - Added Reviewed-by Tested-by. Changes since v2: - Changed exynos5420 - exynos542x in line 33. Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 82 +++ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 6f20c81..5dc9ed2 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -263,6 +263,46 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +/* exynos542x: return pll clock frequency */ +static unsigned long exynos542x_get_pll_clk(int pllreg) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(clk-apll_con0); + break; + case MPLL: + r = readl(clk-mpll_con0); + break; + case EPLL: + r = readl(clk-epll_con0); + k = readl(clk-epll_con1); + break; + case VPLL: + r = readl(clk-vpll_con0); + k = readl(clk-vpll_con1); + break; + case BPLL: + r = readl(clk-bpll_con0); + break; + case RPLL: + r = readl(clk-rpll_con0); + k = readl(clk-rpll_con1); + break; + case SPLL: + r = readl(clk-spll_con0); + break; + default: + printf(Unsupported PLL (%d)\n, pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; @@ -382,46 +422,6 @@ unsigned long clock_get_periph_rate(int peripheral) return 0; } -/* exynos5420: return pll clock frequency */ -static unsigned long exynos5420_get_pll_clk(int pllreg) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long r, k = 0; - - switch (pllreg) { - case APLL: - r = readl(clk-apll_con0); - break; - case MPLL: - r = readl(clk-mpll_con0); - break; - case EPLL: - r = readl(clk-epll_con0); - k = readl(clk-epll_con1); - break; - case VPLL: - r = readl(clk-vpll_con0); - k = readl(clk-vpll_con1); - break; - case BPLL: - r = readl(clk-bpll_con0); - break; - case RPLL: - r = readl(clk-rpll_con0); - k = readl(clk-rpll_con1); - break; - case SPLL: - r = readl(clk-spll_con0); - break; - default: - printf(Unsupported PLL (%d)\n, pllreg); - return 0; - } - - return exynos_get_pll_clk(pllreg, r, k); -} - /* exynos4: return ARM clock frequency */ static unsigned long exynos4_get_arm_clk(void) { @@ -1603,7 +1603,7 @@ unsigned long get_pll_clk(int pllreg) { if (cpu_is_exynos5()) { if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_pll_clk(pllreg); + return exynos542x_get_pll_clk(pllreg); return exynos5_get_pll_clk(pllreg); } else { if (proid_is_exynos4412()) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v5 1/7] Exynos5: Fix compiler warnings due to clock_get_periph_rate
Apparently, members of clk_bit_info array do not map correctly to the members of enum periph_id. This mapping got broken after we changed periph_id(s) to reflect interrupt number instead of their position in a sequence. This patch intends to fix above mentioned issue. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v4: - No Change. Changes since v3: - Added Reviewed-by Tested-by. Changes since v2: - Added debug message for unknown periph IDs. Changes since v1: - Removed exynos5_bit_info array name. arch/arm/cpu/armv7/exynos/clock.c | 80 --- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index b31c13b..6f20c81 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -20,42 +20,45 @@ * positions of the peripheral clocks of the src and div registers */ struct clk_bit_info { + enum periph_id id; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* src_bit div_bit prediv_bit */ +/* periph_id src_bit div_bit prediv_bit */ static struct clk_bit_info clk_bit_info[] = { - {0, 0, -1}, - {4, 4, -1}, - {8, 8, -1}, - {12,12, -1}, - {0, 0, 8}, - {4, 16, 24}, - {8, 0, 8}, - {12,16, 24}, - {-1,-1, -1}, - {16,0, 8}, - {20,16, 24}, - {24,0, 8}, - {0, 0, 4}, - {4, 12, 16}, - {-1,-1, -1}, - {-1,-1, -1}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, + {PERIPH_ID_UART0, 0, 0, -1}, + {PERIPH_ID_UART1, 4, 4, -1}, + {PERIPH_ID_UART2, 8, 8, -1}, + {PERIPH_ID_UART3, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 24, 0}, + {PERIPH_ID_SPI0,16, 0, 8}, + {PERIPH_ID_SPI1,20, 16, 24}, + {PERIPH_ID_SPI2,24, 0, 8}, + {PERIPH_ID_SDMMC0, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 12, 16, 24}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SPI3,0, 0, 4}, + {PERIPH_ID_SPI4,4, 12, 16}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 0, -1}, + {PERIPH_ID_PWM1,24, 0, -1}, + {PERIPH_ID_PWM2,24, 0, -1}, + {PERIPH_ID_PWM3,24, 0, -1}, + {PERIPH_ID_PWM4,24, 0, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, }; /* Epll Clock division values to achive different frequency output */ @@ -260,9 +263,24 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +static struct clk_bit_info *get_clk_bit_info(int peripheral) +{ + int i; + + for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { + if (clk_bit_info[i].id == peripheral) + break; + } + + if (clk_bit_info[i].id == PERIPH_ID_NONE) + debug(ERROR: Peripheral ID %d not found\n, peripheral); + + return clk_bit_info[i]; +} + static unsigned long exynos5_get_periph_rate(int peripheral) { - struct clk_bit_info *bit_info = clk_bit_info[peripheral]; + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); unsigned long sclk, sub_clk; unsigned int src, div, sub_div; struct exynos5_clock *clk = -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 11/11] Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800
From: Doug Anderson diand...@chromium.org It was found that the L2 cache timings that we had before could cause freezes and hangs. We should make things more robust with better timings. Currently the production ChromeOS kernel applies these timings, but it's nice to fixup firmware too (and upstream probably won't take our kernel hacks). This also provides a big cleanup of the L2 cache init code avoiding some duplication. The way things used to work: * low_power_start() was installed by the SPL (both at boot and resume time) and left resident in iRAM for the kernel to use when bringing up additional CPUs. It used configure_l2_ctlr() and configure_l2_actlr() when it detected it was on an A15. This was needed (despite the L2 cache registers being shared among all A15s) because we might have been the first man in after the whole A15 cluster was shutdown. * secondary_cores_configure() was called on at boot time and at resume time. Strangely this called configure_l2_ctlr() but not configure_l2_actlr() which was almost certainly wrong. Given that we'll call both (see next bullet) later in the boot process it didn't matter for normal boot, but I guess this is how L2 cache settings got set on 5420/5800 (but not 5250?) at resume time. * exynos5_set_l2cache_params() was called as part of cache enablement. This should happen at boot time (normally in the SPL except for USB boot where it happens in main U-Boot). Note that the old code wasn't setting ECC/parity in the cache enablement code but we happened to get it anyway because we'd call secondary_cores_configure() at boot time. For resume time we'd get it anyway when the 2nd A15 core came up. Let's make this a whole lot simpler. Now we always set these parameters in the same place for all boots and use the same code for setting up secondary CPUs. Intended net effects of this change (other than cleanup): * Timings go from before: data: 0 cycle setup, 3 cycles (0x2) latency tag: 0 cycle setup, 3 cycles (0x2) latency after: data: 1 cycle setup, 4 cycles (0x3) latency tag: 1 cycle setup, 4 cycles (0x3) latency * L2ACTLR is properly initted on 5420/5800 in all cases. One note is that we're still relying on luck to keep low_power_start() working. The compiler is being nice and not storing anything on the stack. Another note is that on its own this patch won't help to fix cache settings in an RW U-Boot update where we still have the RO SPL. The plan for that is: * Have RW U-Boot re-init the cache right before calling the kernel (after it has turned the L2 cache off). This is why the functions are in a header file instead of lowlevel_init.c. * Have the kernel save the L2 cache settings of the boot CPU and apply them to all other CPUs. We get a little lucky here because the old code was using |= to modify the registers and all of the bits that it's setting are also present in the new settings (!). That means that when the 2nd CPU in the A15 cluster comes up it doesn't actually mess up the settings of the 1st CPU in the A15 cluster. An alternative option is to have the kernel write its own low_power_start() code. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v1: - Fixed compilation error for snow build. arch/arm/cpu/armv7/exynos/common_setup.h | 55 +++ arch/arm/cpu/armv7/exynos/lowlevel_init.c | 55 +-- arch/arm/cpu/armv7/exynos/soc.c | 51 arch/arm/include/asm/arch-exynos/system.h | 2 -- 4 files changed, 70 insertions(+), 93 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/common_setup.h b/arch/arm/cpu/armv7/exynos/common_setup.h index e6318c0..4c00186 100644 --- a/arch/arm/cpu/armv7/exynos/common_setup.h +++ b/arch/arm/cpu/armv7/exynos/common_setup.h @@ -23,6 +23,8 @@ * MA 02111-1307 USA */ +#include asm/arch/system.h + #define DMC_OFFSET 0x1 /* @@ -43,3 +45,56 @@ void system_clock_init(void); int do_lowlevel_init(void); void sdelay(unsigned long); + +enum l2_cache_params { + CACHE_ECC_AND_PARITY = (1 21), + CACHE_TAG_RAM_SETUP = (1 9), + CACHE_DATA_RAM_SETUP = (1 5), +#ifndef CONFIG_EXYNOS5420 + CACHE_TAG_RAM_LATENCY = (2 6), /* 5250 */ + CACHE_DATA_RAM_LATENCY = (2 0), +#else + CACHE_TAG_RAM_LATENCY = (3 6), /* 5420 and 5800 */ + CACHE_DATA_RAM_LATENCY = (3 0), +#endif +}; + +#ifndef CONFIG_SYS_L2CACHE_OFF +/* + * Configure L2CTLR to get timings that keep us from hanging/crashing. + * + * Must be inline here since low_power_start() is called without a + * stack (!). + */ +static inline void configure_l2_ctlr(void) +{ + uint32_t val; + + mrc_l2_ctlr(val); + val |= CACHE_TAG_RAM_SETUP | + CACHE_DATA_RAM_SETUP | + CACHE_TAG_RAM_LATENCY | + CACHE_DATA_RAM_LATENCY
[U-Boot] [PATCH v2 06/11] Exynos542x: Change ambiguous function name set_l2cache
1. Renaming set_l2cache to configure_l2actlr in order to avoid misleading comprehensions. Apparently this name suggests that L2 cache is being set or initialized which is incorrect as per the code in this function. 2. Cleaning missed mrc for L2 control register. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 527d20b..1c70e54 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -71,7 +71,7 @@ static void enable_smp(void) * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. */ -static void set_l2cache(void) +static void configure_l2actlr(void) { uint32_t val; @@ -85,7 +85,6 @@ static void set_l2cache(void) mrc_l2_aux_ctlr(val); val |= (1 7); mcr_l2_aux_ctlr(val); - mrc_l2_ctlr(val); } } @@ -123,7 +122,7 @@ static void low_power_start(void) /* Set the CPU to SVC32 mode */ svc32_mode_en(); - set_l2cache(); + configure_l2actlr(); /* Invalidate L1 TLB */ val = 0x0; @@ -176,7 +175,7 @@ static void power_down_core(void) static void secondary_cores_configure(void) { /* Setup L2 cache */ - set_l2cache(); + configure_l2actlr(); /* Clear secondary boot iRAM base */ writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 08/11] Exynos542x: add L2 control register configuration
This patch does 3 things: 1. Enables ECC by setting 21st bit of L2CTLR. 2. Restore data and tag RAM latencies to 3 cycles because iROM sets 0x3000400 L2CTLR value during switching. 3. Disable clean/evict push to external by setting 3rd bit of L2ACTLR. We need to restore this here due to switching. Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 53 +++ arch/arm/cpu/armv7/exynos/soc.c | 7 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 1c70e54..9892e6b 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -68,24 +68,40 @@ static void enable_smp(void) } /* + * Enable ECC by setting L2CTLR[21]. + * Set L2CTLR[7] to make tag ram latency 3 cycles and + * set L2CTLR[1] to make data ram latency 3 cycles. + * We need to make RAM latency of 3 cycles here because cores + * power ON and OFF while switching. And everytime a core powers + * ON, iROM provides it a default L2CTLR value 0x400 which stands + * for TAG RAM setup of 1 cycle. Hence, we face a need of + * restoring data and tag latency values. + */ +static void configure_l2_ctlr(void) +{ + uint32_t val; + + mrc_l2_ctlr(val); + val |= (1 21); + val |= (1 7); + val |= (1 1); + mcr_l2_ctlr(val); +} + +/* * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. + * Disable clean/evict push to external by setting L2ACTLR[3]. */ -static void configure_l2actlr(void) +static void configure_l2_actlr(void) { uint32_t val; - /* Read MIDR for Primary Part Number */ - mrc_midr(val); - val = (val 4); - val = 0xf; - - /* L2ACTLR[7]: Enable hazard detect timeout for A15 */ - if (val == 0xf) { - mrc_l2_aux_ctlr(val); - val |= (1 7); - mcr_l2_aux_ctlr(val); - } + mrc_l2_aux_ctlr(val); + val |= (1 27); + val |= (1 7); + val |= (1 3); + mcr_l2_aux_ctlr(val); } /* @@ -122,7 +138,16 @@ static void low_power_start(void) /* Set the CPU to SVC32 mode */ svc32_mode_en(); - configure_l2actlr(); + + /* Read MIDR for Primary Part Number */ + mrc_midr(val); + val = (val 4); + val = 0xf; + + if (val == 0xf) { + configure_l2_ctlr(); + configure_l2_actlr(); + } /* Invalidate L1 TLB */ val = 0x0; @@ -175,7 +200,7 @@ static void power_down_core(void) static void secondary_cores_configure(void) { /* Setup L2 cache */ - configure_l2actlr(); + configure_l2_ctlr(); /* Clear secondary boot iRAM base */ writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index 7268b9b..ea201e7 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -10,8 +10,10 @@ #include asm/system.h enum l2_cache_params { +#ifndef CONFIG_EXYNOS5420 CACHE_TAG_RAM_SETUP = (1 9), CACHE_DATA_RAM_SETUP = (1 5), +#endif CACHE_TAG_RAM_LATENCY = (2 6), CACHE_DATA_RAM_LATENCY = (2 0) }; @@ -39,10 +41,15 @@ static void exynos5_set_l2cache_params(void) asm volatile(mrc p15, 1, %0, c9, c0, 2\n : =r(val)); +#ifndef CONFIG_EXYNOS5420 val |= CACHE_TAG_RAM_SETUP | CACHE_DATA_RAM_SETUP | CACHE_TAG_RAM_LATENCY | CACHE_DATA_RAM_LATENCY; +#else + val |= CACHE_TAG_RAM_LATENCY | + CACHE_DATA_RAM_LATENCY; +#endif asm volatile(mcr p15, 1, %0, c9, c0, 2\n : : r(val)); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 05/11] Exynos542x: Add workaround for exynos iROM errata
iROM logic provides undesired jump address for CPU2. This patch adds a programmable susbstitute for a part of iROM logic which wakes up cores and provides jump addresses. This patch creates a logic to make all secondary cores jump to a particular address which evades the possibility of CPU2 jumping to wrong address and create undesired results. Logic of the workaround: Step-1: iROM code checks value at address 0x2020028. Step-2: If value is 0xc9cfcfcf, it jumps to the address (0x202000+CPUid*4), else, it continues executing normally. Step-3: Primary core puts secondary cores in WFE and store 0xc9cfcfcf in 0x2020028 and jump address (pointer to function low_power_start) in (0x202000+CPUid*4). Step-4: When secondary cores recieve event signal they jump to this address and continue execution. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v1: - Added Reviewed-by Tested-by. - Changed to SPDX header in sec_boot.S. arch/arm/cpu/armv7/exynos/Makefile| 2 + arch/arm/cpu/armv7/exynos/lowlevel_init.c | 90 - arch/arm/cpu/armv7/exynos/sec_boot.S | 128 ++ 3 files changed, 202 insertions(+), 18 deletions(-) create mode 100644 arch/arm/cpu/armv7/exynos/sec_boot.S diff --git a/arch/arm/cpu/armv7/exynos/Makefile b/arch/arm/cpu/armv7/exynos/Makefile index e207bd6..8542f89 100644 --- a/arch/arm/cpu/armv7/exynos/Makefile +++ b/arch/arm/cpu/armv7/exynos/Makefile @@ -7,6 +7,8 @@ obj-y += clock.o power.o soc.o system.o pinmux.o tzpc.o +obj-$(CONFIG_EXYNOS5420) += sec_boot.o + ifdef CONFIG_SPL_BUILD obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 3ebbf84..527d20b 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -50,7 +50,7 @@ enum { * before modifying the ACTLR.SMP bit. This is required during boot before * MMU has been enabled, or during a specified reset or power down sequence. */ -void enable_smp(void) +static void enable_smp(void) { uint32_t temp, val; @@ -71,7 +71,7 @@ void enable_smp(void) * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. */ -void set_l2cache(void) +static void set_l2cache(void) { uint32_t val; @@ -90,6 +90,62 @@ void set_l2cache(void) } /* + * Power up secondary CPUs. + */ +static void secondary_cpu_start(void) +{ + enable_smp(); + svc32_mode_en(); + set_pc(CONFIG_EXYNOS_RELOCATE_CODE_BASE); +} + +/* + * This is the entry point of hotplug-in and + * cluster switching. + */ +static void low_power_start(void) +{ + uint32_t val, reg_val; + + reg_val = readl(EXYNOS5420_SPARE_BASE); + if (reg_val != CPU_RST_FLAG_VAL) { + writel(0x0, CONFIG_LOWPOWER_FLAG); + set_pc(0x0); + } + + reg_val = readl(CONFIG_PHY_IRAM_BASE + 0x4); + if (reg_val != (uint32_t)low_power_start) { + /* Store jump address as low_power_start if not present */ + writel((uint32_t)low_power_start, CONFIG_PHY_IRAM_BASE + 0x4); + dsb(); + sev(); + } + + /* Set the CPU to SVC32 mode */ + svc32_mode_en(); + set_l2cache(); + + /* Invalidate L1 TLB */ + val = 0x0; + mcr_tlb(val); + mcr_icache(val); + + /* Disable MMU stuff and caches */ + mrc_sctlr(val); + + val = ~((0x2 12) | 0x7); + val |= ((0x1 12) | (0x8 8) | 0x2); + mcr_sctlr(val); + + /* CPU state is hotplug or reset */ + secondary_cpu_start(); + + /* Core should not enter into WFI here */ + wfi(); + +} + +/* * Pointer to this function is stored in iRam which is used * for jump and power down of a specific core. */ @@ -119,29 +175,25 @@ static void power_down_core(void) */ static void secondary_cores_configure(void) { - uint32_t core_id; + /* Setup L2 cache */ + set_l2cache(); + + /* Clear secondary boot iRAM base */ + writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); - /* Store jump address for power down of secondary cores */ + /* set lowpower flag and address */ + writel(CPU_RST_FLAG_VAL, CONFIG_LOWPOWER_FLAG); + writel((uint32_t)low_power_start, CONFIG_LOWPOWER_ADDR); + writel(CPU_RST_FLAG_VAL, EXYNOS5420_SPARE_BASE); + /* Store jump address for power down */ writel((uint32_t)power_down_core, CONFIG_PHY_IRAM_BASE + 0x4); /* Need all core power down check */ dsb(); sev
[U-Boot] [PATCH v2 09/11] Exynos542x: Fix secondary core booting for thumb
When compiled SPL for Thumb secondary cores failed to boot at the kernel boot up. Only one core came up out of 4. This was happening because the code relocated to the address 0x02073000 by the primary core was an ARM asm code which was executed by the secondary cores as if it was a thumb code. This patch fixes the issue of secondary cores considering relocated code as Thumb instructions and not ARM instructions by jumping to the relocated with the help of bx ARM instruction. bx instruction changes the 5th bit of CPSR which allows execution unit to consider the following instructions as ARM instructions. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 +- arch/arm/include/asm/arch-exynos/system.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 9892e6b..3fbaaf3 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -111,7 +111,7 @@ static void secondary_cpu_start(void) { enable_smp(); svc32_mode_en(); - set_pc(CONFIG_EXYNOS_RELOCATE_CODE_BASE); + branch_bx(CONFIG_EXYNOS_RELOCATE_CODE_BASE); } /* diff --git a/arch/arm/include/asm/arch-exynos/system.h b/arch/arm/include/asm/arch-exynos/system.h index 86903c3..a9fd5e6 100644 --- a/arch/arm/include/asm/arch-exynos/system.h +++ b/arch/arm/include/asm/arch-exynos/system.h @@ -75,6 +75,9 @@ struct exynos5_sysreg { /* Set program counter with the given value */ #define set_pc(x) __asm__ __volatile__ (mov pc, %0\n\t : : r(x)) +/* Branch to the given location */ +#define branch_bx(x) __asm__ __volatile__ (bx %0\n\t : : r(x)) + /* Read Main Id register */ #define mrc_midr(x) __asm__ __volatile__ \ (mrc p15, 0, %0, c0, c0, 0\n\t : =r(x) : ) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 07/11] Exynos542x: cache: Disable clean/evict push to external
L2 Auxiliary Control Register provides configuration and control options for the L2 memory system. Bit 3 of L2ACTLR stands for clean/evict push to external. Setting bit 3 disables clean/evict which is what this patch intends to do. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/soc.c | 9 + 1 file changed, 9 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index 8c7d7d8..7268b9b 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -45,6 +45,15 @@ static void exynos5_set_l2cache_params(void) CACHE_DATA_RAM_LATENCY; asm volatile(mcr p15, 1, %0, c9, c0, 2\n : : r(val)); + +#ifdef CONFIG_EXYNOS5420 + /* Read CP15 L2ACTLR value */ + asm volatile(mrc p15, 1, %0, c15, c0, 0 : =r (val)); + /* Disable clean/evict push to external */ + val |= (0x1 3); + /* Write new vlaue to L2ACTLR */ + asm volatile(mcr p15, 1, %0, c15, c0, 0 : : r (val)); +#endif } /* -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 10/11] Exynos542x: Make A7s boot with thumb-mode U-Boot on warm reset
On warm reset, all cores jump to the low_power_start function because iRAM data is retained and because while executing iROM code all cores find the jump flag 0x02020028 set. In low_power_start, cores check the reset status and if true they clear the jump flag and jump back to 0x0. The A7 cores do jump to 0x0 but consider following instructions as a Thumb instructions which in turn makes them loop inside the iROM code instead of jumping to power_down_core. This issue is fixed by replacing the mov pc instruction with a bx instruction which switches state along with the jump to make the execution unit consider the branch target as an ARM instruction. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v1: - Added Reviewed-by Tested-by. arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 3fbaaf3..e9e3cb7 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -125,7 +125,7 @@ static void low_power_start(void) reg_val = readl(EXYNOS5420_SPARE_BASE); if (reg_val != CPU_RST_FLAG_VAL) { writel(0x0, CONFIG_LOWPOWER_FLAG); - set_pc(0x0); + branch_bx(0x0); } reg_val = readl(CONFIG_PHY_IRAM_BASE + 0x4); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v5 5/7] Exynos5: Use clock_get_periph_rate generic API
Replacing SoC and peripheral specific function calls with generic clock_get_periph_rate calls to get the peripheral clocks. Also, removing dead code of peripheral and SoC specific function implementations which was used earlier for fetching peripheral clocks. This code is not being used anymore because of the introduction of generic clock_get_periph_rate function. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org --- Changes since v4: - Added Reviewed-by. Changes since v3: - Merged patches 5 and 6 of version 3 to fix build errors. Changes since v2: - No change. Changes since v1: - Separated exynos5_get_periph_rate fixes into another patch. arch/arm/cpu/armv7/exynos/clock.c | 278 ++ 1 file changed, 43 insertions(+), 235 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 78f784a..f19fb5c 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -689,27 +689,6 @@ static unsigned long exynos4x12_get_pwm_clk(void) return pclk; } -/* exynos5420: return pwm clock frequency */ -static unsigned long exynos5420_get_pwm_clk(void) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long pclk, sclk; - unsigned int ratio; - - /* -* CLK_DIV_PERIC0 -* PWM_RATIO [31:28] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio 28) 0xf; - sclk = get_pll_clk(MPLL); - - pclk = sclk / (ratio + 1); - - return pclk; -} - /* exynos4: return uart clock frequency */ static unsigned long exynos4_get_uart_clk(int dev_index) { @@ -802,100 +781,6 @@ static unsigned long exynos4x12_get_uart_clk(int dev_index) return uclk; } -/* exynos5: return uart clock frequency */ -static unsigned long exynos5_get_uart_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [3:0] -* UART1_SEL [7:4] -* UART2_SEL [8:11] -* UART3_SEL [12:15] -* UART4_SEL [16:19] -* UART5_SEL [23:20] -*/ - sel = readl(clk-src_peric0); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel == 0x7) - sclk = get_pll_clk(EPLL); - else if (sel == 0x8) - sclk = get_pll_clk(VPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [3:0] -* UART1_RATIO [7:4] -* UART2_RATIO [8:11] -* UART3_RATIO [12:15] -* UART4_RATIO [16:19] -* UART5_RATIO [23:20] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio (dev_index 2)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - -/* exynos5420: return uart clock frequency */ -static unsigned long exynos5420_get_uart_clk(int dev_index) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [6:4] -* UART1_SEL [10:8] -* UART2_SEL [14:12] -* UART3_SEL [18:16] -* generalised calculation as follows -* sel = (sel ((dev_index * 4) + 4)) mask; -*/ - sel = readl(clk-src_peric0); - sel = (sel ((dev_index * 4) + 4)) 0x7; - - if (sel == 0x3) - sclk = get_pll_clk(MPLL); - else if (sel == 0x6) - sclk = get_pll_clk(EPLL); - else if (sel == 0x7) - sclk = get_pll_clk(RPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [11:8] -* UART1_RATIO [15:12] -* UART2_RATIO [19:16] -* UART3_RATIO [23:20] -* generalised calculation as follows -* ratio = (ratio ((dev_index * 4) + 8)) mask; -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio ((dev_index * 4) + 8)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - static unsigned long exynos4_get_mmc_clk(int dev_index) { struct exynos4_clock *clk = @@ -945,94 +830,6 @@ static unsigned long exynos4_get_mmc_clk(int dev_index) return uclk; } -static unsigned long exynos5_get_mmc_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel, ratio, pre_ratio; - int shift = 0; - - sel = readl(clk-src_fsys); - sel = (sel (dev_index 2)) 0xf
[U-Boot] [PATCH v5 4/7] Exynos5: Fix exynos5_get_periph_rate calculations
exynos5_get_periph_rate function reads incorrect div for SDMMC2 3. It also reads prediv and does division only for SDMMC0 2 when actually various other peripherals need that. Adding changes to fix these mistakes in periph rate calculation. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v4: - No Change. Changes since v3: - Added Reviewed-by Tested-by. Changes since v2: - Added checks for negative values in exynos5_get_periph_rate. Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 16900cc..78f784a 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -362,8 +362,8 @@ static struct clk_bit_info *get_clk_bit_info(int peripheral) static unsigned long exynos5_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); - unsigned long sclk, sub_clk; - unsigned int src, div, sub_div; + unsigned long sclk, sub_clk = 0; + unsigned int src, div, sub_div = 0; struct exynos5_clock *clk = (struct exynos5_clock *)samsung_get_base_clock(); @@ -402,10 +402,13 @@ static unsigned long exynos5_get_periph_rate(int peripheral) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: + src = readl(clk-src_fsys); + div = readl(clk-div_fsys1); + break; case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: src = readl(clk-src_fsys); - div = readl(clk-div_fsys1); + div = readl(clk-div_fsys2); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -426,7 +429,8 @@ static unsigned long exynos5_get_periph_rate(int peripheral) return -1; }; - src = (src bit_info-src_bit) 0xf; + if (bit_info-src_bit = 0) + src = (src bit_info-src_bit) 0xf; switch (src) { case EXYNOS_SRC_MPLL: @@ -443,11 +447,12 @@ static unsigned long exynos5_get_periph_rate(int peripheral) } /* Ratio clock division for this peripheral */ - sub_div = (div bit_info-div_bit) 0xf; - sub_clk = sclk / (sub_div + 1); + if (bit_info-div_bit = 0) { + sub_div = (div bit_info-div_bit) 0xf; + sub_clk = sclk / (sub_div + 1); + } - /* Pre-ratio clock division for SDMMC0 and 2 */ - if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) { + if (bit_info-prediv_bit = 0) { div = (div bit_info-prediv_bit) 0xff; return sub_clk / (div + 1); } -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v5 7/7] Exynos: Clock: Cleanup soc_get_periph_rate
Cleaning up soc_get_periph_rate to make the logic easy to comprehend. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v4: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 76 +-- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 3884d4b..8724bc7 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -366,8 +366,8 @@ static struct clk_bit_info *get_clk_bit_info(int peripheral) static unsigned long exynos5_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); - unsigned long sclk, sub_clk = 0; - unsigned int src, div, sub_div = 0; + unsigned long sclk = 0; + unsigned int src = 0, div = 0, sub_div = 0; struct exynos5_clock *clk = (struct exynos5_clock *)samsung_get_base_clock(); @@ -389,30 +389,30 @@ static unsigned long exynos5_get_periph_rate(int peripheral) break; case PERIPH_ID_I2S0: src = readl(clk-src_mau); - div = readl(clk-div_mau); + div = sub_div = readl(clk-div_mau); case PERIPH_ID_SPI0: case PERIPH_ID_SPI1: src = readl(clk-src_peric1); - div = readl(clk-div_peric1); + div = sub_div = readl(clk-div_peric1); break; case PERIPH_ID_SPI2: src = readl(clk-src_peric1); - div = readl(clk-div_peric2); + div = sub_div = readl(clk-div_peric2); break; case PERIPH_ID_SPI3: case PERIPH_ID_SPI4: src = readl(clk-sclk_src_isp); - div = readl(clk-sclk_div_isp); + div = sub_div = readl(clk-sclk_div_isp); break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: src = readl(clk-src_fsys); - div = readl(clk-div_fsys1); + div = sub_div = readl(clk-div_fsys1); break; case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: src = readl(clk-src_fsys); - div = readl(clk-div_fsys2); + div = sub_div = readl(clk-div_fsys2); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -422,12 +422,10 @@ static unsigned long exynos5_get_periph_rate(int peripheral) case PERIPH_ID_I2C5: case PERIPH_ID_I2C6: case PERIPH_ID_I2C7: - sclk = exynos5_get_pll_clk(MPLL); - sub_div = ((readl(clk-div_top1) bit_info-div_bit) -bit_info-div_mask) + 1; - div = ((readl(clk-div_top0) bit_info-prediv_bit) -bit_info-prediv_mask) + 1; - return (sclk / sub_div) / div; + src = EXYNOS_SRC_MPLL; + div = readl(clk-div_top0); + sub_div = readl(clk-div_top1); + break; default: debug(%s: invalid peripheral %d, __func__, peripheral); return -1; @@ -446,29 +444,26 @@ static unsigned long exynos5_get_periph_rate(int peripheral) case EXYNOS_SRC_VPLL: sclk = exynos5_get_pll_clk(VPLL); break; - default: - return 0; } - /* Ratio clock division for this peripheral */ - if (bit_info-div_bit = 0) { - sub_div = (div bit_info-div_bit) bit_info-div_mask; - sub_clk = sclk / (sub_div + 1); - } + /* Clock divider ratio for this peripheral */ + if (bit_info-div_bit = 0) + div = (div bit_info-div_bit) bit_info-div_mask; - if (bit_info-prediv_bit = 0) { - div = (div bit_info-prediv_bit) bit_info-prediv_mask; - return sub_clk / (div + 1); - } + /* Clock pre-divider ratio for this peripheral */ + if (bit_info-prediv_bit = 0) + sub_div = (sub_div bit_info-prediv_bit) + bit_info-prediv_mask; - return sub_clk; + /* Calculate and return required clock rate */ + return (sclk / (div + 1)) / (sub_div + 1); } static unsigned long exynos542x_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); - unsigned long sclk, sub_clk = 0; - unsigned int src, div, sub_div = 0; + unsigned long sclk = 0; + unsigned int src = 0, div = 0, sub_div = 0; struct exynos5420_clock *clk = (struct exynos5420_clock *)samsung_get_base_clock(); @@ -516,10 +511,9 @@ static unsigned long exynos542x_get_periph_rate(int peripheral) case PERIPH_ID_I2C8: case PERIPH_ID_I2C9: case PERIPH_ID_I2C10: - sclk = exynos542x_get_pll_clk(MPLL); - sub_div
[U-Boot] [PATCH v5 6/7] Exynos: clock: change mask bits as per peripheral
We have assumed and kept mask bits for divider and pre-divider as 0xf and 0xff, respectively. But these mask bits change from one peripheral to another, and hence, need to be specified in accordance with the peripherals. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v4: - Isolated maskbit changes. Changes since v3: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 151 -- 1 file changed, 78 insertions(+), 73 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index f19fb5c..3884d4b 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -21,79 +21,83 @@ */ struct clk_bit_info { enum periph_id id; + int32_t src_mask; + int32_t div_mask; + int32_t prediv_mask; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* periph_id src_bit div_bit prediv_bit */ static struct clk_bit_info exynos5_bit_info[] = { - {PERIPH_ID_UART0, 0, 0, -1}, - {PERIPH_ID_UART1, 4, 4, -1}, - {PERIPH_ID_UART2, 8, 8, -1}, - {PERIPH_ID_UART3, 12, 12, -1}, - {PERIPH_ID_I2C0,-1, 24, 0}, - {PERIPH_ID_I2C1,-1, 24, 0}, - {PERIPH_ID_I2C2,-1, 24, 0}, - {PERIPH_ID_I2C3,-1, 24, 0}, - {PERIPH_ID_I2C4,-1, 24, 0}, - {PERIPH_ID_I2C5,-1, 24, 0}, - {PERIPH_ID_I2C6,-1, 24, 0}, - {PERIPH_ID_I2C7,-1, 24, 0}, - {PERIPH_ID_SPI0,16, 0, 8}, - {PERIPH_ID_SPI1,20, 16, 24}, - {PERIPH_ID_SPI2,24, 0, 8}, - {PERIPH_ID_SDMMC0, 0, 0, 8}, - {PERIPH_ID_SDMMC1, 4, 16, 24}, - {PERIPH_ID_SDMMC2, 8, 0, 8}, - {PERIPH_ID_SDMMC3, 12, 16, 24}, - {PERIPH_ID_I2S0,0, 0, 4}, - {PERIPH_ID_I2S1,4, 12, 16}, - {PERIPH_ID_SPI3,0, 0, 4}, - {PERIPH_ID_SPI4,4, 12, 16}, - {PERIPH_ID_SDMMC4, 16, 0, 8}, - {PERIPH_ID_PWM0,24, 0, -1}, - {PERIPH_ID_PWM1,24, 0, -1}, - {PERIPH_ID_PWM2,24, 0, -1}, - {PERIPH_ID_PWM3,24, 0, -1}, - {PERIPH_ID_PWM4,24, 0, -1}, - - {PERIPH_ID_NONE,-1, -1, -1}, + /* periph ids_mask d_mask p_mask s_bit d_bit p_bit */ + {PERIPH_ID_UART0, 0xf,0xf,-1, 0, 0, -1}, + {PERIPH_ID_UART1, 0xf,0xf,-1, 4, 4, -1}, + {PERIPH_ID_UART2, 0xf,0xf,-1, 8, 8, -1}, + {PERIPH_ID_UART3, 0xf,0xf,-1, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_SPI0,0xf,0xf,0xff, 16, 0, 8}, + {PERIPH_ID_SPI1,0xf,0xf,0xff, 20, 16, 24}, + {PERIPH_ID_SPI2,0xf,0xf,0xff, 24, 0, 8}, + {PERIPH_ID_SDMMC0, 0xf,0xf,0xff, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 0xf,0xf,0xff, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 0xf,0xf,0xff, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 0xf,0xf,0xff, 12, 16, 24}, + {PERIPH_ID_I2S0,0xf,0xf,0xff, 0, 0, 4}, + {PERIPH_ID_I2S1,0xf,0xf,0xff, 4, 12, 16}, + {PERIPH_ID_SPI3,0xf,0xf,0xff, 0, 0, 4}, + {PERIPH_ID_SPI4,0xf,0xf,0xff, 4, 12, 16}, + {PERIPH_ID_SDMMC4, 0xf,0xf,0xff, 16, 0, 8}, + {PERIPH_ID_PWM0,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM1,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM2,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM3,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM4,0xf,0xf,-1, 24, 0, -1}, + + {PERIPH_ID_NONE,-1, -1, -1, -1, -1, -1
[U-Boot] [PATCH v4 4/6] Exynos5: Fix exynos5_get_periph_rate calculations
exynos5_get_periph_rate function reads incorrect div for SDMMC2 3. It also reads prediv and does division only for SDMMC0 2 when actually various other peripherals need that. Adding changes to fix these mistakes in periph rate calculation. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - Added Reviewed-by Tested-by. Changes since v2: - Added checks for negative values in exynos5_get_periph_rate. Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 16900cc..78f784a 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -362,8 +362,8 @@ static struct clk_bit_info *get_clk_bit_info(int peripheral) static unsigned long exynos5_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); - unsigned long sclk, sub_clk; - unsigned int src, div, sub_div; + unsigned long sclk, sub_clk = 0; + unsigned int src, div, sub_div = 0; struct exynos5_clock *clk = (struct exynos5_clock *)samsung_get_base_clock(); @@ -402,10 +402,13 @@ static unsigned long exynos5_get_periph_rate(int peripheral) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: + src = readl(clk-src_fsys); + div = readl(clk-div_fsys1); + break; case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: src = readl(clk-src_fsys); - div = readl(clk-div_fsys1); + div = readl(clk-div_fsys2); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -426,7 +429,8 @@ static unsigned long exynos5_get_periph_rate(int peripheral) return -1; }; - src = (src bit_info-src_bit) 0xf; + if (bit_info-src_bit = 0) + src = (src bit_info-src_bit) 0xf; switch (src) { case EXYNOS_SRC_MPLL: @@ -443,11 +447,12 @@ static unsigned long exynos5_get_periph_rate(int peripheral) } /* Ratio clock division for this peripheral */ - sub_div = (div bit_info-div_bit) 0xf; - sub_clk = sclk / (sub_div + 1); + if (bit_info-div_bit = 0) { + sub_div = (div bit_info-div_bit) 0xf; + sub_clk = sclk / (sub_div + 1); + } - /* Pre-ratio clock division for SDMMC0 and 2 */ - if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) { + if (bit_info-prediv_bit = 0) { div = (div bit_info-prediv_bit) 0xff; return sub_clk / (div + 1); } -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 3/6] Exynos542x: Add and enable get_periph_rate support
We planned to fetch peripheral rate through one generic API per peripheral. These generic peripheral functions are in turn expected to fetch apt values from a function refactored as per SoC versions. This patch adds support for fetching peripheral rates for Exynos5420 and Exynos5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v3: - Added a case for SPLL in exynos542x_get_periph_rate. - Changed EXYNOS542x - EXYNOS542X. Changes since v2: - Fixed enum and exynos542x_get_periph_rate switch. - Added checks for negative values in exynos542x_get_periph_rate. Changes since v1: - Changes suuport - support in commit message. - Removed position change of exynos5420_get_pll_clk. - Removed #ifdef. arch/arm/cpu/armv7/exynos/clock.c | 153 +++-- arch/arm/include/asm/arch-exynos/clk.h | 4 + 2 files changed, 150 insertions(+), 7 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 5dc9ed2..16900cc 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -27,7 +27,7 @@ struct clk_bit_info { }; /* periph_id src_bit div_bit prediv_bit */ -static struct clk_bit_info clk_bit_info[] = { +static struct clk_bit_info exynos5_bit_info[] = { {PERIPH_ID_UART0, 0, 0, -1}, {PERIPH_ID_UART1, 4, 4, -1}, {PERIPH_ID_UART2, 8, 8, -1}, @@ -61,6 +61,41 @@ static struct clk_bit_info clk_bit_info[] = { {PERIPH_ID_NONE,-1, -1, -1}, }; +static struct clk_bit_info exynos542x_bit_info[] = { + {PERIPH_ID_UART0, 4, 8, -1}, + {PERIPH_ID_UART1, 8, 12, -1}, + {PERIPH_ID_UART2, 12, 16, -1}, + {PERIPH_ID_UART3, 16, 20, -1}, + {PERIPH_ID_I2C0,-1, 8, -1}, + {PERIPH_ID_I2C1,-1, 8, -1}, + {PERIPH_ID_I2C2,-1, 8, -1}, + {PERIPH_ID_I2C3,-1, 8, -1}, + {PERIPH_ID_I2C4,-1, 8, -1}, + {PERIPH_ID_I2C5,-1, 8, -1}, + {PERIPH_ID_I2C6,-1, 8, -1}, + {PERIPH_ID_I2C7,-1, 8, -1}, + {PERIPH_ID_SPI0,20, 20, 8}, + {PERIPH_ID_SPI1,24, 24, 16}, + {PERIPH_ID_SPI2,28, 28, 24}, + {PERIPH_ID_SDMMC0, 8, 0, -1}, + {PERIPH_ID_SDMMC1, 12, 10, -1}, + {PERIPH_ID_SDMMC2, 16, 20, -1}, + {PERIPH_ID_I2C8,-1, 8, -1}, + {PERIPH_ID_I2C9,-1, 8, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SPI3,12, 16, 0}, + {PERIPH_ID_SPI4,16, 20, 8}, + {PERIPH_ID_PWM0,24, 28, -1}, + {PERIPH_ID_PWM1,24, 28, -1}, + {PERIPH_ID_PWM2,24, 28, -1}, + {PERIPH_ID_PWM3,24, 28, -1}, + {PERIPH_ID_PWM4,24, 28, -1}, + {PERIPH_ID_I2C10, -1, 8, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, +}; + /* Epll Clock division values to achive different frequency output */ static struct set_epll_con_val exynos5_epll_div[] = { { 19200, 0, 48, 3, 1, 0 }, @@ -306,16 +341,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg) static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; + struct clk_bit_info *info; + + if (proid_is_exynos5420() || proid_is_exynos5800()) + info = exynos542x_bit_info; + else + info = exynos5_bit_info; - for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { - if (clk_bit_info[i].id == peripheral) + for (i = 0; info[i].id != PERIPH_ID_NONE; i++) { + if (info[i].id == peripheral) break; } - if (clk_bit_info[i].id == PERIPH_ID_NONE) + if (info[i].id == PERIPH_ID_NONE) debug(ERROR: Peripheral ID %d not found\n, peripheral); - return clk_bit_info[i]; + return info[i]; } static unsigned long exynos5_get_periph_rate(int peripheral) @@ -414,12 +455,110 @@ static unsigned long exynos5_get_periph_rate(int peripheral) return sub_clk; } +static unsigned long exynos542x_get_periph_rate(int peripheral) +{ + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); + unsigned long sclk, sub_clk = 0; + unsigned int src, div, sub_div = 0; + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case
[U-Boot] [PATCH v4 2/6] Exynos542x: Move exynos5420_get_pll_clk up and rename
Moving exynos5420_get_pll_clk function definition up in the code to keep it together with rest of SoC_get_pll_clk functions. This makes code more legible and also removes the need of declaration when called before the position of definition in code. Also, renaming exynos5420_get_pll_clk to exynos542x_get_pll_clk because it is being used for both Exynos 5420 and 5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - Added Reviewed-by Tested-by. Changes since v2: - Changed exynos5420 - exynos542x in line 33. Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 82 +++ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 6f20c81..5dc9ed2 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -263,6 +263,46 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +/* exynos542x: return pll clock frequency */ +static unsigned long exynos542x_get_pll_clk(int pllreg) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(clk-apll_con0); + break; + case MPLL: + r = readl(clk-mpll_con0); + break; + case EPLL: + r = readl(clk-epll_con0); + k = readl(clk-epll_con1); + break; + case VPLL: + r = readl(clk-vpll_con0); + k = readl(clk-vpll_con1); + break; + case BPLL: + r = readl(clk-bpll_con0); + break; + case RPLL: + r = readl(clk-rpll_con0); + k = readl(clk-rpll_con1); + break; + case SPLL: + r = readl(clk-spll_con0); + break; + default: + printf(Unsupported PLL (%d)\n, pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; @@ -382,46 +422,6 @@ unsigned long clock_get_periph_rate(int peripheral) return 0; } -/* exynos5420: return pll clock frequency */ -static unsigned long exynos5420_get_pll_clk(int pllreg) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long r, k = 0; - - switch (pllreg) { - case APLL: - r = readl(clk-apll_con0); - break; - case MPLL: - r = readl(clk-mpll_con0); - break; - case EPLL: - r = readl(clk-epll_con0); - k = readl(clk-epll_con1); - break; - case VPLL: - r = readl(clk-vpll_con0); - k = readl(clk-vpll_con1); - break; - case BPLL: - r = readl(clk-bpll_con0); - break; - case RPLL: - r = readl(clk-rpll_con0); - k = readl(clk-rpll_con1); - break; - case SPLL: - r = readl(clk-spll_con0); - break; - default: - printf(Unsupported PLL (%d)\n, pllreg); - return 0; - } - - return exynos_get_pll_clk(pllreg, r, k); -} - /* exynos4: return ARM clock frequency */ static unsigned long exynos4_get_arm_clk(void) { @@ -1603,7 +1603,7 @@ unsigned long get_pll_clk(int pllreg) { if (cpu_is_exynos5()) { if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_pll_clk(pllreg); + return exynos542x_get_pll_clk(pllreg); return exynos5_get_pll_clk(pllreg); } else { if (proid_is_exynos4412()) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 1/6] Exynos5: Fix compiler warnings due to clock_get_periph_rate
Apparently, members of clk_bit_info array do not map correctly to the members of enum periph_id. This mapping got broken after we changed periph_id(s) to reflect interrupt number instead of their position in a sequence. This patch intends to fix above mentioned issue. Signed-off-by: Akshay Saraswat aksha...@samsung.com Reviewed-by: Simon Glass s...@chromium.org Tested-by: Simon Glass s...@chromium.org --- Changes since v3: - Added Reviewed-by Tested-by. Changes since v2: - Added debug message for unknown periph IDs. Changes since v1: - Removed exynos5_bit_info array name. arch/arm/cpu/armv7/exynos/clock.c | 80 --- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index b31c13b..6f20c81 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -20,42 +20,45 @@ * positions of the peripheral clocks of the src and div registers */ struct clk_bit_info { + enum periph_id id; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* src_bit div_bit prediv_bit */ +/* periph_id src_bit div_bit prediv_bit */ static struct clk_bit_info clk_bit_info[] = { - {0, 0, -1}, - {4, 4, -1}, - {8, 8, -1}, - {12,12, -1}, - {0, 0, 8}, - {4, 16, 24}, - {8, 0, 8}, - {12,16, 24}, - {-1,-1, -1}, - {16,0, 8}, - {20,16, 24}, - {24,0, 8}, - {0, 0, 4}, - {4, 12, 16}, - {-1,-1, -1}, - {-1,-1, -1}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, + {PERIPH_ID_UART0, 0, 0, -1}, + {PERIPH_ID_UART1, 4, 4, -1}, + {PERIPH_ID_UART2, 8, 8, -1}, + {PERIPH_ID_UART3, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 24, 0}, + {PERIPH_ID_SPI0,16, 0, 8}, + {PERIPH_ID_SPI1,20, 16, 24}, + {PERIPH_ID_SPI2,24, 0, 8}, + {PERIPH_ID_SDMMC0, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 12, 16, 24}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SPI3,0, 0, 4}, + {PERIPH_ID_SPI4,4, 12, 16}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 0, -1}, + {PERIPH_ID_PWM1,24, 0, -1}, + {PERIPH_ID_PWM2,24, 0, -1}, + {PERIPH_ID_PWM3,24, 0, -1}, + {PERIPH_ID_PWM4,24, 0, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, }; /* Epll Clock division values to achive different frequency output */ @@ -260,9 +263,24 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +static struct clk_bit_info *get_clk_bit_info(int peripheral) +{ + int i; + + for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { + if (clk_bit_info[i].id == peripheral) + break; + } + + if (clk_bit_info[i].id == PERIPH_ID_NONE) + debug(ERROR: Peripheral ID %d not found\n, peripheral); + + return clk_bit_info[i]; +} + static unsigned long exynos5_get_periph_rate(int peripheral) { - struct clk_bit_info *bit_info = clk_bit_info[peripheral]; + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); unsigned long sclk, sub_clk; unsigned int src, div, sub_div; struct exynos5_clock *clk = -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 0/6] Exynos5: Fix warnings and enrich clock_get_periph_rate
This patch series does following changes - 1. Removing compiler warnings for clock_get_periph_rate. 2. Adding and enabling support for Exynos542x in clock_get_periph_rate. 3. Replacing peripheral specific function calls with clock_get_periph_rate. 4. Remove code from clocks file which became useless due to introduction of clock_get_periph_rate. Changes since v3: - Added Reviewed-by Tested-by in patches 1, 2 and 4. - Patch-3: Handled SPLL case in exynos542x_get_periph_rate. - Patch-3: Changed EXYNOS542x - EXYNOS542X in pll_src_bit enum. - Merged pathces 5 and 6 of version 3. - Patch-6: New patch for dealing with variety of mask bits. Changes since v2: - Patch-1: Added debug message for unknown periph IDs. - Patch-2: Changed exynos5420 - exynos542x in comment. - Patch-3: Fixed enum and soc_get_periph_rate switch. - Patch-3: Added checks for negative values in soc_get_periph_rate. - Patch-4: Added checks for negative values in soc_get_periph_rate. Changes since v1: - Added 2 new patches. Akshay Saraswat (6): Exynos5: Fix compiler warnings due to clock_get_periph_rate Exynos542x: Move exynos5420_get_pll_clk up and rename Exynos542x: Add and enable get_periph_rate support Exynos5: Fix exynos5_get_periph_rate calculations Exynos5: Use clock_get_periph_rate generic API Exynos: clock: change mask bits as per peripheral arch/arm/cpu/armv7/exynos/clock.c | 646 - arch/arm/include/asm/arch-exynos/clk.h | 4 + 2 files changed, 313 insertions(+), 337 deletions(-) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 6/6] Exynos: clock: change mask bits as per peripheral
We have assumed and kept mask bits for divider and pre-divider as 0xf and 0xff, respectively. But these mask bits change from one peripheral to another, and hence, need to be specified in accordance with the peripherals. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v3: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 268 +++--- 1 file changed, 135 insertions(+), 133 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index f19fb5c..4feb5ba 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -21,79 +21,83 @@ */ struct clk_bit_info { enum periph_id id; + int32_t src_mask; + int32_t div_mask; + int32_t prediv_mask; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* periph_id src_bit div_bit prediv_bit */ static struct clk_bit_info exynos5_bit_info[] = { - {PERIPH_ID_UART0, 0, 0, -1}, - {PERIPH_ID_UART1, 4, 4, -1}, - {PERIPH_ID_UART2, 8, 8, -1}, - {PERIPH_ID_UART3, 12, 12, -1}, - {PERIPH_ID_I2C0,-1, 24, 0}, - {PERIPH_ID_I2C1,-1, 24, 0}, - {PERIPH_ID_I2C2,-1, 24, 0}, - {PERIPH_ID_I2C3,-1, 24, 0}, - {PERIPH_ID_I2C4,-1, 24, 0}, - {PERIPH_ID_I2C5,-1, 24, 0}, - {PERIPH_ID_I2C6,-1, 24, 0}, - {PERIPH_ID_I2C7,-1, 24, 0}, - {PERIPH_ID_SPI0,16, 0, 8}, - {PERIPH_ID_SPI1,20, 16, 24}, - {PERIPH_ID_SPI2,24, 0, 8}, - {PERIPH_ID_SDMMC0, 0, 0, 8}, - {PERIPH_ID_SDMMC1, 4, 16, 24}, - {PERIPH_ID_SDMMC2, 8, 0, 8}, - {PERIPH_ID_SDMMC3, 12, 16, 24}, - {PERIPH_ID_I2S0,0, 0, 4}, - {PERIPH_ID_I2S1,4, 12, 16}, - {PERIPH_ID_SPI3,0, 0, 4}, - {PERIPH_ID_SPI4,4, 12, 16}, - {PERIPH_ID_SDMMC4, 16, 0, 8}, - {PERIPH_ID_PWM0,24, 0, -1}, - {PERIPH_ID_PWM1,24, 0, -1}, - {PERIPH_ID_PWM2,24, 0, -1}, - {PERIPH_ID_PWM3,24, 0, -1}, - {PERIPH_ID_PWM4,24, 0, -1}, - - {PERIPH_ID_NONE,-1, -1, -1}, + /* periph ids_mask d_mask p_mask s_bit d_bit p_bit */ + {PERIPH_ID_UART0, 0xf,0xf,-1, 0, 0, -1}, + {PERIPH_ID_UART1, 0xf,0xf,-1, 4, 4, -1}, + {PERIPH_ID_UART2, 0xf,0xf,-1, 8, 8, -1}, + {PERIPH_ID_UART3, 0xf,0xf,-1, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 0x7,0x7,-1, 24, 0}, + {PERIPH_ID_SPI0,0xf,0xf,0xff, 16, 0, 8}, + {PERIPH_ID_SPI1,0xf,0xf,0xff, 20, 16, 24}, + {PERIPH_ID_SPI2,0xf,0xf,0xff, 24, 0, 8}, + {PERIPH_ID_SDMMC0, 0xf,0xf,0xff, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 0xf,0xf,0xff, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 0xf,0xf,0xff, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 0xf,0xf,0xff, 12, 16, 24}, + {PERIPH_ID_I2S0,0xf,0xf,0xff, 0, 0, 4}, + {PERIPH_ID_I2S1,0xf,0xf,0xff, 4, 12, 16}, + {PERIPH_ID_SPI3,0xf,0xf,0xff, 0, 0, 4}, + {PERIPH_ID_SPI4,0xf,0xf,0xff, 4, 12, 16}, + {PERIPH_ID_SDMMC4, 0xf,0xf,0xff, 16, 0, 8}, + {PERIPH_ID_PWM0,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM1,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM2,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM3,0xf,0xf,-1, 24, 0, -1}, + {PERIPH_ID_PWM4,0xf,0xf,-1, 24, 0, -1}, + + {PERIPH_ID_NONE,-1, -1, -1, -1, -1, -1}, }; static struct clk_bit_info exynos542x_bit_info
[U-Boot] [PATCH v4 5/6] Exynos5: Use clock_get_periph_rate generic API
Replacing SoC and peripheral specific function calls with generic clock_get_periph_rate calls to get the peripheral clocks. Also, removing dead code of peripheral and SoC specific function implementations which was used earlier for fetching peripheral clocks. This code is not being used anymore because of the introduction of generic clock_get_periph_rate function. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v3: - Merged patches 5 and 6 of version 3 to fix build errors. Changes since v2: - No change. Changes since v1: - Separated exynos5_get_periph_rate fixes into another patch. arch/arm/cpu/armv7/exynos/clock.c | 278 ++ 1 file changed, 43 insertions(+), 235 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 78f784a..f19fb5c 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -689,27 +689,6 @@ static unsigned long exynos4x12_get_pwm_clk(void) return pclk; } -/* exynos5420: return pwm clock frequency */ -static unsigned long exynos5420_get_pwm_clk(void) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long pclk, sclk; - unsigned int ratio; - - /* -* CLK_DIV_PERIC0 -* PWM_RATIO [31:28] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio 28) 0xf; - sclk = get_pll_clk(MPLL); - - pclk = sclk / (ratio + 1); - - return pclk; -} - /* exynos4: return uart clock frequency */ static unsigned long exynos4_get_uart_clk(int dev_index) { @@ -802,100 +781,6 @@ static unsigned long exynos4x12_get_uart_clk(int dev_index) return uclk; } -/* exynos5: return uart clock frequency */ -static unsigned long exynos5_get_uart_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [3:0] -* UART1_SEL [7:4] -* UART2_SEL [8:11] -* UART3_SEL [12:15] -* UART4_SEL [16:19] -* UART5_SEL [23:20] -*/ - sel = readl(clk-src_peric0); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel == 0x7) - sclk = get_pll_clk(EPLL); - else if (sel == 0x8) - sclk = get_pll_clk(VPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [3:0] -* UART1_RATIO [7:4] -* UART2_RATIO [8:11] -* UART3_RATIO [12:15] -* UART4_RATIO [16:19] -* UART5_RATIO [23:20] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio (dev_index 2)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - -/* exynos5420: return uart clock frequency */ -static unsigned long exynos5420_get_uart_clk(int dev_index) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [6:4] -* UART1_SEL [10:8] -* UART2_SEL [14:12] -* UART3_SEL [18:16] -* generalised calculation as follows -* sel = (sel ((dev_index * 4) + 4)) mask; -*/ - sel = readl(clk-src_peric0); - sel = (sel ((dev_index * 4) + 4)) 0x7; - - if (sel == 0x3) - sclk = get_pll_clk(MPLL); - else if (sel == 0x6) - sclk = get_pll_clk(EPLL); - else if (sel == 0x7) - sclk = get_pll_clk(RPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [11:8] -* UART1_RATIO [15:12] -* UART2_RATIO [19:16] -* UART3_RATIO [23:20] -* generalised calculation as follows -* ratio = (ratio ((dev_index * 4) + 8)) mask; -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio ((dev_index * 4) + 8)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - static unsigned long exynos4_get_mmc_clk(int dev_index) { struct exynos4_clock *clk = @@ -945,94 +830,6 @@ static unsigned long exynos4_get_mmc_clk(int dev_index) return uclk; } -static unsigned long exynos5_get_mmc_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel, ratio, pre_ratio; - int shift = 0; - - sel = readl(clk-src_fsys); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel
Re: [U-Boot] [PATCH v3 3/6] Exynos542x: Add and enable get_periph_rate support
Hi, Hi, All. On 01/28/2015 02:55 PM, Joonyoung Shim wrote: Hi Simon, On 01/28/2015 02:15 PM, Simon Glass wrote: Hi Joonyoung, On 27 January 2015 at 22:12, Joonyoung Shim jy0922.s...@samsung.com wrote: Hi Simon, On 01/28/2015 02:01 PM, Simon Glass wrote: Hi Joonyoung, On 27 January 2015 at 21:46, Joonyoung Shim jy0922.s...@samsung.com wrote: Hi Simon, On 01/28/2015 01:09 PM, Simon Glass wrote: Hi, On 15 January 2015 at 23:09, Joonyoung Shim jy0922.s...@samsung.com wrote: Hi, On 01/16/2015 02:48 PM, Akshay Saraswat wrote: We planned to fetch peripheral rate through one generic API per peripheral. These generic peripheral functions are in turn expected to fetch apt values from a function refactored as per SoC versions. This patch adds support for fetching peripheral rates for Exynos5420 and Exynos5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - Fixed enum and exynos542x_get_periph_rate switch. - Added checks for negative values in exynos542x_get_periph_rate. Changes since v1: - Changes suuport - support in commit message. - Removed position change of exynos5420_get_pll_clk. - Removed #ifdef. arch/arm/cpu/armv7/exynos/clock.c | 151 +++-- arch/arm/include/asm/arch-exynos/clk.h | 3 + 2 files changed, 147 insertions(+), 7 deletions(-) What else needs to be done to get this applied, please? As i said, current this patch has some problem like mask bits, so eMMC doesn't work normally. diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 5dc9ed2..ee6c13b 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -27,7 +27,7 @@ struct clk_bit_info { }; /* periph_id src_bit div_bit prediv_bit */ -static struct clk_bit_info clk_bit_info[] = { +static struct clk_bit_info exynos5_bit_info[] = { {PERIPH_ID_UART0, 0, 0, -1}, {PERIPH_ID_UART1, 4, 4, -1}, {PERIPH_ID_UART2, 8, 8, -1}, @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = { {PERIPH_ID_NONE,-1, -1, -1}, }; +static struct clk_bit_info exynos542x_bit_info[] = { + {PERIPH_ID_UART0, 4, 8, -1}, + {PERIPH_ID_UART1, 8, 12, -1}, + {PERIPH_ID_UART2, 12, 16, -1}, + {PERIPH_ID_UART3, 16, 20, -1}, + {PERIPH_ID_I2C0,-1, 8, -1}, + {PERIPH_ID_I2C1,-1, 8, -1}, + {PERIPH_ID_I2C2,-1, 8, -1}, + {PERIPH_ID_I2C3,-1, 8, -1}, + {PERIPH_ID_I2C4,-1, 8, -1}, + {PERIPH_ID_I2C5,-1, 8, -1}, + {PERIPH_ID_I2C6,-1, 8, -1}, + {PERIPH_ID_I2C7,-1, 8, -1}, + {PERIPH_ID_SPI0,20, 20, 8}, + {PERIPH_ID_SPI1,24, 24, 16}, + {PERIPH_ID_SPI2,28, 28, 24}, + {PERIPH_ID_SDMMC0, 0, 0, -1}, + {PERIPH_ID_SDMMC1, 4, 10, -1}, + {PERIPH_ID_SDMMC2, 8, 20, -1}, + {PERIPH_ID_I2C8,-1, 8, -1}, + {PERIPH_ID_I2C9,-1, 8, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SPI3,12, 16, 0}, + {PERIPH_ID_SPI4,16, 20, 8}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 28, -1}, + {PERIPH_ID_PWM1,24, 28, -1}, + {PERIPH_ID_PWM2,24, 28, -1}, + {PERIPH_ID_PWM3,24, 28, -1}, + {PERIPH_ID_PWM4,24, 28, -1}, + {PERIPH_ID_I2C10, -1, 8, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, +}; + /* Epll Clock division values to achive different frequency output */ static struct set_epll_con_val exynos5_epll_div[] = { { 19200, 0, 48, 3, 1, 0 }, @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg) static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; + struct clk_bit_info *info; - for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { - if (clk_bit_info[i].id == peripheral) + if (proid_is_exynos5420() || proid_is_exynos5800()) + info = exynos542x_bit_info; + else + info = exynos5_bit_info; + + for (i = 0; info[i].id != PERIPH_ID_NONE; i++) { + if (info[i].id == peripheral) break; } - if (clk_bit_info[i].id == PERIPH_ID_NONE) + if (info[i].id == PERIPH_ID_NONE) debug(ERROR: Peripheral ID %d not found\n, peripheral); - return clk_bit_info[i]; + return info[i]; } static unsigned long
Re: [U-Boot] [PATCH 00/11] Add support for booting multiple cores
Hi Kevin, Akshay Saraswat aksha...@samsung.com writes: This patch series introduces changes for booting secondary CPUs on Exynos5420 and Exynos5800. Thanks for this series. I think this should help get the odroid-xu3 behave better with the mainline linux kernel (assuming I can get it working with mainline u-boot/SPL.) Are you testing this on mainline u-boot? Yes, this series is based on mainline u-boot-samsung git. Can you describe what platforms you've tested this on and whether or not those platforms are using secure firmware? I have tested these patches on Chromebook-2 11 and 13 inch having Exynos 5420 and Exynos 5800 respectively. Not sure of how Odroid-xu3 will behave with this set because I don't have that platform and never tested it. Kevin Regards, Akshay Saraswat ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 0/6] Exynos5: Fix warnings and enrich clock_get_periph_rate
This patch series does following changes - 1. Removing compiler warnings for clock_get_periph_rate. 2. Adding and enabling support for Exynos542x in clock_get_periph_rate. 3. Replacing peripheral specific function calls with clock_get_periph_rate. 4. Remove code from clocks file which became useless due to introduction of clock_get_periph_rate. Changes since v2: - Patch-1: Added debug message for unknown periph IDs. - Patch-2: Changed exynos5420 - exynos542x in comment. - Patch-3: Fixed enum and soc_get_periph_rate switch. - Patch-3: Added checks for negative values in soc_get_periph_rate. - Patch-4: Added checks for negative values in soc_get_periph_rate. Changes since v1: - Added 2 new patches. Akshay Saraswat (6): Exynos5: Fix compiler warnings due to clock_get_periph_rate Exynos542x: Move exynos5420_get_pll_clk up and rename Exynos542x: Add and enable get_periph_rate support Exynos5: Fix exynos5_get_periph_rate calculations Exynos5: Use clock_get_periph_rate generic API Exynos5: Remove dead code for fetching clocks arch/arm/cpu/armv7/exynos/clock.c | 584 - arch/arm/include/asm/arch-exynos/clk.h | 3 + 2 files changed, 279 insertions(+), 308 deletions(-) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 1/6] Exynos5: Fix compiler warnings due to clock_get_periph_rate
Apparently, members of clk_bit_info array do not map correctly to the members of enum periph_id. This mapping got broken after we changed periph_id(s) to reflect interrupt number instead of their position in a sequence. This patch intends to fix above mentioned issue. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - Added debug message for unknown periph IDs. Changes since v1: - Removed exynos5_bit_info array name. arch/arm/cpu/armv7/exynos/clock.c | 80 --- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index b31c13b..6f20c81 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -20,42 +20,45 @@ * positions of the peripheral clocks of the src and div registers */ struct clk_bit_info { + enum periph_id id; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* src_bit div_bit prediv_bit */ +/* periph_id src_bit div_bit prediv_bit */ static struct clk_bit_info clk_bit_info[] = { - {0, 0, -1}, - {4, 4, -1}, - {8, 8, -1}, - {12,12, -1}, - {0, 0, 8}, - {4, 16, 24}, - {8, 0, 8}, - {12,16, 24}, - {-1,-1, -1}, - {16,0, 8}, - {20,16, 24}, - {24,0, 8}, - {0, 0, 4}, - {4, 12, 16}, - {-1,-1, -1}, - {-1,-1, -1}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, + {PERIPH_ID_UART0, 0, 0, -1}, + {PERIPH_ID_UART1, 4, 4, -1}, + {PERIPH_ID_UART2, 8, 8, -1}, + {PERIPH_ID_UART3, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 24, 0}, + {PERIPH_ID_SPI0,16, 0, 8}, + {PERIPH_ID_SPI1,20, 16, 24}, + {PERIPH_ID_SPI2,24, 0, 8}, + {PERIPH_ID_SDMMC0, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 12, 16, 24}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SPI3,0, 0, 4}, + {PERIPH_ID_SPI4,4, 12, 16}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 0, -1}, + {PERIPH_ID_PWM1,24, 0, -1}, + {PERIPH_ID_PWM2,24, 0, -1}, + {PERIPH_ID_PWM3,24, 0, -1}, + {PERIPH_ID_PWM4,24, 0, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, }; /* Epll Clock division values to achive different frequency output */ @@ -260,9 +263,24 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +static struct clk_bit_info *get_clk_bit_info(int peripheral) +{ + int i; + + for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { + if (clk_bit_info[i].id == peripheral) + break; + } + + if (clk_bit_info[i].id == PERIPH_ID_NONE) + debug(ERROR: Peripheral ID %d not found\n, peripheral); + + return clk_bit_info[i]; +} + static unsigned long exynos5_get_periph_rate(int peripheral) { - struct clk_bit_info *bit_info = clk_bit_info[peripheral]; + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); unsigned long sclk, sub_clk; unsigned int src, div, sub_div; struct exynos5_clock *clk = -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 4/6] Exynos5: Fix exynos5_get_periph_rate calculations
exynos5_get_periph_rate function reads incorrect div for SDMMC2 3. It also reads prediv and does division only for SDMMC0 2 when actually various other peripherals need that. Adding changes to fix these mistakes in periph rate calculation. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - Added checks for negative values in exynos5_get_periph_rate. Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index ee6c13b..2cd0778 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -363,8 +363,8 @@ static struct clk_bit_info *get_clk_bit_info(int peripheral) static unsigned long exynos5_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); - unsigned long sclk, sub_clk; - unsigned int src, div, sub_div; + unsigned long sclk, sub_clk = 0; + unsigned int src, div, sub_div = 0; struct exynos5_clock *clk = (struct exynos5_clock *)samsung_get_base_clock(); @@ -403,10 +403,13 @@ static unsigned long exynos5_get_periph_rate(int peripheral) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: + src = readl(clk-src_fsys); + div = readl(clk-div_fsys1); + break; case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: src = readl(clk-src_fsys); - div = readl(clk-div_fsys1); + div = readl(clk-div_fsys2); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -427,7 +430,8 @@ static unsigned long exynos5_get_periph_rate(int peripheral) return -1; }; - src = (src bit_info-src_bit) 0xf; + if (bit_info-src_bit = 0) + src = (src bit_info-src_bit) 0xf; switch (src) { case EXYNOS_SRC_MPLL: @@ -444,11 +448,12 @@ static unsigned long exynos5_get_periph_rate(int peripheral) } /* Ratio clock division for this peripheral */ - sub_div = (div bit_info-div_bit) 0xf; - sub_clk = sclk / (sub_div + 1); + if (bit_info-div_bit = 0) { + sub_div = (div bit_info-div_bit) 0xf; + sub_clk = sclk / (sub_div + 1); + } - /* Pre-ratio clock division for SDMMC0 and 2 */ - if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) { + if (bit_info-prediv_bit = 0) { div = (div bit_info-prediv_bit) 0xff; return sub_clk / (div + 1); } -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 2/6] Exynos542x: Move exynos5420_get_pll_clk up and rename
Moving exynos5420_get_pll_clk function definition up in the code to keep it together with rest of SoC_get_pll_clk functions. This makes code more legible and also removes the need of declaration when called before the position of definition in code. Also, renaming exynos5420_get_pll_clk to exynos542x_get_pll_clk because it is being used for both Exynos 5420 and 5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - Changed exynos5420 - exynos542x in line 33. Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 82 +++ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 6f20c81..5dc9ed2 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -263,6 +263,46 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +/* exynos542x: return pll clock frequency */ +static unsigned long exynos542x_get_pll_clk(int pllreg) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(clk-apll_con0); + break; + case MPLL: + r = readl(clk-mpll_con0); + break; + case EPLL: + r = readl(clk-epll_con0); + k = readl(clk-epll_con1); + break; + case VPLL: + r = readl(clk-vpll_con0); + k = readl(clk-vpll_con1); + break; + case BPLL: + r = readl(clk-bpll_con0); + break; + case RPLL: + r = readl(clk-rpll_con0); + k = readl(clk-rpll_con1); + break; + case SPLL: + r = readl(clk-spll_con0); + break; + default: + printf(Unsupported PLL (%d)\n, pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; @@ -382,46 +422,6 @@ unsigned long clock_get_periph_rate(int peripheral) return 0; } -/* exynos5420: return pll clock frequency */ -static unsigned long exynos5420_get_pll_clk(int pllreg) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long r, k = 0; - - switch (pllreg) { - case APLL: - r = readl(clk-apll_con0); - break; - case MPLL: - r = readl(clk-mpll_con0); - break; - case EPLL: - r = readl(clk-epll_con0); - k = readl(clk-epll_con1); - break; - case VPLL: - r = readl(clk-vpll_con0); - k = readl(clk-vpll_con1); - break; - case BPLL: - r = readl(clk-bpll_con0); - break; - case RPLL: - r = readl(clk-rpll_con0); - k = readl(clk-rpll_con1); - break; - case SPLL: - r = readl(clk-spll_con0); - break; - default: - printf(Unsupported PLL (%d)\n, pllreg); - return 0; - } - - return exynos_get_pll_clk(pllreg, r, k); -} - /* exynos4: return ARM clock frequency */ static unsigned long exynos4_get_arm_clk(void) { @@ -1603,7 +1603,7 @@ unsigned long get_pll_clk(int pllreg) { if (cpu_is_exynos5()) { if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_pll_clk(pllreg); + return exynos542x_get_pll_clk(pllreg); return exynos5_get_pll_clk(pllreg); } else { if (proid_is_exynos4412()) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 3/6] Exynos542x: Add and enable get_periph_rate support
We planned to fetch peripheral rate through one generic API per peripheral. These generic peripheral functions are in turn expected to fetch apt values from a function refactored as per SoC versions. This patch adds support for fetching peripheral rates for Exynos5420 and Exynos5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - Fixed enum and exynos542x_get_periph_rate switch. - Added checks for negative values in exynos542x_get_periph_rate. Changes since v1: - Changes suuport - support in commit message. - Removed position change of exynos5420_get_pll_clk. - Removed #ifdef. arch/arm/cpu/armv7/exynos/clock.c | 151 +++-- arch/arm/include/asm/arch-exynos/clk.h | 3 + 2 files changed, 147 insertions(+), 7 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 5dc9ed2..ee6c13b 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -27,7 +27,7 @@ struct clk_bit_info { }; /* periph_id src_bit div_bit prediv_bit */ -static struct clk_bit_info clk_bit_info[] = { +static struct clk_bit_info exynos5_bit_info[] = { {PERIPH_ID_UART0, 0, 0, -1}, {PERIPH_ID_UART1, 4, 4, -1}, {PERIPH_ID_UART2, 8, 8, -1}, @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = { {PERIPH_ID_NONE,-1, -1, -1}, }; +static struct clk_bit_info exynos542x_bit_info[] = { + {PERIPH_ID_UART0, 4, 8, -1}, + {PERIPH_ID_UART1, 8, 12, -1}, + {PERIPH_ID_UART2, 12, 16, -1}, + {PERIPH_ID_UART3, 16, 20, -1}, + {PERIPH_ID_I2C0,-1, 8, -1}, + {PERIPH_ID_I2C1,-1, 8, -1}, + {PERIPH_ID_I2C2,-1, 8, -1}, + {PERIPH_ID_I2C3,-1, 8, -1}, + {PERIPH_ID_I2C4,-1, 8, -1}, + {PERIPH_ID_I2C5,-1, 8, -1}, + {PERIPH_ID_I2C6,-1, 8, -1}, + {PERIPH_ID_I2C7,-1, 8, -1}, + {PERIPH_ID_SPI0,20, 20, 8}, + {PERIPH_ID_SPI1,24, 24, 16}, + {PERIPH_ID_SPI2,28, 28, 24}, + {PERIPH_ID_SDMMC0, 0, 0, -1}, + {PERIPH_ID_SDMMC1, 4, 10, -1}, + {PERIPH_ID_SDMMC2, 8, 20, -1}, + {PERIPH_ID_I2C8,-1, 8, -1}, + {PERIPH_ID_I2C9,-1, 8, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SPI3,12, 16, 0}, + {PERIPH_ID_SPI4,16, 20, 8}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 28, -1}, + {PERIPH_ID_PWM1,24, 28, -1}, + {PERIPH_ID_PWM2,24, 28, -1}, + {PERIPH_ID_PWM3,24, 28, -1}, + {PERIPH_ID_PWM4,24, 28, -1}, + {PERIPH_ID_I2C10, -1, 8, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, +}; + /* Epll Clock division values to achive different frequency output */ static struct set_epll_con_val exynos5_epll_div[] = { { 19200, 0, 48, 3, 1, 0 }, @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg) static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; + struct clk_bit_info *info; - for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { - if (clk_bit_info[i].id == peripheral) + if (proid_is_exynos5420() || proid_is_exynos5800()) + info = exynos542x_bit_info; + else + info = exynos5_bit_info; + + for (i = 0; info[i].id != PERIPH_ID_NONE; i++) { + if (info[i].id == peripheral) break; } - if (clk_bit_info[i].id == PERIPH_ID_NONE) + if (info[i].id == PERIPH_ID_NONE) debug(ERROR: Peripheral ID %d not found\n, peripheral); - return clk_bit_info[i]; + return info[i]; } static unsigned long exynos5_get_periph_rate(int peripheral) @@ -414,12 +456,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral) return sub_clk; } +static unsigned long exynos542x_get_periph_rate(int peripheral) +{ + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); + unsigned long sclk, sub_clk = 0; + unsigned int src, div, sub_div = 0; + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + case PERIPH_ID_PWM0: + case PERIPH_ID_PWM1
[U-Boot] [PATCH v3 5/6] Exynos5: Use clock_get_periph_rate generic API
Replacing SoC and peripheral specific function calls with generic clock_get_periph_rate calls to get the peripheral clocks. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - No change. Changes since v1: - Separated exynos5_get_periph_rate fixes into another patch. arch/arm/cpu/armv7/exynos/clock.c | 52 --- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 2cd0778..31c90b2 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -1768,7 +1768,7 @@ unsigned long get_arm_clk(void) unsigned long get_i2c_clk(void) { if (cpu_is_exynos5()) { - return exynos5_get_i2c_clk(); + return clock_get_periph_rate(PERIPH_ID_I2C0); } else if (cpu_is_exynos4()) { return exynos4_get_i2c_clk(); } else { @@ -1780,8 +1780,6 @@ unsigned long get_i2c_clk(void) unsigned long get_pwm_clk(void) { if (cpu_is_exynos5()) { - if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_pwm_clk(); return clock_get_periph_rate(PERIPH_ID_PWM0); } else { if (proid_is_exynos4412()) @@ -1792,10 +1790,28 @@ unsigned long get_pwm_clk(void) unsigned long get_uart_clk(int dev_index) { + enum periph_id id; + + switch (dev_index) { + case 0: + id = PERIPH_ID_UART0; + break; + case 1: + id = PERIPH_ID_UART1; + break; + case 2: + id = PERIPH_ID_UART2; + break; + case 3: + id = PERIPH_ID_UART3; + break; + default: + debug(%s: invalid UART index %d, __func__, dev_index); + return -1; + } + if (cpu_is_exynos5()) { - if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_uart_clk(dev_index); - return exynos5_get_uart_clk(dev_index); + return clock_get_periph_rate(id); } else { if (proid_is_exynos4412()) return exynos4x12_get_uart_clk(dev_index); @@ -1805,10 +1821,28 @@ unsigned long get_uart_clk(int dev_index) unsigned long get_mmc_clk(int dev_index) { + enum periph_id id; + + switch (dev_index) { + case 0: + id = PERIPH_ID_SDMMC0; + break; + case 1: + id = PERIPH_ID_SDMMC1; + break; + case 2: + id = PERIPH_ID_SDMMC2; + break; + case 3: + id = PERIPH_ID_SDMMC3; + break; + default: + debug(%s: invalid MMC index %d, __func__, dev_index); + return -1; + } + if (cpu_is_exynos5()) { - if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_mmc_clk(dev_index); - return exynos5_get_mmc_clk(dev_index); + return clock_get_periph_rate(id); } else { return exynos4_get_mmc_clk(dev_index); } -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v3 6/6] Exynos5: Remove dead code for fetching clocks
Removing dead code of peripheral and SoC specific function implementations which was used for fetching peripheral clocks. This code is not being used anymore because of the introduction of generic clock_get_periph_rate function. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v2: - No change. Changes since v1: - No change. arch/arm/cpu/armv7/exynos/clock.c | 226 -- 1 file changed, 226 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 31c90b2..96066da 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -687,27 +687,6 @@ static unsigned long exynos4x12_get_pwm_clk(void) return pclk; } -/* exynos5420: return pwm clock frequency */ -static unsigned long exynos5420_get_pwm_clk(void) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long pclk, sclk; - unsigned int ratio; - - /* -* CLK_DIV_PERIC0 -* PWM_RATIO [31:28] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio 28) 0xf; - sclk = get_pll_clk(MPLL); - - pclk = sclk / (ratio + 1); - - return pclk; -} - /* exynos4: return uart clock frequency */ static unsigned long exynos4_get_uart_clk(int dev_index) { @@ -800,100 +779,6 @@ static unsigned long exynos4x12_get_uart_clk(int dev_index) return uclk; } -/* exynos5: return uart clock frequency */ -static unsigned long exynos5_get_uart_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [3:0] -* UART1_SEL [7:4] -* UART2_SEL [8:11] -* UART3_SEL [12:15] -* UART4_SEL [16:19] -* UART5_SEL [23:20] -*/ - sel = readl(clk-src_peric0); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel == 0x7) - sclk = get_pll_clk(EPLL); - else if (sel == 0x8) - sclk = get_pll_clk(VPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [3:0] -* UART1_RATIO [7:4] -* UART2_RATIO [8:11] -* UART3_RATIO [12:15] -* UART4_RATIO [16:19] -* UART5_RATIO [23:20] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio (dev_index 2)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - -/* exynos5420: return uart clock frequency */ -static unsigned long exynos5420_get_uart_clk(int dev_index) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [6:4] -* UART1_SEL [10:8] -* UART2_SEL [14:12] -* UART3_SEL [18:16] -* generalised calculation as follows -* sel = (sel ((dev_index * 4) + 4)) mask; -*/ - sel = readl(clk-src_peric0); - sel = (sel ((dev_index * 4) + 4)) 0x7; - - if (sel == 0x3) - sclk = get_pll_clk(MPLL); - else if (sel == 0x6) - sclk = get_pll_clk(EPLL); - else if (sel == 0x7) - sclk = get_pll_clk(RPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [11:8] -* UART1_RATIO [15:12] -* UART2_RATIO [19:16] -* UART3_RATIO [23:20] -* generalised calculation as follows -* ratio = (ratio ((dev_index * 4) + 8)) mask; -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio ((dev_index * 4) + 8)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - static unsigned long exynos4_get_mmc_clk(int dev_index) { struct exynos4_clock *clk = @@ -943,94 +828,6 @@ static unsigned long exynos4_get_mmc_clk(int dev_index) return uclk; } -static unsigned long exynos5_get_mmc_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel, ratio, pre_ratio; - int shift = 0; - - sel = readl(clk-src_fsys); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel == 0x7) - sclk = get_pll_clk(EPLL); - else if (sel == 0x8) - sclk = get_pll_clk(VPLL); - else - return 0; - - switch (dev_index) { - case 0: - case 1: - ratio = readl(clk-div_fsys1); - pre_ratio
[U-Boot] [PATCH v2 1/6] Exynos5: Fix compiler warnings due to clock_get_periph_rate
Apparently, members of clk_bit_info array do not map correctly to the members of enum periph_id. This mapping got broken after we changed periph_id(s) to reflect interrupt number instead of their position in a sequence. This patch intends to fix above mentioned issue. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v1: - Removed exynos5_bit_info array name. arch/arm/cpu/armv7/exynos/clock.c | 81 --- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index b31c13b..519928c 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -20,42 +20,49 @@ * positions of the peripheral clocks of the src and div registers */ struct clk_bit_info { + enum periph_id id; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* src_bit div_bit prediv_bit */ +/* periph_id src_bit div_bit prediv_bit */ static struct clk_bit_info clk_bit_info[] = { - {0, 0, -1}, - {4, 4, -1}, - {8, 8, -1}, - {12,12, -1}, - {0, 0, 8}, - {4, 16, 24}, - {8, 0, 8}, - {12,16, 24}, - {-1,-1, -1}, - {16,0, 8}, - {20,16, 24}, - {24,0, 8}, - {0, 0, 4}, - {4, 12, 16}, - {-1,-1, -1}, - {-1,-1, -1}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, + {PERIPH_ID_UART0, 0, 0, -1}, + {PERIPH_ID_UART1, 4, 4, -1}, + {PERIPH_ID_UART2, 8, 8, -1}, + {PERIPH_ID_UART3, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 24, 0}, + {PERIPH_ID_SPI0,16, 0, 8}, + {PERIPH_ID_SPI1,20, 16, 24}, + {PERIPH_ID_SPI2,24, 0, 8}, + {PERIPH_ID_SDMMC0, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 12, 16, 24}, + {PERIPH_ID_I2C8,-1, -1, -1}, + {PERIPH_ID_I2C9,-1, -1, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SROMC, -1, -1, -1}, + {PERIPH_ID_SPI3,0, 0, 4}, + {PERIPH_ID_SPI4,4, 12, 16}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 0, -1}, + {PERIPH_ID_PWM1,24, 0, -1}, + {PERIPH_ID_PWM2,24, 0, -1}, + {PERIPH_ID_PWM3,24, 0, -1}, + {PERIPH_ID_PWM4,24, 0, -1}, + {PERIPH_ID_I2C10, -1, -1, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, }; /* Epll Clock division values to achive different frequency output */ @@ -260,9 +267,21 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +static struct clk_bit_info *get_clk_bit_info(int peripheral) +{ + int i; + + for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { + if (clk_bit_info[i].id == peripheral) + break; + } + + return clk_bit_info[i]; +} + static unsigned long exynos5_get_periph_rate(int peripheral) { - struct clk_bit_info *bit_info = clk_bit_info[peripheral]; + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); unsigned long sclk, sub_clk; unsigned int src, div, sub_div; struct exynos5_clock *clk = -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 3/6] Exynos542x: Add and enable get_periph_rate support
We planned to fetch peripheral rate through one generic API per peripheral. These generic peripheral functions are in turn expected to fetch apt values from a function refactored as per SoC versions. This patch adds support for fetching peripheral rates for Exynos5420 and Exynos5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v1: - Changes suuport - support in commit message. - Removed position change of exynos5420_get_pll_clk. - Removed #ifdef. arch/arm/cpu/armv7/exynos/clock.c | 151 +++-- arch/arm/include/asm/arch-exynos/clk.h | 5 +- 2 files changed, 148 insertions(+), 8 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 6a1b05f..1ef4f49 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -27,7 +27,7 @@ struct clk_bit_info { }; /* periph_id src_bit div_bit prediv_bit */ -static struct clk_bit_info clk_bit_info[] = { +static struct clk_bit_info exynos5_bit_info[] = { {PERIPH_ID_UART0, 0, 0, -1}, {PERIPH_ID_UART1, 4, 4, -1}, {PERIPH_ID_UART2, 8, 8, -1}, @@ -65,6 +65,44 @@ static struct clk_bit_info clk_bit_info[] = { {PERIPH_ID_NONE,-1, -1, -1}, }; +static struct clk_bit_info exynos542x_bit_info[] = { + {PERIPH_ID_UART0, 4, 8, -1}, + {PERIPH_ID_UART1, 8, 12, -1}, + {PERIPH_ID_UART2, 12, 16, -1}, + {PERIPH_ID_UART3, 16, 20, -1}, + {PERIPH_ID_I2C0,-1, 8, -1}, + {PERIPH_ID_I2C1,-1, 8, -1}, + {PERIPH_ID_I2C2,-1, 8, -1}, + {PERIPH_ID_I2C3,-1, 8, -1}, + {PERIPH_ID_I2C4,-1, 8, -1}, + {PERIPH_ID_I2C5,-1, 8, -1}, + {PERIPH_ID_I2C6,-1, 8, -1}, + {PERIPH_ID_I2C7,-1, 8, -1}, + {PERIPH_ID_SPI0,20, 20, 8}, + {PERIPH_ID_SPI1,24, 24, 16}, + {PERIPH_ID_SPI2,28, 28, 24}, + {PERIPH_ID_SDMMC0, 0, 0, -1}, + {PERIPH_ID_SDMMC1, 4, 10, -1}, + {PERIPH_ID_SDMMC2, 8, 20, -1}, + {PERIPH_ID_SDMMC3, -1, -1, -1}, + {PERIPH_ID_I2C8,-1, 8, -1}, + {PERIPH_ID_I2C9,-1, 8, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SROMC, -1, -1, -1}, + {PERIPH_ID_SPI3,12, 16, 0}, + {PERIPH_ID_SPI4,16, 20, 8}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 28, -1}, + {PERIPH_ID_PWM1,24, 28, -1}, + {PERIPH_ID_PWM2,24, 28, -1}, + {PERIPH_ID_PWM3,24, 28, -1}, + {PERIPH_ID_PWM4,24, 28, -1}, + {PERIPH_ID_I2C10, -1, 8, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, +}; + /* Epll Clock division values to achive different frequency output */ static struct set_epll_con_val exynos5_epll_div[] = { { 19200, 0, 48, 3, 1, 0 }, @@ -310,13 +348,19 @@ static unsigned long exynos542x_get_pll_clk(int pllreg) static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; + struct clk_bit_info *info; - for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) { - if (clk_bit_info[i].id == peripheral) + if (proid_is_exynos5420() || proid_is_exynos5800()) + info = exynos542x_bit_info; + else + info = exynos5_bit_info; + + for (i = 0; info[i].id != PERIPH_ID_NONE; i++) { + if (info[i].id == peripheral) break; } - return clk_bit_info[i]; + return info[i]; } static unsigned long exynos5_get_periph_rate(int peripheral) @@ -415,12 +459,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral) return sub_clk; } +static unsigned long exynos542x_get_periph_rate(int peripheral) +{ + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); + unsigned long sclk, sub_clk; + unsigned int src, div, sub_div = 0; + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + src = readl(clk-src_peric0); + div = readl(clk-div_peric0); + break; + case PERIPH_ID_PWM0: + case PERIPH_ID_PWM1: + case PERIPH_ID_PWM2: + case PERIPH_ID_PWM3: + case PERIPH_ID_PWM4: + src
[U-Boot] [PATCH v2 5/6] Exynos5: Use clock_get_periph_rate generic API
Replacing SoC and peripheral specific function calls with generic clock_get_periph_rate calls to get the peripheral clocks. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v1: - Separated exynos5_get_periph_rate fixes into another patch. arch/arm/cpu/armv7/exynos/clock.c | 52 --- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index a43e5af..191f794 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -1768,7 +1768,7 @@ unsigned long get_arm_clk(void) unsigned long get_i2c_clk(void) { if (cpu_is_exynos5()) { - return exynos5_get_i2c_clk(); + return clock_get_periph_rate(PERIPH_ID_I2C0); } else if (cpu_is_exynos4()) { return exynos4_get_i2c_clk(); } else { @@ -1780,8 +1780,6 @@ unsigned long get_i2c_clk(void) unsigned long get_pwm_clk(void) { if (cpu_is_exynos5()) { - if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_pwm_clk(); return clock_get_periph_rate(PERIPH_ID_PWM0); } else { if (proid_is_exynos4412()) @@ -1792,10 +1790,28 @@ unsigned long get_pwm_clk(void) unsigned long get_uart_clk(int dev_index) { + enum periph_id id; + + switch (dev_index) { + case 0: + id = PERIPH_ID_UART0; + break; + case 1: + id = PERIPH_ID_UART1; + break; + case 2: + id = PERIPH_ID_UART2; + break; + case 3: + id = PERIPH_ID_UART3; + break; + default: + debug(%s: invalid UART index %d, __func__, dev_index); + return -1; + } + if (cpu_is_exynos5()) { - if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_uart_clk(dev_index); - return exynos5_get_uart_clk(dev_index); + return clock_get_periph_rate(id); } else { if (proid_is_exynos4412()) return exynos4x12_get_uart_clk(dev_index); @@ -1805,10 +1821,28 @@ unsigned long get_uart_clk(int dev_index) unsigned long get_mmc_clk(int dev_index) { + enum periph_id id; + + switch (dev_index) { + case 0: + id = PERIPH_ID_SDMMC0; + break; + case 1: + id = PERIPH_ID_SDMMC1; + break; + case 2: + id = PERIPH_ID_SDMMC2; + break; + case 3: + id = PERIPH_ID_SDMMC3; + break; + default: + debug(%s: invalid MMC index %d, __func__, dev_index); + return -1; + } + if (cpu_is_exynos5()) { - if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_mmc_clk(dev_index); - return exynos5_get_mmc_clk(dev_index); + return clock_get_periph_rate(id); } else { return exynos4_get_mmc_clk(dev_index); } -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 4/6] Exynos5: Fix exynos5_get_periph_rate calculations
exynos5_get_periph_rate function reads incorrect div for SDMMC2 3. It also reads prediv and does division only for SDMMC0 2 when actually various other peripherals need that. Adding changes to fix these mistakes in periph rate calculation. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 1ef4f49..a43e5af 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -406,10 +406,13 @@ static unsigned long exynos5_get_periph_rate(int peripheral) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: + src = readl(clk-src_fsys); + div = readl(clk-div_fsys1); + break; case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: src = readl(clk-src_fsys); - div = readl(clk-div_fsys1); + div = readl(clk-div_fsys2); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -450,8 +453,7 @@ static unsigned long exynos5_get_periph_rate(int peripheral) sub_div = (div bit_info-div_bit) 0xf; sub_clk = sclk / (sub_div + 1); - /* Pre-ratio clock division for SDMMC0 and 2 */ - if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) { + if (bit_info-prediv_bit = 0) { div = (div bit_info-prediv_bit) 0xff; return sub_clk / (div + 1); } -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 2/6] Exynos542x: Move exynos5420_get_pll_clk up and rename
Moving exynos5420_get_pll_clk function definition up in the code to keep it together with rest of SoC_get_pll_clk functions. This makes code more legible and also removes the need of declaration when called before the position of definition in code. Also, renaming exynos5420_get_pll_clk to exynos542x_get_pll_clk because it is being used for both Exynos 5420 and 5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v1: - New patch. arch/arm/cpu/armv7/exynos/clock.c | 82 +++ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 519928c..6a1b05f 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -267,6 +267,46 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +/* exynos5420: return pll clock frequency */ +static unsigned long exynos542x_get_pll_clk(int pllreg) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(clk-apll_con0); + break; + case MPLL: + r = readl(clk-mpll_con0); + break; + case EPLL: + r = readl(clk-epll_con0); + k = readl(clk-epll_con1); + break; + case VPLL: + r = readl(clk-vpll_con0); + k = readl(clk-vpll_con1); + break; + case BPLL: + r = readl(clk-bpll_con0); + break; + case RPLL: + r = readl(clk-rpll_con0); + k = readl(clk-rpll_con1); + break; + case SPLL: + r = readl(clk-spll_con0); + break; + default: + printf(Unsupported PLL (%d)\n, pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; @@ -383,46 +423,6 @@ unsigned long clock_get_periph_rate(int peripheral) return 0; } -/* exynos5420: return pll clock frequency */ -static unsigned long exynos5420_get_pll_clk(int pllreg) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long r, k = 0; - - switch (pllreg) { - case APLL: - r = readl(clk-apll_con0); - break; - case MPLL: - r = readl(clk-mpll_con0); - break; - case EPLL: - r = readl(clk-epll_con0); - k = readl(clk-epll_con1); - break; - case VPLL: - r = readl(clk-vpll_con0); - k = readl(clk-vpll_con1); - break; - case BPLL: - r = readl(clk-bpll_con0); - break; - case RPLL: - r = readl(clk-rpll_con0); - k = readl(clk-rpll_con1); - break; - case SPLL: - r = readl(clk-spll_con0); - break; - default: - printf(Unsupported PLL (%d)\n, pllreg); - return 0; - } - - return exynos_get_pll_clk(pllreg, r, k); -} - /* exynos4: return ARM clock frequency */ static unsigned long exynos4_get_arm_clk(void) { @@ -1604,7 +1604,7 @@ unsigned long get_pll_clk(int pllreg) { if (cpu_is_exynos5()) { if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_pll_clk(pllreg); + return exynos542x_get_pll_clk(pllreg); return exynos5_get_pll_clk(pllreg); } else { if (proid_is_exynos4412()) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v2 0/4] Exynos5: Fix warnings and enrich clock_get_periph_rate
This patch series does following changes - 1. Removing compiler warnings for clock_get_periph_rate. 2. Adding and enabling support for Exynos542x in clock_get_periph_rate. 3. Replacing peripheral specific function calls with clock_get_periph_rate. 4. Remove code from clocks file which became useless due to introduction of clock_get_periph_rate. Changes since v1: - Added 2 new patches. Akshay Saraswat (6): Exynos5: Fix compiler warnings due to clock_get_periph_rate Exynos542x: Move exynos5420_get_pll_clk up and rename Exynos542x: Add and enable get_periph_rate support Exynos5: Fix exynos5_get_periph_rate calculations Exynos5: Use clock_get_periph_rate generic API Exynos5: Remove dead code for fetching clocks arch/arm/cpu/armv7/exynos/clock.c | 574 - arch/arm/include/asm/arch-exynos/clk.h | 5 +- 2 files changed, 274 insertions(+), 305 deletions(-) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 05/11] Exynos542x: Add workaround for exynos iROM errata
iROM logic provides undesired jump address for CPU2. This patch adds a programmable susbstitute for a part of iROM logic which wakes up cores and provides jump addresses. This patch creates a logic to make all secondary cores jump to a particular address which evades the possibility of CPU2 jumping to wrong address and create undesired results. Logic of the workaround: Step-1: iROM code checks value at address 0x2020028. Step-2: If value is 0xc9cfcfcf, it jumps to the address (0x202000+CPUid*4), else, it continues executing normally. Step-3: Primary core puts secondary cores in WFE and store 0xc9cfcfcf in 0x2020028 and jump address (pointer to function low_power_start) in (0x202000+CPUid*4). Step-4: When secondary cores recieve event signal they jump to this address and continue execution. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/Makefile| 2 + arch/arm/cpu/armv7/exynos/lowlevel_init.c | 90 +++ arch/arm/cpu/armv7/exynos/sec_boot.S | 145 ++ 3 files changed, 219 insertions(+), 18 deletions(-) create mode 100644 arch/arm/cpu/armv7/exynos/sec_boot.S diff --git a/arch/arm/cpu/armv7/exynos/Makefile b/arch/arm/cpu/armv7/exynos/Makefile index e207bd6..8542f89 100644 --- a/arch/arm/cpu/armv7/exynos/Makefile +++ b/arch/arm/cpu/armv7/exynos/Makefile @@ -7,6 +7,8 @@ obj-y += clock.o power.o soc.o system.o pinmux.o tzpc.o +obj-$(CONFIG_EXYNOS5420) += sec_boot.o + ifdef CONFIG_SPL_BUILD obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 3097382..d3c466e 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -49,7 +49,7 @@ enum { * before modifying the ACTLR.SMP bit. This is required during boot before * MMU has been enabled, or during a specified reset or power down sequence. */ -void enable_smp(void) +static void enable_smp(void) { uint32_t temp, val; @@ -70,7 +70,7 @@ void enable_smp(void) * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. */ -void set_l2cache(void) +static void set_l2cache(void) { uint32_t val; @@ -89,6 +89,62 @@ void set_l2cache(void) } /* + * Power up secondary CPUs. + */ +static void secondary_cpu_start(void) +{ + enable_smp(); + svc32_mode_en(); + set_pc(CONFIG_EXYNOS_RELOCATE_CODE_BASE); +} + +/* + * This is the entry point of hotplug-in and + * cluster switching. + */ +static void low_power_start(void) +{ + uint32_t val, reg_val; + + reg_val = readl(RST_FLAG_REG); + if (reg_val != RST_FLAG_VAL) { + writel(0x0, CONFIG_LOWPOWER_FLAG); + set_pc(0x0); + } + + reg_val = readl(CONFIG_PHY_IRAM_BASE + 0x4); + if (reg_val != (uint32_t)low_power_start) { + /* Store jump address as low_power_start if not present */ + writel((uint32_t)low_power_start, CONFIG_PHY_IRAM_BASE + 0x4); + dsb(); + sev(); + } + + /* Set the CPU to SVC32 mode */ + svc32_mode_en(); + set_l2cache(); + + /* Invalidate L1 TLB */ + val = 0x0; + mcr_tlb(val); + mcr_icache(val); + + /* Disable MMU stuff and caches */ + mrc_sctlr(val); + + val = ~((0x2 12) | 0x7); + val |= ((0x1 12) | (0x8 8) | 0x2); + mcr_sctlr(val); + + /* CPU state is hotplug or reset */ + secondary_cpu_start(); + + /* Core should not enter into WFI here */ + wfi(); + +} + +/* * Pointer to this function is stored in iRam which is used * for jump and power down of a specific core. */ @@ -118,29 +174,25 @@ static void power_down_core(void) */ static void secondary_cores_configure(void) { - uint32_t core_id; + /* Setup L2 cache */ + set_l2cache(); + + /* Clear secondary boot iRAM base */ + writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); - /* Store jump address for power down of secondary cores */ + /* set lowpower flag and address */ + writel(RST_FLAG_VAL, CONFIG_LOWPOWER_FLAG); + writel((uint32_t)low_power_start, CONFIG_LOWPOWER_ADDR); + writel(RST_FLAG_VAL, RST_FLAG_REG); + /* Store jump address for power down */ writel((uint32_t)power_down_core, CONFIG_PHY_IRAM_BASE + 0x4); /* Need all core power down check */ dsb(); sev(); - - /* -* Power down all cores(secondary) while primary core must -* wait for all cores to go down. -*/ - for (core_id = 1; core_id != CORE_COUNT; core_id++) { - while ((readl(ARM_CORE0_STATUS
[U-Boot] [PATCH 02/11] Exynos542x: CPU: Power down all secondary cores
This patch adds code to shutdown secondary cores. When U-boot comes up, all secondary cores appear powered on, which is undesirable and causes side effects while initializing these cores in kernel. Secondary core power down happens in following steps: Step-1: After Exynos power-on, primary core starts executing first. Step-2: In iROM code every core has to check 2 flags i.e. addresses 0x02020028 0x02020004. Step-3: Initially 0x02020028 is 0 for all cores and 0x02020004 has a jump address for primary core and 0 for all secondary cores. Step-4: Therefore, primary core follows normal iROM execution and jumps to BL1 eventually, whereas all secondary cores enter WFE. Step-5: When primary core comes into function secondary_cores_configure, it puts pointer to function power_down_core into 0x02020004 and provides DSB and SEV for all cores so that they may come out of WFE and jump to power_down_core function. Step-6: And ultimately because of power_down_core all secondary cores shut-down. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 62 ++ arch/arm/include/asm/arch-exynos/cpu.h| 30 +++ arch/arm/include/asm/arch-exynos/system.h | 87 +++ 3 files changed, 179 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 83e1dcf..43c957b 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -31,6 +31,7 @@ #include asm/arch/tzpc.h #include asm/arch/periph.h #include asm/arch/pinmux.h +#include asm/arch/system.h #include common_setup.h /* These are the things we can do during low-level init */ @@ -42,6 +43,62 @@ enum { DO_POWER= 1 4, }; +#ifdef CONFIG_EXYNOS5420 +/* + * Pointer to this function is stored in iRam which is used + * for jump and power down of a specific core. + */ +static void power_down_core(void) +{ + uint32_t tmp, core_id, core_config; + + /* Get the core id */ + mrc_mpafr(core_id); + tmp = core_id 0x3; + core_id = (core_id 6) ~3; + core_id |= tmp; + + /* Set the status of the core to low */ + core_config = (core_id * CORE_CONFIG_OFFSET); + core_config += ARM_CORE0_CONFIG; + writel(0x0, core_config); + + /* Core enter WFI */ + wfi(); +} + +/* + * Configurations for secondary cores are inapt at this stage. + * Reconfigure secondary cores. Shutdown and change the status + * of all cores except the primary core. + */ +static void secondary_cores_configure(void) +{ + uint32_t core_id; + + /* Store jump address for power down of secondary cores */ + writel((uint32_t)power_down_core, CONFIG_PHY_IRAM_BASE + 0x4); + + /* Need all core power down check */ + dsb(); + sev(); + + /* +* Power down all cores(secondary) while primary core must +* wait for all cores to go down. +*/ + for (core_id = 1; core_id != CORE_COUNT; core_id++) { + while ((readl(ARM_CORE0_STATUS + + (core_id * CORE_CONFIG_OFFSET)) +0xff) != 0x0) { + isb(); + sev(); + } + isb(); + } +} +#endif + int do_lowlevel_init(void) { uint32_t reset_status; @@ -49,6 +106,11 @@ int do_lowlevel_init(void) arch_cpu_init(); +#ifdef CONFIG_EXYNOS5420 + /* Reconfigure secondary cores */ + secondary_cores_configure(); +#endif + reset_status = get_reset_status(); switch (reset_status) { diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index 29674ad..f1f9994 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -177,6 +177,7 @@ #define EXYNOS5420_GPIO_PART1_BASE 0x1401 #define EXYNOS5420_MIPI_DSIM_BASE 0x1450 #define EXYNOS5420_DP_BASE 0x145B +#define EXYNOS5420_INF_REG_BASE0x10040800 #define EXYNOS5420_USBPHY_BASE DEVICE_NOT_AVAILABLE #define EXYNOS5420_USBOTG_BASE DEVICE_NOT_AVAILABLE @@ -186,6 +187,35 @@ #define EXYNOS5420_USB3PHY_BASEDEVICE_NOT_AVAILABLE #define EXYNOS5420_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE +#define ARM_CORE0_CONFIG (EXYNOS5420_POWER_BASE + 0x2000) +#define ARM_CORE0_STATUS (EXYNOS5420_POWER_BASE + 0x2004) +#define CORE_CONFIG_OFFSET 0x80 +#define CORE_COUNT 0x8 + +/* + * POWER + */ +#define PMU_BASE EXYNOS5420_POWER_BASE +#define SW_RST_REG_OFFSET 0x400 + +#define INF_REG_BASE EXYNOS5420_INF_REG_BASE +#define INF_REG0_OFFSET0x00
[U-Boot] [PATCH 03/11] Exynos542x: Add workaround for ARM errata 798870
This patch adds workaround for ARM errata 798870 which says If back-to-back speculative cache line fills (fill A and fill B) are issued from the L1 data cache of a CPU to the L2 cache, the second request (fill B) is then cancelled, and the second request would have detected a hazard against a recent write or eviction (write B) to the same cache line as fill B then the L2 logic might deadlock. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 43c957b..7073c5c 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -45,6 +45,28 @@ enum { #ifdef CONFIG_EXYNOS5420 /* + * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been + * stalled for 1024 cycles to verify that its hazard condition still exists. + */ +void set_l2cache(void) +{ + uint32_t val; + + /* Read MIDR for Primary Part Number*/ + mrc_midr(val); + val = (val 4); + val = 0xf; + + /* L2ACTLR[7]: Enable hazard detect timeout for A15 */ + if (val == 0xf) { + mrc_l2_aux_ctlr(val); + val |= (1 7); + mcr_l2_aux_ctlr(val); + mrc_l2_ctlr(val); + } +} + +/* * Pointer to this function is stored in iRam which is used * for jump and power down of a specific core. */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 06/11] Exynos542x: Change ambiguous function name set_l2cache
1. Renaming set_l2cache to configure_l2actlr in order to avoid misleading comprehensions. Apparently this name suggests that L2 cache is being set or initialized which is incorrect as per the code in this function. 2. Cleaning missed mrc for L2 control register. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index d3c466e..688972b 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -70,7 +70,7 @@ static void enable_smp(void) * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. */ -static void set_l2cache(void) +static void configure_l2actlr(void) { uint32_t val; @@ -84,7 +84,6 @@ static void set_l2cache(void) mrc_l2_aux_ctlr(val); val |= (1 7); mcr_l2_aux_ctlr(val); - mrc_l2_ctlr(val); } } @@ -122,7 +121,7 @@ static void low_power_start(void) /* Set the CPU to SVC32 mode */ svc32_mode_en(); - set_l2cache(); + configure_l2actlr(); /* Invalidate L1 TLB */ val = 0x0; @@ -175,7 +174,7 @@ static void power_down_core(void) static void secondary_cores_configure(void) { /* Setup L2 cache */ - set_l2cache(); + configure_l2actlr(); /* Clear secondary boot iRAM base */ writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 04/11] Exynos542x: Add workaround for ARM errata 799270
This patch adds workaround for the ARM errata 799270 which says If the L2 cache logic clock is stopped because of L2 inactivity, setting or clearing the ACTLR.SMP bit might not be effective. The bit is modified in the ACTLR, meaning a read of the register returns the updated value. However the logic that uses that bit retains the previous value. Signed-off-by: Kimoon Kim kimoon@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 7073c5c..3097382 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -45,6 +45,28 @@ enum { #ifdef CONFIG_EXYNOS5420 /* + * Ensure that the L2 logic has been used within the previous 256 cycles + * before modifying the ACTLR.SMP bit. This is required during boot before + * MMU has been enabled, or during a specified reset or power down sequence. + */ +void enable_smp(void) +{ + uint32_t temp, val; + + /* Enable SMP mode */ + mrc_auxr(temp); + temp |= (1 6); + + /* Dummy read to assure L2 access */ + val = readl(INF_REG_BASE); + val = 0; + temp |= val; + mcr_auxr(temp); + dsb(); + isb(); +} + +/* * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 10/11] Exynos542x: Make A7s boot with thumb-mode U-Boot on warm reset
On warm reset, all cores jump to the low_power_start function because iRAM data is retained and because while executing iROM code all cores find the jump flag 0x02020028 set. In low_power_start, cores check the reset status and if true they clear the jump flag and jump back to 0x0. The A7 cores do jump to 0x0 but consider following instructions as a Thumb instructions which in turn makes them loop inside the iROM code instead of jumping to power_down_core. This issue is fixed by replacing the mov pc instruction with a bx instruction which switches state along with the jump to make the execution unit consider the branch target as an ARM instruction. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index d9f3f4b..a459432 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -124,7 +124,7 @@ static void low_power_start(void) reg_val = readl(RST_FLAG_REG); if (reg_val != RST_FLAG_VAL) { writel(0x0, CONFIG_LOWPOWER_FLAG); - set_pc(0x0); + branch_bx(0x0); } reg_val = readl(CONFIG_PHY_IRAM_BASE + 0x4); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 11/11] Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800
From: Doug Anderson diand...@chromium.org It was found that the L2 cache timings that we had before could cause freezes and hangs. We should make things more robust with better timings. Currently the production ChromeOS kernel applies these timings, but it's nice to fixup firmware too (and upstream probably won't take our kernel hacks). This also provides a big cleanup of the L2 cache init code avoiding some duplication. The way things used to work: * low_power_start() was installed by the SPL (both at boot and resume time) and left resident in iRAM for the kernel to use when bringing up additional CPUs. It used configure_l2_ctlr() and configure_l2_actlr() when it detected it was on an A15. This was needed (despite the L2 cache registers being shared among all A15s) because we might have been the first man in after the whole A15 cluster was shutdown. * secondary_cores_configure() was called on at boot time and at resume time. Strangely this called configure_l2_ctlr() but not configure_l2_actlr() which was almost certainly wrong. Given that we'll call both (see next bullet) later in the boot process it didn't matter for normal boot, but I guess this is how L2 cache settings got set on 5420/5800 (but not 5250?) at resume time. * exynos5_set_l2cache_params() was called as part of cache enablement. This should happen at boot time (normally in the SPL except for USB boot where it happens in main U-Boot). Note that the old code wasn't setting ECC/parity in the cache enablement code but we happened to get it anyway because we'd call secondary_cores_configure() at boot time. For resume time we'd get it anyway when the 2nd A15 core came up. Let's make this a whole lot simpler. Now we always set these parameters in the same place for all boots and use the same code for setting up secondary CPUs. Intended net effects of this change (other than cleanup): * Timings go from before: data: 0 cycle setup, 3 cycles (0x2) latency tag: 0 cycle setup, 3 cycles (0x2) latency after: data: 1 cycle setup, 4 cycles (0x3) latency tag: 1 cycle setup, 4 cycles (0x3) latency * L2ACTLR is properly initted on 5420/5800 in all cases. One note is that we're still relying on luck to keep low_power_start() working. The compiler is being nice and not storing anything on the stack. Another note is that on its own this patch won't help to fix cache settings in an RW U-Boot update where we still have the RO SPL. The plan for that is: * Have RW U-Boot re-init the cache right before calling the kernel (after it has turned the L2 cache off). This is why the functions are in a header file instead of lowlevel_init.c. * Have the kernel save the L2 cache settings of the boot CPU and apply them to all other CPUs. We get a little lucky here because the old code was using |= to modify the registers and all of the bits that it's setting are also present in the new settings (!). That means that when the 2nd CPU in the A15 cluster comes up it doesn't actually mess up the settings of the 1st CPU in the A15 cluster. An alternative option is to have the kernel write its own low_power_start() code. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/common_setup.h | 55 +++ arch/arm/cpu/armv7/exynos/lowlevel_init.c | 55 +-- arch/arm/cpu/armv7/exynos/soc.c | 51 3 files changed, 70 insertions(+), 91 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/common_setup.h b/arch/arm/cpu/armv7/exynos/common_setup.h index e6318c0..7fa9683 100644 --- a/arch/arm/cpu/armv7/exynos/common_setup.h +++ b/arch/arm/cpu/armv7/exynos/common_setup.h @@ -23,6 +23,8 @@ * MA 02111-1307 USA */ +#include asm/arch/system.h + #define DMC_OFFSET 0x1 /* @@ -43,3 +45,56 @@ void system_clock_init(void); int do_lowlevel_init(void); void sdelay(unsigned long); + +enum l2_cache_params { + CACHE_ECC_AND_PARITY = (1 21), + CACHE_TAG_RAM_SETUP = (1 9), + CACHE_DATA_RAM_SETUP = (1 5), +#ifndef CONFIG_EXYNOS5420 + CACHE_TAG_RAM_LATENCY = (2 6), /* 5250 */ + CACHE_DATA_RAM_LATENCY = (2 0), +#else + CACHE_TAG_RAM_LATENCY = (3 6), /* 5420 and 5422 */ + CACHE_DATA_RAM_LATENCY = (3 0), +#endif +}; + +#ifndef CONFIG_SYS_L2CACHE_OFF +/* + * Configure L2CTLR to get timings that keep us from hanging/crashing. + * + * Must be inline here since low_power_start() is called without a + * stack (!). + */ +static inline void configure_l2_ctlr(void) +{ + uint32_t val; + + mrc_l2_ctlr(val); + val |= CACHE_TAG_RAM_SETUP | + CACHE_DATA_RAM_SETUP | + CACHE_TAG_RAM_LATENCY | + CACHE_DATA_RAM_LATENCY | + CACHE_ECC_AND_PARITY; + mcr_l2_ctlr(val); +} + +/* + * Configure L2ACTLR. + * + * Must be inline here
[U-Boot] [PATCH v2 6/6] Exynos5: Remove dead code for fetching clocks
Removing dead code of peripheral and SoC specific function implementations which was used for fetching peripheral clocks. This code is not being used anymore because of the introduction of generic clock_get_periph_rate function. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- Changes since v1: - No change. arch/arm/cpu/armv7/exynos/clock.c | 226 -- 1 file changed, 226 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 191f794..c0ac8fb 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -687,27 +687,6 @@ static unsigned long exynos4x12_get_pwm_clk(void) return pclk; } -/* exynos5420: return pwm clock frequency */ -static unsigned long exynos5420_get_pwm_clk(void) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long pclk, sclk; - unsigned int ratio; - - /* -* CLK_DIV_PERIC0 -* PWM_RATIO [31:28] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio 28) 0xf; - sclk = get_pll_clk(MPLL); - - pclk = sclk / (ratio + 1); - - return pclk; -} - /* exynos4: return uart clock frequency */ static unsigned long exynos4_get_uart_clk(int dev_index) { @@ -800,100 +779,6 @@ static unsigned long exynos4x12_get_uart_clk(int dev_index) return uclk; } -/* exynos5: return uart clock frequency */ -static unsigned long exynos5_get_uart_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [3:0] -* UART1_SEL [7:4] -* UART2_SEL [8:11] -* UART3_SEL [12:15] -* UART4_SEL [16:19] -* UART5_SEL [23:20] -*/ - sel = readl(clk-src_peric0); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel == 0x7) - sclk = get_pll_clk(EPLL); - else if (sel == 0x8) - sclk = get_pll_clk(VPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [3:0] -* UART1_RATIO [7:4] -* UART2_RATIO [8:11] -* UART3_RATIO [12:15] -* UART4_RATIO [16:19] -* UART5_RATIO [23:20] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio (dev_index 2)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - -/* exynos5420: return uart clock frequency */ -static unsigned long exynos5420_get_uart_clk(int dev_index) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [6:4] -* UART1_SEL [10:8] -* UART2_SEL [14:12] -* UART3_SEL [18:16] -* generalised calculation as follows -* sel = (sel ((dev_index * 4) + 4)) mask; -*/ - sel = readl(clk-src_peric0); - sel = (sel ((dev_index * 4) + 4)) 0x7; - - if (sel == 0x3) - sclk = get_pll_clk(MPLL); - else if (sel == 0x6) - sclk = get_pll_clk(EPLL); - else if (sel == 0x7) - sclk = get_pll_clk(RPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [11:8] -* UART1_RATIO [15:12] -* UART2_RATIO [19:16] -* UART3_RATIO [23:20] -* generalised calculation as follows -* ratio = (ratio ((dev_index * 4) + 8)) mask; -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio ((dev_index * 4) + 8)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - static unsigned long exynos4_get_mmc_clk(int dev_index) { struct exynos4_clock *clk = @@ -943,94 +828,6 @@ static unsigned long exynos4_get_mmc_clk(int dev_index) return uclk; } -static unsigned long exynos5_get_mmc_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel, ratio, pre_ratio; - int shift = 0; - - sel = readl(clk-src_fsys); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel == 0x7) - sclk = get_pll_clk(EPLL); - else if (sel == 0x8) - sclk = get_pll_clk(VPLL); - else - return 0; - - switch (dev_index) { - case 0: - case 1: - ratio = readl(clk-div_fsys1); - pre_ratio = readl(clk-div_fsys1
[U-Boot] [PATCH 01/11] Exynos542x: Config: Add various configs
This patch adds iRAM, CPU state and low power configs which are the addresses acting as flag registers. iROM code checks CONFIG_LOWPOWER_FLAG address. If it is equal to CONFIG_LOWPOWER_EN then it jumps to the address (0x0202+CPUID*4). This is a part of iROM logic. Rest other flags are being used at various places during kernel switching and reset. They are nowhere documented because they are part programming. These configs are serving as flags for us because they are representing the addresses in iRAM which we are using for storing and extracting CPU Status and GIC status. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- include/configs/exynos5-common.h | 28 1 file changed, 28 insertions(+) diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index ad63f3c..831bfd3 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -231,4 +231,32 @@ MEM_LAYOUT_ENV_SETTINGS \ BOOTENV +/* iRAM */ +#define CONFIG_PHY_IRAM_BASE 0x0202 +#define CONFIG_SEC_IRAM_SIZE 0x53000 /* 332KB */ + +#define CONFIG_EXYNOS_RELOCATE_CODE_BASE (CONFIG_PHY_IRAM_BASE \ + + CONFIG_SEC_IRAM_SIZE) + +/* + * Low Power settings + */ +#define CONFIG_LOWPOWER_FLAG 0x02020028 +#define CONFIG_LOWPOWER_ADDR 0x0202002C +#define CONFIG_LOWPOWER_EN 0xc9cfcfcf + +/* + * CPU State Settings + */ +#define CONFIG_CPU_STATE (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x28) +#define CONFIG_GIC_STATE (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x38) + +#define CONFIG_CPU0_STATE (CONFIG_CPU_STATE + 0x0) +#define CONFIG_CPU1_STATE (CONFIG_CPU_STATE + 0x4) +#define CONFIG_CPU2_STATE (CONFIG_CPU_STATE + 0x8) +#define CONFIG_CPU3_STATE (CONFIG_CPU_STATE + 0xC) + +#define RESET (1 0) +#define SECONDARY_RESET(1 1) + #endif /* __CONFIG_EXYNOS5_COMMON_H */ -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 00/11] Add support for booting multiple cores
This patch series introduces changes for booting secondary CPUs on Exynos5420 and Exynos5800. Akshay Saraswat (10): Exynos542x: Config: Add various configs Exynos542x: CPU: Power down all secondary cores Exynos542x: Add workaround for ARM errata 798870 Exynos542x: Add workaround for ARM errata 799270 Exynos542x: Add workaround for exynos iROM errata Exynos542x: Change ambiguous function name set_l2cache Exynos542x: cache: Disable clean/evict push to external Exynos542x: add L2 control register configuration Exynos542x: Fix secondary core booting for thumb Exynos542x: Make A7s boot with thumb-mode U-Boot on warm reset Doug Anderson (1): Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800 arch/arm/cpu/armv7/exynos/Makefile| 2 + arch/arm/cpu/armv7/exynos/common_setup.h | 55 +++ arch/arm/cpu/armv7/exynos/lowlevel_init.c | 159 ++ arch/arm/cpu/armv7/exynos/sec_boot.S | 145 +++ arch/arm/cpu/armv7/exynos/soc.c | 35 --- arch/arm/include/asm/arch-exynos/cpu.h| 30 ++ arch/arm/include/asm/arch-exynos/system.h | 90 + include/configs/exynos5-common.h | 28 ++ 8 files changed, 509 insertions(+), 35 deletions(-) create mode 100644 arch/arm/cpu/armv7/exynos/sec_boot.S -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 09/11] Exynos542x: Fix secondary core booting for thumb
When compiled SPL for Thumb secondary cores failed to boot at the kernel boot up. Only one core came up out of 4. This was happening because the code relocated to the address 0x02073000 by the primary core was an ARM asm code which was executed by the secondary cores as if it was a thumb code. This patch fixes the issue of secondary cores considering relocated code as Thumb instructions and not ARM instructions by jumping to the relocated with the help of bx ARM instruction. bx instruction changes the 5th bit of CPSR which allows execution unit to consider the following instructions as ARM instructions. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 2 +- arch/arm/include/asm/arch-exynos/system.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 57b4c66..d9f3f4b 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -110,7 +110,7 @@ static void secondary_cpu_start(void) { enable_smp(); svc32_mode_en(); - set_pc(CONFIG_EXYNOS_RELOCATE_CODE_BASE); + branch_bx(CONFIG_EXYNOS_RELOCATE_CODE_BASE); } /* diff --git a/arch/arm/include/asm/arch-exynos/system.h b/arch/arm/include/asm/arch-exynos/system.h index 86903c3..a9fd5e6 100644 --- a/arch/arm/include/asm/arch-exynos/system.h +++ b/arch/arm/include/asm/arch-exynos/system.h @@ -75,6 +75,9 @@ struct exynos5_sysreg { /* Set program counter with the given value */ #define set_pc(x) __asm__ __volatile__ (mov pc, %0\n\t : : r(x)) +/* Branch to the given location */ +#define branch_bx(x) __asm__ __volatile__ (bx %0\n\t : : r(x)) + /* Read Main Id register */ #define mrc_midr(x) __asm__ __volatile__ \ (mrc p15, 0, %0, c0, c0, 0\n\t : =r(x) : ) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 07/11] Exynos542x: cache: Disable clean/evict push to external
L2 Auxiliary Control Register provides configuration and control options for the L2 memory system. Bit 3 of L2ACTLR stands for clean/evict push to external. Setting bit 3 disables clean/evict which is what this patch intends to do. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/soc.c | 9 + 1 file changed, 9 insertions(+) diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index 8c7d7d8..7268b9b 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -45,6 +45,15 @@ static void exynos5_set_l2cache_params(void) CACHE_DATA_RAM_LATENCY; asm volatile(mcr p15, 1, %0, c9, c0, 2\n : : r(val)); + +#ifdef CONFIG_EXYNOS5420 + /* Read CP15 L2ACTLR value */ + asm volatile(mrc p15, 1, %0, c15, c0, 0 : =r (val)); + /* Disable clean/evict push to external */ + val |= (0x1 3); + /* Write new vlaue to L2ACTLR */ + asm volatile(mcr p15, 1, %0, c15, c0, 0 : : r (val)); +#endif } /* -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 08/11] Exynos542x: add L2 control register configuration
This patch does 3 things: 1. Enables ECC by setting 21st bit of L2CTLR. 2. Restore data and tag RAM latencies to 3 cycles because iROM sets 0x3000400 L2CTLR value during switching. 3. Disable clean/evict push to external by setting 3rd bit of L2ACTLR. We need to restore this here due to switching. Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/lowlevel_init.c | 53 +++ arch/arm/cpu/armv7/exynos/soc.c | 7 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 688972b..57b4c66 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c @@ -67,24 +67,40 @@ static void enable_smp(void) } /* + * Enable ECC by setting L2CTLR[21]. + * Set L2CTLR[7] to make tag ram latency 3 cycles and + * set L2CTLR[1] to make data ram latency 3 cycles. + * We need to make RAM latency of 3 cycles here because cores + * power ON and OFF while switching. And everytime a core powers + * ON, iROM provides it a default L2CTLR value 0x400 which stands + * for TAG RAM setup of 1 cycle. Hence, we face a need of + * restoring data and tag latency values. + */ +static void configure_l2_ctlr(void) +{ + uint32_t val; + + mrc_l2_ctlr(val); + val |= (1 21); + val |= (1 7); + val |= (1 1); + mcr_l2_ctlr(val); +} + +/* * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been * stalled for 1024 cycles to verify that its hazard condition still exists. + * Disable clean/evict push to external by setting L2ACTLR[3]. */ -static void configure_l2actlr(void) +static void configure_l2_actlr(void) { uint32_t val; - /* Read MIDR for Primary Part Number*/ - mrc_midr(val); - val = (val 4); - val = 0xf; - - /* L2ACTLR[7]: Enable hazard detect timeout for A15 */ - if (val == 0xf) { - mrc_l2_aux_ctlr(val); - val |= (1 7); - mcr_l2_aux_ctlr(val); - } + mrc_l2_aux_ctlr(val); + val |= (1 27); + val |= (1 7); + val |= (1 3); + mcr_l2_aux_ctlr(val); } /* @@ -121,7 +137,16 @@ static void low_power_start(void) /* Set the CPU to SVC32 mode */ svc32_mode_en(); - configure_l2actlr(); + + /* Read MIDR for Primary Part Number*/ + mrc_midr(val); + val = (val 4); + val = 0xf; + + if (val == 0xf) { + configure_l2_ctlr(); + configure_l2_actlr(); + } /* Invalidate L1 TLB */ val = 0x0; @@ -174,7 +199,7 @@ static void power_down_core(void) static void secondary_cores_configure(void) { /* Setup L2 cache */ - configure_l2actlr(); + configure_l2_ctlr(); /* Clear secondary boot iRAM base */ writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C)); diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index 7268b9b..ea201e7 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -10,8 +10,10 @@ #include asm/system.h enum l2_cache_params { +#ifndef CONFIG_EXYNOS5420 CACHE_TAG_RAM_SETUP = (1 9), CACHE_DATA_RAM_SETUP = (1 5), +#endif CACHE_TAG_RAM_LATENCY = (2 6), CACHE_DATA_RAM_LATENCY = (2 0) }; @@ -39,10 +41,15 @@ static void exynos5_set_l2cache_params(void) asm volatile(mrc p15, 1, %0, c9, c0, 2\n : =r(val)); +#ifndef CONFIG_EXYNOS5420 val |= CACHE_TAG_RAM_SETUP | CACHE_DATA_RAM_SETUP | CACHE_TAG_RAM_LATENCY | CACHE_DATA_RAM_LATENCY; +#else + val |= CACHE_TAG_RAM_LATENCY | + CACHE_DATA_RAM_LATENCY; +#endif asm volatile(mcr p15, 1, %0, c9, c0, 2\n : : r(val)); -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 0/4] Exynos5: Fix warnings and enrich clock_get_periph_rate
This patch series does following changes - 1. Removing compiler warnings for clock_get_periph_rate. 2. Adding and enabling support for Exynos542x in clock_get_periph_rate. 3. Replacing peripheral specific function calls with clock_get_periph_rate. 4. Remove code from clocks file which became useless due to introduction of clock_get_periph_rate. Akshay Saraswat (4): Exynos5: Fix compiler warnings due to clock_get_periph_rate Exynos542x: Add and enable get_periph_rate support Exynos5: Use clock_get_periph_rate generic API Exynos5: Remove dead code for fetching clocks arch/arm/cpu/armv7/exynos/clock.c | 572 - arch/arm/include/asm/arch-exynos/clk.h | 8 + 2 files changed, 278 insertions(+), 302 deletions(-) -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 3/4] Exynos5: Use clock_get_periph_rate generic API
Replacing SoC and peripheral specific function calls with generic clock_get_periph_rate calls to get the peripheral clocks. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/clock.c | 60 +++ 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 9ac4579..9c719aa 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -406,10 +406,13 @@ static unsigned long exynos5_get_periph_rate(int peripheral) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: + src = readl(clk-src_fsys); + div = readl(clk-div_fsys1); + break; case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: src = readl(clk-src_fsys); - div = readl(clk-div_fsys1); + div = readl(clk-div_fsys2); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -450,8 +453,7 @@ static unsigned long exynos5_get_periph_rate(int peripheral) sub_div = (div bit_info-div_bit) 0xf; sub_clk = sclk / (sub_div + 1); - /* Pre-ratio clock division for SDMMC0 and 2 */ - if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) { + if (bit_info-prediv_bit = 0) { div = (div bit_info-prediv_bit) 0xff; return sub_clk / (div + 1); } @@ -1766,7 +1768,7 @@ unsigned long get_arm_clk(void) unsigned long get_i2c_clk(void) { if (cpu_is_exynos5()) { - return exynos5_get_i2c_clk(); + return clock_get_periph_rate(PERIPH_ID_I2C0); } else if (cpu_is_exynos4()) { return exynos4_get_i2c_clk(); } else { @@ -1778,8 +1780,6 @@ unsigned long get_i2c_clk(void) unsigned long get_pwm_clk(void) { if (cpu_is_exynos5()) { - if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_pwm_clk(); return clock_get_periph_rate(PERIPH_ID_PWM0); } else { if (proid_is_exynos4412()) @@ -1790,10 +1790,28 @@ unsigned long get_pwm_clk(void) unsigned long get_uart_clk(int dev_index) { + enum periph_id id; + + switch (dev_index) { + case 0: + id = PERIPH_ID_UART0; + break; + case 1: + id = PERIPH_ID_UART1; + break; + case 2: + id = PERIPH_ID_UART2; + break; + case 3: + id = PERIPH_ID_UART3; + break; + default: + debug(%s: invalid UART index %d, __func__, dev_index); + return -1; + } + if (cpu_is_exynos5()) { - if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_uart_clk(dev_index); - return exynos5_get_uart_clk(dev_index); + return clock_get_periph_rate(id); } else { if (proid_is_exynos4412()) return exynos4x12_get_uart_clk(dev_index); @@ -1803,10 +1821,28 @@ unsigned long get_uart_clk(int dev_index) unsigned long get_mmc_clk(int dev_index) { + enum periph_id id; + + switch (dev_index) { + case 0: + id = PERIPH_ID_SDMMC0; + break; + case 1: + id = PERIPH_ID_SDMMC1; + break; + case 2: + id = PERIPH_ID_SDMMC2; + break; + case 3: + id = PERIPH_ID_SDMMC3; + break; + default: + debug(%s: invalid MMC index %d, __func__, dev_index); + return -1; + } + if (cpu_is_exynos5()) { - if (proid_is_exynos5420() || proid_is_exynos5800()) - return exynos5420_get_mmc_clk(dev_index); - return exynos5_get_mmc_clk(dev_index); + return clock_get_periph_rate(id); } else { return exynos4_get_mmc_clk(dev_index); } -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 1/4] Exynos5: Fix compiler warnings due to clock_get_periph_rate
Apparently, members of clk_bit_info array do not map correctly to the members of enum periph_id. This mapping got broken after we changed periph_id(s) to reflect interrupt number instead of their position in a sequence. This patch intends to fix above mentioned issue. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/clock.c | 81 --- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index b31c13b..863974a 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -20,42 +20,49 @@ * positions of the peripheral clocks of the src and div registers */ struct clk_bit_info { + enum periph_id id; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* src_bit div_bit prediv_bit */ +/* periph_id src_bit div_bit prediv_bit */ static struct clk_bit_info clk_bit_info[] = { - {0, 0, -1}, - {4, 4, -1}, - {8, 8, -1}, - {12,12, -1}, - {0, 0, 8}, - {4, 16, 24}, - {8, 0, 8}, - {12,16, 24}, - {-1,-1, -1}, - {16,0, 8}, - {20,16, 24}, - {24,0, 8}, - {0, 0, 4}, - {4, 12, 16}, - {-1,-1, -1}, - {-1,-1, -1}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, + {PERIPH_ID_UART0, 0, 0, -1}, + {PERIPH_ID_UART1, 4, 4, -1}, + {PERIPH_ID_UART2, 8, 8, -1}, + {PERIPH_ID_UART3, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 24, 0}, + {PERIPH_ID_SPI0,16, 0, 8}, + {PERIPH_ID_SPI1,20, 16, 24}, + {PERIPH_ID_SPI2,24, 0, 8}, + {PERIPH_ID_SDMMC0, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 12, 16, 24}, + {PERIPH_ID_I2C8,-1, -1, -1}, + {PERIPH_ID_I2C9,-1, -1, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SROMC, -1, -1, -1}, + {PERIPH_ID_SPI3,0, 0, 4}, + {PERIPH_ID_SPI4,4, 12, 16}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 0, -1}, + {PERIPH_ID_PWM1,24, 0, -1}, + {PERIPH_ID_PWM2,24, 0, -1}, + {PERIPH_ID_PWM3,24, 0, -1}, + {PERIPH_ID_PWM4,24, 0, -1}, + {PERIPH_ID_I2C10, -1, -1, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, }; /* Epll Clock division values to achive different frequency output */ @@ -260,9 +267,21 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +static struct clk_bit_info *get_clk_bit_info(int peripheral) +{ + int i; + + for (i = 0; exynos5_bit_info[i].id != PERIPH_ID_NONE; i++) { + if (exynos5_bit_info[i].id == peripheral) + break; + } + + return exynos5_bit_info[i]; +} + static unsigned long exynos5_get_periph_rate(int peripheral) { - struct clk_bit_info *bit_info = clk_bit_info[peripheral]; + struct clk_bit_info *bit_info = get_clk_bit_info(peripheral); unsigned long sclk, sub_clk; unsigned int src, div, sub_div; struct exynos5_clock *clk = -- 1.9.1 ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 2/4] Exynos542x: Add and enable get_periph_rate support
We planned to fetch peripheral rate through one generic API per peripheral. These generic peripheral functions are in turn expected to fetch apt values from a function refactored as per SoC versions. This patch adds suuport for fetching peripheral rates for Exynos5420 and Exynos5800. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/clock.c | 211 +++-- arch/arm/include/asm/arch-exynos/clk.h | 8 ++ 2 files changed, 183 insertions(+), 36 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 863974a..9ac4579 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -27,7 +27,7 @@ struct clk_bit_info { }; /* periph_id src_bit div_bit prediv_bit */ -static struct clk_bit_info clk_bit_info[] = { +static struct clk_bit_info exynos5_bit_info[] = { {PERIPH_ID_UART0, 0, 0, -1}, {PERIPH_ID_UART1, 4, 4, -1}, {PERIPH_ID_UART2, 8, 8, -1}, @@ -65,6 +65,44 @@ static struct clk_bit_info clk_bit_info[] = { {PERIPH_ID_NONE,-1, -1, -1}, }; +static struct clk_bit_info exynos542x_bit_info[] = { + {PERIPH_ID_UART0, 4, 8, -1}, + {PERIPH_ID_UART1, 8, 12, -1}, + {PERIPH_ID_UART2, 12, 16, -1}, + {PERIPH_ID_UART3, 16, 20, -1}, + {PERIPH_ID_I2C0,-1, 8, -1}, + {PERIPH_ID_I2C1,-1, 8, -1}, + {PERIPH_ID_I2C2,-1, 8, -1}, + {PERIPH_ID_I2C3,-1, 8, -1}, + {PERIPH_ID_I2C4,-1, 8, -1}, + {PERIPH_ID_I2C5,-1, 8, -1}, + {PERIPH_ID_I2C6,-1, 8, -1}, + {PERIPH_ID_I2C7,-1, 8, -1}, + {PERIPH_ID_SPI0,20, 20, 8}, + {PERIPH_ID_SPI1,24, 24, 16}, + {PERIPH_ID_SPI2,28, 28, 24}, + {PERIPH_ID_SDMMC0, 0, 0, -1}, + {PERIPH_ID_SDMMC1, 4, 10, -1}, + {PERIPH_ID_SDMMC2, 8, 20, -1}, + {PERIPH_ID_SDMMC3, -1, -1, -1}, + {PERIPH_ID_I2C8,-1, 8, -1}, + {PERIPH_ID_I2C9,-1, 8, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SROMC, -1, -1, -1}, + {PERIPH_ID_SPI3,12, 16, 0}, + {PERIPH_ID_SPI4,16, 20, 8}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 28, -1}, + {PERIPH_ID_PWM1,24, 28, -1}, + {PERIPH_ID_PWM2,24, 28, -1}, + {PERIPH_ID_PWM3,24, 28, -1}, + {PERIPH_ID_PWM4,24, 28, -1}, + {PERIPH_ID_I2C10, -1, 8, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, +}; + /* Epll Clock division values to achive different frequency output */ static struct set_epll_con_val exynos5_epll_div[] = { { 19200, 0, 48, 3, 1, 0 }, @@ -267,16 +305,62 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +/* exynos5420: return pll clock frequency */ +static unsigned long exynos5420_get_pll_clk(int pllreg) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)samsung_get_base_clock(); + unsigned long r, k = 0; + + switch (pllreg) { + case APLL: + r = readl(clk-apll_con0); + break; + case MPLL: + r = readl(clk-mpll_con0); + break; + case EPLL: + r = readl(clk-epll_con0); + k = readl(clk-epll_con1); + break; + case VPLL: + r = readl(clk-vpll_con0); + k = readl(clk-vpll_con1); + break; + case BPLL: + r = readl(clk-bpll_con0); + break; + case RPLL: + r = readl(clk-rpll_con0); + k = readl(clk-rpll_con1); + break; + case SPLL: + r = readl(clk-spll_con0); + break; + default: + printf(Unsupported PLL (%d)\n, pllreg); + return 0; + } + + return exynos_get_pll_clk(pllreg, r, k); +} + static struct clk_bit_info *get_clk_bit_info(int peripheral) { int i; + struct clk_bit_info *info; + + if (proid_is_exynos5420() || proid_is_exynos5800()) + info = exynos542x_bit_info; + else + info = exynos5_bit_info; - for (i = 0; exynos5_bit_info[i].id != PERIPH_ID_NONE; i++) { - if (exynos5_bit_info[i].id == peripheral) + for (i = 0; info[i].id != PERIPH_ID_NONE; i++) { + if (info[i].id == peripheral
[U-Boot] [PATCH 4/4] Exynos5: Remove dead code for fetching clocks
Removing dead code of peripheral and SoC specific function implementations which was used for fetching peripheral clocks. This code is not being used anymore because of the introduction of generic clock_get_periph_rate function. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/clock.c | 226 -- 1 file changed, 226 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 9c719aa..41af3a6 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -687,27 +687,6 @@ static unsigned long exynos4x12_get_pwm_clk(void) return pclk; } -/* exynos5420: return pwm clock frequency */ -static unsigned long exynos5420_get_pwm_clk(void) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long pclk, sclk; - unsigned int ratio; - - /* -* CLK_DIV_PERIC0 -* PWM_RATIO [31:28] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio 28) 0xf; - sclk = get_pll_clk(MPLL); - - pclk = sclk / (ratio + 1); - - return pclk; -} - /* exynos4: return uart clock frequency */ static unsigned long exynos4_get_uart_clk(int dev_index) { @@ -800,100 +779,6 @@ static unsigned long exynos4x12_get_uart_clk(int dev_index) return uclk; } -/* exynos5: return uart clock frequency */ -static unsigned long exynos5_get_uart_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [3:0] -* UART1_SEL [7:4] -* UART2_SEL [8:11] -* UART3_SEL [12:15] -* UART4_SEL [16:19] -* UART5_SEL [23:20] -*/ - sel = readl(clk-src_peric0); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel == 0x7) - sclk = get_pll_clk(EPLL); - else if (sel == 0x8) - sclk = get_pll_clk(VPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [3:0] -* UART1_RATIO [7:4] -* UART2_RATIO [8:11] -* UART3_RATIO [12:15] -* UART4_RATIO [16:19] -* UART5_RATIO [23:20] -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio (dev_index 2)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - -/* exynos5420: return uart clock frequency */ -static unsigned long exynos5420_get_uart_clk(int dev_index) -{ - struct exynos5420_clock *clk = - (struct exynos5420_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel; - unsigned int ratio; - - /* -* CLK_SRC_PERIC0 -* UART0_SEL [6:4] -* UART1_SEL [10:8] -* UART2_SEL [14:12] -* UART3_SEL [18:16] -* generalised calculation as follows -* sel = (sel ((dev_index * 4) + 4)) mask; -*/ - sel = readl(clk-src_peric0); - sel = (sel ((dev_index * 4) + 4)) 0x7; - - if (sel == 0x3) - sclk = get_pll_clk(MPLL); - else if (sel == 0x6) - sclk = get_pll_clk(EPLL); - else if (sel == 0x7) - sclk = get_pll_clk(RPLL); - else - return 0; - - /* -* CLK_DIV_PERIC0 -* UART0_RATIO [11:8] -* UART1_RATIO [15:12] -* UART2_RATIO [19:16] -* UART3_RATIO [23:20] -* generalised calculation as follows -* ratio = (ratio ((dev_index * 4) + 8)) mask; -*/ - ratio = readl(clk-div_peric0); - ratio = (ratio ((dev_index * 4) + 8)) 0xf; - - uclk = sclk / (ratio + 1); - - return uclk; -} - static unsigned long exynos4_get_mmc_clk(int dev_index) { struct exynos4_clock *clk = @@ -943,94 +828,6 @@ static unsigned long exynos4_get_mmc_clk(int dev_index) return uclk; } -static unsigned long exynos5_get_mmc_clk(int dev_index) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned long uclk, sclk; - unsigned int sel, ratio, pre_ratio; - int shift = 0; - - sel = readl(clk-src_fsys); - sel = (sel (dev_index 2)) 0xf; - - if (sel == 0x6) - sclk = get_pll_clk(MPLL); - else if (sel == 0x7) - sclk = get_pll_clk(EPLL); - else if (sel == 0x8) - sclk = get_pll_clk(VPLL); - else - return 0; - - switch (dev_index) { - case 0: - case 1: - ratio = readl(clk-div_fsys1); - pre_ratio = readl(clk-div_fsys1); - break; - case 2: - case 3
[U-Boot] [PATCH] Exynos: Fix warnings from clock_get_periph_rate
Apparently, members of clk_bit_info array do not map correctly to the members of enum periph_id. This mapping got broken after we changed periph_id(s) to reflect interrupt number instead of their position in a sequence. This patch intends to fix above mentioned issue and add get_periph_rate for Exynos5420. Signed-off-by: Akshay Saraswat aksha...@samsung.com --- arch/arm/cpu/armv7/exynos/clock.c | 574 - arch/arm/include/asm/arch-exynos/clk.h | 8 + 2 files changed, 279 insertions(+), 303 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index b31c13b..1f201e2 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -20,42 +20,87 @@ * positions of the peripheral clocks of the src and div registers */ struct clk_bit_info { + enum periph_id id; int8_t src_bit; int8_t div_bit; int8_t prediv_bit; }; -/* src_bit div_bit prediv_bit */ -static struct clk_bit_info clk_bit_info[] = { - {0, 0, -1}, - {4, 4, -1}, - {8, 8, -1}, - {12,12, -1}, - {0, 0, 8}, - {4, 16, 24}, - {8, 0, 8}, - {12,16, 24}, - {-1,-1, -1}, - {16,0, 8}, - {20,16, 24}, - {24,0, 8}, - {0, 0, 4}, - {4, 12, 16}, - {-1,-1, -1}, - {-1,-1, -1}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {-1,24, 0}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, - {24,0, -1}, +/* periph_id src_bit div_bit prediv_bit */ +static struct clk_bit_info exynos5_bit_info[] = { + {PERIPH_ID_UART0, 0, 0, -1}, + {PERIPH_ID_UART1, 4, 4, -1}, + {PERIPH_ID_UART2, 8, 8, -1}, + {PERIPH_ID_UART3, 12, 12, -1}, + {PERIPH_ID_I2C0,-1, 24, 0}, + {PERIPH_ID_I2C1,-1, 24, 0}, + {PERIPH_ID_I2C2,-1, 24, 0}, + {PERIPH_ID_I2C3,-1, 24, 0}, + {PERIPH_ID_I2C4,-1, 24, 0}, + {PERIPH_ID_I2C5,-1, 24, 0}, + {PERIPH_ID_I2C6,-1, 24, 0}, + {PERIPH_ID_I2C7,-1, 24, 0}, + {PERIPH_ID_SPI0,16, 0, 8}, + {PERIPH_ID_SPI1,20, 16, 24}, + {PERIPH_ID_SPI2,24, 0, 8}, + {PERIPH_ID_SDMMC0, 0, 0, 8}, + {PERIPH_ID_SDMMC1, 4, 16, 24}, + {PERIPH_ID_SDMMC2, 8, 0, 8}, + {PERIPH_ID_SDMMC3, 12, 16, 24}, + {PERIPH_ID_I2C8,-1, -1, -1}, + {PERIPH_ID_I2C9,-1, -1, -1}, + {PERIPH_ID_I2S0,0, 0, 4}, + {PERIPH_ID_I2S1,4, 12, 16}, + {PERIPH_ID_SROMC, -1, -1, -1}, + {PERIPH_ID_SPI3,0, 0, 4}, + {PERIPH_ID_SPI4,4, 12, 16}, + {PERIPH_ID_SDMMC4, 16, 0, 8}, + {PERIPH_ID_PWM0,24, 0, -1}, + {PERIPH_ID_PWM1,24, 0, -1}, + {PERIPH_ID_PWM2,24, 0, -1}, + {PERIPH_ID_PWM3,24, 0, -1}, + {PERIPH_ID_PWM4,24, 0, -1}, + {PERIPH_ID_I2C10, -1, -1, -1}, + + {PERIPH_ID_NONE,-1, -1, -1}, +}; + +static struct clk_bit_info exynos542x_bit_info[] = { + {PERIPH_ID_UART0, 4, 8, -1}, + {PERIPH_ID_UART1, 8, 12, -1}, + {PERIPH_ID_UART2, 12, 16, -1}, + {PERIPH_ID_UART3, 16, 20, -1}, + {PERIPH_ID_I2C0,-1, 8, -1}, + {PERIPH_ID_I2C1,-1, 8, -1}, + {PERIPH_ID_I2C2,-1, 8, -1}, + {PERIPH_ID_I2C3,-1, 8, -1}, + {PERIPH_ID_I2C4,-1, 8, -1}, + {PERIPH_ID_I2C5,-1, 8, -1}, + {PERIPH_ID_I2C6,-1, 8, -1}, + {PERIPH_ID_I2C7,-1, 8, -1}, + {PERIPH_ID_SPI0,20, 20, 8}, + {PERIPH_ID_SPI1,24, 24, 16}, + {PERIPH_ID_SPI2,28, 28, 24}, + {PERIPH_ID_SDMMC0, 0, 0, -1}, + {PERIPH_ID_SDMMC1, 4, 10, -1}, + {PERIPH_ID_SDMMC2, 8, 20, -1}, + {PERIPH_ID_SDMMC3, -1, -1, -1}, + {PERIPH_ID_I2C8,-1, 8, -1}, + {PERIPH_ID_I2C9,-1, 8, -1}, + {PERIPH_ID_I2S0,0, 0, 4
Re: [U-Boot] [PATCH 08/18] exynos5: config: prepare for dm i2c support
Hi Przemyslaw, Hello Akshay, On 01/09/2015 10:21 AM, Akshay Saraswat wrote: Hi Przemyslaw, This commit allows for test i2c drivers with new i2c api on Exynos5xxx based boards. The S3C24X0 I2C driver supports driver model I2C api, but i2c peripherials drivers on exynos5 boards doesn't. So this commit allows for test ported driver before switch the Exynos5 boards to DM I2C at all. Signed-off-by: Przemyslaw Marczak p.marc...@samsung.com Cc: Akshay Saraswat aksha...@samsung.com Cc: Simon Glass s...@chromium.org Cc: Minkyu Kang mk7.k...@samsung.com --- include/configs/exynos5-common.h | 29 ++--- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index ad63f3c..b7af8a5 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -54,13 +54,6 @@ #define CONFIG_CMD_DTT #define CONFIG_TMU_CMD_DTT -/* TPM */ -#define CONFIG_TPM -#define CONFIG_CMD_TPM -#define CONFIG_TPM_TIS_I2C -#define CONFIG_TPM_TIS_I2C_BUS_NUMBER 3 -#define CONFIG_TPM_TIS_I2C_SLAVE_ADDR 0x20 - /* MMC SPL */ #define COPY_BL2_FNPTR_ADDR 0x02020030 #define CONFIG_SUPPORT_EMMC_BOOT @@ -126,15 +119,29 @@ #define SPI_FLASH_UBOOT_POS (CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE) /* I2C */ -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_SYS_I2C +#if 0 /* For test */ Quick test over SMDK 5250 after replacing #if 0 - 1. Looks like there is some problem in changing bus beyond 7. Please check. Console prints are as follows - SMDK5250 # i2c dev 8 Setting bus to 8 Failure changing bus number (-19) exit not allowed from main input shell. I think that this is right, because, the defined buses are: - exynos5.dtsi - 0, 1, 2, 3 (periph_id: 56, 57, 58, 59), - exynos5250.dtsi - 4, 5, 6, 7 (periph_id: 60, 61, 62, 63) but there are no additional i2c nodes in exynos5250-smdk5250.dts file. So, you can use only i2c bus 0:7. The additional i2c bus nodes are defined in: - exynos54xx.dtsi - 8, 9, 10 (periph_id: 87, 88, 203), So for exynos54xx boards we can switch between i2c 0:10. Yes, you are right, I didn't refer UM. We need only 0-7 for 5250. +#define CONFIG_DM_I2C +#endif #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C_S3C24X0_SPEED 10 /* 100 Kbps */ #define CONFIG_SYS_I2C_S3C24X0 -#define CONFIG_I2C_MULTI_BUS +#define CONFIG_SYS_I2C_S3C24X0_SPEED 10 /* 100 Kbps */ #define CONFIG_SYS_I2C_S3C24X0_SLAVE0x0 +#ifndef CONFIG_DM_I2C +#define CONFIG_SYS_I2C_INIT_BOARD +#define CONFIG_SYS_I2C +#define CONFIG_I2C_MULTI_BUS +#endif /* ifndef CONFIG_DM_I2C */ #define CONFIG_I2C_EDID +/* TPM */ +#ifndef CONFIG_DM_I2C +#define CONFIG_TPM +#define CONFIG_CMD_TPM +#define CONFIG_TPM_TIS_I2C +#define CONFIG_TPM_TIS_I2C_BUS_NUMBER 3 +#define CONFIG_TPM_TIS_I2C_SLAVE_ADDR 0x20 +#endif + /* SPI */ #ifdef CONFIG_SPI_FLASH #define CONFIG_EXYNOS_SPI -- 1.9.1 Regards, Akshay Saraswat So if you would like to use i2c 8, then please add proper nodes to dts - but please notice that the reg addresses are different for 5250/54xx. Best regards, -- Przemyslaw Marczak Samsung RD Institute Poland Samsung Electronics p.marc...@samsung.com Regards, Akshay Saraswat ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] Question about compile warnings of exynos clock
Hi, Hi, On 01/13/2015 11:56 AM, Simon Glass wrote: Hi, On 12 January 2015 at 18:51, Joonyoung Shim jy0922.s...@samsung.com wrote: Hi, On 01/13/2015 11:47 AM, Simon Glass wrote: Hi, On 12 January 2015 at 18:36, Joonyoung Shim jy0922.s...@samsung.com wrote: Hi, On 01/13/2015 11:27 AM, Simon Glass wrote: Hi, On 12 January 2015 at 18:24, Joonyoung Shim jy0922.s...@samsung.com wrote: Hi, I found below compile warnings, CC arch/arm/cpu/armv7/exynos/clock.o arch/arm/cpu/armv7/exynos/clock.c: In function .clock_get_periph_rate.: arch/arm/cpu/armv7/exynos/clock.c:265:47: warning: array subscript is above array bounds [-Warray-bounds] struct clk_bit_info *bit_info = clk_bit_info[peripheral]; ^ arch/arm/cpu/armv7/exynos/clock.c:265:47: warning: array subscript is above array bounds [-Warray-bounds] ... static unsigned long exynos5_get_periph_rate(int peripheral) { struct clk_bit_info *bit_info = clk_bit_info[peripheral]; This can access out of bounds of clk_bit_info[] array from exynos5_get_periph_rate(). The peripheral value comes from enum periph_id but it gets out of count clk_bit_info[] array. So, i don't think exynos5_get_periph_rate is working correctly. Currently, exynos5_get_periph_rate is used by clock_get_periph_rate only from get_pwm_clk. Is it ongoing to work for generic api to get the clk freq? If not, let's remove exynos5_get_periph_rate and clock_get_periph_rate. That's going in the wrong direction - these functions make the code much easier to follow and refactor. We should remove get_pwm_clk(), get_mmc_clk() etc. and use generic functions instead. I know, but current codes are wrong, so first i want to correct it even if it is old way because it's really easy. And then we can go to generic functions. So not remove the generic functions? Is it this line which is broken? clock_get_periph_rate(PERIPH_ID_PWM0); If so, it seems like everything else uses its own function. It should all move easily to the generic function I think. The basic problem is the generic function is wrong. Oh dear, does it not work for anything? I have posted the patch relevant to this. I removed the generic peripheral clock API. It's not used anywhere. Just get clock for pwm0. how about? https://patchwork.ozlabs.org/patch/426535/ I dont think it's a good idea to remove this function and expect to put in same effort again in future. Instead, fixing this warning should be easier. By the way, I don't see the mentioned warning when I compile ToT u-boot-samsung for smdk5250 and smdk5420 with arm-2011.09 compiler. Do we need any other patch or config to encounter this? Best Regards, Jaehoon Chung Regards, Simon ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot Regards, Akshay Saraswat ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot