#include <common.h>
#include <config.h>
+#include <cpu_func.h>
+#include <env.h>
+#include <init.h>
+#include <irq_func.h>
#include <linux/printk.h>
#include <linux/kernel.h>
#include <linux/io.h>
#define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000)
#define CREG_CPU_START (CREG_BASE + 0x400)
#define CREG_CPU_START_MASK 0xF
+#define CREG_CPU_START_POL BIT(4)
#define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000)
#define SDIO_UHS_REG_EXT (SDIO_BASE + 0x108)
u32_env nvlim;
u32_env icache;
u32_env dcache;
+ u32_env csm_location;
+ u32_env l2_cache;
};
/*
{ "non_volatile_limit", ENV_HEX, true, 0, 0xF, &env_common.nvlim },
{ "icache_ena", ENV_HEX, true, 0, 1, &env_common.icache },
{ "dcache_ena", ENV_HEX, true, 0, 1, &env_common.dcache },
+#if defined(CONFIG_BOARD_HSDK_4XD)
+ { "l2_cache_ena", ENV_HEX, true, 0, 1, &env_common.l2_cache },
+ { "csm_location", ENV_HEX, true, 0, NO_CCM, &env_common.csm_location },
+#endif /* CONFIG_BOARD_HSDK_4XD */
{}
};
{}
};
+enum board_type {
+ T_BOARD_NONE,
+ T_BOARD_HSDK,
+ T_BOARD_HSDK_4XD
+};
+
+static inline enum board_type get_board_type_runtime(void)
+{
+ u32 arc_id = read_aux_reg(ARC_AUX_IDENTITY) & 0xFF;
+
+ if (arc_id == 0x52)
+ return T_BOARD_HSDK;
+ else if (arc_id == 0x54)
+ return T_BOARD_HSDK_4XD;
+ else
+ return T_BOARD_NONE;
+}
+
+static inline enum board_type get_board_type_config(void)
+{
+ if (IS_ENABLED(CONFIG_BOARD_HSDK))
+ return T_BOARD_HSDK;
+ else if (IS_ENABLED(CONFIG_BOARD_HSDK_4XD))
+ return T_BOARD_HSDK_4XD;
+ else
+ return T_BOARD_NONE;
+}
+
+static bool is_board_match_runtime(enum board_type type_req)
+{
+ return get_board_type_runtime() == type_req;
+}
+
+static bool is_board_match_config(enum board_type type_req)
+{
+ return get_board_type_config() == type_req;
+}
+
+static const char * board_name(enum board_type type)
+{
+ switch (type) {
+ case T_BOARD_HSDK:
+ return "ARC HS Development Kit";
+ case T_BOARD_HSDK_4XD:
+ return "ARC HS4x/HS4xD Development Kit";
+ default:
+ return "?";
+ }
+}
+
+static bool board_mismatch(void)
+{
+ return get_board_type_config() != get_board_type_runtime();
+}
+
static void sync_cross_cpu_data(void)
{
u32 value;
flush_dcache_all();
write_aux_reg(ARC_AUX_NON_VOLATILE_LIMIT, val);
- write_aux_reg(AUX_AUX_CACHE_LIMIT, val);
+ /* AUX_AUX_CACHE_LIMIT reg is missing starting from HS48 */
+ if (is_board_match_runtime(T_BOARD_HSDK))
+ write_aux_reg(AUX_AUX_CACHE_LIMIT, val);
flush_n_invalidate_dcache_all();
}
+static void init_cluster_slc(void)
+{
+ /* ARC HS38 doesn't support SLC disabling */
+ if (!is_board_match_config(T_BOARD_HSDK_4XD))
+ return;
+
+ if (env_common.l2_cache.val)
+ slc_enable();
+ else
+ slc_disable();
+}
+
+#define CREG_CSM_BASE (CREG_BASE + 0x210)
+
+static void init_cluster_csm(void)
+{
+ /* ARC HS38 in HSDK SoC doesn't include CSM */
+ if (!is_board_match_config(T_BOARD_HSDK_4XD))
+ return;
+
+ if (env_common.csm_location.val == NO_CCM) {
+ write_aux_reg(ARC_AUX_CSM_ENABLE, 0);
+ } else {
+ /*
+ * CSM base address is 256kByte aligned but we allow to map
+ * CSM only to aperture start (256MByte aligned)
+ * The field in CREG_CSM_BASE is in 17:2 bits itself so we need
+ * to shift it.
+ */
+ u32 csm_base = (env_common.csm_location.val * SZ_1K) << 2;
+
+ write_aux_reg(ARC_AUX_CSM_ENABLE, 1);
+ writel(csm_base, (void __iomem *)CREG_CSM_BASE);
+ }
+}
+
static void init_master_icache(void)
{
if (icache_status()) {
__builtin_arc_flag(1);
}
-static void smp_kick_cpu_x(u32 cpu_id)
+static u32 get_masked_cpu_ctart_reg(void)
{
int cmd = readl((void __iomem *)CREG_CPU_START);
+ /*
+ * Quirk for HSDK-4xD - due to HW issues HSDK can use any pulse polarity
+ * and HSDK-4xD require active low polarity of cpu_start pulse.
+ */
+ cmd &= ~CREG_CPU_START_POL;
+
+ cmd &= ~CREG_CPU_START_MASK;
+
+ return cmd;
+}
+
+static void smp_kick_cpu_x(u32 cpu_id)
+{
+ int cmd;
+
if (cpu_id > NR_CPUS)
return;
- cmd &= ~CREG_CPU_START_MASK;
+ cmd = get_masked_cpu_ctart_reg();
cmd |= (1 << cpu_id);
writel(cmd, (void __iomem *)CREG_CPU_START);
}
static u32 prepare_cpu_ctart_reg(void)
{
- int cmd = readl((void __iomem *)CREG_CPU_START);
-
- cmd &= ~CREG_CPU_START_MASK;
-
- return cmd | env_common.core_mask.val;
+ return get_masked_cpu_ctart_reg() | env_common.core_mask.val;
}
/* slave CPU entry for configuration */
* cores.
*/
init_cluster_nvlim();
+ init_cluster_csm();
+ init_cluster_slc();
}
static int check_master_cpu_id(void)
{
int ret;
+ if (board_mismatch()) {
+ printf("ERR: U-boot is not configured for this board!\n");
+ return CMD_RET_FAILURE;
+ }
+
/*
* Check for 'halt' parameter. 'halt' = enter halt-mode just before
* starting the application; can be used for debug.
static bool done = false;
int ret;
+ if (board_mismatch()) {
+ printf("ERR: U-boot is not configured for this board!\n");
+ return CMD_RET_FAILURE;
+ }
+
/* hsdk_init can be run only once */
if (done) {
printf("HSDK HW is already initialized! Please reset the board if you want to change the configuration.\n");
soc_clk_ctl("eth-clk", NULL, CLK_PRINT | CLK_MHZ);
soc_clk_ctl("usb-clk", NULL, CLK_PRINT | CLK_MHZ);
soc_clk_ctl("sdio-clk", NULL, CLK_PRINT | CLK_MHZ);
-/* soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ); */
+ if (is_board_match_runtime(T_BOARD_HSDK_4XD))
+ soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ);
soc_clk_ctl("gfx-core-clk", NULL, CLK_PRINT | CLK_MHZ);
- soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ);
- soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
+ if (is_board_match_runtime(T_BOARD_HSDK)) {
+ soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ);
+ soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
+ }
soc_clk_ctl("dmac-core-clk", NULL, CLK_PRINT | CLK_MHZ);
soc_clk_ctl("dmac-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
soc_clk_ctl("sdio-ref-clk", NULL, CLK_PRINT | CLK_MHZ);
printf("\n");
/* HDMI clock domain */
-/* soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ); */
-/* soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ); */
-/* printf("\n"); */
+ if (is_board_match_runtime(T_BOARD_HSDK_4XD)) {
+ soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ);
+ soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ);
+ printf("\n");
+ }
/* TUN clock domain */
soc_clk_ctl("tun-pll", NULL, CLK_PRINT | CLK_MHZ);
soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ);
soc_clk_ctl("rom-clk", NULL, CLK_PRINT | CLK_MHZ);
soc_clk_ctl("pwm-clk", NULL, CLK_PRINT | CLK_MHZ);
+ if (is_board_match_runtime(T_BOARD_HSDK_4XD))
+ soc_clk_ctl("timer-clk", NULL, CLK_PRINT | CLK_MHZ);
printf("\n");
return CMD_RET_SUCCESS;
*/
init_memory_bridge();
+ /*
+ * Switch SDIO external ciu clock divider from default div-by-8 to
+ * minimum possible div-by-2.
+ */
+ writel(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *)SDIO_UHS_REG_EXT);
+
return 0;
}
return 0;
}
-int board_mmc_getcd(struct mmc *mmc)
-{
- struct dwmci_host *host = mmc->priv;
-
- return !(dwmci_readl(host, DWMCI_CDETECT) & 1);
-}
-
-int board_mmc_init(bd_t *bis)
+int checkboard(void)
{
- struct dwmci_host *host = NULL;
+ printf("Board: Synopsys %s\n", board_name(get_board_type_runtime()));
- host = malloc(sizeof(struct dwmci_host));
- if (!host) {
- printf("dwmci_host malloc fail!\n");
- return 1;
- }
+ if (board_mismatch())
+ printf("WARN: U-boot is configured NOT for this board but for %s!\n",
+ board_name(get_board_type_config()));
- /*
- * Switch SDIO external ciu clock divider from default div-by-8 to
- * minimum possible div-by-2.
- */
- writel(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *)SDIO_UHS_REG_EXT);
-
- memset(host, 0, sizeof(struct dwmci_host));
- host->name = "Synopsys Mobile storage";
- host->ioaddr = (void *)ARC_DWMMC_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 ARC HS Development Kit\n");
return 0;
};