* [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II @ 2018-06-30 3:48 Andrey Smirnov 2018-06-30 3:48 ` [PATCH 01/11] ARM: nxp-imx8mq-evk: Update DDR initialization code Andrey Smirnov ` (10 more replies) 0 siblings, 11 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Everyone: This is part II of i.MX8MQ EVK board support patches. This time this is bits and pieces that were necessary in order to allow booting vendor Linux kernel availible here (tag: rel_imx_4.9.51_8mq_ga): https://source.codeaurora.org/external/imx/linux-imx Sources for ATF were taken from here (tag: rel_imx_4.9.51_8mq_ga): https://source.codeaurora.org/external/imx/imx-atf This patchest is also availible at: https://github.com/ndreys/barebox/tree/imx8m-support-part-II-v1 Feedback is welcome! Thanks, Andrey Smirnov Andrey Smirnov (11): ARM: nxp-imx8mq-evk: Update DDR initialization code ARM: Add code to support SMCCC on AArch64 ARM: i.MX8MQ: Configure cntfrq only in EL3 ARM: i.MX8MQ: Add a macro to load BL31 ATF blob ARM: i.MX: xload-esdhc: Move image base to MX8MQ_ATF_BL33_BASE_ADDR ARM: i.MX: xload-esdhc: Allow patching first word of the image ARM: i.MX: fimware: Add pre-built BL31 ATF blob ARM: nxp-imx8mq-evk: Add code to load ATF BL31 blob ARM: i.MX8MQ: Query and display ATF fimware hash if availible ARM: nxp-imx8mq-evk: Add bootflow comments firmware: Fix copy-paste comment mistake arch/arm/Kconfig | 4 + arch/arm/boards/nxp-imx8mq-evk/ddr_init.c | 120 +++++----- arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c | 219 +++++------------- arch/arm/boards/nxp-imx8mq-evk/lowlevel.c | 45 +++- arch/arm/cpu/Makefile | 4 +- arch/arm/cpu/smccc-call_64.S | 52 +++++ arch/arm/include/asm/asm-offsets.h | 1 + arch/arm/lib/asm-offsets.c | 7 +- arch/arm/mach-imx/Kconfig | 2 + arch/arm/mach-imx/imx8mq.c | 29 ++- arch/arm/mach-imx/include/mach/atf.h | 63 +++++ arch/arm/mach-imx/xload-esdhc.c | 19 +- firmware/Kconfig | 3 + firmware/Makefile | 6 +- firmware/imx/imx8m-bl31.bin | Bin 0 -> 46744 bytes include/linux/arm-smccc.h | 135 +++++++++++ 16 files changed, 479 insertions(+), 230 deletions(-) create mode 100644 arch/arm/cpu/smccc-call_64.S create mode 100644 arch/arm/include/asm/asm-offsets.h create mode 100644 arch/arm/mach-imx/include/mach/atf.h create mode 100755 firmware/imx/imx8m-bl31.bin create mode 100644 include/linux/arm-smccc.h -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 01/11] ARM: nxp-imx8mq-evk: Update DDR initialization code 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-06-30 3:48 ` [PATCH 02/11] ARM: Add code to support SMCCC on AArch64 Andrey Smirnov ` (9 subsequent siblings) 10 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Previous version of DDR initialization code was generated by a beta version of MX8_DDR_tool. This updates the code to the output of MX8_DDR_tool v1.0, which seem to fix the vendor Linux kernel hang* that was happening with the previous version. * The kernel would hang as soon as it tried to utilize DDR's DVFS features and switch DDR frequency (disabling busfreq-imx8mq.c would fix the problem). Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- arch/arm/boards/nxp-imx8mq-evk/ddr_init.c | 120 +++++----- arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c | 219 +++++------------- 2 files changed, 125 insertions(+), 214 deletions(-) diff --git a/arch/arm/boards/nxp-imx8mq-evk/ddr_init.c b/arch/arm/boards/nxp-imx8mq-evk/ddr_init.c index 81691b2fa..44103b5e2 100644 --- a/arch/arm/boards/nxp-imx8mq-evk/ddr_init.c +++ b/arch/arm/boards/nxp-imx8mq-evk/ddr_init.c @@ -2,7 +2,8 @@ * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ - * Generated code from MX8_DDR_tool + * + * Generated code from MX8M_DDR_tool */ #include "ddr.h" @@ -21,7 +22,7 @@ void ddr_init(void) reg32_write(0x303a00f8,tmp); reg32_write(0x30391000,0x8f000000); reg32_write(0x30391004,0x8f000000); - reg32_write(0x30360068,0xbbe580); + reg32_write(0x30360068,0xece580); tmp=reg32_read(0x30360060); tmp &= ~0x80; reg32_write(0x30360060,tmp); @@ -41,18 +42,19 @@ void ddr_init(void) reg32_write(0x30391000,0x8f000006); reg32_write(0x3d400304,0x1); reg32_write(0x3d400030,0x1); - reg32_write(0x3d400000,0x83080020); + reg32_write(0x3d400000,0xa3080020); + reg32_write(0x3d400028,0x0); + reg32_write(0x3d400020,0x203); + reg32_write(0x3d400024,0x186a000); reg32_write(0x3d400064,0x6100e0); reg32_write(0x3d4000d0,0xc003061c); reg32_write(0x3d4000d4,0x9e0000); reg32_write(0x3d4000dc,0xd4002d); reg32_write(0x3d4000e0,0x310008); - reg32_write(0x3d4000e8,0x46004d); - reg32_write(0x3d4000ec,0x15004d); - reg32_write(0x3d4000f4,0x639); + reg32_write(0x3d4000e8,0x66004a); + reg32_write(0x3d4000ec,0x16004a); reg32_write(0x3d400100,0x1a201b22); reg32_write(0x3d400104,0x60633); - reg32_write(0x3d400108,0x70e1214); reg32_write(0x3d40010c,0xc0c000); reg32_write(0x3d400110,0xf04080f); reg32_write(0x3d400114,0x2040c0c); @@ -64,78 +66,77 @@ void ddr_init(void) reg32_write(0x3d400144,0xa00050); reg32_write(0x3d400180,0x3200018); reg32_write(0x3d400184,0x28061a8); + reg32_write(0x3d400188,0x0); reg32_write(0x3d400190,0x497820a); reg32_write(0x3d400194,0x80303); - reg32_write(0x3d4001b4,0x170a); - reg32_write(0x3d4001b0,0x11); reg32_write(0x3d4001a0,0xe0400018); reg32_write(0x3d4001a4,0xdf00e4); - reg32_write(0x3d4001a8,0x0); + reg32_write(0x3d4001a8,0x80000000); + reg32_write(0x3d4001b0,0x11); + reg32_write(0x3d4001b4,0x170a); reg32_write(0x3d4001c0,0x1); reg32_write(0x3d4001c4,0x1); + reg32_write(0x3d4000f4,0x639); + reg32_write(0x3d400108,0x70e1214); reg32_write(0x3d400200,0x15); reg32_write(0x3d40020c,0x0); reg32_write(0x3d400210,0x1f1f); reg32_write(0x3d400204,0x80808); reg32_write(0x3d400214,0x7070707); reg32_write(0x3d400218,0x48080707); + reg32_write(0x3d402020,0x1); + reg32_write(0x3d402024,0x518b00); + reg32_write(0x3d402050,0x20d040); + reg32_write(0x3d402064,0x14002f); + reg32_write(0x3d4020dc,0x940009); + reg32_write(0x3d4020e0,0x310000); + reg32_write(0x3d4020e8,0x66004a); + reg32_write(0x3d4020ec,0x16004a); + reg32_write(0x3d402100,0xb070508); + reg32_write(0x3d402104,0x3040b); + reg32_write(0x3d402108,0x305090c); + reg32_write(0x3d40210c,0x505000); + reg32_write(0x3d402110,0x4040204); + reg32_write(0x3d402114,0x2030303); + reg32_write(0x3d402118,0x1010004); + reg32_write(0x3d40211c,0x301); + reg32_write(0x3d402130,0x20300); + reg32_write(0x3d402134,0xa100002); + reg32_write(0x3d402138,0x31); + reg32_write(0x3d402144,0x220011); + reg32_write(0x3d402180,0xa70006); + reg32_write(0x3d402190,0x3858202); + reg32_write(0x3d402194,0x80303); + reg32_write(0x3d4021b4,0x502); reg32_write(0x3d400244,0x0); - reg32_write(0x3d400490,0x1); - reg32_write(0x3d400250,0x29001f01); + reg32_write(0x3d400250,0x29001505); reg32_write(0x3d400254,0x2c); - reg32_write(0x3d400264,0x900093e7); + reg32_write(0x3d40025c,0x5900575b); + reg32_write(0x3d400264,0x9); reg32_write(0x3d40026c,0x2005574); - reg32_write(0x3d400400,0x400); + reg32_write(0x3d400300,0x16); + reg32_write(0x3d400304,0x0); + reg32_write(0x3d40030c,0x0); + reg32_write(0x3d400320,0x1); + reg32_write(0x3d40036c,0x11); + reg32_write(0x3d400400,0x111); + reg32_write(0x3d400404,0x10f3); reg32_write(0x3d400408,0x72ff); - reg32_write(0x3d400494,0x10e00); - reg32_write(0x3d400498,0x620096); - reg32_write(0x3d40049c,0x10e00); - reg32_write(0x3d4004a0,0x12c); + reg32_write(0x3d400490,0x1); + reg32_write(0x3d400494,0x1110d00); + reg32_write(0x3d400498,0x620790); + reg32_write(0x3d40049c,0x100001); + reg32_write(0x3d4004a0,0x41f); reg32_write(0x30391000,0x8f000004); reg32_write(0x30391000,0x8f000000); - reg32_write(0x3d400304,0x0); reg32_write(0x3d400030,0xa8); + do{ + tmp=reg32_read(0x3d400004); + if(tmp&0x223) break; + }while(1); reg32_write(0x3d400320,0x0); reg32_write(0x3d000000,0x1); reg32_write(0x3d4001b0,0x10); - reg32_write(0x3d402100,0xa040305); - reg32_write(0x3d402104,0x30407); - reg32_write(0x3d402108,0x203060b); - reg32_write(0x3d40210c,0x505000); - reg32_write(0x3d402110,0x2040202); - reg32_write(0x3d402114,0x2030202); - reg32_write(0x3d402118,0x1010004); - reg32_write(0x3d40211c,0x301); - reg32_write(0x3d402138,0x1d); - reg32_write(0x3d402144,0x14000a); - reg32_write(0x3d403024,0x30d400); - reg32_write(0x3d402050,0x20d040); - reg32_write(0x3d402190,0x3818200); - reg32_write(0x3d4021b4,0x100); - reg32_write(0x3d402064,0xc001c); - reg32_write(0x3d4020dc,0x840000); - reg32_write(0x3d4020e8,0x46004d); - reg32_write(0x3d4020ec,0x15004d); - reg32_write(0x3d4020e0,0x310000); - reg32_write(0x3d403100,0x6010102); - reg32_write(0x3d403104,0x30404); - reg32_write(0x3d403108,0x203060b); - reg32_write(0x3d40310c,0x505000); - reg32_write(0x3d403110,0x2040202); - reg32_write(0x3d403114,0x2030202); - reg32_write(0x3d403118,0x1010004); - reg32_write(0x3d40311c,0x301); - reg32_write(0x3d403138,0x8); - reg32_write(0x3d403144,0x50003); - reg32_write(0x3d403024,0xc3500); - reg32_write(0x3d403050,0x20d040); - reg32_write(0x3d403190,0x3818200); - reg32_write(0x3d4031b4,0x100); - reg32_write(0x3d403064,0x30007); - reg32_write(0x3d4030dc,0x840000); - reg32_write(0x3d4030e8,0x46004d); - reg32_write(0x3d4030ec,0x15004d); - reg32_write(0x3d4030e0,0x310000); reg32_write(0x3c040280,0x0); reg32_write(0x3c040284,0x1); reg32_write(0x3c040288,0x2); @@ -218,6 +219,7 @@ void ddr_init(void) /* enable port 0 */ reg32_write(DDRC_PCTRL_0(0), 0x00000001); - tmp = reg32_read(DDRC_CRCPARSTAT(0)); - reg32_write(DDRC_RFSHCTL3(0), 0x00000000); + /* enable DDR auto-refresh mode */ + tmp = reg32_read(DDRC_RFSHCTL3(0)) & ~0x1; + reg32_write(DDRC_RFSHCTL3(0), tmp); } \ No newline at end of file diff --git a/arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c b/arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c index 156d7cf87..1b30ff725 100644 --- a/arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c +++ b/arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c @@ -2,6 +2,8 @@ * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ + * + * Generated code from MX8M_DDR_tool */ #include "ddr.h" @@ -32,14 +34,6 @@ void ddr_cfg_phy(void) { reg32_write(0x3c44857c,0x1ff); reg32_write(0x3c44c17c,0x1ff); reg32_write(0x3c44c57c,0x1ff); - reg32_write(0x3c84017c,0x1ff); - reg32_write(0x3c84057c,0x1ff); - reg32_write(0x3c84417c,0x1ff); - reg32_write(0x3c84457c,0x1ff); - reg32_write(0x3c84817c,0x1ff); - reg32_write(0x3c84857c,0x1ff); - reg32_write(0x3c84c17c,0x1ff); - reg32_write(0x3c84c57c,0x1ff); reg32_write(0x3c000154,0x1ff); reg32_write(0x3c004154,0x1ff); reg32_write(0x3c008154,0x1ff); @@ -52,22 +46,16 @@ void ddr_cfg_phy(void) { reg32_write(0x3c024154,0x1ff); reg32_write(0x3c080314,0x19); reg32_write(0x3c480314,0x7); - reg32_write(0x3c880314,0x7); reg32_write(0x3c0800b8,0x2); - reg32_write(0x3c4800b8,0x2); - reg32_write(0x3c8800b8,0x2); + reg32_write(0x3c4800b8,0x1); reg32_write(0x3c240810,0x0); reg32_write(0x3c640810,0x0); - reg32_write(0x3ca40810,0x0); reg32_write(0x3c080090,0xab); reg32_write(0x3c0800e8,0x0); reg32_write(0x3c480090,0xab); reg32_write(0x3c0800e8,0x0); - reg32_write(0x3c880090,0xab); - reg32_write(0x3c0800e8,0x0); - reg32_write(0x3c080158,0x7); + reg32_write(0x3c080158,0x3); reg32_write(0x3c480158,0xa); - reg32_write(0x3c880158,0xa); reg32_write(0x3c040134,0xe00); reg32_write(0x3c040534,0xe00); reg32_write(0x3c044134,0xe00); @@ -84,14 +72,6 @@ void ddr_cfg_phy(void) { reg32_write(0x3c448534,0xe00); reg32_write(0x3c44c134,0xe00); reg32_write(0x3c44c534,0xe00); - reg32_write(0x3c840134,0xe00); - reg32_write(0x3c840534,0xe00); - reg32_write(0x3c844134,0xe00); - reg32_write(0x3c844534,0xe00); - reg32_write(0x3c848134,0xe00); - reg32_write(0x3c848534,0xe00); - reg32_write(0x3c84c134,0xe00); - reg32_write(0x3c84c534,0xe00); reg32_write(0x3c040124,0xfbe); reg32_write(0x3c040524,0xfbe); reg32_write(0x3c044124,0xfbe); @@ -108,14 +88,6 @@ void ddr_cfg_phy(void) { reg32_write(0x3c448524,0xfbe); reg32_write(0x3c44c124,0xfbe); reg32_write(0x3c44c524,0xfbe); - reg32_write(0x3c840124,0xfbe); - reg32_write(0x3c840524,0xfbe); - reg32_write(0x3c844124,0xfbe); - reg32_write(0x3c844524,0xfbe); - reg32_write(0x3c848124,0xfbe); - reg32_write(0x3c848524,0xfbe); - reg32_write(0x3c84c124,0xfbe); - reg32_write(0x3c84c524,0xfbe); reg32_write(0x3c00010c,0x63); reg32_write(0x3c00410c,0x63); reg32_write(0x3c00810c,0x63); @@ -130,8 +102,7 @@ void ddr_cfg_phy(void) { reg32_write(0x3c0801d4,0x4); reg32_write(0x3c080140,0x0); reg32_write(0x3c080020,0x320); - reg32_write(0x3c480020,0x64); - reg32_write(0x3c880020,0x19); + reg32_write(0x3c480020,0xa7); reg32_write(0x3c080220,0x9); reg32_write(0x3c0802c8,0xdc); reg32_write(0x3c04010c,0x5a1); @@ -151,33 +122,21 @@ void ddr_cfg_phy(void) { reg32_write(0x3c44850c,0x5a1); reg32_write(0x3c44c10c,0x5a1); reg32_write(0x3c44c50c,0x5a1); - reg32_write(0x3c8802c8,0xdc); - reg32_write(0x3c84010c,0x5a1); - reg32_write(0x3c84050c,0x5a1); - reg32_write(0x3c84410c,0x5a1); - reg32_write(0x3c84450c,0x5a1); - reg32_write(0x3c84810c,0x5a1); - reg32_write(0x3c84850c,0x5a1); - reg32_write(0x3c84c10c,0x5a1); - reg32_write(0x3c84c50c,0x5a1); reg32_write(0x3c0803e8,0x1); reg32_write(0x3c4803e8,0x1); - reg32_write(0x3c8803e8,0x1); reg32_write(0x3c080064,0x1); reg32_write(0x3c480064,0x1); - reg32_write(0x3c880064,0x1); - reg32_write(0x3c0803c0,0x660); + reg32_write(0x3c0803c0,0x0); reg32_write(0x3c0803c4,0x0); reg32_write(0x3c0803c8,0x4444); reg32_write(0x3c0803cc,0x8888); - reg32_write(0x3c0803d0,0x5665); + reg32_write(0x3c0803d0,0x5555); reg32_write(0x3c0803d4,0x0); reg32_write(0x3c0803d8,0x0); reg32_write(0x3c0803dc,0xf000); reg32_write(0x3c080094,0x0); reg32_write(0x3c0800b4,0x0); reg32_write(0x3c4800b4,0x0); - reg32_write(0x3c8800b4,0x0); reg32_write(0x3c080180,0x2); //enable APB bus to access DDRPHY RAM @@ -195,31 +154,32 @@ void ddr_cfg_phy(void) { reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54008,0x131f); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54009,0xc8); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5400b,0x2); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5400d,0x100); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54012,0x310); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54019,0x2dd4); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401a,0x31); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401b,0x4d46); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401c,0x4d08); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401e,0x15); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401b,0x4a66); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401c,0x4a08); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401e,0x16); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401f,0x2dd4); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54020,0x31); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54021,0x4d46); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54022,0x4d08); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54024,0x15); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54021,0x4a66); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54022,0x4a08); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54024,0x16); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5402b,0x1000); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5402c,0x3); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54032,0xd400); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54033,0x312d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54034,0x4600); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54035,0x84d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54036,0x4d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54037,0x1500); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54034,0x6600); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54035,0x84a); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54036,0x4a); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54037,0x1600); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54038,0xd400); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54039,0x312d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403a,0x4600); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403b,0x84d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403c,0x4d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403d,0x1500); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403a,0x6600); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403b,0x84a); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403c,0x4a); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403d,0x1600); //disable APB bus to access DDRPHY RAM reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0000, 0x1); @@ -233,96 +193,57 @@ void ddr_cfg_phy(void) { reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1); //set the PHY input clock to the desired frequency for pstate 1 - reg32_write(0x3038a008,0x7070000); - reg32_write(0x3038a004,0x5000000); - reg32_write(0x3038a088,0x7070000); - reg32_write(0x3038a084,0x2010000); - reg32_write(0x303a00ec,0xffff); - tmp=reg32_read(0x303a00f8); - tmp |= 0x20; - reg32_write(0x303a00f8,tmp); - reg32_write(0x30389804,0x1000000); - - //enable APB bus to access DDRPHY RAM - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0000, 0x0); - - reg32_write(0x3c150008,0x101); - reg32_write(0x3c15000c,0x190); - reg32_write(0x3c150020,0x121f); - reg32_write(0x3c150064,0x84); - reg32_write(0x3c150068,0x31); - reg32_write(0x3c15006c,0x4d46); - reg32_write(0x3c150070,0x4d08); - reg32_write(0x3c150074,0x0); - reg32_write(0x3c150078,0x15); - reg32_write(0x3c15007c,0x84); - reg32_write(0x3c150080,0x31); - reg32_write(0x3c150084,0x4d46); - reg32_write(0x3c150088,0x4d08); - reg32_write(0x3c15008c,0x0); - reg32_write(0x3c150090,0x15); - reg32_write(0x3c1500c8,0x8400); - reg32_write(0x3c1500cc,0x3100); - reg32_write(0x3c1500d0,0x4600); - reg32_write(0x3c1500d4,0x84d); - reg32_write(0x3c1500d8,0x4d); - reg32_write(0x3c1500dc,0x1500); - reg32_write(0x3c1500e0,0x8400); - reg32_write(0x3c1500e4,0x3100); - reg32_write(0x3c1500e8,0x4600); - reg32_write(0x3c1500ec,0x84d); - reg32_write(0x3c1500f0,0x4d); - reg32_write(0x3c1500f4,0x1500); - reg32_write(0x3c1500f8,0x0); - - //disable APB bus to access DDRPHY RAM - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0000, 0x1); - //Reset MPU and run - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x9); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x0); - wait_ddrphy_training_complete(); - - //configure DDRPHY-FW DMEM structure @clock2... - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1); - - //set the PHY input clock to the desired frequency for pstate 2 - reg32_write(0x3038a008,0x7070000); - reg32_write(0x3038a004,0x2000000); reg32_write(0x3038a088,0x7070000); - reg32_write(0x3038a084,0x2010000); + reg32_write(0x3038a084,0x4030000); reg32_write(0x303a00ec,0xffff); tmp=reg32_read(0x303a00f8); tmp |= 0x20; reg32_write(0x303a00f8,tmp); - reg32_write(0x30389804,0x1000000); + reg32_write(0x30360068,0xf5a406); + tmp=reg32_read(0x30360060); + tmp &= ~0x80; + reg32_write(0x30360060,tmp); + tmp=reg32_read(0x30360060); + tmp |= 0x200; + reg32_write(0x30360060,tmp); + tmp=reg32_read(0x30360060); + tmp &= ~0x20; + reg32_write(0x30360060,tmp); + tmp=reg32_read(0x30360060); + tmp &= ~0x10; + reg32_write(0x30360060,tmp); + do{ + tmp=reg32_read(0x30360060); + if(tmp&0x80000000) break; + }while(1); + reg32_write(0x30389808,0x1000000); //enable APB bus to access DDRPHY RAM reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0000, 0x0); - reg32_write(0x3c150008,0x102); - reg32_write(0x3c15000c,0x64); + reg32_write(0x3c150008,0x1); + reg32_write(0x3c15000c,0x29c); reg32_write(0x3c150020,0x121f); - reg32_write(0x3c150064,0x84); + reg32_write(0x3c150064,0x994); reg32_write(0x3c150068,0x31); reg32_write(0x3c15006c,0x4d46); reg32_write(0x3c150070,0x4d08); reg32_write(0x3c150074,0x0); reg32_write(0x3c150078,0x15); - reg32_write(0x3c15007c,0x84); + reg32_write(0x3c15007c,0x994); reg32_write(0x3c150080,0x31); reg32_write(0x3c150084,0x4d46); reg32_write(0x3c150088,0x4d08); reg32_write(0x3c15008c,0x0); reg32_write(0x3c150090,0x15); - reg32_write(0x3c1500c8,0x8400); - reg32_write(0x3c1500cc,0x3100); + reg32_write(0x3c1500c8,0x9400); + reg32_write(0x3c1500cc,0x3109); reg32_write(0x3c1500d0,0x4600); reg32_write(0x3c1500d4,0x84d); reg32_write(0x3c1500d8,0x4d); reg32_write(0x3c1500dc,0x1500); - reg32_write(0x3c1500e0,0x8400); - reg32_write(0x3c1500e4,0x3100); + reg32_write(0x3c1500e0,0x9400); + reg32_write(0x3c1500e4,0x3109); reg32_write(0x3c1500e8,0x4600); reg32_write(0x3c1500ec,0x84d); reg32_write(0x3c1500f0,0x4d); @@ -344,7 +265,7 @@ void ddr_cfg_phy(void) { tmp=reg32_read(0x303a00f8); tmp |= 0x20; reg32_write(0x303a00f8,tmp); - reg32_write(0x30360068,0xbbe580); + reg32_write(0x30360068,0xece580); tmp=reg32_read(0x30360060); tmp &= ~0x80; reg32_write(0x30360060,tmp); @@ -380,28 +301,28 @@ void ddr_cfg_phy(void) { reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54012,0x310); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54019,0x2dd4); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401a,0x31); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401b,0x4d46); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401c,0x4d08); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401e,0x15); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401b,0x4a66); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401c,0x4a08); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401e,0x16); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5401f,0x2dd4); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54020,0x31); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54021,0x4d46); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54022,0x4d08); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54024,0x15); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54021,0x4a66); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54022,0x4a08); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54024,0x16); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5402b,0x1000); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5402c,0x3); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54032,0xd400); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54033,0x312d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54034,0x4600); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54035,0x84d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54036,0x4d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54037,0x1500); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54034,0x6600); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54035,0x84a); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54036,0x4a); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54037,0x1600); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54038,0xd400); reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54039,0x312d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403a,0x4600); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403b,0x84d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403c,0x4d); - reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403d,0x1500); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403a,0x6600); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403b,0x84a); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403c,0x4a); + reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x5403d,0x1600); //disable APB bus to access DDRPHY RAM reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0000, 0x1); @@ -912,10 +833,6 @@ void ddr_cfg_phy(void) { reg32_write(0x3c480030,0xc9); reg32_write(0x3c480034,0x7d1); reg32_write(0x3c480038,0x2c); - reg32_write(0x3c88002c,0x65); - reg32_write(0x3c880030,0xc9); - reg32_write(0x3c880034,0x7d1); - reg32_write(0x3c880038,0x2c); reg32_write(0x3c240030,0x0); reg32_write(0x3c240034,0x173); reg32_write(0x3c240038,0x60); @@ -928,8 +845,6 @@ void ddr_cfg_phy(void) { reg32_write(0x3c080044,0x3); reg32_write(0x3c480040,0x5a); reg32_write(0x3c480044,0x3); - reg32_write(0x3c880040,0x5a); - reg32_write(0x3c880044,0x3); reg32_write(0x3c100200,0xe0); reg32_write(0x3c100204,0x12); reg32_write(0x3c100208,0xe0); @@ -942,12 +857,6 @@ void ddr_cfg_phy(void) { reg32_write(0x3c50020c,0x12); reg32_write(0x3c500210,0xe0); reg32_write(0x3c500214,0x12); - reg32_write(0x3c900200,0xe0); - reg32_write(0x3c900204,0x12); - reg32_write(0x3c900208,0xe0); - reg32_write(0x3c90020c,0x12); - reg32_write(0x3c900210,0xe0); - reg32_write(0x3c900214,0x12); reg32_write(0x3c1003f4,0xf); reg32_write(0x3c040044,0x1); reg32_write(0x3c040048,0x1); -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 02/11] ARM: Add code to support SMCCC on AArch64 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov 2018-06-30 3:48 ` [PATCH 01/11] ARM: nxp-imx8mq-evk: Update DDR initialization code Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-07-02 6:26 ` Sascha Hauer 2018-06-30 3:48 ` [PATCH 03/11] ARM: i.MX8MQ: Configure cntfrq only in EL3 Andrey Smirnov ` (8 subsequent siblings) 10 siblings, 1 reply; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Port SMCCC code from Linux kernel. To accomodate that: - Introduce CONFIG_ARM_SMCCC, to allow enabling the code independent of CONFIG_ARM_SECURE_MONITOR - Bring <linux/arm-smccc.h> in - Add necessary constants to arch/arm/asm-offsets.c Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- arch/arm/Kconfig | 4 + arch/arm/cpu/Makefile | 4 +- arch/arm/cpu/smccc-call_64.S | 52 +++++++++++ arch/arm/include/asm/asm-offsets.h | 1 + arch/arm/lib/asm-offsets.c | 7 +- include/linux/arm-smccc.h | 135 +++++++++++++++++++++++++++++ 6 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 arch/arm/cpu/smccc-call_64.S create mode 100644 arch/arm/include/asm/asm-offsets.h create mode 100644 include/linux/arm-smccc.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3555b4ee5..6f8eec708 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -388,7 +388,11 @@ config ARM_SEMIHOSTING the data on the host computer connected to the target via debugging channel (JTAG, SWD). If unsure say N +config ARM_SMCCC + bool + config ARM_SECURE_MONITOR + select ARM_SMCCC bool config ARM_PSCI diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 5b4b832e8..874d723e2 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -21,8 +21,8 @@ obj-$(CONFIG_CPU_32v7) += no-mmu.o endif obj-$(CONFIG_ARM_PSCI) += psci.o -obj-$(CONFIG_ARM_SECURE_MONITOR) += smccc-call.o -AFLAGS_smccc-call.o :=-Wa,-march=armv7-a +obj-pbl-$(CONFIG_ARM_SMCCC) += smccc-call$(S64).o +AFLAGS_smccc-call$(S64).o :=-Wa,-march=armv$(if $(S64),8,7)-a obj-$(CONFIG_ARM_SECURE_MONITOR) += sm.o sm_as.o AFLAGS_sm_as.o :=-Wa,-march=armv7-a diff --git a/arch/arm/cpu/smccc-call_64.S b/arch/arm/cpu/smccc-call_64.S new file mode 100644 index 000000000..44888fb59 --- /dev/null +++ b/arch/arm/cpu/smccc-call_64.S @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, Linaro Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <linux/linkage.h> +#include <linux/arm-smccc.h> +#include <asm/asm-offsets.h> + + .macro SMCCC instr + .cfi_startproc + \instr #0 + ldr x4, [sp] + stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS] + stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS] + ldr x4, [sp, #8] + cbz x4, 1f /* no quirk structure */ + ldr x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS] + cmp x9, #ARM_SMCCC_QUIRK_QCOM_A6 + b.ne 1f + str x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS] +1: ret + .cfi_endproc + .endm + +/* + * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, + * unsigned long a3, unsigned long a4, unsigned long a5, + * unsigned long a6, unsigned long a7, struct arm_smccc_res *res, + * struct arm_smccc_quirk *quirk) + */ +ENTRY(__arm_smccc_smc) + SMCCC smc +ENDPROC(__arm_smccc_smc) + +/* + * void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, + * unsigned long a3, unsigned long a4, unsigned long a5, + * unsigned long a6, unsigned long a7, struct arm_smccc_res *res, + * struct arm_smccc_quirk *quirk) + */ +ENTRY(__arm_smccc_hvc) + SMCCC hvc +ENDPROC(__arm_smccc_hvc) \ No newline at end of file diff --git a/arch/arm/include/asm/asm-offsets.h b/arch/arm/include/asm/asm-offsets.h new file mode 100644 index 000000000..2f84e8399 --- /dev/null +++ b/arch/arm/include/asm/asm-offsets.h @@ -0,0 +1 @@ +#include <generated/asm-offsets.h> \ No newline at end of file diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c index 7bf6d129c..cdff6f782 100644 --- a/arch/arm/lib/asm-offsets.c +++ b/arch/arm/lib/asm-offsets.c @@ -9,8 +9,13 @@ */ #include <linux/kbuild.h> +#include <linux/arm-smccc.h> int main(void) { - return 0; + DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0)); + DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2)); + DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id)); + DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state)); + return 0; } diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h new file mode 100644 index 000000000..1b38b7b37 --- /dev/null +++ b/include/linux/arm-smccc.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015, Linaro Limited + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __LINUX_ARM_SMCCC_H +#define __LINUX_ARM_SMCCC_H + +/* + * This file provides common defines for ARM SMC Calling Convention as + * specified in + * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + */ + +/* This constant is shifted by 31, make sure it's of an unsigned type */ +#define ARM_SMCCC_STD_CALL 0UL +#define ARM_SMCCC_FAST_CALL 1UL +#define ARM_SMCCC_TYPE_SHIFT 31 + +#define ARM_SMCCC_SMC_32 0 +#define ARM_SMCCC_SMC_64 1 +#define ARM_SMCCC_CALL_CONV_SHIFT 30 + +#define ARM_SMCCC_OWNER_MASK 0x3F +#define ARM_SMCCC_OWNER_SHIFT 24 + +#define ARM_SMCCC_FUNC_MASK 0xFFFF + +#define ARM_SMCCC_IS_FAST_CALL(smc_val) \ + ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT)) +#define ARM_SMCCC_IS_64(smc_val) \ + ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT)) +#define ARM_SMCCC_FUNC_NUM(smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK) +#define ARM_SMCCC_OWNER_NUM(smc_val) \ + (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK) + +#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \ + (((type) << ARM_SMCCC_TYPE_SHIFT) | \ + ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \ + (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \ + ((func_num) & ARM_SMCCC_FUNC_MASK)) + +#define ARM_SMCCC_OWNER_ARCH 0 +#define ARM_SMCCC_OWNER_CPU 1 +#define ARM_SMCCC_OWNER_SIP 2 +#define ARM_SMCCC_OWNER_OEM 3 +#define ARM_SMCCC_OWNER_STANDARD 4 +#define ARM_SMCCC_OWNER_TRUSTED_APP 48 +#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49 +#define ARM_SMCCC_OWNER_TRUSTED_OS 50 +#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63 + +#define ARM_SMCCC_QUIRK_NONE 0 +#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */ + +#ifndef __ASSEMBLY__ + +#include <linux/linkage.h> +#include <linux/types.h> +/** + * struct arm_smccc_res - Result from SMC/HVC call + * @a0-a3 result values from registers 0 to 3 + */ +struct arm_smccc_res { + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; +}; + +/** + * struct arm_smccc_quirk - Contains quirk information + * @id: quirk identification + * @state: quirk specific information + * @a6: Qualcomm quirk entry for returning post-smc call contents of a6 + */ +struct arm_smccc_quirk { + int id; + union { + unsigned long a6; + } state; +}; + +/** + * __arm_smccc_smc() - make SMC calls + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required. + * + * This function is used to make SMC calls following SMC Calling Convention. + * The content of the supplied param are copied to registers 0 to 7 prior + * to the SMC instruction. The return values are updated with the content + * from register 0 to 3 on return from the SMC instruction. An optional + * quirk structure provides vendor specific behavior. + */ +asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, unsigned long a4, + unsigned long a5, unsigned long a6, unsigned long a7, + struct arm_smccc_res *res, struct arm_smccc_quirk *quirk); + +/** + * __arm_smccc_hvc() - make HVC calls + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required. + * + * This function is used to make HVC calls following SMC Calling + * Convention. The content of the supplied param are copied to registers 0 + * to 7 prior to the HVC instruction. The return values are updated with + * the content from register 0 to 3 on return from the HVC instruction. An + * optional quirk structure provides vendor specific behavior. + */ +asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, unsigned long a4, + unsigned long a5, unsigned long a6, unsigned long a7, + struct arm_smccc_res *res, struct arm_smccc_quirk *quirk); + +#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL) + +#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__) + +#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL) + +#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__) + +#endif /*__ASSEMBLY__*/ +#endif /*__LINUX_ARM_SMCCC_H*/ -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 02/11] ARM: Add code to support SMCCC on AArch64 2018-06-30 3:48 ` [PATCH 02/11] ARM: Add code to support SMCCC on AArch64 Andrey Smirnov @ 2018-07-02 6:26 ` Sascha Hauer 2018-07-03 17:44 ` Andrey Smirnov 0 siblings, 1 reply; 23+ messages in thread From: Sascha Hauer @ 2018-07-02 6:26 UTC (permalink / raw) To: Andrey Smirnov; +Cc: barebox On Fri, Jun 29, 2018 at 08:48:51PM -0700, Andrey Smirnov wrote: > Port SMCCC code from Linux kernel. To accomodate that: > > - Introduce CONFIG_ARM_SMCCC, to allow enabling the code > independent of CONFIG_ARM_SECURE_MONITOR > > - Bring <linux/arm-smccc.h> in > > - Add necessary constants to arch/arm/asm-offsets.c > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > --- > arch/arm/Kconfig | 4 + > arch/arm/cpu/Makefile | 4 +- > arch/arm/cpu/smccc-call_64.S | 52 +++++++++++ > arch/arm/include/asm/asm-offsets.h | 1 + > arch/arm/lib/asm-offsets.c | 7 +- > include/linux/arm-smccc.h | 135 +++++++++++++++++++++++++++++ > 6 files changed, 200 insertions(+), 3 deletions(-) > create mode 100644 arch/arm/cpu/smccc-call_64.S > create mode 100644 arch/arm/include/asm/asm-offsets.h > create mode 100644 include/linux/arm-smccc.h > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig > index 3555b4ee5..6f8eec708 100644 > --- a/arch/arm/Kconfig > +++ b/arch/arm/Kconfig > @@ -388,7 +388,11 @@ config ARM_SEMIHOSTING > the data on the host computer connected to the target via > debugging channel (JTAG, SWD). If unsure say N > > +config ARM_SMCCC > + bool > + > config ARM_SECURE_MONITOR > + select ARM_SMCCC Whitespaces instead of tab here. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 02/11] ARM: Add code to support SMCCC on AArch64 2018-07-02 6:26 ` Sascha Hauer @ 2018-07-03 17:44 ` Andrey Smirnov 0 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-07-03 17:44 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Sun, Jul 1, 2018 at 11:26 PM Sascha Hauer <s.hauer@pengutronix.de> wrote: > > On Fri, Jun 29, 2018 at 08:48:51PM -0700, Andrey Smirnov wrote: > > Port SMCCC code from Linux kernel. To accomodate that: > > > > - Introduce CONFIG_ARM_SMCCC, to allow enabling the code > > independent of CONFIG_ARM_SECURE_MONITOR > > > > - Bring <linux/arm-smccc.h> in > > > > - Add necessary constants to arch/arm/asm-offsets.c > > > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > > --- > > arch/arm/Kconfig | 4 + > > arch/arm/cpu/Makefile | 4 +- > > arch/arm/cpu/smccc-call_64.S | 52 +++++++++++ > > arch/arm/include/asm/asm-offsets.h | 1 + > > arch/arm/lib/asm-offsets.c | 7 +- > > include/linux/arm-smccc.h | 135 +++++++++++++++++++++++++++++ > > 6 files changed, 200 insertions(+), 3 deletions(-) > > create mode 100644 arch/arm/cpu/smccc-call_64.S > > create mode 100644 arch/arm/include/asm/asm-offsets.h > > create mode 100644 include/linux/arm-smccc.h > > > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig > > index 3555b4ee5..6f8eec708 100644 > > --- a/arch/arm/Kconfig > > +++ b/arch/arm/Kconfig > > @@ -388,7 +388,11 @@ config ARM_SEMIHOSTING > > the data on the host computer connected to the target via > > debugging channel (JTAG, SWD). If unsure say N > > > > +config ARM_SMCCC > > + bool > > + > > config ARM_SECURE_MONITOR > > + select ARM_SMCCC > > Whitespaces instead of tab here. > OK, will fix in v2. Thanks, Andrey Smirnov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 03/11] ARM: i.MX8MQ: Configure cntfrq only in EL3 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov 2018-06-30 3:48 ` [PATCH 01/11] ARM: nxp-imx8mq-evk: Update DDR initialization code Andrey Smirnov 2018-06-30 3:48 ` [PATCH 02/11] ARM: Add code to support SMCCC on AArch64 Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-06-30 3:48 ` [PATCH 04/11] ARM: i.MX8MQ: Add a macro to load BL31 ATF blob Andrey Smirnov ` (7 subsequent siblings) 10 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov We only can (and should only need to) configure cntfrq when running in EL3 and executing this code in any other exception level will result in exception. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- arch/arm/mach-imx/imx8mq.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-imx/imx8mq.c b/arch/arm/mach-imx/imx8mq.c index f3246e437..dbcf4fa59 100644 --- a/arch/arm/mach-imx/imx8mq.c +++ b/arch/arm/mach-imx/imx8mq.c @@ -62,12 +62,14 @@ static void imx8mq_silicon_revision(void) static int imx8mq_init_syscnt_frequency(void) { - void __iomem *syscnt = IOMEM(MX8MQ_SYSCNT_CTRL_BASE_ADDR); - /* - * Update with accurate clock frequency - */ - set_cntfrq(syscnt_get_cntfrq(syscnt)); - syscnt_enable(syscnt); + if (current_el() == 3) { + void __iomem *syscnt = IOMEM(MX8MQ_SYSCNT_CTRL_BASE_ADDR); + /* + * Update with accurate clock frequency + */ + set_cntfrq(syscnt_get_cntfrq(syscnt)); + syscnt_enable(syscnt); + } return 0; } -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 04/11] ARM: i.MX8MQ: Add a macro to load BL31 ATF blob 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov ` (2 preceding siblings ...) 2018-06-30 3:48 ` [PATCH 03/11] ARM: i.MX8MQ: Configure cntfrq only in EL3 Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-07-02 6:25 ` Sascha Hauer 2018-06-30 3:48 ` [PATCH 05/11] ARM: i.MX: xload-esdhc: Move image base to MX8MQ_ATF_BL33_BASE_ADDR Andrey Smirnov ` (6 subsequent siblings) 10 siblings, 1 reply; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Add a macro containing all of the code needed to load and transfer control to BL31 ATF blob on i.MX8M. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- arch/arm/mach-imx/include/mach/atf.h | 63 ++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 arch/arm/mach-imx/include/mach/atf.h diff --git a/arch/arm/mach-imx/include/mach/atf.h b/arch/arm/mach-imx/include/mach/atf.h new file mode 100644 index 000000000..0b5018459 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/atf.h @@ -0,0 +1,63 @@ +#ifndef __IMX_ATF_H__ +#define __IMX_ATF_H__ + +#include <asm/system.h> + +#define MX8MQ_ATF_BL31_SIZE_LIMIT SZ_64K +#define MX8MQ_ATF_BL31_BASE_ADDR 0x00910000 +#define MX8MQ_ATF_BL33_BASE_ADDR 0x40200000 + +/** + * imx8mq_atf_load_bl31 - Load ATF BL31 blob and transfer contol to it + * + * @name: Name of the BL31 blob + * + * This macro: + + * 1. Copies built-in BL31 blob to an address i.MX8M's BL31 + * expects to be placed + * + * 2. Sets up temporary stack pointer for EL2, which is execution + * level that BL31 will drop us off at after it completes its + * initialization routine + * + * 3. Transfers control to BL31 + * + * NOTE: This has to be a macro in order delay the expansion of + * get_builtin_firmware(), otherwise it'll incorrectly interpret + * "name" literally + * + * NOTE: This function will do nothing if executed at any other EL + * than EL3. This is done intentionally to support single entry point + * initialization (see i.MX8M EVK for an example) + * + * NOTE: This function expects NXP's implementation of ATF that can be + * found at: + * https://source.codeaurora.org/external/imx/imx-atf + * + * any other implementation may or may not work + * + */ +#define imx8mq_atf_load_bl31(name) \ + do { \ + void __noreturn (*bl31)(void) = \ + (void *)MX8MQ_ATF_BL31_BASE_ADDR; \ + size_t bl31_size; \ + const u8 *fw; \ + \ + if (current_el() != 3) \ + break; \ + \ + get_builtin_firmware(name, &fw, &bl31_size); \ + if (WARN_ON(bl31_size > MX8MQ_ATF_BL31_SIZE_LIMIT)) \ + break; \ + \ + memcpy(bl31, fw, bl31_size); \ + asm volatile("msr sp_el2, %0" : : \ + "r" (MX8MQ_ATF_BL33_BASE_ADDR - 16) : \ + "cc"); \ + \ + bl31(); \ + } while (0) + +#endif \ No newline at end of file -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 04/11] ARM: i.MX8MQ: Add a macro to load BL31 ATF blob 2018-06-30 3:48 ` [PATCH 04/11] ARM: i.MX8MQ: Add a macro to load BL31 ATF blob Andrey Smirnov @ 2018-07-02 6:25 ` Sascha Hauer 2018-07-03 17:58 ` Andrey Smirnov 0 siblings, 1 reply; 23+ messages in thread From: Sascha Hauer @ 2018-07-02 6:25 UTC (permalink / raw) To: Andrey Smirnov; +Cc: barebox On Fri, Jun 29, 2018 at 08:48:53PM -0700, Andrey Smirnov wrote: > Add a macro containing all of the code needed to load and transfer > control to BL31 ATF blob on i.MX8M. > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > --- > arch/arm/mach-imx/include/mach/atf.h | 63 ++++++++++++++++++++++++++++ > 1 file changed, 63 insertions(+) > create mode 100644 arch/arm/mach-imx/include/mach/atf.h > > diff --git a/arch/arm/mach-imx/include/mach/atf.h b/arch/arm/mach-imx/include/mach/atf.h > new file mode 100644 > index 000000000..0b5018459 > --- /dev/null > +++ b/arch/arm/mach-imx/include/mach/atf.h > @@ -0,0 +1,63 @@ > +#ifndef __IMX_ATF_H__ > +#define __IMX_ATF_H__ > + > +#include <asm/system.h> > + > +#define MX8MQ_ATF_BL31_SIZE_LIMIT SZ_64K > +#define MX8MQ_ATF_BL31_BASE_ADDR 0x00910000 > +#define MX8MQ_ATF_BL33_BASE_ADDR 0x40200000 > + > +/** > + * imx8mq_atf_load_bl31 - Load ATF BL31 blob and transfer contol to it > + * > + * @name: Name of the BL31 blob > + * > + * This macro: > + > + * 1. Copies built-in BL31 blob to an address i.MX8M's BL31 > + * expects to be placed > + * > + * 2. Sets up temporary stack pointer for EL2, which is execution > + * level that BL31 will drop us off at after it completes its > + * initialization routine > + * > + * 3. Transfers control to BL31 > + * > + * NOTE: This has to be a macro in order delay the expansion of > + * get_builtin_firmware(), otherwise it'll incorrectly interpret > + * "name" literally You show a good reason why we should add the firmware name strings to the image along with a function that iterates over them. How to add the firmware name strings is already provided in the Kernels firmware/Makefile. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 04/11] ARM: i.MX8MQ: Add a macro to load BL31 ATF blob 2018-07-02 6:25 ` Sascha Hauer @ 2018-07-03 17:58 ` Andrey Smirnov 2018-07-19 23:01 ` Andrey Smirnov 0 siblings, 1 reply; 23+ messages in thread From: Andrey Smirnov @ 2018-07-03 17:58 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Sun, Jul 1, 2018 at 11:25 PM Sascha Hauer <s.hauer@pengutronix.de> wrote: > > On Fri, Jun 29, 2018 at 08:48:53PM -0700, Andrey Smirnov wrote: > > Add a macro containing all of the code needed to load and transfer > > control to BL31 ATF blob on i.MX8M. > > > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > > --- > > arch/arm/mach-imx/include/mach/atf.h | 63 ++++++++++++++++++++++++++++ > > 1 file changed, 63 insertions(+) > > create mode 100644 arch/arm/mach-imx/include/mach/atf.h > > > > diff --git a/arch/arm/mach-imx/include/mach/atf.h b/arch/arm/mach-imx/include/mach/atf.h > > new file mode 100644 > > index 000000000..0b5018459 > > --- /dev/null > > +++ b/arch/arm/mach-imx/include/mach/atf.h > > @@ -0,0 +1,63 @@ > > +#ifndef __IMX_ATF_H__ > > +#define __IMX_ATF_H__ > > + > > +#include <asm/system.h> > > + > > +#define MX8MQ_ATF_BL31_SIZE_LIMIT SZ_64K > > +#define MX8MQ_ATF_BL31_BASE_ADDR 0x00910000 > > +#define MX8MQ_ATF_BL33_BASE_ADDR 0x40200000 > > + > > +/** > > + * imx8mq_atf_load_bl31 - Load ATF BL31 blob and transfer contol to it > > + * > > + * @name: Name of the BL31 blob > > + * > > + * This macro: > > + > > + * 1. Copies built-in BL31 blob to an address i.MX8M's BL31 > > + * expects to be placed > > + * > > + * 2. Sets up temporary stack pointer for EL2, which is execution > > + * level that BL31 will drop us off at after it completes its > > + * initialization routine > > + * > > + * 3. Transfers control to BL31 > > + * > > + * NOTE: This has to be a macro in order delay the expansion of > > + * get_builtin_firmware(), otherwise it'll incorrectly interpret > > + * "name" literally > > You show a good reason why we should add the firmware name strings > to the image along with a function that iterates over them. How > to add the firmware name strings is already provided in the Kernels > firmware/Makefile. > OK, makes sense. I'll work on adding that feature as a part of v2. Thanks, Andrey Smirnov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 04/11] ARM: i.MX8MQ: Add a macro to load BL31 ATF blob 2018-07-03 17:58 ` Andrey Smirnov @ 2018-07-19 23:01 ` Andrey Smirnov 0 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-07-19 23:01 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Tue, Jul 3, 2018 at 10:58 AM Andrey Smirnov <andrew.smirnov@gmail.com> wrote: > > On Sun, Jul 1, 2018 at 11:25 PM Sascha Hauer <s.hauer@pengutronix.de> wrote: > > > > On Fri, Jun 29, 2018 at 08:48:53PM -0700, Andrey Smirnov wrote: > > > Add a macro containing all of the code needed to load and transfer > > > control to BL31 ATF blob on i.MX8M. > > > > > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > > > --- > > > arch/arm/mach-imx/include/mach/atf.h | 63 ++++++++++++++++++++++++++++ > > > 1 file changed, 63 insertions(+) > > > create mode 100644 arch/arm/mach-imx/include/mach/atf.h > > > > > > diff --git a/arch/arm/mach-imx/include/mach/atf.h b/arch/arm/mach-imx/include/mach/atf.h > > > new file mode 100644 > > > index 000000000..0b5018459 > > > --- /dev/null > > > +++ b/arch/arm/mach-imx/include/mach/atf.h > > > @@ -0,0 +1,63 @@ > > > +#ifndef __IMX_ATF_H__ > > > +#define __IMX_ATF_H__ > > > + > > > +#include <asm/system.h> > > > + > > > +#define MX8MQ_ATF_BL31_SIZE_LIMIT SZ_64K > > > +#define MX8MQ_ATF_BL31_BASE_ADDR 0x00910000 > > > +#define MX8MQ_ATF_BL33_BASE_ADDR 0x40200000 > > > + > > > +/** > > > + * imx8mq_atf_load_bl31 - Load ATF BL31 blob and transfer contol to it > > > + * > > > + * @name: Name of the BL31 blob > > > + * > > > + * This macro: > > > + > > > + * 1. Copies built-in BL31 blob to an address i.MX8M's BL31 > > > + * expects to be placed > > > + * > > > + * 2. Sets up temporary stack pointer for EL2, which is execution > > > + * level that BL31 will drop us off at after it completes its > > > + * initialization routine > > > + * > > > + * 3. Transfers control to BL31 > > > + * > > > + * NOTE: This has to be a macro in order delay the expansion of > > > + * get_builtin_firmware(), otherwise it'll incorrectly interpret > > > + * "name" literally > > > > You show a good reason why we should add the firmware name strings > > to the image along with a function that iterates over them. How > > to add the firmware name strings is already provided in the Kernels > > firmware/Makefile. > > > > OK, makes sense. I'll work on adding that feature as a part of v2. > Hmm, I just realized two things: - Implementing that besides porting a bunch of code would require early relocation, which I really would like to avoid - We can convert imx8mq_atf_load_bl31() into a function if we change its signature to accept a blob pointer and blob size. And leave it up to the user as to how that blob is obtained. Given the first and simplicity of the second, I think I am going to go that way for v2. Thanks, Andrey Smirnov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 05/11] ARM: i.MX: xload-esdhc: Move image base to MX8MQ_ATF_BL33_BASE_ADDR 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov ` (3 preceding siblings ...) 2018-06-30 3:48 ` [PATCH 04/11] ARM: i.MX8MQ: Add a macro to load BL31 ATF blob Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-06-30 3:48 ` [PATCH 06/11] ARM: i.MX: xload-esdhc: Allow patching first word of the image Andrey Smirnov ` (5 subsequent siblings) 10 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov BL31 ATF implementation provided by NXP will jump to MX8MQ_ATF_BL33_BASE_ADDR after completing its initialization. Move image base used by imx8_esdhc_start_image() in order to support that. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- arch/arm/mach-imx/xload-esdhc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/xload-esdhc.c b/arch/arm/mach-imx/xload-esdhc.c index 08ba9b08d..98ebdfcf7 100644 --- a/arch/arm/mach-imx/xload-esdhc.c +++ b/arch/arm/mach-imx/xload-esdhc.c @@ -14,6 +14,7 @@ #include <common.h> #include <io.h> #include <mci.h> +#include <mach/atf.h> #include <mach/imx6-regs.h> #include <mach/imx8mq-regs.h> #include <mach/xload.h> @@ -323,5 +324,5 @@ int imx8_esdhc_start_image(int instance) esdhc.is_mx6 = 1; - return esdhc_start_image(&esdhc, MX8MQ_DDR_CSD1_BASE_ADDR, SZ_32K); + return esdhc_start_image(&esdhc, MX8MQ_ATF_BL33_BASE_ADDR, SZ_32K); } \ No newline at end of file -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 06/11] ARM: i.MX: xload-esdhc: Allow patching first word of the image 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov ` (4 preceding siblings ...) 2018-06-30 3:48 ` [PATCH 05/11] ARM: i.MX: xload-esdhc: Move image base to MX8MQ_ATF_BL33_BASE_ADDR Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-07-02 6:20 ` Sascha Hauer 2018-06-30 3:48 ` [PATCH 07/11] ARM: i.MX: fimware: Add pre-built BL31 ATF blob Andrey Smirnov ` (4 subsequent siblings) 10 siblings, 1 reply; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Depending on how SD card/eMMC was programmed first byte of the image ther may or may not have appropriate branch instruction. Extend esdhc_start_image() to allow passing a custom callback that would patch the first instruction in memory to correctly redirect the CPU to the resto of the code. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- arch/arm/mach-imx/xload-esdhc.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-imx/xload-esdhc.c b/arch/arm/mach-imx/xload-esdhc.c index 98ebdfcf7..c017a8b10 100644 --- a/arch/arm/mach-imx/xload-esdhc.c +++ b/arch/arm/mach-imx/xload-esdhc.c @@ -219,7 +219,8 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len) } static int -esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset) +esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset, + u32 (*opcode_b)(u32)) { void *buf = (void *)address; u32 *ivt = buf + offset + SZ_1K; @@ -254,6 +255,9 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset) bb = buf + ofs; + if (opcode_b) + *(u32 *)buf = opcode_b(ofs); + bb(); } @@ -292,7 +296,12 @@ int imx6_esdhc_start_image(int instance) esdhc.is_mx6 = 1; - return esdhc_start_image(&esdhc, 0x10000000, 0); + return esdhc_start_image(&esdhc, 0x10000000, 0, NULL); +} + +static u32 aarch64_opcode_b(u32 to) +{ + return 0x14000000 | (to / 4); } /** @@ -324,5 +333,8 @@ int imx8_esdhc_start_image(int instance) esdhc.is_mx6 = 1; - return esdhc_start_image(&esdhc, MX8MQ_ATF_BL33_BASE_ADDR, SZ_32K); + return esdhc_start_image(&esdhc, + MX8MQ_ATF_BL33_BASE_ADDR, + SZ_32K, + aarch64_opcode_b); } \ No newline at end of file -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 06/11] ARM: i.MX: xload-esdhc: Allow patching first word of the image 2018-06-30 3:48 ` [PATCH 06/11] ARM: i.MX: xload-esdhc: Allow patching first word of the image Andrey Smirnov @ 2018-07-02 6:20 ` Sascha Hauer 2018-07-03 18:12 ` Andrey Smirnov 0 siblings, 1 reply; 23+ messages in thread From: Sascha Hauer @ 2018-07-02 6:20 UTC (permalink / raw) To: Andrey Smirnov; +Cc: barebox On Fri, Jun 29, 2018 at 08:48:55PM -0700, Andrey Smirnov wrote: > Depending on how SD card/eMMC was programmed first byte of the image > ther may or may not have appropriate branch instruction. Extend > esdhc_start_image() to allow passing a custom callback that would > patch the first instruction in memory to correctly redirect the CPU to > the resto of the code. > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > --- > arch/arm/mach-imx/xload-esdhc.c | 18 +++++++++++++++--- > 1 file changed, 15 insertions(+), 3 deletions(-) > > diff --git a/arch/arm/mach-imx/xload-esdhc.c b/arch/arm/mach-imx/xload-esdhc.c > index 98ebdfcf7..c017a8b10 100644 > --- a/arch/arm/mach-imx/xload-esdhc.c > +++ b/arch/arm/mach-imx/xload-esdhc.c > @@ -219,7 +219,8 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len) > } > > static int > -esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset) > +esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset, > + u32 (*opcode_b)(u32)) > { > void *buf = (void *)address; > u32 *ivt = buf + offset + SZ_1K; > @@ -254,6 +255,9 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset) > > bb = buf + ofs; > > + if (opcode_b) > + *(u32 *)buf = opcode_b(ofs); > + If I understand correctly this is to make sure that the bl31 binary which jumps to MX8MQ_ATF_BL33_BASE_ADDR jumps over the imx header to the barebox image, right? Maybe we should memmove the barebox image to MX8MQ_ATF_BL33_BASE_ADDR instead of inserting handweaved assembly into the binary. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 06/11] ARM: i.MX: xload-esdhc: Allow patching first word of the image 2018-07-02 6:20 ` Sascha Hauer @ 2018-07-03 18:12 ` Andrey Smirnov 0 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-07-03 18:12 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Sun, Jul 1, 2018 at 11:20 PM Sascha Hauer <s.hauer@pengutronix.de> wrote: > > On Fri, Jun 29, 2018 at 08:48:55PM -0700, Andrey Smirnov wrote: > > Depending on how SD card/eMMC was programmed first byte of the image > > ther may or may not have appropriate branch instruction. Extend > > esdhc_start_image() to allow passing a custom callback that would > > patch the first instruction in memory to correctly redirect the CPU to > > the resto of the code. > > > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > > --- > > arch/arm/mach-imx/xload-esdhc.c | 18 +++++++++++++++--- > > 1 file changed, 15 insertions(+), 3 deletions(-) > > > > diff --git a/arch/arm/mach-imx/xload-esdhc.c b/arch/arm/mach-imx/xload-esdhc.c > > index 98ebdfcf7..c017a8b10 100644 > > --- a/arch/arm/mach-imx/xload-esdhc.c > > +++ b/arch/arm/mach-imx/xload-esdhc.c > > @@ -219,7 +219,8 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len) > > } > > > > static int > > -esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset) > > +esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset, > > + u32 (*opcode_b)(u32)) > > { > > void *buf = (void *)address; > > u32 *ivt = buf + offset + SZ_1K; > > @@ -254,6 +255,9 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset) > > > > bb = buf + ofs; > > > > + if (opcode_b) > > + *(u32 *)buf = opcode_b(ofs); > > + > > If I understand correctly this is to make sure that the bl31 binary > which jumps to MX8MQ_ATF_BL33_BASE_ADDR jumps over the imx header > to the barebox image, right? > That's right. > Maybe we should memmove the barebox image to MX8MQ_ATF_BL33_BASE_ADDR > instead of inserting handweaved assembly into the binary. > Yeah good point, I haven't thought about that. We definitely should be able to do this. But now that I think of it, it should be possible to make second esdhc_read_blocks() call such that the image is placed the way we want it without extra memmove(). I'll give both a try and will update in v2 according to the results. Thanks, Andrey Smirnov. _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 07/11] ARM: i.MX: fimware: Add pre-built BL31 ATF blob 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov ` (5 preceding siblings ...) 2018-06-30 3:48 ` [PATCH 06/11] ARM: i.MX: xload-esdhc: Allow patching first word of the image Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-07-02 5:23 ` Sascha Hauer 2018-06-30 3:48 ` [PATCH 08/11] ARM: nxp-imx8mq-evk: Add code to load ATF BL31 blob Andrey Smirnov ` (3 subsequent siblings) 10 siblings, 1 reply; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Running Linux on i.MX8M requires us to use and proerly set up a ARM Trusted Firmware blob. For the sake of convenience, add a pre-built blob to our firmware tree, so it can be used by individual boards. This blob was built using Buildroot: - commit: 6b02b8210acb18773f2c4b26cfc11d1f9bc4fb88 - defconig: freescale_imx8mqevk_defconfig The resulting file of interest is output/images/bl31.bin Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- firmware/Kconfig | 3 +++ firmware/Makefile | 2 ++ firmware/imx/imx8m-bl31.bin | Bin 0 -> 46744 bytes 3 files changed, 5 insertions(+) create mode 100755 firmware/imx/imx8m-bl31.bin diff --git a/firmware/Kconfig b/firmware/Kconfig index b6449644b..3c5f0c30e 100644 --- a/firmware/Kconfig +++ b/firmware/Kconfig @@ -7,4 +7,7 @@ config EXTRA_FIRMWARE_DIR config FIRMWARE_IMX_LPDDR4_PMU_TRAIN bool +config CONFIG_FIRMWARE_IMX8MQ_ATF + bool + endmenu diff --git a/firmware/Makefile b/firmware/Makefile index c82e81ae4..62124933d 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -9,6 +9,8 @@ firmware-$(CONFIG_FIRMWARE_IMX_LPDDR4_PMU_TRAIN) += \ imx/lpddr4_pmu_train_2d_dmem.bin \ imx/lpddr4_pmu_train_2d_imem.bin +firmware-$(CONFIG_FIRMWARE_IMX8MQ_ATF) += imx/imx8m-bl31.bin + # Create $(fwabs) from $(CONFIG_EXTRA_FIRMWARE_DIR) -- if it doesn't have a # leading /, it's relative to $(srctree). fwdir := $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE_DIR)) diff --git a/firmware/imx/imx8m-bl31.bin b/firmware/imx/imx8m-bl31.bin new file mode 100755 index 0000000000000000000000000000000000000000..b2310e4334c498686550a2ecab796ba905a13ebe GIT binary patch literal 46744 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 T1f8H0bnadH=+w{g^6$?d>FQ|r literal 0 HcmV?d00001 -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 07/11] ARM: i.MX: fimware: Add pre-built BL31 ATF blob 2018-06-30 3:48 ` [PATCH 07/11] ARM: i.MX: fimware: Add pre-built BL31 ATF blob Andrey Smirnov @ 2018-07-02 5:23 ` Sascha Hauer 2018-07-03 17:59 ` Andrey Smirnov 0 siblings, 1 reply; 23+ messages in thread From: Sascha Hauer @ 2018-07-02 5:23 UTC (permalink / raw) To: Andrey Smirnov; +Cc: barebox On Fri, Jun 29, 2018 at 08:48:56PM -0700, Andrey Smirnov wrote: > Running Linux on i.MX8M requires us to use and proerly set up a ARM > Trusted Firmware blob. For the sake of convenience, add a pre-built > blob to our firmware tree, so it can be used by individual boards. > > This blob was built using Buildroot: > > - commit: 6b02b8210acb18773f2c4b26cfc11d1f9bc4fb88 > - defconig: freescale_imx8mqevk_defconfig > > The resulting file of interest is output/images/bl31.bin > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > --- > firmware/Kconfig | 3 +++ > firmware/Makefile | 2 ++ > firmware/imx/imx8m-bl31.bin | Bin 0 -> 46744 bytes > 3 files changed, 5 insertions(+) > create mode 100755 firmware/imx/imx8m-bl31.bin > > diff --git a/firmware/Kconfig b/firmware/Kconfig > index b6449644b..3c5f0c30e 100644 > --- a/firmware/Kconfig > +++ b/firmware/Kconfig > @@ -7,4 +7,7 @@ config EXTRA_FIRMWARE_DIR > config FIRMWARE_IMX_LPDDR4_PMU_TRAIN > bool > > +config CONFIG_FIRMWARE_IMX8MQ_ATF > + bool This superfluous CONFIG_ is added here and removed later. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 07/11] ARM: i.MX: fimware: Add pre-built BL31 ATF blob 2018-07-02 5:23 ` Sascha Hauer @ 2018-07-03 17:59 ` Andrey Smirnov 0 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-07-03 17:59 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Sun, Jul 1, 2018 at 10:23 PM Sascha Hauer <s.hauer@pengutronix.de> wrote: > > On Fri, Jun 29, 2018 at 08:48:56PM -0700, Andrey Smirnov wrote: > > Running Linux on i.MX8M requires us to use and proerly set up a ARM > > Trusted Firmware blob. For the sake of convenience, add a pre-built > > blob to our firmware tree, so it can be used by individual boards. > > > > This blob was built using Buildroot: > > > > - commit: 6b02b8210acb18773f2c4b26cfc11d1f9bc4fb88 > > - defconig: freescale_imx8mqevk_defconfig > > > > The resulting file of interest is output/images/bl31.bin > > > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > > --- > > firmware/Kconfig | 3 +++ > > firmware/Makefile | 2 ++ > > firmware/imx/imx8m-bl31.bin | Bin 0 -> 46744 bytes > > 3 files changed, 5 insertions(+) > > create mode 100755 firmware/imx/imx8m-bl31.bin > > > > diff --git a/firmware/Kconfig b/firmware/Kconfig > > index b6449644b..3c5f0c30e 100644 > > --- a/firmware/Kconfig > > +++ b/firmware/Kconfig > > @@ -7,4 +7,7 @@ config EXTRA_FIRMWARE_DIR > > config FIRMWARE_IMX_LPDDR4_PMU_TRAIN > > bool > > > > +config CONFIG_FIRMWARE_IMX8MQ_ATF > > + bool > > This superfluous CONFIG_ is added here and removed later. > Ugh. Missed this. Will fix in v2. Thanks, Andrey Smirnov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 08/11] ARM: nxp-imx8mq-evk: Add code to load ATF BL31 blob 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov ` (6 preceding siblings ...) 2018-06-30 3:48 ` [PATCH 07/11] ARM: i.MX: fimware: Add pre-built BL31 ATF blob Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-06-30 3:48 ` [PATCH 09/11] ARM: i.MX8MQ: Query and display ATF fimware hash if availible Andrey Smirnov ` (2 subsequent siblings) 10 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- arch/arm/boards/nxp-imx8mq-evk/lowlevel.c | 3 +++ arch/arm/mach-imx/Kconfig | 2 ++ firmware/Kconfig | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c index 1ed918ee0..c2dc6460a 100644 --- a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c +++ b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c @@ -23,6 +23,7 @@ #include <asm/cache.h> #include <asm/sections.h> #include <asm/mmu.h> +#include <mach/atf.h> #include "ddr.h" @@ -75,6 +76,8 @@ ENTRY_FUNCTION(start_nxp_imx8mq_evk, r0, r1, r2) if (get_pc() < MX8MQ_DDR_CSD1_BASE_ADDR) nxp_imx8mq_evk_sram_setup(); + imx8mq_atf_load_bl31(imx_imx8m_bl31_bin); + barebox_arm_entry(MX8MQ_DDR_CSD1_BASE_ADDR, SZ_2G + SZ_1G, __dtb_imx8mq_evk_start); } diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index a743bbfda..0086a7803 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -449,6 +449,8 @@ config MACH_NXP_IMX8MQ_EVK bool "NXP i.MX8MQ EVK Board" select ARCH_IMX8MQ select FIRMWARE_IMX_LPDDR4_PMU_TRAIN + select FIRMWARE_IMX8MQ_ATF + select ARM_SMCCC endif diff --git a/firmware/Kconfig b/firmware/Kconfig index 3c5f0c30e..a6f79e8a9 100644 --- a/firmware/Kconfig +++ b/firmware/Kconfig @@ -7,7 +7,7 @@ config EXTRA_FIRMWARE_DIR config FIRMWARE_IMX_LPDDR4_PMU_TRAIN bool -config CONFIG_FIRMWARE_IMX8MQ_ATF +config FIRMWARE_IMX8MQ_ATF bool endmenu -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 09/11] ARM: i.MX8MQ: Query and display ATF fimware hash if availible 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov ` (7 preceding siblings ...) 2018-06-30 3:48 ` [PATCH 08/11] ARM: nxp-imx8mq-evk: Add code to load ATF BL31 blob Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-06-30 3:48 ` [PATCH 10/11] ARM: nxp-imx8mq-evk: Add bootflow comments Andrey Smirnov 2018-06-30 3:49 ` [PATCH 11/11] firmware: Fix copy-paste comment mistake Andrey Smirnov 10 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- arch/arm/mach-imx/imx8mq.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm/mach-imx/imx8mq.c b/arch/arm/mach-imx/imx8mq.c index dbcf4fa59..152f07bc1 100644 --- a/arch/arm/mach-imx/imx8mq.c +++ b/arch/arm/mach-imx/imx8mq.c @@ -20,11 +20,16 @@ #include <mach/revision.h> #include <mach/imx8mq-regs.h> +#include <linux/arm-smccc.h> + #define IMX8MQ_ROM_VERSION_A0 0x800 #define IMX8MQ_ROM_VERSION_B0 0x83C #define MX8MQ_ANATOP_DIGPROG 0x6c +#define FSL_SIP_BUILDINFO 0xC2000003 +#define FSL_SIP_BUILDINFO_GET_COMMITHASH 0x00 + static void imx8mq_silicon_revision(void) { void __iomem *anatop = IOMEM(MX8MQ_ANATOP_BASE_ADDR); @@ -81,7 +86,17 @@ core_initcall(imx8mq_init_syscnt_frequency); int imx8mq_init(void) { + struct arm_smccc_res res; + imx8mq_silicon_revision(); + if (IS_ENABLED(CONFIG_ARM_SMCCC) && + IS_ENABLED(CONFIG_FIRMWARE_IMX8MQ_ATF)) { + arm_smccc_smc(FSL_SIP_BUILDINFO, + FSL_SIP_BUILDINFO_GET_COMMITHASH, + 0, 0, 0, 0, 0, 0, &res); + pr_info("i.MX ARM Trusted Firmware: %s\n", (char *)&res.a0); + } + return 0; } -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 10/11] ARM: nxp-imx8mq-evk: Add bootflow comments 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov ` (8 preceding siblings ...) 2018-06-30 3:48 ` [PATCH 09/11] ARM: i.MX8MQ: Query and display ATF fimware hash if availible Andrey Smirnov @ 2018-06-30 3:48 ` Andrey Smirnov 2018-07-02 5:48 ` Sascha Hauer 2018-06-30 3:49 ` [PATCH 11/11] firmware: Fix copy-paste comment mistake Andrey Smirnov 10 siblings, 1 reply; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:48 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Add some notes on how the boot-flow goes while I still remember it. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- arch/arm/boards/nxp-imx8mq-evk/lowlevel.c | 42 +++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c index c2dc6460a..7dd778c21 100644 --- a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c +++ b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c @@ -66,6 +66,26 @@ static void nxp_imx8mq_evk_sram_setup(void) BUG_ON(ret); } +/* + * Power-on execution flow of start_nxp_imx8mq_evk() might not be + * obvious for a very frist read, so here's, hopefully helpful, + * summary: + * + * 1. MaskROM uploads PBL into OCRAM and that's where this function is + * executed for the first time + * + * 2. DDR is initialized and full i.MX image is loaded to the + * beginning of RAM + * + * 3. start_nxp_imx8mq_evk, now in RAM, is executed again + * + * 4. BL31 blob is uploaded to OCRAM and the control is transfer to it + * + * 5. BL31 exits EL3 into EL2 at address MX8MQ_ATF_BL33_BASE_ADDR, + * executing start_nxp_imx8mq_evk() the third time + * + * 6. Standard barebox boot flow continues + */ ENTRY_FUNCTION(start_nxp_imx8mq_evk, r0, r1, r2) { arm_cpu_lowlevel_init(); @@ -73,11 +93,29 @@ ENTRY_FUNCTION(start_nxp_imx8mq_evk, r0, r1, r2) if (IS_ENABLED(CONFIG_DEBUG_LL)) setup_uart(); - if (get_pc() < MX8MQ_DDR_CSD1_BASE_ADDR) + if (get_pc() < MX8MQ_DDR_CSD1_BASE_ADDR) { + /* + * We assume that we were just loaded by MaskROM into + * SRAM if we are not running from DDR. We also assume + * that means DDR needs to be initialized for the + * first time. + */ nxp_imx8mq_evk_sram_setup(); - + } + + /* + * Straight from the power-on we are at EL3, so the following + * code _will_ load and jump to ATF. + * + * However when this function is re-executed upon exit from + * ATF's initialization routine, it is EL2 and it is + * short-circuited to a no-op. + */ imx8mq_atf_load_bl31(imx_imx8m_bl31_bin); + /* + * Standard entry we hit once we initialized both DDR and ATF + */ barebox_arm_entry(MX8MQ_DDR_CSD1_BASE_ADDR, SZ_2G + SZ_1G, __dtb_imx8mq_evk_start); } -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 10/11] ARM: nxp-imx8mq-evk: Add bootflow comments 2018-06-30 3:48 ` [PATCH 10/11] ARM: nxp-imx8mq-evk: Add bootflow comments Andrey Smirnov @ 2018-07-02 5:48 ` Sascha Hauer 2018-07-03 18:00 ` Andrey Smirnov 0 siblings, 1 reply; 23+ messages in thread From: Sascha Hauer @ 2018-07-02 5:48 UTC (permalink / raw) To: Andrey Smirnov; +Cc: barebox On Fri, Jun 29, 2018 at 08:48:59PM -0700, Andrey Smirnov wrote: > Add some notes on how the boot-flow goes while I still remember it. > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > --- > arch/arm/boards/nxp-imx8mq-evk/lowlevel.c | 42 +++++++++++++++++++++-- > 1 file changed, 40 insertions(+), 2 deletions(-) > > diff --git a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c > index c2dc6460a..7dd778c21 100644 > --- a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c > +++ b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c > @@ -66,6 +66,26 @@ static void nxp_imx8mq_evk_sram_setup(void) > BUG_ON(ret); > } > > +/* > + * Power-on execution flow of start_nxp_imx8mq_evk() might not be > + * obvious for a very frist read, so here's, hopefully helpful, > + * summary: > + * > + * 1. MaskROM uploads PBL into OCRAM and that's where this function is > + * executed for the first time > + * > + * 2. DDR is initialized and full i.MX image is loaded to the > + * beginning of RAM > + * > + * 3. start_nxp_imx8mq_evk, now in RAM, is executed again > + * > + * 4. BL31 blob is uploaded to OCRAM and the control is transfer to it > + * > + * 5. BL31 exits EL3 into EL2 at address MX8MQ_ATF_BL33_BASE_ADDR, > + * executing start_nxp_imx8mq_evk() the third time > + * > + * 6. Standard barebox boot flow continues > + */ > ENTRY_FUNCTION(start_nxp_imx8mq_evk, r0, r1, r2) > { > arm_cpu_lowlevel_init(); > @@ -73,11 +93,29 @@ ENTRY_FUNCTION(start_nxp_imx8mq_evk, r0, r1, r2) > if (IS_ENABLED(CONFIG_DEBUG_LL)) > setup_uart(); > > - if (get_pc() < MX8MQ_DDR_CSD1_BASE_ADDR) > + if (get_pc() < MX8MQ_DDR_CSD1_BASE_ADDR) { > + /* > + * We assume that we were just loaded by MaskROM into > + * SRAM if we are not running from DDR. We also assume > + * that means DDR needs to be initialized for the > + * first time. > + */ > nxp_imx8mq_evk_sram_setup(); > - > + } > + > + /* > + * Straight from the power-on we are at EL3, so the following > + * code _will_ load and jump to ATF. > + * > + * However when this function is re-executed upon exit from > + * ATF's initialization routine, it is EL2 and it is > + * short-circuited to a no-op. > + */ > imx8mq_atf_load_bl31(imx_imx8m_bl31_bin); Maybe the flow would be more clear if we add a if (current_el() == 3) around the imx8mq_atf_load_bl31() Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 10/11] ARM: nxp-imx8mq-evk: Add bootflow comments 2018-07-02 5:48 ` Sascha Hauer @ 2018-07-03 18:00 ` Andrey Smirnov 0 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-07-03 18:00 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Sun, Jul 1, 2018 at 10:48 PM Sascha Hauer <s.hauer@pengutronix.de> wrote: > > On Fri, Jun 29, 2018 at 08:48:59PM -0700, Andrey Smirnov wrote: > > Add some notes on how the boot-flow goes while I still remember it. > > > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > > --- > > arch/arm/boards/nxp-imx8mq-evk/lowlevel.c | 42 +++++++++++++++++++++-- > > 1 file changed, 40 insertions(+), 2 deletions(-) > > > > diff --git a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c > > index c2dc6460a..7dd778c21 100644 > > --- a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c > > +++ b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c > > @@ -66,6 +66,26 @@ static void nxp_imx8mq_evk_sram_setup(void) > > BUG_ON(ret); > > } > > > > +/* > > + * Power-on execution flow of start_nxp_imx8mq_evk() might not be > > + * obvious for a very frist read, so here's, hopefully helpful, > > + * summary: > > + * > > + * 1. MaskROM uploads PBL into OCRAM and that's where this function is > > + * executed for the first time > > + * > > + * 2. DDR is initialized and full i.MX image is loaded to the > > + * beginning of RAM > > + * > > + * 3. start_nxp_imx8mq_evk, now in RAM, is executed again > > + * > > + * 4. BL31 blob is uploaded to OCRAM and the control is transfer to it > > + * > > + * 5. BL31 exits EL3 into EL2 at address MX8MQ_ATF_BL33_BASE_ADDR, > > + * executing start_nxp_imx8mq_evk() the third time > > + * > > + * 6. Standard barebox boot flow continues > > + */ > > ENTRY_FUNCTION(start_nxp_imx8mq_evk, r0, r1, r2) > > { > > arm_cpu_lowlevel_init(); > > @@ -73,11 +93,29 @@ ENTRY_FUNCTION(start_nxp_imx8mq_evk, r0, r1, r2) > > if (IS_ENABLED(CONFIG_DEBUG_LL)) > > setup_uart(); > > > > - if (get_pc() < MX8MQ_DDR_CSD1_BASE_ADDR) > > + if (get_pc() < MX8MQ_DDR_CSD1_BASE_ADDR) { > > + /* > > + * We assume that we were just loaded by MaskROM into > > + * SRAM if we are not running from DDR. We also assume > > + * that means DDR needs to be initialized for the > > + * first time. > > + */ > > nxp_imx8mq_evk_sram_setup(); > > - > > + } > > + > > + /* > > + * Straight from the power-on we are at EL3, so the following > > + * code _will_ load and jump to ATF. > > + * > > + * However when this function is re-executed upon exit from > > + * ATF's initialization routine, it is EL2 and it is > > + * short-circuited to a no-op. > > + */ > > imx8mq_atf_load_bl31(imx_imx8m_bl31_bin); > > Maybe the flow would be more clear if we add a if (current_el() == 3) > around the imx8mq_atf_load_bl31() > Yeah, I think so too. I'll make the change in v2. Thanks, Andrey Smirnov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 11/11] firmware: Fix copy-paste comment mistake 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov ` (9 preceding siblings ...) 2018-06-30 3:48 ` [PATCH 10/11] ARM: nxp-imx8mq-evk: Add bootflow comments Andrey Smirnov @ 2018-06-30 3:49 ` Andrey Smirnov 10 siblings, 0 replies; 23+ messages in thread From: Andrey Smirnov @ 2018-06-30 3:49 UTC (permalink / raw) To: barebox; +Cc: Andrey Smirnov Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- firmware/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/Makefile b/firmware/Makefile index 62124933d..7f4dc4932 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -57,6 +57,6 @@ endif targets := $(patsubst $(obj)/%,%, \ $(shell find $(obj) -name \*.gen.S 2>/dev/null)) -# just to build a built-in.o. Otherwise compilation fails when no devicetree is -# created. +# just to build a built-in.o. Otherwise compilation fails when no +# firmware is built. obj- += dummy.o -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2018-07-19 23:01 UTC | newest] Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-06-30 3:48 [PATCH 00/11] ARM: i.MX8MQ and EVK support, part II Andrey Smirnov 2018-06-30 3:48 ` [PATCH 01/11] ARM: nxp-imx8mq-evk: Update DDR initialization code Andrey Smirnov 2018-06-30 3:48 ` [PATCH 02/11] ARM: Add code to support SMCCC on AArch64 Andrey Smirnov 2018-07-02 6:26 ` Sascha Hauer 2018-07-03 17:44 ` Andrey Smirnov 2018-06-30 3:48 ` [PATCH 03/11] ARM: i.MX8MQ: Configure cntfrq only in EL3 Andrey Smirnov 2018-06-30 3:48 ` [PATCH 04/11] ARM: i.MX8MQ: Add a macro to load BL31 ATF blob Andrey Smirnov 2018-07-02 6:25 ` Sascha Hauer 2018-07-03 17:58 ` Andrey Smirnov 2018-07-19 23:01 ` Andrey Smirnov 2018-06-30 3:48 ` [PATCH 05/11] ARM: i.MX: xload-esdhc: Move image base to MX8MQ_ATF_BL33_BASE_ADDR Andrey Smirnov 2018-06-30 3:48 ` [PATCH 06/11] ARM: i.MX: xload-esdhc: Allow patching first word of the image Andrey Smirnov 2018-07-02 6:20 ` Sascha Hauer 2018-07-03 18:12 ` Andrey Smirnov 2018-06-30 3:48 ` [PATCH 07/11] ARM: i.MX: fimware: Add pre-built BL31 ATF blob Andrey Smirnov 2018-07-02 5:23 ` Sascha Hauer 2018-07-03 17:59 ` Andrey Smirnov 2018-06-30 3:48 ` [PATCH 08/11] ARM: nxp-imx8mq-evk: Add code to load ATF BL31 blob Andrey Smirnov 2018-06-30 3:48 ` [PATCH 09/11] ARM: i.MX8MQ: Query and display ATF fimware hash if availible Andrey Smirnov 2018-06-30 3:48 ` [PATCH 10/11] ARM: nxp-imx8mq-evk: Add bootflow comments Andrey Smirnov 2018-07-02 5:48 ` Sascha Hauer 2018-07-03 18:00 ` Andrey Smirnov 2018-06-30 3:49 ` [PATCH 11/11] firmware: Fix copy-paste comment mistake Andrey Smirnov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox