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-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *		http://www.samsung.com/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * samsung - Common hr-timer support (s3c and s5p)
^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/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/clockchips.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/of.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/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/sched_clock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <clocksource/samsung_pwm.h>
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * Clocksource driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define REG_TCFG0			0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define REG_TCFG1			0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define REG_TCON			0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define REG_TINT_CSTAT			0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define REG_TCNTB(chan)			(0x0c + 12 * (chan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define REG_TCMPB(chan)			(0x10 + 12 * (chan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define TCFG0_PRESCALER_MASK		0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define TCFG0_PRESCALER1_SHIFT		8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define TCFG1_SHIFT(x)	  		((x) * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define TCFG1_MUX_MASK	  		0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * Each channel occupies 4 bits in TCON register, but there is a gap of 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * bits (one channel) after channel 0, so channels have different numbering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * when accessing TCON register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * In addition, the location of autoreload bit for channel 4 (TCON channel 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * in its set of bits is 2 as opposed to 3 for other channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define TCON_START(chan)		(1 << (4 * (chan) + 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) #define TCON_MANUALUPDATE(chan)		(1 << (4 * (chan) + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define TCON_INVERT(chan)		(1 << (4 * (chan) + 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define _TCON_AUTORELOAD(chan)		(1 << (4 * (chan) + 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define _TCON_AUTORELOAD4(chan)		(1 << (4 * (chan) + 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define TCON_AUTORELOAD(chan)		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	((chan < 5) ? _TCON_AUTORELOAD(chan) : _TCON_AUTORELOAD4(chan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) DEFINE_SPINLOCK(samsung_pwm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) EXPORT_SYMBOL(samsung_pwm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) struct samsung_pwm_clocksource {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	void __iomem *source_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	unsigned int irq[SAMSUNG_PWM_NUM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	struct samsung_pwm_variant variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	struct clk *timerclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	unsigned int event_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	unsigned int source_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	unsigned int tcnt_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	unsigned int tscaler_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	unsigned int tdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	unsigned long clock_count_per_tick;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) static struct samsung_pwm_clocksource pwm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) static void samsung_timer_set_prescale(unsigned int channel, u16 prescale)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	u8 shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	if (channel >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		shift = TCFG0_PRESCALER1_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	spin_lock_irqsave(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	reg = readl(pwm.base + REG_TCFG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	reg &= ~(TCFG0_PRESCALER_MASK << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	reg |= (prescale - 1) << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	writel(reg, pwm.base + REG_TCFG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void samsung_timer_set_divisor(unsigned int channel, u8 divisor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	u8 shift = TCFG1_SHIFT(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	u8 bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	bits = (fls(divisor) - 1) - pwm.variant.div_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	spin_lock_irqsave(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	reg = readl(pwm.base + REG_TCFG1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	reg &= ~(TCFG1_MUX_MASK << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	reg |= bits << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	writel(reg, pwm.base + REG_TCFG1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static void samsung_time_stop(unsigned int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	unsigned long tcon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	if (channel > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		++channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	spin_lock_irqsave(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	tcon = readl_relaxed(pwm.base + REG_TCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	tcon &= ~TCON_START(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	writel_relaxed(tcon, pwm.base + REG_TCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static void samsung_time_setup(unsigned int channel, unsigned long tcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	unsigned long tcon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	unsigned int tcon_chan = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (tcon_chan > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		++tcon_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	spin_lock_irqsave(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	tcon = readl_relaxed(pwm.base + REG_TCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	tcon &= ~(TCON_START(tcon_chan) | TCON_AUTORELOAD(tcon_chan));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	tcon |= TCON_MANUALUPDATE(tcon_chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	writel_relaxed(tcnt, pwm.base + REG_TCNTB(channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	writel_relaxed(tcnt, pwm.base + REG_TCMPB(channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	writel_relaxed(tcon, pwm.base + REG_TCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void samsung_time_start(unsigned int channel, bool periodic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	unsigned long tcon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if (channel > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		++channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	spin_lock_irqsave(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	tcon = readl_relaxed(pwm.base + REG_TCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	tcon &= ~TCON_MANUALUPDATE(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	tcon |= TCON_START(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (periodic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		tcon |= TCON_AUTORELOAD(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		tcon &= ~TCON_AUTORELOAD(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	writel_relaxed(tcon, pwm.base + REG_TCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int samsung_set_next_event(unsigned long cycles,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 				struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	 * This check is needed to account for internal rounding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	 * errors inside clockevents core, which might result in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	 * passing cycles = 0, which in turn would not generate any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	 * timer interrupt and hang the system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	 * Another solution would be to set up the clockevent device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	 * with min_delta = 2, but this would unnecessarily increase
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	 * the minimum sleep period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	if (!cycles)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		cycles = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	samsung_time_setup(pwm.event_id, cycles);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	samsung_time_start(pwm.event_id, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int samsung_shutdown(struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	samsung_time_stop(pwm.event_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int samsung_set_periodic(struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	samsung_time_stop(pwm.event_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	samsung_time_setup(pwm.event_id, pwm.clock_count_per_tick - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	samsung_time_start(pwm.event_id, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void samsung_clockevent_resume(struct clock_event_device *cev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	samsung_timer_set_prescale(pwm.event_id, pwm.tscaler_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	samsung_timer_set_divisor(pwm.event_id, pwm.tdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (pwm.variant.has_tint_cstat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		u32 mask = (1 << pwm.event_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		writel(mask | (mask << 5), pwm.base + REG_TINT_CSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static struct clock_event_device time_event_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	.name			= "samsung_event_timer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	.features		= CLOCK_EVT_FEAT_PERIODIC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 				  CLOCK_EVT_FEAT_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	.rating			= 200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	.set_next_event		= samsung_set_next_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	.set_state_shutdown	= samsung_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	.set_state_periodic	= samsung_set_periodic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	.set_state_oneshot	= samsung_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	.tick_resume		= samsung_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	.resume			= samsung_clockevent_resume,
^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) static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	struct clock_event_device *evt = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	if (pwm.variant.has_tint_cstat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		u32 mask = (1 << pwm.event_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		writel(mask | (mask << 5), pwm.base + REG_TINT_CSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	evt->event_handler(evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static void __init samsung_clockevent_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	unsigned long pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	unsigned long clock_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	unsigned int irq_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	pclk = clk_get_rate(pwm.timerclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	samsung_timer_set_prescale(pwm.event_id, pwm.tscaler_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	samsung_timer_set_divisor(pwm.event_id, pwm.tdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	clock_rate = pclk / (pwm.tscaler_div * pwm.tdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	pwm.clock_count_per_tick = clock_rate / HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	time_event_device.cpumask = cpumask_of(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	clockevents_config_and_register(&time_event_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 						clock_rate, 1, pwm.tcnt_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	irq_number = pwm.irq[pwm.event_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	if (request_irq(irq_number, samsung_clock_event_isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 			IRQF_TIMER | IRQF_IRQPOLL, "samsung_time_irq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 			&time_event_device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		pr_err("%s: request_irq() failed\n", "samsung_time_irq");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (pwm.variant.has_tint_cstat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		u32 mask = (1 << pwm.event_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		writel(mask | (mask << 5), pwm.base + REG_TINT_CSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static void samsung_clocksource_suspend(struct clocksource *cs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	samsung_time_stop(pwm.source_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static void samsung_clocksource_resume(struct clocksource *cs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	samsung_timer_set_prescale(pwm.source_id, pwm.tscaler_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	samsung_timer_set_divisor(pwm.source_id, pwm.tdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	samsung_time_setup(pwm.source_id, pwm.tcnt_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	samsung_time_start(pwm.source_id, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static u64 notrace samsung_clocksource_read(struct clocksource *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	return ~readl_relaxed(pwm.source_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static struct clocksource samsung_clocksource = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	.name		= "samsung_clocksource_timer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	.rating		= 250,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	.read		= samsung_clocksource_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	.suspend	= samsung_clocksource_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	.resume		= samsung_clocksource_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)  * Override the global weak sched_clock symbol with this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)  * local implementation which uses the clocksource to get some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)  * better resolution when scheduling the kernel. We accept that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)  * this wraps around for now, since it is just a relative time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)  * stamp. (Inspired by U300 implementation.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static u64 notrace samsung_read_sched_clock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	return samsung_clocksource_read(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static int __init samsung_clocksource_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	unsigned long pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	unsigned long clock_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	pclk = clk_get_rate(pwm.timerclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	samsung_timer_set_prescale(pwm.source_id, pwm.tscaler_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	samsung_timer_set_divisor(pwm.source_id, pwm.tdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	clock_rate = pclk / (pwm.tscaler_div * pwm.tdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	samsung_time_setup(pwm.source_id, pwm.tcnt_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	samsung_time_start(pwm.source_id, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	if (pwm.source_id == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		pwm.source_reg = pwm.base + 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		pwm.source_reg = pwm.base + pwm.source_id * 0x0c + 0x14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	sched_clock_register(samsung_read_sched_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 						pwm.variant.bits, clock_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	samsung_clocksource.mask = CLOCKSOURCE_MASK(pwm.variant.bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	return clocksource_register_hz(&samsung_clocksource, clock_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void __init samsung_timer_resources(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	clk_prepare_enable(pwm.timerclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	pwm.tcnt_max = (1UL << pwm.variant.bits) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	if (pwm.variant.bits == 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		pwm.tscaler_div = 25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		pwm.tdiv = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		pwm.tscaler_div = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		pwm.tdiv = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)  * PWM master driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static int __init _samsung_pwm_clocksource_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	u8 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	mask = ~pwm.variant.output_mask & ((1 << SAMSUNG_PWM_NUM) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	channel = fls(mask) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	if (channel < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		pr_crit("failed to find PWM channel for clocksource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	pwm.source_id = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	mask &= ~(1 << channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	channel = fls(mask) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (channel < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		pr_crit("failed to find PWM channel for clock event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	pwm.event_id = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	samsung_timer_resources();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	samsung_clockevent_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	return samsung_clocksource_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) void __init samsung_pwm_clocksource_init(void __iomem *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 			unsigned int *irqs, struct samsung_pwm_variant *variant)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	pwm.base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	memcpy(&pwm.variant, variant, sizeof(pwm.variant));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	memcpy(pwm.irq, irqs, SAMSUNG_PWM_NUM * sizeof(*irqs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	pwm.timerclk = clk_get(NULL, "timers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	if (IS_ERR(pwm.timerclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		panic("failed to get timers clock for timer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	_samsung_pwm_clocksource_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) #ifdef CONFIG_TIMER_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static int __init samsung_pwm_alloc(struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 				    const struct samsung_pwm_variant *variant)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	const __be32 *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	memcpy(&pwm.variant, variant, sizeof(pwm.variant));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	for (i = 0; i < SAMSUNG_PWM_NUM; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		pwm.irq[i] = irq_of_parse_and_map(np, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	of_property_for_each_u32(np, "samsung,pwm-outputs", prop, cur, val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		if (val >= SAMSUNG_PWM_NUM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 			pr_warn("%s: invalid channel index in samsung,pwm-outputs property\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		pwm.variant.output_mask |= 1 << val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	pwm.base = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	if (!pwm.base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		pr_err("%s: failed to map PWM registers\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	pwm.timerclk = of_clk_get_by_name(np, "timers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	if (IS_ERR(pwm.timerclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		pr_crit("failed to get timers clock for timer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		return PTR_ERR(pwm.timerclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	return _samsung_pwm_clocksource_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static const struct samsung_pwm_variant s3c24xx_variant = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	.bits		= 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	.div_base	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	.has_tint_cstat	= false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	.tclk_mask	= (1 << 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static int __init s3c2410_pwm_clocksource_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	return samsung_pwm_alloc(np, &s3c24xx_variant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) TIMER_OF_DECLARE(s3c2410_pwm, "samsung,s3c2410-pwm", s3c2410_pwm_clocksource_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static const struct samsung_pwm_variant s3c64xx_variant = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	.bits		= 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	.div_base	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	.has_tint_cstat	= true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	.tclk_mask	= (1 << 7) | (1 << 6) | (1 << 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static int __init s3c64xx_pwm_clocksource_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	return samsung_pwm_alloc(np, &s3c64xx_variant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) TIMER_OF_DECLARE(s3c6400_pwm, "samsung,s3c6400-pwm", s3c64xx_pwm_clocksource_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static const struct samsung_pwm_variant s5p64x0_variant = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	.bits		= 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	.div_base	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	.has_tint_cstat	= true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	.tclk_mask	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static int __init s5p64x0_pwm_clocksource_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	return samsung_pwm_alloc(np, &s5p64x0_variant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) TIMER_OF_DECLARE(s5p6440_pwm, "samsung,s5p6440-pwm", s5p64x0_pwm_clocksource_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static const struct samsung_pwm_variant s5p_variant = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	.bits		= 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	.div_base	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	.has_tint_cstat	= true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	.tclk_mask	= (1 << 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static int __init s5p_pwm_clocksource_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	return samsung_pwm_alloc(np, &s5p_variant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) TIMER_OF_DECLARE(s5pc100_pwm, "samsung,s5pc100-pwm", s5p_pwm_clocksource_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) #endif