Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2014-2018 Nuvoton Technologies tomer.maimon@nuvoton.com
0004  * All rights reserved.
0005  *
0006  * Copyright 2017 Google, Inc.
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/sched.h>
0011 #include <linux/init.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/err.h>
0014 #include <linux/clk.h>
0015 #include <linux/io.h>
0016 #include <linux/clockchips.h>
0017 #include <linux/of_irq.h>
0018 #include <linux/of_address.h>
0019 #include "timer-of.h"
0020 
0021 /* Timers registers */
0022 #define NPCM7XX_REG_TCSR0   0x0 /* Timer 0 Control and Status Register */
0023 #define NPCM7XX_REG_TICR0   0x8 /* Timer 0 Initial Count Register */
0024 #define NPCM7XX_REG_TCSR1   0x4 /* Timer 1 Control and Status Register */
0025 #define NPCM7XX_REG_TICR1   0xc /* Timer 1 Initial Count Register */
0026 #define NPCM7XX_REG_TDR1    0x14 /* Timer 1 Data Register */
0027 #define NPCM7XX_REG_TISR    0x18 /* Timer Interrupt Status Register */
0028 
0029 /* Timers control */
0030 #define NPCM7XX_Tx_RESETINT     0x1f
0031 #define NPCM7XX_Tx_PERIOD       BIT(27)
0032 #define NPCM7XX_Tx_INTEN        BIT(29)
0033 #define NPCM7XX_Tx_COUNTEN      BIT(30)
0034 #define NPCM7XX_Tx_ONESHOT      0x0
0035 #define NPCM7XX_Tx_OPER         GENMASK(28, 27)
0036 #define NPCM7XX_Tx_MIN_PRESCALE     0x1
0037 #define NPCM7XX_Tx_TDR_MASK_BITS    24
0038 #define NPCM7XX_Tx_MAX_CNT      0xFFFFFF
0039 #define NPCM7XX_T0_CLR_INT      0x1
0040 #define NPCM7XX_Tx_CLR_CSR      0x0
0041 
0042 /* Timers operating mode */
0043 #define NPCM7XX_START_PERIODIC_Tx (NPCM7XX_Tx_PERIOD | NPCM7XX_Tx_COUNTEN | \
0044                     NPCM7XX_Tx_INTEN | \
0045                     NPCM7XX_Tx_MIN_PRESCALE)
0046 
0047 #define NPCM7XX_START_ONESHOT_Tx (NPCM7XX_Tx_ONESHOT | NPCM7XX_Tx_COUNTEN | \
0048                     NPCM7XX_Tx_INTEN | \
0049                     NPCM7XX_Tx_MIN_PRESCALE)
0050 
0051 #define NPCM7XX_START_Tx (NPCM7XX_Tx_COUNTEN | NPCM7XX_Tx_PERIOD | \
0052                 NPCM7XX_Tx_MIN_PRESCALE)
0053 
0054 #define NPCM7XX_DEFAULT_CSR (NPCM7XX_Tx_CLR_CSR | NPCM7XX_Tx_MIN_PRESCALE)
0055 
0056 static int npcm7xx_timer_resume(struct clock_event_device *evt)
0057 {
0058     struct timer_of *to = to_timer_of(evt);
0059     u32 val;
0060 
0061     val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
0062     val |= NPCM7XX_Tx_COUNTEN;
0063     writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
0064 
0065     return 0;
0066 }
0067 
0068 static int npcm7xx_timer_shutdown(struct clock_event_device *evt)
0069 {
0070     struct timer_of *to = to_timer_of(evt);
0071     u32 val;
0072 
0073     val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
0074     val &= ~NPCM7XX_Tx_COUNTEN;
0075     writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
0076 
0077     return 0;
0078 }
0079 
0080 static int npcm7xx_timer_oneshot(struct clock_event_device *evt)
0081 {
0082     struct timer_of *to = to_timer_of(evt);
0083     u32 val;
0084 
0085     val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
0086     val &= ~NPCM7XX_Tx_OPER;
0087     val |= NPCM7XX_START_ONESHOT_Tx;
0088     writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
0089 
0090     return 0;
0091 }
0092 
0093 static int npcm7xx_timer_periodic(struct clock_event_device *evt)
0094 {
0095     struct timer_of *to = to_timer_of(evt);
0096     u32 val;
0097 
0098     writel(timer_of_period(to), timer_of_base(to) + NPCM7XX_REG_TICR0);
0099 
0100     val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
0101     val &= ~NPCM7XX_Tx_OPER;
0102     val |= NPCM7XX_START_PERIODIC_Tx;
0103     writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
0104 
0105     return 0;
0106 }
0107 
0108 static int npcm7xx_clockevent_set_next_event(unsigned long evt,
0109         struct clock_event_device *clk)
0110 {
0111     struct timer_of *to = to_timer_of(clk);
0112     u32 val;
0113 
0114     writel(evt, timer_of_base(to) + NPCM7XX_REG_TICR0);
0115     val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
0116     val |= NPCM7XX_START_Tx;
0117     writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
0118 
0119     return 0;
0120 }
0121 
0122 static irqreturn_t npcm7xx_timer0_interrupt(int irq, void *dev_id)
0123 {
0124     struct clock_event_device *evt = (struct clock_event_device *)dev_id;
0125     struct timer_of *to = to_timer_of(evt);
0126 
0127     writel(NPCM7XX_T0_CLR_INT, timer_of_base(to) + NPCM7XX_REG_TISR);
0128 
0129     evt->event_handler(evt);
0130 
0131     return IRQ_HANDLED;
0132 }
0133 
0134 static struct timer_of npcm7xx_to = {
0135     .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
0136 
0137     .clkevt = {
0138         .name           = "npcm7xx-timer0",
0139         .features       = CLOCK_EVT_FEAT_PERIODIC |
0140                       CLOCK_EVT_FEAT_ONESHOT,
0141         .set_next_event     = npcm7xx_clockevent_set_next_event,
0142         .set_state_shutdown = npcm7xx_timer_shutdown,
0143         .set_state_periodic = npcm7xx_timer_periodic,
0144         .set_state_oneshot  = npcm7xx_timer_oneshot,
0145         .tick_resume        = npcm7xx_timer_resume,
0146         .rating         = 300,
0147     },
0148 
0149     .of_irq = {
0150         .handler = npcm7xx_timer0_interrupt,
0151         .flags = IRQF_TIMER | IRQF_IRQPOLL,
0152     },
0153 };
0154 
0155 static void __init npcm7xx_clockevents_init(void)
0156 {
0157     writel(NPCM7XX_DEFAULT_CSR,
0158         timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR0);
0159 
0160     writel(NPCM7XX_Tx_RESETINT,
0161         timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TISR);
0162 
0163     npcm7xx_to.clkevt.cpumask = cpumask_of(0);
0164     clockevents_config_and_register(&npcm7xx_to.clkevt,
0165                     timer_of_rate(&npcm7xx_to),
0166                     0x1, NPCM7XX_Tx_MAX_CNT);
0167 }
0168 
0169 static void __init npcm7xx_clocksource_init(void)
0170 {
0171     u32 val;
0172 
0173     writel(NPCM7XX_DEFAULT_CSR,
0174         timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
0175     writel(NPCM7XX_Tx_MAX_CNT,
0176         timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TICR1);
0177 
0178     val = readl(timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
0179     val |= NPCM7XX_START_Tx;
0180     writel(val, timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
0181 
0182     clocksource_mmio_init(timer_of_base(&npcm7xx_to) +
0183                 NPCM7XX_REG_TDR1,
0184                 "npcm7xx-timer1", timer_of_rate(&npcm7xx_to),
0185                 200, (unsigned int)NPCM7XX_Tx_TDR_MASK_BITS,
0186                 clocksource_mmio_readl_down);
0187 }
0188 
0189 static int __init npcm7xx_timer_init(struct device_node *np)
0190 {
0191     int ret;
0192 
0193     ret = timer_of_init(np, &npcm7xx_to);
0194     if (ret)
0195         return ret;
0196 
0197     /* Clock input is divided by PRESCALE + 1 before it is fed */
0198     /* to the counter */
0199     npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate /
0200         (NPCM7XX_Tx_MIN_PRESCALE + 1);
0201 
0202     npcm7xx_clocksource_init();
0203     npcm7xx_clockevents_init();
0204 
0205     pr_info("Enabling NPCM7xx clocksource timer base: %px, IRQ: %d ",
0206         timer_of_base(&npcm7xx_to), timer_of_irq(&npcm7xx_to));
0207 
0208     return 0;
0209 }
0210 
0211 TIMER_OF_DECLARE(wpcm450, "nuvoton,wpcm450-timer", npcm7xx_timer_init);
0212 TIMER_OF_DECLARE(npcm7xx, "nuvoton,npcm750-timer", npcm7xx_timer_init);
0213