18f6d5bbbSryan_chen // SPDX-License-Identifier: GPL-2.0 28f6d5bbbSryan_chen /* 38f6d5bbbSryan_chen * Copyright 2017 Google, Inc 48f6d5bbbSryan_chen */ 58f6d5bbbSryan_chen 68f6d5bbbSryan_chen #include <common.h> 78f6d5bbbSryan_chen #include <dm.h> 88f6d5bbbSryan_chen #include <misc.h> 98f6d5bbbSryan_chen #include <reset.h> 108f6d5bbbSryan_chen #include <reset-uclass.h> 118f6d5bbbSryan_chen #include <wdt.h> 128f6d5bbbSryan_chen #include <asm/io.h> 138f6d5bbbSryan_chen #include <asm/arch/wdt.h> 143ddf1a0dSryan_chen #include <asm/arch/scu_ast2500.h> 158f6d5bbbSryan_chen 163ddf1a0dSryan_chen struct ast2500_reset_priv { 178f6d5bbbSryan_chen /* WDT used to perform resets. */ 188f6d5bbbSryan_chen struct udevice *wdt; 198f6d5bbbSryan_chen struct ast2500_scu *scu; 208f6d5bbbSryan_chen }; 218f6d5bbbSryan_chen 2239283ea7Sryan_chen static int ast2500_reset_assert(struct reset_ctl *reset_ctl) 238f6d5bbbSryan_chen { 243ddf1a0dSryan_chen struct ast2500_reset_priv *priv = dev_get_priv(reset_ctl->dev); 2539283ea7Sryan_chen struct ast2500_scu *scu = priv->scu; 268f6d5bbbSryan_chen u32 reset_mode, reset_mask; 278f6d5bbbSryan_chen bool reset_sdram; 2839283ea7Sryan_chen int ret = 0; 298f6d5bbbSryan_chen 3039283ea7Sryan_chen printf("ast2500_reset_assert reset_ctl->id %d \n", reset_ctl->id); 318f6d5bbbSryan_chen /* 328f6d5bbbSryan_chen * To reset SDRAM, a specifal flag in SYSRESET register 338f6d5bbbSryan_chen * needs to be enabled first 348f6d5bbbSryan_chen */ 358f6d5bbbSryan_chen reset_mode = ast_reset_mode_from_flags(reset_ctl->id); 368f6d5bbbSryan_chen reset_mask = ast_reset_mask_from_flags(reset_ctl->id); 378f6d5bbbSryan_chen reset_sdram = reset_mode == WDT_CTRL_RESET_SOC && 388f6d5bbbSryan_chen (reset_mask & WDT_RESET_SDRAM); 398f6d5bbbSryan_chen #if 0 408f6d5bbbSryan_chen if (reset_sdram) { 418f6d5bbbSryan_chen ast_scu_unlock(priv->scu); 428f6d5bbbSryan_chen setbits_le32(&priv->scu->sysreset_ctrl1, 438f6d5bbbSryan_chen SCU_SYSRESET_SDRAM_WDT); 448f6d5bbbSryan_chen ret = wdt_expire_now(priv->wdt, reset_ctl->id); 458f6d5bbbSryan_chen clrbits_le32(&priv->scu->sysreset_ctrl1, 468f6d5bbbSryan_chen SCU_SYSRESET_SDRAM_WDT); 478f6d5bbbSryan_chen ast_scu_lock(priv->scu); 488f6d5bbbSryan_chen } else { 498f6d5bbbSryan_chen ret = wdt_expire_now(priv->wdt, reset_ctl->id); 508f6d5bbbSryan_chen } 518f6d5bbbSryan_chen #endif 5239283ea7Sryan_chen if(reset_ctl->id >= 32) 5339283ea7Sryan_chen setbits_le32(scu->sysreset_ctrl1 , BIT(reset_ctl->id - 32)); 5439283ea7Sryan_chen else 5539283ea7Sryan_chen setbits_le32(scu->sysreset_ctrl1 , BIT(reset_ctl->id)); 5639283ea7Sryan_chen 578f6d5bbbSryan_chen return ret; 588f6d5bbbSryan_chen } 598f6d5bbbSryan_chen 6039283ea7Sryan_chen static int ast2500_reset_request(struct reset_ctl *reset_ctl) 618f6d5bbbSryan_chen { 623ddf1a0dSryan_chen debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl, 638f6d5bbbSryan_chen reset_ctl->dev, reset_ctl->id); 648f6d5bbbSryan_chen 658f6d5bbbSryan_chen return 0; 668f6d5bbbSryan_chen } 678f6d5bbbSryan_chen 6839283ea7Sryan_chen static int ast2500_reset_probe(struct udevice *dev) 698f6d5bbbSryan_chen { 703ddf1a0dSryan_chen struct ast2500_reset_priv *priv = dev_get_priv(dev); 713ddf1a0dSryan_chen struct udevice *clk_dev; 723ddf1a0dSryan_chen int ret = 0; 738f6d5bbbSryan_chen 743ddf1a0dSryan_chen /* find SCU base address from clock device */ 753ddf1a0dSryan_chen ret = uclass_get_device_by_driver(UCLASS_CLK, DM_GET_DRIVER(aspeed_scu), 763ddf1a0dSryan_chen &clk_dev); 773ddf1a0dSryan_chen if (ret) { 783ddf1a0dSryan_chen debug("clock device not found\n"); 793ddf1a0dSryan_chen return ret; 803ddf1a0dSryan_chen } 813ddf1a0dSryan_chen 823ddf1a0dSryan_chen priv->scu = devfdt_get_addr_ptr(clk_dev); 833ddf1a0dSryan_chen if (IS_ERR(priv->scu)) { 843ddf1a0dSryan_chen debug("%s(): can't get SCU\n", __func__); 853ddf1a0dSryan_chen return PTR_ERR(priv->scu); 863ddf1a0dSryan_chen } 873ddf1a0dSryan_chen 883ddf1a0dSryan_chen return 0; 893ddf1a0dSryan_chen } 90*2fa13dd8Sryan_chen 91*2fa13dd8Sryan_chen static int ast2500_ofdata_to_platdata(struct udevice *dev) 923ddf1a0dSryan_chen { 933ddf1a0dSryan_chen struct ast2500_reset_priv *priv = dev_get_priv(dev); 943ddf1a0dSryan_chen int ret; 953ddf1a0dSryan_chen 963ddf1a0dSryan_chen ret = uclass_get_device_by_phandle(UCLASS_WDT, dev, "aspeed,wdt", 973ddf1a0dSryan_chen &priv->wdt); 983ddf1a0dSryan_chen if (ret) { 993ddf1a0dSryan_chen debug("%s: can't find WDT for reset controller", __func__); 1003ddf1a0dSryan_chen return ret; 1013ddf1a0dSryan_chen } 1028f6d5bbbSryan_chen 1038f6d5bbbSryan_chen return 0; 1048f6d5bbbSryan_chen } 1058f6d5bbbSryan_chen 1068f6d5bbbSryan_chen static const struct udevice_id aspeed_reset_ids[] = { 1078f6d5bbbSryan_chen { .compatible = "aspeed,ast2500-reset" }, 1088f6d5bbbSryan_chen { } 1098f6d5bbbSryan_chen }; 1108f6d5bbbSryan_chen 1118f6d5bbbSryan_chen struct reset_ops aspeed_reset_ops = { 11239283ea7Sryan_chen .rst_assert = ast2500_reset_assert, 11339283ea7Sryan_chen .request = ast2500_reset_request, 1148f6d5bbbSryan_chen }; 1158f6d5bbbSryan_chen 1168f6d5bbbSryan_chen U_BOOT_DRIVER(aspeed_reset) = { 1178f6d5bbbSryan_chen .name = "aspeed_reset", 1188f6d5bbbSryan_chen .id = UCLASS_RESET, 1198f6d5bbbSryan_chen .of_match = aspeed_reset_ids, 12039283ea7Sryan_chen .probe = ast2500_reset_probe, 1218f6d5bbbSryan_chen .ops = &aspeed_reset_ops, 122*2fa13dd8Sryan_chen .ofdata_to_platdata = ast2500_ofdata_to_platdata, 1233ddf1a0dSryan_chen .priv_auto_alloc_size = sizeof(struct ast2500_reset_priv), 1248f6d5bbbSryan_chen }; 125