1// SPDX-License-Identifier: GPL-2.0 2#include <linux/clocksource.h> 3#include <linux/sched_clock.h> 4#include <linux/of_address.h> 5#include <linux/printk.h> 6#include <linux/delay.h> 7#include <linux/init.h> 8#include <linux/clk.h> 9 10static void __iomem *xtal_in_cnt; 11static struct delay_timer delay_timer; 12 13static unsigned long notrace read_xtal_counter(void) 14{ 15 return readl_relaxed(xtal_in_cnt); 16} 17 18static u64 notrace read_sched_clock(void) 19{ 20 return read_xtal_counter(); 21} 22 23static int __init tango_clocksource_init(struct device_node *np) 24{ 25 struct clk *clk; 26 int xtal_freq, ret; 27 28 xtal_in_cnt = of_iomap(np, 0); 29 if (xtal_in_cnt == NULL) { 30 pr_err("%pOF: invalid address\n", np); 31 return -ENXIO; 32 } 33 34 clk = of_clk_get(np, 0); 35 if (IS_ERR(clk)) { 36 pr_err("%pOF: invalid clock\n", np); 37 return PTR_ERR(clk); 38 } 39 40 xtal_freq = clk_get_rate(clk); 41 delay_timer.freq = xtal_freq; 42 delay_timer.read_current_timer = read_xtal_counter; 43 44 ret = clocksource_mmio_init(xtal_in_cnt, "tango-xtal", xtal_freq, 350, 45 32, clocksource_mmio_readl_up); 46 if (ret) { 47 pr_err("%pOF: registration failed\n", np); 48 return ret; 49 } 50 51 sched_clock_register(read_sched_clock, 32, xtal_freq); 52 register_current_timer_delay(&delay_timer); 53 54 return 0; 55} 56 57TIMER_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init); 58