// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2018 Synopsys, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include 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 RESET_REG (void *)(SYSCON_BASE + 0x18) #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 136: writel(readl(PLLCON) & PLL_MASK_0, PLLCON); /* pll_off=1, M=17, N=1, OD=1, PLL_OUT_CLK=136M */ writel((readl(PLLCON) & PLL_MASK_1) | 0x100111, PLLCON); /* pll_off=0, M=17, N=1, OD=1, PLL_OUT_CLK=136M */ writel((readl(PLLCON) & PLL_MASK_2) | 0x100111, 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; /* 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; gd->cpu_clk = fdtdec_get_int(gd->fdt_blob, offset, "clock-frequency", 0); if (!gd->cpu_clk) return -EINVAL; /* If CPU freq > 100 MHz, divide eFLASH clock by 2 */ if (gd->cpu_clk > 100000000) { u32 reg = readl(AHBCKDIV); reg &= ~(0xF << 8); reg |= 2 << 8; writel(reg, AHBCKDIV); } return set_cpu_freq(gd->cpu_clk); } #define IOTDK_RESET_SEQ 0x55AA6699 void reset_cpu(void) { writel(IOTDK_RESET_SEQ, RESET_REG); } int checkboard(void) { puts("Board: Synopsys IoT Development Kit\n"); return 0; };