timer-of.c (5401B)
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 */ 22static __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 if (of_irq->percpu) 29 free_percpu_irq(of_irq->irq, clkevt); 30 else 31 free_irq(of_irq->irq, clkevt); 32} 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 */ 50static __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 struct clock_event_device *clkevt = &to->clkevt; 56 57 if (of_irq->name) { 58 of_irq->irq = ret = of_irq_get_byname(np, of_irq->name); 59 if (ret < 0) { 60 pr_err("Failed to get interrupt %s for %pOF\n", 61 of_irq->name, np); 62 return ret; 63 } 64 } else { 65 of_irq->irq = irq_of_parse_and_map(np, of_irq->index); 66 } 67 if (!of_irq->irq) { 68 pr_err("Failed to map interrupt for %pOF\n", np); 69 return -EINVAL; 70 } 71 72 ret = of_irq->percpu ? 73 request_percpu_irq(of_irq->irq, of_irq->handler, 74 np->full_name, clkevt) : 75 request_irq(of_irq->irq, of_irq->handler, 76 of_irq->flags ? of_irq->flags : IRQF_TIMER, 77 np->full_name, clkevt); 78 if (ret) { 79 pr_err("Failed to request irq %d for %pOF\n", of_irq->irq, np); 80 return ret; 81 } 82 83 clkevt->irq = of_irq->irq; 84 85 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 */ 94static __init void timer_of_clk_exit(struct of_timer_clk *of_clk) 95{ 96 of_clk->rate = 0; 97 clk_disable_unprepare(of_clk->clk); 98 clk_put(of_clk->clk); 99} 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 */ 110static __init int timer_of_clk_init(struct device_node *np, 111 struct of_timer_clk *of_clk) 112{ 113 int ret; 114 115 of_clk->clk = of_clk->name ? of_clk_get_by_name(np, of_clk->name) : 116 of_clk_get(np, of_clk->index); 117 if (IS_ERR(of_clk->clk)) { 118 ret = PTR_ERR(of_clk->clk); 119 if (ret != -EPROBE_DEFER) 120 pr_err("Failed to get clock for %pOF\n", np); 121 goto out; 122 } 123 124 ret = clk_prepare_enable(of_clk->clk); 125 if (ret) { 126 pr_err("Failed for enable clock for %pOF\n", np); 127 goto out_clk_put; 128 } 129 130 of_clk->rate = clk_get_rate(of_clk->clk); 131 if (!of_clk->rate) { 132 ret = -EINVAL; 133 pr_err("Failed to get clock rate for %pOF\n", np); 134 goto out_clk_disable; 135 } 136 137 of_clk->period = DIV_ROUND_UP(of_clk->rate, HZ); 138out: 139 return ret; 140 141out_clk_disable: 142 clk_disable_unprepare(of_clk->clk); 143out_clk_put: 144 clk_put(of_clk->clk); 145 146 goto out; 147} 148 149static __init void timer_of_base_exit(struct of_timer_base *of_base) 150{ 151 iounmap(of_base->base); 152} 153 154static __init int timer_of_base_init(struct device_node *np, 155 struct of_timer_base *of_base) 156{ 157 of_base->base = of_base->name ? 158 of_io_request_and_map(np, of_base->index, of_base->name) : 159 of_iomap(np, of_base->index); 160 if (IS_ERR_OR_NULL(of_base->base)) { 161 pr_err("Failed to iomap (%s:%s)\n", np->name, of_base->name); 162 return of_base->base ? PTR_ERR(of_base->base) : -ENOMEM; 163 } 164 165 return 0; 166} 167 168int __init timer_of_init(struct device_node *np, struct timer_of *to) 169{ 170 int ret = -EINVAL; 171 int flags = 0; 172 173 if (to->flags & TIMER_OF_BASE) { 174 ret = timer_of_base_init(np, &to->of_base); 175 if (ret) 176 goto out_fail; 177 flags |= TIMER_OF_BASE; 178 } 179 180 if (to->flags & TIMER_OF_CLOCK) { 181 ret = timer_of_clk_init(np, &to->of_clk); 182 if (ret) 183 goto out_fail; 184 flags |= TIMER_OF_CLOCK; 185 } 186 187 if (to->flags & TIMER_OF_IRQ) { 188 ret = timer_of_irq_init(np, &to->of_irq); 189 if (ret) 190 goto out_fail; 191 flags |= TIMER_OF_IRQ; 192 } 193 194 if (!to->clkevt.name) 195 to->clkevt.name = np->full_name; 196 197 to->np = np; 198 199 return ret; 200 201out_fail: 202 if (flags & TIMER_OF_IRQ) 203 timer_of_irq_exit(&to->of_irq); 204 205 if (flags & TIMER_OF_CLOCK) 206 timer_of_clk_exit(&to->of_clk); 207 208 if (flags & TIMER_OF_BASE) 209 timer_of_base_exit(&to->of_base); 210 return ret; 211} 212 213/** 214 * timer_of_cleanup - release timer_of resources 215 * @to: timer_of structure 216 * 217 * Release the resources that has been used in timer_of_init(). 218 * This function should be called in init error cases 219 */ 220void __init timer_of_cleanup(struct timer_of *to) 221{ 222 if (to->flags & TIMER_OF_IRQ) 223 timer_of_irq_exit(&to->of_irq); 224 225 if (to->flags & TIMER_OF_CLOCK) 226 timer_of_clk_exit(&to->of_clk); 227 228 if (to->flags & TIMER_OF_BASE) 229 timer_of_base_exit(&to->of_base); 230}