Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[MIPS] DS1287: Add clockevent driver

Signed-off-by: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Yoichi Yuasa and committed by
Ralf Baechle
6457d9fc 4247417d

+185 -49
+4
arch/mips/Kconfig
··· 81 81 config MACH_DECSTATION 82 82 bool "DECstations" 83 83 select BOOT_ELF32 84 + select CEVT_DS1287 84 85 select CEVT_R4K 85 86 select CSRC_IOASIC 86 87 select CSRC_R4K ··· 769 768 bool 770 769 771 770 config CEVT_BCM1480 771 + bool 772 + 773 + config CEVT_DS1287 772 774 bool 773 775 774 776 config CEVT_GT641XX
+24 -49
arch/mips/dec/time.c
··· 9 9 * 10 10 */ 11 11 #include <linux/bcd.h> 12 - #include <linux/errno.h> 13 12 #include <linux/init.h> 14 - #include <linux/interrupt.h> 15 - #include <linux/kernel.h> 16 13 #include <linux/mc146818rtc.h> 17 - #include <linux/mm.h> 18 - #include <linux/module.h> 19 14 #include <linux/param.h> 20 - #include <linux/sched.h> 21 - #include <linux/string.h> 22 - #include <linux/time.h> 23 - #include <linux/types.h> 24 15 25 - #include <asm/bootinfo.h> 26 - #include <asm/cpu.h> 27 - #include <asm/io.h> 28 - #include <asm/irq.h> 29 - #include <asm/mipsregs.h> 30 - #include <asm/sections.h> 16 + #include <asm/cpu-features.h> 17 + #include <asm/ds1287.h> 31 18 #include <asm/time.h> 32 - 33 19 #include <asm/dec/interrupts.h> 34 20 #include <asm/dec/ioasic.h> 35 - #include <asm/dec/ioasic_addrs.h> 36 21 #include <asm/dec/machtype.h> 37 22 38 23 unsigned long read_persistent_clock(void) ··· 124 139 return retval; 125 140 } 126 141 127 - static int dec_timer_state(void) 128 - { 129 - return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0; 130 - } 131 - 132 - static void dec_timer_ack(void) 133 - { 134 - CMOS_READ(RTC_REG_C); /* Ack the RTC interrupt. */ 135 - } 136 - 137 - static cycle_t dec_ioasic_hpt_read(void) 138 - { 139 - /* 140 - * The free-running counter is 32-bit which is good for about 141 - * 2 minutes, 50 seconds at possible count rates of up to 25MHz. 142 - */ 143 - return ioasic_read(IO_REG_FCTR); 144 - } 145 - 146 - 147 142 void __init plat_time_init(void) 148 143 { 149 - mips_timer_ack = dec_timer_ack; 144 + u32 start, end; 145 + int i = HZ / 10; 150 146 151 - if (!cpu_has_counter && IOASIC) 147 + /* Set up the rate of periodic DS1287 interrupts. */ 148 + ds1287_set_base_clock(HZ); 149 + 150 + if (cpu_has_counter) { 151 + while (!ds1287_timer_state()) 152 + ; 153 + 154 + start = read_c0_count(); 155 + 156 + while (i--) 157 + while (!ds1287_timer_state()) 158 + ; 159 + 160 + end = read_c0_count(); 161 + 162 + mips_hpt_frequency = (end - start) * 10; 163 + printk(KERN_INFO "MIPS counter frequency %dHz\n", 164 + mips_hpt_frequency); 165 + } else if (IOASIC) 152 166 /* For pre-R4k systems we use the I/O ASIC's counter. */ 153 167 dec_ioasic_clocksource_init(); 154 168 155 - /* Set up the rate of periodic DS1287 interrupts. */ 156 - CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A); 157 - } 158 - 159 - void __init plat_timer_setup(struct irqaction *irq) 160 - { 161 - setup_irq(dec_interrupt[DEC_IRQ_RTC], irq); 162 - 163 - /* Enable periodic DS1287 interrupts. */ 164 - CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B); 169 + ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]); 165 170 }
+1
arch/mips/kernel/Makefile
··· 10 10 11 11 obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o 12 12 obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o 13 + obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o 13 14 obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o 14 15 obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o 15 16 obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
+129
arch/mips/kernel/cevt-ds1287.c
··· 1 + /* 2 + * DS1287 clockevent driver 3 + * 4 + * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 + */ 20 + #include <linux/clockchips.h> 21 + #include <linux/init.h> 22 + #include <linux/interrupt.h> 23 + #include <linux/mc146818rtc.h> 24 + 25 + #include <asm/time.h> 26 + 27 + int ds1287_timer_state(void) 28 + { 29 + return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0; 30 + } 31 + 32 + int ds1287_set_base_clock(unsigned int hz) 33 + { 34 + u8 rate; 35 + 36 + switch (hz) { 37 + case 128: 38 + rate = 0x9; 39 + break; 40 + case 256: 41 + rate = 0x8; 42 + break; 43 + case 1024: 44 + rate = 0x6; 45 + break; 46 + default: 47 + return -EINVAL; 48 + } 49 + 50 + CMOS_WRITE(RTC_REF_CLCK_32KHZ | rate, RTC_REG_A); 51 + 52 + return 0; 53 + } 54 + 55 + static int ds1287_set_next_event(unsigned long delta, 56 + struct clock_event_device *evt) 57 + { 58 + return -EINVAL; 59 + } 60 + 61 + static void ds1287_set_mode(enum clock_event_mode mode, 62 + struct clock_event_device *evt) 63 + { 64 + u8 val; 65 + 66 + spin_lock(&rtc_lock); 67 + 68 + val = CMOS_READ(RTC_REG_B); 69 + 70 + switch (mode) { 71 + case CLOCK_EVT_MODE_PERIODIC: 72 + val |= RTC_PIE; 73 + break; 74 + default: 75 + val &= ~RTC_PIE; 76 + break; 77 + } 78 + 79 + CMOS_WRITE(val, RTC_REG_B); 80 + 81 + spin_unlock(&rtc_lock); 82 + } 83 + 84 + static void ds1287_event_handler(struct clock_event_device *dev) 85 + { 86 + } 87 + 88 + static struct clock_event_device ds1287_clockevent = { 89 + .name = "ds1287", 90 + .features = CLOCK_EVT_FEAT_PERIODIC, 91 + .cpumask = CPU_MASK_CPU0, 92 + .set_next_event = ds1287_set_next_event, 93 + .set_mode = ds1287_set_mode, 94 + .event_handler = ds1287_event_handler, 95 + }; 96 + 97 + static irqreturn_t ds1287_interrupt(int irq, void *dev_id) 98 + { 99 + struct clock_event_device *cd = &ds1287_clockevent; 100 + 101 + /* Ack the RTC interrupt. */ 102 + CMOS_READ(RTC_REG_C); 103 + 104 + cd->event_handler(cd); 105 + 106 + return IRQ_HANDLED; 107 + } 108 + 109 + static struct irqaction ds1287_irqaction = { 110 + .handler = ds1287_interrupt, 111 + .flags = IRQF_DISABLED | IRQF_PERCPU, 112 + .name = "ds1287", 113 + }; 114 + 115 + int __init ds1287_clockevent_init(int irq) 116 + { 117 + struct clock_event_device *cd; 118 + 119 + cd = &ds1287_clockevent; 120 + cd->rating = 100; 121 + cd->irq = irq; 122 + clockevent_set_clock(cd, 32768); 123 + cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); 124 + cd->min_delta_ns = clockevent_delta2ns(0x300, cd); 125 + 126 + clockevents_register_device(&ds1287_clockevent); 127 + 128 + return setup_irq(irq, &ds1287_irqaction); 129 + }
+27
include/asm-mips/ds1287.h
··· 1 + /* 2 + * DS1287 timer functions. 3 + * 4 + * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 + */ 20 + #ifndef __ASM_DS1287_H 21 + #define __ASM_DS1287_H 22 + 23 + extern int ds1287_timer_state(void); 24 + extern void ds1287_set_base_clock(unsigned int clock); 25 + extern int ds1287_clockevent_init(int irq); 26 + 27 + #endif