[U-Boot] [PATCH 0/7] Exynos4412 SPL support

Hi,
This patch series adds support for using U-Boot's SPL as the second stage bootloader ("BL2") on Exynos4412 SoCs.
- Patch #1 adds support for the EMMC/SD OM pin configuration, which is used by the boards I tested on. - Patch #2 configures the magic values used to indicate system suspend state (which are identical to exynos5). - Patch #3 renames the existing exynos4 clock/dmc initialisation code to reflect the fact that it only supports exynos4210. - Patches #4 and #5 add/fill in structs reflecting the PMU and TZASC register layouts on exynos4412, respectively. - Patch #6 adds the exynos4412 DMC and clock initialisation code and enables building the SPL on exynos4412 platforms. - Patch #7 enables building the "mkexynosspl" utility for exynos4 SoCs.
The majority of the logic in patch #6 comes from a vendor u-boot dump (2010.12!), however, small portions (mostly code used for 2GB RAM initialisation) were reverse engineered from the vendor bootloader found on a GT-N7100.
This patch series has been tested on a GT-I9300 (exynos4412, 1GB RAM) and a GT-N7100 (exynos4412 prime, 2GB RAM), with a few additional patchsets applied for board/HW support (which I intend to upstream in the future).
Cheers, Simon
Simon Shields (7): ARM: exynos: spl: add EMMC/SD boot mode support exynos4: configure power down magic values ARM: exynos: rename exynos4 setup files to exynos4210 ARM: exynos: fill in exynos4412_power struct ARM: exynos: add exynos4412 TZASC memory layout ARM: exynos: SPL support for exynos 4412 tools: build mkexynosspl for exynos4 as well
arch/arm/mach-exynos/Kconfig | 6 + arch/arm/mach-exynos/Makefile | 3 +- ...init_exynos4.c => clock_init_exynos4210.c} | 2 +- arch/arm/mach-exynos/clock_init_exynos4412.c | 122 +++++ ...c_init_exynos4.c => dmc_init_exynos4210.c} | 2 +- arch/arm/mach-exynos/dmc_init_exynos4412.c | 185 ++++++++ .../{exynos4_setup.h => exynos4210_setup.h} | 0 arch/arm/mach-exynos/exynos4412_setup.h | 425 ++++++++++++++++++ arch/arm/mach-exynos/include/mach/cpu.h | 2 +- arch/arm/mach-exynos/include/mach/dmc.h | 19 + arch/arm/mach-exynos/include/mach/power.h | 290 +++++++++++- arch/arm/mach-exynos/power.c | 12 + arch/arm/mach-exynos/spl_boot.c | 22 +- include/configs/exynos4-common.h | 5 + tools/Makefile | 1 + 15 files changed, 1084 insertions(+), 12 deletions(-) rename arch/arm/mach-exynos/{clock_init_exynos4.c => clock_init_exynos4210.c} (99%) create mode 100644 arch/arm/mach-exynos/clock_init_exynos4412.c rename arch/arm/mach-exynos/{dmc_init_exynos4.c => dmc_init_exynos4210.c} (99%) create mode 100644 arch/arm/mach-exynos/dmc_init_exynos4412.c rename arch/arm/mach-exynos/{exynos4_setup.h => exynos4210_setup.h} (100%) create mode 100644 arch/arm/mach-exynos/exynos4412_setup.h

Match the iROM behaviour: try and load u-boot from EMMC, and if that fails, fall back to using the SD card.
Signed-off-by: Simon Shields simon@lineageos.org --- arch/arm/mach-exynos/spl_boot.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-exynos/spl_boot.c b/arch/arm/mach-exynos/spl_boot.c index b4945bd8e2..6e84206fc5 100644 --- a/arch/arm/mach-exynos/spl_boot.c +++ b/arch/arm/mach-exynos/spl_boot.c @@ -186,6 +186,7 @@ void copy_uboot_to_ram(void)
u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL; u32 offset = 0, size = 0; + u32 ret; #ifdef CONFIG_SPI_BOOTING struct spl_machine_param *param = spl_get_machine_params(); #endif @@ -220,23 +221,30 @@ void copy_uboot_to_ram(void) exynos_spi_copy(param->uboot_size, CONFIG_SYS_TEXT_BASE); break; #endif - case BOOT_MODE_SD: - offset = BL2_START_OFFSET; - size = BL2_SIZE_BLOC_COUNT; - copy_bl2 = get_irom_func(MMC_INDEX); - break; #ifdef CONFIG_SUPPORT_EMMC_BOOT case BOOT_MODE_EMMC: + case BOOT_MODE_EMMC_SD: /* Set the FSYS1 clock divisor value for EMMC boot */ emmc_boot_clk_div_set();
copy_bl2_from_emmc = get_irom_func(EMMC44_INDEX); end_bootop_from_emmc = get_irom_func(EMMC44_END_INDEX);
- copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE); + ret = copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, + CONFIG_SYS_TEXT_BASE); end_bootop_from_emmc(); - break; + + if (bootmode == BOOT_MODE_EMMC || ret) + break; + /* Fall through if EMMC boot failed and SD boot is enabled */ +#else + case BOOT_MODE_EMMC_SD: #endif + case BOOT_MODE_SD: + offset = BL2_START_OFFSET; + size = BL2_SIZE_BLOC_COUNT; + copy_bl2 = get_irom_func(MMC_INDEX); + break; #ifdef CONFIG_USB_BOOTING case BOOT_MODE_USB: /*

These values are used to indicate the power-down state of the system. We need them to know how much initialisation we should do on bootup.
Signed-off-by: Simon Shields simon@lineageos.org --- include/configs/exynos4-common.h | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/include/configs/exynos4-common.h b/include/configs/exynos4-common.h index 005f65d4ed..d7997930e9 100644 --- a/include/configs/exynos4-common.h +++ b/include/configs/exynos4-common.h @@ -22,6 +22,11 @@ #define CONFIG_SYS_DFU_DATA_BUF_SIZE SZ_32M #define DFU_DEFAULT_POLL_TIMEOUT 300
+/* Power Down Modes */ +#define S5P_CHECK_SLEEP 0x00000BAD +#define S5P_CHECK_DIDLE 0xBAD00000 +#define S5P_CHECK_LPA 0xABAD0000 + /* USB Samsung's IDs */ #define CONFIG_G_DNL_THOR_VENDOR_NUM 0x04E8 #define CONFIG_G_DNL_THOR_PRODUCT_NUM 0x685D

The current set of exynos4 initialisation code is only compatible with exynos4210. Rename it to reflect this, and allow for the introduction of exynos4412 support in a later patch set.
Signed-off-by: Simon Shields simon@lineageos.org --- arch/arm/mach-exynos/Makefile | 2 +- .../{clock_init_exynos4.c => clock_init_exynos4210.c} | 2 +- .../mach-exynos/{dmc_init_exynos4.c => dmc_init_exynos4210.c} | 2 +- arch/arm/mach-exynos/{exynos4_setup.h => exynos4210_setup.h} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename arch/arm/mach-exynos/{clock_init_exynos4.c => clock_init_exynos4210.c} (99%) rename arch/arm/mach-exynos/{dmc_init_exynos4.c => dmc_init_exynos4210.c} (99%) rename arch/arm/mach-exynos/{exynos4_setup.h => exynos4210_setup.h} (100%)
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index e895c13157..ce88921868 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_EXYNOS5420) += sec_boot.o ifdef CONFIG_SPL_BUILD obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o -obj-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4.o clock_init_exynos4.o +obj-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4210.o clock_init_exynos4210.o obj-y += spl_boot.o tzpc.o obj-y += lowlevel_init.o endif diff --git a/arch/arm/mach-exynos/clock_init_exynos4.c b/arch/arm/mach-exynos/clock_init_exynos4210.c similarity index 99% rename from arch/arm/mach-exynos/clock_init_exynos4.c rename to arch/arm/mach-exynos/clock_init_exynos4210.c index 584e4bac09..77f866119e 100644 --- a/arch/arm/mach-exynos/clock_init_exynos4.c +++ b/arch/arm/mach-exynos/clock_init_exynos4210.c @@ -30,7 +30,7 @@ #include <asm/arch/clk.h> #include <asm/arch/clock.h> #include "common_setup.h" -#include "exynos4_setup.h" +#include "exynos4210_setup.h"
/* * system_clock_init: Initialize core clock and bus clock. diff --git a/arch/arm/mach-exynos/dmc_init_exynos4.c b/arch/arm/mach-exynos/dmc_init_exynos4210.c similarity index 99% rename from arch/arm/mach-exynos/dmc_init_exynos4.c rename to arch/arm/mach-exynos/dmc_init_exynos4210.c index ecddc72684..3343496271 100644 --- a/arch/arm/mach-exynos/dmc_init_exynos4.c +++ b/arch/arm/mach-exynos/dmc_init_exynos4210.c @@ -26,7 +26,7 @@ #include <config.h> #include <asm/arch/dmc.h> #include "common_setup.h" -#include "exynos4_setup.h" +#include "exynos4210_setup.h"
struct mem_timings mem = { .direct_cmd_msr = { diff --git a/arch/arm/mach-exynos/exynos4_setup.h b/arch/arm/mach-exynos/exynos4210_setup.h similarity index 100% rename from arch/arm/mach-exynos/exynos4_setup.h rename to arch/arm/mach-exynos/exynos4210_setup.h

add all registers of the exynos4412 PMU according to the datasheet
Signed-off-by: Simon Shields simon@lineageos.org --- arch/arm/mach-exynos/include/mach/power.h | 290 +++++++++++++++++++++- 1 file changed, 289 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-exynos/include/mach/power.h b/arch/arm/mach-exynos/include/mach/power.h index a3d8974dcb..8a84eab98b 100644 --- a/arch/arm/mach-exynos/include/mach/power.h +++ b/arch/arm/mach-exynos/include/mach/power.h @@ -210,10 +210,298 @@ struct exynos4_power { };
struct exynos4412_power { - unsigned char res1[0x0704]; + unsigned int om_stat; + unsigned int lpi_mask0; + unsigned int lpi_mask1; + unsigned int lpi_mask2; + unsigned int rtc_clko_sel; + unsigned int gnss_rtc_out_ctrl; + unsigned int lpi_denial_mask0; + unsigned int lpi_denial_mask1; + unsigned int lpi_denial_mask2; + unsigned int c2c_ctrl; + unsigned char res1[0xd8]; + unsigned int intr_sspread_enable; + unsigned int intr_sspread_use_standbywfi; + unsigned int intr_sspread_blocking_duration; + unsigned char res2[0xf4]; + unsigned int central_seq_configuration; + unsigned char res3[0x4]; + unsigned int central_seq_option; + unsigned char res4[0x34]; + unsigned int central_seq_configuration_coreblk; + unsigned char res5[0x1bc]; + unsigned int swreset; + unsigned int rst_stat; + unsigned int automatic_wdt_reset_disable; + unsigned int mask_wdt_reset_request; + unsigned char res6[0x1f0]; + unsigned int wakeup_stat; + unsigned int eint_wakeup_mask; + unsigned int wakeup_mask; + unsigned char res7[0x14]; + unsigned int wakeup_stat_coreblk; + unsigned char res8[0x4]; + unsigned int wakeup_mask_coreblk; + unsigned char res9[0xd4]; + unsigned int hdmi_phy_control; unsigned int usbhost_phy_control; unsigned int hsic1_phy_control; unsigned int hsic2_phy_control; + unsigned int mipi_phy0_control; + unsigned int mipi_phy1_control; + unsigned int adc_phy_control; + unsigned char res10[0x64]; + unsigned int body_bias_con0; + unsigned int body_bias_con1; + unsigned int body_bias_con2; + unsigned int body_bias_con3; + unsigned char res11[0x70]; + unsigned int inform0; + unsigned int inform1; + unsigned int inform2; + unsigned int inform3; + unsigned int inform4; + unsigned int inform5; + unsigned int inform6; + unsigned int inform7; + unsigned char res12[0xe0]; + unsigned char res13[0x80]; + unsigned int irom_data_reg0; + unsigned int irom_data_reg1; + unsigned int irom_data_reg2; + unsigned int irom_data_reg3; + unsigned char res14[0x70]; + unsigned int pmu_debug; + unsigned char res15[0x5fc]; + unsigned int arm_core0_sys_pwr_reg; + unsigned int dis_irq_arm_core0_local_sys_pwr_reg; + unsigned int dis_irq_arm_core0_central_sys_pwr_reg; + unsigned char res16[0x4]; + unsigned int arm_core1_pwr_reg; + unsigned int dis_irq_arm_core1_local_sys_pwr_reg; + unsigned int dis_irq_arm_core1_central_sys_pwr_reg; + unsigned char res17[0x34]; + unsigned int isp_arm_sys_pwr_reg; + unsigned int dis_irq_isp_arm_local_sys_pwr_reg; + unsigned int dis_irq_isp_arm_central_sys_pwr_reg; + unsigned char res18[0x24]; + unsigned int arm_common_sys_pwr_reg; + unsigned char res19[0x3c]; + unsigned int arm_l2_0_sys_pwr_reg; + unsigned int arm_l2_1_sys_pwr_reg; + unsigned char res20[0x38]; + unsigned int cmu_aclkstop_sys_pwr_reg; + unsigned int cmu_sclkstop_sys_pwr_reg; + unsigned char res21[0x4]; + unsigned int cmu_reset_sys_pwr_reg; + unsigned int cmu_aclkstop_coreblk_sys_pwr_reg; + unsigned int cmu_sclkstop_coreblk_sys_pwr_reg; + unsigned char res22[0x4]; + unsigned int cmu_reset_coreblk_sys_pwr_reg; + unsigned int apll_sysclk_sys_pwr_reg; + unsigned int mpll_sysclk_sys_pwr_reg; + unsigned int vpll_sysclk_sys_pwr_reg; + unsigned int epll_sysclk_sys_pwr_reg; + unsigned int mplluser_sysclk_sys_pwr_reg; + unsigned char res23[0x4]; + unsigned int cmu_clkstop_gps_alive_sys_pwr_reg; + unsigned int cmu_reset_gps_alive_sys_pwr_reg; + unsigned int cmu_clkstop_cam_sys_pwr_reg; + unsigned int cmu_clkstop_tv_sys_pwr_reg; + unsigned int cmu_clkstop_mfc_sys_pwr_reg; + unsigned int cmu_clkstop_g3d_sys_pwr_reg; + unsigned int cmu_clkstop_lcd0_sys_pwr_reg; + unsigned int cmu_clkstop_isp_sys_pwr_reg; + unsigned int cmu_clkstop_maudio_sys_pwr_reg; + unsigned int cmu_clkstop_gps_sys_pwr_reg; + unsigned int cmu_reset_cam_sys_pwr_reg; + unsigned int cmu_reset_tv_sys_pwr_reg; + unsigned int cmu_reset_mfc_sys_pwr_reg; + unsigned int cmu_reset_g3d_sys_pwr_reg; + unsigned int cmu_reset_lcd0_sys_pwr_reg; + unsigned int cmu_reset_isp_sys_pwr_reg; + unsigned int cmu_reset_maudio_sys_pwr_reg; + unsigned int cmu_reset_gps_sys_pwr_reg; + unsigned int top_bus_sys_pwr_reg; + unsigned int top_retention_sys_pwr_reg; + unsigned int top_pwr_sys_pwr_reg; + unsigned char res24[0x4]; + unsigned int top_bus_coreblk_pwr_reg; + unsigned int top_retention_coreblk_pwr_reg; + unsigned int top_pwr_coreblk_pwr_reg; + unsigned char res25[0x4]; + unsigned int logic_reset_sys_pwr_reg; + unsigned int oscclk_gate_sys_pwr_reg; + unsigned char res26[0x8]; + unsigned int logic_reset_coreblk_sys_pwr_reg; + unsigned int oscclk_gate_coreblk_sys_pwr_reg; + unsigned char res27[0x8]; + unsigned int onenandxl_mem_sys_pwr_reg; + unsigned int hsi_mem_sys_pwr_reg; + unsigned int g2d_acp_mem_sys_pwr_reg; + unsigned int usbotg_mem_sys_pwr_reg; + unsigned int sdmmc_mem_sys_pwr_reg; + unsigned int cssys_mem_sys_pwr_reg; + unsigned int secss_mem_sys_pwr_reg; + unsigned int rotator_mem_sys_pwr_reg; + unsigned char res28[0x20]; + unsigned int pad_retention_dram_sys_pwr_reg; + unsigned int pad_retention_maudio_sys_pwr_reg; + unsigned char res29[0x18]; + unsigned int pad_retention_gpio_sys_pwr_reg; + unsigned int pad_retention_uart_sys_pwr_reg; + unsigned int pad_retention_mmca_sys_pwr_reg; + unsigned int pad_retention_mmcb_sys_pwr_reg; + unsigned int pad_retention_ebia_sys_pwr_reg; + unsigned int pad_retention_ebib_sys_pwr_reg; + unsigned char resZ1[0x4]; + unsigned int pad_retention_gpio_coreblk_sys_pwr_reg; + unsigned int pad_isolation_sys_pwr_reg; + unsigned char res30[0xc]; + unsigned int pad_isolation_coreblk_sys_pwr_reg; + unsigned char res31[0xc]; + unsigned int pad_alv_sel_sys_pwr_reg; + unsigned char res32[0x1c]; + unsigned int xusbxti_sys_pwr_reg; + unsigned int xxti_sys_pwr_reg; + unsigned char res33[0x38]; + unsigned int ext_regulator_sys_pwr_reg; + unsigned char res34[0x3c]; + unsigned int gpio_mode_sys_pwr_reg; + unsigned char resZ2[0x1c]; + unsigned int gpio_mode_coreblk_sys_pwr_reg; + unsigned char res35[0x1c]; + unsigned int gpio_mode_maudio_sys_pwr_reg; + unsigned int top_asb_reset_sys_pwr_reg; + unsigned int top_asb_isolation_sys_pwr_reg; + unsigned char res36[0x34]; + unsigned int cam_sys_pwr_reg; + unsigned int tv_sys_pwr_reg; + unsigned int mfc_sys_pwr_reg; + unsigned int g3d_sys_pwr_reg; + unsigned int lcd0_sys_pwr_reg; + unsigned int isp_sys_pwr_reg; + unsigned int maudio_sys_pwr_reg; + unsigned int gps_sys_pwr_reg; + unsigned int gps_alive_sys_pwr_reg; + unsigned char res37[0xc]; + unsigned int dram_freq_down_sys_pwr_reg; + unsigned int ddrphy_dlloff_sys_pwr_reg; + unsigned int cmu_sysclk_isp_sys_pwr_reg; + unsigned int cmu_sysclk_gps_sys_pwr_reg; + unsigned int lpddr_phy_dll_lock_sys_pwr_reg; + unsigned char res38[0xc3c]; + unsigned int arm_core0_configuration; + unsigned int arm_core0_status; + unsigned int arm_core0_option; + unsigned char res39[0x74]; + unsigned int arm_core1_configuration; + unsigned int arm_core1_status; + unsigned int arm_core1_option; + unsigned char res40[0x1f4]; + unsigned int isp_arm_configuration; + unsigned int isp_arm_status; + unsigned int isp_arm_option; + unsigned char res41[0x17c]; + unsigned int arm_common_option; + unsigned char res42[0x1f4]; + unsigned int arm_l2_0_configuration; + unsigned int arm_l2_0_status; + unsigned int arm_l2_0_option; + unsigned char res43[0x14]; + unsigned int arm_l2_1_configuration; + unsigned int arm_l2_1_status; + unsigned int arm_l2_1_option; + unsigned char res44[0x37c]; + unsigned int dram_freq_down_option; + unsigned char res45[0x41c]; + unsigned int ddrphy_dlloff_option; + unsigned char res46[0x3c]; + unsigned int onenandxl_mem_option; + unsigned char res47[0x1c]; + unsigned int hsi_mem_option; + unsigned char res48[0x1c]; + unsigned int g2d_acp_mem_option; + unsigned char res49[0x1c]; + unsigned int usbotg_mem_option; + unsigned char res50[0x1c]; + unsigned int sdmmc_mem_option; + unsigned char res51[0x1c]; + unsigned int cssys_mem_option; + unsigned char res52[0x1c]; + unsigned int secss_mem_option; + unsigned char res53[0x7c]; + unsigned int rotator_mem_option; + unsigned char res54[0xdc]; + unsigned int pad_retention_maudio_option; + unsigned char res55[0xdc]; + unsigned int pad_retention_gpio_option; + unsigned char res56[0x1c]; + unsigned int pad_retention_uart_option; + unsigned char res57[0x1c]; + unsigned int pad_retention_mmca_option; + unsigned char res58[0x1c]; + unsigned int pad_retention_mmcb_option; + unsigned char res59[0x1c]; + unsigned int pad_retention_ebia_option; + unsigned char res60[0x1c]; + unsigned int pad_retention_ebib_option; + unsigned char res61[0x3c]; + unsigned int pad_retention_gpio_coreblk_option; + unsigned char res62[0x114]; + unsigned char res63[0xc]; + unsigned int ps_hold_control; + unsigned char res64[0xf0]; + unsigned int xusbxti_configuration; + unsigned int xusbxti_status; + unsigned char res65[0x14]; + unsigned int xusbxti_duration; + unsigned int xxti_configuration; + unsigned int xxti_status; + unsigned char res66[0x14]; + unsigned int xxti_duration; + unsigned char res67[0x1c0]; + unsigned char res68[0x1c]; + unsigned int ext_reguilator_duration; + unsigned char res69[0x5e0]; + unsigned int cam_configuration; + unsigned int cam_status; + unsigned int cam_option; + unsigned char res70[0x14]; + unsigned int tv_configuration; + unsigned int tv_status; + unsigned int tv_option; + unsigned char res71[0x14]; + unsigned int mfc_configuration; + unsigned int mfc_status; + unsigned int mfc_option; + unsigned char res72[0x14]; + unsigned int g3d_configuration; + unsigned int g3d_status; + unsigned int g3d_option; + unsigned char res73[0x14]; + unsigned int lcd0_configuration; + unsigned int lcd0_status; + unsigned int lcd0_option; + unsigned char res74[0x14]; + unsigned int isp_configuration; + unsigned int isp_status; + unsigned int isp_option; + unsigned char res75[0xc]; + unsigned int isp_duration0; + unsigned char res76[0x4]; + unsigned int maudio_configuration; + unsigned int maudio_status; + unsigned int maudio_option; + unsigned char res77[0x14]; + unsigned int gps_configuration; + unsigned int gps_status; + unsigned int gps_option; + unsigned char res78[0x14]; + unsigned int gps_alive_configuration; + unsigned int gps_alive_status; + unsigned int gps_alive_option; };
struct exynos5_power {

This patch adds the TZASC registers and base address as documented in the user manual. A follow-up patch will use this to mark all address spaces as non-secure.
Signed-off-by: Simon Shields simon@lineageos.org --- arch/arm/mach-exynos/include/mach/cpu.h | 2 +- arch/arm/mach-exynos/include/mach/dmc.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-exynos/include/mach/cpu.h b/arch/arm/mach-exynos/include/mach/cpu.h index aeb3755fe6..37d3118749 100644 --- a/arch/arm/mach-exynos/include/mach/cpu.h +++ b/arch/arm/mach-exynos/include/mach/cpu.h @@ -69,6 +69,7 @@ #define EXYNOS4X12_TZPC_BASE 0x10110000 #define EXYNOS4X12_DMC_CTRL_BASE 0x10600000 #define EXYNOS4X12_GPIO_PART4_BASE 0x106E0000 +#define EXYNOS4X12_DMC_TZASC_BASE 0x10700000 #define EXYNOS4X12_ACE_SFR_BASE 0x10830000 #define EXYNOS4X12_GPIO_PART2_BASE 0x11000000 #define EXYNOS4X12_GPIO_PART2_0 0x11000000 @@ -100,7 +101,6 @@ #define EXYNOS4X12_AUDIOSS_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_USB3PHY_BASE DEVICE_NOT_AVAILABLE -#define EXYNOS4X12_DMC_TZASC_BASE DEVICE_NOT_AVAILABLE
/* EXYNOS5 */ #define EXYNOS5_I2C_SPACING 0x10000 diff --git a/arch/arm/mach-exynos/include/mach/dmc.h b/arch/arm/mach-exynos/include/mach/dmc.h index 4990a1af39..49f00fc564 100644 --- a/arch/arm/mach-exynos/include/mach/dmc.h +++ b/arch/arm/mach-exynos/include/mach/dmc.h @@ -419,6 +419,25 @@ struct exynos5420_phy_control { unsigned int phy_con42; };
+struct exynos4412_tzasc { + unsigned char res1[0x100]; + unsigned int region_setup_low_0; + unsigned int region_setup_high_0; + unsigned int region_attributes_0; + unsigned int res2; + unsigned int region_setup_low_1; + unsigned int region_setup_high_1; + unsigned int region_setup_attributes_1; + unsigned int res3; + unsigned int region_setup_low_2; + unsigned int region_setup_high_2; + unsigned int region_setup_attributes_2; + unsigned int res4; + unsigned int region_setup_low_3; + unsigned int region_setup_high_3; + unsigned int region_attributes_3; +}; + struct exynos5420_tzasc { unsigned char res1[0xf00]; unsigned int membaseconfig0;

This patch adds support for using u-boot's SPL in place of a proprietary BL2 on exynos 4412 boards. This has been verified to work on both exynos4412 boards (i9300 and i9305), and exynos4412-prime boards (n7100 and n7105), with one or two gigabytes of RAM. Using u-boot as SPL requires an appropriate FWBL1 that does not verify the signature of BL2.
The majority of the configuration logic comes from the vendor u-boot drop, while some was reverse-engineered from a proprietary bootloader.
Note that this patch does not initialise the exynos4412-prime clocks as they're initialised by the proprietary bootloader - instead, they're initialised to the same state as normal exynos4412 clocks.
Signed-off-by: Simon Shields simon@lineageos.org --- arch/arm/mach-exynos/Kconfig | 6 + arch/arm/mach-exynos/Makefile | 1 + arch/arm/mach-exynos/clock_init_exynos4412.c | 122 ++++++ arch/arm/mach-exynos/dmc_init_exynos4412.c | 185 ++++++++ arch/arm/mach-exynos/exynos4412_setup.h | 425 +++++++++++++++++++ arch/arm/mach-exynos/power.c | 12 + 6 files changed, 751 insertions(+) create mode 100644 arch/arm/mach-exynos/clock_init_exynos4412.c create mode 100644 arch/arm/mach-exynos/dmc_init_exynos4412.c create mode 100644 arch/arm/mach-exynos/exynos4412_setup.h
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index ed04369cfa..17eaf99724 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -42,6 +42,9 @@ endchoice
if ARCH_EXYNOS4
+config EXYNOS4412 + bool + choice prompt "EXYNOS4 board select"
@@ -59,12 +62,15 @@ config TARGET_S5PC210_UNIVERSAL config TARGET_ORIGEN bool "Exynos4412 Origen board" select SUPPORT_SPL + select EXYNOS4412
config TARGET_TRATS2 bool "Exynos4412 Trat2 board" + select EXYNOS4412
config TARGET_ODROID bool "Exynos4412 Odroid board" + select EXYNOS4412
endchoice endif diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index ce88921868..5dcad9643b 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -13,6 +13,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o obj-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4210.o clock_init_exynos4210.o +obj-$(CONFIG_EXYNOS4412)+= dmc_init_exynos4412.o clock_init_exynos4412.o obj-y += spl_boot.o tzpc.o obj-y += lowlevel_init.o endif diff --git a/arch/arm/mach-exynos/clock_init_exynos4412.c b/arch/arm/mach-exynos/clock_init_exynos4412.c new file mode 100644 index 0000000000..140d8b3482 --- /dev/null +++ b/arch/arm/mach-exynos/clock_init_exynos4412.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Clock initialisation for Exynos4412 based boards + * + * Copyright (C) 2018 Simon Shields simon@lineageos.org + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/arch/clock.h> +#include <asm/arch/power.h> +#include "common_setup.h" +#include "exynos4412_setup.h" + +static void reset_isp(void) +{ + struct exynos4412_power *pwr = + (struct exynos4412_power *)samsung_get_base_power(); + + /* + * This is needed on some SoC revisions + * to ensure that the ISP power domain is usable. + * It doesn't hurt to have it on SoC revisions where it's + * not needed, so we just do it on all. + */ + writel(0, &pwr->cmu_reset_isp_sys_pwr_reg); + writel(0, &pwr->cmu_sysclk_isp_sys_pwr_reg); +} + +void system_clock_init(void) +{ + struct exynos4x12_clock *clk = + (struct exynos4x12_clock *)samsung_get_base_clock(); + + reset_isp(); + + /* Switch clocks away from PLLs while we configure them */ + writel(CLK_SRC_CPU_INIT, &clk->src_cpu); + writel(CLK_SRC_TOP0_INIT, &clk->src_top0); + writel(CLK_SRC_TOP1_INIT, &clk->src_top1); + writel(CLK_SRC_LEFTBUS_VAL, &clk->src_leftbus); + writel(CLK_SRC_RIGHTBUS_VAL, &clk->src_rightbus); + writel(CLK_SRC_PERIL0_VAL, &clk->src_peril0); + writel(CLK_SRC_LCD0_VAL, &clk->src_lcd); + + sdelay(0x10000); + + writel(CLK_DIV_DMC0_VAL, &clk->div_dmc0); + writel(CLK_DIV_DMC1_VAL, &clk->div_dmc1); + writel(CLK_DIV_TOP_VAL, &clk->div_top); + writel(CLK_DIV_LEFTBUS_VAL, &clk->div_leftbus); + writel(CLK_DIV_RIGHTBUS_VAL, &clk->div_rightbus); + writel(CLK_DIV_PERIL0_VAL, &clk->div_peril0); + + /* PLLs */ + writel(APLL_LOCK_VAL, &clk->apll_lock); + writel(MPLL_LOCK_VAL, &clk->mpll_lock); + writel(EPLL_LOCK_VAL, &clk->epll_lock); + writel(VPLL_LOCK_VAL, &clk->vpll_lock); + + writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0); + writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1); + + /* APLL: 800MHz */ + writel(APLL_CON1_VAL, &clk->apll_con1); + writel(APLL_CON0_VAL, &clk->apll_con0); + + /* + * The iROM sets MPLL at 400MHz. + * Skip increasing MPLL if it's not at 400MHz + */ + if (readl(&clk->mpll_con0) == 0xa0640301) { + /* MPLL: 800MHz */ + writel(MPLL_CON1_VAL, &clk->mpll_con1); + writel(MPLL_CON0_VAL, &clk->mpll_con0); + } + + /* EPLL: 96MHz */ + writel(EPLL_CON2_VAL, &clk->epll_con2); + writel(EPLL_CON1_VAL, &clk->epll_con1); + writel(EPLL_CON0_VAL, &clk->epll_con0); + + /* VPLL: 108MHz */ + writel(VPLL_CON2_VAL, &clk->vpll_con2); + writel(VPLL_CON1_VAL, &clk->vpll_con1); + writel(VPLL_CON0_VAL, &clk->vpll_con0); + + /* Stabilise */ + sdelay(0x40000); + + /* Now that PLLs are set up, use them. */ + writel(CLK_SRC_CPU_PLLS, &clk->src_cpu); + writel(CLK_SRC_DMC_PLLS, &clk->src_dmc); + writel(CLK_SRC_TOP0_PLLS, &clk->src_top0); + writel(CLK_SRC_TOP1_PLLS, &clk->src_top1); + + sdelay(0x10000); + + /* + * In the SDMMC booting case, we need to reconfigure MMC clock + * to make the iROM happy. + */ + u32 fsys2_div = readl(&clk->div_fsys2); + /* new MMC2 div is 16 */ + fsys2_div |= 0xf; + writel(fsys2_div, &clk->div_fsys2); +} + +void emmc_boot_clk_div_set(void) +{ + struct exynos4x12_clock *clk = (struct exynos4x12_clock *) + samsung_get_base_clock(); + u32 div_fsys3 = readl(&clk->div_fsys3); + + div_fsys3 &= ~(0xff0f); + div_fsys3 |= (1 << 8) | 0x7; + + writel(div_fsys3, &clk->div_fsys3); +} diff --git a/arch/arm/mach-exynos/dmc_init_exynos4412.c b/arch/arm/mach-exynos/dmc_init_exynos4412.c new file mode 100644 index 0000000000..a1efd09d02 --- /dev/null +++ b/arch/arm/mach-exynos/dmc_init_exynos4412.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Simon Shields simon@lineageos.org + */ +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/cpu.h> +#include <asm/arch/dmc.h> +#include <asm/arch/power.h> +#include <debug_uart.h> +#include "common_setup.h" +#include "exynos4412_setup.h" + +#define NR_TZASC_BANKS 4 + +/* Allow non-secure and secure access to all memory */ +#define RA0_VAL 0xf0000000 + +static void tzasc_init(void) +{ + unsigned int start = samsung_get_base_dmc_tzasc(); + unsigned int end = start + (DMC_OFFSET * (NR_TZASC_BANKS - 1)); + + for (; start <= end; start += DMC_OFFSET) { + struct exynos4412_tzasc *asc = (struct exynos4412_tzasc *)start; + + writel(RA0_VAL, &asc->region_attributes_0); + } +} + +static int board_num_mem_chips(void) +{ + u32 pkgid = readl(EXYNOS4_PRO_ID + 4); + + /* 2GB of RAM */ + if ((pkgid & 0x30) == 0x10) + return 2; + return 1; +} + +static void set_prime_stopctrl(void) +{ + struct exynos4x12_clock *clk = (struct exynos4x12_clock *) + samsung_get_base_clock(); + + /* PRE_WAIT_CNT, POST_WAIT_CNT = 0x1 */ + writel(0x101, &clk->atclk_stopctrl); +} + +static void do_directcmd(struct exynos4_dmc *dmc, u32 cmd, int chip, u32 delay) +{ + if (delay) + sdelay(delay); + if (chip) + cmd |= CMD_CHIP(1); + + writel(cmd, &dmc->directcmd); +} + +void mem_ctrl_init(int reset) +{ + struct exynos4_dmc *dmcs[2]; + int chips = board_num_mem_chips(); + int rev = exynos4412_get_rev(); + u32 memcontrol = DMC_MEMCONTROL; + u32 prechconfig = 0x64000000; + u32 zqcontrol = DMC_PHYZQCONTROL; + + dmcs[0] = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl(); + dmcs[1] = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl() + + DMC_OFFSET); + + if (rev == EXYNOS4412_REV_ZERO) + prechconfig |= 0xffff; + else if (rev == EXYNOS4412_REV_PRIME) + set_prime_stopctrl(); + + if (chips == 2) { + memcontrol |= MEM_2CHIPS; + zqcontrol |= CTRL_ZQ_MODE_DDS_2GB; + } else { + zqcontrol |= CTRL_ZQ_MODE_DDS_1GB; + } + + for (int idx = 0; idx < ARRAY_SIZE(dmcs); idx++) { + struct exynos4_dmc *dmc = dmcs[idx]; + + writel(zqcontrol, &dmc->phyzqcontrol); + writel(PHYCONTROL0_VAL_INIT, &dmc->phycontrol0); + writel(PHYCONTROL0_VAL_INIT | CTRL_DLL_ON, &dmc->phycontrol0); + + writel(PHYCONTROL1_VAL, &dmc->phycontrol1); + writel(PHYCONTROL0_VAL, &dmc->phycontrol0); + writel(PHYCONTROL1_VAL | FP_RESYNC, &dmc->phycontrol1); + writel(PHYCONTROL1_VAL, &dmc->phycontrol1); + writel(PHYCONTROL1_VAL | FP_RESYNC, &dmc->phycontrol1); + writel(PHYCONTROL1_VAL, &dmc->phycontrol1); + + writel(DMC_CONCONTROL_INIT, &dmc->concontrol); + writel(memcontrol, &dmc->memcontrol); + /* map first gigabyte of RAM at 0x40000000 - 0x7fffffff */ + writel(CHIP_BASE(0x40) | DMC_MEMCONFIG0, &dmc->memconfig0); + + /* map second gigabyte at 0x80000000 - 0xbfffffff */ + if (chips == 2) + writel(CHIP_BASE(0x80) | DMC_MEMCONFIG0, + &dmc->memconfig1); + writel(DMC_IVCONTROL, &dmc->ivcontrol); + writel(prechconfig, &dmc->prechconfig); + writel(PHYCONTROL0_VAL_STAGE2, &dmc->phycontrol0); + + writel(T_REFI(0x5d), &dmc->timingref); + + if (rev == EXYNOS4412_REV_PRIME) { + writel(T_RFC(0x3a) | T_RRD(0x5) | T_RP(0xa) | T_RCD(0x8) + | T_RC(0x1c) | T_RAS(0x13), + &dmc->timingrow); + writel(T_WTR(0x4) | T_WR(0x7) | T_RTP(0x4) | CL(0x0) + | WL(0x3) | RL(0x6), &dmc->timingdata); + writel(T_FAW(0x16) | T_XSR(0x3e) | T_XP(0x4) + | T_CKE(0x7) | T_MRD(0x5), + &dmc->timingpower); + } else { + u32 timingrow = T_RFC(0x34) | T_RP(0x9) | T_RCD(0x8) + | T_RC(0x1a) | T_RAS(0x11); + if (rev == EXYNOS4412_REV_ZERO) + timingrow |= T_RRD(0xa); + else + timingrow |= T_RRD(0x4); + writel(timingrow, &dmc->timingrow); + writel(T_WTR(0x3) | T_WR(0x6) | T_RTP(0x3) | CL(0x3) + | WL(0x3) | RL(0x6), &dmc->timingdata); + writel(T_FAW(0x14) | T_XSR(0x38) | T_XP(0x3) + | T_CKE(0x6) | T_MRD(0x5), + &dmc->timingpower); + } + + for (int i = 0; i < chips; i++) { + do_directcmd(dmc, CMD_TYPE(0x7), i, 0x100000); + do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x7) + | CMD_ADDR(0x1c00), i, 0x100000); + do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x1) + | CMD_ADDR(0xbfc), i, 0x100000); + do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x0) + | CMD_ADDR(0x608), i, 0x100000); + do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x0) + | CMD_ADDR(0x810), i, 0); + do_directcmd(dmc, CMD_TYPE(0x0) | CMD_BANK(0x0) + | CMD_ADDR(0xc08), i, 0); + } + } + + writel(PHYCONTROL0_VAL, &dmcs[0]->phycontrol0); + writel(MEM_TERM_EN | PHY_READ_EN | CTRL_SHGATE | CTRL_REF(8) + | CTRL_SHIFTC(4), &dmcs[0]->phycontrol1); + writel(PHYCONTROL0_VAL | CTRL_DLL_START, &dmcs[0]->phycontrol0); + sdelay(0x20000); + + writel(CTRL_REF(8) | FP_RESYNC | CTRL_SHIFTC(4), &dmcs[0]->phycontrol1); + writel(CTRL_REF(8) | CTRL_SHIFTC(4), &dmcs[0]->phycontrol1); + + sdelay(0x20000); + + writel(PHYCONTROL0_VAL, &dmcs[1]->phycontrol0); + writel(MEM_TERM_EN | PHY_READ_EN | CTRL_SHGATE | CTRL_REF(8) + | CTRL_SHIFTC(4), &dmcs[1]->phycontrol1); + writel(PHYCONTROL0_VAL | CTRL_DLL_START, &dmcs[1]->phycontrol0); + sdelay(0x20000); + + writel(CTRL_REF(8) | FP_RESYNC | CTRL_SHIFTC(4), &dmcs[1]->phycontrol1); + writel(CTRL_REF(8) | CTRL_SHIFTC(4), &dmcs[1]->phycontrol1); + + sdelay(0x20000); + + writel(DMC_CONCONTROL, &dmcs[0]->concontrol); + writel(DMC_CONCONTROL, &dmcs[1]->concontrol); + + memcontrol |= DSREF_EN | TP_EN | DPWRDN_EN | CLK_STOP_EN; + writel(memcontrol, &dmcs[0]->memcontrol); + writel(memcontrol, &dmcs[1]->memcontrol); + + tzasc_init(); +} diff --git a/arch/arm/mach-exynos/exynos4412_setup.h b/arch/arm/mach-exynos/exynos4412_setup.h new file mode 100644 index 0000000000..73ab75af7f --- /dev/null +++ b/arch/arm/mach-exynos/exynos4412_setup.h @@ -0,0 +1,425 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2011 Samsung Electronics Co. Ltd + * Copyright (C) 2018 Simon Shields simon@lineageos.org + */ + +#ifndef _EXYNOS4412_SETUP_H +#define _EXYNOS4412_SETUP_H + +#include <config.h> +#include <version.h> + +#include <asm/arch/cpu.h> + +#define EXYNOS4412_REV_ZERO 0x00 +#define EXYNOS4412_REV_MAIN 0x10 +#define EXYNOS4412_REV_PRIME 0x20 +#define EXYNOS4412_REV_MASK 0xf0 + +static inline int exynos4412_get_rev(void) +{ + return readl(EXYNOS4_PRO_ID) & EXYNOS4412_REV_MASK; +} + +/* CLK_DIV_CPU0 */ +#define CORE2_RATIO 0x0 +#define APLL_RATIO 0x1 +#define PCLK_DBG_RATIO 0x1 +#define ATB_RATIO 0x3 +#define PERIPH_RATIO 0x7 +#define COREM1_RATIO 0x5 +#define COREM0_RATIO 0x2 +#define CORE_RATIO 0x0 + +/* CLK_DIV_CPU1 */ +#define CORES_RATIO 0x3 +#define HPM_RATIO 0x0 +#define COPY_RATIO 0x3 + +#define CLK_DIV_CPU0_VAL ((CORE2_RATIO << 28) \ + | (APLL_RATIO << 24) \ + | (PCLK_DBG_RATIO << 20)\ + | (ATB_RATIO << 16) \ + | (PERIPH_RATIO << 12) \ + | (COREM1_RATIO << 8) \ + | (COREM0_RATIO << 4) \ + | (CORE_RATIO)) + +#define CLK_DIV_CPU1_VAL ((CORES_RATIO << 8) \ + | (HPM_RATIO << 4) \ + | (COPY_RATIO)) +/* APLL_CON1 / MPLL_CON1 */ +#define RESV1 (1 << 24) +#define RESV0 (1 << 23) +#define BYPASS (1 << 22) +#define DCC_ENB (1 << 21) /* Active low */ +#define AFC_ENB (1 << 20) /* Active low */ +#define FEED_EN (1 << 16) +#define LOCK_CON_OUT(x) ((x) << 14) +#define LOCK_CON_IN(x) ((x) << 12) +#define LOCK_CON_DLY(x) ((x) << 8) +#define AFC(x) ((x) << 0) + +/* MPLL */ +/* 800MHz = (0x64) * 24000000 / (3 * (1 << 0)) */ +#define MPLL_MDIV 0x64 +#define MPLL_PDIV 0x3 +#define MPLL_SDIV 0x0 +#define MPLL_CON1_VAL (RESV0 | LOCK_CON_IN(3) | LOCK_CON_DLY(8)) + +/* ARM_CLOCK/APLL */ +/* 800MHz = (0x64) * 24000000 / (3 * (1 << 0)) */ +#define APLL_MDIV 0x64 +#define APLL_PDIV 0x3 +#define APLL_SDIV 0x0 +#define APLL_CON1_VAL (RESV0 | LOCK_CON_IN(3) | LOCK_CON_DLY(8)) + +/* EPLL_CON1 / VPLL_CON1 */ +#define SELF_PF(x) ((x) << 29) +#define MRR(x) ((x) << 24) +#define MFR(x) ((x) << 16) +#define K(x) ((x) << 0) + +/* EPLL_CON2 / VPLL_CON2 */ +#define EXTAFC(x) ((x) << 8) +#define DCC_ENB_EV (1 << 7) /* Active low */ +#define AFC_ENB_EV (1 << 6) /* Active low */ +#define SSCG_EN (1 << 5) +#define BYPASS_EV (1 << 4) +#define FVCO_EN (1 << 3) +#define FSEL (1 << 2) +#define ICP_BOOST(x) ((x) << 0) + +/* EPLL */ +/* Fout = (M + K/65536) * Fin / (P * (1 << S)) */ +/* 96MHz = (0x40) * 24000000 / (2 * (1 << 3)) */ +#define EPLL_MDIV 0x40 +#define EPLL_PDIV 0x2 +#define EPLL_SDIV 0x3 + +#define EPLL_CON1_VAL SELF_PF(3) | MRR(6) | MFR(1) +#define EPLL_CON2_VAL DCC_ENB_EV + +/* VPLL */ +#define VPLL_MDIV 0x48 +#define VPLL_PDIV 0x2 +#define VPLL_SDIV 0x3 + +#define VPLL_CON1_VAL SELF_PF(3) | MRR(6) | MFR(1) +#define VPLL_CON2_VAL DCC_ENB_EV + +/* Set PLL */ +#define set_pll(mdiv, pdiv, sdiv) ((1 << 31) | (mdiv << 16) \ + | (pdiv << 8) | (sdiv)) + +#define APLL_CON0_VAL set_pll(APLL_MDIV, APLL_PDIV, APLL_SDIV) +#define MPLL_CON0_VAL set_pll(MPLL_MDIV, MPLL_PDIV, MPLL_SDIV) +#define EPLL_CON0_VAL set_pll(EPLL_MDIV, EPLL_PDIV, EPLL_SDIV) +#define VPLL_CON0_VAL set_pll(VPLL_MDIV, VPLL_PDIV, VPLL_SDIV) + +/* CLK_SRC_CPU */ +#define MUX_MPLL_USER_SEL_C(x) ((x) << 24) /* 0: FINPLL, 1: FOUTMPLL */ +#define MUX_HPM_SEL(x) ((x) << 20) /* 0: MOUTAPLL, 1: SCLKMPLL */ +#define MUX_CORE_SEL(x) ((x) << 16) /* 0: MOUTAPLL, 1: SCLKMPLL */ +#define MUX_APLL_SEL(x) ((x) << 0) /* 0: FINPLL, 1: MOUTAPLLFOUT */ + +/* All clocks from XusbXTI */ +#define CLK_SRC_CPU_INIT (MUX_MPLL_USER_SEL_C(0) | MUX_HPM_SEL(0) \ + | MUX_CORE_SEL(0) | MUX_APLL_SEL(0)) + +#define CLK_SRC_CPU_PLLS (MUX_MPLL_USER_SEL_C(1) | MUX_APLL_SEL(1)) + +/* CLK_SRC_DMC */ +#define MUX_PWI_SEL(x) ((x) << 16) /* 0: XXTI, 1: XusbXTI, ... */ +#define MUX_MPLL_SEL(x) ((x) << 12) /* 0: FINPLL, 1: MOUTMPLLFOUT */ +#define MUX_DPHY_SEL(x) ((x) << 8) /* 0: SCLKMPLL, 1: SCLKAPLL */ +#define MUX_DMC_BUS_SEL ((x) << 4) /* 0: SCLKMPLL, 1: SCLKAPLL */ + +#define CLK_SRC_DMC_PLLS (MUX_PWI_SEL(1) | MUX_MPLL_SEL(1)) + +/* CLK_DIV_DMC0 */ +#define CORE_TIMERS_RATIO 0x0 +#define COPY2_RATIO 0x0 +#define DMCP_RATIO 0x1 +#define DMCD_RATIO 0x1 +#define DMC_RATIO 0x7 +#define DPHY_RATIO 0x1 +#define ACP_PCLK_RATIO 0x1 +#define ACP_RATIO 0x7 + +#define CLK_DIV_DMC0_VAL ((CORE_TIMERS_RATIO << 28) \ + | (COPY2_RATIO << 24) \ + | (DMCP_RATIO << 20) \ + | (DMCD_RATIO << 16) \ + | (DMC_RATIO << 12) \ + | (DPHY_RATIO << 8) \ + | (ACP_PCLK_RATIO << 4) \ + | (ACP_RATIO)) + +/* CLK_DIV_DMC1 */ +#define DPM_RATIO 0x7 +#define DVSEM_RATIO 0x7 +#define C2C_ACLK_RATIO 0x1 +#define PWI_RATIO 0x7 +#define C2C_RATIO 0x7 +#define G2D_ACP_RATIO 0x3 + +#define CLK_DIV_DMC1_VAL ((DPM_RATIO << 24) \ + | (DVSEM_RATIO << 16) \ + | (C2C_ACLK_RATIO << 12) \ + | (PWI_RATIO << 8) \ + | (C2C_RATIO << 4) \ + | (G2D_ACP_RATIO)) + +/* CLK_SRC_TOP0 */ +#define MUX_ONENAND_SEL(x) ((x) << 28) /* 0 = DOUT133, 1 = DOUT166 */ +#define MUX_ACLK_133_SEL(x) ((x) << 24) /* 0 = SCLKMPLL, 1 = SCLKAPLL */ +#define MUX_ACLK_160_SEL(x) ((x) << 20) /* ditto */ +#define MUX_ACLK_100_SEL(x) ((x) << 16) /* ditto */ +#define MUX_ACLK_200_SEL(x) ((x) << 12) /* ditto */ +#define MUX_VPLL_SEL(x) ((x) << 8) /* 0: FINPLL, 1: FOUTVPLL */ +#define MUX_EPLL_SEL(x) ((x) << 4) /* 0: FINPLL, 1: FOUTEPLL */ +#define CLK_SRC_TOP0_INIT (MUX_ONENAND_SEL(0) \ + | MUX_ACLK_133_SEL(0) \ + | MUX_ACLK_160_SEL(0) \ + | MUX_ACLK_100_SEL(0) \ + | MUX_ACLK_200_SEL(0) \ + | MUX_VPLL_SEL(0) \ + | MUX_EPLL_SEL(0)) + +#define CLK_SRC_TOP0_PLLS (MUX_VPLL_SEL(1) | MUX_EPLL_SEL(1)) + +/* CLK_SRC_TOP1 */ +/* 0: FINPLL, 1: DIVOUT_ACLK_400_MCUISP */ +#define MUX_ACLK_400_MCUISP_SUB_SEL(x) ((x) << 24) +/* 0: FINPLL, 1: DIVOUT_ACLK_200 */ +#define MUX_ACLK_200_SUB_SEL(x) ((x) << 20) +/* 0: FINPLL, 1: DIVOUT_ACLK_266_GPS */ +#define MUX_ACLK_266_GPS_SUB_SEL(x) ((x) << 16) +/* 0: FINPLL, 1: SCLKMPLL */ +#define MUX_MPLL_USER_T_SEL(x) ((x) << 12) +/* 0: SCLKMPLL_USER_T, 1: SCLKAPLL */ +#define MUX_ACLK_400_MCUISP_SEL(x) ((x) << 8) +/* 0: SCLKMPLL_USER_T, 1: SCLKAPLL */ +#define MUX_ACLK_266_GPS_SEL(x) ((x) << 4) + +#define CLK_SRC_TOP1_INIT (MUX_ACLK_400_MCUISP_SUB_SEL(0) \ + | MUX_ACLK_200_SUB_SEL(0) \ + | MUX_ACLK_266_GPS_SUB_SEL(0) \ + | MUX_MPLL_USER_T_SEL(0)) + +#define CLK_SRC_TOP1_PLLS (MUX_ACLK_266_GPS_SUB_SEL(1) | MUX_MPLL_USER_T_SEL(1)) + +/* CLK_DIV_TOP */ +#define ACLK_400_MCUISP_RATIO 0x1 +#define ACLK_266_GPS_RATIO 0x2 +#define ONENAND_RATIO 0x1 +#define ACLK_133_RATIO 0x7 +#define ACLK_160_RATIO 0x4 +#define ACLK_100_RATIO 0xf +#define ACLK_200_RATIO 0x4 + +#define CLK_DIV_TOP_VAL ((ACLK_400_MCUISP_RATIO << 24) \ + | (ACLK_266_GPS_RATIO << 20) \ + | (ONENAND_RATIO << 16) \ + | (ACLK_133_RATIO << 12) \ + | (ACLK_160_RATIO << 8) \ + | (ACLK_100_RATIO << 4) \ + | (ACLK_200_RATIO)) + +/* CLK_SRC_LEFTBUS */ +#define MUX_MPLL_USER_SEL_L(x) ((x) << 4) /* 0: FINPLL, 1: FOUTMPLL */ +#define MUX_GDL_SEL(x) ((x) << 0) /* 0: SCLKMPLL, 1: SCLKAPLL */ +#define CLK_SRC_LEFTBUS_VAL (MUX_MPLL_USER_SEL_L(1) | MUX_GDL_SEL(0)) + +/* CLK_DIV_LEFTBUS */ +#define GPL_RATIO 0x1 +#define GDL_RATIO 0x7 +#define CLK_DIV_LEFTBUS_VAL ((GPL_RATIO << 4) \ + | (GDL_RATIO)) + +/* CLK_SRC_RIGHTBUS */ +#define MUX_MPLL_USER_SEL_R(x) ((x) << 4) /* 0: FINPLL, 1: FOUTMPLL */ +#define MUX_GDR_SEL(x) ((x) << 0) /* 0: SCLKMPLL, 1: SCLKAPLL */ +#define CLK_SRC_RIGHTBUS_VAL (MUX_MPLL_USER_SEL_R(1) | MUX_GDR_SEL(0)) + +/* CLK_DIV_RIGHTBUS */ +#define GPR_RATIO 0x1 +#define GDR_RATIO 0x7 +#define CLK_DIV_RIGHTBUS_VAL ((GPR_RATIO << 4) \ + | (GDR_RATIO)) + +/* APLL_LOCK */ +#define APLL_LOCK_VAL (0x3E8) +/* MPLL_LOCK */ +#define MPLL_LOCK_VAL (0x2F1) +/* EPLL_LOCK */ +#define EPLL_LOCK_VAL (0x2321) +/* VPLL_LOCK */ +#define VPLL_LOCK_VAL (0x2321) + +/* CLK_SRC_PERIL0 */ +#define UART4_SEL(x) ((x) << 16) /* 6: SCLK_MPLL_USER_T */ +#define UART3_SEL(x) ((x) << 12) +#define UART2_SEL(x) ((x) << 8) +#define UART1_SEL(x) ((x) << 4) +#define UART0_SEL(x) ((x) << 0) +#define CLK_SRC_PERIL0_VAL (UART4_SEL(6) \ + | UART3_SEL(6) \ + | UART2_SEL(6) \ + | UART1_SEL(6) \ + | UART0_SEL(6)) + +/* CLK_DIV_PERIL0 */ +#define UART5_RATIO 8 +#define UART4_RATIO 8 +#define UART3_RATIO 8 +#define UART2_RATIO 8 +#define UART1_RATIO 8 +#define UART0_RATIO 8 + +#define CLK_DIV_PERIL0_VAL ((UART5_RATIO << 20) \ + | (UART4_RATIO << 16) \ + | (UART3_RATIO << 12) \ + | (UART2_RATIO << 8) \ + | (UART1_RATIO << 4) \ + | (UART0_RATIO)) + +/* CLK_SRC_LCD0 */ +#define MIPI0_SEL(x) ((x) << 12) /* 1: XusbXTI */ +#define MDNIE_PWM0_SEL(x) ((x) << 8) /* 1: XusbXTI */ +#define MDNIE0_SEL(x) ((x) << 4) /* 6: SCLK_MPLL_USER_T */ +#define FIMD0_SEL(x) ((x) << 0) /* 6: SCLK_MPLL_USER_T */ + +#define CLK_SRC_LCD0_VAL (MIPI0_SEL(0x1) \ + | MDNIE_PWM0_SEL(0x1) \ + | MDNIE0_SEL(0x6) \ + | FIMD0_SEL(0x6)) + +/* DMC PHYCONTROL0 */ +#define CTRL_FORCE(x) ((x) << 24) +#define CTRL_INC(x) ((x) << 16) +#define CTRL_START_POINT(x) ((x) << 8) +#define DQS_DELAY(x) ((x) << 4) +#define CTRL_DFDQS (0x1 << 3) +#define CTRL_HALF (0x1 << 2) +#define CTRL_DLL_ON (0x1 << 1) +#define CTRL_DLL_START (0x1 << 0) + +/* CTRL_DLL_START will be ORd in when appropriate */ +#define PHYCONTROL0_VAL_INIT (CTRL_FORCE(0x71) | CTRL_INC(0x10) \ + | CTRL_START_POINT(0x10) \ + | CTRL_DFDQS) +#define PHYCONTROL0_VAL_STAGE2 (CTRL_FORCE(0x9c) | CTRL_INC(0x40) \ + | DQS_DELAY(0xf) | CTRL_DFDQS | CTRL_HALF \ + | CTRL_DLL_ON | CTRL_DLL_START) +#define PHYCONTROL0_VAL (CTRL_FORCE(0x7f) | CTRL_INC(0x10) \ + | CTRL_START_POINT(0x10) \ + | CTRL_DFDQS | CTRL_DLL_ON) + +/* DMC PHYCONTROL1 */ +#define MEM_TERM_EN (0x1 << 31) +#define PHY_READ_EN (0x1 << 30) +#define CTRL_SHGATE (0x1 << 29) +#define CTRL_REF(x) (x << 4) +#define FP_RESYNC (0x1 << 3) +#define CTRL_SHIFTC(x) (x << 0) + +#define PHYCONTROL1_VAL (CTRL_REF(8) | CTRL_SHIFTC(4)) + +/* DMC TIMINGREF */ +#define T_REFI(x) ((x) << 0) + +/* DMC TIMINGROW */ +#define T_RFC(x) ((x) << 24) +#define T_RRD(x) ((x) << 20) +#define T_RP(x) ((x) << 16) +#define T_RCD(x) ((x) << 12) +#define T_RC(x) ((x) << 6) +#define T_RAS(x) ((x) << 0) + +/* DMC TIMINGDATA */ +#define T_WTR(x) ((x) << 28) +#define T_WR(x) ((x) << 24) +#define T_RTP(x) ((x) << 20) +#define CL(x) ((x) << 16) +#define WL(x) ((x) << 8) +#define RL(x) ((x) << 0) + +/* DMC TIMINGPOWER */ +#define T_FAW(x) ((x) << 26) +#define T_XSR(x) ((x) << 16) +#define T_XP(x) ((x) << 8) +#define T_CKE(x) ((x) << 4) +#define T_MRD(x) ((x) << 0) + +/* DMC CONCONTROL */ +#define TIMEOUT_LEVEL0 (0xfff << 16) +#define RD_FETCH (0x3 << 12) +#define DRV_TYPE (0x3 << 6) +#define AREF_EN (0x1 << 5) +#define PDN_DQ_DISABLE (0x1 << 4) +#define IO_PDN_CON (0x1 << 3) +#define CLK_RATIO (0x1 << 1) + +#define DMC_CONCONTROL_INIT (TIMEOUT_LEVEL0 | RD_FETCH \ + | DRV_TYPE | IO_PDN_CON | CLK_RATIO) + +#define DMC_CONCONTROL (TIMEOUT_LEVEL0 | RD_FETCH \ + | DRV_TYPE | AREF_EN \ + | PDN_DQ_DISABLE | IO_PDN_CON \ + | CLK_RATIO) + +/* DMC MEMCONTROL */ +#define BURSTLEN (0x2 << 20) +#define MEM_WIDTH (0x2 << 12) +#define MEM_2CHIPS (0x1 << 16) +#define MEM_TYPE (0x5 << 8) /* LPDDR2-S4 */ +#define DSREF_EN (0x1 << 5) +#define TP_EN (0x1 << 4) +#define DPWRDN_EN (0x1 << 1) +#define CLK_STOP_EN (0x1 << 0) + +#define DMC_MEMCONTROL (BURSTLEN | MEM_WIDTH | MEM_TYPE) + +/* DMC MEMCONFIG0 */ +#define CHIP_BASE(x) ((x) << 24) +#define CHIP_MASK (0xc0 << 16) +#define CHIP_MAP (0x1 << 12) +#define CHIP_COL (0x3 << 8) +#define CHIP_ROW (0x2 << 4) +#define CHIP_BANK (0x3 << 0) + +#define DMC_MEMCONFIG0 (CHIP_MASK | CHIP_MAP | CHIP_COL | CHIP_ROW | CHIP_BANK) + +/* DMC DIRECTCMD */ +#define CMD_TYPE(x) ((x) << 24) +#define CMD_CHIP(x) ((x) << 20) +#define CMD_BANK(x) ((x) << 16) +#define CMD_ADDR(x) ((x) << 0) + +/* DMC_PHYZQCONTROL */ +#define CTRL_DCC (0xe38 << 20) +#define CTRL_ZQ_FORCE_IMPP (0x2 << 17) +#define CTRL_ZQ_FORCE_IMPN (0x5 << 14) +#define CTRL_ZQ_MODE_TERM (0x2 << 11) +#define CTRL_ZQ_MODE_DDS_1GB (0x4 << 8) +#define CTRL_ZQ_MODE_DDS_2GB (0x5 << 8) +#define CTRL_ZQ_DIV (0 << 4) +#define CTRL_ZQ_FORCE (0 << 2) +#define CTRL_ZQ_START (1 << 1) +#define CTRL_ZQ_MODE_NOTTERM (1 << 0) + +#define DMC_PHYZQCONTROL (CTRL_DCC | CTRL_ZQ_FORCE_IMPP \ + | CTRL_ZQ_FORCE_IMPN | CTRL_ZQ_MODE_TERM \ + | CTRL_ZQ_DIV | CTRL_ZQ_FORCE | CTRL_ZQ_START \ + | CTRL_ZQ_MODE_NOTTERM) + +/* DMC IVCONTROL */ +#define IV_ON (0x1 << 31) +#define IV_SIZE_128B (0x7 << 0) + +#define DMC_IVCONTROL (IV_ON | IV_SIZE_128B) +#endif + diff --git a/arch/arm/mach-exynos/power.c b/arch/arm/mach-exynos/power.c index 63c410acef..a513b89551 100644 --- a/arch/arm/mach-exynos/power.c +++ b/arch/arm/mach-exynos/power.c @@ -162,6 +162,16 @@ static void exynos5_set_ps_hold_ctrl(void) EXYNOS_PS_HOLD_CONTROL_DATA_HIGH); }
+static void exynos4412_set_ps_hold_ctrl(void) +{ + struct exynos4412_power *power = + (struct exynos4412_power *)samsung_get_base_power(); + + /* Set PS-Hold high */ + setbits_le32(&power->ps_hold_control, + EXYNOS_PS_HOLD_CONTROL_DATA_HIGH); +} + /* * Set ps_hold data driving value high * This enables the machine to stay powered on @@ -172,6 +182,8 @@ void set_ps_hold_ctrl(void) { if (cpu_is_exynos5()) exynos5_set_ps_hold_ctrl(); + else if (proid_is_exynos4412()) + exynos4412_set_ps_hold_ctrl(); }

Exynos4 uses the same SPL format as exynos5420/5250, so reuse mkexynosspl.
Signed-off-by: Simon Shields simon@lineageos.org --- tools/Makefile | 1 + 1 file changed, 1 insertion(+)
diff --git a/tools/Makefile b/tools/Makefile index 0c3341e695..63db215f9f 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -166,6 +166,7 @@ HOSTLOADLIBES_fit_check_sign := $(HOSTLOADLIBES_mkimage)
hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl +hostprogs-$(CONFIG_EXYNOS4) += mkexynosspl HOSTCFLAGS_mkexynosspl.o := -pedantic
ifdtool-objs := $(LIBFDT_OBJS) ifdtool.o

Hi Simon,
On Wed, 12 Sep 2018 at 17:25, Simon Shields simon@lineageos.org wrote:
Hi,
This patch series adds support for using U-Boot's SPL as the second stage bootloader ("BL2") on Exynos4412 SoCs.
- Patch #1 adds support for the EMMC/SD OM pin configuration, which is used by the boards I tested on.
- Patch #2 configures the magic values used to indicate system suspend state (which are identical to exynos5).
- Patch #3 renames the existing exynos4 clock/dmc initialisation code to reflect the fact that it only supports exynos4210.
- Patches #4 and #5 add/fill in structs reflecting the PMU and TZASC register layouts on exynos4412, respectively.
- Patch #6 adds the exynos4412 DMC and clock initialisation code and enables building the SPL on exynos4412 platforms.
- Patch #7 enables building the "mkexynosspl" utility for exynos4 SoCs.
The majority of the logic in patch #6 comes from a vendor u-boot dump (2010.12!), however, small portions (mostly code used for 2GB RAM initialisation) were reverse engineered from the vendor bootloader found on a GT-N7100.
This patch series has been tested on a GT-I9300 (exynos4412, 1GB RAM) and a GT-N7100 (exynos4412 prime, 2GB RAM), with a few additional patchsets applied for board/HW support (which I intend to upstream in the future).
Cheers, Simon
Could you elaborate more on how to generate stage bootloader (BL2) image, I am not aware of such process and what are next step to create SPL for Exynos platform.
I have build these patches for Odroid-U3 boards, with no SPL enable.
Best Regards -Anand

Hi Anand,
On Thu, Sep 13, 2018 at 08:39:52PM +0530, Anand Moon wrote:
Hi Simon,
On Wed, 12 Sep 2018 at 17:25, Simon Shields simon@lineageos.org wrote:
Hi,
This patch series adds support for using U-Boot's SPL as the second stage bootloader ("BL2") on Exynos4412 SoCs.
- Patch #1 adds support for the EMMC/SD OM pin configuration, which is used by the boards I tested on.
- Patch #2 configures the magic values used to indicate system suspend state (which are identical to exynos5).
- Patch #3 renames the existing exynos4 clock/dmc initialisation code to reflect the fact that it only supports exynos4210.
- Patches #4 and #5 add/fill in structs reflecting the PMU and TZASC register layouts on exynos4412, respectively.
- Patch #6 adds the exynos4412 DMC and clock initialisation code and enables building the SPL on exynos4412 platforms.
- Patch #7 enables building the "mkexynosspl" utility for exynos4 SoCs.
The majority of the logic in patch #6 comes from a vendor u-boot dump (2010.12!), however, small portions (mostly code used for 2GB RAM initialisation) were reverse engineered from the vendor bootloader found on a GT-N7100.
This patch series has been tested on a GT-I9300 (exynos4412, 1GB RAM) and a GT-N7100 (exynos4412 prime, 2GB RAM), with a few additional patchsets applied for board/HW support (which I intend to upstream in the future).
Cheers, Simon
Could you elaborate more on how to generate stage bootloader (BL2) image, I am not aware of such process and what are next step to create SPL for Exynos platform.
I have build these patches for Odroid-U3 boards, with no SPL enable.
Of course!
You need to add "select SUPPORT_SPL" to the relevant TARGET_ kconfig entry (e.g. [0]). Then, you need to configure the SPL suitably in include/configs/<target>.h - see [1], these values should not need changing between boards. Finally, you need to enable some SPL stuff in the defconfig (see [2]). That should allow u-boot to generate a SPL binary, which should go in spl/<target>-spl.bin.
After that, you need to assemble an image suitable for flashing to an sdcard/eMMC. I use these two scripts [3], [4] combined with this BL1 [5] (originally from the ODROID-X u-boot sources, which no longer appear to be available) for eMMC and sdcard respectively.
The usage of the script is:
./create_4412_<sd|emmc>_image.sh <bl1 binary> <spl binary> <u-boot.bin> <outfile>
<outfile> can then be dd'd directly to an SD card or to the eMMC boot0 partition.
Hope that gets things working for you!
Cheers, Simon
Best Regards -Anand
[0]: https://github.com/fourkbomb/u-boot/blob/4be16a7/arch/arm/mach-exynos/Kconfi... [1]: https://github.com/fourkbomb/u-boot/blob/4be16a7/include/configs/midas.h#L31... [2]: https://github.com/fourkbomb/u-boot/blob/4be16a7/configs/midas_defconfig#L6-... [3]: https://github.com/fourkbomb/buildroot-external-midas/blob/master/board/mida... [4]: https://github.com/fourkbomb/buildroot-external-midas/blob/master/board/mida... [5]: https://github.com/fourkbomb/buildroot-external-midas/blob/master/board/mida...

Hi Simon, On Fri, 14 Sep 2018 at 08:00, Simon Shields simon@lineageos.org wrote:
Hi Anand,
On Thu, Sep 13, 2018 at 08:39:52PM +0530, Anand Moon wrote:
Hi Simon,
On Wed, 12 Sep 2018 at 17:25, Simon Shields simon@lineageos.org wrote:
Hi,
This patch series adds support for using U-Boot's SPL as the second stage bootloader ("BL2") on Exynos4412 SoCs.
- Patch #1 adds support for the EMMC/SD OM pin configuration, which is used by the boards I tested on.
- Patch #2 configures the magic values used to indicate system suspend state (which are identical to exynos5).
- Patch #3 renames the existing exynos4 clock/dmc initialisation code to reflect the fact that it only supports exynos4210.
- Patches #4 and #5 add/fill in structs reflecting the PMU and TZASC register layouts on exynos4412, respectively.
- Patch #6 adds the exynos4412 DMC and clock initialisation code and enables building the SPL on exynos4412 platforms.
- Patch #7 enables building the "mkexynosspl" utility for exynos4 SoCs.
The majority of the logic in patch #6 comes from a vendor u-boot dump (2010.12!), however, small portions (mostly code used for 2GB RAM initialisation) were reverse engineered from the vendor bootloader found on a GT-N7100.
This patch series has been tested on a GT-I9300 (exynos4412, 1GB RAM) and a GT-N7100 (exynos4412 prime, 2GB RAM), with a few additional patchsets applied for board/HW support (which I intend to upstream in the future).
Cheers, Simon
Could you elaborate more on how to generate stage bootloader (BL2) image, I am not aware of such process and what are next step to create SPL for Exynos platform.
I have build these patches for Odroid-U3 boards, with no SPL enable.
Of course!
You need to add "select SUPPORT_SPL" to the relevant TARGET_ kconfig entry (e.g. [0]). Then, you need to configure the SPL suitably in include/configs/<target>.h - see [1], these values should not need changing between boards. Finally, you need to enable some SPL stuff in the defconfig (see [2]). That should allow u-boot to generate a SPL binary, which should go in spl/<target>-spl.bin.
After that, you need to assemble an image suitable for flashing to an sdcard/eMMC. I use these two scripts [3], [4] combined with this BL1 [5] (originally from the ODROID-X u-boot sources, which no longer appear to be available) for eMMC and sdcard respectively.
The usage of the script is:
./create_4412_<sd|emmc>_image.sh <bl1 binary> <spl binary> <u-boot.bin> <outfile>
<outfile> can then be dd'd directly to an SD card or to the eMMC boot0 partition.
Hope that gets things working for you!
Cheers, Simon
Best Regards -Anand
Thank you very much for this inside on building SPL image. I will give this a try on Odroid U3.
Do you have plan to add some low-level code to control clk memory cpu.
[0] https://github.com/SamsungARTIK/u-boot-artik/tree/artik-exynos/v2012.07/boar...
Actually I failed to understand how the communication between the kernel binary and u-boot with out this code.
Also what about trusted zone, and do we need to get this spl image signed by Samsung/Hardkernel to make this work.
Best Regards -Anand

Hi Anand,
On Fri, Sep 14, 2018 at 05:31:38PM +0530, Anand Moon wrote:
Hi Simon, On Fri, 14 Sep 2018 at 08:00, Simon Shields simon@lineageos.org wrote:
Hi Anand,
On Thu, Sep 13, 2018 at 08:39:52PM +0530, Anand Moon wrote:
Hi Simon,
On Wed, 12 Sep 2018 at 17:25, Simon Shields simon@lineageos.org wrote:
Hi,
This patch series adds support for using U-Boot's SPL as the second stage bootloader ("BL2") on Exynos4412 SoCs.
- Patch #1 adds support for the EMMC/SD OM pin configuration, which is used by the boards I tested on.
- Patch #2 configures the magic values used to indicate system suspend state (which are identical to exynos5).
- Patch #3 renames the existing exynos4 clock/dmc initialisation code to reflect the fact that it only supports exynos4210.
- Patches #4 and #5 add/fill in structs reflecting the PMU and TZASC register layouts on exynos4412, respectively.
- Patch #6 adds the exynos4412 DMC and clock initialisation code and enables building the SPL on exynos4412 platforms.
- Patch #7 enables building the "mkexynosspl" utility for exynos4 SoCs.
The majority of the logic in patch #6 comes from a vendor u-boot dump (2010.12!), however, small portions (mostly code used for 2GB RAM initialisation) were reverse engineered from the vendor bootloader found on a GT-N7100.
This patch series has been tested on a GT-I9300 (exynos4412, 1GB RAM) and a GT-N7100 (exynos4412 prime, 2GB RAM), with a few additional patchsets applied for board/HW support (which I intend to upstream in the future).
Cheers, Simon
Could you elaborate more on how to generate stage bootloader (BL2) image, I am not aware of such process and what are next step to create SPL for Exynos platform.
I have build these patches for Odroid-U3 boards, with no SPL enable.
Of course!
You need to add "select SUPPORT_SPL" to the relevant TARGET_ kconfig entry (e.g. [0]). Then, you need to configure the SPL suitably in include/configs/<target>.h - see [1], these values should not need changing between boards. Finally, you need to enable some SPL stuff in the defconfig (see [2]). That should allow u-boot to generate a SPL binary, which should go in spl/<target>-spl.bin.
After that, you need to assemble an image suitable for flashing to an sdcard/eMMC. I use these two scripts [3], [4] combined with this BL1 [5] (originally from the ODROID-X u-boot sources, which no longer appear to be available) for eMMC and sdcard respectively.
The usage of the script is:
./create_4412_<sd|emmc>_image.sh <bl1 binary> <spl binary> <u-boot.bin> <outfile>
<outfile> can then be dd'd directly to an SD card or to the eMMC boot0 partition.
Hope that gets things working for you!
Cheers, Simon
Best Regards -Anand
Thank you very much for this inside on building SPL image. I will give this a try on Odroid U3.
Do you have plan to add some low-level code to control clk memory cpu.
[0] https://github.com/SamsungARTIK/u-boot-artik/tree/artik-exynos/v2012.07/boar...
Actually I failed to understand how the communication between the kernel binary and u-boot with out this code.
That code is not actually board-specific. It's added in patch #6. All the BL2 does is initialise clocks and memory (DMC), then load U-Boot from the appropriate boot medium.
Also what about trusted zone, and do we need to get this spl image signed by Samsung/Hardkernel to make this work.
As with other Exynos SoCs in U-Boot, this doesn't support loading trustzone. As a result, you need to remove the "secure-firmware" node from the Linux kernel (you can also do it with CONFIG_OF_BOARD_SETUP[0]). Adding support for the TZSW could probably be done, but the goal here was to remove blobs from the boot process - so I don't really have any interest in adding TZSW support right now.
Best Regards -Anand
Cheers, Simon
[0]: https://github.com/fourkbomb/u-boot/blob/4be16a7/board/samsung/midas/midas.c...

Hi Simon On Fri, 14 Sep 2018 at 19:18, Simon Shields simon@lineageos.org wrote:
Hi Anand,
On Fri, Sep 14, 2018 at 05:31:38PM +0530, Anand Moon wrote:
Hi Simon, On Fri, 14 Sep 2018 at 08:00, Simon Shields simon@lineageos.org wrote:
Hi Anand,
On Thu, Sep 13, 2018 at 08:39:52PM +0530, Anand Moon wrote:
Hi Simon,
On Wed, 12 Sep 2018 at 17:25, Simon Shields simon@lineageos.org wrote:
Hi,
This patch series adds support for using U-Boot's SPL as the second stage bootloader ("BL2") on Exynos4412 SoCs.
- Patch #1 adds support for the EMMC/SD OM pin configuration, which is used by the boards I tested on.
- Patch #2 configures the magic values used to indicate system suspend state (which are identical to exynos5).
- Patch #3 renames the existing exynos4 clock/dmc initialisation code to reflect the fact that it only supports exynos4210.
- Patches #4 and #5 add/fill in structs reflecting the PMU and TZASC register layouts on exynos4412, respectively.
- Patch #6 adds the exynos4412 DMC and clock initialisation code and enables building the SPL on exynos4412 platforms.
- Patch #7 enables building the "mkexynosspl" utility for exynos4 SoCs.
The majority of the logic in patch #6 comes from a vendor u-boot dump (2010.12!), however, small portions (mostly code used for 2GB RAM initialisation) were reverse engineered from the vendor bootloader found on a GT-N7100.
This patch series has been tested on a GT-I9300 (exynos4412, 1GB RAM) and a GT-N7100 (exynos4412 prime, 2GB RAM), with a few additional patchsets applied for board/HW support (which I intend to upstream in the future).
Cheers, Simon
Could you elaborate more on how to generate stage bootloader (BL2) image, I am not aware of such process and what are next step to create SPL for Exynos platform.
I have build these patches for Odroid-U3 boards, with no SPL enable.
Of course!
You need to add "select SUPPORT_SPL" to the relevant TARGET_ kconfig entry (e.g. [0]). Then, you need to configure the SPL suitably in include/configs/<target>.h - see [1], these values should not need changing between boards. Finally, you need to enable some SPL stuff in the defconfig (see [2]). That should allow u-boot to generate a SPL binary, which should go in spl/<target>-spl.bin.
After that, you need to assemble an image suitable for flashing to an sdcard/eMMC. I use these two scripts [3], [4] combined with this BL1 [5] (originally from the ODROID-X u-boot sources, which no longer appear to be available) for eMMC and sdcard respectively.
The usage of the script is:
./create_4412_<sd|emmc>_image.sh <bl1 binary> <spl binary> <u-boot.bin> <outfile>
<outfile> can then be dd'd directly to an SD card or to the eMMC boot0 partition.
Hope that gets things working for you!
Cheers, Simon
Best Regards -Anand
Thank you very much for this inside on building SPL image. I will give this a try on Odroid U3.
Do you have plan to add some low-level code to control clk memory cpu.
[0] https://github.com/SamsungARTIK/u-boot-artik/tree/artik-exynos/v2012.07/boar...
Actually I failed to understand how the communication between the kernel binary and u-boot with out this code.
That code is not actually board-specific. It's added in patch #6. All the BL2 does is initialise clocks and memory (DMC), then load U-Boot from the appropriate boot medium.
Also what about trusted zone, and do we need to get this spl image signed by Samsung/Hardkernel to make this work.
As with other Exynos SoCs in U-Boot, this doesn't support loading trustzone. As a result, you need to remove the "secure-firmware" node from the Linux kernel (you can also do it with CONFIG_OF_BOARD_SETUP[0]). Adding support for the TZSW could probably be done, but the goal here was to remove blobs from the boot process - so I don't really have any interest in adding TZSW support right now.
Best Regards -Anand
Cheers, Simon
Adding samsung maintainers. + Minkyum and +Lukasz
Sorry for late testing of these patches
I manage to get the code compile on the my Archlinux Odroid U3 image with some twerks in the u-boot. with the new odroid I am able to boot using u-boot up till loading of the kernel but it failed to move ahead. How can I debug this further.
------------------------------------------------------------ Starting Reboot... [ 1613.704042] watchdog: watchdog0: nowayout prevents watchdog being stopped! [ 1613.705323] watchdog: watchdog0: nowayout prevents watchdog being stopped! [ 1613.712163] watchdog: watchdog0: watchdog did not stop! [ 1613.718887] systemd-shutdow: 26 output lines suppressed due to ratelimiting [ 1613.744412] systemd-shutdown[1]: Syncing filesystems and block devices.
U-Boot 2018.09-00275-g3502a38e59-dirty (Oct 29 2018 - 07:22:01 +0000)
CPU: Exynos4412 @ 1 GHz Model: Odroid based on Exynos4412 Board: Odroid based on Exynos4412 Type: u3 DRAM: 2 GiB LDO20@VDDQ_EMMC_1.8V: set 1800000 uV; enabling LDO22@VDDQ_EMMC_2.8V: set 2800000 uV; enabling LDO21@TFLASH_2.8V: set 2800000 uV; enabling MMC: SAMSUNG SDHCI: 1, EXYNOS DWMMC: 0 Loading Environment from MMC... Card did not respond to voltage select! *** Warning - No block device, using default environment
In: serial Out: serial Err: serial Net: Net Initialization Skipped No ethernet found. Hit any key to stop autoboot: 0 switch to partitions #0, OK mmc1 is current device Scanning mmc 1:1... Found U-Boot script /boot/boot.scr 732 bytes read in 5 ms (142.6 KiB/s) ## Executing script at 42000000 6355984 bytes read in 127 ms (47.7 MiB/s) 72400 bytes read in 122 ms (579.1 KiB/s) 5656893 bytes read in 117 ms (46.1 MiB/s) ## Flattened Device Tree blob at 40800000 Booting using the fdt blob at 0x40800000 Loading Ramdisk to 4fa9a000, end 4ffff13d ... OK Loading Device Tree to 4fa85000, end 4fa99acf ... OK
Starting kernel ...
------------------------------------------------------------ Best Regards -Anand

Dear Simon Shields,
On 12/09/18 17:28, Simon Shields wrote:
Hi,
This patch series adds support for using U-Boot's SPL as the second stage bootloader ("BL2") on Exynos4412 SoCs.
- Patch #1 adds support for the EMMC/SD OM pin configuration, which is used by the boards I tested on.
- Patch #2 configures the magic values used to indicate system suspend state (which are identical to exynos5).
- Patch #3 renames the existing exynos4 clock/dmc initialisation code to reflect the fact that it only supports exynos4210.
- Patches #4 and #5 add/fill in structs reflecting the PMU and TZASC register layouts on exynos4412, respectively.
- Patch #6 adds the exynos4412 DMC and clock initialisation code and enables building the SPL on exynos4412 platforms.
- Patch #7 enables building the "mkexynosspl" utility for exynos4 SoCs.
The majority of the logic in patch #6 comes from a vendor u-boot dump (2010.12!), however, small portions (mostly code used for 2GB RAM initialisation) were reverse engineered from the vendor bootloader found on a GT-N7100.
This patch series has been tested on a GT-I9300 (exynos4412, 1GB RAM) and a GT-N7100 (exynos4412 prime, 2GB RAM), with a few additional patchsets applied for board/HW support (which I intend to upstream in the future).
Cheers, Simon
Simon Shields (7): ARM: exynos: spl: add EMMC/SD boot mode support exynos4: configure power down magic values ARM: exynos: rename exynos4 setup files to exynos4210 ARM: exynos: fill in exynos4412_power struct ARM: exynos: add exynos4412 TZASC memory layout ARM: exynos: SPL support for exynos 4412 tools: build mkexynosspl for exynos4 as well
arch/arm/mach-exynos/Kconfig | 6 + arch/arm/mach-exynos/Makefile | 3 +- ...init_exynos4.c => clock_init_exynos4210.c} | 2 +- arch/arm/mach-exynos/clock_init_exynos4412.c | 122 +++++ ...c_init_exynos4.c => dmc_init_exynos4210.c} | 2 +- arch/arm/mach-exynos/dmc_init_exynos4412.c | 185 ++++++++ .../{exynos4_setup.h => exynos4210_setup.h} | 0 arch/arm/mach-exynos/exynos4412_setup.h | 425 ++++++++++++++++++ arch/arm/mach-exynos/include/mach/cpu.h | 2 +- arch/arm/mach-exynos/include/mach/dmc.h | 19 + arch/arm/mach-exynos/include/mach/power.h | 290 +++++++++++- arch/arm/mach-exynos/power.c | 12 + arch/arm/mach-exynos/spl_boot.c | 22 +- include/configs/exynos4-common.h | 5 + tools/Makefile | 1 + 15 files changed, 1084 insertions(+), 12 deletions(-) rename arch/arm/mach-exynos/{clock_init_exynos4.c => clock_init_exynos4210.c} (99%) create mode 100644 arch/arm/mach-exynos/clock_init_exynos4412.c rename arch/arm/mach-exynos/{dmc_init_exynos4.c => dmc_init_exynos4210.c} (99%) create mode 100644 arch/arm/mach-exynos/dmc_init_exynos4412.c rename arch/arm/mach-exynos/{exynos4_setup.h => exynos4210_setup.h} (100%) create mode 100644 arch/arm/mach-exynos/exynos4412_setup.h
I've got warning/error.
arch/arm/mach-exynos/spl_boot.c: In function 'copy_uboot_to_ram': arch/arm/mach-exynos/spl_boot.c:189:6: warning: unused variable 'ret' [-Wunused-variable] u32 ret; ^~~ CC spl/arch/arm/mach-exynos/lowlevel_init.o AS spl/arch/arm/lib/crt0_arm_efi.o LD spl/arch/arm/lib/built-in.o CC spl/arch/arm/lib/reloc_arm_efi.o AR spl/arch/arm/lib/lib.a LD spl/arch/arm/mach-exynos/built-in.o spl/arch/arm/mach-exynos/dmc_init_exynos4412.o: In function `board_num_mem_chips': /home/share/Work/u-boot-samsung/arch/arm/mach-exynos/dmc_init_exynos4412.c:35: multiple definition of `mem_ctrl_init' spl/arch/arm/mach-exynos/dmc_init_exynos4210.o:/home/share/Work/u-boot-samsung/arch/arm/mach-exynos/dmc_init_exynos4210.c:169: first defined here spl/arch/arm/mach-exynos/clock_init_exynos4412.o: In function `system_clock_init': /home/share/Work/u-boot-samsung/arch/arm/mach-exynos/clock_init_exynos4412.c:34: multiple definition of `system_clock_init' spl/arch/arm/mach-exynos/clock_init_exynos4210.o:/home/share/Work/u-boot-samsung/arch/arm/mach-exynos/clock_init_exynos4210.c:40: first defined here make[2]: *** [spl/arch/arm/mach-exynos/built-in.o] Error 1 make[1]: *** [spl/arch/arm/mach-exynos] Error 2 make: *** [spl/u-boot-spl] Error 2
Could you please check?
Thanks, Minkyu Kang.
participants (3)
-
Anand Moon
-
Minkyu Kang
-
Simon Shields