Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of https://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / arch / microblaze / kernel / timer.c
index fb0c614..c897745 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/clockchips.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/timecounter.h>
 #include <asm/cpuinfo.h>
 
 static void __iomem *timer_baseaddr;
@@ -43,10 +44,33 @@ static unsigned int timer_clock_freq;
 #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 +78,10 @@ static inline void xilinx_timer0_start_periodic(unsigned long load_val)
        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 +96,8 @@ static inline void xilinx_timer0_start_periodic(unsigned long load_val)
         * 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 +105,13 @@ static inline void xilinx_timer0_start_oneshot(unsigned long load_val)
        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,14 +157,14 @@ static struct clock_event_device clockevent_xilinx_timer = {
 
 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)
 {
        struct clock_event_device *evt = &clockevent_xilinx_timer;
 #ifdef CONFIG_HEART_BEAT
-       heartbeat();
+       microblaze_heartbeat();
 #endif
        timer_ack();
        evt->event_handler(evt);
@@ -169,7 +193,7 @@ static __init void xilinx_clockevent_init(void)
 
 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 +241,10 @@ static int __init xilinx_clocksource_init(void)
                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 +269,15 @@ static void __init xilinx_timer_init(struct device_node *timer)
                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);
@@ -274,7 +307,7 @@ static void __init xilinx_timer_init(struct device_node *timer)
 
        setup_irq(irq, &timer_irqaction);
 #ifdef CONFIG_HEART_BEAT
-       setup_heartbeat();
+       microblaze_setup_heartbeat();
 #endif
        xilinx_clocksource_init();
        xilinx_clockevent_init();