17237d22bSSergey Kostanbaev /*
27237d22bSSergey Kostanbaev * Board initialization for EP93xx
37237d22bSSergey Kostanbaev *
47237d22bSSergey Kostanbaev * Copyright (C) 2013
57237d22bSSergey Kostanbaev * Sergey Kostanbaev <sergey.kostanbaev <at> fairwaves.ru>
67237d22bSSergey Kostanbaev *
77237d22bSSergey Kostanbaev * Copyright (C) 2009
87237d22bSSergey Kostanbaev * Matthias Kaehlcke <matthias <at> kaehlcke.net>
97237d22bSSergey Kostanbaev *
107237d22bSSergey Kostanbaev * (C) Copyright 2002 2003
117237d22bSSergey Kostanbaev * Network Audio Technologies, Inc. <www.netaudiotech.com>
127237d22bSSergey Kostanbaev * Adam Bezanson <bezanson <at> netaudiotech.com>
137237d22bSSergey Kostanbaev *
147237d22bSSergey Kostanbaev * SPDX-License-Identifier: GPL-2.0+
157237d22bSSergey Kostanbaev */
167237d22bSSergey Kostanbaev
177237d22bSSergey Kostanbaev #include <config.h>
187237d22bSSergey Kostanbaev #include <common.h>
197237d22bSSergey Kostanbaev #include <netdev.h>
207237d22bSSergey Kostanbaev #include <asm/io.h>
21*c62db35dSSimon Glass #include <asm/mach-types.h>
227237d22bSSergey Kostanbaev #include <asm/arch/ep93xx.h>
237237d22bSSergey Kostanbaev
247237d22bSSergey Kostanbaev DECLARE_GLOBAL_DATA_PTR;
257237d22bSSergey Kostanbaev
267237d22bSSergey Kostanbaev /*
277237d22bSSergey Kostanbaev * usb_div: 4, nbyp2: 1, pll2_en: 1
287237d22bSSergey Kostanbaev * pll2_x1: 368640000.000000, pll2_x2ip: 15360000.000000,
297237d22bSSergey Kostanbaev * pll2_x2: 384000000.000000, pll2_out: 192000000.000000
307237d22bSSergey Kostanbaev */
317237d22bSSergey Kostanbaev #define CLKSET2_VAL (23 << SYSCON_CLKSET_PLL_X2IPD_SHIFT | \
327237d22bSSergey Kostanbaev 24 << SYSCON_CLKSET_PLL_X2FBD2_SHIFT | \
337237d22bSSergey Kostanbaev 24 << SYSCON_CLKSET_PLL_X1FBD1_SHIFT | \
347237d22bSSergey Kostanbaev 1 << SYSCON_CLKSET_PLL_PS_SHIFT | \
357237d22bSSergey Kostanbaev SYSCON_CLKSET2_PLL2_EN | \
367237d22bSSergey Kostanbaev SYSCON_CLKSET2_NBYP2 | \
377237d22bSSergey Kostanbaev 3 << SYSCON_CLKSET2_USB_DIV_SHIFT)
387237d22bSSergey Kostanbaev
397237d22bSSergey Kostanbaev #define SMC_BCR6_VALUE (2 << SMC_BCR_IDCY_SHIFT | 5 << SMC_BCR_WST1_SHIFT | \
407237d22bSSergey Kostanbaev SMC_BCR_BLE | 2 << SMC_BCR_WST2_SHIFT | \
417237d22bSSergey Kostanbaev 1 << SMC_BCR_MW_SHIFT)
427237d22bSSergey Kostanbaev
437237d22bSSergey Kostanbaev /* delay execution before timers are initialized */
early_udelay(uint32_t usecs)447237d22bSSergey Kostanbaev static inline void early_udelay(uint32_t usecs)
457237d22bSSergey Kostanbaev {
467237d22bSSergey Kostanbaev /* loop takes 4 cycles at 5.0ns (fastest case, running at 200MHz) */
477237d22bSSergey Kostanbaev register uint32_t loops = (usecs * 1000) / 20;
487237d22bSSergey Kostanbaev
497237d22bSSergey Kostanbaev __asm__ volatile ("1:\n"
507237d22bSSergey Kostanbaev "subs %0, %1, #1\n"
517237d22bSSergey Kostanbaev "bne 1b" : "=r" (loops) : "0" (loops));
527237d22bSSergey Kostanbaev }
537237d22bSSergey Kostanbaev
547237d22bSSergey Kostanbaev #ifndef CONFIG_EP93XX_NO_FLASH_CFG
flash_cfg(void)557237d22bSSergey Kostanbaev static void flash_cfg(void)
567237d22bSSergey Kostanbaev {
577237d22bSSergey Kostanbaev struct smc_regs *smc = (struct smc_regs *)SMC_BASE;
587237d22bSSergey Kostanbaev
597237d22bSSergey Kostanbaev writel(SMC_BCR6_VALUE, &smc->bcr6);
607237d22bSSergey Kostanbaev }
617237d22bSSergey Kostanbaev #else
627237d22bSSergey Kostanbaev #define flash_cfg()
637237d22bSSergey Kostanbaev #endif
647237d22bSSergey Kostanbaev
board_init(void)657237d22bSSergey Kostanbaev int board_init(void)
667237d22bSSergey Kostanbaev {
677237d22bSSergey Kostanbaev /*
687237d22bSSergey Kostanbaev * Setup PLL2, PPL1 has been set during lowlevel init
697237d22bSSergey Kostanbaev */
707237d22bSSergey Kostanbaev struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
717237d22bSSergey Kostanbaev writel(CLKSET2_VAL, &syscon->clkset2);
727237d22bSSergey Kostanbaev
737237d22bSSergey Kostanbaev /*
747237d22bSSergey Kostanbaev * the user's guide recommends to wait at least 1 ms for PLL2 to
757237d22bSSergey Kostanbaev * stabilize
767237d22bSSergey Kostanbaev */
777237d22bSSergey Kostanbaev early_udelay(1000);
787237d22bSSergey Kostanbaev
797237d22bSSergey Kostanbaev /* Go to Async mode */
807237d22bSSergey Kostanbaev __asm__ volatile ("mrc p15, 0, r0, c1, c0, 0");
817237d22bSSergey Kostanbaev __asm__ volatile ("orr r0, r0, #0xc0000000");
827237d22bSSergey Kostanbaev __asm__ volatile ("mcr p15, 0, r0, c1, c0, 0");
837237d22bSSergey Kostanbaev
847237d22bSSergey Kostanbaev icache_enable();
857237d22bSSergey Kostanbaev
867237d22bSSergey Kostanbaev #ifdef USE_920T_MMU
877237d22bSSergey Kostanbaev dcache_enable();
887237d22bSSergey Kostanbaev #endif
897237d22bSSergey Kostanbaev
907237d22bSSergey Kostanbaev /* Machine number, as defined in linux/arch/arm/tools/mach-types */
917237d22bSSergey Kostanbaev gd->bd->bi_arch_number = CONFIG_MACH_TYPE;
927237d22bSSergey Kostanbaev
937237d22bSSergey Kostanbaev /* adress of boot parameters */
947237d22bSSergey Kostanbaev gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR;
957237d22bSSergey Kostanbaev
967237d22bSSergey Kostanbaev /* We have a console */
977237d22bSSergey Kostanbaev gd->have_console = 1;
987237d22bSSergey Kostanbaev
997237d22bSSergey Kostanbaev enable_interrupts();
1007237d22bSSergey Kostanbaev
1017237d22bSSergey Kostanbaev flash_cfg();
1027237d22bSSergey Kostanbaev
1037237d22bSSergey Kostanbaev green_led_on();
1047237d22bSSergey Kostanbaev red_led_off();
1057237d22bSSergey Kostanbaev
1067237d22bSSergey Kostanbaev return 0;
1077237d22bSSergey Kostanbaev }
1087237d22bSSergey Kostanbaev
board_early_init_f(void)1097237d22bSSergey Kostanbaev int board_early_init_f(void)
1107237d22bSSergey Kostanbaev {
1117237d22bSSergey Kostanbaev /*
1127237d22bSSergey Kostanbaev * set UARTBAUD bit to drive UARTs with 14.7456MHz instead of
1137237d22bSSergey Kostanbaev * 14.7456/2 MHz
1147237d22bSSergey Kostanbaev */
1157237d22bSSergey Kostanbaev struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
1167237d22bSSergey Kostanbaev writel(SYSCON_PWRCNT_UART_BAUD, &syscon->pwrcnt);
1177237d22bSSergey Kostanbaev return 0;
1187237d22bSSergey Kostanbaev }
1197237d22bSSergey Kostanbaev
board_eth_init(bd_t * bd)1207237d22bSSergey Kostanbaev int board_eth_init(bd_t *bd)
1217237d22bSSergey Kostanbaev {
1227237d22bSSergey Kostanbaev return ep93xx_eth_initialize(0, MAC_BASE);
1237237d22bSSergey Kostanbaev }
1247237d22bSSergey Kostanbaev
dram_fill_bank_addr(unsigned dram_addr_mask,unsigned dram_bank_cnt,unsigned dram_bank_base[CONFIG_NR_DRAM_BANKS])1257237d22bSSergey Kostanbaev static void dram_fill_bank_addr(unsigned dram_addr_mask, unsigned dram_bank_cnt,
1267237d22bSSergey Kostanbaev unsigned dram_bank_base[CONFIG_NR_DRAM_BANKS])
1277237d22bSSergey Kostanbaev {
1287237d22bSSergey Kostanbaev if (dram_bank_cnt == 1) {
1297237d22bSSergey Kostanbaev dram_bank_base[0] = PHYS_SDRAM_1;
1307237d22bSSergey Kostanbaev } else {
1317237d22bSSergey Kostanbaev /* Table lookup for holes in address space. Maximum memory
1327237d22bSSergey Kostanbaev * for the single SDCS may be up to 256Mb. We start scanning
1337237d22bSSergey Kostanbaev * banks from 1Mb, so it could be up to 128 banks theoretically.
1347237d22bSSergey Kostanbaev * We need at maximum 7 bits for the loockup, 8 slots is
1357237d22bSSergey Kostanbaev * enough for the worst case.
1367237d22bSSergey Kostanbaev */
1377237d22bSSergey Kostanbaev unsigned tbl[8];
1387237d22bSSergey Kostanbaev unsigned i = dram_bank_cnt / 2;
1397237d22bSSergey Kostanbaev unsigned j = 0x00100000; /* 1 Mb */
1407237d22bSSergey Kostanbaev unsigned *ptbl = tbl;
1417237d22bSSergey Kostanbaev do {
1427237d22bSSergey Kostanbaev while (!(dram_addr_mask & j)) {
1437237d22bSSergey Kostanbaev j <<= 1;
1447237d22bSSergey Kostanbaev }
1457237d22bSSergey Kostanbaev *ptbl++ = j;
1467237d22bSSergey Kostanbaev j <<= 1;
1477237d22bSSergey Kostanbaev i >>= 1;
1487237d22bSSergey Kostanbaev } while (i != 0);
1497237d22bSSergey Kostanbaev
1507237d22bSSergey Kostanbaev for (i = dram_bank_cnt, j = 0;
1517237d22bSSergey Kostanbaev (i != 0) && (j < CONFIG_NR_DRAM_BANKS); --i, ++j) {
1527237d22bSSergey Kostanbaev unsigned addr = PHYS_SDRAM_1;
1537237d22bSSergey Kostanbaev unsigned k;
1547237d22bSSergey Kostanbaev unsigned bit;
1557237d22bSSergey Kostanbaev
1567237d22bSSergey Kostanbaev for (k = 0, bit = 1; k < 8; k++, bit <<= 1) {
1577237d22bSSergey Kostanbaev if (bit & j)
1587237d22bSSergey Kostanbaev addr |= tbl[k];
1597237d22bSSergey Kostanbaev }
1607237d22bSSergey Kostanbaev
1617237d22bSSergey Kostanbaev dram_bank_base[j] = addr;
1627237d22bSSergey Kostanbaev }
1637237d22bSSergey Kostanbaev }
1647237d22bSSergey Kostanbaev }
1657237d22bSSergey Kostanbaev
1667237d22bSSergey Kostanbaev /* called in board_init_f (before relocation) */
dram_init_banksize_int(int print)1677237d22bSSergey Kostanbaev static unsigned dram_init_banksize_int(int print)
1687237d22bSSergey Kostanbaev {
1697237d22bSSergey Kostanbaev /*
1707237d22bSSergey Kostanbaev * Collect information of banks that has been filled during lowlevel
1717237d22bSSergey Kostanbaev * initialization
1727237d22bSSergey Kostanbaev */
1737237d22bSSergey Kostanbaev unsigned i;
1747237d22bSSergey Kostanbaev unsigned dram_bank_base[CONFIG_NR_DRAM_BANKS];
1757237d22bSSergey Kostanbaev unsigned dram_total = 0;
1767237d22bSSergey Kostanbaev unsigned dram_bank_size = *(unsigned *)
1777237d22bSSergey Kostanbaev (PHYS_SDRAM_1 | UBOOT_MEMORYCNF_BANK_SIZE);
1787237d22bSSergey Kostanbaev unsigned dram_addr_mask = *(unsigned *)
1797237d22bSSergey Kostanbaev (PHYS_SDRAM_1 | UBOOT_MEMORYCNF_BANK_MASK);
1807237d22bSSergey Kostanbaev unsigned dram_bank_cnt = *(unsigned *)
1817237d22bSSergey Kostanbaev (PHYS_SDRAM_1 | UBOOT_MEMORYCNF_BANK_COUNT);
1827237d22bSSergey Kostanbaev
1837237d22bSSergey Kostanbaev dram_fill_bank_addr(dram_addr_mask, dram_bank_cnt, dram_bank_base);
1847237d22bSSergey Kostanbaev
1857237d22bSSergey Kostanbaev for (i = 0; i < dram_bank_cnt; i++) {
1867237d22bSSergey Kostanbaev gd->bd->bi_dram[i].start = dram_bank_base[i];
1877237d22bSSergey Kostanbaev gd->bd->bi_dram[i].size = dram_bank_size;
1887237d22bSSergey Kostanbaev dram_total += dram_bank_size;
1897237d22bSSergey Kostanbaev }
1907237d22bSSergey Kostanbaev for (; i < CONFIG_NR_DRAM_BANKS; i++) {
1917237d22bSSergey Kostanbaev gd->bd->bi_dram[i].start = 0;
1927237d22bSSergey Kostanbaev gd->bd->bi_dram[i].size = 0;
1937237d22bSSergey Kostanbaev }
1947237d22bSSergey Kostanbaev
1957237d22bSSergey Kostanbaev if (print) {
1967237d22bSSergey Kostanbaev printf("DRAM mask: %08x\n", dram_addr_mask);
1977237d22bSSergey Kostanbaev printf("DRAM total %u banks:\n", dram_bank_cnt);
1987237d22bSSergey Kostanbaev printf("bank base-address size\n");
1997237d22bSSergey Kostanbaev
2007237d22bSSergey Kostanbaev if (dram_bank_cnt > CONFIG_NR_DRAM_BANKS) {
2017237d22bSSergey Kostanbaev printf("WARNING! UBoot was configured for %u banks,\n"
2027237d22bSSergey Kostanbaev "but %u has been found. "
2037237d22bSSergey Kostanbaev "Supressing extra memory banks\n",
2047237d22bSSergey Kostanbaev CONFIG_NR_DRAM_BANKS, dram_bank_cnt);
2057237d22bSSergey Kostanbaev dram_bank_cnt = CONFIG_NR_DRAM_BANKS;
2067237d22bSSergey Kostanbaev }
2077237d22bSSergey Kostanbaev
2087237d22bSSergey Kostanbaev for (i = 0; i < dram_bank_cnt; i++) {
2097237d22bSSergey Kostanbaev printf(" %u %08x %08x\n",
2107237d22bSSergey Kostanbaev i, dram_bank_base[i], dram_bank_size);
2117237d22bSSergey Kostanbaev }
2127237d22bSSergey Kostanbaev printf(" ------------------------------------------\n"
2137237d22bSSergey Kostanbaev "Total %9d\n\n",
2147237d22bSSergey Kostanbaev dram_total);
2157237d22bSSergey Kostanbaev }
2167237d22bSSergey Kostanbaev
2177237d22bSSergey Kostanbaev return dram_total;
2187237d22bSSergey Kostanbaev }
2197237d22bSSergey Kostanbaev
dram_init_banksize(void)22076b00acaSSimon Glass int dram_init_banksize(void)
2217237d22bSSergey Kostanbaev {
2227237d22bSSergey Kostanbaev dram_init_banksize_int(0);
22376b00acaSSimon Glass
22476b00acaSSimon Glass return 0;
2257237d22bSSergey Kostanbaev }
2267237d22bSSergey Kostanbaev
2277237d22bSSergey Kostanbaev /* called in board_init_f (before relocation) */
dram_init(void)2287237d22bSSergey Kostanbaev int dram_init(void)
2297237d22bSSergey Kostanbaev {
2307237d22bSSergey Kostanbaev struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
2317237d22bSSergey Kostanbaev unsigned sec_id = readl(SECURITY_EXTENSIONID);
2327237d22bSSergey Kostanbaev unsigned chip_id = readl(&syscon->chipid);
2337237d22bSSergey Kostanbaev
2347237d22bSSergey Kostanbaev printf("CPU: Cirrus Logic ");
2357237d22bSSergey Kostanbaev switch (sec_id & 0x000001FE) {
2367237d22bSSergey Kostanbaev case 0x00000008:
2377237d22bSSergey Kostanbaev printf("EP9301");
2387237d22bSSergey Kostanbaev break;
2397237d22bSSergey Kostanbaev case 0x00000004:
2407237d22bSSergey Kostanbaev printf("EP9307");
2417237d22bSSergey Kostanbaev break;
2427237d22bSSergey Kostanbaev case 0x00000002:
2437237d22bSSergey Kostanbaev printf("EP931x");
2447237d22bSSergey Kostanbaev break;
2457237d22bSSergey Kostanbaev case 0x00000000:
2467237d22bSSergey Kostanbaev printf("EP9315");
2477237d22bSSergey Kostanbaev break;
2487237d22bSSergey Kostanbaev default:
2497237d22bSSergey Kostanbaev printf("<unknown>");
2507237d22bSSergey Kostanbaev break;
2517237d22bSSergey Kostanbaev }
2527237d22bSSergey Kostanbaev
2537237d22bSSergey Kostanbaev printf(" - Rev. ");
2547237d22bSSergey Kostanbaev switch (chip_id & 0xF0000000) {
2557237d22bSSergey Kostanbaev case 0x00000000:
2567237d22bSSergey Kostanbaev printf("A");
2577237d22bSSergey Kostanbaev break;
2587237d22bSSergey Kostanbaev case 0x10000000:
2597237d22bSSergey Kostanbaev printf("B");
2607237d22bSSergey Kostanbaev break;
2617237d22bSSergey Kostanbaev case 0x20000000:
2627237d22bSSergey Kostanbaev printf("C");
2637237d22bSSergey Kostanbaev break;
2647237d22bSSergey Kostanbaev case 0x30000000:
2657237d22bSSergey Kostanbaev printf("D0");
2667237d22bSSergey Kostanbaev break;
2677237d22bSSergey Kostanbaev case 0x40000000:
2687237d22bSSergey Kostanbaev printf("D1");
2697237d22bSSergey Kostanbaev break;
2707237d22bSSergey Kostanbaev case 0x50000000:
2717237d22bSSergey Kostanbaev printf("E0");
2727237d22bSSergey Kostanbaev break;
2737237d22bSSergey Kostanbaev case 0x60000000:
2747237d22bSSergey Kostanbaev printf("E1");
2757237d22bSSergey Kostanbaev break;
2767237d22bSSergey Kostanbaev case 0x70000000:
2777237d22bSSergey Kostanbaev printf("E2");
2787237d22bSSergey Kostanbaev break;
2797237d22bSSergey Kostanbaev default:
2807237d22bSSergey Kostanbaev printf("?");
2817237d22bSSergey Kostanbaev break;
2827237d22bSSergey Kostanbaev }
2837237d22bSSergey Kostanbaev printf(" (SecExtID=%.8x/ChipID=%.8x)\n", sec_id, chip_id);
2847237d22bSSergey Kostanbaev
2857237d22bSSergey Kostanbaev gd->ram_size = dram_init_banksize_int(1);
2867237d22bSSergey Kostanbaev return 0;
2877237d22bSSergey Kostanbaev }
288