1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * identify.c: machine identification code.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
6*4882a593Smuzhiyun * Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun #include <linux/init.h>
9*4882a593Smuzhiyun #include <linux/kernel.h>
10*4882a593Smuzhiyun #include <linux/mc146818rtc.h>
11*4882a593Smuzhiyun #include <linux/export.h>
12*4882a593Smuzhiyun #include <linux/string.h>
13*4882a593Smuzhiyun #include <linux/types.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <asm/bootinfo.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <asm/dec/ioasic.h>
18*4882a593Smuzhiyun #include <asm/dec/ioasic_addrs.h>
19*4882a593Smuzhiyun #include <asm/dec/kn01.h>
20*4882a593Smuzhiyun #include <asm/dec/kn02.h>
21*4882a593Smuzhiyun #include <asm/dec/kn02ba.h>
22*4882a593Smuzhiyun #include <asm/dec/kn02ca.h>
23*4882a593Smuzhiyun #include <asm/dec/kn03.h>
24*4882a593Smuzhiyun #include <asm/dec/kn230.h>
25*4882a593Smuzhiyun #include <asm/dec/prom.h>
26*4882a593Smuzhiyun #include <asm/dec/system.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include "dectypes.h"
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static const char *dec_system_strings[] = {
31*4882a593Smuzhiyun [MACH_DSUNKNOWN] "unknown DECstation",
32*4882a593Smuzhiyun [MACH_DS23100] "DECstation 2100/3100",
33*4882a593Smuzhiyun [MACH_DS5100] "DECsystem 5100",
34*4882a593Smuzhiyun [MACH_DS5000_200] "DECstation 5000/200",
35*4882a593Smuzhiyun [MACH_DS5000_1XX] "DECstation 5000/1xx",
36*4882a593Smuzhiyun [MACH_DS5000_XX] "Personal DECstation 5000/xx",
37*4882a593Smuzhiyun [MACH_DS5000_2X0] "DECstation 5000/2x0",
38*4882a593Smuzhiyun [MACH_DS5400] "DECsystem 5400",
39*4882a593Smuzhiyun [MACH_DS5500] "DECsystem 5500",
40*4882a593Smuzhiyun [MACH_DS5800] "DECsystem 5800",
41*4882a593Smuzhiyun [MACH_DS5900] "DECsystem 5900",
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun
get_system_type(void)44*4882a593Smuzhiyun const char *get_system_type(void)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun #define STR_BUF_LEN 64
47*4882a593Smuzhiyun static char system[STR_BUF_LEN];
48*4882a593Smuzhiyun static int called = 0;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (called == 0) {
51*4882a593Smuzhiyun called = 1;
52*4882a593Smuzhiyun snprintf(system, STR_BUF_LEN, "Digital %s",
53*4882a593Smuzhiyun dec_system_strings[mips_machtype]);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun return system;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /*
61*4882a593Smuzhiyun * Setup essential system-specific memory addresses. We need them
62*4882a593Smuzhiyun * early. Semantically the functions belong to prom/init.c, but they
63*4882a593Smuzhiyun * are compact enough we want them inlined. --macro
64*4882a593Smuzhiyun */
65*4882a593Smuzhiyun volatile u8 *dec_rtc_base;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun EXPORT_SYMBOL(dec_rtc_base);
68*4882a593Smuzhiyun
prom_init_kn01(void)69*4882a593Smuzhiyun static inline void prom_init_kn01(void)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun dec_kn_slot_base = KN01_SLOT_BASE;
72*4882a593Smuzhiyun dec_kn_slot_size = KN01_SLOT_SIZE;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
prom_init_kn230(void)77*4882a593Smuzhiyun static inline void prom_init_kn230(void)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun dec_kn_slot_base = KN01_SLOT_BASE;
80*4882a593Smuzhiyun dec_kn_slot_size = KN01_SLOT_SIZE;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
prom_init_kn02(void)85*4882a593Smuzhiyun static inline void prom_init_kn02(void)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun dec_kn_slot_base = KN02_SLOT_BASE;
88*4882a593Smuzhiyun dec_kn_slot_size = KN02_SLOT_SIZE;
89*4882a593Smuzhiyun dec_tc_bus = 1;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN02_RTC);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
prom_init_kn02xa(void)94*4882a593Smuzhiyun static inline void prom_init_kn02xa(void)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun dec_kn_slot_base = KN02XA_SLOT_BASE;
97*4882a593Smuzhiyun dec_kn_slot_size = IOASIC_SLOT_SIZE;
98*4882a593Smuzhiyun dec_tc_bus = 1;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
101*4882a593Smuzhiyun dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
prom_init_kn03(void)104*4882a593Smuzhiyun static inline void prom_init_kn03(void)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun dec_kn_slot_base = KN03_SLOT_BASE;
107*4882a593Smuzhiyun dec_kn_slot_size = IOASIC_SLOT_SIZE;
108*4882a593Smuzhiyun dec_tc_bus = 1;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
111*4882a593Smuzhiyun dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun
prom_identify_arch(u32 magic)115*4882a593Smuzhiyun void __init prom_identify_arch(u32 magic)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun unsigned char dec_cpunum, dec_firmrev, dec_etc, dec_systype;
118*4882a593Smuzhiyun u32 dec_sysid;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (!prom_is_rex(magic)) {
121*4882a593Smuzhiyun dec_sysid = simple_strtoul(prom_getenv("systype"),
122*4882a593Smuzhiyun (char **)0, 0);
123*4882a593Smuzhiyun } else {
124*4882a593Smuzhiyun dec_sysid = rex_getsysid();
125*4882a593Smuzhiyun if (dec_sysid == 0) {
126*4882a593Smuzhiyun printk("Zero sysid returned from PROM! "
127*4882a593Smuzhiyun "Assuming a PMAX-like machine.\n");
128*4882a593Smuzhiyun dec_sysid = 1;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun dec_cpunum = (dec_sysid & 0xff000000) >> 24;
133*4882a593Smuzhiyun dec_systype = (dec_sysid & 0xff0000) >> 16;
134*4882a593Smuzhiyun dec_firmrev = (dec_sysid & 0xff00) >> 8;
135*4882a593Smuzhiyun dec_etc = dec_sysid & 0xff;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /*
138*4882a593Smuzhiyun * FIXME: This may not be an exhaustive list of DECStations/Servers!
139*4882a593Smuzhiyun * Put all model-specific initialisation calls here.
140*4882a593Smuzhiyun */
141*4882a593Smuzhiyun switch (dec_systype) {
142*4882a593Smuzhiyun case DS2100_3100:
143*4882a593Smuzhiyun mips_machtype = MACH_DS23100;
144*4882a593Smuzhiyun prom_init_kn01();
145*4882a593Smuzhiyun break;
146*4882a593Smuzhiyun case DS5100: /* DS5100 MIPSMATE */
147*4882a593Smuzhiyun mips_machtype = MACH_DS5100;
148*4882a593Smuzhiyun prom_init_kn230();
149*4882a593Smuzhiyun break;
150*4882a593Smuzhiyun case DS5000_200: /* DS5000 3max */
151*4882a593Smuzhiyun mips_machtype = MACH_DS5000_200;
152*4882a593Smuzhiyun prom_init_kn02();
153*4882a593Smuzhiyun break;
154*4882a593Smuzhiyun case DS5000_1XX: /* DS5000/100 3min */
155*4882a593Smuzhiyun mips_machtype = MACH_DS5000_1XX;
156*4882a593Smuzhiyun prom_init_kn02xa();
157*4882a593Smuzhiyun break;
158*4882a593Smuzhiyun case DS5000_2X0: /* DS5000/240 3max+ or DS5900 bigmax */
159*4882a593Smuzhiyun mips_machtype = MACH_DS5000_2X0;
160*4882a593Smuzhiyun prom_init_kn03();
161*4882a593Smuzhiyun if (!(ioasic_read(IO_REG_SIR) & KN03_IO_INR_3MAXP))
162*4882a593Smuzhiyun mips_machtype = MACH_DS5900;
163*4882a593Smuzhiyun break;
164*4882a593Smuzhiyun case DS5000_XX: /* Personal DS5000/xx maxine */
165*4882a593Smuzhiyun mips_machtype = MACH_DS5000_XX;
166*4882a593Smuzhiyun prom_init_kn02xa();
167*4882a593Smuzhiyun break;
168*4882a593Smuzhiyun case DS5800: /* DS5800 Isis */
169*4882a593Smuzhiyun mips_machtype = MACH_DS5800;
170*4882a593Smuzhiyun break;
171*4882a593Smuzhiyun case DS5400: /* DS5400 MIPSfair */
172*4882a593Smuzhiyun mips_machtype = MACH_DS5400;
173*4882a593Smuzhiyun break;
174*4882a593Smuzhiyun case DS5500: /* DS5500 MIPSfair-2 */
175*4882a593Smuzhiyun mips_machtype = MACH_DS5500;
176*4882a593Smuzhiyun break;
177*4882a593Smuzhiyun default:
178*4882a593Smuzhiyun mips_machtype = MACH_DSUNKNOWN;
179*4882a593Smuzhiyun break;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun if (mips_machtype == MACH_DSUNKNOWN)
183*4882a593Smuzhiyun printk("This is an %s, id is %x\n",
184*4882a593Smuzhiyun dec_system_strings[mips_machtype], dec_systype);
185*4882a593Smuzhiyun else
186*4882a593Smuzhiyun printk("This is a %s\n", dec_system_strings[mips_machtype]);
187*4882a593Smuzhiyun }
188