diff options
-rw-r--r-- | arch/arc/include/asm/arcregs.h | 25 | ||||
-rw-r--r-- | arch/arc/lib/cpu.c | 200 | ||||
-rw-r--r-- | board/synopsys/axs10x/axs10x.c | 8 | ||||
-rw-r--r-- | board/synopsys/emsdp/emsdp.c | 70 | ||||
-rw-r--r-- | board/synopsys/hsdk/hsdk.c | 8 | ||||
-rw-r--r-- | board/synopsys/iot_devkit/iot_devkit.c | 10 | ||||
-rw-r--r-- | include/configs/emsdp.h | 2 |
7 files changed, 274 insertions, 49 deletions
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 9920d2e719..fff6591c68 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -16,6 +16,20 @@ * access: "lr"/"sr". */ +/* + * Typically 8 least significant bits of Build Configuration Register (BCR) + * describe version of the HW block in question. Moreover if decoded version + * is 0 this means given HW block is absent - this is especially useful because + * we may safely read BRC regardless HW block existence while an attempt to + * access any other AUX regs associated with this HW block lead to imediate + * "instruction error" exception. + * + * I.e. before using any cofigurable HW block it's required to make sure it + * exists at all, and for that we introduce a special macro below. + */ +#define ARC_BCR_VERSION_MASK GENMASK(7, 0) +#define ARC_FEATURE_EXISTS(bcr) !!(__builtin_arc_lr(bcr) & ARC_BCR_VERSION_MASK) + #define ARC_AUX_IDENTITY 0x04 #define ARC_AUX_STATUS32 0x0a @@ -73,7 +87,7 @@ #define ARC_BCR_CLUSTER 0xcf /* MMU Management regs */ -#define ARC_AUX_MMU_BCR 0x06f +#define ARC_AUX_MMU_BCR 0x6f /* IO coherency related auxiliary registers */ #define ARC_AUX_IO_COH_ENABLE 0x500 @@ -81,6 +95,15 @@ #define ARC_AUX_IO_COH_AP0_BASE 0x508 #define ARC_AUX_IO_COH_AP0_SIZE 0x509 +/* XY-memory related */ +#define ARC_AUX_XY_BUILD 0x79 + +/* DSP-extensions related auxiliary registers */ +#define ARC_AUX_DSP_BUILD 0x7A + +/* ARC Subsystems related auxiliary registers */ +#define ARC_AUX_SUBSYS_BUILD 0xF0 + #ifndef __ASSEMBLY__ /* Accessors for auxiliary registers */ #define read_aux_reg(reg) __builtin_arc_lr(reg) diff --git a/arch/arc/lib/cpu.c b/arch/arc/lib/cpu.c index a969a16722..07daaa8d15 100644 --- a/arch/arc/lib/cpu.c +++ b/arch/arc/lib/cpu.c @@ -4,6 +4,7 @@ */ #include <common.h> +#include <malloc.h> #include <asm/arcregs.h> #include <asm/cache.h> @@ -35,34 +36,193 @@ int dram_init(void) } #ifdef CONFIG_DISPLAY_CPUINFO -const char *decode_identity(void) +const char *arc_700_version(int arcver, char *name, int name_len) { - int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff; + const char *arc_ver; + + switch (arcver) { + case 0x32: + arc_ver = "v4.4-4.5"; + break; + case 0x33: + arc_ver = "v4.6-v4.9"; + break; + case 0x34: + arc_ver = "v4.10"; + break; + case 0x35: + arc_ver = "v4.11"; + break; + default: + arc_ver = "unknown version"; + } + + snprintf(name, name_len, "ARC 700 %s", arc_ver); + + return name; +} + +struct em_template_t { + const bool cache; + const bool dsp; + const bool xymem; + const char name[8]; +}; + +static const struct em_template_t em_versions[] = { + {false, false, false, "EM4"}, + {true, false, false, "EM6"}, + {false, true, false, "EM5D"}, + {true, true, false, "EM7D"}, + {false, true, true, "EM9D"}, + {true, true, true, "EM11D"}, +}; + +const char *arc_em_version(int arcver, char *name, int name_len) +{ + const char *arc_name = "EM"; + const char *arc_ver; + bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD); + bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD); + bool xymem = ARC_FEATURE_EXISTS(ARC_AUX_XY_BUILD); + int i; + + for (i = 0; i++ < sizeof(em_versions) / sizeof(struct em_template_t);) { + if (em_versions[i].cache == cache && + em_versions[i].dsp == dsp && + em_versions[i].xymem == xymem) { + arc_name = em_versions[i].name; + break; + } + } + + switch (arcver) { + case 0x41: + arc_ver = "v1.1a"; + break; + case 0x42: + arc_ver = "v3.0"; + break; + case 0x43: + arc_ver = "v4.0"; + break; + case 0x44: + arc_ver = "v5.0"; + break; + default: + arc_ver = "unknown version"; + } + + snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver); + + return name; +} + +struct hs_template_t { + const bool cache; + const bool mmu; + const bool dual_issue; + const bool dsp; + const char name[8]; +}; + +static const struct hs_template_t hs_versions[] = { + {false, false, false, false, "HS34"}, + {true, false, false, false, "HS36"}, + {true, true, false, false, "HS38"}, + {false, false, true, false, "HS44"}, + {true, false, true, false, "HS46"}, + {true, true, true, false, "HS48"}, + {false, false, true, true, "HS45D"}, + {true, false, true, true, "HS47D"}, +}; + +const char *arc_hs_version(int arcver, char *name, int name_len) +{ + const char *arc_name = "HS"; + const char *arc_ver; + bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD); + bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD); + bool mmu = !!read_aux_reg(ARC_AUX_MMU_BCR); + bool dual_issue = arcver == 0x54 ? true : false; + int i; + + for (i = 0; i++ < sizeof(hs_versions) / sizeof(struct hs_template_t);) { + if (hs_versions[i].cache == cache && + hs_versions[i].mmu == mmu && + hs_versions[i].dual_issue == dual_issue && + hs_versions[i].dsp == dsp) { + arc_name = hs_versions[i].name; + break; + } + } switch (arcver) { - /* ARCompact cores */ - case 0x32: return "ARC 700 v4.4-4.5"; - case 0x33: return "ARC 700 v4.6-v4.9"; - case 0x34: return "ARC 700 v4.10"; - case 0x35: return "ARC 700 v4.11"; - - /* ARCv2 cores */ - case 0x41: return "ARC EM v1.1a"; - case 0x42: return "ARC EM v3.0"; - case 0x43: return "ARC EM v4.0"; - case 0x50: return "ARC HS v1.0"; - case 0x51: return "ARC EM v2.0"; - case 0x52: return "ARC EM v2.1"; - case 0x53: return "ARC HS v3.0"; - case 0x54: return "ARC HS v4.0"; - - default: return "Unknown ARC core"; + case 0x50: + arc_ver = "v1.0"; + break; + case 0x51: + arc_ver = "v2.0"; + break; + case 0x52: + arc_ver = "v2.1c"; + break; + case 0x53: + arc_ver = "v3.0"; + break; + case 0x54: + arc_ver = "v4.0"; + break; + default: + arc_ver = "unknown version"; } + + snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver); + + return name; +} + +const char *decode_identity(void) +{ +#define MAX_CPU_NAME_LEN 64 + + int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff; + char *name = malloc(MAX_CPU_NAME_LEN); + + if (arcver >= 0x50) + return arc_hs_version(arcver, name, MAX_CPU_NAME_LEN); + else if (arcver >= 0x40) + return arc_em_version(arcver, name, MAX_CPU_NAME_LEN); + else if (arcver >= 0x30) + return arc_700_version(arcver, name, MAX_CPU_NAME_LEN); + else + return "Unknown ARC core"; +} + +const char *decode_subsystem(void) +{ + int subsys_type = read_aux_reg(ARC_AUX_SUBSYS_BUILD) & GENMASK(3, 0); + + switch (subsys_type) { + case 0: return NULL; + case 2: return "ARC Sensor & Control IP Subsystem"; + case 3: return "ARC Data Fusion IP Subsystem"; + case 4: return "ARC Secure Subsystem"; + default: return "Unknown subsystem"; + }; } __weak int print_cpuinfo(void) { - printf("CPU: %s\n", decode_identity()); + const char *subsys_name = decode_subsystem(); + char mhz[8]; + + printf("CPU: %s at %s MHz\n", decode_identity(), + strmhz(mhz, gd->cpu_clk)); + + if (subsys_name) + printf("Subsys:%s\n", subsys_name); + return 0; } #endif /* CONFIG_DISPLAY_CPUINFO */ diff --git a/board/synopsys/axs10x/axs10x.c b/board/synopsys/axs10x/axs10x.c index c95f7af7a7..ffa7c154b5 100644 --- a/board/synopsys/axs10x/axs10x.c +++ b/board/synopsys/axs10x/axs10x.c @@ -109,3 +109,11 @@ void smp_kick_all_cpus(void) writel(cmd, (void __iomem *)AXC003_CREG_CPU_START); } #endif + +int checkboard(void) +{ + printf("Board: ARC Software Development Platform AXS%s\n", + is_isa_arcv2() ? "103" : "101"); + + return 0; +}; diff --git a/board/synopsys/emsdp/emsdp.c b/board/synopsys/emsdp/emsdp.c index b5ec7f17ec..c0770b58c1 100644 --- a/board/synopsys/emsdp/emsdp.c +++ b/board/synopsys/emsdp/emsdp.c @@ -7,10 +7,46 @@ #include <dwmmc.h> #include <malloc.h> +#include <asm/arcregs.h> + DECLARE_GLOBAL_DATA_PTR; -#define ARC_PERIPHERAL_BASE 0xF0000000 -#define SDIO_BASE (ARC_PERIPHERAL_BASE + 0x10000) +#define ARC_PERIPHERAL_BASE 0xF0000000 + +#define CGU_ARC_FMEAS_ARC (void *)(ARC_PERIPHERAL_BASE + 0x84) +#define CGU_ARC_FMEAS_ARC_START BIT(31) +#define CGU_ARC_FMEAS_ARC_DONE BIT(30) +#define CGU_ARC_FMEAS_ARC_CNT_MASK GENMASK(14, 0) +#define CGU_ARC_FMEAS_ARC_RCNT_OFFSET 0 +#define CGU_ARC_FMEAS_ARC_FCNT_OFFSET 15 + +#define SDIO_BASE (void *)(ARC_PERIPHERAL_BASE + 0x10000) + +int mach_cpu_init(void) +{ + int rcnt, fcnt; + u32 data; + + /* Start frequency measurement */ + writel(CGU_ARC_FMEAS_ARC_START, CGU_ARC_FMEAS_ARC); + + /* Poll DONE bit */ + do { + data = readl(CGU_ARC_FMEAS_ARC); + } while (!(data & CGU_ARC_FMEAS_ARC_DONE)); + + /* Amount of reference 100 MHz clocks */ + rcnt = ((data >> CGU_ARC_FMEAS_ARC_RCNT_OFFSET) & + CGU_ARC_FMEAS_ARC_CNT_MASK); + + /* Amount of CPU clocks */ + fcnt = ((data >> CGU_ARC_FMEAS_ARC_FCNT_OFFSET) & + CGU_ARC_FMEAS_ARC_CNT_MASK); + + gd->cpu_clk = ((100 * fcnt) / rcnt) * 1000000; + + return 0; +} int board_mmc_init(bd_t *bis) { @@ -24,7 +60,7 @@ int board_mmc_init(bd_t *bis) memset(host, 0, sizeof(struct dwmci_host)); host->name = "Synopsys Mobile storage"; - host->ioaddr = (void *)SDIO_BASE; + host->ioaddr = SDIO_BASE; host->buswidth = 4; host->dev_index = 0; host->bus_hz = 50000000; @@ -42,31 +78,32 @@ int board_mmc_getcd(struct mmc *mmc) } #define CREG_BASE 0xF0001000 -#define CREG_BOOT_OFFSET 0 -#define CREG_BOOT_WP_OFFSET 8 +#define CREG_BOOT (void *)(CREG_BASE + 0x0FF0) +#define CREG_IP_SW_RESET (void *)(CREG_BASE + 0x0FF0) +#define CREG_IP_VERSION (void *)(CREG_BASE + 0x0FF8) -#define CGU_BASE 0xF0000000 -#define CGU_IP_SW_RESET 0x0FF0 +/* Bits in CREG_BOOT register */ +#define CREG_BOOT_WP_BIT BIT(8) void reset_cpu(ulong addr) { - writel(1, (u32 *)(CGU_BASE + CGU_IP_SW_RESET)); + writel(1, CREG_IP_SW_RESET); while (1) ; /* loop forever till reset */ } static int do_emsdp_rom(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { - u32 creg_boot = readl((u32 *)(CREG_BASE + CREG_BOOT_OFFSET)); + u32 creg_boot = readl(CREG_BOOT); if (!strcmp(argv[1], "unlock")) - creg_boot &= ~BIT(CREG_BOOT_WP_OFFSET); + creg_boot &= ~CREG_BOOT_WP_BIT; else if (!strcmp(argv[1], "lock")) - creg_boot |= BIT(CREG_BOOT_WP_OFFSET); + creg_boot |= CREG_BOOT_WP_BIT; else return CMD_RET_USAGE; - writel(creg_boot, (u32 *)(CREG_BASE + CREG_BOOT_OFFSET)); + writel(creg_boot, CREG_BOOT); return CMD_RET_SUCCESS; } @@ -97,3 +134,12 @@ U_BOOT_CMD( "rom unlock - Unlock non-volatile memory for writing\n" "emsdp rom lock - Lock non-volatile memory to prevent writing\n" ); + +int checkboard(void) +{ + int version = readl(CREG_IP_VERSION); + + printf("Board: ARC EM Software Development Platform v%d.%d\n", + (version >> 16) & 0xff, version & 0xff); + return 0; +}; diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index b6aefdbe6d..8a2c201477 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -1054,10 +1054,8 @@ int board_mmc_init(bd_t *bis) return 0; } -#ifdef CONFIG_DISPLAY_CPUINFO -int print_cpuinfo(void) +int checkboard(void) { - printf("CPU: ARC HS38 v2.1c\n"); + puts("Board: Synopsys ARC HS Development Kit\n"); return 0; -} -#endif /* CONFIG_DISPLAY_CPUINFO */ +}; diff --git a/board/synopsys/iot_devkit/iot_devkit.c b/board/synopsys/iot_devkit/iot_devkit.c index f8838fb3ce..8424e09bd3 100644 --- a/board/synopsys/iot_devkit/iot_devkit.c +++ b/board/synopsys/iot_devkit/iot_devkit.c @@ -189,13 +189,3 @@ int checkboard(void) puts("Board: Synopsys IoT Development Kit\n"); return 0; }; - -#ifdef CONFIG_DISPLAY_CPUINFO -int print_cpuinfo(void) -{ - char mhz[8]; - - printf("CPU: ARC EM9D at %s MHz\n", strmhz(mhz, gd->cpu_clk)); - return 0; -} -#endif /* CONFIG_DISPLAY_CPUINFO */ diff --git a/include/configs/emsdp.h b/include/configs/emsdp.h index 385d59e338..9a205edc7c 100644 --- a/include/configs/emsdp.h +++ b/include/configs/emsdp.h @@ -11,7 +11,7 @@ #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_SDRAM_BASE 0x10000000 -#define CONFIG_SYS_SDRAM_SIZE SZ_8M +#define CONFIG_SYS_SDRAM_SIZE SZ_16M #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + SZ_1M) |