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> 14*3ddf1a0dSryan_chen #include <asm/arch/scu_ast2500.h> 158f6d5bbbSryan_chen 16*3ddf1a0dSryan_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 { 24*3ddf1a0dSryan_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 { 62*3ddf1a0dSryan_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 { 70*3ddf1a0dSryan_chen struct ast2500_reset_priv *priv = dev_get_priv(dev); 71*3ddf1a0dSryan_chen struct udevice *clk_dev; 72*3ddf1a0dSryan_chen int ret = 0; 738f6d5bbbSryan_chen 74*3ddf1a0dSryan_chen /* find SCU base address from clock device */ 75*3ddf1a0dSryan_chen ret = uclass_get_device_by_driver(UCLASS_CLK, DM_GET_DRIVER(aspeed_scu), 76*3ddf1a0dSryan_chen &clk_dev); 77*3ddf1a0dSryan_chen if (ret) { 78*3ddf1a0dSryan_chen debug("clock device not found\n"); 79*3ddf1a0dSryan_chen return ret; 80*3ddf1a0dSryan_chen } 81*3ddf1a0dSryan_chen 82*3ddf1a0dSryan_chen priv->scu = devfdt_get_addr_ptr(clk_dev); 83*3ddf1a0dSryan_chen if (IS_ERR(priv->scu)) { 84*3ddf1a0dSryan_chen debug("%s(): can't get SCU\n", __func__); 85*3ddf1a0dSryan_chen return PTR_ERR(priv->scu); 86*3ddf1a0dSryan_chen } 87*3ddf1a0dSryan_chen 88*3ddf1a0dSryan_chen return 0; 89*3ddf1a0dSryan_chen } 90*3ddf1a0dSryan_chen static int aspeed_ofdata_to_platdata(struct udevice *dev) 91*3ddf1a0dSryan_chen { 92*3ddf1a0dSryan_chen struct ast2500_reset_priv *priv = dev_get_priv(dev); 93*3ddf1a0dSryan_chen int ret; 94*3ddf1a0dSryan_chen 95*3ddf1a0dSryan_chen ret = uclass_get_device_by_phandle(UCLASS_WDT, dev, "aspeed,wdt", 96*3ddf1a0dSryan_chen &priv->wdt); 97*3ddf1a0dSryan_chen if (ret) { 98*3ddf1a0dSryan_chen debug("%s: can't find WDT for reset controller", __func__); 99*3ddf1a0dSryan_chen return ret; 100*3ddf1a0dSryan_chen } 1018f6d5bbbSryan_chen 1028f6d5bbbSryan_chen return 0; 1038f6d5bbbSryan_chen } 1048f6d5bbbSryan_chen 1058f6d5bbbSryan_chen static const struct udevice_id aspeed_reset_ids[] = { 1068f6d5bbbSryan_chen { .compatible = "aspeed,ast2500-reset" }, 1078f6d5bbbSryan_chen { } 1088f6d5bbbSryan_chen }; 1098f6d5bbbSryan_chen 1108f6d5bbbSryan_chen struct reset_ops aspeed_reset_ops = { 11139283ea7Sryan_chen .rst_assert = ast2500_reset_assert, 11239283ea7Sryan_chen .request = ast2500_reset_request, 1138f6d5bbbSryan_chen }; 1148f6d5bbbSryan_chen 1158f6d5bbbSryan_chen U_BOOT_DRIVER(aspeed_reset) = { 1168f6d5bbbSryan_chen .name = "aspeed_reset", 1178f6d5bbbSryan_chen .id = UCLASS_RESET, 1188f6d5bbbSryan_chen .of_match = aspeed_reset_ids, 11939283ea7Sryan_chen .probe = ast2500_reset_probe, 1208f6d5bbbSryan_chen .ops = &aspeed_reset_ops, 1218f6d5bbbSryan_chen .ofdata_to_platdata = aspeed_ofdata_to_platdata, 122*3ddf1a0dSryan_chen .priv_auto_alloc_size = sizeof(struct ast2500_reset_priv), 1238f6d5bbbSryan_chen }; 124