1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <reset-uclass.h> 10 #include <linux/io.h> 11 12 struct rockchip_reset_priv { 13 void __iomem *base; 14 unsigned int sf_reset_offset; 15 unsigned int sf_reset_num; 16 }; 17 18 static int rockchip_reset_request(struct reset_ctl *reset_ctl) 19 { 20 struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev); 21 22 debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (sf_reset_num=%d)\n", __func__, 23 reset_ctl, reset_ctl->dev, reset_ctl->id, priv->sf_reset_num); 24 25 if (reset_ctl->id / 16 >= priv->sf_reset_num) 26 return -EINVAL; 27 28 return 0; 29 } 30 31 static int rockchip_reset_free(struct reset_ctl *reset_ctl) 32 { 33 debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl, 34 reset_ctl->dev, reset_ctl->id); 35 36 return 0; 37 } 38 39 static int rockchip_reset_assert(struct reset_ctl *reset_ctl) 40 { 41 struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev); 42 int bank = reset_ctl->id / 16; 43 int offset = reset_ctl->id % 16; 44 45 debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__, 46 reset_ctl, reset_ctl->dev, reset_ctl->id, 47 priv->base + (bank * 4)); 48 49 writel(BIT(offset) | (BIT(offset) << 16), priv->base + (bank * 4)); 50 51 return 0; 52 } 53 54 static int rockchip_reset_deassert(struct reset_ctl *reset_ctl) 55 { 56 struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev); 57 int bank = reset_ctl->id / 16; 58 int offset = reset_ctl->id % 16; 59 60 debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__, 61 reset_ctl, reset_ctl->dev, reset_ctl->id, 62 priv->base + (bank * 4)); 63 64 writel((BIT(offset) << 16), priv->base + (bank * 4)); 65 66 return 0; 67 } 68 69 struct reset_ops rockchip_reset_ops = { 70 .request = rockchip_reset_request, 71 .free = rockchip_reset_free, 72 .rst_assert = rockchip_reset_assert, 73 .rst_deassert = rockchip_reset_deassert, 74 }; 75 76 static int rockchip_reset_probe(struct udevice *dev) 77 { 78 struct rockchip_reset_priv *priv = dev_get_priv(dev); 79 fdt_addr_t addr; 80 fdt_size_t size; 81 82 addr = dev_read_addr_size(dev, "reg", &size); 83 if (addr == FDT_ADDR_T_NONE) 84 return -EINVAL; 85 86 if ((priv->sf_reset_offset == 0) && (priv->sf_reset_num == 0)) 87 return -EINVAL; 88 89 addr += priv->sf_reset_offset; 90 priv->base = ioremap(addr, size); 91 92 debug("%s(base=%p) (sf_reset_offset=%x, sf_reset_num=%d)\n", __func__, 93 priv->base, priv->sf_reset_offset, priv->sf_reset_num); 94 95 return 0; 96 } 97 98 U_BOOT_DRIVER(rockchip_reset) = { 99 .name = "rockchip_reset", 100 .id = UCLASS_RESET, 101 .probe = rockchip_reset_probe, 102 .ops = &rockchip_reset_ops, 103 .priv_auto_alloc_size = sizeof(struct rockchip_reset_priv), 104 }; 105