18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/clocksource.h> 38c2ecf20Sopenharmony_ci#include <linux/sched_clock.h> 48c2ecf20Sopenharmony_ci#include <linux/of_address.h> 58c2ecf20Sopenharmony_ci#include <linux/printk.h> 68c2ecf20Sopenharmony_ci#include <linux/delay.h> 78c2ecf20Sopenharmony_ci#include <linux/init.h> 88c2ecf20Sopenharmony_ci#include <linux/clk.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_cistatic void __iomem *xtal_in_cnt; 118c2ecf20Sopenharmony_cistatic struct delay_timer delay_timer; 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistatic unsigned long notrace read_xtal_counter(void) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci return readl_relaxed(xtal_in_cnt); 168c2ecf20Sopenharmony_ci} 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic u64 notrace read_sched_clock(void) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci return read_xtal_counter(); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic int __init tango_clocksource_init(struct device_node *np) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci struct clk *clk; 268c2ecf20Sopenharmony_ci int xtal_freq, ret; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci xtal_in_cnt = of_iomap(np, 0); 298c2ecf20Sopenharmony_ci if (xtal_in_cnt == NULL) { 308c2ecf20Sopenharmony_ci pr_err("%pOF: invalid address\n", np); 318c2ecf20Sopenharmony_ci return -ENXIO; 328c2ecf20Sopenharmony_ci } 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci clk = of_clk_get(np, 0); 358c2ecf20Sopenharmony_ci if (IS_ERR(clk)) { 368c2ecf20Sopenharmony_ci pr_err("%pOF: invalid clock\n", np); 378c2ecf20Sopenharmony_ci return PTR_ERR(clk); 388c2ecf20Sopenharmony_ci } 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci xtal_freq = clk_get_rate(clk); 418c2ecf20Sopenharmony_ci delay_timer.freq = xtal_freq; 428c2ecf20Sopenharmony_ci delay_timer.read_current_timer = read_xtal_counter; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci ret = clocksource_mmio_init(xtal_in_cnt, "tango-xtal", xtal_freq, 350, 458c2ecf20Sopenharmony_ci 32, clocksource_mmio_readl_up); 468c2ecf20Sopenharmony_ci if (ret) { 478c2ecf20Sopenharmony_ci pr_err("%pOF: registration failed\n", np); 488c2ecf20Sopenharmony_ci return ret; 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci sched_clock_register(read_sched_clock, 32, xtal_freq); 528c2ecf20Sopenharmony_ci register_current_timer_delay(&delay_timer); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci return 0; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciTIMER_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init); 58