162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci *  linux/arch/m68k/sun3/config.c
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci *  Copyright (C) 1996,1997 Pekka Pietik{inen
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
762306a36Sopenharmony_ci * License.  See the file COPYING in the main directory of this archive
862306a36Sopenharmony_ci * for more details.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/types.h>
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/mm.h>
1462306a36Sopenharmony_ci#include <linux/seq_file.h>
1562306a36Sopenharmony_ci#include <linux/tty.h>
1662306a36Sopenharmony_ci#include <linux/console.h>
1762306a36Sopenharmony_ci#include <linux/init.h>
1862306a36Sopenharmony_ci#include <linux/memblock.h>
1962306a36Sopenharmony_ci#include <linux/platform_device.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <asm/oplib.h>
2262306a36Sopenharmony_ci#include <asm/setup.h>
2362306a36Sopenharmony_ci#include <asm/contregs.h>
2462306a36Sopenharmony_ci#include <asm/movs.h>
2562306a36Sopenharmony_ci#include <asm/pgalloc.h>
2662306a36Sopenharmony_ci#include <asm/sun3-head.h>
2762306a36Sopenharmony_ci#include <asm/sun3mmu.h>
2862306a36Sopenharmony_ci#include <asm/machdep.h>
2962306a36Sopenharmony_ci#include <asm/machines.h>
3062306a36Sopenharmony_ci#include <asm/idprom.h>
3162306a36Sopenharmony_ci#include <asm/intersil.h>
3262306a36Sopenharmony_ci#include <asm/irq.h>
3362306a36Sopenharmony_ci#include <asm/sections.h>
3462306a36Sopenharmony_ci#include <asm/sun3ints.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cichar sun3_reserved_pmeg[SUN3_PMEGS_NUM];
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic void sun3_sched_init(void);
3962306a36Sopenharmony_ciextern void sun3_get_model (char* model);
4062306a36Sopenharmony_ciextern int sun3_hwclk(int set, struct rtc_time *t);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_civolatile char* clock_va;
4362306a36Sopenharmony_ciextern unsigned long availmem;
4462306a36Sopenharmony_ciunsigned long num_pages;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic void sun3_get_hardware_list(struct seq_file *m)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	seq_printf(m, "PROM Revision:\t%s\n", romvec->pv_monid);
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_civoid __init sun3_init(void)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	unsigned char enable_register;
5462306a36Sopenharmony_ci	int i;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	m68k_machtype= MACH_SUN3;
5762306a36Sopenharmony_ci	m68k_cputype = CPU_68020;
5862306a36Sopenharmony_ci	m68k_fputype = FPU_68881; /* mc68881 actually */
5962306a36Sopenharmony_ci	m68k_mmutype = MMU_SUN3;
6062306a36Sopenharmony_ci	clock_va    =          (char *) 0xfe06000;	/* dark  */
6162306a36Sopenharmony_ci	sun3_intreg = (unsigned char *) 0xfe0a000;	/* magic */
6262306a36Sopenharmony_ci	sun3_disable_interrupts();
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	prom_init((void *)LINUX_OPPROM_BEGVM);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	GET_CONTROL_BYTE(AC_SENABLE,enable_register);
6762306a36Sopenharmony_ci	enable_register |= 0x50; /* Enable FPU */
6862306a36Sopenharmony_ci	SET_CONTROL_BYTE(AC_SENABLE,enable_register);
6962306a36Sopenharmony_ci	GET_CONTROL_BYTE(AC_SENABLE,enable_register);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	/* This code looks suspicious, because it doesn't subtract
7262306a36Sopenharmony_ci           memory belonging to the kernel from the available space */
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	memset(sun3_reserved_pmeg, 0, sizeof(sun3_reserved_pmeg));
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/* Reserve important PMEGS */
7862306a36Sopenharmony_ci	/* FIXME: These should be probed instead of hardcoded */
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	for (i=0; i<8; i++)		/* Kernel PMEGs */
8162306a36Sopenharmony_ci		sun3_reserved_pmeg[i] = 1;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	sun3_reserved_pmeg[247] = 1;	/* ROM mapping  */
8462306a36Sopenharmony_ci	sun3_reserved_pmeg[248] = 1;	/* AMD Ethernet */
8562306a36Sopenharmony_ci	sun3_reserved_pmeg[251] = 1;	/* VB area      */
8662306a36Sopenharmony_ci	sun3_reserved_pmeg[254] = 1;	/* main I/O     */
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	sun3_reserved_pmeg[249] = 1;
8962306a36Sopenharmony_ci	sun3_reserved_pmeg[252] = 1;
9062306a36Sopenharmony_ci	sun3_reserved_pmeg[253] = 1;
9162306a36Sopenharmony_ci	set_fc(USER_DATA);
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/* Without this, Bad Things happen when something calls arch_reset. */
9562306a36Sopenharmony_cistatic void sun3_reboot (void)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	prom_reboot ("vmlinux");
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic void sun3_halt (void)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	prom_halt ();
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/* sun3 bootmem allocation */
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic void __init sun3_bootmem_alloc(unsigned long memory_start,
10862306a36Sopenharmony_ci				      unsigned long memory_end)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	unsigned long start_page;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	/* align start/end to page boundaries */
11362306a36Sopenharmony_ci	memory_start = ((memory_start + (PAGE_SIZE-1)) & PAGE_MASK);
11462306a36Sopenharmony_ci	memory_end = memory_end & PAGE_MASK;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	start_page = __pa(memory_start) >> PAGE_SHIFT;
11762306a36Sopenharmony_ci	max_pfn = num_pages = __pa(memory_end) >> PAGE_SHIFT;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	high_memory = (void *)memory_end;
12062306a36Sopenharmony_ci	availmem = memory_start;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	m68k_setup_node(0);
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_civoid __init config_sun3(void)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	unsigned long memory_start, memory_end;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	pr_info("ARCH: SUN3\n");
13162306a36Sopenharmony_ci	idprom_init();
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	/* Subtract kernel memory from available memory */
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci        mach_sched_init      =  sun3_sched_init;
13662306a36Sopenharmony_ci        mach_init_IRQ        =  sun3_init_IRQ;
13762306a36Sopenharmony_ci        mach_reset           =  sun3_reboot;
13862306a36Sopenharmony_ci	mach_get_model	     =  sun3_get_model;
13962306a36Sopenharmony_ci	mach_hwclk           =  sun3_hwclk;
14062306a36Sopenharmony_ci	mach_halt	     =  sun3_halt;
14162306a36Sopenharmony_ci	mach_get_hardware_list = sun3_get_hardware_list;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	memory_start = ((((unsigned long)_end) + 0x2000) & ~0x1fff);
14462306a36Sopenharmony_ci// PROM seems to want the last couple of physical pages. --m
14562306a36Sopenharmony_ci	memory_end   = *(romvec->pv_sun3mem) + PAGE_OFFSET - 2*PAGE_SIZE;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	m68k_num_memory=1;
14862306a36Sopenharmony_ci        m68k_memory[0].size=*(romvec->pv_sun3mem);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	sun3_bootmem_alloc(memory_start, memory_end);
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic void __init sun3_sched_init(void)
15462306a36Sopenharmony_ci{
15562306a36Sopenharmony_ci	sun3_disable_interrupts();
15662306a36Sopenharmony_ci        intersil_clock->cmd_reg=(INTERSIL_RUN|INTERSIL_INT_DISABLE|INTERSIL_24H_MODE);
15762306a36Sopenharmony_ci        intersil_clock->int_reg=INTERSIL_HZ_100_MASK;
15862306a36Sopenharmony_ci	intersil_clear();
15962306a36Sopenharmony_ci        sun3_enable_irq(5);
16062306a36Sopenharmony_ci        intersil_clock->cmd_reg=(INTERSIL_RUN|INTERSIL_INT_ENABLE|INTERSIL_24H_MODE);
16162306a36Sopenharmony_ci        sun3_enable_interrupts();
16262306a36Sopenharmony_ci        intersil_clear();
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SUN3_SCSI)
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_cistatic const struct resource sun3_scsi_vme_rsrc[] __initconst = {
16862306a36Sopenharmony_ci	{
16962306a36Sopenharmony_ci		.flags = IORESOURCE_IRQ,
17062306a36Sopenharmony_ci		.start = SUN3_VEC_VMESCSI0,
17162306a36Sopenharmony_ci		.end   = SUN3_VEC_VMESCSI0,
17262306a36Sopenharmony_ci	}, {
17362306a36Sopenharmony_ci		.flags = IORESOURCE_MEM,
17462306a36Sopenharmony_ci		.start = 0xff200000,
17562306a36Sopenharmony_ci		.end   = 0xff200021,
17662306a36Sopenharmony_ci	}, {
17762306a36Sopenharmony_ci		.flags = IORESOURCE_IRQ,
17862306a36Sopenharmony_ci		.start = SUN3_VEC_VMESCSI1,
17962306a36Sopenharmony_ci		.end   = SUN3_VEC_VMESCSI1,
18062306a36Sopenharmony_ci	}, {
18162306a36Sopenharmony_ci		.flags = IORESOURCE_MEM,
18262306a36Sopenharmony_ci		.start = 0xff204000,
18362306a36Sopenharmony_ci		.end   = 0xff204021,
18462306a36Sopenharmony_ci	},
18562306a36Sopenharmony_ci};
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci/*
18862306a36Sopenharmony_ci * Int: level 2 autovector
18962306a36Sopenharmony_ci * IO: type 1, base 0x00140000, 5 bits phys space: A<4..0>
19062306a36Sopenharmony_ci */
19162306a36Sopenharmony_cistatic const struct resource sun3_scsi_rsrc[] __initconst = {
19262306a36Sopenharmony_ci	{
19362306a36Sopenharmony_ci		.flags = IORESOURCE_IRQ,
19462306a36Sopenharmony_ci		.start = 2,
19562306a36Sopenharmony_ci		.end   = 2,
19662306a36Sopenharmony_ci	}, {
19762306a36Sopenharmony_ci		.flags = IORESOURCE_MEM,
19862306a36Sopenharmony_ci		.start = 0x00140000,
19962306a36Sopenharmony_ci		.end   = 0x0014001f,
20062306a36Sopenharmony_ci	},
20162306a36Sopenharmony_ci};
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ciint __init sun3_platform_init(void)
20462306a36Sopenharmony_ci{
20562306a36Sopenharmony_ci	switch (idprom->id_machtype) {
20662306a36Sopenharmony_ci	case SM_SUN3 | SM_3_160:
20762306a36Sopenharmony_ci	case SM_SUN3 | SM_3_260:
20862306a36Sopenharmony_ci		platform_device_register_simple("sun3_scsi_vme", -1,
20962306a36Sopenharmony_ci			sun3_scsi_vme_rsrc, ARRAY_SIZE(sun3_scsi_vme_rsrc));
21062306a36Sopenharmony_ci		break;
21162306a36Sopenharmony_ci	case SM_SUN3 | SM_3_50:
21262306a36Sopenharmony_ci	case SM_SUN3 | SM_3_60:
21362306a36Sopenharmony_ci		platform_device_register_simple("sun3_scsi", -1,
21462306a36Sopenharmony_ci			sun3_scsi_rsrc, ARRAY_SIZE(sun3_scsi_rsrc));
21562306a36Sopenharmony_ci		break;
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci	return 0;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ciarch_initcall(sun3_platform_init);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci#endif
223