1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Renesas RZ/N1 Watchdog timer. 4 * This is a 12-bit timer driver from a (62.5/16384) MHz clock. It can't even 5 * cope with 2 seconds. 6 * 7 * Copyright 2018 Renesas Electronics Europe Ltd. 8 * 9 * Derived from Ralink RT288x watchdog timer. 10 */ 11 12 #include <linux/clk.h> 13 #include <linux/interrupt.h> 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/of_address.h> 17 #include <linux/of_irq.h> 18 #include <linux/platform_device.h> 19 #include <linux/reboot.h> 20 #include <linux/watchdog.h> 21 22 #define DEFAULT_TIMEOUT 60 23 24 #define RZN1_WDT_RETRIGGER 0x0 25 #define RZN1_WDT_RETRIGGER_RELOAD_VAL 0 26 #define RZN1_WDT_RETRIGGER_RELOAD_VAL_MASK 0xfff 27 #define RZN1_WDT_RETRIGGER_PRESCALE BIT(12) 28 #define RZN1_WDT_RETRIGGER_ENABLE BIT(13) 29 #define RZN1_WDT_RETRIGGER_WDSI (0x2 << 14) 30 31 #define RZN1_WDT_PRESCALER 16384 32 #define RZN1_WDT_MAX 4095 33 34 struct rzn1_watchdog { 35 struct watchdog_device wdtdev; 36 void __iomem *base; 37 unsigned long clk_rate_khz; 38 }; 39 40 static inline uint32_t max_heart_beat_ms(unsigned long clk_rate_khz) 41 { 42 return (RZN1_WDT_MAX * RZN1_WDT_PRESCALER) / clk_rate_khz; 43 } 44 45 static inline uint32_t compute_reload_value(uint32_t tick_ms, 46 unsigned long clk_rate_khz) 47 { 48 return (tick_ms * clk_rate_khz) / RZN1_WDT_PRESCALER; 49 } 50 51 static int rzn1_wdt_ping(struct watchdog_device *w) 52 { 53 struct rzn1_watchdog *wdt = watchdog_get_drvdata(w); 54 55 /* Any value retrigggers the watchdog */ 56 writel(0, wdt->base + RZN1_WDT_RETRIGGER); 57 58 return 0; 59 } 60 61 static int rzn1_wdt_start(struct watchdog_device *w) 62 { 63 struct rzn1_watchdog *wdt = watchdog_get_drvdata(w); 64 u32 val; 65 66 /* 67 * The hardware allows you to write to this reg only once. 68 * Since this includes the reload value, there is no way to change the 69 * timeout once started. Also note that the WDT clock is half the bus 70 * fabric clock rate, so if the bus fabric clock rate is changed after 71 * the WDT is started, the WDT interval will be wrong. 72 */ 73 val = RZN1_WDT_RETRIGGER_WDSI; 74 val |= RZN1_WDT_RETRIGGER_ENABLE; 75 val |= RZN1_WDT_RETRIGGER_PRESCALE; 76 val |= compute_reload_value(w->max_hw_heartbeat_ms, wdt->clk_rate_khz); 77 writel(val, wdt->base + RZN1_WDT_RETRIGGER); 78 79 return 0; 80 } 81 82 static irqreturn_t rzn1_wdt_irq(int irq, void *_wdt) 83 { 84 pr_crit("RZN1 Watchdog. Initiating system reboot\n"); 85 emergency_restart(); 86 87 return IRQ_HANDLED; 88 } 89 90 static struct watchdog_info rzn1_wdt_info = { 91 .identity = "RZ/N1 Watchdog", 92 .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 93 }; 94 95 static const struct watchdog_ops rzn1_wdt_ops = { 96 .owner = THIS_MODULE, 97 .start = rzn1_wdt_start, 98 .ping = rzn1_wdt_ping, 99 }; 100 101 static void rzn1_wdt_clk_disable_unprepare(void *data) 102 { 103 clk_disable_unprepare(data); 104 } 105 106 static int rzn1_wdt_probe(struct platform_device *pdev) 107 { 108 struct device *dev = &pdev->dev; 109 struct rzn1_watchdog *wdt; 110 struct device_node *np = dev->of_node; 111 struct clk *clk; 112 unsigned long clk_rate; 113 int ret; 114 int irq; 115 116 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); 117 if (!wdt) 118 return -ENOMEM; 119 120 wdt->base = devm_platform_ioremap_resource(pdev, 0); 121 if (IS_ERR(wdt->base)) 122 return PTR_ERR(wdt->base); 123 124 irq = platform_get_irq(pdev, 0); 125 if (irq < 0) 126 return irq; 127 128 ret = devm_request_irq(dev, irq, rzn1_wdt_irq, 0, 129 np->name, wdt); 130 if (ret) { 131 dev_err(dev, "failed to request irq %d\n", irq); 132 return ret; 133 } 134 135 clk = devm_clk_get(dev, NULL); 136 if (IS_ERR(clk)) { 137 dev_err(dev, "failed to get the clock\n"); 138 return PTR_ERR(clk); 139 } 140 141 ret = clk_prepare_enable(clk); 142 if (ret) { 143 dev_err(dev, "failed to prepare/enable the clock\n"); 144 return ret; 145 } 146 147 ret = devm_add_action_or_reset(dev, rzn1_wdt_clk_disable_unprepare, 148 clk); 149 if (ret) 150 return ret; 151 152 clk_rate = clk_get_rate(clk); 153 if (!clk_rate) { 154 dev_err(dev, "failed to get the clock rate\n"); 155 return -EINVAL; 156 } 157 158 wdt->clk_rate_khz = clk_rate / 1000; 159 wdt->wdtdev.info = &rzn1_wdt_info, 160 wdt->wdtdev.ops = &rzn1_wdt_ops, 161 wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS, 162 wdt->wdtdev.parent = dev; 163 /* 164 * The period of the watchdog cannot be changed once set 165 * and is limited to a very short period. 166 * Configure it for a 1s period once and for all, and 167 * rely on the heart-beat provided by the watchdog core 168 * to make this usable by the user-space. 169 */ 170 wdt->wdtdev.max_hw_heartbeat_ms = max_heart_beat_ms(wdt->clk_rate_khz); 171 if (wdt->wdtdev.max_hw_heartbeat_ms > 1000) 172 wdt->wdtdev.max_hw_heartbeat_ms = 1000; 173 174 wdt->wdtdev.timeout = DEFAULT_TIMEOUT; 175 ret = watchdog_init_timeout(&wdt->wdtdev, 0, dev); 176 if (ret) 177 return ret; 178 179 watchdog_set_drvdata(&wdt->wdtdev, wdt); 180 181 return devm_watchdog_register_device(dev, &wdt->wdtdev); 182 } 183 184 185 static const struct of_device_id rzn1_wdt_match[] = { 186 { .compatible = "renesas,rzn1-wdt" }, 187 {}, 188 }; 189 MODULE_DEVICE_TABLE(of, rzn1_wdt_match); 190 191 static struct platform_driver rzn1_wdt_driver = { 192 .probe = rzn1_wdt_probe, 193 .driver = { 194 .name = KBUILD_MODNAME, 195 .of_match_table = rzn1_wdt_match, 196 }, 197 }; 198 199 module_platform_driver(rzn1_wdt_driver); 200 201 MODULE_DESCRIPTION("Renesas RZ/N1 hardware watchdog"); 202 MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>"); 203 MODULE_LICENSE("GPL"); 204