diff options
Diffstat (limited to 'arch/m68k/bvme6000')
| -rw-r--r-- | arch/m68k/bvme6000/Makefile | 2 | ||||
| -rw-r--r-- | arch/m68k/bvme6000/bvmeints.c | 160 | ||||
| -rw-r--r-- | arch/m68k/bvme6000/config.c | 79 | ||||
| -rw-r--r-- | arch/m68k/bvme6000/rtc.c | 78 |
4 files changed, 61 insertions, 258 deletions
diff --git a/arch/m68k/bvme6000/Makefile b/arch/m68k/bvme6000/Makefile index 2348e6ceed1..d8174004fe2 100644 --- a/arch/m68k/bvme6000/Makefile +++ b/arch/m68k/bvme6000/Makefile @@ -2,4 +2,4 @@ # Makefile for Linux arch/m68k/bvme6000 source directory # -obj-y := config.o bvmeints.o rtc.o +obj-y := config.o rtc.o diff --git a/arch/m68k/bvme6000/bvmeints.c b/arch/m68k/bvme6000/bvmeints.c deleted file mode 100644 index 298a8df0266..00000000000 --- a/arch/m68k/bvme6000/bvmeints.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * arch/m68k/bvme6000/bvmeints.c - * - * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk] - * - * based on amiints.c -- Amiga Linux interrupt handling code - * - * 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. - * - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/seq_file.h> - -#include <asm/ptrace.h> -#include <asm/system.h> -#include <asm/irq.h> -#include <asm/traps.h> - -static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp); - -/* - * This should ideally be 4 elements only, for speed. - */ - -static struct { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - const char *devname; - unsigned count; -} irq_tab[256]; - -/* - * void bvme6000_init_IRQ (void) - * - * Parameters: None - * - * Returns: Nothing - * - * This function is called during kernel startup to initialize - * the bvme6000 IRQ handling routines. - */ - -void bvme6000_init_IRQ (void) -{ - int i; - - for (i = 0; i < 256; i++) { - irq_tab[i].handler = bvme6000_defhand; - irq_tab[i].flags = IRQ_FLG_STD; - irq_tab[i].dev_id = NULL; - irq_tab[i].devname = NULL; - irq_tab[i].count = 0; - } -} - -int bvme6000_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - if (irq > 255) { - printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); - return -ENXIO; - } -#if 0 - /* Nothing special about auto-vectored devices for the BVME6000, - * but treat it specially to avoid changes elsewhere. - */ - - if (irq >= VEC_INT1 && irq <= VEC_INT7) - return cpu_request_irq(irq - VEC_SPUR, handler, flags, - devname, dev_id); -#endif - if (!(irq_tab[irq].flags & IRQ_FLG_STD)) { - if (irq_tab[irq].flags & IRQ_FLG_LOCK) { - printk("%s: IRQ %d from %s is not replaceable\n", - __FUNCTION__, irq, irq_tab[irq].devname); - return -EBUSY; - } - if (flags & IRQ_FLG_REPLACE) { - printk("%s: %s can't replace IRQ %d from %s\n", - __FUNCTION__, devname, irq, irq_tab[irq].devname); - return -EBUSY; - } - } - irq_tab[irq].handler = handler; - irq_tab[irq].flags = flags; - irq_tab[irq].dev_id = dev_id; - irq_tab[irq].devname = devname; - return 0; -} - -void bvme6000_free_irq(unsigned int irq, void *dev_id) -{ - if (irq > 255) { - printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); - return; - } -#if 0 - if (irq >= VEC_INT1 && irq <= VEC_INT7) { - cpu_free_irq(irq - VEC_SPUR, dev_id); - return; - } -#endif - if (irq_tab[irq].dev_id != dev_id) - printk("%s: Removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, irq_tab[irq].devname); - - irq_tab[irq].handler = bvme6000_defhand; - irq_tab[irq].flags = IRQ_FLG_STD; - irq_tab[irq].dev_id = NULL; - irq_tab[irq].devname = NULL; -} - -irqreturn_t bvme6000_process_int (unsigned long vec, struct pt_regs *fp) -{ - if (vec > 255) { - printk ("bvme6000_process_int: Illegal vector %ld", vec); - return IRQ_NONE; - } else { - irq_tab[vec].count++; - irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp); - return IRQ_HANDLED; - } -} - -int show_bvme6000_interrupts(struct seq_file *p, void *v) -{ - int i; - - for (i = 0; i < 256; i++) { - if (irq_tab[i].count) - seq_printf(p, "Vec 0x%02x: %8d %s\n", - i, irq_tab[i].count, - irq_tab[i].devname ? irq_tab[i].devname : "free"); - } - return 0; -} - - -static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp) -{ - printk ("Unknown interrupt 0x%02x\n", irq); - return IRQ_NONE; -} - -void bvme6000_enable_irq (unsigned int irq) -{ -} - - -void bvme6000_disable_irq (unsigned int irq) -{ -} - diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index 3ffc84f9c29..478623dbb20 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c @@ -25,9 +25,11 @@ #include <linux/genhd.h> #include <linux/rtc.h> #include <linux/interrupt.h> +#include <linux/bcd.h> #include <asm/bootinfo.h> -#include <asm/system.h> +#include <asm/bootinfo-vme.h> +#include <asm/byteorder.h> #include <asm/pgtable.h> #include <asm/setup.h> #include <asm/irq.h> @@ -36,35 +38,23 @@ #include <asm/machdep.h> #include <asm/bvme6000hw.h> -extern irqreturn_t bvme6000_process_int (int level, struct pt_regs *regs); -extern void bvme6000_init_IRQ (void); -extern void bvme6000_free_irq (unsigned int, void *); -extern int show_bvme6000_interrupts(struct seq_file *, void *); -extern void bvme6000_enable_irq (unsigned int); -extern void bvme6000_disable_irq (unsigned int); static void bvme6000_get_model(char *model); -static int bvme6000_get_hardware_list(char *buffer); -extern int bvme6000_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); -extern void bvme6000_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); -extern unsigned long bvme6000_gettimeoffset (void); +extern void bvme6000_sched_init(irq_handler_t handler); +extern u32 bvme6000_gettimeoffset(void); extern int bvme6000_hwclk (int, struct rtc_time *); extern int bvme6000_set_clock_mmss (unsigned long); extern void bvme6000_reset (void); -extern void bvme6000_waitbut(void); void bvme6000_set_vectors (void); -static unsigned char bcd2bin (unsigned char b); -static unsigned char bin2bcd (unsigned char b); +/* Save tick handler routine pointer, will point to xtime_update() in + * kernel/timer/timekeeping.c, called via bvme6000_process_int() */ -/* Save tick handler routine pointer, will point to do_timer() in - * kernel/sched.c, called via bvme6000_process_int() */ +static irq_handler_t tick_handler; -static irqreturn_t (*tick_handler)(int, void *, struct pt_regs *); - -int bvme6000_parse_bootinfo(const struct bi_record *bi) +int __init bvme6000_parse_bootinfo(const struct bi_record *bi) { - if (bi->tag == BI_VME_TYPE) + if (be16_to_cpu(bi->tag) == BI_VME_TYPE) return 0; else return 1; @@ -91,16 +81,15 @@ static void bvme6000_get_model(char *model) sprintf(model, "BVME%d000", m68k_cputype == CPU_68060 ? 6 : 4); } - -/* No hardware options on BVME6000? */ - -static int bvme6000_get_hardware_list(char *buffer) +/* + * This function is called during kernel startup to initialize + * the bvme6000 IRQ handling routines. + */ +static void __init bvme6000_init_IRQ(void) { - *buffer = '\0'; - return 0; + m68k_setup_user_interrupt(VEC_USER, 192); } - void __init config_bvme6000(void) { volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; @@ -123,18 +112,11 @@ void __init config_bvme6000(void) mach_max_dma_address = 0xffffffff; mach_sched_init = bvme6000_sched_init; mach_init_IRQ = bvme6000_init_IRQ; - mach_gettimeoffset = bvme6000_gettimeoffset; + arch_gettimeoffset = bvme6000_gettimeoffset; mach_hwclk = bvme6000_hwclk; mach_set_clock_mmss = bvme6000_set_clock_mmss; mach_reset = bvme6000_reset; - mach_free_irq = bvme6000_free_irq; - mach_process_int = bvme6000_process_int; - mach_get_irq_list = show_bvme6000_interrupts; - mach_request_irq = bvme6000_request_irq; - enable_irq = bvme6000_enable_irq; - disable_irq = bvme6000_disable_irq; mach_get_model = bvme6000_get_model; - mach_get_hardware_list = bvme6000_get_hardware_list; printk ("Board is %sconfigured as a System Controller\n", *config_reg_ptr & BVME_CONFIG_SW1 ? "" : "not "); @@ -142,7 +124,7 @@ void __init config_bvme6000(void) /* Now do the PIT configuration */ pit->pgcr = 0x00; /* Unidirectional 8 bit, no handshake for now */ - pit->psrr = 0x18; /* PIACK and PIRQ fucntions enabled */ + pit->psrr = 0x18; /* PIACK and PIRQ functions enabled */ pit->pacr = 0x00; /* Sub Mode 00, H2 i/p, no DMA */ pit->padr = 0x00; /* Just to be tidy! */ pit->paddr = 0x00; /* All inputs for now (safest) */ @@ -159,7 +141,7 @@ void __init config_bvme6000(void) } -irqreturn_t bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp) +irqreturn_t bvme6000_abort_int (int irq, void *dev_id) { unsigned long *new = (unsigned long *)vectors; unsigned long *old = (unsigned long *)0xf8000000; @@ -176,14 +158,14 @@ irqreturn_t bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp) } -static irqreturn_t bvme6000_timer_int (int irq, void *dev_id, struct pt_regs *fp) +static irqreturn_t bvme6000_timer_int (int irq, void *dev_id) { volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; unsigned char msr = rtc->msr & 0xc0; rtc->msr = msr | 0x20; /* Ack the interrupt */ - return tick_handler(irq, dev_id, fp); + return tick_handler(irq, dev_id); } /* @@ -195,7 +177,7 @@ static irqreturn_t bvme6000_timer_int (int irq, void *dev_id, struct pt_regs *fp * so divide by 8 to get the microsecond result. */ -void bvme6000_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *)) +void bvme6000_sched_init (irq_handler_t timer_routine) { volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; unsigned char msr = rtc->msr & 0xc0; @@ -236,13 +218,13 @@ void bvme6000_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_re * results... */ -unsigned long bvme6000_gettimeoffset (void) +u32 bvme6000_gettimeoffset(void) { volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; unsigned char msr = rtc->msr & 0xc0; unsigned char t1int, t1op; - unsigned long v = 800000, ov; + u32 v = 800000, ov; rtc->msr = 0; /* Ensure timer registers accessible */ @@ -266,20 +248,9 @@ unsigned long bvme6000_gettimeoffset (void) v += 10000; /* Int pending, + 10ms */ rtc->msr = msr; - return v; + return v * 1000; } -static unsigned char bcd2bin (unsigned char b) -{ - return ((b>>4)*10 + (b&15)); -} - -static unsigned char bin2bcd (unsigned char b) -{ - return (((b/10)*16) + (b%10)); -} - - /* * Looks like op is non-zero for setting the clock, and zero for * reading the clock. diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c index c6b2a410bf9..cf12a17dc28 100644 --- a/arch/m68k/bvme6000/rtc.c +++ b/arch/m68k/bvme6000/rtc.c @@ -9,18 +9,18 @@ #include <linux/types.h> #include <linux/errno.h> #include <linux/miscdevice.h> -#include <linux/slab.h> #include <linux/ioport.h> +#include <linux/capability.h> #include <linux/fcntl.h> #include <linux/init.h> #include <linux/poll.h> +#include <linux/module.h> #include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */ -#include <linux/smp_lock.h> +#include <linux/bcd.h> #include <asm/bvme6000hw.h> #include <asm/io.h> #include <asm/uaccess.h> -#include <asm/system.h> #include <asm/setup.h> /* @@ -30,21 +30,18 @@ * 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; +static atomic_t rtc_status = ATOMIC_INIT(1); -static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; unsigned char msr; unsigned long flags; struct rtc_time wtime; + void __user *argp = (void __user *)arg; switch (cmd) { case RTC_RD_TIME: /* Read the time/date from RTC */ @@ -55,19 +52,19 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, rtc->msr = 0x40; memset(&wtime, 0, sizeof(struct rtc_time)); do { - 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); + 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; - } while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec)); + wtime.tm_wday = bcd2bin(rtc->bcd_dow)-1; + } while (wtime.tm_sec != bcd2bin(rtc->bcd_sec)); rtc->msr = msr; local_irq_restore(flags); - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + return copy_to_user(argp, &wtime, sizeof wtime) ? -EFAULT : 0; } case RTC_SET_TIME: /* Set the RTC */ @@ -79,8 +76,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) + if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time))) return -EFAULT; yrs = rtc_tm.tm_year; @@ -113,14 +109,14 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, rtc->t0cr_rtmr = yrs%4; rtc->bcd_tenms = 0; - rtc->bcd_sec = BIN2BCD(sec); - rtc->bcd_min = BIN2BCD(min); - rtc->bcd_hr = BIN2BCD(hrs); - rtc->bcd_dom = BIN2BCD(day); - rtc->bcd_mth = BIN2BCD(mon); - rtc->bcd_year = BIN2BCD(yrs%100); + rtc->bcd_sec = bin2bcd(sec); + rtc->bcd_min = bin2bcd(min); + rtc->bcd_hr = bin2bcd(hrs); + rtc->bcd_dom = bin2bcd(day); + rtc->bcd_mth = bin2bcd(mon); + rtc->bcd_year = bin2bcd(yrs%100); if (rtc_tm.tm_wday >= 0) - rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1); + rtc->bcd_dow = bin2bcd(rtc_tm.tm_wday+1); rtc->t0cr_rtmr = yrs%4 | 0x08; rtc->msr = msr; @@ -133,25 +129,20 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } /* - * 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. + * We enforce only one user at a time here with the open/close. */ - static int rtc_open(struct inode *inode, struct file *file) { - if(rtc_status) + if (!atomic_dec_and_test(&rtc_status)) { + atomic_inc(&rtc_status); return -EBUSY; - - rtc_status = 1; + } return 0; } static int rtc_release(struct inode *inode, struct file *file) { - lock_kernel(); - rtc_status = 0; - unlock_kernel(); + atomic_inc(&rtc_status); return 0; } @@ -159,10 +150,11 @@ static int rtc_release(struct inode *inode, struct file *file) * The various file operations we support. */ -static struct file_operations rtc_fops = { - .ioctl = rtc_ioctl, - .open = rtc_open, - .release = rtc_release, +static const struct file_operations rtc_fops = { + .unlocked_ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, + .llseek = noop_llseek, }; static struct miscdevice rtc_dev = { @@ -171,7 +163,7 @@ static struct miscdevice rtc_dev = { .fops = &rtc_fops }; -int __init rtc_DP8570A_init(void) +static int __init rtc_DP8570A_init(void) { if (!MACH_IS_BVME6000) return -ENODEV; @@ -179,4 +171,4 @@ int __init rtc_DP8570A_init(void) printk(KERN_INFO "DP8570A Real Time Clock Driver v%s\n", RTC_VERSION); return misc_register(&rtc_dev); } - +module_init(rtc_DP8570A_init); |
