1/* 2 * Copyright (c) 2016, Mellanox Technologies. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33#include <linux/interrupt.h> 34#include <linux/clocksource.h> 35#include <linux/clockchips.h> 36#include <linux/clk.h> 37#include <linux/of.h> 38#include <linux/of_irq.h> 39#include <linux/cpu.h> 40#include <soc/nps/common.h> 41 42#define NPS_MSU_TICK_LOW 0xC8 43#define NPS_CLUSTER_OFFSET 8 44#define NPS_CLUSTER_NUM 16 45 46/* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */ 47static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly; 48 49static int __init nps_get_timer_clk(struct device_node *node, 50 unsigned long *timer_freq, 51 struct clk **clk) 52{ 53 int ret; 54 55 *clk = of_clk_get(node, 0); 56 ret = PTR_ERR_OR_ZERO(*clk); 57 if (ret) { 58 pr_err("timer missing clk\n"); 59 return ret; 60 } 61 62 ret = clk_prepare_enable(*clk); 63 if (ret) { 64 pr_err("Couldn't enable parent clk\n"); 65 clk_put(*clk); 66 return ret; 67 } 68 69 *timer_freq = clk_get_rate(*clk); 70 if (!(*timer_freq)) { 71 pr_err("Couldn't get clk rate\n"); 72 clk_disable_unprepare(*clk); 73 clk_put(*clk); 74 return -EINVAL; 75 } 76 77 return 0; 78} 79 80static u64 nps_clksrc_read(struct clocksource *clksrc) 81{ 82 int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET; 83 84 return (u64)ioread32be(nps_msu_reg_low_addr[cluster]); 85} 86 87static int __init nps_setup_clocksource(struct device_node *node) 88{ 89 int ret, cluster; 90 struct clk *clk; 91 unsigned long nps_timer1_freq; 92 93 94 for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++) 95 nps_msu_reg_low_addr[cluster] = 96 nps_host_reg((cluster << NPS_CLUSTER_OFFSET), 97 NPS_MSU_BLKID, NPS_MSU_TICK_LOW); 98 99 ret = nps_get_timer_clk(node, &nps_timer1_freq, &clk); 100 if (ret) 101 return ret; 102 103 ret = clocksource_mmio_init(nps_msu_reg_low_addr, "nps-tick", 104 nps_timer1_freq, 300, 32, nps_clksrc_read); 105 if (ret) { 106 pr_err("Couldn't register clock source.\n"); 107 clk_disable_unprepare(clk); 108 } 109 110 return ret; 111} 112 113TIMER_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer", 114 nps_setup_clocksource); 115TIMER_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1", 116 nps_setup_clocksource); 117 118#ifdef CONFIG_EZNPS_MTM_EXT 119#include <soc/nps/mtm.h> 120 121/* Timer related Aux registers */ 122#define NPS_REG_TIMER0_TSI 0xFFFFF850 123#define NPS_REG_TIMER0_LIMIT 0x23 124#define NPS_REG_TIMER0_CTRL 0x22 125#define NPS_REG_TIMER0_CNT 0x21 126 127/* 128 * Interrupt Enabled (IE) - re-arm the timer 129 * Not Halted (NH) - is cleared when working with JTAG (for debug) 130 */ 131#define TIMER0_CTRL_IE BIT(0) 132#define TIMER0_CTRL_NH BIT(1) 133 134static unsigned long nps_timer0_freq; 135static unsigned long nps_timer0_irq; 136 137static void nps_clkevent_rm_thread(void) 138{ 139 int thread; 140 unsigned int cflags, enabled_threads; 141 142 hw_schd_save(&cflags); 143 144 enabled_threads = read_aux_reg(NPS_REG_TIMER0_TSI); 145 146 /* remove thread from TSI1 */ 147 thread = read_aux_reg(CTOP_AUX_THREAD_ID); 148 enabled_threads &= ~(1 << thread); 149 write_aux_reg(NPS_REG_TIMER0_TSI, enabled_threads); 150 151 /* Acknowledge and if needed re-arm the timer */ 152 if (!enabled_threads) 153 write_aux_reg(NPS_REG_TIMER0_CTRL, TIMER0_CTRL_NH); 154 else 155 write_aux_reg(NPS_REG_TIMER0_CTRL, 156 TIMER0_CTRL_IE | TIMER0_CTRL_NH); 157 158 hw_schd_restore(cflags); 159} 160 161static void nps_clkevent_add_thread(unsigned long delta) 162{ 163 int thread; 164 unsigned int cflags, enabled_threads; 165 166 hw_schd_save(&cflags); 167 168 /* add thread to TSI1 */ 169 thread = read_aux_reg(CTOP_AUX_THREAD_ID); 170 enabled_threads = read_aux_reg(NPS_REG_TIMER0_TSI); 171 enabled_threads |= (1 << thread); 172 write_aux_reg(NPS_REG_TIMER0_TSI, enabled_threads); 173 174 /* set next timer event */ 175 write_aux_reg(NPS_REG_TIMER0_LIMIT, delta); 176 write_aux_reg(NPS_REG_TIMER0_CNT, 0); 177 write_aux_reg(NPS_REG_TIMER0_CTRL, 178 TIMER0_CTRL_IE | TIMER0_CTRL_NH); 179 180 hw_schd_restore(cflags); 181} 182 183/* 184 * Whenever anyone tries to change modes, we just mask interrupts 185 * and wait for the next event to get set. 186 */ 187static int nps_clkevent_set_state(struct clock_event_device *dev) 188{ 189 nps_clkevent_rm_thread(); 190 disable_percpu_irq(nps_timer0_irq); 191 192 return 0; 193} 194 195static int nps_clkevent_set_next_event(unsigned long delta, 196 struct clock_event_device *dev) 197{ 198 nps_clkevent_add_thread(delta); 199 enable_percpu_irq(nps_timer0_irq, IRQ_TYPE_NONE); 200 201 return 0; 202} 203 204static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = { 205 .name = "NPS Timer0", 206 .features = CLOCK_EVT_FEAT_ONESHOT, 207 .rating = 300, 208 .set_next_event = nps_clkevent_set_next_event, 209 .set_state_oneshot = nps_clkevent_set_state, 210 .set_state_oneshot_stopped = nps_clkevent_set_state, 211 .set_state_shutdown = nps_clkevent_set_state, 212 .tick_resume = nps_clkevent_set_state, 213}; 214 215static irqreturn_t timer_irq_handler(int irq, void *dev_id) 216{ 217 struct clock_event_device *evt = dev_id; 218 219 nps_clkevent_rm_thread(); 220 evt->event_handler(evt); 221 222 return IRQ_HANDLED; 223} 224 225static int nps_timer_starting_cpu(unsigned int cpu) 226{ 227 struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device); 228 229 evt->cpumask = cpumask_of(smp_processor_id()); 230 231 clockevents_config_and_register(evt, nps_timer0_freq, 0, ULONG_MAX); 232 enable_percpu_irq(nps_timer0_irq, IRQ_TYPE_NONE); 233 234 return 0; 235} 236 237static int nps_timer_dying_cpu(unsigned int cpu) 238{ 239 disable_percpu_irq(nps_timer0_irq); 240 return 0; 241} 242 243static int __init nps_setup_clockevent(struct device_node *node) 244{ 245 struct clk *clk; 246 int ret; 247 248 nps_timer0_irq = irq_of_parse_and_map(node, 0); 249 if (nps_timer0_irq <= 0) { 250 pr_err("clockevent: missing irq\n"); 251 return -EINVAL; 252 } 253 254 ret = nps_get_timer_clk(node, &nps_timer0_freq, &clk); 255 if (ret) 256 return ret; 257 258 /* Needs apriori irq_set_percpu_devid() done in intc map function */ 259 ret = request_percpu_irq(nps_timer0_irq, timer_irq_handler, 260 "Timer0 (per-cpu-tick)", 261 &nps_clockevent_device); 262 if (ret) { 263 pr_err("Couldn't request irq\n"); 264 clk_disable_unprepare(clk); 265 return ret; 266 } 267 268 ret = cpuhp_setup_state(CPUHP_AP_ARC_TIMER_STARTING, 269 "clockevents/nps:starting", 270 nps_timer_starting_cpu, 271 nps_timer_dying_cpu); 272 if (ret) { 273 pr_err("Failed to setup hotplug state\n"); 274 clk_disable_unprepare(clk); 275 free_percpu_irq(nps_timer0_irq, &nps_clockevent_device); 276 return ret; 277 } 278 279 return 0; 280} 281 282TIMER_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0", 283 nps_setup_clockevent); 284#endif /* CONFIG_EZNPS_MTM_EXT */ 285