1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0 2760188c1SElaine Zhang /* 3760188c1SElaine Zhang * (C) Copyright 2017 Rockchip Electronics Co., Ltd 4760188c1SElaine Zhang */ 5760188c1SElaine Zhang 6760188c1SElaine Zhang #include <common.h> 7760188c1SElaine Zhang #include <dm.h> 8760188c1SElaine Zhang #include <reset-uclass.h> 9760188c1SElaine Zhang #include <linux/io.h> 10760188c1SElaine Zhang #include <asm/arch/hardware.h> 11760188c1SElaine Zhang #include <dm/lists.h> 12760188c1SElaine Zhang /* 13760188c1SElaine Zhang * Each reg has 16 bits reset signal for devices 14760188c1SElaine Zhang * Note: Not including rk2818 and older SoCs 15760188c1SElaine Zhang */ 16760188c1SElaine Zhang #define ROCKCHIP_RESET_NUM_IN_REG 16 17760188c1SElaine Zhang 18760188c1SElaine Zhang struct rockchip_reset_priv { 19760188c1SElaine Zhang void __iomem *base; 20760188c1SElaine Zhang /* Rockchip reset reg locate at cru controller */ 21760188c1SElaine Zhang u32 reset_reg_offset; 22760188c1SElaine Zhang /* Rockchip reset reg number */ 23760188c1SElaine Zhang u32 reset_reg_num; 24760188c1SElaine Zhang }; 25760188c1SElaine Zhang 26760188c1SElaine Zhang static int rockchip_reset_request(struct reset_ctl *reset_ctl) 27760188c1SElaine Zhang { 28760188c1SElaine Zhang struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev); 29760188c1SElaine Zhang 30760188c1SElaine Zhang debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_num=%d)\n", __func__, 31760188c1SElaine Zhang reset_ctl, reset_ctl->dev, reset_ctl->id, priv->reset_reg_num); 32760188c1SElaine Zhang 33760188c1SElaine Zhang if (reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG >= priv->reset_reg_num) 34760188c1SElaine Zhang return -EINVAL; 35760188c1SElaine Zhang 36760188c1SElaine Zhang return 0; 37760188c1SElaine Zhang } 38760188c1SElaine Zhang 39760188c1SElaine Zhang static int rockchip_reset_free(struct reset_ctl *reset_ctl) 40760188c1SElaine Zhang { 41760188c1SElaine Zhang debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl, 42760188c1SElaine Zhang reset_ctl->dev, reset_ctl->id); 43760188c1SElaine Zhang 44760188c1SElaine Zhang return 0; 45760188c1SElaine Zhang } 46760188c1SElaine Zhang 47760188c1SElaine Zhang static int rockchip_reset_assert(struct reset_ctl *reset_ctl) 48760188c1SElaine Zhang { 49760188c1SElaine Zhang struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev); 50760188c1SElaine Zhang int bank = reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG; 51760188c1SElaine Zhang int offset = reset_ctl->id % ROCKCHIP_RESET_NUM_IN_REG; 52760188c1SElaine Zhang 53760188c1SElaine Zhang debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__, 54760188c1SElaine Zhang reset_ctl, reset_ctl->dev, reset_ctl->id, 55760188c1SElaine Zhang priv->base + (bank * 4)); 56760188c1SElaine Zhang 57760188c1SElaine Zhang rk_setreg(priv->base + (bank * 4), BIT(offset)); 58760188c1SElaine Zhang 59760188c1SElaine Zhang return 0; 60760188c1SElaine Zhang } 61760188c1SElaine Zhang 62760188c1SElaine Zhang static int rockchip_reset_deassert(struct reset_ctl *reset_ctl) 63760188c1SElaine Zhang { 64760188c1SElaine Zhang struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev); 65760188c1SElaine Zhang int bank = reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG; 66760188c1SElaine Zhang int offset = reset_ctl->id % ROCKCHIP_RESET_NUM_IN_REG; 67760188c1SElaine Zhang 68760188c1SElaine Zhang debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__, 69760188c1SElaine Zhang reset_ctl, reset_ctl->dev, reset_ctl->id, 70760188c1SElaine Zhang priv->base + (bank * 4)); 71760188c1SElaine Zhang 72760188c1SElaine Zhang rk_clrreg(priv->base + (bank * 4), BIT(offset)); 73760188c1SElaine Zhang 74760188c1SElaine Zhang return 0; 75760188c1SElaine Zhang } 76760188c1SElaine Zhang 77760188c1SElaine Zhang struct reset_ops rockchip_reset_ops = { 78760188c1SElaine Zhang .request = rockchip_reset_request, 79760188c1SElaine Zhang .free = rockchip_reset_free, 80760188c1SElaine Zhang .rst_assert = rockchip_reset_assert, 81760188c1SElaine Zhang .rst_deassert = rockchip_reset_deassert, 82760188c1SElaine Zhang }; 83760188c1SElaine Zhang 84760188c1SElaine Zhang static int rockchip_reset_probe(struct udevice *dev) 85760188c1SElaine Zhang { 86760188c1SElaine Zhang struct rockchip_reset_priv *priv = dev_get_priv(dev); 87760188c1SElaine Zhang fdt_addr_t addr; 88760188c1SElaine Zhang fdt_size_t size; 89760188c1SElaine Zhang 90760188c1SElaine Zhang addr = dev_read_addr_size(dev, "reg", &size); 91760188c1SElaine Zhang if (addr == FDT_ADDR_T_NONE) 92760188c1SElaine Zhang return -EINVAL; 93760188c1SElaine Zhang 94760188c1SElaine Zhang if ((priv->reset_reg_offset == 0) && (priv->reset_reg_num == 0)) 95760188c1SElaine Zhang return -EINVAL; 96760188c1SElaine Zhang 97760188c1SElaine Zhang addr += priv->reset_reg_offset; 98760188c1SElaine Zhang priv->base = ioremap(addr, size); 99760188c1SElaine Zhang 100760188c1SElaine Zhang debug("%s(base=%p) (reg_offset=%x, reg_num=%d)\n", __func__, 101760188c1SElaine Zhang priv->base, priv->reset_reg_offset, priv->reset_reg_num); 102760188c1SElaine Zhang 103760188c1SElaine Zhang return 0; 104760188c1SElaine Zhang } 105760188c1SElaine Zhang 106760188c1SElaine Zhang int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number) 107760188c1SElaine Zhang { 108760188c1SElaine Zhang struct udevice *rst_dev; 109760188c1SElaine Zhang struct rockchip_reset_priv *priv; 110760188c1SElaine Zhang int ret; 111760188c1SElaine Zhang 112760188c1SElaine Zhang ret = device_bind_driver_to_node(pdev, "rockchip_reset", "reset", 113760188c1SElaine Zhang dev_ofnode(pdev), &rst_dev); 114760188c1SElaine Zhang if (ret) { 115760188c1SElaine Zhang debug("Warning: No rockchip reset driver: ret=%d\n", ret); 116760188c1SElaine Zhang return ret; 117760188c1SElaine Zhang } 118760188c1SElaine Zhang priv = malloc(sizeof(struct rockchip_reset_priv)); 119760188c1SElaine Zhang priv->reset_reg_offset = reg_offset; 120760188c1SElaine Zhang priv->reset_reg_num = reg_number; 121760188c1SElaine Zhang rst_dev->priv = priv; 122760188c1SElaine Zhang 123760188c1SElaine Zhang return 0; 124760188c1SElaine Zhang } 125760188c1SElaine Zhang 126760188c1SElaine Zhang U_BOOT_DRIVER(rockchip_reset) = { 127760188c1SElaine Zhang .name = "rockchip_reset", 128760188c1SElaine Zhang .id = UCLASS_RESET, 129760188c1SElaine Zhang .probe = rockchip_reset_probe, 130760188c1SElaine Zhang .ops = &rockchip_reset_ops, 131760188c1SElaine Zhang .priv_auto_alloc_size = sizeof(struct rockchip_reset_priv), 132760188c1SElaine Zhang }; 133