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 <misc.h> 9 #include <reset.h> 10 #include <reset-uclass.h> 11 #include <wdt.h> 12 #include <asm/io.h> 13 #include <asm/arch/scu_ast2500.h> 14 15 struct ast2500_reset_priv { 16 /* WDT used to perform resets. */ 17 struct udevice *wdt; 18 struct ast2500_scu *scu; 19 }; 20 21 static int ast2500_reset_deassert(struct reset_ctl *reset_ctl) 22 { 23 struct ast2500_reset_priv *priv = dev_get_priv(reset_ctl->dev); 24 struct ast2500_scu *scu = priv->scu; 25 int ret = 0; 26 27 debug("ast2500_reset_deassert reset_ctl->id %ld \n", reset_ctl->id); 28 29 if(reset_ctl->id >= 32) 30 clrbits_le32(&scu->sysreset_ctrl2 , BIT(reset_ctl->id - 32)); 31 else 32 clrbits_le32(&scu->sysreset_ctrl1 , BIT(reset_ctl->id)); 33 34 return ret; 35 } 36 37 static int ast2500_reset_assert(struct reset_ctl *reset_ctl) 38 { 39 struct ast2500_reset_priv *priv = dev_get_priv(reset_ctl->dev); 40 struct ast2500_scu *scu = priv->scu; 41 // u32 reset_mode, reset_mask; 42 // bool reset_sdram; 43 int ret = 0; 44 45 debug("ast2500_reset_assert reset_ctl->id %ld \n", reset_ctl->id); 46 /* 47 * To reset SDRAM, a specifal flag in SYSRESET register 48 * needs to be enabled first 49 */ 50 #if 0 51 reset_mode = ast_reset_mode_from_flags(reset_ctl->id); 52 reset_mask = ast_reset_mask_from_flags(reset_ctl->id); 53 reset_sdram = reset_mode == WDT_CTRL_RESET_SOC && 54 (reset_mask & WDT_RESET_SDRAM); 55 56 if (reset_sdram) { 57 ast_scu_unlock(priv->scu); 58 setbits_le32(&priv->scu->sysreset_ctrl1, 59 SCU_SYSRESET_SDRAM_WDT); 60 ret = wdt_expire_now(priv->wdt, reset_ctl->id); 61 clrbits_le32(&priv->scu->sysreset_ctrl1, 62 SCU_SYSRESET_SDRAM_WDT); 63 ast_scu_lock(priv->scu); 64 } else { 65 ret = wdt_expire_now(priv->wdt, reset_ctl->id); 66 } 67 #endif 68 if(reset_ctl->id >= 32) 69 setbits_le32(&scu->sysreset_ctrl2 , BIT(reset_ctl->id - 32)); 70 else 71 setbits_le32(&scu->sysreset_ctrl1 , BIT(reset_ctl->id)); 72 73 return ret; 74 } 75 76 77 static int ast2500_reset_request(struct reset_ctl *reset_ctl) 78 { 79 debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl, 80 reset_ctl->dev, reset_ctl->id); 81 82 return 0; 83 } 84 85 static int ast2500_reset_probe(struct udevice *dev) 86 { 87 struct ast2500_reset_priv *priv = dev_get_priv(dev); 88 struct udevice *clk_dev; 89 int ret = 0; 90 91 /* find SCU base address from clock device */ 92 ret = uclass_get_device_by_driver(UCLASS_CLK, DM_GET_DRIVER(aspeed_scu), 93 &clk_dev); 94 if (ret) { 95 debug("clock device not found\n"); 96 return ret; 97 } 98 99 priv->scu = devfdt_get_addr_ptr(clk_dev); 100 if (IS_ERR(priv->scu)) { 101 debug("%s(): can't get SCU\n", __func__); 102 return PTR_ERR(priv->scu); 103 } 104 105 return 0; 106 } 107 108 static int ast2500_ofdata_to_platdata(struct udevice *dev) 109 { 110 struct ast2500_reset_priv *priv = dev_get_priv(dev); 111 int ret; 112 113 ret = uclass_get_device_by_phandle(UCLASS_WDT, dev, "aspeed,wdt", 114 &priv->wdt); 115 if (ret) { 116 debug("%s: can't find WDT for reset controller", __func__); 117 return ret; 118 } 119 120 return 0; 121 } 122 123 static const struct udevice_id aspeed_reset_ids[] = { 124 { .compatible = "aspeed,ast2500-reset" }, 125 { } 126 }; 127 128 struct reset_ops aspeed_reset_ops = { 129 .rst_assert = ast2500_reset_assert, 130 .rst_deassert = ast2500_reset_deassert, 131 .request = ast2500_reset_request, 132 }; 133 134 U_BOOT_DRIVER(aspeed_reset) = { 135 .name = "aspeed_reset", 136 .id = UCLASS_RESET, 137 .of_match = aspeed_reset_ids, 138 .probe = ast2500_reset_probe, 139 .ops = &aspeed_reset_ops, 140 .ofdata_to_platdata = ast2500_ofdata_to_platdata, 141 .priv_auto_alloc_size = sizeof(struct ast2500_reset_priv), 142 }; 143