[PATCH] clk: zynqmp: Fix clk dump values
Michal Simek
monstr at monstr.eu
Tue Mar 30 09:23:40 CEST 2021
pá 26. 2. 2021 v 11:53 odesílatel Michal Simek <michal.simek at xilinx.com> napsal:
>
> From: T Karthik Reddy <t.karthik.reddy at xilinx.com>
>
> With "clk dump" command, few clocks are showing up incorrect values
> and some clocks are displayed as "unknown".
>
> Add missing clocks to zynqmp clock driver to display proper
> clocks rates.
>
> Implement a simple way to get clock source, instead of calling
> functions. Change existing functions to this simple mechanism.
>
> Fix gem clock name "gem_rx" to "gem_tx" which was incorrect.
> Change dbf_fpd & dbf_lpd clk names to dbg_fpd & dbg_lpd.
>
> Signed-off-by: Michal Simek <michal.simek at xilinx.com>
> Signed-off-by: T Karthik Reddy <t.karthik.reddy at xilinx.com>
> ---
>
> drivers/clk/clk_zynqmp.c | 251 ++++++++++++++++++++++++++-------------
> 1 file changed, 170 insertions(+), 81 deletions(-)
>
> diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c
> index 609d8e3b2fff..13a623fdb96a 100644
> --- a/drivers/clk/clk_zynqmp.c
> +++ b/drivers/clk/clk_zynqmp.c
> @@ -97,8 +97,7 @@ static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
> #define CLK_CTRL_DIV1_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
> #define CLK_CTRL_DIV0_SHIFT 8
> #define CLK_CTRL_DIV0_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
> -#define CLK_CTRL_SRCSEL_SHIFT 0
> -#define CLK_CTRL_SRCSEL_MASK (0x3 << CLK_CTRL_SRCSEL_SHIFT)
> +#define CLK_CTRL_SRCSEL_MASK 0x7
> #define PLLCTRL_FBDIV_MASK 0x7f00
> #define PLLCTRL_FBDIV_SHIFT 8
> #define PLLCTRL_RESET_MASK 1
> @@ -132,7 +131,7 @@ enum zynqmp_clk {
> iou_switch,
> gem_tsu_ref, gem_tsu,
> gem0_ref, gem1_ref, gem2_ref, gem3_ref,
> - gem0_rx, gem1_rx, gem2_rx, gem3_rx,
> + gem0_tx, gem1_tx, gem2_tx, gem3_tx,
> qspi_ref,
> sdio0_ref, sdio1_ref,
> uart0_ref, uart1_ref,
> @@ -152,7 +151,7 @@ static const char * const clk_names[clk_max] = {
> "iopll", "rpll", "apll", "dpll",
> "vpll", "iopll_to_fpd", "rpll_to_fpd",
> "apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd",
> - "acpu", "acpu_half", "dbf_fpd", "dbf_lpd",
> + "acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
> "dbg_trace", "dbg_tstmp", "dp_video_ref",
> "dp_audio_ref", "dp_stc_ref", "gdma_ref",
> "dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref",
> @@ -172,6 +171,38 @@ static const char * const clk_names[clk_max] = {
> "ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt"
> };
>
> +static const u32 pll_src[][4] = {
> + {apll, 0xff, dpll, vpll}, /* acpu */
> + {dpll, vpll, 0xff, 0xff}, /* ddr_ref */
> + {rpll, iopll, 0xff, 0xff}, /* dll_ref */
> + {iopll, 0xff, rpll, dpll_to_lpd}, /* gem_tsu_ref */
> + {iopll, 0xff, rpll, dpll}, /* peripheral */
> + {apll, 0xff, iopll_to_fpd, dpll}, /* wdt */
> + {iopll_to_fpd, 0xff, dpll, apll}, /* dbg_fpd */
> + {iopll, 0xff, rpll, dpll_to_lpd}, /* timestamp_ref */
> + {iopll_to_fpd, 0xff, apll, dpll}, /* sata_ref */
> + {iopll_to_fpd, 0xff, rpll_to_fpd, dpll},/* pcie_ref */
> + {iopll_to_fpd, 0xff, vpll, dpll}, /* gpu_ref */
> + {apll, 0xff, vpll, dpll}, /* topsw_main_ref */
> + {rpll, 0xff, iopll, dpll_to_lpd}, /* cpu_r5_ref */
> +};
> +
> +enum zynqmp_clk_pll_src {
> + ACPU_CLK_SRC = 0,
> + DDR_CLK_SRC,
> + DLL_CLK_SRC,
> + GEM_TSU_CLK_SRC,
> + PERI_CLK_SRC,
> + WDT_CLK_SRC,
> + DBG_FPD_CLK_SRC,
> + TIMESTAMP_CLK_SRC,
> + SATA_CLK_SRC,
> + PCIE_CLK_SRC,
> + GPU_CLK_SRC,
> + TOPSW_MAIN_CLK_SRC,
> + CPU_R5_CLK_SRC
> +};
> +
> struct zynqmp_clk_priv {
> unsigned long ps_clk_freq;
> unsigned long video_clk;
> @@ -195,12 +226,38 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
> return CRF_APB_VPLL_CTRL;
> case acpu:
> return CRF_APB_ACPU_CTRL;
> + case dbg_fpd:
> + return CRF_APB_DBG_FPD_CTRL;
> + case dbg_trace:
> + return CRF_APB_DBG_TRACE_CTRL;
> + case dbg_tstmp:
> + return CRF_APB_DBG_TSTMP_CTRL;
> + case gpu_ref ... gpu_pp1_ref:
> + return CRF_APB_GPU_REF_CTRL;
> case ddr_ref:
> return CRF_APB_DDR_CTRL;
> + case sata_ref:
> + return CRF_APB_SATA_REF_CTRL;
> + case pcie_ref:
> + return CRF_APB_PCIE_REF_CTRL;
> + case gdma_ref:
> + return CRF_APB_GDMA_REF_CTRL;
> + case dpdma_ref:
> + return CRF_APB_DPDMA_REF_CTRL;
> + case topsw_main:
> + return CRF_APB_TOPSW_MAIN_CTRL;
> + case topsw_lsbus:
> + return CRF_APB_TOPSW_LSBUS_CTRL;
> + case lpd_switch:
> + return CRL_APB_LPD_SWITCH_CTRL;
> + case lpd_lsbus:
> + return CRL_APB_LPD_LSBUS_CTRL;
> case qspi_ref:
> return CRL_APB_QSPI_REF_CTRL;
> case usb3_dual_ref:
> return CRL_APB_USB3_DUAL_REF_CTRL;
> + case gem_tsu_ref:
> + return CRL_APB_GEM_TSU_REF_CTRL;
> case gem0_ref:
> return CRL_APB_GEM0_REF_CTRL;
> case gem1_ref:
> @@ -213,6 +270,8 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
> return CRL_APB_USB0_BUS_REF_CTRL;
> case usb1_bus_ref:
> return CRL_APB_USB1_BUS_REF_CTRL;
> + case cpu_r5:
> + return CRL_APB_CPU_R5_CTRL;
> case uart0_ref:
> return CRL_APB_UART0_REF_CTRL;
> case uart1_ref:
> @@ -235,6 +294,14 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
> return CRL_APB_CAN0_REF_CTRL;
> case can1_ref:
> return CRL_APB_CAN1_REF_CTRL;
> + case dll_ref:
> + return CRL_APB_DLL_REF_CTRL;
> + case adma_ref:
> + return CRL_APB_ADMA_REF_CTRL;
> + case timestamp_ref:
> + return CRL_APB_TIMESTAMP_REF_CTRL;
> + case ams_ref:
> + return CRL_APB_AMS_REF_CTRL;
> case pl0:
> return CRL_APB_PL0_REF_CTRL;
> case pl1:
> @@ -253,68 +320,6 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
> return 0;
> }
>
> -static enum zynqmp_clk zynqmp_clk_get_cpu_pll(u32 clk_ctrl)
> -{
> - u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
> - CLK_CTRL_SRCSEL_SHIFT;
> -
> - switch (srcsel) {
> - case 2:
> - return dpll;
> - case 3:
> - return vpll;
> - case 0 ... 1:
> - default:
> - return apll;
> - }
> -}
> -
> -static enum zynqmp_clk zynqmp_clk_get_ddr_pll(u32 clk_ctrl)
> -{
> - u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
> - CLK_CTRL_SRCSEL_SHIFT;
> -
> - switch (srcsel) {
> - case 1:
> - return vpll;
> - case 0:
> - default:
> - return dpll;
> - }
> -}
> -
> -static enum zynqmp_clk zynqmp_clk_get_peripheral_pll(u32 clk_ctrl)
> -{
> - u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
> - CLK_CTRL_SRCSEL_SHIFT;
> -
> - switch (srcsel) {
> - case 2:
> - return rpll;
> - case 3:
> - return dpll;
> - case 0 ... 1:
> - default:
> - return iopll;
> - }
> -}
> -
> -static enum zynqmp_clk zynqmp_clk_get_wdt_pll(u32 clk_ctrl)
> -{
> - u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
> - CLK_CTRL_SRCSEL_SHIFT;
> -
> - switch (srcsel) {
> - case 2:
> - return iopll_to_fpd;
> - case 3:
> - return dpll;
> - case 0 ... 1:
> - default:
> - return apll;
> - }
> -}
> -
> static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
> struct zynqmp_clk_priv *priv,
> bool is_pre_src)
> @@ -378,7 +383,7 @@ static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
> static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
> enum zynqmp_clk id)
> {
> - u32 clk_ctrl, div;
> + u32 clk_ctrl, div, srcsel;
> enum zynqmp_clk pll;
> int ret;
> unsigned long pllrate;
> @@ -391,7 +396,8 @@ static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
>
> div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
>
> - pll = zynqmp_clk_get_cpu_pll(clk_ctrl);
> + srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
> + pll = pll_src[ACPU_CLK_SRC][srcsel];
> pllrate = zynqmp_clk_get_pll_rate(priv, pll);
> if (IS_ERR_VALUE(pllrate))
> return pllrate;
> @@ -401,7 +407,7 @@ static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
>
> static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
> {
> - u32 clk_ctrl, div;
> + u32 clk_ctrl, div, srcsel;
> enum zynqmp_clk pll;
> int ret;
> ulong pllrate;
> @@ -414,7 +420,8 @@ static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
>
> div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
>
> - pll = zynqmp_clk_get_ddr_pll(clk_ctrl);
> + srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
> + pll = pll_src[DDR_CLK_SRC][srcsel];
> pllrate = zynqmp_clk_get_pll_rate(priv, pll);
> if (IS_ERR_VALUE(pllrate))
> return pllrate;
> @@ -422,11 +429,33 @@ static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
> return DIV_ROUND_CLOSEST(pllrate, div);
> }
>
> +static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
> +{
> + u32 clk_ctrl, srcsel;
> + enum zynqmp_clk pll;
> + ulong pllrate;
> + int ret;
> +
> + ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
> + if (ret) {
> + printf("%s mio read fail\n", __func__);
> + return -EIO;
> + }
> +
> + srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
> + pll = pll_src[DLL_CLK_SRC][srcsel];
> + pllrate = zynqmp_clk_get_pll_rate(priv, pll);
> + if (IS_ERR_VALUE(pllrate))
> + return pllrate;
> +
> + return pllrate;
> +}
> +
> static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
> - enum zynqmp_clk id, bool two_divs)
> + enum zynqmp_clk id, bool two_divs)
> {
> enum zynqmp_clk pll;
> - u32 clk_ctrl, div0;
> + u32 clk_ctrl, div0, srcsel;
> u32 div1 = 1;
> int ret;
> ulong pllrate;
> @@ -446,8 +475,13 @@ static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
> if (!div1)
> div1 = 1;
> }
> + srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
> +
> + if (id == gem_tsu_ref)
> + pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
> + else
> + pll = pll_src[PERI_CLK_SRC][srcsel];
>
> - pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
> pllrate = zynqmp_clk_get_pll_rate(priv, pll);
> if (IS_ERR_VALUE(pllrate))
> return pllrate;
> @@ -457,11 +491,11 @@ static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
> DIV_ROUND_CLOSEST(pllrate, div0), div1);
> }
>
> -static ulong zynqmp_clk_get_wdt_rate(struct zynqmp_clk_priv *priv,
> - enum zynqmp_clk id, bool two_divs)
> +static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
> + enum zynqmp_clk id, bool two_divs)
> {
> enum zynqmp_clk pll;
> - u32 clk_ctrl, div0;
> + u32 clk_ctrl, div0, srcsel;
> u32 div1 = 1;
> int ret;
> ulong pllrate;
> @@ -475,8 +509,45 @@ static ulong zynqmp_clk_get_wdt_rate(struct zynqmp_clk_priv *priv,
> div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> if (!div0)
> div0 = 1;
> + srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
>
> - pll = zynqmp_clk_get_wdt_pll(clk_ctrl);
> + switch (id) {
> + case wdt:
> + case dbg_trace:
> + case topsw_lsbus:
> + pll = pll_src[WDT_CLK_SRC][srcsel];
> + break;
> + case dbg_fpd:
> + case dbg_tstmp:
> + pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
> + break;
> + case timestamp_ref:
> + pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
> + break;
> + case sata_ref:
> + pll = pll_src[SATA_CLK_SRC][srcsel];
> + break;
> + case pcie_ref:
> + pll = pll_src[PCIE_CLK_SRC][srcsel];
> + break;
> + case gpu_ref ... gpu_pp1_ref:
> + pll = pll_src[GPU_CLK_SRC][srcsel];
> + break;
> + case gdma_ref:
> + case dpdma_ref:
> + case topsw_main:
> + pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
> + break;
> + case cpu_r5:
> + case ams_ref:
> + case adma_ref:
> + case lpd_lsbus:
> + case lpd_switch:
> + pll = pll_src[CPU_R5_CLK_SRC][srcsel];
> + break;
> + default:
> + return -ENXIO;
> + }
> if (two_divs) {
> ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
> if (ret) {
> @@ -533,7 +604,7 @@ static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
> enum zynqmp_clk pll;
> u32 clk_ctrl, div0 = 0, div1 = 0;
> ulong pll_rate, new_rate;
> - u32 reg;
> + u32 reg, srcsel;
> int ret;
> u32 mask;
>
> @@ -544,7 +615,8 @@ static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
> return -EIO;
> }
>
> - pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
> + srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
> + pll = pll_src[PERI_CLK_SRC][srcsel];
> pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
> if (IS_ERR_VALUE(pll_rate))
> return pll_rate;
> @@ -588,14 +660,31 @@ static ulong zynqmp_clk_get_rate(struct clk *clk)
> return zynqmp_clk_get_cpu_rate(priv, id);
> case ddr_ref:
> return zynqmp_clk_get_ddr_rate(priv);
> + case dll_ref:
> + return zynqmp_clk_get_dll_rate(priv);
> + case gem_tsu_ref:
> + case pl0 ... pl3:
> case gem0_ref ... gem3_ref:
> case qspi_ref ... can1_ref:
> - case pl0 ... pl3:
> + case usb0_bus_ref ... usb3_dual_ref:
> two_divs = true;
> return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
> case wdt:
> + case topsw_lsbus:
> + case sata_ref ... gpu_pp1_ref:
> two_divs = true;
> - return zynqmp_clk_get_wdt_rate(priv, id, two_divs);
> + case cpu_r5:
> + case dbg_fpd:
> + case ams_ref:
> + case adma_ref:
> + case lpd_lsbus:
> + case dbg_trace:
> + case dbg_tstmp:
> + case lpd_switch:
> + case topsw_main:
> + case timestamp_ref:
> + case gdma_ref ... dpdma_ref:
> + return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
> default:
> return -ENXIO;
> }
> --
> 2.30.0
>
Applied.
M
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs
More information about the U-Boot
mailing list