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>
9e95b19f8SDylan 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 /*
19e95b19f8SDylan Hung * SCU 80 & 90 clock stop control for MAC controllers
20e95b19f8SDylan Hung */
21e95b19f8SDylan Hung #define SCU_CLKSTOP_MAC1 (20)
22e95b19f8SDylan Hung #define SCU_CLKSTOP_MAC2 (21)
23e95b19f8SDylan Hung #define SCU_CLKSTOP_MAC3 (20)
24e95b19f8SDylan Hung #define SCU_CLKSTOP_MAC4 (21)
25e95b19f8SDylan Hung
26e95b19f8SDylan 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
58e95b19f8SDylan Hung #define RGMII12_CLK_OUTPUT_DELAY_PS 1000
59e95b19f8SDylan Hung #define RGMII34_CLK_OUTPUT_DELAY_PS 1600
60e95b19f8SDylan 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)
85e95b19f8SDylan Hung
86e95b19f8SDylan Hung /*
87e95b19f8SDylan Hung * SCU 320 & 330 Frequency counters
88e95b19f8SDylan Hung */
89e95b19f8SDylan Hung #define FREQC_CTRL_RESERVED GENMASK(31, 30)
90e95b19f8SDylan Hung #define FREQC_CTRL_RESULT GENMASK(29, 16)
91e95b19f8SDylan Hung #define FREQC_CTRL_RING_STAGE GENMASK(15, 9)
92e95b19f8SDylan Hung #define FREQC_CTRL_PIN_O_CTRL BIT(8)
93e95b19f8SDylan Hung #define FREQC_CTRL_PIN_O_DIS 0
94e95b19f8SDylan Hung #define FREQC_CTRL_PIN_O_EN 1
95e95b19f8SDylan Hung #define FREQC_CTRL_CMP_RESULT BIT(7)
96e95b19f8SDylan Hung #define FREQC_CTRL_CMP_RESULT_FAIL 0
97e95b19f8SDylan Hung #define FREQC_CTRL_CMP_RESULT_PASS 1
98e95b19f8SDylan Hung #define FREQC_CTRL_STATUS BIT(6)
99e95b19f8SDylan Hung #define FREQC_CTRL_STATUS_NOT_FINISHED 0
100e95b19f8SDylan Hung #define FREQC_CTRL_STATUS_FINISHED 1
101e95b19f8SDylan Hung #define FREQC_CTRL_SRC_SEL GENMASK(5, 2)
102e95b19f8SDylan Hung #define FREQC_CTRL_SRC_SEL_HCLK_DIE0 9
103e95b19f8SDylan Hung #define FREQC_CTRL_SRC_SEL_DLY32_DIE0 3
104e95b19f8SDylan Hung #define FREQC_CTRL_SRC_SEL_HCLK_DIE1 1
105e95b19f8SDylan Hung #define FREQC_CTRL_SRC_SEL_DLY32_DIE1 7
106e95b19f8SDylan Hung #define FREQC_CTRL_OSC_CTRL BIT(1)
107e95b19f8SDylan Hung #define FREQC_CTRL_OSC_DIS 0
108e95b19f8SDylan Hung #define FREQC_CTRL_OSC_EN 1
109e95b19f8SDylan Hung #define FREQC_CTRL_RING_CTRL BIT(0)
110e95b19f8SDylan Hung #define FREQC_CTRL_RING_DIS 0
111e95b19f8SDylan Hung #define FREQC_CTRL_RING_EN 1
112e95b19f8SDylan Hung
113e95b19f8SDylan Hung #define FREQC_RANGE_RESERVED0 GENMASK(31, 30)
114e95b19f8SDylan Hung #define FREQC_RANGE_LOWER GENMASK(29, 16)
115e95b19f8SDylan Hung #define FREQC_RANGE_RESERVED1 GENMASK(15, 14)
116e95b19f8SDylan Hung #define FREQC_RANGE_UPPER GENMASK(13, 0)
117e95b19f8SDylan Hung
118e95b19f8SDylan Hung #define DLY32_NUM_OF_TAPS 32
119e95b19f8SDylan Hung #define DLY32_AVERAGE_COUNT_LOG2 4
120e95b19f8SDylan Hung #define DLY32_AVERAGE_COUNT BIT(DLY32_AVERAGE_COUNT_LOG2)
121e95b19f8SDylan 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
ast2600_get_pll_rate(struct ast2600_scu * scu,int pll_idx)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
ast2600_get_apll_rate(struct ast2600_scu * scu)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
ast2600_get_hclk(struct ast2600_scu * scu)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
ast2600_get_bclk_rate(struct ast2600_scu * scu)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
3798ad54a5aSryan_chen rate = ast2600_get_pll_rate(scu, ASPEED_CLK_EPLL);
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
ast2600_get_pclk1(struct ast2600_scu * scu)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
ast2600_get_pclk2(struct ast2600_scu * scu)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
ast2600_get_uxclk_in_rate(struct ast2600_scu * scu)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
ast2600_get_huxclk_in_rate(struct ast2600_scu * scu)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
ast2600_get_uart_uxclk_rate(struct ast2600_scu * scu)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
ast2600_get_uart_huxclk_rate(struct ast2600_scu * scu)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
ast2600_get_sdio_clk_rate(struct ast2600_scu * scu)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
ast2600_get_emmc_clk_rate(struct ast2600_scu * scu)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
5254c944043SChia-Wei Wang #ifdef CONFIG_SPL_BUILD
ast2600_enable_uart_pinmux(struct ast2600_scu * scu,int uart_idx)5264c944043SChia-Wei Wang static void ast2600_enable_uart_pinmux(struct ast2600_scu *scu, int uart_idx)
5274c944043SChia-Wei Wang {
5284c944043SChia-Wei Wang switch(uart_idx) {
5294c944043SChia-Wei Wang case 1:
5304c944043SChia-Wei Wang scu->pinmux_ctrl7 |= (BIT(7) | BIT(6));
5314c944043SChia-Wei Wang break;
5324c944043SChia-Wei Wang case 2:
5334c944043SChia-Wei Wang scu->pinmux_ctrl7 |= (BIT(14) | BIT(15));
5344c944043SChia-Wei Wang break;
5354c944043SChia-Wei Wang case 3:
5364c944043SChia-Wei Wang scu->pinmux_ctrl6 |= (BIT(28) | BIT(29));
5374c944043SChia-Wei Wang break;
5384c944043SChia-Wei Wang case 4:
5394c944043SChia-Wei Wang scu->pinmux_ctrl4 |= (BIT(14) | BIT(15));
5404c944043SChia-Wei Wang break;
5414c944043SChia-Wei Wang case 5:
5424c944043SChia-Wei Wang /* do nothgin */
5434c944043SChia-Wei Wang break;
5444c944043SChia-Wei Wang case 6:
5454c944043SChia-Wei Wang scu->pinmux_ctrl5 |= (BIT(16) | BIT(17));
5464c944043SChia-Wei Wang break;
5474c944043SChia-Wei Wang case 7:
5484c944043SChia-Wei Wang scu->pinmux_ctrl5 |= (BIT(18) | BIT(19));
5494c944043SChia-Wei Wang break;
5504c944043SChia-Wei Wang case 8:
5514c944043SChia-Wei Wang scu->pinmux_ctrl5 |= (BIT(20) | BIT(21));
5524c944043SChia-Wei Wang break;
5534c944043SChia-Wei Wang case 9:
5544c944043SChia-Wei Wang scu->pinmux_ctrl5 |= (BIT(22) | BIT(23));
5554c944043SChia-Wei Wang break;
5564c944043SChia-Wei Wang case 10:
5574c944043SChia-Wei Wang scu->pinmux_ctrl8 |= (BIT(20) | BIT(21));
5584c944043SChia-Wei Wang break;
5594c944043SChia-Wei Wang case 11:
5604c944043SChia-Wei Wang scu->pinmux_ctrl8 |= (BIT(22) | BIT(23));
5614c944043SChia-Wei Wang break;
5624c944043SChia-Wei Wang case 12:
5634c944043SChia-Wei Wang scu->pinmux_ctrl19 |= (BIT(0) | BIT(1));
5644c944043SChia-Wei Wang scu->pinmux_ctrl6 &= ~(BIT(0) | BIT(1));
5654c944043SChia-Wei Wang break;
5664c944043SChia-Wei Wang case 13:
5674c944043SChia-Wei Wang scu->pinmux_ctrl19 |= (BIT(2) | BIT(3));
5684c944043SChia-Wei Wang scu->pinmux_ctrl6 &= ~(BIT(2) | BIT(3));
5694c944043SChia-Wei Wang break;
5704c944043SChia-Wei Wang default:
5714c944043SChia-Wei Wang break;
5724c944043SChia-Wei Wang }
5734c944043SChia-Wei Wang }
5744c944043SChia-Wei Wang #endif
5754c944043SChia-Wei Wang
ast2600_get_uart_clk_rate(struct ast2600_scu * scu,int uart_idx)576f51926eeSryan_chen static u32 ast2600_get_uart_clk_rate(struct ast2600_scu *scu, int uart_idx)
57727881d20Sryan_chen {
578de49ffa7SChia-Wei Wang u32 hicr9 = readl(0x1e789098);
57927881d20Sryan_chen u32 uart_sel = readl(&scu->clk_sel4);
58027881d20Sryan_chen u32 uart_sel5 = readl(&scu->clk_sel5);
58127881d20Sryan_chen ulong uart_clk = 0;
58227881d20Sryan_chen
5834c944043SChia-Wei Wang #ifdef CONFIG_SPL_BUILD
5844c944043SChia-Wei Wang ast2600_enable_uart_pinmux(scu, uart_idx);
5854c944043SChia-Wei Wang #endif
5864c944043SChia-Wei Wang
58727881d20Sryan_chen switch (uart_idx) {
58827881d20Sryan_chen case 1:
58927881d20Sryan_chen case 2:
59027881d20Sryan_chen case 3:
59127881d20Sryan_chen case 4:
592de49ffa7SChia-Wei Wang hicr9 &= ~(BIT(uart_idx + 3));
593de49ffa7SChia-Wei Wang writel(hicr9, 0x1e789098);
59427881d20Sryan_chen case 6:
59527881d20Sryan_chen if (uart_sel & BIT(uart_idx - 1))
5962e195992Sryan_chen uart_clk = ast2600_get_uart_huxclk_rate(scu);
597550e691bSryan_chen else
5982e195992Sryan_chen uart_clk = ast2600_get_uart_uxclk_rate(scu);
59927881d20Sryan_chen break;
60027881d20Sryan_chen case 5: //24mhz is come form usb phy 48Mhz
60127881d20Sryan_chen {
60227881d20Sryan_chen u8 uart5_clk_sel = 0;
60327881d20Sryan_chen //high bit
60427881d20Sryan_chen if (readl(&scu->misc_ctrl1) & BIT(12))
60527881d20Sryan_chen uart5_clk_sel = 0x2;
60627881d20Sryan_chen else
60727881d20Sryan_chen uart5_clk_sel = 0x0;
608550e691bSryan_chen
60927881d20Sryan_chen if (readl(&scu->clk_sel2) & BIT(14))
61027881d20Sryan_chen uart5_clk_sel |= 0x1;
611550e691bSryan_chen
61227881d20Sryan_chen switch (uart5_clk_sel) {
61327881d20Sryan_chen case 0:
61427881d20Sryan_chen uart_clk = 24000000;
61527881d20Sryan_chen break;
61627881d20Sryan_chen case 1:
617def99fcbSryan_chen uart_clk = 192000000;
61827881d20Sryan_chen break;
61927881d20Sryan_chen case 2:
62027881d20Sryan_chen uart_clk = 24000000 / 13;
62127881d20Sryan_chen break;
62227881d20Sryan_chen case 3:
62327881d20Sryan_chen uart_clk = 192000000 / 13;
62427881d20Sryan_chen break;
62527881d20Sryan_chen }
6265d05f4fcSRyan Chen } break;
62727881d20Sryan_chen case 7:
62827881d20Sryan_chen case 8:
62927881d20Sryan_chen case 9:
63027881d20Sryan_chen case 10:
63127881d20Sryan_chen case 11:
63227881d20Sryan_chen case 12:
63327881d20Sryan_chen case 13:
63427881d20Sryan_chen if (uart_sel5 & BIT(uart_idx - 1))
6352e195992Sryan_chen uart_clk = ast2600_get_uart_huxclk_rate(scu);
63627881d20Sryan_chen else
6372e195992Sryan_chen uart_clk = ast2600_get_uart_uxclk_rate(scu);
63827881d20Sryan_chen break;
63927881d20Sryan_chen }
64027881d20Sryan_chen
64127881d20Sryan_chen return uart_clk;
642550e691bSryan_chen }
643550e691bSryan_chen
ast2600_clk_get_rate(struct clk * clk)644feb42054Sryan_chen static ulong ast2600_clk_get_rate(struct clk *clk)
645feb42054Sryan_chen {
646feb42054Sryan_chen struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
647feb42054Sryan_chen ulong rate = 0;
648feb42054Sryan_chen
649feb42054Sryan_chen switch (clk->id) {
650feb42054Sryan_chen case ASPEED_CLK_HPLL:
651bbbfb0c5Sryan_chen case ASPEED_CLK_EPLL:
652bbbfb0c5Sryan_chen case ASPEED_CLK_DPLL:
653d812df15Sryan_chen case ASPEED_CLK_MPLL:
654bbbfb0c5Sryan_chen rate = ast2600_get_pll_rate(priv->scu, clk->id);
655d812df15Sryan_chen break;
656feb42054Sryan_chen case ASPEED_CLK_AHB:
657feb42054Sryan_chen rate = ast2600_get_hclk(priv->scu);
658feb42054Sryan_chen break;
6596fa1ef3dSryan_chen case ASPEED_CLK_APB1:
6606fa1ef3dSryan_chen rate = ast2600_get_pclk1(priv->scu);
6616fa1ef3dSryan_chen break;
6626fa1ef3dSryan_chen case ASPEED_CLK_APB2:
6636fa1ef3dSryan_chen rate = ast2600_get_pclk2(priv->scu);
664feb42054Sryan_chen break;
665bbbfb0c5Sryan_chen case ASPEED_CLK_APLL:
666bbbfb0c5Sryan_chen rate = ast2600_get_apll_rate(priv->scu);
667bbbfb0c5Sryan_chen break;
668feb42054Sryan_chen case ASPEED_CLK_GATE_UART1CLK:
669feb42054Sryan_chen rate = ast2600_get_uart_clk_rate(priv->scu, 1);
670feb42054Sryan_chen break;
671feb42054Sryan_chen case ASPEED_CLK_GATE_UART2CLK:
672feb42054Sryan_chen rate = ast2600_get_uart_clk_rate(priv->scu, 2);
673feb42054Sryan_chen break;
674feb42054Sryan_chen case ASPEED_CLK_GATE_UART3CLK:
675feb42054Sryan_chen rate = ast2600_get_uart_clk_rate(priv->scu, 3);
676feb42054Sryan_chen break;
677feb42054Sryan_chen case ASPEED_CLK_GATE_UART4CLK:
678feb42054Sryan_chen rate = ast2600_get_uart_clk_rate(priv->scu, 4);
679feb42054Sryan_chen break;
680feb42054Sryan_chen case ASPEED_CLK_GATE_UART5CLK:
681feb42054Sryan_chen rate = ast2600_get_uart_clk_rate(priv->scu, 5);
682feb42054Sryan_chen break;
683c304f173Sryan_chen case ASPEED_CLK_BCLK:
684c304f173Sryan_chen rate = ast2600_get_bclk_rate(priv->scu);
685c304f173Sryan_chen break;
686f51926eeSryan_chen case ASPEED_CLK_SDIO:
687f51926eeSryan_chen rate = ast2600_get_sdio_clk_rate(priv->scu);
688f51926eeSryan_chen break;
689f51926eeSryan_chen case ASPEED_CLK_EMMC:
690f51926eeSryan_chen rate = ast2600_get_emmc_clk_rate(priv->scu);
691f51926eeSryan_chen break;
6922e195992Sryan_chen case ASPEED_CLK_UARTX:
6932e195992Sryan_chen rate = ast2600_get_uart_uxclk_rate(priv->scu);
6942e195992Sryan_chen break;
6950998ddefSryan_chen case ASPEED_CLK_HUARTX:
6962e195992Sryan_chen rate = ast2600_get_uart_huxclk_rate(priv->scu);
6972e195992Sryan_chen break;
698feb42054Sryan_chen default:
699d812df15Sryan_chen pr_debug("can't get clk rate\n");
700feb42054Sryan_chen return -ENOENT;
701feb42054Sryan_chen }
702feb42054Sryan_chen
703feb42054Sryan_chen return rate;
704feb42054Sryan_chen }
705feb42054Sryan_chen
706577fcdaeSDylan Hung /**
707577fcdaeSDylan Hung * @brief lookup PLL divider config by input/output rate
708577fcdaeSDylan Hung * @param[in] *pll - PLL descriptor
709577fcdaeSDylan Hung * @return true - if PLL divider config is found, false - else
710a8fc7648SRyan Chen * The function caller shall fill "pll->in" and "pll->out",
711a8fc7648SRyan Chen * then this function will search the lookup table
712a8fc7648SRyan Chen * to find a valid PLL divider configuration.
713550e691bSryan_chen */
ast2600_search_clock_config(struct ast2600_pll_desc * pll)714577fcdaeSDylan Hung static bool ast2600_search_clock_config(struct ast2600_pll_desc *pll)
715550e691bSryan_chen {
716577fcdaeSDylan Hung u32 i;
717577fcdaeSDylan Hung bool is_found = false;
718550e691bSryan_chen
719577fcdaeSDylan Hung for (i = 0; i < ARRAY_SIZE(ast2600_pll_lookup); i++) {
720577fcdaeSDylan Hung const struct ast2600_pll_desc *def_cfg = &ast2600_pll_lookup[i];
721ed3899c5SRyan Chen
722ed3899c5SRyan Chen if (def_cfg->in == pll->in && def_cfg->out == pll->out) {
723577fcdaeSDylan Hung is_found = true;
724577fcdaeSDylan Hung pll->cfg.reg.w = def_cfg->cfg.reg.w;
725577fcdaeSDylan Hung pll->cfg.ext_reg = def_cfg->cfg.ext_reg;
726577fcdaeSDylan Hung break;
727550e691bSryan_chen }
728550e691bSryan_chen }
729577fcdaeSDylan Hung return is_found;
730550e691bSryan_chen }
731ed3899c5SRyan Chen
ast2600_configure_pll(struct ast2600_scu * scu,struct ast2600_pll_cfg * p_cfg,int pll_idx)732fd52be0bSDylan Hung static u32 ast2600_configure_pll(struct ast2600_scu *scu,
733fd52be0bSDylan Hung struct ast2600_pll_cfg *p_cfg, int pll_idx)
734fd52be0bSDylan Hung {
735fd52be0bSDylan Hung u32 addr, addr_ext;
736fd52be0bSDylan Hung u32 reg;
737550e691bSryan_chen
738fd52be0bSDylan Hung switch (pll_idx) {
739fd52be0bSDylan Hung case ASPEED_CLK_HPLL:
740fd52be0bSDylan Hung addr = (u32)(&scu->h_pll_param);
741fd52be0bSDylan Hung addr_ext = (u32)(&scu->h_pll_ext_param);
742fd52be0bSDylan Hung break;
743fd52be0bSDylan Hung case ASPEED_CLK_MPLL:
744fd52be0bSDylan Hung addr = (u32)(&scu->m_pll_param);
745fd52be0bSDylan Hung addr_ext = (u32)(&scu->m_pll_ext_param);
746fd52be0bSDylan Hung break;
747fd52be0bSDylan Hung case ASPEED_CLK_DPLL:
748fd52be0bSDylan Hung addr = (u32)(&scu->d_pll_param);
749fd52be0bSDylan Hung addr_ext = (u32)(&scu->d_pll_ext_param);
750fd52be0bSDylan Hung break;
751fd52be0bSDylan Hung case ASPEED_CLK_EPLL:
752fd52be0bSDylan Hung addr = (u32)(&scu->e_pll_param);
753fd52be0bSDylan Hung addr_ext = (u32)(&scu->e_pll_ext_param);
754fd52be0bSDylan Hung break;
755fd52be0bSDylan Hung default:
756fd52be0bSDylan Hung debug("unknown PLL index\n");
757fd52be0bSDylan Hung return 1;
758fd52be0bSDylan Hung }
759fd52be0bSDylan Hung
760fd52be0bSDylan Hung p_cfg->reg.b.bypass = 0;
761*e9f7e664SDylan Hung p_cfg->reg.b.off = 0;
762fd52be0bSDylan Hung p_cfg->reg.b.reset = 1;
763fd52be0bSDylan Hung
764fd52be0bSDylan Hung reg = readl(addr);
765fd52be0bSDylan Hung reg &= ~GENMASK(25, 0);
766fd52be0bSDylan Hung reg |= p_cfg->reg.w;
767fd52be0bSDylan Hung writel(reg, addr);
768fd52be0bSDylan Hung
769fd52be0bSDylan Hung /* write extend parameter */
770fd52be0bSDylan Hung writel(p_cfg->ext_reg, addr_ext);
771fd52be0bSDylan Hung udelay(100);
772fd52be0bSDylan Hung p_cfg->reg.b.off = 0;
773fd52be0bSDylan Hung p_cfg->reg.b.reset = 0;
774fd52be0bSDylan Hung reg &= ~GENMASK(25, 0);
775fd52be0bSDylan Hung reg |= p_cfg->reg.w;
776fd52be0bSDylan Hung writel(reg, addr);
777ed3899c5SRyan Chen while (!(readl(addr_ext) & BIT(31)))
778ed3899c5SRyan Chen ;
779fd52be0bSDylan Hung
780fd52be0bSDylan Hung return 0;
781fd52be0bSDylan Hung }
782ed3899c5SRyan Chen
ast2600_configure_ddr(struct ast2600_scu * scu,ulong rate)783feb42054Sryan_chen static u32 ast2600_configure_ddr(struct ast2600_scu *scu, ulong rate)
784550e691bSryan_chen {
785577fcdaeSDylan Hung struct ast2600_pll_desc mpll;
786550e691bSryan_chen
787577fcdaeSDylan Hung mpll.in = AST2600_CLK_IN;
788577fcdaeSDylan Hung mpll.out = rate;
789f27685ebSRyan Chen if (ast2600_search_clock_config(&mpll) == false) {
790577fcdaeSDylan Hung printf("error!! unable to find valid DDR clock setting\n");
791577fcdaeSDylan Hung return 0;
792577fcdaeSDylan Hung }
793ed3899c5SRyan Chen ast2600_configure_pll(scu, &mpll.cfg, ASPEED_CLK_MPLL);
794577fcdaeSDylan Hung
795cc476ffcSDylan Hung return ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
796d6e349c7Sryan_chen }
797d6e349c7Sryan_chen
ast2600_clk_set_rate(struct clk * clk,ulong rate)798d6e349c7Sryan_chen static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate)
799550e691bSryan_chen {
800f0d895afSryan_chen struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
801550e691bSryan_chen ulong new_rate;
802ed3899c5SRyan Chen
803550e691bSryan_chen switch (clk->id) {
804f0d895afSryan_chen case ASPEED_CLK_MPLL:
805feb42054Sryan_chen new_rate = ast2600_configure_ddr(priv->scu, rate);
806550e691bSryan_chen break;
807550e691bSryan_chen default:
808550e691bSryan_chen return -ENOENT;
809550e691bSryan_chen }
810550e691bSryan_chen
811550e691bSryan_chen return new_rate;
812550e691bSryan_chen }
813feb42054Sryan_chen
ast2600_calc_dly32_time(struct ast2600_scu * scu,int die_id,int stage)814e95b19f8SDylan Hung static int ast2600_calc_dly32_time(struct ast2600_scu *scu, int die_id, int stage)
815cc476ffcSDylan Hung {
816e95b19f8SDylan Hung int ret, i;
817e95b19f8SDylan Hung u64 sum = 0;
818e95b19f8SDylan Hung u32 base, value, reset_sel, dly32_sel;
819e95b19f8SDylan Hung
820e95b19f8SDylan Hung if (die_id) {
821e95b19f8SDylan Hung base = (u32)&scu->freq_counter_ctrl2;
822e95b19f8SDylan Hung reset_sel = FREQC_CTRL_SRC_SEL_HCLK_DIE1;
823e95b19f8SDylan Hung dly32_sel = FREQC_CTRL_SRC_SEL_DLY32_DIE1;
824e95b19f8SDylan Hung } else {
825e95b19f8SDylan Hung base = (u32)&scu->freq_counter_ctrl1;
826e95b19f8SDylan Hung reset_sel = FREQC_CTRL_SRC_SEL_HCLK_DIE0;
827e95b19f8SDylan Hung dly32_sel = FREQC_CTRL_SRC_SEL_DLY32_DIE0;
828e95b19f8SDylan Hung }
829e95b19f8SDylan Hung
830e95b19f8SDylan Hung for (i = 0; i < DLY32_AVERAGE_COUNT; i++) {
831e95b19f8SDylan Hung /* reset frequency-counter */
832e95b19f8SDylan Hung writel(FIELD_PREP(FREQC_CTRL_SRC_SEL, reset_sel), base);
833e95b19f8SDylan Hung ret = readl_poll_timeout(base, value, !(value & FREQC_CTRL_RESULT), 1000);
834e95b19f8SDylan Hung if (ret)
835e95b19f8SDylan Hung return -1;
836e95b19f8SDylan Hung
837e95b19f8SDylan Hung /* start frequency counter */
838e95b19f8SDylan Hung value = FIELD_PREP(FREQC_CTRL_RING_STAGE, stage)
839e95b19f8SDylan Hung | FIELD_PREP(FREQC_CTRL_SRC_SEL, dly32_sel)
840e95b19f8SDylan Hung | FIELD_PREP(FREQC_CTRL_RING_CTRL, FREQC_CTRL_RING_EN);
841e95b19f8SDylan Hung writel(value, base);
842e95b19f8SDylan Hung
843e95b19f8SDylan Hung /* delay for a while for settling down */
844e95b19f8SDylan Hung udelay(100);
845e95b19f8SDylan Hung
846e95b19f8SDylan Hung /* enable osc for measurement */
847e95b19f8SDylan Hung value |= FIELD_PREP(FREQC_CTRL_OSC_CTRL, FREQC_CTRL_OSC_EN);
848e95b19f8SDylan Hung writel(value, base);
849e95b19f8SDylan Hung ret = readl_poll_timeout(base, value, value & FREQC_CTRL_STATUS, 1000);
850e95b19f8SDylan Hung if (ret)
851e95b19f8SDylan Hung return -1;
852e95b19f8SDylan Hung
853e95b19f8SDylan Hung /* the result is represented in T count, will translate to pico-second later */
854e95b19f8SDylan Hung sum += FIELD_GET(FREQC_CTRL_RESULT, value);
855e95b19f8SDylan Hung }
856e95b19f8SDylan Hung
857e95b19f8SDylan Hung /* return the DLY32 value in pico-second */
858e95b19f8SDylan Hung return (2560000 / (int)(sum >> DLY32_AVERAGE_COUNT_LOG2));
859e95b19f8SDylan Hung }
860e95b19f8SDylan Hung
ast2600_init_dly32_lookup(struct ast2600_clk_priv * priv)861e95b19f8SDylan Hung static void ast2600_init_dly32_lookup(struct ast2600_clk_priv *priv)
862e95b19f8SDylan Hung {
863e95b19f8SDylan Hung struct ast2600_scu *scu = priv->scu;
864e95b19f8SDylan Hung int i;
865e95b19f8SDylan Hung
866e95b19f8SDylan Hung for (i = 0; i < DLY32_NUM_OF_TAPS; i++) {
867e95b19f8SDylan Hung priv->dly32_lookup[0][i] = ast2600_calc_dly32_time(scu, 0, i);
868e95b19f8SDylan Hung priv->dly32_lookup[1][i] = ast2600_calc_dly32_time(scu, 1, i);
869e95b19f8SDylan Hung }
870e95b19f8SDylan Hung
871e95b19f8SDylan Hung #ifdef DEBUG
872e95b19f8SDylan Hung for (i = 0; i < DLY32_NUM_OF_TAPS; i++)
873e95b19f8SDylan Hung printf("28nm DLY32[%d] = %d ps\n", i, priv->dly32_lookup[0][i]);
874e95b19f8SDylan Hung
875e95b19f8SDylan Hung for (i = 0; i < DLY32_NUM_OF_TAPS; i++)
876e95b19f8SDylan Hung printf("55nm DLY32[%d] = %d ps\n", i, priv->dly32_lookup[1][i]);
877e95b19f8SDylan Hung #endif
878e95b19f8SDylan Hung }
879e95b19f8SDylan Hung
880e95b19f8SDylan Hung /**
881e95b19f8SDylan Hung * @brief find the DLY32 tap number fitting the target delay time
882e95b19f8SDylan Hung *
883e95b19f8SDylan Hung * @param target_pico_sec target delay time in pico-second
884e95b19f8SDylan Hung * @param lookup DLY32 lookup table
885e95b19f8SDylan Hung * @return int DLY32 tap number
886e95b19f8SDylan Hung */
ast2600_find_dly32_tap(int target_pico_sec,int * lookup)887e95b19f8SDylan Hung static int ast2600_find_dly32_tap(int target_pico_sec, int *lookup)
888e95b19f8SDylan Hung {
8891e460bb5SDylan Hung int i;
8901e460bb5SDylan Hung bool found = false;
891e95b19f8SDylan Hung
8921e460bb5SDylan Hung for (i = 0; i < DLY32_NUM_OF_TAPS; i++) {
8931e460bb5SDylan Hung if (lookup[i] >= target_pico_sec) {
8941e460bb5SDylan Hung found = true;
8951e460bb5SDylan Hung break;
8961e460bb5SDylan Hung }
8971e460bb5SDylan Hung }
8981e460bb5SDylan Hung
8991e460bb5SDylan Hung if (!found)
900e95b19f8SDylan Hung return -1;
901e95b19f8SDylan Hung
90202e6089fSDylan Hung return i;
903e95b19f8SDylan Hung }
904e95b19f8SDylan Hung
ast2600_configure_mac12_clk(struct ast2600_clk_priv * priv,struct udevice * dev)905e95b19f8SDylan Hung static u32 ast2600_configure_mac12_clk(struct ast2600_clk_priv *priv, struct udevice *dev)
906e95b19f8SDylan Hung {
907e95b19f8SDylan Hung struct ast2600_scu *scu = priv->scu;
908a98c71fbSDylan Hung struct mac_delay_config mac1_cfg, mac2_cfg;
909e40a4e44SDylan Hung u32 reg[3];
910a98c71fbSDylan Hung int ret;
9114760b3f8SDylan Hung
912e40a4e44SDylan Hung reg[0] = MAC_DEF_DELAY_1G;
913e40a4e44SDylan Hung reg[1] = MAC_DEF_DELAY_100M;
914e40a4e44SDylan Hung reg[2] = MAC_DEF_DELAY_10M;
915a98c71fbSDylan Hung
916e95b19f8SDylan Hung ret = ast2600_find_dly32_tap(RGMII12_CLK_OUTPUT_DELAY_PS, priv->dly32_lookup[0]);
917e95b19f8SDylan Hung if (ret > 0) {
91802e6089fSDylan Hung debug("suggested tx delay for mac1/2: %d\n", priv->dly32_lookup[0][ret]);
919e95b19f8SDylan Hung
920e95b19f8SDylan Hung reg[0] &= ~(MAC_CLK_1G_OUTPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_2);
921e95b19f8SDylan Hung reg[0] |= FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, ret) |
922e95b19f8SDylan Hung FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, ret);
923e95b19f8SDylan Hung reg[1] &= ~(MAC_CLK_100M_10M_OUTPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
924e95b19f8SDylan Hung reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, ret) |
925e95b19f8SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, ret);
926e95b19f8SDylan Hung reg[2] &= ~(MAC_CLK_100M_10M_OUTPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
927e95b19f8SDylan Hung reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, ret) |
928e95b19f8SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, ret);
929e95b19f8SDylan Hung }
930e40a4e44SDylan Hung ret = dev_read_u32_array(dev, "mac0-clk-delay", (u32 *)&mac1_cfg,
931e40a4e44SDylan Hung sizeof(mac1_cfg) / sizeof(u32));
932a98c71fbSDylan Hung if (!ret) {
933e40a4e44SDylan Hung reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_1);
934e40a4e44SDylan Hung reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, mac1_cfg.rx_delay_1000) |
935e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, mac1_cfg.tx_delay_1000);
936e40a4e44SDylan Hung
937e40a4e44SDylan Hung reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
938e40a4e44SDylan Hung reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac1_cfg.rx_delay_100) |
939e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac1_cfg.tx_delay_100);
940e40a4e44SDylan Hung
941e40a4e44SDylan Hung reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
942e40a4e44SDylan Hung reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac1_cfg.rx_delay_10) |
943e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac1_cfg.tx_delay_10);
944a98c71fbSDylan Hung }
945a98c71fbSDylan Hung
946e40a4e44SDylan Hung ret = dev_read_u32_array(dev, "mac1-clk-delay", (u32 *)&mac2_cfg,
947e40a4e44SDylan Hung sizeof(mac2_cfg) / sizeof(u32));
948a98c71fbSDylan Hung if (!ret) {
949e40a4e44SDylan Hung reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_2 | MAC_CLK_1G_OUTPUT_DELAY_2);
950e40a4e44SDylan Hung reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, mac2_cfg.rx_delay_1000) |
951e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, mac2_cfg.tx_delay_1000);
952e40a4e44SDylan Hung
953e40a4e44SDylan Hung reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
954e40a4e44SDylan Hung reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac2_cfg.rx_delay_100) |
955e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac2_cfg.tx_delay_100);
956e40a4e44SDylan Hung
957e40a4e44SDylan Hung reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
958e40a4e44SDylan Hung reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac2_cfg.rx_delay_10) |
959e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac2_cfg.tx_delay_10);
960a98c71fbSDylan Hung }
961a98c71fbSDylan Hung
962e40a4e44SDylan Hung reg[0] |= (readl(&scu->mac12_clk_delay) & ~GENMASK(25, 0));
963e40a4e44SDylan Hung writel(reg[0], &scu->mac12_clk_delay);
964e40a4e44SDylan Hung writel(reg[1], &scu->mac12_clk_delay_100M);
965e40a4e44SDylan Hung writel(reg[2], &scu->mac12_clk_delay_10M);
966cc476ffcSDylan Hung
967ed30249cSDylan Hung /* MAC AHB = HPLL / 6 */
968eff28274SJohnny Huang clrsetbits_le32(&scu->clk_sel1, GENMASK(18, 16), (0x2 << 16));
969894c19cfSDylan Hung
970cc476ffcSDylan Hung return 0;
971cc476ffcSDylan Hung }
972cc476ffcSDylan Hung
ast2600_configure_mac34_clk(struct ast2600_clk_priv * priv,struct udevice * dev)973e95b19f8SDylan Hung static u32 ast2600_configure_mac34_clk(struct ast2600_clk_priv *priv, struct udevice *dev)
97454f9cba1SDylan Hung {
975e95b19f8SDylan Hung struct ast2600_scu *scu = priv->scu;
976a98c71fbSDylan Hung struct mac_delay_config mac3_cfg, mac4_cfg;
977e40a4e44SDylan Hung u32 reg[3];
978a98c71fbSDylan Hung int ret;
979a98c71fbSDylan Hung
980e40a4e44SDylan Hung reg[0] = MAC34_DEF_DELAY_1G;
981e40a4e44SDylan Hung reg[1] = MAC34_DEF_DELAY_100M;
982e40a4e44SDylan Hung reg[2] = MAC34_DEF_DELAY_10M;
983a98c71fbSDylan Hung
984e95b19f8SDylan Hung ret = ast2600_find_dly32_tap(RGMII34_CLK_OUTPUT_DELAY_PS, priv->dly32_lookup[1]);
985e95b19f8SDylan Hung if (ret > 0) {
98602e6089fSDylan Hung debug("suggested tx delay for mac3/4: %d\n", priv->dly32_lookup[1][ret]);
987e95b19f8SDylan Hung
988e95b19f8SDylan Hung reg[0] &= ~(MAC_CLK_1G_OUTPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_2);
989e95b19f8SDylan Hung reg[0] |= FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, ret) |
990e95b19f8SDylan Hung FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, ret);
991e95b19f8SDylan Hung reg[1] &= ~(MAC_CLK_100M_10M_OUTPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
992e95b19f8SDylan Hung reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, ret) |
993e95b19f8SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, ret);
994e95b19f8SDylan Hung reg[2] &= ~(MAC_CLK_100M_10M_OUTPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
995e95b19f8SDylan Hung reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, ret) |
996e95b19f8SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, ret);
997e95b19f8SDylan Hung }
998e95b19f8SDylan Hung
999a98c71fbSDylan Hung ret = dev_read_u32_array(dev, "mac2-clk-delay", (u32 *)&mac3_cfg, sizeof(mac3_cfg) / sizeof(u32));
1000a98c71fbSDylan Hung if (!ret) {
1001e40a4e44SDylan Hung reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_1);
1002e40a4e44SDylan Hung reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, mac3_cfg.rx_delay_1000) |
1003e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, mac3_cfg.tx_delay_1000);
1004e40a4e44SDylan Hung
1005e40a4e44SDylan Hung reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
1006e40a4e44SDylan Hung reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac3_cfg.rx_delay_100) |
1007e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac3_cfg.tx_delay_100);
1008e40a4e44SDylan Hung
1009e40a4e44SDylan Hung reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
1010e40a4e44SDylan Hung reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac3_cfg.rx_delay_10) |
1011e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac3_cfg.tx_delay_10);
1012a98c71fbSDylan Hung }
1013a98c71fbSDylan Hung
1014a98c71fbSDylan Hung ret = dev_read_u32_array(dev, "mac3-clk-delay", (u32 *)&mac4_cfg, sizeof(mac4_cfg) / sizeof(u32));
1015a98c71fbSDylan Hung if (!ret) {
1016e40a4e44SDylan Hung reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_2 | MAC_CLK_1G_OUTPUT_DELAY_2);
1017e40a4e44SDylan Hung reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, mac4_cfg.rx_delay_1000) |
1018e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, mac4_cfg.tx_delay_1000);
1019e40a4e44SDylan Hung
1020e40a4e44SDylan Hung reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
1021e40a4e44SDylan Hung reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac4_cfg.rx_delay_100) |
1022e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac4_cfg.tx_delay_100);
1023e40a4e44SDylan Hung
1024e40a4e44SDylan Hung reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
1025e40a4e44SDylan Hung reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac4_cfg.rx_delay_10) |
1026e40a4e44SDylan Hung FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac4_cfg.tx_delay_10);
1027a98c71fbSDylan Hung }
1028a98c71fbSDylan Hung
1029e40a4e44SDylan Hung reg[0] |= (readl(&scu->mac34_clk_delay) & ~GENMASK(25, 0));
1030e40a4e44SDylan Hung reg[0] &= ~MAC_CLK_RGMII_125M_SRC_SEL;
1031e40a4e44SDylan Hung reg[0] |= FIELD_PREP(MAC_CLK_RGMII_125M_SRC_SEL, MAC_CLK_RGMII_125M_SRC_PAD_RGMIICK);
1032e40a4e44SDylan Hung writel(reg[0], &scu->mac34_clk_delay);
1033e40a4e44SDylan Hung writel(reg[1], &scu->mac34_clk_delay_100M);
1034e40a4e44SDylan Hung writel(reg[2], &scu->mac34_clk_delay_10M);
103554f9cba1SDylan Hung
1036eff28274SJohnny Huang /*
1037eff28274SJohnny Huang * clock source seletion and divider
1038eff28274SJohnny Huang * scu310[26:24] : MAC AHB bus clock = HCLK / 2
1039eff28274SJohnny Huang * scu310[18:16] : RMII 50M = HCLK_200M / 4
1040eff28274SJohnny Huang */
1041eff28274SJohnny Huang clrsetbits_le32(&scu->clk_sel4, (GENMASK(26, 24) | GENMASK(18, 16)),
1042eff28274SJohnny Huang ((0x0 << 24) | (0x3 << 16)));
104354f9cba1SDylan Hung
1044eff28274SJohnny Huang /*
1045eff28274SJohnny Huang * set driving strength
1046eff28274SJohnny Huang * scu458[3:2] : MAC4 driving strength
1047eff28274SJohnny Huang * scu458[1:0] : MAC3 driving strength
1048eff28274SJohnny Huang */
1049eff28274SJohnny Huang clrsetbits_le32(&scu->pinmux_ctrl16, GENMASK(3, 0),
1050a961159eSDylan Hung (0x3 << 2) | (0x3 << 0));
105154f9cba1SDylan Hung
105254f9cba1SDylan Hung return 0;
105354f9cba1SDylan Hung }
1054eff28274SJohnny Huang
105554f9cba1SDylan Hung /**
10565b5c3d44SDylan Hung * ast2600 RGMII clock source tree
105754f9cba1SDylan Hung * 125M from external PAD -------->|\
105854f9cba1SDylan Hung * HPLL -->|\ | |---->RGMII 125M for MAC#1 & MAC#2
105954f9cba1SDylan Hung * | |---->| divider |---->|/ +
106054f9cba1SDylan Hung * EPLL -->|/ |
106154f9cba1SDylan Hung * |
1062eff28274SJohnny Huang * +---------<-----------|RGMIICK PAD output enable|<-------------+
106354f9cba1SDylan Hung * |
1064eff28274SJohnny Huang * +--------------------------->|\
106554f9cba1SDylan Hung * | |----> RGMII 125M for MAC#3 & MAC#4
1066eff28274SJohnny Huang * HCLK 200M ---->|divider|---->|/
1067eff28274SJohnny Huang * To simplify the control flow:
1068eff28274SJohnny Huang * 1. RGMII 1/2 always use EPLL as the internal clock source
1069eff28274SJohnny Huang * 2. RGMII 3/4 always use RGMIICK pad as the RGMII 125M source
1070eff28274SJohnny Huang * 125M from external PAD -------->|\
1071eff28274SJohnny Huang * | |---->RGMII 125M for MAC#1 & MAC#2
1072eff28274SJohnny Huang * EPLL---->| divider |--->|/ +
1073eff28274SJohnny Huang * |
1074eff28274SJohnny Huang * +<--------------------|RGMIICK PAD output enable|<-------------+
1075eff28274SJohnny Huang * |
1076eff28274SJohnny Huang * +--------------------------->RGMII 125M for MAC#3 & MAC#4
1077eff28274SJohnny Huang */
1078eff28274SJohnny Huang #define RGMIICK_SRC_PAD 0
1079eff28274SJohnny Huang #define RGMIICK_SRC_EPLL 1 /* recommended */
1080eff28274SJohnny Huang #define RGMIICK_SRC_HPLL 2
1081eff28274SJohnny Huang
1082eff28274SJohnny Huang #define RGMIICK_DIV2 1
1083eff28274SJohnny Huang #define RGMIICK_DIV3 2
1084eff28274SJohnny Huang #define RGMIICK_DIV4 3
1085eff28274SJohnny Huang #define RGMIICK_DIV5 4
1086eff28274SJohnny Huang #define RGMIICK_DIV6 5
1087eff28274SJohnny Huang #define RGMIICK_DIV7 6
1088eff28274SJohnny Huang #define RGMIICK_DIV8 7 /* recommended */
1089eff28274SJohnny Huang
1090eff28274SJohnny Huang #define RMIICK_DIV4 0
1091eff28274SJohnny Huang #define RMIICK_DIV8 1
1092eff28274SJohnny Huang #define RMIICK_DIV12 2
1093eff28274SJohnny Huang #define RMIICK_DIV16 3
1094eff28274SJohnny Huang #define RMIICK_DIV20 4 /* recommended */
1095eff28274SJohnny Huang #define RMIICK_DIV24 5
1096eff28274SJohnny Huang #define RMIICK_DIV28 6
1097eff28274SJohnny Huang #define RMIICK_DIV32 7
1098eff28274SJohnny Huang
1099eff28274SJohnny Huang struct ast2600_mac_clk_div {
1100eff28274SJohnny Huang u32 src; /* 0=external PAD, 1=internal PLL */
1101eff28274SJohnny Huang u32 fin; /* divider input speed */
1102eff28274SJohnny Huang u32 n; /* 0=div2, 1=div2, 2=div3, 3=div4,...,7=div8 */
1103eff28274SJohnny Huang u32 fout; /* fout = fin / n */
1104eff28274SJohnny Huang };
1105eff28274SJohnny Huang
1106eff28274SJohnny Huang struct ast2600_mac_clk_div rgmii_clk_defconfig = {
1107eff28274SJohnny Huang .src = ASPEED_CLK_EPLL,
1108eff28274SJohnny Huang .fin = 1000000000,
1109eff28274SJohnny Huang .n = RGMIICK_DIV8,
1110eff28274SJohnny Huang .fout = 125000000,
1111eff28274SJohnny Huang };
1112eff28274SJohnny Huang
1113eff28274SJohnny Huang struct ast2600_mac_clk_div rmii_clk_defconfig = {
1114eff28274SJohnny Huang .src = ASPEED_CLK_EPLL,
1115eff28274SJohnny Huang .fin = 1000000000,
1116eff28274SJohnny Huang .n = RMIICK_DIV20,
1117eff28274SJohnny Huang .fout = 50000000,
1118eff28274SJohnny Huang };
1119ed3899c5SRyan Chen
ast2600_init_mac_pll(struct ast2600_scu * p_scu,struct ast2600_mac_clk_div * p_cfg)1120eff28274SJohnny Huang static void ast2600_init_mac_pll(struct ast2600_scu *p_scu,
1121eff28274SJohnny Huang struct ast2600_mac_clk_div *p_cfg)
1122eff28274SJohnny Huang {
1123eff28274SJohnny Huang struct ast2600_pll_desc pll;
1124eff28274SJohnny Huang
1125eff28274SJohnny Huang pll.in = AST2600_CLK_IN;
1126eff28274SJohnny Huang pll.out = p_cfg->fin;
1127ed3899c5SRyan Chen if (ast2600_search_clock_config(&pll) == false) {
1128ed3899c5SRyan Chen pr_err("unable to find valid ETHNET MAC clock setting\n");
11293f295164SRyan Chen debug("%s: pll cfg = 0x%08x 0x%08x\n", __func__, pll.cfg.reg.w,
11303f295164SRyan Chen pll.cfg.ext_reg);
11313f295164SRyan Chen debug("%s: pll cfg = %02x %02x %02x\n", __func__,
11323f295164SRyan Chen pll.cfg.reg.b.m, pll.cfg.reg.b.n, pll.cfg.reg.b.p);
1133eff28274SJohnny Huang return;
1134eff28274SJohnny Huang }
1135ed3899c5SRyan Chen ast2600_configure_pll(p_scu, &pll.cfg, p_cfg->src);
1136eff28274SJohnny Huang }
1137eff28274SJohnny Huang
ast2600_init_rgmii_clk(struct ast2600_scu * p_scu,struct ast2600_mac_clk_div * p_cfg)1138eff28274SJohnny Huang static void ast2600_init_rgmii_clk(struct ast2600_scu *p_scu,
1139eff28274SJohnny Huang struct ast2600_mac_clk_div *p_cfg)
1140eff28274SJohnny Huang {
1141eff28274SJohnny Huang u32 reg_304 = readl(&p_scu->clk_sel2);
1142eff28274SJohnny Huang u32 reg_340 = readl(&p_scu->mac12_clk_delay);
1143eff28274SJohnny Huang u32 reg_350 = readl(&p_scu->mac34_clk_delay);
1144eff28274SJohnny Huang
1145e40a4e44SDylan Hung reg_340 &= ~(MAC_CLK_RGMII_125M_SRC_SEL | MAC_CLK_RMII2_50M_RCLK_O_CTRL |
1146e40a4e44SDylan Hung MAC_CLK_RMII1_50M_RCLK_O_CTRL | MAC_CLK_RGMIICK_PAD_DIR);
1147e40a4e44SDylan Hung /* RGMIICK PAD output enable (to MAC 3/4) */
1148e40a4e44SDylan Hung reg_340 |= FIELD_PREP(MAC_CLK_RGMIICK_PAD_DIR, MAC_CLK_RGMIICK_PAD_DIR_OUTPUT);
11493f295164SRyan Chen if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
1150eff28274SJohnny Huang /*
1151eff28274SJohnny Huang * re-init PLL if the current PLL output frequency doesn't match
1152eff28274SJohnny Huang * the divider setting
1153eff28274SJohnny Huang */
1154ed3899c5SRyan Chen if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
1155eff28274SJohnny Huang ast2600_init_mac_pll(p_scu, p_cfg);
1156e40a4e44SDylan Hung /* select RGMII 125M from internal source */
1157e40a4e44SDylan Hung reg_340 |= FIELD_PREP(MAC_CLK_RGMII_125M_SRC_SEL, MAC_CLK_RGMII_125M_SRC_PLL);
1158eff28274SJohnny Huang }
1159eff28274SJohnny Huang
1160eff28274SJohnny Huang reg_304 &= ~GENMASK(23, 20);
1161eff28274SJohnny Huang
1162eff28274SJohnny Huang /* set clock divider */
1163eff28274SJohnny Huang reg_304 |= (p_cfg->n & 0x7) << 20;
1164eff28274SJohnny Huang
1165eff28274SJohnny Huang /* select internal clock source */
1166ed3899c5SRyan Chen if (p_cfg->src == ASPEED_CLK_HPLL)
1167eff28274SJohnny Huang reg_304 |= BIT(23);
1168eff28274SJohnny Huang
1169eff28274SJohnny Huang /* RGMII 3/4 clock source select */
1170eff28274SJohnny Huang reg_350 &= ~BIT(31);
1171eff28274SJohnny Huang
1172eff28274SJohnny Huang writel(reg_304, &p_scu->clk_sel2);
1173eff28274SJohnny Huang writel(reg_340, &p_scu->mac12_clk_delay);
1174eff28274SJohnny Huang writel(reg_350, &p_scu->mac34_clk_delay);
1175eff28274SJohnny Huang }
1176eff28274SJohnny Huang
1177eff28274SJohnny Huang /**
11785b5c3d44SDylan Hung * ast2600 RMII/NCSI clock source tree
11795b5c3d44SDylan Hung * HPLL -->|\
11805b5c3d44SDylan Hung * | |---->| divider |----> RMII 50M for MAC#1 & MAC#2
11815b5c3d44SDylan Hung * EPLL -->|/
11825b5c3d44SDylan Hung * HCLK(SCLICLK)---->| divider |----> RMII 50M for MAC#3 & MAC#4
118354f9cba1SDylan Hung */
ast2600_init_rmii_clk(struct ast2600_scu * p_scu,struct ast2600_mac_clk_div * p_cfg)1184eff28274SJohnny Huang static void ast2600_init_rmii_clk(struct ast2600_scu *p_scu,
1185eff28274SJohnny Huang struct ast2600_mac_clk_div *p_cfg)
118654f9cba1SDylan Hung {
1187eff28274SJohnny Huang u32 reg_304;
1188eff28274SJohnny Huang u32 reg_310;
1189eff28274SJohnny Huang
11903f295164SRyan Chen if (p_cfg->src == ASPEED_CLK_EPLL || p_cfg->src == ASPEED_CLK_HPLL) {
1191eff28274SJohnny Huang /*
1192eff28274SJohnny Huang * re-init PLL if the current PLL output frequency doesn't match
1193eff28274SJohnny Huang * the divider setting
1194eff28274SJohnny Huang */
1195ed3899c5SRyan Chen if (p_cfg->fin != ast2600_get_pll_rate(p_scu, p_cfg->src))
1196eff28274SJohnny Huang ast2600_init_mac_pll(p_scu, p_cfg);
1197eff28274SJohnny Huang }
119854f9cba1SDylan Hung
1199eff28274SJohnny Huang reg_304 = readl(&p_scu->clk_sel2);
1200eff28274SJohnny Huang reg_310 = readl(&p_scu->clk_sel4);
1201eff28274SJohnny Huang
1202eff28274SJohnny Huang reg_304 &= ~GENMASK(19, 16);
1203eff28274SJohnny Huang
1204eff28274SJohnny Huang /* set RMII 1/2 clock divider */
1205eff28274SJohnny Huang reg_304 |= (p_cfg->n & 0x7) << 16;
1206eff28274SJohnny Huang
1207eff28274SJohnny Huang /* RMII clock source selection */
1208ed3899c5SRyan Chen if (p_cfg->src == ASPEED_CLK_HPLL)
1209eff28274SJohnny Huang reg_304 |= BIT(19);
1210eff28274SJohnny Huang
1211eff28274SJohnny Huang /* set RMII 3/4 clock divider */
1212eff28274SJohnny Huang reg_310 &= ~GENMASK(18, 16);
1213eff28274SJohnny Huang reg_310 |= (0x3 << 16);
1214eff28274SJohnny Huang
1215eff28274SJohnny Huang writel(reg_304, &p_scu->clk_sel2);
1216eff28274SJohnny Huang writel(reg_310, &p_scu->clk_sel4);
1217eff28274SJohnny Huang }
1218eff28274SJohnny Huang
ast2600_configure_mac(struct ast2600_scu * scu,int index)1219f9aa0ee1Sryan_chen static u32 ast2600_configure_mac(struct ast2600_scu *scu, int index)
1220f9aa0ee1Sryan_chen {
1221f9aa0ee1Sryan_chen u32 reset_bit;
1222f9aa0ee1Sryan_chen u32 clkstop_bit;
1223f9aa0ee1Sryan_chen
1224f9aa0ee1Sryan_chen switch (index) {
1225f9aa0ee1Sryan_chen case 1:
1226f9aa0ee1Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC1);
1227f9aa0ee1Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC1);
1228f9aa0ee1Sryan_chen writel(reset_bit, &scu->sysreset_ctrl1);
1229f9aa0ee1Sryan_chen udelay(100);
1230f9aa0ee1Sryan_chen writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1231f9aa0ee1Sryan_chen mdelay(10);
1232f9aa0ee1Sryan_chen writel(reset_bit, &scu->sysreset_clr_ctrl1);
1233f9aa0ee1Sryan_chen break;
1234f9aa0ee1Sryan_chen case 2:
1235f9aa0ee1Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC2);
1236f9aa0ee1Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC2);
1237f9aa0ee1Sryan_chen writel(reset_bit, &scu->sysreset_ctrl1);
1238f9aa0ee1Sryan_chen udelay(100);
1239f9aa0ee1Sryan_chen writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1240f9aa0ee1Sryan_chen mdelay(10);
1241f9aa0ee1Sryan_chen writel(reset_bit, &scu->sysreset_clr_ctrl1);
1242f9aa0ee1Sryan_chen break;
1243f9aa0ee1Sryan_chen case 3:
1244f9aa0ee1Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC3 - 32);
1245f9aa0ee1Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC3);
1246f9aa0ee1Sryan_chen writel(reset_bit, &scu->sysreset_ctrl2);
1247f9aa0ee1Sryan_chen udelay(100);
1248f9aa0ee1Sryan_chen writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1249f9aa0ee1Sryan_chen mdelay(10);
1250f9aa0ee1Sryan_chen writel(reset_bit, &scu->sysreset_clr_ctrl2);
1251f9aa0ee1Sryan_chen break;
1252f9aa0ee1Sryan_chen case 4:
1253f9aa0ee1Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC4 - 32);
1254f9aa0ee1Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC4);
1255f9aa0ee1Sryan_chen writel(reset_bit, &scu->sysreset_ctrl2);
1256f9aa0ee1Sryan_chen udelay(100);
1257f9aa0ee1Sryan_chen writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1258f9aa0ee1Sryan_chen mdelay(10);
1259f9aa0ee1Sryan_chen writel(reset_bit, &scu->sysreset_clr_ctrl2);
1260f9aa0ee1Sryan_chen break;
1261f9aa0ee1Sryan_chen default:
1262f9aa0ee1Sryan_chen return -EINVAL;
1263f9aa0ee1Sryan_chen }
1264f9aa0ee1Sryan_chen
1265f9aa0ee1Sryan_chen return 0;
1266f9aa0ee1Sryan_chen }
1267550e691bSryan_chen
1268a8fc7648SRyan Chen #define SCU_CLK_ECC_RSA_FROM_HPLL_CLK BIT(19)
1269a8fc7648SRyan Chen #define SCU_CLK_ECC_RSA_CLK_MASK GENMASK(27, 26)
1270ed3899c5SRyan Chen #define SCU_CLK_ECC_RSA_CLK_DIV(x) ((x) << 26)
ast2600_configure_rsa_ecc_clk(struct ast2600_scu * scu)1271a8fc7648SRyan Chen static void ast2600_configure_rsa_ecc_clk(struct ast2600_scu *scu)
1272a8fc7648SRyan Chen {
1273a8fc7648SRyan Chen u32 clk_sel = readl(&scu->clk_sel1);
1274a8fc7648SRyan Chen
12757e3c964cSJohnny Huang /* Configure RSA clock = HPLL/4 */
1276a8fc7648SRyan Chen clk_sel |= SCU_CLK_ECC_RSA_FROM_HPLL_CLK;
1277a8fc7648SRyan Chen clk_sel &= ~SCU_CLK_ECC_RSA_CLK_MASK;
12787e3c964cSJohnny Huang clk_sel |= SCU_CLK_ECC_RSA_CLK_DIV(3);
1279a8fc7648SRyan Chen
1280a8fc7648SRyan Chen writel(clk_sel, &scu->clk_sel1);
1281a8fc7648SRyan Chen }
1282a8fc7648SRyan Chen
1283f51926eeSryan_chen #define SCU_CLKSTOP_SDIO 4
ast2600_enable_sdclk(struct ast2600_scu * scu)1284f51926eeSryan_chen static ulong ast2600_enable_sdclk(struct ast2600_scu *scu)
1285f51926eeSryan_chen {
1286f51926eeSryan_chen u32 reset_bit;
1287f51926eeSryan_chen u32 clkstop_bit;
1288f51926eeSryan_chen
1289f51926eeSryan_chen reset_bit = BIT(ASPEED_RESET_SD - 32);
1290f51926eeSryan_chen clkstop_bit = BIT(SCU_CLKSTOP_SDIO);
1291f51926eeSryan_chen
1292fc9f12e6Sryan_chen writel(reset_bit, &scu->sysreset_ctrl2);
1293fc9f12e6Sryan_chen
1294f51926eeSryan_chen udelay(100);
1295f51926eeSryan_chen //enable clk
1296f51926eeSryan_chen writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1297f51926eeSryan_chen mdelay(10);
1298fc9f12e6Sryan_chen writel(reset_bit, &scu->sysreset_clr_ctrl2);
1299f51926eeSryan_chen
1300f51926eeSryan_chen return 0;
1301f51926eeSryan_chen }
1302f51926eeSryan_chen
1303f51926eeSryan_chen #define SCU_CLKSTOP_EXTSD 31
1304f51926eeSryan_chen #define SCU_CLK_SD_MASK (0x7 << 28)
1305ed3899c5SRyan Chen #define SCU_CLK_SD_DIV(x) ((x) << 28)
13062cd7cba2Sryan_chen #define SCU_CLK_SD_FROM_APLL_CLK BIT(8)
1307f51926eeSryan_chen
ast2600_enable_extsdclk(struct ast2600_scu * scu)1308f51926eeSryan_chen static ulong ast2600_enable_extsdclk(struct ast2600_scu *scu)
1309f51926eeSryan_chen {
1310f51926eeSryan_chen u32 clk_sel = readl(&scu->clk_sel4);
1311f51926eeSryan_chen u32 enableclk_bit;
13122cd7cba2Sryan_chen u32 rate = 0;
13132cd7cba2Sryan_chen u32 div = 0;
13142cd7cba2Sryan_chen int i = 0;
1315f51926eeSryan_chen
1316f51926eeSryan_chen enableclk_bit = BIT(SCU_CLKSTOP_EXTSD);
1317f51926eeSryan_chen
1318a8fc7648SRyan Chen /* ast2600 sd controller max clk is 200Mhz :
1319a8fc7648SRyan Chen * use apll for clock source 800/4 = 200 : controller max is 200mhz
1320a8fc7648SRyan Chen */
13212cd7cba2Sryan_chen rate = ast2600_get_apll_rate(scu);
13222cd7cba2Sryan_chen for (i = 0; i < 8; i++) {
13232cd7cba2Sryan_chen div = (i + 1) * 2;
13242cd7cba2Sryan_chen if ((rate / div) <= 200000000)
13252cd7cba2Sryan_chen break;
13262cd7cba2Sryan_chen }
1327f51926eeSryan_chen clk_sel &= ~SCU_CLK_SD_MASK;
13282cd7cba2Sryan_chen clk_sel |= SCU_CLK_SD_DIV(i) | SCU_CLK_SD_FROM_APLL_CLK;
1329f51926eeSryan_chen writel(clk_sel, &scu->clk_sel4);
1330f51926eeSryan_chen
1331f51926eeSryan_chen //enable clk
1332f51926eeSryan_chen setbits_le32(&scu->clk_sel4, enableclk_bit);
1333f51926eeSryan_chen
1334f51926eeSryan_chen return 0;
1335f51926eeSryan_chen }
1336f51926eeSryan_chen
1337f51926eeSryan_chen #define SCU_CLKSTOP_EMMC 27
ast2600_enable_emmcclk(struct ast2600_scu * scu)1338f51926eeSryan_chen static ulong ast2600_enable_emmcclk(struct ast2600_scu *scu)
1339f51926eeSryan_chen {
1340f51926eeSryan_chen u32 reset_bit;
1341f51926eeSryan_chen u32 clkstop_bit;
1342f51926eeSryan_chen
1343f51926eeSryan_chen reset_bit = BIT(ASPEED_RESET_EMMC);
1344f51926eeSryan_chen clkstop_bit = BIT(SCU_CLKSTOP_EMMC);
1345f51926eeSryan_chen
1346fc9f12e6Sryan_chen writel(reset_bit, &scu->sysreset_ctrl1);
1347f51926eeSryan_chen udelay(100);
1348f51926eeSryan_chen //enable clk
1349f51926eeSryan_chen writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1350f51926eeSryan_chen mdelay(10);
1351fc9f12e6Sryan_chen writel(reset_bit, &scu->sysreset_clr_ctrl1);
1352f51926eeSryan_chen
1353f51926eeSryan_chen return 0;
1354f51926eeSryan_chen }
1355f51926eeSryan_chen
1356f51926eeSryan_chen #define SCU_CLKSTOP_EXTEMMC 15
1357f51926eeSryan_chen #define SCU_CLK_EMMC_MASK (0x7 << 12)
1358ed3899c5SRyan Chen #define SCU_CLK_EMMC_DIV(x) ((x) << 12)
1359a8fc7648SRyan Chen #define SCU_CLK_EMMC_FROM_MPLL_CLK BIT(11)
1360f51926eeSryan_chen
ast2600_enable_extemmcclk(struct ast2600_scu * scu)1361f51926eeSryan_chen static ulong ast2600_enable_extemmcclk(struct ast2600_scu *scu)
1362f51926eeSryan_chen {
136385d48d8cSryan_chen u32 revision_id = readl(&scu->chip_id1);
1364f51926eeSryan_chen u32 clk_sel = readl(&scu->clk_sel1);
1365ed3899c5SRyan Chen u32 enableclk_bit = BIT(SCU_CLKSTOP_EXTEMMC);
1366f4c4ddb1Sryan_chen u32 rate = 0;
1367f4c4ddb1Sryan_chen u32 div = 0;
1368f4c4ddb1Sryan_chen int i = 0;
1369f51926eeSryan_chen
1370ed3899c5SRyan Chen /*
1371ed3899c5SRyan Chen * ast2600 eMMC controller max clk is 200Mhz
1372ed3899c5SRyan Chen * HPll->1/2->|\
1373ed3899c5SRyan Chen * |->SCU300[11]->SCU300[14:12][1/N] +
1374ed3899c5SRyan Chen * MPLL------>|/ |
1375ed3899c5SRyan Chen * +----------------------------------------------+
1376ed3899c5SRyan Chen * |
1377ed3899c5SRyan Chen * +---------> EMMC12C[15:8][1/N]-> eMMC clk
1378a8fc7648SRyan Chen */
137985d48d8cSryan_chen if (((revision_id & CHIP_REVISION_ID) >> 16)) {
13808c32294fSryan_chen //AST2600A1 : use mpll to be clk source
1381b0c30ea3Sryan_chen rate = ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL);
1382b0c30ea3Sryan_chen for (i = 0; i < 8; i++) {
1383b0c30ea3Sryan_chen div = (i + 1) * 2;
1384b0c30ea3Sryan_chen if ((rate / div) <= 200000000)
1385b0c30ea3Sryan_chen break;
1386b0c30ea3Sryan_chen }
1387b0c30ea3Sryan_chen
1388b0c30ea3Sryan_chen clk_sel &= ~SCU_CLK_EMMC_MASK;
13892cd7cba2Sryan_chen clk_sel |= SCU_CLK_EMMC_DIV(i) | SCU_CLK_EMMC_FROM_MPLL_CLK;
1390b0c30ea3Sryan_chen writel(clk_sel, &scu->clk_sel1);
1391b0c30ea3Sryan_chen
1392b0c30ea3Sryan_chen } else {
13932cd7cba2Sryan_chen //AST2600A0 : use hpll to be clk source
1394f4c4ddb1Sryan_chen rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL);
1395f4c4ddb1Sryan_chen
1396f4c4ddb1Sryan_chen for (i = 0; i < 8; i++) {
1397f4c4ddb1Sryan_chen div = (i + 1) * 4;
1398f4c4ddb1Sryan_chen if ((rate / div) <= 200000000)
1399f4c4ddb1Sryan_chen break;
1400f4c4ddb1Sryan_chen }
1401f4c4ddb1Sryan_chen
1402f4c4ddb1Sryan_chen clk_sel &= ~SCU_CLK_EMMC_MASK;
1403f4c4ddb1Sryan_chen clk_sel |= SCU_CLK_EMMC_DIV(i);
1404f51926eeSryan_chen writel(clk_sel, &scu->clk_sel1);
1405b0c30ea3Sryan_chen }
1406f51926eeSryan_chen setbits_le32(&scu->clk_sel1, enableclk_bit);
1407f51926eeSryan_chen
1408f51926eeSryan_chen return 0;
1409f51926eeSryan_chen }
1410f51926eeSryan_chen
1411baf00c26Sryan_chen #define SCU_CLKSTOP_FSICLK 30
1412baf00c26Sryan_chen
ast2600_enable_fsiclk(struct ast2600_scu * scu)1413baf00c26Sryan_chen static ulong ast2600_enable_fsiclk(struct ast2600_scu *scu)
1414baf00c26Sryan_chen {
1415baf00c26Sryan_chen u32 reset_bit;
1416baf00c26Sryan_chen u32 clkstop_bit;
1417baf00c26Sryan_chen
1418baf00c26Sryan_chen reset_bit = BIT(ASPEED_RESET_FSI % 32);
1419baf00c26Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_FSICLK);
1420baf00c26Sryan_chen
1421baf00c26Sryan_chen /* The FSI clock is shared between masters. If it's already on
1422ed3899c5SRyan Chen * don't touch it, as that will reset the existing master.
1423ed3899c5SRyan Chen */
1424baf00c26Sryan_chen if (!(readl(&scu->clk_stop_ctrl2) & clkstop_bit)) {
1425baf00c26Sryan_chen debug("%s: already running, not touching it\n", __func__);
1426baf00c26Sryan_chen return 0;
1427baf00c26Sryan_chen }
1428baf00c26Sryan_chen
1429baf00c26Sryan_chen writel(reset_bit, &scu->sysreset_ctrl2);
1430baf00c26Sryan_chen udelay(100);
1431baf00c26Sryan_chen writel(clkstop_bit, &scu->clk_stop_clr_ctrl2);
1432baf00c26Sryan_chen mdelay(10);
1433baf00c26Sryan_chen writel(reset_bit, &scu->sysreset_clr_ctrl2);
1434baf00c26Sryan_chen
1435baf00c26Sryan_chen return 0;
1436baf00c26Sryan_chen }
1437baf00c26Sryan_chen
ast2600_enable_usbahclk(struct ast2600_scu * scu)1438b8ec5ceaSryan_chen static ulong ast2600_enable_usbahclk(struct ast2600_scu *scu)
1439b8ec5ceaSryan_chen {
1440b8ec5ceaSryan_chen u32 reset_bit;
1441b8ec5ceaSryan_chen u32 clkstop_bit;
1442b8ec5ceaSryan_chen
1443b8ec5ceaSryan_chen reset_bit = BIT(ASPEED_RESET_EHCI_P1);
1444b8ec5ceaSryan_chen clkstop_bit = BIT(14);
1445b8ec5ceaSryan_chen
1446b8ec5ceaSryan_chen writel(reset_bit, &scu->sysreset_ctrl1);
1447b8ec5ceaSryan_chen udelay(100);
1448b8ec5ceaSryan_chen writel(clkstop_bit, &scu->clk_stop_ctrl1);
1449b8ec5ceaSryan_chen mdelay(20);
1450b8ec5ceaSryan_chen writel(reset_bit, &scu->sysreset_clr_ctrl1);
1451b8ec5ceaSryan_chen
1452b8ec5ceaSryan_chen return 0;
1453b8ec5ceaSryan_chen }
1454b8ec5ceaSryan_chen
ast2600_enable_usbbhclk(struct ast2600_scu * scu)1455b8ec5ceaSryan_chen static ulong ast2600_enable_usbbhclk(struct ast2600_scu *scu)
1456b8ec5ceaSryan_chen {
1457b8ec5ceaSryan_chen u32 reset_bit;
1458b8ec5ceaSryan_chen u32 clkstop_bit;
1459b8ec5ceaSryan_chen
1460b8ec5ceaSryan_chen reset_bit = BIT(ASPEED_RESET_EHCI_P2);
1461b8ec5ceaSryan_chen clkstop_bit = BIT(7);
1462b8ec5ceaSryan_chen
1463b8ec5ceaSryan_chen writel(reset_bit, &scu->sysreset_ctrl1);
1464b8ec5ceaSryan_chen udelay(100);
1465b8ec5ceaSryan_chen writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1466b8ec5ceaSryan_chen mdelay(20);
1467b8ec5ceaSryan_chen
1468b8ec5ceaSryan_chen writel(reset_bit, &scu->sysreset_clr_ctrl1);
1469b8ec5ceaSryan_chen
1470b8ec5ceaSryan_chen return 0;
1471b8ec5ceaSryan_chen }
1472b8ec5ceaSryan_chen
1473089713adSJoel Stanley /* also known as yclk */
ast2600_enable_haceclk(struct ast2600_scu * scu)1474089713adSJoel Stanley static ulong ast2600_enable_haceclk(struct ast2600_scu *scu)
1475089713adSJoel Stanley {
1476089713adSJoel Stanley u32 reset_bit;
1477089713adSJoel Stanley u32 clkstop_bit;
1478089713adSJoel Stanley
1479089713adSJoel Stanley reset_bit = BIT(ASPEED_RESET_HACE);
1480089713adSJoel Stanley clkstop_bit = BIT(13);
1481089713adSJoel Stanley
1482089713adSJoel Stanley writel(reset_bit, &scu->sysreset_ctrl1);
1483089713adSJoel Stanley udelay(100);
1484089713adSJoel Stanley writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1485089713adSJoel Stanley mdelay(20);
1486089713adSJoel Stanley
1487089713adSJoel Stanley writel(reset_bit, &scu->sysreset_clr_ctrl1);
1488089713adSJoel Stanley
1489089713adSJoel Stanley return 0;
1490089713adSJoel Stanley }
1491089713adSJoel Stanley
ast2600_enable_rsaeccclk(struct ast2600_scu * scu)1492f6110ecdSChia-Wei Wang static ulong ast2600_enable_rsaeccclk(struct ast2600_scu *scu)
1493f6110ecdSChia-Wei Wang {
1494f6110ecdSChia-Wei Wang u32 clkstop_bit;
1495f6110ecdSChia-Wei Wang
1496f6110ecdSChia-Wei Wang clkstop_bit = BIT(24);
1497f6110ecdSChia-Wei Wang
1498f6110ecdSChia-Wei Wang writel(clkstop_bit, &scu->clk_stop_clr_ctrl1);
1499f6110ecdSChia-Wei Wang mdelay(20);
1500f6110ecdSChia-Wei Wang
1501f6110ecdSChia-Wei Wang return 0;
1502f6110ecdSChia-Wei Wang }
1503f6110ecdSChia-Wei Wang
ast2600_clk_enable(struct clk * clk)1504d6e349c7Sryan_chen static int ast2600_clk_enable(struct clk *clk)
1505550e691bSryan_chen {
1506f0d895afSryan_chen struct ast2600_clk_priv *priv = dev_get_priv(clk->dev);
1507550e691bSryan_chen
1508550e691bSryan_chen switch (clk->id) {
150986f91560Sryan_chen case ASPEED_CLK_GATE_MAC1CLK:
151086f91560Sryan_chen ast2600_configure_mac(priv->scu, 1);
1511550e691bSryan_chen break;
151286f91560Sryan_chen case ASPEED_CLK_GATE_MAC2CLK:
151386f91560Sryan_chen ast2600_configure_mac(priv->scu, 2);
1514550e691bSryan_chen break;
151577843939Sryan_chen case ASPEED_CLK_GATE_MAC3CLK:
151677843939Sryan_chen ast2600_configure_mac(priv->scu, 3);
151777843939Sryan_chen break;
151877843939Sryan_chen case ASPEED_CLK_GATE_MAC4CLK:
151977843939Sryan_chen ast2600_configure_mac(priv->scu, 4);
152077843939Sryan_chen break;
1521f51926eeSryan_chen case ASPEED_CLK_GATE_SDCLK:
1522f51926eeSryan_chen ast2600_enable_sdclk(priv->scu);
1523f51926eeSryan_chen break;
1524f51926eeSryan_chen case ASPEED_CLK_GATE_SDEXTCLK:
1525f51926eeSryan_chen ast2600_enable_extsdclk(priv->scu);
1526f51926eeSryan_chen break;
1527f51926eeSryan_chen case ASPEED_CLK_GATE_EMMCCLK:
1528f51926eeSryan_chen ast2600_enable_emmcclk(priv->scu);
1529f51926eeSryan_chen break;
1530f51926eeSryan_chen case ASPEED_CLK_GATE_EMMCEXTCLK:
1531f51926eeSryan_chen ast2600_enable_extemmcclk(priv->scu);
1532f51926eeSryan_chen break;
1533baf00c26Sryan_chen case ASPEED_CLK_GATE_FSICLK:
1534baf00c26Sryan_chen ast2600_enable_fsiclk(priv->scu);
1535baf00c26Sryan_chen break;
1536b8ec5ceaSryan_chen case ASPEED_CLK_GATE_USBPORT1CLK:
1537b8ec5ceaSryan_chen ast2600_enable_usbahclk(priv->scu);
1538b8ec5ceaSryan_chen break;
1539b8ec5ceaSryan_chen case ASPEED_CLK_GATE_USBPORT2CLK:
1540b8ec5ceaSryan_chen ast2600_enable_usbbhclk(priv->scu);
1541b8ec5ceaSryan_chen break;
1542089713adSJoel Stanley case ASPEED_CLK_GATE_YCLK:
1543089713adSJoel Stanley ast2600_enable_haceclk(priv->scu);
1544089713adSJoel Stanley break;
1545f6110ecdSChia-Wei Wang case ASPEED_CLK_GATE_RSAECCCLK:
1546f6110ecdSChia-Wei Wang ast2600_enable_rsaeccclk(priv->scu);
1547f6110ecdSChia-Wei Wang break;
1548550e691bSryan_chen default:
1549ed3899c5SRyan Chen pr_err("can't enable clk\n");
1550550e691bSryan_chen return -ENOENT;
1551550e691bSryan_chen }
1552550e691bSryan_chen
1553550e691bSryan_chen return 0;
1554550e691bSryan_chen }
1555550e691bSryan_chen
1556f9aa0ee1Sryan_chen struct clk_ops ast2600_clk_ops = {
1557d6e349c7Sryan_chen .get_rate = ast2600_clk_get_rate,
1558d6e349c7Sryan_chen .set_rate = ast2600_clk_set_rate,
1559d6e349c7Sryan_chen .enable = ast2600_clk_enable,
1560550e691bSryan_chen };
1561550e691bSryan_chen
ast2600_clk_probe(struct udevice * dev)1562d6e349c7Sryan_chen static int ast2600_clk_probe(struct udevice *dev)
1563550e691bSryan_chen {
1564f0d895afSryan_chen struct ast2600_clk_priv *priv = dev_get_priv(dev);
156561ab9607Sryan_chen u32 uart_clk_source;
1566550e691bSryan_chen
1567f0d895afSryan_chen priv->scu = devfdt_get_addr_ptr(dev);
1568f0d895afSryan_chen if (IS_ERR(priv->scu))
1569f0d895afSryan_chen return PTR_ERR(priv->scu);
1570550e691bSryan_chen
15715d05f4fcSRyan Chen uart_clk_source = dev_read_u32_default(dev, "uart-clk-source", 0x0);
157261ab9607Sryan_chen
157361ab9607Sryan_chen if (uart_clk_source) {
157456dd3e85Sryan_chen if (uart_clk_source & GENMASK(5, 0))
15755d05f4fcSRyan Chen setbits_le32(&priv->scu->clk_sel4,
15765d05f4fcSRyan Chen uart_clk_source & GENMASK(5, 0));
157756dd3e85Sryan_chen if (uart_clk_source & GENMASK(12, 6))
15785d05f4fcSRyan Chen setbits_le32(&priv->scu->clk_sel5,
15795d05f4fcSRyan Chen uart_clk_source & GENMASK(12, 6));
158061ab9607Sryan_chen }
158161ab9607Sryan_chen
1582b89500a2SDylan Hung ast2600_init_rgmii_clk(priv->scu, &rgmii_clk_defconfig);
1583b89500a2SDylan Hung ast2600_init_rmii_clk(priv->scu, &rmii_clk_defconfig);
1584e95b19f8SDylan Hung ast2600_init_dly32_lookup(priv);
1585e95b19f8SDylan Hung ast2600_configure_mac12_clk(priv, dev);
1586e95b19f8SDylan Hung ast2600_configure_mac34_clk(priv, dev);
1587a8fc7648SRyan Chen ast2600_configure_rsa_ecc_clk(priv->scu);
1588fd0306aaSJohnny Huang
1589550e691bSryan_chen return 0;
1590550e691bSryan_chen }
1591550e691bSryan_chen
ast2600_clk_bind(struct udevice * dev)1592d6e349c7Sryan_chen static int ast2600_clk_bind(struct udevice *dev)
1593550e691bSryan_chen {
1594550e691bSryan_chen int ret;
1595550e691bSryan_chen
1596550e691bSryan_chen /* The reset driver does not have a device node, so bind it here */
1597550e691bSryan_chen ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
1598550e691bSryan_chen if (ret)
1599550e691bSryan_chen debug("Warning: No reset driver: ret=%d\n", ret);
1600550e691bSryan_chen
1601550e691bSryan_chen return 0;
1602550e691bSryan_chen }
1603550e691bSryan_chen
1604d35ac78cSryan_chen struct aspeed_clks {
1605d35ac78cSryan_chen ulong id;
1606d35ac78cSryan_chen const char *name;
1607d35ac78cSryan_chen };
1608d35ac78cSryan_chen
1609d35ac78cSryan_chen static struct aspeed_clks aspeed_clk_names[] = {
16105d05f4fcSRyan Chen { ASPEED_CLK_HPLL, "hpll" }, { ASPEED_CLK_MPLL, "mpll" },
16115d05f4fcSRyan Chen { ASPEED_CLK_APLL, "apll" }, { ASPEED_CLK_EPLL, "epll" },
16125d05f4fcSRyan Chen { ASPEED_CLK_DPLL, "dpll" }, { ASPEED_CLK_AHB, "hclk" },
16135d05f4fcSRyan Chen { ASPEED_CLK_APB1, "pclk1" }, { ASPEED_CLK_APB2, "pclk2" },
16145d05f4fcSRyan Chen { ASPEED_CLK_BCLK, "bclk" }, { ASPEED_CLK_UARTX, "uxclk" },
1615def99fcbSryan_chen { ASPEED_CLK_HUARTX, "huxclk" },
1616d35ac78cSryan_chen };
1617d35ac78cSryan_chen
soc_clk_dump(void)1618d35ac78cSryan_chen int soc_clk_dump(void)
1619d35ac78cSryan_chen {
1620d35ac78cSryan_chen struct udevice *dev;
1621d35ac78cSryan_chen struct clk clk;
1622d35ac78cSryan_chen unsigned long rate;
1623d35ac78cSryan_chen int i, ret;
1624d35ac78cSryan_chen
16255d05f4fcSRyan Chen ret = uclass_get_device_by_driver(UCLASS_CLK, DM_GET_DRIVER(aspeed_scu),
16265d05f4fcSRyan Chen &dev);
1627d35ac78cSryan_chen if (ret)
1628d35ac78cSryan_chen return ret;
1629d35ac78cSryan_chen
1630d35ac78cSryan_chen printf("Clk\t\tHz\n");
1631d35ac78cSryan_chen
1632d35ac78cSryan_chen for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) {
1633d35ac78cSryan_chen clk.id = aspeed_clk_names[i].id;
1634d35ac78cSryan_chen ret = clk_request(dev, &clk);
1635d35ac78cSryan_chen if (ret < 0) {
1636d35ac78cSryan_chen debug("%s clk_request() failed: %d\n", __func__, ret);
1637d35ac78cSryan_chen continue;
1638d35ac78cSryan_chen }
1639d35ac78cSryan_chen
1640d35ac78cSryan_chen ret = clk_get_rate(&clk);
1641d35ac78cSryan_chen rate = ret;
1642d35ac78cSryan_chen
1643d35ac78cSryan_chen clk_free(&clk);
1644d35ac78cSryan_chen
1645d35ac78cSryan_chen if (ret == -ENOTSUPP) {
1646d35ac78cSryan_chen printf("clk ID %lu not supported yet\n",
1647d35ac78cSryan_chen aspeed_clk_names[i].id);
1648d35ac78cSryan_chen continue;
1649d35ac78cSryan_chen }
1650d35ac78cSryan_chen if (ret < 0) {
16515d05f4fcSRyan Chen printf("%s %lu: get_rate err: %d\n", __func__,
16525d05f4fcSRyan Chen aspeed_clk_names[i].id, ret);
1653d35ac78cSryan_chen continue;
1654d35ac78cSryan_chen }
1655d35ac78cSryan_chen
16565d05f4fcSRyan Chen printf("%s(%3lu):\t%lu\n", aspeed_clk_names[i].name,
16575d05f4fcSRyan Chen aspeed_clk_names[i].id, rate);
1658d35ac78cSryan_chen }
1659d35ac78cSryan_chen
1660d35ac78cSryan_chen return 0;
1661d35ac78cSryan_chen }
1662d35ac78cSryan_chen
1663d6e349c7Sryan_chen static const struct udevice_id ast2600_clk_ids[] = {
16645d05f4fcSRyan Chen {
16655d05f4fcSRyan Chen .compatible = "aspeed,ast2600-scu",
16665d05f4fcSRyan Chen },
1667550e691bSryan_chen {}
1668550e691bSryan_chen };
1669550e691bSryan_chen
1670aa36597fSDylan Hung U_BOOT_DRIVER(aspeed_scu) = {
1671aa36597fSDylan Hung .name = "aspeed_scu",
1672550e691bSryan_chen .id = UCLASS_CLK,
1673d6e349c7Sryan_chen .of_match = ast2600_clk_ids,
1674f0d895afSryan_chen .priv_auto_alloc_size = sizeof(struct ast2600_clk_priv),
1675f9aa0ee1Sryan_chen .ops = &ast2600_clk_ops,
1676d6e349c7Sryan_chen .bind = ast2600_clk_bind,
1677d6e349c7Sryan_chen .probe = ast2600_clk_probe,
1678550e691bSryan_chen };
1679