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