diff options
Diffstat (limited to 'board/synopsys/iot_devkit/iot_devkit.c')
-rw-r--r-- | board/synopsys/iot_devkit/iot_devkit.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/board/synopsys/iot_devkit/iot_devkit.c b/board/synopsys/iot_devkit/iot_devkit.c new file mode 100644 index 0000000..c185d5c --- /dev/null +++ b/board/synopsys/iot_devkit/iot_devkit.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + */ + +#include <common.h> +#include <malloc.h> +#include <dwmmc.h> +#include <linux/libfdt.h> +#include <fdtdec.h> + +#include <asm/arcregs.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define SYSCON_BASE 0xf000a000 +#define AHBCKDIV (void *)(SYSCON_BASE + 0x04) +#define APBCKDIV (void *)(SYSCON_BASE + 0x08) +#define APBCKEN (void *)(SYSCON_BASE + 0x0C) +#define CLKSEL (void *)(SYSCON_BASE + 0x24) +#define CLKSTAT (void *)(SYSCON_BASE + 0x28) +#define PLLCON (void *)(SYSCON_BASE + 0x2C) +#define APBCKSEL (void *)(SYSCON_BASE + 0x30) +#define AHBCKEN (void *)(SYSCON_BASE + 0x34) +#define USBPHY_PLL (void *)(SYSCON_BASE + 0x78) +#define USBCFG (void *)(SYSCON_BASE + 0x7c) + +#define PLL_MASK_0 0xffcfffff +#define PLL_MASK_1 0xffcfff00 +#define PLL_MASK_2 0xfbcfff00 + +#define CLKSEL_DEFAULT 0x5a690000 + +static int set_cpu_freq(unsigned int clk) +{ + clk /= 1000000; + + /* Set clk to ext Xtal (LSN value 0) */ + writel(CLKSEL_DEFAULT, CLKSEL); + + switch (clk) { + case 16: + /* Bypass mode */ + return 0; + + case 50: + writel(readl(PLLCON) & PLL_MASK_0, PLLCON); + /* pll_off=1, M=25, N=1, OD=3, PLL_OUT_CLK=50M */ + writel((readl(PLLCON) & PLL_MASK_1) | 0x300191, PLLCON); + /* pll_off=0, M=25, N=1, OD=3, PLL_OUT_CLK=50M */ + writel((readl(PLLCON) & PLL_MASK_2) | 0x300191, PLLCON); + break; + + case 72: + writel(readl(PLLCON) & PLL_MASK_0, PLLCON); + /* pll_off=1, M=18, N=1, OD=2, PLL_OUT_CLK=72M */ + writel((readl(PLLCON) & PLL_MASK_1) | 0x200121, PLLCON); + /* pll_off=0, M=18, N=1, OD=2, PLL_OUT_CLK=72M */ + writel((readl(PLLCON) & PLL_MASK_2) | 0x200121, PLLCON); + break; + + case 100: + writel(readl(PLLCON) & PLL_MASK_0, PLLCON); + /* pll_off=1,M=25, N=1, OD=2, PLL_OUT_CLK=100M */ + writel((readl(PLLCON) & PLL_MASK_1) | 0x200191, PLLCON); + /* pll_off=0,M=25, N=1, OD=2, PLL_OUT_CLK=100M */ + writel((readl(PLLCON) & PLL_MASK_2) | 0x200191, PLLCON); + break; + + case 144: + writel(readl(PLLCON) & PLL_MASK_0, PLLCON); + /* pll_off=1, M=18, N=1, OD=1, PLL_OUT_CLK=144M */ + writel((readl(PLLCON) & PLL_MASK_1) | 0x100121, PLLCON); + /* pll_off=0, M=18, N=1, OD=1, PLL_OUT_CLK=144M */ + writel((readl(PLLCON) & PLL_MASK_2) | 0x100121, PLLCON); + break; + + default: + return -EINVAL; + } + + while (!(readl(CLKSTAT) & 0x4)) + ; + + /* Set clk from PLL on bus (LSN = 1) */ + writel(CLKSEL_DEFAULT | BIT(0), CLKSEL); + + return 0; +} + +extern u8 __rom_end[]; +extern u8 __ram_start[]; +extern u8 __ram_end[]; + +/* + * Use mach_cpu_init() for .data section copy as board_early_init_f() will be + * too late: initf_dm() will use a value of "av_" variable from not yet + * initialized (by copy) area. + */ +int mach_cpu_init(void) +{ + int offset, freq; + + /* Don't relocate U-Boot */ + gd->flags |= GD_FLG_SKIP_RELOC; + + /* Copy data from ROM to RAM */ + u8 *src = __rom_end; + u8 *dst = __ram_start; + + while (dst < __ram_end) + *dst++ = *src++; + + /* Enable debug uart */ +#define DEBUG_UART_BASE 0x80014000 +#define DEBUG_UART_DLF_OFFSET 0xc0 + write_aux_reg(DEBUG_UART_BASE + DEBUG_UART_DLF_OFFSET, 1); + + offset = fdt_path_offset(gd->fdt_blob, "/cpu_card/core_clk"); + if (offset < 0) + return offset; + + freq = fdtdec_get_int(gd->fdt_blob, offset, "clock-frequency", 0); + if (!freq) + return -EINVAL; + + /* If CPU freq > 100 MHz, divide eFLASH clock by 2 */ + if (freq > 100000000) { + u32 reg = readl(AHBCKDIV); + + reg &= ~(0xF << 8); + reg |= 2 << 8; + writel(reg, AHBCKDIV); + } + + return set_cpu_freq(freq); +} + +#define ARC_PERIPHERAL_BASE 0xF0000000 +#define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xB000) + +int board_mmc_init(bd_t *bis) +{ + struct dwmci_host *host = NULL; + + host = malloc(sizeof(struct dwmci_host)); + if (!host) { + printf("dwmci_host malloc fail!\n"); + return -ENOMEM; + } + + memset(host, 0, sizeof(struct dwmci_host)); + host->name = "Synopsys Mobile storage"; + host->ioaddr = (void *)SDIO_BASE; + host->buswidth = 4; + host->dev_index = 0; + host->bus_hz = 50000000; + + add_dwmci(host, host->bus_hz / 2, 400000); + + return 0; +} + +int checkboard(void) +{ + puts("Board: Synopsys IoT Development Kit\n"); + return 0; +}; |