clk-apmixed.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2015 MediaTek Inc.
  4. * Author: James Liao <[email protected]>
  5. */
  6. #include <linux/delay.h>
  7. #include <linux/module.h>
  8. #include <linux/of_address.h>
  9. #include <linux/slab.h>
  10. #include "clk-mtk.h"
  11. #define REF2USB_TX_EN BIT(0)
  12. #define REF2USB_TX_LPF_EN BIT(1)
  13. #define REF2USB_TX_OUT_EN BIT(2)
  14. #define REF2USB_EN_MASK (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \
  15. REF2USB_TX_OUT_EN)
  16. struct mtk_ref2usb_tx {
  17. struct clk_hw hw;
  18. void __iomem *base_addr;
  19. };
  20. static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw)
  21. {
  22. return container_of(hw, struct mtk_ref2usb_tx, hw);
  23. }
  24. static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw)
  25. {
  26. struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
  27. return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK;
  28. }
  29. static int mtk_ref2usb_tx_prepare(struct clk_hw *hw)
  30. {
  31. struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
  32. u32 val;
  33. val = readl(tx->base_addr);
  34. val |= REF2USB_TX_EN;
  35. writel(val, tx->base_addr);
  36. udelay(100);
  37. val |= REF2USB_TX_LPF_EN;
  38. writel(val, tx->base_addr);
  39. val |= REF2USB_TX_OUT_EN;
  40. writel(val, tx->base_addr);
  41. return 0;
  42. }
  43. static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw)
  44. {
  45. struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
  46. u32 val;
  47. val = readl(tx->base_addr);
  48. val &= ~REF2USB_EN_MASK;
  49. writel(val, tx->base_addr);
  50. }
  51. static const struct clk_ops mtk_ref2usb_tx_ops = {
  52. .is_prepared = mtk_ref2usb_tx_is_prepared,
  53. .prepare = mtk_ref2usb_tx_prepare,
  54. .unprepare = mtk_ref2usb_tx_unprepare,
  55. };
  56. struct clk_hw *mtk_clk_register_ref2usb_tx(const char *name,
  57. const char *parent_name, void __iomem *reg)
  58. {
  59. struct mtk_ref2usb_tx *tx;
  60. struct clk_init_data init = {};
  61. int ret;
  62. tx = kzalloc(sizeof(*tx), GFP_KERNEL);
  63. if (!tx)
  64. return ERR_PTR(-ENOMEM);
  65. tx->base_addr = reg;
  66. tx->hw.init = &init;
  67. init.name = name;
  68. init.ops = &mtk_ref2usb_tx_ops;
  69. init.parent_names = &parent_name;
  70. init.num_parents = 1;
  71. ret = clk_hw_register(NULL, &tx->hw);
  72. if (ret) {
  73. kfree(tx);
  74. return ERR_PTR(ret);
  75. }
  76. return &tx->hw;
  77. }
  78. EXPORT_SYMBOL_GPL(mtk_clk_register_ref2usb_tx);
  79. void mtk_clk_unregister_ref2usb_tx(struct clk_hw *hw)
  80. {
  81. struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
  82. clk_hw_unregister(hw);
  83. kfree(tx);
  84. }
  85. EXPORT_SYMBOL_GPL(mtk_clk_unregister_ref2usb_tx);
  86. MODULE_LICENSE("GPL");