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 23 static struct txx9_tmr_reg __iomem *txx9_cs_tmrptr; 24 25 static cycle_t txx9_cs_read(void) 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 33 static 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 41 void __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 59 static struct txx9_tmr_reg __iomem *txx9_tmrptr; 60 61 static 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 69 static 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 99 static 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 111 static 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 .cpumask = CPU_MASK_CPU0, 116 .set_mode = txx9tmr_set_mode, 117 .set_next_event = txx9tmr_set_next_event, 118 }; 119 120 static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id) 121 { 122 struct clock_event_device *cd = &txx9tmr_clock_event_device; 123 struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; 124 125 __raw_writel(0, &tmrptr->tisr); /* ack interrupt */ 126 cd->event_handler(cd); 127 return IRQ_HANDLED; 128 } 129 130 static struct irqaction txx9tmr_irq = { 131 .handler = txx9tmr_interrupt, 132 .flags = IRQF_DISABLED | IRQF_PERCPU, 133 .name = "txx9tmr", 134 }; 135 136 void __init txx9_clockevent_init(unsigned long baseaddr, int irq, 137 unsigned int imbusclk) 138 { 139 struct clock_event_device *cd = &txx9tmr_clock_event_device; 140 struct txx9_tmr_reg __iomem *tmrptr; 141 142 tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); 143 txx9tmr_stop_and_clear(tmrptr); 144 __raw_writel(TIMER_CCD, &tmrptr->ccdr); 145 __raw_writel(0, &tmrptr->itmr); 146 txx9_tmrptr = tmrptr; 147 148 clockevent_set_clock(cd, TIMER_CLK(imbusclk)); 149 cd->max_delta_ns = 150 clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd); 151 cd->min_delta_ns = clockevent_delta2ns(0xf, cd); 152 cd->irq = irq; 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 159 void __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