162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * identify.c: machine identification code. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine 662306a36Sopenharmony_ci * Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include <linux/init.h> 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/mc146818rtc.h> 1162306a36Sopenharmony_ci#include <linux/export.h> 1262306a36Sopenharmony_ci#include <linux/string.h> 1362306a36Sopenharmony_ci#include <linux/types.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <asm/bootinfo.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <asm/dec/ioasic.h> 1862306a36Sopenharmony_ci#include <asm/dec/ioasic_addrs.h> 1962306a36Sopenharmony_ci#include <asm/dec/kn01.h> 2062306a36Sopenharmony_ci#include <asm/dec/kn02.h> 2162306a36Sopenharmony_ci#include <asm/dec/kn02ba.h> 2262306a36Sopenharmony_ci#include <asm/dec/kn02ca.h> 2362306a36Sopenharmony_ci#include <asm/dec/kn03.h> 2462306a36Sopenharmony_ci#include <asm/dec/kn230.h> 2562306a36Sopenharmony_ci#include <asm/dec/prom.h> 2662306a36Sopenharmony_ci#include <asm/dec/system.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include "dectypes.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic const char *dec_system_strings[] = { 3162306a36Sopenharmony_ci [MACH_DSUNKNOWN] "unknown DECstation", 3262306a36Sopenharmony_ci [MACH_DS23100] "DECstation 2100/3100", 3362306a36Sopenharmony_ci [MACH_DS5100] "DECsystem 5100", 3462306a36Sopenharmony_ci [MACH_DS5000_200] "DECstation 5000/200", 3562306a36Sopenharmony_ci [MACH_DS5000_1XX] "DECstation 5000/1xx", 3662306a36Sopenharmony_ci [MACH_DS5000_XX] "Personal DECstation 5000/xx", 3762306a36Sopenharmony_ci [MACH_DS5000_2X0] "DECstation 5000/2x0", 3862306a36Sopenharmony_ci [MACH_DS5400] "DECsystem 5400", 3962306a36Sopenharmony_ci [MACH_DS5500] "DECsystem 5500", 4062306a36Sopenharmony_ci [MACH_DS5800] "DECsystem 5800", 4162306a36Sopenharmony_ci [MACH_DS5900] "DECsystem 5900", 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciconst char *get_system_type(void) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci#define STR_BUF_LEN 64 4762306a36Sopenharmony_ci static char system[STR_BUF_LEN]; 4862306a36Sopenharmony_ci static int called = 0; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (called == 0) { 5162306a36Sopenharmony_ci called = 1; 5262306a36Sopenharmony_ci snprintf(system, STR_BUF_LEN, "Digital %s", 5362306a36Sopenharmony_ci dec_system_strings[mips_machtype]); 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci return system; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* 6162306a36Sopenharmony_ci * Setup essential system-specific memory addresses. We need them 6262306a36Sopenharmony_ci * early. Semantically the functions belong to prom/init.c, but they 6362306a36Sopenharmony_ci * are compact enough we want them inlined. --macro 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_civolatile u8 *dec_rtc_base; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciEXPORT_SYMBOL(dec_rtc_base); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic inline void prom_init_kn01(void) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci dec_kn_slot_base = KN01_SLOT_BASE; 7262306a36Sopenharmony_ci dec_kn_slot_size = KN01_SLOT_SIZE; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic inline void prom_init_kn230(void) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci dec_kn_slot_base = KN01_SLOT_BASE; 8062306a36Sopenharmony_ci dec_kn_slot_size = KN01_SLOT_SIZE; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic inline void prom_init_kn02(void) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci dec_kn_slot_base = KN02_SLOT_BASE; 8862306a36Sopenharmony_ci dec_kn_slot_size = KN02_SLOT_SIZE; 8962306a36Sopenharmony_ci dec_tc_bus = 1; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN02_RTC); 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic inline void prom_init_kn02xa(void) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci dec_kn_slot_base = KN02XA_SLOT_BASE; 9762306a36Sopenharmony_ci dec_kn_slot_size = IOASIC_SLOT_SIZE; 9862306a36Sopenharmony_ci dec_tc_bus = 1; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL); 10162306a36Sopenharmony_ci dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic inline void prom_init_kn03(void) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci dec_kn_slot_base = KN03_SLOT_BASE; 10762306a36Sopenharmony_ci dec_kn_slot_size = IOASIC_SLOT_SIZE; 10862306a36Sopenharmony_ci dec_tc_bus = 1; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL); 11162306a36Sopenharmony_ci dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY); 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_civoid __init prom_identify_arch(u32 magic) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci unsigned char dec_cpunum, dec_firmrev, dec_etc, dec_systype; 11862306a36Sopenharmony_ci u32 dec_sysid; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci if (!prom_is_rex(magic)) { 12162306a36Sopenharmony_ci dec_sysid = simple_strtoul(prom_getenv("systype"), 12262306a36Sopenharmony_ci (char **)0, 0); 12362306a36Sopenharmony_ci } else { 12462306a36Sopenharmony_ci dec_sysid = rex_getsysid(); 12562306a36Sopenharmony_ci if (dec_sysid == 0) { 12662306a36Sopenharmony_ci printk("Zero sysid returned from PROM! " 12762306a36Sopenharmony_ci "Assuming a PMAX-like machine.\n"); 12862306a36Sopenharmony_ci dec_sysid = 1; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci dec_cpunum = (dec_sysid & 0xff000000) >> 24; 13362306a36Sopenharmony_ci dec_systype = (dec_sysid & 0xff0000) >> 16; 13462306a36Sopenharmony_ci dec_firmrev = (dec_sysid & 0xff00) >> 8; 13562306a36Sopenharmony_ci dec_etc = dec_sysid & 0xff; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* 13862306a36Sopenharmony_ci * FIXME: This may not be an exhaustive list of DECStations/Servers! 13962306a36Sopenharmony_ci * Put all model-specific initialisation calls here. 14062306a36Sopenharmony_ci */ 14162306a36Sopenharmony_ci switch (dec_systype) { 14262306a36Sopenharmony_ci case DS2100_3100: 14362306a36Sopenharmony_ci mips_machtype = MACH_DS23100; 14462306a36Sopenharmony_ci prom_init_kn01(); 14562306a36Sopenharmony_ci break; 14662306a36Sopenharmony_ci case DS5100: /* DS5100 MIPSMATE */ 14762306a36Sopenharmony_ci mips_machtype = MACH_DS5100; 14862306a36Sopenharmony_ci prom_init_kn230(); 14962306a36Sopenharmony_ci break; 15062306a36Sopenharmony_ci case DS5000_200: /* DS5000 3max */ 15162306a36Sopenharmony_ci mips_machtype = MACH_DS5000_200; 15262306a36Sopenharmony_ci prom_init_kn02(); 15362306a36Sopenharmony_ci break; 15462306a36Sopenharmony_ci case DS5000_1XX: /* DS5000/100 3min */ 15562306a36Sopenharmony_ci mips_machtype = MACH_DS5000_1XX; 15662306a36Sopenharmony_ci prom_init_kn02xa(); 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci case DS5000_2X0: /* DS5000/240 3max+ or DS5900 bigmax */ 15962306a36Sopenharmony_ci mips_machtype = MACH_DS5000_2X0; 16062306a36Sopenharmony_ci prom_init_kn03(); 16162306a36Sopenharmony_ci if (!(ioasic_read(IO_REG_SIR) & KN03_IO_INR_3MAXP)) 16262306a36Sopenharmony_ci mips_machtype = MACH_DS5900; 16362306a36Sopenharmony_ci break; 16462306a36Sopenharmony_ci case DS5000_XX: /* Personal DS5000/xx maxine */ 16562306a36Sopenharmony_ci mips_machtype = MACH_DS5000_XX; 16662306a36Sopenharmony_ci prom_init_kn02xa(); 16762306a36Sopenharmony_ci break; 16862306a36Sopenharmony_ci case DS5800: /* DS5800 Isis */ 16962306a36Sopenharmony_ci mips_machtype = MACH_DS5800; 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci case DS5400: /* DS5400 MIPSfair */ 17262306a36Sopenharmony_ci mips_machtype = MACH_DS5400; 17362306a36Sopenharmony_ci break; 17462306a36Sopenharmony_ci case DS5500: /* DS5500 MIPSfair-2 */ 17562306a36Sopenharmony_ci mips_machtype = MACH_DS5500; 17662306a36Sopenharmony_ci break; 17762306a36Sopenharmony_ci default: 17862306a36Sopenharmony_ci mips_machtype = MACH_DSUNKNOWN; 17962306a36Sopenharmony_ci break; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (mips_machtype == MACH_DSUNKNOWN) 18362306a36Sopenharmony_ci printk("This is an %s, id is %x\n", 18462306a36Sopenharmony_ci dec_system_strings[mips_machtype], dec_systype); 18562306a36Sopenharmony_ci else 18662306a36Sopenharmony_ci printk("This is a %s\n", dec_system_strings[mips_machtype]); 18762306a36Sopenharmony_ci} 188