Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2013 by John Crispin <john@phrozen.org>
0007  */
0008 
0009 #include <linux/clockchips.h>
0010 #include <linux/clocksource.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/reset.h>
0013 #include <linux/init.h>
0014 #include <linux/time.h>
0015 #include <linux/of.h>
0016 #include <linux/of_irq.h>
0017 #include <linux/of_address.h>
0018 
0019 #include <asm/mach-ralink/ralink_regs.h>
0020 
0021 #define SYSTICK_FREQ        (50 * 1000)
0022 
0023 #define SYSTICK_CONFIG      0x00
0024 #define SYSTICK_COMPARE     0x04
0025 #define SYSTICK_COUNT       0x08
0026 
0027 /* route systick irq to mips irq 7 instead of the r4k-timer */
0028 #define CFG_EXT_STK_EN      0x2
0029 /* enable the counter */
0030 #define CFG_CNT_EN      0x1
0031 
0032 struct systick_device {
0033     void __iomem *membase;
0034     struct clock_event_device dev;
0035     int irq_requested;
0036     int freq_scale;
0037 };
0038 
0039 static int systick_set_oneshot(struct clock_event_device *evt);
0040 static int systick_shutdown(struct clock_event_device *evt);
0041 
0042 static int systick_next_event(unsigned long delta,
0043                 struct clock_event_device *evt)
0044 {
0045     struct systick_device *sdev;
0046     u32 count;
0047 
0048     sdev = container_of(evt, struct systick_device, dev);
0049     count = ioread32(sdev->membase + SYSTICK_COUNT);
0050     count = (count + delta) % SYSTICK_FREQ;
0051     iowrite32(count, sdev->membase + SYSTICK_COMPARE);
0052 
0053     return 0;
0054 }
0055 
0056 static void systick_event_handler(struct clock_event_device *dev)
0057 {
0058     /* noting to do here */
0059 }
0060 
0061 static irqreturn_t systick_interrupt(int irq, void *dev_id)
0062 {
0063     struct clock_event_device *dev = (struct clock_event_device *) dev_id;
0064 
0065     dev->event_handler(dev);
0066 
0067     return IRQ_HANDLED;
0068 }
0069 
0070 static struct systick_device systick = {
0071     .dev = {
0072         /*
0073          * cevt-r4k uses 300, make sure systick
0074          * gets used if available
0075          */
0076         .rating         = 310,
0077         .features       = CLOCK_EVT_FEAT_ONESHOT,
0078         .set_next_event     = systick_next_event,
0079         .set_state_shutdown = systick_shutdown,
0080         .set_state_oneshot  = systick_set_oneshot,
0081         .event_handler      = systick_event_handler,
0082     },
0083 };
0084 
0085 static int systick_shutdown(struct clock_event_device *evt)
0086 {
0087     struct systick_device *sdev;
0088 
0089     sdev = container_of(evt, struct systick_device, dev);
0090 
0091     if (sdev->irq_requested)
0092         free_irq(systick.dev.irq, &systick.dev);
0093     sdev->irq_requested = 0;
0094     iowrite32(0, systick.membase + SYSTICK_CONFIG);
0095 
0096     return 0;
0097 }
0098 
0099 static int systick_set_oneshot(struct clock_event_device *evt)
0100 {
0101     const char *name = systick.dev.name;
0102     struct systick_device *sdev;
0103     int irq = systick.dev.irq;
0104 
0105     sdev = container_of(evt, struct systick_device, dev);
0106 
0107     if (!sdev->irq_requested) {
0108         if (request_irq(irq, systick_interrupt,
0109                 IRQF_PERCPU | IRQF_TIMER, name, &systick.dev))
0110             pr_err("Failed to request irq %d (%s)\n", irq, name);
0111     }
0112     sdev->irq_requested = 1;
0113     iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
0114           systick.membase + SYSTICK_CONFIG);
0115 
0116     return 0;
0117 }
0118 
0119 static int __init ralink_systick_init(struct device_node *np)
0120 {
0121     int ret;
0122 
0123     systick.membase = of_iomap(np, 0);
0124     if (!systick.membase)
0125         return -ENXIO;
0126 
0127     systick.dev.name = np->name;
0128     clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
0129     systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
0130     systick.dev.max_delta_ticks = 0x7fff;
0131     systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
0132     systick.dev.min_delta_ticks = 0x3;
0133     systick.dev.irq = irq_of_parse_and_map(np, 0);
0134     if (!systick.dev.irq) {
0135         pr_err("%pOFn: request_irq failed", np);
0136         return -EINVAL;
0137     }
0138 
0139     ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
0140                     SYSTICK_FREQ, 301, 16,
0141                     clocksource_mmio_readl_up);
0142     if (ret)
0143         return ret;
0144 
0145     clockevents_register_device(&systick.dev);
0146 
0147     pr_info("%pOFn: running - mult: %d, shift: %d\n",
0148             np, systick.dev.mult, systick.dev.shift);
0149 
0150     return 0;
0151 }
0152 
0153 TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);