reset-sifive.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2020 Sifive, Inc.
  4. * Author: Sagar Kadam <sagar.kadam@sifive.com>
  5. */
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <reset-uclass.h>
  9. #include <asm/io.h>
  10. #include <dm/device_compat.h>
  11. #include <dm/device-internal.h>
  12. #include <dm/lists.h>
  13. #include <linux/bitops.h>
  14. #define PRCI_RESETREG_OFFSET 0x28
  15. struct sifive_reset_priv {
  16. void *base;
  17. /* number of reset signals */
  18. int nr_reset;
  19. };
  20. static int sifive_rst_trigger(struct reset_ctl *rst, bool level)
  21. {
  22. struct sifive_reset_priv *priv = dev_get_priv(rst->dev);
  23. int id = rst->id;
  24. int regval = readl(priv->base + PRCI_RESETREG_OFFSET);
  25. /* Derive bitposition from rst id */
  26. if (level)
  27. /* Reset deassert */
  28. regval |= BIT(id);
  29. else
  30. /* Reset assert */
  31. regval &= ~BIT(id);
  32. writel(regval, priv->base + PRCI_RESETREG_OFFSET);
  33. return 0;
  34. }
  35. static int sifive_reset_assert(struct reset_ctl *rst)
  36. {
  37. return sifive_rst_trigger(rst, false);
  38. }
  39. static int sifive_reset_deassert(struct reset_ctl *rst)
  40. {
  41. return sifive_rst_trigger(rst, true);
  42. }
  43. static int sifive_reset_request(struct reset_ctl *rst)
  44. {
  45. struct sifive_reset_priv *priv = dev_get_priv(rst->dev);
  46. debug("%s(rst=%p) (dev=%p, id=%lu) (nr_reset=%d)\n", __func__,
  47. rst, rst->dev, rst->id, priv->nr_reset);
  48. if (rst->id > priv->nr_reset)
  49. return -EINVAL;
  50. return 0;
  51. }
  52. static int sifive_reset_free(struct reset_ctl *rst)
  53. {
  54. struct sifive_reset_priv *priv = dev_get_priv(rst->dev);
  55. debug("%s(rst=%p) (dev=%p, id=%lu) (nr_reset=%d)\n", __func__,
  56. rst, rst->dev, rst->id, priv->nr_reset);
  57. return 0;
  58. }
  59. static int sifive_reset_probe(struct udevice *dev)
  60. {
  61. struct sifive_reset_priv *priv = dev_get_priv(dev);
  62. priv->base = dev_remap_addr(dev);
  63. if (!priv->base)
  64. return -ENOMEM;
  65. return 0;
  66. }
  67. int sifive_reset_bind(struct udevice *dev, ulong count)
  68. {
  69. struct udevice *rst_dev;
  70. struct sifive_reset_priv *priv;
  71. int ret;
  72. ret = device_bind_driver_to_node(dev, "sifive-reset", "reset",
  73. dev_ofnode(dev), &rst_dev);
  74. if (ret) {
  75. dev_err(dev, "failed to bind sifive_reset driver (ret=%d)\n", ret);
  76. return ret;
  77. }
  78. priv = malloc(sizeof(struct sifive_reset_priv));
  79. priv->nr_reset = count;
  80. dev_set_priv(rst_dev, priv);
  81. return 0;
  82. }
  83. const struct reset_ops sifive_reset_ops = {
  84. .request = sifive_reset_request,
  85. .rfree = sifive_reset_free,
  86. .rst_assert = sifive_reset_assert,
  87. .rst_deassert = sifive_reset_deassert,
  88. };
  89. U_BOOT_DRIVER(sifive_reset) = {
  90. .name = "sifive-reset",
  91. .id = UCLASS_RESET,
  92. .ops = &sifive_reset_ops,
  93. .probe = sifive_reset_probe,
  94. .priv_auto = sizeof(struct sifive_reset_priv),
  95. };