root/drivers/clocksource/timer-npcm7xx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. npcm7xx_timer_resume
  2. npcm7xx_timer_shutdown
  3. npcm7xx_timer_oneshot
  4. npcm7xx_timer_periodic
  5. npcm7xx_clockevent_set_next_event
  6. npcm7xx_timer0_interrupt
  7. npcm7xx_clockevents_init
  8. npcm7xx_clocksource_init
  9. npcm7xx_timer_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2014-2018 Nuvoton Technologies tomer.maimon@nuvoton.com
   4  * All rights reserved.
   5  *
   6  * Copyright 2017 Google, Inc.
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/sched.h>
  11 #include <linux/init.h>
  12 #include <linux/interrupt.h>
  13 #include <linux/err.h>
  14 #include <linux/clk.h>
  15 #include <linux/io.h>
  16 #include <linux/clockchips.h>
  17 #include <linux/of_irq.h>
  18 #include <linux/of_address.h>
  19 #include "timer-of.h"
  20 
  21 /* Timers registers */
  22 #define NPCM7XX_REG_TCSR0       0x0 /* Timer 0 Control and Status Register */
  23 #define NPCM7XX_REG_TICR0       0x8 /* Timer 0 Initial Count Register */
  24 #define NPCM7XX_REG_TCSR1       0x4 /* Timer 1 Control and Status Register */
  25 #define NPCM7XX_REG_TICR1       0xc /* Timer 1 Initial Count Register */
  26 #define NPCM7XX_REG_TDR1        0x14 /* Timer 1 Data Register */
  27 #define NPCM7XX_REG_TISR        0x18 /* Timer Interrupt Status Register */
  28 
  29 /* Timers control */
  30 #define NPCM7XX_Tx_RESETINT             0x1f
  31 #define NPCM7XX_Tx_PERIOD               BIT(27)
  32 #define NPCM7XX_Tx_INTEN                BIT(29)
  33 #define NPCM7XX_Tx_COUNTEN              BIT(30)
  34 #define NPCM7XX_Tx_ONESHOT              0x0
  35 #define NPCM7XX_Tx_OPER                 GENMASK(28, 27)
  36 #define NPCM7XX_Tx_MIN_PRESCALE         0x1
  37 #define NPCM7XX_Tx_TDR_MASK_BITS        24
  38 #define NPCM7XX_Tx_MAX_CNT              0xFFFFFF
  39 #define NPCM7XX_T0_CLR_INT              0x1
  40 #define NPCM7XX_Tx_CLR_CSR              0x0
  41 
  42 /* Timers operating mode */
  43 #define NPCM7XX_START_PERIODIC_Tx (NPCM7XX_Tx_PERIOD | NPCM7XX_Tx_COUNTEN | \
  44                                         NPCM7XX_Tx_INTEN | \
  45                                         NPCM7XX_Tx_MIN_PRESCALE)
  46 
  47 #define NPCM7XX_START_ONESHOT_Tx (NPCM7XX_Tx_ONESHOT | NPCM7XX_Tx_COUNTEN | \
  48                                         NPCM7XX_Tx_INTEN | \
  49                                         NPCM7XX_Tx_MIN_PRESCALE)
  50 
  51 #define NPCM7XX_START_Tx (NPCM7XX_Tx_COUNTEN | NPCM7XX_Tx_PERIOD | \
  52                                 NPCM7XX_Tx_MIN_PRESCALE)
  53 
  54 #define NPCM7XX_DEFAULT_CSR (NPCM7XX_Tx_CLR_CSR | NPCM7XX_Tx_MIN_PRESCALE)
  55 
  56 static int npcm7xx_timer_resume(struct clock_event_device *evt)
  57 {
  58         struct timer_of *to = to_timer_of(evt);
  59         u32 val;
  60 
  61         val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  62         val |= NPCM7XX_Tx_COUNTEN;
  63         writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  64 
  65         return 0;
  66 }
  67 
  68 static int npcm7xx_timer_shutdown(struct clock_event_device *evt)
  69 {
  70         struct timer_of *to = to_timer_of(evt);
  71         u32 val;
  72 
  73         val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  74         val &= ~NPCM7XX_Tx_COUNTEN;
  75         writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  76 
  77         return 0;
  78 }
  79 
  80 static int npcm7xx_timer_oneshot(struct clock_event_device *evt)
  81 {
  82         struct timer_of *to = to_timer_of(evt);
  83         u32 val;
  84 
  85         val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  86         val &= ~NPCM7XX_Tx_OPER;
  87         val |= NPCM7XX_START_ONESHOT_Tx;
  88         writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  89 
  90         return 0;
  91 }
  92 
  93 static int npcm7xx_timer_periodic(struct clock_event_device *evt)
  94 {
  95         struct timer_of *to = to_timer_of(evt);
  96         u32 val;
  97 
  98         writel(timer_of_period(to), timer_of_base(to) + NPCM7XX_REG_TICR0);
  99 
 100         val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
 101         val &= ~NPCM7XX_Tx_OPER;
 102         val |= NPCM7XX_START_PERIODIC_Tx;
 103         writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
 104 
 105         return 0;
 106 }
 107 
 108 static int npcm7xx_clockevent_set_next_event(unsigned long evt,
 109                 struct clock_event_device *clk)
 110 {
 111         struct timer_of *to = to_timer_of(clk);
 112         u32 val;
 113 
 114         writel(evt, timer_of_base(to) + NPCM7XX_REG_TICR0);
 115         val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
 116         val |= NPCM7XX_START_Tx;
 117         writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
 118 
 119         return 0;
 120 }
 121 
 122 static irqreturn_t npcm7xx_timer0_interrupt(int irq, void *dev_id)
 123 {
 124         struct clock_event_device *evt = (struct clock_event_device *)dev_id;
 125         struct timer_of *to = to_timer_of(evt);
 126 
 127         writel(NPCM7XX_T0_CLR_INT, timer_of_base(to) + NPCM7XX_REG_TISR);
 128 
 129         evt->event_handler(evt);
 130 
 131         return IRQ_HANDLED;
 132 }
 133 
 134 static struct timer_of npcm7xx_to = {
 135         .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
 136 
 137         .clkevt = {
 138                 .name               = "npcm7xx-timer0",
 139                 .features           = CLOCK_EVT_FEAT_PERIODIC |
 140                                       CLOCK_EVT_FEAT_ONESHOT,
 141                 .set_next_event     = npcm7xx_clockevent_set_next_event,
 142                 .set_state_shutdown = npcm7xx_timer_shutdown,
 143                 .set_state_periodic = npcm7xx_timer_periodic,
 144                 .set_state_oneshot  = npcm7xx_timer_oneshot,
 145                 .tick_resume        = npcm7xx_timer_resume,
 146                 .rating             = 300,
 147         },
 148 
 149         .of_irq = {
 150                 .handler = npcm7xx_timer0_interrupt,
 151                 .flags = IRQF_TIMER | IRQF_IRQPOLL,
 152         },
 153 };
 154 
 155 static void __init npcm7xx_clockevents_init(void)
 156 {
 157         writel(NPCM7XX_DEFAULT_CSR,
 158                 timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR0);
 159 
 160         writel(NPCM7XX_Tx_RESETINT,
 161                 timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TISR);
 162 
 163         npcm7xx_to.clkevt.cpumask = cpumask_of(0);
 164         clockevents_config_and_register(&npcm7xx_to.clkevt,
 165                                         timer_of_rate(&npcm7xx_to),
 166                                         0x1, NPCM7XX_Tx_MAX_CNT);
 167 }
 168 
 169 static void __init npcm7xx_clocksource_init(void)
 170 {
 171         u32 val;
 172 
 173         writel(NPCM7XX_DEFAULT_CSR,
 174                 timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
 175         writel(NPCM7XX_Tx_MAX_CNT,
 176                 timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TICR1);
 177 
 178         val = readl(timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
 179         val |= NPCM7XX_START_Tx;
 180         writel(val, timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
 181 
 182         clocksource_mmio_init(timer_of_base(&npcm7xx_to) +
 183                                 NPCM7XX_REG_TDR1,
 184                                 "npcm7xx-timer1", timer_of_rate(&npcm7xx_to),
 185                                 200, (unsigned int)NPCM7XX_Tx_TDR_MASK_BITS,
 186                                 clocksource_mmio_readl_down);
 187 }
 188 
 189 static int __init npcm7xx_timer_init(struct device_node *np)
 190 {
 191         int ret;
 192 
 193         ret = timer_of_init(np, &npcm7xx_to);
 194         if (ret)
 195                 return ret;
 196 
 197         /* Clock input is divided by PRESCALE + 1 before it is fed */
 198         /* to the counter */
 199         npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate /
 200                 (NPCM7XX_Tx_MIN_PRESCALE + 1);
 201 
 202         npcm7xx_clocksource_init();
 203         npcm7xx_clockevents_init();
 204 
 205         pr_info("Enabling NPCM7xx clocksource timer base: %px, IRQ: %d ",
 206                 timer_of_base(&npcm7xx_to), timer_of_irq(&npcm7xx_to));
 207 
 208         return 0;
 209 }
 210 
 211 TIMER_OF_DECLARE(npcm7xx, "nuvoton,npcm750-timer", npcm7xx_timer_init);
 212 

/* [<][>][^][v][top][bottom][index][help] */