reset-rockchip.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * (C) Copyright 2017 Rockchip Electronics Co., Ltd
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <reset-uclass.h>
  8. #include <linux/io.h>
  9. #include <asm/arch/hardware.h>
  10. #include <dm/lists.h>
  11. /*
  12. * Each reg has 16 bits reset signal for devices
  13. * Note: Not including rk2818 and older SoCs
  14. */
  15. #define ROCKCHIP_RESET_NUM_IN_REG 16
  16. struct rockchip_reset_priv {
  17. void __iomem *base;
  18. /* Rockchip reset reg locate at cru controller */
  19. u32 reset_reg_offset;
  20. /* Rockchip reset reg number */
  21. u32 reset_reg_num;
  22. };
  23. static int rockchip_reset_request(struct reset_ctl *reset_ctl)
  24. {
  25. struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev);
  26. debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_num=%d)\n", __func__,
  27. reset_ctl, reset_ctl->dev, reset_ctl->id, priv->reset_reg_num);
  28. if (reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG >= priv->reset_reg_num)
  29. return -EINVAL;
  30. return 0;
  31. }
  32. static int rockchip_reset_free(struct reset_ctl *reset_ctl)
  33. {
  34. debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
  35. reset_ctl->dev, reset_ctl->id);
  36. return 0;
  37. }
  38. static int rockchip_reset_assert(struct reset_ctl *reset_ctl)
  39. {
  40. struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev);
  41. int bank = reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG;
  42. int offset = reset_ctl->id % ROCKCHIP_RESET_NUM_IN_REG;
  43. debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__,
  44. reset_ctl, reset_ctl->dev, reset_ctl->id,
  45. priv->base + (bank * 4));
  46. rk_setreg(priv->base + (bank * 4), BIT(offset));
  47. return 0;
  48. }
  49. static int rockchip_reset_deassert(struct reset_ctl *reset_ctl)
  50. {
  51. struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev);
  52. int bank = reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG;
  53. int offset = reset_ctl->id % ROCKCHIP_RESET_NUM_IN_REG;
  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. rk_clrreg(priv->base + (bank * 4), BIT(offset));
  58. return 0;
  59. }
  60. struct reset_ops rockchip_reset_ops = {
  61. .request = rockchip_reset_request,
  62. .free = rockchip_reset_free,
  63. .rst_assert = rockchip_reset_assert,
  64. .rst_deassert = rockchip_reset_deassert,
  65. };
  66. static int rockchip_reset_probe(struct udevice *dev)
  67. {
  68. struct rockchip_reset_priv *priv = dev_get_priv(dev);
  69. fdt_addr_t addr;
  70. fdt_size_t size;
  71. addr = dev_read_addr_size(dev, "reg", &size);
  72. if (addr == FDT_ADDR_T_NONE)
  73. return -EINVAL;
  74. if ((priv->reset_reg_offset == 0) && (priv->reset_reg_num == 0))
  75. return -EINVAL;
  76. addr += priv->reset_reg_offset;
  77. priv->base = ioremap(addr, size);
  78. debug("%s(base=%p) (reg_offset=%x, reg_num=%d)\n", __func__,
  79. priv->base, priv->reset_reg_offset, priv->reset_reg_num);
  80. return 0;
  81. }
  82. int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number)
  83. {
  84. struct udevice *rst_dev;
  85. struct rockchip_reset_priv *priv;
  86. int ret;
  87. ret = device_bind_driver_to_node(pdev, "rockchip_reset", "reset",
  88. dev_ofnode(pdev), &rst_dev);
  89. if (ret) {
  90. debug("Warning: No rockchip reset driver: ret=%d\n", ret);
  91. return ret;
  92. }
  93. priv = malloc(sizeof(struct rockchip_reset_priv));
  94. priv->reset_reg_offset = reg_offset;
  95. priv->reset_reg_num = reg_number;
  96. rst_dev->priv = priv;
  97. return 0;
  98. }
  99. U_BOOT_DRIVER(rockchip_reset) = {
  100. .name = "rockchip_reset",
  101. .id = UCLASS_RESET,
  102. .probe = rockchip_reset_probe,
  103. .ops = &rockchip_reset_ops,
  104. .priv_auto_alloc_size = sizeof(struct rockchip_reset_priv),
  105. };