File Index
Files and directories
Sign in
FILE

cevt-ds1287.c

File preview with syntax highlighting.

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