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 216bbbfb0c5Sryan_chen extern u32 ast2600_get_pll_rate(struct ast2600_scu *scu, int pll_idx) 217550e691bSryan_chen { 218d6e349c7Sryan_chen u32 clkin = AST2600_CLK_IN; 219bbbfb0c5Sryan_chen u32 pll_reg = 0; 2209639db61Sryan_chen unsigned int mult, div = 1; 221550e691bSryan_chen 222bbbfb0c5Sryan_chen switch (pll_idx) { 223bbbfb0c5Sryan_chen case ASPEED_CLK_HPLL: 224bbbfb0c5Sryan_chen pll_reg = readl(&scu->h_pll_param); 225bbbfb0c5Sryan_chen break; 226bbbfb0c5Sryan_chen case ASPEED_CLK_MPLL: 227bbbfb0c5Sryan_chen pll_reg = readl(&scu->m_pll_param); 228bbbfb0c5Sryan_chen break; 229bbbfb0c5Sryan_chen case ASPEED_CLK_DPLL: 230bbbfb0c5Sryan_chen pll_reg = readl(&scu->d_pll_param); 231bbbfb0c5Sryan_chen break; 232bbbfb0c5Sryan_chen case ASPEED_CLK_EPLL: 233bbbfb0c5Sryan_chen pll_reg = readl(&scu->e_pll_param); 234bbbfb0c5Sryan_chen break; 235bbbfb0c5Sryan_chen } 236bbbfb0c5Sryan_chen if (pll_reg & BIT(24)) { 2379639db61Sryan_chen /* Pass through mode */ 238ed3899c5SRyan Chen mult = 1; 239ed3899c5SRyan Chen div = 1; 2409639db61Sryan_chen } else { 24175ced45aSDylan Hung union ast2600_pll_reg reg; 242ed3899c5SRyan Chen /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1) 243ed3899c5SRyan Chen * HPLL Numerator (M) = fix 0x5F when SCU500[10]=1 244ed3899c5SRyan Chen * Fixed 0xBF when SCU500[10]=0 and SCU500[8]=1 245ed3899c5SRyan Chen * SCU200[12:0] (default 0x8F) when SCU510[10]=0 and SCU510[8]=0 246ed3899c5SRyan Chen * HPLL Denumerator (N) = SCU200[18:13] (default 0x2) 247ed3899c5SRyan Chen * HPLL Divider (P) = SCU200[22:19] (default 0x0) 248ed3899c5SRyan Chen * HPLL Bandwidth Adj (NB) = fix 0x2F when SCU500[10]=1 249ed3899c5SRyan Chen * Fixed 0x5F when SCU500[10]=0 and SCU500[8]=1 250ed3899c5SRyan Chen * SCU204[11:0] (default 0x31) when SCU500[10]=0 and SCU500[8]=0 251e5c4f4dfSryan_chen */ 252ed3899c5SRyan Chen reg.w = pll_reg; 253f27685ebSRyan Chen if (pll_idx == ASPEED_CLK_HPLL) { 254e5c4f4dfSryan_chen u32 hwstrap1 = readl(&scu->hwstrap1.hwstrap); 255ed3899c5SRyan Chen 256ed3899c5SRyan Chen if (hwstrap1 & BIT(10)) { 257e5c4f4dfSryan_chen reg.b.m = 0x5F; 258ed3899c5SRyan Chen } else { 259e5c4f4dfSryan_chen if (hwstrap1 & BIT(8)) 260e5c4f4dfSryan_chen reg.b.m = 0xBF; 261a8fc7648SRyan Chen /* Otherwise keep default 0x8F */ 262e5c4f4dfSryan_chen } 263e5c4f4dfSryan_chen } 26475ced45aSDylan Hung mult = (reg.b.m + 1) / (reg.b.n + 1); 26575ced45aSDylan Hung div = (reg.b.p + 1); 2669639db61Sryan_chen } 267a8fc7648SRyan Chen 2689639db61Sryan_chen return ((clkin * mult) / div); 269550e691bSryan_chen } 270550e691bSryan_chen 2714f22e838Sryan_chen extern u32 ast2600_get_apll_rate(struct ast2600_scu *scu) 272550e691bSryan_chen { 27385d48d8cSryan_chen u32 hw_rev = readl(&scu->chip_id1); 274bbbfb0c5Sryan_chen u32 clkin = AST2600_CLK_IN; 27539283ea7Sryan_chen u32 apll_reg = readl(&scu->a_pll_param); 27639283ea7Sryan_chen unsigned int mult, div = 1; 277d6e349c7Sryan_chen 2788d615c79SRyan Chen if (((hw_rev & CHIP_REVISION_ID) >> 16) >= 2) { 279a8fc7648SRyan Chen //after A2 version 28085d48d8cSryan_chen if (apll_reg & BIT(24)) { 28185d48d8cSryan_chen /* Pass through mode */ 282ed3899c5SRyan Chen mult = 1; 283ed3899c5SRyan Chen div = 1; 28485d48d8cSryan_chen } else { 28585d48d8cSryan_chen /* F = 25Mhz * [(m + 1) / (n + 1)] / (p + 1) */ 28685d48d8cSryan_chen u32 m = apll_reg & 0x1fff; 28785d48d8cSryan_chen u32 n = (apll_reg >> 13) & 0x3f; 28885d48d8cSryan_chen u32 p = (apll_reg >> 19) & 0xf; 28985d48d8cSryan_chen 29085d48d8cSryan_chen mult = (m + 1); 29185d48d8cSryan_chen div = (n + 1) * (p + 1); 29285d48d8cSryan_chen } 29385d48d8cSryan_chen } else { 29439283ea7Sryan_chen if (apll_reg & BIT(20)) { 295d6e349c7Sryan_chen /* Pass through mode */ 296ed3899c5SRyan Chen mult = 1; 297ed3899c5SRyan Chen div = 1; 298d6e349c7Sryan_chen } else { 299bbbfb0c5Sryan_chen /* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */ 30039283ea7Sryan_chen u32 m = (apll_reg >> 5) & 0x3f; 30139283ea7Sryan_chen u32 od = (apll_reg >> 4) & 0x1; 30239283ea7Sryan_chen u32 n = apll_reg & 0xf; 303d6e349c7Sryan_chen 304bbbfb0c5Sryan_chen mult = (2 - od) * (m + 2); 305bbbfb0c5Sryan_chen div = n + 1; 306d6e349c7Sryan_chen } 30785d48d8cSryan_chen } 308a8fc7648SRyan Chen 309bbbfb0c5Sryan_chen return ((clkin * mult) / div); 31039283ea7Sryan_chen } 31139283ea7Sryan_chen 312d812df15Sryan_chen static u32 ast2600_a0_axi_ahb_div_table[] = { 3135d05f4fcSRyan Chen 2, 3145d05f4fcSRyan Chen 2, 3155d05f4fcSRyan Chen 3, 3165d05f4fcSRyan Chen 4, 317d812df15Sryan_chen }; 318d812df15Sryan_chen 31945e0908aSryan_chen static u32 ast2600_a1_axi_ahb_div0_table[] = { 3205d05f4fcSRyan Chen 3, 3215d05f4fcSRyan Chen 2, 3225d05f4fcSRyan Chen 3, 3235d05f4fcSRyan Chen 4, 32445e0908aSryan_chen }; 32545e0908aSryan_chen 32645e0908aSryan_chen static u32 ast2600_a1_axi_ahb_div1_table[] = { 3275d05f4fcSRyan Chen 3, 3285d05f4fcSRyan Chen 4, 3295d05f4fcSRyan Chen 6, 3305d05f4fcSRyan Chen 8, 331e29dc694Sryan_chen }; 332e29dc694Sryan_chen 333e29dc694Sryan_chen static u32 ast2600_a1_axi_ahb_default_table[] = { 334e29dc694Sryan_chen 3, 4, 3, 4, 2, 2, 2, 2, 335d812df15Sryan_chen }; 336d812df15Sryan_chen 337d812df15Sryan_chen static u32 ast2600_get_hclk(struct ast2600_scu *scu) 338d812df15Sryan_chen { 33985d48d8cSryan_chen u32 hw_rev = readl(&scu->chip_id1); 34045e0908aSryan_chen u32 hwstrap1 = readl(&scu->hwstrap1.hwstrap); 341d812df15Sryan_chen u32 axi_div = 1; 342d812df15Sryan_chen u32 ahb_div = 0; 343d812df15Sryan_chen u32 rate = 0; 344d812df15Sryan_chen 34585d48d8cSryan_chen if ((hw_rev & CHIP_REVISION_ID) >> 16) { 346a8fc7648SRyan Chen //After A0 34745e0908aSryan_chen if (hwstrap1 & BIT(16)) { 348a8fc7648SRyan Chen ast2600_a1_axi_ahb_div1_table[0] = 3495d05f4fcSRyan Chen ast2600_a1_axi_ahb_default_table[(hwstrap1 >> 8) & 35022545706SRyan Chen 0x7] * 2; 351d812df15Sryan_chen axi_div = 1; 3525d05f4fcSRyan Chen ahb_div = 3535d05f4fcSRyan Chen ast2600_a1_axi_ahb_div1_table[(hwstrap1 >> 11) & 3545d05f4fcSRyan Chen 0x3]; 35545e0908aSryan_chen } else { 356a8fc7648SRyan Chen ast2600_a1_axi_ahb_div0_table[0] = 3575d05f4fcSRyan Chen ast2600_a1_axi_ahb_default_table[(hwstrap1 >> 8) & 35822545706SRyan Chen 0x7]; 359d812df15Sryan_chen axi_div = 2; 3605d05f4fcSRyan Chen ahb_div = 3615d05f4fcSRyan Chen ast2600_a1_axi_ahb_div0_table[(hwstrap1 >> 11) & 3625d05f4fcSRyan Chen 0x3]; 36345e0908aSryan_chen } 36445e0908aSryan_chen } else { 365a8fc7648SRyan Chen //A0 : fix axi = hpll / 2 36645e0908aSryan_chen axi_div = 2; 367d812df15Sryan_chen ahb_div = ast2600_a0_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3]; 36845e0908aSryan_chen } 369bbbfb0c5Sryan_chen rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL); 370a8fc7648SRyan Chen 3712717883aSryan_chen return (rate / axi_div / ahb_div); 3722717883aSryan_chen } 3732717883aSryan_chen 374c304f173Sryan_chen static u32 ast2600_get_bclk_rate(struct ast2600_scu *scu) 375c304f173Sryan_chen { 376c304f173Sryan_chen u32 rate; 377c304f173Sryan_chen u32 bclk_sel = (readl(&scu->clk_sel1) >> 20) & 0x7; 378ed3899c5SRyan Chen 379*8ad54a5aSryan_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 3926fa1ef3dSryan_chen static u32 ast2600_get_pclk1(struct ast2600_scu *scu) 3932717883aSryan_chen { 3942717883aSryan_chen u32 clk_sel1 = readl(&scu->clk_sel1); 3956fa1ef3dSryan_chen u32 apb_div = ast2600_hpll_pclk1_div_table[((clk_sel1 >> 23) & 0x7)]; 396bbbfb0c5Sryan_chen u32 rate = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL); 3972717883aSryan_chen 3982717883aSryan_chen return (rate / apb_div); 399d812df15Sryan_chen } 400d812df15Sryan_chen 4016fa1ef3dSryan_chen static u32 ast2600_get_pclk2(struct ast2600_scu *scu) 4026fa1ef3dSryan_chen { 4036fa1ef3dSryan_chen u32 clk_sel4 = readl(&scu->clk_sel4); 4046fa1ef3dSryan_chen u32 apb_div = ast2600_hpll_pclk2_div_table[((clk_sel4 >> 9) & 0x7)]; 4056fa1ef3dSryan_chen u32 rate = ast2600_get_hclk(scu); 4066fa1ef3dSryan_chen 4076fa1ef3dSryan_chen return (rate / apb_div); 4086fa1ef3dSryan_chen } 4096fa1ef3dSryan_chen 4102e195992Sryan_chen static u32 ast2600_get_uxclk_in_rate(struct ast2600_scu *scu) 411d6e349c7Sryan_chen { 41227881d20Sryan_chen u32 clk_in = 0; 4132e195992Sryan_chen u32 uxclk_sel = readl(&scu->clk_sel5); 414550e691bSryan_chen 41527881d20Sryan_chen uxclk_sel &= 0x3; 41627881d20Sryan_chen switch (uxclk_sel) { 41727881d20Sryan_chen case 0: 41827881d20Sryan_chen clk_in = ast2600_get_apll_rate(scu) / 4; 41927881d20Sryan_chen break; 42027881d20Sryan_chen case 1: 42127881d20Sryan_chen clk_in = ast2600_get_apll_rate(scu) / 2; 42227881d20Sryan_chen break; 42327881d20Sryan_chen case 2: 42427881d20Sryan_chen clk_in = ast2600_get_apll_rate(scu); 42527881d20Sryan_chen break; 42627881d20Sryan_chen case 3: 42727881d20Sryan_chen clk_in = ast2600_get_hclk(scu); 42827881d20Sryan_chen break; 42927881d20Sryan_chen } 430d6e349c7Sryan_chen 43127881d20Sryan_chen return clk_in; 43227881d20Sryan_chen } 43327881d20Sryan_chen 4342e195992Sryan_chen static u32 ast2600_get_huxclk_in_rate(struct ast2600_scu *scu) 43527881d20Sryan_chen { 43627881d20Sryan_chen u32 clk_in = 0; 4372e195992Sryan_chen u32 huclk_sel = readl(&scu->clk_sel5); 43827881d20Sryan_chen 43927881d20Sryan_chen huclk_sel = ((huclk_sel >> 3) & 0x3); 44027881d20Sryan_chen switch (huclk_sel) { 44127881d20Sryan_chen case 0: 44227881d20Sryan_chen clk_in = ast2600_get_apll_rate(scu) / 4; 44327881d20Sryan_chen break; 44427881d20Sryan_chen case 1: 44527881d20Sryan_chen clk_in = ast2600_get_apll_rate(scu) / 2; 44627881d20Sryan_chen break; 44727881d20Sryan_chen case 2: 44827881d20Sryan_chen clk_in = ast2600_get_apll_rate(scu); 44927881d20Sryan_chen break; 45027881d20Sryan_chen case 3: 45127881d20Sryan_chen clk_in = ast2600_get_hclk(scu); 45227881d20Sryan_chen break; 45327881d20Sryan_chen } 45427881d20Sryan_chen 45527881d20Sryan_chen return clk_in; 45627881d20Sryan_chen } 45727881d20Sryan_chen 4582e195992Sryan_chen static u32 ast2600_get_uart_uxclk_rate(struct ast2600_scu *scu) 45927881d20Sryan_chen { 4602e195992Sryan_chen u32 clk_in = ast2600_get_uxclk_in_rate(scu); 46127881d20Sryan_chen u32 div_reg = readl(&scu->uart_24m_ref_uxclk); 46227881d20Sryan_chen unsigned int mult, div; 46327881d20Sryan_chen 46427881d20Sryan_chen u32 n = (div_reg >> 8) & 0x3ff; 46527881d20Sryan_chen u32 r = div_reg & 0xff; 46627881d20Sryan_chen 46727881d20Sryan_chen mult = r; 4682e195992Sryan_chen div = (n * 2); 46927881d20Sryan_chen return (clk_in * mult) / div; 47027881d20Sryan_chen } 47127881d20Sryan_chen 4722e195992Sryan_chen static u32 ast2600_get_uart_huxclk_rate(struct ast2600_scu *scu) 47327881d20Sryan_chen { 4742e195992Sryan_chen u32 clk_in = ast2600_get_huxclk_in_rate(scu); 47527881d20Sryan_chen u32 div_reg = readl(&scu->uart_24m_ref_huxclk); 47627881d20Sryan_chen 47727881d20Sryan_chen unsigned int mult, div; 47827881d20Sryan_chen 47927881d20Sryan_chen u32 n = (div_reg >> 8) & 0x3ff; 48027881d20Sryan_chen u32 r = div_reg & 0xff; 48127881d20Sryan_chen 48227881d20Sryan_chen mult = r; 4832e195992Sryan_chen div = (n * 2); 48427881d20Sryan_chen return (clk_in * mult) / div; 48527881d20Sryan_chen } 48627881d20Sryan_chen 487f51926eeSryan_chen static u32 ast2600_get_sdio_clk_rate(struct ast2600_scu *scu) 488f51926eeSryan_chen { 489f51926eeSryan_chen u32 clkin = 0; 490f51926eeSryan_chen u32 clk_sel = readl(&scu->clk_sel4); 491f51926eeSryan_chen u32 div = (clk_sel >> 28) & 0x7; 4928004dfdeSChin-Ting Kuo u32 hw_rev = readl(&scu->chip_id1); 493f51926eeSryan_chen 494ed3899c5SRyan Chen if (clk_sel & BIT(8)) 495f51926eeSryan_chen clkin = ast2600_get_apll_rate(scu); 496ed3899c5SRyan Chen else 49710069884Sryan_chen clkin = ast2600_get_hclk(scu); 498ed3899c5SRyan Chen 4998004dfdeSChin-Ting Kuo div = (1 + div) * 2; 5008004dfdeSChin-Ting Kuo if (((hw_rev & GENMASK(23, 16)) >> 16) >= 2) 5018004dfdeSChin-Ting Kuo div = (div & 0xf) ? div : 1; 502f51926eeSryan_chen 503f51926eeSryan_chen return (clkin / div); 504f51926eeSryan_chen } 505f51926eeSryan_chen 506f51926eeSryan_chen static u32 ast2600_get_emmc_clk_rate(struct ast2600_scu *scu) 507f51926eeSryan_chen { 508125f2e11SChin-Ting Kuo u32 mmc_clk_src = readl(&scu->clk_sel1); 509125f2e11SChin-Ting Kuo u32 clkin; 510f51926eeSryan_chen u32 clk_sel = readl(&scu->clk_sel1); 511f51926eeSryan_chen u32 div = (clk_sel >> 12) & 0x7; 512f51926eeSryan_chen 513125f2e11SChin-Ting Kuo if (mmc_clk_src & BIT(11)) { 514125f2e11SChin-Ting Kuo /* emmc clock comes from MPLL */ 515125f2e11SChin-Ting Kuo clkin = ast2600_get_pll_rate(scu, ASPEED_CLK_MPLL); 516125f2e11SChin-Ting Kuo div = (div + 1) * 2; 517125f2e11SChin-Ting Kuo } else { 518125f2e11SChin-Ting Kuo clkin = ast2600_get_pll_rate(scu, ASPEED_CLK_HPLL); 519f51926eeSryan_chen div = (div + 1) << 2; 520125f2e11SChin-Ting Kuo } 521f51926eeSryan_chen 522f51926eeSryan_chen return (clkin / div); 523f51926eeSryan_chen } 524f51926eeSryan_chen 5254c944043SChia-Wei Wang #ifdef CONFIG_SPL_BUILD 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 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 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 */ 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 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; 761fd52be0bSDylan Hung p_cfg->reg.b.off = 1; 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 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 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 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 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 */ 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 9021e460bb5SDylan Hung return lookup[i]; 903e95b19f8SDylan Hung } 904e95b19f8SDylan Hung 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) { 918e95b19f8SDylan Hung debug("suggested tx delay for mac1/2: %d\n", 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 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) { 986e95b19f8SDylan Hung debug("suggested tx delay for mac3/4: %d\n", 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 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 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 */ 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 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) 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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