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