Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.18-rc5 215 lines 5.8 kB view raw
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(3, 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 56static 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 68static 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 80static 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 88 val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0); 89 val |= NPCM7XX_START_ONESHOT_Tx; 90 writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0); 91 92 return 0; 93} 94 95static int npcm7xx_timer_periodic(struct clock_event_device *evt) 96{ 97 struct timer_of *to = to_timer_of(evt); 98 u32 val; 99 100 val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0); 101 val &= ~NPCM7XX_Tx_OPER; 102 103 writel(timer_of_period(to), timer_of_base(to) + NPCM7XX_REG_TICR0); 104 val |= NPCM7XX_START_PERIODIC_Tx; 105 106 writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0); 107 108 return 0; 109} 110 111static int npcm7xx_clockevent_set_next_event(unsigned long evt, 112 struct clock_event_device *clk) 113{ 114 struct timer_of *to = to_timer_of(clk); 115 u32 val; 116 117 writel(evt, timer_of_base(to) + NPCM7XX_REG_TICR0); 118 val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0); 119 val |= NPCM7XX_START_Tx; 120 writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0); 121 122 return 0; 123} 124 125static irqreturn_t npcm7xx_timer0_interrupt(int irq, void *dev_id) 126{ 127 struct clock_event_device *evt = (struct clock_event_device *)dev_id; 128 struct timer_of *to = to_timer_of(evt); 129 130 writel(NPCM7XX_T0_CLR_INT, timer_of_base(to) + NPCM7XX_REG_TISR); 131 132 evt->event_handler(evt); 133 134 return IRQ_HANDLED; 135} 136 137static struct timer_of npcm7xx_to = { 138 .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK, 139 140 .clkevt = { 141 .name = "npcm7xx-timer0", 142 .features = CLOCK_EVT_FEAT_PERIODIC | 143 CLOCK_EVT_FEAT_ONESHOT, 144 .set_next_event = npcm7xx_clockevent_set_next_event, 145 .set_state_shutdown = npcm7xx_timer_shutdown, 146 .set_state_periodic = npcm7xx_timer_periodic, 147 .set_state_oneshot = npcm7xx_timer_oneshot, 148 .tick_resume = npcm7xx_timer_resume, 149 .rating = 300, 150 }, 151 152 .of_irq = { 153 .handler = npcm7xx_timer0_interrupt, 154 .flags = IRQF_TIMER | IRQF_IRQPOLL, 155 }, 156}; 157 158static void __init npcm7xx_clockevents_init(void) 159{ 160 writel(NPCM7XX_DEFAULT_CSR, 161 timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR0); 162 163 writel(NPCM7XX_Tx_RESETINT, 164 timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TISR); 165 166 npcm7xx_to.clkevt.cpumask = cpumask_of(0); 167 clockevents_config_and_register(&npcm7xx_to.clkevt, 168 timer_of_rate(&npcm7xx_to), 169 0x1, NPCM7XX_Tx_MAX_CNT); 170} 171 172static void __init npcm7xx_clocksource_init(void) 173{ 174 u32 val; 175 176 writel(NPCM7XX_DEFAULT_CSR, 177 timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1); 178 writel(NPCM7XX_Tx_MAX_CNT, 179 timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TICR1); 180 181 val = readl(timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1); 182 val |= NPCM7XX_START_Tx; 183 writel(val, timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1); 184 185 clocksource_mmio_init(timer_of_base(&npcm7xx_to) + 186 NPCM7XX_REG_TDR1, 187 "npcm7xx-timer1", timer_of_rate(&npcm7xx_to), 188 200, (unsigned int)NPCM7XX_Tx_TDR_MASK_BITS, 189 clocksource_mmio_readl_down); 190} 191 192static int __init npcm7xx_timer_init(struct device_node *np) 193{ 194 int ret; 195 196 ret = timer_of_init(np, &npcm7xx_to); 197 if (ret) 198 return ret; 199 200 /* Clock input is divided by PRESCALE + 1 before it is fed */ 201 /* to the counter */ 202 npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate / 203 (NPCM7XX_Tx_MIN_PRESCALE + 1); 204 205 npcm7xx_clocksource_init(); 206 npcm7xx_clockevents_init(); 207 208 pr_info("Enabling NPCM7xx clocksource timer base: %px, IRQ: %d ", 209 timer_of_base(&npcm7xx_to), timer_of_irq(&npcm7xx_to)); 210 211 return 0; 212} 213 214TIMER_OF_DECLARE(npcm7xx, "nuvoton,npcm750-timer", npcm7xx_timer_init); 215