1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) STMicroelectronics 2019 - All Rights Reserved 4 * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. 5 * Pascal Paillet <p.paillet@st.com> for STMicroelectronics. 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/clockchips.h> 10 #include <linux/interrupt.h> 11 #include <linux/mfd/stm32-lptimer.h> 12 #include <linux/module.h> 13 #include <linux/of_address.h> 14 #include <linux/of_irq.h> 15 #include <linux/platform_device.h> 16 #include <linux/pm_wakeirq.h> 17 18 #define CFGR_PSC_OFFSET 9 19 #define STM32_LP_RATING 1000 20 #define STM32_TARGET_CLKRATE (32000 * HZ) 21 #define STM32_LP_MAX_PSC 7 22 23 struct stm32_lp_private { 24 struct regmap *reg; 25 struct clock_event_device clkevt; 26 unsigned long period; 27 u32 psc; 28 struct device *dev; 29 struct clk *clk; 30 }; 31 32 static struct stm32_lp_private* 33 to_priv(struct clock_event_device *clkevt) 34 { 35 return container_of(clkevt, struct stm32_lp_private, clkevt); 36 } 37 38 static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt) 39 { 40 struct stm32_lp_private *priv = to_priv(clkevt); 41 42 regmap_write(priv->reg, STM32_LPTIM_CR, 0); 43 regmap_write(priv->reg, STM32_LPTIM_IER, 0); 44 /* clear pending flags */ 45 regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); 46 47 return 0; 48 } 49 50 static int stm32_clkevent_lp_set_timer(unsigned long evt, 51 struct clock_event_device *clkevt, 52 int is_periodic) 53 { 54 struct stm32_lp_private *priv = to_priv(clkevt); 55 56 /* disable LPTIMER to be able to write into IER register*/ 57 regmap_write(priv->reg, STM32_LPTIM_CR, 0); 58 /* enable ARR interrupt */ 59 regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE); 60 /* enable LPTIMER to be able to write into ARR register */ 61 regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); 62 /* set next event counter */ 63 regmap_write(priv->reg, STM32_LPTIM_ARR, evt); 64 65 /* start counter */ 66 if (is_periodic) 67 regmap_write(priv->reg, STM32_LPTIM_CR, 68 STM32_LPTIM_CNTSTRT | STM32_LPTIM_ENABLE); 69 else 70 regmap_write(priv->reg, STM32_LPTIM_CR, 71 STM32_LPTIM_SNGSTRT | STM32_LPTIM_ENABLE); 72 73 return 0; 74 } 75 76 static int stm32_clkevent_lp_set_next_event(unsigned long evt, 77 struct clock_event_device *clkevt) 78 { 79 return stm32_clkevent_lp_set_timer(evt, clkevt, 80 clockevent_state_periodic(clkevt)); 81 } 82 83 static int stm32_clkevent_lp_set_periodic(struct clock_event_device *clkevt) 84 { 85 struct stm32_lp_private *priv = to_priv(clkevt); 86 87 return stm32_clkevent_lp_set_timer(priv->period, clkevt, true); 88 } 89 90 static int stm32_clkevent_lp_set_oneshot(struct clock_event_device *clkevt) 91 { 92 struct stm32_lp_private *priv = to_priv(clkevt); 93 94 return stm32_clkevent_lp_set_timer(priv->period, clkevt, false); 95 } 96 97 static irqreturn_t stm32_clkevent_lp_irq_handler(int irq, void *dev_id) 98 { 99 struct clock_event_device *clkevt = (struct clock_event_device *)dev_id; 100 struct stm32_lp_private *priv = to_priv(clkevt); 101 102 regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); 103 104 if (clkevt->event_handler) 105 clkevt->event_handler(clkevt); 106 107 return IRQ_HANDLED; 108 } 109 110 static void stm32_clkevent_lp_set_prescaler(struct stm32_lp_private *priv, 111 unsigned long *rate) 112 { 113 int i; 114 115 for (i = 0; i <= STM32_LP_MAX_PSC; i++) { 116 if (DIV_ROUND_CLOSEST(*rate, 1 << i) < STM32_TARGET_CLKRATE) 117 break; 118 } 119 120 regmap_write(priv->reg, STM32_LPTIM_CFGR, i << CFGR_PSC_OFFSET); 121 122 /* Adjust rate and period given the prescaler value */ 123 *rate = DIV_ROUND_CLOSEST(*rate, (1 << i)); 124 priv->period = DIV_ROUND_UP(*rate, HZ); 125 priv->psc = i; 126 } 127 128 static void stm32_clkevent_lp_suspend(struct clock_event_device *clkevt) 129 { 130 struct stm32_lp_private *priv = to_priv(clkevt); 131 132 stm32_clkevent_lp_shutdown(clkevt); 133 134 /* balance clk_prepare_enable() from the probe */ 135 clk_disable_unprepare(priv->clk); 136 } 137 138 static void stm32_clkevent_lp_resume(struct clock_event_device *clkevt) 139 { 140 struct stm32_lp_private *priv = to_priv(clkevt); 141 142 clk_prepare_enable(priv->clk); 143 144 /* restore prescaler */ 145 regmap_write(priv->reg, STM32_LPTIM_CFGR, priv->psc << CFGR_PSC_OFFSET); 146 } 147 148 static void stm32_clkevent_lp_init(struct stm32_lp_private *priv, 149 struct device_node *np, unsigned long rate) 150 { 151 priv->clkevt.name = np->full_name; 152 priv->clkevt.cpumask = cpu_possible_mask; 153 priv->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | 154 CLOCK_EVT_FEAT_ONESHOT; 155 priv->clkevt.set_state_shutdown = stm32_clkevent_lp_shutdown; 156 priv->clkevt.set_state_periodic = stm32_clkevent_lp_set_periodic; 157 priv->clkevt.set_state_oneshot = stm32_clkevent_lp_set_oneshot; 158 priv->clkevt.set_next_event = stm32_clkevent_lp_set_next_event; 159 priv->clkevt.rating = STM32_LP_RATING; 160 priv->clkevt.suspend = stm32_clkevent_lp_suspend; 161 priv->clkevt.resume = stm32_clkevent_lp_resume; 162 163 clockevents_config_and_register(&priv->clkevt, rate, 0x1, 164 STM32_LPTIM_MAX_ARR); 165 } 166 167 static int stm32_clkevent_lp_probe(struct platform_device *pdev) 168 { 169 struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent); 170 struct stm32_lp_private *priv; 171 unsigned long rate; 172 int ret, irq; 173 174 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 175 if (!priv) 176 return -ENOMEM; 177 178 priv->reg = ddata->regmap; 179 priv->clk = ddata->clk; 180 ret = clk_prepare_enable(priv->clk); 181 if (ret) 182 return -EINVAL; 183 184 rate = clk_get_rate(priv->clk); 185 if (!rate) { 186 ret = -EINVAL; 187 goto out_clk_disable; 188 } 189 190 irq = platform_get_irq(to_platform_device(pdev->dev.parent), 0); 191 if (irq <= 0) { 192 ret = irq; 193 goto out_clk_disable; 194 } 195 196 if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) { 197 device_set_wakeup_capable(&pdev->dev, true); 198 199 ret = dev_pm_set_wake_irq(&pdev->dev, irq); 200 if (ret) 201 goto out_clk_disable; 202 } 203 204 ret = devm_request_irq(&pdev->dev, irq, stm32_clkevent_lp_irq_handler, 205 IRQF_TIMER, pdev->name, &priv->clkevt); 206 if (ret) 207 goto out_clk_disable; 208 209 stm32_clkevent_lp_set_prescaler(priv, &rate); 210 211 stm32_clkevent_lp_init(priv, pdev->dev.parent->of_node, rate); 212 213 priv->dev = &pdev->dev; 214 215 return 0; 216 217 out_clk_disable: 218 clk_disable_unprepare(priv->clk); 219 return ret; 220 } 221 222 static const struct of_device_id stm32_clkevent_lp_of_match[] = { 223 { .compatible = "st,stm32-lptimer-timer", }, 224 {}, 225 }; 226 MODULE_DEVICE_TABLE(of, stm32_clkevent_lp_of_match); 227 228 static struct platform_driver stm32_clkevent_lp_driver = { 229 .probe = stm32_clkevent_lp_probe, 230 .driver = { 231 .name = "stm32-lptimer-timer", 232 .of_match_table = stm32_clkevent_lp_of_match, 233 .suppress_bind_attrs = true, 234 }, 235 }; 236 module_platform_driver(stm32_clkevent_lp_driver); 237 238 MODULE_ALIAS("platform:stm32-lptimer-timer"); 239 MODULE_DESCRIPTION("STMicroelectronics STM32 clockevent low power driver"); 240