diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-01-18 04:42:24 -0500 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-02-15 12:46:07 -0500 |
commit | af61742813aa9dde65ca796801e36d03b83fa79f (patch) | |
tree | eccf5ea5d87904d79c9aa5574b031d56961247da /arch/arc/kernel | |
parent | f46121bd26d7957866739313f1e098a682e8d3e4 (diff) |
ARC: Boot #2: Verbose Boot reporting / feature verification
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r-- | arch/arc/kernel/setup.c | 223 |
1 files changed, 222 insertions, 1 deletions
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 6e3996cb9df9..e25538e29fe7 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/arcregs.h> | 24 | #include <asm/arcregs.h> |
25 | #include <asm/prom.h> | 25 | #include <asm/prom.h> |
26 | #include <asm/unwind.h> | 26 | #include <asm/unwind.h> |
27 | #include <asm/clk.h> | ||
27 | 28 | ||
28 | #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) | 29 | #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) |
29 | 30 | ||
@@ -35,10 +36,205 @@ struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ | |||
35 | 36 | ||
36 | struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; | 37 | struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; |
37 | 38 | ||
39 | |||
38 | void __init read_arc_build_cfg_regs(void) | 40 | void __init read_arc_build_cfg_regs(void) |
39 | { | 41 | { |
42 | struct bcr_perip uncached_space; | ||
43 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; | ||
44 | FIX_PTR(cpu); | ||
45 | |||
46 | READ_BCR(AUX_IDENTITY, cpu->core); | ||
47 | |||
48 | cpu->timers = read_aux_reg(ARC_REG_TIMERS_BCR); | ||
49 | |||
50 | cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE); | ||
51 | if (cpu->vec_base == 0) | ||
52 | cpu->vec_base = (unsigned int)_int_vec_base_lds; | ||
53 | |||
54 | READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space); | ||
55 | cpu->uncached_base = uncached_space.start << 24; | ||
56 | |||
57 | cpu->extn.mul = read_aux_reg(ARC_REG_MUL_BCR); | ||
58 | cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR); | ||
59 | cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR); | ||
60 | cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR); | ||
61 | cpu->extn.barrel = read_aux_reg(ARC_REG_BARREL_BCR); | ||
62 | READ_BCR(ARC_REG_MAC_BCR, cpu->extn_mac_mul); | ||
63 | |||
64 | cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR); | ||
65 | cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR); | ||
66 | |||
67 | READ_BCR(ARC_REG_XY_MEM_BCR, cpu->extn_xymem); | ||
68 | |||
40 | read_decode_mmu_bcr(); | 69 | read_decode_mmu_bcr(); |
41 | read_decode_cache_bcr(); | 70 | read_decode_cache_bcr(); |
71 | |||
72 | READ_BCR(ARC_REG_FP_BCR, cpu->fp); | ||
73 | READ_BCR(ARC_REG_DPFP_BCR, cpu->dpfp); | ||
74 | } | ||
75 | |||
76 | static const struct cpuinfo_data arc_cpu_tbl[] = { | ||
77 | { {0x10, "ARCTangent A5"}, 0x1F}, | ||
78 | { {0x20, "ARC 600" }, 0x2F}, | ||
79 | { {0x30, "ARC 700" }, 0x33}, | ||
80 | { {0x34, "ARC 700 R4.10"}, 0x34}, | ||
81 | { {0x00, NULL } } | ||
82 | }; | ||
83 | |||
84 | char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) | ||
85 | { | ||
86 | int n = 0; | ||
87 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; | ||
88 | struct bcr_identity *core = &cpu->core; | ||
89 | const struct cpuinfo_data *tbl; | ||
90 | int be = 0; | ||
91 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
92 | be = 1; | ||
93 | #endif | ||
94 | FIX_PTR(cpu); | ||
95 | |||
96 | n += scnprintf(buf + n, len - n, | ||
97 | "\nARC IDENTITY\t: Family [%#02x]" | ||
98 | " Cpu-id [%#02x] Chip-id [%#4x]\n", | ||
99 | core->family, core->cpu_id, | ||
100 | core->chip_id); | ||
101 | |||
102 | for (tbl = &arc_cpu_tbl[0]; tbl->info.id != 0; tbl++) { | ||
103 | if ((core->family >= tbl->info.id) && | ||
104 | (core->family <= tbl->up_range)) { | ||
105 | n += scnprintf(buf + n, len - n, | ||
106 | "processor\t: %s %s\n", | ||
107 | tbl->info.str, | ||
108 | be ? "[Big Endian]" : ""); | ||
109 | break; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | if (tbl->info.id == 0) | ||
114 | n += scnprintf(buf + n, len - n, "UNKNOWN ARC Processor\n"); | ||
115 | |||
116 | n += scnprintf(buf + n, len - n, "CPU speed\t: %u.%02u Mhz\n", | ||
117 | (unsigned int)(arc_get_core_freq() / 1000000), | ||
118 | (unsigned int)(arc_get_core_freq() / 10000) % 100); | ||
119 | |||
120 | n += scnprintf(buf + n, len - n, "Timers\t\t: %s %s\n", | ||
121 | (cpu->timers & 0x200) ? "TIMER1" : "", | ||
122 | (cpu->timers & 0x100) ? "TIMER0" : ""); | ||
123 | |||
124 | n += scnprintf(buf + n, len - n, "Vect Tbl Base\t: %#x\n", | ||
125 | cpu->vec_base); | ||
126 | |||
127 | n += scnprintf(buf + n, len - n, "UNCACHED Base\t: %#x\n", | ||
128 | cpu->uncached_base); | ||
129 | |||
130 | return buf; | ||
131 | } | ||
132 | |||
133 | static const struct id_to_str mul_type_nm[] = { | ||
134 | { 0x0, "N/A"}, | ||
135 | { 0x1, "32x32 (spl Result Reg)" }, | ||
136 | { 0x2, "32x32 (ANY Result Reg)" } | ||
137 | }; | ||
138 | |||
139 | static const struct id_to_str mac_mul_nm[] = { | ||
140 | {0x0, "N/A"}, | ||
141 | {0x1, "N/A"}, | ||
142 | {0x2, "Dual 16 x 16"}, | ||
143 | {0x3, "N/A"}, | ||
144 | {0x4, "32x16"}, | ||
145 | {0x5, "N/A"}, | ||
146 | {0x6, "Dual 16x16 and 32x16"} | ||
147 | }; | ||
148 | |||
149 | char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) | ||
150 | { | ||
151 | int n = 0; | ||
152 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; | ||
153 | |||
154 | FIX_PTR(cpu); | ||
155 | #define IS_AVAIL1(var, str) ((var) ? str : "") | ||
156 | #define IS_AVAIL2(var, str) ((var == 0x2) ? str : "") | ||
157 | #define IS_USED(var) ((var) ? "(in-use)" : "(not used)") | ||
158 | |||
159 | n += scnprintf(buf + n, len - n, | ||
160 | "Extn [700-Base]\t: %s %s %s %s %s %s\n", | ||
161 | IS_AVAIL2(cpu->extn.norm, "norm,"), | ||
162 | IS_AVAIL2(cpu->extn.barrel, "barrel-shift,"), | ||
163 | IS_AVAIL1(cpu->extn.swap, "swap,"), | ||
164 | IS_AVAIL2(cpu->extn.minmax, "minmax,"), | ||
165 | IS_AVAIL1(cpu->extn.crc, "crc,"), | ||
166 | IS_AVAIL2(cpu->extn.ext_arith, "ext-arith")); | ||
167 | |||
168 | n += scnprintf(buf + n, len - n, "Extn [700-MPY]\t: %s", | ||
169 | mul_type_nm[cpu->extn.mul].str); | ||
170 | |||
171 | n += scnprintf(buf + n, len - n, " MAC MPY: %s\n", | ||
172 | mac_mul_nm[cpu->extn_mac_mul.type].str); | ||
173 | |||
174 | if (cpu->core.family == 0x34) { | ||
175 | n += scnprintf(buf + n, len - n, | ||
176 | "Extn [700-4.10]\t: LLOCK/SCOND %s, SWAPE %s, RTSC %s\n", | ||
177 | IS_USED(__CONFIG_ARC_HAS_LLSC_VAL), | ||
178 | IS_USED(__CONFIG_ARC_HAS_SWAPE_VAL), | ||
179 | IS_USED(__CONFIG_ARC_HAS_RTSC_VAL)); | ||
180 | } | ||
181 | |||
182 | n += scnprintf(buf + n, len - n, "Extn [CCM]\t: %s", | ||
183 | !(cpu->dccm.sz || cpu->iccm.sz) ? "N/A" : ""); | ||
184 | |||
185 | if (cpu->dccm.sz) | ||
186 | n += scnprintf(buf + n, len - n, "DCCM: @ %x, %d KB ", | ||
187 | cpu->dccm.base_addr, TO_KB(cpu->dccm.sz)); | ||
188 | |||
189 | if (cpu->iccm.sz) | ||
190 | n += scnprintf(buf + n, len - n, "ICCM: @ %x, %d KB", | ||
191 | cpu->iccm.base_addr, TO_KB(cpu->iccm.sz)); | ||
192 | |||
193 | n += scnprintf(buf + n, len - n, "\nExtn [FPU]\t: %s", | ||
194 | !(cpu->fp.ver || cpu->dpfp.ver) ? "N/A" : ""); | ||
195 | |||
196 | if (cpu->fp.ver) | ||
197 | n += scnprintf(buf + n, len - n, "SP [v%d] %s", | ||
198 | cpu->fp.ver, cpu->fp.fast ? "(fast)" : ""); | ||
199 | |||
200 | if (cpu->dpfp.ver) | ||
201 | n += scnprintf(buf + n, len - n, "DP [v%d] %s", | ||
202 | cpu->dpfp.ver, cpu->dpfp.fast ? "(fast)" : ""); | ||
203 | |||
204 | n += scnprintf(buf + n, len - n, "\n"); | ||
205 | |||
206 | #ifdef _ASM_GENERIC_UNISTD_H | ||
207 | n += scnprintf(buf + n, len - n, | ||
208 | "OS ABI [v2]\t: asm-generic/{unistd,stat,fcntl}\n"); | ||
209 | #endif | ||
210 | |||
211 | return buf; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * Ensure that FP hardware and kernel config match | ||
216 | * -If hardware contains DPFP, kernel needs to save/restore FPU state | ||
217 | * across context switches | ||
218 | * -If hardware lacks DPFP, but kernel configured to save FPU state then | ||
219 | * kernel trying to access non-existant DPFP regs will crash | ||
220 | * | ||
221 | * We only check for Dbl precision Floating Point, because only DPFP | ||
222 | * hardware has dedicated regs which need to be saved/restored on ctx-sw | ||
223 | * (Single Precision uses core regs), thus kernel is kind of oblivious to it | ||
224 | */ | ||
225 | void __init arc_chk_fpu(void) | ||
226 | { | ||
227 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; | ||
228 | |||
229 | if (cpu->dpfp.ver) { | ||
230 | #ifndef CONFIG_ARC_FPU_SAVE_RESTORE | ||
231 | pr_warn("DPFP support broken in this kernel...\n"); | ||
232 | #endif | ||
233 | } else { | ||
234 | #ifdef CONFIG_ARC_FPU_SAVE_RESTORE | ||
235 | panic("H/w lacks DPFP support, apps won't work\n"); | ||
236 | #endif | ||
237 | } | ||
42 | } | 238 | } |
43 | 239 | ||
44 | /* | 240 | /* |
@@ -49,10 +245,25 @@ void __init read_arc_build_cfg_regs(void) | |||
49 | 245 | ||
50 | void __init setup_processor(void) | 246 | void __init setup_processor(void) |
51 | { | 247 | { |
248 | char str[512]; | ||
249 | int cpu_id = smp_processor_id(); | ||
250 | |||
52 | read_arc_build_cfg_regs(); | 251 | read_arc_build_cfg_regs(); |
53 | arc_init_IRQ(); | 252 | arc_init_IRQ(); |
253 | |||
254 | printk(arc_cpu_mumbojumbo(cpu_id, str, sizeof(str))); | ||
255 | |||
54 | arc_mmu_init(); | 256 | arc_mmu_init(); |
55 | arc_cache_init(); | 257 | arc_cache_init(); |
258 | |||
259 | |||
260 | printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str))); | ||
261 | |||
262 | #ifdef CONFIG_SMP | ||
263 | printk(arc_platform_smp_cpuinfo()); | ||
264 | #endif | ||
265 | |||
266 | arc_chk_fpu(); | ||
56 | } | 267 | } |
57 | 268 | ||
58 | void __init __attribute__((weak)) arc_platform_early_init(void) | 269 | void __init __attribute__((weak)) arc_platform_early_init(void) |
@@ -126,12 +337,22 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
126 | if (!str) | 337 | if (!str) |
127 | goto done; | 338 | goto done; |
128 | 339 | ||
129 | seq_printf(m, "ARC700 #%d\n", cpu_id); | 340 | seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE)); |
130 | 341 | ||
131 | seq_printf(m, "Bogo MIPS : \t%lu.%02lu\n", | 342 | seq_printf(m, "Bogo MIPS : \t%lu.%02lu\n", |
132 | loops_per_jiffy / (500000 / HZ), | 343 | loops_per_jiffy / (500000 / HZ), |
133 | (loops_per_jiffy / (5000 / HZ)) % 100); | 344 | (loops_per_jiffy / (5000 / HZ)) % 100); |
134 | 345 | ||
346 | seq_printf(m, arc_mmu_mumbojumbo(cpu_id, str, PAGE_SIZE)); | ||
347 | |||
348 | seq_printf(m, arc_cache_mumbojumbo(cpu_id, str, PAGE_SIZE)); | ||
349 | |||
350 | seq_printf(m, arc_extn_mumbojumbo(cpu_id, str, PAGE_SIZE)); | ||
351 | |||
352 | #ifdef CONFIG_SMP | ||
353 | seq_printf(m, arc_platform_smp_cpuinfo()); | ||
354 | #endif | ||
355 | |||
135 | free_page((unsigned long)str); | 356 | free_page((unsigned long)str); |
136 | done: | 357 | done: |
137 | seq_printf(m, "\n\n"); | 358 | seq_printf(m, "\n\n"); |