clk-mt8186-mcu.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // Copyright (c) 2022 MediaTek Inc.
  4. // Author: Chun-Jie Chen <[email protected]>
  5. #include <linux/clk-provider.h>
  6. #include <linux/platform_device.h>
  7. #include <dt-bindings/clock/mt8186-clk.h>
  8. #include "clk-mtk.h"
  9. static const char * const mcu_armpll_ll_parents[] = {
  10. "clk26m",
  11. "armpll_ll",
  12. "mainpll",
  13. "univpll_d2"
  14. };
  15. static const char * const mcu_armpll_bl_parents[] = {
  16. "clk26m",
  17. "armpll_bl",
  18. "mainpll",
  19. "univpll_d2"
  20. };
  21. static const char * const mcu_armpll_bus_parents[] = {
  22. "clk26m",
  23. "ccipll",
  24. "mainpll",
  25. "univpll_d2"
  26. };
  27. /*
  28. * We only configure the CPU muxes when adjust CPU frequency in MediaTek CPUFreq Driver.
  29. * Other fields like divider always keep the same value. (set once in bootloader)
  30. */
  31. static struct mtk_composite mcu_muxes[] = {
  32. /* CPU_PLLDIV_CFG0 */
  33. MUX(CLK_MCU_ARMPLL_LL_SEL, "mcu_armpll_ll_sel", mcu_armpll_ll_parents, 0x2A0, 9, 2),
  34. /* CPU_PLLDIV_CFG1 */
  35. MUX(CLK_MCU_ARMPLL_BL_SEL, "mcu_armpll_bl_sel", mcu_armpll_bl_parents, 0x2A4, 9, 2),
  36. /* BUS_PLLDIV_CFG */
  37. MUX(CLK_MCU_ARMPLL_BUS_SEL, "mcu_armpll_bus_sel", mcu_armpll_bus_parents, 0x2E0, 9, 2),
  38. };
  39. static const struct of_device_id of_match_clk_mt8186_mcu[] = {
  40. { .compatible = "mediatek,mt8186-mcusys", },
  41. {}
  42. };
  43. static int clk_mt8186_mcu_probe(struct platform_device *pdev)
  44. {
  45. struct clk_hw_onecell_data *clk_data;
  46. struct device_node *node = pdev->dev.of_node;
  47. int r;
  48. void __iomem *base;
  49. clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK);
  50. if (!clk_data)
  51. return -ENOMEM;
  52. base = devm_platform_ioremap_resource(pdev, 0);
  53. if (IS_ERR(base)) {
  54. r = PTR_ERR(base);
  55. goto free_mcu_data;
  56. }
  57. r = mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base,
  58. NULL, clk_data);
  59. if (r)
  60. goto free_mcu_data;
  61. r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
  62. if (r)
  63. goto unregister_composite_muxes;
  64. platform_set_drvdata(pdev, clk_data);
  65. return r;
  66. unregister_composite_muxes:
  67. mtk_clk_unregister_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), clk_data);
  68. free_mcu_data:
  69. mtk_free_clk_data(clk_data);
  70. return r;
  71. }
  72. static int clk_mt8186_mcu_remove(struct platform_device *pdev)
  73. {
  74. struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
  75. struct device_node *node = pdev->dev.of_node;
  76. of_clk_del_provider(node);
  77. mtk_clk_unregister_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), clk_data);
  78. mtk_free_clk_data(clk_data);
  79. return 0;
  80. }
  81. static struct platform_driver clk_mt8186_mcu_drv = {
  82. .probe = clk_mt8186_mcu_probe,
  83. .remove = clk_mt8186_mcu_remove,
  84. .driver = {
  85. .name = "clk-mt8186-mcu",
  86. .of_match_table = of_match_clk_mt8186_mcu,
  87. },
  88. };
  89. builtin_platform_driver(clk_mt8186_mcu_drv);