Fork me on GitHub

基于iTop-4412的U-Boot 2017移植[1]:成功运行

基于iTop-4412的U-Boot 2017移植[1]:成功运行

参考资料:

获取U-Boot

本博客使用的版本是 U-Boot 2017.05-rc1

1
$ git clone git://git.denx.de/u-boot.git

开始移植

本博客参考一款类似与iTOP-4412的开发板(采用相同的SoC):origen 进行移植。

(一) 创建iTOP-4412板级目录

1
2
3
cp board/samsung/origen board/samsung/itop4412 –raf
mv board/samsung/itop4412/origen.c board/samsung/itop4412/itop4412.c
mv board/samsung/itop4412/tools/mkorigenspl.c board/samsung/itop4412/tools/mkitop4412spl.c

(二) 增加文件

1
2
3
4
5
cp include/configs/origen.h include/configs/itop4412.h
cp configs/origen_defconfig configs/itop4412_defconfig
cp arch/arm/dts/exynos4412-odroid.dts arch/arm/dts/exynos4412-itop4412.dts
touch arch/arm/mach-exynos/itop4412_setup.h
touch arch/arm/mach-exynos/board.c

其中board.c将对iTOP-4412的电源管理初始化,不会导致复位。

(三) 修改文件

1、修改arch/arm/dts/Makefile,用于编译设备树:

1
2
3
4
5
6
7
8
9
10
11
12
13
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index bc4dc2c..3be2f3a 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -14,7 +14,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

2、修改arch/arm/include/asm/mach-types.h,增加iTOP-4412的machine 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 9f82efe..e19b24b 100644
--- a/arch/arm/include/asm/mach-types.h
+++ b/arch/arm/include/asm/mach-types.h
@@ -5057,4 +5057,5 @@
#define MACH_TYPE_NASM25 5112
#define MACH_TYPE_TOMATO 5113
#define MACH_TYPE_OMAP3_MRC3D 5114
+#define MACH_TYPE_ITOP4412 5115
#endif

3、修改arch/arm/mach-exynos/Kconfig

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/Kconfig b/arch/arm/mach-exynos/Kconfig
index 46981a5..9078fc5 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -53,6 +53,10 @@ config TARGET_ORIGEN
bool "Exynos4412 Origen board"
select SUPPORT_SPL
+config TARGET_ITOP4412
+ bool "Exynos4412 iTop-4412 board"
+ select SUPPORT_SPL
+
config TARGET_TRATS2
bool "Exynos4412 Trat2 board"
@@ -149,6 +153,7 @@ source "board/samsung/smdkv310/Kconfig"
source "board/samsung/trats/Kconfig"
source "board/samsung/universal_c210/Kconfig"
source "board/samsung/origen/Kconfig"
+source "board/samsung/itop4412/Kconfig"
source "board/samsung/trats2/Kconfig"
source "board/samsung/odroid/Kconfig"
source "board/samsung/arndale/Kconfig"

4、修改 board/samsung/itop4412/Kconfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
diff --git a/board/samsung/itop4412/Kconfig b/board/samsung/itop4412/Kconfig
new file mode 100644
index 0000000..8dfef9a
--- /dev/null
+++ b/board/samsung/itop4412/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_ITOP4412
+
+config SYS_BOARD
+ default "itop4412"
+
+config SYS_VENDOR
+ default "samsung"
+
+config SYS_CONFIG_NAME
+ default "itop4412"
+
+endif

5、修改board/samsung/itop4412/Makefile

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
diff --git a/board/samsung/itop4412/Makefile b/board/samsung/itop4412/Makefile
new file mode 100644
index 0000000..9697620
--- /dev/null
+++ b/board/samsung/itop4412/Makefile
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2011 Samsung Electronics
+#
+# 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/mkorigenspl.c and delete the following work-around
+$(obj)/tools/mkitop4412spl: HOSTCFLAGS:=$(filter-out -O2,$(HOSTCFLAGS))
+else
+obj-y += itop4412.o
+endif

