common.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Spreadtrum clock infrastructure
  4. //
  5. // Copyright (C) 2017 Spreadtrum, Inc.
  6. // Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
  7. #include <linux/mfd/syscon.h>
  8. #include <linux/module.h>
  9. #include <linux/of_address.h>
  10. #include <linux/of_platform.h>
  11. #include <linux/regmap.h>
  12. #include "common.h"
  13. static const struct regmap_config sprdclk_regmap_config = {
  14. .reg_bits = 32,
  15. .reg_stride = 4,
  16. .val_bits = 32,
  17. .max_register = 0xffff,
  18. .fast_io = true,
  19. };
  20. static void sprd_clk_set_regmap(const struct sprd_clk_desc *desc,
  21. struct regmap *regmap)
  22. {
  23. int i;
  24. struct sprd_clk_common *cclk;
  25. for (i = 0; i < desc->num_clk_clks; i++) {
  26. cclk = desc->clk_clks[i];
  27. if (!cclk)
  28. continue;
  29. cclk->regmap = regmap;
  30. }
  31. }
  32. int sprd_clk_regmap_init(struct platform_device *pdev,
  33. const struct sprd_clk_desc *desc)
  34. {
  35. void __iomem *base;
  36. struct device_node *node = pdev->dev.of_node;
  37. struct regmap *regmap;
  38. if (of_find_property(node, "sprd,syscon", NULL)) {
  39. regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
  40. if (IS_ERR(regmap)) {
  41. pr_err("%s: failed to get syscon regmap\n", __func__);
  42. return PTR_ERR(regmap);
  43. }
  44. } else {
  45. base = of_iomap(node, 0);
  46. regmap = devm_regmap_init_mmio(&pdev->dev, base,
  47. &sprdclk_regmap_config);
  48. if (IS_ERR_OR_NULL(regmap)) {
  49. pr_err("failed to init regmap\n");
  50. return PTR_ERR(regmap);
  51. }
  52. }
  53. sprd_clk_set_regmap(desc, regmap);
  54. return 0;
  55. }
  56. EXPORT_SYMBOL_GPL(sprd_clk_regmap_init);
  57. int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw)
  58. {
  59. int i, ret;
  60. struct clk_hw *hw;
  61. for (i = 0; i < clkhw->num; i++) {
  62. const char *name;
  63. hw = clkhw->hws[i];
  64. if (!hw)
  65. continue;
  66. name = hw->init->name;
  67. ret = devm_clk_hw_register(dev, hw);
  68. if (ret) {
  69. dev_err(dev, "Couldn't register clock %d - %s\n",
  70. i, name);
  71. return ret;
  72. }
  73. }
  74. ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clkhw);
  75. if (ret)
  76. dev_err(dev, "Failed to add clock provider\n");
  77. return ret;
  78. }
  79. EXPORT_SYMBOL_GPL(sprd_clk_probe);
  80. MODULE_LICENSE("GPL v2");