firmware/br-ext-chip-allwinner/board/v83x/kernel/patches/00000-drivers_clocksource_s...

79 lines
2.3 KiB
Diff

diff -drupN a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c
--- a/drivers/clocksource/sun4i_timer.c 2018-08-06 17:23:04.000000000 +0300
+++ b/drivers/clocksource/sun4i_timer.c 2022-06-12 05:28:14.000000000 +0300
@@ -23,6 +23,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/slab.h>
#define TIMER_IRQ_EN_REG 0x00
#define TIMER_IRQ_EN(val) BIT(val)
@@ -40,6 +41,8 @@
#define TIMER_SYNC_TICKS 3
static void __iomem *timer_base;
+static int timer_size;
+static void *store_mem;
static u32 ticks_per_jiffy;
/*
@@ -83,6 +86,17 @@ static void sun4i_clkevt_time_start(u8 t
static int sun4i_clkevt_shutdown(struct clock_event_device *evt)
{
+ /*we should store the registers for soc timer first*/
+ memcpy(store_mem, (void *)timer_base, timer_size);
+
+ sun4i_clkevt_time_stop(0);
+ return 0;
+}
+
+static int sun4i_tick_resume(struct clock_event_device *evt)
+{
+ /*we should restore the registers for soc time fist*/
+ memcpy((void *)timer_base, (void *)store_mem, timer_size);
sun4i_clkevt_time_stop(0);
return 0;
}
@@ -115,11 +129,13 @@ static int sun4i_clkevt_next_event(unsig
static struct clock_event_device sun4i_clockevent = {
.name = "sun4i_tick",
.rating = 350,
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_DYNIRQ,
.set_state_shutdown = sun4i_clkevt_shutdown,
.set_state_periodic = sun4i_clkevt_set_periodic,
.set_state_oneshot = sun4i_clkevt_set_oneshot,
- .tick_resume = sun4i_clkevt_shutdown,
+ .tick_resume = sun4i_tick_resume,
.set_next_event = sun4i_clkevt_next_event,
};
@@ -153,6 +169,7 @@ static u64 notrace sun4i_timer_sched_rea
static int __init sun4i_timer_init(struct device_node *node)
{
unsigned long rate = 0;
+ struct resource res;
struct clk *clk;
int ret, irq;
u32 val;
@@ -163,6 +180,15 @@ static int __init sun4i_timer_init(struc
return -ENXIO;
}
+ if (of_address_to_resource(node, 0, &res))
+ return -EINVAL;
+
+ timer_size = resource_size(&res);
+
+ store_mem = (void *)kmalloc(timer_size, GFP_KERNEL);
+ if (store_mem == NULL)
+ return -ENOMEM;
+
irq = irq_of_parse_and_map(node, 0);
if (irq <= 0) {
pr_crit("Can't parse IRQ");