6、修改arch/arm/dts/exynos4412-itop4412.dts,使用uart3(板子上的CON2)作为终端:

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
+/*
+ * Topeet iTop-4412 board device tree source
+ *
+ * Copyright (c) 2017 Ziping Chen
+ * <techping.chan@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+#include "exynos4412.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "TOPEET iTop 4412 Elite board";
+ compatible = "topeet,itop4412-elite", "samsung,exynos4412", "samsung,exynos4";
+
+ chosen {
+ stdout-path = "serial3:115200n8";
+ };
+
+ aliases {
+ serial3 = "/serial@13830000";
+ console = "/serial@13830000";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led2 {
+ label = "red:system";
+ gpios = <&gpl2 0 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ linux,default-trigger = "heartbeat";
+ };
+
+ led3 {
+ label = "red:user";
+ gpios = <&gpk1 1 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ home {
+ label = "GPIO Key Home";
+ linux,code = <KEY_HOME>;
+ gpios = <&gpx1 1 GPIO_ACTIVE_LOW>;
+ };
+
+ back {
+ label = "GPIO Key Back";
+ linux,code = <KEY_BACK>;
+ gpios = <&gpx1 2 GPIO_ACTIVE_LOW>;
+ };
+
+ sleep {
+ label = "GPIO Key Sleep";
+ linux,code = <KEY_POWER>;
+ gpios = <&gpx3 3 GPIO_ACTIVE_LOW>;
+ };
+
+ vol-up {
+ label = "GPIO Key Vol+";
+ linux,code = <KEY_UP>;
+ gpios = <&gpx2 1 GPIO_ACTIVE_LOW>;
+ };
+
+ vol-down {
+ label = "GPIO Key Vol-";
+ linux,code = <KEY_DOWN>;
+ gpios = <&gpx2 0 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ serial3:serial@13830000 {
+ status = "okay";
+ };
+};

7、修改 arch/arm/mach-exynos/Makefile

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/Makefile b/arch/arm/mach-exynos/Makefile
index 0cc6c32..d6e87bc 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -5,6 +5,7 @@
# SPDX-License-Identifier: GPL-2.0+
#
+obj-y += board.o
obj-y += soc.o
obj-$(CONFIG_CPU_V7) += clock.o pinmux.o power.o system.o
obj-$(CONFIG_ARM64) += mmu-arm64.o
@@ -14,7 +15,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_TARGET_ITOP4412)))
+obj-y += dmc_init_exynos4.o clock_init_exynos4.o
+endif
obj-y += spl_boot.o tzpc.o
obj-y += lowlevel_init.o
endif

8、修改 arch/arm/mach-exynos/clock_init_exynos4.c,时钟初始化

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
--- a/arch/arm/mach-exynos/clock_init_exynos4.c
+++ b/arch/arm/mach-exynos/clock_init_exynos4.c
@@ -27,15 +27,21 @@
#include <config.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
+#include <asm/arch/dmc.h>
#include <asm/arch/clk.h>
#include <asm/arch/clock.h>
#include "common_setup.h"
+#ifdef CONFIG_TARGET_ITOP4412
+#include "itop4412_setup.h"
+#else
#include "exynos4_setup.h"
+#endif
/*
* system_clock_init: Initialize core clock and bus clock.
* void system_clock_init(void)
*/
+#ifndef CONFIG_TARGET_ITOP4412
void system_clock_init(void)
{
struct exynos4_clock *clk =
@@ -92,3 +98,374 @@ void system_clock_init(void)
sdelay(0x30000);
}
+#else
+void system_clock_init(void)
+{
+ unsigned int set, clr, clr_src_cpu, clr_pll_con0, clr_src_dmc;
+ struct exynos4x12_clock *clk = (struct exynos4x12_clock *)
+ samsung_get_base_clock();
+
+ /*
+ * CMU_CPU clocks src to MPLL
+ * Bit values: 0 ; 1
+ * MUX_APLL_SEL: FIN_PLL ; FOUT_APLL
+ * MUX_CORE_SEL: MOUT_APLL ; SCLK_MPLL
+ * MUX_HPM_SEL: MOUT_APLL ; SCLK_MPLL_USER_C
+ * MUX_MPLL_USER_SEL_C: FIN_PLL ; SCLK_MPLL
+ */
+ clr_src_cpu = MUX_APLL_SEL(1) | MUX_CORE_SEL(1) |
+ MUX_HPM_SEL(1) | MUX_MPLL_USER_SEL_C(1);
+ set = MUX_APLL_SEL(0) | MUX_CORE_SEL(1) | MUX_HPM_SEL(1) |
+ MUX_MPLL_USER_SEL_C(1);
+
+ clrsetbits_le32(&clk->src_cpu, clr_src_cpu, set);
+
+ /* Wait for mux change */
+ while (readl(&clk->mux_stat_cpu) & MUX_STAT_CPU_CHANGING)
+ continue;
+
+ /* Set APLL to 1400MHz */
+ clr_pll_con0 = SDIV(7) | PDIV(63) | MDIV(1023) | FSEL(1);
+ set = SDIV(0x0) | PDIV(0x3) | MDIV(0xAF) | FSEL(1);
+
+ clrsetbits_le32(&clk->apll_con0, clr_pll_con0, set);
+
+ /* Wait for PLL to be locked */
+ while (!(readl(&clk->apll_con0) & PLL_LOCKED_BIT))
+ continue;
+
+ /* Set CMU_CPU clocks src to APLL */
+ set = MUX_APLL_SEL(1) | MUX_CORE_SEL(0) | MUX_HPM_SEL(0) |
+ MUX_MPLL_USER_SEL_C(1);
+ clrsetbits_le32(&clk->src_cpu, clr_src_cpu, set);
+
+ /* Wait for mux change */
+ while (readl(&clk->mux_stat_cpu) & MUX_STAT_CPU_CHANGING)
+ continue;
+
+ set = CORE_RATIO(0) | COREM0_RATIO(2) | COREM1_RATIO(5) |
+ PERIPH_RATIO(0) | ATB_RATIO(4) | PCLK_DBG_RATIO(1) |
+ APLL_RATIO(0) | CORE2_RATIO(0);
+ /*
+ * Set dividers for MOUTcore = 1400 MHz
+ * coreout = MOUT / (ratio 1) = 1400 MHz (0)
+ * corem0 = armclk / (ratio 1) = 466 MHz (2)
+ * corem1 = armclk / (ratio 1) = 233 MHz (5)
+ * periph = armclk / (ratio 1) = 1400 MHz (0)
+ * atbout = MOUT / (ratio 1) = 280 MHz (4)
+ * pclkdbgout = atbout / (ratio 1) = 140 MHz (1)
+ * sclkapll = MOUTapll / (ratio 1) = 1400 MHz (0)
+ * core2out = core_out / (ratio 1) = 1400 MHz (0) (armclk)
+ */
+ clr = CORE_RATIO(7) | COREM0_RATIO(7) | COREM1_RATIO(7) |
+ PERIPH_RATIO(7) | ATB_RATIO(7) | PCLK_DBG_RATIO(7) |
+ APLL_RATIO(7) | CORE2_RATIO(7);
+
+ clrsetbits_le32(&clk->div_cpu0, clr, set);
+
+ /* Wait for divider ready status */
+ while (readl(&clk->div_stat_cpu0) & DIV_STAT_CPU0_CHANGING)
+ continue;
+
+ /*
+ * For MOUThpm = 1400 MHz (MOUTapll)
+ * doutcopy = MOUThpm / (ratio 1) = 280 (4)
+ * sclkhpm = doutcopy / (ratio 1) = 280 (4)
+ * cores_out = armclk / (ratio 1) = 280 (4)
+ */
+ clr = COPY_RATIO(7) | HPM_RATIO(7) | CORES_RATIO(7);
+ set = COPY_RATIO(4) | HPM_RATIO(4) | CORES_RATIO(4);
+
+ clrsetbits_le32(&clk->div_cpu1, clr, set);
+
+ /* Wait for divider ready status */
+ while (readl(&clk->div_stat_cpu1) & DIV_STAT_CPU1_CHANGING)
+ continue;
+
+ /*
+ * Set CMU_DMC clocks src to APLL
+ * Bit values: 0 ; 1
+ * MUX_C2C_SEL: SCLKMPLL ; SCLKAPLL
+ * MUX_DMC_BUS_SEL: SCLKMPLL ; SCLKAPLL
+ * MUX_DPHY_SEL: SCLKMPLL ; SCLKAPLL
+ * MUX_MPLL_SEL: FINPLL ; MOUT_MPLL_FOUT
+ * MUX_PWI_SEL: 0110 (MPLL); 0111 (EPLL); 1000 (VPLL); 0(XXTI)
+ * MUX_G2D_ACP0_SEL: SCLKMPLL ; SCLKAPLL
+ * MUX_G2D_ACP1_SEL: SCLKEPLL ; SCLKVPLL
+ * MUX_G2D_ACP_SEL: OUT_ACP0 ; OUT_ACP1
+ */
+ clr_src_dmc = MUX_C2C_SEL(1) | MUX_DMC_BUS_SEL(1) |
+ MUX_DPHY_SEL(1) | MUX_MPLL_SEL(1) |
+ MUX_PWI_SEL(15) | MUX_G2D_ACP0_SEL(1) |
+ MUX_G2D_ACP1_SEL(1) | MUX_G2D_ACP_SEL(1);
+ set = MUX_C2C_SEL(1) | MUX_DMC_BUS_SEL(1) | MUX_DPHY_SEL(1) |
+ MUX_MPLL_SEL(0) | MUX_PWI_SEL(0) | MUX_G2D_ACP0_SEL(1) |
+ MUX_G2D_ACP1_SEL(1) | MUX_G2D_ACP_SEL(1);
+
+ clrsetbits_le32(&clk->src_dmc, clr_src_dmc, set);
+
+ /* Wait for mux change */
+ while (readl(&clk->mux_stat_dmc) & MUX_STAT_DMC_CHANGING)
+ continue;
+
+ /* Set MPLL to 800MHz */
+ set = SDIV(0) | PDIV(3) | MDIV(100) | FSEL(0) | PLL_ENABLE(1);
+
+ clrsetbits_le32(&clk->mpll_con0, clr_pll_con0, set);
+
+ /* Wait for PLL to be locked */
+ while (!(readl(&clk->mpll_con0) & PLL_LOCKED_BIT))
+ continue;
+
+ /* Switch back CMU_DMC mux */
+ set = MUX_C2C_SEL(0) | MUX_DMC_BUS_SEL(0) | MUX_DPHY_SEL(0) |
+ MUX_MPLL_SEL(1) | MUX_PWI_SEL(6) | MUX_G2D_ACP0_SEL(0) |
+ MUX_G2D_ACP1_SEL(0) | MUX_G2D_ACP_SEL(0);
+
+ clrsetbits_le32(&clk->src_dmc, clr_src_dmc, set);
+
+ /* Wait for mux change */
+ while (readl(&clk->mux_stat_dmc) & MUX_STAT_DMC_CHANGING)
+ continue;
+
+ /* CLK_DIV_DMC0 */
+ clr = ACP_RATIO(7) | ACP_PCLK_RATIO(7) | DPHY_RATIO(7) |
+ DMC_RATIO(7) | DMCD_RATIO(7) | DMCP_RATIO(7);
+ /*
+ * For:
+ * MOUTdmc = 800 MHz
+ * MOUTdphy = 800 MHz
+ *
+ * aclk_acp = MOUTdmc / (ratio 1) = 200 (3)
+ * pclk_acp = aclk_acp / (ratio 1) = 100 (1)
+ * sclk_dphy = MOUTdphy / (ratio 1) = 400 (1)
+ * sclk_dmc = MOUTdmc / (ratio 1) = 400 (1)
+ * aclk_dmcd = sclk_dmc / (ratio 1) = 200 (1)
+ * aclk_dmcp = aclk_dmcd / (ratio 1) = 100 (1)
+ */
+ set = ACP_RATIO(3) | ACP_PCLK_RATIO(1) | DPHY_RATIO(1) |
+ DMC_RATIO(1) | DMCD_RATIO(1) | DMCP_RATIO(1);
+
+ clrsetbits_le32(&clk->div_dmc0, clr, set);
+
+ /* Wait for divider ready status */
+ while (readl(&clk->div_stat_dmc0) & DIV_STAT_DMC0_CHANGING)
+ continue;
+
+ /* CLK_DIV_DMC1 */
+ clr = G2D_ACP_RATIO(15) | C2C_RATIO(7) | PWI_RATIO(15) |
+ C2C_ACLK_RATIO(7) | DVSEM_RATIO(127) | DPM_RATIO(127);
+ /*
+ * For:
+ * MOUTg2d = 800 MHz
+ * MOUTc2c = 800 Mhz
+ * MOUTpwi = 800 MHz
+ *
+ * sclk_g2d_acp = MOUTg2d / (ratio 1) = 200 (3)
+ * sclk_c2c = MOUTc2c / (ratio 1) = 400 (1)
+ * aclk_c2c = sclk_c2c / (ratio 1) = 200 (1)
+ * sclk_pwi = MOUTpwi / (ratio 1) = 100 (7)
+ */
+ set = G2D_ACP_RATIO(3) | C2C_RATIO(1) | PWI_RATIO(7) |
+ C2C_ACLK_RATIO(1) | DVSEM_RATIO(1) | DPM_RATIO(1);
+
+ clrsetbits_le32(&clk->div_dmc1, clr, set);
+
+ /* Wait for divider ready status */
+ while (readl(&clk->div_stat_dmc1) & DIV_STAT_DMC1_CHANGING)
+ continue;
+
+ /* CLK_SRC_PERIL0 */
+ clr = UART0_SEL(15) | UART1_SEL(15) | UART2_SEL(15) |
+ UART3_SEL(15) | UART4_SEL(15);
+ /*
+ * Set CLK_SRC_PERIL0 clocks src to MPLL
+ * src values: 0(XXTI); 1(XusbXTI); 2(SCLK_HDMI24M); 3(SCLK_USBPHY0);
+ * 5(SCLK_HDMIPHY); 6(SCLK_MPLL_USER_T); 7(SCLK_EPLL);
+ * 8(SCLK_VPLL)
+ *
+ * Set all to SCLK_MPLL_USER_T
+ */
+ set = UART0_SEL(6) | UART1_SEL(6) | UART2_SEL(6) | UART3_SEL(6) |
+ UART4_SEL(6);
+
+ clrsetbits_le32(&clk->src_peril0, clr, set);
+
+ /* CLK_DIV_PERIL0 */
+ clr = UART0_RATIO(15) | UART1_RATIO(15) | UART2_RATIO(15) |
+ UART3_RATIO(15) | UART4_RATIO(15);
+ /*
+ * For MOUTuart0-4: 800MHz
+ *
+ * SCLK_UARTx = MOUTuartX / (ratio 1) = 100 (7)
+ */
+ set = UART0_RATIO(7) | UART1_RATIO(7) | UART2_RATIO(7) |
+ UART3_RATIO(7) | UART4_RATIO(7);
+
+ clrsetbits_le32(&clk->div_peril0, clr, set);
+
+ while (readl(&clk->div_stat_peril0) & DIV_STAT_PERIL0_CHANGING)
+ continue;
+
+ /* CLK_DIV_FSYS1 */
+ clr = MMC0_RATIO(15) | MMC0_PRE_RATIO(255) | MMC1_RATIO(15) |
+ MMC1_PRE_RATIO(255);
+ /*
+ * For MOUTmmc0-3 = 800 MHz (MPLL)
+ *
+ * DOUTmmc1 = MOUTmmc1 / (ratio 1) = 100 (7)
+ * sclk_mmc1 = DOUTmmc1 / (ratio 1) = 50 (1)
+ * DOUTmmc0 = MOUTmmc0 / (ratio 1) = 100 (7)
+ * sclk_mmc0 = DOUTmmc0 / (ratio 1) = 50 (1)
+ */
+ set = MMC0_RATIO(7) | MMC0_PRE_RATIO(1) | MMC1_RATIO(7) |
+ MMC1_PRE_RATIO(1);
+
+ clrsetbits_le32(&clk->div_fsys1, clr, set);
+
+ /* Wait for divider ready status */
+ while (readl(&clk->div_stat_fsys1) & DIV_STAT_FSYS1_CHANGING)
+ continue;
+
+ /* CLK_DIV_FSYS2 */
+ clr = MMC2_RATIO(15) | MMC2_PRE_RATIO(255) | MMC3_RATIO(15) |
+ MMC3_PRE_RATIO(255);
+ /*
+ * For MOUTmmc0-3 = 800 MHz (MPLL)
+ *
+ * DOUTmmc3 = MOUTmmc3 / (ratio 1) = 100 (7)
+ * sclk_mmc3 = DOUTmmc3 / (ratio 1) = 50 (1)
+ * DOUTmmc2 = MOUTmmc2 / (ratio 1) = 100 (7)
+ * sclk_mmc2 = DOUTmmc2 / (ratio 1) = 50 (1)
+ */
+ set = MMC2_RATIO(7) | MMC2_PRE_RATIO(4) | MMC3_RATIO(7) |
+ MMC3_PRE_RATIO(1);
+
+ clrsetbits_le32(&clk->div_fsys2, clr, set);
+
+ /* Wait for divider ready status */
+ while (readl(&clk->div_stat_fsys2) & DIV_STAT_FSYS2_CHANGING)
+ continue;
+
+ /* CLK_DIV_FSYS3 */
+ clr = MMC4_RATIO(15) | MMC4_PRE_RATIO(255);
+ /*
+ * For MOUTmmc4 = 800 MHz (MPLL)
+ *
+ * DOUTmmc4 = MOUTmmc4 / (ratio 1) = 100 (7)
+ * sclk_mmc4 = DOUTmmc4 / (ratio 1) = 100 (0)
+ */
+ set = MMC4_RATIO(7) | MMC4_PRE_RATIO(0);
+
+ clrsetbits_le32(&clk->div_fsys3, clr, set);
+
+ /* Wait for divider ready status */
+ while (readl(&clk->div_stat_fsys3) & DIV_STAT_FSYS3_CHANGING)
+ continue;
+}
+#endif

9、编辑文件itop4412_setup.h:

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
--- /dev/null
+++ b/arch/arm/mach-exynos/itop4412_setup.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __ITOP4412_SETUP__
+#define __ITOP4412_SETUP__
+
+/* A/M PLL_CON0 */
+#define SDIV(x) ((x) & 0x7)
+#define PDIV(x) (((x) & 0x3f) << 8)
+#define MDIV(x) (((x) & 0x3ff) << 16)
+#define FSEL(x) (((x) & 0x1) << 27)
+#define PLL_LOCKED_BIT (0x1 << 29)
+#define PLL_ENABLE(x) (((x) & 0x1) << 31)
+
+/* CLK_SRC_CPU */
+#define MUX_APLL_SEL(x) ((x) & 0x1)
+#define MUX_CORE_SEL(x) (((x) & 0x1) << 16)
+#define MUX_HPM_SEL(x) (((x) & 0x1) << 20)
+#define MUX_MPLL_USER_SEL_C(x) (((x) & 0x1) << 24)
+
+#define MUX_STAT_CHANGING 0x100
+
+/* CLK_MUX_STAT_CPU */
+#define APLL_SEL(x) ((x) & 0x7)
+#define CORE_SEL(x) (((x) & 0x7) << 16)
+#define HPM_SEL(x) (((x) & 0x7) << 20)
+#define MPLL_USER_SEL_C(x) (((x) & 0x7) << 24)
+#define MUX_STAT_CPU_CHANGING (APLL_SEL(MUX_STAT_CHANGING) | \
+ CORE_SEL(MUX_STAT_CHANGING) | \
+ HPM_SEL(MUX_STAT_CHANGING) | \
+ MPLL_USER_SEL_C(MUX_STAT_CHANGING))
+
+/* CLK_DIV_CPU0 */
+#define CORE_RATIO(x) ((x) & 0x7)
+#define COREM0_RATIO(x) (((x) & 0x7) << 4)
+#define COREM1_RATIO(x) (((x) & 0x7) << 8)
+#define PERIPH_RATIO(x) (((x) & 0x7) << 12)
+#define ATB_RATIO(x) (((x) & 0x7) << 16)
+#define PCLK_DBG_RATIO(x) (((x) & 0x7) << 20)
+#define APLL_RATIO(x) (((x) & 0x7) << 24)
+#define CORE2_RATIO(x) (((x) & 0x7) << 28)
+
+/* CLK_DIV_STAT_CPU0 */
+#define DIV_CORE(x) ((x) & 0x1)
+#define DIV_COREM0(x) (((x) & 0x1) << 4)
+#define DIV_COREM1(x) (((x) & 0x1) << 8)
+#define DIV_PERIPH(x) (((x) & 0x1) << 12)
+#define DIV_ATB(x) (((x) & 0x1) << 16)
+#define DIV_PCLK_DBG(x) (((x) & 0x1) << 20)
+#define DIV_APLL(x) (((x) & 0x1) << 24)
+#define DIV_CORE2(x) (((x) & 0x1) << 28)
+
+#define DIV_STAT_CHANGING 0x1
+#define DIV_STAT_CPU0_CHANGING (DIV_CORE(DIV_STAT_CHANGING) | \
+ DIV_COREM0(DIV_STAT_CHANGING) | \
+ DIV_COREM1(DIV_STAT_CHANGING) | \
+ DIV_PERIPH(DIV_STAT_CHANGING) | \
+ DIV_ATB(DIV_STAT_CHANGING) | \
+ DIV_PCLK_DBG(DIV_STAT_CHANGING) | \
+ DIV_APLL(DIV_STAT_CHANGING) | \
+ DIV_CORE2(DIV_STAT_CHANGING))
+
+/* CLK_DIV_CPU1 */
+#define COPY_RATIO(x) ((x) & 0x7)
+#define HPM_RATIO(x) (((x) & 0x7) << 4)
+#define CORES_RATIO(x) (((x) & 0x7) << 8)
+
+/* CLK_DIV_STAT_CPU1 */
+#define DIV_COPY(x) ((x) & 0x7)
+#define DIV_HPM(x) (((x) & 0x1) << 4)
+#define DIV_CORES(x) (((x) & 0x1) << 8)
+
+#define DIV_STAT_CPU1_CHANGING (DIV_COPY(DIV_STAT_CHANGING) | \
+ DIV_HPM(DIV_STAT_CHANGING) | \
+ DIV_CORES(DIV_STAT_CHANGING))
+
+/* CLK_SRC_DMC */
+#define MUX_C2C_SEL(x) ((x) & 0x1)
+#define MUX_DMC_BUS_SEL(x) (((x) & 0x1) << 4)
+#define MUX_DPHY_SEL(x) (((x) & 0x1) << 8)
+#define MUX_MPLL_SEL(x) (((x) & 0x1) << 12)
+#define MUX_PWI_SEL(x) (((x) & 0xf) << 16)
+#define MUX_G2D_ACP0_SEL(x) (((x) & 0x1) << 20)
+#define MUX_G2D_ACP1_SEL(x) (((x) & 0x1) << 24)
+#define MUX_G2D_ACP_SEL(x) (((x) & 0x1) << 28)
+
+/* CLK_MUX_STAT_DMC */
+#define C2C_SEL(x) (((x)) & 0x7)
+#define DMC_BUS_SEL(x) (((x) & 0x7) << 4)
+#define DPHY_SEL(x) (((x) & 0x7) << 8)
+#define MPLL_SEL(x) (((x) & 0x7) << 12)
+/* #define PWI_SEL(x) (((x) & 0xf) << 16) - Reserved */
+#define G2D_ACP0_SEL(x) (((x) & 0x7) << 20)
+#define G2D_ACP1_SEL(x) (((x) & 0x7) << 24)
+#define G2D_ACP_SEL(x) (((x) & 0x7) << 28)
+
+#define MUX_STAT_DMC_CHANGING (C2C_SEL(MUX_STAT_CHANGING) | \
+ DMC_BUS_SEL(MUX_STAT_CHANGING) | \
+ DPHY_SEL(MUX_STAT_CHANGING) | \
+ MPLL_SEL(MUX_STAT_CHANGING) |\
+ G2D_ACP0_SEL(MUX_STAT_CHANGING) | \
+ G2D_ACP1_SEL(MUX_STAT_CHANGING) | \
+ G2D_ACP_SEL(MUX_STAT_CHANGING))
+
+/* CLK_DIV_DMC0 */
+#define ACP_RATIO(x) ((x) & 0x7)
+#define ACP_PCLK_RATIO(x) (((x) & 0x7) << 4)
+#define DPHY_RATIO(x) (((x) & 0x7) << 8)
+#define DMC_RATIO(x) (((x) & 0x7) << 12)
+#define DMCD_RATIO(x) (((x) & 0x7) << 16)
+#define DMCP_RATIO(x) (((x) & 0x7) << 20)
+
+/* CLK_DIV_STAT_DMC0 */
+#define DIV_ACP(x) ((x) & 0x1)
+#define DIV_ACP_PCLK(x) (((x) & 0x1) << 4)
+#define DIV_DPHY(x) (((x) & 0x1) << 8)
+#define DIV_DMC(x) (((x) & 0x1) << 12)
+#define DIV_DMCD(x) (((x) & 0x1) << 16)
+#define DIV_DMCP(x) (((x) & 0x1) << 20)
+
+#define DIV_STAT_DMC0_CHANGING (DIV_ACP(DIV_STAT_CHANGING) | \
+ DIV_ACP_PCLK(DIV_STAT_CHANGING) | \
+ DIV_DPHY(DIV_STAT_CHANGING) | \
+ DIV_DMC(DIV_STAT_CHANGING) | \
+ DIV_DMCD(DIV_STAT_CHANGING) | \
+ DIV_DMCP(DIV_STAT_CHANGING))
+
+/* CLK_DIV_DMC1 */
+#define G2D_ACP_RATIO(x) ((x) & 0xf)
+#define C2C_RATIO(x) (((x) & 0x7) << 4)
+#define PWI_RATIO(x) (((x) & 0xf) << 8)
+#define C2C_ACLK_RATIO(x) (((x) & 0x7) << 12)
+#define DVSEM_RATIO(x) (((x) & 0x7f) << 16)
+#define DPM_RATIO(x) (((x) & 0x7f) << 24)
+
+/* CLK_DIV_STAT_DMC1 */
+#define DIV_G2D_ACP(x) ((x) & 0x1)
+#define DIV_C2C(x) (((x) & 0x1) << 4)
+#define DIV_PWI(x) (((x) & 0x1) << 8)
+#define DIV_C2C_ACLK(x) (((x) & 0x1) << 12)
+#define DIV_DVSEM(x) (((x) & 0x1) << 16)
+#define DIV_DPM(x) (((x) & 0x1) << 24)
+
+#define DIV_STAT_DMC1_CHANGING (DIV_G2D_ACP(DIV_STAT_CHANGING) | \
+ DIV_C2C(DIV_STAT_CHANGING) | \
+ DIV_PWI(DIV_STAT_CHANGING) | \
+ DIV_C2C_ACLK(DIV_STAT_CHANGING) | \
+ DIV_DVSEM(DIV_STAT_CHANGING) | \
+ DIV_DPM(DIV_STAT_CHANGING))
+
+/* Set CLK_SRC_PERIL0 */
+#define UART4_SEL(x) (((x) & 0xf) << 16)
+#define UART3_SEL(x) (((x) & 0xf) << 12)
+#define UART2_SEL(x) (((x) & 0xf) << 8)
+#define UART1_SEL(x) (((x) & 0xf) << 4)
+#define UART0_SEL(x) ((x) & 0xf)
+
+/* Set CLK_DIV_PERIL0 */
+#define UART4_RATIO(x) (((x) & 0xf) << 16)
+#define UART3_RATIO(x) (((x) & 0xf) << 12)
+#define UART2_RATIO(x) (((x) & 0xf) << 8)
+#define UART1_RATIO(x) (((x) & 0xf) << 4)
+#define UART0_RATIO(x) ((x) & 0xf)
+
+/* Set CLK_DIV_STAT_PERIL0 */
+#define DIV_UART4(x) (((x) & 0x1) << 16)
+#define DIV_UART3(x) (((x) & 0x1) << 12)
+#define DIV_UART2(x) (((x) & 0x1) << 8)
+#define DIV_UART1(x) (((x) & 0x1) << 4)
+#define DIV_UART0(x) ((x) & 0x1)
+
+#define DIV_STAT_PERIL0_CHANGING (DIV_UART4(DIV_STAT_CHANGING) | \
+ DIV_UART3(DIV_STAT_CHANGING) | \
+ DIV_UART2(DIV_STAT_CHANGING) | \
+ DIV_UART1(DIV_STAT_CHANGING) | \
+ DIV_UART0(DIV_STAT_CHANGING))
+
+/* CLK_DIV_FSYS1 */
+#define MMC0_RATIO(x) ((x) & 0xf)
+#define MMC0_PRE_RATIO(x) (((x) & 0xff) << 8)
+#define MMC1_RATIO(x) (((x) & 0xf) << 16)
+#define MMC1_PRE_RATIO(x) (((x) & 0xff) << 24)
+
+/* CLK_DIV_STAT_FSYS1 */
+#define DIV_MMC0(x) ((x) & 1)
+#define DIV_MMC0_PRE(x) (((x) & 1) << 8)
+#define DIV_MMC1(x) (((x) & 1) << 16)
+#define DIV_MMC1_PRE(x) (((x) & 1) << 24)
+
+#define DIV_STAT_FSYS1_CHANGING (DIV_MMC0(DIV_STAT_CHANGING) | \
+ DIV_MMC0_PRE(DIV_STAT_CHANGING) | \
+ DIV_MMC1(DIV_STAT_CHANGING) | \
+ DIV_MMC1_PRE(DIV_STAT_CHANGING))
+
+/* CLK_DIV_FSYS2 */
+#define MMC2_RATIO(x) ((x) & 0xf)
+#define MMC2_PRE_RATIO(x) (((x) & 0xff) << 8)
+#define MMC3_RATIO(x) (((x) & 0xf) << 16)
+#define MMC3_PRE_RATIO(x) (((x) & 0xff) << 24)
+
+/* CLK_DIV_STAT_FSYS2 */
+#define DIV_MMC2(x) ((x) & 0x1)
+#define DIV_MMC2_PRE(x) (((x) & 0x1) << 8)
+#define DIV_MMC3(x) (((x) & 0x1) << 16)
+#define DIV_MMC3_PRE(x) (((x) & 0x1) << 24)
+
+#define DIV_STAT_FSYS2_CHANGING (DIV_MMC2(DIV_STAT_CHANGING) | \
+ DIV_MMC2_PRE(DIV_STAT_CHANGING) | \
+ DIV_MMC3(DIV_STAT_CHANGING) | \
+ DIV_MMC3_PRE(DIV_STAT_CHANGING))
+
+/* CLK_DIV_FSYS3 */
+#define MMC4_RATIO(x) ((x) & 0x7)
+#define MMC4_PRE_RATIO(x) (((x) & 0xff) << 8)
+
+/* CLK_DIV_STAT_FSYS3 */
+#define DIV_MMC4(x) ((x) & 0x1)
+#define DIV_MMC4_PRE(x) (((x) & 0x1) << 8)
+
+#define DIV_STAT_FSYS3_CHANGING (DIV_MMC4(DIV_STAT_CHANGING) | \
+ DIV_MMC4_PRE(DIV_STAT_CHANGING))
+
+#endif /*__ITOP4412_SETUP__ */

