diff options
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/clk-uclass.c | 16 | ||||
-rw-r--r-- | drivers/clk/imx/clk-fracn-gppll.c | 5 | ||||
-rw-r--r-- | drivers/clk/imx/clk-imx93.c | 52 | ||||
-rw-r--r-- | drivers/clk/renesas/r8a779h0-cpg-mssr.c | 10 | ||||
-rw-r--r-- | drivers/clk/starfive/clk-jh7110-pll.c | 6 | ||||
-rw-r--r-- | drivers/clk/starfive/clk-jh7110.c | 44 | ||||
-rw-r--r-- | drivers/clk/ti/clk-k3-pll.c | 357 |
7 files changed, 358 insertions, 132 deletions
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index a9937c22dcb..353ae476068 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -569,8 +569,20 @@ ulong clk_set_rate(struct clk *clk, ulong rate) return 0; ops = clk_dev_ops(clk->dev); - if (!ops->set_rate) - return -ENOSYS; + /* Try to find parents which can set rate */ + while (!ops->set_rate) { + struct clk *parent; + + if (!(clk->flags & CLK_SET_RATE_PARENT)) + return -ENOSYS; + + parent = clk_get_parent(clk); + if (IS_ERR_OR_NULL(parent) || !clk_valid(parent)) + return -ENODEV; + + clk = parent; + ops = clk_dev_ops(clk->dev); + } /* get private clock struct used for cache */ clk_get_priv(clk, &clkp); diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c index 8f42a5cb1b7..81e19d393cf 100644 --- a/drivers/clk/imx/clk-fracn-gppll.c +++ b/drivers/clk/imx/clk-fracn-gppll.c @@ -86,6 +86,7 @@ struct clk_fracn_gppll { */ static const struct imx_fracn_gppll_rate_table fracn_tbl[] = { PLL_FRACN_GP(650000000U, 162, 50, 100, 0, 6), + PLL_FRACN_GP(600000000U, 200, 0, 1, 0, 8), PLL_FRACN_GP(594000000U, 198, 0, 1, 0, 8), PLL_FRACN_GP(560000000U, 140, 0, 1, 0, 6), PLL_FRACN_GP(498000000U, 166, 0, 1, 0, 8), @@ -93,7 +94,8 @@ static const struct imx_fracn_gppll_rate_table fracn_tbl[] = { PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9), PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12), PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10), - PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12) + PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12), + PLL_FRACN_GP(200000000U, 200, 0, 1, 0, 24) }; struct imx_fracn_gppll_clk imx_fracn_gppll = { @@ -111,6 +113,7 @@ static const struct imx_fracn_gppll_rate_table int_tbl[] = { PLL_FRACN_GP_INTEGER(1700000000U, 141, 1, 2), PLL_FRACN_GP_INTEGER(1400000000U, 175, 1, 3), PLL_FRACN_GP_INTEGER(900000000U, 150, 1, 4), + PLL_FRACN_GP_INTEGER(800000000U, 200, 1, 6), }; struct imx_fracn_gppll_clk imx_fracn_gppll_integer = { diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c index ede36c412bf..b31e57a4a01 100644 --- a/drivers/clk/imx/clk-imx93.c +++ b/drivers/clk/imx/clk-imx93.c @@ -13,6 +13,11 @@ #include "clk.h" +#define IMX93_CLK_END 207 + +#define PLAT_IMX93 BIT(0) +#define PLAT_IMX91 BIT(1) + enum clk_sel { LOW_SPEED_IO_SEL, NON_IO_SEL, @@ -50,6 +55,7 @@ static const struct imx93_clk_root { u32 off; enum clk_sel sel; unsigned long flags; + unsigned long plat; } root_array[] = { /* a55/m33/bus critical clk for system run */ { IMX93_CLK_A55_PERIPH, "a55_periph_root", 0x0000, FAST_SEL, CLK_IS_CRITICAL }, @@ -60,7 +66,7 @@ static const struct imx93_clk_root { { IMX93_CLK_BUS_AON, "bus_aon_root", 0x0300, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL }, { IMX93_CLK_WAKEUP_AXI, "wakeup_axi_root", 0x0380, FAST_SEL, CLK_IS_CRITICAL }, { IMX93_CLK_SWO_TRACE, "swo_trace_root", 0x0400, LOW_SPEED_IO_SEL, }, - { IMX93_CLK_M33_SYSTICK, "m33_systick_root", 0x0480, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_M33_SYSTICK, "m33_systick_root", 0x0480, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, }, { IMX93_CLK_FLEXIO1, "flexio1_root", 0x0500, LOW_SPEED_IO_SEL, }, { IMX93_CLK_FLEXIO2, "flexio2_root", 0x0580, LOW_SPEED_IO_SEL, }, { IMX93_CLK_LPTMR1, "lptmr1_root", 0x0700, LOW_SPEED_IO_SEL, }, @@ -117,15 +123,15 @@ static const struct imx93_clk_root { { IMX93_CLK_HSIO_ACSCAN_80M, "hsio_acscan_80m_root", 0x1f80, LOW_SPEED_IO_SEL, }, { IMX93_CLK_HSIO_ACSCAN_480M, "hsio_acscan_480m_root", 0x2000, MISC_SEL, }, { IMX93_CLK_NIC_AXI, "nic_axi_root", 0x2080, FAST_SEL, CLK_IS_CRITICAL, }, - { IMX93_CLK_ML_APB, "ml_apb_root", 0x2180, LOW_SPEED_IO_SEL, }, - { IMX93_CLK_ML, "ml_root", 0x2200, FAST_SEL, }, + { IMX93_CLK_ML_APB, "ml_apb_root", 0x2180, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, }, + { IMX93_CLK_ML, "ml_root", 0x2200, FAST_SEL, 0, PLAT_IMX93, }, { IMX93_CLK_MEDIA_AXI, "media_axi_root", 0x2280, FAST_SEL, }, { IMX93_CLK_MEDIA_APB, "media_apb_root", 0x2300, LOW_SPEED_IO_SEL, }, - { IMX93_CLK_MEDIA_LDB, "media_ldb_root", 0x2380, VIDEO_SEL, }, + { IMX93_CLK_MEDIA_LDB, "media_ldb_root", 0x2380, VIDEO_SEL, 0, PLAT_IMX93, }, { IMX93_CLK_MEDIA_DISP_PIX, "media_disp_pix_root", 0x2400, VIDEO_SEL, }, { IMX93_CLK_CAM_PIX, "cam_pix_root", 0x2480, VIDEO_SEL, }, - { IMX93_CLK_MIPI_TEST_BYTE, "mipi_test_byte_root", 0x2500, VIDEO_SEL, }, - { IMX93_CLK_MIPI_PHY_CFG, "mipi_phy_cfg_root", 0x2580, VIDEO_SEL, }, + { IMX93_CLK_MIPI_TEST_BYTE, "mipi_test_byte_root", 0x2500, VIDEO_SEL, 0, PLAT_IMX93, }, + { IMX93_CLK_MIPI_PHY_CFG, "mipi_phy_cfg_root", 0x2580, VIDEO_SEL, 0, PLAT_IMX93, }, { IMX93_CLK_ADC, "adc_root", 0x2700, LOW_SPEED_IO_SEL, }, { IMX93_CLK_PDM, "pdm_root", 0x2780, AUDIO_SEL, }, { IMX93_CLK_TSTMR1, "tstmr1_root", 0x2800, LOW_SPEED_IO_SEL, }, @@ -134,13 +140,16 @@ static const struct imx93_clk_root { { IMX93_CLK_MQS2, "mqs2_root", 0x2980, AUDIO_SEL, }, { IMX93_CLK_AUDIO_XCVR, "audio_xcvr_root", 0x2a00, NON_IO_SEL, }, { IMX93_CLK_SPDIF, "spdif_root", 0x2a80, AUDIO_SEL, }, - { IMX93_CLK_ENET, "enet_root", 0x2b00, NON_IO_SEL, }, - { IMX93_CLK_ENET_TIMER1, "enet_timer1_root", 0x2b80, LOW_SPEED_IO_SEL, }, - { IMX93_CLK_ENET_TIMER2, "enet_timer2_root", 0x2c00, LOW_SPEED_IO_SEL, }, - { IMX93_CLK_ENET_REF, "enet_ref_root", 0x2c80, NON_IO_SEL, }, - { IMX93_CLK_ENET_REF_PHY, "enet_ref_phy_root", 0x2d00, LOW_SPEED_IO_SEL, }, - { IMX93_CLK_I3C1_SLOW, "i3c1_slow_root", 0x2d80, LOW_SPEED_IO_SEL, }, - { IMX93_CLK_I3C2_SLOW, "i3c2_slow_root", 0x2e00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_ENET, "enet_root", 0x2b00, NON_IO_SEL, 0, PLAT_IMX93, }, + { IMX93_CLK_ENET_TIMER1, "enet_timer1_root", 0x2b80, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, }, + { IMX93_CLK_ENET_TIMER2, "enet_timer2_root", 0x2c00, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, }, + { IMX93_CLK_ENET_REF, "enet_ref_root", 0x2c80, NON_IO_SEL, 0, PLAT_IMX93, }, + { IMX93_CLK_ENET_REF_PHY, "enet_ref_phy_root", 0x2d00, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, }, + { IMX91_CLK_ENET1_QOS_TSN, "enet1_qos_tsn_root", 0x2b00, NON_IO_SEL, 0, PLAT_IMX91, }, + { IMX91_CLK_ENET_TIMER, "enet_timer_root", 0x2b80, LOW_SPEED_IO_SEL, 0, PLAT_IMX91, }, + { IMX91_CLK_ENET2_REGULAR, "enet2_regular_root", 0x2c80, NON_IO_SEL, 0, PLAT_IMX91, }, + { IMX93_CLK_I3C1_SLOW, "i3c1_slow_root", 0x2d80, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, }, + { IMX93_CLK_I3C2_SLOW, "i3c2_slow_root", 0x2e00, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, }, { IMX93_CLK_USB_PHY_BURUNIN, "usb_phy_root", 0x2e80, LOW_SPEED_IO_SEL, }, { IMX93_CLK_PAL_CAME_SCAN, "pal_came_scan_root", 0x2f00, MISC_SEL, } }; @@ -152,6 +161,7 @@ static const struct imx93_clk_ccgr { u32 off; unsigned long flags; u32 *shared_count; + unsigned long plat; } ccgr_array[] = { { IMX93_CLK_A55_GATE, "a55_alt", "a55_alt_root", 0x8000, }, /* M33 critical clk for system run */ @@ -226,7 +236,7 @@ static const struct imx93_clk_ccgr { { IMX93_CLK_SAI3_IPG, "sai3_ipg_clk", "bus_wakeup_root", 0x94c0, 0, &share_count_sai3}, { IMX93_CLK_MIPI_CSI_GATE, "mipi_csi", "media_apb_root", 0x9580, }, { IMX93_CLK_MIPI_DSI_GATE, "mipi_dsi", "media_apb_root", 0x95c0, }, - { IMX93_CLK_LVDS_GATE, "lvds", "media_ldb_root", 0x9600, }, + { IMX93_CLK_LVDS_GATE, "lvds", "media_ldb_root", 0x9600, 0, NULL, PLAT_IMX93, }, { IMX93_CLK_LCDIF_GATE, "lcdif", "media_apb_root", 0x9640, }, { IMX93_CLK_PXP_GATE, "pxp", "media_apb_root", 0x9680, }, { IMX93_CLK_ISI_GATE, "isi", "media_apb_root", 0x96c0, }, @@ -240,8 +250,10 @@ static const struct imx93_clk_ccgr { { IMX93_CLK_AUD_XCVR_GATE, "aud_xcvr", "audio_xcvr_root", 0x9b80, }, { IMX93_CLK_SPDIF_GATE, "spdif", "spdif_root", 0x9c00, }, { IMX93_CLK_HSIO_32K_GATE, "hsio_32k", "clock-osc-24m", 0x9dc0, }, - { IMX93_CLK_ENET1_GATE, "enet1", "wakeup_axi_root", 0x9e00, }, - { IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, }, + { IMX93_CLK_ENET1_GATE, "enet1", "wakeup_axi_root", 0x9e00, 0, NULL, PLAT_IMX93, }, + { IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, 0, NULL, PLAT_IMX93, }, + { IMX91_CLK_ENET2_REGULAR_GATE, "enet2_regular", "wakeup_axi_root", 0x9e00, 0, NULL, PLAT_IMX91, }, + { IMX91_CLK_ENET1_QOS_TSN_GATE, "enet1_qos_tsn", "wakeup_axi_root", 0x9e40, 0, NULL, PLAT_IMX91, }, /* Critical because clk accessed during CPU idle */ { IMX93_CLK_SYS_CNT_GATE, "sys_cnt", "clock-osc-24m", 0x9e80, CLK_IS_CRITICAL}, { IMX93_CLK_TSTMR1_GATE, "tstmr1", "bus_aon_root", 0x9ec0, }, @@ -257,6 +269,7 @@ static int imx93_clk_probe(struct udevice *dev) struct clk osc_24m_clk, osc_32k_clk, ext1_clk; void __iomem *base, *anatop_base; int i, ret; + const unsigned long plat = (unsigned long)dev_get_driver_data(dev); clk_dm(IMX93_CLK_DUMMY, clk_register_fixed_rate(NULL, "dummy", 0UL)); @@ -307,6 +320,8 @@ static int imx93_clk_probe(struct udevice *dev) for (i = 0; i < ARRAY_SIZE(root_array); i++) { root = &root_array[i]; + if (root->plat && !(root->plat & plat)) + continue; clk_dm(root->clk, imx93_clk_composite_flags(root->name, parent_names[root->sel], 4, base + root->off, 3, @@ -315,6 +330,8 @@ static int imx93_clk_probe(struct udevice *dev) for (i = 0; i < ARRAY_SIZE(ccgr_array); i++) { ccgr = &ccgr_array[i]; + if (ccgr->plat && !(ccgr->plat & plat)) + continue; clk_dm(ccgr->clk, imx93_clk_gate(NULL, ccgr->name, ccgr->parent_name, ccgr->flags, base + ccgr->off, 0, 1, 1, 3, ccgr->shared_count)); @@ -328,7 +345,8 @@ static int imx93_clk_probe(struct udevice *dev) } static const struct udevice_id imx93_clk_ids[] = { - { .compatible = "fsl,imx93-ccm" }, + { .compatible = "fsl,imx93-ccm", .data = (unsigned long)PLAT_IMX93 }, + { .compatible = "fsl,imx91-ccm", .data = (unsigned long)PLAT_IMX91 }, { /* Sentinel */ }, }; diff --git a/drivers/clk/renesas/r8a779h0-cpg-mssr.c b/drivers/clk/renesas/r8a779h0-cpg-mssr.c index 2e98e262fb0..70fa8ff2871 100644 --- a/drivers/clk/renesas/r8a779h0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779h0-cpg-mssr.c @@ -39,7 +39,6 @@ enum clk_ids { CLK_PLL6, CLK_PLL7, CLK_PLL1_DIV2, - CLK_PLL2_DIV2, CLK_PLL3_DIV2, CLK_PLL4_DIV2, CLK_PLL4_DIV5, @@ -82,7 +81,6 @@ static const struct cpg_core_clk r8a779h0_core_clks[] = { DEF_BASE(".pll7", CLK_PLL7, CLK_TYPE_GEN4_PLL7, CLK_MAIN), DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), - DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1), DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 2, 1), DEF_FIXED(".pll4_div2", CLK_PLL4_DIV2, CLK_PLL4, 2, 1), DEF_FIXED(".pll4_div5", CLK_PLL4_DIV5, CLK_PLL4, 5, 1), @@ -106,10 +104,10 @@ static const struct cpg_core_clk r8a779h0_core_clks[] = { DEF_RATE(".oco", CLK_OCO, 32768), /* Core Clock Outputs */ - DEF_GEN4_Z("zc0", R8A779H0_CLK_ZC0, CLK_TYPE_GEN4_Z, CLK_PLL2_DIV2, 2, 0), - DEF_GEN4_Z("zc1", R8A779H0_CLK_ZC1, CLK_TYPE_GEN4_Z, CLK_PLL2_DIV2, 2, 8), - DEF_GEN4_Z("zc2", R8A779H0_CLK_ZC2, CLK_TYPE_GEN4_Z, CLK_PLL2_DIV2, 2, 32), - DEF_GEN4_Z("zc3", R8A779H0_CLK_ZC3, CLK_TYPE_GEN4_Z, CLK_PLL2_DIV2, 2, 40), + DEF_GEN4_Z("zc0", R8A779H0_CLK_ZC0, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 0), + DEF_GEN4_Z("zc1", R8A779H0_CLK_ZC1, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 8), + DEF_GEN4_Z("zc2", R8A779H0_CLK_ZC2, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 32), + DEF_GEN4_Z("zc3", R8A779H0_CLK_ZC3, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 40), DEF_FIXED("s0d2", R8A779H0_CLK_S0D2, CLK_S0, 2, 1), DEF_FIXED("s0d3", R8A779H0_CLK_S0D3, CLK_S0, 3, 1), DEF_FIXED("s0d4", R8A779H0_CLK_S0D4, CLK_S0, 4, 1), diff --git a/drivers/clk/starfive/clk-jh7110-pll.c b/drivers/clk/starfive/clk-jh7110-pll.c index 6d2bfb3ecb7..f8af17227c5 100644 --- a/drivers/clk/starfive/clk-jh7110-pll.c +++ b/drivers/clk/starfive/clk-jh7110-pll.c @@ -374,13 +374,13 @@ static int jh7110_pll_clk_probe(struct udevice *dev) if (sysreg == FDT_ADDR_T_NONE) return -EINVAL; - clk_dm(JH7110_PLL_ID_TRANS(JH7110_SYSCLK_PLL0_OUT), + clk_dm(JH7110_PLL_ID_TRANS(JH7110_PLLCLK_PLL0_OUT), starfive_jh7110_pll("pll0_out", "oscillator", reg, (void __iomem *)sysreg, &starfive_jh7110_pll0)); - clk_dm(JH7110_PLL_ID_TRANS(JH7110_SYSCLK_PLL1_OUT), + clk_dm(JH7110_PLL_ID_TRANS(JH7110_PLLCLK_PLL1_OUT), starfive_jh7110_pll("pll1_out", "oscillator", reg, (void __iomem *)sysreg, &starfive_jh7110_pll1)); - clk_dm(JH7110_PLL_ID_TRANS(JH7110_SYSCLK_PLL2_OUT), + clk_dm(JH7110_PLL_ID_TRANS(JH7110_PLLCLK_PLL2_OUT), starfive_jh7110_pll("pll2_out", "oscillator", reg, (void __iomem *)sysreg, &starfive_jh7110_pll2)); diff --git a/drivers/clk/starfive/clk-jh7110.c b/drivers/clk/starfive/clk-jh7110.c index 191da75d7ba..6387e949d50 100644 --- a/drivers/clk/starfive/clk-jh7110.c +++ b/drivers/clk/starfive/clk-jh7110.c @@ -495,37 +495,37 @@ static int jh7110_stgcrg_init(struct udevice *dev) { struct jh7110_clk_priv *priv = dev_get_priv(dev); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB_APB), + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB0_APB), starfive_clk_gate(priv->reg, "usb_apb", "apb_bus", - OFFSET(JH7110_STGCLK_USB_APB))); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB_UTMI_APB), + OFFSET(JH7110_STGCLK_USB0_APB))); + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB0_UTMI_APB), starfive_clk_gate(priv->reg, "usb_utmi_apb", "apb_bus", - OFFSET(JH7110_STGCLK_USB_UTMI_APB))); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB_AXI), + OFFSET(JH7110_STGCLK_USB0_UTMI_APB))); + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB0_AXI), starfive_clk_gate(priv->reg, "usb_axi", "stg_axiahb", - OFFSET(JH7110_STGCLK_USB_AXI))); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB_LPM), + OFFSET(JH7110_STGCLK_USB0_AXI))); + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB0_LPM), starfive_clk_gate_divider(priv->reg, "usb_lpm", "oscillator", - OFFSET(JH7110_STGCLK_USB_LPM), 2)); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB_STB), + OFFSET(JH7110_STGCLK_USB0_LPM), 2)); + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB0_STB), starfive_clk_gate_divider(priv->reg, "usb_stb", "oscillator", - OFFSET(JH7110_STGCLK_USB_STB), 3)); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB_APP_125), + OFFSET(JH7110_STGCLK_USB0_STB), 3)); + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB0_APP_125), starfive_clk_gate(priv->reg, "usb_app_125", "usb_125m", - OFFSET(JH7110_STGCLK_USB_APP_125))); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB_REFCLK), + OFFSET(JH7110_STGCLK_USB0_APP_125))); + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_USB0_REFCLK), starfive_clk_divider(priv->reg, "usb_refclk", "oscillator", - OFFSET(JH7110_STGCLK_USB_REFCLK), 2)); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_PCIE0_AXI), + OFFSET(JH7110_STGCLK_USB0_REFCLK), 2)); + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_PCIE0_AXI_MST0), starfive_clk_gate(priv->reg, "pcie0_axi", "stg_axiahb", - OFFSET(JH7110_STGCLK_PCIE0_AXI))); + OFFSET(JH7110_STGCLK_PCIE0_AXI_MST0))); clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_PCIE0_APB), starfive_clk_gate(priv->reg, "pcie0_apb", "apb_bus", @@ -534,10 +534,10 @@ static int jh7110_stgcrg_init(struct udevice *dev) starfive_clk_gate(priv->reg, "pcie0_tl", "stg_axiahb", OFFSET(JH7110_STGCLK_PCIE0_TL))); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_PCIE1_AXI), + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_PCIE1_AXI_MST0), starfive_clk_gate(priv->reg, "pcie1_axi", "stg_axiahb", - OFFSET(JH7110_STGCLK_PCIE1_AXI))); + OFFSET(JH7110_STGCLK_PCIE1_AXI_MST0))); clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_PCIE1_APB), starfive_clk_gate(priv->reg, "pcie1_apb", "apb_bus", @@ -548,14 +548,14 @@ static int jh7110_stgcrg_init(struct udevice *dev) OFFSET(JH7110_STGCLK_PCIE1_TL))); /* Security clocks */ - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_SEC_HCLK), + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_SEC_AHB), starfive_clk_gate(priv->reg, "sec_ahb", "stg_axiahb", - OFFSET(JH7110_STGCLK_SEC_HCLK))); - clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_SEC_MISCAHB), + OFFSET(JH7110_STGCLK_SEC_AHB))); + clk_dm(JH7110_STG_ID_TRANS(JH7110_STGCLK_SEC_MISC_AHB), starfive_clk_gate(priv->reg, "sec_misc_ahb", "stg_axiahb", - OFFSET(JH7110_STGCLK_SEC_MISCAHB))); + OFFSET(JH7110_STGCLK_SEC_MISC_AHB))); return 0; } diff --git a/drivers/clk/ti/clk-k3-pll.c b/drivers/clk/ti/clk-k3-pll.c index b3a1b4cedb7..b775bd55faa 100644 --- a/drivers/clk/ti/clk-k3-pll.c +++ b/drivers/clk/ti/clk-k3-pll.c @@ -14,6 +14,7 @@ #include <linux/clk-provider.h> #include "k3-clk.h" #include <linux/rational.h> +#include <linux/delay.h> /* 16FFT register offsets */ #define PLL_16FFT_CFG 0x08 @@ -29,10 +30,12 @@ /* CAL STAT register bits */ #define PLL_16FFT_CAL_STAT_CAL_LOCK BIT(31) +#define PLL_16FFT_CAL_STAT_CAL_LOCK_TIMEOUT (4350U * 100U) /* CFG register bits */ #define PLL_16FFT_CFG_PLL_TYPE_SHIFT (0) #define PLL_16FFT_CFG_PLL_TYPE_MASK (0x3 << 0) +#define PLL_16FFT_CFG_PLL_TYPE_FRAC2 0 #define PLL_16FFT_CFG_PLL_TYPE_FRACF 1 /* CAL CTRL register bits */ @@ -41,14 +44,21 @@ #define PLL_16FFT_CAL_CTRL_CAL_BYP BIT(15) #define PLL_16FFT_CAL_CTRL_CAL_CNT_SHIFT 16 #define PLL_16FFT_CAL_CTRL_CAL_CNT_MASK (0x7 << 16) +#define PLL_16FFT_CAL_CTRL_CAL_IN_MASK (0xFFFU) /* CTRL register bits */ #define PLL_16FFT_CTRL_BYPASS_EN BIT(31) +#define PLL_16FFT_CTRL_BYP_ON_LOCKLOSS BIT(16) #define PLL_16FFT_CTRL_PLL_EN BIT(15) +#define PLL_16FFT_CTRL_INTL_BYP_EN BIT(8) +#define PLL_16FFT_CTRL_CLK_4PH_EN BIT(5) +#define PLL_16FFT_CTRL_CLK_POSTDIV_EN BIT(4) #define PLL_16FFT_CTRL_DSM_EN BIT(1) +#define PLL_16FFT_CTRL_DAC_EN BIT(0) /* STAT register bits */ #define PLL_16FFT_STAT_LOCK BIT(0) +#define PLL_16FFT_STAT_LOCK_TIMEOUT (150U * 100U) /* FREQ_CTRL0 bits */ #define PLL_16FFT_FREQ_CTRL0_FB_DIV_INT_MASK 0xfff @@ -62,7 +72,6 @@ /* FREQ_CTRL1 bits */ #define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_BITS 24 #define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_MASK 0xffffff -#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_SHIFT 0 /* KICK register magic values */ #define PLL_KICK0_VALUE 0x68ef3490 @@ -75,68 +84,199 @@ */ struct ti_pll_clk { struct clk clk; - void __iomem *reg; + void __iomem *base; }; #define to_clk_pll(_clk) container_of(_clk, struct ti_pll_clk, clk) -static int ti_pll_wait_for_lock(struct clk *clk) +static int ti_pll_clk_disable(struct clk *clk) { struct ti_pll_clk *pll = to_clk_pll(clk); + u32 ctrl; + + ctrl = readl(pll->base + PLL_16FFT_CTRL); + + if ((ctrl & PLL_16FFT_CTRL_PLL_EN)) { + ctrl &= ~PLL_16FFT_CTRL_PLL_EN; + writel(ctrl, pll->base + PLL_16FFT_CTRL); + + /* wait 1us */ + udelay(1); + } + + return 0; +} + +static int ti_pll_clk_enable(struct clk *clk) +{ + struct ti_pll_clk *pll = to_clk_pll(clk); + u32 ctrl; + + ctrl = readl(pll->base + PLL_16FFT_CTRL); + ctrl |= PLL_16FFT_CTRL_PLL_EN; + writel(ctrl, pll->base + PLL_16FFT_CTRL); + + /* Wait 1us */ + udelay(1); + + return 0; +} + +static bool clk_pll_16fft_check_lock(const struct ti_pll_clk *pll) +{ u32 stat; + + stat = readl(pll->base + PLL_16FFT_STAT); + return (stat & PLL_16FFT_STAT_LOCK); +} + +static bool clk_pll_16fft_check_cal_lock(const struct ti_pll_clk *pll) +{ + u32 stat; + + stat = readl(pll->base + PLL_16FFT_CAL_STAT); + return (stat & PLL_16FFT_CAL_STAT_CAL_LOCK); +} + +static void clk_pll_16fft_cal_int(const struct ti_pll_clk *pll) +{ + u32 cal; + + cal = readl(pll->base + PLL_16FFT_CAL_CTRL); + + /* Enable fast cal mode */ + cal |= PLL_16FFT_CAL_CTRL_FAST_CAL; + + /* Disable calibration bypass */ + cal &= ~PLL_16FFT_CAL_CTRL_CAL_BYP; + + /* Set CALCNT to 2 */ + cal &= ~PLL_16FFT_CAL_CTRL_CAL_CNT_MASK; + cal |= 2 << PLL_16FFT_CAL_CTRL_CAL_CNT_SHIFT; + + /* Set CAL_IN to 0 */ + cal &= ~PLL_16FFT_CAL_CTRL_CAL_IN_MASK; + + /* Note this register does not readback the written value. */ + writel(cal, pll->base + PLL_16FFT_CAL_CTRL); + + /* Wait 1us before enabling the CAL_EN field */ + udelay(1); + + cal = readl(pll->base + PLL_16FFT_CAL_CTRL); + + /* Enable calibration for FRACF */ + cal |= PLL_16FFT_CAL_CTRL_CAL_EN; + + /* Note this register does not readback the written value. */ + writel(cal, pll->base + PLL_16FFT_CAL_CTRL); +} + +static void clk_pll_16fft_disable_cal(const struct ti_pll_clk *pll) +{ + u32 cal, stat; + + cal = readl(pll->base + PLL_16FFT_CAL_CTRL); + cal &= ~PLL_16FFT_CAL_CTRL_CAL_EN; + /* Note this register does not readback the written value. */ + writel(cal, pll->base + PLL_16FFT_CAL_CTRL); + do { + stat = readl(pll->base + PLL_16FFT_CAL_STAT); + } while (stat & PLL_16FFT_CAL_STAT_CAL_LOCK); +} + +static int ti_pll_wait_for_lock(struct clk *clk) +{ + struct ti_pll_clk *pll = to_clk_pll(clk); u32 cfg; u32 cal; u32 freq_ctrl1; - int i; + unsigned int i; u32 pllfm; u32 pll_type; - int success; + u32 cal_en = 0; + bool success; - for (i = 0; i < 100000; i++) { - stat = readl(pll->reg + PLL_16FFT_STAT); - if (stat & PLL_16FFT_STAT_LOCK) { - success = 1; + /* + * Minimum VCO input freq is 5MHz, and the longest a lock should + * be consider to be timed out after 750 cycles. Be conservative + * and assume each loop takes 10 cycles and we run at a + * max of 1GHz. That gives 15000 loop cycles. We may end up waiting + * longer than necessary for timeout, but that should be ok. + */ + success = false; + for (i = 0; i < PLL_16FFT_STAT_LOCK_TIMEOUT; i++) { + if (clk_pll_16fft_check_lock(pll)) { + success = true; break; } } - /* Enable calibration if not in fractional mode of the FRACF PLL */ - freq_ctrl1 = readl(pll->reg + PLL_16FFT_FREQ_CTRL1); + /* Disable calibration in the fractional mode of the FRACF PLL based on data + * from silicon and simulation data. + */ + freq_ctrl1 = readl(pll->base + PLL_16FFT_FREQ_CTRL1); pllfm = freq_ctrl1 & PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_MASK; - pllfm >>= PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_SHIFT; - cfg = readl(pll->reg + PLL_16FFT_CFG); + + cfg = readl(pll->base + PLL_16FFT_CFG); pll_type = (cfg & PLL_16FFT_CFG_PLL_TYPE_MASK) >> PLL_16FFT_CFG_PLL_TYPE_SHIFT; - if (success && pll_type == PLL_16FFT_CFG_PLL_TYPE_FRACF && pllfm == 0) { - cal = readl(pll->reg + PLL_16FFT_CAL_CTRL); + if (success && pll_type == PLL_16FFT_CFG_PLL_TYPE_FRACF) { + cal = readl(pll->base + PLL_16FFT_CAL_CTRL); + cal_en = (cal & PLL_16FFT_CAL_CTRL_CAL_EN); + } - /* Enable calibration for FRACF */ - cal |= PLL_16FFT_CAL_CTRL_CAL_EN; + if (success && pll_type == PLL_16FFT_CFG_PLL_TYPE_FRACF && + pllfm == 0 && cal_en == 1) { + /* + * Wait for calibration lock. + * + * Lock should occur within: + * + * 170 * 2^(5+CALCNT) / PFD + * 21760 / PFD + * + * CALCNT = 2, PFD = 5-50MHz. This gives a range of 0.435mS to + * 4.35mS depending on PFD frequency. + * + * Be conservative and assume each loop takes 10 cycles and we run at a + * max of 1GHz. That gives 435000 loop cycles. We may end up waiting + * longer than necessary for timeout, but that should be ok. + * + * The recommend timeout for CALLOCK to go high is 4.35 ms + */ + success = false; + for (i = 0; i < PLL_16FFT_CAL_STAT_CAL_LOCK_TIMEOUT; i++) { + if (clk_pll_16fft_check_cal_lock(pll)) { + success = true; + break; + } + } - /* Enable fast cal mode */ - cal |= PLL_16FFT_CAL_CTRL_FAST_CAL; + /* In case of cal lock failure, operate without calibration */ + if (!success) { + debug("Failure for calibration, falling back without calibration\n"); - /* Disable calibration bypass */ - cal &= ~PLL_16FFT_CAL_CTRL_CAL_BYP; + /* Disable PLL */ + ti_pll_clk_disable(clk); - /* Set CALCNT to 2 */ - cal &= ~PLL_16FFT_CAL_CTRL_CAL_CNT_MASK; - cal |= 2 << PLL_16FFT_CAL_CTRL_CAL_CNT_SHIFT; + /* Disable Calibration */ + clk_pll_16fft_disable_cal(pll); - /* Note this register does not readback the written value. */ - writel(cal, pll->reg + PLL_16FFT_CAL_CTRL); + /* Enable PLL */ + ti_pll_clk_enable(clk); - success = 0; - for (i = 0; i < 100000; i++) { - stat = readl(pll->reg + PLL_16FFT_CAL_STAT); - if (stat & PLL_16FFT_CAL_STAT_CAL_LOCK) { - success = 1; - break; + /* Wait for PLL Lock */ + for (i = 0; i < PLL_16FFT_STAT_LOCK_TIMEOUT; i++) { + if (clk_pll_16fft_check_lock(pll)) { + success = true; + break; + } } } } - if (success == 0) { + if (!success) { printf("%s: pll (%s) failed to lock\n", __func__, clk->dev->name); return -EBUSY; @@ -156,14 +296,14 @@ static ulong ti_pll_clk_get_rate(struct clk *clk) u32 ctrl; /* Check if we are in bypass */ - ctrl = readl(pll->reg + PLL_16FFT_CTRL); + ctrl = readl(pll->base + PLL_16FFT_CTRL); if (ctrl & PLL_16FFT_CTRL_BYPASS_EN) return parent_freq; - pllm = readl(pll->reg + PLL_16FFT_FREQ_CTRL0); - pllfm = readl(pll->reg + PLL_16FFT_FREQ_CTRL1); + pllm = readl(pll->base + PLL_16FFT_FREQ_CTRL0); + pllfm = readl(pll->base + PLL_16FFT_FREQ_CTRL1); - plld = readl(pll->reg + PLL_16FFT_DIV_CTRL) & + plld = readl(pll->base + PLL_16FFT_DIV_CTRL) & PLL_16FFT_DIV_CTRL_REF_DIV_MASK; current_freq = parent_freq * pllm / plld; @@ -180,6 +320,30 @@ static ulong ti_pll_clk_get_rate(struct clk *clk) return current_freq; } +static bool ti_pll_clk_is_bypass(struct ti_pll_clk *pll) +{ + u32 ctrl; + bool ret; + + ctrl = readl(pll->base + PLL_16FFT_CTRL); + ret = (ctrl & PLL_16FFT_CTRL_BYPASS_EN) != 0; + + return ret; +} + +static void ti_pll_clk_bypass(struct ti_pll_clk *pll, bool bypass) +{ + u32 ctrl; + + ctrl = readl(pll->base + PLL_16FFT_CTRL); + if (bypass) + ctrl |= PLL_16FFT_CTRL_BYPASS_EN; + else + ctrl &= ~PLL_16FFT_CTRL_BYPASS_EN; + + writel(ctrl, pll->base + PLL_16FFT_CTRL); +} + static ulong ti_pll_clk_set_rate(struct clk *clk, ulong rate) { struct ti_pll_clk *pll = to_clk_pll(clk); @@ -187,9 +351,13 @@ static ulong ti_pll_clk_set_rate(struct clk *clk, ulong rate) u64 parent_freq = clk_get_parent_rate(clk); int ret; u32 ctrl; + u32 cfg; + u32 pll_type; unsigned long pllm; u32 pllfm = 0; unsigned long plld; + u32 freq_ctrl0; + u32 freq_ctrl1; u32 div_ctrl; u32 rem; int shift; @@ -212,16 +380,22 @@ static ulong ti_pll_clk_set_rate(struct clk *clk, ulong rate) break; } - /* Put PLL to bypass mode */ - ctrl = readl(pll->reg + PLL_16FFT_CTRL); - ctrl |= PLL_16FFT_CTRL_BYPASS_EN; - writel(ctrl, pll->reg + PLL_16FFT_CTRL); + if (!ti_pll_clk_is_bypass(pll)) { + /* Put the PLL into bypass */ + ti_pll_clk_bypass(pll, true); + } + + /* Disable the PLL */ + ti_pll_clk_disable(clk); if (rate == parent_freq) { debug("%s: put %s to bypass\n", __func__, clk->dev->name); return rate; } + cfg = readl(pll->base + PLL_16FFT_CFG); + pll_type = (cfg & PLL_16FFT_CFG_PLL_TYPE_MASK) >> PLL_16FFT_CFG_PLL_TYPE_SHIFT; + debug("%s: pre-frac-calc: rate=%u, parent_freq=%u, plld=%u, pllm=%u\n", __func__, (u32)rate, (u32)parent_freq, (u32)plld, (u32)pllm); @@ -237,31 +411,75 @@ static ulong ti_pll_clk_set_rate(struct clk *clk, ulong rate) plld = 1; } - if (pllfm) - ctrl |= PLL_16FFT_CTRL_DSM_EN; - else - ctrl &= ~PLL_16FFT_CTRL_DSM_EN; + /* Program the new rate */ + freq_ctrl0 = readl(pll->base + PLL_16FFT_FREQ_CTRL0); + freq_ctrl1 = readl(pll->base + PLL_16FFT_FREQ_CTRL1); + div_ctrl = readl(pll->base + PLL_16FFT_DIV_CTRL); + + freq_ctrl0 &= ~PLL_16FFT_FREQ_CTRL0_FB_DIV_INT_MASK; + freq_ctrl0 |= pllm; - writel(pllm, pll->reg + PLL_16FFT_FREQ_CTRL0); - writel(pllfm, pll->reg + PLL_16FFT_FREQ_CTRL1); + freq_ctrl1 &= ~PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_MASK; + freq_ctrl1 |= pllfm; /* * div_ctrl register contains other divider values, so rmw * only plld and leave existing values alone */ - div_ctrl = readl(pll->reg + PLL_16FFT_DIV_CTRL); div_ctrl &= ~PLL_16FFT_DIV_CTRL_REF_DIV_MASK; div_ctrl |= plld; - writel(div_ctrl, pll->reg + PLL_16FFT_DIV_CTRL); - ctrl &= ~PLL_16FFT_CTRL_BYPASS_EN; - ctrl |= PLL_16FFT_CTRL_PLL_EN; - writel(ctrl, pll->reg + PLL_16FFT_CTRL); + /* Make sure we have fractional support if required */ + ctrl = readl(pll->base + PLL_16FFT_CTRL); + + /* Don't use internal bypass,it is not glitch free. Always prefer glitchless bypass */ + ctrl &= ~(PLL_16FFT_CTRL_INTL_BYP_EN | PLL_16FFT_CTRL_CLK_4PH_EN); + + /* Always enable output if PLL, Always bypass if we lose lock */ + ctrl |= (PLL_16FFT_CTRL_CLK_POSTDIV_EN | PLL_16FFT_CTRL_BYP_ON_LOCKLOSS); + + /* Enable fractional support if required */ + if (pll_type == PLL_16FFT_CFG_PLL_TYPE_FRACF) { + if (pllfm != 0) + ctrl |= (PLL_16FFT_CTRL_DSM_EN | PLL_16FFT_CTRL_DAC_EN); + else + ctrl &= ~(PLL_16FFT_CTRL_DSM_EN | PLL_16FFT_CTRL_DAC_EN); + } + + /* Enable Fractional by default for PLL_16FFT_CFG_PLL_TYPE_FRAC2 */ + if (pll_type == PLL_16FFT_CFG_PLL_TYPE_FRAC2) + ctrl |= (PLL_16FFT_CTRL_DSM_EN | PLL_16FFT_CTRL_DAC_EN); + + writel(freq_ctrl0, pll->base + PLL_16FFT_FREQ_CTRL0); + writel(freq_ctrl1, pll->base + PLL_16FFT_FREQ_CTRL1); + writel(div_ctrl, pll->base + PLL_16FFT_DIV_CTRL); + writel(ctrl, pll->base + PLL_16FFT_CTRL); + + /* Configure PLL calibration*/ + if (pll_type == PLL_16FFT_CFG_PLL_TYPE_FRACF) { + if (pllfm != 0) { + /* Disable Calibration in Fractional mode */ + clk_pll_16fft_disable_cal(pll); + } else { + /* Enable Calibration in Integer mode */ + clk_pll_16fft_cal_int(pll); + } + } + + /* + * Wait at least 1 ref cycle before enabling PLL. + * Minimum VCO input frequency is 5MHz, therefore maximum + * wait time for 1 ref clock is 0.2us. + */ + udelay(1); + ti_pll_clk_enable(clk); ret = ti_pll_wait_for_lock(clk); if (ret) return ret; + ti_pll_clk_bypass(pll, false); + debug("%s: pllm=%u, plld=%u, pllfm=%u, parent_freq=%u\n", __func__, (u32)pllm, (u32)plld, (u32)pllfm, (u32)parent_freq); @@ -279,30 +497,7 @@ static ulong ti_pll_clk_set_rate(struct clk *clk, ulong rate) return current_freq; } -static int ti_pll_clk_enable(struct clk *clk) -{ - struct ti_pll_clk *pll = to_clk_pll(clk); - u32 ctrl; - - ctrl = readl(pll->reg + PLL_16FFT_CTRL); - ctrl &= ~PLL_16FFT_CTRL_BYPASS_EN; - ctrl |= PLL_16FFT_CTRL_PLL_EN; - writel(ctrl, pll->reg + PLL_16FFT_CTRL); - - return ti_pll_wait_for_lock(clk); -} - -static int ti_pll_clk_disable(struct clk *clk) -{ - struct ti_pll_clk *pll = to_clk_pll(clk); - u32 ctrl; - ctrl = readl(pll->reg + PLL_16FFT_CTRL); - ctrl |= PLL_16FFT_CTRL_BYPASS_EN; - writel(ctrl, pll->reg + PLL_16FFT_CTRL); - - return 0; -} static const struct clk_ops ti_pll_clk_ops = { .get_rate = ti_pll_clk_get_rate, @@ -323,7 +518,7 @@ struct clk *clk_register_ti_pll(const char *name, const char *parent_name, if (!pll) return ERR_PTR(-ENOMEM); - pll->reg = reg; + pll->base = reg; ret = clk_register(&pll->clk, "ti-pll-clk", name, parent_name); if (ret) { @@ -333,19 +528,19 @@ struct clk *clk_register_ti_pll(const char *name, const char *parent_name, } /* Unlock the PLL registers */ - writel(PLL_KICK0_VALUE, pll->reg + PLL_KICK0); - writel(PLL_KICK1_VALUE, pll->reg + PLL_KICK1); + writel(PLL_KICK0_VALUE, pll->base + PLL_KICK0); + writel(PLL_KICK1_VALUE, pll->base + PLL_KICK1); /* Enable all HSDIV outputs */ - cfg = readl(pll->reg + PLL_16FFT_CFG); + cfg = readl(pll->base + PLL_16FFT_CFG); for (i = 0; i < 16; i++) { hsdiv_presence_bit = BIT(16 + i); hsdiv_ctrl_offs = 0x80 + (i * 4); /* Enable HSDIV output if present */ if ((hsdiv_presence_bit & cfg) != 0UL) { - ctrl = readl(pll->reg + hsdiv_ctrl_offs); + ctrl = readl(pll->base + hsdiv_ctrl_offs); ctrl |= PLL_16FFT_HSDIV_CTRL_CLKOUT_EN; - writel(ctrl, pll->reg + hsdiv_ctrl_offs); + writel(ctrl, pll->base + hsdiv_ctrl_offs); } } |