Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Ralink RT2880 timer
0004  * Author: John Crispin
0005  *
0006  * Copyright (C) 2013 John Crispin <john@phrozen.org>
0007 */
0008 
0009 #include <linux/platform_device.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/timer.h>
0012 #include <linux/of_gpio.h>
0013 #include <linux/clk.h>
0014 
0015 #include <asm/mach-ralink/ralink_regs.h>
0016 
0017 #define TIMER_REG_TMRSTAT       0x00
0018 #define TIMER_REG_TMR0LOAD      0x10
0019 #define TIMER_REG_TMR0CTL       0x18
0020 
0021 #define TMRSTAT_TMR0INT         BIT(0)
0022 
0023 #define TMR0CTL_ENABLE          BIT(7)
0024 #define TMR0CTL_MODE_PERIODIC       BIT(4)
0025 #define TMR0CTL_PRESCALER       1
0026 #define TMR0CTL_PRESCALE_VAL        (0xf - TMR0CTL_PRESCALER)
0027 #define TMR0CTL_PRESCALE_DIV        (65536 / BIT(TMR0CTL_PRESCALER))
0028 
0029 struct rt_timer {
0030     struct device   *dev;
0031     void __iomem    *membase;
0032     int     irq;
0033     unsigned long   timer_freq;
0034     unsigned long   timer_div;
0035 };
0036 
0037 static inline void rt_timer_w32(struct rt_timer *rt, u8 reg, u32 val)
0038 {
0039     __raw_writel(val, rt->membase + reg);
0040 }
0041 
0042 static inline u32 rt_timer_r32(struct rt_timer *rt, u8 reg)
0043 {
0044     return __raw_readl(rt->membase + reg);
0045 }
0046 
0047 static irqreturn_t rt_timer_irq(int irq, void *_rt)
0048 {
0049     struct rt_timer *rt =  (struct rt_timer *) _rt;
0050 
0051     rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
0052     rt_timer_w32(rt, TIMER_REG_TMRSTAT, TMRSTAT_TMR0INT);
0053 
0054     return IRQ_HANDLED;
0055 }
0056 
0057 
0058 static int rt_timer_request(struct rt_timer *rt)
0059 {
0060     int err = request_irq(rt->irq, rt_timer_irq, 0,
0061                         dev_name(rt->dev), rt);
0062     if (err) {
0063         dev_err(rt->dev, "failed to request irq\n");
0064     } else {
0065         u32 t = TMR0CTL_MODE_PERIODIC | TMR0CTL_PRESCALE_VAL;
0066         rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
0067     }
0068     return err;
0069 }
0070 
0071 static int rt_timer_config(struct rt_timer *rt, unsigned long divisor)
0072 {
0073     if (rt->timer_freq < divisor)
0074         rt->timer_div = rt->timer_freq;
0075     else
0076         rt->timer_div = divisor;
0077 
0078     rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
0079 
0080     return 0;
0081 }
0082 
0083 static int rt_timer_enable(struct rt_timer *rt)
0084 {
0085     u32 t;
0086 
0087     rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
0088 
0089     t = rt_timer_r32(rt, TIMER_REG_TMR0CTL);
0090     t |= TMR0CTL_ENABLE;
0091     rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
0092 
0093     return 0;
0094 }
0095 
0096 static int rt_timer_probe(struct platform_device *pdev)
0097 {
0098     struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0099     struct rt_timer *rt;
0100     struct clk *clk;
0101 
0102     rt = devm_kzalloc(&pdev->dev, sizeof(*rt), GFP_KERNEL);
0103     if (!rt) {
0104         dev_err(&pdev->dev, "failed to allocate memory\n");
0105         return -ENOMEM;
0106     }
0107 
0108     rt->irq = platform_get_irq(pdev, 0);
0109     if (rt->irq < 0)
0110         return rt->irq;
0111 
0112     rt->membase = devm_ioremap_resource(&pdev->dev, res);
0113     if (IS_ERR(rt->membase))
0114         return PTR_ERR(rt->membase);
0115 
0116     clk = devm_clk_get(&pdev->dev, NULL);
0117     if (IS_ERR(clk)) {
0118         dev_err(&pdev->dev, "failed get clock rate\n");
0119         return PTR_ERR(clk);
0120     }
0121 
0122     rt->timer_freq = clk_get_rate(clk) / TMR0CTL_PRESCALE_DIV;
0123     if (!rt->timer_freq)
0124         return -EINVAL;
0125 
0126     rt->dev = &pdev->dev;
0127     platform_set_drvdata(pdev, rt);
0128 
0129     rt_timer_request(rt);
0130     rt_timer_config(rt, 2);
0131     rt_timer_enable(rt);
0132 
0133     dev_info(&pdev->dev, "maximum frequency is %luHz\n", rt->timer_freq);
0134 
0135     return 0;
0136 }
0137 
0138 static const struct of_device_id rt_timer_match[] = {
0139     { .compatible = "ralink,rt2880-timer" },
0140     {},
0141 };
0142 
0143 static struct platform_driver rt_timer_driver = {
0144     .probe = rt_timer_probe,
0145     .driver = {
0146         .name           = "rt-timer",
0147         .of_match_table     = rt_timer_match,
0148         .suppress_bind_attrs    = true,
0149     },
0150 };
0151 builtin_platform_driver(rt_timer_driver);