10、修改arch/arm/mach-exynos/dmc_init_exynos4.c,内存控制器初始化 :

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
--- a/arch/arm/mach-exynos/dmc_init_exynos4.c
+++ b/arch/arm/mach-exynos/dmc_init_exynos4.c
@@ -28,6 +28,28 @@
#include "common_setup.h"
#include "exynos4_setup.h"
+#ifdef CONFIG_TARGET_ITOP4412
+struct mem_timings mem = {
+ .direct_cmd_msr = {
+ DIRECT_CMD1, DIRECT_CMD2, DIRECT_CMD3, DIRECT_CMD4
+ },
+ .timingref = 0x000000BB,
+ .timingrow = 0x7846654F,
+ .timingdata = 0x46400506,
+ .timingpower = 0x52000A3C,
+ .zqcontrol = 0xE3855503,
+ .control0 = 0x71101008,
+ .control1 = 0x20000086,
+ .control2 = 0x00000000,
+ .concontrol = 0x0FFF30CA,
+ .prechconfig = 0x64000000,
+ .memcontrol = 0x00302600,
+ .memconfig0 = 0x40801333,
+ .memconfig1 = 0x60801333,
+ .dll_resync = FORCE_DLL_RESYNC,
+ .dll_on = DLL_CONTROL_ON,
+};
+#else
struct mem_timings mem = {
.direct_cmd_msr = {
DIRECT_CMD1, DIRECT_CMD2, DIRECT_CMD3, DIRECT_CMD4
@@ -48,6 +70,7 @@ struct mem_timings mem = {
.dll_resync = FORCE_DLL_RESYNC,
.dll_on = DLL_CONTROL_ON,
};
+#endif
static void phy_control_reset(int ctrl_no, struct exynos4_dmc *dmc)
{
if (ctrl_no) {
@@ -124,6 +147,10 @@ static void dmc_init(struct exynos4_dmc *dmc)
writel(mem.memconfig0, &dmc->memconfig0);
writel(mem.memconfig1, &dmc->memconfig1);
+#ifdef CONFIG_TARGET_ITOP4412
+ writel(0x8000001F, &dmc->ivcontrol);
+#endif
+
/* Config Precharge Policy */
writel(mem.prechconfig, &dmc->prechconfig);
/*
@@ -165,6 +192,7 @@ static void dmc_init(struct exynos4_dmc *dmc)
writel((mem.concontrol | AREF_EN), &dmc->concontrol);
}
+#if 1
void mem_ctrl_init(int reset)
{
struct exynos4_dmc *dmc;
@@ -175,6 +203,7 @@ void mem_ctrl_init(int reset)
* 0: full_sync
*/
writel(1, ASYNC_CONFIG);
+#ifndef CONFIG_TARGET_ITOP4412
#ifdef CONFIG_ORIGEN
/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */
writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE +
@@ -204,6 +233,7 @@ void mem_ctrl_init(int reset)
ABP_SFR_SLV_ADDRMAP_CONF_OFFSET);
#endif
#endif
+#endif
/* DREX0 */
dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl();
dmc_init(dmc);
@@ -211,3 +241,154 @@ void mem_ctrl_init(int reset)
+ DMC_OFFSET);
dmc_init(dmc);
}
+#endif

11、修改arch/arm/mach-exynos/spl_boot.c支持copy_uboot_to_ram:

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
--- a/arch/arm/mach-exynos/spl_boot.c
+++ b/arch/arm/mach-exynos/spl_boot.c
@@ -15,11 +15,17 @@
#include <asm/arch/power.h>
#include <asm/arch/spl.h>
#include <asm/arch/spi.h>
+#include <debug_uart.h>
#include "common_setup.h"
#include "clock_init.h"
DECLARE_GLOBAL_DATA_PTR;
+/*
+ * WARNING: This is going away very soon. Don't use it and don't submit
+ * pafches that rely on it. The global_data area is set up in crt0.S.
+ */
+gd_t gdata __attribute__ ((section(".data")));
/* Index into irom ptr table */
enum index {
@@ -185,6 +191,8 @@ void copy_uboot_to_ram(void)
{
unsigned int bootmode = BOOT_MODE_OM;
u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL;
u32 offset = 0, size = 0;
#ifdef CONFIG_SPI_BOOTING
@@ -254,8 +262,38 @@ void copy_uboot_to_ram(void)
break;
}
- if (copy_bl2)
+#ifdef CONFIG_TARGET_ITOP4412
+ if (copy_bl2) {
+ /*
+ * Here I use iram 0x020250000-0x020260000 (64k)
+ * as an buffer, and copy u-boot from sd card to
+ * this buffer, then copy it to dram started
+ * from 0x43e00000.
+ *
+ */
+ unsigned int i, count = 0;
+ unsigned char *buffer = (unsigned char *)0x02050000;
+ unsigned char *dst = (unsigned char *)CONFIG_SYS_TEXT_BASE;
+ unsigned int step = (0x10000 / 512);
+
+ for (count = 0; count < BL2_SIZE_BLOC_COUNT; count += step) {
+ /* copy u-boot from sdcard to iram firstly. */
+ copy_bl2((u32)(BL2_START_OFFSET+count), (u32)step, (u32)buffer);
+ /* then copy u-boot from iram to dram. */
+ for (i = 0; i < 0x10000; i++) {
+ *dst++ = buffer[i];
+ }
+ }
+ }
+#else
+ if (copy_bl2) {
copy_bl2(offset, size, CONFIG_SYS_TEXT_BASE);
+ }
+#endif
}
void memzero(void *s, size_t n)
@@ -282,7 +320,7 @@ static void setup_global_data(gd_t *gdp)
gd->baudrate = CONFIG_BAUDRATE;
gd->have_console = 1;
}
-
+#include <version.h>
void board_init_f(unsigned long bootflag)
{
__aligned(8) gd_t local_gd;
@@ -293,10 +331,14 @@ void board_init_f(unsigned long bootflag)
if (do_lowlevel_init())
power_exit_wakeup();
+ printascii("\r\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
+ U_BOOT_TIME ")\r\n");
+
copy_uboot_to_ram();
/* Jump to U-Boot image */
uboot = (void *)CONFIG_SYS_TEXT_BASE;
(*uboot)();
/* Never returns Here */
}

