xref: /openbmc/u-boot/arch/arc/lib/cpu.c (revision 87f78478a4a1bf574db0b0e575ca37cf91fb187c)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2660d5f0dSAlexey Brodkin /*
37fe46b96SAlexey Brodkin  * Copyright (C) 2013-2014, 2018 Synopsys, Inc. All rights reserved.
4660d5f0dSAlexey Brodkin  */
5660d5f0dSAlexey Brodkin 
6660d5f0dSAlexey Brodkin #include <common.h>
785e529fdSAlexey Brodkin #include <malloc.h>
8660d5f0dSAlexey Brodkin #include <asm/arcregs.h>
9660d5f0dSAlexey Brodkin #include <asm/cache.h>
10660d5f0dSAlexey Brodkin 
11660d5f0dSAlexey Brodkin DECLARE_GLOBAL_DATA_PTR;
12660d5f0dSAlexey Brodkin 
arch_cpu_init(void)13660d5f0dSAlexey Brodkin int arch_cpu_init(void)
14660d5f0dSAlexey Brodkin {
15660d5f0dSAlexey Brodkin 	timer_init();
16660d5f0dSAlexey Brodkin 
17660d5f0dSAlexey Brodkin 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
18660d5f0dSAlexey Brodkin 	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
19660d5f0dSAlexey Brodkin 
20ef639e6fSAlexey Brodkin 	cache_init();
21ef639e6fSAlexey Brodkin 
22660d5f0dSAlexey Brodkin 	return 0;
23660d5f0dSAlexey Brodkin }
24660d5f0dSAlexey Brodkin 
arch_early_init_r(void)25660d5f0dSAlexey Brodkin int arch_early_init_r(void)
26660d5f0dSAlexey Brodkin {
27660d5f0dSAlexey Brodkin 	gd->bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
28660d5f0dSAlexey Brodkin 	gd->bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
29660d5f0dSAlexey Brodkin 	return 0;
30660d5f0dSAlexey Brodkin }
31f1683aa7SSimon Glass 
32f1683aa7SSimon Glass /* This is a dummy function on arc */
dram_init(void)33f1683aa7SSimon Glass int dram_init(void)
34f1683aa7SSimon Glass {
35f1683aa7SSimon Glass 	return 0;
36f1683aa7SSimon Glass }
377fe46b96SAlexey Brodkin 
387fe46b96SAlexey Brodkin #ifdef CONFIG_DISPLAY_CPUINFO
arc_700_version(int arcver,char * name,int name_len)3985e529fdSAlexey Brodkin const char *arc_700_version(int arcver, char *name, int name_len)
407fe46b96SAlexey Brodkin {
4185e529fdSAlexey Brodkin 	const char *arc_ver;
427fe46b96SAlexey Brodkin 
437fe46b96SAlexey Brodkin 	switch (arcver) {
4485e529fdSAlexey Brodkin 	case 0x32:
4585e529fdSAlexey Brodkin 		arc_ver = "v4.4-4.5";
4685e529fdSAlexey Brodkin 		break;
4785e529fdSAlexey Brodkin 	case 0x33:
4885e529fdSAlexey Brodkin 		arc_ver = "v4.6-v4.9";
4985e529fdSAlexey Brodkin 		break;
5085e529fdSAlexey Brodkin 	case 0x34:
5185e529fdSAlexey Brodkin 		arc_ver = "v4.10";
5285e529fdSAlexey Brodkin 		break;
5385e529fdSAlexey Brodkin 	case 0x35:
5485e529fdSAlexey Brodkin 		arc_ver = "v4.11";
5585e529fdSAlexey Brodkin 		break;
5685e529fdSAlexey Brodkin 	default:
5785e529fdSAlexey Brodkin 		arc_ver = "unknown version";
587fe46b96SAlexey Brodkin 	}
5985e529fdSAlexey Brodkin 
6085e529fdSAlexey Brodkin 	snprintf(name, name_len, "ARC 700 %s", arc_ver);
6185e529fdSAlexey Brodkin 
6285e529fdSAlexey Brodkin 	return name;
6385e529fdSAlexey Brodkin }
6485e529fdSAlexey Brodkin 
6585e529fdSAlexey Brodkin struct em_template_t {
6685e529fdSAlexey Brodkin 	const bool cache;
6785e529fdSAlexey Brodkin 	const bool dsp;
6885e529fdSAlexey Brodkin 	const bool xymem;
6985e529fdSAlexey Brodkin 	const char name[8];
7085e529fdSAlexey Brodkin };
7185e529fdSAlexey Brodkin 
7285e529fdSAlexey Brodkin static const struct em_template_t em_versions[] = {
7385e529fdSAlexey Brodkin 	{false,	false,	false,	"EM4"},
7485e529fdSAlexey Brodkin 	{true,	false,	false,	"EM6"},
7585e529fdSAlexey Brodkin 	{false,	true,	false,	"EM5D"},
7685e529fdSAlexey Brodkin 	{true,	true,	false,	"EM7D"},
7785e529fdSAlexey Brodkin 	{false,	true,	true,	"EM9D"},
7885e529fdSAlexey Brodkin 	{true,	true,	true,	"EM11D"},
7985e529fdSAlexey Brodkin };
8085e529fdSAlexey Brodkin 
arc_em_version(int arcver,char * name,int name_len)8185e529fdSAlexey Brodkin const char *arc_em_version(int arcver, char *name, int name_len)
8285e529fdSAlexey Brodkin {
8385e529fdSAlexey Brodkin 	const char *arc_name = "EM";
8485e529fdSAlexey Brodkin 	const char *arc_ver;
8585e529fdSAlexey Brodkin 	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
8685e529fdSAlexey Brodkin 	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
8785e529fdSAlexey Brodkin 	bool xymem = ARC_FEATURE_EXISTS(ARC_AUX_XY_BUILD);
8885e529fdSAlexey Brodkin 	int i;
8985e529fdSAlexey Brodkin 
90*7181a6d1SAlexey Brodkin 	for (i = 0; i < sizeof(em_versions) / sizeof(struct em_template_t); i++) {
9185e529fdSAlexey Brodkin 		if (em_versions[i].cache == cache &&
9285e529fdSAlexey Brodkin 		    em_versions[i].dsp == dsp &&
9385e529fdSAlexey Brodkin 		    em_versions[i].xymem == xymem) {
9485e529fdSAlexey Brodkin 			arc_name = em_versions[i].name;
9585e529fdSAlexey Brodkin 			break;
9685e529fdSAlexey Brodkin 		}
9785e529fdSAlexey Brodkin 	}
9885e529fdSAlexey Brodkin 
9985e529fdSAlexey Brodkin 	switch (arcver) {
10085e529fdSAlexey Brodkin 	case 0x41:
10185e529fdSAlexey Brodkin 		arc_ver = "v1.1a";
10285e529fdSAlexey Brodkin 		break;
10385e529fdSAlexey Brodkin 	case 0x42:
10485e529fdSAlexey Brodkin 		arc_ver = "v3.0";
10585e529fdSAlexey Brodkin 		break;
10685e529fdSAlexey Brodkin 	case 0x43:
10785e529fdSAlexey Brodkin 		arc_ver = "v4.0";
10885e529fdSAlexey Brodkin 		break;
10985e529fdSAlexey Brodkin 	case 0x44:
11085e529fdSAlexey Brodkin 		arc_ver = "v5.0";
11185e529fdSAlexey Brodkin 		break;
11285e529fdSAlexey Brodkin 	default:
11385e529fdSAlexey Brodkin 		arc_ver = "unknown version";
11485e529fdSAlexey Brodkin 	}
11585e529fdSAlexey Brodkin 
11685e529fdSAlexey Brodkin 	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);
11785e529fdSAlexey Brodkin 
11885e529fdSAlexey Brodkin 	return name;
11985e529fdSAlexey Brodkin }
12085e529fdSAlexey Brodkin 
12185e529fdSAlexey Brodkin struct hs_template_t {
12285e529fdSAlexey Brodkin 	const bool cache;
12385e529fdSAlexey Brodkin 	const bool mmu;
12485e529fdSAlexey Brodkin 	const bool dual_issue;
12585e529fdSAlexey Brodkin 	const bool dsp;
12685e529fdSAlexey Brodkin 	const char name[8];
12785e529fdSAlexey Brodkin };
12885e529fdSAlexey Brodkin 
12985e529fdSAlexey Brodkin static const struct hs_template_t hs_versions[] = {
13085e529fdSAlexey Brodkin 	{false,	false,	false,	false,	"HS34"},
13185e529fdSAlexey Brodkin 	{true,	false,	false,	false,	"HS36"},
13285e529fdSAlexey Brodkin 	{true,	true,	false,	false,	"HS38"},
13385e529fdSAlexey Brodkin 	{false,	false,	true,	false,	"HS44"},
13485e529fdSAlexey Brodkin 	{true,	false,	true,	false,	"HS46"},
13585e529fdSAlexey Brodkin 	{true,	true,	true,	false,	"HS48"},
13685e529fdSAlexey Brodkin 	{false,	false,	true,	true,	"HS45D"},
13785e529fdSAlexey Brodkin 	{true,	false,	true,	true,	"HS47D"},
13885e529fdSAlexey Brodkin };
13985e529fdSAlexey Brodkin 
arc_hs_version(int arcver,char * name,int name_len)14085e529fdSAlexey Brodkin const char *arc_hs_version(int arcver, char *name, int name_len)
14185e529fdSAlexey Brodkin {
14285e529fdSAlexey Brodkin 	const char *arc_name = "HS";
14385e529fdSAlexey Brodkin 	const char *arc_ver;
14485e529fdSAlexey Brodkin 	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
14585e529fdSAlexey Brodkin 	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
14685e529fdSAlexey Brodkin 	bool mmu = !!read_aux_reg(ARC_AUX_MMU_BCR);
14785e529fdSAlexey Brodkin 	bool dual_issue = arcver == 0x54 ? true : false;
14885e529fdSAlexey Brodkin 	int i;
14985e529fdSAlexey Brodkin 
150*7181a6d1SAlexey Brodkin 	for (i = 0; i < sizeof(hs_versions) / sizeof(struct hs_template_t); i++) {
15185e529fdSAlexey Brodkin 		if (hs_versions[i].cache == cache &&
15285e529fdSAlexey Brodkin 		    hs_versions[i].mmu == mmu &&
15385e529fdSAlexey Brodkin 		    hs_versions[i].dual_issue == dual_issue &&
15485e529fdSAlexey Brodkin 		    hs_versions[i].dsp == dsp) {
15585e529fdSAlexey Brodkin 			arc_name = hs_versions[i].name;
15685e529fdSAlexey Brodkin 			break;
15785e529fdSAlexey Brodkin 		}
15885e529fdSAlexey Brodkin 	}
15985e529fdSAlexey Brodkin 
16085e529fdSAlexey Brodkin 	switch (arcver) {
16185e529fdSAlexey Brodkin 	case 0x50:
16285e529fdSAlexey Brodkin 		arc_ver = "v1.0";
16385e529fdSAlexey Brodkin 		break;
16485e529fdSAlexey Brodkin 	case 0x51:
16585e529fdSAlexey Brodkin 		arc_ver = "v2.0";
16685e529fdSAlexey Brodkin 		break;
16785e529fdSAlexey Brodkin 	case 0x52:
16885e529fdSAlexey Brodkin 		arc_ver = "v2.1c";
16985e529fdSAlexey Brodkin 		break;
17085e529fdSAlexey Brodkin 	case 0x53:
17185e529fdSAlexey Brodkin 		arc_ver = "v3.0";
17285e529fdSAlexey Brodkin 		break;
17385e529fdSAlexey Brodkin 	case 0x54:
17485e529fdSAlexey Brodkin 		arc_ver = "v4.0";
17585e529fdSAlexey Brodkin 		break;
17685e529fdSAlexey Brodkin 	default:
17785e529fdSAlexey Brodkin 		arc_ver = "unknown version";
17885e529fdSAlexey Brodkin 	}
17985e529fdSAlexey Brodkin 
18085e529fdSAlexey Brodkin 	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);
18185e529fdSAlexey Brodkin 
18285e529fdSAlexey Brodkin 	return name;
18385e529fdSAlexey Brodkin }
18485e529fdSAlexey Brodkin 
decode_identity(void)18585e529fdSAlexey Brodkin const char *decode_identity(void)
18685e529fdSAlexey Brodkin {
18785e529fdSAlexey Brodkin #define MAX_CPU_NAME_LEN	64
18885e529fdSAlexey Brodkin 
18985e529fdSAlexey Brodkin 	int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff;
19085e529fdSAlexey Brodkin 	char *name = malloc(MAX_CPU_NAME_LEN);
19185e529fdSAlexey Brodkin 
19285e529fdSAlexey Brodkin 	if (arcver >= 0x50)
19385e529fdSAlexey Brodkin 		return arc_hs_version(arcver, name, MAX_CPU_NAME_LEN);
19485e529fdSAlexey Brodkin 	else if (arcver >= 0x40)
19585e529fdSAlexey Brodkin 		return arc_em_version(arcver, name, MAX_CPU_NAME_LEN);
19685e529fdSAlexey Brodkin 	else if (arcver >= 0x30)
19785e529fdSAlexey Brodkin 		return arc_700_version(arcver, name, MAX_CPU_NAME_LEN);
19885e529fdSAlexey Brodkin 	else
19985e529fdSAlexey Brodkin 		return "Unknown ARC core";
20085e529fdSAlexey Brodkin }
20185e529fdSAlexey Brodkin 
decode_subsystem(void)20285e529fdSAlexey Brodkin const char *decode_subsystem(void)
20385e529fdSAlexey Brodkin {
20485e529fdSAlexey Brodkin 	int subsys_type = read_aux_reg(ARC_AUX_SUBSYS_BUILD) & GENMASK(3, 0);
20585e529fdSAlexey Brodkin 
20685e529fdSAlexey Brodkin 	switch (subsys_type) {
20785e529fdSAlexey Brodkin 	case 0: return NULL;
20885e529fdSAlexey Brodkin 	case 2: return "ARC Sensor & Control IP Subsystem";
20985e529fdSAlexey Brodkin 	case 3: return "ARC Data Fusion IP Subsystem";
21085e529fdSAlexey Brodkin 	case 4: return "ARC Secure Subsystem";
21185e529fdSAlexey Brodkin 	default: return "Unknown subsystem";
21285e529fdSAlexey Brodkin 	};
2137fe46b96SAlexey Brodkin }
2147fe46b96SAlexey Brodkin 
print_cpuinfo(void)215ba9f56f3SAlexey Brodkin __weak int print_cpuinfo(void)
2167fe46b96SAlexey Brodkin {
21785e529fdSAlexey Brodkin 	const char *subsys_name = decode_subsystem();
21885e529fdSAlexey Brodkin 	char mhz[8];
21985e529fdSAlexey Brodkin 
22085e529fdSAlexey Brodkin 	printf("CPU:   %s at %s MHz\n", decode_identity(),
22185e529fdSAlexey Brodkin 	       strmhz(mhz, gd->cpu_clk));
22285e529fdSAlexey Brodkin 
22385e529fdSAlexey Brodkin 	if (subsys_name)
22485e529fdSAlexey Brodkin 		printf("Subsys:%s\n", subsys_name);
22585e529fdSAlexey Brodkin 
2267fe46b96SAlexey Brodkin 	return 0;
2277fe46b96SAlexey Brodkin }
2287fe46b96SAlexey Brodkin #endif /* CONFIG_DISPLAY_CPUINFO */
229