/* 
 | 
 * (C) Heiko Schocher, DENX Software Engineering, hs@denx.de. 
 | 
 * Based on: 
 | 
 * U-Boot:board/davinci/da8xxevm/da850evm.c 
 | 
 * 
 | 
 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
 | 
 * 
 | 
 * Based on da830evm.c. Original Copyrights follow: 
 | 
 * 
 | 
 * Copyright (C) 2009 Nick Thompson, GE Fanuc, Ltd. <nick.thompson@gefanuc.com> 
 | 
 * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> 
 | 
 * 
 | 
 * SPDX-License-Identifier:    GPL-2.0+ 
 | 
 */ 
 | 
  
 | 
#include <common.h> 
 | 
#include <i2c.h> 
 | 
#include <net.h> 
 | 
#include <netdev.h> 
 | 
#include <spi.h> 
 | 
#include <spi_flash.h> 
 | 
#include <asm/arch/hardware.h> 
 | 
#include <asm/ti-common/davinci_nand.h> 
 | 
#include <asm/arch/emac_defs.h> 
 | 
#include <asm/arch/pinmux_defs.h> 
 | 
#include <asm/io.h> 
 | 
#include <asm/arch/davinci_misc.h> 
 | 
#include <linux/errno.h> 
 | 
#include <asm/gpio.h> 
 | 
#include <hwconfig.h> 
 | 
#include <bootstage.h> 
 | 
#include <asm/mach-types.h> 
 | 
  
 | 
DECLARE_GLOBAL_DATA_PTR; 
 | 
  
 | 
#ifdef CONFIG_DRIVER_TI_EMAC 
 | 
#ifdef CONFIG_DRIVER_TI_EMAC_USE_RMII 
 | 
#define HAS_RMII 1 
 | 
#else 
 | 
#define HAS_RMII 0 
 | 
#endif 
 | 
#endif /* CONFIG_DRIVER_TI_EMAC */ 
 | 
  
 | 
void dsp_lpsc_on(unsigned domain, unsigned int id) 
 | 
{ 
 | 
    dv_reg_p mdstat, mdctl, ptstat, ptcmd; 
 | 
    struct davinci_psc_regs *psc_regs; 
 | 
  
 | 
    psc_regs = davinci_psc0_regs; 
 | 
    mdstat = &psc_regs->psc0.mdstat[id]; 
 | 
    mdctl = &psc_regs->psc0.mdctl[id]; 
 | 
    ptstat = &psc_regs->ptstat; 
 | 
    ptcmd = &psc_regs->ptcmd; 
 | 
  
 | 
    while (*ptstat & (0x1 << domain)) 
 | 
        ; 
 | 
  
 | 
    if ((*mdstat & 0x1f) == 0x03) 
 | 
        return;                 /* Already on and enabled */ 
 | 
  
 | 
    *mdctl |= 0x03; 
 | 
  
 | 
    *ptcmd = 0x1 << domain; 
 | 
  
 | 
    while (*ptstat & (0x1 << domain)) 
 | 
        ; 
 | 
    while ((*mdstat & 0x1f) != 0x03) 
 | 
        ;        /* Probably an overkill... */ 
 | 
} 
 | 
  
 | 
static void dspwake(void) 
 | 
{ 
 | 
    unsigned *resetvect = (unsigned *)DAVINCI_L3CBARAM_BASE; 
 | 
    u32 val; 
 | 
  
 | 
    /* if the device is ARM only, return */ 
 | 
    if ((readl(CHIP_REV_ID_REG) & 0x3f) == 0x10) 
 | 
        return; 
 | 
  
 | 
    if (hwconfig_subarg_cmp_f("dsp", "wake", "no", NULL)) 
 | 
        return; 
 | 
  
 | 
    *resetvect++ = 0x1E000; /* DSP Idle */ 
 | 
    /* clear out the next 10 words as NOP */ 
 | 
    memset(resetvect, 0, sizeof(unsigned) * 10); 
 | 
  
 | 
    /* setup the DSP reset vector */ 
 | 
    writel(DAVINCI_L3CBARAM_BASE, HOST1CFG); 
 | 
  
 | 
    dsp_lpsc_on(1, DAVINCI_LPSC_GEM); 
 | 
    val = readl(PSC0_MDCTL + (15 * 4)); 
 | 
    val |= 0x100; 
 | 
    writel(val, (PSC0_MDCTL + (15 * 4))); 
 | 
} 
 | 
  
 | 
