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