xref: /openbmc/linux/drivers/clocksource/timer-npcm7xx.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
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