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