mpfs_clk.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2020 Microchip Technology Inc.
  4. * Padmarao Begari <padmarao.begari@microchip.com>
  5. */
  6. #include <common.h>
  7. #include <clk.h>
  8. #include <clk-uclass.h>
  9. #include <dm.h>
  10. #include <log.h>
  11. #include <dm/device.h>
  12. #include <dm/devres.h>
  13. #include <dm/uclass.h>
  14. #include <linux/err.h>
  15. #include "mpfs_clk.h"
  16. /* All methods are delegated to CCF clocks */
  17. static ulong mpfs_clk_get_rate(struct clk *clk)
  18. {
  19. struct clk *c;
  20. int err = clk_get_by_id(clk->id, &c);
  21. if (err)
  22. return err;
  23. return clk_get_rate(c);
  24. }
  25. static ulong mpfs_clk_set_rate(struct clk *clk, unsigned long rate)
  26. {
  27. struct clk *c;
  28. int err = clk_get_by_id(clk->id, &c);
  29. if (err)
  30. return err;
  31. return clk_set_rate(c, rate);
  32. }
  33. static int mpfs_clk_set_parent(struct clk *clk, struct clk *parent)
  34. {
  35. struct clk *c, *p;
  36. int err = clk_get_by_id(clk->id, &c);
  37. if (err)
  38. return err;
  39. err = clk_get_by_id(parent->id, &p);
  40. if (err)
  41. return err;
  42. return clk_set_parent(c, p);
  43. }
  44. static int mpfs_clk_endisable(struct clk *clk, bool enable)
  45. {
  46. struct clk *c;
  47. int err = clk_get_by_id(clk->id, &c);
  48. if (err)
  49. return err;
  50. return enable ? clk_enable(c) : clk_disable(c);
  51. }
  52. static int mpfs_clk_enable(struct clk *clk)
  53. {
  54. return mpfs_clk_endisable(clk, true);
  55. }
  56. static int mpfs_clk_disable(struct clk *clk)
  57. {
  58. return mpfs_clk_endisable(clk, false);
  59. }
  60. static int mpfs_clk_probe(struct udevice *dev)
  61. {
  62. int ret;
  63. void __iomem *base;
  64. u32 clk_rate;
  65. const char *parent_clk_name;
  66. struct clk *clk = dev_get_priv(dev);
  67. base = dev_read_addr_ptr(dev);
  68. if (!base)
  69. return -EINVAL;
  70. ret = clk_get_by_index(dev, 0, clk);
  71. if (ret)
  72. return ret;
  73. dev_read_u32(clk->dev, "clock-frequency", &clk_rate);
  74. parent_clk_name = clk->dev->name;
  75. ret = mpfs_clk_register_cfgs(base, clk_rate, parent_clk_name);
  76. if (ret)
  77. return ret;
  78. ret = mpfs_clk_register_periphs(base, clk_rate, "clk_ahb");
  79. return ret;
  80. }
  81. static const struct clk_ops mpfs_clk_ops = {
  82. .set_rate = mpfs_clk_set_rate,
  83. .get_rate = mpfs_clk_get_rate,
  84. .set_parent = mpfs_clk_set_parent,
  85. .enable = mpfs_clk_enable,
  86. .disable = mpfs_clk_disable,
  87. };
  88. static const struct udevice_id mpfs_of_match[] = {
  89. { .compatible = "microchip,mpfs-clkcfg" },
  90. { }
  91. };
  92. U_BOOT_DRIVER(mpfs_clk) = {
  93. .name = "mpfs_clk",
  94. .id = UCLASS_CLK,
  95. .of_match = mpfs_of_match,
  96. .ops = &mpfs_clk_ops,
  97. .probe = mpfs_clk_probe,
  98. .priv_auto = sizeof(struct clk),
  99. .flags = DM_FLAG_PRE_RELOC,
  100. };