cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

timer-rockchip.c (6947B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Rockchip timer support
      4 *
      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	0x00
     20#define TIMER_LOAD_COUNT1	0x04
     21#define TIMER_CURRENT_VALUE0	0x08
     22#define TIMER_CURRENT_VALUE1	0x0C
     23#define TIMER_CONTROL_REG3288	0x10
     24#define TIMER_CONTROL_REG3399	0x1c
     25#define TIMER_INT_STATUS	0x18
     26
     27#define TIMER_DISABLE		0x0
     28#define TIMER_ENABLE		0x1
     29#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 __init
    128rk_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);