Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Based on linux/arch/mips/kernel/cevt-r4k.c,
0007  *      linux/arch/mips/jmr3927/rbhma3100/setup.c
0008  *
0009  * Copyright 2001 MontaVista Software Inc.
0010  * Copyright (C) 2000-2001 Toshiba Corporation
0011  * Copyright (C) 2007 MIPS Technologies, Inc.
0012  * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
0013  */
0014 #include <linux/init.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/irq.h>
0017 #include <linux/sched_clock.h>
0018 #include <asm/time.h>
0019 #include <asm/txx9tmr.h>
0020 
0021 #define TCR_BASE (TXx9_TMTCR_CCDE | TXx9_TMTCR_CRE | TXx9_TMTCR_TMODE_ITVL)
0022 #define TIMER_CCD   0   /* 1/2 */
0023 #define TIMER_CLK(imclk)    ((imclk) / (2 << TIMER_CCD))
0024 
0025 struct txx9_clocksource {
0026     struct clocksource cs;
0027     struct txx9_tmr_reg __iomem *tmrptr;
0028 };
0029 
0030 static u64 txx9_cs_read(struct clocksource *cs)
0031 {
0032     struct txx9_clocksource *txx9_cs =
0033         container_of(cs, struct txx9_clocksource, cs);
0034     return __raw_readl(&txx9_cs->tmrptr->trr);
0035 }
0036 
0037 /* Use 1 bit smaller width to use full bits in that width */
0038 #define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1)
0039 
0040 static struct txx9_clocksource txx9_clocksource = {
0041     .cs = {
0042         .name       = "TXx9",
0043         .rating     = 200,
0044         .read       = txx9_cs_read,
0045         .mask       = CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS),
0046         .flags      = CLOCK_SOURCE_IS_CONTINUOUS,
0047     },
0048 };
0049 
0050 static u64 notrace txx9_read_sched_clock(void)
0051 {
0052     return __raw_readl(&txx9_clocksource.tmrptr->trr);
0053 }
0054 
0055 void __init txx9_clocksource_init(unsigned long baseaddr,
0056                   unsigned int imbusclk)
0057 {
0058     struct txx9_tmr_reg __iomem *tmrptr;
0059 
0060     clocksource_register_hz(&txx9_clocksource.cs, TIMER_CLK(imbusclk));
0061 
0062     tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
0063     __raw_writel(TCR_BASE, &tmrptr->tcr);
0064     __raw_writel(0, &tmrptr->tisr);
0065     __raw_writel(TIMER_CCD, &tmrptr->ccdr);
0066     __raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr);
0067     __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra);
0068     __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
0069     txx9_clocksource.tmrptr = tmrptr;
0070 
0071     sched_clock_register(txx9_read_sched_clock, TXX9_CLOCKSOURCE_BITS,
0072                  TIMER_CLK(imbusclk));
0073 }
0074 
0075 struct txx9_clock_event_device {
0076     struct clock_event_device cd;
0077     struct txx9_tmr_reg __iomem *tmrptr;
0078 };
0079 
0080 static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
0081 {
0082     /* stop and reset counter */
0083     __raw_writel(TCR_BASE, &tmrptr->tcr);
0084     /* clear pending interrupt */
0085     __raw_writel(0, &tmrptr->tisr);
0086 }
0087 
0088 static int txx9tmr_set_state_periodic(struct clock_event_device *evt)
0089 {
0090     struct txx9_clock_event_device *txx9_cd =
0091         container_of(evt, struct txx9_clock_event_device, cd);
0092     struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
0093 
0094     txx9tmr_stop_and_clear(tmrptr);
0095 
0096     __raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE, &tmrptr->itmr);
0097     /* start timer */
0098     __raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >> evt->shift,
0099              &tmrptr->cpra);
0100     __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
0101     return 0;
0102 }
0103 
0104 static int txx9tmr_set_state_oneshot(struct clock_event_device *evt)
0105 {
0106     struct txx9_clock_event_device *txx9_cd =
0107         container_of(evt, struct txx9_clock_event_device, cd);
0108     struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
0109 
0110     txx9tmr_stop_and_clear(tmrptr);
0111     __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr);
0112     return 0;
0113 }
0114 
0115 static int txx9tmr_set_state_shutdown(struct clock_event_device *evt)
0116 {
0117     struct txx9_clock_event_device *txx9_cd =
0118         container_of(evt, struct txx9_clock_event_device, cd);
0119     struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
0120 
0121     txx9tmr_stop_and_clear(tmrptr);
0122     __raw_writel(0, &tmrptr->itmr);
0123     return 0;
0124 }
0125 
0126 static int txx9tmr_tick_resume(struct clock_event_device *evt)
0127 {
0128     struct txx9_clock_event_device *txx9_cd =
0129         container_of(evt, struct txx9_clock_event_device, cd);
0130     struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
0131 
0132     txx9tmr_stop_and_clear(tmrptr);
0133     __raw_writel(TIMER_CCD, &tmrptr->ccdr);
0134     __raw_writel(0, &tmrptr->itmr);
0135     return 0;
0136 }
0137 
0138 static int txx9tmr_set_next_event(unsigned long delta,
0139                   struct clock_event_device *evt)
0140 {
0141     struct txx9_clock_event_device *txx9_cd =
0142         container_of(evt, struct txx9_clock_event_device, cd);
0143     struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
0144 
0145     txx9tmr_stop_and_clear(tmrptr);
0146     /* start timer */
0147     __raw_writel(delta, &tmrptr->cpra);
0148     __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
0149     return 0;
0150 }
0151 
0152 static struct txx9_clock_event_device txx9_clock_event_device = {
0153     .cd = {
0154         .name           = "TXx9",
0155         .features       = CLOCK_EVT_FEAT_PERIODIC |
0156                       CLOCK_EVT_FEAT_ONESHOT,
0157         .rating         = 200,
0158         .set_state_shutdown = txx9tmr_set_state_shutdown,
0159         .set_state_periodic = txx9tmr_set_state_periodic,
0160         .set_state_oneshot  = txx9tmr_set_state_oneshot,
0161         .tick_resume        = txx9tmr_tick_resume,
0162         .set_next_event     = txx9tmr_set_next_event,
0163     },
0164 };
0165 
0166 static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id)
0167 {
0168     struct txx9_clock_event_device *txx9_cd = dev_id;
0169     struct clock_event_device *cd = &txx9_cd->cd;
0170     struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
0171 
0172     __raw_writel(0, &tmrptr->tisr); /* ack interrupt */
0173     cd->event_handler(cd);
0174     return IRQ_HANDLED;
0175 }
0176 
0177 void __init txx9_clockevent_init(unsigned long baseaddr, int irq,
0178                  unsigned int imbusclk)
0179 {
0180     struct clock_event_device *cd = &txx9_clock_event_device.cd;
0181     struct txx9_tmr_reg __iomem *tmrptr;
0182 
0183     tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
0184     txx9tmr_stop_and_clear(tmrptr);
0185     __raw_writel(TIMER_CCD, &tmrptr->ccdr);
0186     __raw_writel(0, &tmrptr->itmr);
0187     txx9_clock_event_device.tmrptr = tmrptr;
0188 
0189     clockevent_set_clock(cd, TIMER_CLK(imbusclk));
0190     cd->max_delta_ns =
0191         clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd);
0192     cd->max_delta_ticks = 0xffffffff >> (32 - TXX9_TIMER_BITS);
0193     cd->min_delta_ns = clockevent_delta2ns(0xf, cd);
0194     cd->min_delta_ticks = 0xf;
0195     cd->irq = irq;
0196     cd->cpumask = cpumask_of(0);
0197     clockevents_register_device(cd);
0198     if (request_irq(irq, txx9tmr_interrupt, IRQF_PERCPU | IRQF_TIMER,
0199             "txx9tmr", &txx9_clock_event_device))
0200         pr_err("Failed to request irq %d (txx9tmr)\n", irq);
0201     printk(KERN_INFO "TXx9: clockevent device at 0x%lx, irq %d\n",
0202            baseaddr, irq);
0203 }
0204 
0205 void __init txx9_tmr_init(unsigned long baseaddr)
0206 {
0207     struct txx9_tmr_reg __iomem *tmrptr;
0208 
0209     tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
0210     /* Start once to make CounterResetEnable effective */
0211     __raw_writel(TXx9_TMTCR_CRE | TXx9_TMTCR_TCE, &tmrptr->tcr);
0212     /* Stop and reset the counter */
0213     __raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr);
0214     __raw_writel(0, &tmrptr->tisr);
0215     __raw_writel(0xffffffff, &tmrptr->cpra);
0216     __raw_writel(0, &tmrptr->itmr);
0217     __raw_writel(0, &tmrptr->ccdr);
0218     __raw_writel(0, &tmrptr->pgmr);
0219     iounmap(tmrptr);
0220 }