^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