reset-gemini.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Cortina Gemini Reset controller driver
  3. * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <linux/err.h>
  10. #include <linux/init.h>
  11. #include <linux/mfd/syscon.h>
  12. #include <linux/regmap.h>
  13. #include <linux/of.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/reset-controller.h>
  16. #include <dt-bindings/reset/cortina,gemini-reset.h>
  17. /**
  18. * struct gemini_reset - gemini reset controller
  19. * @map: regmap to access the containing system controller
  20. * @rcdev: reset controller device
  21. */
  22. struct gemini_reset {
  23. struct regmap *map;
  24. struct reset_controller_dev rcdev;
  25. };
  26. #define GEMINI_GLOBAL_SOFT_RESET 0x0c
  27. #define to_gemini_reset(p) \
  28. container_of((p), struct gemini_reset, rcdev)
  29. /*
  30. * This is a self-deasserting reset controller.
  31. */
  32. static int gemini_reset(struct reset_controller_dev *rcdev,
  33. unsigned long id)
  34. {
  35. struct gemini_reset *gr = to_gemini_reset(rcdev);
  36. /* Manual says to always set BIT 30 (CPU1) to 1 */
  37. return regmap_write(gr->map,
  38. GEMINI_GLOBAL_SOFT_RESET,
  39. BIT(GEMINI_RESET_CPU1) | BIT(id));
  40. }
  41. static int gemini_reset_status(struct reset_controller_dev *rcdev,
  42. unsigned long id)
  43. {
  44. struct gemini_reset *gr = to_gemini_reset(rcdev);
  45. u32 val;
  46. int ret;
  47. ret = regmap_read(gr->map, GEMINI_GLOBAL_SOFT_RESET, &val);
  48. if (ret)
  49. return ret;
  50. return !!(val & BIT(id));
  51. }
  52. static const struct reset_control_ops gemini_reset_ops = {
  53. .reset = gemini_reset,
  54. .status = gemini_reset_status,
  55. };
  56. static int gemini_reset_probe(struct platform_device *pdev)
  57. {
  58. struct gemini_reset *gr;
  59. struct device *dev = &pdev->dev;
  60. struct device_node *np = dev->of_node;
  61. int ret;
  62. gr = devm_kzalloc(dev, sizeof(*gr), GFP_KERNEL);
  63. if (!gr)
  64. return -ENOMEM;
  65. gr->map = syscon_node_to_regmap(np);
  66. if (IS_ERR(gr->map)) {
  67. ret = PTR_ERR(gr->map);
  68. dev_err(dev, "unable to get regmap (%d)", ret);
  69. return ret;
  70. }
  71. gr->rcdev.owner = THIS_MODULE;
  72. gr->rcdev.nr_resets = 32;
  73. gr->rcdev.ops = &gemini_reset_ops;
  74. gr->rcdev.of_node = pdev->dev.of_node;
  75. ret = devm_reset_controller_register(&pdev->dev, &gr->rcdev);
  76. if (ret)
  77. return ret;
  78. dev_info(dev, "registered Gemini reset controller\n");
  79. return 0;
  80. }
  81. static const struct of_device_id gemini_reset_dt_ids[] = {
  82. { .compatible = "cortina,gemini-syscon", },
  83. { /* sentinel */ },
  84. };
  85. static struct platform_driver gemini_reset_driver = {
  86. .probe = gemini_reset_probe,
  87. .driver = {
  88. .name = "gemini-reset",
  89. .of_match_table = gemini_reset_dt_ids,
  90. .suppress_bind_attrs = true,
  91. },
  92. };
  93. builtin_platform_driver(gemini_reset_driver);