xref: /openbmc/u-boot/drivers/clk/aspeed/clk_ast2600.c (revision e95b19f84d047c195aa3159afb9ba8f300724a9e)
1550e691bSryan_chen // SPDX-License-Identifier: GPL-2.0
2550e691bSryan_chen /*
3550e691bSryan_chen  * Copyright (C) ASPEED Technology Inc.
4550e691bSryan_chen  */
5550e691bSryan_chen 
6550e691bSryan_chen #include <common.h>
7e40a4e44SDylan Hung #include <linux/bitfield.h>
8e40a4e44SDylan Hung #include <linux/bitops.h>
9*e95b19f8SDylan Hung #include <linux/iopoll.h>
10550e691bSryan_chen #include <clk-uclass.h>
11550e691bSryan_chen #include <dm.h>
12550e691bSryan_chen #include <asm/io.h>
13550e691bSryan_chen #include <dm/lists.h>
1462a6bcbfSryan_chen #include <asm/arch/scu_ast2600.h>
15d6e349c7Sryan_chen #include <dt-bindings/clock/ast2600-clock.h>
1639283ea7Sryan_chen #include <dt-bindings/reset/ast2600-reset.h>
17550e691bSryan_chen 
18550e691bSryan_chen /*
19*e95b19f8SDylan Hung  * SCU 80 & 90 clock stop control for MAC controllers
20*e95b19f8SDylan Hung  */
21*e95b19f8SDylan Hung #define SCU_CLKSTOP_MAC1			(20)
22*e95b19f8SDylan Hung #define SCU_CLKSTOP_MAC2			(21)
23*e95b19f8SDylan Hung #define SCU_CLKSTOP_MAC3			(20)
24*e95b19f8SDylan Hung #define SCU_CLKSTOP_MAC4			(21)
25*e95b19f8SDylan Hung 
26*e95b19f8SDylan Hung /*
27a8fc7648SRyan Chen  * MAC Clock Delay settings
28550e691bSryan_chen  */
29e40a4e44SDylan Hung #define MAC_CLK_RGMII_125M_SRC_SEL		BIT(31)
30e40a4e44SDylan Hung #define   MAC_CLK_RGMII_125M_SRC_PAD_RGMIICK	0
31e40a4e44SDylan Hung #define   MAC_CLK_RGMII_125M_SRC_PLL		1
32e40a4e44SDylan Hung #define MAC_CLK_RMII2_50M_RCLK_O_CTRL		BIT(30)
33e40a4e44SDylan Hung #define   MAC_CLK_RMII2_50M_RCLK_O_DIS		0
34e40a4e44SDylan Hung #define   MAC_CLK_RMII2_50M_RCLK_O_EN		1
35e40a4e44SDylan Hung #define MAC_CLK_RMII1_50M_RCLK_O_CTRL		BIT(29)
36e40a4e44SDylan Hung #define   MAC_CLK_RMII1_5M_RCLK_O_DIS		0
37e40a4e44SDylan Hung #define   MAC_CLK_RMII1_5M_RCLK_O_EN		1
38e40a4e44SDylan Hung #define MAC_CLK_RGMIICK_PAD_DIR			BIT(28)
39e40a4e44SDylan Hung #define   MAC_CLK_RGMIICK_PAD_DIR_INPUT		0
40e40a4e44SDylan Hung #define   MAC_CLK_RGMIICK_PAD_DIR_OUTPUT	1
41e40a4e44SDylan Hung #define MAC_CLK_RMII_TXD_FALLING_2		BIT(27)
42e40a4e44SDylan Hung #define MAC_CLK_RMII_TXD_FALLING_1		BIT(26)
43e40a4e44SDylan Hung #define MAC_CLK_RXCLK_INV_2			BIT(25)
44e40a4e44SDylan Hung #define MAC_CLK_RXCLK_INV_1			BIT(24)
45e40a4e44SDylan Hung #define MAC_CLK_1G_INPUT_DELAY_2		GENMASK(23, 18)
46e40a4e44SDylan Hung #define MAC_CLK_1G_INPUT_DELAY_1		GENMASK(17, 12)
47e40a4e44SDylan Hung #define MAC_CLK_1G_OUTPUT_DELAY_2		GENMASK(11, 6)
48e40a4e44SDylan Hung #define MAC_CLK_1G_OUTPUT_DELAY_1		GENMASK(5, 0)
49550e691bSryan_chen 
50e40a4e44SDylan Hung #define MAC_CLK_100M_10M_RESERVED		GENMASK(31, 26)
51e40a4e44SDylan Hung #define MAC_CLK_100M_10M_RXCLK_INV_2		BIT(25)
52e40a4e44SDylan Hung #define MAC_CLK_100M_10M_RXCLK_INV_1		BIT(24)
53e40a4e44SDylan Hung #define MAC_CLK_100M_10M_INPUT_DELAY_2		GENMASK(23, 18)
54e40a4e44SDylan Hung #define MAC_CLK_100M_10M_INPUT_DELAY_1		GENMASK(17, 12)
55e40a4e44SDylan Hung #define MAC_CLK_100M_10M_OUTPUT_DELAY_2		GENMASK(11, 6)
56e40a4e44SDylan Hung #define MAC_CLK_100M_10M_OUTPUT_DELAY_1		GENMASK(5, 0)
5754f9cba1SDylan Hung 
58*e95b19f8SDylan Hung #define RGMII12_CLK_OUTPUT_DELAY_PS		1000
59*e95b19f8SDylan Hung #define RGMII34_CLK_OUTPUT_DELAY_PS		1600
60*e95b19f8SDylan Hung 
61e40a4e44SDylan Hung #define MAC_DEF_DELAY_1G			FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, 16) |        \
62e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, 10) |         \
63e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, 16) |        \
64e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, 10)
65e40a4e44SDylan Hung #define MAC_DEF_DELAY_100M			FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, 16) |  \
66e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, 16) |   \
67e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, 16) |  \
68e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, 16)
69e40a4e44SDylan Hung #define MAC_DEF_DELAY_10M			FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, 16) |  \
70e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, 16) |   \
71e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, 16) |  \
72e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, 16)
73e40a4e44SDylan Hung #define MAC34_DEF_DELAY_1G			FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, 8) |         \
74e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, 4) |          \
75e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, 8) |         \
76e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, 4)
77e40a4e44SDylan Hung #define MAC34_DEF_DELAY_100M			FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, 8) |   \
78e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, 4) |    \
79e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, 8) |   \
80e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, 4)
81e40a4e44SDylan Hung #define MAC34_DEF_DELAY_10M			FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, 8) |   \
82e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, 4) |    \
83e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, 8) |   \
84e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, 4)
85*e95b19f8SDylan Hung 
86*e95b19f8SDylan Hung /*
87*e95b19f8SDylan Hung  * SCU 320 & 330 Frequency counters
88*e95b19f8SDylan Hung  */
89*e95b19f8SDylan Hung #define FREQC_CTRL_RESERVED			GENMASK(31, 30)
90*e95b19f8SDylan Hung #define FREQC_CTRL_RESULT			GENMASK(29, 16)
91*e95b19f8SDylan Hung #define FREQC_CTRL_RING_STAGE			GENMASK(15, 9)
92*e95b19f8SDylan Hung #define FREQC_CTRL_PIN_O_CTRL			BIT(8)
93*e95b19f8SDylan Hung #define   FREQC_CTRL_PIN_O_DIS			0
94*e95b19f8SDylan Hung #define   FREQC_CTRL_PIN_O_EN			1
95*e95b19f8SDylan Hung #define FREQC_CTRL_CMP_RESULT			BIT(7)
96*e95b19f8SDylan Hung #define   FREQC_CTRL_CMP_RESULT_FAIL		0
97*e95b19f8SDylan Hung #define   FREQC_CTRL_CMP_RESULT_PASS		1
98*e95b19f8SDylan Hung #define FREQC_CTRL_STATUS			BIT(6)
99*e95b19f8SDylan Hung #define   FREQC_CTRL_STATUS_NOT_FINISHED	0
100*e95b19f8SDylan Hung #define   FREQC_CTRL_STATUS_FINISHED		1
101*e95b19f8SDylan Hung #define FREQC_CTRL_SRC_SEL			GENMASK(5, 2)
102*e95b19f8SDylan Hung #define   FREQC_CTRL_SRC_SEL_HCLK_DIE0		9
103*e95b19f8SDylan Hung #define   FREQC_CTRL_SRC_SEL_DLY32_DIE0		3
104*e95b19f8SDylan Hung #define   FREQC_CTRL_SRC_SEL_HCLK_DIE1		1
105*e95b19f8SDylan Hung #define   FREQC_CTRL_SRC_SEL_DLY32_DIE1		7
106*e95b19f8SDylan Hung #define FREQC_CTRL_OSC_CTRL			BIT(1)
107*e95b19f8SDylan Hung #define   FREQC_CTRL_OSC_DIS			0
108*e95b19f8SDylan Hung #define   FREQC_CTRL_OSC_EN			1
109*e95b19f8SDylan Hung #define FREQC_CTRL_RING_CTRL			BIT(0)
110*e95b19f8SDylan Hung #define   FREQC_CTRL_RING_DIS			0
111*e95b19f8SDylan Hung #define   FREQC_CTRL_RING_EN			1
112*e95b19f8SDylan Hung 
113*e95b19f8SDylan Hung #define FREQC_RANGE_RESERVED0			GENMASK(31, 30)
114*e95b19f8SDylan Hung #define FREQC_RANGE_LOWER			GENMASK(29, 16)
115*e95b19f8SDylan Hung #define FREQC_RANGE_RESERVED1			GENMASK(15, 14)
116*e95b19f8SDylan Hung #define FREQC_RANGE_UPPER			GENMASK(13, 0)
117*e95b19f8SDylan Hung 
118*e95b19f8SDylan Hung #define DLY32_NUM_OF_TAPS			32
119*e95b19f8SDylan Hung #define DLY32_AVERAGE_COUNT_LOG2		4
120*e95b19f8SDylan Hung #define DLY32_AVERAGE_COUNT			BIT(DLY32_AVERAGE_COUNT_LOG2)
121*e95b19f8SDylan Hung 
122550e691bSryan_chen /*
123550e691bSryan_chen  * TGMII Clock Duty constants, taken from Aspeed SDK
124550e691bSryan_chen  */
125550e691bSryan_chen #define RGMII2_TXCK_DUTY		0x66
126550e691bSryan_chen #define RGMII1_TXCK_DUTY		0x64
127550e691bSryan_chen #define D2PLL_DEFAULT_RATE		(250 * 1000 * 1000)
12885d48d8cSryan_chen #define CHIP_REVISION_ID		GENMASK(23, 16)
12985d48d8cSryan_chen 
130550e691bSryan_chen DECLARE_GLOBAL_DATA_PTR;
131550e691bSryan_chen 
132550e691bSryan_chen /*
133550e691bSryan_chen  * Clock divider/multiplier configuration struct.
134550e691bSryan_chen  * For H-PLL and M-PLL the formula is
135550e691bSryan_chen  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
136550e691bSryan_chen  * M - Numerator
137550e691bSryan_chen  * N - Denumerator
138550e691bSryan_chen  * P - Post Divider
139550e691bSryan_chen  * They have the same layout in their control register.
140550e691bSryan_chen  *
141550e691bSryan_chen  * D-PLL and D2-PLL have extra divider (OD + 1), which is not
142550e691bSryan_chen  * yet needed and ignored by clock configurations.
143550e691bSryan_chen  */
144577fcdaeSDylan Hung union ast2600_pll_reg {
145334bd202SDylan Hung 	u32 w;
146577fcdaeSDylan Hung 	struct {
147fd52be0bSDylan Hung 		unsigned int m : 13;		/* bit[12:0]	*/
148fd52be0bSDylan Hung 		unsigned int n : 6;		/* bit[18:13]	*/
149fd52be0bSDylan Hung 		unsigned int p : 4;		/* bit[22:19]	*/
150fd52be0bSDylan Hung 		unsigned int off : 1;		/* bit[23]	*/
151fd52be0bSDylan Hung 		unsigned int bypass : 1;	/* bit[24]	*/
152fd52be0bSDylan Hung 		unsigned int reset : 1;		/* bit[25]	*/
153fd52be0bSDylan Hung 		unsigned int reserved : 6;	/* bit[31:26]	*/
154577fcdaeSDylan Hung 	} b;
155577fcdaeSDylan Hung };
156577fcdaeSDylan Hung 
157577fcdaeSDylan Hung struct ast2600_pll_cfg {
158577fcdaeSDylan Hung 	union ast2600_pll_reg reg;
159334bd202SDylan Hung 	u32 ext_reg;
160577fcdaeSDylan Hung };
161577fcdaeSDylan Hung 
162577fcdaeSDylan Hung struct ast2600_pll_desc {
163577fcdaeSDylan Hung 	u32 in;
164577fcdaeSDylan Hung 	u32 out;
165577fcdaeSDylan Hung 	struct ast2600_pll_cfg cfg;
166577fcdaeSDylan Hung };
167577fcdaeSDylan Hung 
168577fcdaeSDylan Hung static const struct ast2600_pll_desc ast2600_pll_lookup[] = {
169a8fc7648SRyan Chen 	{
1705d05f4fcSRyan Chen 		.in = AST2600_CLK_IN,
1715d05f4fcSRyan Chen 		.out = 400000000,
1725d05f4fcSRyan Chen 		.cfg.reg.b.m = 95,
1735d05f4fcSRyan Chen 		.cfg.reg.b.n = 2,
1745d05f4fcSRyan Chen 		.cfg.reg.b.p = 1,
175577fcdaeSDylan Hung 		.cfg.ext_reg = 0x31,
176fa59add1SRyan Chen 	}, {
177fa59add1SRyan Chen 		.in = AST2600_CLK_IN,
1785d05f4fcSRyan Chen 		.out = 200000000,
1795d05f4fcSRyan Chen 		.cfg.reg.b.m = 127,
1805d05f4fcSRyan Chen 		.cfg.reg.b.n = 0,
1815d05f4fcSRyan Chen 		.cfg.reg.b.p = 15,
182fa59add1SRyan Chen 		.cfg.ext_reg = 0x3f,
183fa59add1SRyan Chen 	}, {
184fa59add1SRyan Chen 		.in = AST2600_CLK_IN,
1855d05f4fcSRyan Chen 		.out = 334000000,
1865d05f4fcSRyan Chen 		.cfg.reg.b.m = 667,
1875d05f4fcSRyan Chen 		.cfg.reg.b.n = 4,
1885d05f4fcSRyan Chen 		.cfg.reg.b.p = 9,
189fa59add1SRyan Chen 		.cfg.ext_reg = 0x14d,
190fa59add1SRyan Chen 	}, {
191fa59add1SRyan Chen 		.in = AST2600_CLK_IN,
1925d05f4fcSRyan Chen 		.out = 1000000000,
1935d05f4fcSRyan Chen 		.cfg.reg.b.m = 119,
1945d05f4fcSRyan Chen 		.cfg.reg.b.n = 2,
1955d05f4fcSRyan Chen 		.cfg.reg.b.p = 0,
196fa59add1SRyan Chen 		.cfg.ext_reg = 0x3d,
197fa59add1SRyan Chen 	}, {
198fa59add1SRyan Chen 		.in = AST2600_CLK_IN,
1995d05f4fcSRyan Chen 		.out = 50000000,
2005d05f4fcSRyan Chen 		.cfg.reg.b.m = 95,
2015d05f4fcSRyan Chen 		.cfg.reg.b.n = 2,
2025d05f4fcSRyan Chen 		.cfg.reg.b.p = 15,
203fa59add1SRyan Chen 		.cfg.ext_reg = 0x31,
204fa59add1SRyan Chen 	},
205550e691bSryan_chen };
206550e691bSryan_chen 
207a98c71fbSDylan Hung struct mac_delay_config {
208a98c71fbSDylan Hung 	u32 tx_delay_1000;
209a98c71fbSDylan Hung 	u32 rx_delay_1000;
210a98c71fbSDylan Hung 	u32 tx_delay_100;
211a98c71fbSDylan Hung 	u32 rx_delay_100;
212a98c71fbSDylan Hung 	u32 tx_delay_10;
213a98c71fbSDylan Hung 	u32 rx_delay_10;
214a98c71fbSDylan Hung };
215a98c71fbSDylan Hung 
216bbbfb0c5Sryan_chen extern u32 ast2600_get_pll_rate(struct ast2600_scu *scu, int pll_idx)
217550e691bSryan_chen {
218d6e349c7Sryan_chen 	u32 clkin = AST2600_CLK_IN;
219bbbfb0c5Sryan_chen 	u32 pll_reg = 0;
2209639db61Sryan_chen 	unsigned int mult, div = 1;
221550e691bSryan_chen 
222bbbfb0c5Sryan_chen 	switch (pll_idx) {
223bbbfb0c5Sryan_chen 	case ASPEED_CLK_HPLL:
224bbbfb0c5Sryan_chen 		pll_reg = readl(&scu->h_pll_param);
225bbbfb0c5Sryan_chen 		break;
226bbbfb0c5Sryan_chen 	case ASPEED_CLK_MPLL:
227bbbfb0c5Sryan_chen 		pll_reg = readl(&scu->m_pll_param);
228bbbfb0c5Sryan_chen 		break;
229bbbfb0c5Sryan_chen 	case ASPEED_CLK_DPLL:
230bbbfb0c5Sryan_chen 		pll_reg = readl(&scu->d_pll_param);
231bbbfb0c5Sryan_chen 		break;
232bbbfb0c5Sryan_chen 	case ASPEED_CLK_EPLL:
233bbbfb0c5Sryan_chen 		pll_reg = readl(&scu->e_pll_param);
234bbbfb0c5Sryan_chen 		break;
235bbbfb0c5Sryan_chen 	}
236bbbfb0c5Sryan_chen 	if (pll_reg & BIT(24)) {
2379639db61Sryan_chen 		/* Pass through mode */
238ed3899c5SRyan Chen 		mult = 1;
239ed3899c5SRyan Chen 		div = 1;
2409639db61Sryan_chen 	} else {
24175ced45aSDylan Hung 		union ast2600_pll_reg reg;
242ed3899c5SRyan Chen 		/* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1)
243ed3899c5SRyan Chen 		 * HPLL Numerator (M) = fix 0x5F when SCU500[10]=1
244ed3899c5SRyan Chen 		 * Fixed 0xBF when SCU500[10]=0 and SCU500[8]=1
245ed3899c5SRyan Chen 		 * SCU200[12:0] (default 0x8F) when SCU510[10]=0 and SCU510[8]=0
246ed3899c5SRyan Chen 		 * HPLL Denumerator (N) =	SCU200[18:13] (default 0x2)
247ed3899c5SRyan Chen 		 * HPLL Divider (P)	 =	SCU200[22:19] (default 0x0)
248ed3899c5SRyan Chen 		 * HPLL Bandwidth Adj (NB) =  fix 0x2F when SCU500[10]=1
249ed3899c5SRyan Chen 		 * Fixed 0x5F when SCU500[10]=0 and SCU500[8]=1
250ed3899c5SRyan Chen 		 * SCU204[11:0] (default 0x31) when SCU500[10]=0 and SCU500[8]=0
251e5c4f4dfSryan_chen 		 */
252ed3899c5SRyan Chen 		reg.w = pll_reg;
253f27685ebSRyan Chen 		if (pll_idx == ASPEED_CLK_HPLL) {
254e5c4f4dfSryan_chen 			u32 hwstrap1 = readl(&scu->hwstrap1.hwstrap);
255ed3899c5SRyan Chen 
256ed3899c5SRyan Chen 			if (hwstrap1 & BIT(10)) {
257e5c4f4dfSryan_chen 				reg.b.m = 0x5F;
258ed3899c5SRyan Chen 			} else {
259e5c4f4dfSryan_chen 				if (hwstrap1 & BIT(8))
260e5c4f4dfSryan_chen 					reg.b.m = 0xBF;
261a8fc7648SRyan Chen 				/* Otherwise keep default 0x8F */
262e5c4f4dfSryan_chen 			}
263e5c4f4dfSryan_chen 		}
26475ced45aSDylan Hung 		mult = (reg.b.m + 1) / (reg.b.n + 1);
26575ced45aSDylan Hung 		div = (reg.b.p + 1);
2669639db61Sryan_chen 	}
267a8fc7648SRyan Chen 
2689639db61Sryan_chen 	return ((clkin * mult) / div);
269550e691bSryan_chen }
270550e691bSryan_chen 
2714f22e838Sryan_chen extern u32 ast2600_get_apll_rate(struct ast2600_scu *scu)
272550e691bSryan_chen {
27385d48d8cSryan_chen 	u32 hw_rev = readl(&scu->chip_id1);
274bbbfb0c5Sryan_chen 	u32 clkin = AST2600_CLK_IN;
27539283ea7Sryan_chen 	u32 apll_reg = readl(&scu->a_pll_param);
27639283ea7Sryan_chen 	unsigned int mult, div = 1;
277d6e349c7Sryan_chen 
2788d615c79SRyan Chen 	if (((hw_rev & CHIP_REVISION_ID) >> 16) >= 2) {
279a8fc7648SRyan Chen 		//after A2 version
28085d48d8cSryan_chen 		if (apll_reg & BIT(24)) {
28185d48d8cSryan_chen 			/* Pass through mode */
282ed3899c5SRyan Chen 			mult = 1;
283ed3899c5SRyan Chen 			div = 1;
28485d48d8cSryan_chen 		} else {
28585d48d8cSryan_chen 			/* F = 25Mhz * [(m + 1) / (n + 1)] / (p + 1) */
28685d48d8cSryan_chen 			u32 m = apll_reg & 0x1fff;
28785d48d8cSryan_chen 			u32 n = (apll_reg >> 13) & 0x3f;
28885d48d8cSryan_chen 			u32 p = (apll_reg >> 19) & 0xf;
28985d48d8cSryan_chen 
29085d48d8cSryan_chen 			mult = (m + 1);
29185d48d8cSryan_chen 			div = (n + 1) * (p + 1);
29285d48d8cSryan_chen 		}
29385d48d8cSryan_chen 	} else {
29439283ea7Sryan_chen 		if (apll_reg & BIT(20)) {
295d6e349c7Sryan_chen 			/* Pass through mode */
296ed3899c5SRyan Chen 			mult = 1;
297ed3899c5SRyan Chen 			div = 1;
298d6e349c7Sryan_chen 		} else {
299bbbfb0c5Sryan_chen 			/* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */
30039283ea7Sryan_chen 			u32 m = (apll_reg >> 5) & 0x3f;
30139283ea7Sryan_chen 			u32 od = (apll_reg >> 4) & 0x1;
30239283ea7Sryan_chen 			u32 n = apll_reg & 0xf;
303d6e349c7Sryan_chen 
304bbbfb0c5Sryan_chen 			mult = (2 - od) * (m + 2);
305bbbfb0c5Sryan_chen 			div = n + 1;
306d6e349c7Sryan_chen 		}
30785d48d8cSryan_chen 	}
308a8fc7648SRyan Chen 
309bbbfb0c5Sryan_chen 	return ((clkin * mult) / div);
31039283ea7Sryan_chen }
31139283ea7Sryan_chen 
312d812df15Sryan_chen static u32 ast2600_a0_axi_ahb_div_table[] = {
3135d05f4fcSRyan Chen 	2,
3145d05f4fcSRyan Chen 	2,
3155d05f4fcSRyan Chen 	3,
3165d05f4fcSRyan Chen 	4,
317d812df15Sryan_chen };
318d812df15Sryan_chen 
31945e0908aSryan_chen static u32 ast2600_a1_axi_ahb_div0_table[] = {
3205d05f4fcSRyan Chen 	3,
3215d05f4fcSRyan Chen 	2,
3225d05f4fcSRyan Chen 	3,
3235d05f4fcSRyan Chen 	4,
32445e0908aSryan_chen };
32545e0908aSryan_chen 
32645e0908aSryan_chen static u32 ast2600_a1_axi_ahb_div1_table[] = {
3275d05f4fcSRyan Chen 	3,
3285d05f4fcSRyan Chen 	4,
3295d05f4fcSRyan Chen 	6,
3305d05f4fcSRyan Chen 	8,
331e29dc694Sryan_chen };
332e29dc694Sryan_chen 
333e29dc694Sryan_chen static u32 ast2600_a1_axi_ahb_default_table[] = {
334e29dc694Sryan_chen 	3, 4, 3, 4, 2, 2, 2, 2,
335d812df15Sryan_chen };
336d812df15Sryan_chen 
337d812df15Sryan_chen static u32 ast2600_get_hclk(struct ast2600_scu *scu)
338d812df15Sryan_chen {
33985d48d8cSryan_chen 	u32 hw_rev = readl(&scu->chip_id1);
34045e0908aSryan_chen 	u32 hwstrap1 = readl(&scu->hwstrap1.hwstrap);
341d812df15Sryan_chen 	u32 axi_div = 1;
342d812df15Sryan_chen 	u32 ahb_div = 0;
343d812df15Sryan_chen 	u32 rate = 0;
344d812df15Sryan_chen 
34585d48d8cSryan_chen 	if ((hw_rev & CHIP_REVISION_ID) >> 16) {
346a8fc7648SRyan Chen 		//After A0
34745e0908aSryan_chen 		if (hwstrap1 & BIT(16)) {
348a8fc7648SRyan Chen 			ast2600_a1_axi_ahb_div1_table[0] =
3495d05f4fcSRyan Chen 				ast2600_a1_axi_ahb_default_table[(hwstrap1 >> 8) &
35022545706SRyan Chen 								 0x7] * 2;
351d812df15Sryan_chen 			axi_div = 1;
3525d05f4fcSRyan Chen 			ahb_div =
3535d05f4fcSRyan Chen 				ast2600_a1_axi_ahb_div1_table[(hwstrap1 >> 11) &
3545d05f4fcSRyan Chen 							      0x3];
35545e0908aSryan_chen 		} else {
356a8fc7648SRyan Chen 			ast2600_a1_axi_ahb_div0_table[0] =
3575d05f4fcSRyan Chen 				ast2600_a1_axi_ahb_default_table[(hwstrap1 >> 8) &
35822545706SRyan Chen 								 0x7];
359d812df15Sryan_chen 			axi_div = 2;
3605d05f4fcSRyan Chen 			ahb_div =
3615d05f4fcSRyan Chen 				ast2600_a1_axi_ahb_div0_table[(hwstrap1 >> 11) &
3625d05f4fcSRyan Chen 							      0x3];
36345e0908aSryan_chen 		}
36445e0908aSryan_chen 	} else {
365a8fc7648SRyan Chen 		//A0 : fix axi = hpll / 2
36645e0908aSryan_chen 		axi_div = 2;
367d812df15Sryan_chen 		ahb_div = ast2600_a0_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3];
36845e0908aSryan_chen 	}
369bbbfb0c5Sryan_chen 	rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
370a8fc7648SRyan Chen 
3712717883aSryan_chen 	return (rate / axi_div / ahb_div);
3722717883aSryan_chen }
3732717883aSryan_chen 
374c304f173Sryan_chen static u32 ast2600_get_bclk_rate(struct ast2600_scu *scu)
375c304f173Sryan_chen {
376c304f173Sryan_chen 	u32 rate;
377c304f173Sryan_chen 	u32 bclk_sel = (readl(&scu->clk_sel1) >> 20) & 0x7;
378ed3899c5SRyan Chen 
379c304f173Sryan_chen 	rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
380c304f173Sryan_chen 
381c304f173Sryan_chen 	return (rate / ((bclk_sel + 1) * 4));
382c304f173Sryan_chen }
383c304f173Sryan_chen 
3846fa1ef3dSryan_chen static u32 ast2600_hpll_pclk1_div_table[] = {
3852717883aSryan_chen 	4, 8, 12, 16, 20, 24, 28, 32,
3862717883aSryan_chen };
3872717883aSryan_chen 
3886fa1ef3dSryan_chen static u32 ast2600_hpll_pclk2_div_table[] = {
3896fa1ef3dSryan_chen 	2, 4, 6, 8, 10, 12, 14, 16,
3906fa1ef3dSryan_chen };
3916fa1ef3dSryan_chen 
3926fa1ef3dSryan_chen static u32 ast2600_get_pclk1(struct ast2600_scu *scu)
3932717883aSryan_chen {
3942717883aSryan_chen 	u32 clk_sel1 = readl(&scu->clk_sel1);
3956fa1ef3dSryan_chen 	u32 apb_div = ast2600_hpll_pclk1_div_table[((clk_sel1 >> 23) & 0x7)];
396bbbfb0c5Sryan_chen 	u32 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
3972717883aSryan_chen 
3982717883aSryan_chen 	return (rate / apb_div);
399d812df15Sryan_chen }
400d812df15Sryan_chen 
4016fa1ef3dSryan_chen static u32 ast2600_get_pclk2(struct ast2600_scu *scu)
4026fa1ef3dSryan_chen {
4036fa1ef3dSryan_chen 	u32 clk_sel4 = readl(&scu->clk_sel4);
4046fa1ef3dSryan_chen 	u32 apb_div = ast2600_hpll_pclk2_div_table[((clk_sel4 >> 9) & 0x7)];
4056fa1ef3dSryan_chen 	u32 rate = ast2600_get_hclk(scu);
4066fa1ef3dSryan_chen 
4076fa1ef3dSryan_chen 	return (rate / apb_div);
4086fa1ef3dSryan_chen }
4096fa1ef3dSryan_chen 
4102e195992Sryan_chen static u32 ast2600_get_uxclk_in_rate(struct ast2600_scu *scu)
411d6e349c7Sryan_chen {
41227881d20Sryan_chen 	u32 clk_in = 0;
4132e195992Sryan_chen 	u32 uxclk_sel = readl(&scu->clk_sel5);
414550e691bSryan_chen 
41527881d20Sryan_chen 	uxclk_sel &= 0x3;
41627881d20Sryan_chen 	switch (uxclk_sel) {
41727881d20Sryan_chen 	case 0:
41827881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu) / 4;
41927881d20Sryan_chen 		break;
42027881d20Sryan_chen 	case 1:
42127881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu) / 2;
42227881d20Sryan_chen 		break;
42327881d20Sryan_chen 	case 2:
42427881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu);
42527881d20Sryan_chen 		break;
42627881d20Sryan_chen 	case 3:
42727881d20Sryan_chen 		clk_in = ast2600_get_hclk(scu);
42827881d20Sryan_chen 		break;
42927881d20Sryan_chen 	}
430d6e349c7Sryan_chen 
43127881d20Sryan_chen 	return clk_in;
43227881d20Sryan_chen }
43327881d20Sryan_chen 
4342e195992Sryan_chen static u32 ast2600_get_huxclk_in_rate(struct ast2600_scu *scu)
43527881d20Sryan_chen {
43627881d20Sryan_chen 	u32 clk_in = 0;
4372e195992Sryan_chen 	u32 huclk_sel = readl(&scu->clk_sel5);
43827881d20Sryan_chen 
43927881d20Sryan_chen 	huclk_sel = ((huclk_sel >> 3) & 0x3);
44027881d20Sryan_chen 	switch (huclk_sel) {
44127881d20Sryan_chen 	case 0:
44227881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu) / 4;
44327881d20Sryan_chen 		break;
44427881d20Sryan_chen 	case 1:
44527881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu) / 2;
44627881d20Sryan_chen 		break;
44727881d20Sryan_chen 	case 2:
44827881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu);
44927881d20Sryan_chen 		break;
45027881d20Sryan_chen 	case 3:
45127881d20Sryan_chen 		clk_in = ast2600_get_hclk(scu);
45227881d20Sryan_chen 		break;
45327881d20Sryan_chen 	}
45427881d20Sryan_chen 
45527881d20Sryan_chen 	return clk_in;
45627881d20Sryan_chen }
45727881d20Sryan_chen 
4582e195992Sryan_chen static u32 ast2600_get_uart_uxclk_rate(struct ast2600_scu *scu)
45927881d20Sryan_chen {
4602e195992Sryan_chen 	u32 clk_in = ast2600_get_uxclk_in_rate(scu);
46127881d20Sryan_chen 	u32 div_reg = readl(&scu->uart_24m_ref_uxclk);
46227881d20Sryan_chen 	unsigned int mult, div;
46327881d20Sryan_chen 
46427881d20Sryan_chen 	u32 n = (div_reg >> 8) & 0x3ff;
46527881d20Sryan_chen 	u32 r = div_reg & 0xff;
46627881d20Sryan_chen 
46727881d20Sryan_chen 	mult = r;
4682e195992Sryan_chen 	div = (n * 2);
46927881d20Sryan_chen 	return (clk_in * mult) / div;
47027881d20Sryan_chen }
47127881d20Sryan_chen 
4722e195992Sryan_chen static u32 ast2600_get_uart_huxclk_rate(struct ast2600_scu *scu)
47327881d20Sryan_chen {
4742e195992Sryan_chen 	u32 clk_in = ast2600_get_huxclk_in_rate(scu);
47527881d20Sryan_chen 	u32 div_reg = readl(&scu->uart_24m_ref_huxclk);
47627881d20Sryan_chen 
47727881d20Sryan_chen 	unsigned int mult, div;
47827881d20Sryan_chen 
47927881d20Sryan_chen 	u32 n = (div_reg >> 8) & 0x3ff;
48027881d20Sryan_chen 	u32 r = div_reg & 0xff;
48127881d20Sryan_chen 
48227881d20Sryan_chen 	mult = r;
4832e195992Sryan_chen 	div = (n * 2);
48427881d20Sryan_chen 	return (clk_in * mult) / div;
48527881d20Sryan_chen }
48627881d20Sryan_chen 
487f51926eeSryan_chen static u32 ast2600_get_sdio_clk_rate(struct ast2600_scu *scu)
488f51926eeSryan_chen {
489f51926eeSryan_chen 	u32 clkin = 0;
490f51926eeSryan_chen 	u32 clk_sel = readl(&scu->clk_sel4);
491f51926eeSryan_chen 	u32 div = (clk_sel >> 28) & 0x7;
4928004dfdeSChin-Ting Kuo 	u32 hw_rev = readl(&scu->chip_id1);
493f51926eeSryan_chen 
494ed3899c5SRyan Chen 	if (clk_sel & BIT(8))
495f51926eeSryan_chen 		clkin = ast2600_get_apll_rate(scu);
496ed3899c5SRyan Chen 	else
49710069884Sryan_chen 		clkin = ast2600_get_hclk(scu);
498ed3899c5SRyan Chen 
4998004dfdeSChin-Ting Kuo 	div = (1 + div) * 2;
5008004dfdeSChin-Ting Kuo 	if (((hw_rev & GENMASK(23, 16)) >> 16) >= 2)
5018004dfdeSChin-Ting Kuo 		div = (div & 0xf) ? div : 1;
502f51926eeSryan_chen 
503f51926eeSryan_chen 	return (clkin / div);
504f51926eeSryan_chen }
505f51926eeSryan_chen 
506f51926eeSryan_chen static u32 ast2600_get_emmc_clk_rate(struct ast2600_scu *scu)
507f51926eeSryan_chen {
508125f2e11SChin-Ting Kuo 	u32 mmc_clk_src = readl(&scu->clk_sel1);
509125f2e11SChin-Ting Kuo 	u32 clkin;
510f51926eeSryan_chen 	u32 clk_sel = readl(&scu->clk_sel1);
511f51926eeSryan_chen 	u32 div = (clk_sel >> 12) & 0x7;
512f51926eeSryan_chen 
513125f2e11SChin-Ting Kuo 	if (mmc_clk_src & BIT(11)) {
514125f2e11SChin-Ting Kuo 		/* emmc clock comes from MPLL */
515125f2e11SChin-Ting Kuo 		clkin = ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
516125f2e11SChin-Ting Kuo 		div = (div + 1) * 2;
517125f2e11SChin-Ting Kuo 	} else {
518125f2e11SChin-Ting Kuo 		clkin = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
519f51926eeSryan_chen 		div = (div + 1) << 2;
520125f2e11SChin-Ting Kuo 	}
521f51926eeSryan_chen 
522f51926eeSryan_chen 	return (clkin / div);
523f51926eeSryan_chen }
524f51926eeSryan_chen 
525f51926eeSryan_chen static u32 ast2600_get_uart_clk_rate(struct ast2600_scu *scu, int uart_idx)
52627881d20Sryan_chen {
527de49ffa7SChia-Wei Wang 	u32 hicr9 = readl(0x1e789098);
52827881d20Sryan_chen 	u32 uart_sel = readl(&scu->clk_sel4);
52927881d20Sryan_chen 	u32 uart_sel5 = readl(&scu->clk_sel5);
53027881d20Sryan_chen 	ulong uart_clk = 0;
53127881d20Sryan_chen 
53227881d20Sryan_chen 	switch (uart_idx) {
53327881d20Sryan_chen 	case 1:
53427881d20Sryan_chen 	case 2:
53527881d20Sryan_chen 	case 3:
53627881d20Sryan_chen 	case 4:
537de49ffa7SChia-Wei Wang 		hicr9 &= ~(BIT(uart_idx + 3));
538de49ffa7SChia-Wei Wang 		writel(hicr9, 0x1e789098);
53927881d20Sryan_chen 	case 6:
54027881d20Sryan_chen 		if (uart_sel & BIT(uart_idx - 1))
5412e195992Sryan_chen 			uart_clk = ast2600_get_uart_huxclk_rate(scu);
542550e691bSryan_chen 		else
5432e195992Sryan_chen 			uart_clk = ast2600_get_uart_uxclk_rate(scu);
54427881d20Sryan_chen 		break;
54527881d20Sryan_chen 	case 5: //24mhz is come form usb phy 48Mhz
54627881d20Sryan_chen 	{
54727881d20Sryan_chen 		u8 uart5_clk_sel = 0;
54827881d20Sryan_chen 		//high bit
54927881d20Sryan_chen 		if (readl(&scu->misc_ctrl1) & BIT(12))
55027881d20Sryan_chen 			uart5_clk_sel = 0x2;
55127881d20Sryan_chen 		else
55227881d20Sryan_chen 			uart5_clk_sel = 0x0;
553550e691bSryan_chen 
55427881d20Sryan_chen 		if (readl(&scu->clk_sel2) & BIT(14))
55527881d20Sryan_chen 			uart5_clk_sel |= 0x1;
556550e691bSryan_chen 
55727881d20Sryan_chen 		switch (uart5_clk_sel) {
55827881d20Sryan_chen 		case 0:
55927881d20Sryan_chen 			uart_clk = 24000000;
56027881d20Sryan_chen 			break;
56127881d20Sryan_chen 		case 1:
562def99fcbSryan_chen 			uart_clk = 192000000;
56327881d20Sryan_chen 			break;
56427881d20Sryan_chen 		case 2:
56527881d20Sryan_chen 			uart_clk = 24000000 / 13;
56627881d20Sryan_chen 			break;
56727881d20Sryan_chen 		case 3:
56827881d20Sryan_chen 			uart_clk = 192000000 / 13;
56927881d20Sryan_chen 			break;
57027881d20Sryan_chen 		}
5715d05f4fcSRyan Chen 	} break;
57227881d20Sryan_chen 	case 7:
57327881d20Sryan_chen 	case 8:
57427881d20Sryan_chen 	case 9:
57527881d20Sryan_chen 	case 10:
57627881d20Sryan_chen 	case 11:
57727881d20Sryan_chen 	case 12:
57827881d20Sryan_chen 	case 13:
57927881d20Sryan_chen 		if (uart_sel5 & BIT(uart_idx - 1))
5802e195992Sryan_chen 			uart_clk = ast2600_get_uart_huxclk_rate(scu);
58127881d20Sryan_chen 		else
5822e195992Sryan_chen 			uart_clk = ast2600_get_uart_uxclk_rate(scu);
58327881d20Sryan_chen 		break;
58427881d20Sryan_chen 	}
58527881d20Sryan_chen 
58627881d20Sryan_chen 	return uart_clk;
587550e691bSryan_chen }
588550e691bSryan_chen 
589feb42054Sryan_chen static ulong ast2600_clk_get_rate(struct clk *clk)
590feb42054Sryan_chen {
591feb42054Sryan_chen 	struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
592feb42054Sryan_chen 	ulong rate = 0;
593feb42054Sryan_chen 
594feb42054Sryan_chen 	switch (clk->id) {
595feb42054Sryan_chen 	case ASPEED_CLK_HPLL:
596bbbfb0c5Sryan_chen 	case ASPEED_CLK_EPLL:
597bbbfb0c5Sryan_chen 	case ASPEED_CLK_DPLL:
598d812df15Sryan_chen 	case ASPEED_CLK_MPLL:
599bbbfb0c5Sryan_chen 		rate = ast2600_get_pll_rate(priv->scu, clk->id);
600d812df15Sryan_chen 		break;
601feb42054Sryan_chen 	case ASPEED_CLK_AHB:
602feb42054Sryan_chen 		rate = ast2600_get_hclk(priv->scu);
603feb42054Sryan_chen 		break;
6046fa1ef3dSryan_chen 	case ASPEED_CLK_APB1:
6056fa1ef3dSryan_chen 		rate = ast2600_get_pclk1(priv->scu);
6066fa1ef3dSryan_chen 		break;
6076fa1ef3dSryan_chen 	case ASPEED_CLK_APB2:
6086fa1ef3dSryan_chen 		rate = ast2600_get_pclk2(priv->scu);
609feb42054Sryan_chen 		break;
610bbbfb0c5Sryan_chen 	case ASPEED_CLK_APLL:
611bbbfb0c5Sryan_chen 		rate = ast2600_get_apll_rate(priv->scu);
612bbbfb0c5Sryan_chen 		break;
613feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART1CLK:
614feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 1);
615feb42054Sryan_chen 		break;
616feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART2CLK:
617feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 2);
618feb42054Sryan_chen 		break;
619feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART3CLK:
620feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 3);
621feb42054Sryan_chen 		break;
622feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART4CLK:
623feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 4);
624feb42054Sryan_chen 		break;
625feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART5CLK:
626feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 5);
627feb42054Sryan_chen 		break;
628c304f173Sryan_chen 	case ASPEED_CLK_BCLK:
629c304f173Sryan_chen 		rate = ast2600_get_bclk_rate(priv->scu);
630c304f173Sryan_chen 		break;
631f51926eeSryan_chen 	case ASPEED_CLK_SDIO:
632f51926eeSryan_chen 		rate = ast2600_get_sdio_clk_rate(priv->scu);
633f51926eeSryan_chen 		break;
634f51926eeSryan_chen 	case ASPEED_CLK_EMMC:
635f51926eeSryan_chen 		rate = ast2600_get_emmc_clk_rate(priv->scu);
636f51926eeSryan_chen 		break;
6372e195992Sryan_chen 	case ASPEED_CLK_UARTX:
6382e195992Sryan_chen 		rate = ast2600_get_uart_uxclk_rate(priv->scu);
6392e195992Sryan_chen 		break;
6400998ddefSryan_chen 	case ASPEED_CLK_HUARTX:
6412e195992Sryan_chen 		rate = ast2600_get_uart_huxclk_rate(priv->scu);
6422e195992Sryan_chen 		break;
643feb42054Sryan_chen 	default:
644d812df15Sryan_chen 		pr_debug("can't get clk rate\n");
645feb42054Sryan_chen 		return -ENOENT;
646feb42054Sryan_chen 	}
647feb42054Sryan_chen 
648feb42054Sryan_chen 	return rate;
649feb42054Sryan_chen }
650feb42054Sryan_chen 
651577fcdaeSDylan Hung /**
652577fcdaeSDylan Hung  * @brief	lookup PLL divider config by input/output rate
653577fcdaeSDylan Hung  * @param[in]	*pll - PLL descriptor
654577fcdaeSDylan Hung  * @return	true - if PLL divider config is found, false - else
655a8fc7648SRyan Chen  * The function caller shall fill "pll->in" and "pll->out",
656a8fc7648SRyan Chen  * then this function will search the lookup table
657a8fc7648SRyan Chen  * to find a valid PLL divider configuration.
658550e691bSryan_chen  */
659577fcdaeSDylan Hung static bool ast2600_search_clock_config(struct ast2600_pll_desc *pll)
660550e691bSryan_chen {
661577fcdaeSDylan Hung 	u32 i;
662577fcdaeSDylan Hung 	bool is_found = false;
663550e691bSryan_chen 
664577fcdaeSDylan Hung 	for (i = 0; i < ARRAY_SIZE(ast2600_pll_lookup); i++) {
665577fcdaeSDylan Hung 		const struct ast2600_pll_desc *def_cfg = &ast2600_pll_lookup[i];
666ed3899c5SRyan Chen 
667ed3899c5SRyan Chen 		if (def_cfg->in == pll->in && def_cfg->out == pll->out) {
668577fcdaeSDylan Hung 			is_found = true;
669577fcdaeSDylan Hung 			pll->cfg.reg.w = def_cfg->cfg.reg.w;
670577fcdaeSDylan Hung 			pll->cfg.ext_reg = def_cfg->cfg.ext_reg;
671577fcdaeSDylan Hung 			break;
672550e691bSryan_chen 		}
673550e691bSryan_chen 	}
674577fcdaeSDylan Hung 	return is_found;
675550e691bSryan_chen }
676ed3899c5SRyan Chen 
677fd52be0bSDylan Hung static u32 ast2600_configure_pll(struct ast2600_scu *scu,
678fd52be0bSDylan Hung 				 struct ast2600_pll_cfg *p_cfg, int pll_idx)
679fd52be0bSDylan Hung {
680fd52be0bSDylan Hung 	u32 addr, addr_ext;
681fd52be0bSDylan Hung 	u32 reg;
682550e691bSryan_chen 
683fd52be0bSDylan Hung 	switch (pll_idx) {
684fd52be0bSDylan Hung 	case ASPEED_CLK_HPLL:
685fd52be0bSDylan Hung 		addr = (u32)(&scu->h_pll_param);
686fd52be0bSDylan Hung 		addr_ext = (u32)(&scu->h_pll_ext_param);
687fd52be0bSDylan Hung 		break;
688fd52be0bSDylan Hung 	case ASPEED_CLK_MPLL:
689fd52be0bSDylan Hung 		addr = (u32)(&scu->m_pll_param);
690fd52be0bSDylan Hung 		addr_ext = (u32)(&scu->m_pll_ext_param);
691fd52be0bSDylan Hung 		break;
692fd52be0bSDylan Hung 	case ASPEED_CLK_DPLL:
693fd52be0bSDylan Hung 		addr = (u32)(&scu->d_pll_param);
694fd52be0bSDylan Hung 		addr_ext = (u32)(&scu->d_pll_ext_param);
695fd52be0bSDylan Hung 		break;
696fd52be0bSDylan Hung 	case ASPEED_CLK_EPLL:
697fd52be0bSDylan Hung 		addr = (u32)(&scu->e_pll_param);
698fd52be0bSDylan Hung 		addr_ext = (u32)(&scu->e_pll_ext_param);
699fd52be0bSDylan Hung 		break;
700fd52be0bSDylan Hung 	default:
701fd52be0bSDylan Hung 		debug("unknown PLL index\n");
702fd52be0bSDylan Hung 		return 1;
703fd52be0bSDylan Hung 	}
704fd52be0bSDylan Hung 
705fd52be0bSDylan Hung 	p_cfg->reg.b.bypass = 0;
706fd52be0bSDylan Hung 	p_cfg->reg.b.off = 1;
707fd52be0bSDylan Hung 	p_cfg->reg.b.reset = 1;
708fd52be0bSDylan Hung 
709fd52be0bSDylan Hung 	reg = readl(addr);
710fd52be0bSDylan Hung 	reg &= ~GENMASK(25, 0);
711fd52be0bSDylan Hung 	reg |= p_cfg->reg.w;
712fd52be0bSDylan Hung 	writel(reg, addr);
713fd52be0bSDylan Hung 
714fd52be0bSDylan Hung 	/* write extend parameter */
715fd52be0bSDylan Hung 	writel(p_cfg->ext_reg, addr_ext);
716fd52be0bSDylan Hung 	udelay(100);
717fd52be0bSDylan Hung 	p_cfg->reg.b.off = 0;
718fd52be0bSDylan Hung 	p_cfg->reg.b.reset = 0;
719fd52be0bSDylan Hung 	reg &= ~GENMASK(25, 0);
720fd52be0bSDylan Hung 	reg |= p_cfg->reg.w;
721fd52be0bSDylan Hung 	writel(reg, addr);
722ed3899c5SRyan Chen 	while (!(readl(addr_ext) & BIT(31)))
723ed3899c5SRyan Chen 		;
724fd52be0bSDylan Hung 
725fd52be0bSDylan Hung 	return 0;
726fd52be0bSDylan Hung }
727ed3899c5SRyan Chen 
728feb42054Sryan_chen static u32 ast2600_configure_ddr(struct ast2600_scu *scu, ulong rate)
729550e691bSryan_chen {
730577fcdaeSDylan Hung 	struct ast2600_pll_desc mpll;
731550e691bSryan_chen 
732577fcdaeSDylan Hung 	mpll.in = AST2600_CLK_IN;
733577fcdaeSDylan Hung 	mpll.out = rate;
734f27685ebSRyan Chen 	if (ast2600_search_clock_config(&mpll) == false) {
735577fcdaeSDylan Hung 		printf("error!! unable to find valid DDR clock setting\n");
736577fcdaeSDylan Hung 		return 0;
737577fcdaeSDylan Hung 	}
738ed3899c5SRyan Chen 	ast2600_configure_pll(scu, &mpll.cfg, ASPEED_CLK_MPLL);
739577fcdaeSDylan Hung 
740cc476ffcSDylan Hung 	return ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
741d6e349c7Sryan_chen }
742d6e349c7Sryan_chen 
743d6e349c7Sryan_chen static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate)
744550e691bSryan_chen {
745f0d895afSryan_chen 	struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
746550e691bSryan_chen 	ulong new_rate;
747ed3899c5SRyan Chen 
748550e691bSryan_chen 	switch (clk->id) {
749f0d895afSryan_chen 	case ASPEED_CLK_MPLL:
750feb42054Sryan_chen 		new_rate = ast2600_configure_ddr(priv->scu, rate);
751550e691bSryan_chen 		break;
752550e691bSryan_chen 	default:
753550e691bSryan_chen 		return -ENOENT;
754550e691bSryan_chen 	}
755550e691bSryan_chen 
756550e691bSryan_chen 	return new_rate;
757550e691bSryan_chen }
758feb42054Sryan_chen 
759*e95b19f8SDylan Hung static int ast2600_calc_dly32_time(struct ast2600_scu *scu, int die_id, int stage)
760cc476ffcSDylan Hung {
761*e95b19f8SDylan Hung 	int ret, i;
762*e95b19f8SDylan Hung 	u64 sum = 0;
763*e95b19f8SDylan Hung 	u32 base, value, reset_sel, dly32_sel;
764*e95b19f8SDylan Hung 
765*e95b19f8SDylan Hung 	if (die_id) {
766*e95b19f8SDylan Hung 		base = (u32)&scu->freq_counter_ctrl2;
767*e95b19f8SDylan Hung 		reset_sel = FREQC_CTRL_SRC_SEL_HCLK_DIE1;
768*e95b19f8SDylan Hung 		dly32_sel = FREQC_CTRL_SRC_SEL_DLY32_DIE1;
769*e95b19f8SDylan Hung 	} else {
770*e95b19f8SDylan Hung 		base = (u32)&scu->freq_counter_ctrl1;
771*e95b19f8SDylan Hung 		reset_sel = FREQC_CTRL_SRC_SEL_HCLK_DIE0;
772*e95b19f8SDylan Hung 		dly32_sel = FREQC_CTRL_SRC_SEL_DLY32_DIE0;
773*e95b19f8SDylan Hung 	}
774*e95b19f8SDylan Hung 
775*e95b19f8SDylan Hung 	for (i = 0; i < DLY32_AVERAGE_COUNT; i++) {
776*e95b19f8SDylan Hung 		/* reset frequency-counter */
777*e95b19f8SDylan Hung 		writel(FIELD_PREP(FREQC_CTRL_SRC_SEL, reset_sel), base);
778*e95b19f8SDylan Hung 		ret = readl_poll_timeout(base, value, !(value & FREQC_CTRL_RESULT), 1000);
779*e95b19f8SDylan Hung 		if (ret)
780*e95b19f8SDylan Hung 			return -1;
781*e95b19f8SDylan Hung 
782*e95b19f8SDylan Hung 		/* start frequency counter */
783*e95b19f8SDylan Hung 		value = FIELD_PREP(FREQC_CTRL_RING_STAGE, stage)
784*e95b19f8SDylan Hung 		      | FIELD_PREP(FREQC_CTRL_SRC_SEL, dly32_sel)
785*e95b19f8SDylan Hung 		      | FIELD_PREP(FREQC_CTRL_RING_CTRL, FREQC_CTRL_RING_EN);
786*e95b19f8SDylan Hung 		writel(value, base);
787*e95b19f8SDylan Hung 
788*e95b19f8SDylan Hung 		/* delay for a while for settling down */
789*e95b19f8SDylan Hung 		udelay(100);
790*e95b19f8SDylan Hung 
791*e95b19f8SDylan Hung 		/* enable osc for measurement */
792*e95b19f8SDylan Hung 		value |= FIELD_PREP(FREQC_CTRL_OSC_CTRL, FREQC_CTRL_OSC_EN);
793*e95b19f8SDylan Hung 		writel(value, base);
794*e95b19f8SDylan Hung 		ret = readl_poll_timeout(base, value, value & FREQC_CTRL_STATUS, 1000);
795*e95b19f8SDylan Hung 		if (ret)
796*e95b19f8SDylan Hung 			return -1;
797*e95b19f8SDylan Hung 
798*e95b19f8SDylan Hung 		/* the result is represented in T count, will translate to pico-second later */
799*e95b19f8SDylan Hung 		sum += FIELD_GET(FREQC_CTRL_RESULT, value);
800*e95b19f8SDylan Hung 	}
801*e95b19f8SDylan Hung 
802*e95b19f8SDylan Hung 	/* return the DLY32 value in pico-second */
803*e95b19f8SDylan Hung 	return (2560000 / (int)(sum >> DLY32_AVERAGE_COUNT_LOG2));
804*e95b19f8SDylan Hung }
805*e95b19f8SDylan Hung 
806*e95b19f8SDylan Hung static void ast2600_init_dly32_lookup(struct ast2600_clk_priv *priv)
807*e95b19f8SDylan Hung {
808*e95b19f8SDylan Hung 	struct ast2600_scu *scu = priv->scu;
809*e95b19f8SDylan Hung 	int i;
810*e95b19f8SDylan Hung 
811*e95b19f8SDylan Hung 	for (i = 0; i < DLY32_NUM_OF_TAPS; i++) {
812*e95b19f8SDylan Hung 		priv->dly32_lookup[0][i] = ast2600_calc_dly32_time(scu, 0, i);
813*e95b19f8SDylan Hung 		priv->dly32_lookup[1][i] = ast2600_calc_dly32_time(scu, 1, i);
814*e95b19f8SDylan Hung 	}
815*e95b19f8SDylan Hung 
816*e95b19f8SDylan Hung #ifdef DEBUG
817*e95b19f8SDylan Hung 	for (i = 0; i < DLY32_NUM_OF_TAPS; i++)
818*e95b19f8SDylan Hung 		printf("28nm DLY32[%d] = %d ps\n", i, priv->dly32_lookup[0][i]);
819*e95b19f8SDylan Hung 
820*e95b19f8SDylan Hung 	for (i = 0; i < DLY32_NUM_OF_TAPS; i++)
821*e95b19f8SDylan Hung 		printf("55nm DLY32[%d] = %d ps\n", i, priv->dly32_lookup[1][i]);
822*e95b19f8SDylan Hung #endif
823*e95b19f8SDylan Hung }
824*e95b19f8SDylan Hung 
825*e95b19f8SDylan Hung /**
826*e95b19f8SDylan Hung  * @brief find the DLY32 tap number fitting the target delay time
827*e95b19f8SDylan Hung  *
828*e95b19f8SDylan Hung  * @param target_pico_sec target delay time in pico-second
829*e95b19f8SDylan Hung  * @param lookup DLY32 lookup table
830*e95b19f8SDylan Hung  * @return int DLY32 tap number
831*e95b19f8SDylan Hung  */
832*e95b19f8SDylan Hung static int ast2600_find_dly32_tap(int target_pico_sec, int *lookup)
833*e95b19f8SDylan Hung {
834*e95b19f8SDylan Hung 	int tap = DLY32_NUM_OF_TAPS >> 1;
835*e95b19f8SDylan Hung 	int lower = 0;
836*e95b19f8SDylan Hung 	int upper = DLY32_NUM_OF_TAPS - 1;
837*e95b19f8SDylan Hung 
838*e95b19f8SDylan Hung 	/* binary search for the proper delay tap */
839*e95b19f8SDylan Hung 	for (;;) {
840*e95b19f8SDylan Hung 		if (tap == 0 || tap == DLY32_NUM_OF_TAPS - 1)
841*e95b19f8SDylan Hung 			return -1;
842*e95b19f8SDylan Hung 
843*e95b19f8SDylan Hung 		if (lookup[tap] >= target_pico_sec && lookup[tap - 1] < target_pico_sec) {
844*e95b19f8SDylan Hung 			return tap;
845*e95b19f8SDylan Hung 		} else if (lookup[tap] > target_pico_sec) {
846*e95b19f8SDylan Hung 			upper = tap;
847*e95b19f8SDylan Hung 			tap = (tap + lower) >> 1;
848*e95b19f8SDylan Hung 		} else if (lookup[tap] < target_pico_sec) {
849*e95b19f8SDylan Hung 			lower = tap;
850*e95b19f8SDylan Hung 			tap = (tap + upper) >> 1;
851*e95b19f8SDylan Hung 		}
852*e95b19f8SDylan Hung 	}
853*e95b19f8SDylan Hung }
854*e95b19f8SDylan Hung 
855*e95b19f8SDylan Hung static u32 ast2600_configure_mac12_clk(struct ast2600_clk_priv *priv, struct udevice *dev)
856*e95b19f8SDylan Hung {
857*e95b19f8SDylan Hung 	struct ast2600_scu *scu = priv->scu;
858a98c71fbSDylan Hung 	struct mac_delay_config mac1_cfg, mac2_cfg;
859e40a4e44SDylan Hung 	u32 reg[3];
860a98c71fbSDylan Hung 	int ret;
8614760b3f8SDylan Hung 
862e40a4e44SDylan Hung 	reg[0] = MAC_DEF_DELAY_1G;
863e40a4e44SDylan Hung 	reg[1] = MAC_DEF_DELAY_100M;
864e40a4e44SDylan Hung 	reg[2] = MAC_DEF_DELAY_10M;
865a98c71fbSDylan Hung 
866*e95b19f8SDylan Hung 	ret = ast2600_find_dly32_tap(RGMII12_CLK_OUTPUT_DELAY_PS, priv->dly32_lookup[0]);
867*e95b19f8SDylan Hung 	if (ret > 0) {
868*e95b19f8SDylan Hung 		debug("suggested tx delay for mac1/2: %d\n", ret);
869*e95b19f8SDylan Hung 
870*e95b19f8SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_OUTPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_2);
871*e95b19f8SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, ret) |
872*e95b19f8SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, ret);
873*e95b19f8SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_OUTPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
874*e95b19f8SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, ret) |
875*e95b19f8SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, ret);
876*e95b19f8SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_OUTPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
877*e95b19f8SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, ret) |
878*e95b19f8SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, ret);
879*e95b19f8SDylan Hung 	}
880e40a4e44SDylan Hung 	ret = dev_read_u32_array(dev, "mac0-clk-delay", (u32 *)&mac1_cfg,
881e40a4e44SDylan Hung 				 sizeof(mac1_cfg) / sizeof(u32));
882a98c71fbSDylan Hung 	if (!ret) {
883e40a4e44SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_1);
884e40a4e44SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, mac1_cfg.rx_delay_1000) |
885e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, mac1_cfg.tx_delay_1000);
886e40a4e44SDylan Hung 
887e40a4e44SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
888e40a4e44SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac1_cfg.rx_delay_100) |
889e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac1_cfg.tx_delay_100);
890e40a4e44SDylan Hung 
891e40a4e44SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
892e40a4e44SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac1_cfg.rx_delay_10) |
893e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac1_cfg.tx_delay_10);
894a98c71fbSDylan Hung 	}
895a98c71fbSDylan Hung 
896e40a4e44SDylan Hung 	ret = dev_read_u32_array(dev, "mac1-clk-delay", (u32 *)&mac2_cfg,
897e40a4e44SDylan Hung 				 sizeof(mac2_cfg) / sizeof(u32));
898a98c71fbSDylan Hung 	if (!ret) {
899e40a4e44SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_2 | MAC_CLK_1G_OUTPUT_DELAY_2);
900e40a4e44SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, mac2_cfg.rx_delay_1000) |
901e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, mac2_cfg.tx_delay_1000);
902e40a4e44SDylan Hung 
903e40a4e44SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
904e40a4e44SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac2_cfg.rx_delay_100) |
905e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac2_cfg.tx_delay_100);
906e40a4e44SDylan Hung 
907e40a4e44SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
908e40a4e44SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac2_cfg.rx_delay_10) |
909e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac2_cfg.tx_delay_10);
910a98c71fbSDylan Hung 	}
911a98c71fbSDylan Hung 
912e40a4e44SDylan Hung 	reg[0] |= (readl(&scu->mac12_clk_delay) & ~GENMASK(25, 0));
913e40a4e44SDylan Hung 	writel(reg[0], &scu->mac12_clk_delay);
914e40a4e44SDylan Hung 	writel(reg[1], &scu->mac12_clk_delay_100M);
915e40a4e44SDylan Hung 	writel(reg[2], &scu->mac12_clk_delay_10M);
916cc476ffcSDylan Hung 
917ed30249cSDylan Hung 	/* MAC AHB = HPLL / 6 */
918eff28274SJohnny Huang 	clrsetbits_le32(&scu->clk_sel1, GENMASK(18, 16), (0x2 << 16));
919894c19cfSDylan Hung 
920cc476ffcSDylan Hung 	return 0;
921cc476ffcSDylan Hung }
922cc476ffcSDylan Hung 
923*e95b19f8SDylan Hung static u32 ast2600_configure_mac34_clk(struct ast2600_clk_priv *priv, struct udevice *dev)
92454f9cba1SDylan Hung {
925*e95b19f8SDylan Hung 	struct ast2600_scu *scu = priv->scu;
926a98c71fbSDylan Hung 	struct mac_delay_config mac3_cfg, mac4_cfg;
927e40a4e44SDylan Hung 	u32 reg[3];
928a98c71fbSDylan Hung 	int ret;
929a98c71fbSDylan Hung 
930e40a4e44SDylan Hung 	reg[0] = MAC34_DEF_DELAY_1G;
931e40a4e44SDylan Hung 	reg[1] = MAC34_DEF_DELAY_100M;
932e40a4e44SDylan Hung 	reg[2] = MAC34_DEF_DELAY_10M;
933a98c71fbSDylan Hung 
934*e95b19f8SDylan Hung 	ret = ast2600_find_dly32_tap(RGMII34_CLK_OUTPUT_DELAY_PS, priv->dly32_lookup[1]);
935*e95b19f8SDylan Hung 	if (ret > 0) {
936*e95b19f8SDylan Hung 		debug("suggested tx delay for mac3/4: %d\n", ret);
937*e95b19f8SDylan Hung 
938*e95b19f8SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_OUTPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_2);
939*e95b19f8SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, ret) |
940*e95b19f8SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, ret);
941*e95b19f8SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_OUTPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
942*e95b19f8SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, ret) |
943*e95b19f8SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, ret);
944*e95b19f8SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_OUTPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
945*e95b19f8SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, ret) |
946*e95b19f8SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, ret);
947*e95b19f8SDylan Hung 	}
948*e95b19f8SDylan Hung 
949a98c71fbSDylan Hung 	ret = dev_read_u32_array(dev, "mac2-clk-delay", (u32 *)&mac3_cfg, sizeof(mac3_cfg) / sizeof(u32));
950a98c71fbSDylan Hung 	if (!ret) {
951e40a4e44SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_1);
952e40a4e44SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, mac3_cfg.rx_delay_1000) |
953e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, mac3_cfg.tx_delay_1000);
954e40a4e44SDylan Hung 
955e40a4e44SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
956e40a4e44SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac3_cfg.rx_delay_100) |
957e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac3_cfg.tx_delay_100);
958e40a4e44SDylan Hung 
959e40a4e44SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
960e40a4e44SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac3_cfg.rx_delay_10) |
961e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac3_cfg.tx_delay_10);
962a98c71fbSDylan Hung 	}
963a98c71fbSDylan Hung 
964a98c71fbSDylan Hung 	ret = dev_read_u32_array(dev, "mac3-clk-delay", (u32 *)&mac4_cfg, sizeof(mac4_cfg) / sizeof(u32));
965a98c71fbSDylan Hung 	if (!ret) {
966e40a4e44SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_2 | MAC_CLK_1G_OUTPUT_DELAY_2);
967e40a4e44SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, mac4_cfg.rx_delay_1000) |
968e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, mac4_cfg.tx_delay_1000);
969e40a4e44SDylan Hung 
970e40a4e44SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
971e40a4e44SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac4_cfg.rx_delay_100) |
972e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac4_cfg.tx_delay_100);
973e40a4e44SDylan Hung 
974e40a4e44SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
975e40a4e44SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac4_cfg.rx_delay_10) |
976e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac4_cfg.tx_delay_10);
977a98c71fbSDylan Hung 	}
978a98c71fbSDylan Hung 
979e40a4e44SDylan Hung 	reg[0] |= (readl(&scu->mac34_clk_delay) & ~GENMASK(25, 0));
980e40a4e44SDylan Hung 	reg[0] &= ~MAC_CLK_RGMII_125M_SRC_SEL;
981e40a4e44SDylan Hung 	reg[0] |= FIELD_PREP(MAC_CLK_RGMII_125M_SRC_SEL, MAC_CLK_RGMII_125M_SRC_PAD_RGMIICK);
982e40a4e44SDylan Hung 	writel(reg[0], &scu->mac34_clk_delay);
983e40a4e44SDylan Hung 	writel(reg[1], &scu->mac34_clk_delay_100M);
984e40a4e44SDylan Hung 	writel(reg[2], &scu->mac34_clk_delay_10M);
98554f9cba1SDylan Hung 
986eff28274SJohnny Huang 	/*
987eff28274SJohnny Huang 	 * clock source seletion and divider
988eff28274SJohnny Huang 	 * scu310[26:24] : MAC AHB bus clock = HCLK / 2
989eff28274SJohnny Huang 	 * scu310[18:16] : RMII 50M = HCLK_200M / 4
990eff28274SJohnny Huang 	 */
991eff28274SJohnny Huang 	clrsetbits_le32(&scu->clk_sel4, (GENMASK(26, 24) | GENMASK(18, 16)),
992eff28274SJohnny Huang 			((0x0 << 24) | (0x3 << 16)));
99354f9cba1SDylan Hung 
994eff28274SJohnny Huang 	/*
995eff28274SJohnny Huang 	 * set driving strength
996eff28274SJohnny Huang 	 * scu458[3:2] : MAC4 driving strength
997eff28274SJohnny Huang 	 * scu458[1:0] : MAC3 driving strength
998eff28274SJohnny Huang 	 */
999eff28274SJohnny Huang 	clrsetbits_le32(&scu->pinmux_ctrl16, GENMASK(3, 0),
1000a961159eSDylan Hung 			(0x3 << 2) | (0x3 << 0));
100154f9cba1SDylan Hung 
100254f9cba1SDylan Hung 	return 0;
100354f9cba1SDylan Hung }
1004eff28274SJohnny Huang 
100554f9cba1SDylan Hung /**
10065b5c3d44SDylan Hung  * ast2600 RGMII clock source tree
100754f9cba1SDylan Hung  * 125M from external PAD -------->|\
100854f9cba1SDylan Hung  * HPLL -->|\                      | |---->RGMII 125M for MAC#1 & MAC#2
100954f9cba1SDylan Hung  *         | |---->| divider |---->|/                             +
101054f9cba1SDylan Hung  * EPLL -->|/                                                     |
101154f9cba1SDylan Hung  *                                                                |
1012eff28274SJohnny Huang  * +---------<-----------|RGMIICK PAD output enable|<-------------+
101354f9cba1SDylan Hung  * |
1014eff28274SJohnny Huang  * +--------------------------->|\
101554f9cba1SDylan Hung  *                              | |----> RGMII 125M for MAC#3 & MAC#4
1016eff28274SJohnny Huang  * HCLK 200M ---->|divider|---->|/
1017eff28274SJohnny Huang  * To simplify the control flow:
1018eff28274SJohnny Huang  * 1. RGMII 1/2 always use EPLL as the internal clock source
1019eff28274SJohnny Huang  * 2. RGMII 3/4 always use RGMIICK pad as the RGMII 125M source
1020eff28274SJohnny Huang  * 125M from external PAD -------->|\
1021eff28274SJohnny Huang  *                                 | |---->RGMII 125M for MAC#1 & MAC#2
1022eff28274SJohnny Huang  *         EPLL---->| divider |--->|/                             +
1023eff28274SJohnny Huang  *                                                                |
1024eff28274SJohnny Huang  * +<--------------------|RGMIICK PAD output enable|<-------------+
1025eff28274SJohnny Huang  * |
1026eff28274SJohnny Huang  * +--------------------------->RGMII 125M for MAC#3 & MAC#4
1027eff28274SJohnny Huang  */
1028eff28274SJohnny Huang #define RGMIICK_SRC_PAD		0
1029eff28274SJohnny Huang #define RGMIICK_SRC_EPLL	1 /* recommended */
1030eff28274SJohnny Huang #define RGMIICK_SRC_HPLL	2
1031eff28274SJohnny Huang 
1032eff28274SJohnny Huang #define RGMIICK_DIV2	1
1033eff28274SJohnny Huang #define RGMIICK_DIV3	2
1034eff28274SJohnny Huang #define RGMIICK_DIV4	3
1035eff28274SJohnny Huang #define RGMIICK_DIV5	4
1036eff28274SJohnny Huang #define RGMIICK_DIV6	5
1037eff28274SJohnny Huang #define RGMIICK_DIV7	6
1038eff28274SJohnny Huang #define RGMIICK_DIV8	7 /* recommended */
1039eff28274SJohnny Huang 
1040eff28274SJohnny Huang #define RMIICK_DIV4		0
1041eff28274SJohnny Huang #define RMIICK_DIV8		1
1042eff28274SJohnny Huang #define RMIICK_DIV12	2
1043eff28274SJohnny Huang #define RMIICK_DIV16	3
1044eff28274SJohnny Huang #define RMIICK_DIV20	4 /* recommended */
1045eff28274SJohnny Huang #define RMIICK_DIV24	5
1046eff28274SJohnny Huang #define RMIICK_DIV28	6
1047eff28274SJohnny Huang #define RMIICK_DIV32	7
1048eff28274SJohnny Huang 
1049eff28274SJohnny Huang struct ast2600_mac_clk_div {
1050eff28274SJohnny Huang 	u32 src; /* 0=external PAD, 1=internal PLL */
1051eff28274SJohnny Huang 	u32 fin; /* divider input speed */
1052eff28274SJohnny Huang 	u32 n; /* 0=div2, 1=div2, 2=div3, 3=div4,...,7=div8 */
1053eff28274SJohnny Huang 	u32 fout; /* fout = fin / n */
1054eff28274SJohnny Huang };
1055eff28274SJohnny Huang 
1056eff28274SJohnny Huang struct ast2600_mac_clk_div rgmii_clk_defconfig = {
1057eff28274SJohnny Huang 	.src = ASPEED_CLK_EPLL,
1058eff28274SJohnny Huang 	.fin = 1000000000,
1059eff28274SJohnny Huang 	.n = RGMIICK_DIV8,
1060eff28274SJohnny Huang 	.fout = 125000000,
1061eff28274SJohnny Huang };
1062eff28274SJohnny Huang 
1063eff28274SJohnny Huang struct ast2600_mac_clk_div rmii_clk_defconfig = {
1064eff28274SJohnny Huang 	.src = ASPEED_CLK_EPLL,
1065eff28274SJohnny Huang 	.fin = 1000000000,
1066eff28274SJohnny Huang 	.n = RMIICK_DIV20,
1067eff28274SJohnny Huang 	.fout = 50000000,
1068eff28274SJohnny Huang };
1069ed3899c5SRyan Chen 
1070eff28274SJohnny Huang static void ast2600_init_mac_pll(struct ast2600_scu *p_scu,
1071eff28274SJohnny Huang 				 struct ast2600_mac_clk_div *p_cfg)
1072eff28274SJohnny Huang {
1073eff28274SJohnny Huang 	struct ast2600_pll_desc pll;
1074eff28274SJohnny Huang 
1075eff28274SJohnny Huang 	pll.in = AST2600_CLK_IN;
1076eff28274SJohnny Huang 	pll.out = p_cfg->fin;
1077ed3899c5SRyan Chen 	if (ast2600_search_clock_config(&pll) == false) {
1078ed3899c5SRyan Chen 		pr_err("unable to find valid ETHNET MAC clock setting\n");
10793f295164SRyan Chen 		debug("%s: pll cfg = 0x%08x 0x%08x\n", __func__, pll.cfg.reg.w,
10803f295164SRyan Chen 		      pll.cfg.ext_reg);
10813f295164SRyan Chen 		debug("%s: pll cfg = %02x %02x %02x\n", __func__,
10823f295164SRyan Chen 		      pll.cfg.reg.b.m, pll.cfg.reg.b.n, pll.cfg.reg.b.p);
1083eff28274SJohnny Huang 		return;
1084eff28274SJohnny Huang 	}
1085ed3899c5SRyan Chen 	ast2600_configure_pll(p_scu, &pll.cfg, p_cfg->src);
1086eff28274SJohnny Huang }
1087eff28274SJohnny Huang 
1088eff28274SJohnny Huang static void ast2600_init_rgmii_clk(struct ast2600_scu *p_scu,
1089eff28274SJohnny Huang 				   struct ast2600_mac_clk_div *p_cfg)
1090eff28274SJohnny Huang {
1091eff28274SJohnny Huang 	u32 reg_304 = readl(&p_scu->clk_sel2);
1092eff28274SJohnny Huang 	u32 reg_340 = readl(&p_scu->mac12_clk_delay);
1093eff28274SJohnny Huang 	u32 reg_350 = readl(&p_scu->mac34_clk_delay);
1094eff28274SJohnny Huang 
1095e40a4e44SDylan Hung 	reg_340 &= ~(MAC_CLK_RGMII_125M_SRC_SEL | MAC_CLK_RMII2_50M_RCLK_O_CTRL |
1096e40a4e44SDylan Hung 		     MAC_CLK_RMII1_50M_RCLK_O_CTRL | MAC_CLK_RGMIICK_PAD_DIR);
1097e40a4e44SDylan Hung 	/* RGMIICK PAD output enable (to MAC 3/4) */
1098e40a4e44SDylan Hung 	reg_340 |= FIELD_PREP(MAC_CLK_RGMIICK_PAD_DIR, MAC_CLK_RGMIICK_PAD_DIR_OUTPUT);
10993f295164SRyan Chen 	if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
1100eff28274SJohnny Huang 		/*
1101eff28274SJohnny Huang 		 * re-init PLL if the current PLL output frequency doesn't match
1102eff28274SJohnny Huang 		 * the divider setting
1103eff28274SJohnny Huang 		 */
1104ed3899c5SRyan Chen 		if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
1105eff28274SJohnny Huang 			ast2600_init_mac_pll(p_scu, p_cfg);
1106e40a4e44SDylan Hung 		/* select RGMII 125M from internal source */
1107e40a4e44SDylan Hung 		reg_340 |= FIELD_PREP(MAC_CLK_RGMII_125M_SRC_SEL, MAC_CLK_RGMII_125M_SRC_PLL);
1108eff28274SJohnny Huang 	}
1109eff28274SJohnny Huang 
1110eff28274SJohnny Huang 	reg_304 &= ~GENMASK(23, 20);
1111eff28274SJohnny Huang 
1112eff28274SJohnny Huang 	/* set clock divider */
1113eff28274SJohnny Huang 	reg_304 |= (p_cfg->n & 0x7) << 20;
1114eff28274SJohnny Huang 
1115eff28274SJohnny Huang 	/* select internal clock source */
1116ed3899c5SRyan Chen 	if (p_cfg->src == ASPEED_CLK_HPLL)
1117eff28274SJohnny Huang 		reg_304 |= BIT(23);
1118eff28274SJohnny Huang 
1119eff28274SJohnny Huang 	/* RGMII 3/4 clock source select */
1120eff28274SJohnny Huang 	reg_350 &= ~BIT(31);
1121eff28274SJohnny Huang 
1122eff28274SJohnny Huang 	writel(reg_304, &p_scu->clk_sel2);
1123eff28274SJohnny Huang 	writel(reg_340, &p_scu->mac12_clk_delay);
1124eff28274SJohnny Huang 	writel(reg_350, &p_scu->mac34_clk_delay);
1125eff28274SJohnny Huang }
1126eff28274SJohnny Huang 
1127eff28274SJohnny Huang /**
11285b5c3d44SDylan Hung  * ast2600 RMII/NCSI clock source tree
11295b5c3d44SDylan Hung  * HPLL -->|\
11305b5c3d44SDylan Hung  *         | |---->| divider |----> RMII 50M for MAC#1 & MAC#2
11315b5c3d44SDylan Hung  * EPLL -->|/
11325b5c3d44SDylan Hung  * HCLK(SCLICLK)---->| divider |----> RMII 50M for MAC#3 & MAC#4
113354f9cba1SDylan Hung  */
1134eff28274SJohnny Huang static void ast2600_init_rmii_clk(struct ast2600_scu *p_scu,
1135eff28274SJohnny Huang 				  struct ast2600_mac_clk_div *p_cfg)
113654f9cba1SDylan Hung {
1137eff28274SJohnny Huang 	u32 reg_304;
1138eff28274SJohnny Huang 	u32 reg_310;
1139eff28274SJohnny Huang 
11403f295164SRyan Chen 	if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
1141eff28274SJohnny Huang 		/*
1142eff28274SJohnny Huang 		 * re-init PLL if the current PLL output frequency doesn't match
1143eff28274SJohnny Huang 		 * the divider setting
1144eff28274SJohnny Huang 		 */
1145ed3899c5SRyan Chen 		if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
1146eff28274SJohnny Huang 			ast2600_init_mac_pll(p_scu, p_cfg);
1147eff28274SJohnny Huang 	}
114854f9cba1SDylan Hung 
1149eff28274SJohnny Huang 	reg_304 = readl(&p_scu->clk_sel2);
1150eff28274SJohnny Huang 	reg_310 = readl(&p_scu->clk_sel4);
1151eff28274SJohnny Huang 
1152eff28274SJohnny Huang 	reg_304 &= ~GENMASK(19, 16);
1153eff28274SJohnny Huang 
1154eff28274SJohnny Huang 	/* set RMII 1/2 clock divider */
1155eff28274SJohnny Huang 	reg_304 |= (p_cfg->n & 0x7) << 16;
1156eff28274SJohnny Huang 
1157eff28274SJohnny Huang 	/* RMII clock source selection */
1158ed3899c5SRyan Chen 	if (p_cfg->src == ASPEED_CLK_HPLL)
1159eff28274SJohnny Huang 		reg_304 |= BIT(19);
1160eff28274SJohnny Huang 
1161eff28274SJohnny Huang 	/* set RMII 3/4 clock divider */
1162eff28274SJohnny Huang 	reg_310 &= ~GENMASK(18, 16);
1163eff28274SJohnny Huang 	reg_310 |= (0x3 << 16);
1164eff28274SJohnny Huang 
1165eff28274SJohnny Huang 	writel(reg_304, &p_scu->clk_sel2);
1166eff28274SJohnny Huang 	writel(reg_310, &p_scu->clk_sel4);
1167eff28274SJohnny Huang }
1168eff28274SJohnny Huang 
1169f9aa0ee1Sryan_chen static u32 ast2600_configure_mac(struct ast2600_scu *scu, int index)
1170f9aa0ee1Sryan_chen {
1171f9aa0ee1Sryan_chen 	u32 reset_bit;
1172f9aa0ee1Sryan_chen 	u32 clkstop_bit;
1173f9aa0ee1Sryan_chen 
1174f9aa0ee1Sryan_chen 	switch (index) {
1175f9aa0ee1Sryan_chen 	case 1:
1176f9aa0ee1Sryan_chen 		reset_bit = BIT(ASPEED_RESET_MAC1);
1177f9aa0ee1Sryan_chen 		clkstop_bit = BIT(SCU_CLKSTOP_MAC1);
1178f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_ctrl1);
1179f9aa0ee1Sryan_chen 		udelay(100);
1180f9aa0ee1Sryan_chen 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1181f9aa0ee1Sryan_chen 		mdelay(10);
1182f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_clr_ctrl1);
1183f9aa0ee1Sryan_chen 		break;
1184f9aa0ee1Sryan_chen 	case 2:
1185f9aa0ee1Sryan_chen 		reset_bit = BIT(ASPEED_RESET_MAC2);
1186f9aa0ee1Sryan_chen 		clkstop_bit = BIT(SCU_CLKSTOP_MAC2);
1187f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_ctrl1);
1188f9aa0ee1Sryan_chen 		udelay(100);
1189f9aa0ee1Sryan_chen 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1190f9aa0ee1Sryan_chen 		mdelay(10);
1191f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_clr_ctrl1);
1192f9aa0ee1Sryan_chen 		break;
1193f9aa0ee1Sryan_chen 	case 3:
1194f9aa0ee1Sryan_chen 		reset_bit = BIT(ASPEED_RESET_MAC3 - 32);
1195f9aa0ee1Sryan_chen 		clkstop_bit = BIT(SCU_CLKSTOP_MAC3);
1196f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_ctrl2);
1197f9aa0ee1Sryan_chen 		udelay(100);
1198f9aa0ee1Sryan_chen 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1199f9aa0ee1Sryan_chen 		mdelay(10);
1200f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_clr_ctrl2);
1201f9aa0ee1Sryan_chen 		break;
1202f9aa0ee1Sryan_chen 	case 4:
1203f9aa0ee1Sryan_chen 		reset_bit = BIT(ASPEED_RESET_MAC4 - 32);
1204f9aa0ee1Sryan_chen 		clkstop_bit = BIT(SCU_CLKSTOP_MAC4);
1205f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_ctrl2);
1206f9aa0ee1Sryan_chen 		udelay(100);
1207f9aa0ee1Sryan_chen 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1208f9aa0ee1Sryan_chen 		mdelay(10);
1209f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_clr_ctrl2);
1210f9aa0ee1Sryan_chen 		break;
1211f9aa0ee1Sryan_chen 	default:
1212f9aa0ee1Sryan_chen 		return -EINVAL;
1213f9aa0ee1Sryan_chen 	}
1214f9aa0ee1Sryan_chen 
1215f9aa0ee1Sryan_chen 	return 0;
1216f9aa0ee1Sryan_chen }
1217550e691bSryan_chen 
1218a8fc7648SRyan Chen #define SCU_CLK_ECC_RSA_FROM_HPLL_CLK	BIT(19)
1219a8fc7648SRyan Chen #define SCU_CLK_ECC_RSA_CLK_MASK		GENMASK(27, 26)
1220ed3899c5SRyan Chen #define SCU_CLK_ECC_RSA_CLK_DIV(x)		((x) << 26)
1221a8fc7648SRyan Chen static void ast2600_configure_rsa_ecc_clk(struct ast2600_scu *scu)
1222a8fc7648SRyan Chen {
1223a8fc7648SRyan Chen 	u32 clk_sel = readl(&scu->clk_sel1);
1224a8fc7648SRyan Chen 
12257e3c964cSJohnny Huang 	/* Configure RSA clock = HPLL/4 */
1226a8fc7648SRyan Chen 	clk_sel |= SCU_CLK_ECC_RSA_FROM_HPLL_CLK;
1227a8fc7648SRyan Chen 	clk_sel &= ~SCU_CLK_ECC_RSA_CLK_MASK;
12287e3c964cSJohnny Huang 	clk_sel |= SCU_CLK_ECC_RSA_CLK_DIV(3);
1229a8fc7648SRyan Chen 
1230a8fc7648SRyan Chen 	writel(clk_sel, &scu->clk_sel1);
1231a8fc7648SRyan Chen }
1232a8fc7648SRyan Chen 
1233f51926eeSryan_chen #define SCU_CLKSTOP_SDIO 4
1234f51926eeSryan_chen static ulong ast2600_enable_sdclk(struct ast2600_scu *scu)
1235f51926eeSryan_chen {
1236f51926eeSryan_chen 	u32 reset_bit;
1237f51926eeSryan_chen 	u32 clkstop_bit;
1238f51926eeSryan_chen 
1239f51926eeSryan_chen 	reset_bit = BIT(ASPEED_RESET_SD - 32);
1240f51926eeSryan_chen 	clkstop_bit = BIT(SCU_CLKSTOP_SDIO);
1241f51926eeSryan_chen 
1242fc9f12e6Sryan_chen 	writel(reset_bit, &scu->sysreset_ctrl2);
1243fc9f12e6Sryan_chen 
1244f51926eeSryan_chen 	udelay(100);
1245f51926eeSryan_chen 	//enable clk
1246f51926eeSryan_chen 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1247f51926eeSryan_chen 	mdelay(10);
1248fc9f12e6Sryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl2);
1249f51926eeSryan_chen 
1250f51926eeSryan_chen 	return 0;
1251f51926eeSryan_chen }
1252f51926eeSryan_chen 
1253f51926eeSryan_chen #define SCU_CLKSTOP_EXTSD			31
1254f51926eeSryan_chen #define SCU_CLK_SD_MASK				(0x7 << 28)
1255ed3899c5SRyan Chen #define SCU_CLK_SD_DIV(x)			((x) << 28)
12562cd7cba2Sryan_chen #define SCU_CLK_SD_FROM_APLL_CLK	BIT(8)
1257f51926eeSryan_chen 
1258f51926eeSryan_chen static ulong ast2600_enable_extsdclk(struct ast2600_scu *scu)
1259f51926eeSryan_chen {
1260f51926eeSryan_chen 	u32 clk_sel = readl(&scu->clk_sel4);
1261f51926eeSryan_chen 	u32 enableclk_bit;
12622cd7cba2Sryan_chen 	u32 rate = 0;
12632cd7cba2Sryan_chen 	u32 div = 0;
12642cd7cba2Sryan_chen 	int i = 0;
1265f51926eeSryan_chen 
1266f51926eeSryan_chen 	enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
1267f51926eeSryan_chen 
1268a8fc7648SRyan Chen 	/* ast2600 sd controller max clk is 200Mhz :
1269a8fc7648SRyan Chen 	 * use apll for clock source 800/4 = 200 : controller max is 200mhz
1270a8fc7648SRyan Chen 	 */
12712cd7cba2Sryan_chen 	rate = ast2600_get_apll_rate(scu);
12722cd7cba2Sryan_chen 	for (i = 0; i < 8; i++) {
12732cd7cba2Sryan_chen 		div = (i + 1) * 2;
12742cd7cba2Sryan_chen 		if ((rate / div) <= 200000000)
12752cd7cba2Sryan_chen 			break;
12762cd7cba2Sryan_chen 	}
1277f51926eeSryan_chen 	clk_sel &= ~SCU_CLK_SD_MASK;
12782cd7cba2Sryan_chen 	clk_sel |= SCU_CLK_SD_DIV(i) | SCU_CLK_SD_FROM_APLL_CLK;
1279f51926eeSryan_chen 	writel(clk_sel, &scu->clk_sel4);
1280f51926eeSryan_chen 
1281f51926eeSryan_chen 	//enable clk
1282f51926eeSryan_chen 	setbits_le32(&scu->clk_sel4, enableclk_bit);
1283f51926eeSryan_chen 
1284f51926eeSryan_chen 	return 0;
1285f51926eeSryan_chen }
1286f51926eeSryan_chen 
1287f51926eeSryan_chen #define SCU_CLKSTOP_EMMC 27
1288f51926eeSryan_chen static ulong ast2600_enable_emmcclk(struct ast2600_scu *scu)
1289f51926eeSryan_chen {
1290f51926eeSryan_chen 	u32 reset_bit;
1291f51926eeSryan_chen 	u32 clkstop_bit;
1292f51926eeSryan_chen 
1293f51926eeSryan_chen 	reset_bit = BIT(ASPEED_RESET_EMMC);
1294f51926eeSryan_chen 	clkstop_bit = BIT(SCU_CLKSTOP_EMMC);
1295f51926eeSryan_chen 
1296fc9f12e6Sryan_chen 	writel(reset_bit, &scu->sysreset_ctrl1);
1297f51926eeSryan_chen 	udelay(100);
1298f51926eeSryan_chen 	//enable clk
1299f51926eeSryan_chen 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1300f51926eeSryan_chen 	mdelay(10);
1301fc9f12e6Sryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl1);
1302f51926eeSryan_chen 
1303f51926eeSryan_chen 	return 0;
1304f51926eeSryan_chen }
1305f51926eeSryan_chen 
1306f51926eeSryan_chen #define SCU_CLKSTOP_EXTEMMC			15
1307f51926eeSryan_chen #define SCU_CLK_EMMC_MASK			(0x7 << 12)
1308ed3899c5SRyan Chen #define SCU_CLK_EMMC_DIV(x)			((x) << 12)
1309a8fc7648SRyan Chen #define SCU_CLK_EMMC_FROM_MPLL_CLK	BIT(11)
1310f51926eeSryan_chen 
1311f51926eeSryan_chen static ulong ast2600_enable_extemmcclk(struct ast2600_scu *scu)
1312f51926eeSryan_chen {
131385d48d8cSryan_chen 	u32 revision_id = readl(&scu->chip_id1);
1314f51926eeSryan_chen 	u32 clk_sel = readl(&scu->clk_sel1);
1315ed3899c5SRyan Chen 	u32 enableclk_bit = BIT(SCU_CLKSTOP_EXTEMMC);
1316f4c4ddb1Sryan_chen 	u32 rate = 0;
1317f4c4ddb1Sryan_chen 	u32 div = 0;
1318f4c4ddb1Sryan_chen 	int i = 0;
1319f51926eeSryan_chen 
1320ed3899c5SRyan Chen 	/*
1321ed3899c5SRyan Chen 	 * ast2600 eMMC controller max clk is 200Mhz
1322ed3899c5SRyan Chen 	 * HPll->1/2->|\
1323ed3899c5SRyan Chen 	 *				|->SCU300[11]->SCU300[14:12][1/N] +
1324ed3899c5SRyan Chen 	 * MPLL------>|/								  |
1325ed3899c5SRyan Chen 	 * +----------------------------------------------+
1326ed3899c5SRyan Chen 	 * |
1327ed3899c5SRyan Chen 	 * +---------> EMMC12C[15:8][1/N]-> eMMC clk
1328a8fc7648SRyan Chen 	 */
132985d48d8cSryan_chen 	if (((revision_id & CHIP_REVISION_ID) >> 16)) {
13308c32294fSryan_chen 		//AST2600A1 : use mpll to be clk source
1331b0c30ea3Sryan_chen 		rate = ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
1332b0c30ea3Sryan_chen 		for (i = 0; i < 8; i++) {
1333b0c30ea3Sryan_chen 			div = (i + 1) * 2;
1334b0c30ea3Sryan_chen 			if ((rate / div) <= 200000000)
1335b0c30ea3Sryan_chen 				break;
1336b0c30ea3Sryan_chen 		}
1337b0c30ea3Sryan_chen 
1338b0c30ea3Sryan_chen 		clk_sel &= ~SCU_CLK_EMMC_MASK;
13392cd7cba2Sryan_chen 		clk_sel |= SCU_CLK_EMMC_DIV(i) | SCU_CLK_EMMC_FROM_MPLL_CLK;
1340b0c30ea3Sryan_chen 		writel(clk_sel, &scu->clk_sel1);
1341b0c30ea3Sryan_chen 
1342b0c30ea3Sryan_chen 	} else {
13432cd7cba2Sryan_chen 		//AST2600A0 : use hpll to be clk source
1344f4c4ddb1Sryan_chen 		rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
1345f4c4ddb1Sryan_chen 
1346f4c4ddb1Sryan_chen 		for (i = 0; i < 8; i++) {
1347f4c4ddb1Sryan_chen 			div = (i + 1) * 4;
1348f4c4ddb1Sryan_chen 			if ((rate / div) <= 200000000)
1349f4c4ddb1Sryan_chen 				break;
1350f4c4ddb1Sryan_chen 		}
1351f4c4ddb1Sryan_chen 
1352f4c4ddb1Sryan_chen 		clk_sel &= ~SCU_CLK_EMMC_MASK;
1353f4c4ddb1Sryan_chen 		clk_sel |= SCU_CLK_EMMC_DIV(i);
1354f51926eeSryan_chen 		writel(clk_sel, &scu->clk_sel1);
1355b0c30ea3Sryan_chen 	}
1356f51926eeSryan_chen 	setbits_le32(&scu->clk_sel1, enableclk_bit);
1357f51926eeSryan_chen 
1358f51926eeSryan_chen 	return 0;
1359f51926eeSryan_chen }
1360f51926eeSryan_chen 
1361baf00c26Sryan_chen #define SCU_CLKSTOP_FSICLK 30
1362baf00c26Sryan_chen 
1363baf00c26Sryan_chen static ulong ast2600_enable_fsiclk(struct ast2600_scu *scu)
1364baf00c26Sryan_chen {
1365baf00c26Sryan_chen 	u32 reset_bit;
1366baf00c26Sryan_chen 	u32 clkstop_bit;
1367baf00c26Sryan_chen 
1368baf00c26Sryan_chen 	reset_bit = BIT(ASPEED_RESET_FSI % 32);
1369baf00c26Sryan_chen 	clkstop_bit = BIT(SCU_CLKSTOP_FSICLK);
1370baf00c26Sryan_chen 
1371baf00c26Sryan_chen 	/* The FSI clock is shared between masters. If it's already on
1372ed3899c5SRyan Chen 	 * don't touch it, as that will reset the existing master.
1373ed3899c5SRyan Chen 	 */
1374baf00c26Sryan_chen 	if (!(readl(&scu->clk_stop_ctrl2) & clkstop_bit)) {
1375baf00c26Sryan_chen 		debug("%s: already running, not touching it\n", __func__);
1376baf00c26Sryan_chen 		return 0;
1377baf00c26Sryan_chen 	}
1378baf00c26Sryan_chen 
1379baf00c26Sryan_chen 	writel(reset_bit, &scu->sysreset_ctrl2);
1380baf00c26Sryan_chen 	udelay(100);
1381baf00c26Sryan_chen 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1382baf00c26Sryan_chen 	mdelay(10);
1383baf00c26Sryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl2);
1384baf00c26Sryan_chen 
1385baf00c26Sryan_chen 	return 0;
1386baf00c26Sryan_chen }
1387baf00c26Sryan_chen 
1388b8ec5ceaSryan_chen static ulong ast2600_enable_usbahclk(struct ast2600_scu *scu)
1389b8ec5ceaSryan_chen {
1390b8ec5ceaSryan_chen 	u32 reset_bit;
1391b8ec5ceaSryan_chen 	u32 clkstop_bit;
1392b8ec5ceaSryan_chen 
1393b8ec5ceaSryan_chen 	reset_bit = BIT(ASPEED_RESET_EHCI_P1);
1394b8ec5ceaSryan_chen 	clkstop_bit = BIT(14);
1395b8ec5ceaSryan_chen 
1396b8ec5ceaSryan_chen 	writel(reset_bit, &scu->sysreset_ctrl1);
1397b8ec5ceaSryan_chen 	udelay(100);
1398b8ec5ceaSryan_chen 	writel(clkstop_bit, &scu->clk_stop_ctrl1);
1399b8ec5ceaSryan_chen 	mdelay(20);
1400b8ec5ceaSryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl1);
1401b8ec5ceaSryan_chen 
1402b8ec5ceaSryan_chen 	return 0;
1403b8ec5ceaSryan_chen }
1404b8ec5ceaSryan_chen 
1405b8ec5ceaSryan_chen static ulong ast2600_enable_usbbhclk(struct ast2600_scu *scu)
1406b8ec5ceaSryan_chen {
1407b8ec5ceaSryan_chen 	u32 reset_bit;
1408b8ec5ceaSryan_chen 	u32 clkstop_bit;
1409b8ec5ceaSryan_chen 
1410b8ec5ceaSryan_chen 	reset_bit = BIT(ASPEED_RESET_EHCI_P2);
1411b8ec5ceaSryan_chen 	clkstop_bit = BIT(7);
1412b8ec5ceaSryan_chen 
1413b8ec5ceaSryan_chen 	writel(reset_bit, &scu->sysreset_ctrl1);
1414b8ec5ceaSryan_chen 	udelay(100);
1415b8ec5ceaSryan_chen 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1416b8ec5ceaSryan_chen 	mdelay(20);
1417b8ec5ceaSryan_chen 
1418b8ec5ceaSryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl1);
1419b8ec5ceaSryan_chen 
1420b8ec5ceaSryan_chen 	return 0;
1421b8ec5ceaSryan_chen }
1422b8ec5ceaSryan_chen 
1423089713adSJoel Stanley /* also known as yclk */
1424089713adSJoel Stanley static ulong ast2600_enable_haceclk(struct ast2600_scu *scu)
1425089713adSJoel Stanley {
1426089713adSJoel Stanley 	u32 reset_bit;
1427089713adSJoel Stanley 	u32 clkstop_bit;
1428089713adSJoel Stanley 
1429089713adSJoel Stanley 	reset_bit = BIT(ASPEED_RESET_HACE);
1430089713adSJoel Stanley 	clkstop_bit = BIT(13);
1431089713adSJoel Stanley 
1432089713adSJoel Stanley 	writel(reset_bit, &scu->sysreset_ctrl1);
1433089713adSJoel Stanley 	udelay(100);
1434089713adSJoel Stanley 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1435089713adSJoel Stanley 	mdelay(20);
1436089713adSJoel Stanley 
1437089713adSJoel Stanley 	writel(reset_bit, &scu->sysreset_clr_ctrl1);
1438089713adSJoel Stanley 
1439089713adSJoel Stanley 	return 0;
1440089713adSJoel Stanley }
1441089713adSJoel Stanley 
1442f6110ecdSChia-Wei Wang static ulong ast2600_enable_rsaeccclk(struct ast2600_scu *scu)
1443f6110ecdSChia-Wei Wang {
1444f6110ecdSChia-Wei Wang 	u32 clkstop_bit;
1445f6110ecdSChia-Wei Wang 
1446f6110ecdSChia-Wei Wang 	clkstop_bit = BIT(24);
1447f6110ecdSChia-Wei Wang 
1448f6110ecdSChia-Wei Wang 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1449f6110ecdSChia-Wei Wang 	mdelay(20);
1450f6110ecdSChia-Wei Wang 
1451f6110ecdSChia-Wei Wang 	return 0;
1452f6110ecdSChia-Wei Wang }
1453f6110ecdSChia-Wei Wang 
1454d6e349c7Sryan_chen static int ast2600_clk_enable(struct clk *clk)
1455550e691bSryan_chen {
1456f0d895afSryan_chen 	struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
1457550e691bSryan_chen 
1458550e691bSryan_chen 	switch (clk->id) {
145986f91560Sryan_chen 	case ASPEED_CLK_GATE_MAC1CLK:
146086f91560Sryan_chen 		ast2600_configure_mac(priv->scu, 1);
1461550e691bSryan_chen 		break;
146286f91560Sryan_chen 	case ASPEED_CLK_GATE_MAC2CLK:
146386f91560Sryan_chen 		ast2600_configure_mac(priv->scu, 2);
1464550e691bSryan_chen 		break;
146577843939Sryan_chen 	case ASPEED_CLK_GATE_MAC3CLK:
146677843939Sryan_chen 		ast2600_configure_mac(priv->scu, 3);
146777843939Sryan_chen 		break;
146877843939Sryan_chen 	case ASPEED_CLK_GATE_MAC4CLK:
146977843939Sryan_chen 		ast2600_configure_mac(priv->scu, 4);
147077843939Sryan_chen 		break;
1471f51926eeSryan_chen 	case ASPEED_CLK_GATE_SDCLK:
1472f51926eeSryan_chen 		ast2600_enable_sdclk(priv->scu);
1473f51926eeSryan_chen 		break;
1474f51926eeSryan_chen 	case ASPEED_CLK_GATE_SDEXTCLK:
1475f51926eeSryan_chen 		ast2600_enable_extsdclk(priv->scu);
1476f51926eeSryan_chen 		break;
1477f51926eeSryan_chen 	case ASPEED_CLK_GATE_EMMCCLK:
1478f51926eeSryan_chen 		ast2600_enable_emmcclk(priv->scu);
1479f51926eeSryan_chen 		break;
1480f51926eeSryan_chen 	case ASPEED_CLK_GATE_EMMCEXTCLK:
1481f51926eeSryan_chen 		ast2600_enable_extemmcclk(priv->scu);
1482f51926eeSryan_chen 		break;
1483baf00c26Sryan_chen 	case ASPEED_CLK_GATE_FSICLK:
1484baf00c26Sryan_chen 		ast2600_enable_fsiclk(priv->scu);
1485baf00c26Sryan_chen 		break;
1486b8ec5ceaSryan_chen 	case ASPEED_CLK_GATE_USBPORT1CLK:
1487b8ec5ceaSryan_chen 		ast2600_enable_usbahclk(priv->scu);
1488b8ec5ceaSryan_chen 		break;
1489b8ec5ceaSryan_chen 	case ASPEED_CLK_GATE_USBPORT2CLK:
1490b8ec5ceaSryan_chen 		ast2600_enable_usbbhclk(priv->scu);
1491b8ec5ceaSryan_chen 		break;
1492089713adSJoel Stanley 	case ASPEED_CLK_GATE_YCLK:
1493089713adSJoel Stanley 		ast2600_enable_haceclk(priv->scu);
1494089713adSJoel Stanley 		break;
1495f6110ecdSChia-Wei Wang 	case ASPEED_CLK_GATE_RSAECCCLK:
1496f6110ecdSChia-Wei Wang 		ast2600_enable_rsaeccclk(priv->scu);
1497f6110ecdSChia-Wei Wang 		break;
1498550e691bSryan_chen 	default:
1499ed3899c5SRyan Chen 		pr_err("can't enable clk\n");
1500550e691bSryan_chen 		return -ENOENT;
1501550e691bSryan_chen 	}
1502550e691bSryan_chen 
1503550e691bSryan_chen 	return 0;
1504550e691bSryan_chen }
1505550e691bSryan_chen 
1506f9aa0ee1Sryan_chen struct clk_ops ast2600_clk_ops = {
1507d6e349c7Sryan_chen 	.get_rate = ast2600_clk_get_rate,
1508d6e349c7Sryan_chen 	.set_rate = ast2600_clk_set_rate,
1509d6e349c7Sryan_chen 	.enable = ast2600_clk_enable,
1510550e691bSryan_chen };
1511550e691bSryan_chen 
1512d6e349c7Sryan_chen static int ast2600_clk_probe(struct udevice *dev)
1513550e691bSryan_chen {
1514f0d895afSryan_chen 	struct ast2600_clk_priv *priv = dev_get_priv(dev);
151561ab9607Sryan_chen 	u32 uart_clk_source;
1516550e691bSryan_chen 
1517f0d895afSryan_chen 	priv->scu = devfdt_get_addr_ptr(dev);
1518f0d895afSryan_chen 	if (IS_ERR(priv->scu))
1519f0d895afSryan_chen 		return PTR_ERR(priv->scu);
1520550e691bSryan_chen 
15215d05f4fcSRyan Chen 	uart_clk_source = dev_read_u32_default(dev, "uart-clk-source", 0x0);
152261ab9607Sryan_chen 
152361ab9607Sryan_chen 	if (uart_clk_source) {
152456dd3e85Sryan_chen 		if (uart_clk_source & GENMASK(5, 0))
15255d05f4fcSRyan Chen 			setbits_le32(&priv->scu->clk_sel4,
15265d05f4fcSRyan Chen 				     uart_clk_source & GENMASK(5, 0));
152756dd3e85Sryan_chen 		if (uart_clk_source & GENMASK(12, 6))
15285d05f4fcSRyan Chen 			setbits_le32(&priv->scu->clk_sel5,
15295d05f4fcSRyan Chen 				     uart_clk_source & GENMASK(12, 6));
153061ab9607Sryan_chen 	}
153161ab9607Sryan_chen 
1532b89500a2SDylan Hung 	ast2600_init_rgmii_clk(priv->scu, &rgmii_clk_defconfig);
1533b89500a2SDylan Hung 	ast2600_init_rmii_clk(priv->scu, &rmii_clk_defconfig);
1534*e95b19f8SDylan Hung 	ast2600_init_dly32_lookup(priv);
1535*e95b19f8SDylan Hung 	ast2600_configure_mac12_clk(priv, dev);
1536*e95b19f8SDylan Hung 	ast2600_configure_mac34_clk(priv, dev);
1537a8fc7648SRyan Chen 	ast2600_configure_rsa_ecc_clk(priv->scu);
1538fd0306aaSJohnny Huang 
1539550e691bSryan_chen 	return 0;
1540550e691bSryan_chen }
1541550e691bSryan_chen 
1542d6e349c7Sryan_chen static int ast2600_clk_bind(struct udevice *dev)
1543550e691bSryan_chen {
1544550e691bSryan_chen 	int ret;
1545550e691bSryan_chen 
1546550e691bSryan_chen 	/* The reset driver does not have a device node, so bind it here */
1547550e691bSryan_chen 	ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
1548550e691bSryan_chen 	if (ret)
1549550e691bSryan_chen 		debug("Warning: No reset driver: ret=%d\n", ret);
1550550e691bSryan_chen 
1551550e691bSryan_chen 	return 0;
1552550e691bSryan_chen }
1553550e691bSryan_chen 
1554d35ac78cSryan_chen struct aspeed_clks {
1555d35ac78cSryan_chen 	ulong id;
1556d35ac78cSryan_chen 	const char *name;
1557d35ac78cSryan_chen };
1558d35ac78cSryan_chen 
1559d35ac78cSryan_chen static struct aspeed_clks aspeed_clk_names[] = {
15605d05f4fcSRyan Chen 	{ ASPEED_CLK_HPLL, "hpll" },     { ASPEED_CLK_MPLL, "mpll" },
15615d05f4fcSRyan Chen 	{ ASPEED_CLK_APLL, "apll" },     { ASPEED_CLK_EPLL, "epll" },
15625d05f4fcSRyan Chen 	{ ASPEED_CLK_DPLL, "dpll" },     { ASPEED_CLK_AHB, "hclk" },
15635d05f4fcSRyan Chen 	{ ASPEED_CLK_APB1, "pclk1" },    { ASPEED_CLK_APB2, "pclk2" },
15645d05f4fcSRyan Chen 	{ ASPEED_CLK_BCLK, "bclk" },     { ASPEED_CLK_UARTX, "uxclk" },
1565def99fcbSryan_chen 	{ ASPEED_CLK_HUARTX, "huxclk" },
1566d35ac78cSryan_chen };
1567d35ac78cSryan_chen 
1568d35ac78cSryan_chen int soc_clk_dump(void)
1569d35ac78cSryan_chen {
1570d35ac78cSryan_chen 	struct udevice *dev;
1571d35ac78cSryan_chen 	struct clk clk;
1572d35ac78cSryan_chen 	unsigned long rate;
1573d35ac78cSryan_chen 	int i, ret;
1574d35ac78cSryan_chen 
15755d05f4fcSRyan Chen 	ret = uclass_get_device_by_driver(UCLASS_CLK, DM_GET_DRIVER(aspeed_scu),
15765d05f4fcSRyan Chen 					  &dev);
1577d35ac78cSryan_chen 	if (ret)
1578d35ac78cSryan_chen 		return ret;
1579d35ac78cSryan_chen 
1580d35ac78cSryan_chen 	printf("Clk\t\tHz\n");
1581d35ac78cSryan_chen 
1582d35ac78cSryan_chen 	for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
1583d35ac78cSryan_chen 		clk.id = aspeed_clk_names[i].id;
1584d35ac78cSryan_chen 		ret = clk_request(dev, &clk);
1585d35ac78cSryan_chen 		if (ret < 0) {
1586d35ac78cSryan_chen 			debug("%s clk_request() failed: %d\n", __func__, ret);
1587d35ac78cSryan_chen 			continue;
1588d35ac78cSryan_chen 		}
1589d35ac78cSryan_chen 
1590d35ac78cSryan_chen 		ret = clk_get_rate(&clk);
1591d35ac78cSryan_chen 		rate = ret;
1592d35ac78cSryan_chen 
1593d35ac78cSryan_chen 		clk_free(&clk);
1594d35ac78cSryan_chen 
1595d35ac78cSryan_chen 		if (ret == -ENOTSUPP) {
1596d35ac78cSryan_chen 			printf("clk ID %lu not supported yet\n",
1597d35ac78cSryan_chen 			       aspeed_clk_names[i].id);
1598d35ac78cSryan_chen 			continue;
1599d35ac78cSryan_chen 		}
1600d35ac78cSryan_chen 		if (ret < 0) {
16015d05f4fcSRyan Chen 			printf("%s %lu: get_rate err: %d\n", __func__,
16025d05f4fcSRyan Chen 			       aspeed_clk_names[i].id, ret);
1603d35ac78cSryan_chen 			continue;
1604d35ac78cSryan_chen 		}
1605d35ac78cSryan_chen 
16065d05f4fcSRyan Chen 		printf("%s(%3lu):\t%lu\n", aspeed_clk_names[i].name,
16075d05f4fcSRyan Chen 		       aspeed_clk_names[i].id, rate);
1608d35ac78cSryan_chen 	}
1609d35ac78cSryan_chen 
1610d35ac78cSryan_chen 	return 0;
1611d35ac78cSryan_chen }
1612d35ac78cSryan_chen 
1613d6e349c7Sryan_chen static const struct udevice_id ast2600_clk_ids[] = {
16145d05f4fcSRyan Chen 	{
16155d05f4fcSRyan Chen 		.compatible = "aspeed,ast2600-scu",
16165d05f4fcSRyan Chen 	},
1617550e691bSryan_chen 	{}
1618550e691bSryan_chen };
1619550e691bSryan_chen 
1620aa36597fSDylan Hung U_BOOT_DRIVER(aspeed_scu) = {
1621aa36597fSDylan Hung 	.name = "aspeed_scu",
1622550e691bSryan_chen 	.id = UCLASS_CLK,
1623d6e349c7Sryan_chen 	.of_match = ast2600_clk_ids,
1624f0d895afSryan_chen 	.priv_auto_alloc_size = sizeof(struct ast2600_clk_priv),
1625f9aa0ee1Sryan_chen 	.ops = &ast2600_clk_ops,
1626d6e349c7Sryan_chen 	.bind = ast2600_clk_bind,
1627d6e349c7Sryan_chen 	.probe = ast2600_clk_probe,
1628550e691bSryan_chen };
1629