1 // SPDX-License-Identifier: GPL-2.0 2 /* Marvell GTI Watchdog driver 3 * 4 * Copyright (C) 2023 Marvell. 5 */ 6 7 #include <linux/clk.h> 8 #include <linux/interrupt.h> 9 #include <linux/io.h> 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/of.h> 13 #include <linux/watchdog.h> 14 15 /* 16 * Hardware supports following mode of operation: 17 * 1) Interrupt Only: 18 * This will generate the interrupt to arm core whenever timeout happens. 19 * 20 * 2) Interrupt + del3t (Interrupt to firmware (SCP processor)). 21 * This will generate interrupt to arm core on 1st timeout happens 22 * This will generate interrupt to SCP processor on 2nd timeout happens 23 * 24 * 3) Interrupt + Interrupt to SCP processor (called delt3t) + reboot. 25 * This will generate interrupt to arm core on 1st timeout happens 26 * Will generate interrupt to SCP processor on 2nd timeout happens, 27 * if interrupt is configured. 28 * Reboot on 3rd timeout. 29 * 30 * Driver will use hardware in mode-3 above so that system can reboot in case 31 * a hardware hang. Also h/w is configured not to generate SCP interrupt, so 32 * effectively 2nd timeout is ignored within hardware. 33 * 34 * First timeout is effectively watchdog pretimeout. 35 */ 36 37 /* GTI CWD Watchdog (GTI_CWD_WDOG) Register */ 38 #define GTI_CWD_WDOG(reg_offset) (0x8 * (reg_offset)) 39 #define GTI_CWD_WDOG_MODE_INT_DEL3T_RST 0x3 40 #define GTI_CWD_WDOG_MODE_MASK GENMASK_ULL(1, 0) 41 #define GTI_CWD_WDOG_LEN_SHIFT 4 42 #define GTI_CWD_WDOG_LEN_MASK GENMASK_ULL(19, 4) 43 #define GTI_CWD_WDOG_CNT_SHIFT 20 44 #define GTI_CWD_WDOG_CNT_MASK GENMASK_ULL(43, 20) 45 46 /* GTI CWD Watchdog Interrupt (GTI_CWD_INT) Register */ 47 #define GTI_CWD_INT 0x200 48 #define GTI_CWD_INT_PENDING_STATUS(bit) BIT_ULL(bit) 49 50 /* GTI CWD Watchdog Interrupt Enable Clear (GTI_CWD_INT_ENA_CLR) Register */ 51 #define GTI_CWD_INT_ENA_CLR 0x210 52 #define GTI_CWD_INT_ENA_CLR_VAL(bit) BIT_ULL(bit) 53 54 /* GTI CWD Watchdog Interrupt Enable Set (GTI_CWD_INT_ENA_SET) Register */ 55 #define GTI_CWD_INT_ENA_SET 0x218 56 #define GTI_CWD_INT_ENA_SET_VAL(bit) BIT_ULL(bit) 57 58 /* GTI CWD Watchdog Poke (GTI_CWD_POKE) Registers */ 59 #define GTI_CWD_POKE(reg_offset) (0x10000 + 0x8 * (reg_offset)) 60 #define GTI_CWD_POKE_VAL 1 61 62 struct gti_match_data { 63 u32 gti_num_timers; 64 }; 65 66 static const struct gti_match_data match_data_octeontx2 = { 67 .gti_num_timers = 54, 68 }; 69 70 static const struct gti_match_data match_data_cn10k = { 71 .gti_num_timers = 64, 72 }; 73 74 struct gti_wdt_priv { 75 struct watchdog_device wdev; 76 void __iomem *base; 77 u32 clock_freq; 78 struct clk *sclk; 79 /* wdt_timer_idx used for timer to be used for system watchdog */ 80 u32 wdt_timer_idx; 81 const struct gti_match_data *data; 82 }; 83 84 static irqreturn_t gti_wdt_interrupt(int irq, void *data) 85 { 86 struct watchdog_device *wdev = data; 87 struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev); 88 89 /* Clear Interrupt Pending Status */ 90 writeq(GTI_CWD_INT_PENDING_STATUS(priv->wdt_timer_idx), 91 priv->base + GTI_CWD_INT); 92 93 watchdog_notify_pretimeout(wdev); 94 95 return IRQ_HANDLED; 96 } 97 98 static int gti_wdt_ping(struct watchdog_device *wdev) 99 { 100 struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev); 101 102 writeq(GTI_CWD_POKE_VAL, 103 priv->base + GTI_CWD_POKE(priv->wdt_timer_idx)); 104 105 return 0; 106 } 107 108 static int gti_wdt_start(struct watchdog_device *wdev) 109 { 110 struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev); 111 u64 regval; 112 113 if (!wdev->pretimeout) 114 return -EINVAL; 115 116 set_bit(WDOG_HW_RUNNING, &wdev->status); 117 118 /* Clear any pending interrupt */ 119 writeq(GTI_CWD_INT_PENDING_STATUS(priv->wdt_timer_idx), 120 priv->base + GTI_CWD_INT); 121 122 /* Enable Interrupt */ 123 writeq(GTI_CWD_INT_ENA_SET_VAL(priv->wdt_timer_idx), 124 priv->base + GTI_CWD_INT_ENA_SET); 125 126 /* Set (Interrupt + SCP interrupt (DEL3T) + core domain reset) Mode */ 127 regval = readq(priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx)); 128 regval |= GTI_CWD_WDOG_MODE_INT_DEL3T_RST; 129 writeq(regval, priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx)); 130 131 return 0; 132 } 133 134 static int gti_wdt_stop(struct watchdog_device *wdev) 135 { 136 struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev); 137 u64 regval; 138 139 /* Disable Interrupt */ 140 writeq(GTI_CWD_INT_ENA_CLR_VAL(priv->wdt_timer_idx), 141 priv->base + GTI_CWD_INT_ENA_CLR); 142 143 /* Set GTI_CWD_WDOG.Mode = 0 to stop the timer */ 144 regval = readq(priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx)); 145 regval &= ~GTI_CWD_WDOG_MODE_MASK; 146 writeq(regval, priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx)); 147 148 return 0; 149 } 150 151 static int gti_wdt_settimeout(struct watchdog_device *wdev, 152 unsigned int timeout) 153 { 154 struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev); 155 u64 timeout_wdog, regval; 156 157 /* Update new timeout */ 158 wdev->timeout = timeout; 159 160 /* Pretimeout is 1/3 of timeout */ 161 wdev->pretimeout = timeout / 3; 162 163 /* Get clock cycles from pretimeout */ 164 timeout_wdog = (u64)priv->clock_freq * wdev->pretimeout; 165 166 /* Watchdog counts in 1024 cycle steps */ 167 timeout_wdog = timeout_wdog >> 10; 168 169 /* GTI_CWD_WDOG.CNT: reload counter is 16-bit */ 170 timeout_wdog = (timeout_wdog + 0xff) >> 8; 171 if (timeout_wdog >= 0x10000) 172 timeout_wdog = 0xffff; 173 174 /* 175 * GTI_CWD_WDOG.LEN is 24bit, lower 8-bits should be zero and 176 * upper 16-bits are same as GTI_CWD_WDOG.CNT 177 */ 178 regval = readq(priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx)); 179 regval &= GTI_CWD_WDOG_MODE_MASK; 180 regval |= (timeout_wdog << (GTI_CWD_WDOG_CNT_SHIFT + 8)) | 181 (timeout_wdog << GTI_CWD_WDOG_LEN_SHIFT); 182 writeq(regval, priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx)); 183 184 return 0; 185 } 186 187 static int gti_wdt_set_pretimeout(struct watchdog_device *wdev, 188 unsigned int timeout) 189 { 190 struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev); 191 struct watchdog_device *wdog_dev = &priv->wdev; 192 193 if (!timeout) { 194 /* Disable Interrupt */ 195 writeq(GTI_CWD_INT_ENA_CLR_VAL(priv->wdt_timer_idx), 196 priv->base + GTI_CWD_INT_ENA_CLR); 197 return 0; 198 } 199 200 /* pretimeout should 1/3 of max_timeout */ 201 if (timeout * 3 <= wdog_dev->max_timeout) 202 return gti_wdt_settimeout(wdev, timeout * 3); 203 204 return -EINVAL; 205 } 206 207 static void gti_clk_disable_unprepare(void *data) 208 { 209 clk_disable_unprepare(data); 210 } 211 212 static int gti_wdt_get_cntfrq(struct platform_device *pdev, 213 struct gti_wdt_priv *priv) 214 { 215 int err; 216 217 priv->sclk = devm_clk_get_enabled(&pdev->dev, NULL); 218 if (IS_ERR(priv->sclk)) 219 return PTR_ERR(priv->sclk); 220 221 err = devm_add_action_or_reset(&pdev->dev, 222 gti_clk_disable_unprepare, priv->sclk); 223 if (err) 224 return err; 225 226 priv->clock_freq = clk_get_rate(priv->sclk); 227 if (!priv->clock_freq) 228 return -EINVAL; 229 230 return 0; 231 } 232 233 static const struct watchdog_info gti_wdt_ident = { 234 .identity = "Marvell GTI watchdog", 235 .options = WDIOF_SETTIMEOUT | WDIOF_PRETIMEOUT | WDIOF_KEEPALIVEPING | 236 WDIOF_MAGICCLOSE | WDIOF_CARDRESET, 237 }; 238 239 static const struct watchdog_ops gti_wdt_ops = { 240 .owner = THIS_MODULE, 241 .start = gti_wdt_start, 242 .stop = gti_wdt_stop, 243 .ping = gti_wdt_ping, 244 .set_timeout = gti_wdt_settimeout, 245 .set_pretimeout = gti_wdt_set_pretimeout, 246 }; 247 248 static int gti_wdt_probe(struct platform_device *pdev) 249 { 250 struct gti_wdt_priv *priv; 251 struct device *dev = &pdev->dev; 252 struct watchdog_device *wdog_dev; 253 u64 max_pretimeout; 254 u32 wdt_idx; 255 int irq; 256 int err; 257 258 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 259 if (!priv) 260 return -ENOMEM; 261 262 priv->base = devm_platform_ioremap_resource(pdev, 0); 263 if (IS_ERR(priv->base)) 264 return dev_err_probe(&pdev->dev, PTR_ERR(priv->base), 265 "reg property not valid/found\n"); 266 267 err = gti_wdt_get_cntfrq(pdev, priv); 268 if (err) 269 return dev_err_probe(&pdev->dev, err, 270 "GTI clock frequency not valid/found"); 271 272 priv->data = of_device_get_match_data(dev); 273 274 /* default use last timer for watchdog */ 275 priv->wdt_timer_idx = priv->data->gti_num_timers - 1; 276 277 err = of_property_read_u32(dev->of_node, "marvell,wdt-timer-index", 278 &wdt_idx); 279 if (!err) { 280 if (wdt_idx >= priv->data->gti_num_timers) 281 return dev_err_probe(&pdev->dev, -EINVAL, 282 "GTI wdog timer index not valid"); 283 284 priv->wdt_timer_idx = wdt_idx; 285 } 286 287 wdog_dev = &priv->wdev; 288 wdog_dev->info = >i_wdt_ident; 289 wdog_dev->ops = >i_wdt_ops; 290 wdog_dev->parent = dev; 291 /* 292 * Watchdog counter is 24 bit where lower 8 bits are zeros 293 * This counter decrements every 1024 clock cycles. 294 */ 295 max_pretimeout = (GTI_CWD_WDOG_CNT_MASK >> GTI_CWD_WDOG_CNT_SHIFT); 296 max_pretimeout &= ~0xFFUL; 297 max_pretimeout = (max_pretimeout * 1024) / priv->clock_freq; 298 wdog_dev->pretimeout = max_pretimeout; 299 300 /* Maximum timeout is 3 times the pretimeout */ 301 wdog_dev->max_timeout = max_pretimeout * 3; 302 wdog_dev->max_hw_heartbeat_ms = max_pretimeout * 1000; 303 /* Minimum first timeout (pretimeout) is 1, so min_timeout as 3 */ 304 wdog_dev->min_timeout = 3; 305 wdog_dev->timeout = wdog_dev->pretimeout; 306 307 watchdog_set_drvdata(wdog_dev, priv); 308 platform_set_drvdata(pdev, priv); 309 gti_wdt_settimeout(wdog_dev, wdog_dev->timeout); 310 watchdog_stop_on_reboot(wdog_dev); 311 watchdog_stop_on_unregister(wdog_dev); 312 313 err = devm_watchdog_register_device(dev, wdog_dev); 314 if (err) 315 return err; 316 317 irq = platform_get_irq(pdev, 0); 318 if (irq < 0) 319 return irq; 320 321 err = devm_request_irq(dev, irq, gti_wdt_interrupt, 0, 322 pdev->name, &priv->wdev); 323 if (err) 324 return dev_err_probe(dev, err, "Failed to register interrupt handler\n"); 325 326 dev_info(dev, "Watchdog enabled (timeout=%d sec)\n", wdog_dev->timeout); 327 return 0; 328 } 329 330 static const struct of_device_id gti_wdt_of_match[] = { 331 { .compatible = "marvell,cn9670-wdt", .data = &match_data_octeontx2}, 332 { .compatible = "marvell,cn10624-wdt", .data = &match_data_cn10k}, 333 { }, 334 }; 335 MODULE_DEVICE_TABLE(of, gti_wdt_of_match); 336 337 static struct platform_driver gti_wdt_driver = { 338 .driver = { 339 .name = "gti-wdt", 340 .of_match_table = gti_wdt_of_match, 341 }, 342 .probe = gti_wdt_probe, 343 }; 344 module_platform_driver(gti_wdt_driver); 345 346 MODULE_AUTHOR("Bharat Bhushan <bbhushan2@marvell.com>"); 347 MODULE_DESCRIPTION("Marvell GTI watchdog driver"); 348 MODULE_LICENSE("GPL"); 349