From c7fc24dc4420057f103afe8fc64524ebc25c5d37 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 25 Aug 1998 09:12:35 +0000 Subject: o Merge with Linux 2.1.116. o New Newport console code. o New G364 console code. --- arch/m68k/mvme16x/16xints.c | 2 +- arch/m68k/mvme16x/Makefile | 2 +- arch/m68k/mvme16x/config.c | 139 +++++++++++++++---------------------- arch/m68k/mvme16x/rtc.c | 166 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 223 insertions(+), 86 deletions(-) create mode 100644 arch/m68k/mvme16x/rtc.c (limited to 'arch/m68k/mvme16x') diff --git a/arch/m68k/mvme16x/16xints.c b/arch/m68k/mvme16x/16xints.c index c79ff17ad..fbb370a07 100644 --- a/arch/m68k/mvme16x/16xints.c +++ b/arch/m68k/mvme16x/16xints.c @@ -127,7 +127,7 @@ int mvme16x_get_irq_list (char *buf) static void mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp) { - panic ("Unknown interrupt 0x%02x", irq); + printk ("Unknown interrupt 0x%02x\n", irq); } diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile index 97c670f3c..bb7485ab8 100644 --- a/arch/m68k/mvme16x/Makefile +++ b/arch/m68k/mvme16x/Makefile @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := mvme16x.o -O_OBJS := config.o 16xints.o +O_OBJS := config.o 16xints.o rtc.o #OX_OBJS = ksyms.o include $(TOPDIR)/Rules.make diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index 00e7db8d1..838c3bbac 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c @@ -34,26 +34,10 @@ #include #include -typedef struct { - unsigned char - ctrl, - bcd_sec, - bcd_min, - bcd_hr, - bcd_dow, - bcd_dom, - bcd_mth, - bcd_year; -} MK48T08; - -#define RTC_WRITE 0x80 -#define RTC_READ 0x40 -#define RTC_STOP 0x20 - int atari_SCC_reset_done = 1; /* So SCC doesn't get reset */ u_long atari_mch_cookie = 0; -MK48T08 * volatile rtc = (MK48T08 *)0xfffc1ff8; +static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE; extern void mvme16x_process_int (int level, struct pt_regs *regs); extern void mvme16x_init_IRQ (void); @@ -143,6 +127,11 @@ static int mvme16x_get_hardware_list(char *buffer) } +#define pcc2chip ((volatile u_char *)0xfff42000) +#define PccSCCMICR 0x1d +#define PccSCCTICR 0x1e +#define PccSCCRICR 0x1f + __initfunc(void config_mvme16x(void)) { p_bdid p = (p_bdid)mvme_bdid_ptr; @@ -197,7 +186,43 @@ __initfunc(void config_mvme16x(void)) rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : ""); } else + { mvme16x_config = MVME16x_CONFIG_GOT_LP | MVME16x_CONFIG_GOT_CD2401; + + /* Dont allow any interrupts from the CD2401 until the interrupt */ + /* handlers are installed */ + + pcc2chip[PccSCCMICR] = 0x10; + pcc2chip[PccSCCTICR] = 0x10; + pcc2chip[PccSCCRICR] = 0x10; + } +} + +static void mvme16x_abort_int (int irq, void *dev_id, struct pt_regs *fp) +{ + p_bdid p = (p_bdid)mvme_bdid_ptr; + unsigned long *new = (unsigned long *)vectors; + unsigned long *old = (unsigned long *)0xffe00000; + volatile unsigned char uc, *ucp; + + if (p->brdno == 0x0162 || p->brdno == 0x172) + { + ucp = (volatile unsigned char *)0xfff42043; + uc = *ucp | 8; + *ucp = uc; + } + else + { + *(volatile unsigned long *)0xfff40074 = 0x40000000; + } + *(new+4) = *(old+4); /* Illegal instruction */ + *(new+9) = *(old+9); /* Trace */ + *(new+47) = *(old+47); /* Trap #15 */ + + if (p->brdno == 0x0162 || p->brdno == 0x172) + *(new+0x5e) = *(old+0x5e); /* ABORT switch */ + else + *(new+0x6e) = *(old+0x6e); /* ABORT switch */ } static void mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp) @@ -208,15 +233,26 @@ static void mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp) void mvme16x_sched_init (void (*timer_routine)(int, void *, struct pt_regs *)) { + p_bdid p = (p_bdid)mvme_bdid_ptr; + int irq; + tick_handler = timer_routine; /* Using PCCchip2 or MC2 chip tick timer 1 */ *(volatile unsigned long *)0xfff42008 = 0; *(volatile unsigned long *)0xfff42004 = 10000; /* 10ms */ *(volatile unsigned char *)0xfff42017 |= 3; *(volatile unsigned char *)0xfff4201b = 0x16; - if (request_irq(IRQ_MVME16x_TIMER, mvme16x_timer_int, 0, + if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0, "timer", mvme16x_timer_int)) panic ("Couldn't register timer int"); + + if (p->brdno == 0x0162 || p->brdno == 0x172) + irq = MVME162_IRQ_ABORT; + else + irq = MVME167_IRQ_ABORT; + if (request_irq(irq, mvme16x_abort_int, 0, + "abort", mvme16x_abort_int)) + panic ("Couldn't register abort int"); } @@ -254,76 +290,11 @@ int mvme16x_set_clock_mmss (unsigned long nowtime) return 0; } -/* - * console_map_init(), here to avoid having to modify drivers/block/genhd.c - */ - -void console_map_init(void) -{ -} - -/* - * fbmem_init(), here to avoid having to modify drivers/char/mem.c - */ - -void fbmem_init(void) -{ -} - -/* Avoid mods to drivers/char/tty_io.c */ - -unsigned long con_init(unsigned long kmem_start) -{ - return (kmem_start); -} - -/* Avoid mods to drivers/char/tty_io.c */ - -int vcs_init(void) -{ - return (0); -} - -/* Avoid mods to drivers/char/tty_io.c */ - -int kbd_init(void) -{ - return (0); -} - -/* Avoid mods to init/main.c */ - -void no_scroll(char *str, int *ints) -{ -} - -/* Avoid mods to kernel/panic.c */ - -void do_unblank_screen(void) -{ -} - int mvme16x_keyb_init (void) { return 0; } -void mvme16x_set_vectors (void) -{ - p_bdid p = (p_bdid)mvme_bdid_ptr; - unsigned long *new = (unsigned long *)vectors; - unsigned long *old = (unsigned long *)0xffe00000;; - - *(new+4) = *(old+4); /* Illegal instruction */ - *(new+9) = *(old+9); /* Trace */ - *(new+47) = *(old+47); /* Trap #15 */ - - if (p->brdno == 0x0162 || p->brdno == 0x172) - *(new+0x5e) = *(old+0x5e); /* ABORT switch */ - else - *(new+0x6e) = *(old+0x6e); /* ABORT switch */ -} - /*------------------- Serial console stuff ------------------------*/ extern void mvme167_serial_console_setup(int cflag); @@ -372,7 +343,7 @@ static void scc_delay (void) static void scc_write (char ch) { - volatile char *p = (volatile char *)SCC_A_ADDR; + volatile char *p = (volatile char *)MVME_SCC_A_ADDR; do { scc_delay(); diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c new file mode 100644 index 000000000..6b7c0c011 --- /dev/null +++ b/arch/m68k/mvme16x/rtc.c @@ -0,0 +1,166 @@ +/* + * Real Time Clock interface for Linux on the MVME16x + * + * Based on the PC driver by Paul Gortmaker. + */ + +#define RTC_VERSION "1.00" + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For struct rtc_time and ioctls, etc */ +#include + +#include +#include +#include +#include + +/* + * We sponge a minor off of the misc major. No need slurping + * up another valuable major dev number for this. If you add + * an ioctl, make sure you don't conflict with SPARC's RTC + * ioctls. + */ + +#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10) +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) + +static unsigned char days_in_mo[] = +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +static char rtc_status = 0; + +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE; + unsigned long flags; + struct rtc_time wtime; + + switch (cmd) { + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + save_flags(flags); + cli(); + /* Ensure clock and real-time-mode-register are accessible */ + rtc->ctrl = RTC_READ; + wtime.tm_sec = BCD2BIN(rtc->bcd_sec); + wtime.tm_min = BCD2BIN(rtc->bcd_min); + wtime.tm_hour = BCD2BIN(rtc->bcd_hr); + wtime.tm_mday = BCD2BIN(rtc->bcd_dom); + wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1; + wtime.tm_year = BCD2BIN(rtc->bcd_year); + if (wtime.tm_year < 70) + wtime.tm_year += 100; + wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1; + rtc->ctrl = 0; + restore_flags(flags); + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + -EFAULT : 0; + } + case RTC_SET_TIME: /* Set the RTC */ + { + unsigned char leap_yr; + struct rtc_time rtc_tm; + + if (!suser()) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + leap_yr = ((!(rtc_tm.tm_year % 4) && (rtc_tm.tm_year % 100)) || !(rtc_tm.tm_year % 400)); + + if ((rtc_tm.tm_mon > 12) || (rtc_tm.tm_mday == 0)) + return -EINVAL; + + if (rtc_tm.tm_mday > (days_in_mo[rtc_tm.tm_mon] + ((rtc_tm.tm_mon == 2) && leap_yr))) + return -EINVAL; + + if ((rtc_tm.tm_hour >= 24) || (rtc_tm.tm_min >= 60) || (rtc_tm.tm_sec >= 60)) + return -EINVAL; + + save_flags(flags); + cli(); + rtc->ctrl = RTC_WRITE; + + rtc->bcd_sec = BIN2BCD(rtc_tm.tm_sec); + rtc->bcd_min = BIN2BCD(rtc_tm.tm_min); + rtc->bcd_hr = BIN2BCD(rtc_tm.tm_hour); + rtc->bcd_dom = BIN2BCD(rtc_tm.tm_mday); + rtc->bcd_mth = BIN2BCD(rtc_tm.tm_mon + 1); + rtc->bcd_year = BIN2BCD(rtc_tm.tm_year%100); + if (rtc_tm.tm_wday >= 0) + rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1); + + rtc->ctrl = 0; + restore_flags(flags); + return 0; + } + default: + return -EINVAL; + } +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int rtc_open(struct inode *inode, struct file *file) +{ + if(rtc_status) + return -EBUSY; + + rtc_status = 1; + return 0; +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + rtc_status = 0; + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations rtc_fops = { + NULL, + NULL, + NULL, /* No write */ + NULL, /* No readdir */ + NULL, + rtc_ioctl, + NULL, /* No mmap */ + rtc_open, + rtc_release +}; + +static struct miscdevice rtc_dev= +{ + RTC_MINOR, + "rtc", + &rtc_fops +}; + +__initfunc(int rtc_MK48T08_init(void)) +{ + if (!MACH_IS_MVME16x) + return -ENODEV; + + printk(KERN_INFO "MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION); + misc_register(&rtc_dev); + return 0; +} + -- cgit v1.2.3