linux/arch/mips/ralink/timer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Ralink RT2880 timer
   4 * Author: John Crispin
   5 *
   6 * Copyright (C) 2013 John Crispin <john@phrozen.org>
   7*/
   8
   9#include <linux/platform_device.h>
  10#include <linux/interrupt.h>
  11#include <linux/timer.h>
  12#include <linux/of_gpio.h>
  13#include <linux/clk.h>
  14
  15#include <asm/mach-ralink/ralink_regs.h>
  16
  17#define TIMER_REG_TMRSTAT               0x00
  18#define TIMER_REG_TMR0LOAD              0x10
  19#define TIMER_REG_TMR0CTL               0x18
  20
  21#define TMRSTAT_TMR0INT                 BIT(0)
  22
  23#define TMR0CTL_ENABLE                  BIT(7)
  24#define TMR0CTL_MODE_PERIODIC           BIT(4)
  25#define TMR0CTL_PRESCALER               1
  26#define TMR0CTL_PRESCALE_VAL            (0xf - TMR0CTL_PRESCALER)
  27#define TMR0CTL_PRESCALE_DIV            (65536 / BIT(TMR0CTL_PRESCALER))
  28
  29struct rt_timer {
  30        struct device   *dev;
  31        void __iomem    *membase;
  32        int             irq;
  33        unsigned long   timer_freq;
  34        unsigned long   timer_div;
  35};
  36
  37static inline void rt_timer_w32(struct rt_timer *rt, u8 reg, u32 val)
  38{
  39        __raw_writel(val, rt->membase + reg);
  40}
  41
  42static inline u32 rt_timer_r32(struct rt_timer *rt, u8 reg)
  43{
  44        return __raw_readl(rt->membase + reg);
  45}
  46
  47static irqreturn_t rt_timer_irq(int irq, void *_rt)
  48{
  49        struct rt_timer *rt =  (struct rt_timer *) _rt;
  50
  51        rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
  52        rt_timer_w32(rt, TIMER_REG_TMRSTAT, TMRSTAT_TMR0INT);
  53
  54        return IRQ_HANDLED;
  55}
  56
  57
  58static int rt_timer_request(struct rt_timer *rt)
  59{
  60        int err = request_irq(rt->irq, rt_timer_irq, 0,
  61                                                dev_name(rt->dev), rt);
  62        if (err) {
  63                dev_err(rt->dev, "failed to request irq\n");
  64        } else {
  65                u32 t = TMR0CTL_MODE_PERIODIC | TMR0CTL_PRESCALE_VAL;
  66                rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
  67        }
  68        return err;
  69}
  70
  71static int rt_timer_config(struct rt_timer *rt, unsigned long divisor)
  72{
  73        if (rt->timer_freq < divisor)
  74                rt->timer_div = rt->timer_freq;
  75        else
  76                rt->timer_div = divisor;
  77
  78        rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
  79
  80        return 0;
  81}
  82
  83static int rt_timer_enable(struct rt_timer *rt)
  84{
  85        u32 t;
  86
  87        rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
  88
  89        t = rt_timer_r32(rt, TIMER_REG_TMR0CTL);
  90        t |= TMR0CTL_ENABLE;
  91        rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
  92
  93        return 0;
  94}
  95
  96static int rt_timer_probe(struct platform_device *pdev)
  97{
  98        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  99        struct rt_timer *rt;
 100        struct clk *clk;
 101
 102        rt = devm_kzalloc(&pdev->dev, sizeof(*rt), GFP_KERNEL);
 103        if (!rt) {
 104                dev_err(&pdev->dev, "failed to allocate memory\n");
 105                return -ENOMEM;
 106        }
 107
 108        rt->irq = platform_get_irq(pdev, 0);
 109        if (rt->irq < 0) {
 110                dev_err(&pdev->dev, "failed to load irq\n");
 111                return rt->irq;
 112        }
 113
 114        rt->membase = devm_ioremap_resource(&pdev->dev, res);
 115        if (IS_ERR(rt->membase))
 116                return PTR_ERR(rt->membase);
 117
 118        clk = devm_clk_get(&pdev->dev, NULL);
 119        if (IS_ERR(clk)) {
 120                dev_err(&pdev->dev, "failed get clock rate\n");
 121                return PTR_ERR(clk);
 122        }
 123
 124        rt->timer_freq = clk_get_rate(clk) / TMR0CTL_PRESCALE_DIV;
 125        if (!rt->timer_freq)
 126                return -EINVAL;
 127
 128        rt->dev = &pdev->dev;
 129        platform_set_drvdata(pdev, rt);
 130
 131        rt_timer_request(rt);
 132        rt_timer_config(rt, 2);
 133        rt_timer_enable(rt);
 134
 135        dev_info(&pdev->dev, "maximum frequency is %luHz\n", rt->timer_freq);
 136
 137        return 0;
 138}
 139
 140static const struct of_device_id rt_timer_match[] = {
 141        { .compatible = "ralink,rt2880-timer" },
 142        {},
 143};
 144
 145static struct platform_driver rt_timer_driver = {
 146        .probe = rt_timer_probe,
 147        .driver = {
 148                .name                   = "rt-timer",
 149                .of_match_table         = rt_timer_match,
 150                .suppress_bind_attrs    = true,
 151        },
 152};
 153builtin_platform_driver(rt_timer_driver);
 154