12、修改configs/itop4412_defconfig

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
--- /dev/null
+++ b/configs/itop4412_defconfig
@@ -0,0 +1,40 @@
+CONFIG_ARM=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_ARCH_EXYNOS4=y
+CONFIG_TARGET_ITOP4412=y
+CONFIG_IDENT_STRING=" Samsung Electronic"
+CONFIG_DEFAULT_DEVICE_TREE="exynos4412-itop4412"
+CONFIG_SYS_PROMPT="iTOP-4412 # "
+CONFIG_SPL=y
+CONFIG_HUSH_PARSER=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_XIMG is not set
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_DFU=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_NET is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_CACHE=y
+# CONFIG_CMD_MISC is not set
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_ISO_PARTITION=y
+CONFIG_OF_CONTROL=y
+CONFIG_DFU_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
+CONFIG_MMC_SDHCI_S5P=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_G_DNL_MANUFACTURER="Samsung"
+CONFIG_G_DNL_VENDOR_NUM=0x04e8
+CONFIG_G_DNL_PRODUCT_NUM=0x6601

13、修改drivers/serial/serial_s5p.c,配置串口的波特率、格式等信息:

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/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index 96842de..5174150 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -63,12 +63,20 @@ static const int udivslot[] = {
static void __maybe_unused s5p_serial_init(struct s5p_uart *uart)
{
/* enable FIFOs, auto clear Rx FIFO */
+#ifdef CONFIG_ITOP4412
+ writel(0x111, &uart->ufcon);
+#else
writel(0x3, &uart->ufcon);
+#endif
writel(0, &uart->umcon);
/* 8N1 */
writel(0x3, &uart->ulcon);
/* No interrupts, no DMA, pure polling */
+#ifdef CONFIG_ITOP4412
+ writel(0x3c5, &uart->ucon);
+#else
writel(0x245, &uart->ucon);
+#endif
}

14、修改include/configs/itop4412.h

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
diff --git a/include/configs/itop4412.h b/include/configs/itop4412.h
new file mode 100644
index 0000000..fe7cac2
--- /dev/null
+++ b/include/configs/itop4412.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * Configuration settings for the SAMSUNG ORIGEN (EXYNOS4210) board.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_ITOP4412_H
+#define __CONFIG_ITOP4412_H
+
+#include <configs/exynos4-common.h>
+
+#undef CONFIG_SKIP_LOWLEVEL_INIT
+#undef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+/* High Level Configuration Options */
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_GPIO_SUPPORT
+#define CONFIG_DEBUG_UART
+#define CONFIG_DEBUG_UART_S5P
+#define CONFIG_DEBUG_UART_BASE 0x13830000 /* UART3 base address */
+#define CONFIG_DEBUG_UART_CLOCK (100000000) /* SCLK_UART3 is 100MHz */
+
+#define CONFIG_SYS_DCACHE_OFF 1
+
+/* ORIGEN has 4 bank of DRAM */
+#define CONFIG_NR_DRAM_BANKS 4
+#define CONFIG_SYS_SDRAM_BASE 0x40000000
+#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE
+#define SDRAM_BANK_SIZE (256 << 20) /* 256 MB */
+
+/* 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_TEXT_BASE 0x43E00000
+
+#define CONFIG_MACH_TYPE MACH_TYPE_ITOP4412
+
+/* select serial console configuration */
+#define CONFIG_SERIAL3
+#define CONFIG_BAUDRATE 115200
+
+/* Console configuration */
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_SYS_CONSOLE_INFO_QUIET
+#define CONFIG_DEFAULT_CONSOLE "console=ttySAC1,115200n8\0"
+
+#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
+
+
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FS_GENERIC
+#define CONFIG_CMD_BOOTZ
+#define CONFIG_SUPPORT_RAW_INITRD
+
+/* MMC SPL */
+#define COPY_BL2_FNPTR_ADDR 0x02020030
+#define CONFIG_SPL_TEXT_BASE 0x02023400
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "loadaddr=0x40007000\0" \
+ "rdaddr=0x48000000\0" \
+ "kerneladdr=0x40007000\0" \
+ "ramdiskaddr=0x48000000\0" \
+ "console=ttySAC2,115200n8\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
+
+/* MIU (Memory Interleaving Unit) */
+#define CONFIG_MIU_2BIT_21_7_INTERLEAVED
+
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_ENV_SIZE (16 << 10) /* 16 KB */
+#define RESERVE_BLOCK_SIZE (512)
+#define BL1_SIZE (8 << 10) /*16 K reserved for BL1*/
+#define BL2_SIZE (16 << 10)
+
+#define CONFIG_ENV_OFFSET (RESERVE_BLOCK_SIZE + BL1_SIZE + BL2_SIZE)
+
+#define CONFIG_SPL_LDSCRIPT "board/samsung/common/exynos-uboot-spl.lds"
+#define CONFIG_SPL_MAX_FOOTPRINT (14 * 1024)
+
+#define CONFIG_SYS_INIT_SP_ADDR 0x02040000
+
+/* U-Boot copy size from boot Media to DRAM.*/
+#define COPY_BL2_SIZE 0x80000
+#define BL2_START_OFFSET ((CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)/512)
+#define BL2_SIZE_BLOC_COUNT (COPY_BL2_SIZE/512)
+
+#endif /* __CONFIG_ITOP4412_H */

15、修改arch/arm/cpu/armv7/Makefile,支持lowlevel_init:

1
2
3
4
5
6
7
8
9
10
11
12
13
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index 02e8778..47292ee 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -12,7 +12,7 @@ obj-y += cache_v7.o cache_v7_asm.o
obj-y += cpu.o cp15.o
obj-y += syslib.o
-ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONFIG_MX6)$(CONFIG_MX7)$(CONFIG_TI81XX)$(CONFIG_AT91FAMILY)$(CONFIG_ARCH_SUNXI)$(CONFIG_ARCH_SOCFPGA)$(CONFIG_ARCH_MX7ULP)$(CONFIG_LS102XA),)
+ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONFIG_MX6)$(CONFIG_MX7)$(CONFIG_TI81XX)$(CONFIG_AT91FAMILY)$(CONFIG_ARCH_SUNXI)$(CONFIG_ARCH_SOCFPGA)$(CONFIG_ARCH_MX7ULP)$(CONFIG_LS102XA)$(CONFIG_TARGET_ITOP4412),)
ifneq ($(CONFIG_SKIP_LOWLEVEL_INIT),y)
obj-y += lowlevel_init.o
endif

