OpenWrt – Rev 4

Subversion Repositories:
Rev:
#include <common.h>
#include <spl.h>
#include <phy.h>
#include <netdev.h>
#include <ide.h>
#include <nand.h>
#include <asm/arch/spl.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/clock.h>
#include <asm/arch/sysctl.h>

DECLARE_GLOBAL_DATA_PTR;

#ifdef CONFIG_SPL_BUILD

#ifdef DEBUG
#define DILIGENCE (1048576/4)
static int test_memory(u32 memory)
{
        volatile u32 *read;
        volatile u32 *write;
        const u32 INIT_PATTERN = 0xAA55AA55;
        const u32 INC_PATTERN = 0x01030507;
        u32 pattern;
        int check;
        int i;

        check = 0;
        read = write = (volatile u32 *) memory;
        pattern = INIT_PATTERN;
        for (i = 0; i < DILIGENCE; i++) {
                *write++ = pattern;
                pattern += INC_PATTERN;
        }
        puts("testing\n");
        pattern = INIT_PATTERN;
        for (i = 0; i < DILIGENCE; i++) {
                check += (pattern == *read++) ? 1 : 0;
                pattern += INC_PATTERN;
        }
        return (check == DILIGENCE) ? 0 : -1;
}
#endif

void uart_init(void)
{
        /* Reset UART1 */
        reset_block(SYS_CTRL_RST_UART1, 1);
        udelay(100);
        reset_block(SYS_CTRL_RST_UART1, 0);
        udelay(100);

        /* Setup pin mux'ing for UART1 */
        pinmux_set(PINMUX_BANK_MFA, 30, PINMUX_UARTA_SIN);
        pinmux_set(PINMUX_BANK_MFA, 31, PINMUX_UARTA_SOUT);
}

extern void init_ddr(int mhz);

void board_inithw(void)
{
        int plla_freq;
#ifdef DEBUG
        int i;
#endif  /* DEBUG */

        timer_init();
        uart_init();
        preloader_console_init();

        plla_freq = plla_set_config(CONFIG_PLLA_FREQ_MHZ);
        init_ddr(plla_freq);

#ifdef DEBUG
        if(test_memory(CONFIG_SYS_SDRAM_BASE)) {
                puts("memory test failed\n");
        } else {
                puts("memory test done\n");
        }
#endif /* DEBUG */
#ifdef CONFIG_SPL_BSS_DRAM_START
        extern char __bss_dram_start[];
        extern char __bss_dram_end[];
        memset(&__bss_dram_start, 0, __bss_dram_end - __bss_dram_start);
#endif
}

void board_init_f(ulong dummy)
{
        /* Set the stack pointer. */
        asm volatile("mov sp, %0\n" : : "r"(CONFIG_SPL_STACK));

        /* Clear the BSS. */
        memset(__bss_start, 0, __bss_end - __bss_start);

        /* Set global data pointer. */
        gd = &gdata;

        board_inithw();

        board_init_r(NULL, 0);
}

u32 spl_boot_device(void)
{
        return CONFIG_SPL_BOOT_DEVICE;
}

#ifdef CONFIG_SPL_BLOCK_SUPPORT
void spl_block_device_init(void)
{
        ide_init();
}
#endif

#ifdef CONFIG_SPL_OS_BOOT
int spl_start_uboot(void)
{
        /* break into full u-boot on 'c' */
        return (serial_tstc() && serial_getc() == 'c');
}
#endif

void spl_display_print(void)
{
        /* print a hint, so that we will not use the wrong SPL by mistake */
        puts("  Boot device: " BOOT_DEVICE_TYPE "\n" );
}

void lowlevel_init(void)
{
}

#ifdef USE_DL_PREFIX
/* quick and dirty memory allocation */
static ulong next_mem = CONFIG_SPL_MALLOC_START;

void *memalign(size_t alignment, size_t bytes)
{
        ulong mem = ALIGN(next_mem, alignment);

        next_mem = mem + bytes;

        if (next_mem > CONFIG_SYS_SDRAM_BASE + CONFIG_MIN_SDRAM_SIZE) {
                printf("spl: out of memory\n");
                hang();
        }

        return (void *)mem;
}

void free(void* mem)
{
}
#endif

#endif /* CONFIG_SPL_BUILD */

int board_early_init_f(void)
{
        return 0;
}

#define STATIC_CTL_BANK0                (STATIC_CONTROL_BASE + 4)
#define STATIC_READ_CYCLE_SHIFT         0
#define STATIC_DELAYED_OE               (1 << 7)
#define STATIC_WRITE_CYCLE_SHIFT        8
#define STATIC_WRITE_PULSE_SHIFT        16
#define STATIC_WRITE_BURST_EN           (1 << 23)
#define STATIC_TURN_AROUND_SHIFT        24
#define STATIC_BUFFER_PRESENT           (1 << 28)
#define STATIC_READ_BURST_EN            (1 << 29)
#define STATIC_BUS_WIDTH8               (0 << 30)
#define STATIC_BUS_WIDTH16              (1 << 30)
#define STATIC_BUS_WIDTH32              (2 << 30)

void nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
        struct nand_chip *this = mtd->priv;
        unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;

        if (ctrl & NAND_CTRL_CHANGE) {
                nandaddr &= ~(BIT(NAND_ALE_ADDR_PIN) | BIT(NAND_CLE_ADDR_PIN));
                if (ctrl & NAND_CLE)
                        nandaddr |= BIT(NAND_CLE_ADDR_PIN);
                else if (ctrl & NAND_ALE)
                        nandaddr |= BIT(NAND_ALE_ADDR_PIN);
                this->IO_ADDR_W = (void __iomem *) nandaddr;
        }

        if (cmd != NAND_CMD_NONE)
                writeb(cmd, (void __iomem *) nandaddr);
}

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_BOOT_FROM_NAND)

int nand_dev_ready(struct mtd_info *mtd)
{
        struct nand_chip *chip = mtd->priv;

        udelay(chip->chip_delay);

        return 1;
}

void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
        int i;
        struct nand_chip *chip = mtd->priv;

        for (i = 0; i < len; i++)
                buf[i] = readb(chip->IO_ADDR_R);
}

void nand_dev_reset(struct nand_chip *chip)
{
        writeb(NAND_CMD_RESET, chip->IO_ADDR_W + BIT(NAND_CLE_ADDR_PIN));
        udelay(chip->chip_delay);
        writeb(NAND_CMD_STATUS, chip->IO_ADDR_W + BIT(NAND_CLE_ADDR_PIN));
        while (!(readb(chip->IO_ADDR_R) & NAND_STATUS_READY)) {
                ;
        }
}

#else

#define nand_dev_reset(chip)    /* framework will reset the chip anyway */
#define nand_read_buf           NULL /* framework will provide a default one */
#define nand_dev_ready          NULL /* dev_ready is optional */

#endif

int board_nand_init(struct nand_chip *chip)
{
        /* Block reset Static core */
        reset_block(SYS_CTRL_RST_STATIC, 1);
        reset_block(SYS_CTRL_RST_STATIC, 0);

        /* Enable clock to Static core */
        enable_clock(SYS_CTRL_CLK_STATIC);

        /* enable flash support on static bus.
         * Enable static bus onto GPIOs, only CS0 */
        pinmux_set(PINMUX_BANK_MFA, 12, PINMUX_STATIC_DATA0);
        pinmux_set(PINMUX_BANK_MFA, 13, PINMUX_STATIC_DATA1);
        pinmux_set(PINMUX_BANK_MFA, 14, PINMUX_STATIC_DATA2);
        pinmux_set(PINMUX_BANK_MFA, 15, PINMUX_STATIC_DATA3);
        pinmux_set(PINMUX_BANK_MFA, 16, PINMUX_STATIC_DATA4);
        pinmux_set(PINMUX_BANK_MFA, 17, PINMUX_STATIC_DATA5);
        pinmux_set(PINMUX_BANK_MFA, 18, PINMUX_STATIC_DATA6);
        pinmux_set(PINMUX_BANK_MFA, 19, PINMUX_STATIC_DATA7);

        pinmux_set(PINMUX_BANK_MFA, 20, PINMUX_STATIC_NWE);
        pinmux_set(PINMUX_BANK_MFA, 21, PINMUX_STATIC_NOE);
        pinmux_set(PINMUX_BANK_MFA, 22, PINMUX_STATIC_NCS);
        pinmux_set(PINMUX_BANK_MFA, 23, PINMUX_STATIC_ADDR18);
        pinmux_set(PINMUX_BANK_MFA, 24, PINMUX_STATIC_ADDR19);

        /* Setup the static bus CS0 to access FLASH */

        writel((0x3f << STATIC_READ_CYCLE_SHIFT)
                        | (0x3f << STATIC_WRITE_CYCLE_SHIFT)
                        | (0x1f << STATIC_WRITE_PULSE_SHIFT)
                        | (0x03 << STATIC_TURN_AROUND_SHIFT) |
                        STATIC_BUS_WIDTH16,
                STATIC_CTL_BANK0);

        chip->cmd_ctrl = nand_hwcontrol;
        chip->ecc.mode = NAND_ECC_SOFT;
        chip->chip_delay = 30;
        chip->dev_ready = nand_dev_ready;
        chip->read_buf = nand_read_buf;

        nand_dev_reset(chip);

        return 0;
}

