Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) // Copyright (C) 2005-2017 Andes Technology Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *  Andestech ATCPIT100 Timer Device Driver Implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/clocksource.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/clockchips.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/sched_clock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "timer-of.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #ifdef CONFIG_NDS32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <asm/vdso_timer_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * Definition of register offsets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) /* ID and Revision Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define ID_REV		0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) /* Configuration Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define CFG		0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) /* Interrupt Enable Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define INT_EN		0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define CH_INT_EN(c, i)	((1<<i)<<(4*c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define CH0INT0EN	0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /* Interrupt Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define INT_STA		0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define CH0INT0		0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) /* Channel Enable Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define CH_EN		0x1C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define CH0TMR0EN	0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define CH1TMR0EN	0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) /* Channel 0 , 1 Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #define CH0_CTL		(0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define CH1_CTL		(0x20 + 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) /* Channel clock source , bit 3 , 0:External clock , 1:APB clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define APB_CLK		BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) /* Channel mode , bit 0~2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define TMR_32		0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) #define TMR_16		0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) #define TMR_8		0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) /* Channel 0 , 1 Reload Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) #define CH0_REL		(0x24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) #define CH1_REL		(0x24 + 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) /* Channel 0 , 1 Counter Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) #define CH0_CNT		(0x28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define CH1_CNT		(0x28 + 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #define TIMER_SYNC_TICKS	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) static void atcpit100_ch1_tmr0_en(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	writel(~0, base + CH1_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	writel(APB_CLK|TMR_32, base + CH1_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static void atcpit100_ch0_tmr0_en(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	writel(APB_CLK|TMR_32, base + CH0_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) static void atcpit100_clkevt_time_setup(void __iomem *base, unsigned long delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	writel(delay, base + CH0_CNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	writel(delay, base + CH0_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static void atcpit100_timer_clear_interrupt(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	val = readl(base + INT_STA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	writel(val | CH0INT0, base + INT_STA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) static void atcpit100_clocksource_start(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	val = readl(base + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	writel(val | CH1TMR0EN, base + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void atcpit100_clkevt_time_start(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	val = readl(base + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	writel(val | CH0TMR0EN, base + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void atcpit100_clkevt_time_stop(void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	atcpit100_timer_clear_interrupt(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	val = readl(base + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	writel(val & ~CH0TMR0EN, base + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int atcpit100_clkevt_next_event(unsigned long evt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	struct clock_event_device *clkevt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	struct timer_of *to = to_timer_of(clkevt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	val = readl(timer_of_base(to) + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	writel(val & ~CH0TMR0EN, timer_of_base(to) + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	writel(evt, timer_of_base(to) + CH0_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	writel(val | CH0TMR0EN, timer_of_base(to) + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int atcpit100_clkevt_set_periodic(struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	struct timer_of *to = to_timer_of(evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	atcpit100_clkevt_time_setup(timer_of_base(to), timer_of_period(to));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	atcpit100_clkevt_time_start(timer_of_base(to));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int atcpit100_clkevt_shutdown(struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	struct timer_of *to = to_timer_of(evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	atcpit100_clkevt_time_stop(timer_of_base(to));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static int atcpit100_clkevt_set_oneshot(struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	struct timer_of *to = to_timer_of(evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	writel(~0x0, timer_of_base(to) + CH0_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	val = readl(timer_of_base(to) + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	writel(val | CH0TMR0EN, timer_of_base(to) + CH_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static irqreturn_t atcpit100_timer_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	struct clock_event_device *evt = (struct clock_event_device *)dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	struct timer_of *to = to_timer_of(evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	atcpit100_timer_clear_interrupt(timer_of_base(to));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	evt->event_handler(evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct timer_of to = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	.flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	.clkevt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		.name = "atcpit100_tick",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		.rating = 300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		.set_state_shutdown = atcpit100_clkevt_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		.set_state_periodic = atcpit100_clkevt_set_periodic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		.set_state_oneshot = atcpit100_clkevt_set_oneshot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		.tick_resume = atcpit100_clkevt_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		.set_next_event = atcpit100_clkevt_next_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		.cpumask = cpu_possible_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	.of_irq = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		.handler = atcpit100_timer_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		.flags = IRQF_TIMER | IRQF_IRQPOLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	 * FIXME: we currently only support clocking using PCLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	 * and using EXTCLK is not supported in the driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	.of_clk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		.name = "PCLK",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static u64 notrace atcpit100_timer_sched_read(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	return ~readl(timer_of_base(&to) + CH1_CNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #ifdef CONFIG_NDS32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static void fill_vdso_need_info(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	struct resource timer_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	of_address_to_resource(node, 0, &timer_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	timer_info.mapping_base = (unsigned long)timer_res.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	timer_info.cycle_count_down = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	timer_info.cycle_count_reg_offset = CH1_CNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int __init atcpit100_timer_init(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	ret = timer_of_init(node, &to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	base = timer_of_base(&to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	sched_clock_register(atcpit100_timer_sched_read, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		timer_of_rate(&to));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	ret = clocksource_mmio_init(base + CH1_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		node->name, timer_of_rate(&to), 300, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		clocksource_mmio_readl_down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		pr_err("Failed to register clocksource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	/* clear channel 0 timer0 interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	atcpit100_timer_clear_interrupt(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	clockevents_config_and_register(&to.clkevt, timer_of_rate(&to),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 					TIMER_SYNC_TICKS, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	atcpit100_ch0_tmr0_en(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	atcpit100_ch1_tmr0_en(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	atcpit100_clocksource_start(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	atcpit100_clkevt_time_start(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	/* Enable channel 0 timer0 interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	val = readl(base + INT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	writel(val | CH0INT0EN, base + INT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) #ifdef CONFIG_NDS32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	fill_vdso_need_info(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) TIMER_OF_DECLARE(atcpit100, "andestech,atcpit100", atcpit100_timer_init);