diff options
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/hyperv_timer.c | 1 | ||||
-rw-r--r-- | drivers/clocksource/timer-orion.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/timer-stm32-lp.c | 61 |
4 files changed, 60 insertions, 6 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 981a578043a5..80ba6a54248c 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -243,7 +243,7 @@ static u64 arch_counter_read(struct clocksource *cs) return arch_timer_read_counter(); } -static u64 arch_counter_read_cc(const struct cyclecounter *cc) +static u64 arch_counter_read_cc(struct cyclecounter *cc) { return arch_timer_read_counter(); } diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index 09549451dd51..2edc13ca184e 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -22,6 +22,7 @@ #include <linux/irq.h> #include <linux/acpi.h> #include <linux/hyperv.h> +#include <linux/export.h> #include <clocksource/hyperv_timer.h> #include <hyperv/hvhdk.h> #include <asm/mshyperv.h> diff --git a/drivers/clocksource/timer-orion.c b/drivers/clocksource/timer-orion.c index 49e86cb70a7a..61f1e27fc41e 100644 --- a/drivers/clocksource/timer-orion.c +++ b/drivers/clocksource/timer-orion.c @@ -43,7 +43,7 @@ static struct delay_timer orion_delay_timer = { .read_current_timer = orion_read_timer, }; -static void orion_delay_timer_init(unsigned long rate) +static void __init orion_delay_timer_init(unsigned long rate) { orion_delay_timer.freq = rate; register_current_timer_delay(&orion_delay_timer); diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c index 928da2f6de69..6e7944ffd7c0 100644 --- a/drivers/clocksource/timer-stm32-lp.c +++ b/drivers/clocksource/timer-stm32-lp.c @@ -5,6 +5,7 @@ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics. */ +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/clockchips.h> #include <linux/interrupt.h> @@ -27,6 +28,7 @@ struct stm32_lp_private { u32 psc; struct device *dev; struct clk *clk; + u32 version; }; static struct stm32_lp_private* @@ -47,12 +49,46 @@ static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt) return 0; } -static int stm32_clkevent_lp_set_timer(unsigned long evt, - struct clock_event_device *clkevt, - int is_periodic) +static int stm32mp25_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt) { - struct stm32_lp_private *priv = to_priv(clkevt); + int ret; + u32 val; + + regmap_read(priv->reg, STM32_LPTIM_CR, &val); + if (!FIELD_GET(STM32_LPTIM_ENABLE, val)) { + /* Enable LPTIMER to be able to write into IER and ARR registers */ + regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); + /* + * After setting the ENABLE bit, a delay of two counter clock cycles is needed + * before the LPTIM is actually enabled. For 32KHz rate, this makes approximately + * 62.5 micro-seconds, round it up. + */ + udelay(63); + } + /* set next event counter */ + regmap_write(priv->reg, STM32_LPTIM_ARR, evt); + /* enable ARR interrupt */ + regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE); + + /* Poll DIEROK and ARROK to ensure register access has completed */ + ret = regmap_read_poll_timeout_atomic(priv->reg, STM32_LPTIM_ISR, val, + (val & STM32_LPTIM_DIEROK_ARROK) == + STM32_LPTIM_DIEROK_ARROK, + 10, 500); + if (ret) { + dev_err(priv->dev, "access to LPTIM timed out\n"); + /* Disable LPTIMER */ + regmap_write(priv->reg, STM32_LPTIM_CR, 0); + return ret; + } + /* Clear DIEROK and ARROK flags */ + regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_DIEROKCF_ARROKCF); + return 0; +} + +static void stm32_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt) +{ /* disable LPTIMER to be able to write into IER register*/ regmap_write(priv->reg, STM32_LPTIM_CR, 0); /* enable ARR interrupt */ @@ -61,6 +97,22 @@ static int stm32_clkevent_lp_set_timer(unsigned long evt, regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); /* set next event counter */ regmap_write(priv->reg, STM32_LPTIM_ARR, evt); +} + +static int stm32_clkevent_lp_set_timer(unsigned long evt, + struct clock_event_device *clkevt, + int is_periodic) +{ + struct stm32_lp_private *priv = to_priv(clkevt); + int ret; + + if (priv->version == STM32_LPTIM_VERR_23) { + ret = stm32mp25_clkevent_lp_set_evt(priv, evt); + if (ret) + return ret; + } else { + stm32_clkevent_lp_set_evt(priv, evt); + } /* start counter */ if (is_periodic) @@ -176,6 +228,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev) return -ENOMEM; priv->reg = ddata->regmap; + priv->version = ddata->version; priv->clk = ddata->clk; ret = clk_prepare_enable(priv->clk); if (ret) |