blob: 8963d3a5828dc4a315e2f469b572b779a7b0436e [file] [log] [blame]
/*
* Board initialization for EP93xx
*
* Copyright (C) 2013
* Sergey Kostanbaev <sergey.kostanbaev <at> fairwaves.ru>
*
* Copyright (C) 2009
* Matthias Kaehlcke <matthias <at> kaehlcke.net>
*
* (C) Copyright 2002 2003
* Network Audio Technologies, Inc. <www.netaudiotech.com>
* Adam Bezanson <bezanson <at> netaudiotech.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <config.h>
#include <common.h>
#include <netdev.h>
#include <asm/io.h>
#include <asm/arch/ep93xx.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* usb_div: 4, nbyp2: 1, pll2_en: 1
* pll2_x1: 368640000.000000, pll2_x2ip: 15360000.000000,
* pll2_x2: 384000000.000000, pll2_out: 192000000.000000
*/
#define CLKSET2_VAL (23 << SYSCON_CLKSET_PLL_X2IPD_SHIFT | \
24 << SYSCON_CLKSET_PLL_X2FBD2_SHIFT | \
24 << SYSCON_CLKSET_PLL_X1FBD1_SHIFT | \
1 << SYSCON_CLKSET_PLL_PS_SHIFT | \
SYSCON_CLKSET2_PLL2_EN | \
SYSCON_CLKSET2_NBYP2 | \
3 << SYSCON_CLKSET2_USB_DIV_SHIFT)
#define SMC_BCR6_VALUE (2 << SMC_BCR_IDCY_SHIFT | 5 << SMC_BCR_WST1_SHIFT | \
SMC_BCR_BLE | 2 << SMC_BCR_WST2_SHIFT | \
1 << SMC_BCR_MW_SHIFT)
/* delay execution before timers are initialized */
static inline void early_udelay(uint32_t usecs)
{
/* loop takes 4 cycles at 5.0ns (fastest case, running at 200MHz) */
register uint32_t loops = (usecs * 1000) / 20;
__asm__ volatile ("1:\n"
"subs %0, %1, #1\n"
"bne 1b" : "=r" (loops) : "0" (loops));
}
#ifndef CONFIG_EP93XX_NO_FLASH_CFG
static void flash_cfg(void)
{
struct smc_regs *smc = (struct smc_regs *)SMC_BASE;
writel(SMC_BCR6_VALUE, &smc->bcr6);
}
#else
#define flash_cfg()
#endif
int board_init(void)
{
/*
* Setup PLL2, PPL1 has been set during lowlevel init
*/
struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
writel(CLKSET2_VAL, &syscon->clkset2);
/*
* the user's guide recommends to wait at least 1 ms for PLL2 to
* stabilize
*/
early_udelay(1000);
/* Go to Async mode */
__asm__ volatile ("mrc p15, 0, r0, c1, c0, 0");
__asm__ volatile ("orr r0, r0, #0xc0000000");
__asm__ volatile ("mcr p15, 0, r0, c1, c0, 0");
icache_enable();
#ifdef USE_920T_MMU
dcache_enable();
#endif
/* Machine number, as defined in linux/arch/arm/tools/mach-types */
gd->bd->bi_arch_number = CONFIG_MACH_TYPE;
/* adress of boot parameters */
gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR;
/* We have a console */
gd->have_console = 1;
enable_interrupts();
flash_cfg();
green_led_on();
red_led_off();
return 0;
}
int board_early_init_f(void)
{
/*
* set UARTBAUD bit to drive UARTs with 14.7456MHz instead of
* 14.7456/2 MHz
*/
struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
writel(SYSCON_PWRCNT_UART_BAUD, &syscon->pwrcnt);
return 0;
}
int board_eth_init(bd_t *bd)
{
return ep93xx_eth_initialize(0, MAC_BASE);
}
static void dram_fill_bank_addr(unsigned dram_addr_mask, unsigned dram_bank_cnt,
unsigned dram_bank_base[CONFIG_NR_DRAM_BANKS])
{
if (dram_bank_cnt == 1) {
dram_bank_base[0] = PHYS_SDRAM_1;
} else {
/* Table lookup for holes in address space. Maximum memory
* for the single SDCS may be up to 256Mb. We start scanning
* banks from 1Mb, so it could be up to 128 banks theoretically.
* We need at maximum 7 bits for the loockup, 8 slots is
* enough for the worst case.
*/
unsigned tbl[8];
unsigned i = dram_bank_cnt / 2;
unsigned j = 0x00100000; /* 1 Mb */
unsigned *ptbl = tbl;
do {
while (!(dram_addr_mask & j)) {
j <<= 1;
}
*ptbl++ = j;
j <<= 1;
i >>= 1;
} while (i != 0);
for (i = dram_bank_cnt, j = 0;
(i != 0) && (j < CONFIG_NR_DRAM_BANKS); --i, ++j) {
unsigned addr = PHYS_SDRAM_1;
unsigned k;
unsigned bit;
for (k = 0, bit = 1; k < 8; k++, bit <<= 1) {
if (bit & j)
addr |= tbl[k];
}
dram_bank_base[j] = addr;
}
}
}
/* called in board_init_f (before relocation) */
static unsigned dram_init_banksize_int(int print)
{
/*
* Collect information of banks that has been filled during lowlevel
* initialization
*/
unsigned i;
unsigned dram_bank_base[CONFIG_NR_DRAM_BANKS];
unsigned dram_total = 0;
unsigned dram_bank_size = *(unsigned *)
(PHYS_SDRAM_1 | UBOOT_MEMORYCNF_BANK_SIZE);
unsigned dram_addr_mask = *(unsigned *)
(PHYS_SDRAM_1 | UBOOT_MEMORYCNF_BANK_MASK);
unsigned dram_bank_cnt = *(unsigned *)
(PHYS_SDRAM_1 | UBOOT_MEMORYCNF_BANK_COUNT);
dram_fill_bank_addr(dram_addr_mask, dram_bank_cnt, dram_bank_base);
for (i = 0; i < dram_bank_cnt; i++) {
gd->bd->bi_dram[i].start = dram_bank_base[i];
gd->bd->bi_dram[i].size = dram_bank_size;
dram_total += dram_bank_size;
}
for (; i < CONFIG_NR_DRAM_BANKS; i++) {
gd->bd->bi_dram[i].start = 0;
gd->bd->bi_dram[i].size = 0;
}
if (print) {
printf("DRAM mask: %08x\n", dram_addr_mask);
printf("DRAM total %u banks:\n", dram_bank_cnt);
printf("bank base-address size\n");
if (dram_bank_cnt > CONFIG_NR_DRAM_BANKS) {
printf("WARNING! UBoot was configured for %u banks,\n"
"but %u has been found. "
"Supressing extra memory banks\n",
CONFIG_NR_DRAM_BANKS, dram_bank_cnt);
dram_bank_cnt = CONFIG_NR_DRAM_BANKS;
}
for (i = 0; i < dram_bank_cnt; i++) {
printf(" %u %08x %08x\n",
i, dram_bank_base[i], dram_bank_size);
}
printf(" ------------------------------------------\n"
"Total %9d\n\n",
dram_total);
}
return dram_total;
}
void dram_init_banksize(void)
{
dram_init_banksize_int(0);
}
/* called in board_init_f (before relocation) */
int dram_init(void)
{
struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
unsigned sec_id = readl(SECURITY_EXTENSIONID);
unsigned chip_id = readl(&syscon->chipid);
printf("CPU: Cirrus Logic ");
switch (sec_id & 0x000001FE) {
case 0x00000008:
printf("EP9301");
break;
case 0x00000004:
printf("EP9307");
break;
case 0x00000002:
printf("EP931x");
break;
case 0x00000000:
printf("EP9315");
break;
default:
printf("<unknown>");
break;
}
printf(" - Rev. ");
switch (chip_id & 0xF0000000) {
case 0x00000000:
printf("A");
break;
case 0x10000000:
printf("B");
break;
case 0x20000000:
printf("C");
break;
case 0x30000000:
printf("D0");
break;
case 0x40000000:
printf("D1");
break;
case 0x50000000:
printf("E0");
break;
case 0x60000000:
printf("E1");
break;
case 0x70000000:
printf("E2");
break;
default:
printf("?");
break;
}
printf(" (SecExtID=%.8x/ChipID=%.8x)\n", sec_id, chip_id);
gd->ram_size = dram_init_banksize_int(1);
return 0;
}
#ifdef CONFIG_EP93XX_SPI
#include <spi.h>
/*
* EGIO0-EGIPO7 -> port A
* EGIO8-EGIP15 -> port B
*/
static void ep93xx_set_epgio(unsigned num)
{
struct gpio_regs *regs = (struct gpio_regs *)GPIO_BASE;
if (num < 8)
writel(readl(&regs->padr) | (1<<num), &regs->padr);
else
writel(readl(&regs->pbdr) | (1<<(num-8)), &regs->pbdr);
}
static void ep93xx_clear_epgio(unsigned num)
{
struct gpio_regs *regs = (struct gpio_regs *)GPIO_BASE;
if (num < 8)
writel(readl(&regs->padr) & (~(1<<num)), &regs->padr);
else
writel(readl(&regs->pbdr) & (~(1<<(num-8))), &regs->pbdr);
}
static void ep93xx_dir_epgio_out(unsigned num)
{
struct gpio_regs *regs = (struct gpio_regs *)GPIO_BASE;
if (num < 8)
writel(readl(&regs->paddr) | (1<<num), &regs->paddr);
else
writel(readl(&regs->pbddr) | (1<<(num-8)), &regs->pbddr);
}
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
{
if (bus == 0 && cs < 16)
return 1;
return 0;
}
void spi_cs_activate(struct spi_slave *slave)
{
ep93xx_clear_epgio(slave->cs);
}
void spi_cs_deactivate(struct spi_slave *slave)
{
ep93xx_set_epgio(slave->cs);
}
#ifdef CONFIG_MMC_SPI
#include <mmc.h>
#ifndef CONFIG_MMC_SPI_CS_EPGIO
# define CONFIG_MMC_SPI_CS_EPGIO 4
#endif
#ifndef CONFIG_MMC_SPI_SPEED
# define CONFIG_MMC_SPI_SPEED 25000000
#endif
#ifndef CONFIG_MMC_SPI_MODE
# define CONFIG_MMC_SPI_MODE SPI_MODE_0
#endif
int board_mmc_init(bd_t *bis)
{
struct gpio_regs *regs = (struct gpio_regs *)GPIO_BASE;
ep93xx_set_epgio(CONFIG_MMC_SPI_CS_EPGIO);
ep93xx_dir_epgio_out(CONFIG_MMC_SPI_CS_EPGIO);
#ifdef CONFIG_MMC_SPI_POWER_EGPIO
ep93xx_dir_epgio_out(CONFIG_MMC_SPI_POWER_EGPIO);
ep93xx_set_epgio(CONFIG_MMC_SPI_POWER_EGPIO);
#elif defined(CONFIG_MMC_SPI_NPOWER_EGPIO)
ep93xx_dir_epgio_out(CONFIG_MMC_SPI_NPOWER_EGPIO);
ep93xx_clear_epgio(CONFIG_MMC_SPI_NPOWER_EGPIO);
#endif
struct mmc *mmc = mmc_spi_init(0, CONFIG_MMC_SPI_CS_EPGIO,
CONFIG_MMC_SPI_SPEED, CONFIG_MMC_SPI_MODE);
if (!mmc) {
printf("Failed to create MMC Device\n");
return 1;
}
mmc_init(mmc);
return 0;
}
#endif /* CONFIG_MMC_SPI */
#endif /* CONFIG_EP93XX_SPI */