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 <linux/irq.h>
  17#include <linux/sched_clock.h>
  18#include <asm/time.h>
  19#include <asm/txx9tmr.h>
  20
  21#define TCR_BASE (TXx9_TMTCR_CCDE | TXx9_TMTCR_CRE | TXx9_TMTCR_TMODE_ITVL)
  22#define TIMER_CCD       0       /* 1/2 */
  23#define TIMER_CLK(imclk)        ((imclk) / (2 << TIMER_CCD))
  24
  25struct txx9_clocksource {
  26        struct clocksource cs;
  27        struct txx9_tmr_reg __iomem *tmrptr;
  28};
  29
  30static u64 txx9_cs_read(struct clocksource *cs)
  31{
  32        struct txx9_clocksource *txx9_cs =
  33                container_of(cs, struct txx9_clocksource, cs);
  34        return __raw_readl(&txx9_cs->tmrptr->trr);
  35}
  36
  37/* Use 1 bit smaller width to use full bits in that width */
  38#define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1)
  39
  40static struct txx9_clocksource txx9_clocksource = {
  41        .cs = {
  42                .name           = "TXx9",
  43                .rating         = 200,
  44                .read           = txx9_cs_read,
  45                .mask           = CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS),
  46                .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
  47        },
  48};
  49
  50static u64 notrace txx9_read_sched_clock(void)
  51{
  52        return __raw_readl(&txx9_clocksource.tmrptr->trr);
  53}
  54
  55void __init txx9_clocksource_init(unsigned long baseaddr,
  56                                  unsigned int imbusclk)
  57{
  58        struct txx9_tmr_reg __iomem *tmrptr;
  59
  60        clocksource_register_hz(&txx9_clocksource.cs, TIMER_CLK(imbusclk));
  61
  62        tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
  63        __raw_writel(TCR_BASE, &tmrptr->tcr);
  64        __raw_writel(0, &tmrptr->tisr);
  65        __raw_writel(TIMER_CCD, &tmrptr->ccdr);
  66        __raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr);
  67        __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra);
  68        __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
  69        txx9_clocksource.tmrptr = tmrptr;
  70
  71        sched_clock_register(txx9_read_sched_clock, TXX9_CLOCKSOURCE_BITS,
  72                             TIMER_CLK(imbusclk));
  73}
  74
  75struct txx9_clock_event_device {
  76        struct clock_event_device cd;
  77        struct txx9_tmr_reg __iomem *tmrptr;
  78};
  79
  80static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
  81{
  82        /* stop and reset counter */
  83        __raw_writel(TCR_BASE, &tmrptr->tcr);
  84        /* clear pending interrupt */
  85        __raw_writel(0, &tmrptr->tisr);
  86}
  87
  88static int txx9tmr_set_state_periodic(struct clock_event_device *evt)
  89{
  90        struct txx9_clock_event_device *txx9_cd =
  91                container_of(evt, struct txx9_clock_event_device, cd);
  92        struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
  93
  94        txx9tmr_stop_and_clear(tmrptr);
  95
  96        __raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE, &tmrptr->itmr);
  97        /* start timer */
  98        __raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >> evt->shift,
  99                     &tmrptr->cpra);
 100        __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
 101        return 0;
 102}
 103
 104static int txx9tmr_set_state_oneshot(struct clock_event_device *evt)
 105{
 106        struct txx9_clock_event_device *txx9_cd =
 107                container_of(evt, struct txx9_clock_event_device, cd);
 108        struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
 109
 110        txx9tmr_stop_and_clear(tmrptr);
 111        __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr);
 112        return 0;
 113}
 114
 115static int txx9tmr_set_state_shutdown(struct clock_event_device *evt)
 116{
 117        struct txx9_clock_event_device *txx9_cd =
 118                container_of(evt, struct txx9_clock_event_device, cd);
 119        struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
 120
 121        txx9tmr_stop_and_clear(tmrptr);
 122        __raw_writel(0, &tmrptr->itmr);
 123        return 0;
 124}
 125
 126static int txx9tmr_tick_resume(struct clock_event_device *evt)
 127{
 128        struct txx9_clock_event_device *txx9_cd =
 129                container_of(evt, struct txx9_clock_event_device, cd);
 130        struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
 131
 132        txx9tmr_stop_and_clear(tmrptr);
 133        __raw_writel(TIMER_CCD, &tmrptr->ccdr);
 134        __raw_writel(0, &tmrptr->itmr);
 135        return 0;
 136}
 137
 138static int txx9tmr_set_next_event(unsigned long delta,
 139                                  struct clock_event_device *evt)
 140{
 141        struct txx9_clock_event_device *txx9_cd =
 142                container_of(evt, struct txx9_clock_event_device, cd);
 143        struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
 144
 145        txx9tmr_stop_and_clear(tmrptr);
 146        /* start timer */
 147        __raw_writel(delta, &tmrptr->cpra);
 148        __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
 149        return 0;
 150}
 151
 152static struct txx9_clock_event_device txx9_clock_event_device = {
 153        .cd = {
 154                .name                   = "TXx9",
 155                .features               = CLOCK_EVT_FEAT_PERIODIC |
 156                                          CLOCK_EVT_FEAT_ONESHOT,
 157                .rating                 = 200,
 158                .set_state_shutdown     = txx9tmr_set_state_shutdown,
 159                .set_state_periodic     = txx9tmr_set_state_periodic,
 160                .set_state_oneshot      = txx9tmr_set_state_oneshot,
 161                .tick_resume            = txx9tmr_tick_resume,
 162                .set_next_event         = txx9tmr_set_next_event,
 163        },
 164};
 165
 166static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id)
 167{
 168        struct txx9_clock_event_device *txx9_cd = dev_id;
 169        struct clock_event_device *cd = &txx9_cd->cd;
 170        struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
 171
 172        __raw_writel(0, &tmrptr->tisr); /* ack interrupt */
 173        cd->event_handler(cd);
 174        return IRQ_HANDLED;
 175}
 176
 177void __init txx9_clockevent_init(unsigned long baseaddr, int irq,
 178                                 unsigned int imbusclk)
 179{
 180        struct clock_event_device *cd = &txx9_clock_event_device.cd;
 181        struct txx9_tmr_reg __iomem *tmrptr;
 182
 183        tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
 184        txx9tmr_stop_and_clear(tmrptr);
 185        __raw_writel(TIMER_CCD, &tmrptr->ccdr);
 186        __raw_writel(0, &tmrptr->itmr);
 187        txx9_clock_event_device.tmrptr = tmrptr;
 188
 189        clockevent_set_clock(cd, TIMER_CLK(imbusclk));
 190        cd->max_delta_ns =
 191                clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd);
 192        cd->max_delta_ticks = 0xffffffff >> (32 - TXX9_TIMER_BITS);
 193        cd->min_delta_ns = clockevent_delta2ns(0xf, cd);
 194        cd->min_delta_ticks = 0xf;
 195        cd->irq = irq;
 196        cd->cpumask = cpumask_of(0);
 197        clockevents_register_device(cd);
 198        if (request_irq(irq, txx9tmr_interrupt, IRQF_PERCPU | IRQF_TIMER,
 199                        "txx9tmr", &txx9_clock_event_device))
 200                pr_err("Failed to request irq %d (txx9tmr)\n", irq);
 201        printk(KERN_INFO "TXx9: clockevent device at 0x%lx, irq %d\n",
 202               baseaddr, irq);
 203}
 204
 205void __init txx9_tmr_init(unsigned long baseaddr)
 206{
 207        struct txx9_tmr_reg __iomem *tmrptr;
 208
 209        tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
 210        /* Start once to make CounterResetEnable effective */
 211        __raw_writel(TXx9_TMTCR_CRE | TXx9_TMTCR_TCE, &tmrptr->tcr);
 212        /* Stop and reset the counter */
 213        __raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr);
 214        __raw_writel(0, &tmrptr->tisr);
 215        __raw_writel(0xffffffff, &tmrptr->cpra);
 216        __raw_writel(0, &tmrptr->itmr);
 217        __raw_writel(0, &tmrptr->ccdr);
 218        __raw_writel(0, &tmrptr->pgmr);
 219        iounmap(tmrptr);
 220}
 221