xref: /openbmc/u-boot/drivers/clk/aspeed/clk_ast2600.c (revision e40a4e447a0e7f4d8b38c3256349e39ff3701f1f)
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>
7*e40a4e44SDylan Hung #include <linux/bitfield.h>
8*e40a4e44SDylan Hung #include <linux/bitops.h>
9550e691bSryan_chen #include <clk-uclass.h>
10550e691bSryan_chen #include <dm.h>
11550e691bSryan_chen #include <asm/io.h>
12550e691bSryan_chen #include <dm/lists.h>
1362a6bcbfSryan_chen #include <asm/arch/scu_ast2600.h>
14d6e349c7Sryan_chen #include <dt-bindings/clock/ast2600-clock.h>
1539283ea7Sryan_chen #include <dt-bindings/reset/ast2600-reset.h>
16550e691bSryan_chen 
17550e691bSryan_chen /*
18a8fc7648SRyan Chen  * MAC Clock Delay settings
19550e691bSryan_chen  */
20*e40a4e44SDylan Hung #define MAC_CLK_RGMII_125M_SRC_SEL		BIT(31)
21*e40a4e44SDylan Hung #define   MAC_CLK_RGMII_125M_SRC_PAD_RGMIICK	0
22*e40a4e44SDylan Hung #define   MAC_CLK_RGMII_125M_SRC_PLL		1
23*e40a4e44SDylan Hung #define MAC_CLK_RMII2_50M_RCLK_O_CTRL		BIT(30)
24*e40a4e44SDylan Hung #define   MAC_CLK_RMII2_50M_RCLK_O_DIS		0
25*e40a4e44SDylan Hung #define   MAC_CLK_RMII2_50M_RCLK_O_EN		1
26*e40a4e44SDylan Hung #define MAC_CLK_RMII1_50M_RCLK_O_CTRL		BIT(29)
27*e40a4e44SDylan Hung #define   MAC_CLK_RMII1_5M_RCLK_O_DIS		0
28*e40a4e44SDylan Hung #define   MAC_CLK_RMII1_5M_RCLK_O_EN		1
29*e40a4e44SDylan Hung #define MAC_CLK_RGMIICK_PAD_DIR			BIT(28)
30*e40a4e44SDylan Hung #define   MAC_CLK_RGMIICK_PAD_DIR_INPUT		0
31*e40a4e44SDylan Hung #define   MAC_CLK_RGMIICK_PAD_DIR_OUTPUT	1
32*e40a4e44SDylan Hung #define MAC_CLK_RMII_TXD_FALLING_2		BIT(27)
33*e40a4e44SDylan Hung #define MAC_CLK_RMII_TXD_FALLING_1		BIT(26)
34*e40a4e44SDylan Hung #define MAC_CLK_RXCLK_INV_2			BIT(25)
35*e40a4e44SDylan Hung #define MAC_CLK_RXCLK_INV_1			BIT(24)
36*e40a4e44SDylan Hung #define MAC_CLK_1G_INPUT_DELAY_2		GENMASK(23, 18)
37*e40a4e44SDylan Hung #define MAC_CLK_1G_INPUT_DELAY_1		GENMASK(17, 12)
38*e40a4e44SDylan Hung #define MAC_CLK_1G_OUTPUT_DELAY_2		GENMASK(11, 6)
39*e40a4e44SDylan Hung #define MAC_CLK_1G_OUTPUT_DELAY_1		GENMASK(5, 0)
40550e691bSryan_chen 
41*e40a4e44SDylan Hung #define MAC_CLK_100M_10M_RESERVED		GENMASK(31, 26)
42*e40a4e44SDylan Hung #define MAC_CLK_100M_10M_RXCLK_INV_2		BIT(25)
43*e40a4e44SDylan Hung #define MAC_CLK_100M_10M_RXCLK_INV_1		BIT(24)
44*e40a4e44SDylan Hung #define MAC_CLK_100M_10M_INPUT_DELAY_2		GENMASK(23, 18)
45*e40a4e44SDylan Hung #define MAC_CLK_100M_10M_INPUT_DELAY_1		GENMASK(17, 12)
46*e40a4e44SDylan Hung #define MAC_CLK_100M_10M_OUTPUT_DELAY_2		GENMASK(11, 6)
47*e40a4e44SDylan Hung #define MAC_CLK_100M_10M_OUTPUT_DELAY_1		GENMASK(5, 0)
4854f9cba1SDylan Hung 
49*e40a4e44SDylan Hung #define MAC_DEF_DELAY_1G			FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, 16) |        \
50*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, 10) |         \
51*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, 16) |        \
52*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, 10)
53*e40a4e44SDylan Hung #define MAC_DEF_DELAY_100M			FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, 16) |  \
54*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, 16) |   \
55*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, 16) |  \
56*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, 16)
57*e40a4e44SDylan Hung #define MAC_DEF_DELAY_10M			FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, 16) |  \
58*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, 16) |   \
59*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, 16) |  \
60*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, 16)
61*e40a4e44SDylan Hung #define MAC34_DEF_DELAY_1G			FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, 8) |         \
62*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, 4) |          \
63*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, 8) |         \
64*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, 4)
65*e40a4e44SDylan Hung #define MAC34_DEF_DELAY_100M			FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, 8) |   \
66*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, 4) |    \
67*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, 8) |   \
68*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, 4)
69*e40a4e44SDylan Hung #define MAC34_DEF_DELAY_10M			FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, 8) |   \
70*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, 4) |    \
71*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, 8) |   \
72*e40a4e44SDylan Hung 						FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, 4)
73550e691bSryan_chen /*
74550e691bSryan_chen  * TGMII Clock Duty constants, taken from Aspeed SDK
75550e691bSryan_chen  */
76550e691bSryan_chen #define RGMII2_TXCK_DUTY		0x66
77550e691bSryan_chen #define RGMII1_TXCK_DUTY		0x64
78550e691bSryan_chen #define D2PLL_DEFAULT_RATE		(250 * 1000 * 1000)
7985d48d8cSryan_chen #define CHIP_REVISION_ID		GENMASK(23, 16)
8085d48d8cSryan_chen 
81550e691bSryan_chen DECLARE_GLOBAL_DATA_PTR;
82550e691bSryan_chen 
83550e691bSryan_chen /*
84550e691bSryan_chen  * Clock divider/multiplier configuration struct.
85550e691bSryan_chen  * For H-PLL and M-PLL the formula is
86550e691bSryan_chen  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
87550e691bSryan_chen  * M - Numerator
88550e691bSryan_chen  * N - Denumerator
89550e691bSryan_chen  * P - Post Divider
90550e691bSryan_chen  * They have the same layout in their control register.
91550e691bSryan_chen  *
92550e691bSryan_chen  * D-PLL and D2-PLL have extra divider (OD + 1), which is not
93550e691bSryan_chen  * yet needed and ignored by clock configurations.
94550e691bSryan_chen  */
95577fcdaeSDylan Hung union ast2600_pll_reg {
96334bd202SDylan Hung 	u32 w;
97577fcdaeSDylan Hung 	struct {
98fd52be0bSDylan Hung 		unsigned int m : 13;		/* bit[12:0]	*/
99fd52be0bSDylan Hung 		unsigned int n : 6;		/* bit[18:13]	*/
100fd52be0bSDylan Hung 		unsigned int p : 4;		/* bit[22:19]	*/
101fd52be0bSDylan Hung 		unsigned int off : 1;		/* bit[23]	*/
102fd52be0bSDylan Hung 		unsigned int bypass : 1;	/* bit[24]	*/
103fd52be0bSDylan Hung 		unsigned int reset : 1;		/* bit[25]	*/
104fd52be0bSDylan Hung 		unsigned int reserved : 6;	/* bit[31:26]	*/
105577fcdaeSDylan Hung 	} b;
106577fcdaeSDylan Hung };
107577fcdaeSDylan Hung 
108577fcdaeSDylan Hung struct ast2600_pll_cfg {
109577fcdaeSDylan Hung 	union ast2600_pll_reg reg;
110334bd202SDylan Hung 	u32 ext_reg;
111577fcdaeSDylan Hung };
112577fcdaeSDylan Hung 
113577fcdaeSDylan Hung struct ast2600_pll_desc {
114577fcdaeSDylan Hung 	u32 in;
115577fcdaeSDylan Hung 	u32 out;
116577fcdaeSDylan Hung 	struct ast2600_pll_cfg cfg;
117577fcdaeSDylan Hung };
118577fcdaeSDylan Hung 
119577fcdaeSDylan Hung static const struct ast2600_pll_desc ast2600_pll_lookup[] = {
120a8fc7648SRyan Chen 	{
1215d05f4fcSRyan Chen 		.in = AST2600_CLK_IN,
1225d05f4fcSRyan Chen 		.out = 400000000,
1235d05f4fcSRyan Chen 		.cfg.reg.b.m = 95,
1245d05f4fcSRyan Chen 		.cfg.reg.b.n = 2,
1255d05f4fcSRyan Chen 		.cfg.reg.b.p = 1,
126577fcdaeSDylan Hung 		.cfg.ext_reg = 0x31,
127fa59add1SRyan Chen 	}, {
128fa59add1SRyan Chen 		.in = AST2600_CLK_IN,
1295d05f4fcSRyan Chen 		.out = 200000000,
1305d05f4fcSRyan Chen 		.cfg.reg.b.m = 127,
1315d05f4fcSRyan Chen 		.cfg.reg.b.n = 0,
1325d05f4fcSRyan Chen 		.cfg.reg.b.p = 15,
133fa59add1SRyan Chen 		.cfg.ext_reg = 0x3f,
134fa59add1SRyan Chen 	}, {
135fa59add1SRyan Chen 		.in = AST2600_CLK_IN,
1365d05f4fcSRyan Chen 		.out = 334000000,
1375d05f4fcSRyan Chen 		.cfg.reg.b.m = 667,
1385d05f4fcSRyan Chen 		.cfg.reg.b.n = 4,
1395d05f4fcSRyan Chen 		.cfg.reg.b.p = 9,
140fa59add1SRyan Chen 		.cfg.ext_reg = 0x14d,
141fa59add1SRyan Chen 	}, {
142fa59add1SRyan Chen 		.in = AST2600_CLK_IN,
1435d05f4fcSRyan Chen 		.out = 1000000000,
1445d05f4fcSRyan Chen 		.cfg.reg.b.m = 119,
1455d05f4fcSRyan Chen 		.cfg.reg.b.n = 2,
1465d05f4fcSRyan Chen 		.cfg.reg.b.p = 0,
147fa59add1SRyan Chen 		.cfg.ext_reg = 0x3d,
148fa59add1SRyan Chen 	}, {
149fa59add1SRyan Chen 		.in = AST2600_CLK_IN,
1505d05f4fcSRyan Chen 		.out = 50000000,
1515d05f4fcSRyan Chen 		.cfg.reg.b.m = 95,
1525d05f4fcSRyan Chen 		.cfg.reg.b.n = 2,
1535d05f4fcSRyan Chen 		.cfg.reg.b.p = 15,
154fa59add1SRyan Chen 		.cfg.ext_reg = 0x31,
155fa59add1SRyan Chen 	},
156550e691bSryan_chen };
157550e691bSryan_chen 
158a98c71fbSDylan Hung struct mac_delay_config {
159a98c71fbSDylan Hung 	u32 tx_delay_1000;
160a98c71fbSDylan Hung 	u32 rx_delay_1000;
161a98c71fbSDylan Hung 	u32 tx_delay_100;
162a98c71fbSDylan Hung 	u32 rx_delay_100;
163a98c71fbSDylan Hung 	u32 tx_delay_10;
164a98c71fbSDylan Hung 	u32 rx_delay_10;
165a98c71fbSDylan Hung };
166a98c71fbSDylan Hung 
167bbbfb0c5Sryan_chen extern u32 ast2600_get_pll_rate(struct ast2600_scu *scu, int pll_idx)
168550e691bSryan_chen {
169d6e349c7Sryan_chen 	u32 clkin = AST2600_CLK_IN;
170bbbfb0c5Sryan_chen 	u32 pll_reg = 0;
1719639db61Sryan_chen 	unsigned int mult, div = 1;
172550e691bSryan_chen 
173bbbfb0c5Sryan_chen 	switch (pll_idx) {
174bbbfb0c5Sryan_chen 	case ASPEED_CLK_HPLL:
175bbbfb0c5Sryan_chen 		pll_reg = readl(&scu->h_pll_param);
176bbbfb0c5Sryan_chen 		break;
177bbbfb0c5Sryan_chen 	case ASPEED_CLK_MPLL:
178bbbfb0c5Sryan_chen 		pll_reg = readl(&scu->m_pll_param);
179bbbfb0c5Sryan_chen 		break;
180bbbfb0c5Sryan_chen 	case ASPEED_CLK_DPLL:
181bbbfb0c5Sryan_chen 		pll_reg = readl(&scu->d_pll_param);
182bbbfb0c5Sryan_chen 		break;
183bbbfb0c5Sryan_chen 	case ASPEED_CLK_EPLL:
184bbbfb0c5Sryan_chen 		pll_reg = readl(&scu->e_pll_param);
185bbbfb0c5Sryan_chen 		break;
186bbbfb0c5Sryan_chen 	}
187bbbfb0c5Sryan_chen 	if (pll_reg & BIT(24)) {
1889639db61Sryan_chen 		/* Pass through mode */
189ed3899c5SRyan Chen 		mult = 1;
190ed3899c5SRyan Chen 		div = 1;
1919639db61Sryan_chen 	} else {
19275ced45aSDylan Hung 		union ast2600_pll_reg reg;
193ed3899c5SRyan Chen 		/* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1)
194ed3899c5SRyan Chen 		 * HPLL Numerator (M) = fix 0x5F when SCU500[10]=1
195ed3899c5SRyan Chen 		 * Fixed 0xBF when SCU500[10]=0 and SCU500[8]=1
196ed3899c5SRyan Chen 		 * SCU200[12:0] (default 0x8F) when SCU510[10]=0 and SCU510[8]=0
197ed3899c5SRyan Chen 		 * HPLL Denumerator (N) =	SCU200[18:13] (default 0x2)
198ed3899c5SRyan Chen 		 * HPLL Divider (P)	 =	SCU200[22:19] (default 0x0)
199ed3899c5SRyan Chen 		 * HPLL Bandwidth Adj (NB) =  fix 0x2F when SCU500[10]=1
200ed3899c5SRyan Chen 		 * Fixed 0x5F when SCU500[10]=0 and SCU500[8]=1
201ed3899c5SRyan Chen 		 * SCU204[11:0] (default 0x31) when SCU500[10]=0 and SCU500[8]=0
202e5c4f4dfSryan_chen 		 */
203ed3899c5SRyan Chen 		reg.w = pll_reg;
204f27685ebSRyan Chen 		if (pll_idx == ASPEED_CLK_HPLL) {
205e5c4f4dfSryan_chen 			u32 hwstrap1 = readl(&scu->hwstrap1.hwstrap);
206ed3899c5SRyan Chen 
207ed3899c5SRyan Chen 			if (hwstrap1 & BIT(10)) {
208e5c4f4dfSryan_chen 				reg.b.m = 0x5F;
209ed3899c5SRyan Chen 			} else {
210e5c4f4dfSryan_chen 				if (hwstrap1 & BIT(8))
211e5c4f4dfSryan_chen 					reg.b.m = 0xBF;
212a8fc7648SRyan Chen 				/* Otherwise keep default 0x8F */
213e5c4f4dfSryan_chen 			}
214e5c4f4dfSryan_chen 		}
21575ced45aSDylan Hung 		mult = (reg.b.m + 1) / (reg.b.n + 1);
21675ced45aSDylan Hung 		div = (reg.b.p + 1);
2179639db61Sryan_chen 	}
218a8fc7648SRyan Chen 
2199639db61Sryan_chen 	return ((clkin * mult) / div);
220550e691bSryan_chen }
221550e691bSryan_chen 
2224f22e838Sryan_chen extern u32 ast2600_get_apll_rate(struct ast2600_scu *scu)
223550e691bSryan_chen {
22485d48d8cSryan_chen 	u32 hw_rev = readl(&scu->chip_id1);
225bbbfb0c5Sryan_chen 	u32 clkin = AST2600_CLK_IN;
22639283ea7Sryan_chen 	u32 apll_reg = readl(&scu->a_pll_param);
22739283ea7Sryan_chen 	unsigned int mult, div = 1;
228d6e349c7Sryan_chen 
2298d615c79SRyan Chen 	if (((hw_rev & CHIP_REVISION_ID) >> 16) >= 2) {
230a8fc7648SRyan Chen 		//after A2 version
23185d48d8cSryan_chen 		if (apll_reg & BIT(24)) {
23285d48d8cSryan_chen 			/* Pass through mode */
233ed3899c5SRyan Chen 			mult = 1;
234ed3899c5SRyan Chen 			div = 1;
23585d48d8cSryan_chen 		} else {
23685d48d8cSryan_chen 			/* F = 25Mhz * [(m + 1) / (n + 1)] / (p + 1) */
23785d48d8cSryan_chen 			u32 m = apll_reg & 0x1fff;
23885d48d8cSryan_chen 			u32 n = (apll_reg >> 13) & 0x3f;
23985d48d8cSryan_chen 			u32 p = (apll_reg >> 19) & 0xf;
24085d48d8cSryan_chen 
24185d48d8cSryan_chen 			mult = (m + 1);
24285d48d8cSryan_chen 			div = (n + 1) * (p + 1);
24385d48d8cSryan_chen 		}
24485d48d8cSryan_chen 	} else {
24539283ea7Sryan_chen 		if (apll_reg & BIT(20)) {
246d6e349c7Sryan_chen 			/* Pass through mode */
247ed3899c5SRyan Chen 			mult = 1;
248ed3899c5SRyan Chen 			div = 1;
249d6e349c7Sryan_chen 		} else {
250bbbfb0c5Sryan_chen 			/* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */
25139283ea7Sryan_chen 			u32 m = (apll_reg >> 5) & 0x3f;
25239283ea7Sryan_chen 			u32 od = (apll_reg >> 4) & 0x1;
25339283ea7Sryan_chen 			u32 n = apll_reg & 0xf;
254d6e349c7Sryan_chen 
255bbbfb0c5Sryan_chen 			mult = (2 - od) * (m + 2);
256bbbfb0c5Sryan_chen 			div = n + 1;
257d6e349c7Sryan_chen 		}
25885d48d8cSryan_chen 	}
259a8fc7648SRyan Chen 
260bbbfb0c5Sryan_chen 	return ((clkin * mult) / div);
26139283ea7Sryan_chen }
26239283ea7Sryan_chen 
263d812df15Sryan_chen static u32 ast2600_a0_axi_ahb_div_table[] = {
2645d05f4fcSRyan Chen 	2,
2655d05f4fcSRyan Chen 	2,
2665d05f4fcSRyan Chen 	3,
2675d05f4fcSRyan Chen 	4,
268d812df15Sryan_chen };
269d812df15Sryan_chen 
27045e0908aSryan_chen static u32 ast2600_a1_axi_ahb_div0_table[] = {
2715d05f4fcSRyan Chen 	3,
2725d05f4fcSRyan Chen 	2,
2735d05f4fcSRyan Chen 	3,
2745d05f4fcSRyan Chen 	4,
27545e0908aSryan_chen };
27645e0908aSryan_chen 
27745e0908aSryan_chen static u32 ast2600_a1_axi_ahb_div1_table[] = {
2785d05f4fcSRyan Chen 	3,
2795d05f4fcSRyan Chen 	4,
2805d05f4fcSRyan Chen 	6,
2815d05f4fcSRyan Chen 	8,
282e29dc694Sryan_chen };
283e29dc694Sryan_chen 
284e29dc694Sryan_chen static u32 ast2600_a1_axi_ahb_default_table[] = {
285e29dc694Sryan_chen 	3, 4, 3, 4, 2, 2, 2, 2,
286d812df15Sryan_chen };
287d812df15Sryan_chen 
288d812df15Sryan_chen static u32 ast2600_get_hclk(struct ast2600_scu *scu)
289d812df15Sryan_chen {
29085d48d8cSryan_chen 	u32 hw_rev = readl(&scu->chip_id1);
29145e0908aSryan_chen 	u32 hwstrap1 = readl(&scu->hwstrap1.hwstrap);
292d812df15Sryan_chen 	u32 axi_div = 1;
293d812df15Sryan_chen 	u32 ahb_div = 0;
294d812df15Sryan_chen 	u32 rate = 0;
295d812df15Sryan_chen 
29685d48d8cSryan_chen 	if ((hw_rev & CHIP_REVISION_ID) >> 16) {
297a8fc7648SRyan Chen 		//After A0
29845e0908aSryan_chen 		if (hwstrap1 & BIT(16)) {
299a8fc7648SRyan Chen 			ast2600_a1_axi_ahb_div1_table[0] =
3005d05f4fcSRyan Chen 				ast2600_a1_axi_ahb_default_table[(hwstrap1 >> 8) &
30122545706SRyan Chen 								 0x7] * 2;
302d812df15Sryan_chen 			axi_div = 1;
3035d05f4fcSRyan Chen 			ahb_div =
3045d05f4fcSRyan Chen 				ast2600_a1_axi_ahb_div1_table[(hwstrap1 >> 11) &
3055d05f4fcSRyan Chen 							      0x3];
30645e0908aSryan_chen 		} else {
307a8fc7648SRyan Chen 			ast2600_a1_axi_ahb_div0_table[0] =
3085d05f4fcSRyan Chen 				ast2600_a1_axi_ahb_default_table[(hwstrap1 >> 8) &
30922545706SRyan Chen 								 0x7];
310d812df15Sryan_chen 			axi_div = 2;
3115d05f4fcSRyan Chen 			ahb_div =
3125d05f4fcSRyan Chen 				ast2600_a1_axi_ahb_div0_table[(hwstrap1 >> 11) &
3135d05f4fcSRyan Chen 							      0x3];
31445e0908aSryan_chen 		}
31545e0908aSryan_chen 	} else {
316a8fc7648SRyan Chen 		//A0 : fix axi = hpll / 2
31745e0908aSryan_chen 		axi_div = 2;
318d812df15Sryan_chen 		ahb_div = ast2600_a0_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3];
31945e0908aSryan_chen 	}
320bbbfb0c5Sryan_chen 	rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
321a8fc7648SRyan Chen 
3222717883aSryan_chen 	return (rate / axi_div / ahb_div);
3232717883aSryan_chen }
3242717883aSryan_chen 
325c304f173Sryan_chen static u32 ast2600_get_bclk_rate(struct ast2600_scu *scu)
326c304f173Sryan_chen {
327c304f173Sryan_chen 	u32 rate;
328c304f173Sryan_chen 	u32 bclk_sel = (readl(&scu->clk_sel1) >> 20) & 0x7;
329ed3899c5SRyan Chen 
330c304f173Sryan_chen 	rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
331c304f173Sryan_chen 
332c304f173Sryan_chen 	return (rate / ((bclk_sel + 1) * 4));
333c304f173Sryan_chen }
334c304f173Sryan_chen 
3356fa1ef3dSryan_chen static u32 ast2600_hpll_pclk1_div_table[] = {
3362717883aSryan_chen 	4, 8, 12, 16, 20, 24, 28, 32,
3372717883aSryan_chen };
3382717883aSryan_chen 
3396fa1ef3dSryan_chen static u32 ast2600_hpll_pclk2_div_table[] = {
3406fa1ef3dSryan_chen 	2, 4, 6, 8, 10, 12, 14, 16,
3416fa1ef3dSryan_chen };
3426fa1ef3dSryan_chen 
3436fa1ef3dSryan_chen static u32 ast2600_get_pclk1(struct ast2600_scu *scu)
3442717883aSryan_chen {
3452717883aSryan_chen 	u32 clk_sel1 = readl(&scu->clk_sel1);
3466fa1ef3dSryan_chen 	u32 apb_div = ast2600_hpll_pclk1_div_table[((clk_sel1 >> 23) & 0x7)];
347bbbfb0c5Sryan_chen 	u32 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
3482717883aSryan_chen 
3492717883aSryan_chen 	return (rate / apb_div);
350d812df15Sryan_chen }
351d812df15Sryan_chen 
3526fa1ef3dSryan_chen static u32 ast2600_get_pclk2(struct ast2600_scu *scu)
3536fa1ef3dSryan_chen {
3546fa1ef3dSryan_chen 	u32 clk_sel4 = readl(&scu->clk_sel4);
3556fa1ef3dSryan_chen 	u32 apb_div = ast2600_hpll_pclk2_div_table[((clk_sel4 >> 9) & 0x7)];
3566fa1ef3dSryan_chen 	u32 rate = ast2600_get_hclk(scu);
3576fa1ef3dSryan_chen 
3586fa1ef3dSryan_chen 	return (rate / apb_div);
3596fa1ef3dSryan_chen }
3606fa1ef3dSryan_chen 
3612e195992Sryan_chen static u32 ast2600_get_uxclk_in_rate(struct ast2600_scu *scu)
362d6e349c7Sryan_chen {
36327881d20Sryan_chen 	u32 clk_in = 0;
3642e195992Sryan_chen 	u32 uxclk_sel = readl(&scu->clk_sel5);
365550e691bSryan_chen 
36627881d20Sryan_chen 	uxclk_sel &= 0x3;
36727881d20Sryan_chen 	switch (uxclk_sel) {
36827881d20Sryan_chen 	case 0:
36927881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu) / 4;
37027881d20Sryan_chen 		break;
37127881d20Sryan_chen 	case 1:
37227881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu) / 2;
37327881d20Sryan_chen 		break;
37427881d20Sryan_chen 	case 2:
37527881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu);
37627881d20Sryan_chen 		break;
37727881d20Sryan_chen 	case 3:
37827881d20Sryan_chen 		clk_in = ast2600_get_hclk(scu);
37927881d20Sryan_chen 		break;
38027881d20Sryan_chen 	}
381d6e349c7Sryan_chen 
38227881d20Sryan_chen 	return clk_in;
38327881d20Sryan_chen }
38427881d20Sryan_chen 
3852e195992Sryan_chen static u32 ast2600_get_huxclk_in_rate(struct ast2600_scu *scu)
38627881d20Sryan_chen {
38727881d20Sryan_chen 	u32 clk_in = 0;
3882e195992Sryan_chen 	u32 huclk_sel = readl(&scu->clk_sel5);
38927881d20Sryan_chen 
39027881d20Sryan_chen 	huclk_sel = ((huclk_sel >> 3) & 0x3);
39127881d20Sryan_chen 	switch (huclk_sel) {
39227881d20Sryan_chen 	case 0:
39327881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu) / 4;
39427881d20Sryan_chen 		break;
39527881d20Sryan_chen 	case 1:
39627881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu) / 2;
39727881d20Sryan_chen 		break;
39827881d20Sryan_chen 	case 2:
39927881d20Sryan_chen 		clk_in = ast2600_get_apll_rate(scu);
40027881d20Sryan_chen 		break;
40127881d20Sryan_chen 	case 3:
40227881d20Sryan_chen 		clk_in = ast2600_get_hclk(scu);
40327881d20Sryan_chen 		break;
40427881d20Sryan_chen 	}
40527881d20Sryan_chen 
40627881d20Sryan_chen 	return clk_in;
40727881d20Sryan_chen }
40827881d20Sryan_chen 
4092e195992Sryan_chen static u32 ast2600_get_uart_uxclk_rate(struct ast2600_scu *scu)
41027881d20Sryan_chen {
4112e195992Sryan_chen 	u32 clk_in = ast2600_get_uxclk_in_rate(scu);
41227881d20Sryan_chen 	u32 div_reg = readl(&scu->uart_24m_ref_uxclk);
41327881d20Sryan_chen 	unsigned int mult, div;
41427881d20Sryan_chen 
41527881d20Sryan_chen 	u32 n = (div_reg >> 8) & 0x3ff;
41627881d20Sryan_chen 	u32 r = div_reg & 0xff;
41727881d20Sryan_chen 
41827881d20Sryan_chen 	mult = r;
4192e195992Sryan_chen 	div = (n * 2);
42027881d20Sryan_chen 	return (clk_in * mult) / div;
42127881d20Sryan_chen }
42227881d20Sryan_chen 
4232e195992Sryan_chen static u32 ast2600_get_uart_huxclk_rate(struct ast2600_scu *scu)
42427881d20Sryan_chen {
4252e195992Sryan_chen 	u32 clk_in = ast2600_get_huxclk_in_rate(scu);
42627881d20Sryan_chen 	u32 div_reg = readl(&scu->uart_24m_ref_huxclk);
42727881d20Sryan_chen 
42827881d20Sryan_chen 	unsigned int mult, div;
42927881d20Sryan_chen 
43027881d20Sryan_chen 	u32 n = (div_reg >> 8) & 0x3ff;
43127881d20Sryan_chen 	u32 r = div_reg & 0xff;
43227881d20Sryan_chen 
43327881d20Sryan_chen 	mult = r;
4342e195992Sryan_chen 	div = (n * 2);
43527881d20Sryan_chen 	return (clk_in * mult) / div;
43627881d20Sryan_chen }
43727881d20Sryan_chen 
438f51926eeSryan_chen static u32 ast2600_get_sdio_clk_rate(struct ast2600_scu *scu)
439f51926eeSryan_chen {
440f51926eeSryan_chen 	u32 clkin = 0;
441f51926eeSryan_chen 	u32 clk_sel = readl(&scu->clk_sel4);
442f51926eeSryan_chen 	u32 div = (clk_sel >> 28) & 0x7;
4438004dfdeSChin-Ting Kuo 	u32 hw_rev = readl(&scu->chip_id1);
444f51926eeSryan_chen 
445ed3899c5SRyan Chen 	if (clk_sel & BIT(8))
446f51926eeSryan_chen 		clkin = ast2600_get_apll_rate(scu);
447ed3899c5SRyan Chen 	else
44810069884Sryan_chen 		clkin = ast2600_get_hclk(scu);
449ed3899c5SRyan Chen 
4508004dfdeSChin-Ting Kuo 	div = (1 + div) * 2;
4518004dfdeSChin-Ting Kuo 	if (((hw_rev & GENMASK(23, 16)) >> 16) >= 2)
4528004dfdeSChin-Ting Kuo 		div = (div & 0xf) ? div : 1;
453f51926eeSryan_chen 
454f51926eeSryan_chen 	return (clkin / div);
455f51926eeSryan_chen }
456f51926eeSryan_chen 
457f51926eeSryan_chen static u32 ast2600_get_emmc_clk_rate(struct ast2600_scu *scu)
458f51926eeSryan_chen {
459125f2e11SChin-Ting Kuo 	u32 mmc_clk_src = readl(&scu->clk_sel1);
460125f2e11SChin-Ting Kuo 	u32 clkin;
461f51926eeSryan_chen 	u32 clk_sel = readl(&scu->clk_sel1);
462f51926eeSryan_chen 	u32 div = (clk_sel >> 12) & 0x7;
463f51926eeSryan_chen 
464125f2e11SChin-Ting Kuo 	if (mmc_clk_src & BIT(11)) {
465125f2e11SChin-Ting Kuo 		/* emmc clock comes from MPLL */
466125f2e11SChin-Ting Kuo 		clkin = ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
467125f2e11SChin-Ting Kuo 		div = (div + 1) * 2;
468125f2e11SChin-Ting Kuo 	} else {
469125f2e11SChin-Ting Kuo 		clkin = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
470f51926eeSryan_chen 		div = (div + 1) << 2;
471125f2e11SChin-Ting Kuo 	}
472f51926eeSryan_chen 
473f51926eeSryan_chen 	return (clkin / div);
474f51926eeSryan_chen }
475f51926eeSryan_chen 
476f51926eeSryan_chen static u32 ast2600_get_uart_clk_rate(struct ast2600_scu *scu, int uart_idx)
47727881d20Sryan_chen {
478de49ffa7SChia-Wei Wang 	u32 hicr9 = readl(0x1e789098);
47927881d20Sryan_chen 	u32 uart_sel = readl(&scu->clk_sel4);
48027881d20Sryan_chen 	u32 uart_sel5 = readl(&scu->clk_sel5);
48127881d20Sryan_chen 	ulong uart_clk = 0;
48227881d20Sryan_chen 
48327881d20Sryan_chen 	switch (uart_idx) {
48427881d20Sryan_chen 	case 1:
48527881d20Sryan_chen 	case 2:
48627881d20Sryan_chen 	case 3:
48727881d20Sryan_chen 	case 4:
488de49ffa7SChia-Wei Wang 		hicr9 &= ~(BIT(uart_idx + 3));
489de49ffa7SChia-Wei Wang 		writel(hicr9, 0x1e789098);
49027881d20Sryan_chen 	case 6:
49127881d20Sryan_chen 		if (uart_sel & BIT(uart_idx - 1))
4922e195992Sryan_chen 			uart_clk = ast2600_get_uart_huxclk_rate(scu);
493550e691bSryan_chen 		else
4942e195992Sryan_chen 			uart_clk = ast2600_get_uart_uxclk_rate(scu);
49527881d20Sryan_chen 		break;
49627881d20Sryan_chen 	case 5: //24mhz is come form usb phy 48Mhz
49727881d20Sryan_chen 	{
49827881d20Sryan_chen 		u8 uart5_clk_sel = 0;
49927881d20Sryan_chen 		//high bit
50027881d20Sryan_chen 		if (readl(&scu->misc_ctrl1) & BIT(12))
50127881d20Sryan_chen 			uart5_clk_sel = 0x2;
50227881d20Sryan_chen 		else
50327881d20Sryan_chen 			uart5_clk_sel = 0x0;
504550e691bSryan_chen 
50527881d20Sryan_chen 		if (readl(&scu->clk_sel2) & BIT(14))
50627881d20Sryan_chen 			uart5_clk_sel |= 0x1;
507550e691bSryan_chen 
50827881d20Sryan_chen 		switch (uart5_clk_sel) {
50927881d20Sryan_chen 		case 0:
51027881d20Sryan_chen 			uart_clk = 24000000;
51127881d20Sryan_chen 			break;
51227881d20Sryan_chen 		case 1:
513def99fcbSryan_chen 			uart_clk = 192000000;
51427881d20Sryan_chen 			break;
51527881d20Sryan_chen 		case 2:
51627881d20Sryan_chen 			uart_clk = 24000000 / 13;
51727881d20Sryan_chen 			break;
51827881d20Sryan_chen 		case 3:
51927881d20Sryan_chen 			uart_clk = 192000000 / 13;
52027881d20Sryan_chen 			break;
52127881d20Sryan_chen 		}
5225d05f4fcSRyan Chen 	} break;
52327881d20Sryan_chen 	case 7:
52427881d20Sryan_chen 	case 8:
52527881d20Sryan_chen 	case 9:
52627881d20Sryan_chen 	case 10:
52727881d20Sryan_chen 	case 11:
52827881d20Sryan_chen 	case 12:
52927881d20Sryan_chen 	case 13:
53027881d20Sryan_chen 		if (uart_sel5 & BIT(uart_idx - 1))
5312e195992Sryan_chen 			uart_clk = ast2600_get_uart_huxclk_rate(scu);
53227881d20Sryan_chen 		else
5332e195992Sryan_chen 			uart_clk = ast2600_get_uart_uxclk_rate(scu);
53427881d20Sryan_chen 		break;
53527881d20Sryan_chen 	}
53627881d20Sryan_chen 
53727881d20Sryan_chen 	return uart_clk;
538550e691bSryan_chen }
539550e691bSryan_chen 
540feb42054Sryan_chen static ulong ast2600_clk_get_rate(struct clk *clk)
541feb42054Sryan_chen {
542feb42054Sryan_chen 	struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
543feb42054Sryan_chen 	ulong rate = 0;
544feb42054Sryan_chen 
545feb42054Sryan_chen 	switch (clk->id) {
546feb42054Sryan_chen 	case ASPEED_CLK_HPLL:
547bbbfb0c5Sryan_chen 	case ASPEED_CLK_EPLL:
548bbbfb0c5Sryan_chen 	case ASPEED_CLK_DPLL:
549d812df15Sryan_chen 	case ASPEED_CLK_MPLL:
550bbbfb0c5Sryan_chen 		rate = ast2600_get_pll_rate(priv->scu, clk->id);
551d812df15Sryan_chen 		break;
552feb42054Sryan_chen 	case ASPEED_CLK_AHB:
553feb42054Sryan_chen 		rate = ast2600_get_hclk(priv->scu);
554feb42054Sryan_chen 		break;
5556fa1ef3dSryan_chen 	case ASPEED_CLK_APB1:
5566fa1ef3dSryan_chen 		rate = ast2600_get_pclk1(priv->scu);
5576fa1ef3dSryan_chen 		break;
5586fa1ef3dSryan_chen 	case ASPEED_CLK_APB2:
5596fa1ef3dSryan_chen 		rate = ast2600_get_pclk2(priv->scu);
560feb42054Sryan_chen 		break;
561bbbfb0c5Sryan_chen 	case ASPEED_CLK_APLL:
562bbbfb0c5Sryan_chen 		rate = ast2600_get_apll_rate(priv->scu);
563bbbfb0c5Sryan_chen 		break;
564feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART1CLK:
565feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 1);
566feb42054Sryan_chen 		break;
567feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART2CLK:
568feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 2);
569feb42054Sryan_chen 		break;
570feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART3CLK:
571feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 3);
572feb42054Sryan_chen 		break;
573feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART4CLK:
574feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 4);
575feb42054Sryan_chen 		break;
576feb42054Sryan_chen 	case ASPEED_CLK_GATE_UART5CLK:
577feb42054Sryan_chen 		rate = ast2600_get_uart_clk_rate(priv->scu, 5);
578feb42054Sryan_chen 		break;
579c304f173Sryan_chen 	case ASPEED_CLK_BCLK:
580c304f173Sryan_chen 		rate = ast2600_get_bclk_rate(priv->scu);
581c304f173Sryan_chen 		break;
582f51926eeSryan_chen 	case ASPEED_CLK_SDIO:
583f51926eeSryan_chen 		rate = ast2600_get_sdio_clk_rate(priv->scu);
584f51926eeSryan_chen 		break;
585f51926eeSryan_chen 	case ASPEED_CLK_EMMC:
586f51926eeSryan_chen 		rate = ast2600_get_emmc_clk_rate(priv->scu);
587f51926eeSryan_chen 		break;
5882e195992Sryan_chen 	case ASPEED_CLK_UARTX:
5892e195992Sryan_chen 		rate = ast2600_get_uart_uxclk_rate(priv->scu);
5902e195992Sryan_chen 		break;
5910998ddefSryan_chen 	case ASPEED_CLK_HUARTX:
5922e195992Sryan_chen 		rate = ast2600_get_uart_huxclk_rate(priv->scu);
5932e195992Sryan_chen 		break;
594feb42054Sryan_chen 	default:
595d812df15Sryan_chen 		pr_debug("can't get clk rate\n");
596feb42054Sryan_chen 		return -ENOENT;
597feb42054Sryan_chen 	}
598feb42054Sryan_chen 
599feb42054Sryan_chen 	return rate;
600feb42054Sryan_chen }
601feb42054Sryan_chen 
602577fcdaeSDylan Hung /**
603577fcdaeSDylan Hung  * @brief	lookup PLL divider config by input/output rate
604577fcdaeSDylan Hung  * @param[in]	*pll - PLL descriptor
605577fcdaeSDylan Hung  * @return	true - if PLL divider config is found, false - else
606a8fc7648SRyan Chen  * The function caller shall fill "pll->in" and "pll->out",
607a8fc7648SRyan Chen  * then this function will search the lookup table
608a8fc7648SRyan Chen  * to find a valid PLL divider configuration.
609550e691bSryan_chen  */
610577fcdaeSDylan Hung static bool ast2600_search_clock_config(struct ast2600_pll_desc *pll)
611550e691bSryan_chen {
612577fcdaeSDylan Hung 	u32 i;
613577fcdaeSDylan Hung 	bool is_found = false;
614550e691bSryan_chen 
615577fcdaeSDylan Hung 	for (i = 0; i < ARRAY_SIZE(ast2600_pll_lookup); i++) {
616577fcdaeSDylan Hung 		const struct ast2600_pll_desc *def_cfg = &ast2600_pll_lookup[i];
617ed3899c5SRyan Chen 
618ed3899c5SRyan Chen 		if (def_cfg->in == pll->in && def_cfg->out == pll->out) {
619577fcdaeSDylan Hung 			is_found = true;
620577fcdaeSDylan Hung 			pll->cfg.reg.w = def_cfg->cfg.reg.w;
621577fcdaeSDylan Hung 			pll->cfg.ext_reg = def_cfg->cfg.ext_reg;
622577fcdaeSDylan Hung 			break;
623550e691bSryan_chen 		}
624550e691bSryan_chen 	}
625577fcdaeSDylan Hung 	return is_found;
626550e691bSryan_chen }
627ed3899c5SRyan Chen 
628fd52be0bSDylan Hung static u32 ast2600_configure_pll(struct ast2600_scu *scu,
629fd52be0bSDylan Hung 				 struct ast2600_pll_cfg *p_cfg, int pll_idx)
630fd52be0bSDylan Hung {
631fd52be0bSDylan Hung 	u32 addr, addr_ext;
632fd52be0bSDylan Hung 	u32 reg;
633550e691bSryan_chen 
634fd52be0bSDylan Hung 	switch (pll_idx) {
635fd52be0bSDylan Hung 	case ASPEED_CLK_HPLL:
636fd52be0bSDylan Hung 		addr = (u32)(&scu->h_pll_param);
637fd52be0bSDylan Hung 		addr_ext = (u32)(&scu->h_pll_ext_param);
638fd52be0bSDylan Hung 		break;
639fd52be0bSDylan Hung 	case ASPEED_CLK_MPLL:
640fd52be0bSDylan Hung 		addr = (u32)(&scu->m_pll_param);
641fd52be0bSDylan Hung 		addr_ext = (u32)(&scu->m_pll_ext_param);
642fd52be0bSDylan Hung 		break;
643fd52be0bSDylan Hung 	case ASPEED_CLK_DPLL:
644fd52be0bSDylan Hung 		addr = (u32)(&scu->d_pll_param);
645fd52be0bSDylan Hung 		addr_ext = (u32)(&scu->d_pll_ext_param);
646fd52be0bSDylan Hung 		break;
647fd52be0bSDylan Hung 	case ASPEED_CLK_EPLL:
648fd52be0bSDylan Hung 		addr = (u32)(&scu->e_pll_param);
649fd52be0bSDylan Hung 		addr_ext = (u32)(&scu->e_pll_ext_param);
650fd52be0bSDylan Hung 		break;
651fd52be0bSDylan Hung 	default:
652fd52be0bSDylan Hung 		debug("unknown PLL index\n");
653fd52be0bSDylan Hung 		return 1;
654fd52be0bSDylan Hung 	}
655fd52be0bSDylan Hung 
656fd52be0bSDylan Hung 	p_cfg->reg.b.bypass = 0;
657fd52be0bSDylan Hung 	p_cfg->reg.b.off = 1;
658fd52be0bSDylan Hung 	p_cfg->reg.b.reset = 1;
659fd52be0bSDylan Hung 
660fd52be0bSDylan Hung 	reg = readl(addr);
661fd52be0bSDylan Hung 	reg &= ~GENMASK(25, 0);
662fd52be0bSDylan Hung 	reg |= p_cfg->reg.w;
663fd52be0bSDylan Hung 	writel(reg, addr);
664fd52be0bSDylan Hung 
665fd52be0bSDylan Hung 	/* write extend parameter */
666fd52be0bSDylan Hung 	writel(p_cfg->ext_reg, addr_ext);
667fd52be0bSDylan Hung 	udelay(100);
668fd52be0bSDylan Hung 	p_cfg->reg.b.off = 0;
669fd52be0bSDylan Hung 	p_cfg->reg.b.reset = 0;
670fd52be0bSDylan Hung 	reg &= ~GENMASK(25, 0);
671fd52be0bSDylan Hung 	reg |= p_cfg->reg.w;
672fd52be0bSDylan Hung 	writel(reg, addr);
673ed3899c5SRyan Chen 	while (!(readl(addr_ext) & BIT(31)))
674ed3899c5SRyan Chen 		;
675fd52be0bSDylan Hung 
676fd52be0bSDylan Hung 	return 0;
677fd52be0bSDylan Hung }
678ed3899c5SRyan Chen 
679feb42054Sryan_chen static u32 ast2600_configure_ddr(struct ast2600_scu *scu, ulong rate)
680550e691bSryan_chen {
681577fcdaeSDylan Hung 	struct ast2600_pll_desc mpll;
682550e691bSryan_chen 
683577fcdaeSDylan Hung 	mpll.in = AST2600_CLK_IN;
684577fcdaeSDylan Hung 	mpll.out = rate;
685f27685ebSRyan Chen 	if (ast2600_search_clock_config(&mpll) == false) {
686577fcdaeSDylan Hung 		printf("error!! unable to find valid DDR clock setting\n");
687577fcdaeSDylan Hung 		return 0;
688577fcdaeSDylan Hung 	}
689ed3899c5SRyan Chen 	ast2600_configure_pll(scu, &mpll.cfg, ASPEED_CLK_MPLL);
690577fcdaeSDylan Hung 
691cc476ffcSDylan Hung 	return ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
692d6e349c7Sryan_chen }
693d6e349c7Sryan_chen 
694d6e349c7Sryan_chen static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate)
695550e691bSryan_chen {
696f0d895afSryan_chen 	struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
697550e691bSryan_chen 	ulong new_rate;
698ed3899c5SRyan Chen 
699550e691bSryan_chen 	switch (clk->id) {
700f0d895afSryan_chen 	case ASPEED_CLK_MPLL:
701feb42054Sryan_chen 		new_rate = ast2600_configure_ddr(priv->scu, rate);
702550e691bSryan_chen 		break;
703550e691bSryan_chen 	default:
704550e691bSryan_chen 		return -ENOENT;
705550e691bSryan_chen 	}
706550e691bSryan_chen 
707550e691bSryan_chen 	return new_rate;
708550e691bSryan_chen }
709feb42054Sryan_chen 
710f9aa0ee1Sryan_chen #define SCU_CLKSTOP_MAC1	(20)
711f9aa0ee1Sryan_chen #define SCU_CLKSTOP_MAC2	(21)
712f9aa0ee1Sryan_chen #define SCU_CLKSTOP_MAC3	(20)
713f9aa0ee1Sryan_chen #define SCU_CLKSTOP_MAC4	(21)
714f9aa0ee1Sryan_chen 
715a98c71fbSDylan Hung static u32 ast2600_configure_mac12_clk(struct ast2600_scu *scu, struct udevice *dev)
716cc476ffcSDylan Hung {
717a98c71fbSDylan Hung 	struct mac_delay_config mac1_cfg, mac2_cfg;
718*e40a4e44SDylan Hung 	u32 reg[3];
719a98c71fbSDylan Hung 	int ret;
7204760b3f8SDylan Hung 
721*e40a4e44SDylan Hung 	reg[0] = MAC_DEF_DELAY_1G;
722*e40a4e44SDylan Hung 	reg[1] = MAC_DEF_DELAY_100M;
723*e40a4e44SDylan Hung 	reg[2] = MAC_DEF_DELAY_10M;
724a98c71fbSDylan Hung 
725*e40a4e44SDylan Hung 	ret = dev_read_u32_array(dev, "mac0-clk-delay", (u32 *)&mac1_cfg,
726*e40a4e44SDylan Hung 				 sizeof(mac1_cfg) / sizeof(u32));
727a98c71fbSDylan Hung 	if (!ret) {
728*e40a4e44SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_1);
729*e40a4e44SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, mac1_cfg.rx_delay_1000) |
730*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, mac1_cfg.tx_delay_1000);
731*e40a4e44SDylan Hung 
732*e40a4e44SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
733*e40a4e44SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac1_cfg.rx_delay_100) |
734*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac1_cfg.tx_delay_100);
735*e40a4e44SDylan Hung 
736*e40a4e44SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
737*e40a4e44SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac1_cfg.rx_delay_10) |
738*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac1_cfg.tx_delay_10);
739a98c71fbSDylan Hung 	}
740a98c71fbSDylan Hung 
741*e40a4e44SDylan Hung 	ret = dev_read_u32_array(dev, "mac1-clk-delay", (u32 *)&mac2_cfg,
742*e40a4e44SDylan Hung 				 sizeof(mac2_cfg) / sizeof(u32));
743a98c71fbSDylan Hung 	if (!ret) {
744*e40a4e44SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_2 | MAC_CLK_1G_OUTPUT_DELAY_2);
745*e40a4e44SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, mac2_cfg.rx_delay_1000) |
746*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, mac2_cfg.tx_delay_1000);
747*e40a4e44SDylan Hung 
748*e40a4e44SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
749*e40a4e44SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac2_cfg.rx_delay_100) |
750*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac2_cfg.tx_delay_100);
751*e40a4e44SDylan Hung 
752*e40a4e44SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
753*e40a4e44SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac2_cfg.rx_delay_10) |
754*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac2_cfg.tx_delay_10);
755a98c71fbSDylan Hung 	}
756a98c71fbSDylan Hung 
757*e40a4e44SDylan Hung 	reg[0] |= (readl(&scu->mac12_clk_delay) & ~GENMASK(25, 0));
758*e40a4e44SDylan Hung 	writel(reg[0], &scu->mac12_clk_delay);
759*e40a4e44SDylan Hung 	writel(reg[1], &scu->mac12_clk_delay_100M);
760*e40a4e44SDylan Hung 	writel(reg[2], &scu->mac12_clk_delay_10M);
761cc476ffcSDylan Hung 
762ed30249cSDylan Hung 	/* MAC AHB = HPLL / 6 */
763eff28274SJohnny Huang 	clrsetbits_le32(&scu->clk_sel1, GENMASK(18, 16), (0x2 << 16));
764894c19cfSDylan Hung 
765cc476ffcSDylan Hung 	return 0;
766cc476ffcSDylan Hung }
767cc476ffcSDylan Hung 
768a98c71fbSDylan Hung static u32 ast2600_configure_mac34_clk(struct ast2600_scu *scu, struct udevice *dev)
76954f9cba1SDylan Hung {
770a98c71fbSDylan Hung 	struct mac_delay_config mac3_cfg, mac4_cfg;
771*e40a4e44SDylan Hung 	u32 reg[3];
772a98c71fbSDylan Hung 	int ret;
773a98c71fbSDylan Hung 
774*e40a4e44SDylan Hung 	reg[0] = MAC34_DEF_DELAY_1G;
775*e40a4e44SDylan Hung 	reg[1] = MAC34_DEF_DELAY_100M;
776*e40a4e44SDylan Hung 	reg[2] = MAC34_DEF_DELAY_10M;
777a98c71fbSDylan Hung 
778a98c71fbSDylan Hung 	ret = dev_read_u32_array(dev, "mac2-clk-delay", (u32 *)&mac3_cfg, sizeof(mac3_cfg) / sizeof(u32));
779a98c71fbSDylan Hung 	if (!ret) {
780*e40a4e44SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_1);
781*e40a4e44SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, mac3_cfg.rx_delay_1000) |
782*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, mac3_cfg.tx_delay_1000);
783*e40a4e44SDylan Hung 
784*e40a4e44SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
785*e40a4e44SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac3_cfg.rx_delay_100) |
786*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac3_cfg.tx_delay_100);
787*e40a4e44SDylan Hung 
788*e40a4e44SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
789*e40a4e44SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac3_cfg.rx_delay_10) |
790*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac3_cfg.tx_delay_10);
791a98c71fbSDylan Hung 	}
792a98c71fbSDylan Hung 
793a98c71fbSDylan Hung 	ret = dev_read_u32_array(dev, "mac3-clk-delay", (u32 *)&mac4_cfg, sizeof(mac4_cfg) / sizeof(u32));
794a98c71fbSDylan Hung 	if (!ret) {
795*e40a4e44SDylan Hung 		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_2 | MAC_CLK_1G_OUTPUT_DELAY_2);
796*e40a4e44SDylan Hung 		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, mac4_cfg.rx_delay_1000) |
797*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, mac4_cfg.tx_delay_1000);
798*e40a4e44SDylan Hung 
799*e40a4e44SDylan Hung 		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
800*e40a4e44SDylan Hung 		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac4_cfg.rx_delay_100) |
801*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac4_cfg.tx_delay_100);
802*e40a4e44SDylan Hung 
803*e40a4e44SDylan Hung 		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
804*e40a4e44SDylan Hung 		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac4_cfg.rx_delay_10) |
805*e40a4e44SDylan Hung 			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac4_cfg.tx_delay_10);
806a98c71fbSDylan Hung 	}
807a98c71fbSDylan Hung 
808*e40a4e44SDylan Hung 	reg[0] |= (readl(&scu->mac34_clk_delay) & ~GENMASK(25, 0));
809*e40a4e44SDylan Hung 	reg[0] &= ~MAC_CLK_RGMII_125M_SRC_SEL;
810*e40a4e44SDylan Hung 	reg[0] |= FIELD_PREP(MAC_CLK_RGMII_125M_SRC_SEL, MAC_CLK_RGMII_125M_SRC_PAD_RGMIICK);
811*e40a4e44SDylan Hung 	writel(reg[0], &scu->mac34_clk_delay);
812*e40a4e44SDylan Hung 	writel(reg[1], &scu->mac34_clk_delay_100M);
813*e40a4e44SDylan Hung 	writel(reg[2], &scu->mac34_clk_delay_10M);
81454f9cba1SDylan Hung 
815eff28274SJohnny Huang 	/*
816eff28274SJohnny Huang 	 * clock source seletion and divider
817eff28274SJohnny Huang 	 * scu310[26:24] : MAC AHB bus clock = HCLK / 2
818eff28274SJohnny Huang 	 * scu310[18:16] : RMII 50M = HCLK_200M / 4
819eff28274SJohnny Huang 	 */
820eff28274SJohnny Huang 	clrsetbits_le32(&scu->clk_sel4, (GENMASK(26, 24) | GENMASK(18, 16)),
821eff28274SJohnny Huang 			((0x0 << 24) | (0x3 << 16)));
82254f9cba1SDylan Hung 
823eff28274SJohnny Huang 	/*
824eff28274SJohnny Huang 	 * set driving strength
825eff28274SJohnny Huang 	 * scu458[3:2] : MAC4 driving strength
826eff28274SJohnny Huang 	 * scu458[1:0] : MAC3 driving strength
827eff28274SJohnny Huang 	 */
828eff28274SJohnny Huang 	clrsetbits_le32(&scu->pinmux_ctrl16, GENMASK(3, 0),
829a961159eSDylan Hung 			(0x3 << 2) | (0x3 << 0));
83054f9cba1SDylan Hung 
83154f9cba1SDylan Hung 	return 0;
83254f9cba1SDylan Hung }
833eff28274SJohnny Huang 
83454f9cba1SDylan Hung /**
8355b5c3d44SDylan Hung  * ast2600 RGMII clock source tree
83654f9cba1SDylan Hung  * 125M from external PAD -------->|\
83754f9cba1SDylan Hung  * HPLL -->|\                      | |---->RGMII 125M for MAC#1 & MAC#2
83854f9cba1SDylan Hung  *         | |---->| divider |---->|/                             +
83954f9cba1SDylan Hung  * EPLL -->|/                                                     |
84054f9cba1SDylan Hung  *                                                                |
841eff28274SJohnny Huang  * +---------<-----------|RGMIICK PAD output enable|<-------------+
84254f9cba1SDylan Hung  * |
843eff28274SJohnny Huang  * +--------------------------->|\
84454f9cba1SDylan Hung  *                              | |----> RGMII 125M for MAC#3 & MAC#4
845eff28274SJohnny Huang  * HCLK 200M ---->|divider|---->|/
846eff28274SJohnny Huang  * To simplify the control flow:
847eff28274SJohnny Huang  * 1. RGMII 1/2 always use EPLL as the internal clock source
848eff28274SJohnny Huang  * 2. RGMII 3/4 always use RGMIICK pad as the RGMII 125M source
849eff28274SJohnny Huang  * 125M from external PAD -------->|\
850eff28274SJohnny Huang  *                                 | |---->RGMII 125M for MAC#1 & MAC#2
851eff28274SJohnny Huang  *         EPLL---->| divider |--->|/                             +
852eff28274SJohnny Huang  *                                                                |
853eff28274SJohnny Huang  * +<--------------------|RGMIICK PAD output enable|<-------------+
854eff28274SJohnny Huang  * |
855eff28274SJohnny Huang  * +--------------------------->RGMII 125M for MAC#3 & MAC#4
856eff28274SJohnny Huang  */
857eff28274SJohnny Huang #define RGMIICK_SRC_PAD		0
858eff28274SJohnny Huang #define RGMIICK_SRC_EPLL	1 /* recommended */
859eff28274SJohnny Huang #define RGMIICK_SRC_HPLL	2
860eff28274SJohnny Huang 
861eff28274SJohnny Huang #define RGMIICK_DIV2	1
862eff28274SJohnny Huang #define RGMIICK_DIV3	2
863eff28274SJohnny Huang #define RGMIICK_DIV4	3
864eff28274SJohnny Huang #define RGMIICK_DIV5	4
865eff28274SJohnny Huang #define RGMIICK_DIV6	5
866eff28274SJohnny Huang #define RGMIICK_DIV7	6
867eff28274SJohnny Huang #define RGMIICK_DIV8	7 /* recommended */
868eff28274SJohnny Huang 
869eff28274SJohnny Huang #define RMIICK_DIV4		0
870eff28274SJohnny Huang #define RMIICK_DIV8		1
871eff28274SJohnny Huang #define RMIICK_DIV12	2
872eff28274SJohnny Huang #define RMIICK_DIV16	3
873eff28274SJohnny Huang #define RMIICK_DIV20	4 /* recommended */
874eff28274SJohnny Huang #define RMIICK_DIV24	5
875eff28274SJohnny Huang #define RMIICK_DIV28	6
876eff28274SJohnny Huang #define RMIICK_DIV32	7
877eff28274SJohnny Huang 
878eff28274SJohnny Huang struct ast2600_mac_clk_div {
879eff28274SJohnny Huang 	u32 src; /* 0=external PAD, 1=internal PLL */
880eff28274SJohnny Huang 	u32 fin; /* divider input speed */
881eff28274SJohnny Huang 	u32 n; /* 0=div2, 1=div2, 2=div3, 3=div4,...,7=div8 */
882eff28274SJohnny Huang 	u32 fout; /* fout = fin / n */
883eff28274SJohnny Huang };
884eff28274SJohnny Huang 
885eff28274SJohnny Huang struct ast2600_mac_clk_div rgmii_clk_defconfig = {
886eff28274SJohnny Huang 	.src = ASPEED_CLK_EPLL,
887eff28274SJohnny Huang 	.fin = 1000000000,
888eff28274SJohnny Huang 	.n = RGMIICK_DIV8,
889eff28274SJohnny Huang 	.fout = 125000000,
890eff28274SJohnny Huang };
891eff28274SJohnny Huang 
892eff28274SJohnny Huang struct ast2600_mac_clk_div rmii_clk_defconfig = {
893eff28274SJohnny Huang 	.src = ASPEED_CLK_EPLL,
894eff28274SJohnny Huang 	.fin = 1000000000,
895eff28274SJohnny Huang 	.n = RMIICK_DIV20,
896eff28274SJohnny Huang 	.fout = 50000000,
897eff28274SJohnny Huang };
898ed3899c5SRyan Chen 
899eff28274SJohnny Huang static void ast2600_init_mac_pll(struct ast2600_scu *p_scu,
900eff28274SJohnny Huang 				 struct ast2600_mac_clk_div *p_cfg)
901eff28274SJohnny Huang {
902eff28274SJohnny Huang 	struct ast2600_pll_desc pll;
903eff28274SJohnny Huang 
904eff28274SJohnny Huang 	pll.in = AST2600_CLK_IN;
905eff28274SJohnny Huang 	pll.out = p_cfg->fin;
906ed3899c5SRyan Chen 	if (ast2600_search_clock_config(&pll) == false) {
907ed3899c5SRyan Chen 		pr_err("unable to find valid ETHNET MAC clock setting\n");
9083f295164SRyan Chen 		debug("%s: pll cfg = 0x%08x 0x%08x\n", __func__, pll.cfg.reg.w,
9093f295164SRyan Chen 		      pll.cfg.ext_reg);
9103f295164SRyan Chen 		debug("%s: pll cfg = %02x %02x %02x\n", __func__,
9113f295164SRyan Chen 		      pll.cfg.reg.b.m, pll.cfg.reg.b.n, pll.cfg.reg.b.p);
912eff28274SJohnny Huang 		return;
913eff28274SJohnny Huang 	}
914ed3899c5SRyan Chen 	ast2600_configure_pll(p_scu, &pll.cfg, p_cfg->src);
915eff28274SJohnny Huang }
916eff28274SJohnny Huang 
917eff28274SJohnny Huang static void ast2600_init_rgmii_clk(struct ast2600_scu *p_scu,
918eff28274SJohnny Huang 				   struct ast2600_mac_clk_div *p_cfg)
919eff28274SJohnny Huang {
920eff28274SJohnny Huang 	u32 reg_304 = readl(&p_scu->clk_sel2);
921eff28274SJohnny Huang 	u32 reg_340 = readl(&p_scu->mac12_clk_delay);
922eff28274SJohnny Huang 	u32 reg_350 = readl(&p_scu->mac34_clk_delay);
923eff28274SJohnny Huang 
924*e40a4e44SDylan Hung 	reg_340 &= ~(MAC_CLK_RGMII_125M_SRC_SEL | MAC_CLK_RMII2_50M_RCLK_O_CTRL |
925*e40a4e44SDylan Hung 		     MAC_CLK_RMII1_50M_RCLK_O_CTRL | MAC_CLK_RGMIICK_PAD_DIR);
926*e40a4e44SDylan Hung 	/* RGMIICK PAD output enable (to MAC 3/4) */
927*e40a4e44SDylan Hung 	reg_340 |= FIELD_PREP(MAC_CLK_RGMIICK_PAD_DIR, MAC_CLK_RGMIICK_PAD_DIR_OUTPUT);
9283f295164SRyan Chen 	if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
929eff28274SJohnny Huang 		/*
930eff28274SJohnny Huang 		 * re-init PLL if the current PLL output frequency doesn't match
931eff28274SJohnny Huang 		 * the divider setting
932eff28274SJohnny Huang 		 */
933ed3899c5SRyan Chen 		if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
934eff28274SJohnny Huang 			ast2600_init_mac_pll(p_scu, p_cfg);
935*e40a4e44SDylan Hung 		/* select RGMII 125M from internal source */
936*e40a4e44SDylan Hung 		reg_340 |= FIELD_PREP(MAC_CLK_RGMII_125M_SRC_SEL, MAC_CLK_RGMII_125M_SRC_PLL);
937eff28274SJohnny Huang 	}
938eff28274SJohnny Huang 
939eff28274SJohnny Huang 	reg_304 &= ~GENMASK(23, 20);
940eff28274SJohnny Huang 
941eff28274SJohnny Huang 	/* set clock divider */
942eff28274SJohnny Huang 	reg_304 |= (p_cfg->n & 0x7) << 20;
943eff28274SJohnny Huang 
944eff28274SJohnny Huang 	/* select internal clock source */
945ed3899c5SRyan Chen 	if (p_cfg->src == ASPEED_CLK_HPLL)
946eff28274SJohnny Huang 		reg_304 |= BIT(23);
947eff28274SJohnny Huang 
948eff28274SJohnny Huang 	/* RGMII 3/4 clock source select */
949eff28274SJohnny Huang 	reg_350 &= ~BIT(31);
950eff28274SJohnny Huang 
951eff28274SJohnny Huang 	writel(reg_304, &p_scu->clk_sel2);
952eff28274SJohnny Huang 	writel(reg_340, &p_scu->mac12_clk_delay);
953eff28274SJohnny Huang 	writel(reg_350, &p_scu->mac34_clk_delay);
954eff28274SJohnny Huang }
955eff28274SJohnny Huang 
956eff28274SJohnny Huang /**
9575b5c3d44SDylan Hung  * ast2600 RMII/NCSI clock source tree
9585b5c3d44SDylan Hung  * HPLL -->|\
9595b5c3d44SDylan Hung  *         | |---->| divider |----> RMII 50M for MAC#1 & MAC#2
9605b5c3d44SDylan Hung  * EPLL -->|/
9615b5c3d44SDylan Hung  * HCLK(SCLICLK)---->| divider |----> RMII 50M for MAC#3 & MAC#4
96254f9cba1SDylan Hung  */
963eff28274SJohnny Huang static void ast2600_init_rmii_clk(struct ast2600_scu *p_scu,
964eff28274SJohnny Huang 				  struct ast2600_mac_clk_div *p_cfg)
96554f9cba1SDylan Hung {
966eff28274SJohnny Huang 	u32 reg_304;
967eff28274SJohnny Huang 	u32 reg_310;
968eff28274SJohnny Huang 
9693f295164SRyan Chen 	if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
970eff28274SJohnny Huang 		/*
971eff28274SJohnny Huang 		 * re-init PLL if the current PLL output frequency doesn't match
972eff28274SJohnny Huang 		 * the divider setting
973eff28274SJohnny Huang 		 */
974ed3899c5SRyan Chen 		if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
975eff28274SJohnny Huang 			ast2600_init_mac_pll(p_scu, p_cfg);
976eff28274SJohnny Huang 	}
97754f9cba1SDylan Hung 
978eff28274SJohnny Huang 	reg_304 = readl(&p_scu->clk_sel2);
979eff28274SJohnny Huang 	reg_310 = readl(&p_scu->clk_sel4);
980eff28274SJohnny Huang 
981eff28274SJohnny Huang 	reg_304 &= ~GENMASK(19, 16);
982eff28274SJohnny Huang 
983eff28274SJohnny Huang 	/* set RMII 1/2 clock divider */
984eff28274SJohnny Huang 	reg_304 |= (p_cfg->n & 0x7) << 16;
985eff28274SJohnny Huang 
986eff28274SJohnny Huang 	/* RMII clock source selection */
987ed3899c5SRyan Chen 	if (p_cfg->src == ASPEED_CLK_HPLL)
988eff28274SJohnny Huang 		reg_304 |= BIT(19);
989eff28274SJohnny Huang 
990eff28274SJohnny Huang 	/* set RMII 3/4 clock divider */
991eff28274SJohnny Huang 	reg_310 &= ~GENMASK(18, 16);
992eff28274SJohnny Huang 	reg_310 |= (0x3 << 16);
993eff28274SJohnny Huang 
994eff28274SJohnny Huang 	writel(reg_304, &p_scu->clk_sel2);
995eff28274SJohnny Huang 	writel(reg_310, &p_scu->clk_sel4);
996eff28274SJohnny Huang }
997eff28274SJohnny Huang 
998f9aa0ee1Sryan_chen static u32 ast2600_configure_mac(struct ast2600_scu *scu, int index)
999f9aa0ee1Sryan_chen {
1000f9aa0ee1Sryan_chen 	u32 reset_bit;
1001f9aa0ee1Sryan_chen 	u32 clkstop_bit;
1002f9aa0ee1Sryan_chen 
1003f9aa0ee1Sryan_chen 	switch (index) {
1004f9aa0ee1Sryan_chen 	case 1:
1005f9aa0ee1Sryan_chen 		reset_bit = BIT(ASPEED_RESET_MAC1);
1006f9aa0ee1Sryan_chen 		clkstop_bit = BIT(SCU_CLKSTOP_MAC1);
1007f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_ctrl1);
1008f9aa0ee1Sryan_chen 		udelay(100);
1009f9aa0ee1Sryan_chen 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1010f9aa0ee1Sryan_chen 		mdelay(10);
1011f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_clr_ctrl1);
1012f9aa0ee1Sryan_chen 		break;
1013f9aa0ee1Sryan_chen 	case 2:
1014f9aa0ee1Sryan_chen 		reset_bit = BIT(ASPEED_RESET_MAC2);
1015f9aa0ee1Sryan_chen 		clkstop_bit = BIT(SCU_CLKSTOP_MAC2);
1016f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_ctrl1);
1017f9aa0ee1Sryan_chen 		udelay(100);
1018f9aa0ee1Sryan_chen 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1019f9aa0ee1Sryan_chen 		mdelay(10);
1020f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_clr_ctrl1);
1021f9aa0ee1Sryan_chen 		break;
1022f9aa0ee1Sryan_chen 	case 3:
1023f9aa0ee1Sryan_chen 		reset_bit = BIT(ASPEED_RESET_MAC3 - 32);
1024f9aa0ee1Sryan_chen 		clkstop_bit = BIT(SCU_CLKSTOP_MAC3);
1025f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_ctrl2);
1026f9aa0ee1Sryan_chen 		udelay(100);
1027f9aa0ee1Sryan_chen 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1028f9aa0ee1Sryan_chen 		mdelay(10);
1029f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_clr_ctrl2);
1030f9aa0ee1Sryan_chen 		break;
1031f9aa0ee1Sryan_chen 	case 4:
1032f9aa0ee1Sryan_chen 		reset_bit = BIT(ASPEED_RESET_MAC4 - 32);
1033f9aa0ee1Sryan_chen 		clkstop_bit = BIT(SCU_CLKSTOP_MAC4);
1034f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_ctrl2);
1035f9aa0ee1Sryan_chen 		udelay(100);
1036f9aa0ee1Sryan_chen 		writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1037f9aa0ee1Sryan_chen 		mdelay(10);
1038f9aa0ee1Sryan_chen 		writel(reset_bit, &scu->sysreset_clr_ctrl2);
1039f9aa0ee1Sryan_chen 		break;
1040f9aa0ee1Sryan_chen 	default:
1041f9aa0ee1Sryan_chen 		return -EINVAL;
1042f9aa0ee1Sryan_chen 	}
1043f9aa0ee1Sryan_chen 
1044f9aa0ee1Sryan_chen 	return 0;
1045f9aa0ee1Sryan_chen }
1046550e691bSryan_chen 
1047a8fc7648SRyan Chen #define SCU_CLK_ECC_RSA_FROM_HPLL_CLK	BIT(19)
1048a8fc7648SRyan Chen #define SCU_CLK_ECC_RSA_CLK_MASK		GENMASK(27, 26)
1049ed3899c5SRyan Chen #define SCU_CLK_ECC_RSA_CLK_DIV(x)		((x) << 26)
1050a8fc7648SRyan Chen static void ast2600_configure_rsa_ecc_clk(struct ast2600_scu *scu)
1051a8fc7648SRyan Chen {
1052a8fc7648SRyan Chen 	u32 clk_sel = readl(&scu->clk_sel1);
1053a8fc7648SRyan Chen 
10547e3c964cSJohnny Huang 	/* Configure RSA clock = HPLL/4 */
1055a8fc7648SRyan Chen 	clk_sel |= SCU_CLK_ECC_RSA_FROM_HPLL_CLK;
1056a8fc7648SRyan Chen 	clk_sel &= ~SCU_CLK_ECC_RSA_CLK_MASK;
10577e3c964cSJohnny Huang 	clk_sel |= SCU_CLK_ECC_RSA_CLK_DIV(3);
1058a8fc7648SRyan Chen 
1059a8fc7648SRyan Chen 	writel(clk_sel, &scu->clk_sel1);
1060a8fc7648SRyan Chen }
1061a8fc7648SRyan Chen 
1062f51926eeSryan_chen #define SCU_CLKSTOP_SDIO 4
1063f51926eeSryan_chen static ulong ast2600_enable_sdclk(struct ast2600_scu *scu)
1064f51926eeSryan_chen {
1065f51926eeSryan_chen 	u32 reset_bit;
1066f51926eeSryan_chen 	u32 clkstop_bit;
1067f51926eeSryan_chen 
1068f51926eeSryan_chen 	reset_bit = BIT(ASPEED_RESET_SD - 32);
1069f51926eeSryan_chen 	clkstop_bit = BIT(SCU_CLKSTOP_SDIO);
1070f51926eeSryan_chen 
1071fc9f12e6Sryan_chen 	writel(reset_bit, &scu->sysreset_ctrl2);
1072fc9f12e6Sryan_chen 
1073f51926eeSryan_chen 	udelay(100);
1074f51926eeSryan_chen 	//enable clk
1075f51926eeSryan_chen 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1076f51926eeSryan_chen 	mdelay(10);
1077fc9f12e6Sryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl2);
1078f51926eeSryan_chen 
1079f51926eeSryan_chen 	return 0;
1080f51926eeSryan_chen }
1081f51926eeSryan_chen 
1082f51926eeSryan_chen #define SCU_CLKSTOP_EXTSD			31
1083f51926eeSryan_chen #define SCU_CLK_SD_MASK				(0x7 << 28)
1084ed3899c5SRyan Chen #define SCU_CLK_SD_DIV(x)			((x) << 28)
10852cd7cba2Sryan_chen #define SCU_CLK_SD_FROM_APLL_CLK	BIT(8)
1086f51926eeSryan_chen 
1087f51926eeSryan_chen static ulong ast2600_enable_extsdclk(struct ast2600_scu *scu)
1088f51926eeSryan_chen {
1089f51926eeSryan_chen 	u32 clk_sel = readl(&scu->clk_sel4);
1090f51926eeSryan_chen 	u32 enableclk_bit;
10912cd7cba2Sryan_chen 	u32 rate = 0;
10922cd7cba2Sryan_chen 	u32 div = 0;
10932cd7cba2Sryan_chen 	int i = 0;
1094f51926eeSryan_chen 
1095f51926eeSryan_chen 	enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
1096f51926eeSryan_chen 
1097a8fc7648SRyan Chen 	/* ast2600 sd controller max clk is 200Mhz :
1098a8fc7648SRyan Chen 	 * use apll for clock source 800/4 = 200 : controller max is 200mhz
1099a8fc7648SRyan Chen 	 */
11002cd7cba2Sryan_chen 	rate = ast2600_get_apll_rate(scu);
11012cd7cba2Sryan_chen 	for (i = 0; i < 8; i++) {
11022cd7cba2Sryan_chen 		div = (i + 1) * 2;
11032cd7cba2Sryan_chen 		if ((rate / div) <= 200000000)
11042cd7cba2Sryan_chen 			break;
11052cd7cba2Sryan_chen 	}
1106f51926eeSryan_chen 	clk_sel &= ~SCU_CLK_SD_MASK;
11072cd7cba2Sryan_chen 	clk_sel |= SCU_CLK_SD_DIV(i) | SCU_CLK_SD_FROM_APLL_CLK;
1108f51926eeSryan_chen 	writel(clk_sel, &scu->clk_sel4);
1109f51926eeSryan_chen 
1110f51926eeSryan_chen 	//enable clk
1111f51926eeSryan_chen 	setbits_le32(&scu->clk_sel4, enableclk_bit);
1112f51926eeSryan_chen 
1113f51926eeSryan_chen 	return 0;
1114f51926eeSryan_chen }
1115f51926eeSryan_chen 
1116f51926eeSryan_chen #define SCU_CLKSTOP_EMMC 27
1117f51926eeSryan_chen static ulong ast2600_enable_emmcclk(struct ast2600_scu *scu)
1118f51926eeSryan_chen {
1119f51926eeSryan_chen 	u32 reset_bit;
1120f51926eeSryan_chen 	u32 clkstop_bit;
1121f51926eeSryan_chen 
1122f51926eeSryan_chen 	reset_bit = BIT(ASPEED_RESET_EMMC);
1123f51926eeSryan_chen 	clkstop_bit = BIT(SCU_CLKSTOP_EMMC);
1124f51926eeSryan_chen 
1125fc9f12e6Sryan_chen 	writel(reset_bit, &scu->sysreset_ctrl1);
1126f51926eeSryan_chen 	udelay(100);
1127f51926eeSryan_chen 	//enable clk
1128f51926eeSryan_chen 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1129f51926eeSryan_chen 	mdelay(10);
1130fc9f12e6Sryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl1);
1131f51926eeSryan_chen 
1132f51926eeSryan_chen 	return 0;
1133f51926eeSryan_chen }
1134f51926eeSryan_chen 
1135f51926eeSryan_chen #define SCU_CLKSTOP_EXTEMMC			15
1136f51926eeSryan_chen #define SCU_CLK_EMMC_MASK			(0x7 << 12)
1137ed3899c5SRyan Chen #define SCU_CLK_EMMC_DIV(x)			((x) << 12)
1138a8fc7648SRyan Chen #define SCU_CLK_EMMC_FROM_MPLL_CLK	BIT(11)
1139f51926eeSryan_chen 
1140f51926eeSryan_chen static ulong ast2600_enable_extemmcclk(struct ast2600_scu *scu)
1141f51926eeSryan_chen {
114285d48d8cSryan_chen 	u32 revision_id = readl(&scu->chip_id1);
1143f51926eeSryan_chen 	u32 clk_sel = readl(&scu->clk_sel1);
1144ed3899c5SRyan Chen 	u32 enableclk_bit = BIT(SCU_CLKSTOP_EXTEMMC);
1145f4c4ddb1Sryan_chen 	u32 rate = 0;
1146f4c4ddb1Sryan_chen 	u32 div = 0;
1147f4c4ddb1Sryan_chen 	int i = 0;
1148f51926eeSryan_chen 
1149ed3899c5SRyan Chen 	/*
1150ed3899c5SRyan Chen 	 * ast2600 eMMC controller max clk is 200Mhz
1151ed3899c5SRyan Chen 	 * HPll->1/2->|\
1152ed3899c5SRyan Chen 	 *				|->SCU300[11]->SCU300[14:12][1/N] +
1153ed3899c5SRyan Chen 	 * MPLL------>|/								  |
1154ed3899c5SRyan Chen 	 * +----------------------------------------------+
1155ed3899c5SRyan Chen 	 * |
1156ed3899c5SRyan Chen 	 * +---------> EMMC12C[15:8][1/N]-> eMMC clk
1157a8fc7648SRyan Chen 	 */
115885d48d8cSryan_chen 	if (((revision_id & CHIP_REVISION_ID) >> 16)) {
11598c32294fSryan_chen 		//AST2600A1 : use mpll to be clk source
1160b0c30ea3Sryan_chen 		rate = ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
1161b0c30ea3Sryan_chen 		for (i = 0; i < 8; i++) {
1162b0c30ea3Sryan_chen 			div = (i + 1) * 2;
1163b0c30ea3Sryan_chen 			if ((rate / div) <= 200000000)
1164b0c30ea3Sryan_chen 				break;
1165b0c30ea3Sryan_chen 		}
1166b0c30ea3Sryan_chen 
1167b0c30ea3Sryan_chen 		clk_sel &= ~SCU_CLK_EMMC_MASK;
11682cd7cba2Sryan_chen 		clk_sel |= SCU_CLK_EMMC_DIV(i) | SCU_CLK_EMMC_FROM_MPLL_CLK;
1169b0c30ea3Sryan_chen 		writel(clk_sel, &scu->clk_sel1);
1170b0c30ea3Sryan_chen 
1171b0c30ea3Sryan_chen 	} else {
11722cd7cba2Sryan_chen 		//AST2600A0 : use hpll to be clk source
1173f4c4ddb1Sryan_chen 		rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
1174f4c4ddb1Sryan_chen 
1175f4c4ddb1Sryan_chen 		for (i = 0; i < 8; i++) {
1176f4c4ddb1Sryan_chen 			div = (i + 1) * 4;
1177f4c4ddb1Sryan_chen 			if ((rate / div) <= 200000000)
1178f4c4ddb1Sryan_chen 				break;
1179f4c4ddb1Sryan_chen 		}
1180f4c4ddb1Sryan_chen 
1181f4c4ddb1Sryan_chen 		clk_sel &= ~SCU_CLK_EMMC_MASK;
1182f4c4ddb1Sryan_chen 		clk_sel |= SCU_CLK_EMMC_DIV(i);
1183f51926eeSryan_chen 		writel(clk_sel, &scu->clk_sel1);
1184b0c30ea3Sryan_chen 	}
1185f51926eeSryan_chen 	setbits_le32(&scu->clk_sel1, enableclk_bit);
1186f51926eeSryan_chen 
1187f51926eeSryan_chen 	return 0;
1188f51926eeSryan_chen }
1189f51926eeSryan_chen 
1190baf00c26Sryan_chen #define SCU_CLKSTOP_FSICLK 30
1191baf00c26Sryan_chen 
1192baf00c26Sryan_chen static ulong ast2600_enable_fsiclk(struct ast2600_scu *scu)
1193baf00c26Sryan_chen {
1194baf00c26Sryan_chen 	u32 reset_bit;
1195baf00c26Sryan_chen 	u32 clkstop_bit;
1196baf00c26Sryan_chen 
1197baf00c26Sryan_chen 	reset_bit = BIT(ASPEED_RESET_FSI % 32);
1198baf00c26Sryan_chen 	clkstop_bit = BIT(SCU_CLKSTOP_FSICLK);
1199baf00c26Sryan_chen 
1200baf00c26Sryan_chen 	/* The FSI clock is shared between masters. If it's already on
1201ed3899c5SRyan Chen 	 * don't touch it, as that will reset the existing master.
1202ed3899c5SRyan Chen 	 */
1203baf00c26Sryan_chen 	if (!(readl(&scu->clk_stop_ctrl2) & clkstop_bit)) {
1204baf00c26Sryan_chen 		debug("%s: already running, not touching it\n", __func__);
1205baf00c26Sryan_chen 		return 0;
1206baf00c26Sryan_chen 	}
1207baf00c26Sryan_chen 
1208baf00c26Sryan_chen 	writel(reset_bit, &scu->sysreset_ctrl2);
1209baf00c26Sryan_chen 	udelay(100);
1210baf00c26Sryan_chen 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1211baf00c26Sryan_chen 	mdelay(10);
1212baf00c26Sryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl2);
1213baf00c26Sryan_chen 
1214baf00c26Sryan_chen 	return 0;
1215baf00c26Sryan_chen }
1216baf00c26Sryan_chen 
1217b8ec5ceaSryan_chen static ulong ast2600_enable_usbahclk(struct ast2600_scu *scu)
1218b8ec5ceaSryan_chen {
1219b8ec5ceaSryan_chen 	u32 reset_bit;
1220b8ec5ceaSryan_chen 	u32 clkstop_bit;
1221b8ec5ceaSryan_chen 
1222b8ec5ceaSryan_chen 	reset_bit = BIT(ASPEED_RESET_EHCI_P1);
1223b8ec5ceaSryan_chen 	clkstop_bit = BIT(14);
1224b8ec5ceaSryan_chen 
1225b8ec5ceaSryan_chen 	writel(reset_bit, &scu->sysreset_ctrl1);
1226b8ec5ceaSryan_chen 	udelay(100);
1227b8ec5ceaSryan_chen 	writel(clkstop_bit, &scu->clk_stop_ctrl1);
1228b8ec5ceaSryan_chen 	mdelay(20);
1229b8ec5ceaSryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl1);
1230b8ec5ceaSryan_chen 
1231b8ec5ceaSryan_chen 	return 0;
1232b8ec5ceaSryan_chen }
1233b8ec5ceaSryan_chen 
1234b8ec5ceaSryan_chen static ulong ast2600_enable_usbbhclk(struct ast2600_scu *scu)
1235b8ec5ceaSryan_chen {
1236b8ec5ceaSryan_chen 	u32 reset_bit;
1237b8ec5ceaSryan_chen 	u32 clkstop_bit;
1238b8ec5ceaSryan_chen 
1239b8ec5ceaSryan_chen 	reset_bit = BIT(ASPEED_RESET_EHCI_P2);
1240b8ec5ceaSryan_chen 	clkstop_bit = BIT(7);
1241b8ec5ceaSryan_chen 
1242b8ec5ceaSryan_chen 	writel(reset_bit, &scu->sysreset_ctrl1);
1243b8ec5ceaSryan_chen 	udelay(100);
1244b8ec5ceaSryan_chen 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1245b8ec5ceaSryan_chen 	mdelay(20);
1246b8ec5ceaSryan_chen 
1247b8ec5ceaSryan_chen 	writel(reset_bit, &scu->sysreset_clr_ctrl1);
1248b8ec5ceaSryan_chen 
1249b8ec5ceaSryan_chen 	return 0;
1250b8ec5ceaSryan_chen }
1251b8ec5ceaSryan_chen 
1252089713adSJoel Stanley /* also known as yclk */
1253089713adSJoel Stanley static ulong ast2600_enable_haceclk(struct ast2600_scu *scu)
1254089713adSJoel Stanley {
1255089713adSJoel Stanley 	u32 reset_bit;
1256089713adSJoel Stanley 	u32 clkstop_bit;
1257089713adSJoel Stanley 
1258089713adSJoel Stanley 	reset_bit = BIT(ASPEED_RESET_HACE);
1259089713adSJoel Stanley 	clkstop_bit = BIT(13);
1260089713adSJoel Stanley 
1261089713adSJoel Stanley 	writel(reset_bit, &scu->sysreset_ctrl1);
1262089713adSJoel Stanley 	udelay(100);
1263089713adSJoel Stanley 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1264089713adSJoel Stanley 	mdelay(20);
1265089713adSJoel Stanley 
1266089713adSJoel Stanley 	writel(reset_bit, &scu->sysreset_clr_ctrl1);
1267089713adSJoel Stanley 
1268089713adSJoel Stanley 	return 0;
1269089713adSJoel Stanley }
1270089713adSJoel Stanley 
1271f6110ecdSChia-Wei Wang static ulong ast2600_enable_rsaeccclk(struct ast2600_scu *scu)
1272f6110ecdSChia-Wei Wang {
1273f6110ecdSChia-Wei Wang 	u32 clkstop_bit;
1274f6110ecdSChia-Wei Wang 
1275f6110ecdSChia-Wei Wang 	clkstop_bit = BIT(24);
1276f6110ecdSChia-Wei Wang 
1277f6110ecdSChia-Wei Wang 	writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1278f6110ecdSChia-Wei Wang 	mdelay(20);
1279f6110ecdSChia-Wei Wang 
1280f6110ecdSChia-Wei Wang 	return 0;
1281f6110ecdSChia-Wei Wang }
1282f6110ecdSChia-Wei Wang 
1283d6e349c7Sryan_chen static int ast2600_clk_enable(struct clk *clk)
1284550e691bSryan_chen {
1285f0d895afSryan_chen 	struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
1286550e691bSryan_chen 
1287550e691bSryan_chen 	switch (clk->id) {
128886f91560Sryan_chen 	case ASPEED_CLK_GATE_MAC1CLK:
128986f91560Sryan_chen 		ast2600_configure_mac(priv->scu, 1);
1290550e691bSryan_chen 		break;
129186f91560Sryan_chen 	case ASPEED_CLK_GATE_MAC2CLK:
129286f91560Sryan_chen 		ast2600_configure_mac(priv->scu, 2);
1293550e691bSryan_chen 		break;
129477843939Sryan_chen 	case ASPEED_CLK_GATE_MAC3CLK:
129577843939Sryan_chen 		ast2600_configure_mac(priv->scu, 3);
129677843939Sryan_chen 		break;
129777843939Sryan_chen 	case ASPEED_CLK_GATE_MAC4CLK:
129877843939Sryan_chen 		ast2600_configure_mac(priv->scu, 4);
129977843939Sryan_chen 		break;
1300f51926eeSryan_chen 	case ASPEED_CLK_GATE_SDCLK:
1301f51926eeSryan_chen 		ast2600_enable_sdclk(priv->scu);
1302f51926eeSryan_chen 		break;
1303f51926eeSryan_chen 	case ASPEED_CLK_GATE_SDEXTCLK:
1304f51926eeSryan_chen 		ast2600_enable_extsdclk(priv->scu);
1305f51926eeSryan_chen 		break;
1306f51926eeSryan_chen 	case ASPEED_CLK_GATE_EMMCCLK:
1307f51926eeSryan_chen 		ast2600_enable_emmcclk(priv->scu);
1308f51926eeSryan_chen 		break;
1309f51926eeSryan_chen 	case ASPEED_CLK_GATE_EMMCEXTCLK:
1310f51926eeSryan_chen 		ast2600_enable_extemmcclk(priv->scu);
1311f51926eeSryan_chen 		break;
1312baf00c26Sryan_chen 	case ASPEED_CLK_GATE_FSICLK:
1313baf00c26Sryan_chen 		ast2600_enable_fsiclk(priv->scu);
1314baf00c26Sryan_chen 		break;
1315b8ec5ceaSryan_chen 	case ASPEED_CLK_GATE_USBPORT1CLK:
1316b8ec5ceaSryan_chen 		ast2600_enable_usbahclk(priv->scu);
1317b8ec5ceaSryan_chen 		break;
1318b8ec5ceaSryan_chen 	case ASPEED_CLK_GATE_USBPORT2CLK:
1319b8ec5ceaSryan_chen 		ast2600_enable_usbbhclk(priv->scu);
1320b8ec5ceaSryan_chen 		break;
1321089713adSJoel Stanley 	case ASPEED_CLK_GATE_YCLK:
1322089713adSJoel Stanley 		ast2600_enable_haceclk(priv->scu);
1323089713adSJoel Stanley 		break;
1324f6110ecdSChia-Wei Wang 	case ASPEED_CLK_GATE_RSAECCCLK:
1325f6110ecdSChia-Wei Wang 		ast2600_enable_rsaeccclk(priv->scu);
1326f6110ecdSChia-Wei Wang 		break;
1327550e691bSryan_chen 	default:
1328ed3899c5SRyan Chen 		pr_err("can't enable clk\n");
1329550e691bSryan_chen 		return -ENOENT;
1330550e691bSryan_chen 	}
1331550e691bSryan_chen 
1332550e691bSryan_chen 	return 0;
1333550e691bSryan_chen }
1334550e691bSryan_chen 
1335f9aa0ee1Sryan_chen struct clk_ops ast2600_clk_ops = {
1336d6e349c7Sryan_chen 	.get_rate = ast2600_clk_get_rate,
1337d6e349c7Sryan_chen 	.set_rate = ast2600_clk_set_rate,
1338d6e349c7Sryan_chen 	.enable = ast2600_clk_enable,
1339550e691bSryan_chen };
1340550e691bSryan_chen 
1341d6e349c7Sryan_chen static int ast2600_clk_probe(struct udevice *dev)
1342550e691bSryan_chen {
1343f0d895afSryan_chen 	struct ast2600_clk_priv *priv = dev_get_priv(dev);
134461ab9607Sryan_chen 	u32 uart_clk_source;
1345550e691bSryan_chen 
1346f0d895afSryan_chen 	priv->scu = devfdt_get_addr_ptr(dev);
1347f0d895afSryan_chen 	if (IS_ERR(priv->scu))
1348f0d895afSryan_chen 		return PTR_ERR(priv->scu);
1349550e691bSryan_chen 
13505d05f4fcSRyan Chen 	uart_clk_source = dev_read_u32_default(dev, "uart-clk-source", 0x0);
135161ab9607Sryan_chen 
135261ab9607Sryan_chen 	if (uart_clk_source) {
135356dd3e85Sryan_chen 		if (uart_clk_source & GENMASK(5, 0))
13545d05f4fcSRyan Chen 			setbits_le32(&priv->scu->clk_sel4,
13555d05f4fcSRyan Chen 				     uart_clk_source & GENMASK(5, 0));
135656dd3e85Sryan_chen 		if (uart_clk_source & GENMASK(12, 6))
13575d05f4fcSRyan Chen 			setbits_le32(&priv->scu->clk_sel5,
13585d05f4fcSRyan Chen 				     uart_clk_source & GENMASK(12, 6));
135961ab9607Sryan_chen 	}
136061ab9607Sryan_chen 
1361b89500a2SDylan Hung 	ast2600_init_rgmii_clk(priv->scu, &rgmii_clk_defconfig);
1362b89500a2SDylan Hung 	ast2600_init_rmii_clk(priv->scu, &rmii_clk_defconfig);
1363a98c71fbSDylan Hung 	ast2600_configure_mac12_clk(priv->scu, dev);
1364a98c71fbSDylan Hung 	ast2600_configure_mac34_clk(priv->scu, dev);
1365a8fc7648SRyan Chen 	ast2600_configure_rsa_ecc_clk(priv->scu);
1366fd0306aaSJohnny Huang 
1367550e691bSryan_chen 	return 0;
1368550e691bSryan_chen }
1369550e691bSryan_chen 
1370d6e349c7Sryan_chen static int ast2600_clk_bind(struct udevice *dev)
1371550e691bSryan_chen {
1372550e691bSryan_chen 	int ret;
1373550e691bSryan_chen 
1374550e691bSryan_chen 	/* The reset driver does not have a device node, so bind it here */
1375550e691bSryan_chen 	ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
1376550e691bSryan_chen 	if (ret)
1377550e691bSryan_chen 		debug("Warning: No reset driver: ret=%d\n", ret);
1378550e691bSryan_chen 
1379550e691bSryan_chen 	return 0;
1380550e691bSryan_chen }
1381550e691bSryan_chen 
1382d35ac78cSryan_chen struct aspeed_clks {
1383d35ac78cSryan_chen 	ulong id;
1384d35ac78cSryan_chen 	const char *name;
1385d35ac78cSryan_chen };
1386d35ac78cSryan_chen 
1387d35ac78cSryan_chen static struct aspeed_clks aspeed_clk_names[] = {
13885d05f4fcSRyan Chen 	{ ASPEED_CLK_HPLL, "hpll" },     { ASPEED_CLK_MPLL, "mpll" },
13895d05f4fcSRyan Chen 	{ ASPEED_CLK_APLL, "apll" },     { ASPEED_CLK_EPLL, "epll" },
13905d05f4fcSRyan Chen 	{ ASPEED_CLK_DPLL, "dpll" },     { ASPEED_CLK_AHB, "hclk" },
13915d05f4fcSRyan Chen 	{ ASPEED_CLK_APB1, "pclk1" },    { ASPEED_CLK_APB2, "pclk2" },
13925d05f4fcSRyan Chen 	{ ASPEED_CLK_BCLK, "bclk" },     { ASPEED_CLK_UARTX, "uxclk" },
1393def99fcbSryan_chen 	{ ASPEED_CLK_HUARTX, "huxclk" },
1394d35ac78cSryan_chen };
1395d35ac78cSryan_chen 
1396d35ac78cSryan_chen int soc_clk_dump(void)
1397d35ac78cSryan_chen {
1398d35ac78cSryan_chen 	struct udevice *dev;
1399d35ac78cSryan_chen 	struct clk clk;
1400d35ac78cSryan_chen 	unsigned long rate;
1401d35ac78cSryan_chen 	int i, ret;
1402d35ac78cSryan_chen 
14035d05f4fcSRyan Chen 	ret = uclass_get_device_by_driver(UCLASS_CLK, DM_GET_DRIVER(aspeed_scu),
14045d05f4fcSRyan Chen 					  &dev);
1405d35ac78cSryan_chen 	if (ret)
1406d35ac78cSryan_chen 		return ret;
1407d35ac78cSryan_chen 
1408d35ac78cSryan_chen 	printf("Clk\t\tHz\n");
1409d35ac78cSryan_chen 
1410d35ac78cSryan_chen 	for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
1411d35ac78cSryan_chen 		clk.id = aspeed_clk_names[i].id;
1412d35ac78cSryan_chen 		ret = clk_request(dev, &clk);
1413d35ac78cSryan_chen 		if (ret < 0) {
1414d35ac78cSryan_chen 			debug("%s clk_request() failed: %d\n", __func__, ret);
1415d35ac78cSryan_chen 			continue;
1416d35ac78cSryan_chen 		}
1417d35ac78cSryan_chen 
1418d35ac78cSryan_chen 		ret = clk_get_rate(&clk);
1419d35ac78cSryan_chen 		rate = ret;
1420d35ac78cSryan_chen 
1421d35ac78cSryan_chen 		clk_free(&clk);
1422d35ac78cSryan_chen 
1423d35ac78cSryan_chen 		if (ret == -ENOTSUPP) {
1424d35ac78cSryan_chen 			printf("clk ID %lu not supported yet\n",
1425d35ac78cSryan_chen 			       aspeed_clk_names[i].id);
1426d35ac78cSryan_chen 			continue;
1427d35ac78cSryan_chen 		}
1428d35ac78cSryan_chen 		if (ret < 0) {
14295d05f4fcSRyan Chen 			printf("%s %lu: get_rate err: %d\n", __func__,
14305d05f4fcSRyan Chen 			       aspeed_clk_names[i].id, ret);
1431d35ac78cSryan_chen 			continue;
1432d35ac78cSryan_chen 		}
1433d35ac78cSryan_chen 
14345d05f4fcSRyan Chen 		printf("%s(%3lu):\t%lu\n", aspeed_clk_names[i].name,
14355d05f4fcSRyan Chen 		       aspeed_clk_names[i].id, rate);
1436d35ac78cSryan_chen 	}
1437d35ac78cSryan_chen 
1438d35ac78cSryan_chen 	return 0;
1439d35ac78cSryan_chen }
1440d35ac78cSryan_chen 
1441d6e349c7Sryan_chen static const struct udevice_id ast2600_clk_ids[] = {
14425d05f4fcSRyan Chen 	{
14435d05f4fcSRyan Chen 		.compatible = "aspeed,ast2600-scu",
14445d05f4fcSRyan Chen 	},
1445550e691bSryan_chen 	{}
1446550e691bSryan_chen };
1447550e691bSryan_chen 
1448aa36597fSDylan Hung U_BOOT_DRIVER(aspeed_scu) = {
1449aa36597fSDylan Hung 	.name = "aspeed_scu",
1450550e691bSryan_chen 	.id = UCLASS_CLK,
1451d6e349c7Sryan_chen 	.of_match = ast2600_clk_ids,
1452f0d895afSryan_chen 	.priv_auto_alloc_size = sizeof(struct ast2600_clk_priv),
1453f9aa0ee1Sryan_chen 	.ops = &ast2600_clk_ops,
1454d6e349c7Sryan_chen 	.bind = ast2600_clk_bind,
1455d6e349c7Sryan_chen 	.probe = ast2600_clk_probe,
1456550e691bSryan_chen };
1457