1 /* 2 * Copyright 2012-2013 Freescale Semiconductor, Inc. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 */ 9 10 #include <linux/interrupt.h> 11 #include <linux/clockchips.h> 12 #include <linux/clk.h> 13 #include <linux/of_address.h> 14 #include <linux/of_irq.h> 15 #include <linux/sched_clock.h> 16 17 /* 18 * Each pit takes 0x10 Bytes register space 19 */ 20 #define PITMCR 0x00 21 #define PIT0_OFFSET 0x100 22 #define PITn_OFFSET(n) (PIT0_OFFSET + 0x10 * (n)) 23 #define PITLDVAL 0x00 24 #define PITCVAL 0x04 25 #define PITTCTRL 0x08 26 #define PITTFLG 0x0c 27 28 #define PITMCR_MDIS (0x1 << 1) 29 30 #define PITTCTRL_TEN (0x1 << 0) 31 #define PITTCTRL_TIE (0x1 << 1) 32 #define PITCTRL_CHN (0x1 << 2) 33 34 #define PITTFLG_TIF 0x1 35 36 static void __iomem *clksrc_base; 37 static void __iomem *clkevt_base; 38 static unsigned long cycle_per_jiffy; 39 40 static inline void pit_timer_enable(void) 41 { 42 __raw_writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL); 43 } 44 45 static inline void pit_timer_disable(void) 46 { 47 __raw_writel(0, clkevt_base + PITTCTRL); 48 } 49 50 static inline void pit_irq_acknowledge(void) 51 { 52 __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); 53 } 54 55 static u64 notrace pit_read_sched_clock(void) 56 { 57 return ~__raw_readl(clksrc_base + PITCVAL); 58 } 59 60 static int __init pit_clocksource_init(unsigned long rate) 61 { 62 /* set the max load value and start the clock source counter */ 63 __raw_writel(0, clksrc_base + PITTCTRL); 64 __raw_writel(~0UL, clksrc_base + PITLDVAL); 65 __raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL); 66 67 sched_clock_register(pit_read_sched_clock, 32, rate); 68 return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate, 69 300, 32, clocksource_mmio_readl_down); 70 } 71 72 static int pit_set_next_event(unsigned long delta, 73 struct clock_event_device *unused) 74 { 75 /* 76 * set a new value to PITLDVAL register will not restart the timer, 77 * to abort the current cycle and start a timer period with the new 78 * value, the timer must be disabled and enabled again. 79 * and the PITLAVAL should be set to delta minus one according to pit 80 * hardware requirement. 81 */ 82 pit_timer_disable(); 83 __raw_writel(delta - 1, clkevt_base + PITLDVAL); 84 pit_timer_enable(); 85 86 return 0; 87 } 88 89 static int pit_shutdown(struct clock_event_device *evt) 90 { 91 pit_timer_disable(); 92 return 0; 93 } 94 95 static int pit_set_periodic(struct clock_event_device *evt) 96 { 97 pit_set_next_event(cycle_per_jiffy, evt); 98 return 0; 99 } 100 101 static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) 102 { 103 struct clock_event_device *evt = dev_id; 104 105 pit_irq_acknowledge(); 106 107 /* 108 * pit hardware doesn't support oneshot, it will generate an interrupt 109 * and reload the counter value from PITLDVAL when PITCVAL reach zero, 110 * and start the counter again. So software need to disable the timer 111 * to stop the counter loop in ONESHOT mode. 112 */ 113 if (likely(clockevent_state_oneshot(evt))) 114 pit_timer_disable(); 115 116 evt->event_handler(evt); 117 118 return IRQ_HANDLED; 119 } 120 121 static struct clock_event_device clockevent_pit = { 122 .name = "VF pit timer", 123 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 124 .set_state_shutdown = pit_shutdown, 125 .set_state_periodic = pit_set_periodic, 126 .set_next_event = pit_set_next_event, 127 .rating = 300, 128 }; 129 130 static struct irqaction pit_timer_irq = { 131 .name = "VF pit timer", 132 .flags = IRQF_TIMER | IRQF_IRQPOLL, 133 .handler = pit_timer_interrupt, 134 .dev_id = &clockevent_pit, 135 }; 136 137 static int __init pit_clockevent_init(unsigned long rate, int irq) 138 { 139 __raw_writel(0, clkevt_base + PITTCTRL); 140 __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); 141 142 BUG_ON(setup_irq(irq, &pit_timer_irq)); 143 144 clockevent_pit.cpumask = cpumask_of(0); 145 clockevent_pit.irq = irq; 146 /* 147 * The value for the LDVAL register trigger is calculated as: 148 * LDVAL trigger = (period / clock period) - 1 149 * The pit is a 32-bit down count timer, when the conter value 150 * reaches 0, it will generate an interrupt, thus the minimal 151 * LDVAL trigger value is 1. And then the min_delta is 152 * minimal LDVAL trigger value + 1, and the max_delta is full 32-bit. 153 */ 154 clockevents_config_and_register(&clockevent_pit, rate, 2, 0xffffffff); 155 156 return 0; 157 } 158 159 static int __init pit_timer_init(struct device_node *np) 160 { 161 struct clk *pit_clk; 162 void __iomem *timer_base; 163 unsigned long clk_rate; 164 int irq, ret; 165 166 timer_base = of_iomap(np, 0); 167 if (!timer_base) { 168 pr_err("Failed to iomap\n"); 169 return -ENXIO; 170 } 171 172 /* 173 * PIT0 and PIT1 can be chained to build a 64-bit timer, 174 * so choose PIT2 as clocksource, PIT3 as clockevent device, 175 * and leave PIT0 and PIT1 unused for anyone else who needs them. 176 */ 177 clksrc_base = timer_base + PITn_OFFSET(2); 178 clkevt_base = timer_base + PITn_OFFSET(3); 179 180 irq = irq_of_parse_and_map(np, 0); 181 if (irq <= 0) 182 return -EINVAL; 183 184 pit_clk = of_clk_get(np, 0); 185 if (IS_ERR(pit_clk)) 186 return PTR_ERR(pit_clk); 187 188 ret = clk_prepare_enable(pit_clk); 189 if (ret) 190 return ret; 191 192 clk_rate = clk_get_rate(pit_clk); 193 cycle_per_jiffy = clk_rate / (HZ); 194 195 /* enable the pit module */ 196 __raw_writel(~PITMCR_MDIS, timer_base + PITMCR); 197 198 ret = pit_clocksource_init(clk_rate); 199 if (ret) 200 return ret; 201 202 return pit_clockevent_init(clk_rate, irq); 203 } 204 TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init); 205