1 /* 2 * DS1287 clockevent driver 3 * 4 * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> 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 #include <linux/irq.h> 25 26 #include <asm/time.h> 27 28 int ds1287_timer_state(void) 29 { 30 return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0; 31 } 32 33 int ds1287_set_base_clock(unsigned int hz) 34 { 35 u8 rate; 36 37 switch (hz) { 38 case 128: 39 rate = 0x9; 40 break; 41 case 256: 42 rate = 0x8; 43 break; 44 case 1024: 45 rate = 0x6; 46 break; 47 default: 48 return -EINVAL; 49 } 50 51 CMOS_WRITE(RTC_REF_CLCK_32KHZ | rate, RTC_REG_A); 52 53 return 0; 54 } 55 56 static int ds1287_set_next_event(unsigned long delta, 57 struct clock_event_device *evt) 58 { 59 return -EINVAL; 60 } 61 62 static int ds1287_shutdown(struct clock_event_device *evt) 63 { 64 u8 val; 65 66 spin_lock(&rtc_lock); 67 68 val = CMOS_READ(RTC_REG_B); 69 val &= ~RTC_PIE; 70 CMOS_WRITE(val, RTC_REG_B); 71 72 spin_unlock(&rtc_lock); 73 return 0; 74 } 75 76 static int ds1287_set_periodic(struct clock_event_device *evt) 77 { 78 u8 val; 79 80 spin_lock(&rtc_lock); 81 82 val = CMOS_READ(RTC_REG_B); 83 val |= RTC_PIE; 84 CMOS_WRITE(val, RTC_REG_B); 85 86 spin_unlock(&rtc_lock); 87 return 0; 88 } 89 90 static void ds1287_event_handler(struct clock_event_device *dev) 91 { 92 } 93 94 static struct clock_event_device ds1287_clockevent = { 95 .name = "ds1287", 96 .features = CLOCK_EVT_FEAT_PERIODIC, 97 .set_next_event = ds1287_set_next_event, 98 .set_state_shutdown = ds1287_shutdown, 99 .set_state_periodic = ds1287_set_periodic, 100 .tick_resume = ds1287_shutdown, 101 .event_handler = ds1287_event_handler, 102 }; 103 104 static irqreturn_t ds1287_interrupt(int irq, void *dev_id) 105 { 106 struct clock_event_device *cd = &ds1287_clockevent; 107 108 /* Ack the RTC interrupt. */ 109 CMOS_READ(RTC_REG_C); 110 111 cd->event_handler(cd); 112 113 return IRQ_HANDLED; 114 } 115 116 static struct irqaction ds1287_irqaction = { 117 .handler = ds1287_interrupt, 118 .flags = IRQF_PERCPU | IRQF_TIMER, 119 .name = "ds1287", 120 }; 121 122 int __init ds1287_clockevent_init(int irq) 123 { 124 struct clock_event_device *cd; 125 126 cd = &ds1287_clockevent; 127 cd->rating = 100; 128 cd->irq = irq; 129 clockevent_set_clock(cd, 32768); 130 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); 131 cd->max_delta_ticks = 0x7fffffff; 132 cd->min_delta_ns = clockevent_delta2ns(0x300, cd); 133 cd->min_delta_ticks = 0x300; 134 cd->cpumask = cpumask_of(0); 135 136 clockevents_register_device(&ds1287_clockevent); 137 138 return setup_irq(irq, &ds1287_irqaction); 139 } 140