Author: blogic
Date: 2015-10-05 12:27:09 +0200 (Mon, 05 Oct 2015)
New Revision: 47122

Modified:
   trunk/target/linux/ramips/patches-3.18/0066-cevt.patch
Log:
ramips: improve systick timer

when sleep mode is disable use MIPS as clocksource and clockevent instead of 
systick.
because MIPS timer has higher resolution 5ns less than systick 20us and
larger counter bits 32 > 16.
clean interrupt by write compare register at isr.
fix typo cause sleep mode not enable.

Signed-off-by: Michael Lee <[email protected]>

Modified: trunk/target/linux/ramips/patches-3.18/0066-cevt.patch
===================================================================
--- trunk/target/linux/ramips/patches-3.18/0066-cevt.patch      2015-10-05 
10:27:04 UTC (rev 47121)
+++ trunk/target/linux/ramips/patches-3.18/0066-cevt.patch      2015-10-05 
10:27:09 UTC (rev 47122)
@@ -1,12 +1,151 @@
 --- a/arch/mips/ralink/cevt-rt3352.c
 +++ b/arch/mips/ralink/cevt-rt3352.c
-@@ -53,8 +53,7 @@ static int systick_next_event(unsigned l
- 
+@@ -45,18 +45,33 @@ static void (*systick_freq_scaling)(stru
+ static void systick_set_clock_mode(enum clock_event_mode mode,
+                               struct clock_event_device *evt);
+
++static inline unsigned int read_count(struct systick_device *sdev)
++{
++      return ioread32(sdev->membase + SYSTICK_COUNT);
++}
++
++static inline unsigned int read_compare(struct systick_device *sdev)
++{
++      return ioread32(sdev->membase + SYSTICK_COMPARE);
++}
++
++static inline void write_compare(struct systick_device *sdev, unsigned int 
val)
++{
++      iowrite32(val, sdev->membase + SYSTICK_COMPARE);
++}
++
+ static int systick_next_event(unsigned long delta,
+                               struct clock_event_device *evt)
+ {
+       struct systick_device *sdev;
+-      u32 count;
++      int res;
+
        sdev = container_of(evt, struct systick_device, dev);
-       count = ioread32(sdev->membase + SYSTICK_COUNT);
+-      count = ioread32(sdev->membase + SYSTICK_COUNT);
 -      count = (count + delta) % SYSTICK_FREQ;
 -      iowrite32(count, sdev->membase + SYSTICK_COMPARE);
-+      iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE);
- 
-       return 0;
++      delta += read_count(sdev);
++      write_compare(sdev, delta);
++      res = ((int)(read_count(sdev) - delta) >= 0) ? -ETIME : 0;
+
+-      return 0;
++      return res;
  }
+
+ static void systick_event_handler(struct clock_event_device *dev)
+@@ -66,20 +81,25 @@ static void systick_event_handler(struct
+
+ static irqreturn_t systick_interrupt(int irq, void *dev_id)
+ {
+-      struct clock_event_device *dev = (struct clock_event_device *) dev_id;
++      int ret = 0;
++      struct clock_event_device *cdev;
++      struct systick_device *sdev;
+
+-      dev->event_handler(dev);
++      if (read_c0_cause() & STATUSF_IP7) {
++              cdev = (struct clock_event_device *) dev_id;
++              sdev = container_of(cdev, struct systick_device, dev);
++
++              /* Clear Count/Compare Interrupt */
++              write_compare(sdev, read_compare(sdev));
++              cdev->event_handler(cdev);
++              ret = 1;
++      }
+
+-      return IRQ_HANDLED;
++      return IRQ_RETVAL(ret);
+ }
+
+ static struct systick_device systick = {
+       .dev = {
+-              /*
+-               * cevt-r4k uses 300, make sure systick
+-               * gets used if available
+-               */
+-              .rating         = 310,
+               .features       = CLOCK_EVT_FEAT_ONESHOT,
+               .set_next_event = systick_next_event,
+               .set_mode       = systick_set_clock_mode,
+@@ -126,13 +146,14 @@ static void systick_set_clock_mode(enum
+                       systick_freq_scaling(sdev, 1);
+               break;
+
++      case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               if (systick_freq_scaling)
+                       systick_freq_scaling(sdev, 0);
+               if (sdev->irq_requested)
+-                      free_irq(systick.dev.irq, &systick_irqaction);
++                      remove_irq(systick.dev.irq, &systick_irqaction);
+               sdev->irq_requested = 0;
+-              iowrite32(0, systick.membase + SYSTICK_CONFIG);
++              iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG);
+               break;
+
+       default:
+@@ -142,38 +163,45 @@ static void systick_set_clock_mode(enum
+ }
+
+ static const struct of_device_id systick_match[] = {
+-      { .compatible = "ralink,mt7620-systick", .data = mt7620_freq_scaling},
++      { .compatible = "ralink,mt7620a-systick", .data = mt7620_freq_scaling},
+       {},
+ };
+
+ static void __init ralink_systick_init(struct device_node *np)
+ {
+       const struct of_device_id *match;
++      int rating = 200;
+
+       systick.membase = of_iomap(np, 0);
+       if (!systick.membase)
+               return;
+
+       match = of_match_node(systick_match, np);
+-      if (match)
++      if (match) {
+               systick_freq_scaling = match->data;
++              /*
++               * cevt-r4k uses 300, make sure systick
++               * gets used if available
++               */
++              rating = 310;
++      }
+
+-      systick_irqaction.name = np->name;
+-      systick.dev.name = np->name;
+-      clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
+-      systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
+-      systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
++      /* enable counter than register clock source */
++      iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG);
++      clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
++                      SYSTICK_FREQ, rating, 16, clocksource_mmio_readl_up);
++
++      /* register clock event */
+       systick.dev.irq = irq_of_parse_and_map(np, 0);
+       if (!systick.dev.irq) {
+               pr_err("%s: request_irq failed", np->name);
+               return;
+       }
+-
+-      clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
+-                      SYSTICK_FREQ, 301, 16, clocksource_mmio_readl_up);
+-
+-      clockevents_register_device(&systick.dev);
+-
++      systick_irqaction.name = np->name;
++      systick.dev.name = np->name;
++      systick.dev.rating = rating;
++      systick.dev.cpumask = cpumask_of(0);
++      clockevents_config_and_register(&systick.dev, SYSTICK_FREQ, 0x3, 
0x7fff);
+       pr_info("%s: running - mult: %d, shift: %d\n",
+                       np->name, systick.dev.mult, systick.dev.shift);
+ }
_______________________________________________
openwrt-commits mailing list
[email protected]
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-commits

Reply via email to