1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  All you never wanted to know about CPUs	File: ui_cpuinfo.c
5    *
6    *  Routines to display CPU info (common to all CPUs)
7    *
8    *  Author:  Mitch Lichtenberg
9    *
10    *********************************************************************
11    *
12    *  Copyright 2000,2001,2002,2003,2004,2005
13    *  Broadcom Corporation. All rights reserved.
14    *
15    *  This software is furnished under license and may be used and
16    *  copied only in accordance with the following terms and
17    *  conditions.  Subject to these conditions, you may download,
18    *  copy, install, use, modify and distribute modified or unmodified
19    *  copies of this software in source and/or binary form.  No title
20    *  or ownership is transferred hereby.
21    *
22    *  1) Any source code used, modified or distributed must reproduce
23    *     and retain this copyright notice and list of conditions
24    *     as they appear in the source file.
25    *
26    *  2) No right is granted to use any trade name, trademark, or
27    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
28    *     name may not be used to endorse or promote products derived
29    *     from this software without the prior written permission of
30    *     Broadcom Corporation.
31    *
32    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44    *     THE POSSIBILITY OF SUCH DAMAGE.
45    ********************************************************************* */
46
47#include "cfe.h"
48#include "sbmips.h"
49#include "ui_command.h"
50
51#ifdef SIBYTE_SB1250
52#include "sb1250_regs.h"
53#include "sb1250_scd.h"
54#include "sb1250_wid.h"
55#endif
56#ifdef SIBYTE_BCM1480
57#include "bcm1480_regs.h"
58#include "bcm1480_scd.h"
59#include "bcm1480_l2c.h"
60#endif
61
62#include "env_subr.h"
63
64
65/*  *********************************************************************
66    *  Macros
67    ********************************************************************* */
68
69/*
70 * This lets us override the WID by poking values into our PromICE
71 */
72#ifdef _MAGICWID_
73#undef A_SCD_SYSTEM_REVISION
74#define A_SCD_SYSTEM_REVISION 0x1FC00508
75#undef A_SCD_SYSTEM_MANUF
76#define A_SCD_SYSTEM_MANUF 0x1FC00518
77#endif
78
79/*  *********************************************************************
80    *  Externs/forwards
81    ********************************************************************* */
82
83void sb1250_show_cpu_type(void);
84
85/* XXXCGD: could be const, when env_setenv can cope.  */
86#ifdef SIBYTE_SB1250
87static char *show_cpu_type_bcm1250(char *, uint64_t syscfg, uint64_t sysrev);
88static char *show_cpu_type_bcm112x(char *, uint64_t syscfg, uint64_t sysrev);
89static void ibm_waferid_str(uint64_t wid, char *wid_str);
90#endif
91#ifdef SIBYTE_BCM1480
92static char *show_cpu_type_bcm1480(char *, uint64_t syscfg, uint64_t sysrev);
93#endif
94
95
96/*  *********************************************************************
97    *  ui_show_cpu_type()
98    *
99    *  Display board CPU information
100    *
101    *  Input parameters:
102    *  	   nothing
103    *
104    *  Return value:
105    *  	   nothing
106    ********************************************************************* */
107void sb1250_show_cpu_type(void)
108{
109    uint64_t syscfg, sysrev;
110    /* XXXCGD: could be const, when env_setenv can cope.  */
111    char *envval;
112    char *cpuname;
113    char *(*infofn)(char *, uint64_t, uint64_t);
114    char temp[32];
115
116    syscfg = SBREADCSR(A_SCD_SYSTEM_CFG);
117    sysrev = SBREADCSR(A_SCD_SYSTEM_REVISION);
118
119    switch (SYS_SOC_TYPE(sysrev)) {
120#ifdef SIBYTE_SB1250
121	case K_SYS_SOC_TYPE_BCM1250:
122	    cpuname = "1250";
123	    infofn = show_cpu_type_bcm1250;
124	    break;
125
126	case K_SYS_SOC_TYPE_BCM1120:
127	    cpuname = "1120";
128	    infofn = show_cpu_type_bcm112x;
129	    break;
130
131	case K_SYS_SOC_TYPE_BCM1125:
132	    cpuname = "1125";
133	    infofn = show_cpu_type_bcm112x;
134	    break;
135
136	case K_SYS_SOC_TYPE_BCM1125H:
137	    cpuname = "1125H";
138	    infofn = show_cpu_type_bcm112x;
139	    break;
140#endif /* SIBYTE_SB1250 */
141
142#ifdef SIBYTE_BCM1480
143	case K_SYS_SOC_TYPE_BCM1x80:
144	    if (G_SYS_PART(sysrev) == K_SYS_PART_BCM1480)
145		cpuname = "1480";
146	    else if (G_SYS_PART(sysrev) == K_SYS_PART_BCM1280)
147		cpuname = "1280";
148	    else if (G_SYS_PART(sysrev) == K_SYS_PART_BCM1158)
149		cpuname = "1158";
150	    else {
151		sprintf(temp, "unknown_1x80_%04x", (int)G_SYS_PART(sysrev));
152		cpuname = temp;
153		}
154	    infofn = show_cpu_type_bcm1480;
155	    break;
156
157	case K_SYS_SOC_TYPE_BCM1x55:
158	    if (G_SYS_PART(sysrev) == K_SYS_PART_BCM1455)
159		cpuname = "1455";
160	    else if (G_SYS_PART(sysrev) == K_SYS_PART_BCM1255)
161		cpuname = "1255";
162	    else {
163		sprintf(temp, "unknown_1x55_%04x", (int)G_SYS_PART(sysrev));
164		cpuname = temp;
165		}
166	    infofn = show_cpu_type_bcm1480;
167	    break;
168#endif /* SIBYTE_BCM1480 */
169
170	default:
171	    sprintf(temp, "unknown_%04x", (int)G_SYS_PART(sysrev));
172	    cpuname = temp;
173	    infofn = NULL;
174	    break;
175	}
176
177    env_setenv("CPU_TYPE", cpuname,
178	       ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
179
180    envval = NULL;
181    if (infofn != NULL)
182	envval = (*infofn)(cpuname, syscfg, sysrev);
183    if (envval == NULL) {
184        sprintf(temp, "unknown_%02x", (int)G_SYS_REVISION(sysrev));
185	envval = temp;
186    }
187    env_setenv("CPU_REVISION", envval,
188	       ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
189
190    /* Set # of CPUs based on 2nd hex digit of part number */
191    sprintf(temp, "%d", (int)((G_SYS_PART(sysrev) >> 8) & 0x0F));
192    env_setenv("CPU_NUM_CORES", temp,
193	       ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
194
195}
196
197
198#ifdef SIBYTE_SB1250
199static void
200sb1xxx_show_syscfg(uint64_t syscfg)
201{
202    int plldiv;
203    char temp[32];
204
205    /*
206     * Set variable that contains CPU speed, spit out config register
207     */
208    printf("SysCfg: %016llX [PLL_DIV: %d, IOB0_DIV: %s, IOB1_DIV: %s]\n",
209	   syscfg,
210	   (int)G_SYS_PLL_DIV(syscfg),
211	   (syscfg & M_SYS_IOB0_DIV) ? "CPUCLK/3" : "CPUCLK/4",
212	   (syscfg & M_SYS_IOB1_DIV) ? "CPUCLK/2" : "CPUCLK/3");
213
214    plldiv = G_SYS_PLL_DIV(syscfg);
215    if (plldiv == 0) {
216	/* XXX: keep in synch with setting of CPU speed, above. */
217	printf("PLL_DIV of zero found, assuming 6 (300MHz)\n");
218	plldiv = 6;
219    }
220
221    sprintf(temp, "%d", plldiv * 50);
222    env_setenv("CPU_SPEED", temp,
223	       ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
224}
225
226
227/*  *********************************************************************
228    *  show_cpu_type_bcm1250()
229    *
230    *  Display CPU information for BCM1250 CPUs
231    *
232    *  Input parameters:
233    *  	   revstr: pointer to string pointer, to be filled in with
234    *      revision name.
235    *
236    *  Return value:
237    *  	   none.  fills in revstr.
238    ********************************************************************* */
239static char *
240show_cpu_type_bcm1250(char *cpuname, uint64_t syscfg, uint64_t sysrev)
241{
242    char *revstr, *revprintstr;
243    uint64_t cachetest;
244    uint64_t sysmanuf, ibm_wid;
245    uint32_t wid;
246    int bin;
247    unsigned int cpu_pass;
248    char temp[32];
249    static uint8_t cachesizes[16] = {4,2,2,2,2,1,1,1,2,1,1,1,2,1,1,0};
250    static char *binnames[8] = {
251	"2CPU_FI_1D_H2",
252	"2CPU_FI_FD_F2 (OK)",
253	"2CPU_FI_FD_H2",
254	"2CPU_3I_3D_F2",
255	"2CPU_3I_3D_H2",
256	"1CPU_FI_FD_F2",
257	"1CPU_FI_FD_H2",
258	"2CPU_1I_1D_Q2"};
259
260    cpu_pass = G_SYS_REVISION(sysrev);
261
262    wid = G_SYS_WID(SBREADCSR(A_SCD_SYSTEM_REVISION));
263    wid = WID_UNCONVOLUTE(wid);
264
265    if ((wid != 0) && (cpu_pass == K_SYS_REVISION_BCM1250_A2)) {
266	cpu_pass = K_SYS_REVISION_BCM1250_A6;
267	}
268
269    switch (cpu_pass) {
270	case K_SYS_REVISION_BCM1250_PASS1:
271	    revstr = "PASS1";
272	    revprintstr = "Pass 1";
273	    break;
274	case K_SYS_REVISION_BCM1250_A1:
275	    revstr = "A1";
276	    revprintstr = "Pass 2.0 (wirebond)";
277	    break;
278	case K_SYS_REVISION_BCM1250_A2:
279	    revstr = "A2";
280	    revprintstr = "Pass 2.0 (flip-chip)";
281	    break;
282	case K_SYS_REVISION_BCM1250_A3:
283	    revstr = "A3";
284	    revprintstr = "A3 Pass 2.1 (flip-chip)";
285	    break;
286	case K_SYS_REVISION_BCM1250_A4:
287	    revstr = "A4";
288	    revprintstr = "A4 Pass 2.1 (wirebond)";
289	    break;
290	case K_SYS_REVISION_BCM1250_A6:
291	    revstr = revprintstr = "A6";
292	    break;
293	case K_SYS_REVISION_BCM1250_A8:
294	    revprintstr = "A8/A10";
295	    revstr = "A8";
296	    break;
297	case K_SYS_REVISION_BCM1250_A9:
298	    revstr = revprintstr = "A9";
299	    break;
300	case K_SYS_REVISION_BCM1250_B1:
301	    revprintstr = "B0/B1";
302	    revstr = "B1";
303	    break;
304	case K_SYS_REVISION_BCM1250_B2:
305	    revstr = revprintstr = "B2";
306	    break;
307	case K_SYS_REVISION_BCM1250_C0:
308	    revstr = revprintstr = "C0";
309	    break;
310	case K_SYS_REVISION_BCM1250_C1:
311	    revstr = revprintstr = "C1";
312	    break;
313	case K_SYS_REVISION_BCM1250_C2:
314	    revstr = revprintstr = "C2";
315	    break;
316	default:
317	    revstr = NULL;
318	    sprintf(temp, "rev 0x%x", (int)G_SYS_REVISION(sysrev));
319	    revprintstr = temp;
320	    break;
321	}
322    printf("CPU: BCM1250 %s\n", revprintstr);
323
324    if (((G_SYS_PART(sysrev) >> 8) & 0x0F) == 1) {
325	printf("[Uniprocessor CPU mode]\n");
326	}
327
328    /*
329     * Report cache status if the cache was disabled, or the status of
330     * the cache test for non-WID pass2 and pass3 parts.
331     */
332    printf("L2 Cache Status: ");
333    if ((syscfg & M_SYS_L2C_RESET) != 0) {
334	printf("disabled via JTAG\n");
335	}
336    else if ((cpu_pass == K_SYS_REVISION_BCM1250_A1) ||
337	     (cpu_pass == K_SYS_REVISION_BCM1250_A2) ||
338	     (cpu_pass == K_SYS_REVISION_BCM1250_C0) ||
339	     (cpu_pass == K_SYS_REVISION_BCM1250_C1) ) {
340	cachetest = (SBREADCSR(A_MAC_REGISTER(2, R_MAC_HASH_BASE)) & 0x0F);
341	printf("0x%llX    Available L2 Cache: %dKB\n", cachetest,
342	       ((int)cachesizes[(int)cachetest])*128);
343	}
344    else printf("OK\n");
345
346    if (wid == 0) {
347	printf("Wafer ID:  Not set\n");
348	}
349    else if (cpu_pass < K_SYS_REVISION_BCM1250_C0) {
350
351	printf("Wafer ID:   0x%08X  [Lot %d, Wafer %d]\n", wid,
352	       G_WID_LOTID(wid), G_WID_WAFERID(wid));
353
354	bin = G_WID_BIN(wid);
355
356	printf("Manuf Test: Bin %c [%s] ", "EABCDFGH"[bin], binnames[bin]);
357
358	if (bin != K_WID_BIN_2CPU_FI_FD_F2)  {
359	    printf("L2:%d ", G_WID_L2QTR(wid));
360	    printf("CPU0:[I=%d D=%d]  ", G_WID_CPU0_L1I(wid), G_WID_CPU0_L1D(wid));
361	    printf("CPU1:[I=%d D=%d]", G_WID_CPU1_L1I(wid), G_WID_CPU1_L1D(wid));
362	    }
363	printf("\n");
364	}
365
366    if (cpu_pass >= K_SYS_REVISION_BCM1250_C0) {
367	/* Read system_manuf register for C0 or greater*/
368	sysmanuf = SBREADCSR(A_SCD_SYSTEM_MANUF);
369
370	printf("SysManuf:  %016llX [X: %d Y: %d] ", sysmanuf, (int)G_SYS_XPOS(sysmanuf),
371	                                            (int)G_SYS_YPOS(sysmanuf));
372
373	ibm_wid = ((sysmanuf & 0xf000000000LL) >> 4) | (sysmanuf & 0xffffffff);
374	char wid_str[7];
375	ibm_waferid_str(ibm_wid, wid_str);
376	printf("[Wafer ID: %s]", wid_str);
377
378	printf("\n");
379	}
380
381    sb1xxx_show_syscfg(syscfg);
382
383    return (revstr);
384}
385
386/*  *********************************************************************
387    *  show_cpu_type_bcm112x()
388    *
389    *  Display CPU information for BCM112x CPUs
390    *
391    *  Input parameters:
392    *  	   revstr: pointer to string pointer, to be filled in with
393    *      revision name.
394    *
395    *  Return value:
396    *  	   none.  fills in revstr.
397    ********************************************************************* */
398static char *
399show_cpu_type_bcm112x(char *cpuname, uint64_t syscfg, uint64_t sysrev)
400{
401    char *revstr, *revprintstr;
402    char temp[32];
403
404    switch (G_SYS_REVISION(sysrev)) {
405	case K_SYS_REVISION_BCM112x_A1:
406	    revstr = revprintstr = "A1";
407	    break;
408	case K_SYS_REVISION_BCM112x_A2:
409	    revstr = revprintstr = "A2";
410	    break;
411	case K_SYS_REVISION_BCM112x_A3:
412	    revstr = revprintstr = "A3";
413	    break;
414	case K_SYS_REVISION_BCM112x_A4:
415	    revstr = revprintstr = "A4";
416	    break;
417	default:
418	    revstr = NULL;
419	    sprintf(temp, "rev 0x%x", (int)G_SYS_REVISION(sysrev));
420	    revprintstr = temp;
421	    break;
422	}
423    printf("CPU: %s %s\n", env_getenv("CPU_TYPE"), revprintstr);
424
425    printf("L2 Cache: ");
426    if ((syscfg & M_SYS_L2C_RESET) != 0)
427	printf("disabled via JTAG\n");
428    else {
429    /*1122 is 128K.  same soc type as 1125*/
430       if (G_SYS_L2C_SIZE(sysrev) == K_SYS_L2C_SIZE_BCM1122)
431    		printf("128KB\n");
432        else
433      		printf("256KB\n");
434    }
435
436
437    sb1xxx_show_syscfg(syscfg);
438
439    return (revstr);
440}
441
442/* Decode IBMs WaferID code */
443static void ibm_waferid_str(uint64_t wid, char *wid_str)
444{
445  int i;
446
447  for (i=0; i<6; i++) {
448    unsigned char bits;
449    char code;
450
451    bits = wid & 0x3f;
452    wid >>= 6;
453    if (bits < 0xa)
454      code = bits + '0';
455    else if (bits < 0x24)
456      code = (bits - 0xa) + 'A';
457    else if (bits == 0x3d)
458      code = '-';
459    else if (bits == 0x3e)
460      code = '.';
461    else if (bits == 0x3f)
462      code = ' ';
463    else
464      code = '?';
465    wid_str[5-i] = code;
466  }
467  wid_str[6] = '\0';
468}
469#endif /* SIBYTE_SB1250 */
470
471
472#ifdef SIBYTE_BCM1480
473static void
474bcm14xx_show_syscfg(uint64_t syscfg)
475{
476    int plldiv;
477    char temp[32];
478
479    printf("SysCfg: %016llX [PLL_DIV:%d, SW_DIV:%d, CCNUMA:%s, IOB_DIV:%s]\n",
480	   syscfg,
481	   (int)G_BCM1480_SYS_PLL_DIV(syscfg),
482	   (int)G_BCM1480_SYS_SW_DIV(syscfg),
483	   (syscfg & M_BCM1480_SYS_CCNUMA_EN) ? "enable" : "disable",
484	   (syscfg & M_BCM1480_SYS_IOB_DIV) ? "CPUCLK/3" : "CPUCLK/4");
485
486    plldiv = G_BCM1480_SYS_PLL_DIV(syscfg);
487    if (plldiv == 0) {
488	/* XXX: keep in synch with setting of CPU speed, above. */
489	printf("PLL_DIV of zero found, assuming 6 (300MHz)\n");
490	plldiv = 6;
491    }
492
493    sprintf(temp, "%d", plldiv * 50);
494    env_setenv("CPU_SPEED", temp,
495	       ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
496}
497
498
499/*  *********************************************************************
500    *  show_cpu_type_bcm1480()
501    *
502    *  Display CPU information for BCM1480 CPUs
503    *
504    *  Input parameters:
505    *  	   revstr: pointer to string pointer, to be filled in with
506    *      revision name.
507    *
508    *  Return value:
509    *  	   none.  fills in revstr.
510    ********************************************************************* */
511static char *
512show_cpu_type_bcm1480(char *cpuname, uint64_t syscfg, uint64_t sysrev)
513{
514    int cpu_pass = G_SYS_REVISION(sysrev);
515    int enabled_cpus = bcm1480_num_cpus();
516    uint64_t l2c_misc0_value;
517    char *revstr, *revprintstr, *cachestr;
518    char temp[32];
519    int l2_disabled = 0;
520
521#ifdef _BIGSUR_
522    /*
523     * This is a special hack just for the BCM1480 bringup board.  Customers,
524     * please do not include this code in your ports!  The BCM1480 has no
525     * way to read whether the L2 cache is being held in reset or not,
526     * so we are using the least significant config bit (M_BCM1480_SYS_CONFIG)
527     * to pass this information from the boot script to the firmware.
528     */
529    if (syscfg & (1<<S_BCM1480_SYS_CONFIG)) {
530	l2_disabled = 1;
531	}
532#endif
533
534    switch (cpu_pass) {
535	case K_SYS_REVISION_BCM1480_S0:
536	    revstr = "S0";
537	    revprintstr = "S0 (pass1)";
538	    break;
539	case K_SYS_REVISION_BCM1480_A1:
540	    revstr = "A1";
541	    revprintstr = "A1 (pass1)";
542	    break;
543	case K_SYS_REVISION_BCM1480_A2:
544	    revstr = "A2";
545	    revprintstr = "A2 (pass1)";
546	    break;
547	case K_SYS_REVISION_BCM1480_A3:
548	    revstr = "A3";
549	    revprintstr = "A3 (pass1)";
550	    break;
551	case K_SYS_REVISION_BCM1480_B0:
552	    revstr = "B0";
553	    revprintstr = "B0 (pass2)";
554	    break;
555	default:
556	    sprintf(temp, "rev 0x%x", (int)cpu_pass);
557	    revprintstr = temp;
558	    revstr = NULL;
559	    break;
560	}
561
562    printf("CPU: %s %s, %d cpu%s", cpuname, revprintstr, enabled_cpus,
563           enabled_cpus == 1 ? "" : "s");
564    if (G_SYS_NUM_CPUS(sysrev) != enabled_cpus)
565	printf(" enabled (%d disabled - fused)",
566	       G_SYS_NUM_CPUS(sysrev) - enabled_cpus);
567    printf("\n");
568
569    if (l2_disabled) {
570	/* Must not touch L2 cache registers if L2C is held in reset */
571	cachestr = "disabled via JTAG";
572	}
573    else {
574	l2c_misc0_value = SBREADCSR(A_BCM1480_L2_MISC0_VALUE);
575	cachestr = "unknown size";
576	if (G_SYS_L2C_SIZE(sysrev) == K_SYS_L2C_SIZE_1MB &&
577	    G_BCM1480_L2C_MISC0_CACHE_DISABLE(l2c_misc0_value) != 0)
578	    cachestr = "512KB (512KB disabled by software)";
579	else if (G_SYS_L2C_SIZE(sysrev) == K_SYS_L2C_SIZE_1MB)
580	    cachestr = "1MB";
581	else if (G_SYS_L2C_SIZE(sysrev) == K_SYS_L2C_SIZE_512KB)
582	    cachestr = "512KB";
583	}
584
585    printf("L2Cache: %s\n", cachestr);
586
587    bcm14xx_show_syscfg(syscfg);
588
589    return revstr;
590}
591#endif /* SIBYTE_BCM1480 */
592