Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Renesas RZ/G2L WDT Watchdog Driver
0004  *
0005  * Copyright (C) 2021 Renesas Electronics Corporation
0006  */
0007 #include <linux/bitops.h>
0008 #include <linux/clk.h>
0009 #include <linux/delay.h>
0010 #include <linux/io.h>
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/reset.h>
0017 #include <linux/units.h>
0018 #include <linux/watchdog.h>
0019 
0020 #define WDTCNT      0x00
0021 #define WDTSET      0x04
0022 #define WDTTIM      0x08
0023 #define WDTINT      0x0C
0024 #define PECR        0x10
0025 #define PEEN        0x14
0026 #define WDTCNT_WDTEN    BIT(0)
0027 #define WDTINT_INTDISP  BIT(0)
0028 #define PEEN_FORCE  BIT(0)
0029 
0030 #define WDT_DEFAULT_TIMEOUT     60U
0031 
0032 /* Setting period time register only 12 bit set in WDTSET[31:20] */
0033 #define WDTSET_COUNTER_MASK     (0xFFF00000)
0034 #define WDTSET_COUNTER_VAL(f)       ((f) << 20)
0035 
0036 #define F2CYCLE_NSEC(f)         (1000000000 / (f))
0037 
0038 static bool nowayout = WATCHDOG_NOWAYOUT;
0039 module_param(nowayout, bool, 0);
0040 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
0041                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
0042 
0043 struct rzg2l_wdt_priv {
0044     void __iomem *base;
0045     struct watchdog_device wdev;
0046     struct reset_control *rstc;
0047     unsigned long osc_clk_rate;
0048     unsigned long delay;
0049     struct clk *pclk;
0050     struct clk *osc_clk;
0051 };
0052 
0053 static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv)
0054 {
0055     /* delay timer when change the setting register */
0056     ndelay(priv->delay);
0057 }
0058 
0059 static u32 rzg2l_wdt_get_cycle_usec(unsigned long cycle, u32 wdttime)
0060 {
0061     u64 timer_cycle_us = 1024 * 1024ULL * (wdttime + 1) * MICRO;
0062 
0063     return div64_ul(timer_cycle_us, cycle);
0064 }
0065 
0066 static void rzg2l_wdt_write(struct rzg2l_wdt_priv *priv, u32 val, unsigned int reg)
0067 {
0068     if (reg == WDTSET)
0069         val &= WDTSET_COUNTER_MASK;
0070 
0071     writel_relaxed(val, priv->base + reg);
0072     /* Registers other than the WDTINT is always synchronized with WDT_CLK */
0073     if (reg != WDTINT)
0074         rzg2l_wdt_wait_delay(priv);
0075 }
0076 
0077 static void rzg2l_wdt_init_timeout(struct watchdog_device *wdev)
0078 {
0079     struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
0080     u32 time_out;
0081 
0082     /* Clear Lapsed Time Register and clear Interrupt */
0083     rzg2l_wdt_write(priv, WDTINT_INTDISP, WDTINT);
0084     /* 2 consecutive overflow cycle needed to trigger reset */
0085     time_out = (wdev->timeout * (MICRO / 2)) /
0086            rzg2l_wdt_get_cycle_usec(priv->osc_clk_rate, 0);
0087     rzg2l_wdt_write(priv, WDTSET_COUNTER_VAL(time_out), WDTSET);
0088 }
0089 
0090 static int rzg2l_wdt_start(struct watchdog_device *wdev)
0091 {
0092     struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
0093 
0094     pm_runtime_get_sync(wdev->parent);
0095 
0096     /* Initialize time out */
0097     rzg2l_wdt_init_timeout(wdev);
0098 
0099     /* Initialize watchdog counter register */
0100     rzg2l_wdt_write(priv, 0, WDTTIM);
0101 
0102     /* Enable watchdog timer*/
0103     rzg2l_wdt_write(priv, WDTCNT_WDTEN, WDTCNT);
0104 
0105     return 0;
0106 }
0107 
0108 static int rzg2l_wdt_stop(struct watchdog_device *wdev)
0109 {
0110     struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
0111 
0112     pm_runtime_put(wdev->parent);
0113     reset_control_reset(priv->rstc);
0114 
0115     return 0;
0116 }
0117 
0118 static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
0119 {
0120     struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
0121 
0122     wdev->timeout = timeout;
0123 
0124     /*
0125      * If the watchdog is active, reset the module for updating the WDTSET
0126      * register so that it is updated with new timeout values.
0127      */
0128     if (watchdog_active(wdev)) {
0129         pm_runtime_put(wdev->parent);
0130         reset_control_reset(priv->rstc);
0131         rzg2l_wdt_start(wdev);
0132     }
0133 
0134     return 0;
0135 }
0136 
0137 static int rzg2l_wdt_restart(struct watchdog_device *wdev,
0138                  unsigned long action, void *data)
0139 {
0140     struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
0141 
0142     clk_prepare_enable(priv->pclk);
0143     clk_prepare_enable(priv->osc_clk);
0144 
0145     /* Generate Reset (WDTRSTB) Signal on parity error */
0146     rzg2l_wdt_write(priv, 0, PECR);
0147 
0148     /* Force parity error */
0149     rzg2l_wdt_write(priv, PEEN_FORCE, PEEN);
0150 
0151     return 0;
0152 }
0153 
0154 static const struct watchdog_info rzg2l_wdt_ident = {
0155     .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
0156     .identity = "Renesas RZ/G2L WDT Watchdog",
0157 };
0158 
0159 static int rzg2l_wdt_ping(struct watchdog_device *wdev)
0160 {
0161     struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
0162 
0163     rzg2l_wdt_write(priv, WDTINT_INTDISP, WDTINT);
0164 
0165     return 0;
0166 }
0167 
0168 static const struct watchdog_ops rzg2l_wdt_ops = {
0169     .owner = THIS_MODULE,
0170     .start = rzg2l_wdt_start,
0171     .stop = rzg2l_wdt_stop,
0172     .ping = rzg2l_wdt_ping,
0173     .set_timeout = rzg2l_wdt_set_timeout,
0174     .restart = rzg2l_wdt_restart,
0175 };
0176 
0177 static void rzg2l_wdt_reset_assert_pm_disable(void *data)
0178 {
0179     struct watchdog_device *wdev = data;
0180     struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
0181 
0182     pm_runtime_disable(wdev->parent);
0183     reset_control_assert(priv->rstc);
0184 }
0185 
0186 static int rzg2l_wdt_probe(struct platform_device *pdev)
0187 {
0188     struct device *dev = &pdev->dev;
0189     struct rzg2l_wdt_priv *priv;
0190     unsigned long pclk_rate;
0191     int ret;
0192 
0193     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0194     if (!priv)
0195         return -ENOMEM;
0196 
0197     priv->base = devm_platform_ioremap_resource(pdev, 0);
0198     if (IS_ERR(priv->base))
0199         return PTR_ERR(priv->base);
0200 
0201     /* Get watchdog main clock */
0202     priv->osc_clk = devm_clk_get(&pdev->dev, "oscclk");
0203     if (IS_ERR(priv->osc_clk))
0204         return dev_err_probe(&pdev->dev, PTR_ERR(priv->osc_clk), "no oscclk");
0205 
0206     priv->osc_clk_rate = clk_get_rate(priv->osc_clk);
0207     if (!priv->osc_clk_rate)
0208         return dev_err_probe(&pdev->dev, -EINVAL, "oscclk rate is 0");
0209 
0210     /* Get Peripheral clock */
0211     priv->pclk = devm_clk_get(&pdev->dev, "pclk");
0212     if (IS_ERR(priv->pclk))
0213         return dev_err_probe(&pdev->dev, PTR_ERR(priv->pclk), "no pclk");
0214 
0215     pclk_rate = clk_get_rate(priv->pclk);
0216     if (!pclk_rate)
0217         return dev_err_probe(&pdev->dev, -EINVAL, "pclk rate is 0");
0218 
0219     priv->delay = F2CYCLE_NSEC(priv->osc_clk_rate) * 6 + F2CYCLE_NSEC(pclk_rate) * 9;
0220 
0221     priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
0222     if (IS_ERR(priv->rstc))
0223         return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc),
0224                      "failed to get cpg reset");
0225 
0226     ret = reset_control_deassert(priv->rstc);
0227     if (ret)
0228         return dev_err_probe(dev, ret, "failed to deassert");
0229 
0230     pm_runtime_enable(&pdev->dev);
0231 
0232     priv->wdev.info = &rzg2l_wdt_ident;
0233     priv->wdev.ops = &rzg2l_wdt_ops;
0234     priv->wdev.parent = dev;
0235     priv->wdev.min_timeout = 1;
0236     priv->wdev.max_timeout = rzg2l_wdt_get_cycle_usec(priv->osc_clk_rate, 0xfff) /
0237                  USEC_PER_SEC;
0238     priv->wdev.timeout = WDT_DEFAULT_TIMEOUT;
0239 
0240     watchdog_set_drvdata(&priv->wdev, priv);
0241     ret = devm_add_action_or_reset(&pdev->dev,
0242                        rzg2l_wdt_reset_assert_pm_disable,
0243                        &priv->wdev);
0244     if (ret < 0)
0245         return ret;
0246 
0247     watchdog_set_nowayout(&priv->wdev, nowayout);
0248     watchdog_stop_on_unregister(&priv->wdev);
0249 
0250     ret = watchdog_init_timeout(&priv->wdev, 0, dev);
0251     if (ret)
0252         dev_warn(dev, "Specified timeout invalid, using default");
0253 
0254     return devm_watchdog_register_device(&pdev->dev, &priv->wdev);
0255 }
0256 
0257 static const struct of_device_id rzg2l_wdt_ids[] = {
0258     { .compatible = "renesas,rzg2l-wdt", },
0259     { /* sentinel */ }
0260 };
0261 MODULE_DEVICE_TABLE(of, rzg2l_wdt_ids);
0262 
0263 static struct platform_driver rzg2l_wdt_driver = {
0264     .driver = {
0265         .name = "rzg2l_wdt",
0266         .of_match_table = rzg2l_wdt_ids,
0267     },
0268     .probe = rzg2l_wdt_probe,
0269 };
0270 module_platform_driver(rzg2l_wdt_driver);
0271 
0272 MODULE_DESCRIPTION("Renesas RZ/G2L WDT Watchdog Driver");
0273 MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
0274 MODULE_LICENSE("GPL v2");