From bca7910b7dad875e3e7d8e45dd41ab8a07e36133 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:15 +0200 Subject: ARM: tegra: Fix mux type for disp1 and disp2 clocks on Tegra210 On Tegra210 the parents for the disp1 and disp2 clocks are slightly different from earlier chips. Only pll_p, pll_d_out0, pll_d2_out0 and clk_m are valid parents (technically pll_d_out is as well, but U-Boot doesn't know anything about it). Fix up the type name and the mux definition. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/tegra210/clock.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/tegra210/clock.c b/arch/arm/mach-tegra/tegra210/clock.c index 06068c4b7b8..0d7cafea201 100644 --- a/arch/arm/mach-tegra/tegra210/clock.c +++ b/arch/arm/mach-tegra/tegra210/clock.c @@ -40,7 +40,7 @@ enum clock_type_id { CLOCK_TYPE_PDCT, CLOCK_TYPE_ACPT, CLOCK_TYPE_ASPTE, - CLOCK_TYPE_PMDACD2T, + CLOCK_TYPE_PDD2T, CLOCK_TYPE_PCST, CLOCK_TYPE_DP, @@ -97,8 +97,8 @@ static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = { { CLK(AUDIO), CLK(SFROM32KHZ), CLK(PERIPH), CLK(OSC), CLK(EPCI), CLK(NONE), CLK(NONE), CLK(NONE), MASK_BITS_31_29}, - { CLK(PERIPH), CLK(MEMORY), CLK(DISPLAY), CLK(AUDIO), - CLK(CGENERAL), CLK(DISPLAY2), CLK(OSC), CLK(NONE), + { CLK(PERIPH), CLK(NONE), CLK(DISPLAY), CLK(NONE), + CLK(NONE), CLK(DISPLAY2), CLK(OSC), CLK(NONE), MASK_BITS_31_29}, { CLK(PERIPH), CLK(CGENERAL), CLK(SFROM32KHZ), CLK(OSC), CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE), @@ -174,8 +174,8 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { TYPE(PERIPHC_0bh, CLOCK_TYPE_NONE), TYPE(PERIPHC_0ch, CLOCK_TYPE_NONE), TYPE(PERIPHC_SBC1, CLOCK_TYPE_PC2CC3M_T), - TYPE(PERIPHC_DISP1, CLOCK_TYPE_PMDACD2T), - TYPE(PERIPHC_DISP2, CLOCK_TYPE_PMDACD2T), + TYPE(PERIPHC_DISP1, CLOCK_TYPE_PDD2T), + TYPE(PERIPHC_DISP2, CLOCK_TYPE_PDD2T), /* 0x10 */ TYPE(PERIPHC_10h, CLOCK_TYPE_NONE), -- cgit v1.2.3 From bf468e5e1ae71c97f01a1ef2e97e18bd5bca40ce Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:16 +0200 Subject: ARM: tegra: Remove disp1 clock initialization on Tegra210 pll_c is not a valid parent for the disp1 clock, so trying to set it will fail. Given that display is not used in U-Boot, remove the init table entry so that disp1 will keep its default parent (clk_m). Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/tegra210/clock.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/tegra210/clock.c b/arch/arm/mach-tegra/tegra210/clock.c index 0d7cafea201..b240860f08c 100644 --- a/arch/arm/mach-tegra/tegra210/clock.c +++ b/arch/arm/mach-tegra/tegra210/clock.c @@ -1265,7 +1265,6 @@ struct periph_clk_init periph_clk_init_table[] = { { PERIPH_ID_SBC5, CLOCK_ID_PERIPH }, { PERIPH_ID_SBC6, CLOCK_ID_PERIPH }, { PERIPH_ID_HOST1X, CLOCK_ID_PERIPH }, - { PERIPH_ID_DISP1, CLOCK_ID_CGENERAL }, { PERIPH_ID_SDMMC1, CLOCK_ID_PERIPH }, { PERIPH_ID_SDMMC2, CLOCK_ID_PERIPH }, { PERIPH_ID_SDMMC3, CLOCK_ID_PERIPH }, -- cgit v1.2.3 From e9c58f2bb855e02d72a003407afe49d632fd4fc5 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:17 +0200 Subject: ARM: tegra: Use common header for PMU declarations There's no need to replicate the pmu.h header file for every Tegra SoC generation. Use a single header that is shared across generations. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/include/asm/arch-tegra/pmu.h | 13 +++++++++++++ arch/arm/include/asm/arch-tegra114/pmu.h | 12 ------------ arch/arm/include/asm/arch-tegra124/pmu.h | 13 ------------- arch/arm/include/asm/arch-tegra20/pmu.h | 13 ------------- arch/arm/include/asm/arch-tegra210/pmu.h | 13 ------------- arch/arm/include/asm/arch-tegra30/pmu.h | 12 ------------ arch/arm/mach-tegra/board2.c | 2 +- arch/arm/mach-tegra/emc.c | 2 +- 8 files changed, 15 insertions(+), 65 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra/pmu.h delete mode 100644 arch/arm/include/asm/arch-tegra114/pmu.h delete mode 100644 arch/arm/include/asm/arch-tegra124/pmu.h delete mode 100644 arch/arm/include/asm/arch-tegra20/pmu.h delete mode 100644 arch/arm/include/asm/arch-tegra210/pmu.h delete mode 100644 arch/arm/include/asm/arch-tegra30/pmu.h (limited to 'arch') diff --git a/arch/arm/include/asm/arch-tegra/pmu.h b/arch/arm/include/asm/arch-tegra/pmu.h new file mode 100644 index 00000000000..e850875d316 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/pmu.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2010,2011 + * NVIDIA Corporation + */ + +#ifndef _TEGRA_PMU_H_ +#define _TEGRA_PMU_H_ + +/* Set core and CPU voltages to nominal levels */ +int pmu_set_nominal(void); + +#endif /* _TEGRA_PMU_H_ */ diff --git a/arch/arm/include/asm/arch-tegra114/pmu.h b/arch/arm/include/asm/arch-tegra114/pmu.h deleted file mode 100644 index 1e571ee7b31..00000000000 --- a/arch/arm/include/asm/arch-tegra114/pmu.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. - */ - -#ifndef _TEGRA114_PMU_H_ -#define _TEGRA114_PMU_H_ - -/* Set core and CPU voltages to nominal levels */ -int pmu_set_nominal(void); - -#endif /* _TEGRA114_PMU_H_ */ diff --git a/arch/arm/include/asm/arch-tegra124/pmu.h b/arch/arm/include/asm/arch-tegra124/pmu.h deleted file mode 100644 index c38393edefd..00000000000 --- a/arch/arm/include/asm/arch-tegra124/pmu.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010-2013 - * NVIDIA Corporation - */ - -#ifndef _TEGRA124_PMU_H_ -#define _TEGRA124_PMU_H_ - -/* Set core and CPU voltages to nominal levels */ -int pmu_set_nominal(void); - -#endif /* _TEGRA124_PMU_H_ */ diff --git a/arch/arm/include/asm/arch-tegra20/pmu.h b/arch/arm/include/asm/arch-tegra20/pmu.h deleted file mode 100644 index 18766dfed2b..00000000000 --- a/arch/arm/include/asm/arch-tegra20/pmu.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010,2011 - * NVIDIA Corporation - */ - -#ifndef _ARCH_PMU_H_ -#define _ARCH_PMU_H_ - -/* Set core and CPU voltages to nominal levels */ -int pmu_set_nominal(void); - -#endif /* _ARCH_PMU_H_ */ diff --git a/arch/arm/include/asm/arch-tegra210/pmu.h b/arch/arm/include/asm/arch-tegra210/pmu.h deleted file mode 100644 index 6ea36aa4187..00000000000 --- a/arch/arm/include/asm/arch-tegra210/pmu.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010-2015 - * NVIDIA Corporation - */ - -#ifndef _TEGRA210_PMU_H_ -#define _TEGRA210_PMU_H_ - -/* Set core and CPU voltages to nominal levels */ -int pmu_set_nominal(void); - -#endif /* _TEGRA210_PMU_H_ */ diff --git a/arch/arm/include/asm/arch-tegra30/pmu.h b/arch/arm/include/asm/arch-tegra30/pmu.h deleted file mode 100644 index a823f0fbfc6..00000000000 --- a/arch/arm/include/asm/arch-tegra30/pmu.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. - */ - -#ifndef _TEGRA30_PMU_H_ -#define _TEGRA30_PMU_H_ - -/* Set core and CPU voltages to nominal levels */ -int pmu_set_nominal(void); - -#endif /* _TEGRA30_PMU_H_ */ diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index 12257a42b51..b8d5ef0322c 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -24,7 +25,6 @@ #include #include #include -#include #include #ifdef CONFIG_TEGRA_CLOCK_SCALING #include diff --git a/arch/arm/mach-tegra/emc.c b/arch/arm/mach-tegra/emc.c index 6697909d9a3..66628933b65 100644 --- a/arch/arm/mach-tegra/emc.c +++ b/arch/arm/mach-tegra/emc.c @@ -8,10 +8,10 @@ #include #include #include -#include #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; -- cgit v1.2.3 From b64e0b9231e1fd700615cf88cd66079d257849d8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:18 +0200 Subject: ARM: tegra: Guard clock code with a Kconfig symbol Clock code is not relevant on all Tegra SoC generations, so guard it with a Kconfig symbol that can be selected by the generations that need it. This is in preparation for unifying Tegra186 code with the code used on older generations. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/Kconfig | 5 +++++ arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/board.c | 2 ++ arch/arm/mach-tegra/board2.c | 12 ++++++++++-- 4 files changed, 18 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 86b1cd11f75..ee078fec9ad 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -12,6 +12,9 @@ config SPL_LIBGENERIC_SUPPORT config SPL_SERIAL_SUPPORT default y +config TEGRA_CLKRST + bool + config TEGRA_IVC bool "Tegra IVC protocol" help @@ -55,6 +58,7 @@ config TEGRA_ARMV7_COMMON select SPL select SPL_BOARD_INIT if SPL select SUPPORT_SPL + select TEGRA_CLKRST select TEGRA_COMMON select TEGRA_GPIO select TEGRA_NO_BPMP @@ -100,6 +104,7 @@ config TEGRA124 config TEGRA210 bool "Tegra210 family" select TEGRA_ARMV8_COMMON + select TEGRA_CLKRST select TEGRA_GPIO select TEGRA_NO_BPMP diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index d4b4666fb1e..0e812818d7a 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -16,7 +16,7 @@ endif obj-y += ap.o obj-y += board.o board2.o obj-y += cache.o -obj-y += clock.o +obj-$(CONFIG_TEGRA_CLKRST) += clock.o obj-y += pinmux-common.o obj-y += powergate.o obj-y += xusb-padctl-dummy.o diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c index 4e159075d37..209416e6ad8 100644 --- a/arch/arm/mach-tegra/board.c +++ b/arch/arm/mach-tegra/board.c @@ -9,7 +9,9 @@ #include #include #include +#if IS_ENABLED(CONFIG_TEGRA_CLKRST) #include +#endif #include #include #include diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index b8d5ef0322c..b94077221f7 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -22,7 +22,9 @@ #include #include #include +#if IS_ENABLED(CONFIG_TEGRA_CLKRST) #include +#endif #include #include #include @@ -109,8 +111,10 @@ int board_init(void) __maybe_unused int board_id; /* Do clocks and UART first so that printf() works */ +#if IS_ENABLED(CONFIG_TEGRA_CLKRST) clock_init(); clock_verify(); +#endif tegra_gpu_config(); @@ -181,8 +185,10 @@ void gpio_early_init(void) __attribute__((weak, alias("__gpio_early_init"))); int board_early_init_f(void) { +#if IS_ENABLED(CONFIG_TEGRA_CLKRST) if (!clock_early_init_done()) clock_early_init(); +#endif #if defined(CONFIG_TEGRA_DISCONNECT_UDC_ON_BOOT) #define USBCMD_FS2 (1 << 15) @@ -193,10 +199,12 @@ int board_early_init_f(void) #endif /* Do any special system timer/TSC setup */ -#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE) +#if IS_ENABLED(CONFIG_TEGRA_CLKRST) +# if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE) if (!tegra_cpu_is_non_secure()) -#endif +# endif arch_timer_init(); +#endif pinmux_init(); board_init_uart_f(); -- cgit v1.2.3 From 9e57819294a1b2b247f66a6dbfa380137e166ec5 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:19 +0200 Subject: ARM: tegra: Guard GP pad control code with a Kconfig symbol The GP pad control code is not relevant on all Tegra SoC generations, so guard it with a Kconfig symbol that can be selected by the generations that need it. This is in preparation for unifying Tegra186 code with the code used on older generations. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/Kconfig | 5 +++++ arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/cache.c | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index ee078fec9ad..265051b18aa 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -15,6 +15,9 @@ config SPL_SERIAL_SUPPORT config TEGRA_CLKRST bool +config TEGRA_GP_PADCTRL + bool + config TEGRA_IVC bool "Tegra IVC protocol" help @@ -61,6 +64,7 @@ config TEGRA_ARMV7_COMMON select TEGRA_CLKRST select TEGRA_COMMON select TEGRA_GPIO + select TEGRA_GP_PADCTRL select TEGRA_NO_BPMP config TEGRA_ARMV8_COMMON @@ -106,6 +110,7 @@ config TEGRA210 select TEGRA_ARMV8_COMMON select TEGRA_CLKRST select TEGRA_GPIO + select TEGRA_GP_PADCTRL select TEGRA_NO_BPMP config TEGRA186 diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 0e812818d7a..69f802c01b4 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -13,7 +13,7 @@ else obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o endif -obj-y += ap.o +obj-$(CONFIG_TEGRA_GP_PADCTRL) += ap.o obj-y += board.o board2.o obj-y += cache.o obj-$(CONFIG_TEGRA_CLKRST) += clock.o diff --git a/arch/arm/mach-tegra/cache.c b/arch/arm/mach-tegra/cache.c index be414e4e4ac..d7063490e22 100644 --- a/arch/arm/mach-tegra/cache.c +++ b/arch/arm/mach-tegra/cache.c @@ -8,7 +8,9 @@ #include #include #include +#if IS_ENABLED(CONFIG_TEGRA_GP_PADCTRL) #include +#endif #ifndef CONFIG_ARM64 void config_cache(void) -- cgit v1.2.3 From 1a869c703d0493cab9defd4cb5754a175a642052 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:20 +0200 Subject: ARM: tegra: Guard memory controller code with a Kconfig symbol Memory controller code is not relevant on all Tegra SoC generations, so guard it with a Kconfig symbol that can be selected by the generations that need it. This is in preparation for unifying Tegra186 code with the code used on older generations. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/Kconfig | 5 +++++ arch/arm/mach-tegra/board.c | 7 +++++++ 2 files changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 265051b18aa..5763c4ae3cd 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -26,6 +26,9 @@ config TEGRA_IVC U-Boot, it is typically used for communication between the main CPU and various auxiliary processors. +config TEGRA_MC + bool + config TEGRA_COMMON bool "Tegra common options" select BINMAN @@ -65,6 +68,7 @@ config TEGRA_ARMV7_COMMON select TEGRA_COMMON select TEGRA_GPIO select TEGRA_GP_PADCTRL + select TEGRA_MC select TEGRA_NO_BPMP config TEGRA_ARMV8_COMMON @@ -111,6 +115,7 @@ config TEGRA210 select TEGRA_CLKRST select TEGRA_GPIO select TEGRA_GP_PADCTRL + select TEGRA_MC select TEGRA_NO_BPMP config TEGRA186 diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c index 209416e6ad8..a9e26bd1a36 100644 --- a/arch/arm/mach-tegra/board.c +++ b/arch/arm/mach-tegra/board.c @@ -13,7 +13,9 @@ #include #endif #include +#if IS_ENABLED(CONFIG_TEGRA_MC) #include +#endif #include #include #include @@ -68,6 +70,7 @@ bool tegra_cpu_is_non_secure(void) } #endif +#if IS_ENABLED(CONFIG_TEGRA_MC) /* Read the RAM size directly from the memory controller */ static phys_size_t query_sdram_size(void) { @@ -117,11 +120,15 @@ static phys_size_t query_sdram_size(void) return size_bytes; } +#endif int dram_init(void) { +#if IS_ENABLED(CONFIG_TEGRA_MC) /* We do not initialise DRAM here. We just query the size */ gd->ram_size = query_sdram_size(); +#endif + return 0; } -- cgit v1.2.3 From 07ea02bc2dd17a75ec04c5f4ba10b0088f1596d5 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:21 +0200 Subject: ARM: tegra: Guard pin controller code with a Kconfig symbol Pin controller code is not relevant on all Tegra SoC generations, so guard it with a Kconfig symbol that can be selected by the generations that need it. This is in preparation for unifying Tegra186 code with the code used on older generations. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/Kconfig | 5 +++++ arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/board.c | 6 ++++++ arch/arm/mach-tegra/board2.c | 2 ++ 4 files changed, 14 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 5763c4ae3cd..be20ac2e804 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -29,6 +29,9 @@ config TEGRA_IVC config TEGRA_MC bool +config TEGRA_PINCTRL + bool + config TEGRA_COMMON bool "Tegra common options" select BINMAN @@ -70,6 +73,7 @@ config TEGRA_ARMV7_COMMON select TEGRA_GP_PADCTRL select TEGRA_MC select TEGRA_NO_BPMP + select TEGRA_PINCTRL config TEGRA_ARMV8_COMMON bool "Tegra 64-bit common options" @@ -117,6 +121,7 @@ config TEGRA210 select TEGRA_GP_PADCTRL select TEGRA_MC select TEGRA_NO_BPMP + select TEGRA_PINCTRL config TEGRA186 bool "Tegra186 family" diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 69f802c01b4..395e0191a45 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -17,7 +17,7 @@ obj-$(CONFIG_TEGRA_GP_PADCTRL) += ap.o obj-y += board.o board2.o obj-y += cache.o obj-$(CONFIG_TEGRA_CLKRST) += clock.o -obj-y += pinmux-common.o +obj-$(CONFIG_TEGRA_PINCTRL) += pinmux-common.o obj-y += powergate.o obj-y += xusb-padctl-dummy.o endif diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c index a9e26bd1a36..fd23de18047 100644 --- a/arch/arm/mach-tegra/board.c +++ b/arch/arm/mach-tegra/board.c @@ -12,7 +12,9 @@ #if IS_ENABLED(CONFIG_TEGRA_CLKRST) #include #endif +#if IS_ENABLED(CONFIG_TEGRA_PINCTRL) #include +#endif #if IS_ENABLED(CONFIG_TEGRA_MC) #include #endif @@ -132,6 +134,7 @@ int dram_init(void) return 0; } +#if IS_ENABLED(CONFIG_TEGRA_PINCTRL) static int uart_configs[] = { #if defined(CONFIG_TEGRA20) #if defined(CONFIG_TEGRA_UARTA_UAA_UAB) @@ -199,9 +202,11 @@ static void setup_uarts(int uart_ids) } } } +#endif void board_init_uart_f(void) { +#if IS_ENABLED(CONFIG_TEGRA_PINCTRL) int uart_ids = 0; /* bit mask of which UART ids to enable */ #ifdef CONFIG_TEGRA_ENABLE_UARTA @@ -220,6 +225,7 @@ void board_init_uart_f(void) uart_ids |= UARTE; #endif setup_uarts(uart_ids); +#endif } #if !CONFIG_IS_ENABLED(OF_CONTROL) diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index b94077221f7..ce1c9346959 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -25,8 +25,10 @@ #if IS_ENABLED(CONFIG_TEGRA_CLKRST) #include #endif +#if IS_ENABLED(CONFIG_TEGRA_PINCTRL) #include #include +#endif #include #ifdef CONFIG_TEGRA_CLOCK_SCALING #include -- cgit v1.2.3 From e19143b5eb22fd440de8bf42709347fd524897c0 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:22 +0200 Subject: ARM: tegra: Guard powergate code with a Kconfig symbol Powergate code is not relevant on all Tegra SoC generations, so guard it with a Kconfig symbol that can be selected by the generations that need it. This is in preparation for unifying Tegra186 code with the code used on older generations. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/Kconfig | 5 +++++ arch/arm/mach-tegra/Makefile | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index be20ac2e804..db9198348d3 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -32,6 +32,9 @@ config TEGRA_MC config TEGRA_PINCTRL bool +config TEGRA_PMC + bool + config TEGRA_COMMON bool "Tegra common options" select BINMAN @@ -74,6 +77,7 @@ config TEGRA_ARMV7_COMMON select TEGRA_MC select TEGRA_NO_BPMP select TEGRA_PINCTRL + select TEGRA_PMC config TEGRA_ARMV8_COMMON bool "Tegra 64-bit common options" @@ -122,6 +126,7 @@ config TEGRA210 select TEGRA_MC select TEGRA_NO_BPMP select TEGRA_PINCTRL + select TEGRA_PMC config TEGRA186 bool "Tegra186 family" diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 395e0191a45..517be21ee5f 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -18,7 +18,7 @@ obj-y += board.o board2.o obj-y += cache.o obj-$(CONFIG_TEGRA_CLKRST) += clock.o obj-$(CONFIG_TEGRA_PINCTRL) += pinmux-common.o -obj-y += powergate.o +obj-$(CONFIG_TEGRA_PMC) += powergate.o obj-y += xusb-padctl-dummy.o endif -- cgit v1.2.3 From 8f60d18f9406c38a90972798290aa3ce3de92ecb Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:23 +0200 Subject: ARM: tegra: Fix save_boot_params() prototype The save_boot_params() function takes as its first four arguments the first four registers. On 32-bit ARM these are r0, r1, r2 and r3, all of which are 32 bits wide. However, on 64-bit ARM thene registers are x0, x1, x2 and x3, all of which are 64 bits wide. In order to allow reusing the save_boot_params() implementation on 64-bit ARM, change it to take unsigned long parameters rather than the fixed size 32-bit integers. This ensures that the correct values are passed. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/board.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c index fd23de18047..42baf975ec5 100644 --- a/arch/arm/mach-tegra/board.c +++ b/arch/arm/mach-tegra/board.c @@ -42,7 +42,8 @@ enum { static bool from_spl __attribute__ ((section(".data"))); #ifndef CONFIG_SPL_BUILD -void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) +void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2, + unsigned long r3) { from_spl = r0 != UBOOT_NOT_LOADED_FROM_SPL; save_boot_params_ret(); -- cgit v1.2.3 From f9ec2ec8504aa5d94d5be7f43c743040e549b157 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:25 +0200 Subject: ARM: tegra: Support TZ-only access to PMC Some devices may restrict access to the PMC to TrustZone software only. Non-TZ software can detect this and use SMC calls to the firmware that runs in the TrustZone to perform accesses to PMC registers. Note that this also fixes reset_cpu() and the enterrcm command on Tegra186 where they were previously trying to access the PMC at a wrong physical address. Based on work by Kalyani Chidambaram and Tom Warren . Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/include/asm/arch-tegra/pmc.h | 20 ++++++- arch/arm/include/asm/arch-tegra/tegra.h | 6 +++ arch/arm/mach-tegra/Kconfig | 5 ++ arch/arm/mach-tegra/Makefile | 4 +- arch/arm/mach-tegra/clock.c | 13 +++-- arch/arm/mach-tegra/cmd_enterrcm.c | 6 +-- arch/arm/mach-tegra/cpu.c | 20 +++---- arch/arm/mach-tegra/lowlevel_init.S | 39 -------------- arch/arm/mach-tegra/pmc.c | 92 +++++++++++++++++++++++++++++++++ arch/arm/mach-tegra/powergate.c | 11 ++-- 10 files changed, 151 insertions(+), 65 deletions(-) delete mode 100644 arch/arm/mach-tegra/lowlevel_init.S create mode 100644 arch/arm/mach-tegra/pmc.c (limited to 'arch') diff --git a/arch/arm/include/asm/arch-tegra/pmc.h b/arch/arm/include/asm/arch-tegra/pmc.h index 34bbe75d5fd..1524bf29116 100644 --- a/arch/arm/include/asm/arch-tegra/pmc.h +++ b/arch/arm/include/asm/arch-tegra/pmc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * (C) Copyright 2010-2015 + * (C) Copyright 2010-2019 * NVIDIA Corporation */ @@ -388,4 +388,22 @@ struct pmc_ctlr { /* APBDEV_PMC_CNTRL2_0 0x440 */ #define HOLD_CKE_LOW_EN (1 << 12) +/* PMC read/write functions */ +u32 tegra_pmc_readl(unsigned long offset); +void tegra_pmc_writel(u32 value, unsigned long offset); + +#define PMC_CNTRL 0x0 +#define PMC_CNTRL_MAIN_RST BIT(4) + +#if IS_ENABLED(CONFIG_TEGRA186) +# define PMC_SCRATCH0 0x32000 +#else +# define PMC_SCRATCH0 0x00050 +#endif + +/* for secure PMC */ +#define TEGRA_SMC_PMC 0xc2fffe00 +#define TEGRA_SMC_PMC_READ 0xaa +#define TEGRA_SMC_PMC_WRITE 0xbb + #endif /* PMC_H */ diff --git a/arch/arm/include/asm/arch-tegra/tegra.h b/arch/arm/include/asm/arch-tegra/tegra.h index 7ae0129e2db..7a4e0972fb7 100644 --- a/arch/arm/include/asm/arch-tegra/tegra.h +++ b/arch/arm/include/asm/arch-tegra/tegra.h @@ -30,7 +30,13 @@ #define NV_PA_SLINK5_BASE (NV_PA_APB_MISC_BASE + 0xDC00) #define NV_PA_SLINK6_BASE (NV_PA_APB_MISC_BASE + 0xDE00) #define TEGRA_DVC_BASE (NV_PA_APB_MISC_BASE + 0xD000) +#if defined(CONFIG_TEGRA20) || defined(CONFIG_TEGRA30) || \ + defined(CONFIG_TEGRA114) || defined(CONFIG_TEGRA124) || \ + defined(CONFIG_TEGRA132) || defined(CONFIG_TEGRA210) #define NV_PA_PMC_BASE (NV_PA_APB_MISC_BASE + 0xE400) +#else +#define NV_PA_PMC_BASE 0xc360000 +#endif #define NV_PA_EMC_BASE (NV_PA_APB_MISC_BASE + 0xF400) #define NV_PA_FUSE_BASE (NV_PA_APB_MISC_BASE + 0xF800) #if defined(CONFIG_TEGRA20) || defined(CONFIG_TEGRA30) || \ diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index db9198348d3..28914a34a1b 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -35,6 +35,10 @@ config TEGRA_PINCTRL config TEGRA_PMC bool +config TEGRA_PMC_SECURE + bool + depends on TEGRA_PMC + config TEGRA_COMMON bool "Tegra common options" select BINMAN @@ -127,6 +131,7 @@ config TEGRA210 select TEGRA_NO_BPMP select TEGRA_PINCTRL select TEGRA_PMC + select TEGRA_PMC_SECURE config TEGRA186 bool "Tegra186 family" diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 517be21ee5f..f8bc65aa8b1 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0+ # -# (C) Copyright 2010-2015 Nvidia Corporation. +# (C) Copyright 2010-2019 Nvidia Corporation. # # (C) Copyright 2000-2008 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -27,11 +27,11 @@ obj-y += dt-setup.o obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o obj-$(CONFIG_TEGRA_GPU) += gpu.o obj-$(CONFIG_TEGRA_IVC) += ivc.o -obj-y += lowlevel_init.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_ARMV7_PSCI) += psci.o endif obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o +obj-y += pmc.o obj-$(CONFIG_TEGRA20) += tegra20/ obj-$(CONFIG_TEGRA30) += tegra30/ diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index dc5f16b41b6..e539ad8b30a 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2010-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2010-2019, NVIDIA CORPORATION. All rights reserved. */ /* Tegra SoC common clock control functions */ @@ -815,11 +815,16 @@ void tegra30_set_up_pllp(void) int clock_external_output(int clk_id) { - struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 val; if (clk_id >= 1 && clk_id <= 3) { - setbits_le32(&pmc->pmc_clk_out_cntrl, - 1 << (2 + (clk_id - 1) * 8)); + val = tegra_pmc_readl(offsetof(struct pmc_ctlr, + pmc_clk_out_cntrl)); + val |= 1 << (2 + (clk_id - 1) * 8); + tegra_pmc_writel(val, + offsetof(struct pmc_ctlr, + pmc_clk_out_cntrl)); + } else { printf("%s: Unknown output clock id %d\n", __func__, clk_id); return -EINVAL; diff --git a/arch/arm/mach-tegra/cmd_enterrcm.c b/arch/arm/mach-tegra/cmd_enterrcm.c index 4e6beb3e5bb..4a889f0e342 100644 --- a/arch/arm/mach-tegra/cmd_enterrcm.c +++ b/arch/arm/mach-tegra/cmd_enterrcm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2019, NVIDIA CORPORATION. All rights reserved. * * Derived from code (arch/arm/lib/reset.c) that is: * @@ -31,12 +31,10 @@ static int do_enterrcm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; - puts("Entering RCM...\n"); udelay(50000); - pmc->pmc_scratch0 = 2; + tegra_pmc_writel(2, PMC_SCRATCH0); disable_interrupts(); reset_cpu(0); diff --git a/arch/arm/mach-tegra/cpu.c b/arch/arm/mach-tegra/cpu.c index 1b6ad074ed8..3d140760e68 100644 --- a/arch/arm/mach-tegra/cpu.c +++ b/arch/arm/mach-tegra/cpu.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2010-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2010-2019, NVIDIA CORPORATION. All rights reserved. */ #include @@ -299,21 +299,19 @@ void enable_cpu_clock(int enable) static int is_cpu_powered(void) { - struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; - - return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0; + return (tegra_pmc_readl(offsetof(struct pmc_ctlr, + pmc_pwrgate_status)) & CPU_PWRED) ? 1 : 0; } static void remove_cpu_io_clamps(void) { - struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; u32 reg; debug("%s entry\n", __func__); /* Remove the clamps on the CPU I/O signals */ - reg = readl(&pmc->pmc_remove_clamping); + reg = tegra_pmc_readl(offsetof(struct pmc_ctlr, pmc_remove_clamping)); reg |= CPU_CLMP; - writel(reg, &pmc->pmc_remove_clamping); + tegra_pmc_writel(reg, offsetof(struct pmc_ctlr, pmc_remove_clamping)); /* Give I/O signals time to stabilize */ udelay(IO_STABILIZATION_DELAY); @@ -321,17 +319,19 @@ static void remove_cpu_io_clamps(void) void powerup_cpu(void) { - struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; u32 reg; int timeout = IO_STABILIZATION_DELAY; debug("%s entry\n", __func__); if (!is_cpu_powered()) { /* Toggle the CPU power state (OFF -> ON) */ - reg = readl(&pmc->pmc_pwrgate_toggle); + reg = tegra_pmc_readl(offsetof(struct pmc_ctlr, + pmc_pwrgate_toggle)); reg &= PARTID_CP; reg |= START_CP; - writel(reg, &pmc->pmc_pwrgate_toggle); + tegra_pmc_writel(reg, + offsetof(struct pmc_ctlr, + pmc_pwrgate_toggle)); /* Wait for the power to come up */ while (!is_cpu_powered()) { diff --git a/arch/arm/mach-tegra/lowlevel_init.S b/arch/arm/mach-tegra/lowlevel_init.S deleted file mode 100644 index 626f1b64274..00000000000 --- a/arch/arm/mach-tegra/lowlevel_init.S +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * SoC-specific setup info - * - * (C) Copyright 2010,2011 - * NVIDIA Corporation - */ - -#include -#include - -#ifdef CONFIG_ARM64 - .align 5 -ENTRY(reset_cpu) - /* get address for global reset register */ - ldr x1, =PRM_RSTCTRL - ldr w3, [x1] - /* force reset */ - orr w3, w3, #0x10 - str w3, [x1] - mov w0, w0 -1: - b 1b -ENDPROC(reset_cpu) -#else - .align 5 -ENTRY(reset_cpu) - ldr r1, rstctl @ get addr for global reset - @ reg - ldr r3, [r1] - orr r3, r3, #0x10 - str r3, [r1] @ force reset - mov r0, r0 -_loop_forever: - b _loop_forever -rstctl: - .word PRM_RSTCTRL -ENDPROC(reset_cpu) -#endif diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c new file mode 100644 index 00000000000..afd3c54179c --- /dev/null +++ b/arch/arm/mach-tegra/pmc.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. + */ + +#include + +#include + +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE) +static bool tegra_pmc_detect_tz_only(void) +{ + static bool initialized = false; + static bool is_tz_only = false; + u32 value, saved; + + if (!initialized) { + saved = readl(NV_PA_PMC_BASE + PMC_SCRATCH0); + value = saved ^ 0xffffffff; + + if (value == 0xffffffff) + value = 0xdeadbeef; + + /* write pattern and read it back */ + writel(value, NV_PA_PMC_BASE + PMC_SCRATCH0); + value = readl(NV_PA_PMC_BASE + PMC_SCRATCH0); + + /* if we read all-zeroes, access is restricted to TZ only */ + if (value == 0) { + debug("access to PMC is restricted to TZ\n"); + is_tz_only = true; + } else { + /* restore original value */ + writel(saved, NV_PA_PMC_BASE + PMC_SCRATCH0); + } + + initialized = true; + } + + return is_tz_only; +} +#endif + +uint32_t tegra_pmc_readl(unsigned long offset) +{ +#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE) + if (tegra_pmc_detect_tz_only()) { + struct arm_smccc_res res; + + arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_READ, offset, 0, 0, + 0, 0, 0, &res); + if (res.a0) + printf("%s(): SMC failed: %lu\n", __func__, res.a0); + + return res.a1; + } +#endif + + return readl(NV_PA_PMC_BASE + offset); +} + +void tegra_pmc_writel(u32 value, unsigned long offset) +{ +#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE) + if (tegra_pmc_detect_tz_only()) { + struct arm_smccc_res res; + + arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_WRITE, offset, + value, 0, 0, 0, 0, &res); + if (res.a0) + printf("%s(): SMC failed: %lu\n", __func__, res.a0); + + return; + } +#endif + + writel(value, NV_PA_PMC_BASE + offset); +} + +void reset_cpu(ulong addr) +{ + u32 value; + + value = tegra_pmc_readl(PMC_CNTRL); + value |= PMC_CNTRL_MAIN_RST; + tegra_pmc_writel(value, PMC_CNTRL); +} diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index e45f0961b24..761c9ef19e3 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. */ #include @@ -11,6 +11,7 @@ #include #include +#include #define PWRGATE_TOGGLE 0x30 #define PWRGATE_TOGGLE_START (1 << 8) @@ -24,18 +25,18 @@ static int tegra_powergate_set(enum tegra_powergate id, bool state) u32 value, mask = state ? (1 << id) : 0, old_mask; unsigned long start, timeout = 25; - value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS); + value = tegra_pmc_readl(PWRGATE_STATUS); old_mask = value & (1 << id); if (mask == old_mask) return 0; - writel(PWRGATE_TOGGLE_START | id, NV_PA_PMC_BASE + PWRGATE_TOGGLE); + tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); start = get_timer(0); while (get_timer(start) < timeout) { - value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS); + value = tegra_pmc_readl(PWRGATE_STATUS); if ((value & (1 << id)) == mask) return 0; } @@ -69,7 +70,7 @@ static int tegra_powergate_remove_clamping(enum tegra_powergate id) else value = 1 << id; - writel(value, NV_PA_PMC_BASE + REMOVE_CLAMPING); + tegra_pmc_writel(value, REMOVE_CLAMPING); return 0; } -- cgit v1.2.3 From 836a56e729a082639d26499c8eb2d409308542a4 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:26 +0200 Subject: ARM: tegra: Workaround UDC boot issues only if necessary Resetting the USB device controller on boot is only necessary if the SoC actually has a UDC controller and U-Boot enables support for it. All the Tegra boards support UDC via the ChipIdea UDC driver, so make the UDC on boot workaround depend on the ChipIdea UDC driver. This prevents a crash on Tegra186 which does not have the ChipIdea UDC. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 28914a34a1b..faa73559fd4 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -148,6 +148,7 @@ endchoice config TEGRA_DISCONNECT_UDC_ON_BOOT bool "Disconnect USB device mode controller on boot" + depends on CI_UDC default y help When loading U-Boot into RAM over USB protocols using tools such as -- cgit v1.2.3 From a0dbc1314c3275c3af3591fc6f4762ff3367a4fd Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:28 +0200 Subject: ARM: tegra: Unify Tegra186 builds Tegra186 build are currently dealt with in very special ways, which is because Tegra186 is fundamentally different in many respects. It is no longer necessary to do many of the low-level programming because early boot firmware will already have taken care of it. Unfortunately, separating Tegra186 builds from the rest in this way makes it difficult to share code with prior generations of Tegra. With all of the low-level programming code behind Kconfig guards, the build for Tegra186 can again be unified. As a side-effect, and partial reason for this change, other Tegra SoC generations can now make use of the code that deals with taking over a boot from earlier bootloaders. This used to be nvtboot, but has been replaced by cboot nowadays. Rename the files and functions related to this to avoid confusion. The implemented protocols are unchanged. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/include/asm/arch-tegra/cboot.h | 39 +++ arch/arm/mach-tegra/Makefile | 4 +- arch/arm/mach-tegra/board.c | 23 ++ arch/arm/mach-tegra/board186.c | 32 -- arch/arm/mach-tegra/board2.c | 21 ++ arch/arm/mach-tegra/cboot.c | 498 +++++++++++++++++++++++++++ arch/arm/mach-tegra/cboot_ll.S | 20 ++ arch/arm/mach-tegra/tegra186/Makefile | 4 - arch/arm/mach-tegra/tegra186/nvtboot_board.c | 332 ------------------ arch/arm/mach-tegra/tegra186/nvtboot_ll.S | 20 -- arch/arm/mach-tegra/tegra186/nvtboot_mem.c | 172 --------- board/nvidia/p2771-0000/p2771-0000.c | 10 +- 12 files changed, 607 insertions(+), 568 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra/cboot.h delete mode 100644 arch/arm/mach-tegra/board186.c create mode 100644 arch/arm/mach-tegra/cboot.c create mode 100644 arch/arm/mach-tegra/cboot_ll.S delete mode 100644 arch/arm/mach-tegra/tegra186/nvtboot_board.c delete mode 100644 arch/arm/mach-tegra/tegra186/nvtboot_ll.S delete mode 100644 arch/arm/mach-tegra/tegra186/nvtboot_mem.c (limited to 'arch') diff --git a/arch/arm/include/asm/arch-tegra/cboot.h b/arch/arm/include/asm/arch-tegra/cboot.h new file mode 100644 index 00000000000..b3441ec178b --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/cboot.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2019 NVIDIA Corporation. All rights reserved. + */ + +#ifndef _TEGRA_CBOOT_H_ +#define _TEGRA_CBOOT_H_ + +#ifdef CONFIG_ARM64 +extern unsigned long cboot_boot_x0; + +void cboot_save_boot_params(unsigned long x0, unsigned long x1, + unsigned long x2, unsigned long x3); +int cboot_dram_init(void); +int cboot_dram_init_banksize(void); +ulong cboot_get_usable_ram_top(ulong total_size); +#else +static inline void cboot_save_boot_params(unsigned long x0, unsigned long x1, + unsigned long x2, unsigned long x3) +{ +} + +static inline int cboot_dram_init(void) +{ + return -ENOSYS; +} + +static inline int cboot_dram_init_banksize(void) +{ + return -ENOSYS; +} + +static inline ulong cboot_get_usable_ram_top(ulong total_size) +{ + return 0; +} +#endif + +#endif diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index f8bc65aa8b1..41ba674edff 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -5,7 +5,6 @@ # (C) Copyright 2000-2008 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -ifndef CONFIG_TEGRA186 ifdef CONFIG_SPL_BUILD obj-y += spl.o obj-y += cpu.o @@ -20,9 +19,8 @@ obj-$(CONFIG_TEGRA_CLKRST) += clock.o obj-$(CONFIG_TEGRA_PINCTRL) += pinmux-common.o obj-$(CONFIG_TEGRA_PMC) += powergate.o obj-y += xusb-padctl-dummy.o -endif -obj-$(CONFIG_ARM64) += arm64-mmu.o +obj-$(CONFIG_ARM64) += arm64-mmu.o cboot_ll.o cboot.o obj-y += dt-setup.o obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o obj-$(CONFIG_TEGRA_GPU) += gpu.o diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c index 42baf975ec5..abcae15ea33 100644 --- a/arch/arm/mach-tegra/board.c +++ b/arch/arm/mach-tegra/board.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,21 @@ void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2, unsigned long r3) { from_spl = r0 != UBOOT_NOT_LOADED_FROM_SPL; + + /* + * The logic for this is somewhat indirect. The purpose of the marker + * (UBOOT_NOT_LOADED_FROM_SPL) is in fact used to determine if U-Boot + * was loaded from a read-only instance of itself, which is something + * that can happen in secure boot setups. So basically the presence + * of the marker is an indication that U-Boot was loaded by one such + * special variant of U-Boot. Conversely, the absence of the marker + * indicates that this instance of U-Boot was loaded by something + * other than a special U-Boot. This could be SPL, but it could just + * as well be one of any number of other first stage bootloaders. + */ + if (from_spl) + cboot_save_boot_params(r0, r1, r2, r3); + save_boot_params_ret(); } #endif @@ -127,6 +143,13 @@ static phys_size_t query_sdram_size(void) int dram_init(void) { + int err; + + /* try to initialize DRAM from cboot DTB first */ + err = cboot_dram_init(); + if (err == 0) + return 0; + #if IS_ENABLED(CONFIG_TEGRA_MC) /* We do not initialise DRAM here. We just query the size */ gd->ram_size = query_sdram_size(); diff --git a/arch/arm/mach-tegra/board186.c b/arch/arm/mach-tegra/board186.c deleted file mode 100644 index 80b55707e90..00000000000 --- a/arch/arm/mach-tegra/board186.c +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. - */ - -#include -#include - -int board_early_init_f(void) -{ - return 0; -} - -__weak int tegra_board_init(void) -{ - return 0; -} - -int board_init(void) -{ - return tegra_board_init(); -} - -__weak int tegra_soc_board_init_late(void) -{ - return 0; -} - -int board_late_init(void) -{ - return tegra_soc_board_init_late(); -} diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index ce1c9346959..bbc487aa3bf 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ __weak void pin_mux_mmc(void) {} __weak void gpio_early_init_uart(void) {} __weak void pin_mux_display(void) {} __weak void start_cpu_fan(void) {} +__weak void cboot_late_init(void) {} #if defined(CONFIG_TEGRA_NAND) __weak void pin_mux_nand(void) @@ -243,6 +245,7 @@ int board_late_init(void) } #endif start_cpu_fan(); + cboot_late_init(); return 0; } @@ -337,6 +340,15 @@ static ulong usable_ram_size_below_4g(void) */ int dram_init_banksize(void) { + int err; + + /* try to compute DRAM bank size based on cboot DTB first */ + err = cboot_dram_init_banksize(); + if (err == 0) + return err; + + /* fall back to default DRAM bank size computation */ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; gd->bd->bi_dram[0].size = usable_ram_size_below_4g(); @@ -370,5 +382,14 @@ int dram_init_banksize(void) */ ulong board_get_usable_ram_top(ulong total_size) { + ulong ram_top; + + /* try to get top of usable RAM based on cboot DTB first */ + ram_top = cboot_get_usable_ram_top(total_size); + if (ram_top > 0) + return ram_top; + + /* fall back to default usable RAM computation */ + return CONFIG_SYS_SDRAM_BASE + usable_ram_size_below_4g(); } diff --git a/arch/arm/mach-tegra/cboot.c b/arch/arm/mach-tegra/cboot.c new file mode 100644 index 00000000000..3ebf7b05555 --- /dev/null +++ b/arch/arm/mach-tegra/cboot.c @@ -0,0 +1,498 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2016-2018, NVIDIA CORPORATION. + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* + * Size of a region that's large enough to hold the relocated U-Boot and all + * other allocations made around it (stack, heap, page tables, etc.) + * In practice, running "bdinfo" at the shell prompt, the stack reaches about + * 5MB from the address selected for ram_top as of the time of writing, + * so a 16MB region should be plenty. + */ +#define MIN_USABLE_RAM_SIZE SZ_16M +/* + * The amount of space we expect to require for stack usage. Used to validate + * that all reservations fit into the region selected for the relocation target + */ +#define MIN_USABLE_STACK_SIZE SZ_1M + +DECLARE_GLOBAL_DATA_PTR; + +extern struct mm_region tegra_mem_map[]; + +/* + * These variables are written to before relocation, and hence cannot be + * in.bss, since .bss overlaps the DTB that's appended to the U-Boot binary. + * The section attribute forces this into .data and avoids this issue. This + * also has the nice side-effect of the content being valid after relocation. + */ + +/* The number of valid entries in ram_banks[] */ +static int ram_bank_count __attribute__((section(".data"))); + +/* + * The usable top-of-RAM for U-Boot. This is both: + * a) Below 4GB to avoid issues with peripherals that use 32-bit addressing. + * b) At the end of a region that has enough space to hold the relocated U-Boot + * and all other allocations made around it (stack, heap, page tables, etc.) + */ +static u64 ram_top __attribute__((section(".data"))); +/* The base address of the region of RAM that ends at ram_top */ +static u64 region_base __attribute__((section(".data"))); + +int cboot_dram_init(void) +{ + unsigned int na, ns; + const void *cboot_blob = (void *)cboot_boot_x0; + int node, len, i; + const u32 *prop; + + if (!cboot_blob) + return -EINVAL; + + na = fdtdec_get_uint(cboot_blob, 0, "#address-cells", 2); + ns = fdtdec_get_uint(cboot_blob, 0, "#size-cells", 2); + + node = fdt_path_offset(cboot_blob, "/memory"); + if (node < 0) { + pr_err("Can't find /memory node in cboot DTB"); + hang(); + } + prop = fdt_getprop(cboot_blob, node, "reg", &len); + if (!prop) { + pr_err("Can't find /memory/reg property in cboot DTB"); + hang(); + } + + /* Calculate the true # of base/size pairs to read */ + len /= 4; /* Convert bytes to number of cells */ + len /= (na + ns); /* Convert cells to number of banks */ + if (len > CONFIG_NR_DRAM_BANKS) + len = CONFIG_NR_DRAM_BANKS; + + /* Parse the /memory node, and save useful entries */ + gd->ram_size = 0; + ram_bank_count = 0; + for (i = 0; i < len; i++) { + u64 bank_start, bank_end, bank_size, usable_bank_size; + + /* Extract raw memory region data from DTB */ + bank_start = fdt_read_number(prop, na); + prop += na; + bank_size = fdt_read_number(prop, ns); + prop += ns; + gd->ram_size += bank_size; + bank_end = bank_start + bank_size; + debug("Bank %d: %llx..%llx (+%llx)\n", i, + bank_start, bank_end, bank_size); + + /* + * Align the bank to MMU section size. This is not strictly + * necessary, since the translation table construction code + * handles page granularity without issue. However, aligning + * the MMU entries reduces the size and number of levels in the + * page table, so is worth it. + */ + bank_start = ROUND(bank_start, SZ_2M); + bank_end = bank_end & ~(SZ_2M - 1); + bank_size = bank_end - bank_start; + debug(" aligned: %llx..%llx (+%llx)\n", + bank_start, bank_end, bank_size); + if (bank_end <= bank_start) + continue; + + /* Record data used to create MMU translation tables */ + ram_bank_count++; + /* Index below is deliberately 1-based to skip MMIO entry */ + tegra_mem_map[ram_bank_count].virt = bank_start; + tegra_mem_map[ram_bank_count].phys = bank_start; + tegra_mem_map[ram_bank_count].size = bank_size; + tegra_mem_map[ram_bank_count].attrs = + PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE; + + /* Determine best bank to relocate U-Boot into */ + if (bank_end > SZ_4G) + bank_end = SZ_4G; + debug(" end %llx (usable)\n", bank_end); + usable_bank_size = bank_end - bank_start; + debug(" size %llx (usable)\n", usable_bank_size); + if ((usable_bank_size >= MIN_USABLE_RAM_SIZE) && + (bank_end > ram_top)) { + ram_top = bank_end; + region_base = bank_start; + debug("ram top now %llx\n", ram_top); + } + } + + /* Ensure memory map contains the desired sentinel entry */ + tegra_mem_map[ram_bank_count + 1].virt = 0; + tegra_mem_map[ram_bank_count + 1].phys = 0; + tegra_mem_map[ram_bank_count + 1].size = 0; + tegra_mem_map[ram_bank_count + 1].attrs = 0; + + /* Error out if a relocation target couldn't be found */ + if (!ram_top) { + pr_err("Can't find a usable RAM top"); + hang(); + } + + return 0; +} + +int cboot_dram_init_banksize(void) +{ + int i; + + if (ram_bank_count == 0) + return -EINVAL; + + if ((gd->start_addr_sp - region_base) < MIN_USABLE_STACK_SIZE) { + pr_err("Reservations exceed chosen region size"); + hang(); + } + + for (i = 0; i < ram_bank_count; i++) { + gd->bd->bi_dram[i].start = tegra_mem_map[1 + i].virt; + gd->bd->bi_dram[i].size = tegra_mem_map[1 + i].size; + } + +#ifdef CONFIG_PCI + gd->pci_ram_top = ram_top; +#endif + + return 0; +} + +ulong cboot_get_usable_ram_top(ulong total_size) +{ + return ram_top; +} + +/* + * The following few functions run late during the boot process and dynamically + * calculate the load address of various binaries. To keep track of multiple + * allocations, some writable list of RAM banks must be used. tegra_mem_map[] + * is used for this purpose to avoid making yet another copy of the list of RAM + * banks. This is safe because tegra_mem_map[] is only used once during very + * early boot to create U-Boot's page tables, long before this code runs. If + * this assumption becomes invalid later, we can just fix the code to copy the + * list of RAM banks into some private data structure before running. + */ + +static char *gen_varname(const char *var, const char *ext) +{ + size_t len_var = strlen(var); + size_t len_ext = strlen(ext); + size_t len = len_var + len_ext + 1; + char *varext = malloc(len); + + if (!varext) + return 0; + strcpy(varext, var); + strcpy(varext + len_var, ext); + return varext; +} + +static void mark_ram_allocated(int bank, u64 allocated_start, u64 allocated_end) +{ + u64 bank_start = tegra_mem_map[bank].virt; + u64 bank_size = tegra_mem_map[bank].size; + u64 bank_end = bank_start + bank_size; + bool keep_front = allocated_start != bank_start; + bool keep_tail = allocated_end != bank_end; + + if (keep_front && keep_tail) { + /* + * There are CONFIG_NR_DRAM_BANKS DRAM entries in the array, + * starting at index 1 (index 0 is MMIO). So, we are at DRAM + * entry "bank" not "bank - 1" as for a typical 0-base array. + * The number of remaining DRAM entries is therefore + * "CONFIG_NR_DRAM_BANKS - bank". We want to duplicate the + * current entry and shift up the remaining entries, dropping + * the last one. Thus, we must copy one fewer entry than the + * number remaining. + */ + memmove(&tegra_mem_map[bank + 1], &tegra_mem_map[bank], + CONFIG_NR_DRAM_BANKS - bank - 1); + tegra_mem_map[bank].size = allocated_start - bank_start; + bank++; + tegra_mem_map[bank].virt = allocated_end; + tegra_mem_map[bank].phys = allocated_end; + tegra_mem_map[bank].size = bank_end - allocated_end; + } else if (keep_front) { + tegra_mem_map[bank].size = allocated_start - bank_start; + } else if (keep_tail) { + tegra_mem_map[bank].virt = allocated_end; + tegra_mem_map[bank].phys = allocated_end; + tegra_mem_map[bank].size = bank_end - allocated_end; + } else { + /* + * We could move all subsequent banks down in the array but + * that's not necessary for subsequent allocations to work, so + * we skip doing so. + */ + tegra_mem_map[bank].size = 0; + } +} + +static void reserve_ram(u64 start, u64 size) +{ + int bank; + u64 end = start + size; + + for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) { + u64 bank_start = tegra_mem_map[bank].virt; + u64 bank_size = tegra_mem_map[bank].size; + u64 bank_end = bank_start + bank_size; + + if (end <= bank_start || start > bank_end) + continue; + mark_ram_allocated(bank, start, end); + break; + } +} + +static u64 alloc_ram(u64 size, u64 align, u64 offset) +{ + int bank; + + for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) { + u64 bank_start = tegra_mem_map[bank].virt; + u64 bank_size = tegra_mem_map[bank].size; + u64 bank_end = bank_start + bank_size; + u64 allocated = ROUND(bank_start, align) + offset; + u64 allocated_end = allocated + size; + + if (allocated_end > bank_end) + continue; + mark_ram_allocated(bank, allocated, allocated_end); + return allocated; + } + return 0; +} + +static void set_calculated_aliases(char *aliases, u64 address) +{ + char *tmp, *alias; + int err; + + aliases = strdup(aliases); + if (!aliases) { + pr_err("strdup(aliases) failed"); + return; + } + + tmp = aliases; + while (true) { + alias = strsep(&tmp, " "); + if (!alias) + break; + debug("%s: alias: %s\n", __func__, alias); + err = env_set_hex(alias, address); + if (err) + pr_err("Could not set %s\n", alias); + } + + free(aliases); +} + +static void set_calculated_env_var(const char *var) +{ + char *var_size; + char *var_align; + char *var_offset; + char *var_aliases; + u64 size; + u64 align; + u64 offset; + char *aliases; + u64 address; + int err; + + var_size = gen_varname(var, "_size"); + if (!var_size) + return; + var_align = gen_varname(var, "_align"); + if (!var_align) + goto out_free_var_size; + var_offset = gen_varname(var, "_offset"); + if (!var_offset) + goto out_free_var_align; + var_aliases = gen_varname(var, "_aliases"); + if (!var_aliases) + goto out_free_var_offset; + + size = env_get_hex(var_size, 0); + if (!size) { + pr_err("%s not set or zero\n", var_size); + goto out_free_var_aliases; + } + align = env_get_hex(var_align, 1); + /* Handle extant variables, but with a value of 0 */ + if (!align) + align = 1; + offset = env_get_hex(var_offset, 0); + aliases = env_get(var_aliases); + + debug("%s: Calc var %s; size=%llx, align=%llx, offset=%llx\n", + __func__, var, size, align, offset); + if (aliases) + debug("%s: Aliases: %s\n", __func__, aliases); + + address = alloc_ram(size, align, offset); + if (!address) { + pr_err("Could not allocate %s\n", var); + goto out_free_var_aliases; + } + debug("%s: Address %llx\n", __func__, address); + + err = env_set_hex(var, address); + if (err) + pr_err("Could not set %s\n", var); + if (aliases) + set_calculated_aliases(aliases, address); + +out_free_var_aliases: + free(var_aliases); +out_free_var_offset: + free(var_offset); +out_free_var_align: + free(var_align); +out_free_var_size: + free(var_size); +} + +#ifdef DEBUG +static void dump_ram_banks(void) +{ + int bank; + + for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) { + u64 bank_start = tegra_mem_map[bank].virt; + u64 bank_size = tegra_mem_map[bank].size; + u64 bank_end = bank_start + bank_size; + + if (!bank_size) + continue; + printf("%d: %010llx..%010llx (+%010llx)\n", bank - 1, + bank_start, bank_end, bank_size); + } +} +#endif + +static void set_calculated_env_vars(void) +{ + char *vars, *tmp, *var; + +#ifdef DEBUG + printf("RAM banks before any calculated env. var.s:\n"); + dump_ram_banks(); +#endif + + reserve_ram(cboot_boot_x0, fdt_totalsize(cboot_boot_x0)); + +#ifdef DEBUG + printf("RAM after reserving cboot DTB:\n"); + dump_ram_banks(); +#endif + + vars = env_get("calculated_vars"); + if (!vars) { + debug("%s: No env var calculated_vars\n", __func__); + return; + } + + vars = strdup(vars); + if (!vars) { + pr_err("strdup(calculated_vars) failed"); + return; + } + + tmp = vars; + while (true) { + var = strsep(&tmp, " "); + if (!var) + break; + debug("%s: var: %s\n", __func__, var); + set_calculated_env_var(var); +#ifdef DEBUG + printf("RAM banks after allocating %s:\n", var); + dump_ram_banks(); +#endif + } + + free(vars); +} + +static int set_fdt_addr(void) +{ + int ret; + + ret = env_set_hex("fdt_addr", cboot_boot_x0); + if (ret) { + printf("Failed to set fdt_addr to point at DTB: %d\n", ret); + return ret; + } + + return 0; +} + +/* + * Attempt to use /chosen/nvidia,ether-mac in the cboot DTB to U-Boot's + * ethaddr environment variable if possible. + */ +static int set_ethaddr_from_cboot(void) +{ + const void *cboot_blob = (void *)cboot_boot_x0; + int ret, node, len; + const u32 *prop; + + /* Already a valid address in the environment? If so, keep it */ + if (env_get("ethaddr")) + return 0; + + node = fdt_path_offset(cboot_blob, "/chosen"); + if (node < 0) { + printf("Can't find /chosen node in cboot DTB\n"); + return node; + } + prop = fdt_getprop(cboot_blob, node, "nvidia,ether-mac", &len); + if (!prop) { + printf("Can't find nvidia,ether-mac property in cboot DTB\n"); + return -ENOENT; + } + + ret = env_set("ethaddr", (void *)prop); + if (ret) { + printf("Failed to set ethaddr from cboot DTB: %d\n", ret); + return ret; + } + + return 0; +} + +int cboot_late_init(void) +{ + set_calculated_env_vars(); + /* + * Ignore errors here; the value may not be used depending on + * extlinux.conf or boot script content. + */ + set_fdt_addr(); + /* Ignore errors here; not all cases care about Ethernet addresses */ + set_ethaddr_from_cboot(); + + return 0; +} diff --git a/arch/arm/mach-tegra/cboot_ll.S b/arch/arm/mach-tegra/cboot_ll.S new file mode 100644 index 00000000000..4c9ddacc2b3 --- /dev/null +++ b/arch/arm/mach-tegra/cboot_ll.S @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Save cboot-related boot-time CPU state + * + * (C) Copyright 2015-2016 NVIDIA Corporation + */ + +#include +#include + +.align 8 +.globl cboot_boot_x0 +cboot_boot_x0: + .dword 0 + +ENTRY(cboot_save_boot_params) + adr x8, cboot_boot_x0 + str x0, [x8] + b save_boot_params_ret +ENDPROC(cboot_save_boot_params) diff --git a/arch/arm/mach-tegra/tegra186/Makefile b/arch/arm/mach-tegra/tegra186/Makefile index 56f3378ecea..3a240502770 100644 --- a/arch/arm/mach-tegra/tegra186/Makefile +++ b/arch/arm/mach-tegra/tegra186/Makefile @@ -2,8 +2,4 @@ # # SPDX-License-Identifier: GPL-2.0 -obj-y += ../board186.o obj-y += cache.o -obj-y += nvtboot_board.o -obj-y += nvtboot_ll.o -obj-y += nvtboot_mem.o diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_board.c b/arch/arm/mach-tegra/tegra186/nvtboot_board.c deleted file mode 100644 index 83c0e931ea2..00000000000 --- a/arch/arm/mach-tegra/tegra186/nvtboot_board.c +++ /dev/null @@ -1,332 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2016-2018, NVIDIA CORPORATION. - */ - -#include -#include -#include -#include -#include -#include - -extern unsigned long nvtboot_boot_x0; - -/* - * The following few functions run late during the boot process and dynamically - * calculate the load address of various binaries. To keep track of multiple - * allocations, some writable list of RAM banks must be used. tegra_mem_map[] - * is used for this purpose to avoid making yet another copy of the list of RAM - * banks. This is safe because tegra_mem_map[] is only used once during very - * early boot to create U-Boot's page tables, long before this code runs. If - * this assumption becomes invalid later, we can just fix the code to copy the - * list of RAM banks into some private data structure before running. - */ - -extern struct mm_region tegra_mem_map[]; - -static char *gen_varname(const char *var, const char *ext) -{ - size_t len_var = strlen(var); - size_t len_ext = strlen(ext); - size_t len = len_var + len_ext + 1; - char *varext = malloc(len); - - if (!varext) - return 0; - strcpy(varext, var); - strcpy(varext + len_var, ext); - return varext; -} - -static void mark_ram_allocated(int bank, u64 allocated_start, u64 allocated_end) -{ - u64 bank_start = tegra_mem_map[bank].virt; - u64 bank_size = tegra_mem_map[bank].size; - u64 bank_end = bank_start + bank_size; - bool keep_front = allocated_start != bank_start; - bool keep_tail = allocated_end != bank_end; - - if (keep_front && keep_tail) { - /* - * There are CONFIG_NR_DRAM_BANKS DRAM entries in the array, - * starting at index 1 (index 0 is MMIO). So, we are at DRAM - * entry "bank" not "bank - 1" as for a typical 0-base array. - * The number of remaining DRAM entries is therefore - * "CONFIG_NR_DRAM_BANKS - bank". We want to duplicate the - * current entry and shift up the remaining entries, dropping - * the last one. Thus, we must copy one fewer entry than the - * number remaining. - */ - memmove(&tegra_mem_map[bank + 1], &tegra_mem_map[bank], - CONFIG_NR_DRAM_BANKS - bank - 1); - tegra_mem_map[bank].size = allocated_start - bank_start; - bank++; - tegra_mem_map[bank].virt = allocated_end; - tegra_mem_map[bank].phys = allocated_end; - tegra_mem_map[bank].size = bank_end - allocated_end; - } else if (keep_front) { - tegra_mem_map[bank].size = allocated_start - bank_start; - } else if (keep_tail) { - tegra_mem_map[bank].virt = allocated_end; - tegra_mem_map[bank].phys = allocated_end; - tegra_mem_map[bank].size = bank_end - allocated_end; - } else { - /* - * We could move all subsequent banks down in the array but - * that's not necessary for subsequent allocations to work, so - * we skip doing so. - */ - tegra_mem_map[bank].size = 0; - } -} - -static void reserve_ram(u64 start, u64 size) -{ - int bank; - u64 end = start + size; - - for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) { - u64 bank_start = tegra_mem_map[bank].virt; - u64 bank_size = tegra_mem_map[bank].size; - u64 bank_end = bank_start + bank_size; - - if (end <= bank_start || start > bank_end) - continue; - mark_ram_allocated(bank, start, end); - break; - } -} - -static u64 alloc_ram(u64 size, u64 align, u64 offset) -{ - int bank; - - for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) { - u64 bank_start = tegra_mem_map[bank].virt; - u64 bank_size = tegra_mem_map[bank].size; - u64 bank_end = bank_start + bank_size; - u64 allocated = ROUND(bank_start, align) + offset; - u64 allocated_end = allocated + size; - - if (allocated_end > bank_end) - continue; - mark_ram_allocated(bank, allocated, allocated_end); - return allocated; - } - return 0; -} - -static void set_calculated_aliases(char *aliases, u64 address) -{ - char *tmp, *alias; - int err; - - aliases = strdup(aliases); - if (!aliases) { - pr_err("strdup(aliases) failed"); - return; - } - - tmp = aliases; - while (true) { - alias = strsep(&tmp, " "); - if (!alias) - break; - debug("%s: alias: %s\n", __func__, alias); - err = env_set_hex(alias, address); - if (err) - pr_err("Could not set %s\n", alias); - } - - free(aliases); -} - -static void set_calculated_env_var(const char *var) -{ - char *var_size; - char *var_align; - char *var_offset; - char *var_aliases; - u64 size; - u64 align; - u64 offset; - char *aliases; - u64 address; - int err; - - var_size = gen_varname(var, "_size"); - if (!var_size) - return; - var_align = gen_varname(var, "_align"); - if (!var_align) - goto out_free_var_size; - var_offset = gen_varname(var, "_offset"); - if (!var_offset) - goto out_free_var_align; - var_aliases = gen_varname(var, "_aliases"); - if (!var_aliases) - goto out_free_var_offset; - - size = env_get_hex(var_size, 0); - if (!size) { - pr_err("%s not set or zero\n", var_size); - goto out_free_var_aliases; - } - align = env_get_hex(var_align, 1); - /* Handle extant variables, but with a value of 0 */ - if (!align) - align = 1; - offset = env_get_hex(var_offset, 0); - aliases = env_get(var_aliases); - - debug("%s: Calc var %s; size=%llx, align=%llx, offset=%llx\n", - __func__, var, size, align, offset); - if (aliases) - debug("%s: Aliases: %s\n", __func__, aliases); - - address = alloc_ram(size, align, offset); - if (!address) { - pr_err("Could not allocate %s\n", var); - goto out_free_var_aliases; - } - debug("%s: Address %llx\n", __func__, address); - - err = env_set_hex(var, address); - if (err) - pr_err("Could not set %s\n", var); - if (aliases) - set_calculated_aliases(aliases, address); - -out_free_var_aliases: - free(var_aliases); -out_free_var_offset: - free(var_offset); -out_free_var_align: - free(var_align); -out_free_var_size: - free(var_size); -} - -#ifdef DEBUG -static void dump_ram_banks(void) -{ - int bank; - - for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) { - u64 bank_start = tegra_mem_map[bank].virt; - u64 bank_size = tegra_mem_map[bank].size; - u64 bank_end = bank_start + bank_size; - - if (!bank_size) - continue; - printf("%d: %010llx..%010llx (+%010llx)\n", bank - 1, - bank_start, bank_end, bank_size); - } -} -#endif - -static void set_calculated_env_vars(void) -{ - char *vars, *tmp, *var; - -#ifdef DEBUG - printf("RAM banks before any calculated env. var.s:\n"); - dump_ram_banks(); -#endif - - reserve_ram(nvtboot_boot_x0, fdt_totalsize(nvtboot_boot_x0)); - -#ifdef DEBUG - printf("RAM after reserving cboot DTB:\n"); - dump_ram_banks(); -#endif - - vars = env_get("calculated_vars"); - if (!vars) { - debug("%s: No env var calculated_vars\n", __func__); - return; - } - - vars = strdup(vars); - if (!vars) { - pr_err("strdup(calculated_vars) failed"); - return; - } - - tmp = vars; - while (true) { - var = strsep(&tmp, " "); - if (!var) - break; - debug("%s: var: %s\n", __func__, var); - set_calculated_env_var(var); -#ifdef DEBUG - printf("RAM banks affter allocating %s:\n", var); - dump_ram_banks(); -#endif - } - - free(vars); -} - -static int set_fdt_addr(void) -{ - int ret; - - ret = env_set_hex("fdt_addr", nvtboot_boot_x0); - if (ret) { - printf("Failed to set fdt_addr to point at DTB: %d\n", ret); - return ret; - } - - return 0; -} - -/* - * Attempt to use /chosen/nvidia,ether-mac in the nvtboot DTB to U-Boot's - * ethaddr environment variable if possible. - */ -static int set_ethaddr_from_nvtboot(void) -{ - const void *nvtboot_blob = (void *)nvtboot_boot_x0; - int ret, node, len; - const u32 *prop; - - /* Already a valid address in the environment? If so, keep it */ - if (env_get("ethaddr")) - return 0; - - node = fdt_path_offset(nvtboot_blob, "/chosen"); - if (node < 0) { - printf("Can't find /chosen node in nvtboot DTB\n"); - return node; - } - prop = fdt_getprop(nvtboot_blob, node, "nvidia,ether-mac", &len); - if (!prop) { - printf("Can't find nvidia,ether-mac property in nvtboot DTB\n"); - return -ENOENT; - } - - ret = env_set("ethaddr", (void *)prop); - if (ret) { - printf("Failed to set ethaddr from nvtboot DTB: %d\n", ret); - return ret; - } - - return 0; -} - -int tegra_soc_board_init_late(void) -{ - set_calculated_env_vars(); - /* - * Ignore errors here; the value may not be used depending on - * extlinux.conf or boot script content. - */ - set_fdt_addr(); - /* Ignore errors here; not all cases care about Ethernet addresses */ - set_ethaddr_from_nvtboot(); - - return 0; -} diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S b/arch/arm/mach-tegra/tegra186/nvtboot_ll.S deleted file mode 100644 index aa7a863d970..00000000000 --- a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Save nvtboot-related boot-time CPU state - * - * (C) Copyright 2015-2016 NVIDIA Corporation - */ - -#include -#include - -.align 8 -.globl nvtboot_boot_x0 -nvtboot_boot_x0: - .dword 0 - -ENTRY(save_boot_params) - adr x8, nvtboot_boot_x0 - str x0, [x8] - b save_boot_params_ret -ENDPROC(save_boot_params) diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c deleted file mode 100644 index 62142821a59..00000000000 --- a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2016-2018, NVIDIA CORPORATION. - */ - -#include -#include -#include -#include -#include -#include - -/* - * Size of a region that's large enough to hold the relocated U-Boot and all - * other allocations made around it (stack, heap, page tables, etc.) - * In practice, running "bdinfo" at the shell prompt, the stack reaches about - * 5MB from the address selected for ram_top as of the time of writing, - * so a 16MB region should be plenty. - */ -#define MIN_USABLE_RAM_SIZE SZ_16M -/* - * The amount of space we expect to require for stack usage. Used to validate - * that all reservations fit into the region selected for the relocation target - */ -#define MIN_USABLE_STACK_SIZE SZ_1M - -DECLARE_GLOBAL_DATA_PTR; - -extern unsigned long nvtboot_boot_x0; -extern struct mm_region tegra_mem_map[]; - -/* - * These variables are written to before relocation, and hence cannot be - * in.bss, since .bss overlaps the DTB that's appended to the U-Boot binary. - * The section attribute forces this into .data and avoids this issue. This - * also has the nice side-effect of the content being valid after relocation. - */ - -/* The number of valid entries in ram_banks[] */ -static int ram_bank_count __attribute__((section(".data"))); - -/* - * The usable top-of-RAM for U-Boot. This is both: - * a) Below 4GB to avoid issues with peripherals that use 32-bit addressing. - * b) At the end of a region that has enough space to hold the relocated U-Boot - * and all other allocations made around it (stack, heap, page tables, etc.) - */ -static u64 ram_top __attribute__((section(".data"))); -/* The base address of the region of RAM that ends at ram_top */ -static u64 region_base __attribute__((section(".data"))); - -int dram_init(void) -{ - unsigned int na, ns; - const void *nvtboot_blob = (void *)nvtboot_boot_x0; - int node, len, i; - const u32 *prop; - - na = fdtdec_get_uint(nvtboot_blob, 0, "#address-cells", 2); - ns = fdtdec_get_uint(nvtboot_blob, 0, "#size-cells", 2); - - node = fdt_path_offset(nvtboot_blob, "/memory"); - if (node < 0) { - pr_err("Can't find /memory node in nvtboot DTB"); - hang(); - } - prop = fdt_getprop(nvtboot_blob, node, "reg", &len); - if (!prop) { - pr_err("Can't find /memory/reg property in nvtboot DTB"); - hang(); - } - - /* Calculate the true # of base/size pairs to read */ - len /= 4; /* Convert bytes to number of cells */ - len /= (na + ns); /* Convert cells to number of banks */ - if (len > CONFIG_NR_DRAM_BANKS) - len = CONFIG_NR_DRAM_BANKS; - - /* Parse the /memory node, and save useful entries */ - gd->ram_size = 0; - ram_bank_count = 0; - for (i = 0; i < len; i++) { - u64 bank_start, bank_end, bank_size, usable_bank_size; - - /* Extract raw memory region data from DTB */ - bank_start = fdt_read_number(prop, na); - prop += na; - bank_size = fdt_read_number(prop, ns); - prop += ns; - gd->ram_size += bank_size; - bank_end = bank_start + bank_size; - debug("Bank %d: %llx..%llx (+%llx)\n", i, - bank_start, bank_end, bank_size); - - /* - * Align the bank to MMU section size. This is not strictly - * necessary, since the translation table construction code - * handles page granularity without issue. However, aligning - * the MMU entries reduces the size and number of levels in the - * page table, so is worth it. - */ - bank_start = ROUND(bank_start, SZ_2M); - bank_end = bank_end & ~(SZ_2M - 1); - bank_size = bank_end - bank_start; - debug(" aligned: %llx..%llx (+%llx)\n", - bank_start, bank_end, bank_size); - if (bank_end <= bank_start) - continue; - - /* Record data used to create MMU translation tables */ - ram_bank_count++; - /* Index below is deliberately 1-based to skip MMIO entry */ - tegra_mem_map[ram_bank_count].virt = bank_start; - tegra_mem_map[ram_bank_count].phys = bank_start; - tegra_mem_map[ram_bank_count].size = bank_size; - tegra_mem_map[ram_bank_count].attrs = - PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE; - - /* Determine best bank to relocate U-Boot into */ - if (bank_end > SZ_4G) - bank_end = SZ_4G; - debug(" end %llx (usable)\n", bank_end); - usable_bank_size = bank_end - bank_start; - debug(" size %llx (usable)\n", usable_bank_size); - if ((usable_bank_size >= MIN_USABLE_RAM_SIZE) && - (bank_end > ram_top)) { - ram_top = bank_end; - region_base = bank_start; - debug("ram top now %llx\n", ram_top); - } - } - - /* Ensure memory map contains the desired sentinel entry */ - tegra_mem_map[ram_bank_count + 1].virt = 0; - tegra_mem_map[ram_bank_count + 1].phys = 0; - tegra_mem_map[ram_bank_count + 1].size = 0; - tegra_mem_map[ram_bank_count + 1].attrs = 0; - - /* Error out if a relocation target couldn't be found */ - if (!ram_top) { - pr_err("Can't find a usable RAM top"); - hang(); - } - - return 0; -} - -int dram_init_banksize(void) -{ - int i; - - if ((gd->start_addr_sp - region_base) < MIN_USABLE_STACK_SIZE) { - pr_err("Reservations exceed chosen region size"); - hang(); - } - - for (i = 0; i < ram_bank_count; i++) { - gd->bd->bi_dram[i].start = tegra_mem_map[1 + i].virt; - gd->bd->bi_dram[i].size = tegra_mem_map[1 + i].size; - } - -#ifdef CONFIG_PCI - gd->pci_ram_top = ram_top; -#endif - - return 0; -} - -ulong board_get_usable_ram_top(ulong total_size) -{ - return ram_top; -} diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c index 496e8a02111..6f88010c18c 100644 --- a/board/nvidia/p2771-0000/p2771-0000.c +++ b/board/nvidia/p2771-0000/p2771-0000.c @@ -7,7 +7,7 @@ #include #include "../p2571/max77620_init.h" -int tegra_board_init(void) +void pin_mux_mmc(void) { struct udevice *dev; uchar val; @@ -18,19 +18,18 @@ int tegra_board_init(void) ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev); if (ret) { printf("%s: Cannot find MAX77620 I2C chip\n", __func__); - return ret; + return; } /* 0xF2 for 3.3v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */ val = 0xF2; ret = dm_i2c_write(dev, MAX77620_CNFG1_L3_REG, &val, 1); if (ret) { printf("i2c_write 0 0x3c 0x27 failed: %d\n", ret); - return ret; + return; } - - return 0; } +#ifdef CONFIG_PCI_TEGRA int tegra_pcie_board_init(void) { struct udevice *dev; @@ -52,3 +51,4 @@ int tegra_pcie_board_init(void) return 0; } +#endif -- cgit v1.2.3 From ce353babdbc478c40f884555b754c533ab8f8af5 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:29 +0200 Subject: ARM: tegra: Implement cboot_save_boot_params() in C This is easier to deal with and works just as well for this simple function. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/cboot.c | 12 ++++++++++++ arch/arm/mach-tegra/cboot_ll.S | 20 -------------------- 3 files changed, 13 insertions(+), 21 deletions(-) delete mode 100644 arch/arm/mach-tegra/cboot_ll.S (limited to 'arch') diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 41ba674edff..7165d70a60d 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -20,7 +20,7 @@ obj-$(CONFIG_TEGRA_PINCTRL) += pinmux-common.o obj-$(CONFIG_TEGRA_PMC) += powergate.o obj-y += xusb-padctl-dummy.o -obj-$(CONFIG_ARM64) += arm64-mmu.o cboot_ll.o cboot.o +obj-$(CONFIG_ARM64) += arm64-mmu.o cboot.o obj-y += dt-setup.o obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o obj-$(CONFIG_TEGRA_GPU) += gpu.o diff --git a/arch/arm/mach-tegra/cboot.c b/arch/arm/mach-tegra/cboot.c index 3ebf7b05555..a302ca45f39 100644 --- a/arch/arm/mach-tegra/cboot.c +++ b/arch/arm/mach-tegra/cboot.c @@ -52,6 +52,18 @@ static u64 ram_top __attribute__((section(".data"))); /* The base address of the region of RAM that ends at ram_top */ static u64 region_base __attribute__((section(".data"))); +/* + * Explicitly put this in the .data section because it is written before the + * .bss section is zeroed out but it needs to persist. + */ +unsigned long cboot_boot_x0 __attribute__((section(".data"))); + +void cboot_save_boot_params(unsigned long x0, unsigned long x1, + unsigned long x2, unsigned long x3) +{ + cboot_boot_x0 = x0; +} + int cboot_dram_init(void) { unsigned int na, ns; diff --git a/arch/arm/mach-tegra/cboot_ll.S b/arch/arm/mach-tegra/cboot_ll.S deleted file mode 100644 index 4c9ddacc2b3..00000000000 --- a/arch/arm/mach-tegra/cboot_ll.S +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Save cboot-related boot-time CPU state - * - * (C) Copyright 2015-2016 NVIDIA Corporation - */ - -#include -#include - -.align 8 -.globl cboot_boot_x0 -cboot_boot_x0: - .dword 0 - -ENTRY(cboot_save_boot_params) - adr x8, cboot_boot_x0 - str x0, [x8] - b save_boot_params_ret -ENDPROC(cboot_save_boot_params) -- cgit v1.2.3 From 34e12e03c7f4cbd96e584a590d6e091c48ab8e3d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:30 +0200 Subject: ARM: tegra: Implement cboot_get_ethaddr() This function will attempt to look up an Ethernet address in the DTB that was passed in from cboot. It does so by first trying to locate the default Ethernet device for the board (identified by the "ethernet" alias) and if found, reads the "local-mac-address" property. If the "ethernet" alias does not exist, or if it points to a device tree node that doesn't exist, or if the device tree node that it points to does not have a "local-mac-address" property or if the value is invalid, it will fall back to the legacy mechanism of looking for the MAC address stored in the "nvidia,ethernet-mac" or "nvidia,ether-mac" properties of the "/chosen" node. The MAC address is then written to the default Ethernet device for the board (again identified by the "ethernet" alias) in U-Boot's control DTB. This allows the device driver for that device to read the MAC address from the standard location in device tree. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/include/asm/arch-tegra/cboot.h | 6 ++ arch/arm/mach-tegra/cboot.c | 97 +++++++++++++++++++++++++++------ 2 files changed, 86 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-tegra/cboot.h b/arch/arm/include/asm/arch-tegra/cboot.h index b3441ec178b..021c2461757 100644 --- a/arch/arm/include/asm/arch-tegra/cboot.h +++ b/arch/arm/include/asm/arch-tegra/cboot.h @@ -14,6 +14,7 @@ void cboot_save_boot_params(unsigned long x0, unsigned long x1, int cboot_dram_init(void); int cboot_dram_init_banksize(void); ulong cboot_get_usable_ram_top(ulong total_size); +int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN]); #else static inline void cboot_save_boot_params(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3) @@ -34,6 +35,11 @@ static inline ulong cboot_get_usable_ram_top(ulong total_size) { return 0; } + +static inline int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN]) +{ + return -ENOSYS; +} #endif #endif diff --git a/arch/arm/mach-tegra/cboot.c b/arch/arm/mach-tegra/cboot.c index a302ca45f39..628909f2913 100644 --- a/arch/arm/mach-tegra/cboot.c +++ b/arch/arm/mach-tegra/cboot.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -465,46 +466,108 @@ static int set_fdt_addr(void) * Attempt to use /chosen/nvidia,ether-mac in the cboot DTB to U-Boot's * ethaddr environment variable if possible. */ -static int set_ethaddr_from_cboot(void) +static int cboot_get_ethaddr_legacy(const void *fdt, uint8_t mac[ETH_ALEN]) { - const void *cboot_blob = (void *)cboot_boot_x0; - int ret, node, len; - const u32 *prop; - - /* Already a valid address in the environment? If so, keep it */ - if (env_get("ethaddr")) - return 0; - - node = fdt_path_offset(cboot_blob, "/chosen"); + const char *const properties[] = { + "nvidia,ethernet-mac", + "nvidia,ether-mac", + }; + const char *prop; + unsigned int i; + int node, len; + + node = fdt_path_offset(fdt, "/chosen"); if (node < 0) { printf("Can't find /chosen node in cboot DTB\n"); return node; } - prop = fdt_getprop(cboot_blob, node, "nvidia,ether-mac", &len); + + for (i = 0; i < ARRAY_SIZE(properties); i++) { + prop = fdt_getprop(fdt, node, properties[i], &len); + if (prop) + break; + } + if (!prop) { - printf("Can't find nvidia,ether-mac property in cboot DTB\n"); + printf("Can't find Ethernet MAC address in cboot DTB\n"); return -ENOENT; } - ret = env_set("ethaddr", (void *)prop); - if (ret) { - printf("Failed to set ethaddr from cboot DTB: %d\n", ret); - return ret; + eth_parse_enetaddr(prop, mac); + + if (!is_valid_ethaddr(mac)) { + printf("Invalid MAC address: %s\n", prop); + return -EINVAL; } + debug("Legacy MAC address: %pM\n", mac); + return 0; } +int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN]) +{ + int node, len, err = 0; + const uchar *prop; + const char *path; + + path = fdt_get_alias(fdt, "ethernet"); + if (!path) { + err = -ENOENT; + goto out; + } + + debug("ethernet alias found: %s\n", path); + + node = fdt_path_offset(fdt, path); + if (node < 0) { + err = -ENOENT; + goto out; + } + + prop = fdt_getprop(fdt, node, "local-mac-address", &len); + if (!prop) { + err = -ENOENT; + goto out; + } + + if (len != ETH_ALEN) { + err = -EINVAL; + goto out; + } + + debug("MAC address: %pM\n", prop); + memcpy(mac, prop, ETH_ALEN); + +out: + if (err < 0) + err = cboot_get_ethaddr_legacy(fdt, mac); + + return err; +} + int cboot_late_init(void) { + const void *fdt = (const void *)cboot_boot_x0; + uint8_t mac[ETH_ALEN]; + int err; + set_calculated_env_vars(); /* * Ignore errors here; the value may not be used depending on * extlinux.conf or boot script content. */ set_fdt_addr(); + /* Ignore errors here; not all cases care about Ethernet addresses */ - set_ethaddr_from_cboot(); + err = cboot_get_ethaddr(fdt, mac); + if (!err) { + void *blob = (void *)gd->fdt_blob; + + err = fdtdec_set_ethernet_mac_address(blob, mac, sizeof(mac)); + if (err < 0) + printf("failed to set MAC address %pM: %d\n", mac, err); + } return 0; } -- cgit v1.2.3 From b571766453c83aadfd44f6c4adbb0130bbfa50e3 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:31 +0200 Subject: ARM: tegra: Import cbootargs value from cboot DTB Read the boot arguments passed by cboot via the /chosen/bootargs property and store it in the cbootargs environment variable. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/cboot.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-tegra/cboot.c b/arch/arm/mach-tegra/cboot.c index 628909f2913..a829ef794f2 100644 --- a/arch/arm/mach-tegra/cboot.c +++ b/arch/arm/mach-tegra/cboot.c @@ -8,7 +8,9 @@ #include #include #include +#include +#include #include #include @@ -546,10 +548,49 @@ out: return err; } +static char *strip(const char *ptr) +{ + const char *end; + + while (*ptr && isblank(*ptr)) + ptr++; + + /* empty string */ + if (*ptr == '\0') + return strdup(ptr); + + end = ptr; + + while (end[1]) + end++; + + while (isblank(*end)) + end--; + + return strndup(ptr, end - ptr + 1); +} + +static char *cboot_get_bootargs(const void *fdt) +{ + const char *args; + int offset, len; + + offset = fdt_path_offset(fdt, "/chosen"); + if (offset < 0) + return NULL; + + args = fdt_getprop(fdt, offset, "bootargs", &len); + if (!args) + return NULL; + + return strip(args); +} + int cboot_late_init(void) { const void *fdt = (const void *)cboot_boot_x0; uint8_t mac[ETH_ALEN]; + char *bootargs; int err; set_calculated_env_vars(); @@ -569,5 +610,11 @@ int cboot_late_init(void) printf("failed to set MAC address %pM: %d\n", mac, err); } + bootargs = cboot_get_bootargs(fdt); + if (bootargs) { + env_set("cbootargs", bootargs); + free(bootargs); + } + return 0; } -- cgit v1.2.3 From 74a50ac2a4b9a1906fa3787a4bcd5b079e97d3f8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:32 +0200 Subject: ARM: tegra: Enable position independent build for 64-bit Note that U-Boot is always chainloaded from cboot starting with L4T release 28. cboot always loads U-Boot to a fixed address, so making the builds position independent isn't strictly necessary. However, position independent builds can be convenient because if U-Boot is ever loaded to an address different from its link address, it will still be able to boot. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/mach-tegra/Kconfig | 1 + configs/e2220-1170_defconfig | 2 +- configs/p2371-0000_defconfig | 2 +- configs/p2371-2180_defconfig | 2 +- configs/p2571_defconfig | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index faa73559fd4..97e22ead598 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -87,6 +87,7 @@ config TEGRA_ARMV8_COMMON bool "Tegra 64-bit common options" select ARM64 select LINUX_KERNEL_IMAGE_HEADER + select POSITION_INDEPENDENT select TEGRA_COMMON if TEGRA_ARMV8_COMMON diff --git a/configs/e2220-1170_defconfig b/configs/e2220-1170_defconfig index 4d253c50725..d650acae24c 100644 --- a/configs/e2220-1170_defconfig +++ b/configs/e2220-1170_defconfig @@ -1,6 +1,6 @@ CONFIG_ARM=y CONFIG_TEGRA=y -CONFIG_SYS_TEXT_BASE=0x80110000 +CONFIG_SYS_TEXT_BASE=0x80080000 CONFIG_NR_DRAM_BANKS=2 CONFIG_TEGRA210=y CONFIG_OF_SYSTEM_SETUP=y diff --git a/configs/p2371-0000_defconfig b/configs/p2371-0000_defconfig index cdcb98a77ea..aa9c1f66c4f 100644 --- a/configs/p2371-0000_defconfig +++ b/configs/p2371-0000_defconfig @@ -1,6 +1,6 @@ CONFIG_ARM=y CONFIG_TEGRA=y -CONFIG_SYS_TEXT_BASE=0x80110000 +CONFIG_SYS_TEXT_BASE=0x80080000 CONFIG_NR_DRAM_BANKS=2 CONFIG_TEGRA210=y CONFIG_TARGET_P2371_0000=y diff --git a/configs/p2371-2180_defconfig b/configs/p2371-2180_defconfig index 122b1b1fd5a..2fa2fbb5eda 100644 --- a/configs/p2371-2180_defconfig +++ b/configs/p2371-2180_defconfig @@ -1,6 +1,6 @@ CONFIG_ARM=y CONFIG_TEGRA=y -CONFIG_SYS_TEXT_BASE=0x80110000 +CONFIG_SYS_TEXT_BASE=0x80080000 CONFIG_NR_DRAM_BANKS=2 CONFIG_TEGRA210=y CONFIG_TARGET_P2371_2180=y diff --git a/configs/p2571_defconfig b/configs/p2571_defconfig index d28506b1c66..1c47064c04a 100644 --- a/configs/p2571_defconfig +++ b/configs/p2571_defconfig @@ -1,6 +1,6 @@ CONFIG_ARM=y CONFIG_TEGRA=y -CONFIG_SYS_TEXT_BASE=0x80110000 +CONFIG_SYS_TEXT_BASE=0x80080000 CONFIG_NR_DRAM_BANKS=2 CONFIG_TEGRA210=y CONFIG_TARGET_P2571=y -- cgit v1.2.3 From 1e669b4808c4457fc53f78655748ec625dd3440c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:37 +0200 Subject: ARM: tegra: Rename pcie-controller to pcie Recent versions of DTC have checks for PCI host bridge device tree nodes that are named something other than "pci" or "pcie". Fix all occurrences of such nodes for Tegra boards to avoid potential warnings from DTC. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/dts/tegra124-apalis.dts | 2 +- arch/arm/dts/tegra124-cei-tk1-som.dts | 2 +- arch/arm/dts/tegra124-jetson-tk1.dts | 2 +- arch/arm/dts/tegra124.dtsi | 2 +- arch/arm/dts/tegra186-p2771-0000-000.dts | 2 +- arch/arm/dts/tegra186-p2771-0000-500.dts | 2 +- arch/arm/dts/tegra186.dtsi | 2 +- arch/arm/dts/tegra20-harmony.dts | 2 +- arch/arm/dts/tegra20-trimslice.dts | 2 +- arch/arm/dts/tegra20.dtsi | 2 +- arch/arm/dts/tegra210-p2371-2180.dts | 2 +- arch/arm/dts/tegra210.dtsi | 2 +- arch/arm/dts/tegra30-apalis.dts | 2 +- arch/arm/dts/tegra30-beaver.dts | 2 +- arch/arm/dts/tegra30-cardhu.dts | 2 +- arch/arm/dts/tegra30.dtsi | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/arm/dts/tegra124-apalis.dts b/arch/arm/dts/tegra124-apalis.dts index fe08d3ea730..a962c0a2f0a 100644 --- a/arch/arm/dts/tegra124-apalis.dts +++ b/arch/arm/dts/tegra124-apalis.dts @@ -77,7 +77,7 @@ reg = <0x0 0x80000000 0x0 0x80000000>; }; - pcie-controller@01003000 { + pcie@1003000 { status = "okay"; avddio-pex-supply = <&vdd_1v05>; avdd-pex-pll-supply = <&vdd_1v05>; diff --git a/arch/arm/dts/tegra124-cei-tk1-som.dts b/arch/arm/dts/tegra124-cei-tk1-som.dts index b1dd4181ac0..e5b41f3183c 100644 --- a/arch/arm/dts/tegra124-cei-tk1-som.dts +++ b/arch/arm/dts/tegra124-cei-tk1-som.dts @@ -29,7 +29,7 @@ reg = <0x80000000 0x80000000>; }; - pcie-controller@01003000 { + pcie@1003000 { status = "okay"; avddio-pex-supply = <&vdd_1v05_run>; diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts index d6420436cde..59e080a8af6 100644 --- a/arch/arm/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/dts/tegra124-jetson-tk1.dts @@ -29,7 +29,7 @@ reg = <0x80000000 0x80000000>; }; - pcie-controller@01003000 { + pcie@1003000 { status = "okay"; avddio-pex-supply = <&vdd_1v05_run>; diff --git a/arch/arm/dts/tegra124.dtsi b/arch/arm/dts/tegra124.dtsi index 83d63480471..f473ba28e4a 100644 --- a/arch/arm/dts/tegra124.dtsi +++ b/arch/arm/dts/tegra124.dtsi @@ -14,7 +14,7 @@ interrupt-parent = <&lic>; - pcie-controller@01003000 { + pcie@1003000 { compatible = "nvidia,tegra124-pcie"; device_type = "pci"; reg = <0x01003000 0x00000800 /* PADS registers */ diff --git a/arch/arm/dts/tegra186-p2771-0000-000.dts b/arch/arm/dts/tegra186-p2771-0000-000.dts index d97c6fd3d09..84e850d6fca 100644 --- a/arch/arm/dts/tegra186-p2771-0000-000.dts +++ b/arch/arm/dts/tegra186-p2771-0000-000.dts @@ -11,7 +11,7 @@ power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 5) GPIO_ACTIVE_HIGH>; }; - pcie-controller@10003000 { + pcie@10003000 { status = "okay"; pci@1,0 { diff --git a/arch/arm/dts/tegra186-p2771-0000-500.dts b/arch/arm/dts/tegra186-p2771-0000-500.dts index 393a8b246a0..1ac8ab431e9 100644 --- a/arch/arm/dts/tegra186-p2771-0000-500.dts +++ b/arch/arm/dts/tegra186-p2771-0000-500.dts @@ -11,7 +11,7 @@ power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 6) GPIO_ACTIVE_HIGH>; }; - pcie-controller@10003000 { + pcie@10003000 { status = "okay"; pci@1,0 { diff --git a/arch/arm/dts/tegra186.dtsi b/arch/arm/dts/tegra186.dtsi index dd9e3b869de..0a9db9825b8 100644 --- a/arch/arm/dts/tegra186.dtsi +++ b/arch/arm/dts/tegra186.dtsi @@ -217,7 +217,7 @@ #interrupt-cells = <2>; }; - pcie-controller@10003000 { + pcie@10003000 { compatible = "nvidia,tegra186-pcie"; device_type = "pci"; reg = <0x0 0x10003000 0x0 0x00000800 /* PADS registers */ diff --git a/arch/arm/dts/tegra20-harmony.dts b/arch/arm/dts/tegra20-harmony.dts index 0c907054dbd..7fe7d52096c 100644 --- a/arch/arm/dts/tegra20-harmony.dts +++ b/arch/arm/dts/tegra20-harmony.dts @@ -599,7 +599,7 @@ nvidia,sys-clock-req-active-high; }; - pcie-controller@80003000 { + pcie@80003000 { status = "okay"; avdd-pex-supply = <&pci_vdd_reg>; diff --git a/arch/arm/dts/tegra20-trimslice.dts b/arch/arm/dts/tegra20-trimslice.dts index 31f509ab12c..e19001ee2bd 100644 --- a/arch/arm/dts/tegra20-trimslice.dts +++ b/arch/arm/dts/tegra20-trimslice.dts @@ -30,7 +30,7 @@ spi-max-frequency = <25000000>; }; - pcie-controller@80003000 { + pcie@80003000 { status = "okay"; avdd-pex-supply = <&pci_vdd_reg>; diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi index e21ee258b37..275b3432bd8 100644 --- a/arch/arm/dts/tegra20.dtsi +++ b/arch/arm/dts/tegra20.dtsi @@ -580,7 +580,7 @@ reset-names = "fuse"; }; - pcie-controller@80003000 { + pcie@80003000 { compatible = "nvidia,tegra20-pcie"; device_type = "pci"; reg = <0x80003000 0x00000800 /* PADS registers */ diff --git a/arch/arm/dts/tegra210-p2371-2180.dts b/arch/arm/dts/tegra210-p2371-2180.dts index da4349bd039..c2f497c524a 100644 --- a/arch/arm/dts/tegra210-p2371-2180.dts +++ b/arch/arm/dts/tegra210-p2371-2180.dts @@ -21,7 +21,7 @@ reg = <0x0 0x80000000 0x0 0xc0000000>; }; - pcie-controller@01003000 { + pcie@1003000 { status = "okay"; pci@1,0 { diff --git a/arch/arm/dts/tegra210.dtsi b/arch/arm/dts/tegra210.dtsi index 229fed04529..3ec54b11c43 100644 --- a/arch/arm/dts/tegra210.dtsi +++ b/arch/arm/dts/tegra210.dtsi @@ -11,7 +11,7 @@ #address-cells = <2>; #size-cells = <2>; - pcie-controller@01003000 { + pcie@1003000 { compatible = "nvidia,tegra210-pcie"; device_type = "pci"; reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */ diff --git a/arch/arm/dts/tegra30-apalis.dts b/arch/arm/dts/tegra30-apalis.dts index 1a9ce2720ac..77502dfdb47 100644 --- a/arch/arm/dts/tegra30-apalis.dts +++ b/arch/arm/dts/tegra30-apalis.dts @@ -32,7 +32,7 @@ reg = <0x80000000 0x40000000>; }; - pcie-controller@00003000 { + pcie@3000 { status = "okay"; avdd-pexa-supply = <&vdd2_reg>; vdd-pexa-supply = <&vdd2_reg>; diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts index f5fbbe849e2..9bb097b0813 100644 --- a/arch/arm/dts/tegra30-beaver.dts +++ b/arch/arm/dts/tegra30-beaver.dts @@ -28,7 +28,7 @@ reg = <0x80000000 0x7ff00000>; }; - pcie-controller@00003000 { + pcie@3000 { status = "okay"; avdd-pexa-supply = <&ldo1_reg>; diff --git a/arch/arm/dts/tegra30-cardhu.dts b/arch/arm/dts/tegra30-cardhu.dts index 5b9798c5a87..7534861e40d 100644 --- a/arch/arm/dts/tegra30-cardhu.dts +++ b/arch/arm/dts/tegra30-cardhu.dts @@ -27,7 +27,7 @@ reg = <0x80000000 0x40000000>; }; - pcie-controller@00003000 { + pcie@3000 { status = "okay"; /* AVDD_PEXA and VDD_PEXA inputs are grounded on Cardhu. */ diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index 5030065cbdf..f198bc0edbe 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -10,7 +10,7 @@ compatible = "nvidia,tegra30"; interrupt-parent = <&lic>; - pcie-controller@00003000 { + pcie@3000 { compatible = "nvidia,tegra30-pcie"; device_type = "pci"; reg = <0x00003000 0x00000800 /* PADS registers */ -- cgit v1.2.3 From 879a3bc1c2f3e2aadd6f05e6427cf4d97a272f9a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Apr 2019 11:32:38 +0200 Subject: ARM: tegra: Mark built-in Ethernet as default on Jetson TX2 Add an "ethernet" alias that points to the default network interface, which is the built-in EQoS on Jetson TX2. Signed-off-by: Thierry Reding Signed-off-by: Tom Warren --- arch/arm/dts/tegra186-p2771-0000.dtsi | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/dts/tegra186-p2771-0000.dtsi b/arch/arm/dts/tegra186-p2771-0000.dtsi index a1319dc4936..7cda0b41f74 100644 --- a/arch/arm/dts/tegra186-p2771-0000.dtsi +++ b/arch/arm/dts/tegra186-p2771-0000.dtsi @@ -9,6 +9,7 @@ }; aliases { + ethernet = "/ethernet@2490000"; mmc0 = "/sdhci@3460000"; mmc1 = "/sdhci@3400000"; i2c0 = "/bpmp/i2c"; @@ -28,6 +29,7 @@ ethernet@2490000 { status = "okay"; phy-reset-gpios = <&gpio_main TEGRA_MAIN_GPIO(M, 4) GPIO_ACTIVE_LOW>; + local-mac-address = [ 00 00 00 00 00 00 ]; }; i2c@3160000 { -- cgit v1.2.3