0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <linux/module.h>
0009 #include <linux/of_address.h>
0010 #include <linux/slab.h>
0011
0012 #include "clk-mtk.h"
0013
0014 #define REF2USB_TX_EN BIT(0)
0015 #define REF2USB_TX_LPF_EN BIT(1)
0016 #define REF2USB_TX_OUT_EN BIT(2)
0017 #define REF2USB_EN_MASK (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \
0018 REF2USB_TX_OUT_EN)
0019
0020 struct mtk_ref2usb_tx {
0021 struct clk_hw hw;
0022 void __iomem *base_addr;
0023 };
0024
0025 static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw)
0026 {
0027 return container_of(hw, struct mtk_ref2usb_tx, hw);
0028 }
0029
0030 static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw)
0031 {
0032 struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
0033
0034 return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK;
0035 }
0036
0037 static int mtk_ref2usb_tx_prepare(struct clk_hw *hw)
0038 {
0039 struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
0040 u32 val;
0041
0042 val = readl(tx->base_addr);
0043
0044 val |= REF2USB_TX_EN;
0045 writel(val, tx->base_addr);
0046 udelay(100);
0047
0048 val |= REF2USB_TX_LPF_EN;
0049 writel(val, tx->base_addr);
0050
0051 val |= REF2USB_TX_OUT_EN;
0052 writel(val, tx->base_addr);
0053
0054 return 0;
0055 }
0056
0057 static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw)
0058 {
0059 struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
0060 u32 val;
0061
0062 val = readl(tx->base_addr);
0063 val &= ~REF2USB_EN_MASK;
0064 writel(val, tx->base_addr);
0065 }
0066
0067 static const struct clk_ops mtk_ref2usb_tx_ops = {
0068 .is_prepared = mtk_ref2usb_tx_is_prepared,
0069 .prepare = mtk_ref2usb_tx_prepare,
0070 .unprepare = mtk_ref2usb_tx_unprepare,
0071 };
0072
0073 struct clk_hw * __init mtk_clk_register_ref2usb_tx(const char *name,
0074 const char *parent_name, void __iomem *reg)
0075 {
0076 struct mtk_ref2usb_tx *tx;
0077 struct clk_init_data init = {};
0078 int ret;
0079
0080 tx = kzalloc(sizeof(*tx), GFP_KERNEL);
0081 if (!tx)
0082 return ERR_PTR(-ENOMEM);
0083
0084 tx->base_addr = reg;
0085 tx->hw.init = &init;
0086
0087 init.name = name;
0088 init.ops = &mtk_ref2usb_tx_ops;
0089 init.parent_names = &parent_name;
0090 init.num_parents = 1;
0091
0092 ret = clk_hw_register(NULL, &tx->hw);
0093
0094 if (ret) {
0095 kfree(tx);
0096 return ERR_PTR(ret);
0097 }
0098
0099 return &tx->hw;
0100 }
0101
0102 MODULE_LICENSE("GPL");