Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Pistachio clocksource based on general-purpose timers
0004  *
0005  * Copyright (C) 2015 Imagination Technologies
0006  */
0007 
0008 #define pr_fmt(fmt) "%s: " fmt, __func__
0009 
0010 #include <linux/clk.h>
0011 #include <linux/clocksource.h>
0012 #include <linux/clockchips.h>
0013 #include <linux/delay.h>
0014 #include <linux/err.h>
0015 #include <linux/init.h>
0016 #include <linux/spinlock.h>
0017 #include <linux/mfd/syscon.h>
0018 #include <linux/of.h>
0019 #include <linux/of_address.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/regmap.h>
0022 #include <linux/sched_clock.h>
0023 #include <linux/time.h>
0024 
0025 /* Top level reg */
0026 #define CR_TIMER_CTRL_CFG       0x00
0027 #define TIMER_ME_GLOBAL         BIT(0)
0028 #define CR_TIMER_REV            0x10
0029 
0030 /* Timer specific registers */
0031 #define TIMER_CFG           0x20
0032 #define TIMER_ME_LOCAL          BIT(0)
0033 #define TIMER_RELOAD_VALUE      0x24
0034 #define TIMER_CURRENT_VALUE     0x28
0035 #define TIMER_CURRENT_OVERFLOW_VALUE    0x2C
0036 #define TIMER_IRQ_STATUS        0x30
0037 #define TIMER_IRQ_CLEAR         0x34
0038 #define TIMER_IRQ_MASK          0x38
0039 
0040 #define PERIP_TIMER_CONTROL     0x90
0041 
0042 /* Timer specific configuration Values */
0043 #define RELOAD_VALUE            0xffffffff
0044 
0045 struct pistachio_clocksource {
0046     void __iomem *base;
0047     raw_spinlock_t lock;
0048     struct clocksource cs;
0049 };
0050 
0051 static struct pistachio_clocksource pcs_gpt;
0052 
0053 #define to_pistachio_clocksource(cs)    \
0054     container_of(cs, struct pistachio_clocksource, cs)
0055 
0056 static inline u32 gpt_readl(void __iomem *base, u32 offset, u32 gpt_id)
0057 {
0058     return readl(base + 0x20 * gpt_id + offset);
0059 }
0060 
0061 static inline void gpt_writel(void __iomem *base, u32 value, u32 offset,
0062         u32 gpt_id)
0063 {
0064     writel(value, base + 0x20 * gpt_id + offset);
0065 }
0066 
0067 static u64 notrace
0068 pistachio_clocksource_read_cycles(struct clocksource *cs)
0069 {
0070     struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
0071     __maybe_unused u32 overflow;
0072     u32 counter;
0073     unsigned long flags;
0074 
0075     /*
0076      * The counter value is only refreshed after the overflow value is read.
0077      * And they must be read in strict order, hence raw spin lock added.
0078      */
0079 
0080     raw_spin_lock_irqsave(&pcs->lock, flags);
0081     overflow = gpt_readl(pcs->base, TIMER_CURRENT_OVERFLOW_VALUE, 0);
0082     counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0);
0083     raw_spin_unlock_irqrestore(&pcs->lock, flags);
0084 
0085     return (u64)~counter;
0086 }
0087 
0088 static u64 notrace pistachio_read_sched_clock(void)
0089 {
0090     return pistachio_clocksource_read_cycles(&pcs_gpt.cs);
0091 }
0092 
0093 static void pistachio_clksrc_set_mode(struct clocksource *cs, int timeridx,
0094             int enable)
0095 {
0096     struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
0097     u32 val;
0098 
0099     val = gpt_readl(pcs->base, TIMER_CFG, timeridx);
0100     if (enable)
0101         val |= TIMER_ME_LOCAL;
0102     else
0103         val &= ~TIMER_ME_LOCAL;
0104 
0105     gpt_writel(pcs->base, val, TIMER_CFG, timeridx);
0106 }
0107 
0108 static void pistachio_clksrc_enable(struct clocksource *cs, int timeridx)
0109 {
0110     struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
0111 
0112     /* Disable GPT local before loading reload value */
0113     pistachio_clksrc_set_mode(cs, timeridx, false);
0114     gpt_writel(pcs->base, RELOAD_VALUE, TIMER_RELOAD_VALUE, timeridx);
0115     pistachio_clksrc_set_mode(cs, timeridx, true);
0116 }
0117 
0118 static void pistachio_clksrc_disable(struct clocksource *cs, int timeridx)
0119 {
0120     /* Disable GPT local */
0121     pistachio_clksrc_set_mode(cs, timeridx, false);
0122 }
0123 
0124 static int pistachio_clocksource_enable(struct clocksource *cs)
0125 {
0126     pistachio_clksrc_enable(cs, 0);
0127     return 0;
0128 }
0129 
0130 static void pistachio_clocksource_disable(struct clocksource *cs)
0131 {
0132     pistachio_clksrc_disable(cs, 0);
0133 }
0134 
0135 /* Desirable clock source for pistachio platform */
0136 static struct pistachio_clocksource pcs_gpt = {
0137     .cs =   {
0138         .name       = "gptimer",
0139         .rating     = 300,
0140         .enable     = pistachio_clocksource_enable,
0141         .disable    = pistachio_clocksource_disable,
0142         .read       = pistachio_clocksource_read_cycles,
0143         .mask       = CLOCKSOURCE_MASK(32),
0144         .flags      = CLOCK_SOURCE_IS_CONTINUOUS |
0145                   CLOCK_SOURCE_SUSPEND_NONSTOP,
0146         },
0147 };
0148 
0149 static int __init pistachio_clksrc_of_init(struct device_node *node)
0150 {
0151     struct clk *sys_clk, *fast_clk;
0152     struct regmap *periph_regs;
0153     unsigned long rate;
0154     int ret;
0155 
0156     pcs_gpt.base = of_iomap(node, 0);
0157     if (!pcs_gpt.base) {
0158         pr_err("cannot iomap\n");
0159         return -ENXIO;
0160     }
0161 
0162     periph_regs = syscon_regmap_lookup_by_phandle(node, "img,cr-periph");
0163     if (IS_ERR(periph_regs)) {
0164         pr_err("cannot get peripheral regmap (%ld)\n",
0165                PTR_ERR(periph_regs));
0166         return PTR_ERR(periph_regs);
0167     }
0168 
0169     /* Switch to using the fast counter clock */
0170     ret = regmap_update_bits(periph_regs, PERIP_TIMER_CONTROL,
0171                  0xf, 0x0);
0172     if (ret)
0173         return ret;
0174 
0175     sys_clk = of_clk_get_by_name(node, "sys");
0176     if (IS_ERR(sys_clk)) {
0177         pr_err("clock get failed (%ld)\n", PTR_ERR(sys_clk));
0178         return PTR_ERR(sys_clk);
0179     }
0180 
0181     fast_clk = of_clk_get_by_name(node, "fast");
0182     if (IS_ERR(fast_clk)) {
0183         pr_err("clock get failed (%lu)\n", PTR_ERR(fast_clk));
0184         return PTR_ERR(fast_clk);
0185     }
0186 
0187     ret = clk_prepare_enable(sys_clk);
0188     if (ret < 0) {
0189         pr_err("failed to enable clock (%d)\n", ret);
0190         return ret;
0191     }
0192 
0193     ret = clk_prepare_enable(fast_clk);
0194     if (ret < 0) {
0195         pr_err("failed to enable clock (%d)\n", ret);
0196         clk_disable_unprepare(sys_clk);
0197         return ret;
0198     }
0199 
0200     rate = clk_get_rate(fast_clk);
0201 
0202     /* Disable irq's for clocksource usage */
0203     gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 0);
0204     gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 1);
0205     gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 2);
0206     gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 3);
0207 
0208     /* Enable timer block */
0209     writel(TIMER_ME_GLOBAL, pcs_gpt.base);
0210 
0211     raw_spin_lock_init(&pcs_gpt.lock);
0212     sched_clock_register(pistachio_read_sched_clock, 32, rate);
0213     return clocksource_register_hz(&pcs_gpt.cs, rate);
0214 }
0215 TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
0216                pistachio_clksrc_of_init);