int misc_init_r(void) 
 | 
{ 
 | 
    dspwake(); 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
static const struct pinmux_config gpio_pins[] = { 
 | 
    /* GP7[14] selects bootmode*/ 
 | 
    { pinmux(16), 8, 3 },    /* GP7[14] */ 
 | 
}; 
 | 
  
 | 
const struct pinmux_resource pinmuxes[] = { 
 | 
#ifdef CONFIG_DRIVER_TI_EMAC 
 | 
    PINMUX_ITEM(emac_pins_mdio), 
 | 
#ifdef CONFIG_DRIVER_TI_EMAC_USE_RMII 
 | 
    PINMUX_ITEM(emac_pins_rmii), 
 | 
#else 
 | 
    PINMUX_ITEM(emac_pins_mii), 
 | 
#endif 
 | 
#endif 
 | 
    PINMUX_ITEM(uart2_pins_txrx), 
 | 
    PINMUX_ITEM(uart2_pins_rtscts), 
 | 
    PINMUX_ITEM(uart0_pins_txrx), 
 | 
    PINMUX_ITEM(uart0_pins_rtscts), 
 | 
#ifdef CONFIG_NAND_DAVINCI 
 | 
    PINMUX_ITEM(emifa_pins_cs3), 
 | 
    PINMUX_ITEM(emifa_pins_nand), 
 | 
#endif 
 | 
    PINMUX_ITEM(gpio_pins), 
 | 
}; 
 | 
  
 | 
const int pinmuxes_size = ARRAY_SIZE(pinmuxes); 
 | 
  
 | 
const struct lpsc_resource lpsc[] = { 
 | 
    { DAVINCI_LPSC_AEMIF },    /* NAND, NOR */ 
 | 
    { DAVINCI_LPSC_EMAC },    /* image download */ 
 | 
    { DAVINCI_LPSC_UART2 },    /* console */ 
 | 
    { DAVINCI_LPSC_UART0 },    /* console */ 
 | 
    { DAVINCI_LPSC_GPIO }, 
 | 
}; 
 | 
  
 | 
const int lpsc_size = ARRAY_SIZE(lpsc); 
 | 
  
 | 
#ifndef CONFIG_DA850_EVM_MAX_CPU_CLK 
 | 
#define CONFIG_DA850_EVM_MAX_CPU_CLK    300000000 
 | 
#endif 
 | 
  
 | 
#define REV_AM18X_EVM        0x100 
 | 
  
 | 
/* 
 | 
 * get_board_rev() - setup to pass kernel board revision information 
 | 
 * Returns: 
 | 
 * bit[0-3]    Maximum cpu clock rate supported by onboard SoC 
 | 
 *        0000b - 300 MHz 
 | 
 *        0001b - 372 MHz 
 | 
 *        0010b - 408 MHz 
 | 
 *        0011b - 456 MHz 
 | 
 */ 
 | 
u32 get_board_rev(void) 
 | 
{ 
 | 
    char *s; 
 | 
    u32 maxcpuclk = CONFIG_DA850_EVM_MAX_CPU_CLK; 
 | 
    u32 rev = 0; 
 | 
  
 | 
    s = env_get("maxcpuclk"); 
 | 
    if (s) 
 | 
        maxcpuclk = simple_strtoul(s, NULL, 10); 
 | 
  
 | 
    if (maxcpuclk >= 456000000) 
 | 
        rev = 3; 
 | 
    else if (maxcpuclk >= 408000000) 
 | 
        rev = 2; 
 | 
    else if (maxcpuclk >= 372000000) 
 | 
        rev = 1; 
 | 
#ifdef CONFIG_DA850_AM18X_EVM 
 | 
    rev |= REV_AM18X_EVM; 
 | 
#endif 
 | 
    return rev; 
 | 
} 
 | 
  
 | 
int board_early_init_f(void) 
 | 
{ 
 | 
    /* 
 | 
     * Power on required peripherals 
 | 
     * ARM does not have access by default to PSC0 and PSC1 
 | 
     * assuming here that the DSP bootloader has set the IOPU 
 | 
     * such that PSC access is available to ARM 
 | 
     */ 
 | 
    if (da8xx_configure_lpsc_items(lpsc, ARRAY_SIZE(lpsc))) 
 | 
        return 1; 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
int board_init(void) 
 | 
{ 
 | 
    irq_init(); 
 | 
  
 | 
    /* arch number of the board */ 
 | 
    gd->bd->bi_arch_number = MACH_TYPE_DAVINCI_DA850_EVM; 
 | 
  
 | 
    /* address of boot parameters */ 
 | 
    gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; 
 | 
  
 | 
    /* setup the SUSPSRC for ARM to control emulation suspend */ 
 | 
    writel(readl(&davinci_syscfg_regs->suspsrc) & 
 | 
           ~(DAVINCI_SYSCFG_SUSPSRC_EMAC | DAVINCI_SYSCFG_SUSPSRC_I2C | 
 | 
         DAVINCI_SYSCFG_SUSPSRC_SPI1 | DAVINCI_SYSCFG_SUSPSRC_TIMER0 | 
 | 
         DAVINCI_SYSCFG_SUSPSRC_UART0), 
 | 
           &davinci_syscfg_regs->suspsrc); 
 | 
  
 | 
    /* configure pinmux settings */ 
 | 
    if (davinci_configure_pin_mux_items(pinmuxes, ARRAY_SIZE(pinmuxes))) 
 | 
        return 1; 
 | 
  
 | 
#ifdef CONFIG_DRIVER_TI_EMAC 
 | 
    davinci_emac_mii_mode_sel(HAS_RMII); 
 | 
#endif /* CONFIG_DRIVER_TI_EMAC */ 
 | 
  
 | 
    /* enable the console UART */ 
 | 
    writel((DAVINCI_UART_PWREMU_MGMT_FREE | DAVINCI_UART_PWREMU_MGMT_URRST | 
 | 
        DAVINCI_UART_PWREMU_MGMT_UTRST), 
 | 
#if (CONFIG_SYS_NS16550_COM1 == DAVINCI_UART0_BASE) 
 | 
           &davinci_uart0_ctrl_regs->pwremu_mgmt); 
 | 
#else 
 | 
           &davinci_uart2_ctrl_regs->pwremu_mgmt); 
 | 
#endif 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
#ifdef CONFIG_DRIVER_TI_EMAC 
 | 
/* 
 | 
 * Initializes on-board ethernet controllers. 
 | 
 */ 
 | 
int board_eth_init(bd_t *bis) 
 | 
{ 
 | 
    if (!davinci_emac_initialize()) { 
 | 
        printf("Error: Ethernet init failed!\n"); 
 | 
        return -1; 
 | 
    } 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
#endif /* CONFIG_DRIVER_TI_EMAC */ 
 | 
  
 | 
static int init_led(int gpio, char *name, int val) 
 | 
{ 
 | 
    int ret; 
 | 
  
 | 
    ret = gpio_request(gpio, name); 
 | 
    if (ret) 
 | 
        return -1; 
 | 
    ret = gpio_direction_output(gpio, val); 
 | 
    if (ret) 
 | 
        return -1; 
 | 
  
 | 
    return gpio; 
 | 
} 
 | 
  
 | 
#define LED_ON    0 
 | 
#define LED_OFF    1 
 | 
  
 | 
#if !defined(CONFIG_SPL_BUILD) 
 | 
#ifdef CONFIG_SHOW_BOOT_PROGRESS 
 | 
void show_boot_progress(int status) 
 | 
{ 
 | 
    static int red; 
 | 
    static int green; 
 | 
  
 | 
    if (red == 0) 
 | 
        red = init_led(CONFIG_IPAM390_GPIO_LED_RED, "red", LED_ON); 
 | 
    if (red != CONFIG_IPAM390_GPIO_LED_RED) 
 | 
        return; 
 | 
    if (green == 0) 
 | 
        green = init_led(CONFIG_IPAM390_GPIO_LED_GREEN, "green", 
 | 
                 LED_OFF); 
 | 
    if (green != CONFIG_IPAM390_GPIO_LED_GREEN) 
 | 
        return; 
 | 
  
 | 
    switch (status) { 
 | 
    case BOOTSTAGE_ID_RUN_OS: 
 | 
        /* 
 | 
         * set normal state 
 | 
         * LED Red  : on 
 | 
         * LED green: off 
 | 
         */ 
 | 
        gpio_set_value(red, LED_ON); 
 | 
        gpio_set_value(green, LED_OFF); 
 | 
        break; 
 | 
    case BOOTSTAGE_ID_MAIN_LOOP: 
 | 
        /* 
 | 
         * U-Boot operation 
 | 
         * LED Red  : on 
 | 
         * LED green: on 
 | 
         */ 
 | 
        gpio_set_value(red, LED_ON); 
 | 
        gpio_set_value(green, LED_ON); 
 | 
        break; 
 | 
    } 
 | 
} 
 | 
#endif 
 | 
#endif 
 | 
  
 | 
#ifdef CONFIG_SPL_OS_BOOT 
 | 
int spl_start_uboot(void) 
 | 
{ 
 | 
    int ret; 
 | 
    int bootmode = 0; 
 | 
  
 | 
    /* 
 | 
     * GP7[14] selects bootmode: 
 | 
     * 1: boot linux 
 | 
     * 0: boot u-boot 
 | 
     * if error accessing gpio boot U-Boot 
 | 
     * 
 | 
     * SPL bootmode 
 | 
     * 0: boot linux 
 | 
     * 1: boot u-boot 
 | 
     */ 
 | 
    ret = gpio_request(CONFIG_IPAM390_GPIO_BOOTMODE , "bootmode"); 
 | 
    if (ret) 
 | 
        bootmode = 1; 
 | 
    if (!bootmode) { 
 | 
        ret = gpio_direction_input(CONFIG_IPAM390_GPIO_BOOTMODE); 
 | 
        if (ret) 
 | 
            bootmode = 1; 
 | 
    } 
 | 
    if (!bootmode) 
 | 
        ret = gpio_get_value(CONFIG_IPAM390_GPIO_BOOTMODE); 
 | 
    if (!bootmode) 
 | 
        if (ret == 0) 
 | 
            bootmode = 1; 
 | 
    /* 
 | 
     * LED red  : on 
 | 
     * LED green: off 
 | 
     */ 
 | 
    init_led(CONFIG_IPAM390_GPIO_LED_RED, "red", LED_ON); 
 | 
    init_led(CONFIG_IPAM390_GPIO_LED_GREEN, "green", LED_OFF); 
 | 
    return bootmode; 
 | 
} 
 | 
#endif 
 |