reset-mpfs.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * PolarFire SoC (MPFS) Peripheral Clock Reset Controller
  4. *
  5. * Author: Conor Dooley <conor.dooley@microchip.com>
  6. * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
  7. *
  8. */
  9. #include <linux/auxiliary_bus.h>
  10. #include <linux/delay.h>
  11. #include <linux/io.h>
  12. #include <linux/mfd/syscon.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/regmap.h>
  17. #include <linux/reset-controller.h>
  18. #include <linux/slab.h>
  19. #include <dt-bindings/clock/microchip,mpfs-clock.h>
  20. #include <soc/microchip/mpfs.h>
  21. /*
  22. * The ENVM reset is the lowest bit in the register & I am using the CLK_FOO
  23. * defines in the dt to make things easier to configure - so this is accounting
  24. * for the offset of 3 there.
  25. */
  26. #define MPFS_PERIPH_OFFSET CLK_ENVM
  27. #define MPFS_NUM_RESETS 30u
  28. #define MPFS_SLEEP_MIN_US 100
  29. #define MPFS_SLEEP_MAX_US 200
  30. #define REG_SUBBLK_RESET_CR 0x88u
  31. struct mpfs_reset {
  32. struct regmap *regmap;
  33. struct reset_controller_dev rcdev;
  34. };
  35. static inline struct mpfs_reset *to_mpfs_reset(struct reset_controller_dev *rcdev)
  36. {
  37. return container_of(rcdev, struct mpfs_reset, rcdev);
  38. }
  39. /*
  40. * Peripheral clock resets
  41. */
  42. static int mpfs_assert(struct reset_controller_dev *rcdev, unsigned long id)
  43. {
  44. struct mpfs_reset *rst = to_mpfs_reset(rcdev);
  45. return regmap_set_bits(rst->regmap, REG_SUBBLK_RESET_CR, BIT(id));
  46. }
  47. static int mpfs_deassert(struct reset_controller_dev *rcdev, unsigned long id)
  48. {
  49. struct mpfs_reset *rst = to_mpfs_reset(rcdev);
  50. return regmap_clear_bits(rst->regmap, REG_SUBBLK_RESET_CR, BIT(id));
  51. }
  52. static int mpfs_status(struct reset_controller_dev *rcdev, unsigned long id)
  53. {
  54. struct mpfs_reset *rst = to_mpfs_reset(rcdev);
  55. u32 reg;
  56. regmap_read(rst->regmap, REG_SUBBLK_RESET_CR, &reg);
  57. /*
  58. * It is safe to return here as MPFS_NUM_RESETS makes sure the sign bit
  59. * is never hit.
  60. */
  61. return (reg & BIT(id));
  62. }
  63. static int mpfs_reset(struct reset_controller_dev *rcdev, unsigned long id)
  64. {
  65. mpfs_assert(rcdev, id);
  66. usleep_range(MPFS_SLEEP_MIN_US, MPFS_SLEEP_MAX_US);
  67. mpfs_deassert(rcdev, id);
  68. return 0;
  69. }
  70. static const struct reset_control_ops mpfs_reset_ops = {
  71. .reset = mpfs_reset,
  72. .assert = mpfs_assert,
  73. .deassert = mpfs_deassert,
  74. .status = mpfs_status,
  75. };
  76. static int mpfs_reset_xlate(struct reset_controller_dev *rcdev,
  77. const struct of_phandle_args *reset_spec)
  78. {
  79. unsigned int index = reset_spec->args[0];
  80. /*
  81. * CLK_RESERVED does not map to a clock, but it does map to a reset,
  82. * so it has to be accounted for here. It is the reset for the fabric,
  83. * so if this reset gets called - do not reset it.
  84. */
  85. if (index == CLK_RESERVED) {
  86. dev_err(rcdev->dev, "Resetting the fabric is not supported\n");
  87. return -EINVAL;
  88. }
  89. if (index < MPFS_PERIPH_OFFSET || index >= (MPFS_PERIPH_OFFSET + rcdev->nr_resets)) {
  90. dev_err(rcdev->dev, "Invalid reset index %u\n", index);
  91. return -EINVAL;
  92. }
  93. return index - MPFS_PERIPH_OFFSET;
  94. }
  95. static int mpfs_reset_mfd_probe(struct platform_device *pdev)
  96. {
  97. struct reset_controller_dev *rcdev;
  98. struct device *dev = &pdev->dev;
  99. struct mpfs_reset *rst;
  100. rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
  101. if (!rst)
  102. return -ENOMEM;
  103. rcdev = &rst->rcdev;
  104. rcdev->dev = dev;
  105. rcdev->ops = &mpfs_reset_ops;
  106. rcdev->of_node = pdev->dev.parent->of_node;
  107. rcdev->of_reset_n_cells = 1;
  108. rcdev->of_xlate = mpfs_reset_xlate;
  109. rcdev->nr_resets = MPFS_NUM_RESETS;
  110. rst->regmap = device_node_to_regmap(pdev->dev.parent->of_node);
  111. if (IS_ERR(rst->regmap))
  112. return dev_err_probe(dev, PTR_ERR(rst->regmap),
  113. "Failed to find syscon regmap\n");
  114. return devm_reset_controller_register(dev, rcdev);
  115. }
  116. static struct platform_driver mpfs_reset_mfd_driver = {
  117. .probe = mpfs_reset_mfd_probe,
  118. .driver = {
  119. .name = "mpfs-reset",
  120. },
  121. };
  122. module_platform_driver(mpfs_reset_mfd_driver);
  123. static int mpfs_reset_adev_probe(struct auxiliary_device *adev,
  124. const struct auxiliary_device_id *id)
  125. {
  126. struct reset_controller_dev *rcdev;
  127. struct device *dev = &adev->dev;
  128. struct mpfs_reset *rst;
  129. rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
  130. if (!rst)
  131. return -ENOMEM;
  132. rst->regmap = (struct regmap *)adev->dev.platform_data;
  133. rcdev = &rst->rcdev;
  134. rcdev->dev = dev;
  135. rcdev->ops = &mpfs_reset_ops;
  136. rcdev->of_node = dev->parent->of_node;
  137. rcdev->of_reset_n_cells = 1;
  138. rcdev->of_xlate = mpfs_reset_xlate;
  139. rcdev->nr_resets = MPFS_NUM_RESETS;
  140. return devm_reset_controller_register(dev, rcdev);
  141. }
  142. int mpfs_reset_controller_register(struct device *clk_dev, struct regmap *map)
  143. {
  144. struct auxiliary_device *adev;
  145. adev = devm_auxiliary_device_create(clk_dev, "reset-mpfs", (void *)map);
  146. if (!adev)
  147. return -ENODEV;
  148. return 0;
  149. }
  150. EXPORT_SYMBOL_NS_GPL(mpfs_reset_controller_register, "MCHP_CLK_MPFS");
  151. static const struct auxiliary_device_id mpfs_reset_ids[] = {
  152. {
  153. .name = "reset_mpfs.reset-mpfs",
  154. },
  155. { }
  156. };
  157. MODULE_DEVICE_TABLE(auxiliary, mpfs_reset_ids);
  158. static struct auxiliary_driver mpfs_reset_aux_driver = {
  159. .probe = mpfs_reset_adev_probe,
  160. .id_table = mpfs_reset_ids,
  161. };
  162. module_auxiliary_driver(mpfs_reset_aux_driver);
  163. MODULE_DESCRIPTION("Microchip PolarFire SoC Reset Driver");
  164. MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
  165. MODULE_IMPORT_NS("MCHP_CLK_MPFS");