cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cevt-ds1287.c (2350B)


      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}