16、编辑arch/arm/mach-exynos/board.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
diff --git a/arch/arm/mach-exynos/board.c b/arch/arm/mach-exynos/board.c
new file mode 100644
index 0000000..98fbf9d
--- /dev/null
+++ b/arch/arm/mach-exynos/board.c
@@ -0,0 +1,16 @@
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+
+void s_init(void)
+{
+ writel(readl(0x1002330c) | 0x300, 0x1002330c);
+ writel(0, 0x11000c08);
+
+ /* led test */
+ writel(0x10, 0x11000060);
+ writel(0x2, 0x11000064);
+
+ writel(0x1, 0x11000100);
+ writel(0x1, 0x11000104);
+}

用于电源管理设置还有点亮led测试。

移植完成

(一) 编译

1
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

编译完成后得到2个文件:

  • u-boot.bin
  • spl/u-boot-spl.bin

(二) 使用mkbl2给SPL添加校验码

1
$ ./mkbl2 u-boot-spl.bin bl2.bin 14336

(三) 烧写

我的读卡器是/dev/sdc,大家按自己的具体情况修改。

1
$ dd iflag=dsync oflag=dsync if=E4412_N.bl1.bin of=/dev/sdc seek=1;dd iflag=dsync oflag=dsync if=bl2.bin of=/dev/sdc seek=17;dd iflag=dsync oflag=dsync if=u-boot.bin of=/dev/sdc seek=81;sync

成功运行

running

至此,分享结束~ 后续将进一步进行device tree source文件适配与驱动移植,敬请关注。