linux/arch/mips/kernel/cevt-gt641xx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  GT641xx clockevent routines.
   4 *
   5 *  Copyright (C) 2007  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/spinlock.h>
  11#include <linux/irq.h>
  12
  13#include <asm/gt64120.h>
  14#include <asm/time.h>
  15
  16static DEFINE_RAW_SPINLOCK(gt641xx_timer_lock);
  17static unsigned int gt641xx_base_clock;
  18
  19void gt641xx_set_base_clock(unsigned int clock)
  20{
  21        gt641xx_base_clock = clock;
  22}
  23
  24int gt641xx_timer0_state(void)
  25{
  26        if (GT_READ(GT_TC0_OFS))
  27                return 0;
  28
  29        GT_WRITE(GT_TC0_OFS, gt641xx_base_clock / HZ);
  30        GT_WRITE(GT_TC_CONTROL_OFS, GT_TC_CONTROL_ENTC0_MSK);
  31
  32        return 1;
  33}
  34
  35static int gt641xx_timer0_set_next_event(unsigned long delta,
  36                                         struct clock_event_device *evt)
  37{
  38        u32 ctrl;
  39
  40        raw_spin_lock(&gt641xx_timer_lock);
  41
  42        ctrl = GT_READ(GT_TC_CONTROL_OFS);
  43        ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
  44        ctrl |= GT_TC_CONTROL_ENTC0_MSK;
  45
  46        GT_WRITE(GT_TC0_OFS, delta);
  47        GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
  48
  49        raw_spin_unlock(&gt641xx_timer_lock);
  50
  51        return 0;
  52}
  53
  54static int gt641xx_timer0_shutdown(struct clock_event_device *evt)
  55{
  56        u32 ctrl;
  57
  58        raw_spin_lock(&gt641xx_timer_lock);
  59
  60        ctrl = GT_READ(GT_TC_CONTROL_OFS);
  61        ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
  62        GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
  63
  64        raw_spin_unlock(&gt641xx_timer_lock);
  65        return 0;
  66}
  67
  68static int gt641xx_timer0_set_oneshot(struct clock_event_device *evt)
  69{
  70        u32 ctrl;
  71
  72        raw_spin_lock(&gt641xx_timer_lock);
  73
  74        ctrl = GT_READ(GT_TC_CONTROL_OFS);
  75        ctrl &= ~GT_TC_CONTROL_SELTC0_MSK;
  76        ctrl |= GT_TC_CONTROL_ENTC0_MSK;
  77        GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
  78
  79        raw_spin_unlock(&gt641xx_timer_lock);
  80        return 0;
  81}
  82
  83static int gt641xx_timer0_set_periodic(struct clock_event_device *evt)
  84{
  85        u32 ctrl;
  86
  87        raw_spin_lock(&gt641xx_timer_lock);
  88
  89        ctrl = GT_READ(GT_TC_CONTROL_OFS);
  90        ctrl |= GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK;
  91        GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
  92
  93        raw_spin_unlock(&gt641xx_timer_lock);
  94        return 0;
  95}
  96
  97static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
  98{
  99}
 100
 101static struct clock_event_device gt641xx_timer0_clockevent = {
 102        .name                   = "gt641xx-timer0",
 103        .features               = CLOCK_EVT_FEAT_PERIODIC |
 104                                  CLOCK_EVT_FEAT_ONESHOT,
 105        .irq                    = GT641XX_TIMER0_IRQ,
 106        .set_next_event         = gt641xx_timer0_set_next_event,
 107        .set_state_shutdown     = gt641xx_timer0_shutdown,
 108        .set_state_periodic     = gt641xx_timer0_set_periodic,
 109        .set_state_oneshot      = gt641xx_timer0_set_oneshot,
 110        .tick_resume            = gt641xx_timer0_shutdown,
 111        .event_handler          = gt641xx_timer0_event_handler,
 112};
 113
 114static irqreturn_t gt641xx_timer0_interrupt(int irq, void *dev_id)
 115{
 116        struct clock_event_device *cd = &gt641xx_timer0_clockevent;
 117
 118        cd->event_handler(cd);
 119
 120        return IRQ_HANDLED;
 121}
 122
 123static struct irqaction gt641xx_timer0_irqaction = {
 124        .handler        = gt641xx_timer0_interrupt,
 125        .flags          = IRQF_PERCPU | IRQF_TIMER,
 126        .name           = "gt641xx_timer0",
 127};
 128
 129static int __init gt641xx_timer0_clockevent_init(void)
 130{
 131        struct clock_event_device *cd;
 132
 133        if (!gt641xx_base_clock)
 134                return 0;
 135
 136        GT_WRITE(GT_TC0_OFS, gt641xx_base_clock / HZ);
 137
 138        cd = &gt641xx_timer0_clockevent;
 139        cd->rating = 200 + gt641xx_base_clock / 10000000;
 140        clockevent_set_clock(cd, gt641xx_base_clock);
 141        cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
 142        cd->max_delta_ticks = 0x7fffffff;
 143        cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
 144        cd->min_delta_ticks = 0x300;
 145        cd->cpumask = cpumask_of(0);
 146
 147        clockevents_register_device(&gt641xx_timer0_clockevent);
 148
 149        return setup_irq(GT641XX_TIMER0_IRQ, &gt641xx_timer0_irqaction);
 150}
 151arch_initcall(gt641xx_timer0_clockevent_init);
 152