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 #include <asm/arch/hardware.h> 12 #include <dm/lists.h> 13 /* 14 * Each reg has 16 bits reset signal for devices 15 * Note: Not including rk2818 and older SoCs 16 */ 17 #define ROCKCHIP_RESET_NUM_IN_REG 16 18 19 struct rockchip_reset_priv { 20 void __iomem *base; 21 /* Rockchip reset reg locate at cru controller */ 22 u32 reset_reg_offset; 23 /* Rockchip reset reg number */ 24 u32 reset_reg_num; 25 }; 26 27 static int rockchip_reset_request(struct reset_ctl *reset_ctl) 28 { 29 struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev); 30 31 debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_num=%d)\n", __func__, 32 reset_ctl, reset_ctl->dev, reset_ctl->id, priv->reset_reg_num); 33 34 if (reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG >= priv->reset_reg_num) 35 return -EINVAL; 36 37 return 0; 38 } 39 40 static int rockchip_reset_free(struct reset_ctl *reset_ctl) 41 { 42 debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl, 43 reset_ctl->dev, reset_ctl->id); 44 45 return 0; 46 } 47 48 static int rockchip_reset_assert(struct reset_ctl *reset_ctl) 49 { 50 struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev); 51 int bank = reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG; 52 int offset = reset_ctl->id % ROCKCHIP_RESET_NUM_IN_REG; 53 54 debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__, 55 reset_ctl, reset_ctl->dev, reset_ctl->id, 56 priv->base + (bank * 4)); 57 58 rk_setreg(priv->base + (bank * 4), BIT(offset)); 59 60 return 0; 61 } 62 63 static int rockchip_reset_deassert(struct reset_ctl *reset_ctl) 64 { 65 struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev); 66 int bank = reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG; 67 int offset = reset_ctl->id % ROCKCHIP_RESET_NUM_IN_REG; 68 69 debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__, 70 reset_ctl, reset_ctl->dev, reset_ctl->id, 71 priv->base + (bank * 4)); 72 73 rk_clrreg(priv->base + (bank * 4), BIT(offset)); 74 75 return 0; 76 } 77 78 struct reset_ops rockchip_reset_ops = { 79 .request = rockchip_reset_request, 80 .free = rockchip_reset_free, 81 .rst_assert = rockchip_reset_assert, 82 .rst_deassert = rockchip_reset_deassert, 83 }; 84 85 static int rockchip_reset_probe(struct udevice *dev) 86 { 87 struct rockchip_reset_priv *priv = dev_get_priv(dev); 88 fdt_addr_t addr; 89 fdt_size_t size; 90 91 addr = dev_read_addr_size(dev, "reg", &size); 92 if (addr == FDT_ADDR_T_NONE) 93 return -EINVAL; 94 95 if ((priv->reset_reg_offset == 0) && (priv->reset_reg_num == 0)) 96 return -EINVAL; 97 98 addr += priv->reset_reg_offset; 99 priv->base = ioremap(addr, size); 100 101 debug("%s(base=%p) (reg_offset=%x, reg_num=%d)\n", __func__, 102 priv->base, priv->reset_reg_offset, priv->reset_reg_num); 103 104 return 0; 105 } 106 107 int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number) 108 { 109 struct udevice *rst_dev; 110 struct rockchip_reset_priv *priv; 111 int ret; 112 113 ret = device_bind_driver_to_node(pdev, "rockchip_reset", "reset", 114 dev_ofnode(pdev), &rst_dev); 115 if (ret) { 116 debug("Warning: No rockchip reset driver: ret=%d\n", ret); 117 return ret; 118 } 119 priv = malloc(sizeof(struct rockchip_reset_priv)); 120 priv->reset_reg_offset = reg_offset; 121 priv->reset_reg_num = reg_number; 122 rst_dev->priv = priv; 123 124 return 0; 125 } 126 127 U_BOOT_DRIVER(rockchip_reset) = { 128 .name = "rockchip_reset", 129 .id = UCLASS_RESET, 130 .probe = rockchip_reset_probe, 131 .ops = &rockchip_reset_ops, 132 .priv_auto_alloc_size = sizeof(struct rockchip_reset_priv), 133 }; 134