Linux Audio

Check our new training course

Loading...
v6.8
  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
 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	val |= NPCM7XX_START_ONESHOT_Tx;
 88	writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
 89
 90	return 0;
 91}
 92
 93static 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
108static 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
122static 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
134static 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
155static 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
169static 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
189static int __init npcm7xx_timer_init(struct device_node *np)
190{
191	struct clk *clk;
192	int ret;
193
194	ret = timer_of_init(np, &npcm7xx_to);
195	if (ret)
196		return ret;
197
198	/* Clock input is divided by PRESCALE + 1 before it is fed */
199	/* to the counter */
200	npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate /
201		(NPCM7XX_Tx_MIN_PRESCALE + 1);
202
203	/* Enable the clock for timer1, if it exists */
204	clk = of_clk_get(np, 1);
205	if (clk) {
206		if (!IS_ERR(clk))
207			clk_prepare_enable(clk);
208		else
209			pr_warn("%pOF: Failed to get clock for timer1: %pe", np, clk);
210	}
211
212	npcm7xx_clocksource_init();
213	npcm7xx_clockevents_init();
214
215	pr_info("Enabling NPCM7xx clocksource timer base: %px, IRQ: %d ",
216		timer_of_base(&npcm7xx_to), timer_of_irq(&npcm7xx_to));
217
218	return 0;
219}
220
221TIMER_OF_DECLARE(wpcm450, "nuvoton,wpcm450-timer", npcm7xx_timer_init);
222TIMER_OF_DECLARE(npcm7xx, "nuvoton,npcm750-timer", npcm7xx_timer_init);
223
v5.4
  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
 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	val |= NPCM7XX_START_ONESHOT_Tx;
 88	writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
 89
 90	return 0;
 91}
 92
 93static 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
108static 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
122static 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
134static 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
155static 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
169static 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
189static 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
 
211TIMER_OF_DECLARE(npcm7xx, "nuvoton,npcm750-timer", npcm7xx_timer_init);
212