diff --git a/arch/arm/boards/boundarydevices-nitrogen6x/lowlevel.c b/arch/arm/boards/boundarydevices-nitrogen6x/lowlevel.c index 60a84ef63..5371be631 100644 --- a/arch/arm/boards/boundarydevices-nitrogen6x/lowlevel.c +++ b/arch/arm/boards/boundarydevices-nitrogen6x/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -9,7 +10,7 @@ ENTRY_FUNCTION(start_imx6q_nitrogen6x_1g, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); fdt = __dtb_imx6q_nitrogen6x_start - get_runtime_offset(); @@ -22,7 +23,7 @@ ENTRY_FUNCTION(start_imx6dl_nitrogen6x_1g, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); fdt = __dtb_imx6dl_nitrogen6x_start - get_runtime_offset(); diff --git a/arch/arm/boards/datamodul-edm-qmx6/lowlevel.c b/arch/arm/boards/datamodul-edm-qmx6/lowlevel.c index b1ce4e9df..914c275b8 100644 --- a/arch/arm/boards/datamodul-edm-qmx6/lowlevel.c +++ b/arch/arm/boards/datamodul-edm-qmx6/lowlevel.c @@ -21,6 +21,7 @@ #include #include #include +#include static void sdram_init(void) { @@ -142,7 +143,7 @@ ENTRY_FUNCTION(start_imx6_realq7, r0, r1, r2) unsigned long sdram = 0x10000000; void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00940000 - 8); diff --git a/arch/arm/boards/dfi-fs700-m60/lowlevel.c b/arch/arm/boards/dfi-fs700-m60/lowlevel.c index 541e6c187..81b353046 100644 --- a/arch/arm/boards/dfi-fs700-m60/lowlevel.c +++ b/arch/arm/boards/dfi-fs700-m60/lowlevel.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -106,7 +107,7 @@ ENTRY_FUNCTION(start_imx6q_dfi_fs700_m60_6q_nanya, r0, r1, r2) void *fdt; int i; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00940000 - 8); @@ -125,7 +126,7 @@ ENTRY_FUNCTION(start_imx6q_dfi_fs700_m60_6q_micron, r0, r1, r2) void *fdt; int i; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00940000 - 8); @@ -148,7 +149,7 @@ ENTRY_FUNCTION(start_imx6dl_dfi_fs700_m60_6s, r0, r1, r2) void *fdt; int i; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); diff --git a/arch/arm/boards/embest-riotboard/lowlevel.c b/arch/arm/boards/embest-riotboard/lowlevel.c index 64edd61cc..c4ef28786 100644 --- a/arch/arm/boards/embest-riotboard/lowlevel.c +++ b/arch/arm/boards/embest-riotboard/lowlevel.c @@ -30,7 +30,7 @@ ENTRY_FUNCTION(start_imx6s_riotboard, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); if (IS_ENABLED(CONFIG_DEBUG_LL)) { writel(0x4, 0x020e016c); diff --git a/arch/arm/boards/freescale-mx6-arm2/lowlevel.c b/arch/arm/boards/freescale-mx6-arm2/lowlevel.c index 53783bb0a..5676711a1 100644 --- a/arch/arm/boards/freescale-mx6-arm2/lowlevel.c +++ b/arch/arm/boards/freescale-mx6-arm2/lowlevel.c @@ -2,9 +2,10 @@ #include #include #include +#include void __naked barebox_arm_reset_vector(void) { - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); barebox_arm_entry(0x10000000, SZ_2G, NULL); } diff --git a/arch/arm/boards/freescale-mx6-sabrelite/lowlevel.c b/arch/arm/boards/freescale-mx6-sabrelite/lowlevel.c index a154381bf..1b4796571 100644 --- a/arch/arm/boards/freescale-mx6-sabrelite/lowlevel.c +++ b/arch/arm/boards/freescale-mx6-sabrelite/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -9,7 +10,7 @@ ENTRY_FUNCTION(start_imx6q_sabrelite, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); fdt = __dtb_imx6q_sabrelite_start - get_runtime_offset(); @@ -22,7 +23,7 @@ ENTRY_FUNCTION(start_imx6dl_sabrelite, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); fdt = __dtb_imx6dl_sabrelite_start - get_runtime_offset(); diff --git a/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c b/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c index 325de8498..bf1845912 100644 --- a/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c +++ b/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -9,7 +10,7 @@ ENTRY_FUNCTION(start_imx6q_sabresd, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); fdt = __dtb_imx6q_sabresd_start - get_runtime_offset(); diff --git a/arch/arm/boards/gk802/lowlevel.c b/arch/arm/boards/gk802/lowlevel.c index bfedfb6c9..de744a205 100644 --- a/arch/arm/boards/gk802/lowlevel.c +++ b/arch/arm/boards/gk802/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -9,7 +10,7 @@ ENTRY_FUNCTION(start_imx6_gk802, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); fdt = __dtb_imx6q_gk802_start - get_runtime_offset(); barebox_arm_entry(0x10000000, SZ_1G, fdt); diff --git a/arch/arm/boards/guf-santaro/lowlevel.c b/arch/arm/boards/guf-santaro/lowlevel.c index daf9709df..02de84c7b 100644 --- a/arch/arm/boards/guf-santaro/lowlevel.c +++ b/arch/arm/boards/guf-santaro/lowlevel.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,7 @@ ENTRY_FUNCTION(start_imx6q_guf_santaro, r0, r1, r2) void *fdt; int i; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); diff --git a/arch/arm/boards/phytec-phycard-imx6/lowlevel.c b/arch/arm/boards/phytec-phycard-imx6/lowlevel.c index 64312b024..b31638cbb 100644 --- a/arch/arm/boards/phytec-phycard-imx6/lowlevel.c +++ b/arch/arm/boards/phytec-phycard-imx6/lowlevel.c @@ -59,7 +59,7 @@ static void __noreturn start_imx6q_phytec_pbaa03_common(uint32_t size) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); diff --git a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c index 0159d9f1b..55aae0095 100644 --- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c +++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c @@ -61,7 +61,7 @@ ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); @@ -77,7 +77,7 @@ ENTRY_FUNCTION(start_phytec_pbab01_2gib, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); @@ -93,7 +93,7 @@ ENTRY_FUNCTION(start_phytec_pbab01_4gib, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); @@ -106,7 +106,7 @@ ENTRY_FUNCTION(start_phytec_pbab01dl_1gib, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); @@ -119,7 +119,7 @@ ENTRY_FUNCTION(start_phytec_pbab01s_512mb, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); diff --git a/arch/arm/boards/solidrun-hummingboard/lowlevel.c b/arch/arm/boards/solidrun-hummingboard/lowlevel.c index 8710d85c7..eb5283896 100644 --- a/arch/arm/boards/solidrun-hummingboard/lowlevel.c +++ b/arch/arm/boards/solidrun-hummingboard/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -9,7 +10,7 @@ ENTRY_FUNCTION(start_imx6dl_hummingboard, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); fdt = __dtb_imx6dl_hummingboard_start - get_runtime_offset(); barebox_arm_entry(0x10000000, SZ_512M, fdt); diff --git a/arch/arm/boards/tqma6x/lowlevel.c b/arch/arm/boards/tqma6x/lowlevel.c index aed95e6fc..d2eea16c2 100644 --- a/arch/arm/boards/tqma6x/lowlevel.c +++ b/arch/arm/boards/tqma6x/lowlevel.c @@ -45,7 +45,7 @@ ENTRY_FUNCTION(start_imx6q_mba6x, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); @@ -66,7 +66,7 @@ ENTRY_FUNCTION(start_imx6dl_mba6x, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); diff --git a/arch/arm/boards/udoo/lowlevel.c b/arch/arm/boards/udoo/lowlevel.c index 5eac7a3bc..3d9fc68ca 100644 --- a/arch/arm/boards/udoo/lowlevel.c +++ b/arch/arm/boards/udoo/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -9,7 +10,7 @@ ENTRY_FUNCTION(start_imx6_udoo, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); fdt = __dtb_imx6q_udoo_start - get_runtime_offset(); diff --git a/arch/arm/boards/variscite-mx6/lowlevel.c b/arch/arm/boards/variscite-mx6/lowlevel.c index a2c0874d8..74f3a779e 100644 --- a/arch/arm/boards/variscite-mx6/lowlevel.c +++ b/arch/arm/boards/variscite-mx6/lowlevel.c @@ -61,7 +61,7 @@ ENTRY_FUNCTION(start_variscite_custom, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx6_cpu_lowlevel_init(); arm_setup_stack(0x00920000 - 8); diff --git a/arch/arm/include/asm/errata.h b/arch/arm/include/asm/errata.h new file mode 100644 index 000000000..e2ffd8736 --- /dev/null +++ b/arch/arm/include/asm/errata.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014 Lucas Stach, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +static inline void enable_arm_errata_716044_war(void) +{ + __asm__ __volatile__ ( + "mrc p15, 0, r0, c1, c0, 0\n" + "orr r0, r0, #1 << 11\n" + "mcr p15, 0, r0, c1, c0, 0\n" + ); +} + +static inline void enable_arm_errata_742230_war(void) +{ + __asm__ __volatile__ ( + "mrc p15, 0, r0, c15, c0, 1\n" + "orr r0, r0, #1 << 4\n" + "mcr p15, 0, r0, c15, c0, 1\n" + ); +} + +static inline void enable_arm_errata_743622_war(void) +{ + __asm__ __volatile__ ( + "mrc p15, 0, r0, c15, c0, 1\n" + "orr r0, r0, #1 << 6\n" + "mcr p15, 0, r0, c15, c0, 1\n" + ); +} + +static inline void enable_arm_errata_751472_war(void) +{ + __asm__ __volatile__ ( + "mrc p15, 0, r0, c15, c0, 1\n" + "orr r0, r0, #1 << 11\n" + "mcr p15, 0, r0, c15, c0, 1\n" + ); +} + +static inline void enable_arm_errata_761320_war(void) +{ + __asm__ __volatile__ ( + "mrc p15, 0, r0, c15, c0, 1\n" + "orr r0, r0, #1 << 21\n" + "mcr p15, 0, r0, c15, c0, 1\n" + ); +} + +static inline void enable_arm_errata_794072_war(void) +{ + __asm__ __volatile__ ( + "mrc p15, 0, r0, c15, c0, 1\n" + "orr r0, r0, #1 << 4\n" + "mcr p15, 0, r0, c15, c0, 1\n" + ); +} diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 03e5b102f..1d311a417 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o obj-$(CONFIG_BAREBOX_UPDATE_IMX6_NAND) += imx6-bbu-nand.o pbl-y += esdctl.o +lwl-y += cpu_init.o diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c new file mode 100644 index 000000000..68eacf7a6 --- /dev/null +++ b/arch/arm/mach-imx/cpu_init.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2014 Lucas Stach, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +void imx6_cpu_lowlevel_init(void) +{ + arm_cpu_lowlevel_init(); + + enable_arm_errata_742230_war(); + enable_arm_errata_743622_war(); + enable_arm_errata_751472_war(); + enable_arm_errata_761320_war(); + enable_arm_errata_794072_war(); +} diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h index 506b1daaa..505a54268 100644 --- a/arch/arm/mach-imx/include/mach/generic.h +++ b/arch/arm/mach-imx/include/mach/generic.h @@ -33,6 +33,8 @@ int imx51_devices_init(void); int imx53_devices_init(void); int imx6_devices_init(void); +void imx6_cpu_lowlevel_init(void); + /* There's a off-by-one betweem the gpio bank number and the gpiochip */ /* range e.g. GPIO_1_5 is gpio 5 under linux */ #define IMX_GPIO_NR(bank, nr) (((bank) - 1) * 32 + (nr)) diff --git a/arch/arm/mach-tegra/tegra_maincomplex_init.c b/arch/arm/mach-tegra/tegra_maincomplex_init.c index 17490a425..4a362ddba 100644 --- a/arch/arm/mach-tegra/tegra_maincomplex_init.c +++ b/arch/arm/mach-tegra/tegra_maincomplex_init.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,23 @@ void tegra_maincomplex_entry(void) arm_cpu_lowlevel_init(); + chiptype = tegra_get_chiptype(); + + /* enable ARM errata workarounds early */ + switch (chiptype) { + case TEGRA20: + enable_arm_errata_716044_war(); + enable_arm_errata_742230_war(); + enable_arm_errata_751472_war(); + break; + case TEGRA30: + enable_arm_errata_743622_war(); + enable_arm_errata_751472_war(); + break; + default: + break; + } + /* switch to PLLX */ writel(CRC_CCLK_BURST_POLICY_SYS_STATE_RUN << CRC_CCLK_BURST_POLICY_SYS_STATE_SHIFT | @@ -38,8 +56,6 @@ void tegra_maincomplex_entry(void) TEGRA_CLK_RESET_BASE + CRC_CCLK_BURST_POLICY); writel(CRC_SUPER_CDIV_ENB, TEGRA_CLK_RESET_BASE + CRC_SUPER_CCLK_DIV); - chiptype = tegra_get_chiptype(); - if (chiptype >= TEGRA114) { asm("mrc p15, 1, %0, c9, c0, 2" : : "r" (reg)); reg &= ~7; @@ -51,6 +67,7 @@ void tegra_maincomplex_entry(void) case TEGRA20: rambase = 0x0; ramsize = tegra20_get_ramsize(); + break; case TEGRA30: case TEGRA124: