基于Exynos4412开发板的uboot-2019.07移植

Exynos4412 芯片提供的 fwbl.bin只能加载 16KiB 大小的 u-boot-spl.bin到内部 SDRAM,通常编译得到的u-boot.bin远远超过这个限制,因此使用u-boot源代码支持的SPL功能来解决该问题 。不过,u-boot-spl.bin与u-boot.bin共用了很多基础代码。CONFIG_SPL_BUILD选项控制着SPL功能的开关,若在配置文件中启用了该选项,在编译时会在spl子目录下构建出SPL相关的代码文件树。同时它还会把整个启动引导过程分为两个阶段,u-boot-spl.bin完成第一阶段的初始化设置,主要是初始化 SoC时钟、外部内存DDR和早期串口调试功能,最后加载第二阶段涉及的u-boot.bin到外部内存并跳转执行。

开发环境

  • Host OS: ubuntu-18.04-desktop
  • Target Development Board: Single Board Computer「SBC」 based on Exynos4412 SoC
    • 9tripod X4412「深圳九鼎创展有限公司」
      • SCP package「封装」
      • 1G DDR3
      • 4G eMMC
    • TOPEET iTOP4412「讯为」
      • SCP package
      • 1G DDR3
      • 8G eMMC
  • Cross Compiler Toolchain: arm-linux-gnueabihf-
    • gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)
  • u-boot: u-boot-2019.07

移植

在实际的移植过程,u-boot源代码支持众多ARM体系架构的SoC和开发板,优先选择与目标开发板相似的开发板作为参考,比如本文参考的origen开发板,它使用的SoC是Exynos4210,与目标板采用的Exynos4412同属于ARMv7架构和Samsung Exynos4系列,并且开启了SPL功能。本小节以移植u-boot-2019.07到iTOP4412开发板为例阐述说明整个移植过程。

创建board相关的目录和配置

下面先创建相关的目录

1
2
3
$ cd board/samsung/
$ mkdir -p itop4412 itop4412/tools
cd itop4412
添加初始化iTOP4412 board的代码,以及LED初始化代码用于输出早期的调试信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
diff --git a/board/samsung/itop4412/itop4412.c b/board/samsung/itop4412/itop4412.c
new file mode 100644
index 0000000..3b93220
--- /dev/null
+++ b/board/samsung/itop4412/itop4412.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/pinmux.h>
+#include <usb.h>
+
+#ifndef CONFIG_SPL_BUILD
+u32 get_board_rev(void)
+{
+ return 0;
+}
+
+int exynos_init(void)
+{
+ return 0;
+}
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+ return 0;
+}
+
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+int exynos_early_init_f(void)
+{
+ return 0;
+}
+#endif
+
+#else /* !CONFIG_SPL_BUILD */
+void exynos_led_set_on_early(unsigned int led_num)
+{
+#define GPL2CON (0x11000100)
+#define GPL2DAT (0x11000104)
+#define GPK1CON (0x11000060)
+#define GPK1DAT (0x11000064)
+
+ uint8_t val;
+
+ /* LED2 */
+ val = led_num & 0x01;
+ if (val) {
+ clrsetbits_le32(GPL2CON, 0xf << 0, 0x01 << 0);
+ setbits_8(GPL2DAT, 1);
+ }
+
+ /* LED3 */
+ val = led_num & 0x02;
+ if (val) {
+ clrsetbits_le32(GPK1CON, 0xf << 4, 0x01 << 4);
+ setbits_8(GPK1DAT, 1 << 1);
+ }
+}
+#endif
添加SPL相关的工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
diff --git a/board/samsung/itop4412/tools/mkitop4412spl.c b/board/samsung/itop4412/tools/mkitop4412spl.c
new file mode 100644
index 0000000..8d61809
--- /dev/null
+++ b/board/samsung/itop4412/tools/mkitop4412spl.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Based on board/samsung/origen/tool/mkorigenspl.c
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#define BUFSIZE (14*1024)
+#define IMG_SIZE (14*1024)
+#define FILE_PERM (S_IRUSR | S_IWUSR | S_IRGRP \
+ | S_IWGRP | S_IROTH | S_IWOTH)
+/*
+* Requirement:
+* fwbl.bin code reads first 14K bytes from boot device.
+* It then calculates the checksum of 14K-4 bytes and compare with data at
+* 14K-4 offset.
+*
+* This function takes two filenames:
+* IN "u-boot-spl.bin" and
+* OUT "$(BOARD)-spl.bin as filenames.
+* It reads the "u-boot-spl.bin" in 14K buffer.
+* It calculates checksum of 14K-4 Bytes and stores at 14K-4 offset in buffer.
+* It writes the buffer to "$(BOARD)-spl.bin" file.
+*/
+
+int main(int argc, char **argv)
+{
+ int i, len;
+ unsigned char buffer[BUFSIZE] = {0};
+ int ifd, ofd;
+ unsigned int checksum = 0, count;
+
+ if (argc != 3) {
+ printf(" %d Wrong number of arguments\n", argc);
+ exit(EXIT_FAILURE);
+ }
+
+ ifd = open(argv[1], O_RDONLY);
+ if (ifd < 0) {
+ fprintf(stderr, "%s: Can't open %s: %s\n",
+ argv[0], argv[1], strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ ofd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, FILE_PERM);
+ if (ofd < 0) {
+ fprintf(stderr, "%s: Can't open %s: %s\n",
+ argv[0], argv[2], strerror(errno));
+ if (ifd)
+ close(ifd);
+ exit(EXIT_FAILURE);
+ }
+
+ len = lseek(ifd, 0, SEEK_END);
+ lseek(ifd, 0, SEEK_SET);
+
+ count = len < IMG_SIZE ? len : IMG_SIZE;
+
+ if (read(ifd, buffer, count) != count) {
+ fprintf(stderr, "%s: Can't read %s: %s\n",
+ argv[0], argv[1], strerror(errno));
+
+ if (ifd)
+ close(ifd);
+ if (ofd)
+ close(ofd);
+
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < IMG_SIZE - 4; i++)
+ checksum += buffer[i];
+ *(unsigned int *)(buffer+i) = checksum;
+
+ if (write(ofd, buffer, BUFSIZE) != BUFSIZE) {
+ fprintf(stderr, "%s: Can't write %s: %s\n",
+ argv[0], argv[2], strerror(errno));
+
+ if (ifd)
+ close(ifd);
+ if (ofd)
+ close(ofd);
+
+ exit(EXIT_FAILURE);
+ }
+
+ if (ifd)
+ close(ifd);
+ if (ofd)
+ close(ofd);
+
+ return EXIT_SUCCESS;
+}
添加iTOP4412的设备树文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
diff --git a/arch/arm/dts/exynos4412-itop4412.dts b/arch/arm/dts/exynos4412-itop4412.dts
new file mode 100644
index 0000000..d0f463f
--- /dev/null
+++ b/arch/arm/dts/exynos4412-itop4412.dts
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Refer to exynos4210-origen.dts
+ *
+ * TOPEET iTOP4412 development board(based on Exynos4412 SoC) device tree
+ * source
+ *
+ * Copyright (C) 2019 Wang Xinlu <wangkartx@gmail.com>
+ *
+ */
+
+/dts-v1/;
+#include "exynos4412.dtsi"
+
+/ {
+ model = "TOPEET iTOP4412 development board based on Exynos4412";
+ compatible = "TOPEET,itop4412", "samsung,exynos4412";
+
+ chose {
+ stdout-path = "/serial@13820000";
+ };
+
+ aliases {
+ serial2 = "/serial@13820000";
+ console = "/serial@13820000";
+ };
+
+ serial@13800000 {
+ status = "disabled";
+ };
+
+ serial@13810000 {
+ status = "disabled";
+ };
+
+ serial@13820000 {
+ status = "okay";
+ };
+
+ serial@13830000 {
+ status = "disabled";
+ };
+};
+
+&sdhci2 {
+ samsung,bus-width = <4>;
+ samsung,timing = <1 2 3>;
+ cd-gpios = <&gpx0 7 0>;
+ status = "okay";
+};
添加board相关的编译构建文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
diff --git a/board/samsung/itop4412/Makefile b/board/samsung/itop4412/Makefile
new file mode 100644
index 0000000..65df3b8
--- /dev/null
+++ b/board/samsung/itop4412/Makefile
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+ifdef CONFIG_SPL_BUILD
+# necessary to create built-in.o
+obj- := __dummy__.o
+
+hostprogs-y := tools/mkitop4412spl
+always := $(hostprogs-y)
+
+# omit -O2 option to suppress
+# warning: dereferencing type-punned pointer will break strict-aliasing rules
+#
+# TODO:
+# Fix the root cause in tools/mkitop4412spl.c and delete the following work-around
+$(obj)/tools/mkitop4412spl: HOSTCFLAGS:=$(filter-out -O2,$(HOSTCFLAGS))
+endif
+obj-y += itop4412.o
添加board相关的编译配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
diff --git a/board/samsung/itop4412/Kconfig b/board/samsung/itop4412/Kconfig
new file mode 100644
index 0000000..3ed2a25
--- /dev/null
+++ b/board/samsung/itop4412/Kconfig
@@ -0,0 +1,19 @@
+if TARGET_ITOP4412
+
+config SYS_BOARD
+ default "itop4412"
+
+config SYS_VENDOR
+ default "samsung"
+
+config SYS_CONFIG_NAME
+ default "itop4412"
+
+config ITOP4412
+ bool "TOPEET iTOP4412 development board"
+ default y
+
+config EXYNOS4412
+ bool "Samsung Exynos4412 SoC"
+ default y
+endif
添加board相关的维护信息,从代码角度看可能并不是很重要,但是还是有必要的
1
2
3
4
5
6
7
8
9
10
11
12
diff --git a/board/samsung/itop4412/MAINTAINERS b/board/samsung/itop4412/MAINTAINERS
new file mode 100644
index 0000000..77228c2
--- /dev/null
+++ b/board/samsung/itop4412/MAINTAINERS
@@ -0,0 +1,6 @@
+iTOP4412 Development Board
+M: Wang Xinlu <wangkartx@gmail.com>
+S: Maintained
+F: board/samsung/itop4412/
+F: include/configs/itop4412.h
+F: configs/itop4412_defconfig
添加board相关的默认配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
diff --git a/configs/itop4412_defconfig b/configs/itop4412_defconfig
new file mode 100644
index 0000000..8489a56
--- /dev/null
+++ b/configs/itop4412_defconfig
@@ -0,0 +1,37 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_SYS_TEXT_BASE=0x43E00000
+CONFIG_ARCH_EXYNOS4=y
+CONFIG_TARGET_ITOP4412=y
+CONFIG_SPL=y
+CONFIG_SPL_TEXT_BASE=0x02023400
+# CONFIG_SPL_FRAMEWORK is not set
+CONFIG_IDENT_STRING=" for iTOP4412"
+CONFIG_DEFAULT_DEVICE_TREE="exynos4412-itop4412"
+CONFIG_SYS_PROMPT="iTOP4412 # "
+# CONFIG_CMD_XIMG is not set
+CONFIG_DISTRO_DEFAULTS=y
+# CONFIG_USE_BOOTCOMMAND is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_NET is not set
+# CONFIG_CMD_NFS is not set
+# CONFIG_CMD_MISC is not set
+CONFIG_DEBUG_UART=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_DEBUG_UART_BASE=0x13820000
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_S5P=y
+CONFIG_DEBUG_UART_S5P=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_CMD_MMC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
+CONFIG_MMC_SDHCI_S5P=y
+CONFIG_MMC_BROKEN_CD=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT4_WRITE=y
添加board相关的全局设置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
diff --git a/include/configs/itop4412.h b/include/configs/itop4412.h
new file mode 100644
index 0000000..47ae372
--- /dev/null
+++ b/include/configs/itop4412.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Configuration and settings for the TOPEET iTOP4412 development board.
+ */
+
+#ifndef __CONFIG_ITOP4412_H
+#define __CONFIG_ITOP4412_H
+
+#include <configs/exynos4-common.h>
+
+/* iTOP4412 has 4 bank of DRAM */
+#define CONFIG_SYS_SDRAM_BASE 0x40000000
+#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE
+#define SDRAM_BANK_SIZE (256 << 20) /* 256 MiB */
+
+/* memtest works on */
+#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE
+#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x6000000)
+#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x3E00000)
+#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_LOAD_ADDR - 0x1000000)
+
+#define CONFIG_MACH_TYPE MACH_TYPE_ITOP4412
+
+/* select serial console configuration */
+#define CONFIG_BAUDRATE 115200
+
+/* Console configuration */
+#define CONFIG_DEFAULT_CONSOLE "ttySAC2,115200n8"
+
+#define CONFIG_SYS_MEM_TOP_HIDE (1 << 20) /* ram console */
+
+#define CONFIG_SYS_MONITOR_BASE 0x00000000
+
+/* Power Down Modes */
+#define S5P_CHECK_SLEEP 0x00000BAD
+#define S5P_CHECK_DIDLE 0xBAD00000
+#define S5P_CHECK_LPA 0xABAD0000
+
+/* SPL configuration */
+#define CONFIG_SPL_MAX_FOOTPRINT (14 << 10)
+#define CONFIG_SPL_STACK 0x02060000
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "loadaddr=0x40007000\0" \
+ "rdaddr=0x48000000\0" \
+ "kerneladdr=0x40007000\0" \
+ "ramdiskaddr=0x48000000\0" \
+ "console=" CONFIG_DEFAULT_CONSOLE "\0"\
+ "mmcdev=0\0" \
+ "bootenv=uEnv.txt\0" \
+ "loadbootenv=load mmc ${mmcdev} ${loadaddr} ${bootenv}\0" \
+ "importbootenv=echo Importing environment from mmc ...; " \
+ "env import -t $loadaddr $filesize\0" \
+ "loadbootscript=load mmc ${mmcdev} ${loadaddr} boot.scr\0" \
+ "bootscript=echo Running bootscript from mmc${mmcdev} ...; " \
+ "source ${loadaddr}\0"
+
+#define CONFIG_BOOTCOMMAND \
+ "if mmc rescan; then " \
+ "echo SD/MMC found on device ${mmcdev};" \
+ "if run loadbootenv; then " \
+ "echo Loaded environment from ${bootenv};" \
+ "run importbootenv;" \
+ "fi;" \
+ "if test -n $uenvcmd; then " \
+ "echo Running uenvcmd ...;" \
+ "run uenvcmd;" \
+ "fi;" \
+ "if run loadbootscript; then " \
+ "run bootscript; " \
+ "fi; " \
+ "fi;" \
+ "load mmc ${mmcdev} ${loadaddr} uImage; bootm ${loadaddr} "
+
+#define CONFIG_CLK_1000_400_200
+
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_ENV_SIZE (16 << 10) /* 16 KB */
+#define RESERVE_BLOCK_SIZE (512)
+#define FWBL_SIZE (8 << 10) /* 8 KiB reserved for fwbl.bin*/
+#define SPL_SZIE (16 << 10) /* 16KiB reserved for u-boot-spl.bin */
+#define UBOOT_SIZE (0x80000) /* 512 KiB reserved for u-boot.bin*/
+#define TZSW_SIZE (0x27000) /* 156 KiB */
+#define BL2_START_OFFSET ((RESERVE_BLOCK_SIZE + FWBL_SIZE \
+ + SPL_SZIE)/512)
+#define BL2_SIZE_BLOC_COUNT (UBOOT_SIZE/512)
+#define TZSW_START_OFFSET (BL2_START_OFFSET \
+ + BL2_SIZE_BLOC_COUNT)
+#define TZSW_SIZE_BLOC_COUNT (TZSW_SIZE/512)
+#define CONFIG_ENV_OFFSET (RESERVE_BLOCK_SIZE + FWBL_SIZE \
+ + SPL_SZIE + UBOOT_SIZE \
+ + TZSW_SIZE)
+
+#endif /* __CONFIG_H */

修改相关的代码和配置

修改SoC相关的编译配置文件,使iTOP4412相关的配置在menuconfig中出现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 14347e7..bf622c2 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -73,6 +73,11 @@ config TARGET_TRATS2
config TARGET_ODROID
bool "Exynos4412 Odroid board"

+config TARGET_ITOP4412
+ bool "Exynos4412 iTOP4412 board"
+ select OF_CONTROL
+ select SUPPORT_SPL
+
endchoice
endif

@@ -167,6 +172,7 @@ source "board/samsung/arndale/Kconfig"
source "board/samsung/smdk5250/Kconfig"
source "board/samsung/smdk5420/Kconfig"
source "board/samsung/espresso7420/Kconfig"
+source "board/samsung/itop4412/Kconfig"

config SPL_LDSCRIPT
default "board/samsung/common/exynos-uboot-spl.lds" if ARCH_EXYNOS5 || ARCH_EXYNOS4
修改SoC相关的编译构建文件,用于编译iTOP4412启动时需要的初始化代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index e895c13..58749aa 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -12,7 +12,9 @@ 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
+ifneq ($(filter y,$(CONFIG_EXYNOS4210)$(CONFIG_EXYNOS4412)),)
+obj-y += dmc_init_exynos4.o clock_init_exynos4.o
+endif
obj-y += spl_boot.o tzpc.o
obj-y += lowlevel_init.o
endif
修改SoC相关的初始化代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
diff --git a/arch/arm/mach-exynos/lowlevel_init.c b/arch/arm/mach-exynos/lowlevel_init.c
index 1e090fd..55f16db 100644
--- a/arch/arm/mach-exynos/lowlevel_init.c
+++ b/arch/arm/mach-exynos/lowlevel_init.c
@@ -218,12 +218,18 @@ int do_lowlevel_init(void)
#ifdef CONFIG_DEBUG_UART
#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL_SUPPORT)) || \
!defined(CONFIG_SPL_BUILD)
+#ifdef CONFIG_ITOP4412
+ exynos_pinmux_config(PERIPH_ID_UART2, PINMUX_FLAG_NONE);
+#else
exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
+#endif
debug_uart_init();
#endif
#endif
mem_ctrl_init(actions & DO_MEM_RESET);
+#ifndef CONFIG_ITOP4412
tzpc_init();
+#endif
}

return actions & DO_WAKEUP;
修改SoC相关的power设置代码
1
2
3
4
5
6
7
8
9
10
11
12
13
diff --git a/arch/arm/mach-exynos/include/mach/power.h b/arch/arm/mach-exynos/include/mach/power.h
index a3d8974..7b5dcf4 100644
--- a/arch/arm/mach-exynos/include/mach/power.h
+++ b/arch/arm/mach-exynos/include/mach/power.h
@@ -214,6 +214,8 @@ struct exynos4412_power {
unsigned int usbhost_phy_control;
unsigned int hsic1_phy_control;
unsigned int hsic2_phy_control;
+ unsigned char res2[0x2bfc];
+ unsigned int ps_hold_control;
};

struct exynos5_power {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
diff --git a/arch/arm/mach-exynos/power.c b/arch/arm/mach-exynos/power.c
index f2a6c00..8feab8f 100644
--- a/arch/arm/mach-exynos/power.c
+++ b/arch/arm/mach-exynos/power.c
@@ -162,6 +162,32 @@ 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);
+
+#ifdef CONFIG_ITOP4412
+ /*
+ * 0x0 = Disables Pull-up/Pull-down
+ * 0x1 = Enables Pull-down
+ * 0x2 = Reserved
+ * 0x3 = Enables Pull-up
+ *
+ * Due to GPX0_2 attached to PMIC's ONO pin,
+ * make GPX0_2 pin PU for high level,
+ * but all other pin default state for low level
+ * otherwise, keep restarting
+ *
+ */
+ writel(0x5575, (unsigned int *)0x11000C08);
+#endif
+}
+
/*
* Set ps_hold data driving value high
* This enables the machine to stay powered on
@@ -172,6 +198,13 @@ void set_ps_hold_ctrl(void)
{
if (cpu_is_exynos5())
exynos5_set_ps_hold_ctrl();
+
+#ifdef CONFIG_EXYNOS4412
+ if (cpu_is_exynos4()) {
+ if (proid_is_exynos4412())
+ exynos4412_set_ps_hold_ctrl();
+ }
+#endif
}

修改平台的标识符,为itop4412赋予一个独一无二的ID
1
2
3
4
5
6
7
8
9
10
diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h
index 32532b3..ec82f02 100644
--- a/arch/arm/include/asm/mach-types.h
+++ b/arch/arm/include/asm/mach-types.h
@@ -5051,4 +5051,5 @@
#define MACH_TYPE_NASM25 5112
#define MACH_TYPE_TOMATO 5113
#define MACH_TYPE_OMAP3_MRC3D 5114
+#define MACH_TYPE_ITOP4412 5115
#endif
增添itop4412设备树的编译规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 62da168..802afaf 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -12,7 +12,8 @@ dtb-$(CONFIG_EXYNOS4) += exynos4210-origen.dtb \
exynos4210-universal_c210.dtb \
exynos4210-trats.dtb \
exynos4412-trats2.dtb \
- exynos4412-odroid.dtb
+ exynos4412-odroid.dtb \
+ exynos4412-itop4412.dtb

dtb-$(CONFIG_TARGET_HIKEY) += hi6220-hikey.dtb
dtb-$(CONFIG_TARGET_HIKEY960) += hi3660-hikey960.dtb

适配时钟和内存控制器

添加时钟和内存控制器初始化所使用的设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
diff --git a/arch/arm/mach-exynos/exynos4412_setup.h b/arch/arm/mach-exynos/exynos4412_setup.h
new file mode 100644
index 0000000..fc8633b
--- /dev/null
+++ b/arch/arm/mach-exynos/exynos4412_setup.h
@@ -0,0 +1,528 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * refer to exynox4_setup.h
+ * Machine Specific settings for Exynos4412 board
+ *
+ * Copyright (C) 2018 Wang Xinlu <wangkartx@gmail.com>
+ */
+
+#ifndef _EXYNOX4412_SETUP_H
+#define _EXYNOX4412_SETUP_H
+
+#include <config.h>
+
+/*
+ * Refer to the datasheet
+ * The value for high-performance
+ */
+#ifdef CONFIG_CLK_800_400_200
+#define ARM_CLK_800
+#define DRAM_CLK_400
+#endif
+#ifdef CONFIG_CLK_1000_400_200
+#define ARM_CLK_1000
+#define DRAM_CLK_400
+#endif
+
+/* Bus Configuration Register Address */
+#define ASYNC_CONFIG 0x10010350
+
+/* CLK_SRC_CPU */
+#define MUX_MPLL_USER_SEL_C_FINPLL 0x0
+#define MUX_MPLL_USER_SEL_C_FOUTMPLL 0x1
+#define MUX_HPM_SEL_MOUTAPLL 0x0
+#define MUX_HPM_SEL_SCLKMPLL 0x1
+#define MUX_CORE_SEL_MOUTAPLL 0x0
+#define MUX_CORE_SEL_SCLKMPLL 0x1
+#define MUX_APLL_SEL_FILPLL 0x0
+#define MUX_APLL_SEL_FOUTAPLL 0x1
+#define CLK_SRC_CPU_RESET ((MUX_MPLL_USER_SEL_C_FINPLL << 24) \
+ | (MUX_HPM_SEL_MOUTAPLL << 20) \
+ | (MUX_CORE_SEL_MOUTAPLL << 16) \
+ | (MUX_APLL_SEL_FILPLL << 0))
+#define CLK_SRC_CPU_VAL ((MUX_MPLL_USER_SEL_C_FOUTMPLL << 24) \
+ | (MUX_HPM_SEL_MOUTAPLL << 20) \
+ | (MUX_CORE_SEL_MOUTAPLL << 16) \
+ | (MUX_APLL_SEL_FOUTAPLL << 0))
+
+/* CLK_MUX_STAT_CPU */
+#define CLK_MUX_STAT_CPU_RESET 0x01110001
+#define CLK_MUX_STAT_CPU_VAL 0x02110002
+
+/* CLK_DIV_CPU0 */
+#define APLL_RATIO 0x01
+#define CORE_RATIO 0x00
+#define CORE2_RATIO 0x00
+#define PCLK_DBG_RATIO 0x01
+#define ATB_RATIO 0x03
+#define COREM0_RATIO 0x03
+#define COREM1_RATIO 0x07
+#define PERIPH_RATIO 0x03
+
+/* CLK_DIV_CPU1 */
+#define COPY_RATIO 0x02
+#define HPM_RATIO 0x00
+
+
+#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 << 0))
+#define CLK_DIV_CPU1_VAL ((HPM_RATIO << 4) \
+ | (COPY_RATIO << 0))
+
+/* CLK_SRC_DMC */
+#define MUX_G2D_ACP_SEL_MOUTG2D_ACP_0 0x0
+#define MUX_G2D_ACP_SEL_MOUTG2D_ACP_1 0x1
+#define MUX_G2D_ACP_1_SEL_SCLKEPLL 0x0
+#define MUX_G2D_ACP_1_SEL_SCLKAPLL 0x1
+#define MUX_PWI_SEL_XXTI 0x0
+#define MUX_PWI_SEL_XUSBXTI 0x1
+#define MUX_PWI_SEL_SCLK_HDMI24M 0x2
+#define MUX_PWI_SEL_SCLK_USBPHY0 0x3
+#define MUX_PWI_SEL_SCLK_USBPHY1 0x4
+#define MUX_PWI_SEL_SCLK_HDMIPHY 0x5
+#define MUX_PWI_SEL_SCLKMPLL 0x6
+#define MUX_PWI_SEL_SCLKEPLL 0x7
+#define MUX_PWI_SEL_SCLKVPLL 0x8
+#define MUX_MPLL_SEL_FILPLL 0x0
+#define MUX_MPLL_SEL_MOUTMPLLFOUT 0x1
+#define MUX_DPHY_SEL_SCLKMPLL 0x0
+#define MUX_DPHY_SEL_SCLKAPLL 0x1
+#define MUX_DMC_BUS_SEL_SCLKMPLL 0x0
+#define MUX_DMC_BUS_SEL_SCLKAPLL 0x1
+#define CLK_SRC_DMC_VAL ((MUX_PWI_SEL_XUSBXTI << 16) \
+ | (MUX_MPLL_SEL_MOUTMPLLFOUT << 12))
+
+/* CLK_MUX_STAT_DMC */
+#define CLK_MUX_STAT_DMC_VAL 0x11102111
+
+/* CLK_DIV_DMC0 */
+#define DMCP_RATIO 0x1
+#define DMCD_RATIO 0x1
+#define DMC_RATIO 0x1
+#define DPHY_RATIO 0x1
+#define ACP_PCLK_RATIO 0x1
+#define ACP_RATIO 0x3
+#define CLK_DIV_DMC0_VAL ((DMCP_RATIO << 20) \
+ | (DMCD_RATIO << 16) \
+ | (DMC_RATIO << 12) \
+ | (DPHY_RATIO << 8) \
+ | (ACP_PCLK_RATIO << 4) \
+ | (ACP_RATIO << 0))
+
+/* CLK_DIV_DMC1 */
+#define DPM_RATIO 0x1
+#define DVSEM_RATIO 0x1
+#define C2C_ACLK_RATIO 0x1
+#define PWI_RATIO 0xF
+#define C2C_RATIO 0x1
+#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 << 0))
+
+/* CLK_SRC_TOP0 */
+#define MUX_VPLL_SEL_FINPLL 0x0
+#define MUX_VPLL_SEL_FOUTVPLL 0x1
+#define MUX_EPLL_SEL_FINPLL 0x0
+#define MUX_EPLL_SEL_FOUTEPLL 0x1
+#define CLK_SRC_TOP0_RESET 0x00000000
+#define CLK_SRC_TOP0_VAL ((MUX_VPLL_SEL_FOUTVPLL << 8) \
+ | (MUX_EPLL_SEL_FOUTEPLL << 4))
+
+/* CLK_MUX_STAT_TOP0 */
+#define CLK_MUX_STAT_TOP0_RESET 0x11111111
+#define CLK_MUX_STAT_TOP0_VAL 0x11111221
+
+/* CLK_SRC_TOP1 */
+#define MUX_ACLK_266_GPS_SUB_SEL_FINPLL 0x0
+#define MUX_ACLK_266_GPS_SUB_SEL_DIVOUT_ACLK_266_GPS 0x1
+#define MUX_MPLL_USER_SEL_T_FINPLL 0x0
+#define MUX_MPLL_USER_SEL_T_SCLKMPLL 0x1
+#define MUX_ACLK_400_MCUISP_SEL_SCLKMPLL_USER_T 0x0
+#define MUX_ACLK_400_MCUISP_SEL_SCLKAPLL 0x1
+#define CLK_SRC_TOP1_RESET 0x00000000
+#define CLK_SRC_TOP1_VAL ((MUX_ACLK_266_GPS_SUB_SEL_DIVOUT_ACLK_266_GPS << 16) \
+ | (MUX_MPLL_USER_SEL_T_SCLKMPLL << 12))
+
+/* CLK_MUX_STAT_TOP1 */
+#define CLK_MUX_STAT_TOP1_RESET 0x01111110
+#define CLK_MUX_STAT_TOP1_VAL 0x01122110
+
+/* CLK_DIV_TOP */
+#define ACLK_400_MCUISP_RATIO 0x1
+#define ACLK_266_GPS_RATIO 0x2
+#define ONENAND_RATIO 0x1
+#define ACLK_133_RATIO 0x5
+#define ACLK_160_RATIO 0x4
+#define ACLK_100_RATIO 0x7
+#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 << 0))
+
+/* CLK_SRC_LEFTBUS */
+#define MUX_MPLL_USER_SEL_L_FILPLL 0x0
+#define MUX_MPLL_USER_SEL_L_FOUTMPLL 0x1
+#define MUX_GDL_SEL_SCLKMPLL 0x0
+#define MUX_GDL_SEL_SCLKAPLL 0x1
+#define CLK_SRC_LEFTBUS_VAL ((MUX_MPLL_USER_SEL_L_FOUTMPLL << 4) \
+ | (MUX_GDL_SEL_SCLKMPLL << 0))
+
+/* CLK_MUX_STAT_LEFTBUS */
+#define CLK_MUX_STAT_LEFTBUS_VAL 0x00000021
+
+/* CLK_DIV_LEFTBUS */
+#define GPL_RATIO 0x1
+#define GDL_RATIO 0x3
+#define CLK_DIV_LEFTBUS_VAL ((GPL_RATIO << 4) \
+ | (GDL_RATIO << 0))
+
+/* CLK_SRC_RIGHTBUS */
+#define MUX_MPLL_USER_SEL_R_FINPLL 0x0
+#define MUX_MPLL_USER_SEL_R_FOUTMPLL 0x1
+#define MUX_GDR_SEL_SCLKMPLL 0x0
+#define MUX_GDR_SEL_SCLKAPLL 0x1
+#define CLK_SRC_RIGHTBUS_VAL ((MUX_MPLL_USER_SEL_R_FOUTMPLL << 4) \
+ | (MUX_GDR_SEL_SCLKMPLL << 0))
+
+/* CLK_MUX_STAT_LEFTBUS */
+#define CLK_MUX_STAT_RIGHTBUS_VAL 0x00000021
+
+/* CLK_DIV_RIGHTBUS */
+#define GPR_RATIO 0x1
+#define GDR_RATIO 0x3
+#define CLK_DIV_RIGHTBUS_VAL ((GPR_RATIO << 4) \
+ | (GDR_RATIO << 0))
+
+#define DISABLE 0
+#define ENABLE 1
+#define SET_PLL(mdiv, pdiv, sdiv) ((ENABLE << 31) \
+ | (mdiv << 16) \
+ | (pdiv << 8) \
+ | (sdiv << 0))
+
+/* APLL_CON0 */
+#ifdef ARM_CLK_800
+#define APLL_MDIV 0x64
+#define APLL_PDIV 0x03
+#define APLL_SDIV 0x00
+#elif defined ARM_CLK_1000
+#define APLL_MDIV 0x7D
+#define APLL_PDIV 0x03
+#define APLL_SDIV 0x00
+#endif
+#define APLL_CON0_VAL SET_PLL(APLL_MDIV, APLL_PDIV, APLL_SDIV)
+
+/* APLL_LOCK */
+#define APLL_LOCK_VAL (APLL_PDIV * 270)
+
+/* APLL_CON1 */
+#define APLL_DCC_ENB 0x1
+#define APLL_AFC_ENB 0x0
+#define APLL_LOCK_CON_IN 0x3
+#define APLL_LOCK_CON_DLY 0x8
+#define APLL_CON1_VAL ((APLL_DCC_ENB << 21) \
+ | (APLL_AFC_ENB << 20) \
+ | (APLL_LOCK_CON_IN << 12) \
+ | (APLL_LOCK_CON_DLY << 8))
+
+/* MPLL_CON0 */
+#define MPLL_MDIV 0x64
+#define MPLL_PDIV 0x03
+#define MPLL_SDIV 0x00
+#define MPLL_CON0_VAL SET_PLL(MPLL_MDIV, MPLL_PDIV, MPLL_SDIV)
+
+/* MPLL_LOCK */
+#define MPLL_LOCK_VAL (MPLL_PDIV * 2700)
+
+/* MPLL_CON1 */
+#define MPLL_DCC_ENB 0x1
+#define MPLL_AFC_ENB 0x0
+#define MPLL_LOCK_CON_IN 0x3
+#define MPLL_LOCK_CON_DLY 0x8
+#define MPLL_CON1_VAL ((MPLL_DCC_ENB << 21) \
+ | (MPLL_AFC_ENB << 20) \
+ | (MPLL_LOCK_CON_IN << 12) \
+ | (MPLL_LOCK_CON_DLY << 8))
+
+/* EPLL_CON0 */
+#define EPLL_MDIV 0x40
+#define EPLL_PDIV 0x02
+#define EPLL_SDIV 0x02
+#define EPLL_CON0_VAL SET_PLL(EPLL_MDIV, EPLL_PDIV, EPLL_SDIV)
+
+/* EPLL_LOCK */
+#define EPLL_LOCK_VAL (EPLL_PDIV * 3000)
+
+/* EPLL_CON1 */
+#define EPLL_SEL_PF 0x3
+#define EPLL_MRR 0x6
+#define EPLL_MFR 0x1
+#define EPLL_CON1_VAL ((EPLL_SEL_PF << 29) \
+ | (EPLL_MRR << 24) \
+ | (EPLL_MFR << 16))
+
+/* EPLL_CON2 */
+#define EPLL_DCC_ENB 0x1
+#define EPLL_AFC_ENB 0x0
+#define EPLL_FVCO_EN 0x1
+#define EPLL_LOCK_CON_IN 0x3
+#define EPLL_LOCK_OUT_DLY 0x8
+#define EPLL_CON2_VAL (EPLL_DCC_ENB << 7)
+
+/* VPLL_CON0 */
+#define VPLL_MDIV 0xAF
+#define VPLL_PDIV 0x03
+#define VPLL_SDIV 0x02
+#define VPLL_CON0_VAL SET_PLL(VPLL_MDIV, VPLL_PDIV, VPLL_SDIV)
+
+/* VPLL_LOCK */
+#define VPLL_LOCK_VAL (VPLL_PDIV * 3000)
+
+/* VPLL_CON1 */
+#define VPLL_SEL_PF 0x3
+#define VPLL_MRR 0x6
+#define VPLL_MFR 0x1
+#define VPLL_CON1_VAL ((VPLL_SEL_PF << 29) \
+ | (VPLL_MRR << 24) \
+ | (VPLL_MFR << 16))
+
+/* VPLL_CON2 */
+#define VPLL_DCC_ENB 0x1
+#define VPLL_AFC_ENB 0x0
+#define VPLL_FVCO_EN 0x1
+#define VPLL_LOCK_CON_IN 0x3
+#define VPLL_LOCK_OUT_DLY 0x8
+#define VPLL_CON2_VAL (VPLL_DCC_ENB << 7)
+
+/* CLK_SRC_PERIL0 */
+#define UART4_SEL_SCLKMPLL_USER_T 6
+#define UART3_SEL_SCLKMPLL_USER_T 6
+#define UART2_SEL_SCLKMPLL_USER_T 6
+#define UART1_SEL_SCLKMPLL_USER_T 6
+#define UART0_SEL_SCLKMPLL_USER_T 6
+#define CLK_SRC_PERIL0_VAL ((UART4_SEL_SCLKMPLL_USER_T << 16) \
+ | (UART3_SEL_SCLKMPLL_USER_T << 12) \
+ | (UART2_SEL_SCLKMPLL_USER_T << 8) \
+ | (UART1_SEL_SCLKMPLL_USER_T << 4) \
+ | (UART0_SEL_SCLKMPLL_USER_T << 0))
+
+/* CLK_DIV_PERIL0 */
+#define UART4_RATIO 7
+#define UART3_RATIO 7
+#define UART2_RATIO 7
+#define UART1_RATIO 7
+#define UART0_RATIO 7
+#define CLK_DIV_PERIL0_VAL ((UART4_RATIO << 16) \
+ | (UART3_RATIO << 12) \
+ | (UART2_RATIO << 8) \
+ | (UART1_RATIO << 4) \
+ | (UART0_RATIO << 0))
+
+/* CLK_SRC_FSYS */
+#define MMC4_SEL 6
+#define MMC2_SEL 6
+#define CLK_SRC_FSYS_VAL ((MMC4_SEL << 16) \
+ | (MMC2_SEL << 8))
+
+/* CLK_DIV_FSYS2 */
+#define MMC2_RATIO 0x7
+#define MMC2_PRE_RATIO 0x4
+#define CLK_DIV_FSYS2_VAL ((MMC2_PRE_RATIO << 8) \
+ | (MMC2_RATIO << 0))
+
+/* CLK_DIV_FSYS3 */
+#define MMC4_RATIO 0x7
+#define MMC4_PRE_RATIO 0x4
+#define CLK_DIV_FSYS3_VAL ((MMC4_PRE_RATIO << 8) \
+ | (MMC4_RATIO << 0))
+
+/* DMC */
+#define DIRECT_CMD_NOP 0x07000000
+#define DIRECT_CMD_ZQ 0x0a000000
+#define DIRECT_CMD_CHIP1_SHIFT (1 << 20)
+#define MEM_TIMINGS_MSR_COUNT 4
+#define CTRL_START (1 << 0)
+#define CTRL_DLL_ON (1 << 1)
+#define AREF_EN (1 << 5)
+#define DRV_TYPE (1 << 6)
+
+struct mem_timings {
+ unsigned direct_cmd_msr[MEM_TIMINGS_MSR_COUNT];
+ unsigned timingref;
+ unsigned timingrow;
+ unsigned timingdata;
+ unsigned timingpower;
+ unsigned zqcontrol;
+ unsigned control0;
+ unsigned control1;
+ unsigned control2;
+ unsigned concontrol;
+ unsigned prechconfig;
+ unsigned memcontrol;
+ unsigned memconfig0;
+ unsigned memconfig1;
+ unsigned dll_resync;
+ unsigned dll_on;
+};
+
+/* MIU */
+/* MIU Config Register Offsets*/
+#define APB_SFR_INTERLEAVE_CONF_OFFSET 0x400
+#define APB_SFR_ARBRITATION_CONF_OFFSET 0xC00
+
+/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */
+#define APB_SFR_INTERLEAVE_CONF_VAL 0x20001507
+#define APB_SFR_ARBRITATION_CONF_VAL 0x00000001
+
+#define FORCE_DLL_RESYNC 3
+#define DLL_CONTROL_ON 1
+
+#define DIRECT_CMD1 0x00020000
+#define DIRECT_CMD2 0x00030000
+#define DIRECT_CMD3 0x00010002
+#define DIRECT_CMD4 0x00000328
+
+#define CTRL_ZQ_MODE_NOTERM (0x1 << 0)
+#define CTRL_ZQ_START (0x1 << 1)
+#define CTRL_ZQ_DIV (0 << 4)
+#ifdef CONFIG_X4412
+#define CTRL_ZQ_MODE_DDS (0x5 << 8)
+#define CTRL_ZQ_MODE_TERM (0x2 << 11)
+#define CTRL_ZQ_FORCE_IMPN (0x5 << 14)
+#define CTRL_ZQ_FORCE_IMPP (0x2 << 17)
+#endif
+#ifdef CONFIG_ITOP4412
+#define CTRL_ZQ_MODE_DDS (0x7 << 8)
+#define CTRL_ZQ_MODE_TERM (0x2 << 11)
+#define CTRL_ZQ_FORCE_IMPN (0x5 << 14)
+#define CTRL_ZQ_FORCE_IMPP (0x6 << 17)
+#endif
+#define CTRL_DCC (0xE38 << 20)
+#define ZQ_CONTROL_VAL (CTRL_ZQ_MODE_NOTERM | CTRL_ZQ_START\
+ | CTRL_ZQ_DIV | CTRL_ZQ_MODE_DDS\
+ | CTRL_ZQ_MODE_TERM | CTRL_ZQ_FORCE_IMPN\
+ | CTRL_ZQ_FORCE_IMPP | CTRL_DCC)
+
+#define CLK_RATIO (1 << 1)
+#define DIV_PIPE (1 << 3)
+#define AWR_ON (1 << 4)
+#define AREF_DISABLE (0 << 5)
+#ifdef CONFIG_X4412
+#define DRV_TYPE_DISABLE (3 << 6)
+#endif
+#ifdef CONFIG_ITOP4412
+#define DRV_TYPE_DISABLE (0 << 6)
+#endif
+#define CHIP0_NOT_EMPTY (0 << 8)
+#define CHIP1_NOT_EMPTY (0 << 9)
+#define DQ_SWAP_DISABLE (0 << 10)
+#define QOS_FAST_DISABLE (0 << 11)
+#define RD_FETCH (0x3 << 12)
+#define TIMEOUT_LEVEL0 (0xFFF << 16)
+#define CONCONTROL_VAL (CLK_RATIO | DIV_PIPE | AWR_ON\
+ | AREF_DISABLE | DRV_TYPE_DISABLE\
+ | CHIP0_NOT_EMPTY | CHIP1_NOT_EMPTY\
+ | DQ_SWAP_DISABLE | QOS_FAST_DISABLE\
+ | RD_FETCH | TIMEOUT_LEVEL0)
+
+#define CLK_STOP_DISABLE (0 << 0)
+#define DPWRDN_DISABLE (0 << 1)
+#define DPWRDN_TYPE (0 << 2)
+#define TP_DISABLE (0 << 4)
+#define DSREF_DIABLE (0 << 5)
+#ifdef CONFIG_X4412
+#define ADD_LAT_PALL (0 << 6)
+#endif
+#ifdef CONFIG_ITOP4412
+#define ADD_LAT_PALL (1 << 6)
+#endif
+#define MEM_TYPE_DDR3 (0x6 << 8)
+#define MEM_WIDTH_32 (0x2 << 12)
+#define NUM_CHIP_2 (0 << 16)
+#define BL_8 (0x3 << 20)
+#define MEMCONTROL_VAL (CLK_STOP_DISABLE | DPWRDN_DISABLE\
+ | DPWRDN_TYPE | TP_DISABLE | DSREF_DIABLE\
+ | ADD_LAT_PALL | MEM_TYPE_DDR3 | MEM_WIDTH_32\
+ | NUM_CHIP_2 | BL_8)
+
+
+#define CHIP_BANK_8 (0x3 << 0)
+#ifdef CONFIG_X4412
+#define CHIP_ROW (0x2 << 4) /* 14 bits */
+#endif
+#ifdef CONFIG_ITOP4412
+#define CHIP_ROW (0x3 << 4) /* 15 bits */
+#endif
+#define CHIP_COL_10 (0x3 << 8)
+#define CHIP_MAP_INTERLEAVED (1 << 12)
+#define CHIP_MASK (0xC0 << 16)
+#define CHIP0_BASE (0x40 << 24)
+#define CHIP1_BASE (0x60 << 24)
+#define MEMCONFIG0_VAL (CHIP_BANK_8 | CHIP_ROW | CHIP_COL_10\
+ | CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP0_BASE)
+#define MEMCONFIG1_VAL (CHIP_BANK_8 | CHIP_ROW | CHIP_COL_10\
+ | CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP1_BASE)
+
+#ifdef CONFIG_X4412
+#define TP_CNT (0x64 << 24)
+#endif
+#ifdef CONFIG_ITOP4412
+#define TP_CNT (0xff << 24)
+#endif
+#define PRECHCONFIG TP_CNT
+
+#define CTRL_OFF (0 << 0)
+#define CTRL_DLL_OFF (0 << 1)
+#define CTRL_HALF (0 << 2)
+#define CTRL_DFDQS (1 << 3)
+#define DQS_DELAY (0 << 4)
+#define CTRL_START_POINT (0x10 << 8)
+#define CTRL_INC (0x10 << 16)
+#define CTRL_FORCE (0x71 << 24)
+#define CONTROL0_VAL (CTRL_OFF | CTRL_DLL_OFF | CTRL_HALF\
+ | CTRL_DFDQS | DQS_DELAY | CTRL_START_POINT\
+ | CTRL_INC | CTRL_FORCE)
+
+#define CTRL_SHIFTC (0x6 << 0)
+#define CTRL_REF (8 << 4)
+#define CTRL_SHGATE (1 << 29)
+#ifdef CONFIG_X4412
+#define TERM_READ_EN (0 << 30)
+#define TERM_WRITE_EN (0 << 31)
+#endif
+#ifdef CONFIG_ITOP4412
+#define TERM_READ_EN (1 << 30)
+#define TERM_WRITE_EN (1 << 31)
+#endif
+#define CONTROL1_VAL (CTRL_SHIFTC | CTRL_REF | CTRL_SHGATE\
+ | TERM_READ_EN | TERM_WRITE_EN)
+
+#define CONTROL2_VAL 0x00000000
+
+#ifdef CONFIG_EXYNOS4412
+#define TIMINGREF_VAL 0x000000BB
+#define TIMINGDATA_VAL 0x46400506
+#define TIMINGPOWER_VAL 0x52000A3C
+#ifdef CONFIG_X4412
+#define TIMINGROW_VAL 0x7846654f
+#endif
+#ifdef CONFIG_ITOP4412
+#define TIMINGROW_VAL 0x4046654f
+#endif
+#endif /* CONFIG_EXYNOS4412 */
+#endif
修改SoC时钟初始化相关的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
diff --git a/arch/arm/mach-exynos/clock_init_exynos4.c b/arch/arm/mach-exynos/clock_init_exynos4.c
index 584e4ba..4cb05fa 100644
--- a/arch/arm/mach-exynos/clock_init_exynos4.c
+++ b/arch/arm/mach-exynos/clock_init_exynos4.c
@@ -30,12 +30,17 @@
#include <asm/arch/clk.h>
#include <asm/arch/clock.h>
#include "common_setup.h"
+#ifdef CONFIG_EXYNOS4412
+#include "exynos4412_setup.h"
+#else
#include "exynos4_setup.h"
+#endif

/*
* system_clock_init: Initialize core clock and bus clock.
* void system_clock_init(void)
*/
+#ifndef CONFIG_EXYNOS4412
void system_clock_init(void)
{
struct exynos4_clock *clk =
@@ -92,3 +97,189 @@ void system_clock_init(void)

sdelay(0x30000);
}
+#else /* !CONFIG_EXYNOS4412 */
+static inline void wait_mux_state(unsigned int status, void *addr)
+{
+ unsigned int res = 0;
+
+ do {
+ res = readl(addr);
+ }while(status != res);
+}
+
+static inline void wait_pll_lock(void *addr)
+{
+ unsigned int res = 0;
+
+ do {
+ res = readl(addr);
+ res >>= 29;
+ }while(!(res & 0x1));
+}
+
+void system_clock_init(void)
+{
+ struct exynos4x12_clock *clk =
+ (struct exynos4x12_clock *)samsung_get_base_clock();
+
+ /*
+ * bypass PLLs and reset clock source of cpu
+ * MUX_MPLL_CTRL_USER_C: select FINPLL:0
+ * MUX_HPM: select MOUTAPLL:0
+ * MUX_CORE: select MOUTAPLL:0
+ * MUX_APLL: select FINPLL:0
+ *
+ */
+ writel(CLK_SRC_CPU_RESET, &clk->src_cpu);
+ wait_mux_state(CLK_MUX_STAT_CPU_RESET, &clk->mux_stat_cpu);
+
+ /*
+ * setup divisor of DMC clocks
+ *
+ * DIV_DMC0:
+ * DOUTDMC(SCLK_DMC) = MOUTDMC_BUS / (DMC_RATIO + 1) : DMC_RATIO:1
+ * DOUTDMCD(ACLK_DMCD) = DOUTDMC / (DMCD_RATIO + 1) : DMCD_RATIO:1
+ * DOUTDMCP(ACLK_DMCP) = DOUTDMCD/ (DMCP_RATIO + 1) : DMCP_RATIO:1
+ * DOUTACP(ACLK_ACP) = MOUTDMC_BUS / (ACP_RATIO + 1) : ACP_RATIO:3
+ * DOUTACP_PCLK(PCLK_ACP) = DOUTACP / (ACP_PCLK_RATIO + 1) : ACP_PCLK_RATIO:1
+ *
+ * For example:
+ * if MOUTDMC_BUS = 800MHz, then
+ * SCLK_DMC = 400MHz
+ * ACLK_DMCD = 200MHz
+ * ACLK_DMCP = 100MHz
+ * ACLK_ACP = 200MHz
+ * PCLK_ACP = 100MHz
+ * fi
+ */
+ writel(CLK_DIV_DMC0_VAL, &clk->div_dmc0);
+ writel(CLK_DIV_DMC1_VAL, &clk->div_dmc1);
+
+ writel(CLK_SRC_TOP0_RESET, &clk->src_top0);
+ wait_mux_state(CLK_MUX_STAT_TOP0_RESET, &clk->mux_stat_top0);
+ writel(CLK_SRC_TOP1_RESET, &clk->src_top1);
+ wait_mux_state(CLK_MUX_STAT_TOP1_RESET, &clk->mux_stat_top1);
+ writel(CLK_DIV_TOP_VAL, &clk->div_top);
+
+ writel(CLK_SRC_LEFTBUS_VAL, &clk->src_leftbus);
+ wait_mux_state(CLK_MUX_STAT_LEFTBUS_VAL, &clk->mux_stat_leftbus);
+ writel(CLK_DIV_LEFTBUS_VAL, &clk->div_leftbus);
+
+ writel(CLK_SRC_RIGHTBUS_VAL, &clk->src_rightbus);
+ wait_mux_state(CLK_MUX_STAT_RIGHTBUS_VAL, &clk->mux_stat_rightbus);
+ writel(CLK_DIV_RIGHTBUS_VAL, &clk->div_rightbus);
+
+ 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);
+
+ /*
+ * DIV_CPU0:
+ * DOUTCORE = MOUTCORE/(CORE_RATIO + 1)
+ * DOUTCORE2 = DOUTCORE/(CORE2_RATE + 1)
+ * DOUTCOREM0 = DOUTCORE2/(COREM0_RATIO + 1)
+ * DOUTCOREM1 = DOUTCORE2/(COREM1_RATIO + 1)
+ * DOUTPERIPH = DOUTCORE2/(PERIPH_RATIO + 1)
+ * SCLK_APLL = MOUTAPLL/(APLL_RATIO + 1)
+ * DOUTATB = MOUTCORE/(ATB_RATIO + 1)
+ * DOUTPCLK_DBG = DOUTATB/PCLK_DBG_RATIO + 1)
+ *
+ * ---------------------------------------
+ * MOUTAPLL 1000MHz 800MHz
+ * ---------------------------------------
+ * ARMCLK 1000 8000
+ * ACLK_COREM0 250 200
+ * ACLK_CORES 250 200
+ * ACLK_COREM1 125 100
+ * PERIPHCLK 250 200
+ * ATCLK 250 200
+ * PCLK_DBG 125 100
+ * --------------------------------------
+ */
+ writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0);
+
+ /*
+ * DIV_CPU1:
+ * DOUTCOPY = MOUTHPM/(COPY_RATIO + 1)
+ * DOUTHPM = DOUTCOPY/(HPM_RATIO + 1)
+ *
+ * -------------------------------------
+ * MOUTHPM 1000MHz 800MHz
+ * -------------------------------------
+ * DOUTCOPY 333 266
+ * SCLK_HPM 165 133
+ * -------------------------------------
+ */
+ writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1);
+
+ /*
+ * set APLL to 1000MHz or 800MHz
+ */
+ writel(APLL_CON1_VAL, &clk->apll_con1);
+ writel(APLL_CON0_VAL, &clk->apll_con0);
+
+ /*
+ * always set MPLL to 800MHZ
+ */
+ writel(MPLL_CON1_VAL, &clk->mpll_con1);
+ writel(MPLL_CON0_VAL, &clk->mpll_con0);
+
+ /*
+ * always set EPLL to 192MHz
+ */
+ writel(EPLL_CON2_VAL, &clk->epll_con2);
+ writel(EPLL_CON1_VAL, &clk->epll_con1);
+ writel(EPLL_CON0_VAL, &clk->epll_con0);
+
+ /*
+ * always set VPLL to 350MHz
+ */
+ writel(VPLL_CON2_VAL, &clk->vpll_con2);
+ writel(VPLL_CON1_VAL, &clk->vpll_con1);
+ writel(VPLL_CON0_VAL, &clk->vpll_con0);
+
+ wait_pll_lock(&clk->apll_con0);
+ wait_pll_lock(&clk->mpll_con0);
+ wait_pll_lock(&clk->epll_con0);
+ wait_pll_lock(&clk->vpll_con0);
+
+ /*
+ * select clock source for CPU_BLK
+ * MUX_MPLL_CTRL_USER_C: select SCLK_MPLL:1
+ * MUX_HPM: select MOUTAPLL:0
+ * MUX_CORE: select MOUTAPLL:0
+ * MUX_APLL: select FOUTAPLL:1
+ */
+ writel(CLK_SRC_CPU_VAL, &clk->src_cpu);
+ wait_mux_state(CLK_MUX_STAT_CPU_VAL, &clk->mux_stat_cpu);
+
+ /*
+ * select clock source for DMC_BLK
+ *
+ */
+ writel(CLK_SRC_DMC_VAL, &clk->src_dmc);
+ wait_mux_state(CLK_MUX_STAT_DMC_VAL, &clk->mux_stat_dmc);
+ writel(CLK_SRC_TOP0_VAL, &clk->src_top0);
+ wait_mux_state(CLK_MUX_STAT_TOP0_VAL, &clk->mux_stat_top0);
+ writel(CLK_SRC_TOP1_VAL, &clk->src_top1);
+ wait_mux_state(CLK_MUX_STAT_TOP1_VAL, &clk->mux_stat_top1);
+
+ /* set UART clock for early debug
+ *
+ * UART0-3 = 100MHz
+ *
+ */
+ writel(CLK_SRC_PERIL0_VAL, &clk->src_peril0);
+ writel(CLK_DIV_PERIL0_VAL, &clk->div_peril0);
+
+ /* MMC clock
+ *
+ * MMC2, MMC4 = 20MHz
+ *
+ */
+ writel(CLK_SRC_FSYS_VAL, &clk->src_fsys);
+ writel(CLK_DIV_FSYS2_VAL, &clk->div_fsys2);
+ writel(CLK_DIV_FSYS3_VAL, &clk->div_fsys3);
+}
+#endif
修改外设控制器的时钟设置代码

结构体struct exynos4x12_clock与Exynos4412 SoC的时钟寄存器才是一致的,而结构体struct exynos4_clock是不一致的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
diff --git a/arch/arm/mach-exynos/clock.c b/arch/arm/mach-exynos/clock.c
index 73aa4cd..ae455ce 100644
--- a/arch/arm/mach-exynos/clock.c
+++ b/arch/arm/mach-exynos/clock.c
@@ -782,8 +782,13 @@ static unsigned long exynos4x12_get_uart_clk(int dev_index)

static unsigned long exynos4_get_mmc_clk(int dev_index)
{
+#ifdef CONFIG_EXYNOS4412
+ struct exynos4x12_clock *clk =
+ (struct exynos4x12_clock *)samsung_get_base_clock();
+#else
struct exynos4_clock *clk =
(struct exynos4_clock *)samsung_get_base_clock();
+#endif
unsigned long uclk, sclk;
unsigned int sel, ratio, pre_ratio;
int shift = 0;
@@ -832,8 +837,13 @@ static unsigned long exynos4_get_mmc_clk(int dev_index)
/* exynos4: set the mmc clock */
static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
{
+#ifdef CONFIG_EXYNOS4412
+ struct exynos4x12_clock *clk =
+ (struct exynos4x12_clock *)samsung_get_base_clock();
+#else
struct exynos4_clock *clk =
(struct exynos4_clock *)samsung_get_base_clock();
+#endif
unsigned int addr, clear_bit, set_bit;

/*
修改内存控制器初始化相关的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
diff --git a/arch/arm/mach-exynos/dmc_init_exynos4.c b/arch/arm/mach-exynos/dmc_init_exynos4.c
index ecddc72..977e46e 100644
--- a/arch/arm/mach-exynos/dmc_init_exynos4.c
+++ b/arch/arm/mach-exynos/dmc_init_exynos4.c
@@ -26,7 +26,11 @@
#include <config.h>
#include <asm/arch/dmc.h>
#include "common_setup.h"
+#ifdef CONFIG_EXYNOS4412
+#include "exynos4412_setup.h"
+#else
#include "exynos4_setup.h"
+#endif

struct mem_timings mem = {
.direct_cmd_msr = {
@@ -92,7 +96,11 @@ static void dmc_init(struct exynos4_dmc *dmc)
* Auto Calibration Start: Enable
*/
writel(mem.zqcontrol, &dmc->phyzqcontrol);
+#ifdef CONFIG_EXYNOS4412
+ sdelay(0x100);
+#else
sdelay(0x100000);
+#endif

/*
* Update DLL Information:
@@ -137,29 +145,57 @@ static void dmc_init(struct exynos4_dmc *dmc)

/* Chip0: NOP Command: Assert and Hold CKE to high level */
writel(DIRECT_CMD_NOP, &dmc->directcmd);
+#ifdef CONFIG_EXYNOS4412
+ sdelay(0x20000);
+#else
sdelay(0x100000);
+#endif

/* Chip0: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */
dmc_config_mrs(dmc, 0);
+#ifdef CONFIG_EXYNOS4412
+ sdelay(0x200);
+#else
sdelay(0x100000);
+#endif

/* Chip0: ZQINIT */
writel(DIRECT_CMD_ZQ, &dmc->directcmd);
+#ifdef CONFIG_EXYNOS4412
+ sdelay(0x200);
+#else
sdelay(0x100000);
+#endif

writel((DIRECT_CMD_NOP | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd);
+#ifdef CONFIG_EXYNOS4412
+ sdelay(0x20000);
+#else
sdelay(0x100000);
+#endif

/* Chip1: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */
dmc_config_mrs(dmc, 1);
+#ifdef CONFIG_EXYNOS4412
+ sdelay(0x200);
+#else
sdelay(0x100000);
+#endif

/* Chip1: ZQINIT */
writel((DIRECT_CMD_ZQ | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd);
+#ifdef CONFIG_EXYNOS4412
+ sdelay(0x200);
+#else
sdelay(0x100000);
+#endif

phy_control_reset(1, dmc);
+#ifdef CONFIG_EXYNOS4412
+ sdelay(0x200);
+#else
sdelay(0x100000);
+#endif

/* turn on DREX0, DREX1 */
writel((mem.concontrol | AREF_EN), &dmc->concontrol);
@@ -175,7 +211,7 @@ void mem_ctrl_init(int reset)
* 0: full_sync
*/
writel(1, ASYNC_CONFIG);
-#ifdef CONFIG_ORIGEN
+#if defined (CONFIG_ORIGEN) || defined (CONFIG_EXYNOS4412)
/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */
writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE +
APB_SFR_INTERLEAVE_CONF_OFFSET);

编译烧写与调试验证

至此,整个移植过程涉及的代码及配置文件已经全部给出了,你只要将上面patch应用到自己的源代码上或者是使用git clone https://github.com/chasinglulu/u-boot.git拷贝我已经移植好代码,就完成了基本的移植过程。下面通过验证调试来检验我们在移植过程中有没有出错或者出现其他异常,通过调试并发现解决问题才是我们升级打怪(bug)和提升能力的最佳时刻。

编译烧写

编译命令如下:

1
2
make O=../build/ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- itop4412_defconfig
make O=../build/ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4

烧写脚本fusing-sd.sh的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#! /bin/bash

CUR_DIR=$(cd $(dirname "$0"); pwd)
IMAGE_DIR=""
DEVICE=""

# images name
BL1_FWBL_IMG="itop4412-fwbl.bin"
BL1_SPL_IMG="itop4412-spl.bin"
BL2_UBOOT_IMG="itop4412-u-boot.bin"
TZSW_IMG="itop4412-tzsw.bin"
ENV_IMG="itop4412-env.bin"

# itop4412 images position
BL1_FWBL_POS=1
BL1_SPL_POS=17
BL2_UBOOT_POS=49
TZSW_POS=1073
ENV_POS=1385

function usage()
{
echo "Usage:"
echo " $(basename $0) [/dev/sdX] [image-dir]"
echo " /dev/sdX device file for sd card"
echo " image-dir image direction, optional"
}

function bl1_fwbl_fusing()
{
echo "BL1_FWBL fusing ..."
dd iflag=dsync oflag=dsync if=$IMAGE_DIR/$BL1_FWBL_IMG of=$DEVICE seek=$BL1_FWBL_POS
echo "Finish fusing BL1_FWBL image."
}

function bl1_spl_fusing()
{
echo "BL1_SPL fusing ..."
dd iflag=dsync oflag=dsync if=$IMAGE_DIR/$BL1_SPL_IMG of=$DEVICE seek=$BL1_SPL_POS
echo "Finish fusing BL1_SPL image."
}

function bl2_uboot_fusing()
{
echo "BL2_UBOOT fusing ..."
dd iflag=dsync oflag=dsync if=$IMAGE_DIR/$BL2_UBOOT_IMG of=$DEVICE seek=$BL2_UBOOT_POS
echo "Finish fusing BL2_UBOOT image."
}

function tzsw_fusing()
{
echo "TZSW fusing ..."
dd iflag=dsync oflag=dsync if=$IMAGE_DIR/$TZSW_IMG of=$DEVICE seek=$TZSW_POS
echo "Finish fusing TZSW image."
}

function env_fusing()
{
echo "ENV fusing ..."
dd iflag=dsync oflag=dsync if=$IMAGE_DIR/$ENV_IMG of=$DEVICE seek=$ENV_POS
echo "Finish fusing ENV image."
}

function main()
{
echo "--------------------------[Begin]--------------------------"
echo "May take a few minutes, wait ..."
bl1_fwbl_fusing
bl1_spl_fusing
bl2_uboot_fusing
tzsw_fusing
env_fusing
echo "--------------------------[End]----------------------------"
}

while getopts :h opt
do
case $opt in
h)
usage $0
exit 0
;;
?)
echo "unknown option"
;;
esac
done

if [ $# -le 0 ] || [ $# -ge 3 ]
then
echo "arguments too few or many."
usage $0
exit 1
else
DEVICE="$1"
if [ $# -eq 2 ]
then
IMAGE_DIR="$2"
else
IMAGE_DIR="$CUR_DIR"
fi
fi

if [ -b "$DEVICE" ]
then
echo "$DEVICE is identified."
else
echo "$DEVICE is NOT device file."
dd if=/dev/zero of=$DEVICE bs=512 count=2048
BL1_FWBL_POS=0
BL1_SPL_POS=16
BL2_UBOOT_POS=48
TZSW_POS=1072
ENV_POS=1384
fi

main

sync;sync;sync

烧写命令如下:

1
2
3
sh fusing-sd.sh /dev/sdX
or
sh fusing-sd.sh /dev/sdX ~/exynos4412/images/

/dev/sdX指的是SD卡在Ubuntu 18.04系统内的设备描述符,具体的说,用sda、sdb、sdc等替代sdX。

调试与验证

总结