brintos

brintos / linux-shallow public Read only

0
0
Text · 6.8 KiB · 1f95d0a Raw
305 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Rockchip timer support4 *5 * Copyright (C) Daniel Lezcano <daniel.lezcano@linaro.org>6 */7#include <linux/clk.h>8#include <linux/clockchips.h>9#include <linux/init.h>10#include <linux/interrupt.h>11#include <linux/sched_clock.h>12#include <linux/slab.h>13#include <linux/of.h>14#include <linux/of_address.h>15#include <linux/of_irq.h>16 17#define TIMER_NAME "rk_timer"18 19#define TIMER_LOAD_COUNT0	0x0020#define TIMER_LOAD_COUNT1	0x0421#define TIMER_CURRENT_VALUE0	0x0822#define TIMER_CURRENT_VALUE1	0x0C23#define TIMER_CONTROL_REG3288	0x1024#define TIMER_CONTROL_REG3399	0x1c25#define TIMER_INT_STATUS	0x1826 27#define TIMER_DISABLE		0x028#define TIMER_ENABLE		0x129#define TIMER_MODE_FREE_RUNNING			(0 << 1)30#define TIMER_MODE_USER_DEFINED_COUNT		(1 << 1)31#define TIMER_INT_UNMASK			(1 << 2)32 33struct rk_timer {34	void __iomem *base;35	void __iomem *ctrl;36	struct clk *clk;37	struct clk *pclk;38	u32 freq;39	int irq;40};41 42struct rk_clkevt {43	struct clock_event_device ce;44	struct rk_timer timer;45};46 47static struct rk_clkevt *rk_clkevt;48static struct rk_timer *rk_clksrc;49 50static inline struct rk_timer *rk_timer(struct clock_event_device *ce)51{52	return &container_of(ce, struct rk_clkevt, ce)->timer;53}54 55static inline void rk_timer_disable(struct rk_timer *timer)56{57	writel_relaxed(TIMER_DISABLE, timer->ctrl);58}59 60static inline void rk_timer_enable(struct rk_timer *timer, u32 flags)61{62	writel_relaxed(TIMER_ENABLE | flags, timer->ctrl);63}64 65static void rk_timer_update_counter(unsigned long cycles,66				    struct rk_timer *timer)67{68	writel_relaxed(cycles, timer->base + TIMER_LOAD_COUNT0);69	writel_relaxed(0, timer->base + TIMER_LOAD_COUNT1);70}71 72static void rk_timer_interrupt_clear(struct rk_timer *timer)73{74	writel_relaxed(1, timer->base + TIMER_INT_STATUS);75}76 77static inline int rk_timer_set_next_event(unsigned long cycles,78					  struct clock_event_device *ce)79{80	struct rk_timer *timer = rk_timer(ce);81 82	rk_timer_disable(timer);83	rk_timer_update_counter(cycles, timer);84	rk_timer_enable(timer, TIMER_MODE_USER_DEFINED_COUNT |85			       TIMER_INT_UNMASK);86	return 0;87}88 89static int rk_timer_shutdown(struct clock_event_device *ce)90{91	struct rk_timer *timer = rk_timer(ce);92 93	rk_timer_disable(timer);94	return 0;95}96 97static int rk_timer_set_periodic(struct clock_event_device *ce)98{99	struct rk_timer *timer = rk_timer(ce);100 101	rk_timer_disable(timer);102	rk_timer_update_counter(timer->freq / HZ - 1, timer);103	rk_timer_enable(timer, TIMER_MODE_FREE_RUNNING | TIMER_INT_UNMASK);104	return 0;105}106 107static irqreturn_t rk_timer_interrupt(int irq, void *dev_id)108{109	struct clock_event_device *ce = dev_id;110	struct rk_timer *timer = rk_timer(ce);111 112	rk_timer_interrupt_clear(timer);113 114	if (clockevent_state_oneshot(ce))115		rk_timer_disable(timer);116 117	ce->event_handler(ce);118 119	return IRQ_HANDLED;120}121 122static u64 notrace rk_timer_sched_read(void)123{124	return ~readl_relaxed(rk_clksrc->base + TIMER_CURRENT_VALUE0);125}126 127static int __init128rk_timer_probe(struct rk_timer *timer, struct device_node *np)129{130	struct clk *timer_clk;131	struct clk *pclk;132	int ret = -EINVAL, irq;133	u32 ctrl_reg = TIMER_CONTROL_REG3288;134 135	timer->base = of_iomap(np, 0);136	if (!timer->base) {137		pr_err("Failed to get base address for '%s'\n", TIMER_NAME);138		return -ENXIO;139	}140 141	if (of_device_is_compatible(np, "rockchip,rk3399-timer"))142		ctrl_reg = TIMER_CONTROL_REG3399;143 144	timer->ctrl = timer->base + ctrl_reg;145 146	pclk = of_clk_get_by_name(np, "pclk");147	if (IS_ERR(pclk)) {148		ret = PTR_ERR(pclk);149		pr_err("Failed to get pclk for '%s'\n", TIMER_NAME);150		goto out_unmap;151	}152 153	ret = clk_prepare_enable(pclk);154	if (ret) {155		pr_err("Failed to enable pclk for '%s'\n", TIMER_NAME);156		goto out_unmap;157	}158	timer->pclk = pclk;159 160	timer_clk = of_clk_get_by_name(np, "timer");161	if (IS_ERR(timer_clk)) {162		ret = PTR_ERR(timer_clk);163		pr_err("Failed to get timer clock for '%s'\n", TIMER_NAME);164		goto out_timer_clk;165	}166 167	ret = clk_prepare_enable(timer_clk);168	if (ret) {169		pr_err("Failed to enable timer clock\n");170		goto out_timer_clk;171	}172	timer->clk = timer_clk;173 174	timer->freq = clk_get_rate(timer_clk);175 176	irq = irq_of_parse_and_map(np, 0);177	if (!irq) {178		ret = -EINVAL;179		pr_err("Failed to map interrupts for '%s'\n", TIMER_NAME);180		goto out_irq;181	}182	timer->irq = irq;183 184	rk_timer_interrupt_clear(timer);185	rk_timer_disable(timer);186	return 0;187 188out_irq:189	clk_disable_unprepare(timer_clk);190out_timer_clk:191	clk_disable_unprepare(pclk);192out_unmap:193	iounmap(timer->base);194 195	return ret;196}197 198static void __init rk_timer_cleanup(struct rk_timer *timer)199{200	clk_disable_unprepare(timer->clk);201	clk_disable_unprepare(timer->pclk);202	iounmap(timer->base);203}204 205static int __init rk_clkevt_init(struct device_node *np)206{207	struct clock_event_device *ce;208	int ret = -EINVAL;209 210	rk_clkevt = kzalloc(sizeof(struct rk_clkevt), GFP_KERNEL);211	if (!rk_clkevt) {212		ret = -ENOMEM;213		goto out;214	}215 216	ret = rk_timer_probe(&rk_clkevt->timer, np);217	if (ret)218		goto out_probe;219 220	ce = &rk_clkevt->ce;221	ce->name = TIMER_NAME;222	ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |223		       CLOCK_EVT_FEAT_DYNIRQ;224	ce->set_next_event = rk_timer_set_next_event;225	ce->set_state_shutdown = rk_timer_shutdown;226	ce->set_state_periodic = rk_timer_set_periodic;227	ce->irq = rk_clkevt->timer.irq;228	ce->cpumask = cpu_possible_mask;229	ce->rating = 250;230 231	ret = request_irq(rk_clkevt->timer.irq, rk_timer_interrupt, IRQF_TIMER,232			  TIMER_NAME, ce);233	if (ret) {234		pr_err("Failed to initialize '%s': %d\n",235			TIMER_NAME, ret);236		goto out_irq;237	}238 239	clockevents_config_and_register(&rk_clkevt->ce,240					rk_clkevt->timer.freq, 1, UINT_MAX);241	return 0;242 243out_irq:244	rk_timer_cleanup(&rk_clkevt->timer);245out_probe:246	kfree(rk_clkevt);247out:248	/* Leave rk_clkevt not NULL to prevent future init */249	rk_clkevt = ERR_PTR(ret);250	return ret;251}252 253static int __init rk_clksrc_init(struct device_node *np)254{255	int ret = -EINVAL;256 257	rk_clksrc = kzalloc(sizeof(struct rk_timer), GFP_KERNEL);258	if (!rk_clksrc) {259		ret = -ENOMEM;260		goto out;261	}262 263	ret = rk_timer_probe(rk_clksrc, np);264	if (ret)265		goto out_probe;266 267	rk_timer_update_counter(UINT_MAX, rk_clksrc);268	rk_timer_enable(rk_clksrc, 0);269 270	ret = clocksource_mmio_init(rk_clksrc->base + TIMER_CURRENT_VALUE0,271		TIMER_NAME, rk_clksrc->freq, 250, 32,272		clocksource_mmio_readl_down);273	if (ret) {274		pr_err("Failed to register clocksource\n");275		goto out_clocksource;276	}277 278	sched_clock_register(rk_timer_sched_read, 32, rk_clksrc->freq);279	return 0;280 281out_clocksource:282	rk_timer_cleanup(rk_clksrc);283out_probe:284	kfree(rk_clksrc);285out:286	/* Leave rk_clksrc not NULL to prevent future init */287	rk_clksrc = ERR_PTR(ret);288	return ret;289}290 291static int __init rk_timer_init(struct device_node *np)292{293	if (!rk_clkevt)294		return rk_clkevt_init(np);295 296	if (!rk_clksrc)297		return rk_clksrc_init(np);298 299	pr_err("Too many timer definitions for '%s'\n", TIMER_NAME);300	return -EINVAL;301}302 303TIMER_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init);304TIMER_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init);305