int board_init(void)
{
        gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
        gd->bd->bi_arch_number = MACH_TYPE_OXNAS;

        /* assume uart is already initialized by SPL */

#if defined(CONFIG_START_IDE)
        puts("IDE:   ");
        ide_init();
#endif

        return 0;
}

/* copied from board/evb64260/sdram_init.c */
/*
 * Check memory range for valid RAM. A simple memory test determines
 * the actually available RAM size between addresses `base' and
 * `base + maxsize'. Some (not all) hardware errors are detected:
 * - short between address lines
 * - short between data lines
 */
static long int dram_size (long int *base, long int maxsize)
{
        volatile long int *addr, *b = base;
        long int cnt, val, save1, save2;

#define STARTVAL (CONFIG_MIN_SDRAM_SIZE / 2)    /* start test at half size */
        for (cnt = STARTVAL / sizeof (long); cnt < maxsize / sizeof (long);
             cnt <<= 1) {
                addr = base + cnt;      /* pointer arith! */

                save1 = *addr;  /* save contents of addr */
                save2 = *b;     /* save contents of base */

                *addr = cnt;    /* write cnt to addr */
                *b = 0;         /* put null at base */

                /* check at base address */
                if ((*b) != 0) {
                        *addr = save1;  /* restore *addr */
                        *b = save2;     /* restore *b */
                        return (0);
                }
                val = *addr;    /* read *addr */

                *addr = save1;
                *b = save2;

                if (val != cnt) {
                        /* fix boundary condition.. STARTVAL means zero */
                        if (cnt == STARTVAL / sizeof (long))
                                cnt = 0;
                        return (cnt * sizeof (long));
                }
        }
        return maxsize;
}

int dram_init(void)
{
        gd->ram_size = dram_size((long int *)CONFIG_SYS_SDRAM_BASE,
                                        CONFIG_MAX_SDRAM_SIZE);
        return 0;
}

int board_eth_init(bd_t *bis)
{
        u32 value;

        /* set the pin multiplexers to enable talking to Ethernent Phys */
        pinmux_set(PINMUX_BANK_MFA, 3, PINMUX_MACA_MDC);
        pinmux_set(PINMUX_BANK_MFA, 4, PINMUX_MACA_MDIO);

        // Ensure the MAC block is properly reset
        reset_block(SYS_CTRL_RST_MAC, 1);
        udelay(10);
        reset_block(SYS_CTRL_RST_MAC, 0);

        // Enable the clock to the MAC block
        enable_clock(SYS_CTRL_CLK_MAC);

        value = readl(SYS_CTRL_GMAC_CTRL);
        /* Use simple mux for 25/125 Mhz clock switching */
        value |= BIT(SYS_CTRL_GMAC_SIMPLE_MUX);
        /* Enable GMII_GTXCLK to follow GMII_REFCLK - required for gigabit PHY */
        value |= BIT(SYS_CTRL_GMAC_CKEN_GTX);
        /* set auto tx speed */
        value |= BIT(SYS_CTRL_GMAC_AUTOSPEED);

        writel(value, SYS_CTRL_GMAC_CTRL);

        return designware_initialize(MAC_BASE, PHY_INTERFACE_MODE_RGMII);
}