--- a/arch/arm/mach-gemini/time.c	2015-03-25 23:06:03.188317455 +0200
+++ b/arch/arm/mach-gemini/time.c	2015-03-25 23:06:24.417315486 +0200
@@ -15,15 +15,18 @@
 #include <asm/mach/time.h>
 #include <linux/clockchips.h>
 #include <linux/clocksource.h>
+#include <linux/sched_clock.h>
 
 /*
  * Register definitions for the timers
  */
-#define TIMER_COUNT(BASE_ADDR)		(BASE_ADDR  + 0x00)
-#define TIMER_LOAD(BASE_ADDR)		(BASE_ADDR  + 0x04)
-#define TIMER_MATCH1(BASE_ADDR)		(BASE_ADDR  + 0x08)
-#define TIMER_MATCH2(BASE_ADDR)		(BASE_ADDR  + 0x0C)
-#define TIMER_CR(BASE_ADDR)		(BASE_ADDR  + 0x30)
+#define TIMER_COUNT(BASE_ADDR)		(IO_ADDRESS(BASE_ADDR) + 0x00)
+#define TIMER_LOAD(BASE_ADDR)		(IO_ADDRESS(BASE_ADDR) + 0x04)
+#define TIMER_MATCH1(BASE_ADDR)		(IO_ADDRESS(BASE_ADDR) + 0x08)
+#define TIMER_MATCH2(BASE_ADDR)		(IO_ADDRESS(BASE_ADDR) + 0x0C)
+#define TIMER_CR(BASE_ADDR)		(IO_ADDRESS(BASE_ADDR) + 0x30)
+#define TIMER_INTR_STATE(BASE_ADDR)	(IO_ADDRESS(BASE_ADDR) + 0x34)
+#define TIMER_INTR_MASK(BASE_ADDR)	(IO_ADDRESS(BASE_ADDR) + 0x38)
 
 #define TIMER_1_CR_ENABLE		(1 << 0)
 #define TIMER_1_CR_CLOCK		(1 << 1)
@@ -34,27 +37,38 @@
 #define TIMER_3_CR_ENABLE		(1 << 6)
 #define TIMER_3_CR_CLOCK		(1 << 7)
 #define TIMER_3_CR_INT			(1 << 8)
+#define TIMER_1_CR_UPDOWN		(1 << 9)
+#define TIMER_2_CR_UPDOWN		(1 << 10)
+#define TIMER_3_CR_UPDOWN		(1 << 11)
+
+#define TIMER_1_INT_MATCH1		(1 << 0)
+#define TIMER_1_INT_MATCH2		(1 << 1)
+#define TIMER_1_INT_OVERFLOW		(1 << 2)
+#define TIMER_2_INT_MATCH1		(1 << 3)
+#define TIMER_2_INT_MATCH2		(1 << 4)
+#define TIMER_2_INT_OVERFLOW		(1 << 5)
+#define TIMER_3_INT_MATCH1		(1 << 6)
+#define TIMER_3_INT_MATCH2		(1 << 7)
+#define TIMER_3_INT_OVERFLOW		(1 << 8)
+#define TIMER_INT_ALL_MASK		0x1ff
 
 static unsigned int tick_rate;
 
+static u64 notrace gemini_read_sched_clock(void)
+{
+	return readl(TIMER_COUNT(GEMINI_TIMER3_BASE));
+}
+
 static int gemini_timer_set_next_event(unsigned long cycles,
 				       struct clock_event_device *evt)
 {
 	u32 cr;
 
-	cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
-
-	/* This may be overdoing it, feel free to test without this */
-	cr &= ~TIMER_2_CR_ENABLE;
-	cr &= ~TIMER_2_CR_INT;
-	writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
-
-	/* Set next event */
-	writel(cycles, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
-	writel(cycles, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
-	cr |= TIMER_2_CR_ENABLE;
-	cr |= TIMER_2_CR_INT;
-	writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+	/* Setup the match register */
+	cr = readl(TIMER_COUNT(GEMINI_TIMER1_BASE));
+	writel(cr + cycles, TIMER_MATCH1(GEMINI_TIMER1_BASE));
+	if (readl(TIMER_COUNT(GEMINI_TIMER1_BASE)) - cr > cycles)
+		return -ETIME;
 
 	return 0;
 }
@@ -66,48 +80,68 @@
 	u32 cr;
 
 	switch (mode) {
-        case CLOCK_EVT_MODE_PERIODIC:
-		/* Start the timer */
-		writel(period,
-		       TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
-		writel(period,
-		       TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
-		cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
-		cr |= TIMER_2_CR_ENABLE;
-		cr |= TIMER_2_CR_INT;
-		writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+	case CLOCK_EVT_MODE_PERIODIC:
+		/* Stop timer and interrupt. */
+		cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
+		cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
+		writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
+
+		/* Setup timer to fire at 1/HZ intervals. */
+		cr = 0xffffffff - (period - 1);
+		writel(cr, TIMER_COUNT(GEMINI_TIMER1_BASE));
+		writel(cr, TIMER_LOAD(GEMINI_TIMER1_BASE));
+
+		/* enable interrupt on overflaw */
+		cr = readl(TIMER_INTR_MASK(GEMINI_TIMER_BASE));
+		cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
+		cr |= TIMER_1_INT_OVERFLOW;
+		writel(cr, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
+
+		/* start the timer */
+		cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
+		cr |= TIMER_1_CR_ENABLE | TIMER_1_CR_INT;
+		writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
 		break;
+
 	case CLOCK_EVT_MODE_ONESHOT:
 	case CLOCK_EVT_MODE_UNUSED:
-        case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		/* Stop timer and interrupt. */
+		cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
+		cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
+		writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
+
+		/* Setup counter start from 0 */
+		writel(0, TIMER_COUNT(GEMINI_TIMER1_BASE));
+		writel(0, TIMER_LOAD(GEMINI_TIMER1_BASE));
+
+		/* enable interrupt */
+		cr = readl(TIMER_INTR_MASK(GEMINI_TIMER_BASE));
+		cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
+		cr |= TIMER_1_INT_MATCH1;
+		writel(cr, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
+
+		/* start the timer */
+		cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
+		cr |= TIMER_1_CR_ENABLE;
+		writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
+		break;
+
 	case CLOCK_EVT_MODE_RESUME:
-		/*
-		 * Disable also for oneshot: the set_next() call will
-		 * arm the timer instead.
-		 */
-		cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
-		cr &= ~TIMER_2_CR_ENABLE;
-		cr &= ~TIMER_2_CR_INT;
-		writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
 		break;
-	default:
-                break;
 	}
 }
 
-/* Use TIMER2 as clock event */
 static struct clock_event_device gemini_clockevent = {
-	.name		= "TIMER2",
-	.rating		= 300, /* Reasonably fast and accurate clock event */
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_next_event	= gemini_timer_set_next_event,
-	.set_mode	= gemini_timer_set_mode,
+	.name           = "gemini_timer_1",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.shift          = 32,
+	.rating         = 300,
+	.set_next_event = gemini_timer_set_next_event,
+	.set_mode       = gemini_timer_set_mode,
 };
 
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id)
+static irqreturn_t gemini_timer_intr(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = &gemini_clockevent;
 
@@ -116,14 +150,11 @@
 }
 
 static struct irqaction gemini_timer_irq = {
-	.name		= "Gemini Timer Tick",
-	.flags		= IRQF_TIMER,
-	.handler	= gemini_timer_interrupt,
+	.name		= "gemini timer 1",
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
+	.handler	= gemini_timer_intr,
 };
 
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
 void __init gemini_timer_init(void)
 {
 	u32 reg_v;
@@ -151,20 +182,35 @@
 	}
 
 	/*
-	 * Make irqs happen for the system timer
+	 * Reset the interrupt mask and status
 	 */
-	setup_irq(IRQ_TIMER2, &gemini_timer_irq);
+	writel(TIMER_INT_ALL_MASK, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
+	writel(0, TIMER_INTR_STATE(GEMINI_TIMER_BASE));
+	writel(TIMER_1_CR_UPDOWN | TIMER_3_CR_ENABLE | TIMER_3_CR_UPDOWN,
+		TIMER_CR(GEMINI_TIMER_BASE));
 
-	/* Enable and use TIMER1 as clock source */
-	writel(0xffffffff, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)));
-	writel(0xffffffff, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER1_BASE)));
-	writel(TIMER_1_CR_ENABLE, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
-	if (clocksource_mmio_init(TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)),
-				  "TIMER1", tick_rate, 300, 32,
-				  clocksource_mmio_readl_up))
-		pr_err("timer: failed to initialize gemini clock source\n");
+	/*
+	 * Setup free-running clocksource timer (interrupts
+	 * disabled.)
+	 */
+	writel(0, TIMER_COUNT(GEMINI_TIMER3_BASE));
+	writel(0, TIMER_LOAD(GEMINI_TIMER3_BASE));
+	writel(0, TIMER_MATCH1(GEMINI_TIMER3_BASE));
+	writel(0, TIMER_MATCH2(GEMINI_TIMER3_BASE));
+	clocksource_mmio_init(TIMER_COUNT(GEMINI_TIMER3_BASE),
+			"gemini_clocksource", tick_rate,
+			300, 32, clocksource_mmio_readl_up);
+	sched_clock_register(gemini_read_sched_clock, 32, tick_rate);
 
-	/* Configure and register the clockevent */
+	/*
+	 * Setup clockevent timer (interrupt-driven.)
+	 */
+	writel(0, TIMER_COUNT(GEMINI_TIMER1_BASE));
+	writel(0, TIMER_LOAD(GEMINI_TIMER1_BASE));
+	writel(0, TIMER_MATCH1(GEMINI_TIMER1_BASE));
+	writel(0, TIMER_MATCH2(GEMINI_TIMER1_BASE));
+	setup_irq(IRQ_TIMER1, &gemini_timer_irq);
+	gemini_clockevent.cpumask = cpumask_of(0);
 	clockevents_config_and_register(&gemini_clockevent, tick_rate,
 					1, 0xffffffff);
 }
