Lines Matching +full:poll +full:- +full:period
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
12 #include <linux/mfd/stm32-lptimer.h>
27 unsigned long period; member
44 regmap_write(priv->reg, STM32_LPTIM_CR, 0); in stm32_clkevent_lp_shutdown()
45 regmap_write(priv->reg, STM32_LPTIM_IER, 0); in stm32_clkevent_lp_shutdown()
47 regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); in stm32_clkevent_lp_shutdown()
57 regmap_read(priv->reg, STM32_LPTIM_CR, &val); in stm32mp25_clkevent_lp_set_evt()
60 regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); in stm32mp25_clkevent_lp_set_evt()
64 * 62.5 micro-seconds, round it up. in stm32mp25_clkevent_lp_set_evt()
69 regmap_write(priv->reg, STM32_LPTIM_ARR, evt); in stm32mp25_clkevent_lp_set_evt()
71 regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE); in stm32mp25_clkevent_lp_set_evt()
73 /* Poll DIEROK and ARROK to ensure register access has completed */ in stm32mp25_clkevent_lp_set_evt()
74 ret = regmap_read_poll_timeout_atomic(priv->reg, STM32_LPTIM_ISR, val, in stm32mp25_clkevent_lp_set_evt()
79 dev_err(priv->dev, "access to LPTIM timed out\n"); in stm32mp25_clkevent_lp_set_evt()
81 regmap_write(priv->reg, STM32_LPTIM_CR, 0); in stm32mp25_clkevent_lp_set_evt()
85 regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_DIEROKCF_ARROKCF); in stm32mp25_clkevent_lp_set_evt()
93 regmap_write(priv->reg, STM32_LPTIM_CR, 0); in stm32_clkevent_lp_set_evt()
95 regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE); in stm32_clkevent_lp_set_evt()
97 regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); in stm32_clkevent_lp_set_evt()
99 regmap_write(priv->reg, STM32_LPTIM_ARR, evt); in stm32_clkevent_lp_set_evt()
109 if (priv->version == STM32_LPTIM_VERR_23) { in stm32_clkevent_lp_set_timer()
119 regmap_write(priv->reg, STM32_LPTIM_CR, in stm32_clkevent_lp_set_timer()
122 regmap_write(priv->reg, STM32_LPTIM_CR, in stm32_clkevent_lp_set_timer()
139 return stm32_clkevent_lp_set_timer(priv->period, clkevt, true); in stm32_clkevent_lp_set_periodic()
146 return stm32_clkevent_lp_set_timer(priv->period, clkevt, false); in stm32_clkevent_lp_set_oneshot()
154 regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); in stm32_clkevent_lp_irq_handler()
156 if (clkevt->event_handler) in stm32_clkevent_lp_irq_handler()
157 clkevt->event_handler(clkevt); in stm32_clkevent_lp_irq_handler()
172 regmap_write(priv->reg, STM32_LPTIM_CFGR, i << CFGR_PSC_OFFSET); in stm32_clkevent_lp_set_prescaler()
174 /* Adjust rate and period given the prescaler value */ in stm32_clkevent_lp_set_prescaler()
176 priv->period = DIV_ROUND_UP(*rate, HZ); in stm32_clkevent_lp_set_prescaler()
177 priv->psc = i; in stm32_clkevent_lp_set_prescaler()
187 clk_disable_unprepare(priv->clk); in stm32_clkevent_lp_suspend()
194 clk_prepare_enable(priv->clk); in stm32_clkevent_lp_resume()
197 regmap_write(priv->reg, STM32_LPTIM_CFGR, priv->psc << CFGR_PSC_OFFSET); in stm32_clkevent_lp_resume()
203 priv->clkevt.name = np->full_name; in stm32_clkevent_lp_init()
204 priv->clkevt.cpumask = cpu_possible_mask; in stm32_clkevent_lp_init()
205 priv->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | in stm32_clkevent_lp_init()
207 priv->clkevt.set_state_shutdown = stm32_clkevent_lp_shutdown; in stm32_clkevent_lp_init()
208 priv->clkevt.set_state_periodic = stm32_clkevent_lp_set_periodic; in stm32_clkevent_lp_init()
209 priv->clkevt.set_state_oneshot = stm32_clkevent_lp_set_oneshot; in stm32_clkevent_lp_init()
210 priv->clkevt.set_next_event = stm32_clkevent_lp_set_next_event; in stm32_clkevent_lp_init()
211 priv->clkevt.rating = STM32_LP_RATING; in stm32_clkevent_lp_init()
212 priv->clkevt.suspend = stm32_clkevent_lp_suspend; in stm32_clkevent_lp_init()
213 priv->clkevt.resume = stm32_clkevent_lp_resume; in stm32_clkevent_lp_init()
215 clockevents_config_and_register(&priv->clkevt, rate, 0x1, in stm32_clkevent_lp_init()
221 struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent); in stm32_clkevent_lp_probe()
226 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in stm32_clkevent_lp_probe()
228 return -ENOMEM; in stm32_clkevent_lp_probe()
230 priv->reg = ddata->regmap; in stm32_clkevent_lp_probe()
231 priv->version = ddata->version; in stm32_clkevent_lp_probe()
232 priv->clk = ddata->clk; in stm32_clkevent_lp_probe()
233 ret = clk_prepare_enable(priv->clk); in stm32_clkevent_lp_probe()
235 return -EINVAL; in stm32_clkevent_lp_probe()
237 rate = clk_get_rate(priv->clk); in stm32_clkevent_lp_probe()
239 ret = -EINVAL; in stm32_clkevent_lp_probe()
243 irq = platform_get_irq(to_platform_device(pdev->dev.parent), 0); in stm32_clkevent_lp_probe()
249 if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) { in stm32_clkevent_lp_probe()
250 device_set_wakeup_capable(&pdev->dev, true); in stm32_clkevent_lp_probe()
252 ret = dev_pm_set_wake_irq(&pdev->dev, irq); in stm32_clkevent_lp_probe()
257 ret = devm_request_irq(&pdev->dev, irq, stm32_clkevent_lp_irq_handler, in stm32_clkevent_lp_probe()
258 IRQF_TIMER, pdev->name, &priv->clkevt); in stm32_clkevent_lp_probe()
264 stm32_clkevent_lp_init(priv, pdev->dev.parent->of_node, rate); in stm32_clkevent_lp_probe()
266 priv->dev = &pdev->dev; in stm32_clkevent_lp_probe()
271 clk_disable_unprepare(priv->clk); in stm32_clkevent_lp_probe()
276 { .compatible = "st,stm32-lptimer-timer", },
284 .name = "stm32-lptimer-timer",
291 MODULE_ALIAS("platform:stm32-lptimer-timer");