1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Zynq PLL driver |
4 | * |
5 | * Copyright (C) 2013 Xilinx |
6 | * |
7 | * Sören Brinkmann <soren.brinkmann@xilinx.com> |
8 | */ |
9 | #include <linux/clk/zynq.h> |
10 | #include <linux/clk-provider.h> |
11 | #include <linux/slab.h> |
12 | #include <linux/io.h> |
13 | |
14 | /** |
15 | * struct zynq_pll - pll clock |
16 | * @hw: Handle between common and hardware-specific interfaces |
17 | * @pll_ctrl: PLL control register |
18 | * @pll_status: PLL status register |
19 | * @lock: Register lock |
20 | * @lockbit: Indicates the associated PLL_LOCKED bit in the PLL status |
21 | * register. |
22 | */ |
23 | struct zynq_pll { |
24 | struct clk_hw hw; |
25 | void __iomem *pll_ctrl; |
26 | void __iomem *pll_status; |
27 | spinlock_t *lock; |
28 | u8 lockbit; |
29 | }; |
30 | #define to_zynq_pll(_hw) container_of(_hw, struct zynq_pll, hw) |
31 | |
32 | /* Register bitfield defines */ |
33 | #define PLLCTRL_FBDIV_MASK 0x7f000 |
34 | #define PLLCTRL_FBDIV_SHIFT 12 |
35 | #define PLLCTRL_BPQUAL_MASK (1 << 3) |
36 | #define PLLCTRL_PWRDWN_MASK 2 |
37 | #define PLLCTRL_PWRDWN_SHIFT 1 |
38 | #define PLLCTRL_RESET_MASK 1 |
39 | #define PLLCTRL_RESET_SHIFT 0 |
40 | |
41 | #define PLL_FBDIV_MIN 13 |
42 | #define PLL_FBDIV_MAX 66 |
43 | |
44 | /** |
45 | * zynq_pll_round_rate() - Round a clock frequency |
46 | * @hw: Handle between common and hardware-specific interfaces |
47 | * @rate: Desired clock frequency |
48 | * @prate: Clock frequency of parent clock |
49 | * Return: frequency closest to @rate the hardware can generate. |
50 | */ |
51 | static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate, |
52 | unsigned long *prate) |
53 | { |
54 | u32 fbdiv; |
55 | |
56 | fbdiv = DIV_ROUND_CLOSEST(rate, *prate); |
57 | if (fbdiv < PLL_FBDIV_MIN) |
58 | fbdiv = PLL_FBDIV_MIN; |
59 | else if (fbdiv > PLL_FBDIV_MAX) |
60 | fbdiv = PLL_FBDIV_MAX; |
61 | |
62 | return *prate * fbdiv; |
63 | } |
64 | |
65 | /** |
66 | * zynq_pll_recalc_rate() - Recalculate clock frequency |
67 | * @hw: Handle between common and hardware-specific interfaces |
68 | * @parent_rate: Clock frequency of parent clock |
69 | * Return: current clock frequency. |
70 | */ |
71 | static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw, |
72 | unsigned long parent_rate) |
73 | { |
74 | struct zynq_pll *clk = to_zynq_pll(hw); |
75 | u32 fbdiv; |
76 | |
77 | /* |
78 | * makes probably sense to redundantly save fbdiv in the struct |
79 | * zynq_pll to save the IO access. |
80 | */ |
81 | fbdiv = (readl(addr: clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >> |
82 | PLLCTRL_FBDIV_SHIFT; |
83 | |
84 | return parent_rate * fbdiv; |
85 | } |
86 | |
87 | /** |
88 | * zynq_pll_is_enabled - Check if a clock is enabled |
89 | * @hw: Handle between common and hardware-specific interfaces |
90 | * Return: 1 if the clock is enabled, 0 otherwise. |
91 | * |
92 | * Not sure this is a good idea, but since disabled means bypassed for |
93 | * this clock implementation we say we are always enabled. |
94 | */ |
95 | static int zynq_pll_is_enabled(struct clk_hw *hw) |
96 | { |
97 | unsigned long flags = 0; |
98 | u32 reg; |
99 | struct zynq_pll *clk = to_zynq_pll(hw); |
100 | |
101 | spin_lock_irqsave(clk->lock, flags); |
102 | |
103 | reg = readl(addr: clk->pll_ctrl); |
104 | |
105 | spin_unlock_irqrestore(lock: clk->lock, flags); |
106 | |
107 | return !(reg & (PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK)); |
108 | } |
109 | |
110 | /** |
111 | * zynq_pll_enable - Enable clock |
112 | * @hw: Handle between common and hardware-specific interfaces |
113 | * Return: 0 on success |
114 | */ |
115 | static int zynq_pll_enable(struct clk_hw *hw) |
116 | { |
117 | unsigned long flags = 0; |
118 | u32 reg; |
119 | struct zynq_pll *clk = to_zynq_pll(hw); |
120 | |
121 | if (zynq_pll_is_enabled(hw)) |
122 | return 0; |
123 | |
124 | pr_info("PLL: enable\n" ); |
125 | |
126 | /* Power up PLL and wait for lock */ |
127 | spin_lock_irqsave(clk->lock, flags); |
128 | |
129 | reg = readl(addr: clk->pll_ctrl); |
130 | reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK); |
131 | writel(val: reg, addr: clk->pll_ctrl); |
132 | while (!(readl(addr: clk->pll_status) & (1 << clk->lockbit))) |
133 | ; |
134 | |
135 | spin_unlock_irqrestore(lock: clk->lock, flags); |
136 | |
137 | return 0; |
138 | } |
139 | |
140 | /** |
141 | * zynq_pll_disable - Disable clock |
142 | * @hw: Handle between common and hardware-specific interfaces |
143 | * Returns 0 on success |
144 | */ |
145 | static void zynq_pll_disable(struct clk_hw *hw) |
146 | { |
147 | unsigned long flags = 0; |
148 | u32 reg; |
149 | struct zynq_pll *clk = to_zynq_pll(hw); |
150 | |
151 | if (!zynq_pll_is_enabled(hw)) |
152 | return; |
153 | |
154 | pr_info("PLL: shutdown\n" ); |
155 | |
156 | /* shut down PLL */ |
157 | spin_lock_irqsave(clk->lock, flags); |
158 | |
159 | reg = readl(addr: clk->pll_ctrl); |
160 | reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK; |
161 | writel(val: reg, addr: clk->pll_ctrl); |
162 | |
163 | spin_unlock_irqrestore(lock: clk->lock, flags); |
164 | } |
165 | |
166 | static const struct clk_ops zynq_pll_ops = { |
167 | .enable = zynq_pll_enable, |
168 | .disable = zynq_pll_disable, |
169 | .is_enabled = zynq_pll_is_enabled, |
170 | .round_rate = zynq_pll_round_rate, |
171 | .recalc_rate = zynq_pll_recalc_rate |
172 | }; |
173 | |
174 | /** |
175 | * clk_register_zynq_pll() - Register PLL with the clock framework |
176 | * @name: PLL name |
177 | * @parent: Parent clock name |
178 | * @pll_ctrl: Pointer to PLL control register |
179 | * @pll_status: Pointer to PLL status register |
180 | * @lock_index: Bit index to this PLL's lock status bit in @pll_status |
181 | * @lock: Register lock |
182 | * Return: handle to the registered clock. |
183 | */ |
184 | struct clk *clk_register_zynq_pll(const char *name, const char *parent, |
185 | void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index, |
186 | spinlock_t *lock) |
187 | { |
188 | struct zynq_pll *pll; |
189 | struct clk *clk; |
190 | u32 reg; |
191 | const char *parent_arr[1] = {parent}; |
192 | unsigned long flags = 0; |
193 | struct clk_init_data initd = { |
194 | .name = name, |
195 | .parent_names = parent_arr, |
196 | .ops = &zynq_pll_ops, |
197 | .num_parents = 1, |
198 | .flags = 0 |
199 | }; |
200 | |
201 | pll = kmalloc(size: sizeof(*pll), GFP_KERNEL); |
202 | if (!pll) |
203 | return ERR_PTR(error: -ENOMEM); |
204 | |
205 | /* Populate the struct */ |
206 | pll->hw.init = &initd; |
207 | pll->pll_ctrl = pll_ctrl; |
208 | pll->pll_status = pll_status; |
209 | pll->lockbit = lock_index; |
210 | pll->lock = lock; |
211 | |
212 | spin_lock_irqsave(pll->lock, flags); |
213 | |
214 | reg = readl(addr: pll->pll_ctrl); |
215 | reg &= ~PLLCTRL_BPQUAL_MASK; |
216 | writel(val: reg, addr: pll->pll_ctrl); |
217 | |
218 | spin_unlock_irqrestore(lock: pll->lock, flags); |
219 | |
220 | clk = clk_register(NULL, hw: &pll->hw); |
221 | if (WARN_ON(IS_ERR(clk))) |
222 | goto free_pll; |
223 | |
224 | return clk; |
225 | |
226 | free_pll: |
227 | kfree(objp: pll); |
228 | |
229 | return clk; |
230 | } |
231 | |