xref: /openbmc/u-boot/drivers/clk/clk_meson.c (revision 9c2cb97e22a7a12bf87d0af7e90156afe7a78d21)
1  // SPDX-License-Identifier: GPL-2.0+
2  /*
3   * (C) Copyright 2018 - Beniamino Galvani <b.galvani@gmail.com>
4   * (C) Copyright 2018 - BayLibre, SAS
5   * Author: Neil Armstrong <narmstrong@baylibre.com>
6   */
7  
8  #include <common.h>
9  #include <asm/arch/clock.h>
10  #include <asm/io.h>
11  #include <clk-uclass.h>
12  #include <div64.h>
13  #include <dm.h>
14  #include <dt-bindings/clock/gxbb-clkc.h>
15  #include "clk_meson.h"
16  
17  /* This driver support only basic clock tree operations :
18   * - Can calculate clock frequency on a limited tree
19   * - Can Read muxes and basic dividers (0-based only)
20   * - Can enable/disable gates with limited propagation
21   * - Can reparent without propagation, only on muxes
22   * - Can set rates without reparenting
23   * This driver is adapted to what is actually supported by U-Boot
24   */
25  
26  /* Only the clocks ids we don't want to expose, such as the internal muxes
27   * and dividers of composite clocks, will remain defined here.
28   */
29  #define CLKID_MPEG_SEL		  10
30  #define CLKID_MPEG_DIV		  11
31  #define CLKID_SAR_ADC_DIV	  99
32  #define CLKID_MALI_0_DIV	  101
33  #define CLKID_MALI_1_DIV	  104
34  #define CLKID_CTS_AMCLK_SEL	  108
35  #define CLKID_CTS_AMCLK_DIV	  109
36  #define CLKID_CTS_MCLK_I958_SEL	  111
37  #define CLKID_CTS_MCLK_I958_DIV	  112
38  #define CLKID_32K_CLK_SEL	  115
39  #define CLKID_32K_CLK_DIV	  116
40  #define CLKID_SD_EMMC_A_CLK0_SEL  117
41  #define CLKID_SD_EMMC_A_CLK0_DIV  118
42  #define CLKID_SD_EMMC_B_CLK0_SEL  120
43  #define CLKID_SD_EMMC_B_CLK0_DIV  121
44  #define CLKID_SD_EMMC_C_CLK0_SEL  123
45  #define CLKID_SD_EMMC_C_CLK0_DIV  124
46  #define CLKID_VPU_0_DIV		  127
47  #define CLKID_VPU_1_DIV		  130
48  #define CLKID_VAPB_0_DIV	  134
49  #define CLKID_VAPB_1_DIV	  137
50  #define CLKID_HDMI_PLL_PRE_MULT	  141
51  #define CLKID_MPLL0_DIV		  142
52  #define CLKID_MPLL1_DIV		  143
53  #define CLKID_MPLL2_DIV		  144
54  #define CLKID_MPLL_PREDIV	  145
55  #define CLKID_FCLK_DIV2_DIV	  146
56  #define CLKID_FCLK_DIV3_DIV	  147
57  #define CLKID_FCLK_DIV4_DIV	  148
58  #define CLKID_FCLK_DIV5_DIV	  149
59  #define CLKID_FCLK_DIV7_DIV	  150
60  #define CLKID_VDEC_1_SEL	  151
61  #define CLKID_VDEC_1_DIV	  152
62  #define CLKID_VDEC_HEVC_SEL	  154
63  #define CLKID_VDEC_HEVC_DIV	  155
64  
65  #define XTAL_RATE 24000000
66  
67  struct meson_clk {
68  	void __iomem *addr;
69  };
70  
71  static ulong meson_div_get_rate(struct clk *clk, unsigned long id);
72  static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
73  				ulong current_rate);
74  static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
75  				  unsigned long parent_id);
76  static ulong meson_mux_get_rate(struct clk *clk, unsigned long id);
77  static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
78  				      ulong rate, ulong current_rate);
79  static ulong meson_mux_get_parent(struct clk *clk, unsigned long id);
80  static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id);
81  
82  struct meson_gate gates[] = {
83  	/* Everything Else (EE) domain gates */
84  	MESON_GATE(CLKID_DDR, HHI_GCLK_MPEG0, 0),
85  	MESON_GATE(CLKID_DOS, HHI_GCLK_MPEG0, 1),
86  	MESON_GATE(CLKID_ISA, HHI_GCLK_MPEG0, 5),
87  	MESON_GATE(CLKID_PL301, HHI_GCLK_MPEG0, 6),
88  	MESON_GATE(CLKID_PERIPHS, HHI_GCLK_MPEG0, 7),
89  	MESON_GATE(CLKID_SPICC, HHI_GCLK_MPEG0, 8),
90  	MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9),
91  	MESON_GATE(CLKID_SAR_ADC, HHI_GCLK_MPEG0, 10),
92  	MESON_GATE(CLKID_SMART_CARD, HHI_GCLK_MPEG0, 11),
93  	MESON_GATE(CLKID_RNG0, HHI_GCLK_MPEG0, 12),
94  	MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13),
95  	MESON_GATE(CLKID_SDHC, HHI_GCLK_MPEG0, 14),
96  	MESON_GATE(CLKID_STREAM, HHI_GCLK_MPEG0, 15),
97  	MESON_GATE(CLKID_ASYNC_FIFO, HHI_GCLK_MPEG0, 16),
98  	MESON_GATE(CLKID_SDIO, HHI_GCLK_MPEG0, 17),
99  	MESON_GATE(CLKID_ABUF, HHI_GCLK_MPEG0, 18),
100  	MESON_GATE(CLKID_HIU_IFACE, HHI_GCLK_MPEG0, 19),
101  	MESON_GATE(CLKID_ASSIST_MISC, HHI_GCLK_MPEG0, 23),
102  	MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 24),
103  	MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25),
104  	MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26),
105  	MESON_GATE(CLKID_SPI, HHI_GCLK_MPEG0, 30),
106  
107  	MESON_GATE(CLKID_I2S_SPDIF, HHI_GCLK_MPEG1, 2),
108  	MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3),
109  	MESON_GATE(CLKID_DEMUX, HHI_GCLK_MPEG1, 4),
110  	MESON_GATE(CLKID_AIU_GLUE, HHI_GCLK_MPEG1, 6),
111  	MESON_GATE(CLKID_IEC958, HHI_GCLK_MPEG1, 7),
112  	MESON_GATE(CLKID_I2S_OUT, HHI_GCLK_MPEG1, 8),
113  	MESON_GATE(CLKID_AMCLK, HHI_GCLK_MPEG1, 9),
114  	MESON_GATE(CLKID_AIFIFO2, HHI_GCLK_MPEG1, 10),
115  	MESON_GATE(CLKID_MIXER, HHI_GCLK_MPEG1, 11),
116  	MESON_GATE(CLKID_MIXER_IFACE, HHI_GCLK_MPEG1, 12),
117  	MESON_GATE(CLKID_ADC, HHI_GCLK_MPEG1, 13),
118  	MESON_GATE(CLKID_BLKMV, HHI_GCLK_MPEG1, 14),
119  	MESON_GATE(CLKID_AIU, HHI_GCLK_MPEG1, 15),
120  	MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16),
121  	MESON_GATE(CLKID_G2D, HHI_GCLK_MPEG1, 20),
122  	MESON_GATE(CLKID_USB0, HHI_GCLK_MPEG1, 21),
123  	MESON_GATE(CLKID_USB1, HHI_GCLK_MPEG1, 22),
124  	MESON_GATE(CLKID_RESET, HHI_GCLK_MPEG1, 23),
125  	MESON_GATE(CLKID_NAND, HHI_GCLK_MPEG1, 24),
126  	MESON_GATE(CLKID_DOS_PARSER, HHI_GCLK_MPEG1, 25),
127  	MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 26),
128  	MESON_GATE(CLKID_VDIN1, HHI_GCLK_MPEG1, 28),
129  	MESON_GATE(CLKID_AHB_ARB0, HHI_GCLK_MPEG1, 29),
130  	MESON_GATE(CLKID_EFUSE, HHI_GCLK_MPEG1, 30),
131  	MESON_GATE(CLKID_BOOT_ROM, HHI_GCLK_MPEG1, 31),
132  
133  	MESON_GATE(CLKID_AHB_DATA_BUS, HHI_GCLK_MPEG2, 1),
134  	MESON_GATE(CLKID_AHB_CTRL_BUS, HHI_GCLK_MPEG2, 2),
135  	MESON_GATE(CLKID_HDMI_INTR_SYNC, HHI_GCLK_MPEG2, 3),
136  	MESON_GATE(CLKID_HDMI_PCLK, HHI_GCLK_MPEG2, 4),
137  	MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8),
138  	MESON_GATE(CLKID_USB0_DDR_BRIDGE, HHI_GCLK_MPEG2, 9),
139  	MESON_GATE(CLKID_MMC_PCLK, HHI_GCLK_MPEG2, 11),
140  	MESON_GATE(CLKID_DVIN, HHI_GCLK_MPEG2, 12),
141  	MESON_GATE(CLKID_UART2, HHI_GCLK_MPEG2, 15),
142  	MESON_GATE(CLKID_SANA, HHI_GCLK_MPEG2, 22),
143  	MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25),
144  	MESON_GATE(CLKID_SEC_AHB_AHB3_BRIDGE, HHI_GCLK_MPEG2, 26),
145  	MESON_GATE(CLKID_CLK81_A53, HHI_GCLK_MPEG2, 29),
146  
147  	MESON_GATE(CLKID_VCLK2_VENCI0, HHI_GCLK_OTHER, 1),
148  	MESON_GATE(CLKID_VCLK2_VENCI1, HHI_GCLK_OTHER, 2),
149  	MESON_GATE(CLKID_VCLK2_VENCP0, HHI_GCLK_OTHER, 3),
150  	MESON_GATE(CLKID_VCLK2_VENCP1, HHI_GCLK_OTHER, 4),
151  	MESON_GATE(CLKID_GCLK_VENCI_INT0, HHI_GCLK_OTHER, 8),
152  	MESON_GATE(CLKID_DAC_CLK, HHI_GCLK_OTHER, 10),
153  	MESON_GATE(CLKID_AOCLK_GATE, HHI_GCLK_OTHER, 14),
154  	MESON_GATE(CLKID_IEC958_GATE, HHI_GCLK_OTHER, 16),
155  	MESON_GATE(CLKID_ENC480P, HHI_GCLK_OTHER, 20),
156  	MESON_GATE(CLKID_RNG1, HHI_GCLK_OTHER, 21),
157  	MESON_GATE(CLKID_GCLK_VENCI_INT1, HHI_GCLK_OTHER, 22),
158  	MESON_GATE(CLKID_VCLK2_VENCLMCC, HHI_GCLK_OTHER, 24),
159  	MESON_GATE(CLKID_VCLK2_VENCL, HHI_GCLK_OTHER, 25),
160  	MESON_GATE(CLKID_VCLK_OTHER, HHI_GCLK_OTHER, 26),
161  	MESON_GATE(CLKID_EDP, HHI_GCLK_OTHER, 31),
162  
163  	/* Always On (AO) domain gates */
164  	MESON_GATE(CLKID_AO_MEDIA_CPU, HHI_GCLK_AO, 0),
165  	MESON_GATE(CLKID_AO_AHB_SRAM, HHI_GCLK_AO, 1),
166  	MESON_GATE(CLKID_AO_AHB_BUS, HHI_GCLK_AO, 2),
167  	MESON_GATE(CLKID_AO_IFACE, HHI_GCLK_AO, 3),
168  	MESON_GATE(CLKID_AO_I2C, HHI_GCLK_AO, 4),
169  
170  	/* PLL Gates */
171  	/* CLKID_FCLK_DIV2 is critical for the SCPI Processor */
172  	MESON_GATE(CLKID_FCLK_DIV3, HHI_MPLL_CNTL6, 28),
173  	MESON_GATE(CLKID_FCLK_DIV4, HHI_MPLL_CNTL6, 29),
174  	MESON_GATE(CLKID_FCLK_DIV5, HHI_MPLL_CNTL6, 30),
175  	MESON_GATE(CLKID_FCLK_DIV7, HHI_MPLL_CNTL6, 31),
176  	MESON_GATE(CLKID_MPLL0, HHI_MPLL_CNTL7, 14),
177  	MESON_GATE(CLKID_MPLL1, HHI_MPLL_CNTL8, 14),
178  	MESON_GATE(CLKID_MPLL2, HHI_MPLL_CNTL9, 14),
179  	/* CLKID_CLK81 is critical for the system */
180  
181  	/* Peripheral Gates */
182  	MESON_GATE(CLKID_SAR_ADC_CLK, HHI_SAR_CLK_CNTL, 8),
183  	MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7),
184  	MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23),
185  	MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7),
186  	MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8),
187  	MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24),
188  	MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8),
189  	MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24),
190  	MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30),
191  };
192  
193  static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on)
194  {
195  	struct meson_clk *priv = dev_get_priv(clk->dev);
196  	struct meson_gate *gate;
197  
198  	debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id);
199  
200  	/* Propagate through muxes */
201  	switch (id) {
202  	case CLKID_VPU:
203  		return meson_set_gate_by_id(clk,
204  				meson_mux_get_parent(clk, CLKID_VPU), on);
205  	case CLKID_VAPB_SEL:
206  		return meson_set_gate_by_id(clk,
207  				meson_mux_get_parent(clk, CLKID_VAPB_SEL), on);
208  	}
209  
210  	if (id >= ARRAY_SIZE(gates))
211  		return -ENOENT;
212  
213  	gate = &gates[id];
214  
215  	if (gate->reg == 0)
216  		return 0;
217  
218  	debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id);
219  
220  	clrsetbits_le32(priv->addr + gate->reg,
221  			BIT(gate->bit), on ? BIT(gate->bit) : 0);
222  
223  	/* Propagate to next gate(s) */
224  	switch (id) {
225  	case CLKID_VAPB:
226  		return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on);
227  	}
228  
229  	return 0;
230  }
231  
232  static int meson_clk_enable(struct clk *clk)
233  {
234  	return meson_set_gate_by_id(clk, clk->id, true);
235  }
236  
237  static int meson_clk_disable(struct clk *clk)
238  {
239  	return meson_set_gate_by_id(clk, clk->id, false);
240  }
241  
242  static struct parm meson_vpu_0_div_parm = {
243  	HHI_VPU_CLK_CNTL, 0, 7,
244  };
245  
246  int meson_vpu_0_div_parent = CLKID_VPU_0_SEL;
247  
248  static struct parm meson_vpu_1_div_parm = {
249  	HHI_VPU_CLK_CNTL, 16, 7,
250  };
251  
252  int meson_vpu_1_div_parent = CLKID_VPU_1_SEL;
253  
254  static struct parm meson_vapb_0_div_parm = {
255  	HHI_VAPBCLK_CNTL, 0, 7,
256  };
257  
258  int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL;
259  
260  static struct parm meson_vapb_1_div_parm = {
261  	HHI_VAPBCLK_CNTL, 16, 7,
262  };
263  
264  int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL;
265  
266  static ulong meson_div_get_rate(struct clk *clk, unsigned long id)
267  {
268  	struct meson_clk *priv = dev_get_priv(clk->dev);
269  	unsigned int rate, parent_rate;
270  	struct parm *parm;
271  	int parent;
272  	u32 reg;
273  
274  	switch (id) {
275  	case CLKID_VPU_0_DIV:
276  		parm = &meson_vpu_0_div_parm;
277  		parent = meson_vpu_0_div_parent;
278  		break;
279  	case CLKID_VPU_1_DIV:
280  		parm = &meson_vpu_1_div_parm;
281  		parent = meson_vpu_1_div_parent;
282  		break;
283  	case CLKID_VAPB_0_DIV:
284  		parm = &meson_vapb_0_div_parm;
285  		parent = meson_vapb_0_div_parent;
286  		break;
287  	case CLKID_VAPB_1_DIV:
288  		parm = &meson_vapb_1_div_parm;
289  		parent = meson_vapb_1_div_parent;
290  		break;
291  	default:
292  		return -ENOENT;
293  	}
294  
295  	reg = readl(priv->addr + parm->reg_off);
296  	reg = PARM_GET(parm->width, parm->shift, reg);
297  
298  	debug("%s: div of %ld is %d\n", __func__, id, reg + 1);
299  
300  	parent_rate = meson_clk_get_rate_by_id(clk, parent);
301  	if (IS_ERR_VALUE(parent_rate))
302  		return parent_rate;
303  
304  	debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate);
305  
306  	rate = parent_rate / (reg + 1);
307  
308  	debug("%s: rate of %ld is %d\n", __func__, id, rate);
309  
310  	return rate;
311  }
312  
313  static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
314  				ulong current_rate)
315  {
316  	struct meson_clk *priv = dev_get_priv(clk->dev);
317  	unsigned int new_div = -EINVAL;
318  	unsigned long parent_rate;
319  	struct parm *parm;
320  	int parent;
321  	u32 reg;
322  	int ret;
323  
324  	if (current_rate == rate)
325  		return 0;
326  
327  	debug("%s: setting rate of %ld from %ld to %ld\n",
328  	      __func__, id, current_rate, rate);
329  
330  	switch (id) {
331  	case CLKID_VPU_0_DIV:
332  		parm = &meson_vpu_0_div_parm;
333  		parent = meson_vpu_0_div_parent;
334  		break;
335  	case CLKID_VPU_1_DIV:
336  		parm = &meson_vpu_1_div_parm;
337  		parent = meson_vpu_1_div_parent;
338  		break;
339  	case CLKID_VAPB_0_DIV:
340  		parm = &meson_vapb_0_div_parm;
341  		parent = meson_vapb_0_div_parent;
342  		break;
343  	case CLKID_VAPB_1_DIV:
344  		parm = &meson_vapb_1_div_parm;
345  		parent = meson_vapb_1_div_parent;
346  		break;
347  	default:
348  		return -ENOENT;
349  	}
350  
351  	parent_rate = meson_clk_get_rate_by_id(clk, parent);
352  	if (IS_ERR_VALUE(parent_rate))
353  		return parent_rate;
354  
355  	debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate);
356  
357  	/* If can't divide, set parent instead */
358  	if (!parent_rate || rate > parent_rate)
359  		return meson_clk_set_rate_by_id(clk, parent, rate,
360  						current_rate);
361  
362  	new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
363  
364  	debug("%s: new div of %ld is %d\n", __func__, id, new_div);
365  
366  	/* If overflow, try to set parent rate and retry */
367  	if (!new_div || new_div > (1 << parm->width)) {
368  		ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate);
369  		if (IS_ERR_VALUE(ret))
370  			return ret;
371  
372  		parent_rate = meson_clk_get_rate_by_id(clk, parent);
373  		if (IS_ERR_VALUE(parent_rate))
374  			return parent_rate;
375  
376  		new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
377  
378  		debug("%s: new new div of %ld is %d\n", __func__, id, new_div);
379  
380  		if (!new_div || new_div > (1 << parm->width))
381  			return -EINVAL;
382  	}
383  
384  	debug("%s: setting div of %ld to %d\n", __func__, id, new_div);
385  
386  	reg = readl(priv->addr + parm->reg_off);
387  	writel(PARM_SET(parm->width, parm->shift, reg, new_div - 1),
388  	       priv->addr + parm->reg_off);
389  
390  	debug("%s: new rate of %ld is %ld\n",
391  	      __func__, id, meson_div_get_rate(clk, id));
392  
393  	return 0;
394  }
395  
396  static struct parm meson_vpu_mux_parm = {
397  	HHI_VPU_CLK_CNTL, 31, 1,
398  };
399  
400  int meson_vpu_mux_parents[] = {
401  	CLKID_VPU_0,
402  	CLKID_VPU_1,
403  };
404  
405  static struct parm meson_vpu_0_mux_parm = {
406  	HHI_VPU_CLK_CNTL, 9, 2,
407  };
408  
409  static struct parm meson_vpu_1_mux_parm = {
410  	HHI_VPU_CLK_CNTL, 25, 2,
411  };
412  
413  static int meson_vpu_0_1_mux_parents[] = {
414  	CLKID_FCLK_DIV4,
415  	CLKID_FCLK_DIV3,
416  	CLKID_FCLK_DIV5,
417  	CLKID_FCLK_DIV7,
418  };
419  
420  static struct parm meson_vapb_sel_mux_parm = {
421  	HHI_VAPBCLK_CNTL, 31, 1,
422  };
423  
424  int meson_vapb_sel_mux_parents[] = {
425  	CLKID_VAPB_0,
426  	CLKID_VAPB_1,
427  };
428  
429  static struct parm meson_vapb_0_mux_parm = {
430  	HHI_VAPBCLK_CNTL, 9, 2,
431  };
432  
433  static struct parm meson_vapb_1_mux_parm = {
434  	HHI_VAPBCLK_CNTL, 25, 2,
435  };
436  
437  static int meson_vapb_0_1_mux_parents[] = {
438  	CLKID_FCLK_DIV4,
439  	CLKID_FCLK_DIV3,
440  	CLKID_FCLK_DIV5,
441  	CLKID_FCLK_DIV7,
442  };
443  
444  static ulong meson_mux_get_parent(struct clk *clk, unsigned long id)
445  {
446  	struct meson_clk *priv = dev_get_priv(clk->dev);
447  	struct parm *parm;
448  	int *parents;
449  	u32 reg;
450  
451  	switch (id) {
452  	case CLKID_VPU:
453  		parm = &meson_vpu_mux_parm;
454  		parents = meson_vpu_mux_parents;
455  		break;
456  	case CLKID_VPU_0_SEL:
457  		parm = &meson_vpu_0_mux_parm;
458  		parents = meson_vpu_0_1_mux_parents;
459  		break;
460  	case CLKID_VPU_1_SEL:
461  		parm = &meson_vpu_1_mux_parm;
462  		parents = meson_vpu_0_1_mux_parents;
463  		break;
464  	case CLKID_VAPB_SEL:
465  		parm = &meson_vapb_sel_mux_parm;
466  		parents = meson_vapb_sel_mux_parents;
467  		break;
468  	case CLKID_VAPB_0_SEL:
469  		parm = &meson_vapb_0_mux_parm;
470  		parents = meson_vapb_0_1_mux_parents;
471  		break;
472  	case CLKID_VAPB_1_SEL:
473  		parm = &meson_vapb_1_mux_parm;
474  		parents = meson_vapb_0_1_mux_parents;
475  		break;
476  	default:
477  		return -ENOENT;
478  	}
479  
480  	reg = readl(priv->addr + parm->reg_off);
481  	reg = PARM_GET(parm->width, parm->shift, reg);
482  
483  	debug("%s: parent of %ld is %d (%d)\n",
484  	      __func__, id, parents[reg], reg);
485  
486  	return parents[reg];
487  }
488  
489  static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
490  				  unsigned long parent_id)
491  {
492  	unsigned long cur_parent = meson_mux_get_parent(clk, id);
493  	struct meson_clk *priv = dev_get_priv(clk->dev);
494  	unsigned int new_index = -EINVAL;
495  	struct parm *parm;
496  	int *parents;
497  	u32 reg;
498  	int i;
499  
500  	if (IS_ERR_VALUE(cur_parent))
501  		return cur_parent;
502  
503  	debug("%s: setting parent of %ld from %ld to %ld\n",
504  	      __func__, id, cur_parent, parent_id);
505  
506  	if (cur_parent == parent_id)
507  		return 0;
508  
509  	switch (id) {
510  	case CLKID_VPU:
511  		parm = &meson_vpu_mux_parm;
512  		parents = meson_vpu_mux_parents;
513  		break;
514  	case CLKID_VPU_0_SEL:
515  		parm = &meson_vpu_0_mux_parm;
516  		parents = meson_vpu_0_1_mux_parents;
517  		break;
518  	case CLKID_VPU_1_SEL:
519  		parm = &meson_vpu_1_mux_parm;
520  		parents = meson_vpu_0_1_mux_parents;
521  		break;
522  	case CLKID_VAPB_SEL:
523  		parm = &meson_vapb_sel_mux_parm;
524  		parents = meson_vapb_sel_mux_parents;
525  		break;
526  	case CLKID_VAPB_0_SEL:
527  		parm = &meson_vapb_0_mux_parm;
528  		parents = meson_vapb_0_1_mux_parents;
529  		break;
530  	case CLKID_VAPB_1_SEL:
531  		parm = &meson_vapb_1_mux_parm;
532  		parents = meson_vapb_0_1_mux_parents;
533  		break;
534  	default:
535  		/* Not a mux */
536  		return -ENOENT;
537  	}
538  
539  	for (i = 0 ; i < (1 << parm->width) ; ++i) {
540  		if (parents[i] == parent_id)
541  			new_index = i;
542  	}
543  
544  	if (IS_ERR_VALUE(new_index))
545  		return new_index;
546  
547  	debug("%s: new index of %ld is %d\n", __func__, id, new_index);
548  
549  	reg = readl(priv->addr + parm->reg_off);
550  	writel(PARM_SET(parm->width, parm->shift, reg, new_index),
551  	       priv->addr + parm->reg_off);
552  
553  	debug("%s: new parent of %ld is %ld\n",
554  	      __func__, id, meson_mux_get_parent(clk, id));
555  
556  	return 0;
557  }
558  
559  static ulong meson_mux_get_rate(struct clk *clk, unsigned long id)
560  {
561  	int parent = meson_mux_get_parent(clk, id);
562  
563  	if (IS_ERR_VALUE(parent))
564  		return parent;
565  
566  	return meson_clk_get_rate_by_id(clk, parent);
567  }
568  
569  static unsigned long meson_clk81_get_rate(struct clk *clk)
570  {
571  	struct meson_clk *priv = dev_get_priv(clk->dev);
572  	unsigned long parent_rate;
573  	u32 reg;
574  	int parents[] = {
575  		-1,
576  		-1,
577  		CLKID_FCLK_DIV7,
578  		CLKID_MPLL1,
579  		CLKID_MPLL2,
580  		CLKID_FCLK_DIV4,
581  		CLKID_FCLK_DIV3,
582  		CLKID_FCLK_DIV5
583  	};
584  
585  	/* mux */
586  	reg = readl(priv->addr + HHI_MPEG_CLK_CNTL);
587  	reg = (reg >> 12) & 7;
588  
589  	switch (reg) {
590  	case 0:
591  		parent_rate = XTAL_RATE;
592  		break;
593  	case 1:
594  		return -ENOENT;
595  	default:
596  		parent_rate = meson_clk_get_rate_by_id(clk, parents[reg]);
597  	}
598  
599  	/* divider */
600  	reg = readl(priv->addr + HHI_MPEG_CLK_CNTL);
601  	reg = reg & ((1 << 7) - 1);
602  
603  	return parent_rate / reg;
604  }
605  
606  static long mpll_rate_from_params(unsigned long parent_rate,
607  				  unsigned long sdm,
608  				  unsigned long n2)
609  {
610  	unsigned long divisor = (SDM_DEN * n2) + sdm;
611  
612  	if (n2 < N2_MIN)
613  		return -EINVAL;
614  
615  	return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor);
616  }
617  
618  static struct parm meson_mpll0_parm[3] = {
619  	{HHI_MPLL_CNTL7, 0, 14}, /* psdm */
620  	{HHI_MPLL_CNTL7, 16, 9}, /* pn2 */
621  };
622  
623  static struct parm meson_mpll1_parm[3] = {
624  	{HHI_MPLL_CNTL8, 0, 14}, /* psdm */
625  	{HHI_MPLL_CNTL8, 16, 9}, /* pn2 */
626  };
627  
628  static struct parm meson_mpll2_parm[3] = {
629  	{HHI_MPLL_CNTL9, 0, 14}, /* psdm */
630  	{HHI_MPLL_CNTL9, 16, 9}, /* pn2 */
631  };
632  
633  /*
634   * MultiPhase Locked Loops are outputs from a PLL with additional frequency
635   * scaling capabilities. MPLL rates are calculated as:
636   *
637   * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384)
638   */
639  static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id)
640  {
641  	struct meson_clk *priv = dev_get_priv(clk->dev);
642  	struct parm *psdm, *pn2;
643  	unsigned long reg, sdm, n2;
644  	unsigned long parent_rate;
645  
646  	switch (id) {
647  	case CLKID_MPLL0:
648  		psdm = &meson_mpll0_parm[0];
649  		pn2 = &meson_mpll0_parm[1];
650  		break;
651  	case CLKID_MPLL1:
652  		psdm = &meson_mpll1_parm[0];
653  		pn2 = &meson_mpll1_parm[1];
654  		break;
655  	case CLKID_MPLL2:
656  		psdm = &meson_mpll2_parm[0];
657  		pn2 = &meson_mpll2_parm[1];
658  		break;
659  	default:
660  		return -ENOENT;
661  	}
662  
663  	parent_rate = meson_clk_get_rate_by_id(clk, CLKID_FIXED_PLL);
664  	if (IS_ERR_VALUE(parent_rate))
665  		return parent_rate;
666  
667  	reg = readl(priv->addr + psdm->reg_off);
668  	sdm = PARM_GET(psdm->width, psdm->shift, reg);
669  
670  	reg = readl(priv->addr + pn2->reg_off);
671  	n2 = PARM_GET(pn2->width, pn2->shift, reg);
672  
673  	return mpll_rate_from_params(parent_rate, sdm, n2);
674  }
675  
676  static struct parm meson_fixed_pll_parm[3] = {
677  	{HHI_MPLL_CNTL, 0, 9}, /* pm */
678  	{HHI_MPLL_CNTL, 9, 5}, /* pn */
679  	{HHI_MPLL_CNTL, 16, 2}, /* pod */
680  };
681  
682  static struct parm meson_sys_pll_parm[3] = {
683  	{HHI_SYS_PLL_CNTL, 0, 9}, /* pm */
684  	{HHI_SYS_PLL_CNTL, 9, 5}, /* pn */
685  	{HHI_SYS_PLL_CNTL, 10, 2}, /* pod */
686  };
687  
688  static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
689  {
690  	struct meson_clk *priv = dev_get_priv(clk->dev);
691  	struct parm *pm, *pn, *pod;
692  	unsigned long parent_rate_mhz = XTAL_RATE / 1000000;
693  	u16 n, m, od;
694  	u32 reg;
695  
696  	switch (id) {
697  	case CLKID_FIXED_PLL:
698  		pm = &meson_fixed_pll_parm[0];
699  		pn = &meson_fixed_pll_parm[1];
700  		pod = &meson_fixed_pll_parm[2];
701  		break;
702  	case CLKID_SYS_PLL:
703  		pm = &meson_sys_pll_parm[0];
704  		pn = &meson_sys_pll_parm[1];
705  		pod = &meson_sys_pll_parm[2];
706  		break;
707  	default:
708  		return -ENOENT;
709  	}
710  
711  	reg = readl(priv->addr + pn->reg_off);
712  	n = PARM_GET(pn->width, pn->shift, reg);
713  
714  	reg = readl(priv->addr + pm->reg_off);
715  	m = PARM_GET(pm->width, pm->shift, reg);
716  
717  	reg = readl(priv->addr + pod->reg_off);
718  	od = PARM_GET(pod->width, pod->shift, reg);
719  
720  	return ((parent_rate_mhz * m / n) >> od) * 1000000;
721  }
722  
723  static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
724  {
725  	ulong rate;
726  
727  	switch (id) {
728  	case CLKID_FIXED_PLL:
729  	case CLKID_SYS_PLL:
730  		rate = meson_pll_get_rate(clk, id);
731  		break;
732  	case CLKID_FCLK_DIV2:
733  		rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 2;
734  		break;
735  	case CLKID_FCLK_DIV3:
736  		rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 3;
737  		break;
738  	case CLKID_FCLK_DIV4:
739  		rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 4;
740  		break;
741  	case CLKID_FCLK_DIV5:
742  		rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 5;
743  		break;
744  	case CLKID_FCLK_DIV7:
745  		rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 7;
746  		break;
747  	case CLKID_MPLL0:
748  	case CLKID_MPLL1:
749  	case CLKID_MPLL2:
750  		rate = meson_mpll_get_rate(clk, id);
751  		break;
752  	case CLKID_CLK81:
753  		rate = meson_clk81_get_rate(clk);
754  		break;
755  	case CLKID_VPU_0:
756  		rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV);
757  		break;
758  	case CLKID_VPU_1:
759  		rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV);
760  		break;
761  	case CLKID_VAPB:
762  		rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL);
763  		break;
764  	case CLKID_VAPB_0:
765  		rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV);
766  		break;
767  	case CLKID_VAPB_1:
768  		rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV);
769  		break;
770  	case CLKID_VPU_0_DIV:
771  	case CLKID_VPU_1_DIV:
772  	case CLKID_VAPB_0_DIV:
773  	case CLKID_VAPB_1_DIV:
774  		rate = meson_div_get_rate(clk, id);
775  		break;
776  	case CLKID_VPU:
777  	case CLKID_VPU_0_SEL:
778  	case CLKID_VPU_1_SEL:
779  	case CLKID_VAPB_SEL:
780  	case CLKID_VAPB_0_SEL:
781  	case CLKID_VAPB_1_SEL:
782  		rate = meson_mux_get_rate(clk, id);
783  		break;
784  	default:
785  		if (gates[id].reg != 0) {
786  			/* a clock gate */
787  			rate = meson_clk81_get_rate(clk);
788  			break;
789  		}
790  		return -ENOENT;
791  	}
792  
793  	printf("clock %lu has rate %lu\n", id, rate);
794  	return rate;
795  }
796  
797  static ulong meson_clk_get_rate(struct clk *clk)
798  {
799  	return meson_clk_get_rate_by_id(clk, clk->id);
800  }
801  
802  static int meson_clk_set_parent(struct clk *clk, struct clk *parent)
803  {
804  	return meson_mux_set_parent(clk, clk->id, parent->id);
805  }
806  
807  static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
808  				      ulong rate, ulong current_rate)
809  {
810  	if (current_rate == rate)
811  		return 0;
812  
813  	switch (id) {
814  	/* Fixed clocks */
815  	case CLKID_FIXED_PLL:
816  	case CLKID_SYS_PLL:
817  	case CLKID_FCLK_DIV2:
818  	case CLKID_FCLK_DIV3:
819  	case CLKID_FCLK_DIV4:
820  	case CLKID_FCLK_DIV5:
821  	case CLKID_FCLK_DIV7:
822  	case CLKID_MPLL0:
823  	case CLKID_MPLL1:
824  	case CLKID_MPLL2:
825  	case CLKID_CLK81:
826  		if (current_rate != rate)
827  			return -EINVAL;
828  
829  		return 0;
830  	case CLKID_VPU:
831  		return meson_clk_set_rate_by_id(clk,
832  				meson_mux_get_parent(clk, CLKID_VPU), rate,
833  						     current_rate);
834  	case CLKID_VAPB:
835  	case CLKID_VAPB_SEL:
836  		return meson_clk_set_rate_by_id(clk,
837  				meson_mux_get_parent(clk, CLKID_VAPB_SEL),
838  				rate, current_rate);
839  	case CLKID_VPU_0:
840  		return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate,
841  					  current_rate);
842  	case CLKID_VPU_1:
843  		return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate,
844  					  current_rate);
845  	case CLKID_VAPB_0:
846  		return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate,
847  					  current_rate);
848  	case CLKID_VAPB_1:
849  		return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate,
850  					  current_rate);
851  	case CLKID_VPU_0_DIV:
852  	case CLKID_VPU_1_DIV:
853  	case CLKID_VAPB_0_DIV:
854  	case CLKID_VAPB_1_DIV:
855  		return meson_div_set_rate(clk, id, rate, current_rate);
856  	default:
857  		return -ENOENT;
858  	}
859  
860  	return -EINVAL;
861  }
862  
863  static ulong meson_clk_set_rate(struct clk *clk, ulong rate)
864  {
865  	ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id);
866  	int ret;
867  
868  	if (IS_ERR_VALUE(current_rate))
869  		return current_rate;
870  
871  	debug("%s: setting rate of %ld from %ld to %ld\n",
872  	      __func__, clk->id, current_rate, rate);
873  
874  	ret = meson_clk_set_rate_by_id(clk, clk->id, rate, current_rate);
875  	if (IS_ERR_VALUE(ret))
876  		return ret;
877  
878  	printf("clock %lu has new rate %lu\n", clk->id,
879  	       meson_clk_get_rate_by_id(clk, clk->id));
880  
881  	return 0;
882  }
883  
884  static int meson_clk_probe(struct udevice *dev)
885  {
886  	struct meson_clk *priv = dev_get_priv(dev);
887  
888  	priv->addr = dev_read_addr_ptr(dev);
889  
890  	debug("meson-clk: probed at addr %p\n", priv->addr);
891  
892  	return 0;
893  }
894  
895  static struct clk_ops meson_clk_ops = {
896  	.disable	= meson_clk_disable,
897  	.enable		= meson_clk_enable,
898  	.get_rate	= meson_clk_get_rate,
899  	.set_parent	= meson_clk_set_parent,
900  	.set_rate	= meson_clk_set_rate,
901  };
902  
903  static const struct udevice_id meson_clk_ids[] = {
904  	{ .compatible = "amlogic,gxbb-clkc" },
905  	{ .compatible = "amlogic,gxl-clkc" },
906  	{ }
907  };
908  
909  U_BOOT_DRIVER(meson_clk) = {
910  	.name		= "meson_clk",
911  	.id		= UCLASS_CLK,
912  	.of_match	= meson_clk_ids,
913  	.priv_auto_alloc_size = sizeof(struct meson_clk),
914  	.ops		= &meson_clk_ops,
915  	.probe		= meson_clk_probe,
916  };
917