mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
clocksource/drivers/samsung_pwm: Switch to raw_spinlock_t type
Samsung PWM timer might be used as a clock source on some legacy systems. When PREEMPT_RT is enabled on ARM, regular spinlock is converted to a sleeping lock (mutex-based), which must not be used in atomic context such as hard interrupt handlers. Switch the samsung_pwm_lock to the raw_spinlock, which remains a true non-sleeping spinlock even under PREEMPT_RT. Fixes:7aac482e62("clocksource: samsung_pwm_timer: Make PWM spinlock global") Fixes:f11899894c("clocksource: add samsung pwm timer driver") Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com> Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Uwe Kleine-König <ukleinek@kernel.org> Link: https://patch.msgid.link/20260713085653.1145015-1-m.szyprowski@samsung.com
This commit is contained in:
parent
e998c6300e
commit
3b212f9d70
|
|
@ -56,7 +56,7 @@
|
|||
#define TCON_AUTORELOAD(chan) \
|
||||
((chan < 5) ? _TCON_AUTORELOAD(chan) : _TCON_AUTORELOAD4(chan))
|
||||
|
||||
DEFINE_SPINLOCK(samsung_pwm_lock);
|
||||
DEFINE_RAW_SPINLOCK(samsung_pwm_lock);
|
||||
EXPORT_SYMBOL(samsung_pwm_lock);
|
||||
|
||||
struct samsung_pwm_clocksource {
|
||||
|
|
@ -87,14 +87,14 @@ static void samsung_timer_set_prescale(unsigned int channel, u16 prescale)
|
|||
if (channel >= 2)
|
||||
shift = TCFG0_PRESCALER1_SHIFT;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
reg = readl(pwm.base + REG_TCFG0);
|
||||
reg &= ~(TCFG0_PRESCALER_MASK << shift);
|
||||
reg |= (prescale - 1) << shift;
|
||||
writel(reg, pwm.base + REG_TCFG0);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
}
|
||||
|
||||
static void samsung_timer_set_divisor(unsigned int channel, u8 divisor)
|
||||
|
|
@ -106,14 +106,14 @@ static void samsung_timer_set_divisor(unsigned int channel, u8 divisor)
|
|||
|
||||
bits = (fls(divisor) - 1) - pwm.variant.div_base;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
reg = readl(pwm.base + REG_TCFG1);
|
||||
reg &= ~(TCFG1_MUX_MASK << shift);
|
||||
reg |= bits << shift;
|
||||
writel(reg, pwm.base + REG_TCFG1);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
}
|
||||
|
||||
static void samsung_time_stop(unsigned int channel)
|
||||
|
|
@ -124,13 +124,13 @@ static void samsung_time_stop(unsigned int channel)
|
|||
if (channel > 0)
|
||||
++channel;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
tcon = readl_relaxed(pwm.base + REG_TCON);
|
||||
tcon &= ~TCON_START(channel);
|
||||
writel_relaxed(tcon, pwm.base + REG_TCON);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
}
|
||||
|
||||
static void samsung_time_setup(unsigned int channel, unsigned long tcnt)
|
||||
|
|
@ -142,7 +142,7 @@ static void samsung_time_setup(unsigned int channel, unsigned long tcnt)
|
|||
if (tcon_chan > 0)
|
||||
++tcon_chan;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
tcon = readl_relaxed(pwm.base + REG_TCON);
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ static void samsung_time_setup(unsigned int channel, unsigned long tcnt)
|
|||
writel_relaxed(tcnt, pwm.base + REG_TCMPB(channel));
|
||||
writel_relaxed(tcon, pwm.base + REG_TCON);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
}
|
||||
|
||||
static void samsung_time_start(unsigned int channel, bool periodic)
|
||||
|
|
@ -164,7 +164,7 @@ static void samsung_time_start(unsigned int channel, bool periodic)
|
|||
if (channel > 0)
|
||||
++channel;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
tcon = readl_relaxed(pwm.base + REG_TCON);
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ static void samsung_time_start(unsigned int channel, bool periodic)
|
|||
|
||||
writel_relaxed(tcon, pwm.base + REG_TCON);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
}
|
||||
|
||||
static int samsung_set_next_event(unsigned long cycles,
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ struct samsung_pwm_chip {
|
|||
* IP. Should this change, both drivers will need to be modified to
|
||||
* properly synchronize accesses to particular instances.
|
||||
*/
|
||||
static DEFINE_SPINLOCK(samsung_pwm_lock);
|
||||
static DEFINE_RAW_SPINLOCK(samsung_pwm_lock);
|
||||
#endif
|
||||
|
||||
static inline
|
||||
|
|
@ -141,14 +141,14 @@ static void pwm_samsung_set_divisor(struct samsung_pwm_chip *our_chip,
|
|||
|
||||
bits = (fls(divisor) - 1) - our_chip->variant.div_base;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
reg = readl(our_chip->base + REG_TCFG1);
|
||||
reg &= ~(TCFG1_MUX_MASK << shift);
|
||||
reg |= bits << shift;
|
||||
writel(reg, our_chip->base + REG_TCFG1);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
}
|
||||
|
||||
static int pwm_samsung_is_tdiv(struct samsung_pwm_chip *our_chip, unsigned int chan)
|
||||
|
|
@ -249,7 +249,7 @@ static int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
|||
unsigned long flags;
|
||||
u32 tcon;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
tcon = readl(our_chip->base + REG_TCON);
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ static int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
|||
|
||||
our_chip->disabled_mask &= ~BIT(pwm->hwpwm);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -275,7 +275,7 @@ static void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
|||
unsigned long flags;
|
||||
u32 tcon;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
tcon = readl(our_chip->base + REG_TCON);
|
||||
tcon &= ~TCON_AUTORELOAD(tcon_chan);
|
||||
|
|
@ -290,7 +290,7 @@ static void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
|||
|
||||
our_chip->disabled_mask |= BIT(pwm->hwpwm);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
}
|
||||
|
||||
static void pwm_samsung_manual_update(struct samsung_pwm_chip *our_chip,
|
||||
|
|
@ -298,11 +298,11 @@ static void pwm_samsung_manual_update(struct samsung_pwm_chip *our_chip,
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
__pwm_samsung_manual_update(our_chip, pwm);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
}
|
||||
|
||||
static int __pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
|
|
@ -390,7 +390,7 @@ static void pwm_samsung_set_invert(struct samsung_pwm_chip *our_chip,
|
|||
unsigned long flags;
|
||||
u32 tcon;
|
||||
|
||||
spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
raw_spin_lock_irqsave(&samsung_pwm_lock, flags);
|
||||
|
||||
tcon = readl(our_chip->base + REG_TCON);
|
||||
|
||||
|
|
@ -404,7 +404,7 @@ static void pwm_samsung_set_invert(struct samsung_pwm_chip *our_chip,
|
|||
|
||||
writel(tcon, our_chip->base + REG_TCON);
|
||||
|
||||
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&samsung_pwm_lock, flags);
|
||||
}
|
||||
|
||||
static int pwm_samsung_set_polarity(struct pwm_chip *chip,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* spinlock is not shared between both drivers.
|
||||
*/
|
||||
#ifdef CONFIG_CLKSRC_SAMSUNG_PWM
|
||||
extern spinlock_t samsung_pwm_lock;
|
||||
extern raw_spinlock_t samsung_pwm_lock;
|
||||
#endif
|
||||
|
||||
struct samsung_pwm_variant {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user