reset-lantiq.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. *
  4. * Copyright (C) 2010 John Crispin <blogic@phrozen.org>
  5. * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  6. * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
  7. * Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de>
  8. */
  9. #include <linux/mfd/syscon.h>
  10. #include <linux/module.h>
  11. #include <linux/regmap.h>
  12. #include <linux/reset-controller.h>
  13. #include <linux/of_address.h>
  14. #include <linux/of_platform.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/property.h>
  17. #define LANTIQ_RCU_RESET_TIMEOUT 10000
  18. struct lantiq_rcu_reset_priv {
  19. struct reset_controller_dev rcdev;
  20. struct device *dev;
  21. struct regmap *regmap;
  22. u32 reset_offset;
  23. u32 status_offset;
  24. };
  25. static struct lantiq_rcu_reset_priv *to_lantiq_rcu_reset_priv(
  26. struct reset_controller_dev *rcdev)
  27. {
  28. return container_of(rcdev, struct lantiq_rcu_reset_priv, rcdev);
  29. }
  30. static int lantiq_rcu_reset_status(struct reset_controller_dev *rcdev,
  31. unsigned long id)
  32. {
  33. struct lantiq_rcu_reset_priv *priv = to_lantiq_rcu_reset_priv(rcdev);
  34. unsigned int status = (id >> 8) & 0x1f;
  35. u32 val;
  36. int ret;
  37. ret = regmap_read(priv->regmap, priv->status_offset, &val);
  38. if (ret)
  39. return ret;
  40. return !!(val & BIT(status));
  41. }
  42. static int lantiq_rcu_reset_status_timeout(struct reset_controller_dev *rcdev,
  43. unsigned long id, bool assert)
  44. {
  45. int ret;
  46. int retry = LANTIQ_RCU_RESET_TIMEOUT;
  47. do {
  48. ret = lantiq_rcu_reset_status(rcdev, id);
  49. if (ret < 0)
  50. return ret;
  51. if (ret == assert)
  52. return 0;
  53. usleep_range(20, 40);
  54. } while (--retry);
  55. return -ETIMEDOUT;
  56. }
  57. static int lantiq_rcu_reset_update(struct reset_controller_dev *rcdev,
  58. unsigned long id, bool assert)
  59. {
  60. struct lantiq_rcu_reset_priv *priv = to_lantiq_rcu_reset_priv(rcdev);
  61. unsigned int set = id & 0x1f;
  62. u32 val = assert ? BIT(set) : 0;
  63. int ret;
  64. ret = regmap_update_bits(priv->regmap, priv->reset_offset, BIT(set),
  65. val);
  66. if (ret) {
  67. dev_err(priv->dev, "Failed to set reset bit %u\n", set);
  68. return ret;
  69. }
  70. ret = lantiq_rcu_reset_status_timeout(rcdev, id, assert);
  71. if (ret)
  72. dev_err(priv->dev, "Failed to %s bit %u\n",
  73. assert ? "assert" : "deassert", set);
  74. return ret;
  75. }
  76. static int lantiq_rcu_reset_assert(struct reset_controller_dev *rcdev,
  77. unsigned long id)
  78. {
  79. return lantiq_rcu_reset_update(rcdev, id, true);
  80. }
  81. static int lantiq_rcu_reset_deassert(struct reset_controller_dev *rcdev,
  82. unsigned long id)
  83. {
  84. return lantiq_rcu_reset_update(rcdev, id, false);
  85. }
  86. static int lantiq_rcu_reset_reset(struct reset_controller_dev *rcdev,
  87. unsigned long id)
  88. {
  89. int ret;
  90. ret = lantiq_rcu_reset_assert(rcdev, id);
  91. if (ret)
  92. return ret;
  93. return lantiq_rcu_reset_deassert(rcdev, id);
  94. }
  95. static const struct reset_control_ops lantiq_rcu_reset_ops = {
  96. .assert = lantiq_rcu_reset_assert,
  97. .deassert = lantiq_rcu_reset_deassert,
  98. .status = lantiq_rcu_reset_status,
  99. .reset = lantiq_rcu_reset_reset,
  100. };
  101. static int lantiq_rcu_reset_of_parse(struct platform_device *pdev,
  102. struct lantiq_rcu_reset_priv *priv)
  103. {
  104. struct device *dev = &pdev->dev;
  105. const __be32 *offset;
  106. priv->regmap = syscon_node_to_regmap(dev->of_node->parent);
  107. if (IS_ERR(priv->regmap)) {
  108. dev_err(&pdev->dev, "Failed to lookup RCU regmap\n");
  109. return PTR_ERR(priv->regmap);
  110. }
  111. offset = of_get_address(dev->of_node, 0, NULL, NULL);
  112. if (!offset) {
  113. dev_err(&pdev->dev, "Failed to get RCU reset offset\n");
  114. return -ENOENT;
  115. }
  116. priv->reset_offset = __be32_to_cpu(*offset);
  117. offset = of_get_address(dev->of_node, 1, NULL, NULL);
  118. if (!offset) {
  119. dev_err(&pdev->dev, "Failed to get RCU status offset\n");
  120. return -ENOENT;
  121. }
  122. priv->status_offset = __be32_to_cpu(*offset);
  123. return 0;
  124. }
  125. static int lantiq_rcu_reset_xlate(struct reset_controller_dev *rcdev,
  126. const struct of_phandle_args *reset_spec)
  127. {
  128. unsigned int status, set;
  129. set = reset_spec->args[0];
  130. status = reset_spec->args[1];
  131. if (set >= rcdev->nr_resets || status >= rcdev->nr_resets)
  132. return -EINVAL;
  133. return (status << 8) | set;
  134. }
  135. static int lantiq_rcu_reset_probe(struct platform_device *pdev)
  136. {
  137. struct lantiq_rcu_reset_priv *priv;
  138. int err;
  139. priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  140. if (!priv)
  141. return -ENOMEM;
  142. priv->dev = &pdev->dev;
  143. platform_set_drvdata(pdev, priv);
  144. err = lantiq_rcu_reset_of_parse(pdev, priv);
  145. if (err)
  146. return err;
  147. priv->rcdev.ops = &lantiq_rcu_reset_ops;
  148. priv->rcdev.owner = THIS_MODULE;
  149. priv->rcdev.of_node = pdev->dev.of_node;
  150. priv->rcdev.nr_resets = 32;
  151. priv->rcdev.of_xlate = lantiq_rcu_reset_xlate;
  152. priv->rcdev.of_reset_n_cells = 2;
  153. return reset_controller_register(&priv->rcdev);
  154. }
  155. static const struct of_device_id lantiq_rcu_reset_dt_ids[] = {
  156. { .compatible = "lantiq,danube-reset", },
  157. { .compatible = "lantiq,xrx200-reset", },
  158. { },
  159. };
  160. MODULE_DEVICE_TABLE(of, lantiq_rcu_reset_dt_ids);
  161. static struct platform_driver lantiq_rcu_reset_driver = {
  162. .probe = lantiq_rcu_reset_probe,
  163. .driver = {
  164. .name = "lantiq-reset",
  165. .of_match_table = lantiq_rcu_reset_dt_ids,
  166. },
  167. };
  168. module_platform_driver(lantiq_rcu_reset_driver);
  169. MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
  170. MODULE_DESCRIPTION("Lantiq XWAY RCU Reset Controller Driver");
  171. MODULE_LICENSE("GPL");