|
@@ -156,4 +156,54 @@ static int __init sprd_timer_init(struct device_node *np)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static struct timer_of suspend_to = {
|
|
|
+ .flags = TIMER_OF_BASE | TIMER_OF_CLOCK,
|
|
|
+};
|
|
|
+
|
|
|
+static u64 sprd_suspend_timer_read(struct clocksource *cs)
|
|
|
+{
|
|
|
+ return ~(u64)readl_relaxed(timer_of_base(&suspend_to) +
|
|
|
+ TIMER_VALUE_SHDW_LO) & cs->mask;
|
|
|
+}
|
|
|
+
|
|
|
+static int sprd_suspend_timer_enable(struct clocksource *cs)
|
|
|
+{
|
|
|
+ sprd_timer_update_counter(timer_of_base(&suspend_to),
|
|
|
+ TIMER_VALUE_LO_MASK);
|
|
|
+ sprd_timer_enable(timer_of_base(&suspend_to), TIMER_CTL_PERIOD_MODE);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void sprd_suspend_timer_disable(struct clocksource *cs)
|
|
|
+{
|
|
|
+ sprd_timer_disable(timer_of_base(&suspend_to));
|
|
|
+}
|
|
|
+
|
|
|
+static struct clocksource suspend_clocksource = {
|
|
|
+ .name = "sprd_suspend_timer",
|
|
|
+ .rating = 200,
|
|
|
+ .read = sprd_suspend_timer_read,
|
|
|
+ .enable = sprd_suspend_timer_enable,
|
|
|
+ .disable = sprd_suspend_timer_disable,
|
|
|
+ .mask = CLOCKSOURCE_MASK(32),
|
|
|
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
|
|
|
+};
|
|
|
+
|
|
|
+static int __init sprd_suspend_timer_init(struct device_node *np)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = timer_of_init(np, &suspend_to);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ clocksource_register_hz(&suspend_clocksource,
|
|
|
+ timer_of_rate(&suspend_to));
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
TIMER_OF_DECLARE(sc9860_timer, "sprd,sc9860-timer", sprd_timer_init);
|
|
|
+TIMER_OF_DECLARE(sc9860_persistent_timer, "sprd,sc9860-suspend-timer",
|
|
|
+ sprd_suspend_timer_init);
|