reset-berlin.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright (C) 2014 Marvell Technology Group Ltd.
  3. *
  4. * Antoine Tenart <antoine.tenart@free-electrons.com>
  5. * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
  6. *
  7. * This file is licensed under the terms of the GNU General Public
  8. * License version 2. This program is licensed "as is" without any
  9. * warranty of any kind, whether express or implied.
  10. */
  11. #include <linux/delay.h>
  12. #include <linux/io.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/of_address.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/reset-controller.h>
  18. #include <linux/slab.h>
  19. #include <linux/types.h>
  20. #define BERLIN_MAX_RESETS 32
  21. #define to_berlin_reset_priv(p) \
  22. container_of((p), struct berlin_reset_priv, rcdev)
  23. struct berlin_reset_priv {
  24. void __iomem *base;
  25. unsigned int size;
  26. struct reset_controller_dev rcdev;
  27. };
  28. static int berlin_reset_reset(struct reset_controller_dev *rcdev,
  29. unsigned long id)
  30. {
  31. struct berlin_reset_priv *priv = to_berlin_reset_priv(rcdev);
  32. int offset = id >> 8;
  33. int mask = BIT(id & 0x1f);
  34. writel(mask, priv->base + offset);
  35. /* let the reset be effective */
  36. udelay(10);
  37. return 0;
  38. }
  39. static struct reset_control_ops berlin_reset_ops = {
  40. .reset = berlin_reset_reset,
  41. };
  42. static int berlin_reset_xlate(struct reset_controller_dev *rcdev,
  43. const struct of_phandle_args *reset_spec)
  44. {
  45. struct berlin_reset_priv *priv = to_berlin_reset_priv(rcdev);
  46. unsigned offset, bit;
  47. if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
  48. return -EINVAL;
  49. offset = reset_spec->args[0];
  50. bit = reset_spec->args[1];
  51. if (offset >= priv->size)
  52. return -EINVAL;
  53. if (bit >= BERLIN_MAX_RESETS)
  54. return -EINVAL;
  55. return (offset << 8) | bit;
  56. }
  57. static int __berlin_reset_init(struct device_node *np)
  58. {
  59. struct berlin_reset_priv *priv;
  60. struct resource res;
  61. resource_size_t size;
  62. int ret;
  63. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  64. if (!priv)
  65. return -ENOMEM;
  66. ret = of_address_to_resource(np, 0, &res);
  67. if (ret)
  68. goto err;
  69. size = resource_size(&res);
  70. priv->base = ioremap(res.start, size);
  71. if (!priv->base) {
  72. ret = -ENOMEM;
  73. goto err;
  74. }
  75. priv->size = size;
  76. priv->rcdev.owner = THIS_MODULE;
  77. priv->rcdev.ops = &berlin_reset_ops;
  78. priv->rcdev.of_node = np;
  79. priv->rcdev.of_reset_n_cells = 2;
  80. priv->rcdev.of_xlate = berlin_reset_xlate;
  81. reset_controller_register(&priv->rcdev);
  82. return 0;
  83. err:
  84. kfree(priv);
  85. return ret;
  86. }
  87. static const struct of_device_id berlin_reset_of_match[] __initconst = {
  88. { .compatible = "marvell,berlin2-chip-ctrl" },
  89. { .compatible = "marvell,berlin2cd-chip-ctrl" },
  90. { .compatible = "marvell,berlin2q-chip-ctrl" },
  91. { },
  92. };
  93. static int __init berlin_reset_init(void)
  94. {
  95. struct device_node *np;
  96. int ret;
  97. for_each_matching_node(np, berlin_reset_of_match) {
  98. ret = __berlin_reset_init(np);
  99. if (ret)
  100. return ret;
  101. }
  102. return 0;
  103. }
  104. arch_initcall(berlin_reset_init);