reset-rockchip.c 3.5 KB

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