183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 21eb0a464Smaxims@google.com /* 31eb0a464Smaxims@google.com * Copyright 2017 Google, Inc 41eb0a464Smaxims@google.com */ 51eb0a464Smaxims@google.com 61eb0a464Smaxims@google.com #include <common.h> 71eb0a464Smaxims@google.com #include <dm.h> 81eb0a464Smaxims@google.com #include <errno.h> 91eb0a464Smaxims@google.com #include <wdt.h> 101eb0a464Smaxims@google.com #include <asm/io.h> 111eb0a464Smaxims@google.com #include <asm/arch/wdt.h> 121eb0a464Smaxims@google.com 13612dc3e3Sryan_chen enum aspeed_wdt_model { 14612dc3e3Sryan_chen WDT_AST2400, 15612dc3e3Sryan_chen WDT_AST2500, 16612dc3e3Sryan_chen WDT_AST2600, 17612dc3e3Sryan_chen }; 181eb0a464Smaxims@google.com 191eb0a464Smaxims@google.com struct ast_wdt_priv { 201eb0a464Smaxims@google.com struct ast_wdt *regs; 211eb0a464Smaxims@google.com }; 221eb0a464Smaxims@google.com 231eb0a464Smaxims@google.com static int ast_wdt_start(struct udevice *dev, u64 timeout, ulong flags) 241eb0a464Smaxims@google.com { 251eb0a464Smaxims@google.com struct ast_wdt_priv *priv = dev_get_priv(dev); 261eb0a464Smaxims@google.com ulong driver_data = dev_get_driver_data(dev); 271eb0a464Smaxims@google.com u32 reset_mode = ast_reset_mode_from_flags(flags); 28*10655ec9Sryan_chen printf("ast_wdt_start to %ld \n", timeout); 291eb0a464Smaxims@google.com clrsetbits_le32(&priv->regs->ctrl, 301eb0a464Smaxims@google.com WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT, 311eb0a464Smaxims@google.com reset_mode << WDT_CTRL_RESET_MODE_SHIFT); 321eb0a464Smaxims@google.com 331eb0a464Smaxims@google.com if (driver_data >= WDT_AST2500 && reset_mode == WDT_CTRL_RESET_SOC) 341eb0a464Smaxims@google.com writel(ast_reset_mask_from_flags(flags), 351eb0a464Smaxims@google.com &priv->regs->reset_mask); 361eb0a464Smaxims@google.com 371eb0a464Smaxims@google.com writel((u32) timeout, &priv->regs->counter_reload_val); 381eb0a464Smaxims@google.com writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart); 391eb0a464Smaxims@google.com /* 401eb0a464Smaxims@google.com * Setting CLK1MHZ bit is just for compatibility with ast2400 part. 411eb0a464Smaxims@google.com * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is 421eb0a464Smaxims@google.com * read-only 431eb0a464Smaxims@google.com */ 441eb0a464Smaxims@google.com setbits_le32(&priv->regs->ctrl, 451eb0a464Smaxims@google.com WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ); 461eb0a464Smaxims@google.com 471eb0a464Smaxims@google.com return 0; 481eb0a464Smaxims@google.com } 491eb0a464Smaxims@google.com 501eb0a464Smaxims@google.com static int ast_wdt_stop(struct udevice *dev) 511eb0a464Smaxims@google.com { 521eb0a464Smaxims@google.com struct ast_wdt_priv *priv = dev_get_priv(dev); 531eb0a464Smaxims@google.com 541eb0a464Smaxims@google.com clrbits_le32(&priv->regs->ctrl, WDT_CTRL_EN); 551eb0a464Smaxims@google.com 56e1a8dfdeSCédric Le Goater writel(WDT_RESET_DEFAULT, &priv->regs->reset_mask); 571eb0a464Smaxims@google.com return 0; 581eb0a464Smaxims@google.com } 591eb0a464Smaxims@google.com 601eb0a464Smaxims@google.com static int ast_wdt_reset(struct udevice *dev) 611eb0a464Smaxims@google.com { 621eb0a464Smaxims@google.com struct ast_wdt_priv *priv = dev_get_priv(dev); 631eb0a464Smaxims@google.com 641eb0a464Smaxims@google.com writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart); 651eb0a464Smaxims@google.com 661eb0a464Smaxims@google.com return 0; 671eb0a464Smaxims@google.com } 681eb0a464Smaxims@google.com 691eb0a464Smaxims@google.com static int ast_wdt_expire_now(struct udevice *dev, ulong flags) 701eb0a464Smaxims@google.com { 711eb0a464Smaxims@google.com struct ast_wdt_priv *priv = dev_get_priv(dev); 721eb0a464Smaxims@google.com int ret; 731eb0a464Smaxims@google.com 741eb0a464Smaxims@google.com ret = ast_wdt_start(dev, 1, flags); 751eb0a464Smaxims@google.com if (ret) 761eb0a464Smaxims@google.com return ret; 771eb0a464Smaxims@google.com 781eb0a464Smaxims@google.com while (readl(&priv->regs->ctrl) & WDT_CTRL_EN) 791eb0a464Smaxims@google.com ; 801eb0a464Smaxims@google.com 811eb0a464Smaxims@google.com return ast_wdt_stop(dev); 821eb0a464Smaxims@google.com } 831eb0a464Smaxims@google.com 841eb0a464Smaxims@google.com static int ast_wdt_ofdata_to_platdata(struct udevice *dev) 851eb0a464Smaxims@google.com { 861eb0a464Smaxims@google.com struct ast_wdt_priv *priv = dev_get_priv(dev); 871eb0a464Smaxims@google.com 88a821c4afSSimon Glass priv->regs = devfdt_get_addr_ptr(dev); 891eb0a464Smaxims@google.com if (IS_ERR(priv->regs)) 901eb0a464Smaxims@google.com return PTR_ERR(priv->regs); 911eb0a464Smaxims@google.com 921eb0a464Smaxims@google.com return 0; 931eb0a464Smaxims@google.com } 941eb0a464Smaxims@google.com 951eb0a464Smaxims@google.com static const struct wdt_ops ast_wdt_ops = { 961eb0a464Smaxims@google.com .start = ast_wdt_start, 971eb0a464Smaxims@google.com .reset = ast_wdt_reset, 981eb0a464Smaxims@google.com .stop = ast_wdt_stop, 991eb0a464Smaxims@google.com .expire_now = ast_wdt_expire_now, 1001eb0a464Smaxims@google.com }; 1011eb0a464Smaxims@google.com 1021eb0a464Smaxims@google.com static int ast_wdt_probe(struct udevice *dev) 1031eb0a464Smaxims@google.com { 1041eb0a464Smaxims@google.com debug("%s() wdt%u\n", __func__, dev->seq); 1051eb0a464Smaxims@google.com ast_wdt_stop(dev); 1061eb0a464Smaxims@google.com 1071eb0a464Smaxims@google.com return 0; 1081eb0a464Smaxims@google.com } 1091eb0a464Smaxims@google.com 110*10655ec9Sryan_chen static const struct udevice_id ast_wdt_ids[] = { 111*10655ec9Sryan_chen { .compatible = "aspeed,wdt", .data = WDT_AST2500 }, 112*10655ec9Sryan_chen { .compatible = "aspeed,ast2600-wdt", .data = WDT_AST2600 }, 113*10655ec9Sryan_chen { .compatible = "aspeed,ast2500-wdt", .data = WDT_AST2500 }, 114*10655ec9Sryan_chen { .compatible = "aspeed,ast2400-wdt", .data = WDT_AST2400 }, 115*10655ec9Sryan_chen {} 116*10655ec9Sryan_chen }; 117*10655ec9Sryan_chen 1181eb0a464Smaxims@google.com U_BOOT_DRIVER(ast_wdt) = { 1191eb0a464Smaxims@google.com .name = "ast_wdt", 1201eb0a464Smaxims@google.com .id = UCLASS_WDT, 1211eb0a464Smaxims@google.com .of_match = ast_wdt_ids, 1221eb0a464Smaxims@google.com .probe = ast_wdt_probe, 1231eb0a464Smaxims@google.com .priv_auto_alloc_size = sizeof(struct ast_wdt_priv), 1241eb0a464Smaxims@google.com .ofdata_to_platdata = ast_wdt_ofdata_to_platdata, 1251eb0a464Smaxims@google.com .ops = &ast_wdt_ops, 1261eb0a464Smaxims@google.com }; 127