1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (c) 2014 MediaTek Inc. |
4 | * Author: James Liao <jamesjj.liao@mediatek.com> |
5 | */ |
6 | |
7 | #ifndef __DRV_CLK_MTK_PLL_H |
8 | #define __DRV_CLK_MTK_PLL_H |
9 | |
10 | #include <linux/clk-provider.h> |
11 | #include <linux/types.h> |
12 | |
13 | struct clk_ops; |
14 | struct clk_hw_onecell_data; |
15 | struct device_node; |
16 | |
17 | struct mtk_pll_div_table { |
18 | u32 div; |
19 | unsigned long freq; |
20 | }; |
21 | |
22 | #define HAVE_RST_BAR BIT(0) |
23 | #define PLL_AO BIT(1) |
24 | #define POSTDIV_MASK GENMASK(2, 0) |
25 | |
26 | struct mtk_pll_data { |
27 | int id; |
28 | const char *name; |
29 | u32 reg; |
30 | u32 pwr_reg; |
31 | u32 en_mask; |
32 | u32 pd_reg; |
33 | u32 tuner_reg; |
34 | u32 tuner_en_reg; |
35 | u8 tuner_en_bit; |
36 | int pd_shift; |
37 | unsigned int flags; |
38 | const struct clk_ops *ops; |
39 | u32 rst_bar_mask; |
40 | unsigned long fmin; |
41 | unsigned long fmax; |
42 | int pcwbits; |
43 | int pcwibits; |
44 | u32 pcw_reg; |
45 | int pcw_shift; |
46 | u32 pcw_chg_reg; |
47 | const struct mtk_pll_div_table *div_table; |
48 | const char *parent_name; |
49 | u32 en_reg; |
50 | u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ |
51 | u8 pcw_chg_bit; |
52 | }; |
53 | |
54 | /* |
55 | * MediaTek PLLs are configured through their pcw value. The pcw value describes |
56 | * a divider in the PLL feedback loop which consists of 7 bits for the integer |
57 | * part and the remaining bits (if present) for the fractional part. Also they |
58 | * have a 3 bit power-of-two post divider. |
59 | */ |
60 | |
61 | struct mtk_clk_pll { |
62 | struct clk_hw hw; |
63 | void __iomem *base_addr; |
64 | void __iomem *pd_addr; |
65 | void __iomem *pwr_addr; |
66 | void __iomem *tuner_addr; |
67 | void __iomem *tuner_en_addr; |
68 | void __iomem *pcw_addr; |
69 | void __iomem *pcw_chg_addr; |
70 | void __iomem *en_addr; |
71 | const struct mtk_pll_data *data; |
72 | }; |
73 | |
74 | int mtk_clk_register_plls(struct device_node *node, |
75 | const struct mtk_pll_data *plls, int num_plls, |
76 | struct clk_hw_onecell_data *clk_data); |
77 | void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, |
78 | struct clk_hw_onecell_data *clk_data); |
79 | |
80 | extern const struct clk_ops mtk_pll_ops; |
81 | |
82 | static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) |
83 | { |
84 | return container_of(hw, struct mtk_clk_pll, hw); |
85 | } |
86 | |
87 | int mtk_pll_is_prepared(struct clk_hw *hw); |
88 | |
89 | int mtk_pll_prepare(struct clk_hw *hw); |
90 | |
91 | void mtk_pll_unprepare(struct clk_hw *hw); |
92 | |
93 | unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate); |
94 | |
95 | void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv, |
96 | u32 freq, u32 fin); |
97 | int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate, |
98 | unsigned long parent_rate); |
99 | long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate, |
100 | unsigned long *prate); |
101 | |
102 | struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, |
103 | const struct mtk_pll_data *data, |
104 | void __iomem *base, |
105 | const struct clk_ops *pll_ops); |
106 | struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, |
107 | void __iomem *base); |
108 | void mtk_clk_unregister_pll(struct clk_hw *hw); |
109 | |
110 | __iomem void *mtk_clk_pll_get_base(struct clk_hw *hw, |
111 | const struct mtk_pll_data *data); |
112 | |
113 | #endif /* __DRV_CLK_MTK_PLL_H */ |
114 | |