248 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Renesas RZ/A Series WDT Driver4 *5 * Copyright (C) 2017 Renesas Electronics America, Inc.6 * Copyright (C) 2017 Chris Brandt7 */8 9#include <linux/bitops.h>10#include <linux/clk.h>11#include <linux/delay.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/platform_device.h>16#include <linux/watchdog.h>17 18#define DEFAULT_TIMEOUT 3019 20/* Watchdog Timer Registers */21#define WTCSR 022#define WTCSR_MAGIC 0xA50023#define WTSCR_WT BIT(6)24#define WTSCR_TME BIT(5)25#define WTSCR_CKS(i) (i)26 27#define WTCNT 228#define WTCNT_MAGIC 0x5A0029 30#define WRCSR 431#define WRCSR_MAGIC 0x5A0032#define WRCSR_RSTE BIT(6)33#define WRCSR_CLEAR_WOVF 0xA500 /* special value */34 35/* The maximum CKS register setting value to get the longest timeout */36#define CKS_3BIT 0x737#define CKS_4BIT 0xF38 39#define DIVIDER_3BIT 16384 /* Clock divider when CKS = 0x7 */40#define DIVIDER_4BIT 4194304 /* Clock divider when CKS = 0xF */41 42struct rza_wdt {43 struct watchdog_device wdev;44 void __iomem *base;45 struct clk *clk;46 u8 count;47 u8 cks;48};49 50static void rza_wdt_calc_timeout(struct rza_wdt *priv, int timeout)51{52 unsigned long rate = clk_get_rate(priv->clk);53 unsigned int ticks;54 55 if (priv->cks == CKS_4BIT) {56 ticks = DIV_ROUND_UP(timeout * rate, DIVIDER_4BIT);57 58 /*59 * Since max_timeout was set in probe, we know that the timeout60 * value passed will never calculate to a tick value greater61 * than 256.62 */63 priv->count = 256 - ticks;64 65 } else {66 /* Start timer with longest timeout */67 priv->count = 0;68 }69 70 pr_debug("%s: timeout set to %u (WTCNT=%d)\n", __func__,71 timeout, priv->count);72}73 74static int rza_wdt_start(struct watchdog_device *wdev)75{76 struct rza_wdt *priv = watchdog_get_drvdata(wdev);77 78 /* Stop timer */79 writew(WTCSR_MAGIC | 0, priv->base + WTCSR);80 81 /* Must dummy read WRCSR:WOVF at least once before clearing */82 readb(priv->base + WRCSR);83 writew(WRCSR_CLEAR_WOVF, priv->base + WRCSR);84 85 rza_wdt_calc_timeout(priv, wdev->timeout);86 87 writew(WRCSR_MAGIC | WRCSR_RSTE, priv->base + WRCSR);88 writew(WTCNT_MAGIC | priv->count, priv->base + WTCNT);89 writew(WTCSR_MAGIC | WTSCR_WT | WTSCR_TME |90 WTSCR_CKS(priv->cks), priv->base + WTCSR);91 92 return 0;93}94 95static int rza_wdt_stop(struct watchdog_device *wdev)96{97 struct rza_wdt *priv = watchdog_get_drvdata(wdev);98 99 writew(WTCSR_MAGIC | 0, priv->base + WTCSR);100 101 return 0;102}103 104static int rza_wdt_ping(struct watchdog_device *wdev)105{106 struct rza_wdt *priv = watchdog_get_drvdata(wdev);107 108 writew(WTCNT_MAGIC | priv->count, priv->base + WTCNT);109 110 pr_debug("%s: timeout = %u\n", __func__, wdev->timeout);111 112 return 0;113}114 115static int rza_set_timeout(struct watchdog_device *wdev, unsigned int timeout)116{117 wdev->timeout = timeout;118 rza_wdt_start(wdev);119 return 0;120}121 122static int rza_wdt_restart(struct watchdog_device *wdev, unsigned long action,123 void *data)124{125 struct rza_wdt *priv = watchdog_get_drvdata(wdev);126 127 /* Stop timer */128 writew(WTCSR_MAGIC | 0, priv->base + WTCSR);129 130 /* Must dummy read WRCSR:WOVF at least once before clearing */131 readb(priv->base + WRCSR);132 writew(WRCSR_CLEAR_WOVF, priv->base + WRCSR);133 134 /*135 * Start timer with fastest clock source and only 1 clock left before136 * overflow with reset option enabled.137 */138 writew(WRCSR_MAGIC | WRCSR_RSTE, priv->base + WRCSR);139 writew(WTCNT_MAGIC | 255, priv->base + WTCNT);140 writew(WTCSR_MAGIC | WTSCR_WT | WTSCR_TME, priv->base + WTCSR);141 142 /*143 * Actually make sure the above sequence hits hardware before sleeping.144 */145 wmb();146 147 /* Wait for WDT overflow (reset) */148 udelay(20);149 150 return 0;151}152 153static const struct watchdog_info rza_wdt_ident = {154 .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,155 .identity = "Renesas RZ/A WDT Watchdog",156};157 158static const struct watchdog_ops rza_wdt_ops = {159 .owner = THIS_MODULE,160 .start = rza_wdt_start,161 .stop = rza_wdt_stop,162 .ping = rza_wdt_ping,163 .set_timeout = rza_set_timeout,164 .restart = rza_wdt_restart,165};166 167static int rza_wdt_probe(struct platform_device *pdev)168{169 struct device *dev = &pdev->dev;170 struct rza_wdt *priv;171 unsigned long rate;172 int ret;173 174 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);175 if (!priv)176 return -ENOMEM;177 178 priv->base = devm_platform_ioremap_resource(pdev, 0);179 if (IS_ERR(priv->base))180 return PTR_ERR(priv->base);181 182 priv->clk = devm_clk_get(dev, NULL);183 if (IS_ERR(priv->clk))184 return PTR_ERR(priv->clk);185 186 rate = clk_get_rate(priv->clk);187 if (rate < 16384) {188 dev_err(dev, "invalid clock rate (%ld)\n", rate);189 return -ENOENT;190 }191 192 priv->wdev.info = &rza_wdt_ident;193 priv->wdev.ops = &rza_wdt_ops;194 priv->wdev.parent = dev;195 196 priv->cks = (u8)(uintptr_t) of_device_get_match_data(dev);197 if (priv->cks == CKS_4BIT) {198 /* Assume slowest clock rate possible (CKS=0xF) */199 priv->wdev.max_timeout = (DIVIDER_4BIT * U8_MAX) / rate;200 201 } else if (priv->cks == CKS_3BIT) {202 /* Assume slowest clock rate possible (CKS=7) */203 rate /= DIVIDER_3BIT;204 205 /*206 * Since the max possible timeout of our 8-bit count207 * register is less than a second, we must use208 * max_hw_heartbeat_ms.209 */210 priv->wdev.max_hw_heartbeat_ms = (1000 * U8_MAX) / rate;211 dev_dbg(dev, "max hw timeout of %dms\n",212 priv->wdev.max_hw_heartbeat_ms);213 }214 215 priv->wdev.min_timeout = 1;216 priv->wdev.timeout = DEFAULT_TIMEOUT;217 218 watchdog_init_timeout(&priv->wdev, 0, dev);219 watchdog_set_drvdata(&priv->wdev, priv);220 221 ret = devm_watchdog_register_device(dev, &priv->wdev);222 if (ret)223 dev_err(dev, "Cannot register watchdog device\n");224 225 return ret;226}227 228static const struct of_device_id rza_wdt_of_match[] = {229 { .compatible = "renesas,r7s9210-wdt", .data = (void *)CKS_4BIT, },230 { .compatible = "renesas,rza-wdt", .data = (void *)CKS_3BIT, },231 { /* sentinel */ }232};233MODULE_DEVICE_TABLE(of, rza_wdt_of_match);234 235static struct platform_driver rza_wdt_driver = {236 .probe = rza_wdt_probe,237 .driver = {238 .name = "rza_wdt",239 .of_match_table = rza_wdt_of_match,240 },241};242 243module_platform_driver(rza_wdt_driver);244 245MODULE_DESCRIPTION("Renesas RZ/A WDT Driver");246MODULE_AUTHOR("Chris Brandt <chris.brandt@renesas.com>");247MODULE_LICENSE("GPL v2");248