1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2017, Linaro Ltd. All rights reserved. 4 * 5 * Author: Daniel Lezcano <daniel.lezcano@linaro.org> 6 */ 7 #include <linux/clk.h> 8 #include <linux/interrupt.h> 9 #include <linux/of.h> 10 #include <linux/of_address.h> 11 #include <linux/of_irq.h> 12 #include <linux/slab.h> 13 14 #include "timer-of.h" 15 16 /** 17 * timer_of_irq_exit - Release the interrupt 18 * @of_irq: an of_timer_irq structure pointer 19 * 20 * Free the irq resource 21 */ 22 static __init void timer_of_irq_exit(struct of_timer_irq *of_irq) 23 { 24 struct timer_of *to = container_of(of_irq, struct timer_of, of_irq); 25 26 struct clock_event_device *clkevt = &to->clkevt; 27 28 of_irq->percpu ? free_percpu_irq(of_irq->irq, clkevt) : 29 free_irq(of_irq->irq, clkevt); 30 } 31 32 /** 33 * timer_of_irq_init - Request the interrupt 34 * @np: a device tree node pointer 35 * @of_irq: an of_timer_irq structure pointer 36 * 37 * Get the interrupt number from the DT from its definition and 38 * request it. The interrupt is gotten by falling back the following way: 39 * 40 * - Get interrupt number by name 41 * - Get interrupt number by index 42 * 43 * When the interrupt is per CPU, 'request_percpu_irq()' is called, 44 * otherwise 'request_irq()' is used. 45 * 46 * Returns 0 on success, < 0 otherwise 47 */ 48 static __init int timer_of_irq_init(struct device_node *np, 49 struct of_timer_irq *of_irq) 50 { 51 int ret; 52 struct timer_of *to = container_of(of_irq, struct timer_of, of_irq); 53 struct clock_event_device *clkevt = &to->clkevt; 54 55 if (of_irq->name) { 56 of_irq->irq = ret = of_irq_get_byname(np, of_irq->name); 57 if (ret < 0) { 58 pr_err("Failed to get interrupt %s for %pOF\n", 59 of_irq->name, np); 60 return ret; 61 } 62 } else { 63 of_irq->irq = irq_of_parse_and_map(np, of_irq->index); 64 } 65 if (!of_irq->irq) { 66 pr_err("Failed to map interrupt for %pOF\n", np); 67 return -EINVAL; 68 } 69 70 ret = of_irq->percpu ? 71 request_percpu_irq(of_irq->irq, of_irq->handler, 72 np->full_name, clkevt) : 73 request_irq(of_irq->irq, of_irq->handler, 74 of_irq->flags ? of_irq->flags : IRQF_TIMER, 75 np->full_name, clkevt); 76 if (ret) { 77 pr_err("Failed to request irq %d for %pOF\n", of_irq->irq, np); 78 return ret; 79 } 80 81 clkevt->irq = of_irq->irq; 82 83 return 0; 84 } 85 86 /** 87 * timer_of_clk_exit - Release the clock resources 88 * @of_clk: a of_timer_clk structure pointer 89 * 90 * Disables and releases the refcount on the clk 91 */ 92 static __init void timer_of_clk_exit(struct of_timer_clk *of_clk) 93 { 94 of_clk->rate = 0; 95 clk_disable_unprepare(of_clk->clk); 96 clk_put(of_clk->clk); 97 } 98 99 /** 100 * timer_of_clk_init - Initialize the clock resources 101 * @np: a device tree node pointer 102 * @of_clk: a of_timer_clk structure pointer 103 * 104 * Get the clock by name or by index, enable it and get the rate 105 * 106 * Returns 0 on success, < 0 otherwise 107 */ 108 static __init int timer_of_clk_init(struct device_node *np, 109 struct of_timer_clk *of_clk) 110 { 111 int ret; 112 113 of_clk->clk = of_clk->name ? of_clk_get_by_name(np, of_clk->name) : 114 of_clk_get(np, of_clk->index); 115 if (IS_ERR(of_clk->clk)) { 116 ret = PTR_ERR(of_clk->clk); 117 if (ret != -EPROBE_DEFER) 118 pr_err("Failed to get clock for %pOF\n", np); 119 goto out; 120 } 121 122 ret = clk_prepare_enable(of_clk->clk); 123 if (ret) { 124 pr_err("Failed for enable clock for %pOF\n", np); 125 goto out_clk_put; 126 } 127 128 of_clk->rate = clk_get_rate(of_clk->clk); 129 if (!of_clk->rate) { 130 ret = -EINVAL; 131 pr_err("Failed to get clock rate for %pOF\n", np); 132 goto out_clk_disable; 133 } 134 135 of_clk->period = DIV_ROUND_UP(of_clk->rate, HZ); 136 out: 137 return ret; 138 139 out_clk_disable: 140 clk_disable_unprepare(of_clk->clk); 141 out_clk_put: 142 clk_put(of_clk->clk); 143 144 goto out; 145 } 146 147 static __init void timer_of_base_exit(struct of_timer_base *of_base) 148 { 149 iounmap(of_base->base); 150 } 151 152 static __init int timer_of_base_init(struct device_node *np, 153 struct of_timer_base *of_base) 154 { 155 of_base->base = of_base->name ? 156 of_io_request_and_map(np, of_base->index, of_base->name) : 157 of_iomap(np, of_base->index); 158 if (IS_ERR(of_base->base)) { 159 pr_err("Failed to iomap (%s)\n", of_base->name); 160 return PTR_ERR(of_base->base); 161 } 162 163 return 0; 164 } 165 166 int __init timer_of_init(struct device_node *np, struct timer_of *to) 167 { 168 int ret = -EINVAL; 169 int flags = 0; 170 171 if (to->flags & TIMER_OF_BASE) { 172 ret = timer_of_base_init(np, &to->of_base); 173 if (ret) 174 goto out_fail; 175 flags |= TIMER_OF_BASE; 176 } 177 178 if (to->flags & TIMER_OF_CLOCK) { 179 ret = timer_of_clk_init(np, &to->of_clk); 180 if (ret) 181 goto out_fail; 182 flags |= TIMER_OF_CLOCK; 183 } 184 185 if (to->flags & TIMER_OF_IRQ) { 186 ret = timer_of_irq_init(np, &to->of_irq); 187 if (ret) 188 goto out_fail; 189 flags |= TIMER_OF_IRQ; 190 } 191 192 if (!to->clkevt.name) 193 to->clkevt.name = np->name; 194 195 to->np = np; 196 197 return ret; 198 199 out_fail: 200 if (flags & TIMER_OF_IRQ) 201 timer_of_irq_exit(&to->of_irq); 202 203 if (flags & TIMER_OF_CLOCK) 204 timer_of_clk_exit(&to->of_clk); 205 206 if (flags & TIMER_OF_BASE) 207 timer_of_base_exit(&to->of_base); 208 return ret; 209 } 210 211 /** 212 * timer_of_cleanup - release timer_of ressources 213 * @to: timer_of structure 214 * 215 * Release the ressources that has been used in timer_of_init(). 216 * This function should be called in init error cases 217 */ 218 void __init timer_of_cleanup(struct timer_of *to) 219 { 220 if (to->flags & TIMER_OF_IRQ) 221 timer_of_irq_exit(&to->of_irq); 222 223 if (to->flags & TIMER_OF_CLOCK) 224 timer_of_clk_exit(&to->of_clk); 225 226 if (to->flags & TIMER_OF_BASE) 227 timer_of_base_exit(&to->of_base); 228 } 229