@@ -17,6 +17,7 @@
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
/*
* Register definitions for the timers
@@ -81,9 +82,15 @@ struct fttmr010 {
bool count_down;
u32 t1_enable_val;
struct clock_event_device clkevt;
+#ifdef CONFIG_ARM
+ struct delay_timer delay_timer;
+#endif
};
-/* A local singleton used by sched_clock, which is stateless */
+/*
+ * A local singleton used by sched_clock and delay timer reads, which are
+ * fast and stateless
+ */
static struct fttmr010 *local_fttmr;
static inline struct fttmr010 *to_fttmr010(struct clock_event_device *evt)
@@ -101,6 +108,20 @@ static u64 notrace fttmr010_read_sched_clock_down(void)
return ~readl(local_fttmr->base + TIMER2_COUNT);
}
+#ifdef CONFIG_ARM
+
+static unsigned long fttmr010_read_current_timer_up(void)
+{
+ return readl(local_fttmr->base + TIMER2_COUNT);
+}
+
+static unsigned long fttmr010_read_current_timer_down(void)
+{
+ return ~readl(local_fttmr->base + TIMER2_COUNT);
+}
+
+#endif
+
static int fttmr010_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
@@ -347,6 +368,18 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed)
fttmr010->tick_rate,
1, 0xffffffff);
+#ifdef CONFIG_ARM
+ /* Also use this timer for delays */
+ if (fttmr010->count_down)
+ fttmr010->delay_timer.read_current_timer =
+ fttmr010_read_current_timer_down;
+ else
+ fttmr010->delay_timer.read_current_timer =
+ fttmr010_read_current_timer_up;
+ fttmr010->delay_timer.freq = fttmr010->tick_rate;
+ register_current_timer_delay(&fttmr010->delay_timer);
+#endif
+
return 0;
out_unmap: