microblaze: Make timer driver endian aware

Detect endianess directly on the hardware and use
ioread/iowrite functions.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index 717a3d9..dd96f0e 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -43,10 +43,33 @@
 #define TCSR_PWMA	(1<<9)
 #define TCSR_ENALL	(1<<10)
 
+static unsigned int (*read_fn)(void __iomem *);
+static void (*write_fn)(u32, void __iomem *);
+
+static void timer_write32(u32 val, void __iomem *addr)
+{
+	iowrite32(val, addr);
+}
+
+static unsigned int timer_read32(void __iomem *addr)
+{
+	return ioread32(addr);
+}
+
+static void timer_write32_be(u32 val, void __iomem *addr)
+{
+	iowrite32be(val, addr);
+}
+
+static unsigned int timer_read32_be(void __iomem *addr)
+{
+	return ioread32be(addr);
+}
+
 static inline void xilinx_timer0_stop(void)
 {
-	out_be32(timer_baseaddr + TCSR0,
-		 in_be32(timer_baseaddr + TCSR0) & ~TCSR_ENT);
+	write_fn(read_fn(timer_baseaddr + TCSR0) & ~TCSR_ENT,
+		 timer_baseaddr + TCSR0);
 }
 
 static inline void xilinx_timer0_start_periodic(unsigned long load_val)
@@ -54,10 +77,10 @@
 	if (!load_val)
 		load_val = 1;
 	/* loading value to timer reg */
-	out_be32(timer_baseaddr + TLR0, load_val);
+	write_fn(load_val, timer_baseaddr + TLR0);
 
 	/* load the initial value */
-	out_be32(timer_baseaddr + TCSR0, TCSR_LOAD);
+	write_fn(TCSR_LOAD, timer_baseaddr + TCSR0);
 
 	/* see timer data sheet for detail
 	 * !ENALL - don't enable 'em all
@@ -72,8 +95,8 @@
 	 * UDT - set the timer as down counter
 	 * !MDT0 - generate mode
 	 */
-	out_be32(timer_baseaddr + TCSR0,
-			TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
+	write_fn(TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT,
+		 timer_baseaddr + TCSR0);
 }
 
 static inline void xilinx_timer0_start_oneshot(unsigned long load_val)
@@ -81,13 +104,13 @@
 	if (!load_val)
 		load_val = 1;
 	/* loading value to timer reg */
-	out_be32(timer_baseaddr + TLR0, load_val);
+	write_fn(load_val, timer_baseaddr + TLR0);
 
 	/* load the initial value */
-	out_be32(timer_baseaddr + TCSR0, TCSR_LOAD);
+	write_fn(TCSR_LOAD, timer_baseaddr + TCSR0);
 
-	out_be32(timer_baseaddr + TCSR0,
-			TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
+	write_fn(TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT,
+		 timer_baseaddr + TCSR0);
 }
 
 static int xilinx_timer_set_next_event(unsigned long delta,
@@ -133,7 +156,7 @@
 
 static inline void timer_ack(void)
 {
-	out_be32(timer_baseaddr + TCSR0, in_be32(timer_baseaddr + TCSR0));
+	write_fn(read_fn(timer_baseaddr + TCSR0), timer_baseaddr + TCSR0);
 }
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
@@ -169,7 +192,7 @@
 
 static u64 xilinx_clock_read(void)
 {
-	return in_be32(timer_baseaddr + TCR1);
+	return read_fn(timer_baseaddr + TCR1);
 }
 
 static cycle_t xilinx_read(struct clocksource *cs)
@@ -217,10 +240,10 @@
 		panic("failed to register clocksource");
 
 	/* stop timer1 */
-	out_be32(timer_baseaddr + TCSR1,
-		 in_be32(timer_baseaddr + TCSR1) & ~TCSR_ENT);
+	write_fn(read_fn(timer_baseaddr + TCSR1) & ~TCSR_ENT,
+		 timer_baseaddr + TCSR1);
 	/* start timer1 - up counting without interrupt */
-	out_be32(timer_baseaddr + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT);
+	write_fn(TCSR_TINT|TCSR_ENT|TCSR_ARHT, timer_baseaddr + TCSR1);
 
 	/* register timecounter - for ftrace support */
 	init_xilinx_timecounter();
@@ -245,6 +268,15 @@
 		BUG();
 	}
 
+	write_fn = timer_write32;
+	read_fn = timer_read32;
+
+	write_fn(TCSR_MDT, timer_baseaddr + TCSR0);
+	if (!(read_fn(timer_baseaddr + TCSR0) & TCSR_MDT)) {
+		write_fn = timer_write32_be;
+		read_fn = timer_read32_be;
+	}
+
 	irq = irq_of_parse_and_map(timer, 0);
 
 	of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num);