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