blob: 2d29fb6ed880830ad05dedb1e2f6079a6a13cebe [file] [log] [blame]
/*
* Copyright (C) 2015 Hardkernel Co,. Ltd
* Dongjin Kim <tobetter@gmail.com>
*
* 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/arch/secure_apb.h>
#include <asm/arch/eth_setup.h>
#include <asm/arch-gxb/gpio.h>
#include <asm-generic/gpio.h>
//#include <usb/fastboot.h>
#include <asm/arch/efuse.h>
#ifdef CONFIG_AML_VPU
#include <vpu.h>
#endif
#ifdef CONFIG_AML_HDMITX20
#include <amlogic/hdmi.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
extern int board_get_recovery_message(void);
#define GPIO_SW_UMS 28 /* GPIOY_5 */
#define GPIO_BLUELED 132
#define GPIO_USB_PWREN 123
#define GPIO_OTG_PWREN 124
#define GPIO_TF3V3 35 /* GPIOY_12 */
#define GPIO_TF1V8 122 /* GPIOAO_3 */
#define GPIO_HUB_RST 123 /* GPIOAO_4 */
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 = PHYS_SDRAM_1_SIZE;
return 0;
}
void secondary_boot_func(void)
{
/*
* TODO: should be written in ASM if necessary
*/
}
/*
* Discover the boot device within MicroSD or eMMC
* and return 1 for eMMC, otherwise 0.
*/
#define BOOT_DEVICE_RESERVED 0
#define BOOT_DEVICE_EMMC 1
#define BOOT_DEVICE_NAND 2
#define BOOT_DEVICE_SPI 3
#define BOOT_DEVICE_SD 4
#define BOOT_DEVICE_USB 5
int get_boot_device(void)
{
return readl(AO_SEC_GP_CFG0) & 0xf;
}
/*
* Discover the boot reason:
* 1. check if the board is started with Android Self-Installation.
* 2. if rebooted by 'reboot' command in previous kernel boot.
* 3. Otherwise returns normal boot response by power cycle.
*/
int board_reboot_reason(void)
{
static int __reboot_reason = ODROID_REBOOT_CMD_UNKNOWN;
if (ODROID_REBOOT_CMD_UNKNOWN == __reboot_reason) {
__reboot_reason = board_get_recovery_message();
if (ODROID_REBOOT_CMD_UNKNOWN == __reboot_reason)
__reboot_reason = (readl(AO_SEC_SD_CFG15) >> 12) & 0xf;
}
return __reboot_reason;
}
int board_print_info(void)
{
int i;
int offset, length;
char buf[EFUSE_BYTES];
printf("-------------------------------------------------\n");
printf("* Welcome to Hardkernel's ODROID-C2\n");
printf("-------------------------------------------------\n");
/* CPU */
printf("CPU : AMLogic S905\n");
/* S/N */
offset = 20;
length = 16;
memset(buf, 0, EFUSE_BYTES);
efuse_read_usr(buf, length, (loff_t *)&offset);
buf[length] = '\0';
printf("S/N : ");
printf("%s\n", buf);
/* MAC */
offset = 52;
length = 6;
memset(buf, 0, EFUSE_BYTES);
efuse_read_usr(buf, length, (loff_t *)&offset);
buf[length] = '\0';
printf("MAC : ");
for (i=0;i<(length-1);i++)
printf("%02x:", buf[i]);
printf("%02x\n", buf[i]);
/* BID */
offset = 70;
length = 48;
memset(buf, 0, EFUSE_BYTES);
efuse_read_usr(buf, length, (loff_t *)&offset);
buf[0xA] = '\0';
printf("BID : ");
printf("%s\n", buf);
printf("-------------------------------------------------\n");
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
//setbits_le32(P_PREG_PAD_GPIO5_EN_N,1<<29);//CARD_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 int sd_emmc_detect(unsigned port)
{
int ret;
switch (port) {
case SDIO_PORT_A:
break;
case SDIO_PORT_B:
setbits_le32(P_PREG_PAD_GPIO5_EN_N,1<<29);//CARD_6
ret=readl(P_PREG_PAD_GPIO5_I)&(1<<29)?0:1;
printf("ret = %d .",ret);
if ((readl(P_PERIPHS_PIN_MUX_8)&(3<<9))) { //if uart pinmux set, debug board in
if (!(readl(P_PREG_PAD_GPIO2_I)&(1<<24))) {
printf("sdio debug board detected, sd card with 1bit mode\n");
sd_debug_board_1bit_flag = 1;
}
else{
printf("sdio debug board detected, no sd card in\n");
sd_debug_board_1bit_flag = 0;
return 1;
}
}
break;
default:
break;
}
return 0;
}
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;
}
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)
{
#ifdef CONFIG_VLSI_EMULATOR
//board_mmc_register(SDIO_PORT_A);
#else
//board_mmc_register(SDIO_PORT_B);
#endif
switch (get_boot_device())
{
case BOOT_DEVICE_EMMC:
board_mmc_register(SDIO_PORT_C); // "mmc0"
board_mmc_register(SDIO_PORT_B);
break;
case BOOT_DEVICE_SD:
board_mmc_register(SDIO_PORT_B); // "mmc0"
board_mmc_register(SDIO_PORT_C);
break;
default:
printf("No available mmc device! Check boot device!\n");
do_reset(NULL, 0, 0, NULL);
break;
}
// board_mmc_register(SDIO_PORT_B1);
return 0;
}
#endif
#if defined(CONFIG_SYS_I2C_AML)
#include <aml_i2c.h>
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,
}
};
static void board_i2c_init(void)
{
//disable all other pins which share with I2C_SDA_AO & I2C_SCK_AO
clrbits_le32(P_AO_RTI_PIN_MUX_REG,
(1 << 2) | (1 << 24) | (1 << 1) | (1 << 23));
//enable I2C MASTER AO pins
setbits_le32(P_AO_RTI_PIN_MUX_REG,
(MESON_I2C_MASTER_AO_GPIOAO_4_BIT
| MESON_I2C_MASTER_AO_GPIOAO_5_BIT));
udelay(10);
//Amlogic I2C controller initialized
//note: it must be call before any I2C operation
aml_i2c_init();
udelay(10);
}
#endif
#if defined(CONFIG_BOARD_EARLY_INIT_F)
int board_early_init_f(void)
{
return 0;
}
#endif
#if 0
static void board_run_fastboot(void)
{
run_command("fastboot", 0);
}
static void board_run_recovery(void)
{
run_command("movi read dtb 0 ${dtb_mem_addr}", 0);
run_command("movi read recovery 0 ${loadaddr}", 0);
run_command("bootm ${load_addr}", 0);
}
#endif
#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{
// int reboot_reason;
/*
* If UMS SW is 'on', the device will run as USB Mass Storage
*/
if (1 == gpio_get_value(GPIO_SW_UMS))
run_command("ums 0 mmc 0", 0);
// board_partition_init();
#ifdef CONFIG_DISPLAY_LOGO
run_command("showlogo 720p60hz", 0);
#endif
#if 0
reboot_reason = board_reboot_reason();
if (ODROID_REBOOT_CMD_FASTBOOT == reboot_reason)
board_run_fastboot();
else if (ODROID_REBOOT_CMD_RECOVERY == reboot_reason)
board_run_recovery();
#endif
return 0;
}
#endif
#if defined(CONFIG_USB_DWC_OTG_HCD)
#include <asm/arch/usb.h>
static void callback_otg_power(char power)
{
gpio_direction_output(GPIO_OTG_PWREN, power);
}
static void callback_host_power(char power)
{
gpio_direction_output(GPIO_USB_PWREN, power);
}
static struct amlogic_usb_config usb_config0 = {
.clk_selecter = USB_PHY_CLK_SEL_XTAL,
.pll_divider = 1,
.base_addr = CONFIG_M8_USBPORT_BASE_A,
.id_mode = USB_ID_MODE_SW_HOST,
.set_vbus_power = callback_otg_power,
};
static struct amlogic_usb_config usb_config1= {
.clk_selecter = USB_PHY_CLK_SEL_XTAL,
.pll_divider = 1,
.base_addr = CONFIG_M8_USBPORT_BASE_B,
.id_mode = USB_ID_MODE_SW_HOST,
.set_vbus_power = callback_host_power,
};
struct amlogic_usb_config *amlogic_usb_config(int port)
{
if (0 == port)
return &usb_config0;
else if (1 == port)
return &usb_config1;
return NULL;
}
#endif
int board_init(void)
{
board_print_info();
/* T-Flash Init voltage : T-Flash I/O 3.3V, T-Flash mem 3.3V */
gpio_request(GPIO_TF1V8, "TF_1V8");
gpio_direction_output(GPIO_TF1V8, 0);
gpio_request(GPIO_TF3V3, "TF_3V3");
gpio_direction_output(GPIO_TF3V3, 1);
/* LED: SYSLED (Blue color) */
gpio_request(GPIO_BLUELED, "blueled");
gpio_direction_output(GPIO_BLUELED, 0);
/*
* USB Host: RST_N for GL852
* Off by default, On when USB HOST is activated
*/
gpio_request(GPIO_USB_PWREN, "usb_pwren");
gpio_direction_output(GPIO_USB_PWREN, 0);
/*
* USB OTG: Power
* Off by default, On when USB OTG is activated
*/
gpio_request(GPIO_OTG_PWREN, "otg_pwren");
gpio_direction_output(GPIO_OTG_PWREN, 0);
/*
* GPIO: USB MassStorage
* Low - Normal boot
* High - Act as USB Mass Storage Device
*/
gpio_request(GPIO_SW_UMS, "sw_ums");
gpio_direction_input(GPIO_SW_UMS);
gpio_request(GPIO_HUB_RST, "hub_rst");
gpio_direction_output(GPIO_HUB_RST, 0);
mdelay(20);
gpio_direction_output(GPIO_HUB_RST, 1);
mdelay(20);
#if defined(CONFIG_USB_DWC_OTG_HCD)
board_usb_init(&usb_config0, BOARD_USB_MODE_SLAVE);
board_usb_init(&usb_config1, BOARD_USB_MODE_HOST);
#endif
#ifdef CONFIG_AML_VPU
vpu_probe();
#endif
#ifdef CONFIG_AML_HDMITX20
hdmi_tx_init();
#endif
return 0;
}
phys_size_t get_effective_memsize(void)
{
phys_size_t phys_size = (readl(AO_SEC_GP_CFG0) & 0xFFFF0000) << 4;
#if defined(CONFIG_SYS_MEM_TOP_HIDE)
phys_size -= CONFIG_SYS_MEM_TOP_HIDE;
#endif
return phys_size;
}
#ifdef CONFIG_MULTI_DTB
int checkhw(char * name)
{
unsigned int ddr_size=0;
char loc_name[64] = {0};
int i;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
ddr_size += gd->bd->bi_dram[i].size;
}
#if defined(CONFIG_SYS_MEM_TOP_HIDE)
ddr_size += CONFIG_SYS_MEM_TOP_HIDE;
#endif
switch (ddr_size) {
case 0x80000000:
strcpy(loc_name, "odroidc2_2g\0");
break;
case 0x40000000:
strcpy(loc_name, "odroidc2_1g\0");
break;
case 0x2000000:
strcpy(loc_name, "odroidc2_512m\0");
break;
default:
//printf("DDR size: 0x%x, multi-dt doesn't support\n", ddr_size);
strcpy(loc_name, "odroidc2_unsupport");
break;
}
strcpy(name, loc_name);
setenv("aml_dt", loc_name);
return 0;
}
#endif