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
ast_wdt_start(struct udevice * dev,u64 timeout,ulong flags)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
ast_wdt_stop(struct udevice * dev)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
ast_wdt_reset(struct udevice * dev)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
ast_wdt_expire_now(struct udevice * dev,ulong flags)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
ast_wdt_ofdata_to_platdata(struct udevice * dev)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
ast_wdt_probe(struct udevice * dev)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