1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2013-2014, 2018 Synopsys, Inc. All rights reserved.
4  */
5 
6 #include <common.h>
7 #include <init.h>
8 #include <malloc.h>
9 #include <vsprintf.h>
10 #include <asm/arcregs.h>
11 #include <asm/cache.h>
12 #include <asm/global_data.h>
13 #include <linux/bitops.h>
14 
15 DECLARE_GLOBAL_DATA_PTR;
16 
arch_cpu_init(void)17 int arch_cpu_init(void)
18 {
19 	timer_init();
20 
21 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
22 	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
23 
24 	cache_init();
25 
26 	return 0;
27 }
28 
29 /* This is a dummy function on arc */
dram_init(void)30 int dram_init(void)
31 {
32 	return 0;
33 }
34 
35 #ifdef CONFIG_DISPLAY_CPUINFO
arc_700_version(int arcver,char * name,int name_len)36 const char *arc_700_version(int arcver, char *name, int name_len)
37 {
38 	const char *arc_ver;
39 
40 	switch (arcver) {
41 	case 0x32:
42 		arc_ver = "v4.4-4.5";
43 		break;
44 	case 0x33:
45 		arc_ver = "v4.6-v4.9";
46 		break;
47 	case 0x34:
48 		arc_ver = "v4.10";
49 		break;
50 	case 0x35:
51 		arc_ver = "v4.11";
52 		break;
53 	default:
54 		arc_ver = "unknown version";
55 	}
56 
57 	snprintf(name, name_len, "ARC 700 %s", arc_ver);
58 
59 	return name;
60 }
61 
62 struct em_template_t {
63 	const bool cache;
64 	const bool dsp;
65 	const bool xymem;
66 	const char name[8];
67 };
68 
69 static const struct em_template_t em_versions[] = {
70 	{false,	false,	false,	"EM4"},
71 	{true,	false,	false,	"EM6"},
72 	{false,	true,	false,	"EM5D"},
73 	{true,	true,	false,	"EM7D"},
74 	{false,	true,	true,	"EM9D"},
75 	{true,	true,	true,	"EM11D"},
76 };
77 
arc_em_version(int arcver,char * name,int name_len)78 const char *arc_em_version(int arcver, char *name, int name_len)
79 {
80 	const char *arc_name = "EM";
81 	const char *arc_ver;
82 	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
83 	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
84 	bool xymem = ARC_FEATURE_EXISTS(ARC_AUX_XY_BUILD);
85 	int i;
86 
87 	for (i = 0; i < sizeof(em_versions) / sizeof(struct em_template_t); i++) {
88 		if (em_versions[i].cache == cache &&
89 		    em_versions[i].dsp == dsp &&
90 		    em_versions[i].xymem == xymem) {
91 			arc_name = em_versions[i].name;
92 			break;
93 		}
94 	}
95 
96 	switch (arcver) {
97 	case 0x41:
98 		arc_ver = "v1.1a";
99 		break;
100 	case 0x42:
101 		arc_ver = "v3.0";
102 		break;
103 	case 0x43:
104 		arc_ver = "v4.0";
105 		break;
106 	case 0x44:
107 		arc_ver = "v5.0";
108 		break;
109 	default:
110 		arc_ver = "unknown version";
111 	}
112 
113 	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);
114 
115 	return name;
116 }
117 
118 struct hs_template_t {
119 	const bool cache;
120 	const bool mmu;
121 	const bool dual_issue;
122 	const bool dsp;
123 	const char name[8];
124 };
125 
126 static const struct hs_template_t hs_versions[] = {
127 	{false,	false,	false,	false,	"HS34"},
128 	{true,	false,	false,	false,	"HS36"},
129 	{true,	true,	false,	false,	"HS38"},
130 	{false,	false,	true,	false,	"HS44"},
131 	{true,	false,	true,	false,	"HS46"},
132 	{true,	true,	true,	false,	"HS48"},
133 	{false,	false,	true,	true,	"HS45D"},
134 	{true,	false,	true,	true,	"HS47D"},
135 };
136 
arc_hs_version(int arcver,char * name,int name_len)137 const char *arc_hs_version(int arcver, char *name, int name_len)
138 {
139 	const char *arc_name = "HS";
140 	const char *arc_ver;
141 	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
142 	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
143 	bool mmu = !!read_aux_reg(ARC_AUX_MMU_BCR);
144 	bool dual_issue = arcver == 0x54 ? true : false;
145 	int i;
146 
147 	for (i = 0; i < sizeof(hs_versions) / sizeof(struct hs_template_t); i++) {
148 		if (hs_versions[i].cache == cache &&
149 		    hs_versions[i].mmu == mmu &&
150 		    hs_versions[i].dual_issue == dual_issue &&
151 		    hs_versions[i].dsp == dsp) {
152 			arc_name = hs_versions[i].name;
153 			break;
154 		}
155 	}
156 
157 	switch (arcver) {
158 	case 0x50:
159 		arc_ver = "v1.0";
160 		break;
161 	case 0x51:
162 		arc_ver = "v2.0";
163 		break;
164 	case 0x52:
165 		arc_ver = "v2.1c";
166 		break;
167 	case 0x53:
168 		arc_ver = "v3.0";
169 		break;
170 	case 0x54:
171 		arc_ver = "v4.0";
172 		break;
173 	default:
174 		arc_ver = "unknown version";
175 	}
176 
177 	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);
178 
179 	return name;
180 }
181 
decode_identity(void)182 const char *decode_identity(void)
183 {
184 #define MAX_CPU_NAME_LEN	64
185 
186 	int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff;
187 	char *name = malloc(MAX_CPU_NAME_LEN);
188 
189 	if (arcver >= 0x50)
190 		return arc_hs_version(arcver, name, MAX_CPU_NAME_LEN);
191 	else if (arcver >= 0x40)
192 		return arc_em_version(arcver, name, MAX_CPU_NAME_LEN);
193 	else if (arcver >= 0x30)
194 		return arc_700_version(arcver, name, MAX_CPU_NAME_LEN);
195 	else
196 		return "Unknown ARC core";
197 }
198 
decode_subsystem(void)199 const char *decode_subsystem(void)
200 {
201 	int subsys_type = read_aux_reg(ARC_AUX_SUBSYS_BUILD) & GENMASK(3, 0);
202 
203 	switch (subsys_type) {
204 	case 0: return NULL;
205 	case 2: return "ARC Sensor & Control IP Subsystem";
206 	case 3: return "ARC Data Fusion IP Subsystem";
207 	case 4: return "ARC Secure Subsystem";
208 	default: return "Unknown subsystem";
209 	};
210 }
211 
print_cpuinfo(void)212 __weak int print_cpuinfo(void)
213 {
214 	const char *subsys_name = decode_subsystem();
215 	char mhz[8];
216 
217 	printf("CPU:   %s at %s MHz\n", decode_identity(),
218 	       strmhz(mhz, gd->cpu_clk));
219 
220 	if (subsys_name)
221 		printf("Subsys:%s\n", subsys_name);
222 
223 	return 0;
224 }
225 #endif /* CONFIG_DISPLAY_CPUINFO */
226