If you don't want to compile a kernel exclusively for a Sun 3, say N.
+config X68000
+ bool "SHARP X68000 support"
+ depends on !MMU
+ select M68000
+ select GENERIC_CLOCKEVENTS
+ help
+ This option enbales support for SHARP X68000 series (exclude X68030).
+
endif # M68KCLASSIC
config PILOT
head-$(CONFIG_SUN3) := arch/m68k/kernel/sun3-head.o
head-$(CONFIG_M68000) := arch/m68k/68000/head.o
head-$(CONFIG_COLDFIRE) := arch/m68k/coldfire/head.o
+head-$(CONFIG_X68000) := arch/m68k/x68k/head.o
core-y += arch/m68k/kernel/ arch/m68k/mm/
libs-y += arch/m68k/lib/
core-$(CONFIG_M68040) += arch/m68k/fpsp040/
core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
+ifndef CONFIG_X68000
core-$(CONFIG_M68000) += arch/m68k/68000/
+endif
core-$(CONFIG_COLDFIRE) += arch/m68k/coldfire/
-
+core-$(CONFIG_X68000) += arch/m68k/x68k/
all: zImage
install:
sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
+
+vmlinux.bin vmlinux.bin.gz: vmlinux
+ $(Q)$(MAKE) $(build)=arch/m68k/x68k arch/m68k/x68k/$@
* With EtherNAT add-on card on Atari, the highest interrupt
* number is 140 so NR_IRQS needs to be 141.
*/
-#if defined(CONFIG_COLDFIRE)
+#if defined(CONFIG_COLDFIRE) || defined(CONFIG_X68000)
#define NR_IRQS 256
#elif defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
#define NR_IRQS 200
extern unsigned long hw_timer_offset(void);
extern void config_BSP(char *command, int len);
-
+extern void zs_console_register(void);
#endif /* _M68K_MACHDEP_H */
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+CFLAGS_signal.o = -O0
#include <linux/initrd.h>
#include <linux/root_dev.h>
#include <linux/rtc.h>
+#include <linux/platform_device.h>
#include <asm/setup.h>
#include <asm/bootinfo.h>
#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con;
#endif
-
+ parse_early_param();
+#if defined(CONFIG_X68000)
+ zs_console_register();
+#endif
/*
* Give all the memory to the bootmap allocator, tell it to put the
* boot mem_map at the start of memory.
/*
* Get kmalloc into gear.
*/
+ early_platform_driver_probe("earlyprintk",1,0);
paging_init();
}
/* copy to the gap we'd made */
"2: movel %4@+,%/a0@+\n\t"
" dbra %1,2b\n\t"
- " bral ret_from_signal\n"
+ " jmp ret_from_signal\n"
#endif
: /* no outputs, it doesn't ever return */
: "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
.romvec : {
__rom_start = .;
_romvec = .;
+ vectors = .;
*(.romvec)
*(.data..initvect)
}
--- /dev/null
+##################################################
+#
+# Makefile for X68000
+#
+# Copyright 2016 Yoshinori Sato
+
+extra-y := head.o
+obj-y += entry.o ints.o mfp-timer.o x68k.o zs_earlyprintk.o
+
+targets := vmlinux.bin vmlinux.bin.gz
+
+OBJCOPYFLAGS_vmlinux.bin := -Obinary
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,gzip)
+
+CLEAN_FILES += arch/$(ARCH)/x68k/vmlinux.bin arch/$(ARCH)/x68k/vmlinux.bin.gz
--- /dev/null
+/*
+ * entry.S -- non-mmu 68000 interrupt and exception entry points
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ * Linux/m68k support by Hamish Macdonald
+ */
+
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/traps.h>
+#include <asm/asm-offsets.h>
+#include <asm/entry.h>
+
+.text
+
+.globl system_call
+.globl resume
+.globl ret_from_exception
+.globl ret_from_signal
+.globl sys_call_table
+.globl bad_interrupt
+.globl inthandler
+.globl inttable
+
+badsys:
+ movel #-ENOSYS,%sp@(PT_OFF_D0)
+ jra ret_from_exception
+
+do_trace:
+ movel #-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
+ subql #4,%sp
+ SAVE_SWITCH_STACK
+ jbsr syscall_trace_enter
+ RESTORE_SWITCH_STACK
+ addql #4,%sp
+ movel %sp@(PT_OFF_ORIG_D0),%d1
+ movel #-ENOSYS,%d0
+ cmpl #NR_syscalls,%d1
+ jcc 1f
+ lsl #2,%d1
+ lea sys_call_table, %a0
+ jbsr %a0@(%d1)
+
+1: movel %d0,%sp@(PT_OFF_D0) /* save the return value */
+ subql #4,%sp /* dummy return address */
+ SAVE_SWITCH_STACK
+ jbsr syscall_trace_leave
+
+ret_from_signal:
+ RESTORE_SWITCH_STACK
+ addql #4,%sp
+ jra ret_from_exception
+
+ENTRY(system_call)
+ subq #2,%sp
+ movel %sp@(2),%sp@
+ movew %sp@(6),%sp@(4)
+ movel %sp@(8),%sp@(6)
+ movew #4<<12,%sp@(8)
+ SAVE_ALL_SYS
+ /* save top of frame*/
+ pea %sp@
+ jbsr set_esp0
+ addql #4,%sp
+ movel %sp@(PT_OFF_ORIG_D0),%d0
+
+ movel %sp,%d1 /* get thread_info pointer */
+ andl #-THREAD_SIZE,%d1
+ movel %d1,%a2
+ btst #(TIF_SYSCALL_TRACE%8),%a2@(TINFO_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
+ jne do_trace
+ cmpl #NR_syscalls,%d0
+ jcc badsys
+ lsl #2,%d0
+ lea sys_call_table,%a0
+ movel %a0@(%d0), %a0
+ jbsr %a0@
+ movel %d0,%sp@(PT_OFF_D0) /* save the return value*/
+
+ret_from_exception:
+ btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel*/
+ jeq Luser_return /* if so, skip resched, signals*/
+
+Lkernel_return:
+ movel %sp@(PT_OFF_PC), %d0
+ btst #0,%d0
+ bne 1f
+ moveml %sp@+,%a0-%a2/%d1-%d5
+ movel %sp@+,%d0
+ addql #4,%sp /* orig d0 */
+ addql #4,%sp
+ movel %sp@(2),%sp@(4)
+ movew %sp@,%sp@(2)
+ addq #2,%sp
+ rte
+1: stop #0x2700
+Luser_return:
+ /* only allow interrupts when we are really the last one on the*/
+ /* kernel stack, otherwise stack overflow can occur during*/
+ /* heavy interrupt load*/
+ andw #ALLOWINT,%sr
+
+ movel %sp,%d1 /* get thread_info pointer */
+ andl #-THREAD_SIZE,%d1
+ movel %d1,%a2
+1:
+ movel %a2@(TINFO_FLAGS),%d1 /* thread_info->flags */
+ beq Lkernel_return
+
+Lwork_to_do:
+ movel %a2@(TINFO_FLAGS),%d1 /* thread_info->flags */
+ btst #TIF_NEED_RESCHED,%d1
+ jne reschedule
+
+Lsignal_return:
+ subql #4,%sp /* dummy return address*/
+ SAVE_SWITCH_STACK
+ pea %sp@(SWITCH_STACK_SIZE)
+ bsrw do_notify_resume
+ addql #4,%sp
+ RESTORE_SWITCH_STACK
+ addql #4,%sp
+ jra 1b
+
+/*
+ * This is the main interrupt handler, responsible for calling process_int()
+ */
+
+inttable:
+ .rept 256-64
+ bsrw inthandler
+ .endr
+
+inthandler:
+ subq #2,%sp
+ movel %sp@(2),%sp@
+ movew %sp@(6),%sp@(4)
+ movel %sp@(8),%sp@(6)
+ pea -1
+ movel %d0,%sp@-
+ movel %sp@(8),%d0
+ subl #inttable+4,%d0
+ moveml %d1-%d5/%a0-%a2,%sp@-
+ movel %d0,%d1
+ orw #4<<12,%d1
+ movew %d1, %sp@(PT_OFF_FORMATVEC)
+ lsr #2,%d0
+ add #64, %d0
+ and #0x3ff, %d0
+
+ movel %sp,%sp@-
+ movel %d0,%sp@- /* put vector # on stack*/
+ jbsr do_IRQ /* process the IRQ*/
+3: addql #8,%sp /* pop parameters off stack*/
+ bra ret_from_exception
+
+/*
+ * Handler for uninitialized and spurious interrupts.
+ */
+ENTRY(bad_inthandler)
+ addql #1,irq_err_count
+ rte
+
+/*
+ * Beware - when entering resume, prev (the current task) is
+ * in a0, next (the new task) is in a1, so don't change these
+ * registers until their contents are no longer needed.
+ */
+ENTRY(resume)
+ movel %a0,%d1 /* save prev thread in d1 */
+ movew %sr,%a0@(TASK_THREAD+THREAD_SR) /* save sr */
+ SAVE_SWITCH_STACK
+ movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
+ movel %usp,%a3 /* save usp */
+ movel %a3,%a0@(TASK_THREAD+THREAD_USP)
+
+ movel %a1@(TASK_THREAD+THREAD_USP),%a3 /* restore user stack */
+ movel %a3,%usp
+ movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
+ RESTORE_SWITCH_STACK
+ movew %a1@(TASK_THREAD+THREAD_SR),%sr /* restore thread status reg */
+ rts
+
--- /dev/null
+/*
+ * head.S - Common startup code for 68000 core based CPU's
+ *
+ * 2012.10.21, Luis Alves <ljalvs@gmail.com>, Single head.S file for all
+ * 68000 core based CPU's. Based on the sources from:
+ * Coldfire by Greg Ungerer <gerg@snapgear.com>
+ * 68328 by D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
+ * Kenneth Albanowski <kjahds@kjahds.com>,
+ * The Silver Hammer Group, Ltd.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+
+
+.global _start
+.global _rambase
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.data
+
+/*****************************************************************************
+ * RAM setup pointers. Used by the kernel to determine RAM location and size.
+ *****************************************************************************/
+
+_rambase:
+ .long 0
+_ramvec:
+ .long 0
+_ramstart:
+ .long 0
+_ramend:
+ .long 0
+
+__HEAD
+
+/*****************************************************************************
+ * Entry point, where all begins!
+ *****************************************************************************/
+
+_start:
+ movew #0x2700, %sr /* disable all interrupts */
+
+ moveal #_etext, %a0
+ moveal #_sdata, %a1
+ moveal #__bss_start, %a2
+/*****************************************************************************
+ * Setup basic memory information for kernel
+ *****************************************************************************/
+ movel #CONFIG_RAMBASE,_rambase /* set the base of RAM */
+ movel #0x400000, _ramend /* set end ram addr */
+ lea __bss_stop,%a1
+ movel %a1,_ramstart
+
+ lea __bss_start, %a0 /* get start of bss */
+ lea __bss_stop, %a1 /* get end of bss */
+_clear_bss:
+ movel #0, (%a0)+ /* clear each word */
+ cmpl %a0, %a1 /* check if at end */
+ bne _clear_bss
+
+/*****************************************************************************
+ * Load the current task pointer and stack.
+ *****************************************************************************/
+ lea init_thread_union,%a0
+ lea THREAD_SIZE(%a0),%sp
+ jsr start_kernel /* start Linux kernel */
+_exit:
+ jmp _exit /* should never get here */
--- /dev/null
+/*
+ * int_sr.c
+ *
+ * Copyright 2016 Yoshinori Sato
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/traps.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+
+/* assembler routines */
+asmlinkage void system_call(void);
+asmlinkage void buserr(void);
+asmlinkage void trap(void);
+asmlinkage void inthandler(void);
+
+extern e_vector *inttable;
+
+/* Bitmap of IRQ masked */
+#define IMASK_PRIORITY 7
+
+static DECLARE_BITMAP(imask_mask, IMASK_PRIORITY);
+static int interrupt_priority;
+
+const static char priority[] = {
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 1,1,1,1,3,3,3,3,3,3,3,3,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+
+static inline void set_interrupt_registers(int ip)
+{
+ unsigned short sr;
+
+ asm volatile("movew %%sr, %0\n\t"
+ "andw #0x0700, %0\n\t"
+ "cmpw #0x0700, %0\n\t"
+ "beq 1f\n\t"
+ "movew %%sr,%0\n\t"
+ "andw #~0x0700, %0\n\t"
+ "orw %1, %0\n\t"
+ "movew %0, %%sr\n"
+ "1:"
+ : "=&r" (sr)
+ : "g" (ip));
+}
+
+static void sr_mask(struct irq_data *data)
+{
+ unsigned int irq = data->irq;
+
+ clear_bit(priority[irq - 0x40], imask_mask);
+ if (interrupt_priority < priority[irq - 0x40])
+ interrupt_priority = priority[irq - 0x40];
+ set_interrupt_registers(interrupt_priority << 8);
+}
+
+static void sr_unmask(struct irq_data *data)
+{
+ unsigned int irq = data->irq;
+
+ set_bit(priority[irq - 0x40], imask_mask);
+ interrupt_priority = find_first_zero_bit(imask_mask, IMASK_PRIORITY);
+ set_interrupt_registers(interrupt_priority << 8);
+}
+
+static struct irq_chip intc_irq_chip = {
+ .name = "M68K-SR-INT",
+ .irq_mask = sr_mask,
+ .irq_unmask = sr_unmask,
+};
+
+/*
+ * This function should be called during kernel startup to initialize
+ * the machine vector table.
+ */
+void __init trap_init(void)
+{
+ int i;
+ unsigned long v = (unsigned long)&inttable;
+
+ for (i = 0; i < VEC_USER; i++)
+ vectors[i] = trap;
+ for (i = VEC_SPUR; i <= VEC_INT7; i++)
+ vectors[i] = bad_inthandler;
+
+ for (i = VEC_USER; i < 256; i++)
+ vectors[i] = v + (i - VEC_USER)*4;
+ vectors[VEC_BUSERR] = buserr;
+ vectors[VEC_SYS] = system_call;
+
+}
+
+void __init init_IRQ(void)
+{
+ int i;
+
+ for (i = 0; i < NR_IRQS; i++) {
+ irq_set_chip(i, &intc_irq_chip);
+ irq_set_handler(i, handle_level_irq);
+ }
+}
+
--- /dev/null
+/*
+ * X68000 MFP Timer
+ * Copyright 2016 Yoshinori Sato
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/clockchips.h>
+
+#define INPUT_FREQ (4000000 / 200)
+#define MFP_IRQ 0x44
+#define TDDR (void *)0xe88025
+#define TCDCR (void *)0xe8801d
+#define IERB (void *)0xe88009
+#define IMRB (void *)0xe88015
+
+static irqreturn_t interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *ced = (struct clock_event_device *)dev_id;
+
+ ced->event_handler(ced);
+ return IRQ_HANDLED;
+}
+
+static int periodic(struct clock_event_device *ced)
+{
+ __raw_writeb((INPUT_FREQ + HZ/2) / HZ, TDDR);
+ __raw_writeb(0x07, TCDCR);
+ __raw_writeb(__raw_readb(IERB) | 0x10, IERB);
+ __raw_writeb(__raw_readb(IMRB) | 0x10, IMRB);
+ return 0;
+}
+
+static struct clock_event_device mfp_ced = {
+ .name = "timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC,
+ .rating = 200,
+ .set_state_periodic = periodic,
+};
+
+void __init hw_timer_init(irq_handler_t handler)
+{
+ if (request_irq(MFP_IRQ, interrupt, IRQF_TIMER, "timer", &mfp_ced) < 0) {
+ pr_err("%s: Failed to request_irq\n", __func__);
+ return;
+ }
+ clockevents_config_and_register(&mfp_ced, INPUT_FREQ, 2, 0xff);
+}
--- /dev/null
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <asm/machdep.h>
+
+/***************************************************************************/
+
+void scc_puts(char *);
+
+void __init config_BSP(char *command, int len)
+{
+ mach_sched_init = hw_timer_init;
+ mach_hwclk = NULL;
+ mach_reset = NULL;
+ memcpy(command, (void *)0x7e00, len);
+}
+
+static struct resource scc_a_rsrcs[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ .start = 0xe98005,
+ .end = 0xe98007,
+ },
+
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = 0x50,
+ },
+};
+
+struct platform_device scc_a_pdev = {
+ .name = "scc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(scc_a_rsrcs),
+ .resource = scc_a_rsrcs,
+};
+EXPORT_SYMBOL(scc_a_pdev);
+
+struct platform_device scc_b_pdev = {
+ .name = "scc",
+ .id = 1,
+ .num_resources = 0,
+};
+EXPORT_SYMBOL(scc_b_pdev);
+
+static int __init x68k_platform_init(void)
+{
+ __raw_writeb(0, (void *)0xe86001);
+ platform_device_register(&scc_a_pdev);
+
+ return 0;
+}
+
+arch_initcall(x68k_platform_init);
--- /dev/null
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#define CMD ((void *)0xe98005)
+#define DATA ((void *)0xe98007)
+
+static void zs_write(struct console *co, const char *ptr,
+ unsigned len)
+{
+ for(;len>0;len--) {
+ while(! (__raw_readb(CMD) & 4));
+ if (*ptr == '\n') {
+ __raw_writeb('\r', DATA);
+ while(! (__raw_readb(CMD) & 4));
+ }
+ __raw_writeb(*ptr++, DATA);
+ }
+}
+
+static struct console zs_console = {
+ .name = "zs_console",
+ .write = zs_write,
+ .setup = NULL,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+static char zs_console_buf[32];
+
+static int zs_probe(struct platform_device *pdev)
+{
+ if (zs_console.data)
+ return -EEXIST;
+
+ if (!strstr(zs_console_buf, "keep"))
+ zs_console.flags |= CON_BOOT;
+
+ __raw_writeb(9, CMD);
+ __raw_writeb(0, CMD);
+ register_console(&zs_console);
+ return 0;
+}
+
+static int zs_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver zs_driver = {
+ .probe = zs_probe,
+ .remove = zs_remove,
+ .driver = {
+ .name = "X68000-ZS",
+ .owner = THIS_MODULE,
+ },
+};
+
+early_platform_init_buffer("earlyprintk", &zs_driver,
+ zs_console_buf, ARRAY_SIZE(zs_console_buf));
+
+static struct platform_device zs_console_device = {
+ .name = "X68000-ZS",
+ .id = 0,
+};
+
+static struct platform_device *devices[] __initdata = {
+ &zs_console_device,
+};
+
+void __init zs_console_register(void)
+{
+ early_platform_add_devices(devices,
+ ARRAY_SIZE(devices));
+}