1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2017 Google, Inc 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <errno.h> 9 #include <wdt.h> 10 #include <asm/io.h> 11 12 /* 13 * Special value that needs to be written to counter_restart register to 14 * (re)start the timer 15 */ 16 #define WDT_COUNTER_RESTART_VAL 0x4755 17 18 /* Control register */ 19 #define WDT_CTRL_RESET_MODE_SHIFT 5 20 #define WDT_CTRL_RESET_MODE_MASK 3 21 22 #define WDT_CTRL_EN (1 << 0) 23 #define WDT_CTRL_RESET (1 << 1) 24 #define WDT_CTRL_CLK1MHZ (1 << 4) 25 #define WDT_CTRL_2ND_BOOT (1 << 7) 26 27 /* Values for Reset Mode */ 28 #define WDT_CTRL_RESET_SOC 0 29 #define WDT_CTRL_RESET_CHIP 1 30 #define WDT_CTRL_RESET_CPU 2 31 #define WDT_CTRL_RESET_MASK 3 32 33 /* Reset Mask register */ 34 #define WDT_RESET_ARM (1 << 0) 35 #define WDT_RESET_COPROC (1 << 1) 36 #define WDT_RESET_SDRAM (1 << 2) 37 #define WDT_RESET_AHB (1 << 3) 38 #define WDT_RESET_I2C (1 << 4) 39 #define WDT_RESET_MAC1 (1 << 5) 40 #define WDT_RESET_MAC2 (1 << 6) 41 #define WDT_RESET_GCRT (1 << 7) 42 #define WDT_RESET_USB20 (1 << 8) 43 #define WDT_RESET_USB11_HOST (1 << 9) 44 #define WDT_RESET_USB11_EHCI2 (1 << 10) 45 #define WDT_RESET_VIDEO (1 << 11) 46 #define WDT_RESET_HAC (1 << 12) 47 #define WDT_RESET_LPC (1 << 13) 48 #define WDT_RESET_SDSDIO (1 << 14) 49 #define WDT_RESET_MIC (1 << 15) 50 #define WDT_RESET_CRT2C (1 << 16) 51 #define WDT_RESET_PWM (1 << 17) 52 #define WDT_RESET_PECI (1 << 18) 53 #define WDT_RESET_JTAG (1 << 19) 54 #define WDT_RESET_ADC (1 << 20) 55 #define WDT_RESET_GPIO (1 << 21) 56 #define WDT_RESET_MCTP (1 << 22) 57 #define WDT_RESET_XDMA (1 << 23) 58 #define WDT_RESET_SPI (1 << 24) 59 #define WDT_RESET_MISC (1 << 25) 60 61 #define WDT_RESET_DEFAULT \ 62 (WDT_RESET_ARM | WDT_RESET_COPROC | WDT_RESET_I2C | \ 63 WDT_RESET_MAC1 | WDT_RESET_MAC2 | WDT_RESET_GCRT | \ 64 WDT_RESET_USB20 | WDT_RESET_USB11_HOST | WDT_RESET_USB11_EHCI2 | \ 65 WDT_RESET_VIDEO | WDT_RESET_HAC | WDT_RESET_LPC | \ 66 WDT_RESET_SDSDIO | WDT_RESET_MIC | WDT_RESET_CRT2C | \ 67 WDT_RESET_PWM | WDT_RESET_PECI | WDT_RESET_JTAG | \ 68 WDT_RESET_ADC | WDT_RESET_GPIO | WDT_RESET_MISC) 69 70 enum aspeed_wdt_model { 71 WDT_AST2400, 72 WDT_AST2500, 73 WDT_AST2600, 74 }; 75 76 struct ast_wdt { 77 u32 counter_status; 78 u32 counter_reload_val; 79 u32 counter_restart; 80 u32 ctrl; 81 u32 timeout_status; 82 u32 clr_timeout_status; 83 u32 reset_width; 84 /* On pre-ast2500 SoCs this register is reserved. */ 85 u32 reset_mask1; 86 u32 reset_mask2; //ast2600 support 87 u32 sw_ctrl; //ast2600 support 88 u32 sw_reset_mask1; //ast2600 support 89 u32 sw_reset_mask2; //ast2600 support 90 u32 sw_fun_disable; //ast2600 support 91 92 }; 93 94 struct ast_wdt_priv { 95 struct ast_wdt *regs; 96 }; 97 98 static int ast_wdt_start(struct udevice *dev, u64 timeout, ulong flags) 99 { 100 struct ast_wdt_priv *priv = dev_get_priv(dev); 101 102 writel((u32) timeout, &priv->regs->counter_reload_val); 103 104 writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart); 105 106 writel(WDT_CTRL_EN | WDT_CTRL_RESET, &priv->regs->ctrl); 107 108 return 0; 109 } 110 111 static int ast_wdt_stop(struct udevice *dev) 112 { 113 struct ast_wdt_priv *priv = dev_get_priv(dev); 114 ulong driver_data = dev_get_driver_data(dev); 115 116 clrbits_le32(&priv->regs->ctrl, WDT_CTRL_EN); 117 118 if(driver_data == WDT_AST2600) { 119 writel(0x030f1ff1, &priv->regs->reset_mask1); 120 writel(0x3fffff1, &priv->regs->reset_mask2); 121 } else 122 writel(WDT_RESET_DEFAULT, &priv->regs->reset_mask1); 123 124 return 0; 125 } 126 127 static int ast_wdt_reset(struct udevice *dev) 128 { 129 struct ast_wdt_priv *priv = dev_get_priv(dev); 130 131 writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart); 132 133 return 0; 134 } 135 136 static int ast_wdt_expire_now(struct udevice *dev, ulong flags) 137 { 138 struct ast_wdt_priv *priv = dev_get_priv(dev); 139 int ret; 140 141 ret = ast_wdt_start(dev, 1, flags); 142 if (ret) 143 return ret; 144 145 while (readl(&priv->regs->ctrl) & WDT_CTRL_EN); 146 147 return ast_wdt_stop(dev); 148 } 149 150 static int ast_wdt_ofdata_to_platdata(struct udevice *dev) 151 { 152 struct ast_wdt_priv *priv = dev_get_priv(dev); 153 154 priv->regs = devfdt_get_addr_ptr(dev); 155 if (IS_ERR(priv->regs)) 156 return PTR_ERR(priv->regs); 157 158 return 0; 159 } 160 161 static const struct wdt_ops ast_wdt_ops = { 162 .start = ast_wdt_start, 163 .reset = ast_wdt_reset, 164 .stop = ast_wdt_stop, 165 .expire_now = ast_wdt_expire_now, 166 }; 167 168 static int ast_wdt_probe(struct udevice *dev) 169 { 170 debug("%s() wdt%u\n", __func__, dev->seq); 171 ast_wdt_stop(dev); 172 173 return 0; 174 } 175 176 static const struct udevice_id ast_wdt_ids[] = { 177 { .compatible = "aspeed,wdt", .data = WDT_AST2500 }, 178 { .compatible = "aspeed,ast2600-wdt", .data = WDT_AST2600 }, 179 { .compatible = "aspeed,ast2500-wdt", .data = WDT_AST2500 }, 180 { .compatible = "aspeed,ast2400-wdt", .data = WDT_AST2400 }, 181 {} 182 }; 183 184 U_BOOT_DRIVER(ast_wdt) = { 185 .name = "ast_wdt", 186 .id = UCLASS_WDT, 187 .of_match = ast_wdt_ids, 188 .probe = ast_wdt_probe, 189 .priv_auto_alloc_size = sizeof(struct ast_wdt_priv), 190 .ofdata_to_platdata = ast_wdt_ofdata_to_platdata, 191 .ops = &ast_wdt_ops, 192 }; 193