11eb0a464Smaxims@google.com /* 21eb0a464Smaxims@google.com * Copyright 2017 Google, Inc 31eb0a464Smaxims@google.com * 41eb0a464Smaxims@google.com * SPDX-License-Identifier: GPL-2.0+ 51eb0a464Smaxims@google.com */ 61eb0a464Smaxims@google.com 71eb0a464Smaxims@google.com #include <common.h> 81eb0a464Smaxims@google.com #include <dm.h> 91eb0a464Smaxims@google.com #include <errno.h> 101eb0a464Smaxims@google.com #include <wdt.h> 111eb0a464Smaxims@google.com #include <asm/io.h> 121eb0a464Smaxims@google.com #include <asm/arch/wdt.h> 131eb0a464Smaxims@google.com 141eb0a464Smaxims@google.com #define WDT_AST2500 2500 151eb0a464Smaxims@google.com #define WDT_AST2400 2400 161eb0a464Smaxims@google.com 171eb0a464Smaxims@google.com DECLARE_GLOBAL_DATA_PTR; 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); 281eb0a464Smaxims@google.com 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 561eb0a464Smaxims@google.com return 0; 571eb0a464Smaxims@google.com } 581eb0a464Smaxims@google.com 591eb0a464Smaxims@google.com static int ast_wdt_reset(struct udevice *dev) 601eb0a464Smaxims@google.com { 611eb0a464Smaxims@google.com struct ast_wdt_priv *priv = dev_get_priv(dev); 621eb0a464Smaxims@google.com 631eb0a464Smaxims@google.com writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart); 641eb0a464Smaxims@google.com 651eb0a464Smaxims@google.com return 0; 661eb0a464Smaxims@google.com } 671eb0a464Smaxims@google.com 681eb0a464Smaxims@google.com static int ast_wdt_expire_now(struct udevice *dev, ulong flags) 691eb0a464Smaxims@google.com { 701eb0a464Smaxims@google.com struct ast_wdt_priv *priv = dev_get_priv(dev); 711eb0a464Smaxims@google.com int ret; 721eb0a464Smaxims@google.com 731eb0a464Smaxims@google.com ret = ast_wdt_start(dev, 1, flags); 741eb0a464Smaxims@google.com if (ret) 751eb0a464Smaxims@google.com return ret; 761eb0a464Smaxims@google.com 771eb0a464Smaxims@google.com while (readl(&priv->regs->ctrl) & WDT_CTRL_EN) 781eb0a464Smaxims@google.com ; 791eb0a464Smaxims@google.com 801eb0a464Smaxims@google.com return ast_wdt_stop(dev); 811eb0a464Smaxims@google.com } 821eb0a464Smaxims@google.com 831eb0a464Smaxims@google.com static int ast_wdt_ofdata_to_platdata(struct udevice *dev) 841eb0a464Smaxims@google.com { 851eb0a464Smaxims@google.com struct ast_wdt_priv *priv = dev_get_priv(dev); 861eb0a464Smaxims@google.com 87*a821c4afSSimon Glass priv->regs = devfdt_get_addr_ptr(dev); 881eb0a464Smaxims@google.com if (IS_ERR(priv->regs)) 891eb0a464Smaxims@google.com return PTR_ERR(priv->regs); 901eb0a464Smaxims@google.com 911eb0a464Smaxims@google.com return 0; 921eb0a464Smaxims@google.com } 931eb0a464Smaxims@google.com 941eb0a464Smaxims@google.com static const struct wdt_ops ast_wdt_ops = { 951eb0a464Smaxims@google.com .start = ast_wdt_start, 961eb0a464Smaxims@google.com .reset = ast_wdt_reset, 971eb0a464Smaxims@google.com .stop = ast_wdt_stop, 981eb0a464Smaxims@google.com .expire_now = ast_wdt_expire_now, 991eb0a464Smaxims@google.com }; 1001eb0a464Smaxims@google.com 1011eb0a464Smaxims@google.com static const struct udevice_id ast_wdt_ids[] = { 1021eb0a464Smaxims@google.com { .compatible = "aspeed,wdt", .data = WDT_AST2500 }, 1031eb0a464Smaxims@google.com { .compatible = "aspeed,ast2500-wdt", .data = WDT_AST2500 }, 1041eb0a464Smaxims@google.com { .compatible = "aspeed,ast2400-wdt", .data = WDT_AST2400 }, 1051eb0a464Smaxims@google.com {} 1061eb0a464Smaxims@google.com }; 1071eb0a464Smaxims@google.com 1081eb0a464Smaxims@google.com static int ast_wdt_probe(struct udevice *dev) 1091eb0a464Smaxims@google.com { 1101eb0a464Smaxims@google.com debug("%s() wdt%u\n", __func__, dev->seq); 1111eb0a464Smaxims@google.com ast_wdt_stop(dev); 1121eb0a464Smaxims@google.com 1131eb0a464Smaxims@google.com return 0; 1141eb0a464Smaxims@google.com } 1151eb0a464Smaxims@google.com 1161eb0a464Smaxims@google.com U_BOOT_DRIVER(ast_wdt) = { 1171eb0a464Smaxims@google.com .name = "ast_wdt", 1181eb0a464Smaxims@google.com .id = UCLASS_WDT, 1191eb0a464Smaxims@google.com .of_match = ast_wdt_ids, 1201eb0a464Smaxims@google.com .probe = ast_wdt_probe, 1211eb0a464Smaxims@google.com .priv_auto_alloc_size = sizeof(struct ast_wdt_priv), 1221eb0a464Smaxims@google.com .ofdata_to_platdata = ast_wdt_ofdata_to_platdata, 1231eb0a464Smaxims@google.com .ops = &ast_wdt_ops, 1241eb0a464Smaxims@google.com .flags = DM_FLAG_PRE_RELOC, 1251eb0a464Smaxims@google.com }; 126