523 lines
11 KiB
C
523 lines
11 KiB
C
/*
|
|
* Copyright (C) 2015 Hardkernel Co,. Ltd
|
|
* Dongjin Kim <[email protected]>
|
|
*
|
|
* 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
|