11c00289eSTomer Maimon // SPDX-License-Identifier: GPL-2.0
21c00289eSTomer Maimon /*
31c00289eSTomer Maimon * Copyright (C) 2014-2018 Nuvoton Technologies tomer.maimon@nuvoton.com
41c00289eSTomer Maimon * All rights reserved.
51c00289eSTomer Maimon *
61c00289eSTomer Maimon * Copyright 2017 Google, Inc.
71c00289eSTomer Maimon */
81c00289eSTomer Maimon
91c00289eSTomer Maimon #include <linux/kernel.h>
101c00289eSTomer Maimon #include <linux/sched.h>
111c00289eSTomer Maimon #include <linux/init.h>
121c00289eSTomer Maimon #include <linux/interrupt.h>
131c00289eSTomer Maimon #include <linux/err.h>
141c00289eSTomer Maimon #include <linux/clk.h>
151c00289eSTomer Maimon #include <linux/io.h>
161c00289eSTomer Maimon #include <linux/clockchips.h>
171c00289eSTomer Maimon #include <linux/of_irq.h>
181c00289eSTomer Maimon #include <linux/of_address.h>
191c00289eSTomer Maimon #include "timer-of.h"
201c00289eSTomer Maimon
211c00289eSTomer Maimon /* Timers registers */
221c00289eSTomer Maimon #define NPCM7XX_REG_TCSR0 0x0 /* Timer 0 Control and Status Register */
231c00289eSTomer Maimon #define NPCM7XX_REG_TICR0 0x8 /* Timer 0 Initial Count Register */
241c00289eSTomer Maimon #define NPCM7XX_REG_TCSR1 0x4 /* Timer 1 Control and Status Register */
251c00289eSTomer Maimon #define NPCM7XX_REG_TICR1 0xc /* Timer 1 Initial Count Register */
261c00289eSTomer Maimon #define NPCM7XX_REG_TDR1 0x14 /* Timer 1 Data Register */
271c00289eSTomer Maimon #define NPCM7XX_REG_TISR 0x18 /* Timer Interrupt Status Register */
281c00289eSTomer Maimon
291c00289eSTomer Maimon /* Timers control */
301c00289eSTomer Maimon #define NPCM7XX_Tx_RESETINT 0x1f
311c00289eSTomer Maimon #define NPCM7XX_Tx_PERIOD BIT(27)
321c00289eSTomer Maimon #define NPCM7XX_Tx_INTEN BIT(29)
331c00289eSTomer Maimon #define NPCM7XX_Tx_COUNTEN BIT(30)
341c00289eSTomer Maimon #define NPCM7XX_Tx_ONESHOT 0x0
35a2b58537SAvi Fishman #define NPCM7XX_Tx_OPER GENMASK(28, 27)
361c00289eSTomer Maimon #define NPCM7XX_Tx_MIN_PRESCALE 0x1
371c00289eSTomer Maimon #define NPCM7XX_Tx_TDR_MASK_BITS 24
381c00289eSTomer Maimon #define NPCM7XX_Tx_MAX_CNT 0xFFFFFF
391c00289eSTomer Maimon #define NPCM7XX_T0_CLR_INT 0x1
401c00289eSTomer Maimon #define NPCM7XX_Tx_CLR_CSR 0x0
411c00289eSTomer Maimon
421c00289eSTomer Maimon /* Timers operating mode */
431c00289eSTomer Maimon #define NPCM7XX_START_PERIODIC_Tx (NPCM7XX_Tx_PERIOD | NPCM7XX_Tx_COUNTEN | \
441c00289eSTomer Maimon NPCM7XX_Tx_INTEN | \
451c00289eSTomer Maimon NPCM7XX_Tx_MIN_PRESCALE)
461c00289eSTomer Maimon
471c00289eSTomer Maimon #define NPCM7XX_START_ONESHOT_Tx (NPCM7XX_Tx_ONESHOT | NPCM7XX_Tx_COUNTEN | \
481c00289eSTomer Maimon NPCM7XX_Tx_INTEN | \
491c00289eSTomer Maimon NPCM7XX_Tx_MIN_PRESCALE)
501c00289eSTomer Maimon
511c00289eSTomer Maimon #define NPCM7XX_START_Tx (NPCM7XX_Tx_COUNTEN | NPCM7XX_Tx_PERIOD | \
521c00289eSTomer Maimon NPCM7XX_Tx_MIN_PRESCALE)
531c00289eSTomer Maimon
541c00289eSTomer Maimon #define NPCM7XX_DEFAULT_CSR (NPCM7XX_Tx_CLR_CSR | NPCM7XX_Tx_MIN_PRESCALE)
551c00289eSTomer Maimon
npcm7xx_timer_resume(struct clock_event_device * evt)561c00289eSTomer Maimon static int npcm7xx_timer_resume(struct clock_event_device *evt)
571c00289eSTomer Maimon {
581c00289eSTomer Maimon struct timer_of *to = to_timer_of(evt);
591c00289eSTomer Maimon u32 val;
601c00289eSTomer Maimon
611c00289eSTomer Maimon val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
621c00289eSTomer Maimon val |= NPCM7XX_Tx_COUNTEN;
631c00289eSTomer Maimon writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
641c00289eSTomer Maimon
651c00289eSTomer Maimon return 0;
661c00289eSTomer Maimon }
671c00289eSTomer Maimon
npcm7xx_timer_shutdown(struct clock_event_device * evt)681c00289eSTomer Maimon static int npcm7xx_timer_shutdown(struct clock_event_device *evt)
691c00289eSTomer Maimon {
701c00289eSTomer Maimon struct timer_of *to = to_timer_of(evt);
711c00289eSTomer Maimon u32 val;
721c00289eSTomer Maimon
731c00289eSTomer Maimon val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
741c00289eSTomer Maimon val &= ~NPCM7XX_Tx_COUNTEN;
751c00289eSTomer Maimon writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
761c00289eSTomer Maimon
771c00289eSTomer Maimon return 0;
781c00289eSTomer Maimon }
791c00289eSTomer Maimon
npcm7xx_timer_oneshot(struct clock_event_device * evt)801c00289eSTomer Maimon static int npcm7xx_timer_oneshot(struct clock_event_device *evt)
811c00289eSTomer Maimon {
821c00289eSTomer Maimon struct timer_of *to = to_timer_of(evt);
831c00289eSTomer Maimon u32 val;
841c00289eSTomer Maimon
851c00289eSTomer Maimon val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
861c00289eSTomer Maimon val &= ~NPCM7XX_Tx_OPER;
871c00289eSTomer Maimon val |= NPCM7XX_START_ONESHOT_Tx;
881c00289eSTomer Maimon writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
891c00289eSTomer Maimon
901c00289eSTomer Maimon return 0;
911c00289eSTomer Maimon }
921c00289eSTomer Maimon
npcm7xx_timer_periodic(struct clock_event_device * evt)931c00289eSTomer Maimon static int npcm7xx_timer_periodic(struct clock_event_device *evt)
941c00289eSTomer Maimon {
951c00289eSTomer Maimon struct timer_of *to = to_timer_of(evt);
961c00289eSTomer Maimon u32 val;
971c00289eSTomer Maimon
98a2b58537SAvi Fishman writel(timer_of_period(to), timer_of_base(to) + NPCM7XX_REG_TICR0);
99a2b58537SAvi Fishman
1001c00289eSTomer Maimon val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
1011c00289eSTomer Maimon val &= ~NPCM7XX_Tx_OPER;
1021c00289eSTomer Maimon val |= NPCM7XX_START_PERIODIC_Tx;
1031c00289eSTomer Maimon writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
1041c00289eSTomer Maimon
1051c00289eSTomer Maimon return 0;
1061c00289eSTomer Maimon }
1071c00289eSTomer Maimon
npcm7xx_clockevent_set_next_event(unsigned long evt,struct clock_event_device * clk)1081c00289eSTomer Maimon static int npcm7xx_clockevent_set_next_event(unsigned long evt,
1091c00289eSTomer Maimon struct clock_event_device *clk)
1101c00289eSTomer Maimon {
1111c00289eSTomer Maimon struct timer_of *to = to_timer_of(clk);
1121c00289eSTomer Maimon u32 val;
1131c00289eSTomer Maimon
1141c00289eSTomer Maimon writel(evt, timer_of_base(to) + NPCM7XX_REG_TICR0);
1151c00289eSTomer Maimon val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
1161c00289eSTomer Maimon val |= NPCM7XX_START_Tx;
1171c00289eSTomer Maimon writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
1181c00289eSTomer Maimon
1191c00289eSTomer Maimon return 0;
1201c00289eSTomer Maimon }
1211c00289eSTomer Maimon
npcm7xx_timer0_interrupt(int irq,void * dev_id)1221c00289eSTomer Maimon static irqreturn_t npcm7xx_timer0_interrupt(int irq, void *dev_id)
1231c00289eSTomer Maimon {
1241c00289eSTomer Maimon struct clock_event_device *evt = (struct clock_event_device *)dev_id;
1251c00289eSTomer Maimon struct timer_of *to = to_timer_of(evt);
1261c00289eSTomer Maimon
1271c00289eSTomer Maimon writel(NPCM7XX_T0_CLR_INT, timer_of_base(to) + NPCM7XX_REG_TISR);
1281c00289eSTomer Maimon
1291c00289eSTomer Maimon evt->event_handler(evt);
1301c00289eSTomer Maimon
1311c00289eSTomer Maimon return IRQ_HANDLED;
1321c00289eSTomer Maimon }
1331c00289eSTomer Maimon
1341c00289eSTomer Maimon static struct timer_of npcm7xx_to = {
1351c00289eSTomer Maimon .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
1361c00289eSTomer Maimon
1371c00289eSTomer Maimon .clkevt = {
1381c00289eSTomer Maimon .name = "npcm7xx-timer0",
1391c00289eSTomer Maimon .features = CLOCK_EVT_FEAT_PERIODIC |
1401c00289eSTomer Maimon CLOCK_EVT_FEAT_ONESHOT,
1411c00289eSTomer Maimon .set_next_event = npcm7xx_clockevent_set_next_event,
1421c00289eSTomer Maimon .set_state_shutdown = npcm7xx_timer_shutdown,
1431c00289eSTomer Maimon .set_state_periodic = npcm7xx_timer_periodic,
1441c00289eSTomer Maimon .set_state_oneshot = npcm7xx_timer_oneshot,
1451c00289eSTomer Maimon .tick_resume = npcm7xx_timer_resume,
1461c00289eSTomer Maimon .rating = 300,
1471c00289eSTomer Maimon },
1481c00289eSTomer Maimon
1491c00289eSTomer Maimon .of_irq = {
1501c00289eSTomer Maimon .handler = npcm7xx_timer0_interrupt,
1511c00289eSTomer Maimon .flags = IRQF_TIMER | IRQF_IRQPOLL,
1521c00289eSTomer Maimon },
1531c00289eSTomer Maimon };
1541c00289eSTomer Maimon
npcm7xx_clockevents_init(void)1551c00289eSTomer Maimon static void __init npcm7xx_clockevents_init(void)
1561c00289eSTomer Maimon {
1571c00289eSTomer Maimon writel(NPCM7XX_DEFAULT_CSR,
1581c00289eSTomer Maimon timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR0);
1591c00289eSTomer Maimon
1601c00289eSTomer Maimon writel(NPCM7XX_Tx_RESETINT,
1611c00289eSTomer Maimon timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TISR);
1621c00289eSTomer Maimon
1631c00289eSTomer Maimon npcm7xx_to.clkevt.cpumask = cpumask_of(0);
1641c00289eSTomer Maimon clockevents_config_and_register(&npcm7xx_to.clkevt,
1651c00289eSTomer Maimon timer_of_rate(&npcm7xx_to),
1661c00289eSTomer Maimon 0x1, NPCM7XX_Tx_MAX_CNT);
1671c00289eSTomer Maimon }
1681c00289eSTomer Maimon
npcm7xx_clocksource_init(void)1691c00289eSTomer Maimon static void __init npcm7xx_clocksource_init(void)
1701c00289eSTomer Maimon {
1711c00289eSTomer Maimon u32 val;
1721c00289eSTomer Maimon
1731c00289eSTomer Maimon writel(NPCM7XX_DEFAULT_CSR,
1741c00289eSTomer Maimon timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
1751c00289eSTomer Maimon writel(NPCM7XX_Tx_MAX_CNT,
1761c00289eSTomer Maimon timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TICR1);
1771c00289eSTomer Maimon
1781c00289eSTomer Maimon val = readl(timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
1791c00289eSTomer Maimon val |= NPCM7XX_START_Tx;
1801c00289eSTomer Maimon writel(val, timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
1811c00289eSTomer Maimon
1821c00289eSTomer Maimon clocksource_mmio_init(timer_of_base(&npcm7xx_to) +
1831c00289eSTomer Maimon NPCM7XX_REG_TDR1,
1841c00289eSTomer Maimon "npcm7xx-timer1", timer_of_rate(&npcm7xx_to),
1851c00289eSTomer Maimon 200, (unsigned int)NPCM7XX_Tx_TDR_MASK_BITS,
1861c00289eSTomer Maimon clocksource_mmio_readl_down);
1871c00289eSTomer Maimon }
1881c00289eSTomer Maimon
npcm7xx_timer_init(struct device_node * np)1891c00289eSTomer Maimon static int __init npcm7xx_timer_init(struct device_node *np)
1901c00289eSTomer Maimon {
191*db78539fSJonathan Neuschäfer struct clk *clk;
1921c00289eSTomer Maimon int ret;
1931c00289eSTomer Maimon
1941c00289eSTomer Maimon ret = timer_of_init(np, &npcm7xx_to);
1951c00289eSTomer Maimon if (ret)
1961c00289eSTomer Maimon return ret;
1971c00289eSTomer Maimon
1981c00289eSTomer Maimon /* Clock input is divided by PRESCALE + 1 before it is fed */
1991c00289eSTomer Maimon /* to the counter */
2001c00289eSTomer Maimon npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate /
2011c00289eSTomer Maimon (NPCM7XX_Tx_MIN_PRESCALE + 1);
2021c00289eSTomer Maimon
203*db78539fSJonathan Neuschäfer /* Enable the clock for timer1, if it exists */
204*db78539fSJonathan Neuschäfer clk = of_clk_get(np, 1);
205*db78539fSJonathan Neuschäfer if (clk) {
206*db78539fSJonathan Neuschäfer if (!IS_ERR(clk))
207*db78539fSJonathan Neuschäfer clk_prepare_enable(clk);
208*db78539fSJonathan Neuschäfer else
209*db78539fSJonathan Neuschäfer pr_warn("%pOF: Failed to get clock for timer1: %pe", np, clk);
210*db78539fSJonathan Neuschäfer }
211*db78539fSJonathan Neuschäfer
2121c00289eSTomer Maimon npcm7xx_clocksource_init();
2131c00289eSTomer Maimon npcm7xx_clockevents_init();
2141c00289eSTomer Maimon
2151c00289eSTomer Maimon pr_info("Enabling NPCM7xx clocksource timer base: %px, IRQ: %d ",
2161c00289eSTomer Maimon timer_of_base(&npcm7xx_to), timer_of_irq(&npcm7xx_to));
2171c00289eSTomer Maimon
2181c00289eSTomer Maimon return 0;
2191c00289eSTomer Maimon }
2201c00289eSTomer Maimon
221690daddcSJonathan Neuschäfer TIMER_OF_DECLARE(wpcm450, "nuvoton,wpcm450-timer", npcm7xx_timer_init);
2221c00289eSTomer Maimon TIMER_OF_DECLARE(npcm7xx, "nuvoton,npcm750-timer", npcm7xx_timer_init);
2231c00289eSTomer Maimon
224