mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-08-31 22:39:08 +09:00
![Doug Anderson](/assets/img/avatar_default.png)
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 <dianders@chromium.org> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com> Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
133 lines
4.2 KiB
C
133 lines
4.2 KiB
C
/*
|
|
* (C) Copyright 2012 Samsung Electronics
|
|
* Donghwa Lee <dh09.lee@samsung.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#ifndef __ASM_ARM_ARCH_SYSTEM_H_
|
|
#define __ASM_ARM_ARCH_SYSTEM_H_
|
|
|
|
#ifndef __ASSEMBLY__
|
|
struct exynos4_sysreg {
|
|
unsigned char res1[0x210];
|
|
unsigned int display_ctrl;
|
|
unsigned int display_ctrl2;
|
|
unsigned int camera_control;
|
|
unsigned int audio_endian;
|
|
unsigned int jtag_con;
|
|
};
|
|
|
|
struct exynos5_sysreg {
|
|
unsigned char res1[0x214];
|
|
unsigned int disp1blk_cfg;
|
|
unsigned int disp2blk_cfg;
|
|
unsigned int hdcp_e_fuse;
|
|
unsigned int gsclblk_cfg0;
|
|
unsigned int gsclblk_cfg1;
|
|
unsigned int reserved;
|
|
unsigned int ispblk_cfg;
|
|
unsigned int usb20phy_cfg;
|
|
unsigned char res2[0x29c];
|
|
unsigned int mipi_dphy;
|
|
unsigned int dptx_dphy;
|
|
unsigned int phyclk_sel;
|
|
};
|
|
#endif
|
|
|
|
#define USB20_PHY_CFG_HOST_LINK_EN (1 << 0)
|
|
|
|
/*
|
|
* Data Synchronization Barrier acts as a special kind of memory barrier.
|
|
* No instruction in program order after this instruction executes until
|
|
* this instruction completes. This instruction completes when:
|
|
* - All explicit memory accesses before this instruction complete.
|
|
* - All Cache, Branch predictor and TLB maintenance operations before
|
|
* this instruction complete.
|
|
*/
|
|
#define dsb() __asm__ __volatile__ ("dsb\n\t" : : );
|
|
|
|
/*
|
|
* This instruction causes an event to be signaled to all cores
|
|
* within a multiprocessor system. If SEV is implemented,
|
|
* WFE must also be implemented.
|
|
*/
|
|
#define sev() __asm__ __volatile__ ("sev\n\t" : : );
|
|
/*
|
|
* If the Event Register is not set, WFE suspends execution until
|
|
* one of the following events occurs:
|
|
* - an IRQ interrupt, unless masked by the CPSR I-bit
|
|
* - an FIQ interrupt, unless masked by the CPSR F-bit
|
|
* - an Imprecise Data abort, unless masked by the CPSR A-bit
|
|
* - a Debug Entry request, if Debug is enabled
|
|
* - an Event signaled by another processor using the SEV instruction.
|
|
* If the Event Register is set, WFE clears it and returns immediately.
|
|
* If WFE is implemented, SEV must also be implemented.
|
|
*/
|
|
#define wfe() __asm__ __volatile__ ("wfe\n\t" : : );
|
|
|
|
/* Move 0xd3 value to CPSR register to enable SVC mode */
|
|
#define svc32_mode_en() __asm__ __volatile__ \
|
|
("@ I&F disable, Mode: 0x13 - SVC\n\t" \
|
|
"msr cpsr_c, #0x13|0xC0\n\t" : : )
|
|
|
|
/* 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) : )
|
|
|
|
/* Read Multiprocessor Affinity Register */
|
|
#define mrc_mpafr(x) __asm__ __volatile__ \
|
|
("mrc p15, 0, %0, c0, c0, 5\n\t" : "=r"(x) : )
|
|
|
|
/* Read System Control Register */
|
|
#define mrc_sctlr(x) __asm__ __volatile__ \
|
|
("mrc p15, 0, %0, c1, c0, 0\n\t" : "=r"(x) : )
|
|
|
|
/* Read Auxiliary Control Register */
|
|
#define mrc_auxr(x) __asm__ __volatile__ \
|
|
("mrc p15, 0, %0, c1, c0, 1\n\t" : "=r"(x) : )
|
|
|
|
/* Read L2 Control register */
|
|
#define mrc_l2_ctlr(x) __asm__ __volatile__ \
|
|
("mrc p15, 1, %0, c9, c0, 2\n\t" : "=r"(x) : )
|
|
|
|
/* Read L2 Auxilliary Control register */
|
|
#define mrc_l2_aux_ctlr(x) __asm__ __volatile__ \
|
|
("mrc p15, 1, %0, c15, c0, 0\n\t" : "=r"(x) : )
|
|
|
|
/* Write System Control Register */
|
|
#define mcr_sctlr(x) __asm__ __volatile__ \
|
|
("mcr p15, 0, %0, c1, c0, 0\n\t" : : "r"(x))
|
|
|
|
/* Write Auxiliary Control Register */
|
|
#define mcr_auxr(x) __asm__ __volatile__ \
|
|
("mcr p15, 0, %0, c1, c0, 1\n\t" : : "r"(x))
|
|
|
|
/* Invalidate all instruction caches to PoU */
|
|
#define mcr_icache(x) __asm__ __volatile__ \
|
|
("mcr p15, 0, %0, c7, c5, 0\n\t" : : "r"(x))
|
|
|
|
/* Invalidate unified TLB */
|
|
#define mcr_tlb(x) __asm__ __volatile__ \
|
|
("mcr p15, 0, %0, c8, c7, 0\n\t" : : "r"(x))
|
|
|
|
/* Write L2 Control register */
|
|
#define mcr_l2_ctlr(x) __asm__ __volatile__ \
|
|
("mcr p15, 1, %0, c9, c0, 2\n\t" : : "r"(x))
|
|
|
|
/* Write L2 Auxilliary Control register */
|
|
#define mcr_l2_aux_ctlr(x) __asm__ __volatile__ \
|
|
("mcr p15, 1, %0, c15, c0, 0\n\t" : : "r"(x))
|
|
|
|
void set_usbhost_mode(unsigned int mode);
|
|
void set_system_display_ctrl(void);
|
|
int exynos_lcd_early_init(const void *blob);
|
|
|
|
#endif /* _EXYNOS4_SYSTEM_H */
|