linux/arch/mips/kernel/cevt-txx9.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Based on linux/arch/mips/kernel/cevt-r4k.c,
   7 *          linux/arch/mips/jmr3927/rbhma3100/setup.c
   8 *
   9 * Copyright 2001 MontaVista Software Inc.
  10 * Copyright (C) 2000-2001 Toshiba Corporation
  11 * Copyright (C) 2007 MIPS Technologies, Inc.
  12 * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
  13 */
  14#include <linux/init.h>
  15#include <linux/interrupt.h>
  16#include <asm/time.h>
  17#include <asm/txx9tmr.h>
  18
  19#define TCR_BASE (TXx9_TMTCR_CCDE | TXx9_TMTCR_CRE | TXx9_TMTCR_TMODE_ITVL)
  20#define TIMER_CCD       0       /* 1/2 */
  21#define TIMER_CLK(imclk)        ((imclk) / (2 << TIMER_CCD))
  22
  23static struct txx9_tmr_reg __iomem *txx9_cs_tmrptr;
  24
  25static cycle_t txx9_cs_read(struct clocksource *cs)
  26{
  27        return __raw_readl(&txx9_cs_tmrptr->trr);
  28}
  29
  30/* Use 1 bit smaller width to use full bits in that width */
  31#define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1)
  32
  33static struct clocksource txx9_clocksource = {
  34        .name           = "TXx9",
  35        .rating         = 200,
  36        .read           = txx9_cs_read,
  37        .mask           = CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS),
  38        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
  39};
  40
  41void __init txx9_clocksource_init(unsigned long baseaddr,
  42                                  unsigned int imbusclk)
  43{
  44        struct txx9_tmr_reg __iomem *tmrptr;
  45
  46        clocksource_set_clock(&txx9_clocksource, TIMER_CLK(imbusclk));
  47        clocksource_register(&txx9_clocksource);
  48
  49        tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
  50        __raw_writel(TCR_BASE, &tmrptr->tcr);
  51        __raw_writel(0, &tmrptr->tisr);
  52        __raw_writel(TIMER_CCD, &tmrptr->ccdr);
  53        __raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr);
  54        __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra);
  55        __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
  56        txx9_cs_tmrptr = tmrptr;
  57}
  58
  59static struct txx9_tmr_reg __iomem *txx9_tmrptr;
  60
  61static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
  62{
  63        /* stop and reset counter */
  64        __raw_writel(TCR_BASE, &tmrptr->tcr);
  65        /* clear pending interrupt */
  66        __raw_writel(0, &tmrptr->tisr);
  67}
  68
  69static void txx9tmr_set_mode(enum clock_event_mode mode,
  70                             struct clock_event_device *evt)
  71{
  72        struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
  73
  74        txx9tmr_stop_and_clear(tmrptr);
  75        switch (mode) {
  76        case CLOCK_EVT_MODE_PERIODIC:
  77                __raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE,
  78                             &tmrptr->itmr);
  79                /* start timer */
  80                __raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >>
  81                             evt->shift,
  82                             &tmrptr->cpra);
  83                __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
  84                break;
  85        case CLOCK_EVT_MODE_SHUTDOWN:
  86        case CLOCK_EVT_MODE_UNUSED:
  87                __raw_writel(0, &tmrptr->itmr);
  88                break;
  89        case CLOCK_EVT_MODE_ONESHOT:
  90                __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr);
  91                break;
  92        case CLOCK_EVT_MODE_RESUME:
  93                __raw_writel(TIMER_CCD, &tmrptr->ccdr);
  94                __raw_writel(0, &tmrptr->itmr);
  95                break;
  96        }
  97}
  98
  99static int txx9tmr_set_next_event(unsigned long delta,
 100                                  struct clock_event_device *evt)
 101{
 102        struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
 103
 104        txx9tmr_stop_and_clear(tmrptr);
 105        /* start timer */
 106        __raw_writel(delta, &tmrptr->cpra);
 107        __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
 108        return 0;
 109}
 110
 111static struct clock_event_device txx9tmr_clock_event_device = {
 112        .name           = "TXx9",
 113        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 114        .rating         = 200,
 115        .set_mode       = txx9tmr_set_mode,
 116        .set_next_event = txx9tmr_set_next_event,
 117};
 118
 119static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id)
 120{
 121        struct clock_event_device *cd = &txx9tmr_clock_event_device;
 122        struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
 123
 124        __raw_writel(0, &tmrptr->tisr); /* ack interrupt */
 125        cd->event_handler(cd);
 126        return IRQ_HANDLED;
 127}
 128
 129static struct irqaction txx9tmr_irq = {
 130        .handler        = txx9tmr_interrupt,
 131        .flags          = IRQF_DISABLED | IRQF_PERCPU,
 132        .name           = "txx9tmr",
 133};
 134
 135void __init txx9_clockevent_init(unsigned long baseaddr, int irq,
 136                                 unsigned int imbusclk)
 137{
 138        struct clock_event_device *cd = &txx9tmr_clock_event_device;
 139        struct txx9_tmr_reg __iomem *tmrptr;
 140
 141        tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
 142        txx9tmr_stop_and_clear(tmrptr);
 143        __raw_writel(TIMER_CCD, &tmrptr->ccdr);
 144        __raw_writel(0, &tmrptr->itmr);
 145        txx9_tmrptr = tmrptr;
 146
 147        clockevent_set_clock(cd, TIMER_CLK(imbusclk));
 148        cd->max_delta_ns =
 149                clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd);
 150        cd->min_delta_ns = clockevent_delta2ns(0xf, cd);
 151        cd->irq = irq;
 152        cd->cpumask = cpumask_of(0),
 153        clockevents_register_device(cd);
 154        setup_irq(irq, &txx9tmr_irq);
 155        printk(KERN_INFO "TXx9: clockevent device at 0x%lx, irq %d\n",
 156               baseaddr, irq);
 157}
 158
 159void __init txx9_tmr_init(unsigned long baseaddr)
 160{
 161        struct txx9_tmr_reg __iomem *tmrptr;
 162
 163        tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
 164        /* Start once to make CounterResetEnable effective */
 165        __raw_writel(TXx9_TMTCR_CRE | TXx9_TMTCR_TCE, &tmrptr->tcr);
 166        /* Stop and reset the counter */
 167        __raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr);
 168        __raw_writel(0, &tmrptr->tisr);
 169        __raw_writel(0xffffffff, &tmrptr->cpra);
 170        __raw_writel(0, &tmrptr->itmr);
 171        __raw_writel(0, &tmrptr->ccdr);
 172        __raw_writel(0, &tmrptr->pgmr);
 173        iounmap(tmrptr);
 174}
 175