Merge tag 'exfat-for-5.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/linki...
[linux-2.6-microblaze.git] / drivers / watchdog / rzg2l_wdt.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Renesas RZ/G2L WDT Watchdog Driver
4  *
5  * Copyright (C) 2021 Renesas Electronics Corporation
6  */
7 #include <linux/bitops.h>
8 #include <linux/clk.h>
9 #include <linux/delay.h>
10 #include <linux/io.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/reset.h>
17 #include <linux/units.h>
18 #include <linux/watchdog.h>
19
20 #define WDTCNT          0x00
21 #define WDTSET          0x04
22 #define WDTTIM          0x08
23 #define WDTINT          0x0C
24 #define PECR            0x10
25 #define PEEN            0x14
26 #define WDTCNT_WDTEN    BIT(0)
27 #define WDTINT_INTDISP  BIT(0)
28 #define PEEN_FORCE      BIT(0)
29
30 #define WDT_DEFAULT_TIMEOUT             60U
31
32 /* Setting period time register only 12 bit set in WDTSET[31:20] */
33 #define WDTSET_COUNTER_MASK             (0xFFF00000)
34 #define WDTSET_COUNTER_VAL(f)           ((f) << 20)
35
36 #define F2CYCLE_NSEC(f)                 (1000000000 / (f))
37
38 static bool nowayout = WATCHDOG_NOWAYOUT;
39 module_param(nowayout, bool, 0);
40 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
41                                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
42
43 struct rzg2l_wdt_priv {
44         void __iomem *base;
45         struct watchdog_device wdev;
46         struct reset_control *rstc;
47         unsigned long osc_clk_rate;
48         unsigned long delay;
49         struct clk *pclk;
50         struct clk *osc_clk;
51 };
52
53 static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv)
54 {
55         /* delay timer when change the setting register */
56         ndelay(priv->delay);
57 }
58
59 static u32 rzg2l_wdt_get_cycle_usec(unsigned long cycle, u32 wdttime)
60 {
61         u64 timer_cycle_us = 1024 * 1024ULL * (wdttime + 1) * MICRO;
62
63         return div64_ul(timer_cycle_us, cycle);
64 }
65
66 static void rzg2l_wdt_write(struct rzg2l_wdt_priv *priv, u32 val, unsigned int reg)
67 {
68         if (reg == WDTSET)
69                 val &= WDTSET_COUNTER_MASK;
70
71         writel_relaxed(val, priv->base + reg);
72         /* Registers other than the WDTINT is always synchronized with WDT_CLK */
73         if (reg != WDTINT)
74                 rzg2l_wdt_wait_delay(priv);
75 }
76
77 static void rzg2l_wdt_init_timeout(struct watchdog_device *wdev)
78 {
79         struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
80         u32 time_out;
81
82         /* Clear Lapsed Time Register and clear Interrupt */
83         rzg2l_wdt_write(priv, WDTINT_INTDISP, WDTINT);
84         /* 2 consecutive overflow cycle needed to trigger reset */
85         time_out = (wdev->timeout * (MICRO / 2)) /
86                    rzg2l_wdt_get_cycle_usec(priv->osc_clk_rate, 0);
87         rzg2l_wdt_write(priv, WDTSET_COUNTER_VAL(time_out), WDTSET);
88 }
89
90 static int rzg2l_wdt_start(struct watchdog_device *wdev)
91 {
92         struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
93
94         pm_runtime_get_sync(wdev->parent);
95
96         /* Initialize time out */
97         rzg2l_wdt_init_timeout(wdev);
98
99         /* Initialize watchdog counter register */
100         rzg2l_wdt_write(priv, 0, WDTTIM);
101
102         /* Enable watchdog timer*/
103         rzg2l_wdt_write(priv, WDTCNT_WDTEN, WDTCNT);
104
105         return 0;
106 }
107
108 static int rzg2l_wdt_stop(struct watchdog_device *wdev)
109 {
110         struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
111
112         pm_runtime_put(wdev->parent);
113         reset_control_reset(priv->rstc);
114
115         return 0;
116 }
117
118 static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
119 {
120         struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
121
122         wdev->timeout = timeout;
123
124         /*
125          * If the watchdog is active, reset the module for updating the WDTSET
126          * register so that it is updated with new timeout values.
127          */
128         if (watchdog_active(wdev)) {
129                 pm_runtime_put(wdev->parent);
130                 reset_control_reset(priv->rstc);
131                 rzg2l_wdt_start(wdev);
132         }
133
134         return 0;
135 }
136
137 static int rzg2l_wdt_restart(struct watchdog_device *wdev,
138                              unsigned long action, void *data)
139 {
140         struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
141
142         clk_prepare_enable(priv->pclk);
143         clk_prepare_enable(priv->osc_clk);
144
145         /* Generate Reset (WDTRSTB) Signal on parity error */
146         rzg2l_wdt_write(priv, 0, PECR);
147
148         /* Force parity error */
149         rzg2l_wdt_write(priv, PEEN_FORCE, PEEN);
150
151         return 0;
152 }
153
154 static const struct watchdog_info rzg2l_wdt_ident = {
155         .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
156         .identity = "Renesas RZ/G2L WDT Watchdog",
157 };
158
159 static int rzg2l_wdt_ping(struct watchdog_device *wdev)
160 {
161         struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
162
163         rzg2l_wdt_write(priv, WDTINT_INTDISP, WDTINT);
164
165         return 0;
166 }
167
168 static const struct watchdog_ops rzg2l_wdt_ops = {
169         .owner = THIS_MODULE,
170         .start = rzg2l_wdt_start,
171         .stop = rzg2l_wdt_stop,
172         .ping = rzg2l_wdt_ping,
173         .set_timeout = rzg2l_wdt_set_timeout,
174         .restart = rzg2l_wdt_restart,
175 };
176
177 static void rzg2l_wdt_reset_assert_pm_disable(void *data)
178 {
179         struct watchdog_device *wdev = data;
180         struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
181
182         pm_runtime_disable(wdev->parent);
183         reset_control_assert(priv->rstc);
184 }
185
186 static int rzg2l_wdt_probe(struct platform_device *pdev)
187 {
188         struct device *dev = &pdev->dev;
189         struct rzg2l_wdt_priv *priv;
190         unsigned long pclk_rate;
191         int ret;
192
193         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
194         if (!priv)
195                 return -ENOMEM;
196
197         priv->base = devm_platform_ioremap_resource(pdev, 0);
198         if (IS_ERR(priv->base))
199                 return PTR_ERR(priv->base);
200
201         /* Get watchdog main clock */
202         priv->osc_clk = devm_clk_get(&pdev->dev, "oscclk");
203         if (IS_ERR(priv->osc_clk))
204                 return dev_err_probe(&pdev->dev, PTR_ERR(priv->osc_clk), "no oscclk");
205
206         priv->osc_clk_rate = clk_get_rate(priv->osc_clk);
207         if (!priv->osc_clk_rate)
208                 return dev_err_probe(&pdev->dev, -EINVAL, "oscclk rate is 0");
209
210         /* Get Peripheral clock */
211         priv->pclk = devm_clk_get(&pdev->dev, "pclk");
212         if (IS_ERR(priv->pclk))
213                 return dev_err_probe(&pdev->dev, PTR_ERR(priv->pclk), "no pclk");
214
215         pclk_rate = clk_get_rate(priv->pclk);
216         if (!pclk_rate)
217                 return dev_err_probe(&pdev->dev, -EINVAL, "pclk rate is 0");
218
219         priv->delay = F2CYCLE_NSEC(priv->osc_clk_rate) * 6 + F2CYCLE_NSEC(pclk_rate) * 9;
220
221         priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
222         if (IS_ERR(priv->rstc))
223                 return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc),
224                                      "failed to get cpg reset");
225
226         ret = reset_control_deassert(priv->rstc);
227         if (ret)
228                 return dev_err_probe(dev, ret, "failed to deassert");
229
230         pm_runtime_enable(&pdev->dev);
231
232         priv->wdev.info = &rzg2l_wdt_ident;
233         priv->wdev.ops = &rzg2l_wdt_ops;
234         priv->wdev.parent = dev;
235         priv->wdev.min_timeout = 1;
236         priv->wdev.max_timeout = rzg2l_wdt_get_cycle_usec(priv->osc_clk_rate, 0xfff) /
237                                  USEC_PER_SEC;
238         priv->wdev.timeout = WDT_DEFAULT_TIMEOUT;
239
240         watchdog_set_drvdata(&priv->wdev, priv);
241         ret = devm_add_action_or_reset(&pdev->dev,
242                                        rzg2l_wdt_reset_assert_pm_disable,
243                                        &priv->wdev);
244         if (ret < 0)
245                 return ret;
246
247         watchdog_set_nowayout(&priv->wdev, nowayout);
248         watchdog_stop_on_unregister(&priv->wdev);
249
250         ret = watchdog_init_timeout(&priv->wdev, 0, dev);
251         if (ret)
252                 dev_warn(dev, "Specified timeout invalid, using default");
253
254         return devm_watchdog_register_device(&pdev->dev, &priv->wdev);
255 }
256
257 static const struct of_device_id rzg2l_wdt_ids[] = {
258         { .compatible = "renesas,rzg2l-wdt", },
259         { /* sentinel */ }
260 };
261 MODULE_DEVICE_TABLE(of, rzg2l_wdt_ids);
262
263 static struct platform_driver rzg2l_wdt_driver = {
264         .driver = {
265                 .name = "rzg2l_wdt",
266                 .of_match_table = rzg2l_wdt_ids,
267         },
268         .probe = rzg2l_wdt_probe,
269 };
270 module_platform_driver(rzg2l_wdt_driver);
271
272 MODULE_DESCRIPTION("Renesas RZ/G2L WDT Watchdog Driver");
273 MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
274 MODULE_LICENSE("GPL v2");