summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Go <luke.go@hardkernel.com>2019-06-19 11:46:06 +0900
committerDongjin Kim <tobetter@gmail.com>2020-02-13 17:13:40 +0900
commit1823eb28b55e6d95789020a671872488c857b3dc (patch)
treeab285275e2d9eca7635358dfef900e79b960e71e
parent800d2781a0a41169b5f0a0c423fb98958fc978e0 (diff)
downloadu-boot-odroid-c1-1823eb28b55e6d95789020a671872488c857b3dc.tar.gz
ODROID-C4: introduce new board ODROID-C4 and its board configuration
Change-Id: I112d1c669784fd989405c6dfe788e084eb09785e
-rw-r--r--board/amlogic/Kconfig9
-rw-r--r--board/hardkernel/odroidc4/Kconfig22
-rw-r--r--board/hardkernel/odroidc4/Makefile3
-rw-r--r--board/hardkernel/odroidc4/aml-user-key.sigbin0 -> 6976 bytes
-rw-r--r--board/hardkernel/odroidc4/firmware/scp_task/pwm_ctrl.h40
-rw-r--r--board/hardkernel/odroidc4/firmware/scp_task/pwr_ctrl.c179
-rw-r--r--board/hardkernel/odroidc4/firmware/timing.c357
-rw-r--r--board/hardkernel/odroidc4/odroidc4.c416
-rw-r--r--configs/odroidc4_defconfig6
-rw-r--r--include/configs/odroidc4.h17
10 files changed, 1049 insertions, 0 deletions
diff --git a/board/amlogic/Kconfig b/board/amlogic/Kconfig
index c2ccdf48e4..2597603959 100644
--- a/board/amlogic/Kconfig
+++ b/board/amlogic/Kconfig
@@ -274,6 +274,11 @@ config ODROID_N2
select ODROID_COMMON
default n
+config ODROID_C4
+ bool "Support Hardkernel ODROID-C3 board"
+ select ODROID_COMMON
+ default n
+
if GXB_SKT_V1
source "board/amlogic/gxb_skt_v1/Kconfig"
endif
@@ -534,3 +539,7 @@ endif
if ODROID_N2
source "board/hardkernel/odroidn2/Kconfig"
endif
+
+if ODROID_C4
+source "board/hardkernel/odroidc4/Kconfig"
+endif
diff --git a/board/hardkernel/odroidc4/Kconfig b/board/hardkernel/odroidc4/Kconfig
new file mode 100644
index 0000000000..bb3467cd68
--- /dev/null
+++ b/board/hardkernel/odroidc4/Kconfig
@@ -0,0 +1,22 @@
+if TARGET_MESON_G12A
+
+config SYS_CPU
+ string
+ default "armv8"
+
+config SYS_BOARD
+ string
+ default "odroidc4"
+
+config SYS_VENDOR
+ string
+ default "hardkernel"
+
+config SYS_SOC
+ string
+ default "g12a"
+
+config SYS_CONFIG_NAME
+ default "odroidc4"
+
+endif
diff --git a/board/hardkernel/odroidc4/Makefile b/board/hardkernel/odroidc4/Makefile
new file mode 100644
index 0000000000..567e550274
--- /dev/null
+++ b/board/hardkernel/odroidc4/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS += -Iboard/hardkernel/odroid-common
+
+obj-y += $(BOARD).o
diff --git a/board/hardkernel/odroidc4/aml-user-key.sig b/board/hardkernel/odroidc4/aml-user-key.sig
new file mode 100644
index 0000000000..2ceabc16e0
--- /dev/null
+++ b/board/hardkernel/odroidc4/aml-user-key.sig
Binary files differ
diff --git a/board/hardkernel/odroidc4/firmware/scp_task/pwm_ctrl.h b/board/hardkernel/odroidc4/firmware/scp_task/pwm_ctrl.h
new file mode 100644
index 0000000000..11dc06b99b
--- /dev/null
+++ b/board/hardkernel/odroidc4/firmware/scp_task/pwm_ctrl.h
@@ -0,0 +1,40 @@
+/*
+ * board/hardkernel/odroidc4/firmware/scp_task/pwr_ctrl.h
+ * table for Dynamic Voltage/Frequency Scaling
+ */
+#ifndef __PWM_CTRL_H__
+#define __PWM_CTRL_H__
+
+static int pwm_voltage_table_ee[][2] = {
+ { 0x1c0000, 681},
+ { 0x1b0001, 691},
+ { 0x1a0002, 701},
+ { 0x190003, 711},
+ { 0x180004, 721},
+ { 0x170005, 731},
+ { 0x160006, 741},
+ { 0x150007, 751},
+ { 0x140008, 761},
+ { 0x130009, 772},
+ { 0x12000a, 782},
+ { 0x11000b, 792},
+ { 0x10000c, 802},
+ { 0x0f000d, 812},
+ { 0x0e000e, 822},
+ { 0x0d000f, 832},
+ { 0x0c0010, 842},
+ { 0x0b0011, 852},
+ { 0x0a0012, 862},
+ { 0x090013, 872},
+ { 0x080014, 882},
+ { 0x070015, 892},
+ { 0x060016, 902},
+ { 0x050017, 912},
+ { 0x040018, 922},
+ { 0x030019, 932},
+ { 0x02001a, 942},
+ { 0x01001b, 952},
+ { 0x00001c, 962}
+};
+
+#endif //__PWM_CTRL_H__
diff --git a/board/hardkernel/odroidc4/firmware/scp_task/pwr_ctrl.c b/board/hardkernel/odroidc4/firmware/scp_task/pwr_ctrl.c
new file mode 100644
index 0000000000..7b782a5700
--- /dev/null
+++ b/board/hardkernel/odroidc4/firmware/scp_task/pwr_ctrl.c
@@ -0,0 +1,179 @@
+/*
+ * board/hardkernel/odroidc4/firmware/scp_task/pwr_ctrl.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <gpio.h>
+#include "pwm_ctrl.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static void set_vddee_voltage(unsigned int target_voltage)
+{
+ unsigned int to;
+
+ for (to = 0; to < ARRAY_SIZE(pwm_voltage_table_ee); to++) {
+ if (pwm_voltage_table_ee[to][1] >= target_voltage) {
+ break;
+ }
+ }
+
+ if (to >= ARRAY_SIZE(pwm_voltage_table_ee)) {
+ to = ARRAY_SIZE(pwm_voltage_table_ee) - 1;
+ }
+
+ writel(pwm_voltage_table_ee[to][0],AO_PWM_PWM_B);
+}
+
+static void power_off_at_24M(unsigned int suspend_from)
+{
+ /*set gpioH_8 low to power off vcc 5v*/
+ writel(readl(PREG_PAD_GPIO3_EN_N) & (~(1 << 8)), PREG_PAD_GPIO3_EN_N);
+ writel(readl(PERIPHS_PIN_MUX_C) & (~(0xf)), PERIPHS_PIN_MUX_C);
+
+ /*set test_n low to power off vcck & vcc 3.3v*/
+ writel(readl(AO_GPIO_O) & (~(1 << 31)), AO_GPIO_O);
+ writel(readl(AO_GPIO_O_EN_N) & (~(1 << 31)), AO_GPIO_O_EN_N);
+ writel(readl(AO_RTI_PIN_MUX_REG1) & (~(0xf << 28)), AO_RTI_PIN_MUX_REG1);
+
+ /*step down ee voltage*/
+ set_vddee_voltage(CONFIG_VDDEE_SLEEP_VOLTAGE);
+}
+
+static void power_on_at_24M(unsigned int suspend_from)
+{
+ /*step up ee voltage*/
+ set_vddee_voltage(CONFIG_VDDEE_INIT_VOLTAGE);
+
+ /*set test_n low to power on vcck & vcc 3.3v*/
+ writel(readl(AO_GPIO_O) | (1 << 31), AO_GPIO_O);
+ writel(readl(AO_GPIO_O_EN_N) & (~(1 << 31)), AO_GPIO_O_EN_N);
+ writel(readl(AO_RTI_PIN_MUX_REG1) & (~(0xf << 28)), AO_RTI_PIN_MUX_REG1);
+ _udelay(100);
+
+ /*set gpioH_8 low to power on vcc 5v*/
+ writel(readl(PREG_PAD_GPIO3_EN_N) | (1 << 8), PREG_PAD_GPIO3_EN_N);
+ writel(readl(PERIPHS_PIN_MUX_C) & (~(0xf)), PERIPHS_PIN_MUX_C);
+ _udelay(10000);
+}
+
+void get_wakeup_source(void *response, unsigned int suspend_from)
+{
+ struct wakeup_info *p = (struct wakeup_info *)response;
+ struct wakeup_gpio_info *gpio;
+ unsigned val;
+ unsigned i = 0;
+
+ p->status = RESPONSE_OK;
+ val = (POWER_KEY_WAKEUP_SRC | AUTO_WAKEUP_SRC | REMOTE_WAKEUP_SRC |
+ RTC_WAKEUP_SRC | BT_WAKEUP_SRC | ETH_PHY_GPIO_SRC);
+
+ p->sources = val;
+
+ /* Power Key: AO_GPIO[3]*/
+ gpio = &(p->gpio_info[i]);
+ gpio->wakeup_id = POWER_KEY_WAKEUP_SRC;
+ gpio->gpio_in_idx = GPIOAO_3;
+ gpio->gpio_in_ao = 1;
+ gpio->gpio_out_idx = -1;
+ gpio->gpio_out_ao = -1;
+ gpio->irq = IRQ_AO_GPIO0_NUM;
+ gpio->trig_type = GPIO_IRQ_FALLING_EDGE;
+ p->gpio_info_count = ++i;
+
+ /*Eth:GPIOZ_14*/
+ gpio = &(p->gpio_info[i]);
+ gpio->wakeup_id = ETH_PHY_GPIO_SRC;
+ gpio->gpio_in_idx = GPIOZ_14;
+ gpio->gpio_in_ao = 0;
+ gpio->gpio_out_idx = -1;
+ gpio->gpio_out_ao = -1;
+ gpio->irq = IRQ_GPIO1_NUM;
+ gpio->trig_type = GPIO_IRQ_FALLING_EDGE;
+ p->gpio_info_count = ++i;
+
+}
+extern void __switch_idle_task(void);
+
+static unsigned int detect_key(unsigned int suspend_from)
+{
+ int exit_reason = 0;
+ unsigned *irq = (unsigned *)WAKEUP_SRC_IRQ_ADDR_BASE;
+#ifdef CONFIG_ADC_KEY
+ unsigned char adc_key_cnt = 0;
+ saradc_enable();
+#endif
+ init_remote();
+
+ do {
+ if (irq[IRQ_AO_IR_DEC] == IRQ_AO_IR_DEC_NUM) {
+ irq[IRQ_AO_IR_DEC] = 0xFFFFFFFF;
+ if (remote_detect_key())
+ exit_reason = REMOTE_WAKEUP;
+ }
+
+#ifdef CONFIG_ADC_KEY
+ if (irq[IRQ_AO_TIMERA] == IRQ_AO_TIMERA_NUM) {
+ irq[IRQ_AO_TIMERA] = 0xFFFFFFFF;
+ if (check_adc_key_resume()) {
+ adc_key_cnt++;
+ /*using variable 'adc_key_cnt' to eliminate the dithering of the key*/
+ if (2 == adc_key_cnt)
+ exit_reason = POWER_KEY_WAKEUP;
+ } else {
+ adc_key_cnt = 0;
+ }
+ }
+#endif
+
+#ifdef CONFIG_GPIO_POWER_KEY
+ if (irq[IRQ_AO_GPIO0] == IRQ_AO_GPIO0_NUM) {
+ irq[IRQ_AO_GPIO0] = 0xFFFFFFFF;
+ if ((readl(AO_GPIO_I) & (1<<3)) == 0)
+ exit_reason = POWER_KEY_WAKEUP;
+ }
+#endif
+
+#if 0
+ if (irq[IRQ_GPIO1] == IRQ_GPIO1_NUM) {
+ irq[IRQ_GPIO1] = 0xFFFFFFFF;
+ if (!(readl(PREG_PAD_GPIO4_I) & (0x01 << 14))
+ && (readl(PREG_PAD_GPIO4_EN_N) & (0x01 << 14)))
+ exit_reason = ETH_PHY_GPIO;
+ }
+#endif
+ if (exit_reason)
+ break;
+ else
+ __switch_idle_task();
+ } while (1);
+
+#ifdef CONFIG_ADC_KEY
+ saradc_disable();
+#endif
+
+ return exit_reason;
+}
+
+static void pwr_op_init(struct pwr_op *pwr_op)
+{
+ pwr_op->power_off_at_24M = power_off_at_24M;
+ pwr_op->power_on_at_24M = power_on_at_24M;
+ pwr_op->detect_key = detect_key;
+ pwr_op->get_wakeup_source = get_wakeup_source;
+}
diff --git a/board/hardkernel/odroidc4/firmware/timing.c b/board/hardkernel/odroidc4/firmware/timing.c
new file mode 100644
index 0000000000..4dcaa6c918
--- /dev/null
+++ b/board/hardkernel/odroidc4/firmware/timing.c
@@ -0,0 +1,357 @@
+/*
+ * board/hardkernel/odroidc4/firmware/timing.c
+ *
+ * (C) Copyright 2019 Hardkernel Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <asm/arch/secure_apb.h>
+#include <asm/arch/timing.h>
+#include <asm/arch/ddr_define.h>
+
+
+
+/* ddr config support multiple configs for boards which use same bootloader:
+ * config steps:
+ * 1. add a new data struct in __ddr_setting[]
+ * 2. config correct board_id, ddr_type, freq, etc..
+ */
+
+
+/* CAUTION!! */
+/* Confirm ddr configs with hardware designer,
+ * if you don't know how to config, then don't edit it
+ */
+
+/* Key configs */
+/*
+ * board_id: check hardware adc config
+ * dram_rank_config:
+ * #define CONFIG_DDR_CHL_AUTO 0xF
+ * #define CONFIG_DDR0_16BIT_CH0 0x1
+ * #define CONFIG_DDR0_16BIT_RANK01_CH0 0x4
+ * #define CONFIG_DDR0_32BIT_RANK0_CH0 0x2
+ * #define CONFIG_DDR0_32BIT_RANK01_CH01 0x3
+ * #define CONFIG_DDR0_32BIT_16BIT_RANK0_CH0 0x5
+ * #define CONFIG_DDR0_32BIT_16BIT_RANK01_CH0 0x6
+ * DramType:
+ * #define CONFIG_DDR_TYPE_DDR3 0
+ * #define CONFIG_DDR_TYPE_DDR4 1
+ * #define CONFIG_DDR_TYPE_LPDDR4 2
+ * #define CONFIG_DDR_TYPE_LPDDR3 3
+ * DRAMFreq:
+ * {pstate0, pstate1, pstate2, pstate3} //more than one pstate means use dynamic freq
+ *
+ */
+
+
+/* ddr configs */
+#define DDR_RFC_TYPE_DDR3_512Mbx1 0
+#define DDR_RFC_TYPE_DDR3_512Mbx2 1
+#define DDR_RFC_TYPE_DDR3_512Mbx4 2
+#define DDR_RFC_TYPE_DDR3_512Mbx8 3
+#define DDR_RFC_TYPE_DDR3_512Mbx16 4
+#define DDR_RFC_TYPE_DDR4_2Gbx1 5
+#define DDR_RFC_TYPE_DDR4_2Gbx2 6
+#define DDR_RFC_TYPE_DDR4_2Gbx4 7
+#define DDR_RFC_TYPE_DDR4_2Gbx8 8
+
+#define DDR_RFC_TYPE_LPDDR4_2Gbx1 9
+#define DDR_RFC_TYPE_LPDDR4_3Gbx1 10
+#define DDR_RFC_TYPE_LPDDR4_4Gbx1 11
+
+#define CONFIG_DDR4_DEFAULT_CLK 1320
+
+ddr_set_t __ddr_setting[] = {
+{
+ /* odroid-c4 ddr4 : (4Gbitx2)x2, (8Gbitx2)x2 */
+ .board_id = CONFIG_BOARD_ID_MASK,
+ .version = 1,
+ .dram_rank_config = CONFIG_DDR0_32BIT_RANK01_CH0, /* bus width 32bit, use cs0 cs1 */
+ .DramType = CONFIG_DDR_TYPE_DDR4,
+ /* 912 (DDR4-1866) / 1056 (DDR4-2133) / 1200 (DDR4-2400)/ 1320 (DDR4-2666) */
+ .DRAMFreq = {CONFIG_DDR4_DEFAULT_CLK, 0, 0, 0},
+ .ddr_rfc_type = DDR_RFC_TYPE_DDR4_2Gbx8,
+ .ddr_base_addr = CFG_DDR_BASE_ADDR,
+ .ddr_start_offset = CFG_DDR_START_OFFSET,
+ .imem_load_addr = 0xFFFC0000, /* sram */
+ .dmem_load_size = 0x1000, /* 4K */
+
+ .DisabledDbyte = 0xf0,
+ .Is2Ttiming = 1,
+ .HdtCtrl = 0xC8,
+ .dram_cs0_size_MB = 0xffff,
+ .dram_cs1_size_MB = 0xffff,
+ .training_SequenceCtrl = {0x31f,0x61}, /* ddr3 0x21f 0x31f */
+ .phy_odt_config_rank = {0x30,0x30,0x30,0x30}, /* Odt pattern for accesses, targeting rank 0. [3:0] is used, for write ODT [7:4] is used for, read ODT */
+ .dfi_odt_config = 0x0808,
+ .PllBypassEn = 0, /* bit0-ps0,bit1-ps1 */
+ .ddr_rdbi_wr_enable = 0,
+ .clk_drv_ohm = 40,
+ .cs_drv_ohm = 40,
+ .ac_drv_ohm = 40,
+ .soc_data_drv_ohm_p = 34,
+ .soc_data_drv_ohm_n = 34,
+ .soc_data_odt_ohm_p = 60,
+ .soc_data_odt_ohm_n = 0,
+ .dram_data_drv_ohm = 48, /* ddr4 sdram only 34 or 48, skt board use 34 better */
+ .dram_data_odt_ohm = 60,
+ .dram_ac_odt_ohm = 0,
+ .soc_clk_slew_rate = 0x3ff,
+ .soc_cs_slew_rate = 0x3ff,
+ .soc_ac_slew_rate = 0x3ff,
+ .soc_data_slew_rate = 0x2ff,
+ .vref_output_permil = 500,
+ .vref_receiver_permil = 700,
+ .vref_dram_permil = 700,
+ //.vref_reverse = 0,
+ .ac_trace_delay = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+ .ac_pinmux = {00, 00},
+ .ddr_dmc_remap = {
+ [0] = ( 5 | 7 << 5 | 8 << 10 | 9 << 15 | 10 << 20 | 11 << 25 ),
+ [1] = ( 12| 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25 ),
+ [2] = ( 17| 18 << 5 | 19 << 10 | 21 << 15 | 22 << 20 | 23 << 25 ),
+ [3] = ( 24| 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25 ),
+ [4] = ( 30| 13 << 5 | 20 << 10 | 6 << 15 | 0 << 20 | 0 << 25 ),
+ },
+ .ddr_lpddr34_ca_remap = {00,00},
+ .ddr_lpddr34_dq_remap = {00,00},
+ .dram_rtt_nom_wr_park = {00,00},
+ .pll_ssc_mode = 0,
+ .ddr_func = DDR_FUNC,
+ .magic = DRAM_CFG_MAGIC,
+},
+{
+ /* odroid-c4 ddr4 : 8Gbitx2 */
+ .board_id = CONFIG_BOARD_ID_MASK,
+ .version = 1,
+ .dram_rank_config = CONFIG_DDR0_32BIT_RANK0_CH0, /* bus width 32bit, use cs0 only */
+ .DramType = CONFIG_DDR_TYPE_DDR4,
+ /* 912 (DDR4-1866) / 1056 (DDR4-2133) / 1200 (DDR4-2400)/ 1320 (DDR4-2666) */
+ .DRAMFreq = {CONFIG_DDR4_DEFAULT_CLK, 0, 0, 0},
+ .ddr_rfc_type = DDR_RFC_TYPE_DDR4_2Gbx8,
+ .ddr_base_addr = CFG_DDR_BASE_ADDR,
+ .ddr_start_offset = CFG_DDR_START_OFFSET,
+ .imem_load_addr = 0xFFFC0000, /* sram */
+ .dmem_load_size = 0x1000, /* 4K */
+
+ .DisabledDbyte = 0xf0,
+ .Is2Ttiming = 1,
+ .HdtCtrl = 0xC8,
+ .dram_cs0_size_MB = 0xffff,
+ .dram_cs1_size_MB = 0,
+ .training_SequenceCtrl = {0x31f,0x61}, /* ddr3 0x21f 0x31f */
+ .phy_odt_config_rank = {0x30,0x30,0x30,0x30}, /* Odt pattern for accesses, targeting rank 0. [3:0] is used, for write ODT [7:4] is used for, read ODT */
+ .dfi_odt_config = 0x0808,
+ .PllBypassEn = 0, /* bit0-ps0,bit1-ps1 */
+ .ddr_rdbi_wr_enable = 0,
+ .clk_drv_ohm = 40,
+ .cs_drv_ohm = 40,
+ .ac_drv_ohm = 40,
+ .soc_data_drv_ohm_p = 34,
+ .soc_data_drv_ohm_n = 34,
+ .soc_data_odt_ohm_p = 60,
+ .soc_data_odt_ohm_n = 0,
+ .dram_data_drv_ohm = 48, /* ddr4 sdram only 34 or 48, skt board use 34 better */
+ .dram_data_odt_ohm = 60,
+ .dram_ac_odt_ohm = 0,
+ .soc_clk_slew_rate = 0x3ff,
+ .soc_cs_slew_rate = 0x3ff,
+ .soc_ac_slew_rate = 0x3ff,
+ .soc_data_slew_rate = 0x2ff,
+ .vref_output_permil = 500,
+ .vref_receiver_permil = 700,
+ .vref_dram_permil = 700,
+ //.vref_reverse = 0,
+ .ac_trace_delay = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+ .ac_pinmux = {00, 00},
+ .ddr_dmc_remap = {
+ [0] = ( 5 | 7 << 5 | 8 << 10 | 9 << 15 | 10 << 20 | 11 << 25 ),
+ [1] = ( 12| 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25 ),
+ [2] = ( 17| 18 << 5 | 19 << 10 | 21 << 15 | 22 << 20 | 23 << 25 ),
+ [3] = ( 24| 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25 ),
+ [4] = ( 30| 13 << 5 | 20 << 10 | 6 << 15 | 0 << 20 | 0 << 25 ),
+ },
+ .ddr_lpddr34_ca_remap = {00,00},
+ .ddr_lpddr34_dq_remap = {00,00},
+ .dram_rtt_nom_wr_park = {00,00},
+ .pll_ssc_mode = 0,
+ .ddr_func = DDR_FUNC,
+ .magic = DRAM_CFG_MAGIC,
+},
+};
+
+pll_set_t __pll_setting = {
+ .cpu_clk = CONFIG_CPU_CLK / 24 * 24,
+#ifdef CONFIG_PXP_EMULATOR
+ .pxp = 1,
+#else
+ .pxp = 0,
+#endif
+ .spi_ctrl = 0,
+ .lCustomerID = CONFIG_AML_CUSTOMER_ID,
+#ifdef CONFIG_DEBUG_MODE
+ .debug_mode = CONFIG_DEBUG_MODE,
+ .ddr_clk_debug = CONFIG_DDR_CLK_DEBUG,
+ .cpu_clk_debug = CONFIG_CPU_CLK_DEBUG,
+#endif
+};
+
+ddr_reg_t __ddr_reg[] = {
+ /* demo, user defined override register */
+ {0xaabbccdd, 0, 0, 0, 0, 0},
+ {0x11223344, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+};
+
+#define VCCK_VAL CONFIG_VCCK_INIT_VOLTAGE
+#define VDDEE_VAL CONFIG_VDDEE_INIT_VOLTAGE
+/* VCCK PWM table */
+#if (VCCK_VAL == 800)
+ #define VCCK_VAL_REG 0x00150007
+#elif (VCCK_VAL == 810)
+ #define VCCK_VAL_REG 0x00140008
+#elif (VCCK_VAL == 820)
+ #define VCCK_VAL_REG 0x00130009
+#elif (VCCK_VAL == 830)
+ #define VCCK_VAL_REG 0x0012000a
+#elif (VCCK_VAL == 840)
+ #define VCCK_VAL_REG 0x0011000b
+#elif (VCCK_VAL == 850)
+ #define VCCK_VAL_REG 0x0010000c
+#elif (VCCK_VAL == 860)
+ #define VCCK_VAL_REG 0x000f000d
+#elif (VCCK_VAL == 870)
+ #define VCCK_VAL_REG 0x000e000e
+#elif (VCCK_VAL == 880)
+ #define VCCK_VAL_REG 0x000d000f
+#elif (VCCK_VAL == 890)
+ #define VCCK_VAL_REG 0x000c0010
+#elif (VCCK_VAL == 900)
+ #define VCCK_VAL_REG 0x000b0011
+#elif (VCCK_VAL == 910)
+ #define VCCK_VAL_REG 0x000a0012
+#elif (VCCK_VAL == 920)
+ #define VCCK_VAL_REG 0x00090013
+#elif (VCCK_VAL == 930)
+ #define VCCK_VAL_REG 0x00080014
+#elif (VCCK_VAL == 940)
+ #define VCCK_VAL_REG 0x00070015
+#elif (VCCK_VAL == 950)
+ #define VCCK_VAL_REG 0x00060016
+#elif (VCCK_VAL == 960)
+ #define VCCK_VAL_REG 0x00050017
+#elif (VCCK_VAL == 970)
+ #define VCCK_VAL_REG 0x00040018
+#elif (VCCK_VAL == 980)
+ #define VCCK_VAL_REG 0x00030019
+#elif (VCCK_VAL == 990)
+ #define VCCK_VAL_REG 0x0002001a
+#elif (VCCK_VAL == 1000)
+ #define VCCK_VAL_REG 0x0001001b
+#elif (VCCK_VAL == 1010)
+ #define VCCK_VAL_REG 0x0000001c
+#else
+ #error "VCCK val out of range\n"
+#endif
+
+/* VDDEE_VAL_REG0: VDDEE PWM table 0.67v-0.97v*/
+/* VDDEE_VAL_REG1: VDDEE PWM table 0.69v-0.89v*/
+#if (VDDEE_VAL == 800)
+ #define VDDEE_VAL_REG0 0x0010000c
+ #define VDDEE_VAL_REG1 0x0008000a
+#elif (VDDEE_VAL == 810)
+ #define VDDEE_VAL_REG0 0x000f000d
+ #define VDDEE_VAL_REG1 0x0007000b
+#elif (VDDEE_VAL == 820)
+ #define VDDEE_VAL_REG0 0x000e000e
+ #define VDDEE_VAL_REG1 0x0006000c
+#elif (VDDEE_VAL == 830)
+ #define VDDEE_VAL_REG0 0x000d000f
+ #define VDDEE_VAL_REG1 0x0005000d
+#elif (VDDEE_VAL == 840)
+ #define VDDEE_VAL_REG0 0x000c0010
+ #define VDDEE_VAL_REG1 0x0004000e
+#elif (VDDEE_VAL == 850)
+ #define VDDEE_VAL_REG0 0x000b0011
+ #define VDDEE_VAL_REG1 0x0003000f
+#elif (VDDEE_VAL == 860)
+ #define VDDEE_VAL_REG0 0x000a0012
+ #define VDDEE_VAL_REG1 0x00020010
+#elif (VDDEE_VAL == 870)
+ #define VDDEE_VAL_REG0 0x00090013
+ #define VDDEE_VAL_REG1 0x00010011
+#elif (VDDEE_VAL == 880)
+ #define VDDEE_VAL_REG0 0x00080014
+ #define VDDEE_VAL_REG1 0x00000012
+#else
+ #error "VDDEE val out of range\n"
+#endif
+
+/* for PWM use */
+/* PWM driver check http://scgit.amlogic.com:8080/#/c/38093/ */
+#define GPIO_O_EN_N_REG3 ((0xff634400 + (0x19 << 2)))
+#define GPIO_O_REG3 ((0xff634400 + (0x1a << 2)))
+#define GPIO_I_REG3 ((0xff634400 + (0x1b << 2)))
+#define AO_PIN_MUX_REG0 ((0xff800000 + (0x05 << 2)))
+#define AO_PIN_MUX_REG1 ((0xff800000 + (0x06 << 2)))
+
+bl2_reg_t __bl2_reg[] = {
+ /* demo, user defined override register */
+ /* eg: PWM init */
+
+ /* PWM_AO_D */
+ /* VCCK_VAL_REG: check PWM table */
+ {AO_PWM_PWM_D, VCCK_VAL_REG, 0xffffffff, 0, BL2_INIT_STAGE_1, 0},
+ {AO_PWM_MISC_REG_CD, ((1 << 23) | (1 << 1)), (0x7f << 16), 0, BL2_INIT_STAGE_1, 0},
+ {AO_PIN_MUX_REG1, (3 << 20), (0xF << 20), 0, BL2_INIT_STAGE_1, 0},
+
+ /* set BOOT_9 input */
+ //{PAD_PULL_UP_EN_REG0, 1 << 9, 1 << 9, 0, BL2_INIT_STAGE_1, 0},
+
+ /* PWM_AO_B */
+ /* VDDEE init start */
+ /* step1: CHK HW */
+ {(uint64_t)P_ASSIST_POR_CONFIG, 7, 0, 0, BL2_INIT_STAGE_PWM_CHK_HW, 0},
+
+ /* step2: match PWM config */
+ /* GPIO9[BIT7]=H use PWM_CFG0(0.67v-0.97v), =L use PWM_CFG1(0.69v-0.89v) */
+ {0x1, PWM_CFG0, 0, 0, BL2_INIT_STAGE_PWM_CFG_GROUP, 0},
+ {0x0, PWM_CFG1, 0, 0, BL2_INIT_STAGE_PWM_CFG_GROUP, 0},
+
+ /* step3: config PWM */
+ /* VDDEE_VAL_REG0: VDDEE PWM table 0.67v-0.97v*/
+ {AO_PWM_PWM_B, VDDEE_VAL_REG0, 0xffffffff, 0, BL2_INIT_STAGE_PWM_INIT | PWM_CFG0, 0},
+ {AO_PWM_MISC_REG_AB, ((1 << 23) | (1 << 1)), (0x7f << 16), 0, BL2_INIT_STAGE_PWM_INIT | PWM_CFG0, 0},
+ {AO_PIN_MUX_REG1, (3 << 16), (0xF << 16), 0, BL2_INIT_STAGE_PWM_INIT | PWM_CFG0, 0},
+ /* VDDEE_VAL_REG1: VDDEE PWM table 0.69v-0.89v*/
+ {AO_PWM_PWM_B, VDDEE_VAL_REG1, 0xffffffff, 0, BL2_INIT_STAGE_PWM_INIT | PWM_CFG1, 0},
+ {AO_PWM_MISC_REG_AB, ((1 << 23) | (1 << 1)), (0x7f << 16), 0, BL2_INIT_STAGE_PWM_INIT | PWM_CFG1, 0},
+ {AO_PIN_MUX_REG1, (3 << 16), (0xF << 16), 0, BL2_INIT_STAGE_PWM_INIT | PWM_CFG1, 0},
+ /* VDDEE init done */
+ /* Enable 5V_EN */
+#if 0 // FIXME
+ {GPIO_O_EN_N_REG3, (0 << 8), (1 << 8), 0, BL2_INIT_STAGE_1, 0},
+ {GPIO_O_REG3, (1 << 8), 0xffffffff, 0, BL2_INIT_STAGE_1, 0},
+#endif
+ /* Enable VCCK */
+ {AO_SEC_REG0, (1 << 0), 0xffffffff, 0, BL2_INIT_STAGE_1, 0},
+ {AO_GPIO_O, (1 << 31), 0xffffffff, 0, BL2_INIT_STAGE_1, 0},
+
+ /* Init sys led*/
+ {AO_GPIO_O_EN_N, (0 << 11), (1 << 11), 0, BL2_INIT_STAGE_1, 0},
+ {AO_GPIO_O, (0 << 11), (1 << 11), 0, BL2_INIT_STAGE_1, 0},
+};
diff --git a/board/hardkernel/odroidc4/odroidc4.c b/board/hardkernel/odroidc4/odroidc4.c
new file mode 100644
index 0000000000..0879573cbf
--- /dev/null
+++ b/board/hardkernel/odroidc4/odroidc4.c
@@ -0,0 +1,416 @@
+/*
+ * board/hardkernel/odroidc4/odroidc4.c
+ *
+ * (C) Copyright 2019 Hardkernel Co., Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <environment.h>
+#include <fdt_support.h>
+#include <libfdt.h>
+#include <asm/cpu_id.h>
+#include <asm/arch/secure_apb.h>
+#ifdef CONFIG_SYS_I2C_AML
+#include <aml_i2c.h>
+#endif
+#ifdef CONFIG_AML_VPU
+#include <vpu.h>
+#endif
+#include <vpp.h>
+#ifdef CONFIG_AML_HDMITX20
+#include <amlogic/hdmi.h>
+#endif
+#include <asm/arch/eth_setup.h>
+#include <phy.h>
+#include <linux/mtd/partitions.h>
+#include <linux/sizes.h>
+#include <asm-generic/gpio.h>
+#include <dm.h>
+#ifdef CONFIG_AML_SPIFC
+#include <amlogic/spifc.h>
+#endif
+
+#include <odroid-common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+//new static eth setup
+struct eth_board_socket* eth_board_skt;
+
+
+int serial_set_pin_port(unsigned long port_base)
+{
+ //UART in "Always On Module"
+ //GPIOAO_0==tx,GPIOAO_1==rx
+ //setbits_le32(P_AO_RTI_PIN_MUX_REG,3<<11);
+ return 0;
+}
+
+int dram_init(void)
+{
+ gd->ram_size = (((readl(AO_SEC_GP_CFG0)) & 0xFFFF0000) << 4);
+ return 0;
+}
+
+/* secondary_boot_func
+ * this function should be write with asm, here, is is only for compiling pass
+ * */
+void secondary_boot_func(void)
+{
+}
+
+#ifdef ETHERNET_EXTERNAL_PHY
+
+static int dwmac_meson_cfg_drive_strength(void)
+{
+ writel(0xaaaaaaa5, P_PAD_DS_REG4A);
+ return 0;
+}
+
+static void setup_net_chip_ext(void)
+{
+ eth_aml_reg0_t eth_reg0;
+ writel(0x11111111, P_PERIPHS_PIN_MUX_6);
+ writel(0x111111, P_PERIPHS_PIN_MUX_7);
+
+ eth_reg0.d32 = 0;
+ eth_reg0.b.phy_intf_sel = 1;
+ eth_reg0.b.rx_clk_rmii_invert = 0;
+ eth_reg0.b.rgmii_tx_clk_src = 0;
+ eth_reg0.b.rgmii_tx_clk_phase = 1;
+ eth_reg0.b.rgmii_tx_clk_ratio = 4;
+ eth_reg0.b.phy_ref_clk_enable = 1;
+ eth_reg0.b.clk_rmii_i_invert = 0;
+ eth_reg0.b.clk_en = 1;
+ eth_reg0.b.adj_enable = 0;
+ eth_reg0.b.adj_setup = 0;
+ eth_reg0.b.adj_delay = 0;
+ eth_reg0.b.adj_skew = 0;
+ eth_reg0.b.cali_start = 0;
+ eth_reg0.b.cali_rise = 0;
+ eth_reg0.b.cali_sel = 0;
+ eth_reg0.b.rgmii_rx_reuse = 0;
+ eth_reg0.b.eth_urgent = 0;
+ setbits_le32(P_PREG_ETH_REG0, eth_reg0.d32);// rmii mode
+
+ setbits_le32(HHI_GCLK_MPEG1, 0x1 << 3);
+ /* power on memory */
+ clrbits_le32(HHI_MEM_PD_REG0, (1 << 3) | (1<<2));
+}
+#endif
+extern struct eth_board_socket* eth_board_setup(char *name);
+extern int designware_initialize(ulong base_addr, u32 interface);
+
+int board_eth_init(bd_t *bis)
+{
+#ifdef ETHERNET_EXTERNAL_PHY
+ dwmac_meson_cfg_drive_strength();
+ setup_net_chip_ext();
+#endif
+ udelay(1000);
+ designware_initialize(ETH_BASE, PHY_INTERFACE_MODE_RMII);
+ return 0;
+}
+
+#if CONFIG_AML_SD_EMMC
+#include <mmc.h>
+#include <asm/arch/sd_emmc.h>
+static int sd_emmc_init(unsigned port)
+{
+ switch (port)
+ {
+ case SDIO_PORT_A:
+ break;
+ case SDIO_PORT_B:
+ //todo add card detect
+ /* check card detect */
+ clrbits_le32(P_PERIPHS_PIN_MUX_9, 0xF << 24);
+ setbits_le32(P_PREG_PAD_GPIO1_EN_N, 1 << 6);
+ setbits_le32(P_PAD_PULL_UP_EN_REG1, 1 << 6);
+ setbits_le32(P_PAD_PULL_UP_REG1, 1 << 6);
+ break;
+ case SDIO_PORT_C:
+ //enable pull up
+ //clrbits_le32(P_PAD_PULL_UP_REG3, 0xff<<0);
+ break;
+ default:
+ break;
+ }
+
+ return cpu_sd_emmc_init(port);
+}
+
+extern unsigned sd_debug_board_1bit_flag;
+
+
+static void sd_emmc_pwr_prepare(unsigned port)
+{
+ cpu_sd_emmc_pwr_prepare(port);
+}
+
+static void sd_emmc_pwr_on(unsigned port)
+{
+ switch (port)
+ {
+ case SDIO_PORT_A:
+ break;
+ case SDIO_PORT_B:
+ // clrbits_le32(P_PREG_PAD_GPIO5_O,(1<<31)); //CARD_8
+ // clrbits_le32(P_PREG_PAD_GPIO5_EN_N,(1<<31));
+ /// @todo NOT FINISH
+ break;
+ case SDIO_PORT_C:
+ break;
+ default:
+ break;
+ }
+ return;
+}
+static void sd_emmc_pwr_off(unsigned port)
+{
+ /// @todo NOT FINISH
+ switch (port)
+ {
+ case SDIO_PORT_A:
+ break;
+ case SDIO_PORT_B:
+ // setbits_le32(P_PREG_PAD_GPIO5_O,(1<<31)); //CARD_8
+ // clrbits_le32(P_PREG_PAD_GPIO5_EN_N,(1<<31));
+ break;
+ case SDIO_PORT_C:
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+// #define CONFIG_TSD 1
+static void board_mmc_register(unsigned port)
+{
+ struct aml_card_sd_info *aml_priv=cpu_sd_emmc_get(port);
+ if (aml_priv == NULL)
+ return;
+
+ aml_priv->sd_emmc_init=sd_emmc_init;
+ aml_priv->sd_emmc_detect=sd_emmc_detect;
+ aml_priv->sd_emmc_pwr_off=sd_emmc_pwr_off;
+ aml_priv->sd_emmc_pwr_on=sd_emmc_pwr_on;
+ aml_priv->sd_emmc_pwr_prepare=sd_emmc_pwr_prepare;
+ aml_priv->desc_buf = malloc(NEWSD_MAX_DESC_MUN*(sizeof(struct sd_emmc_desc_info)));
+
+ if (NULL == aml_priv->desc_buf)
+ printf(" desc_buf Dma alloc Fail!\n");
+ else
+ printf("aml_priv->desc_buf = 0x%p\n",aml_priv->desc_buf);
+
+ sd_emmc_register(aml_priv);
+}
+int board_mmc_init(bd_t *bis)
+{
+ board_mmc_register(SDIO_PORT_C); // eMMC
+ board_mmc_register(SDIO_PORT_B); // SD card
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_SYS_I2C_AML
+struct aml_i2c_platform g_aml_i2c_plat = {
+ .wait_count = 1000000,
+ .wait_ack_interval = 5,
+ .wait_read_interval = 5,
+ .wait_xfer_interval = 5,
+ .master_no = AML_I2C_MASTER_AO,
+ .use_pio = 0,
+ .master_i2c_speed = AML_I2C_SPPED_400K,
+ .master_ao_pinmux = {
+ .scl_reg = (unsigned long)MESON_I2C_MASTER_AO_GPIOAO_4_REG,
+ .scl_bit = MESON_I2C_MASTER_AO_GPIOAO_4_BIT,
+ .sda_reg = (unsigned long)MESON_I2C_MASTER_AO_GPIOAO_5_REG,
+ .sda_bit = MESON_I2C_MASTER_AO_GPIOAO_5_BIT,
+ }
+};
+#endif
+
+#if defined(CONFIG_BOARD_EARLY_INIT_F)
+int board_early_init_f(void){
+ /*add board early init function here*/
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_USB_XHCI_AMLOGIC_V2
+#include <asm/arch/usb-v2.h>
+#include <asm/arch/gpio.h>
+#define CONFIG_GXL_USB_U2_PORT_NUM 2
+
+#ifdef CONFIG_USB_XHCI_AMLOGIC_USB3_V2
+#define CONFIG_GXL_USB_U3_PORT_NUM 1
+#else
+#define CONFIG_GXL_USB_U3_PORT_NUM 0
+#endif
+
+static void gpio_set_vbus_power(char is_power_on)
+{
+ int ret;
+
+ /* USB Host power enable/disable */
+ usbhost_set_power(is_power_on);
+
+ /* usb otg power enable */
+ ret = gpio_request(CONFIG_USB_GPIO_PWR,
+ CONFIG_USB_GPIO_PWR_NAME);
+ if (ret && ret != -EBUSY) {
+ printf("gpio: requesting pin %u failed\n",
+ CONFIG_USB_GPIO_PWR);
+ return;
+ }
+
+ gpio_direction_output(CONFIG_USB_GPIO_PWR, !!is_power_on);
+}
+
+struct amlogic_usb_config g_usb_config_GXL_skt={
+ CONFIG_GXL_XHCI_BASE,
+ USB_ID_MODE_HARDWARE,
+ gpio_set_vbus_power,//gpio_set_vbus_power, //set_vbus_power
+ CONFIG_GXL_USB_PHY2_BASE,
+ CONFIG_GXL_USB_PHY3_BASE,
+ CONFIG_GXL_USB_U2_PORT_NUM,
+ CONFIG_GXL_USB_U3_PORT_NUM,
+ .usb_phy2_pll_base_addr = {
+ CONFIG_USB_PHY_20,
+ CONFIG_USB_PHY_21,
+ }
+};
+
+#endif /*CONFIG_USB_XHCI_AMLOGIC*/
+
+#ifdef CONFIG_AML_HDMITX20
+static void hdmi_tx_set_hdmi_5v(void)
+{
+}
+#endif
+
+#ifdef CONFIG_AML_SPIFC
+/*
+ * BOOT_3: NOR_HOLDn:reg0[15:12]=3
+ * BOOT_4: NOR_D:reg0[19:16]=3
+ * BOOT_5: NOR_Q:reg0[23:20]=3
+ * BOOT_6: NOR_C:reg0[27:24]=3
+ * BOOT_7: NOR_WPn:reg0[31:28]=3
+ * BOOT_14: NOR_CS:reg1[27:24]=3
+ */
+#define SPIFC_NUM_CS 1
+static int spifc_cs_gpios[SPIFC_NUM_CS] = {54};
+
+static int spifc_pinctrl_enable(void *pinctrl, bool enable)
+{
+ unsigned int val;
+
+ val = readl(P_PERIPHS_PIN_MUX_0);
+ val &= ~(0xfffff << 12);
+ if (enable)
+ val |= 0x33333 << 12;
+ writel(val, P_PERIPHS_PIN_MUX_0);
+
+ val = readl(P_PERIPHS_PIN_MUX_1);
+ val &= ~(0xf << 24);
+ writel(val, P_PERIPHS_PIN_MUX_1);
+ return 0;
+}
+
+static const struct spifc_platdata spifc_platdata = {
+ .reg = 0xffd14000,
+ .mem_map = 0xf6000000,
+ .pinctrl_enable = spifc_pinctrl_enable,
+ .num_chipselect = SPIFC_NUM_CS,
+ .cs_gpios = spifc_cs_gpios,
+};
+
+U_BOOT_DEVICE(spifc) = {
+ .name = "spifc",
+ .platdata = &spifc_platdata,
+};
+#endif /* CONFIG_AML_SPIFC */
+
+int board_init(void)
+{
+ board_led_alive(1);
+
+#ifdef CONFIG_USB_XHCI_AMLOGIC_V2
+ board_usb_pll_disable(&g_usb_config_GXL_skt);
+ board_usb_init(&g_usb_config_GXL_skt,BOARD_USB_MODE_HOST);
+#endif /*CONFIG_USB_XHCI_AMLOGIC*/
+
+ return 0;
+}
+
+#if !defined(CONFIG_FASTBOOT_FLASH_MMC_DEV)
+#define CONFIG_FASTBOOT_FLASH_MMC_DEV 0
+#endif
+
+extern void cvbs_init(void);
+
+#ifdef CONFIG_BOARD_LATE_INIT
+int board_late_init(void)
+{
+#if defined(CONFIG_FASTBOOT_FLASH_MMC_DEV)
+ /* select the default mmc device */
+ int mmc_devnum = CONFIG_FASTBOOT_FLASH_MMC_DEV;
+
+ if (get_boot_device() == BOOT_DEVICE_EMMC)
+ mmc_devnum = 0;
+ else if (get_boot_device() == BOOT_DEVICE_SD)
+ mmc_devnum = 1;
+
+ /* select the default mmc device */
+ mmc_select_hwpart(mmc_devnum, 0);
+#endif
+#ifdef CONFIG_AML_VPU
+ vpu_probe();
+#endif
+ vpp_init();
+#ifdef CONFIG_AML_HDMITX20
+ hdmi_tx_set_hdmi_5v();
+ hdmi_tx_init();
+#endif
+
+#ifdef CONFIG_AML_CVBS
+ run_command("cvbs init; cvbs output 480cvbs", 0);
+ board_cvbs_probe();
+#endif
+
+ /* boot logo display - 1080p60hz */
+ run_command("showlogo", 0);
+
+ if (get_boot_device() == BOOT_DEVICE_SPI) {
+ setenv("bootdelay", "0");
+ setenv("bootcmd", "run booting_from_spi");
+ }
+
+ usbhost_early_poweron();
+
+ return 0;
+}
+#endif
+
+/* SECTION_SHIFT is 29 that means 512MB size */
+#define SECTION_SHIFT 29
+phys_size_t get_effective_memsize(void)
+{
+ phys_size_t size_aligned;
+
+ size_aligned = (((readl(AO_SEC_GP_CFG0)) & 0xFFFF0000) << 4);
+ size_aligned = ((size_aligned >> SECTION_SHIFT) << SECTION_SHIFT);
+
+#if defined(CONFIG_SYS_MEM_TOP_HIDE)
+ size_aligned = size_aligned - CONFIG_SYS_MEM_TOP_HIDE;
+#endif
+
+ return size_aligned;
+}
diff --git a/configs/odroidc4_defconfig b/configs/odroidc4_defconfig
new file mode 100644
index 0000000000..d8e5d0234a
--- /dev/null
+++ b/configs/odroidc4_defconfig
@@ -0,0 +1,6 @@
+CONFIG_ARM=y
+CONFIG_TARGET_MESON_G12A=y
+CONFIG_ODROID_C4=y
+CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_AML_GPIO=y
diff --git a/include/configs/odroidc4.h b/include/configs/odroidc4.h
new file mode 100644
index 0000000000..8b6c735b34
--- /dev/null
+++ b/include/configs/odroidc4.h
@@ -0,0 +1,17 @@
+/*
+ * include/configs/odroidc4.h
+ *
+ * (C) Copyright 2018 Hardkernel Co., Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __ODROID_C4_H__
+#define __ODROID_C4_H__
+
+#define CONFIG_DEVICE_PRODUCT "odroidc4"
+#define ODROID_BOARD_UUID "9098004a-a1dd-11e8-98d0-529269fb1459"
+
+#include "odroid-g12-common.h"
+
+#endif