1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * DS1287 clockevent driver
5 * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org>
7 #include <linux/clockchips.h>
8 #include <linux/init.h>
9 #include <linux/interrupt.h>
10 #include <linux/mc146818rtc.h>
11 #include <linux/irq.h>
15 int ds1287_timer_state(void)
17 return (CMOS_READ(RTC_REG_C
) & RTC_PF
) != 0;
20 int ds1287_set_base_clock(unsigned int hz
)
38 CMOS_WRITE(RTC_REF_CLCK_32KHZ
| rate
, RTC_REG_A
);
43 static int ds1287_set_next_event(unsigned long delta
,
44 struct clock_event_device
*evt
)
49 static int ds1287_shutdown(struct clock_event_device
*evt
)
55 val
= CMOS_READ(RTC_REG_B
);
57 CMOS_WRITE(val
, RTC_REG_B
);
59 spin_unlock(&rtc_lock
);
63 static int ds1287_set_periodic(struct clock_event_device
*evt
)
69 val
= CMOS_READ(RTC_REG_B
);
71 CMOS_WRITE(val
, RTC_REG_B
);
73 spin_unlock(&rtc_lock
);
77 static void ds1287_event_handler(struct clock_event_device
*dev
)
81 static struct clock_event_device ds1287_clockevent
= {
83 .features
= CLOCK_EVT_FEAT_PERIODIC
,
84 .set_next_event
= ds1287_set_next_event
,
85 .set_state_shutdown
= ds1287_shutdown
,
86 .set_state_periodic
= ds1287_set_periodic
,
87 .tick_resume
= ds1287_shutdown
,
88 .event_handler
= ds1287_event_handler
,
91 static irqreturn_t
ds1287_interrupt(int irq
, void *dev_id
)
93 struct clock_event_device
*cd
= &ds1287_clockevent
;
95 /* Ack the RTC interrupt. */
98 cd
->event_handler(cd
);
103 static struct irqaction ds1287_irqaction
= {
104 .handler
= ds1287_interrupt
,
105 .flags
= IRQF_PERCPU
| IRQF_TIMER
,
109 int __init
ds1287_clockevent_init(int irq
)
111 struct clock_event_device
*cd
;
113 cd
= &ds1287_clockevent
;
116 clockevent_set_clock(cd
, 32768);
117 cd
->max_delta_ns
= clockevent_delta2ns(0x7fffffff, cd
);
118 cd
->max_delta_ticks
= 0x7fffffff;
119 cd
->min_delta_ns
= clockevent_delta2ns(0x300, cd
);
120 cd
->min_delta_ticks
= 0x300;
121 cd
->cpumask
= cpumask_of(0);
123 clockevents_register_device(&ds1287_clockevent
);
125 return setup_irq(irq
, &ds1287_irqaction
);