1 /* 2 * Marvell Orion SoC timer handling. 3 * 4 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> 5 * 6 * This file is licensed under the terms of the GNU General Public 7 * License version 2. This program is licensed "as is" without any 8 * warranty of any kind, whether express or implied. 9 * 10 * Timer 0 is used as free-running clocksource, while timer 1 is 11 * used as clock_event_device. 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/bitops.h> 16 #include <linux/clk.h> 17 #include <linux/clockchips.h> 18 #include <linux/delay.h> 19 #include <linux/interrupt.h> 20 #include <linux/of_address.h> 21 #include <linux/of_irq.h> 22 #include <linux/spinlock.h> 23 #include <linux/sched_clock.h> 24 25 #define TIMER_CTRL 0x00 26 #define TIMER0_EN BIT(0) 27 #define TIMER0_RELOAD_EN BIT(1) 28 #define TIMER1_EN BIT(2) 29 #define TIMER1_RELOAD_EN BIT(3) 30 #define TIMER0_RELOAD 0x10 31 #define TIMER0_VAL 0x14 32 #define TIMER1_RELOAD 0x18 33 #define TIMER1_VAL 0x1c 34 35 #define ORION_ONESHOT_MIN 1 36 #define ORION_ONESHOT_MAX 0xfffffffe 37 38 static void __iomem *timer_base; 39 40 static unsigned long notrace orion_read_timer(void) 41 { 42 return ~readl(timer_base + TIMER0_VAL); 43 } 44 45 static struct delay_timer orion_delay_timer = { 46 .read_current_timer = orion_read_timer, 47 }; 48 49 static void orion_delay_timer_init(unsigned long rate) 50 { 51 orion_delay_timer.freq = rate; 52 register_current_timer_delay(&orion_delay_timer); 53 } 54 55 /* 56 * Free-running clocksource handling. 57 */ 58 static u64 notrace orion_read_sched_clock(void) 59 { 60 return ~readl(timer_base + TIMER0_VAL); 61 } 62 63 /* 64 * Clockevent handling. 65 */ 66 static u32 ticks_per_jiffy; 67 68 static int orion_clkevt_next_event(unsigned long delta, 69 struct clock_event_device *dev) 70 { 71 /* setup and enable one-shot timer */ 72 writel(delta, timer_base + TIMER1_VAL); 73 atomic_io_modify(timer_base + TIMER_CTRL, 74 TIMER1_RELOAD_EN | TIMER1_EN, TIMER1_EN); 75 76 return 0; 77 } 78 79 static int orion_clkevt_shutdown(struct clock_event_device *dev) 80 { 81 /* disable timer */ 82 atomic_io_modify(timer_base + TIMER_CTRL, 83 TIMER1_RELOAD_EN | TIMER1_EN, 0); 84 return 0; 85 } 86 87 static int orion_clkevt_set_periodic(struct clock_event_device *dev) 88 { 89 /* setup and enable periodic timer at 1/HZ intervals */ 90 writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); 91 writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); 92 atomic_io_modify(timer_base + TIMER_CTRL, 93 TIMER1_RELOAD_EN | TIMER1_EN, 94 TIMER1_RELOAD_EN | TIMER1_EN); 95 return 0; 96 } 97 98 static struct clock_event_device orion_clkevt = { 99 .name = "orion_event", 100 .features = CLOCK_EVT_FEAT_ONESHOT | 101 CLOCK_EVT_FEAT_PERIODIC, 102 .shift = 32, 103 .rating = 300, 104 .set_next_event = orion_clkevt_next_event, 105 .set_state_shutdown = orion_clkevt_shutdown, 106 .set_state_periodic = orion_clkevt_set_periodic, 107 .set_state_oneshot = orion_clkevt_shutdown, 108 .tick_resume = orion_clkevt_shutdown, 109 }; 110 111 static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id) 112 { 113 orion_clkevt.event_handler(&orion_clkevt); 114 return IRQ_HANDLED; 115 } 116 117 static struct irqaction orion_clkevt_irq = { 118 .name = "orion_event", 119 .flags = IRQF_TIMER, 120 .handler = orion_clkevt_irq_handler, 121 }; 122 123 static int __init orion_timer_init(struct device_node *np) 124 { 125 unsigned long rate; 126 struct clk *clk; 127 int irq, ret; 128 129 /* timer registers are shared with watchdog timer */ 130 timer_base = of_iomap(np, 0); 131 if (!timer_base) { 132 pr_err("%pOFn: unable to map resource\n", np); 133 return -ENXIO; 134 } 135 136 clk = of_clk_get(np, 0); 137 if (IS_ERR(clk)) { 138 pr_err("%pOFn: unable to get clk\n", np); 139 return PTR_ERR(clk); 140 } 141 142 ret = clk_prepare_enable(clk); 143 if (ret) { 144 pr_err("Failed to prepare clock\n"); 145 return ret; 146 } 147 148 /* we are only interested in timer1 irq */ 149 irq = irq_of_parse_and_map(np, 1); 150 if (irq <= 0) { 151 pr_err("%pOFn: unable to parse timer1 irq\n", np); 152 return -EINVAL; 153 } 154 155 rate = clk_get_rate(clk); 156 157 /* setup timer0 as free-running clocksource */ 158 writel(~0, timer_base + TIMER0_VAL); 159 writel(~0, timer_base + TIMER0_RELOAD); 160 atomic_io_modify(timer_base + TIMER_CTRL, 161 TIMER0_RELOAD_EN | TIMER0_EN, 162 TIMER0_RELOAD_EN | TIMER0_EN); 163 164 ret = clocksource_mmio_init(timer_base + TIMER0_VAL, 165 "orion_clocksource", rate, 300, 32, 166 clocksource_mmio_readl_down); 167 if (ret) { 168 pr_err("Failed to initialize mmio timer\n"); 169 return ret; 170 } 171 172 sched_clock_register(orion_read_sched_clock, 32, rate); 173 174 /* setup timer1 as clockevent timer */ 175 ret = setup_irq(irq, &orion_clkevt_irq); 176 if (ret) { 177 pr_err("%pOFn: unable to setup irq\n", np); 178 return ret; 179 } 180 181 ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ; 182 orion_clkevt.cpumask = cpumask_of(0); 183 orion_clkevt.irq = irq; 184 clockevents_config_and_register(&orion_clkevt, rate, 185 ORION_ONESHOT_MIN, ORION_ONESHOT_MAX); 186 187 188 orion_delay_timer_init(rate); 189 190 return 0; 191 } 192 TIMER_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); 193