From 0a93edbae6c051b5b4e8a84de6feee478abefee0 Mon Sep 17 00:00:00 2001 From: Satya Rama Aditya Pinapala Date: Sat, 25 Jan 2020 14:25:11 -0800 Subject: [PATCH] disp: msm: dsi: rework DSI PLL to be configured within PHY Change avoids clock framework APIs to configure the DSI PHY PLL. It follows HW recommendation to set the byte and pclk dividers. Change-Id: I8c110f3997e4ec4c2eaa28778b70091855725ab8 Signed-off-by: Satya Rama Aditya Pinapala --- msm/Makefile | 1 - msm/dsi/dsi_catalog.c | 25 +- msm/dsi/dsi_catalog.h | 8 +- msm/dsi/dsi_clk.h | 25 +- msm/dsi/dsi_clk_manager.c | 22 +- msm/dsi/dsi_defs.h | 19 +- msm/dsi/dsi_display.c | 256 ++-- msm/dsi/dsi_display.h | 13 +- msm/dsi/dsi_phy.c | 49 +- msm/dsi/dsi_phy.h | 33 +- msm/dsi/dsi_phy_hw.h | 31 +- msm/dsi/dsi_pll.c | 9 +- msm/dsi/dsi_pll.h | 105 +- msm/dsi/dsi_pll_10nm.c | 2074 ------------------------------- msm/dsi/dsi_pll_5nm.c | 2453 ++++++++++--------------------------- msm/dsi/dsi_pll_5nm.h | 250 ++++ 16 files changed, 1176 insertions(+), 4197 deletions(-) delete mode 100644 msm/dsi/dsi_pll_10nm.c create mode 100644 msm/dsi/dsi_pll_5nm.h diff --git a/msm/Makefile b/msm/Makefile index 9c7df05e71..fb0c7bfdf5 100644 --- a/msm/Makefile +++ b/msm/Makefile @@ -109,7 +109,6 @@ msm_drm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi_phy.o \ dsi/dsi_phy_timing_v4_0.o \ dsi/dsi_pll.o \ dsi/dsi_pll_5nm.o \ - dsi/dsi_pll_10nm.o \ dsi/dsi_ctrl_hw_cmn.o \ dsi/dsi_ctrl_hw_1_4.o \ dsi/dsi_ctrl_hw_2_0.o \ diff --git a/msm/dsi/dsi_catalog.c b/msm/dsi/dsi_catalog.c index 60880e663e..636f000c8c 100644 --- a/msm/dsi/dsi_catalog.c +++ b/msm/dsi/dsi_catalog.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #include @@ -343,3 +343,26 @@ int dsi_catalog_phy_setup(struct dsi_phy_hw *phy, return rc; } + +int dsi_catalog_phy_pll_setup(struct dsi_phy_hw *phy, u32 pll_ver) +{ + int rc = 0; + + if (pll_ver >= DSI_PLL_VERSION_UNKNOWN) { + DSI_ERR("Unsupported version: %d\n", pll_ver); + return -EOPNOTSUPP; + } + + switch (pll_ver) { + case DSI_PLL_VERSION_5NM: + phy->ops.configure = dsi_pll_5nm_configure; + phy->ops.pll_toggle = dsi_pll_5nm_toggle; + break; + default: + phy->ops.configure = NULL; + phy->ops.pll_toggle = NULL; + break; + } + + return rc; +} diff --git a/msm/dsi/dsi_catalog.h b/msm/dsi/dsi_catalog.h index 18214259ec..f76aae181e 100644 --- a/msm/dsi/dsi_catalog.h +++ b/msm/dsi/dsi_catalog.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef _DSI_CATALOG_H_ @@ -284,4 +284,10 @@ void dsi_ctrl_hw_22_configure_cmddma_window(struct dsi_ctrl_hw *ctrl, void dsi_ctrl_hw_22_reset_trigger_controls(struct dsi_ctrl_hw *ctrl, struct dsi_host_common_cfg *cfg); u32 dsi_ctrl_hw_22_log_line_count(struct dsi_ctrl_hw *ctrl, bool cmd_mode); + +/* PLL specific functions */ +int dsi_catalog_phy_pll_setup(struct dsi_phy_hw *phy, u32 pll_ver); +int dsi_pll_5nm_configure(void *pll, bool commit); +int dsi_pll_5nm_toggle(void *pll, bool prepare); + #endif /* _DSI_CATALOG_H_ */ diff --git a/msm/dsi/dsi_clk.h b/msm/dsi/dsi_clk.h index e990ee047e..8a45460fd2 100644 --- a/msm/dsi/dsi_clk.h +++ b/msm/dsi/dsi_clk.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _DSI_CLK_H_ @@ -173,6 +173,25 @@ typedef int (*pre_clockon_cb)(void *priv, enum dsi_clk_state new_state); +/** + * typedef *phy_configure_cb() - Callback to configure PHY for PLL clocks + * @priv: private data pointer. + * @commit: boolean to specify if calculated PHY configuration needs to be + * committed. Set to false in case of dynamic clock switch. + * + * @return: error code. + */ +typedef int (*phy_configure_cb)(void *priv, bool commit); + +/** + * typedef *pll_toggle_cb() - Callback to toggle PHY PLL + * @priv: private data pointer. + * @prepare: specifies if the PLL needs to be turned on or off. + * + * @return: error code. + */ +typedef int (*pll_toggle_cb)(void *priv, bool prepare); + /** * struct dsi_clk_info - clock information for DSI hardware. * @name: client name. @@ -185,6 +204,8 @@ typedef int (*pre_clockon_cb)(void *priv, * @post_clkoff_cb callback after clock is turned off * @post_clkon_cb callback after clock is turned on * @pre_clkon_cb callback before clock is turned on + * @phy_config_cb callback to configure PHY PLL + * @phy_pll_toggle_cb callback to toggle PHY PLL state * @priv_data pointer to private data * @master_ndx master DSI controller index * @dsi_ctrl_count number of DSI controllers @@ -199,6 +220,8 @@ struct dsi_clk_info { post_clockoff_cb post_clkoff_cb; post_clockon_cb post_clkon_cb; pre_clockon_cb pre_clkon_cb; + phy_configure_cb phy_config_cb; + pll_toggle_cb phy_pll_toggle_cb; void *priv_data; u32 master_ndx; u32 dsi_ctrl_count; diff --git a/msm/dsi/dsi_clk_manager.c b/msm/dsi/dsi_clk_manager.c index b8b5bec682..2333f1bd1f 100644 --- a/msm/dsi/dsi_clk_manager.c +++ b/msm/dsi/dsi_clk_manager.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include @@ -33,6 +33,8 @@ struct dsi_clk_mngr { u32 core_clk_state; u32 link_clk_state; + phy_configure_cb phy_config_cb; + pll_toggle_cb phy_pll_toggle_cb; pre_clockoff_cb pre_clkoff_cb; post_clockoff_cb post_clkoff_cb; post_clockon_cb post_clkon_cb; @@ -498,10 +500,6 @@ error: */ static int dsi_link_hs_clk_stop(struct dsi_link_hs_clk_info *link_hs_clks) { - struct dsi_link_clks *l_clks; - - l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); - dsi_link_hs_clk_disable(link_hs_clks); dsi_link_hs_clk_unprepare(link_hs_clks); @@ -616,6 +614,9 @@ static int dsi_display_link_clk_enable(struct dsi_link_clks *clks, int rc = 0; int i; struct dsi_link_clks *clk, *m_clks; + struct dsi_clk_mngr *mngr; + + mngr = container_of(clks, struct dsi_clk_mngr, link_clks[master_ndx]); /* * In case of split DSI usecases, the clock for master controller should @@ -635,6 +636,10 @@ static int dsi_display_link_clk_enable(struct dsi_link_clks *clks, } if (l_type & DSI_LINK_HS_CLK) { + if (!mngr->is_cont_splash_enabled) { + mngr->phy_config_cb(mngr->priv_data, true); + mngr->phy_pll_toggle_cb(mngr->priv_data, true); + } rc = dsi_link_hs_clk_start(&m_clks->hs_clks, DSI_LINK_CLK_START, master_ndx); if (rc) { @@ -724,6 +729,9 @@ static int dsi_display_link_clk_disable(struct dsi_link_clks *clks, int rc = 0; int i; struct dsi_link_clks *clk, *m_clks; + struct dsi_clk_mngr *mngr; + + mngr = container_of(clks, struct dsi_clk_mngr, link_clks[master_ndx]); /* * In case of split DSI usecases, clock for slave DSI controllers should @@ -767,6 +775,8 @@ static int dsi_display_link_clk_disable(struct dsi_link_clks *clks, if (rc) DSI_ERR("failed to turn off master hs link clocks, rc=%d\n", rc); + if (!mngr->is_cont_splash_enabled) + mngr->phy_pll_toggle_cb(mngr->priv_data, false); } return rc; @@ -1439,6 +1449,8 @@ void *dsi_display_clk_mngr_register(struct dsi_clk_info *info) mngr->post_clkon_cb = info->post_clkon_cb; mngr->pre_clkoff_cb = info->pre_clkoff_cb; mngr->post_clkoff_cb = info->post_clkoff_cb; + mngr->phy_config_cb = info->phy_config_cb; + mngr->phy_pll_toggle_cb = info->phy_pll_toggle_cb; mngr->priv_data = info->priv_data; memcpy(mngr->name, info->name, MAX_STRING_LEN); diff --git a/msm/dsi/dsi_defs.h b/msm/dsi/dsi_defs.h index 9f424781b7..72bab7b38e 100644 --- a/msm/dsi/dsi_defs.h +++ b/msm/dsi/dsi_defs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _DSI_DEFS_H_ @@ -739,6 +739,23 @@ static inline int dsi_pixel_format_to_bpp(enum dsi_pixel_format fmt) return 24; } +/* return number of DSI data lanes */ +static inline int dsi_get_num_of_data_lanes(enum dsi_data_lanes dlanes) +{ + int num_of_lanes = 0; + + if (dlanes & DSI_DATA_LANE_0) + num_of_lanes++; + if (dlanes & DSI_DATA_LANE_1) + num_of_lanes++; + if (dlanes & DSI_DATA_LANE_2) + num_of_lanes++; + if (dlanes & DSI_DATA_LANE_3) + num_of_lanes++; + + return num_of_lanes; +} + static inline u64 dsi_h_active_dce(struct dsi_mode_info *mode) { u64 h_active = 0; diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 746c039974..1b3daab468 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include @@ -2608,26 +2608,68 @@ error: return rc; } +int dsi_display_phy_pll_toggle(void *priv, bool prepare) +{ + int rc = 0; + struct dsi_display *display = priv; + struct dsi_display_ctrl *m_ctrl; + + if (!display) { + DSI_ERR("invalid arguments\n"); + return -EINVAL; + } + + m_ctrl = &display->ctrl[display->clk_master_idx]; + if (!m_ctrl->phy) { + DSI_ERR("[%s] PHY not found\n", display->name); + return -EINVAL; + } + + rc = dsi_phy_pll_toggle(m_ctrl->phy, prepare); + + return rc; +} + +int dsi_display_phy_configure(void *priv, bool commit) +{ + int rc = 0; + struct dsi_display *display = priv; + struct dsi_display_ctrl *m_ctrl; + struct dsi_pll_resource *pll_res; + struct dsi_ctrl *ctrl; + + if (!display) { + DSI_ERR("invalid arguments\n"); + return -EINVAL; + } + + m_ctrl = &display->ctrl[display->clk_master_idx]; + if ((!m_ctrl->phy) || (!m_ctrl->ctrl)) { + DSI_ERR("[%s] PHY not found\n", display->name); + return -EINVAL; + } + + pll_res = m_ctrl->phy->pll; + if (!pll_res) { + DSI_ERR("[%s] PLL res not found\n", display->name); + return -EINVAL; + } + + ctrl = m_ctrl->ctrl; + pll_res->byteclk_rate = ctrl->clk_freq.byte_clk_rate; + pll_res->pclk_rate = ctrl->clk_freq.pix_clk_rate; + + rc = dsi_phy_configure(m_ctrl->phy, commit); + + return rc; +} + static int dsi_display_set_clk_src(struct dsi_display *display) { int rc = 0; int i; struct dsi_display_ctrl *m_ctrl, *ctrl; - /* - * For CPHY mode, the parent of mux_clks need to be set - * to Cphy_clks to have correct dividers for byte and - * pixel clocks. - */ - if (display->panel->host_config.phy_type == DSI_PHY_TYPE_CPHY) { - rc = dsi_clk_update_parent(&display->clock_info.cphy_clks, - &display->clock_info.mux_clks); - if (rc) { - DSI_ERR("failed update mux parent to shadow\n"); - return rc; - } - } - /* * In case of split DSI usecases, the clock for master controller should * be enabled before the other controller. Master controller in the @@ -2636,7 +2678,7 @@ static int dsi_display_set_clk_src(struct dsi_display *display) m_ctrl = &display->ctrl[display->clk_master_idx]; rc = dsi_ctrl_set_clock_source(m_ctrl->ctrl, - &display->clock_info.mux_clks); + &display->clock_info.pll_clks); if (rc) { DSI_ERR("[%s] failed to set source clocks for master, rc=%d\n", display->name, rc); @@ -2650,7 +2692,7 @@ static int dsi_display_set_clk_src(struct dsi_display *display) continue; rc = dsi_ctrl_set_clock_source(ctrl->ctrl, - &display->clock_info.mux_clks); + &display->clock_info.pll_clks); if (rc) { DSI_ERR("[%s] failed to set source clocks, rc=%d\n", display->name, rc); @@ -3320,46 +3362,6 @@ static int dsi_display_mipi_host_deinit(struct dsi_display *display) return rc; } -static int dsi_display_clocks_deinit(struct dsi_display *display) -{ - int rc = 0; - struct dsi_clk_link_set *src = &display->clock_info.src_clks; - struct dsi_clk_link_set *mux = &display->clock_info.mux_clks; - struct dsi_clk_link_set *shadow = &display->clock_info.shadow_clks; - - if (src->byte_clk) { - devm_clk_put(&display->pdev->dev, src->byte_clk); - src->byte_clk = NULL; - } - - if (src->pixel_clk) { - devm_clk_put(&display->pdev->dev, src->pixel_clk); - src->pixel_clk = NULL; - } - - if (mux->byte_clk) { - devm_clk_put(&display->pdev->dev, mux->byte_clk); - mux->byte_clk = NULL; - } - - if (mux->pixel_clk) { - devm_clk_put(&display->pdev->dev, mux->pixel_clk); - mux->pixel_clk = NULL; - } - - if (shadow->byte_clk) { - devm_clk_put(&display->pdev->dev, shadow->byte_clk); - shadow->byte_clk = NULL; - } - - if (shadow->pixel_clk) { - devm_clk_put(&display->pdev->dev, shadow->pixel_clk); - shadow->pixel_clk = NULL; - } - - return rc; -} - static bool dsi_display_check_prefix(const char *clk_prefix, const char *clk_name) { @@ -3393,20 +3395,9 @@ static int dsi_display_clocks_init(struct dsi_display *display) { int i, rc = 0, num_clk = 0; const char *clk_name; - const char *src_byte = "src_byte", *src_pixel = "src_pixel"; - const char *mux_byte = "mux_byte", *mux_pixel = "mux_pixel"; - const char *cphy_byte = "cphy_byte", *cphy_pixel = "cphy_pixel"; - const char *shadow_byte = "shadow_byte", *shadow_pixel = "shadow_pixel"; - const char *shadow_cphybyte = "shadow_cphybyte", - *shadow_cphypixel = "shadow_cphypixel"; + const char *pll_byte = "pll_byte", *pll_dsi = "pll_dsi"; struct clk *dsi_clk; - struct dsi_clk_link_set *src = &display->clock_info.src_clks; - struct dsi_clk_link_set *mux = &display->clock_info.mux_clks; - struct dsi_clk_link_set *cphy = &display->clock_info.cphy_clks; - struct dsi_clk_link_set *shadow = &display->clock_info.shadow_clks; - struct dsi_clk_link_set *shadow_cphy = - &display->clock_info.shadow_cphy_clks; - struct dsi_dyn_clk_caps *dyn_clk_caps = &(display->panel->dyn_clk_caps); + struct dsi_clk_link_set *pll = &display->clock_info.pll_clks; char *dsi_clock_name; if (!strcmp(display->display_type, "primary")) @@ -3416,8 +3407,6 @@ static int dsi_display_clocks_init(struct dsi_display *display) num_clk = dsi_display_get_clocks_count(display, dsi_clock_name); - DSI_DEBUG("clk count=%d\n", num_clk); - for (i = 0; i < num_clk; i++) { dsi_display_get_clock_name(display, dsi_clock_name, i, &clk_name); @@ -3430,105 +3419,30 @@ static int dsi_display_clocks_init(struct dsi_display *display) DSI_ERR("failed to get %s, rc=%d\n", clk_name, rc); - if (dsi_display_check_prefix(mux_byte, clk_name)) { - mux->byte_clk = NULL; - goto error; - } - if (dsi_display_check_prefix(mux_pixel, clk_name)) { - mux->pixel_clk = NULL; + if (dsi_display_check_prefix(pll_byte, clk_name)) { + pll->byte_clk = NULL; goto error; } - if (dsi_display_check_prefix(cphy_byte, clk_name)) { - cphy->byte_clk = NULL; + if (dsi_display_check_prefix(pll_dsi, clk_name)) { + pll->pixel_clk = NULL; goto error; } - if (dsi_display_check_prefix(cphy_pixel, clk_name)) { - cphy->pixel_clk = NULL; - goto error; - } - - if (dyn_clk_caps->dyn_clk_support && - (display->panel->panel_mode == - DSI_OP_VIDEO_MODE)) { - - if (dsi_display_check_prefix(src_byte, - clk_name)) - src->byte_clk = NULL; - if (dsi_display_check_prefix(src_pixel, - clk_name)) - src->pixel_clk = NULL; - if (dsi_display_check_prefix(shadow_byte, - clk_name)) - shadow->byte_clk = NULL; - if (dsi_display_check_prefix(shadow_pixel, - clk_name)) - shadow->pixel_clk = NULL; - if (dsi_display_check_prefix(shadow_cphybyte, - clk_name)) - shadow_cphy->byte_clk = NULL; - if (dsi_display_check_prefix(shadow_cphypixel, - clk_name)) - shadow_cphy->pixel_clk = NULL; - - dyn_clk_caps->dyn_clk_support = false; - } } - if (dsi_display_check_prefix(src_byte, clk_name)) { - src->byte_clk = dsi_clk; + if (dsi_display_check_prefix(pll_byte, clk_name)) { + pll->byte_clk = dsi_clk; + continue; + } + if (dsi_display_check_prefix(pll_dsi, clk_name)) { + pll->pixel_clk = dsi_clk; continue; } - if (dsi_display_check_prefix(src_pixel, clk_name)) { - src->pixel_clk = dsi_clk; - continue; - } - - if (dsi_display_check_prefix(cphy_byte, clk_name)) { - cphy->byte_clk = dsi_clk; - continue; - } - - if (dsi_display_check_prefix(cphy_pixel, clk_name)) { - cphy->pixel_clk = dsi_clk; - continue; - } - - if (dsi_display_check_prefix(mux_byte, clk_name)) { - mux->byte_clk = dsi_clk; - continue; - } - - if (dsi_display_check_prefix(mux_pixel, clk_name)) { - mux->pixel_clk = dsi_clk; - continue; - } - - if (dsi_display_check_prefix(shadow_byte, clk_name)) { - shadow->byte_clk = dsi_clk; - continue; - } - - if (dsi_display_check_prefix(shadow_pixel, clk_name)) { - shadow->pixel_clk = dsi_clk; - continue; - } - - if (dsi_display_check_prefix(shadow_cphybyte, clk_name)) { - shadow_cphy->byte_clk = dsi_clk; - continue; - } - - if (dsi_display_check_prefix(shadow_cphypixel, clk_name)) { - shadow_cphy->pixel_clk = dsi_clk; - continue; - } } return 0; error: - (void)dsi_display_clocks_deinit(display); return rc; } @@ -4168,10 +4082,6 @@ static int dsi_display_res_deinit(struct dsi_display *display) int i; struct dsi_display_ctrl *ctrl; - rc = dsi_display_clocks_deinit(display); - if (rc) - DSI_ERR("clocks deinit failed, rc=%d\n", rc); - display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; dsi_phy_put(ctrl->phy); @@ -4506,28 +4416,17 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display, u8 ctrl_version; struct dsi_display_ctrl *m_ctrl, *ctrl; struct dsi_dyn_clk_caps *dyn_clk_caps; - struct dsi_clk_link_set *parent_clk, *enable_clk; + struct dsi_clk_link_set *enable_clk; m_ctrl = &display->ctrl[display->clk_master_idx]; dyn_clk_caps = &(display->panel->dyn_clk_caps); ctrl_version = m_ctrl->ctrl->version; - if (dsi_display_is_type_cphy(display)) { - enable_clk = &display->clock_info.cphy_clks; - parent_clk = &display->clock_info.shadow_cphy_clks; - } else { - enable_clk = &display->clock_info.src_clks; - parent_clk = &display->clock_info.shadow_clks; - } + enable_clk = &display->clock_info.pll_clks; dsi_clk_prepare_enable(enable_clk); - rc = dsi_clk_update_parent(parent_clk, - &display->clock_info.mux_clks); - if (rc) { - DSI_ERR("failed to update mux parent\n"); - goto exit; - } + dsi_display_phy_configure(display, false); display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; @@ -4584,8 +4483,6 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display, } defer_dfps_wait: - rc = dsi_clk_update_parent(enable_clk, - &display->clock_info.mux_clks); if (rc) DSI_ERR("could not switch back to src clks %d\n", rc); @@ -4612,9 +4509,6 @@ recover_byte_clk: bkp_freq->byte_intf_clk_rate, i); } -exit: - dsi_clk_disable_unprepare(&display->clock_info.src_clks); - return rc; } @@ -5526,6 +5420,8 @@ static int dsi_display_bind(struct device *dev, info.pre_clkon_cb = dsi_pre_clkon_cb; info.post_clkoff_cb = dsi_post_clkoff_cb; info.post_clkon_cb = dsi_post_clkon_cb; + info.phy_config_cb = dsi_display_phy_configure; + info.phy_pll_toggle_cb = dsi_display_phy_pll_toggle; info.priv_data = display; info.master_ndx = display->clk_master_idx; info.dsi_ctrl_count = display->ctrl_count; diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index f829ac8d91..cce1500ed4 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef _DSI_DISPLAY_H_ @@ -104,17 +104,10 @@ struct dsi_display_boot_param { /** * struct dsi_display_clk_info - dsi display clock source information - * @src_clks: Source clocks for DSI display. - * @mux_clks: Mux clocks used for DFPS. - * @shadow_clks: Used for D-phy clock switch. - * @shadow_cphy_clks: Used for C-phy clock switch. + * @pll_clks: PLL clocks for DSI. */ struct dsi_display_clk_info { - struct dsi_clk_link_set src_clks; - struct dsi_clk_link_set mux_clks; - struct dsi_clk_link_set cphy_clks; - struct dsi_clk_link_set shadow_clks; - struct dsi_clk_link_set shadow_cphy_clks; + struct dsi_clk_link_set pll_clks; }; /** diff --git a/msm/dsi/dsi_phy.c b/msm/dsi/dsi_phy.c index 952618133b..4eb372d81c 100644 --- a/msm/dsi/dsi_phy.c +++ b/msm/dsi/dsi_phy.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include @@ -461,6 +461,14 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) goto fail_settings; } + rc = dsi_catalog_phy_pll_setup(&dsi_phy->hw, + dsi_phy->pll->pll_revision); + if (rc) { + DSI_PHY_ERR(dsi_phy, "Catalog does not support PLL version (%d)\n", + dsi_phy->pll->pll_revision); + goto fail_settings; + } + item->phy = dsi_phy; mutex_lock(&dsi_phy_list_lock); @@ -760,6 +768,45 @@ error: return rc; } +/** + * dsi_phy_configure() - Configure DSI PHY PLL + * @dsi_phy: DSI PHY handle. + * @commit: boolean to specify if calculated PHY configuration + * needs to be committed. Set to false in case of + * dynamic clock switch. + * + * Return: error code. + */ +int dsi_phy_configure(struct msm_dsi_phy *phy, bool commit) +{ + int rc = 0; + + phy->pll->type = phy->cfg.phy_type; + phy->pll->bpp = dsi_pixel_format_to_bpp(phy->dst_format); + phy->pll->lanes = dsi_get_num_of_data_lanes(phy->data_lanes); + if (phy->hw.ops.configure) + rc = phy->hw.ops.configure(phy->pll, commit); + + return rc; +} + +/** + * dsi_phy_pll_toggle() - Toggle DSI PHY PLL + * @dsi_phy: DSI PHY handle. + * @prepare: specifies if PLL needs to be turned on or not. + * + * Return: error code. + */ +int dsi_phy_pll_toggle(struct msm_dsi_phy *phy, bool prepare) +{ + int rc = 0; + + if (phy->hw.ops.pll_toggle) + rc = phy->hw.ops.pll_toggle(phy->pll, prepare); + + return rc; +} + static int dsi_phy_enable_ulps(struct msm_dsi_phy *phy, struct dsi_host_config *config, bool clamp_enabled) { diff --git a/msm/dsi/dsi_phy.h b/msm/dsi/dsi_phy.h index 7fe7c060c8..8e36c70dd4 100644 --- a/msm/dsi/dsi_phy.h +++ b/msm/dsi/dsi_phy.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _DSI_PHY_H_ @@ -356,9 +356,9 @@ void dsi_phy_dynamic_refresh_clear(struct msm_dsi_phy *phy); * @dst: Pointer to cache location. * @size: Number of phy lane settings. */ -int dsi_phy_dyn_refresh_cache_phy_timings(struct msm_dsi_phy *phy, +int dsi_phy_dyn_refresh_cache_phy_timings(struct msm_dsi_phy *phy, u32 *dst, + u32 size); - u32 *dst, u32 size); /** * dsi_phy_set_continuous_clk() - API to set/unset force clock lane HS request. * @phy: DSI PHY Handle. @@ -375,4 +375,31 @@ void dsi_phy_set_continuous_clk(struct msm_dsi_phy *phy, bool enable); */ int dsi_phy_get_io_resources(struct msm_io_res *io_res); +/** + * dsi_phy_configure() - Configure DSI PHY PLL + * @dsi_phy: DSI PHY handle. + * @commit: boolean to specify if calculated PHY configuration + * needs to be committed. Set to false in case of + * dynamic clock switch. + * + * Return: error code. + */ +int dsi_phy_configure(struct msm_dsi_phy *dsi_phy, bool commit); + +/** + * dsi_phy_pll_toggle() - Toggle DSI PHY PLL + * @dsi_phy: DSI PHY handle. + * @prepare: specifies if PLL needs to be turned on or not. + * + * Return: error code. + */ +int dsi_phy_pll_toggle(struct msm_dsi_phy *dsi_phy, bool prepare); + +/** + * dsi_phy_dynclk_configure() - Configure DSI PHY PLL during dynamic clock + * @dsi_phy: DSI PHY handle. + * + * Return: error code. + */ +int dsi_phy_dynclk_configure(struct msm_dsi_phy *phy); #endif /* _DSI_PHY_H_ */ diff --git a/msm/dsi/dsi_phy_hw.h b/msm/dsi/dsi_phy_hw.h index 62e9e01254..fd27dd42b6 100644 --- a/msm/dsi/dsi_phy_hw.h +++ b/msm/dsi/dsi_phy_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef _DSI_PHY_HW_H_ @@ -47,6 +47,18 @@ enum dsi_phy_version { DSI_PHY_VERSION_MAX }; +/** + * enum dsi_pll_version - DSI PHY PLL version enumeration + * @DSI_PLL_VERSION_5NM: 5nm PLL + * @DSI_PLL_VERSION_10NM: 10nm PLL + * @DSI_PLL_VERSION_UNKNOWN: Unknown PLL version + */ +enum dsi_pll_version { + DSI_PLL_VERSION_5NM, + DSI_PLL_VERSION_10NM, + DSI_PLL_VERSION_UNKNOWN +}; + /** * enum dsi_phy_hw_features - features supported by DSI PHY hardware * @DSI_PHY_DPHY: Supports DPHY @@ -344,6 +356,23 @@ struct dsi_phy_hw_ops { void *timing_ops; struct phy_ulps_config_ops ulps_ops; struct phy_dyn_refresh_ops dyn_refresh_ops; + + /** + * configure() - Configure the DSI PHY PLL + * @pll: Pointer to DSI PLL. + * @commit: boolean to specify if calculated PHY configuration + needs to be committed. Set to false in case of + dynamic clock switch. + */ + int (*configure)(void *pll, bool commit); + + /** + * pll_toggle() - Toggle the DSI PHY PLL + * @pll: Pointer to DSI PLL. + * @prepare: specify if PLL needs to be turned on or off. + */ + int (*pll_toggle)(void *pll, bool prepare); + }; /** diff --git a/msm/dsi/dsi_pll.c b/msm/dsi/dsi_pll.c index ce5d1cf3e2..3f8c927f8e 100644 --- a/msm/dsi/dsi_pll.c +++ b/msm/dsi/dsi_pll.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "%s: " fmt, __func__ @@ -23,9 +23,6 @@ static int dsi_pll_clock_register(struct platform_device *pdev, case DSI_PLL_5NM: rc = dsi_pll_clock_register_5nm(pdev, pll_res); break; - case DSI_PLL_10NM: - rc = dsi_pll_clock_register_10nm(pdev, pll_res); - break; default: rc = -EINVAL; break; @@ -144,14 +141,12 @@ int dsi_pll_init(struct platform_device *pdev, struct dsi_pll_resource **pll) DSI_PLL_INFO(pll_res, "DSI pll label = %s\n", label); /** - * Currently, Only supports 5nm and 10nm PLL version. Will add + * Currently, Only supports 5nm. Will add * support for other versions as needed. */ if (!strcmp(label, "dsi_pll_5nm")) pll_res->pll_revision = DSI_PLL_5NM; - else if (!strcmp(label, "dsi_pll_10nm")) - pll_res->pll_revision = DSI_PLL_10NM; else return -ENOTSUPP; diff --git a/msm/dsi/dsi_pll.h b/msm/dsi/dsi_pll.h index 386fe6a931..351790305d 100644 --- a/msm/dsi/dsi_pll.h +++ b/msm/dsi/dsi_pll.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef __DSI_PLL_H @@ -87,20 +87,11 @@ struct dsi_pll_resource { void __iomem *dyn_pll_base; s64 vco_current_rate; - s64 vco_locking_rate; s64 vco_ref_clk_rate; - - /* - * Certain pll's needs to update the same vco rate after resume in - * suspend/resume scenario. Cached the vco rate for such plls. - */ - unsigned long vco_cached_rate; - u32 cached_cfg0; - u32 cached_cfg1; - u32 cached_outdiv; - - u32 cached_postdiv1; - u32 cached_postdiv3; + s64 vco_min_rate; + s64 vco_rate; + s64 byteclk_rate; + s64 pclk_rate; u32 pll_revision; @@ -115,24 +106,11 @@ struct dsi_pll_resource { */ bool pll_on; - /* - * handoff_status is true of pll is already enabled by bootloader with - * continuous splash enable case. Clock API will call the handoff API - * to enable the status. It is disabled if continuous splash - * feature is disabled. - */ - bool handoff_resources; - /* * caching the pll trim codes in the case of dynamic refresh */ int cache_pll_trim_codes[3]; - /* - * for maintaining the status of saving trim codes - */ - bool reg_upd; - /* * PLL index if multiple index are available. Eg. in case of @@ -147,11 +125,6 @@ struct dsi_pll_resource { struct dsi_pll_resource *slave; - /* - * target pll revision information - */ - int revision; - void *priv; /* @@ -160,24 +133,20 @@ struct dsi_pll_resource { struct dfps_info *dfps; /* - * for cases where dfps trigger happens before first - * suspend/resume and handoff is not finished. + * DSI pixel depth and lane information */ - bool dfps_trigger; + int bpp; + int lanes; + + /* + * DSI PHY type DPHY/CPHY + */ + enum dsi_phy_type type; }; -struct dsi_pll_vco_clk { - struct clk_hw hw; - unsigned long ref_clk_rate; - u64 min_rate; - u64 max_rate; - u32 pll_en_seq_cnt; - struct lpfr_cfg *lpfr_lut; - u32 lpfr_lut_size; - void *priv; - - int (*pll_enable_seqs[MAX_DSI_PLL_EN_SEQS]) - (struct dsi_pll_resource *pll_res); +struct dsi_pll_clk { + struct clk_hw hw; + void *priv; }; struct dsi_pll_vco_calc { @@ -191,47 +160,21 @@ struct dsi_pll_vco_calc { s64 pll_plllock_cmp3; }; -static inline bool is_gdsc_disabled(struct dsi_pll_resource *pll_res) -{ - if (!pll_res->gdsc_base) { - WARN(1, "gdsc_base register is not defined\n"); - return true; - } - return readl_relaxed(pll_res->gdsc_base) & BIT(31) ? false : true; -} +struct dsi_pll_div_table { + u32 min_hz; + u32 max_hz; + int pll_div; + int phy_div; +}; -static inline int dsi_pll_div_prepare(struct clk_hw *hw) +static inline struct dsi_pll_clk *to_pll_clk_hw(struct clk_hw *hw) { - struct clk_hw *parent_hw = clk_hw_get_parent(hw); - /* Restore the divider's value */ - return hw->init->ops->set_rate(hw, clk_hw_get_rate(hw), - clk_hw_get_rate(parent_hw)); -} - -static inline int dsi_set_mux_sel(void *context, unsigned int reg, - unsigned int val) -{ - return 0; -} - -static inline int dsi_get_mux_sel(void *context, unsigned int reg, - unsigned int *val) -{ - *val = 0; - return 0; -} - -static inline struct dsi_pll_vco_clk *to_vco_clk_hw(struct clk_hw *hw) -{ - return container_of(hw, struct dsi_pll_vco_clk, hw); + return container_of(hw, struct dsi_pll_clk, hw); } int dsi_pll_clock_register_5nm(struct platform_device *pdev, struct dsi_pll_resource *pll_res); -int dsi_pll_clock_register_10nm(struct platform_device *pdev, - struct dsi_pll_resource *pll_res); - int dsi_pll_init(struct platform_device *pdev, struct dsi_pll_resource **pll_res); #endif diff --git a/msm/dsi/dsi_pll_10nm.c b/msm/dsi/dsi_pll_10nm.c deleted file mode 100644 index cf641943f4..0000000000 --- a/msm/dsi/dsi_pll_10nm.c +++ /dev/null @@ -1,2074 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include "dsi_pll.h" -#include - -#define VCO_DELAY_USEC 1 - -#define MHZ_250 250000000UL -#define MHZ_500 500000000UL -#define MHZ_1000 1000000000UL -#define MHZ_1100 1100000000UL -#define MHZ_1900 1900000000UL -#define MHZ_3000 3000000000UL - -/* Register Offsets from PLL base address */ -#define PLL_ANALOG_CONTROLS_ONE 0x000 -#define PLL_ANALOG_CONTROLS_TWO 0x004 -#define PLL_INT_LOOP_SETTINGS 0x008 -#define PLL_INT_LOOP_SETTINGS_TWO 0x00c -#define PLL_ANALOG_CONTROLS_THREE 0x010 -#define PLL_ANALOG_CONTROLS_FOUR 0x014 -#define PLL_INT_LOOP_CONTROLS 0x018 -#define PLL_DSM_DIVIDER 0x01c -#define PLL_FEEDBACK_DIVIDER 0x020 -#define PLL_SYSTEM_MUXES 0x024 -#define PLL_FREQ_UPDATE_CONTROL_OVERRIDES 0x028 -#define PLL_CMODE 0x02c -#define PLL_CALIBRATION_SETTINGS 0x030 -#define PLL_BAND_SEL_CAL_TIMER_LOW 0x034 -#define PLL_BAND_SEL_CAL_TIMER_HIGH 0x038 -#define PLL_BAND_SEL_CAL_SETTINGS 0x03c -#define PLL_BAND_SEL_MIN 0x040 -#define PLL_BAND_SEL_MAX 0x044 -#define PLL_BAND_SEL_PFILT 0x048 -#define PLL_BAND_SEL_IFILT 0x04c -#define PLL_BAND_SEL_CAL_SETTINGS_TWO 0x050 -#define PLL_BAND_SEL_CAL_SETTINGS_THREE 0x054 -#define PLL_BAND_SEL_CAL_SETTINGS_FOUR 0x058 -#define PLL_BAND_SEL_ICODE_HIGH 0x05c -#define PLL_BAND_SEL_ICODE_LOW 0x060 -#define PLL_FREQ_DETECT_SETTINGS_ONE 0x064 -#define PLL_PFILT 0x07c -#define PLL_IFILT 0x080 -#define PLL_GAIN 0x084 -#define PLL_ICODE_LOW 0x088 -#define PLL_ICODE_HIGH 0x08c -#define PLL_LOCKDET 0x090 -#define PLL_OUTDIV 0x094 -#define PLL_FASTLOCK_CONTROL 0x098 -#define PLL_PASS_OUT_OVERRIDE_ONE 0x09c -#define PLL_PASS_OUT_OVERRIDE_TWO 0x0a0 -#define PLL_CORE_OVERRIDE 0x0a4 -#define PLL_CORE_INPUT_OVERRIDE 0x0a8 -#define PLL_RATE_CHANGE 0x0ac -#define PLL_PLL_DIGITAL_TIMERS 0x0b0 -#define PLL_PLL_DIGITAL_TIMERS_TWO 0x0b4 -#define PLL_DEC_FRAC_MUXES 0x0c8 -#define PLL_DECIMAL_DIV_START_1 0x0cc -#define PLL_FRAC_DIV_START_LOW_1 0x0d0 -#define PLL_FRAC_DIV_START_MID_1 0x0d4 -#define PLL_FRAC_DIV_START_HIGH_1 0x0d8 -#define PLL_MASH_CONTROL 0x0ec -#define PLL_SSC_MUX_CONTROL 0x108 -#define PLL_SSC_STEPSIZE_LOW_1 0x10c -#define PLL_SSC_STEPSIZE_HIGH_1 0x110 -#define PLL_SSC_DIV_PER_LOW_1 0x114 -#define PLL_SSC_DIV_PER_HIGH_1 0x118 -#define PLL_SSC_DIV_ADJPER_LOW_1 0x11c -#define PLL_SSC_DIV_ADJPER_HIGH_1 0x120 -#define PLL_SSC_CONTROL 0x13c -#define PLL_PLL_OUTDIV_RATE 0x140 -#define PLL_PLL_LOCKDET_RATE_1 0x144 -#define PLL_PLL_PROP_GAIN_RATE_1 0x14c -#define PLL_PLL_BAND_SET_RATE_1 0x154 -#define PLL_PLL_INT_GAIN_IFILT_BAND_1 0x15c -#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x164 -#define PLL_FASTLOCK_EN_BAND 0x16c -#define PLL_FREQ_TUNE_ACCUM_INIT_LOW 0x170 -#define PLL_FREQ_TUNE_ACCUM_INIT_MID 0x174 -#define PLL_FREQ_TUNE_ACCUM_INIT_HIGH 0x178 -#define PLL_FREQ_TUNE_ACCUM_INIT_MUX 0x17c -#define PLL_PLL_LOCK_OVERRIDE 0x180 -#define PLL_PLL_LOCK_DELAY 0x184 -#define PLL_PLL_LOCK_MIN_DELAY 0x188 -#define PLL_CLOCK_INVERTERS 0x18c -#define PLL_SPARE_AND_JPC_OVERRIDES 0x190 -#define PLL_BIAS_CONTROL_1 0x194 -#define PLL_BIAS_CONTROL_2 0x198 -#define PLL_ALOG_OBSV_BUS_CTRL_1 0x19c -#define PLL_COMMON_STATUS_ONE 0x1a0 - -/* Register Offsets from PHY base address */ -#define PHY_CMN_CLK_CFG0 0x010 -#define PHY_CMN_CLK_CFG1 0x014 -#define PHY_CMN_RBUF_CTRL 0x01c -#define PHY_CMN_PLL_CNTRL 0x038 -#define PHY_CMN_CTRL_0 0x024 -#define PHY_CMN_CTRL_2 0x02c - -/* Bit definition of SSC control registers */ -#define SSC_CENTER BIT(0) -#define SSC_EN BIT(1) -#define SSC_FREQ_UPDATE BIT(2) -#define SSC_FREQ_UPDATE_MUX BIT(3) -#define SSC_UPDATE_SSC BIT(4) -#define SSC_UPDATE_SSC_MUX BIT(5) -#define SSC_START BIT(6) -#define SSC_START_MUX BIT(7) - -/* Dynamic Refresh Control Registers */ -#define DSI_DYNAMIC_REFRESH_PLL_CTRL0 (0x014) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL1 (0x018) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL2 (0x01C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL3 (0x020) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL4 (0x024) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL5 (0x028) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL6 (0x02C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL7 (0x030) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL8 (0x034) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL9 (0x038) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL10 (0x03C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL11 (0x040) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL12 (0x044) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL13 (0x048) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL14 (0x04C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL15 (0x050) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL16 (0x054) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL17 (0x058) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL18 (0x05C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL19 (0x060) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL20 (0x064) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL21 (0x068) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL22 (0x06C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL23 (0x070) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL24 (0x074) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL25 (0x078) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL26 (0x07C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL27 (0x080) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL28 (0x084) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL29 (0x088) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL30 (0x08C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL31 (0x090) -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR (0x094) -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2 (0x098) - -#define DSI_PHY_TO_PLL_OFFSET (0x600) -enum { - DSI_PLL_0, - DSI_PLL_1, - DSI_PLL_MAX -}; - -struct dsi_pll_regs { - u32 pll_prop_gain_rate; - u32 pll_lockdet_rate; - u32 decimal_div_start; - u32 frac_div_start_low; - u32 frac_div_start_mid; - u32 frac_div_start_high; - u32 pll_clock_inverters; - u32 ssc_stepsize_low; - u32 ssc_stepsize_high; - u32 ssc_div_per_low; - u32 ssc_div_per_high; - u32 ssc_adjper_low; - u32 ssc_adjper_high; - u32 ssc_control; -}; - -struct dsi_pll_config { - u32 ref_freq; - bool div_override; - u32 output_div; - bool ignore_frac; - bool disable_prescaler; - bool enable_ssc; - bool ssc_center; - u32 dec_bits; - u32 frac_bits; - u32 lock_timer; - u32 ssc_freq; - u32 ssc_offset; - u32 ssc_adj_per; - u32 thresh_cycles; - u32 refclk_cycles; -}; - -struct dsi_pll_10nm { - struct dsi_pll_resource *rsc; - struct dsi_pll_config pll_configuration; - struct dsi_pll_regs reg_setup; -}; - -static inline int pll_reg_read(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - u32 data; - struct dsi_pll_resource *rsc = context; - - data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data | BIT(5)); - ndelay(250); - *val = DSI_PLL_REG_R(rsc->pll_base, reg); - - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data); - - return rc; -} - -static inline int pll_reg_write(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - DSI_PLL_REG_W(rsc->pll_base, reg, val); - - return rc; -} - -static inline int phy_reg_read(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - *val = DSI_PLL_REG_R(rsc->phy_base, reg); - - return rc; -} - -static inline int phy_reg_write(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - DSI_PLL_REG_W(rsc->phy_base, reg, val); - - return rc; -} - -static inline int phy_reg_update_bits_sub(struct dsi_pll_resource *rsc, - unsigned int reg, unsigned int mask, unsigned int val) -{ - u32 reg_val; - - reg_val = DSI_PLL_REG_R(rsc->phy_base, reg); - reg_val &= ~mask; - reg_val |= (val & mask); - DSI_PLL_REG_W(rsc->phy_base, reg, reg_val); - - return 0; -} - -static inline int phy_reg_update_bits(void *context, unsigned int reg, - unsigned int mask, unsigned int val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - rc = phy_reg_update_bits_sub(rsc, reg, mask, val); - if (!rc && rsc->slave) - rc = phy_reg_update_bits_sub(rsc->slave, reg, mask, val); - - return rc; -} - -static inline int pclk_mux_read_sel(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - *val = (DSI_PLL_REG_R(rsc->phy_base, reg) & 0x3); - - return rc; -} - -static inline int pclk_mux_write_sel_sub(struct dsi_pll_resource *rsc, - unsigned int reg, unsigned int val) -{ - u32 reg_val; - - reg_val = DSI_PLL_REG_R(rsc->phy_base, reg); - reg_val &= ~0x03; - reg_val |= val; - - DSI_PLL_REG_W(rsc->phy_base, reg, reg_val); - - return 0; -} - -static inline int pclk_mux_write_sel(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - rc = pclk_mux_write_sel_sub(rsc, reg, val); - if (!rc && rsc->slave) - rc = pclk_mux_write_sel_sub(rsc->slave, reg, val); - - /* - * cache the current parent index for cases where parent - * is not changing but rate is changing. In that case - * clock framework won't call parent_set and hence dsiclk_sel - * bit won't be programmed. e.g. dfps update use case. - */ - rsc->cached_cfg1 = val; - - return rc; -} - -static int dsi_pll_10nm_get_gdsc_status(struct dsi_pll_resource *rsc) -{ - u32 reg = 0; - bool status; - - reg = DSI_PLL_REG_R(rsc->gdsc_base, 0x0); - status = reg & BIT(31); - pr_err("reg:0x%x status:%d\n", reg, status); - - return status; -} - -static struct dsi_pll_resource *pll_rsc_db[DSI_PLL_MAX]; -static struct dsi_pll_10nm plls[DSI_PLL_MAX]; - -static void dsi_pll_config_slave(struct dsi_pll_resource *rsc) -{ - u32 reg; - struct dsi_pll_resource *orsc = pll_rsc_db[DSI_PLL_1]; - - if (!rsc) - return; - - /* Only DSI PLL0 can act as a master */ - if (rsc->index != DSI_PLL_0) - return; - - /* default configuration: source is either internal or ref clock */ - rsc->slave = NULL; - - if (!orsc) { - pr_debug("slave PLL unavilable, assuming standalone config\n"); - return; - } - - /* check to see if the source of DSI1 PLL bitclk is set to external */ - reg = DSI_PLL_REG_R(orsc->phy_base, PHY_CMN_CLK_CFG1); - reg &= (BIT(2) | BIT(3)); - if (reg == 0x04) - rsc->slave = pll_rsc_db[DSI_PLL_1]; /* external source */ - - pr_debug("Slave PLL %s\n", rsc->slave ? "configured" : "absent"); -} - -static void dsi_pll_setup_config(struct dsi_pll_10nm *pll, - struct dsi_pll_resource *rsc) -{ - struct dsi_pll_config *config = &pll->pll_configuration; - - config->ref_freq = 19200000; - config->output_div = 1; - config->dec_bits = 8; - config->frac_bits = 18; - config->lock_timer = 64; - config->ssc_freq = 31500; - config->ssc_offset = 5000; - config->ssc_adj_per = 2; - config->thresh_cycles = 32; - config->refclk_cycles = 256; - - config->div_override = false; - config->ignore_frac = false; - config->disable_prescaler = false; - config->enable_ssc = rsc->ssc_en; - config->ssc_center = rsc->ssc_center; - - if (config->enable_ssc) { - if (rsc->ssc_freq) - config->ssc_freq = rsc->ssc_freq; - if (rsc->ssc_ppm) - config->ssc_offset = rsc->ssc_ppm; - } - - dsi_pll_config_slave(rsc); -} - -static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll, - struct dsi_pll_resource *rsc) -{ - struct dsi_pll_config *config = &pll->pll_configuration; - struct dsi_pll_regs *regs = &pll->reg_setup; - u64 fref = rsc->vco_ref_clk_rate; - u64 pll_freq; - u64 divider; - u64 dec, dec_multiple; - u32 frac; - u64 multiplier; - - pll_freq = rsc->vco_current_rate; - - if (config->disable_prescaler) - divider = fref; - else - divider = fref * 2; - - multiplier = 1 << config->frac_bits; - dec_multiple = div_u64(pll_freq * multiplier, divider); - div_u64_rem(dec_multiple, multiplier, &frac); - - dec = div_u64(dec_multiple, multiplier); - - if (pll_freq <= MHZ_1900) - regs->pll_prop_gain_rate = 8; - else if (pll_freq <= MHZ_3000) - regs->pll_prop_gain_rate = 10; - else - regs->pll_prop_gain_rate = 12; - if (pll_freq < MHZ_1100) - regs->pll_clock_inverters = 8; - else - regs->pll_clock_inverters = 0; - - regs->pll_lockdet_rate = config->lock_timer; - regs->decimal_div_start = dec; - regs->frac_div_start_low = (frac & 0xff); - regs->frac_div_start_mid = (frac & 0xff00) >> 8; - regs->frac_div_start_high = (frac & 0x30000) >> 16; -} - -static void dsi_pll_calc_ssc(struct dsi_pll_10nm *pll, - struct dsi_pll_resource *rsc) -{ - struct dsi_pll_config *config = &pll->pll_configuration; - struct dsi_pll_regs *regs = &pll->reg_setup; - u32 ssc_per; - u32 ssc_mod; - u64 ssc_step_size; - u64 frac; - - if (!config->enable_ssc) { - pr_debug("SSC not enabled\n"); - return; - } - - ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 1; - ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1); - ssc_per -= ssc_mod; - - frac = regs->frac_div_start_low | - (regs->frac_div_start_mid << 8) | - (regs->frac_div_start_high << 16); - ssc_step_size = regs->decimal_div_start; - ssc_step_size *= (1 << config->frac_bits); - ssc_step_size += frac; - ssc_step_size *= config->ssc_offset; - ssc_step_size *= (config->ssc_adj_per + 1); - ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1)); - ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000); - - regs->ssc_div_per_low = ssc_per & 0xFF; - regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8; - regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF); - regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8); - regs->ssc_adjper_low = config->ssc_adj_per & 0xFF; - regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8; - - regs->ssc_control = config->ssc_center ? SSC_CENTER : 0; - - pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n", - regs->decimal_div_start, frac, config->frac_bits); - pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n", - ssc_per, (u32)ssc_step_size, config->ssc_adj_per); -} - -static void dsi_pll_ssc_commit(struct dsi_pll_10nm *pll, - struct dsi_pll_resource *rsc) -{ - void __iomem *pll_base = rsc->pll_base; - struct dsi_pll_regs *regs = &pll->reg_setup; - - if (pll->pll_configuration.enable_ssc) { - pr_debug("SSC is enabled\n"); - - DSI_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_LOW_1, - regs->ssc_stepsize_low); - DSI_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_HIGH_1, - regs->ssc_stepsize_high); - DSI_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_LOW_1, - regs->ssc_div_per_low); - DSI_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_HIGH_1, - regs->ssc_div_per_high); - DSI_PLL_REG_W(pll_base, PLL_SSC_DIV_ADJPER_LOW_1, - regs->ssc_adjper_low); - DSI_PLL_REG_W(pll_base, PLL_SSC_DIV_ADJPER_HIGH_1, - regs->ssc_adjper_high); - DSI_PLL_REG_W(pll_base, PLL_SSC_CONTROL, - SSC_EN | regs->ssc_control); - } -} - -static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll, - struct dsi_pll_resource *rsc) -{ - void __iomem *pll_base = rsc->pll_base; - - DSI_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_ONE, 0x80); - DSI_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_TWO, 0x03); - DSI_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_THREE, 0x00); - DSI_PLL_REG_W(pll_base, PLL_DSM_DIVIDER, 0x00); - DSI_PLL_REG_W(pll_base, PLL_FEEDBACK_DIVIDER, 0x4e); - DSI_PLL_REG_W(pll_base, PLL_CALIBRATION_SETTINGS, 0x40); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba); - DSI_PLL_REG_W(pll_base, PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c); - DSI_PLL_REG_W(pll_base, PLL_OUTDIV, 0x00); - DSI_PLL_REG_W(pll_base, PLL_CORE_OVERRIDE, 0x00); - DSI_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS_TWO, 0x08); - DSI_PLL_REG_W(pll_base, PLL_PLL_PROP_GAIN_RATE_1, 0x08); - DSI_PLL_REG_W(pll_base, PLL_PLL_BAND_SET_RATE_1, 0xc0); - DSI_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0xfa); - DSI_PLL_REG_W(pll_base, PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c); - DSI_PLL_REG_W(pll_base, PLL_PLL_LOCK_OVERRIDE, 0x80); - DSI_PLL_REG_W(pll_base, PLL_PFILT, 0x29); - DSI_PLL_REG_W(pll_base, PLL_IFILT, 0x3f); -} - -static void dsi_pll_init_val(struct dsi_pll_resource *rsc) -{ - void __iomem *pll_base = rsc->pll_base; - - DSI_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x10); - DSI_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS, 0x3f); - DSI_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS_TWO, 0x0); - DSI_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FOUR, 0x0); - DSI_PLL_REG_W(pll_base, PLL_INT_LOOP_CONTROLS, 0x80); - DSI_PLL_REG_W(pll_base, PLL_FREQ_UPDATE_CONTROL_OVERRIDES, 0x0); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_LOW, 0x0); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_HIGH, 0x02); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS, 0x82); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_MIN, 0x00); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_MAX, 0xff); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_PFILT, 0x00); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_IFILT, 0x00); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_TWO, 0x25); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_FOUR, 0x4f); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_HIGH, 0x0a); - DSI_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_LOW, 0x0); - DSI_PLL_REG_W(pll_base, PLL_GAIN, 0x42); - DSI_PLL_REG_W(pll_base, PLL_ICODE_LOW, 0x00); - DSI_PLL_REG_W(pll_base, PLL_ICODE_HIGH, 0x00); - DSI_PLL_REG_W(pll_base, PLL_LOCKDET, 0x30); - DSI_PLL_REG_W(pll_base, PLL_FASTLOCK_CONTROL, 0x04); - DSI_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_ONE, 0x00); - DSI_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_TWO, 0x00); - DSI_PLL_REG_W(pll_base, PLL_RATE_CHANGE, 0x01); - DSI_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS, 0x08); - DSI_PLL_REG_W(pll_base, PLL_DEC_FRAC_MUXES, 0x00); - DSI_PLL_REG_W(pll_base, PLL_MASH_CONTROL, 0x03); - DSI_PLL_REG_W(pll_base, PLL_SSC_MUX_CONTROL, 0x0); - DSI_PLL_REG_W(pll_base, PLL_SSC_CONTROL, 0x0); - DSI_PLL_REG_W(pll_base, PLL_FASTLOCK_EN_BAND, 0x03); - DSI_PLL_REG_W(pll_base, PLL_FREQ_TUNE_ACCUM_INIT_MUX, 0x0); - DSI_PLL_REG_W(pll_base, PLL_PLL_LOCK_MIN_DELAY, 0x19); - DSI_PLL_REG_W(pll_base, PLL_SPARE_AND_JPC_OVERRIDES, 0x0); - DSI_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_1, 0x40); - DSI_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_2, 0x20); - DSI_PLL_REG_W(pll_base, PLL_ALOG_OBSV_BUS_CTRL_1, 0x0); -} - -static void dsi_pll_commit(struct dsi_pll_10nm *pll, - struct dsi_pll_resource *rsc) -{ - void __iomem *pll_base = rsc->pll_base; - struct dsi_pll_regs *reg = &pll->reg_setup; - - DSI_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x12); - DSI_PLL_REG_W(pll_base, PLL_DECIMAL_DIV_START_1, - reg->decimal_div_start); - DSI_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_LOW_1, - reg->frac_div_start_low); - DSI_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_MID_1, - reg->frac_div_start_mid); - DSI_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_HIGH_1, - reg->frac_div_start_high); - DSI_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0x40); - DSI_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x06); - DSI_PLL_REG_W(pll_base, PLL_CMODE, 0x10); - DSI_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS, reg->pll_clock_inverters); - -} - -static int vco_10nm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *rsc = vco->priv; - struct dsi_pll_10nm *pll; - - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - if (rsc->pll_on) - return 0; - - pll = rsc->priv; - if (!pll) { - pr_err("pll configuration not found\n"); - return -EINVAL; - } - - pr_debug("ndx=%d, rate=%lu\n", rsc->index, rate); - - rsc->vco_current_rate = rate; - rsc->vco_ref_clk_rate = vco->ref_clk_rate; - rsc->dfps_trigger = false; - - dsi_pll_init_val(rsc); - - dsi_pll_setup_config(pll, rsc); - - dsi_pll_calc_dec_frac(pll, rsc); - - dsi_pll_calc_ssc(pll, rsc); - - dsi_pll_commit(pll, rsc); - - dsi_pll_config_hzindep_reg(pll, rsc); - - dsi_pll_ssc_commit(pll, rsc); - - /* flush, ensure all register writes are done*/ - wmb(); - - return 0; -} - -static int dsi_pll_read_stored_trim_codes(struct dsi_pll_resource *pll_res, - unsigned long vco_clk_rate) -{ - int i; - bool found = false; - - if (!pll_res->dfps) - return -EINVAL; - - for (i = 0; i < pll_res->dfps->vco_rate_cnt; i++) { - struct dfps_codes_info *codes_info = - &pll_res->dfps->codes_dfps[i]; - - pr_debug("valid=%d vco_rate=%d, code %d %d %d\n", - codes_info->is_valid, codes_info->clk_rate, - codes_info->pll_codes.pll_codes_1, - codes_info->pll_codes.pll_codes_2, - codes_info->pll_codes.pll_codes_3); - - if (vco_clk_rate != codes_info->clk_rate && - codes_info->is_valid) - continue; - - pll_res->cache_pll_trim_codes[0] = - codes_info->pll_codes.pll_codes_1; - pll_res->cache_pll_trim_codes[1] = - codes_info->pll_codes.pll_codes_2; - pll_res->cache_pll_trim_codes[2] = - codes_info->pll_codes.pll_codes_3; - found = true; - break; - } - - if (!found) - return -EINVAL; - - pr_debug("trim_code_0=0x%x trim_code_1=0x%x trim_code_2=0x%x\n", - pll_res->cache_pll_trim_codes[0], - pll_res->cache_pll_trim_codes[1], - pll_res->cache_pll_trim_codes[2]); - - return 0; -} - -static void shadow_dsi_pll_dynamic_refresh_10nm(struct dsi_pll_10nm *pll, - struct dsi_pll_resource *rsc) -{ - u32 data; - u32 offset = DSI_PHY_TO_PLL_OFFSET; - u32 upper_addr = 0; - struct dsi_pll_regs *reg = &pll->reg_setup; - - data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); - data &= ~BIT(5); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL0, - PHY_CMN_CLK_CFG1, PHY_CMN_PLL_CNTRL, data, 0); - upper_addr |= (upper_8_bit(PHY_CMN_CLK_CFG1) << 0); - upper_addr |= (upper_8_bit(PHY_CMN_PLL_CNTRL) << 1); - - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL1, - PHY_CMN_RBUF_CTRL, - (PLL_DECIMAL_DIV_START_1 + offset), - 0, reg->decimal_div_start); - upper_addr |= (upper_8_bit(PHY_CMN_RBUF_CTRL) << 2); - upper_addr |= (upper_8_bit(PLL_DECIMAL_DIV_START_1 + offset) << 3); - - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL2, - (PLL_FRAC_DIV_START_LOW_1 + offset), - (PLL_FRAC_DIV_START_MID_1 + offset), - reg->frac_div_start_low, reg->frac_div_start_mid); - upper_addr |= (upper_8_bit(PLL_FRAC_DIV_START_LOW_1 + offset) << 4); - upper_addr |= (upper_8_bit(PLL_FRAC_DIV_START_MID_1 + offset) << 5); - - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL3, - (PLL_FRAC_DIV_START_HIGH_1 + offset), - (PLL_PLL_PROP_GAIN_RATE_1 + offset), - reg->frac_div_start_high, reg->pll_prop_gain_rate); - upper_addr |= (upper_8_bit(PLL_FRAC_DIV_START_HIGH_1 + offset) << 6); - upper_addr |= (upper_8_bit(PLL_PLL_PROP_GAIN_RATE_1 + offset) << 7); - - data = DSI_PLL_REG_R(rsc->pll_base, PLL_PLL_OUTDIV_RATE) & 0x03; - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL4, - (PLL_PLL_OUTDIV_RATE + offset), - (PLL_FREQ_TUNE_ACCUM_INIT_LOW + offset), - data, 0); - upper_addr |= (upper_8_bit(PLL_PLL_OUTDIV_RATE + offset) << 8); - upper_addr |= (upper_8_bit(PLL_FREQ_TUNE_ACCUM_INIT_LOW + offset) << 9); - - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL5, - (PLL_FREQ_TUNE_ACCUM_INIT_MID + offset), - (PLL_FREQ_TUNE_ACCUM_INIT_HIGH + offset), - rsc->cache_pll_trim_codes[1], - rsc->cache_pll_trim_codes[0]); - upper_addr |= - (upper_8_bit(PLL_FREQ_TUNE_ACCUM_INIT_MID + offset) << 10); - upper_addr |= - (upper_8_bit(PLL_FREQ_TUNE_ACCUM_INIT_HIGH + offset) << 11); - - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL6, - (PLL_FREQ_TUNE_ACCUM_INIT_MUX + offset), - (PLL_PLL_BAND_SET_RATE_1 + offset), - 0x07, rsc->cache_pll_trim_codes[2]); - upper_addr |= - (upper_8_bit(PLL_FREQ_TUNE_ACCUM_INIT_MUX + offset) << 12); - upper_addr |= (upper_8_bit(PLL_PLL_BAND_SET_RATE_1 + offset) << 13); - - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL7, - (PLL_CALIBRATION_SETTINGS + offset), - (PLL_BAND_SEL_CAL_SETTINGS + offset), 0x44, 0x3a); - upper_addr |= (upper_8_bit(PLL_CALIBRATION_SETTINGS + offset) << 14); - upper_addr |= (upper_8_bit(PLL_BAND_SEL_CAL_SETTINGS + offset) << 15); - - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL8, - (PLL_PLL_LOCKDET_RATE_1 + offset), - (PLL_PLL_LOCK_DELAY + offset), 0x10, 0x06); - upper_addr |= (upper_8_bit(PLL_PLL_LOCKDET_RATE_1 + offset) << 16); - upper_addr |= (upper_8_bit(PLL_PLL_LOCK_DELAY + offset) << 17); - - data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG0); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL17, - PHY_CMN_CTRL_2, PHY_CMN_CLK_CFG0, 0x40, data); - if (rsc->slave) - DSI_DYN_PLL_REG_W(rsc->slave->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL10, - PHY_CMN_CLK_CFG0, PHY_CMN_CTRL_0, - data, 0x7f); - - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL18, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - /* Dummy register writes */ - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL19, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL20, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL21, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL22, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL23, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL24, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL25, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL26, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL27, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL28, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL29, - PHY_CMN_PLL_CNTRL, PHY_CMN_PLL_CNTRL, 0x01, 0x01); - - /* Registers to configure after PLL enable delay */ - data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1) | BIT(5); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL30, - PHY_CMN_CLK_CFG1, PHY_CMN_RBUF_CTRL, data, 0x01); - DSI_DYN_PLL_REG_W(rsc->dyn_pll_base, DSI_DYNAMIC_REFRESH_PLL_CTRL31, - PHY_CMN_CLK_CFG1, PHY_CMN_CLK_CFG1, data, data); - if (rsc->slave) { - data = DSI_PLL_REG_R(rsc->slave->phy_base, PHY_CMN_CLK_CFG1) | - BIT(5); - DSI_DYN_PLL_REG_W(rsc->slave->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL30, - PHY_CMN_CLK_CFG1, PHY_CMN_RBUF_CTRL, - data, 0x01); - DSI_DYN_PLL_REG_W(rsc->slave->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL31, - PHY_CMN_CLK_CFG1, PHY_CMN_CLK_CFG1, - data, data); - } - - DSI_PLL_REG_W(rsc->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR, upper_addr); - DSI_PLL_REG_W(rsc->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2, 0); - wmb(); /* commit register writes */ -} - -static int shadow_vco_10nm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int rc; - struct dsi_pll_10nm *pll; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *rsc = vco->priv; - - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - pll = rsc->priv; - if (!pll) { - pr_err("pll configuration not found\n"); - return -EINVAL; - } - - rc = dsi_pll_read_stored_trim_codes(rsc, rate); - if (rc) { - pr_err("cannot find pll codes rate=%ld\n", rate); - return -EINVAL; - } - pr_debug("ndx=%d, rate=%lu\n", rsc->index, rate); - - rsc->vco_current_rate = rate; - rsc->vco_ref_clk_rate = vco->ref_clk_rate; - - dsi_pll_setup_config(pll, rsc); - - dsi_pll_calc_dec_frac(pll, rsc); - - /* program dynamic refresh control registers */ - shadow_dsi_pll_dynamic_refresh_10nm(pll, rsc); - - /* update cached vco rate */ - rsc->vco_cached_rate = rate; - rsc->dfps_trigger = true; - - return 0; -} - -static int dsi_pll_10nm_lock_status(struct dsi_pll_resource *pll) -{ - int rc; - u32 status; - u32 const delay_us = 100; - u32 const timeout_us = 5000; - - rc = readl_poll_timeout_atomic(pll->pll_base + PLL_COMMON_STATUS_ONE, - status, - ((status & BIT(0)) > 0), - delay_us, - timeout_us); - if (rc) - pr_err("DSI PLL(%d) lock failed, status=0x%08x\n", - pll->index, status); - - return rc; -} - -static void dsi_pll_disable_pll_bias(struct dsi_pll_resource *rsc) -{ - u32 data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - - DSI_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0); - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5)); - ndelay(250); -} - -static void dsi_pll_enable_pll_bias(struct dsi_pll_resource *rsc) -{ - u32 data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data | BIT(5)); - DSI_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0xc0); - ndelay(250); -} - -static void dsi_pll_disable_global_clk(struct dsi_pll_resource *rsc) -{ - u32 data; - - data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data & ~BIT(5))); -} - -static void dsi_pll_enable_global_clk(struct dsi_pll_resource *rsc) -{ - u32 data; - - data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data | BIT(5))); -} - -static int dsi_pll_enable(struct dsi_pll_vco_clk *vco) -{ - int rc; - struct dsi_pll_resource *rsc = vco->priv; - - dsi_pll_enable_pll_bias(rsc); - if (rsc->slave) - dsi_pll_enable_pll_bias(rsc->slave); - - phy_reg_update_bits_sub(rsc, PHY_CMN_CLK_CFG1, 0x03, rsc->cached_cfg1); - if (rsc->slave) - phy_reg_update_bits_sub(rsc->slave, PHY_CMN_CLK_CFG1, - 0x03, rsc->slave->cached_cfg1); - wmb(); /* ensure dsiclk_sel is always programmed before pll start */ - - /* Start PLL */ - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0x01); - - /* - * ensure all PLL configurations are written prior to checking - * for PLL lock. - */ - wmb(); - - /* Check for PLL lock */ - rc = dsi_pll_10nm_lock_status(rsc); - if (rc) { - pr_err("PLL(%d) lock failed\n", rsc->index); - goto error; - } - - rsc->pll_on = true; - - dsi_pll_enable_global_clk(rsc); - if (rsc->slave) - dsi_pll_enable_global_clk(rsc->slave); - - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0x01); - if (rsc->slave) - DSI_PLL_REG_W(rsc->slave->phy_base, PHY_CMN_RBUF_CTRL, 0x01); - -error: - return rc; -} - -static void dsi_pll_disable_sub(struct dsi_pll_resource *rsc) -{ - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0); - dsi_pll_disable_pll_bias(rsc); -} - -static void dsi_pll_disable(struct dsi_pll_vco_clk *vco) -{ - struct dsi_pll_resource *rsc = vco->priv; - - if (!rsc->pll_on) { - pr_err("failed to enable pll (%d) resources\n", rsc->index); - return; - } - - rsc->handoff_resources = false; - rsc->dfps_trigger = false; - - pr_debug("stop PLL (%d)\n", rsc->index); - - /* - * To avoid any stray glitches while - * abruptly powering down the PLL - * make sure to gate the clock using - * the clock enable bit before powering - * down the PLL - */ - dsi_pll_disable_global_clk(rsc); - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0); - dsi_pll_disable_sub(rsc); - if (rsc->slave) { - dsi_pll_disable_global_clk(rsc->slave); - dsi_pll_disable_sub(rsc->slave); - } - /* flush, ensure all register writes are done*/ - wmb(); - rsc->pll_on = false; -} - -long vco_10nm_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - *parent_rate = rrate; - - return rrate; -} - -static void vco_10nm_unprepare(struct clk_hw *hw) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *pll = vco->priv; - - if (!pll) { - pr_err("dsi pll resources not available\n"); - return; - } - - /* - * During unprepare in continuous splash use case we want driver - * to pick all dividers instead of retaining bootloader configurations. - * Also handle use cases where dynamic refresh triggered before - * first suspend/resume. - */ - if (!pll->handoff_resources || pll->dfps_trigger) { - pll->cached_cfg0 = DSI_PLL_REG_R(pll->phy_base, - PHY_CMN_CLK_CFG0); - pll->cached_outdiv = DSI_PLL_REG_R(pll->pll_base, - PLL_PLL_OUTDIV_RATE); - pr_debug("cfg0=%d,cfg1=%d, outdiv=%d\n", pll->cached_cfg0, - pll->cached_cfg1, pll->cached_outdiv); - - pll->vco_cached_rate = clk_get_rate(hw->clk); - } - - /* - * When continuous splash screen feature is enabled, we need to cache - * the mux configuration for the pixel_clk_src mux clock. The clock - * framework does not call back to re-configure the mux value if it is - * does not change.For such usecases, we need to ensure that the cached - * value is programmed prior to PLL being locked - */ - if (pll->handoff_resources) { - pll->cached_cfg1 = DSI_PLL_REG_R(pll->phy_base, - PHY_CMN_CLK_CFG1); - if (pll->slave) - pll->slave->cached_cfg1 = - DSI_PLL_REG_R(pll->slave->phy_base, - PHY_CMN_CLK_CFG1); - } - - dsi_pll_disable(vco); -} - -static int vco_10nm_prepare(struct clk_hw *hw) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *pll = vco->priv; - - if (!pll) { - pr_err("dsi pll resources are not available\n"); - return -EINVAL; - } - - /* Skip vco recalculation for continuous splash use case */ - if (pll->handoff_resources) { - pll->pll_on = true; - return 0; - } - - if ((pll->vco_cached_rate != 0) && - (pll->vco_cached_rate == clk_hw_get_rate(hw))) { - rc = vco_10nm_set_rate(hw, pll->vco_cached_rate, - pll->vco_cached_rate); - if (rc) { - pr_err("pll(%d) set_rate failed, rc=%d\n", - pll->index, rc); - return rc; - } - pr_debug("cfg0=%d, cfg1=%d\n", pll->cached_cfg0, - pll->cached_cfg1); - DSI_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, - pll->cached_cfg0); - if (pll->slave) - DSI_PLL_REG_W(pll->slave->phy_base, PHY_CMN_CLK_CFG0, - pll->cached_cfg0); - DSI_PLL_REG_W(pll->pll_base, PLL_PLL_OUTDIV_RATE, - pll->cached_outdiv); - } - rc = dsi_pll_enable(vco); - - return rc; -} - -static unsigned long vco_10nm_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *pll = vco->priv; - int rc = 0; - - if (!vco->priv) - pr_err("vco priv is null\n"); - - if (!pll) { - pr_err("pll is null\n"); - return 0; - } - - /* - * In the case when vco rate is set, the recalculation function should - * return the current rate as to avoid trying to set the vco rate - * again. However durng handoff, recalculation should set the flag - * according to the status of PLL. - */ - if (pll->vco_current_rate != 0) { - pr_debug("returning vco rate = %lld\n", pll->vco_current_rate); - return pll->vco_current_rate; - } - - pll->handoff_resources = true; - - if (!dsi_pll_10nm_get_gdsc_status(pll)) { - pll->handoff_resources = false; - pr_err("Hand_off_resources not needed since gdsc is off\n"); - return 0; - } - - if (dsi_pll_10nm_lock_status(pll)) { - pll->handoff_resources = false; - pr_err("PLL not enabled\n"); - } - - return rc; -} - -static int pixel_clk_get_div(void *context, unsigned int reg, unsigned int *div) -{ - struct dsi_pll_resource *pll = context; - u32 reg_val; - - reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - *div = (reg_val & 0xF0) >> 4; - - /** - * Common clock framework the divider value is interpreted as one less - * hence we return one less for all dividers except when zero - */ - if (*div != 0) - *div -= 1; - - return 0; -} - -static void pixel_clk_set_div_sub(struct dsi_pll_resource *pll, int div) -{ - u32 reg_val; - - reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - reg_val &= ~0xF0; - reg_val |= (div << 4); - DSI_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, reg_val); - - /* - * cache the current parent index for cases where parent - * is not changing but rate is changing. In that case - * clock framework won't call parent_set and hence dsiclk_sel - * bit won't be programmed. e.g. dfps update use case. - */ - pll->cached_cfg0 = reg_val; -} - -static int pixel_clk_set_div(void *context, unsigned int reg, unsigned int div) -{ - struct dsi_pll_resource *pll = context; - - /** - * In common clock framework the divider value provided is one less and - * and hence adjusting the divider value by one prior to writing it to - * hardware - */ - div++; - pixel_clk_set_div_sub(pll, div); - if (pll->slave) - pixel_clk_set_div_sub(pll->slave, div); - - return 0; -} - -static int bit_clk_get_div(void *context, unsigned int reg, unsigned int *div) -{ - struct dsi_pll_resource *pll = context; - u32 reg_val; - - reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - *div = (reg_val & 0x0F); - - /** - *Common clock framework the divider value is interpreted as one less - * hence we return one less for all dividers except when zero - */ - if (*div != 0) - *div -= 1; - - return 0; -} - -static void bit_clk_set_div_sub(struct dsi_pll_resource *rsc, int div) -{ - u32 reg_val; - - reg_val = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG0); - reg_val &= ~0x0F; - reg_val |= div; - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG0, reg_val); -} - -static int bit_clk_set_div(void *context, unsigned int reg, unsigned int div) -{ - struct dsi_pll_resource *rsc = context; - - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - /** - * In common clock framework the divider value provided is one less and - * and hence adjusting the divider value by one prior to writing it to - * hardware - */ - div++; - - bit_clk_set_div_sub(rsc, div); - /* For slave PLL, this divider always should be set to 1 */ - if (rsc->slave) - bit_clk_set_div_sub(rsc->slave, 1); - - return 0; -} - -static struct regmap_config dsi_pll_10nm_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x7c0, -}; - -static struct regmap_bus pll_regmap_bus = { - .reg_write = pll_reg_write, - .reg_read = pll_reg_read, -}; - -static struct regmap_bus pclk_src_mux_regmap_bus = { - .reg_read = pclk_mux_read_sel, - .reg_write = pclk_mux_write_sel, -}; - -static struct regmap_bus pclk_src_regmap_bus = { - .reg_write = pixel_clk_set_div, - .reg_read = pixel_clk_get_div, -}; - -static struct regmap_bus bitclk_src_regmap_bus = { - .reg_write = bit_clk_set_div, - .reg_read = bit_clk_get_div, -}; - -static const struct clk_ops clk_ops_vco_10nm = { - .recalc_rate = vco_10nm_recalc_rate, - .set_rate = vco_10nm_set_rate, - .round_rate = vco_10nm_round_rate, - .prepare = vco_10nm_prepare, - .unprepare = vco_10nm_unprepare, -}; - -static const struct clk_ops clk_ops_shadow_vco_10nm = { - .recalc_rate = vco_10nm_recalc_rate, - .set_rate = shadow_vco_10nm_set_rate, - .round_rate = vco_10nm_round_rate, -}; - -static struct regmap_bus dsi_mux_regmap_bus = { - .reg_write = dsi_set_mux_sel, - .reg_read = dsi_get_mux_sel, -}; - -/* - * Clock tree for generating DSI byte and pixel clocks. - * - * - * +---------------+ - * | vco_clk | - * +-------+-------+ - * | - * | - * +---------------+ - * | pll_out_div | - * | DIV(1,2,4,8) | - * +-------+-------+ - * | - * +-----------------------------+--------+ - * | | | - * +-------v-------+ | | - * | bitclk_src | | | - * | DIV(1..15) | | | - * +-------+-------+ | | - * | | | - * +----------+---------+ | | - * Shadow Path | | | | | - * + +-------v-------+ | +------v------+ | +------v-------+ - * | | byteclk_src | | |post_bit_div | | |post_vco_div | - * | | DIV(8) | | |DIV (2) | | |DIV(4) | - * | +-------+-------+ | +------+------+ | +------+-------+ - * | | | | | | | - * | | | +------+ | | - * | | +-------------+ | | +----+ - * | +--------+ | | | | - * | | +-v--v-v---v------+ - * +-v---------v----+ \ pclk_src_mux / - * \ byteclk_mux / \ / - * \ / +-----+-----+ - * +----+-----+ | Shadow Path - * | | + - * v +-----v------+ | - * dsi_byte_clk | pclk_src | | - * | DIV(1..15) | | - * +-----+------+ | - * | | - * | | - * +--------+ | - * | | - * +---v----v----+ - * \ pclk_mux / - * \ / - * +---+---+ - * | - * | - * v - * dsi_pclk - * - */ - -static struct dsi_pll_vco_clk dsi0pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_10nm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct dsi_pll_vco_clk dsi0pll_shadow_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_shadow_vco_10nm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_10nm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_shadow_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_shadow_vco_10nm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct clk_regmap_div dsi0pll_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pll_out_div", - .parent_names = (const char *[]){"dsi0pll_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_shadow_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_pll_out_div", - .parent_names = (const char *[]){ - "dsi0pll_shadow_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pll_out_div", - .parent_names = (const char *[]){"dsi1pll_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_shadow_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_pll_out_div", - .parent_names = (const char *[]){ - "dsi1pll_shadow_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_bitclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_bitclk_src", - .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_shadow_bitclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_bitclk_src", - .parent_names = (const char *[]){ - "dsi0pll_shadow_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_bitclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_bitclk_src", - .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_shadow_bitclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_bitclk_src", - .parent_names = (const char *[]){ - "dsi1pll_shadow_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_fixed_factor dsi0pll_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_vco_div", - .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_post_vco_div", - .parent_names = (const char *[]){"dsi0pll_shadow_pll_out_div"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_vco_div", - .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_post_vco_div", - .parent_names = (const char *[]){"dsi1pll_shadow_pll_out_div"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_byteclk_src", - .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_byteclk_src", - .parent_names = (const char *[]){"dsi0pll_shadow_bitclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_byteclk_src", - .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_byteclk_src", - .parent_names = (const char *[]){"dsi1pll_shadow_bitclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_bit_div", - .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_post_bit_div", - .parent_names = (const char *[]){"dsi0pll_shadow_bitclk_src"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_bit_div", - .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_post_bit_div", - .parent_names = (const char *[]){"dsi1pll_shadow_bitclk_src"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_regmap_mux dsi0pll_byteclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_byteclk", - .parent_names = (const char *[]){"dsi0pll_byteclk_src", - "dsi0pll_shadow_byteclk_src"}, - .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | - CLK_SET_RATE_NO_REPARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_byteclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1_phy_pll_out_byteclk", - .parent_names = (const char *[]){"dsi1pll_byteclk_src", - "dsi1pll_shadow_byteclk_src"}, - .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | - CLK_SET_RATE_NO_REPARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src_mux", - .parent_names = (const char *[]){"dsi0pll_bitclk_src", - "dsi0pll_post_bit_div", - "dsi0pll_pll_out_div", - "dsi0pll_post_vco_div"}, - .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_shadow_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_pclk_src_mux", - .parent_names = (const char *[]){ - "dsi0pll_shadow_bitclk_src", - "dsi0pll_shadow_post_bit_div", - "dsi0pll_shadow_pll_out_div", - "dsi0pll_shadow_post_vco_div"}, - .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src_mux", - .parent_names = (const char *[]){"dsi1pll_bitclk_src", - "dsi1pll_post_bit_div", - "dsi1pll_pll_out_div", - "dsi1pll_post_vco_div"}, - .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_shadow_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_pclk_src_mux", - .parent_names = (const char *[]){ - "dsi1pll_shadow_bitclk_src", - "dsi1pll_shadow_post_bit_div", - "dsi1pll_shadow_pll_out_div", - "dsi1pll_shadow_post_vco_div"}, - .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_pclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src", - .parent_names = (const char *[]){ - "dsi0pll_pclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_shadow_pclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_pclk_src", - .parent_names = (const char *[]){ - "dsi0pll_shadow_pclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_pclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src", - .parent_names = (const char *[]){ - "dsi1pll_pclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_shadow_pclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_pclk_src", - .parent_names = (const char *[]){ - "dsi1pll_shadow_pclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_pclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_dsiclk", - .parent_names = (const char *[]){"dsi0pll_pclk_src", - "dsi0pll_shadow_pclk_src"}, - .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | - CLK_SET_RATE_NO_REPARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_pclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1_phy_pll_out_dsiclk", - .parent_names = (const char *[]){"dsi1pll_pclk_src", - "dsi1pll_shadow_pclk_src"}, - .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | - CLK_SET_RATE_NO_REPARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_hw *dsi_pllcc_10nm[] = { - [VCO_CLK_0] = &dsi0pll_vco_clk.hw, - [PLL_OUT_DIV_0_CLK] = &dsi0pll_pll_out_div.clkr.hw, - [BITCLK_SRC_0_CLK] = &dsi0pll_bitclk_src.clkr.hw, - [BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw, - [POST_BIT_DIV_0_CLK] = &dsi0pll_post_bit_div.hw, - [POST_VCO_DIV_0_CLK] = &dsi0pll_post_vco_div.hw, - [BYTECLK_MUX_0_CLK] = &dsi0pll_byteclk_mux.clkr.hw, - [PCLK_SRC_MUX_0_CLK] = &dsi0pll_pclk_src_mux.clkr.hw, - [PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw, - [PCLK_MUX_0_CLK] = &dsi0pll_pclk_mux.clkr.hw, - [SHADOW_VCO_CLK_0] = &dsi0pll_shadow_vco_clk.hw, - [SHADOW_PLL_OUT_DIV_0_CLK] = &dsi0pll_shadow_pll_out_div.clkr.hw, - [SHADOW_BITCLK_SRC_0_CLK] = &dsi0pll_shadow_bitclk_src.clkr.hw, - [SHADOW_BYTECLK_SRC_0_CLK] = &dsi0pll_shadow_byteclk_src.hw, - [SHADOW_POST_BIT_DIV_0_CLK] = &dsi0pll_shadow_post_bit_div.hw, - [SHADOW_POST_VCO_DIV_0_CLK] = &dsi0pll_shadow_post_vco_div.hw, - [SHADOW_PCLK_SRC_MUX_0_CLK] = &dsi0pll_shadow_pclk_src_mux.clkr.hw, - [SHADOW_PCLK_SRC_0_CLK] = &dsi0pll_shadow_pclk_src.clkr.hw, - [VCO_CLK_1] = &dsi1pll_vco_clk.hw, - [PLL_OUT_DIV_1_CLK] = &dsi1pll_pll_out_div.clkr.hw, - [BITCLK_SRC_1_CLK] = &dsi1pll_bitclk_src.clkr.hw, - [BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw, - [POST_BIT_DIV_1_CLK] = &dsi1pll_post_bit_div.hw, - [POST_VCO_DIV_1_CLK] = &dsi1pll_post_vco_div.hw, - [BYTECLK_MUX_1_CLK] = &dsi1pll_byteclk_mux.clkr.hw, - [PCLK_SRC_MUX_1_CLK] = &dsi1pll_pclk_src_mux.clkr.hw, - [PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw, - [PCLK_MUX_1_CLK] = &dsi1pll_pclk_mux.clkr.hw, - [SHADOW_VCO_CLK_1] = &dsi1pll_shadow_vco_clk.hw, - [SHADOW_PLL_OUT_DIV_1_CLK] = &dsi1pll_shadow_pll_out_div.clkr.hw, - [SHADOW_BITCLK_SRC_1_CLK] = &dsi1pll_shadow_bitclk_src.clkr.hw, - [SHADOW_BYTECLK_SRC_1_CLK] = &dsi1pll_shadow_byteclk_src.hw, - [SHADOW_POST_BIT_DIV_1_CLK] = &dsi1pll_shadow_post_bit_div.hw, - [SHADOW_POST_VCO_DIV_1_CLK] = &dsi1pll_shadow_post_vco_div.hw, - [SHADOW_PCLK_SRC_MUX_1_CLK] = &dsi1pll_shadow_pclk_src_mux.clkr.hw, - [SHADOW_PCLK_SRC_1_CLK] = &dsi1pll_shadow_pclk_src.clkr.hw, -}; - -int dsi_pll_clock_register_10nm(struct platform_device *pdev, - struct dsi_pll_resource *pll_res) -{ - int rc = 0, ndx, i; - struct clk *clk; - struct clk_onecell_data *clk_data; - int num_clks = ARRAY_SIZE(dsi_pllcc_10nm); - struct regmap *rmap; - struct regmap_config *rmap_config; - - ndx = pll_res->index; - - if (ndx >= DSI_PLL_MAX) { - pr_err("pll index(%d) NOT supported\n", ndx); - return -EINVAL; - } - - pll_rsc_db[ndx] = pll_res; - plls[ndx].rsc = pll_res; - pll_res->priv = &plls[ndx]; - pll_res->vco_delay = VCO_DELAY_USEC; - - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kcalloc(&pdev->dev, num_clks, - sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - - clk_data->clk_num = num_clks; - - rmap_config = devm_kmemdup(&pdev->dev, &dsi_pll_10nm_config, - sizeof(struct regmap_config), GFP_KERNEL); - if (!rmap_config) - return -ENOMEM; - - /* Establish client data */ - if (ndx == 0) { - rmap_config->name = "pll_out"; - rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus, - pll_res, rmap_config); - dsi0pll_pll_out_div.clkr.regmap = rmap; - dsi0pll_shadow_pll_out_div.clkr.regmap = rmap; - - rmap_config->name = "bitclk_src"; - rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus, - pll_res, rmap_config); - dsi0pll_bitclk_src.clkr.regmap = rmap; - dsi0pll_shadow_bitclk_src.clkr.regmap = rmap; - - rmap_config->name = "pclk_src"; - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, rmap_config); - dsi0pll_pclk_src.clkr.regmap = rmap; - dsi0pll_shadow_pclk_src.clkr.regmap = rmap; - - rmap_config->name = "pclk_mux"; - rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, rmap_config); - dsi0pll_pclk_mux.clkr.regmap = rmap; - - rmap_config->name = "pclk_src_mux"; - rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, - pll_res, rmap_config); - dsi0pll_pclk_src_mux.clkr.regmap = rmap; - dsi0pll_shadow_pclk_src_mux.clkr.regmap = rmap; - - rmap_config->name = "byteclk_mux"; - rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, rmap_config); - dsi0pll_byteclk_mux.clkr.regmap = rmap; - - dsi0pll_vco_clk.priv = pll_res; - dsi0pll_shadow_vco_clk.priv = pll_res; - - for (i = VCO_CLK_0; i <= SHADOW_PCLK_SRC_0_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - dsi_pllcc_10nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - } else { - rmap_config->name = "pll_out"; - rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus, - pll_res, rmap_config); - dsi1pll_pll_out_div.clkr.regmap = rmap; - dsi1pll_shadow_pll_out_div.clkr.regmap = rmap; - - rmap_config->name = "bitclk_src"; - rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus, - pll_res, rmap_config); - dsi1pll_bitclk_src.clkr.regmap = rmap; - dsi1pll_shadow_bitclk_src.clkr.regmap = rmap; - - rmap_config->name = "pclk_src"; - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, rmap_config); - dsi1pll_pclk_src.clkr.regmap = rmap; - dsi1pll_shadow_pclk_src.clkr.regmap = rmap; - - rmap_config->name = "pclk_mux"; - rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, rmap_config); - dsi1pll_pclk_mux.clkr.regmap = rmap; - - rmap_config->name = "pclk_src_mux"; - rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, - pll_res, rmap_config); - dsi1pll_pclk_src_mux.clkr.regmap = rmap; - dsi1pll_shadow_pclk_src_mux.clkr.regmap = rmap; - - rmap_config->name = "byteclk_mux"; - rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, rmap_config); - dsi1pll_byteclk_mux.clkr.regmap = rmap; - - dsi1pll_vco_clk.priv = pll_res; - dsi1pll_shadow_vco_clk.priv = pll_res; - - for (i = VCO_CLK_1; i <= SHADOW_PCLK_SRC_1_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - dsi_pllcc_10nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - } - if (!rc) { - pr_info("Registered DSI PLL ndx=%d, clocks successfully\n", - ndx); - - return rc; - } -clk_register_fail: - return rc; -} diff --git a/msm/dsi/dsi_pll_5nm.c b/msm/dsi/dsi_pll_5nm.c index 8ecd313536..182775e70a 100644 --- a/msm/dsi/dsi_pll_5nm.c +++ b/msm/dsi/dsi_pll_5nm.c @@ -1,18 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ -#define pr_fmt(fmt) "%s: " fmt, __func__ - #include #include #include #include #include #include -#include "dsi_pll.h" -#include +#include "dsi_pll_5nm.h" #define VCO_DELAY_USEC 1 @@ -23,225 +20,6 @@ #define MHZ_1900 1900000000UL #define MHZ_3000 3000000000UL -/* Register Offsets from PLL base address */ -#define PLL_ANALOG_CONTROLS_ONE 0x0000 -#define PLL_ANALOG_CONTROLS_TWO 0x0004 -#define PLL_INT_LOOP_SETTINGS 0x0008 -#define PLL_INT_LOOP_SETTINGS_TWO 0x000C -#define PLL_ANALOG_CONTROLS_THREE 0x0010 -#define PLL_ANALOG_CONTROLS_FOUR 0x0014 -#define PLL_ANALOG_CONTROLS_FIVE 0x0018 -#define PLL_INT_LOOP_CONTROLS 0x001C -#define PLL_DSM_DIVIDER 0x0020 -#define PLL_FEEDBACK_DIVIDER 0x0024 -#define PLL_SYSTEM_MUXES 0x0028 -#define PLL_FREQ_UPDATE_CONTROL_OVERRIDES 0x002C -#define PLL_CMODE 0x0030 -#define PLL_PSM_CTRL 0x0034 -#define PLL_RSM_CTRL 0x0038 -#define PLL_VCO_TUNE_MAP 0x003C -#define PLL_PLL_CNTRL 0x0040 -#define PLL_CALIBRATION_SETTINGS 0x0044 -#define PLL_BAND_SEL_CAL_TIMER_LOW 0x0048 -#define PLL_BAND_SEL_CAL_TIMER_HIGH 0x004C -#define PLL_BAND_SEL_CAL_SETTINGS 0x0050 -#define PLL_BAND_SEL_MIN 0x0054 -#define PLL_BAND_SEL_MAX 0x0058 -#define PLL_BAND_SEL_PFILT 0x005C -#define PLL_BAND_SEL_IFILT 0x0060 -#define PLL_BAND_SEL_CAL_SETTINGS_TWO 0x0064 -#define PLL_BAND_SEL_CAL_SETTINGS_THREE 0x0068 -#define PLL_BAND_SEL_CAL_SETTINGS_FOUR 0x006C -#define PLL_BAND_SEL_ICODE_HIGH 0x0070 -#define PLL_BAND_SEL_ICODE_LOW 0x0074 -#define PLL_FREQ_DETECT_SETTINGS_ONE 0x0078 -#define PLL_FREQ_DETECT_THRESH 0x007C -#define PLL_FREQ_DET_REFCLK_HIGH 0x0080 -#define PLL_FREQ_DET_REFCLK_LOW 0x0084 -#define PLL_FREQ_DET_PLLCLK_HIGH 0x0088 -#define PLL_FREQ_DET_PLLCLK_LOW 0x008C -#define PLL_PFILT 0x0090 -#define PLL_IFILT 0x0094 -#define PLL_PLL_GAIN 0x0098 -#define PLL_ICODE_LOW 0x009C -#define PLL_ICODE_HIGH 0x00A0 -#define PLL_LOCKDET 0x00A4 -#define PLL_OUTDIV 0x00A8 -#define PLL_FASTLOCK_CONTROL 0x00AC -#define PLL_PASS_OUT_OVERRIDE_ONE 0x00B0 -#define PLL_PASS_OUT_OVERRIDE_TWO 0x00B4 -#define PLL_CORE_OVERRIDE 0x00B8 -#define PLL_CORE_INPUT_OVERRIDE 0x00BC -#define PLL_RATE_CHANGE 0x00C0 -#define PLL_PLL_DIGITAL_TIMERS 0x00C4 -#define PLL_PLL_DIGITAL_TIMERS_TWO 0x00C8 -#define PLL_DECIMAL_DIV_START 0x00CC -#define PLL_FRAC_DIV_START_LOW 0x00D0 -#define PLL_FRAC_DIV_START_MID 0x00D4 -#define PLL_FRAC_DIV_START_HIGH 0x00D8 -#define PLL_DEC_FRAC_MUXES 0x00DC -#define PLL_DECIMAL_DIV_START_1 0x00E0 -#define PLL_FRAC_DIV_START_LOW_1 0x00E4 -#define PLL_FRAC_DIV_START_MID_1 0x00E8 -#define PLL_FRAC_DIV_START_HIGH_1 0x00EC -#define PLL_DECIMAL_DIV_START_2 0x00F0 -#define PLL_FRAC_DIV_START_LOW_2 0x00F4 -#define PLL_FRAC_DIV_START_MID_2 0x00F8 -#define PLL_FRAC_DIV_START_HIGH_2 0x00FC -#define PLL_MASH_CONTROL 0x0100 -#define PLL_SSC_STEPSIZE_LOW 0x0104 -#define PLL_SSC_STEPSIZE_HIGH 0x0108 -#define PLL_SSC_DIV_PER_LOW 0x010C -#define PLL_SSC_DIV_PER_HIGH 0x0110 -#define PLL_SSC_ADJPER_LOW 0x0114 -#define PLL_SSC_ADJPER_HIGH 0x0118 -#define PLL_SSC_MUX_CONTROL 0x011C -#define PLL_SSC_STEPSIZE_LOW_1 0x0120 -#define PLL_SSC_STEPSIZE_HIGH_1 0x0124 -#define PLL_SSC_DIV_PER_LOW_1 0x0128 -#define PLL_SSC_DIV_PER_HIGH_1 0x012C -#define PLL_SSC_ADJPER_LOW_1 0x0130 -#define PLL_SSC_ADJPER_HIGH_1 0x0134 -#define PLL_SSC_STEPSIZE_LOW_2 0x0138 -#define PLL_SSC_STEPSIZE_HIGH_2 0x013C -#define PLL_SSC_DIV_PER_LOW_2 0x0140 -#define PLL_SSC_DIV_PER_HIGH_2 0x0144 -#define PLL_SSC_ADJPER_LOW_2 0x0148 -#define PLL_SSC_ADJPER_HIGH_2 0x014C -#define PLL_SSC_CONTROL 0x0150 -#define PLL_PLL_OUTDIV_RATE 0x0154 -#define PLL_PLL_LOCKDET_RATE_1 0x0158 -#define PLL_PLL_LOCKDET_RATE_2 0x015C -#define PLL_PLL_PROP_GAIN_RATE_1 0x0160 -#define PLL_PLL_PROP_GAIN_RATE_2 0x0164 -#define PLL_PLL_BAND_SEL_RATE_1 0x0168 -#define PLL_PLL_BAND_SEL_RATE_2 0x016C -#define PLL_PLL_INT_GAIN_IFILT_BAND_1 0x0170 -#define PLL_PLL_INT_GAIN_IFILT_BAND_2 0x0174 -#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x0178 -#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_2 0x017C -#define PLL_PLL_FASTLOCK_EN_BAND 0x0180 -#define PLL_FREQ_TUNE_ACCUM_INIT_MID 0x0184 -#define PLL_FREQ_TUNE_ACCUM_INIT_HIGH 0x0188 -#define PLL_FREQ_TUNE_ACCUM_INIT_MUX 0x018C -#define PLL_PLL_LOCK_OVERRIDE 0x0190 -#define PLL_PLL_LOCK_DELAY 0x0194 -#define PLL_PLL_LOCK_MIN_DELAY 0x0198 -#define PLL_CLOCK_INVERTERS 0x019C -#define PLL_SPARE_AND_JPC_OVERRIDES 0x01A0 -#define PLL_BIAS_CONTROL_1 0x01A4 -#define PLL_BIAS_CONTROL_2 0x01A8 -#define PLL_ALOG_OBSV_BUS_CTRL_1 0x01AC -#define PLL_COMMON_STATUS_ONE 0x01B0 -#define PLL_COMMON_STATUS_TWO 0x01B4 -#define PLL_BAND_SEL_CAL 0x01B8 -#define PLL_ICODE_ACCUM_STATUS_LOW 0x01BC -#define PLL_ICODE_ACCUM_STATUS_HIGH 0x01C0 -#define PLL_FD_OUT_LOW 0x01C4 -#define PLL_FD_OUT_HIGH 0x01C8 -#define PLL_ALOG_OBSV_BUS_STATUS_1 0x01CC -#define PLL_PLL_MISC_CONFIG 0x01D0 -#define PLL_FLL_CONFIG 0x01D4 -#define PLL_FLL_FREQ_ACQ_TIME 0x01D8 -#define PLL_FLL_CODE0 0x01DC -#define PLL_FLL_CODE1 0x01E0 -#define PLL_FLL_GAIN0 0x01E4 -#define PLL_FLL_GAIN1 0x01E8 -#define PLL_SW_RESET 0x01EC -#define PLL_FAST_PWRUP 0x01F0 -#define PLL_LOCKTIME0 0x01F4 -#define PLL_LOCKTIME1 0x01F8 -#define PLL_DEBUG_BUS_SEL 0x01FC -#define PLL_DEBUG_BUS0 0x0200 -#define PLL_DEBUG_BUS1 0x0204 -#define PLL_DEBUG_BUS2 0x0208 -#define PLL_DEBUG_BUS3 0x020C -#define PLL_ANALOG_FLL_CONTROL_OVERRIDES 0x0210 -#define PLL_VCO_CONFIG 0x0214 -#define PLL_VCO_CAL_CODE1_MODE0_STATUS 0x0218 -#define PLL_VCO_CAL_CODE1_MODE1_STATUS 0x021C -#define PLL_RESET_SM_STATUS 0x0220 -#define PLL_TDC_OFFSET 0x0224 -#define PLL_PS3_PWRDOWN_CONTROLS 0x0228 -#define PLL_PS4_PWRDOWN_CONTROLS 0x022C -#define PLL_PLL_RST_CONTROLS 0x0230 -#define PLL_GEAR_BAND_SELECT_CONTROLS 0x0234 -#define PLL_PSM_CLK_CONTROLS 0x0238 -#define PLL_SYSTEM_MUXES_2 0x023C -#define PLL_VCO_CONFIG_1 0x0240 -#define PLL_VCO_CONFIG_2 0x0244 -#define PLL_CLOCK_INVERTERS_1 0x0248 -#define PLL_CLOCK_INVERTERS_2 0x024C -#define PLL_CMODE_1 0x0250 -#define PLL_CMODE_2 0x0254 -#define PLL_ANALOG_CONTROLS_FIVE_1 0x0258 -#define PLL_ANALOG_CONTROLS_FIVE_2 0x025C -#define PLL_PERF_OPTIMIZE 0x0260 - -/* Register Offsets from PHY base address */ -#define PHY_CMN_CLK_CFG0 0x010 -#define PHY_CMN_CLK_CFG1 0x014 -#define PHY_CMN_GLBL_CTRL 0x018 -#define PHY_CMN_RBUF_CTRL 0x01C -#define PHY_CMN_CTRL_0 0x024 -#define PHY_CMN_CTRL_2 0x02C -#define PHY_CMN_CTRL_3 0x030 -#define PHY_CMN_PLL_CNTRL 0x03C -#define PHY_CMN_GLBL_DIGTOP_SPARE4 0x128 - -/* Bit definition of SSC control registers */ -#define SSC_CENTER BIT(0) -#define SSC_EN BIT(1) -#define SSC_FREQ_UPDATE BIT(2) -#define SSC_FREQ_UPDATE_MUX BIT(3) -#define SSC_UPDATE_SSC BIT(4) -#define SSC_UPDATE_SSC_MUX BIT(5) -#define SSC_START BIT(6) -#define SSC_START_MUX BIT(7) - -/* Dynamic Refresh Control Registers */ -#define DSI_DYNAMIC_REFRESH_PLL_CTRL0 (0x014) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL1 (0x018) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL2 (0x01C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL3 (0x020) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL4 (0x024) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL5 (0x028) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL6 (0x02C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL7 (0x030) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL8 (0x034) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL9 (0x038) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL10 (0x03C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL11 (0x040) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL12 (0x044) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL13 (0x048) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL14 (0x04C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL15 (0x050) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL16 (0x054) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL17 (0x058) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL18 (0x05C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL19 (0x060) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL20 (0x064) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL21 (0x068) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL22 (0x06C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL23 (0x070) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL24 (0x074) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL25 (0x078) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL26 (0x07C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL27 (0x080) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL28 (0x084) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL29 (0x088) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL30 (0x08C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL31 (0x090) -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR (0x094) -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2 (0x098) - -#define DSI_PHY_TO_PLL_OFFSET (0x500) -enum { - DSI_PLL_0, - DSI_PLL_1, - DSI_PLL_MAX -}; - struct dsi_pll_regs { u32 pll_prop_gain_rate; u32 pll_lockdet_rate; @@ -291,186 +69,113 @@ static inline bool dsi_pll_5nm_is_hw_revision( true : false; } -static inline int pll_reg_read(void *context, unsigned int reg, - unsigned int *val) +static inline void dsi_pll_set_pll_post_div(struct dsi_pll_resource *pll, u32 + pll_post_div) { - int rc = 0; - u32 data; - struct dsi_pll_resource *rsc = context; + u32 pll_post_div_val = 0; - data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data | BIT(5)); - ndelay(250); + if (pll_post_div == 1) + pll_post_div_val = 0; + if (pll_post_div == 2) + pll_post_div_val = 1; + if (pll_post_div == 4) + pll_post_div_val = 2; + if (pll_post_div == 8) + pll_post_div_val = 3; - *val = DSI_PLL_REG_R(rsc->pll_base, reg); - - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data); - - return rc; + DSI_PLL_REG_W(pll->pll_base, PLL_PLL_OUTDIV_RATE, pll_post_div_val); + if (pll->slave) + DSI_PLL_REG_W(pll->slave->pll_base, PLL_PLL_OUTDIV_RATE, + pll_post_div_val); } -static inline int pll_reg_write(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - DSI_PLL_REG_W(rsc->pll_base, reg, val); - - return rc; -} - -static inline int phy_reg_read(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - *val = DSI_PLL_REG_R(rsc->phy_base, reg); - - return rc; -} - -static inline int phy_reg_write(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - DSI_PLL_REG_W(rsc->phy_base, reg, val); - - return rc; -} - -static inline int phy_reg_update_bits_sub(struct dsi_pll_resource *rsc, - unsigned int reg, unsigned int mask, unsigned int val) +static inline int dsi_pll_get_pll_post_div(struct dsi_pll_resource *pll) { u32 reg_val; - reg_val = DSI_PLL_REG_R(rsc->phy_base, reg); - reg_val &= ~mask; - reg_val |= (val & mask); - DSI_PLL_REG_W(rsc->phy_base, reg, reg_val); + reg_val = DSI_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE); - return 0; + return (1 << reg_val); } -static inline int phy_reg_update_bits(void *context, unsigned int reg, - unsigned int mask, unsigned int val) +static inline void dsi_pll_set_phy_post_div(struct dsi_pll_resource *pll, u32 + phy_post_div) { - int rc = 0; - struct dsi_pll_resource *rsc = context; + u32 reg_val = 0; - rc = phy_reg_update_bits_sub(rsc, reg, mask, val); - if (!rc && rsc->slave) - rc = phy_reg_update_bits_sub(rsc->slave, reg, mask, val); - - return rc; -} - -static inline int pclk_mux_read_sel(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - - /* Return cached cfg1 as its updated with cached cfg1 in pll_enable */ - if (!rsc->handoff_resources) { - *val = (rsc->cached_cfg1) & 0x3; - return rc; + reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); + reg_val &= ~0x0F; + reg_val |= phy_post_div; + DSI_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, reg_val); + if (pll->slave) { + reg_val = DSI_PLL_REG_R(pll->slave->phy_base, PHY_CMN_CLK_CFG0); + reg_val &= ~0x0F; + reg_val |= phy_post_div; + DSI_PLL_REG_W(pll->slave->phy_base, PHY_CMN_CLK_CFG0, reg_val); } - - *val = (DSI_PLL_REG_R(rsc->phy_base, reg) & 0x3); - - return rc; } -static inline int pclk_mux_write_sel_sub(struct dsi_pll_resource *rsc, - unsigned int reg, unsigned int val) +static inline int dsi_pll_get_phy_post_div(struct dsi_pll_resource *pll) +{ + u32 reg_val = 0; + + reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); + + return (reg_val & 0xF); +} + + +static inline void dsi_pll_set_dsi_clk(struct dsi_pll_resource *pll, u32 + dsi_clk) +{ + u32 reg_val = 0; + + reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG1); + reg_val &= ~0x3; + reg_val |= dsi_clk; + DSI_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG1, reg_val); + if (pll->slave) { + reg_val = DSI_PLL_REG_R(pll->slave->phy_base, PHY_CMN_CLK_CFG1); + reg_val &= ~0x3; + reg_val |= dsi_clk; + DSI_PLL_REG_W(pll->slave->phy_base, PHY_CMN_CLK_CFG1, reg_val); + } +} + +static inline int dsi_pll_get_dsi_clk(struct dsi_pll_resource *pll) { u32 reg_val; - reg_val = DSI_PLL_REG_R(rsc->phy_base, reg); - reg_val &= ~0x03; - reg_val |= val; + reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG1); - DSI_PLL_REG_W(rsc->phy_base, reg, reg_val); - - return 0; + return (reg_val & 0x3); } -static inline int pclk_mux_write_sel(void *context, unsigned int reg, - unsigned int val) +static inline void dsi_pll_set_pclk_div(struct dsi_pll_resource *pll, u32 + pclk_div) { - int rc = 0; - struct dsi_pll_resource *rsc = context; - struct dsi_pll_5nm *pll = rsc->priv; + u32 reg_val = 0; - if (pll->cphy_enabled) - WARN_ON("PHY is in CPHY mode. PLL config is incorrect\n"); - rc = pclk_mux_write_sel_sub(rsc, reg, val); - if (!rc && rsc->slave) - rc = pclk_mux_write_sel_sub(rsc->slave, reg, val); - - - /* - * cache the current parent index for cases where parent - * is not changing but rate is changing. In that case - * clock framework won't call parent_set and hence dsiclk_sel - * bit won't be programmed. e.g. dfps update use case. - */ - rsc->cached_cfg1 = val; - - return rc; + reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); + reg_val &= ~0xF0; + reg_val |= (pclk_div << 4); + DSI_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, reg_val); + if (pll->slave) { + reg_val = DSI_PLL_REG_R(pll->slave->phy_base, PHY_CMN_CLK_CFG0); + reg_val &= ~0xF0; + reg_val |= (pclk_div << 4); + DSI_PLL_REG_W(pll->slave->phy_base, PHY_CMN_CLK_CFG0, reg_val); + } } -static inline int cphy_pclk_mux_read_sel(void *context, unsigned int reg, - unsigned int *val) +static inline int dsi_pll_get_pclk_div(struct dsi_pll_resource *pll) { - struct dsi_pll_resource *rsc = context; + u32 reg_val; - *val = (DSI_PLL_REG_R(rsc->phy_base, reg) & 0x3); + reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - return 0; -} - -static inline int cphy_pclk_mux_write_sel(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct dsi_pll_resource *rsc = context; - struct dsi_pll_5nm *pll = rsc->priv; - - if (!pll->cphy_enabled) - WARN_ON("PHY-> not in CPHY mode. PLL config is incorrect\n"); - /* For Cphy configuration, val should always be 3 */ - val = 3; - rc = pclk_mux_write_sel_sub(rsc, reg, val); - if (!rc && rsc->slave) - rc = pclk_mux_write_sel_sub(rsc->slave, reg, val); - - /* - * cache the current parent index for cases where parent - * is not changing but rate is changing. In that case - * clock framework won't call parent_set and hence dsiclk_sel - * bit won't be programmed. e.g. dfps update use case. - */ - rsc->cached_cfg1 = val; - - return rc; -} - -static int dsi_pll_5nm_get_gdsc_status(struct dsi_pll_resource *rsc) -{ - u32 reg = 0; - bool status; - - reg = DSI_PLL_REG_R(rsc->gdsc_base, 0x0); - status = reg & BIT(31); - pr_err("reg:0x%x status:%d\n", reg, status); - - return status; + return ((reg_val & 0xF0) >> 4); } static struct dsi_pll_resource *pll_rsc_db[DSI_PLL_MAX]; @@ -492,7 +197,8 @@ static void dsi_pll_config_slave(struct dsi_pll_resource *rsc) rsc->slave = NULL; if (!orsc) { - pr_warn("slave PLL unavilable, assuming standalone config\n"); + DSI_PLL_WARN(rsc, + "slave PLL unavilable, assuming standalone config\n"); return; } @@ -502,7 +208,8 @@ static void dsi_pll_config_slave(struct dsi_pll_resource *rsc) if (reg == 0x04) rsc->slave = pll_rsc_db[DSI_PLL_1]; /* external source */ - pr_debug("Slave PLL %s\n", rsc->slave ? "configured" : "absent"); + DSI_PLL_DBG(rsc, "Slave PLL %s\n", + rsc->slave ? "configured" : "absent"); } static void dsi_pll_setup_config(struct dsi_pll_5nm *pll, @@ -595,7 +302,7 @@ static void dsi_pll_calc_ssc(struct dsi_pll_5nm *pll, u64 frac; if (!config->enable_ssc) { - pr_debug("SSC not enabled\n"); + DSI_PLL_DBG(rsc, "SSC not enabled\n"); return; } @@ -623,9 +330,9 @@ static void dsi_pll_calc_ssc(struct dsi_pll_5nm *pll, regs->ssc_control = config->ssc_center ? SSC_CENTER : 0; - pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n", + DSI_PLL_DBG(rsc, "SCC: Dec:%d, frac:%llu, frac_bits:%d\n", regs->decimal_div_start, frac, config->frac_bits); - pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n", + DSI_PLL_DBG(rsc, "SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n", ssc_per, (u32)ssc_step_size, config->ssc_adj_per); } @@ -636,7 +343,7 @@ static void dsi_pll_ssc_commit(struct dsi_pll_5nm *pll, struct dsi_pll_regs *regs = &pll->reg_setup; if (pll->pll_configuration.enable_ssc) { - pr_debug("SSC is enabled\n"); + DSI_PLL_DBG(rsc, "SSC is enabled\n"); DSI_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_LOW_1, regs->ssc_stepsize_low); @@ -885,48 +592,507 @@ static void dsi_pll_commit(struct dsi_pll_5nm *pll, reg->pll_clock_inverters); } -static int vco_5nm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) +static int dsi_pll_5nm_lock_status(struct dsi_pll_resource *pll) +{ + int rc; + u32 status; + u32 const delay_us = 100; + u32 const timeout_us = 5000; + + rc = readl_poll_timeout_atomic(pll->pll_base + PLL_COMMON_STATUS_ONE, + status, + ((status & BIT(0)) > 0), + delay_us, + timeout_us); + if (rc) + DSI_PLL_ERR(pll, "lock failed, status=0x%08x\n", status); + + return rc; +} + +static void dsi_pll_disable_pll_bias(struct dsi_pll_resource *rsc) +{ + u32 data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); + + DSI_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0); + DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5)); + ndelay(250); +} + +static void dsi_pll_enable_pll_bias(struct dsi_pll_resource *rsc) +{ + u32 data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); + + DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data | BIT(5)); + DSI_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0xc0); + ndelay(250); +} + +static void dsi_pll_disable_global_clk(struct dsi_pll_resource *rsc) +{ + u32 data; + + data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); + DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data & ~BIT(5))); +} + +static void dsi_pll_enable_global_clk(struct dsi_pll_resource *rsc) +{ + u32 data; + + DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_3, 0x04); + + data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); + + /* Turn on clk_en_sel bit prior to resync toggle fifo */ + DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data | BIT(5) | + BIT(4))); +} + +static void dsi_pll_phy_dig_reset(struct dsi_pll_resource *rsc) +{ + /* + * Reset the PHY digital domain. This would be needed when + * coming out of a CX or analog rail power collapse while + * ensuring that the pads maintain LP00 or LP11 state + */ + DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_GLBL_DIGTOP_SPARE4, BIT(0)); + wmb(); /* Ensure that the reset is asserted */ + DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_GLBL_DIGTOP_SPARE4, 0x0); + wmb(); /* Ensure that the reset is deasserted */ +} + +static void dsi_pll_disable_sub(struct dsi_pll_resource *rsc) +{ + DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0); + dsi_pll_disable_pll_bias(rsc); +} + +static void dsi_pll_unprepare_stub(struct clk_hw *hw) +{ + return; +} + +static int dsi_pll_prepare_stub(struct clk_hw *hw) +{ + return 0; +} + +static int dsi_pll_set_rate_stub(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + return 0; +} + +static long dsi_pll_byteclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct dsi_pll_clk *pll = to_pll_clk_hw(hw); + struct dsi_pll_resource *pll_res = pll->priv; + + return pll_res->byteclk_rate; +} + +static long dsi_pll_pclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct dsi_pll_clk *pll = to_pll_clk_hw(hw); + struct dsi_pll_resource *pll_res = pll->priv; + + return pll_res->pclk_rate; +} + +static unsigned long dsi_pll_vco_recalc_rate(struct dsi_pll_resource *pll) +{ + u64 ref_clk; + u64 multiplier; + u32 frac; + u32 dec; + u32 pll_post_div; + u64 pll_freq, tmp64; + u64 vco_rate; + + ref_clk = pll->vco_ref_clk_rate; + + dec = DSI_PLL_REG_R(pll->pll_base, PLL_DECIMAL_DIV_START_1); + dec &= 0xFF; + + frac = DSI_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_LOW_1); + frac |= ((DSI_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_MID_1) & 0xFF) + << 8); + frac |= ((DSI_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_HIGH_1) & 0x3) + << 16); + + multiplier = 1 << 18; + pll_freq = dec * (ref_clk * 2); + tmp64 = (ref_clk * 2 * frac); + pll_freq += div_u64(tmp64, multiplier); + + pll_post_div = dsi_pll_get_pll_post_div(pll); + + vco_rate = div_u64(pll_freq, pll_post_div); + + return vco_rate; +} + +static unsigned long dsi_pll_byteclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct dsi_pll_clk *byte_pll = to_pll_clk_hw(hw); + struct dsi_pll_resource *pll = NULL; + u64 vco_rate = 0; + u64 byte_rate = 0; + u32 phy_post_div; + + if (!byte_pll->priv) { + DSI_PLL_INFO(pll, "pll priv is null\n"); + return 0; + } + + pll = byte_pll->priv; + + /* + * In the case when byteclk rate is set, the recalculation function + * should return the current rate. Recalc rate is also called during + * clock registration, during which the function should reverse + * calculate clock rates that were set as part of UEFI. + */ + if (pll->byteclk_rate != 0) { + DSI_PLL_DBG(pll, "returning byte clk rate = %lld %lld\n", + pll->byteclk_rate, parent_rate); + return pll->byteclk_rate; + } + + vco_rate = dsi_pll_vco_recalc_rate(pll); + + phy_post_div = dsi_pll_get_phy_post_div(pll); + byte_rate = div_u64(vco_rate, phy_post_div); + + if (pll->type == DSI_PHY_TYPE_DPHY) + byte_rate = div_u64(vco_rate, 8); + else + byte_rate = div_u64(vco_rate, 7); + + return byte_rate; +} + +static unsigned long dsi_pll_pclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct dsi_pll_clk *pix_pll = to_pll_clk_hw(hw); + struct dsi_pll_resource *pll = NULL; + u64 vco_rate = 0; + u64 pclk_rate = 0; + u32 phy_post_div, pclk_div; + + if (!pix_pll->priv) { + DSI_PLL_INFO(pll, "pll priv is null\n"); + return 0; + } + + pll = pix_pll->priv; + + /* + * In the case when pclk rate is set, the recalculation function + * should return the current rate. Recalc rate is also called during + * clock registration, during which the function should reverse + * calculate the clock rates that were set as part of UEFI. + */ + if (pll->pclk_rate != 0) { + DSI_PLL_DBG(pll, "returning pclk rate = %lld %lld\n", + pll->pclk_rate, parent_rate); + return pll->pclk_rate; + } + + vco_rate = dsi_pll_vco_recalc_rate(pll); + + if (pll->type == DSI_PHY_TYPE_DPHY) { + phy_post_div = dsi_pll_get_phy_post_div(pll); + pclk_rate = div_u64(vco_rate, phy_post_div); + pclk_rate = div_u64(pclk_rate, 2); + pclk_div = dsi_pll_get_pclk_div(pll); + pclk_rate = div_u64(pclk_rate, pclk_div); + } else { + pclk_rate = vco_rate * 2; + pclk_rate = div_u64(pclk_rate, 7); + pclk_div = dsi_pll_get_pclk_div(pll); + pclk_rate = div_u64(pclk_rate, pclk_div); + } + + return pclk_rate; +} + +static const struct clk_ops pll_byteclk_ops = { + .recalc_rate = dsi_pll_byteclk_recalc_rate, + .set_rate = dsi_pll_set_rate_stub, + .round_rate = dsi_pll_byteclk_round_rate, + .prepare = dsi_pll_prepare_stub, + .unprepare = dsi_pll_unprepare_stub, +}; + +static const struct clk_ops pll_pclk_ops = { + .recalc_rate = dsi_pll_pclk_recalc_rate, + .set_rate = dsi_pll_set_rate_stub, + .round_rate = dsi_pll_pclk_round_rate, + .prepare = dsi_pll_prepare_stub, + .unprepare = dsi_pll_unprepare_stub, +}; + +/* + * Clock tree for generating DSI byte and pclk. + * + * + * +-------------------------------+ +----------------------------+ + * | dsi_phy_pll_out_byteclk | | dsi_phy_pll_out_dsiclk | + * +---------------+---------------+ +--------------+-------------+ + * | | + * | | + * v v + * dsi_byte_clk dsi_pclk + * + * + */ + +static struct dsi_pll_clk dsi0_phy_pll_out_byteclk = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0_phy_pll_out_byteclk", + .ops = &pll_byteclk_ops, + }, +}; + +static struct dsi_pll_clk dsi1_phy_pll_out_byteclk = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1_phy_pll_out_byteclk", + .ops = &pll_byteclk_ops, + }, +}; + +static struct dsi_pll_clk dsi0_phy_pll_out_dsiclk = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0_phy_pll_out_dsiclk", + .ops = &pll_pclk_ops, + }, +}; + +static struct dsi_pll_clk dsi1_phy_pll_out_dsiclk = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1_phy_pll_out_dsiclk", + .ops = &pll_pclk_ops, + }, +}; + +int dsi_pll_clock_register_5nm(struct platform_device *pdev, + struct dsi_pll_resource *pll_res) +{ + int rc = 0, ndx; + struct clk *clk; + struct clk_onecell_data *clk_data; + int num_clks = 4; + + if (!pdev || !pdev->dev.of_node || + !pll_res || !pll_res->pll_base || !pll_res->phy_base) { + DSI_PLL_ERR(pll_res, "Invalid params\n"); + return -EINVAL; + } + + ndx = pll_res->index; + + if (ndx >= DSI_PLL_MAX) { + DSI_PLL_ERR(pll_res, "not supported\n"); + return -EINVAL; + } + + pll_rsc_db[ndx] = pll_res; + plls[ndx].rsc = pll_res; + pll_res->priv = &plls[ndx]; + pll_res->vco_delay = VCO_DELAY_USEC; + pll_res->vco_min_rate = 600000000; + pll_res->vco_ref_clk_rate = 19200000UL; + + clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->clks = devm_kzalloc(&pdev->dev, (num_clks * + sizeof(struct clk *)), GFP_KERNEL); + if (!clk_data->clks) + return -ENOMEM; + + clk_data->clk_num = num_clks; + + /* Establish client data */ + if (ndx == 0) { + dsi0_phy_pll_out_byteclk.priv = pll_res; + dsi0_phy_pll_out_dsiclk.priv = pll_res; + + clk = devm_clk_register(&pdev->dev, + &dsi0_phy_pll_out_byteclk.hw); + if (IS_ERR(clk)) { + DSI_PLL_ERR(pll_res, + "clk registration failed for DSI clock\n"); + rc = -EINVAL; + goto clk_register_fail; + } + clk_data->clks[0] = clk; + + clk = devm_clk_register(&pdev->dev, + &dsi0_phy_pll_out_dsiclk.hw); + if (IS_ERR(clk)) { + DSI_PLL_ERR(pll_res, + "clk registration failed for DSI clock\n"); + rc = -EINVAL; + goto clk_register_fail; + } + clk_data->clks[1] = clk; + + + rc = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, clk_data); + } else { + dsi1_phy_pll_out_byteclk.priv = pll_res; + dsi1_phy_pll_out_dsiclk.priv = pll_res; + + + clk = devm_clk_register(&pdev->dev, + &dsi1_phy_pll_out_byteclk.hw); + if (IS_ERR(clk)) { + DSI_PLL_ERR(pll_res, + "clk registration failed for DSI clock\n"); + rc = -EINVAL; + goto clk_register_fail; + } + clk_data->clks[2] = clk; + + clk = devm_clk_register(&pdev->dev, + &dsi1_phy_pll_out_dsiclk.hw); + if (IS_ERR(clk)) { + DSI_PLL_ERR(pll_res, + "clk registration failed for DSI clock\n"); + rc = -EINVAL; + goto clk_register_fail; + } + clk_data->clks[3] = clk; + + rc = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, clk_data); + } + if (!rc) { + DSI_PLL_INFO(pll_res, "Registered clocks successfully\n"); + + return rc; + } +clk_register_fail: + return rc; +} + +static int dsi_pll_5nm_set_byteclk_div(struct dsi_pll_resource *pll, + bool commit) +{ + + int i = 0; + int table_size; + u32 pll_post_div = 0, phy_post_div = 0; + struct dsi_pll_div_table *table; + u32 bitclk_rate; + + if (pll->type == DSI_PHY_TYPE_DPHY) { + bitclk_rate = pll->byteclk_rate * 8; + table_size = ARRAY_SIZE(pll_5nm_dphy); + table = pll_5nm_dphy; + } else { + bitclk_rate = pll->byteclk_rate * 7; + table_size = ARRAY_SIZE(pll_5nm_cphy); + table = pll_5nm_cphy; + } + + for (i = 0; i < table_size; i++) { + if ((table[i].min_hz <= bitclk_rate) && + (bitclk_rate <= table[i].max_hz)) { + pll_post_div = table[i].pll_div; + phy_post_div = table[i].phy_div; + break; + } + } + + DSI_PLL_DBG(pll, "bit clk rate: %llu, pll_post_div: %d, phy_post_div: %d\n", + bitclk_rate, pll_post_div, phy_post_div); + + if (commit) { + dsi_pll_set_pll_post_div(pll, pll_post_div); + dsi_pll_set_phy_post_div(pll, phy_post_div); + } + + pll->vco_rate = bitclk_rate * pll_post_div * phy_post_div; + + return 0; +} + +static int dsi_pll_5nm_set_pclk_div(struct dsi_pll_resource *pll, bool commit) +{ + + int dsi_clk = 0, pclk_div = 0; + u64 pclk_src_rate; + u32 pll_post_div; + u32 phy_post_div; + + pll_post_div = dsi_pll_get_pll_post_div(pll); + pclk_src_rate = div_u64(pll->vco_rate, pll_post_div); + if (pll->type == DSI_PHY_TYPE_DPHY) { + dsi_clk = 0x1; + phy_post_div = dsi_pll_get_phy_post_div(pll); + pclk_src_rate = div_u64(pclk_src_rate, phy_post_div); + pclk_src_rate = div_u64(pclk_src_rate, 2); + } else { + dsi_clk = 0x3; + pclk_src_rate *= 2; + pclk_src_rate = div_u64(pclk_src_rate, 7); + } + + pclk_div = pclk_src_rate / pll->pclk_rate; + + DSI_PLL_DBG(pll, "pclk rate: %llu, dsi_clk: %d, pclk_div: %d\n", + pll->pclk_rate, dsi_clk, pclk_div); + + if (commit) { + dsi_pll_set_dsi_clk(pll, dsi_clk); + dsi_pll_set_pclk_div(pll, pclk_div); + } + + return 0; + +} + +static int dsi_pll_5nm_vco_set_rate(struct dsi_pll_resource *pll_res) { - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *rsc = vco->priv; struct dsi_pll_5nm *pll; - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - if (rsc->pll_on) + if (pll_res->pll_on) return 0; - pll = rsc->priv; + pll = pll_res->priv; if (!pll) { - pr_err("pll configuration not found\n"); + DSI_PLL_ERR(pll_res, "pll configuration not found\n"); return -EINVAL; } - pr_debug("ndx=%d, rate=%lu\n", rsc->index, rate); + DSI_PLL_DBG(pll_res, "rate=%lu\n", pll_res->vco_rate); - rsc->vco_current_rate = rate; - rsc->vco_ref_clk_rate = vco->ref_clk_rate; - rsc->dfps_trigger = false; + pll_res->vco_current_rate = pll_res->vco_rate; - dsi_pll_init_val(rsc); + dsi_pll_detect_phy_mode(pll, pll_res); - dsi_pll_detect_phy_mode(pll, rsc); + dsi_pll_setup_config(pll, pll_res); - dsi_pll_setup_config(pll, rsc); + dsi_pll_calc_dec_frac(pll, pll_res); - dsi_pll_calc_dec_frac(pll, rsc); + dsi_pll_calc_ssc(pll, pll_res); - dsi_pll_calc_ssc(pll, rsc); + dsi_pll_commit(pll, pll_res); - dsi_pll_commit(pll, rsc); + dsi_pll_config_hzindep_reg(pll, pll_res); - dsi_pll_config_hzindep_reg(pll, rsc); - - dsi_pll_ssc_commit(pll, rsc); + dsi_pll_ssc_commit(pll, pll_res); /* flush, ensure all register writes are done*/ wmb(); @@ -947,7 +1113,7 @@ static int dsi_pll_read_stored_trim_codes(struct dsi_pll_resource *pll_res, struct dfps_codes_info *codes_info = &pll_res->dfps->codes_dfps[i]; - pr_debug("valid=%d vco_rate=%d, code %d %d %d\n", + DSI_PLL_DBG(pll_res, "valid=%d vco_rate=%d, code %d %d %d\n", codes_info->is_valid, codes_info->clk_rate, codes_info->pll_codes.pll_codes_1, codes_info->pll_codes.pll_codes_2, @@ -970,7 +1136,7 @@ static int dsi_pll_read_stored_trim_codes(struct dsi_pll_resource *pll_res, if (!found) return -EINVAL; - pr_debug("trim_code_0=0x%x trim_code_1=0x%x trim_code_2=0x%x\n", + DSI_PLL_DBG(pll_res, "trim_code_0=0x%x trim_code_1=0x%x trim_code_2=0x%x\n", pll_res->cache_pll_trim_codes[0], pll_res->cache_pll_trim_codes[1], pll_res->cache_pll_trim_codes[2]); @@ -978,8 +1144,8 @@ static int dsi_pll_read_stored_trim_codes(struct dsi_pll_resource *pll_res, return 0; } -static void shadow_dsi_pll_dynamic_refresh_5nm(struct dsi_pll_5nm *pll, - struct dsi_pll_resource *rsc) +static void dsi_pll_5nm_dynamic_refresh(struct dsi_pll_5nm *pll, + struct dsi_pll_resource *rsc) { u32 data; u32 offset = DSI_PHY_TO_PLL_OFFSET; @@ -1036,8 +1202,7 @@ static void shadow_dsi_pll_dynamic_refresh_5nm(struct dsi_pll_5nm *pll, (PLL_CLOCK_INVERTERS_1 + offset), pll->cphy_enabled ? 0x00 : 0x10, reg->pll_clock_inverters); - upper_addr |= - (upper_8_bit(PLL_CMODE_1 + offset) << 12); + upper_addr |= (upper_8_bit(PLL_CMODE_1 + offset) << 12); upper_addr |= (upper_8_bit(PLL_CLOCK_INVERTERS_1 + offset) << 13); data = DSI_PLL_REG_R(rsc->pll_base, PLL_VCO_CONFIG_1); @@ -1162,143 +1327,47 @@ static void shadow_dsi_pll_dynamic_refresh_5nm(struct dsi_pll_5nm *pll, wmb(); /* commit register writes */ } -static int shadow_vco_5nm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) +static int dsi_pll_5nm_dynamic_clk_vco_set_rate(struct dsi_pll_resource *rsc) { int rc; struct dsi_pll_5nm *pll; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *rsc = vco->priv; + u32 rate; if (!rsc) { - pr_err("pll resource not found\n"); + DSI_PLL_ERR(rsc, "pll resource not found\n"); return -EINVAL; } + rate = rsc->vco_rate; pll = rsc->priv; if (!pll) { - pr_err("pll configuration not found\n"); + DSI_PLL_ERR(rsc, "pll configuration not found\n"); return -EINVAL; } rc = dsi_pll_read_stored_trim_codes(rsc, rate); if (rc) { - pr_err("cannot find pll codes rate=%ld\n", rate); + DSI_PLL_ERR(rsc, "cannot find pll codes rate=%ld\n", rate); return -EINVAL; } - pr_debug("ndx=%d, rate=%lu\n", rsc->index, rate); + DSI_PLL_DBG(rsc, "ndx=%d, rate=%lu\n", rate); rsc->vco_current_rate = rate; - rsc->vco_ref_clk_rate = vco->ref_clk_rate; dsi_pll_setup_config(pll, rsc); dsi_pll_calc_dec_frac(pll, rsc); /* program dynamic refresh control registers */ - shadow_dsi_pll_dynamic_refresh_5nm(pll, rsc); - - /* update cached vco rate */ - rsc->vco_cached_rate = rate; - rsc->dfps_trigger = true; + dsi_pll_5nm_dynamic_refresh(pll, rsc); return 0; } -static int dsi_pll_5nm_lock_status(struct dsi_pll_resource *pll) +static int dsi_pll_5nm_enable(struct dsi_pll_resource *rsc) { - int rc; - u32 status; - u32 const delay_us = 100; - u32 const timeout_us = 5000; - - rc = readl_poll_timeout_atomic(pll->pll_base + PLL_COMMON_STATUS_ONE, - status, - ((status & BIT(0)) > 0), - delay_us, - timeout_us); - if (rc && !pll->handoff_resources) - pr_err("DSI PLL(%d) lock failed, status=0x%08x\n", - pll->index, status); - - return rc; -} - -static void dsi_pll_disable_pll_bias(struct dsi_pll_resource *rsc) -{ - u32 data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - - DSI_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0); - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5)); - ndelay(250); -} - -static void dsi_pll_enable_pll_bias(struct dsi_pll_resource *rsc) -{ - u32 data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data | BIT(5)); - DSI_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0xc0); - ndelay(250); -} - -static void dsi_pll_disable_global_clk(struct dsi_pll_resource *rsc) -{ - u32 data; - - data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data & ~BIT(5))); -} - -static void dsi_pll_enable_global_clk(struct dsi_pll_resource *rsc) -{ - u32 data; - - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_3, 0x04); - - data = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); - - /* Turn on clk_en_sel bit prior to resync toggle fifo */ - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data | BIT(5) | - BIT(4))); -} - -static void dsi_pll_phy_dig_reset(struct dsi_pll_resource *rsc) -{ - /* - * Reset the PHY digital domain. This would be needed when - * coming out of a CX or analog rail power collapse while - * ensuring that the pads maintain LP00 or LP11 state - */ - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_GLBL_DIGTOP_SPARE4, BIT(0)); - wmb(); /* Ensure that the reset is asserted */ - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_GLBL_DIGTOP_SPARE4, 0x0); - wmb(); /* Ensure that the reset is deasserted */ -} - -static int dsi_pll_enable(struct dsi_pll_vco_clk *vco) -{ - int rc; - struct dsi_pll_resource *rsc = vco->priv; - struct dsi_pll_5nm *pll = rsc->priv; - - dsi_pll_enable_pll_bias(rsc); - if (rsc->slave) - dsi_pll_enable_pll_bias(rsc->slave); - - /* For Cphy configuration, pclk_mux is always set to 3 divider */ - if (pll->cphy_enabled) { - rsc->cached_cfg1 |= 0x3; - if (rsc->slave) - rsc->slave->cached_cfg1 |= 0x3; - } - - phy_reg_update_bits_sub(rsc, PHY_CMN_CLK_CFG1, 0x03, rsc->cached_cfg1); - if (rsc->slave) - phy_reg_update_bits_sub(rsc->slave, PHY_CMN_CLK_CFG1, - 0x03, rsc->slave->cached_cfg1); - wmb(); /* ensure dsiclk_sel is always programmed before pll start */ + int rc = 0; /* Start PLL */ DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0x01); @@ -1312,7 +1381,7 @@ static int dsi_pll_enable(struct dsi_pll_vco_clk *vco) /* Check for PLL lock */ rc = dsi_pll_5nm_lock_status(rsc); if (rc) { - pr_err("PLL(%d) lock failed\n", rsc->index); + DSI_PLL_ERR(rsc, "lock failed\n"); goto error; } @@ -1331,29 +1400,22 @@ static int dsi_pll_enable(struct dsi_pll_vco_clk *vco) if (rsc->slave) dsi_pll_enable_global_clk(rsc->slave); + /* flush, ensure all register writes are done*/ + wmb(); error: return rc; } -static void dsi_pll_disable_sub(struct dsi_pll_resource *rsc) +static int dsi_pll_5nm_disable(struct dsi_pll_resource *rsc) { - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0); - dsi_pll_disable_pll_bias(rsc); -} - -static void dsi_pll_disable(struct dsi_pll_vco_clk *vco) -{ - struct dsi_pll_resource *rsc = vco->priv; + int rc = 0; if (!rsc->pll_on) { - pr_err("failed to enable pll (%d) resources\n", rsc->index); - return; + DSI_PLL_ERR(rsc, "is not enabled\n"); + return -EINVAL; } - rsc->handoff_resources = false; - rsc->dfps_trigger = false; - - pr_debug("stop PLL (%d)\n", rsc->index); + DSI_PLL_DBG(rsc, "stop PLL\n"); /* * To avoid any stray glitches while @@ -1372,1323 +1434,54 @@ static void dsi_pll_disable(struct dsi_pll_vco_clk *vco) /* flush, ensure all register writes are done*/ wmb(); rsc->pll_on = false; -} - -long vco_5nm_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - *parent_rate = rrate; - - return rrate; -} - -static void vco_5nm_unprepare(struct clk_hw *hw) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *pll = vco->priv; - - if (!pll) { - pr_err("dsi pll resources not available\n"); - return; - } - - /* - * During unprepare in continuous splash use case we want driver - * to pick all dividers instead of retaining bootloader configurations. - * Also handle the usecases when dynamic refresh gets triggered while - * handoff_resources flag is still set. For video mode, this flag does - * not get cleared until first suspend. Whereas for command mode, it - * doesnt get cleared until first idle power collapse. We need to make - * sure that we save and restore the divider settings when dynamic FPS - * is triggered. - */ - if (!pll->handoff_resources || pll->dfps_trigger) { - pll->cached_cfg0 = DSI_PLL_REG_R(pll->phy_base, - PHY_CMN_CLK_CFG0); - pll->cached_outdiv = DSI_PLL_REG_R(pll->pll_base, - PLL_PLL_OUTDIV_RATE); - pr_debug("cfg0=%d,cfg1=%d, outdiv=%d\n", pll->cached_cfg0, - pll->cached_cfg1, pll->cached_outdiv); - - pll->vco_cached_rate = clk_get_rate(hw->clk); - } - - /* - * When continuous splash screen feature is enabled, we need to cache - * the mux configuration for the pixel_clk_src mux clock. The clock - * framework does not call back to re-configure the mux value if it is - * does not change.For such usecases, we need to ensure that the cached - * value is programmed prior to PLL being locked - */ - if (pll->handoff_resources) { - pll->cached_cfg1 = DSI_PLL_REG_R(pll->phy_base, - PHY_CMN_CLK_CFG1); - if (pll->slave) - pll->slave->cached_cfg1 = - DSI_PLL_REG_R(pll->slave->phy_base, - PHY_CMN_CLK_CFG1); - } - - dsi_pll_disable(vco); -} - -static int vco_5nm_prepare(struct clk_hw *hw) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *pll = vco->priv; - - if (!pll) { - pr_err("dsi pll resources are not available\n"); - return -EINVAL; - } - - /* Skip vco recalculation for continuous splash use case */ - if (pll->handoff_resources) { - pll->pll_on = true; - return 0; - } - - if ((pll->vco_cached_rate != 0) && - (pll->vco_cached_rate == clk_hw_get_rate(hw))) { - rc = vco_5nm_set_rate(hw, pll->vco_cached_rate, - pll->vco_cached_rate); - if (rc) { - pr_err("pll(%d) set_rate failed, rc=%d\n", - pll->index, rc); - return rc; - } - pr_debug("cfg0=%d, cfg1=%d\n", pll->cached_cfg0, - pll->cached_cfg1); - DSI_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, - pll->cached_cfg0); - if (pll->slave) - DSI_PLL_REG_W(pll->slave->phy_base, PHY_CMN_CLK_CFG0, - pll->cached_cfg0); - DSI_PLL_REG_W(pll->pll_base, PLL_PLL_OUTDIV_RATE, - pll->cached_outdiv); - } - - rc = dsi_pll_enable(vco); return rc; } -static unsigned long vco_5nm_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) +int dsi_pll_5nm_configure(void *pll, bool commit) { + int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct dsi_pll_resource *pll = vco->priv; + struct dsi_pll_resource *rsc = (struct dsi_pll_resource *)pll; - if (!vco->priv) { - pr_err("vco priv is null\n"); - return 0; - } - - if (!pll->priv) { - pr_err("pll priv is null\n"); - return 0; - } - /* - * In the case when vco arte is set, the recalculation function should - * return the current rate as to avoid trying to set the vco rate - * again. However durng handoff, recalculation should set the flag - * according to the status of PLL. - */ - if (pll->vco_current_rate != 0) { - pr_debug("returning vco rate = %lld\n", pll->vco_current_rate); - return pll->vco_current_rate; - } - - pll->handoff_resources = true; - - - if (!dsi_pll_5nm_get_gdsc_status(pll)) { - pll->handoff_resources = false; - pr_err("Hand_off_resources not needed since gdsc is off\n"); - return 0; - } - - dsi_pll_detect_phy_mode(pll->priv, pll); - - if (dsi_pll_5nm_lock_status(pll)) { - pr_err("PLL not enabled\n"); - pll->handoff_resources = false; - } - pr_err("handoff_resources %s\n", pll->handoff_resources ? "true" : "false"); - - return rc; -} - -static int pixel_clk_get_div(void *context, unsigned int reg, unsigned int *div) -{ - struct dsi_pll_resource *pll = context; - u32 reg_val; - - reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - *div = (reg_val & 0xF0) >> 4; - - return 0; -} - -static void pixel_clk_set_div_sub(struct dsi_pll_resource *pll, int div) -{ - u32 reg_val; - - reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - reg_val &= ~0xF0; - reg_val |= (div << 4); - DSI_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, reg_val); - - /* - * cache the current parent index for cases where parent - * is not changing but rate is changing. In that case - * clock framework won't call parent_set and hence dsiclk_sel - * bit won't be programmed. e.g. dfps update use case. - */ - pll->cached_cfg0 = reg_val; -} - -static int pixel_clk_set_div(void *context, unsigned int reg, unsigned int div) -{ - struct dsi_pll_resource *pll = context; - - pixel_clk_set_div_sub(pll, div); - if (pll->slave) - pixel_clk_set_div_sub(pll->slave, div); - - return 0; -} - -static int bit_clk_get_div(void *context, unsigned int reg, unsigned int *div) -{ - struct dsi_pll_resource *pll = context; - u32 reg_val; - - reg_val = DSI_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - *div = (reg_val & 0x0F); - - return 0; -} - -static void bit_clk_set_div_sub(struct dsi_pll_resource *rsc, int div) -{ - u32 reg_val; - - reg_val = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG0); - reg_val &= ~0x0F; - reg_val |= div; - DSI_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG0, reg_val); -} - -static int bit_clk_set_div(void *context, unsigned int reg, unsigned int div) -{ - struct dsi_pll_resource *rsc = context; - - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - bit_clk_set_div_sub(rsc, div); - /* For slave PLL, this divider always should be set to 1 */ + /* PLL power needs to be enabled before accessing PLL registers */ + dsi_pll_enable_pll_bias(rsc); if (rsc->slave) - bit_clk_set_div_sub(rsc->slave, 1); + dsi_pll_enable_pll_bias(rsc->slave); + + dsi_pll_init_val(rsc); + + rc = dsi_pll_5nm_set_byteclk_div(rsc, commit); + + if (commit) { + rc = dsi_pll_5nm_set_pclk_div(rsc, commit); + rc = dsi_pll_5nm_vco_set_rate(rsc); + } else { + rc = dsi_pll_5nm_dynamic_clk_vco_set_rate(rsc); + } return 0; } -static struct regmap_config dsi_pll_5nm_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x7c0, -}; - -static struct regmap_bus pll_regmap_bus = { - .reg_write = pll_reg_write, - .reg_read = pll_reg_read, -}; - -static struct regmap_bus pclk_src_mux_regmap_bus = { - .reg_read = pclk_mux_read_sel, - .reg_write = pclk_mux_write_sel, -}; - -static struct regmap_bus cphy_pclk_src_mux_regmap_bus = { - .reg_read = cphy_pclk_mux_read_sel, - .reg_write = cphy_pclk_mux_write_sel, -}; - -static struct regmap_bus pclk_src_regmap_bus = { - .reg_write = pixel_clk_set_div, - .reg_read = pixel_clk_get_div, -}; - -static struct regmap_bus bitclk_src_regmap_bus = { - .reg_write = bit_clk_set_div, - .reg_read = bit_clk_get_div, -}; - -static const struct clk_ops clk_ops_vco_5nm = { - .recalc_rate = vco_5nm_recalc_rate, - .set_rate = vco_5nm_set_rate, - .round_rate = vco_5nm_round_rate, - .prepare = vco_5nm_prepare, - .unprepare = vco_5nm_unprepare, -}; - -static const struct clk_ops clk_ops_shadow_vco_5nm = { - .recalc_rate = vco_5nm_recalc_rate, - .set_rate = shadow_vco_5nm_set_rate, - .round_rate = vco_5nm_round_rate, -}; - -static struct regmap_bus dsi_mux_regmap_bus = { - .reg_write = dsi_set_mux_sel, - .reg_read = dsi_get_mux_sel, -}; - -/* - * Clock tree for generating DSI byte and pclk. - * - * - * +---------------+ - * | vco_clk | - * +-------+-------+ - * | - * | - * +---------------+ - * | pll_out_div | - * | DIV(1,2,4,8) | - * +-------+-------+ - * | - * +-----------------------------+-------+---------------+ - * | | | | - * +-------v-------+ | | | - * | bitclk_src | | - * | DIV(1..15) | Not supported for DPHY | - * +-------+-------+ | - * | | | | - * +-------------v+---------+---------+ | | | - * | | | | | | | - * +-----v-----+ +-----v-----+ | +------v------+ | +-----v------+ +-----v------+ - * |byteclk_src| |byteclk_src| | |post_bit_div | | |post_vco_div| |post_vco_div| - * | DIV(8) | | DIV(7) | | | DIV (2) | | | DIV(4) | | DIV(3.5) | - * +-----+-----+ +-----+-----+ | +------+------+ | +-----+------+ +------+-----+ - * | | | | | | | - *Shadow Path | CPHY Path | | | | +----v - * + | | +------+ | | +---+ | - * +---+ | +-----+ | | | | | - * | | | +-v--v----v---v---+ +--------v--------+ - * +---v--v--------v---+ \ pclk_src_mux / \ cphy_pclk_src / - * \ byteclk_mux / \ / \ mux / - * \ / +-----+-----+ +-----+-----+ - * +------+------+ | Shadow Path | - * | | + | - * v +-----v------+ | +------v------+ - * dsi_byte_clk | pclk_src | | |cphy_pclk_src| - * | DIV(1..15) | | | DIV(1..15) | - * +-----+------+ | +------+------+ - * | | | - * | | CPHY Path - * | | | - * +-------+ | +-------+ - * | | | - * +---v---v----v------+ - * \ pclk_mux / - * +------+------+ - * | - * v - * dsi_pclk - * - */ - -static struct dsi_pll_vco_clk dsi0pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_5nm, - }, -}; - -static struct dsi_pll_vco_clk dsi0pll_shadow_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_shadow_vco_5nm, - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_5nm, - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_shadow_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_shadow_vco_5nm, - }, -}; - -static struct clk_regmap_div dsi0pll_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pll_out_div", - .parent_names = (const char *[]){"dsi0pll_vco_clk"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_shadow_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_pll_out_div", - .parent_names = (const char *[]){ - "dsi0pll_shadow_vco_clk"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pll_out_div", - .parent_names = (const char *[]){"dsi1pll_vco_clk"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_shadow_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_pll_out_div", - .parent_names = (const char *[]){ - "dsi1pll_shadow_vco_clk"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_bitclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_bitclk_src", - .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_shadow_bitclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_bitclk_src", - .parent_names = (const char *[]){ - "dsi0pll_shadow_pll_out_div"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_bitclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_bitclk_src", - .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_shadow_bitclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_bitclk_src", - .parent_names = (const char *[]){ - "dsi1pll_shadow_pll_out_div"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_fixed_factor dsi0pll_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_vco_div", - .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_post_vco_div", - .parent_names = (const char *[]){"dsi0pll_shadow_pll_out_div"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_vco_div", - .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_post_vco_div3_5 = { - .div = 7, - .mult = 2, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_vco_div3_5", - .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_post_vco_div3_5 = { - .div = 7, - .mult = 2, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_post_vco_div3_5", - .parent_names = (const char *[]){"dsi0pll_shadow_pll_out_div"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_post_vco_div3_5 = { - .div = 7, - .mult = 2, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_vco_div3_5", - .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_post_vco_div3_5 = { - .div = 7, - .mult = 2, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_post_vco_div3_5", - .parent_names = (const char *[]){"dsi1pll_shadow_pll_out_div"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_post_vco_div", - .parent_names = (const char *[]){"dsi1pll_shadow_pll_out_div"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_byteclk_src", - .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_byteclk_src", - .parent_names = (const char *[]){"dsi0pll_shadow_bitclk_src"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_byteclk_src", - .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_cphy_byteclk_src = { - .div = 7, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_cphy_byteclk_src", - .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_cphy_byteclk_src = { - .div = 7, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_cphy_byteclk_src", - .parent_names = (const char *[]){"dsi0pll_shadow_bitclk_src"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_cphy_byteclk_src = { - .div = 7, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_cphy_byteclk_src", - .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_cphy_byteclk_src = { - .div = 7, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_cphy_byteclk_src", - .parent_names = (const char *[]){"dsi1pll_shadow_bitclk_src"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_byteclk_src", - .parent_names = (const char *[]){"dsi1pll_shadow_bitclk_src"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_bit_div", - .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_post_bit_div", - .parent_names = (const char *[]){"dsi0pll_shadow_bitclk_src"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_bit_div", - .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_post_bit_div", - .parent_names = (const char *[]){"dsi1pll_shadow_bitclk_src"}, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_regmap_mux dsi0pll_byteclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_byteclk", - .parent_names = (const char *[]){"dsi0pll_byteclk_src", - "dsi0pll_shadow_byteclk_src", - "dsi0pll_cphy_byteclk_src", - "dsi0pll_shadow_cphy_byteclk_src"}, - .num_parents = 4, - .flags = (CLK_SET_RATE_PARENT | - CLK_SET_RATE_NO_REPARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_byteclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1_phy_pll_out_byteclk", - .parent_names = (const char *[]){"dsi1pll_byteclk_src", - "dsi1pll_shadow_byteclk_src", - "dsi1pll_cphy_byteclk_src", - "dsi1pll_shadow_cphy_byteclk_src"}, - .num_parents = 4, - .flags = (CLK_SET_RATE_PARENT | - CLK_SET_RATE_NO_REPARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src_mux", - .parent_names = (const char *[]){"dsi0pll_bitclk_src", - "dsi0pll_post_bit_div"}, - .num_parents = 2, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_shadow_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_pclk_src_mux", - .parent_names = (const char *[]){ - "dsi0pll_shadow_bitclk_src", - "dsi0pll_shadow_post_bit_div"}, - .num_parents = 2, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_cphy_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_cphy_pclk_src_mux", - .parent_names = - (const char *[]){"dsi0pll_post_vco_div3_5"}, - .num_parents = 1, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_shadow_cphy_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_cphy_pclk_src_mux", - .parent_names = - (const char *[]){ - "dsi0pll_shadow_post_vco_div3_5"}, - .num_parents = 1, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src_mux", - .parent_names = (const char *[]){"dsi1pll_bitclk_src", - "dsi1pll_post_bit_div"}, - .num_parents = 2, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_shadow_cphy_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_cphy_pclk_src_mux", - .parent_names = - (const char *[]){ - "dsi1pll_shadow_post_vco_div3_5"}, - .num_parents = 1, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_shadow_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_pclk_src_mux", - .parent_names = (const char *[]){ - "dsi1pll_shadow_bitclk_src", - "dsi1pll_shadow_post_bit_div"}, - .num_parents = 2, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_cphy_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_cphy_pclk_src_mux", - .parent_names = - (const char *[]){"dsi1pll_post_vco_div3_5"}, - .num_parents = 1, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_pclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src", - .parent_names = (const char *[]){ - "dsi0pll_pclk_src_mux"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_shadow_pclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_pclk_src", - .parent_names = (const char *[]){ - "dsi0pll_shadow_pclk_src_mux"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_cphy_pclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_cphy_pclk_src", - .parent_names = (const char *[]){ - "dsi0pll_cphy_pclk_src_mux"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_shadow_cphy_pclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_cphy_pclk_src", - .parent_names = (const char *[]){ - "dsi0pll_shadow_cphy_pclk_src_mux"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_pclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src", - .parent_names = (const char *[]){ - "dsi1pll_pclk_src_mux"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_shadow_pclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_pclk_src", - .parent_names = (const char *[]){ - "dsi1pll_shadow_pclk_src_mux"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_cphy_pclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_cphy_pclk_src", - .parent_names = (const char *[]){ - "dsi1pll_cphy_pclk_src_mux"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_shadow_cphy_pclk_src = { - .shift = 0, - .width = 4, - .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_cphy_pclk_src", - .parent_names = (const char *[]){ - "dsi1pll_shadow_cphy_pclk_src_mux"}, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_pclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_dsiclk", - .parent_names = (const char *[]){"dsi0pll_pclk_src", - "dsi0pll_shadow_pclk_src", - "dsi0pll_cphy_pclk_src", - "dsi0pll_shadow_cphy_pclk_src"}, - .num_parents = 4, - .flags = (CLK_SET_RATE_PARENT | - CLK_SET_RATE_NO_REPARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_pclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1_phy_pll_out_dsiclk", - .parent_names = (const char *[]){"dsi1pll_pclk_src", - "dsi1pll_shadow_pclk_src", - "dsi1pll_cphy_pclk_src", - "dsi1pll_shadow_cphy_pclk_src"}, - .num_parents = 4, - .flags = (CLK_SET_RATE_PARENT | - CLK_SET_RATE_NO_REPARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_hw *dsi_pllcc_5nm[] = { - [VCO_CLK_0] = &dsi0pll_vco_clk.hw, - [PLL_OUT_DIV_0_CLK] = &dsi0pll_pll_out_div.clkr.hw, - [BITCLK_SRC_0_CLK] = &dsi0pll_bitclk_src.clkr.hw, - [BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw, - [CPHY_BYTECLK_SRC_0_CLK] = &dsi0pll_cphy_byteclk_src.hw, - [POST_BIT_DIV_0_CLK] = &dsi0pll_post_bit_div.hw, - [POST_VCO_DIV_0_CLK] = &dsi0pll_post_vco_div.hw, - [POST_VCO_DIV3_5_0_CLK] = &dsi0pll_post_vco_div3_5.hw, - [BYTECLK_MUX_0_CLK] = &dsi0pll_byteclk_mux.clkr.hw, - [PCLK_SRC_MUX_0_CLK] = &dsi0pll_pclk_src_mux.clkr.hw, - [PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw, - [PCLK_MUX_0_CLK] = &dsi0pll_pclk_mux.clkr.hw, - [CPHY_PCLK_SRC_MUX_0_CLK] = &dsi0pll_cphy_pclk_src_mux.clkr.hw, - [CPHY_PCLK_SRC_0_CLK] = &dsi0pll_cphy_pclk_src.clkr.hw, - [SHADOW_VCO_CLK_0] = &dsi0pll_shadow_vco_clk.hw, - [SHADOW_PLL_OUT_DIV_0_CLK] = &dsi0pll_shadow_pll_out_div.clkr.hw, - [SHADOW_BITCLK_SRC_0_CLK] = &dsi0pll_shadow_bitclk_src.clkr.hw, - [SHADOW_BYTECLK_SRC_0_CLK] = &dsi0pll_shadow_byteclk_src.hw, - [SHADOW_CPHY_BYTECLK_SRC_0_CLK] = &dsi0pll_shadow_cphy_byteclk_src.hw, - [SHADOW_POST_BIT_DIV_0_CLK] = &dsi0pll_shadow_post_bit_div.hw, - [SHADOW_POST_VCO_DIV_0_CLK] = &dsi0pll_shadow_post_vco_div.hw, - [SHADOW_POST_VCO_DIV3_5_0_CLK] = &dsi0pll_shadow_post_vco_div3_5.hw, - [SHADOW_PCLK_SRC_MUX_0_CLK] = &dsi0pll_shadow_pclk_src_mux.clkr.hw, - [SHADOW_PCLK_SRC_0_CLK] = &dsi0pll_shadow_pclk_src.clkr.hw, - [SHADOW_CPHY_PCLK_SRC_MUX_0_CLK] = - &dsi0pll_shadow_cphy_pclk_src_mux.clkr.hw, - [SHADOW_CPHY_PCLK_SRC_0_CLK] = &dsi0pll_shadow_cphy_pclk_src.clkr.hw, - [VCO_CLK_1] = &dsi1pll_vco_clk.hw, - [PLL_OUT_DIV_1_CLK] = &dsi1pll_pll_out_div.clkr.hw, - [BITCLK_SRC_1_CLK] = &dsi1pll_bitclk_src.clkr.hw, - [BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw, - [CPHY_BYTECLK_SRC_1_CLK] = &dsi1pll_cphy_byteclk_src.hw, - [POST_BIT_DIV_1_CLK] = &dsi1pll_post_bit_div.hw, - [POST_VCO_DIV_1_CLK] = &dsi1pll_post_vco_div.hw, - [POST_VCO_DIV3_5_1_CLK] = &dsi1pll_post_vco_div3_5.hw, - [BYTECLK_MUX_1_CLK] = &dsi1pll_byteclk_mux.clkr.hw, - [PCLK_SRC_MUX_1_CLK] = &dsi1pll_pclk_src_mux.clkr.hw, - [PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw, - [PCLK_MUX_1_CLK] = &dsi1pll_pclk_mux.clkr.hw, - [CPHY_PCLK_SRC_MUX_1_CLK] = &dsi1pll_cphy_pclk_src_mux.clkr.hw, - [CPHY_PCLK_SRC_1_CLK] = &dsi1pll_cphy_pclk_src.clkr.hw, - [SHADOW_VCO_CLK_1] = &dsi1pll_shadow_vco_clk.hw, - [SHADOW_PLL_OUT_DIV_1_CLK] = &dsi1pll_shadow_pll_out_div.clkr.hw, - [SHADOW_BITCLK_SRC_1_CLK] = &dsi1pll_shadow_bitclk_src.clkr.hw, - [SHADOW_BYTECLK_SRC_1_CLK] = &dsi1pll_shadow_byteclk_src.hw, - [SHADOW_CPHY_BYTECLK_SRC_1_CLK] = &dsi1pll_shadow_cphy_byteclk_src.hw, - [SHADOW_POST_BIT_DIV_1_CLK] = &dsi1pll_shadow_post_bit_div.hw, - [SHADOW_POST_VCO_DIV_1_CLK] = &dsi1pll_shadow_post_vco_div.hw, - [SHADOW_POST_VCO_DIV3_5_1_CLK] = &dsi1pll_shadow_post_vco_div3_5.hw, - [SHADOW_PCLK_SRC_MUX_1_CLK] = &dsi1pll_shadow_pclk_src_mux.clkr.hw, - [SHADOW_PCLK_SRC_1_CLK] = &dsi1pll_shadow_pclk_src.clkr.hw, - [SHADOW_CPHY_PCLK_SRC_MUX_1_CLK] = - &dsi1pll_shadow_cphy_pclk_src_mux.clkr.hw, - [SHADOW_CPHY_PCLK_SRC_1_CLK] = &dsi1pll_shadow_cphy_pclk_src.clkr.hw, -}; - -int dsi_pll_clock_register_5nm(struct platform_device *pdev, - struct dsi_pll_resource *pll_res) +int dsi_pll_5nm_toggle(void *pll, bool prepare) { - int rc = 0, ndx, i; - struct clk *clk; - struct clk_onecell_data *clk_data; - int num_clks = ARRAY_SIZE(dsi_pllcc_5nm); - struct regmap *rmap; - struct regmap_config *rmap_config; + int rc = 0; + struct dsi_pll_resource *pll_res = (struct dsi_pll_resource *)pll; - if (!pdev || !pdev->dev.of_node || - !pll_res || !pll_res->pll_base || !pll_res->phy_base) { - pr_err("Invalid params\n"); + if (!pll_res) { + DSI_PLL_ERR(pll_res, "dsi pll resources are not available\n"); return -EINVAL; } - ndx = pll_res->index; - - if (ndx >= DSI_PLL_MAX) { - pr_err("pll index(%d) NOT supported\n", ndx); - return -EINVAL; - } - - pll_rsc_db[ndx] = pll_res; - plls[ndx].rsc = pll_res; - pll_res->priv = &plls[ndx]; - pll_res->vco_delay = VCO_DELAY_USEC; - - clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data), - GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kzalloc(&pdev->dev, (num_clks * - sizeof(struct clk *)), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - - clk_data->clk_num = num_clks; - - rmap_config = devm_kmemdup(&pdev->dev, &dsi_pll_5nm_config, - sizeof(struct regmap_config), GFP_KERNEL); - if (!rmap_config) - return -ENOMEM; - - /* Establish client data */ - if (ndx == 0) { - rmap_config->name = "pll_out"; - rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus, - pll_res, rmap_config); - dsi0pll_pll_out_div.clkr.regmap = rmap; - dsi0pll_shadow_pll_out_div.clkr.regmap = rmap; - - rmap_config->name = "bitclk_src"; - rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus, - pll_res, rmap_config); - dsi0pll_bitclk_src.clkr.regmap = rmap; - dsi0pll_shadow_bitclk_src.clkr.regmap = rmap; - - rmap_config->name = "pclk_src"; - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, rmap_config); - dsi0pll_pclk_src.clkr.regmap = rmap; - dsi0pll_cphy_pclk_src.clkr.regmap = rmap; - dsi0pll_shadow_pclk_src.clkr.regmap = rmap; - dsi0pll_shadow_cphy_pclk_src.clkr.regmap = rmap; - - rmap_config->name = "pclk_mux"; - rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, rmap_config); - dsi0pll_pclk_mux.clkr.regmap = rmap; - - rmap_config->name = "pclk_src_mux"; - rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, - pll_res, rmap_config); - dsi0pll_pclk_src_mux.clkr.regmap = rmap; - dsi0pll_shadow_pclk_src_mux.clkr.regmap = rmap; - - rmap_config->name = "cphy_pclk_src_mux"; - rmap = devm_regmap_init(&pdev->dev, - &cphy_pclk_src_mux_regmap_bus, - pll_res, rmap_config); - dsi0pll_cphy_pclk_src_mux.clkr.regmap = rmap; - dsi0pll_shadow_cphy_pclk_src_mux.clkr.regmap = rmap; - - rmap_config->name = "byteclk_mux"; - rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, rmap_config); - dsi0pll_byteclk_mux.clkr.regmap = rmap; - - dsi0pll_vco_clk.priv = pll_res; - dsi0pll_shadow_vco_clk.priv = pll_res; - - if (dsi_pll_5nm_is_hw_revision(pll_res)) { - dsi0pll_vco_clk.min_rate = 600000000; - dsi0pll_vco_clk.max_rate = 5000000000; - dsi0pll_shadow_vco_clk.min_rate = 600000000; - dsi0pll_shadow_vco_clk.max_rate = 5000000000; - } - - for (i = VCO_CLK_0; i <= SHADOW_CPHY_PCLK_SRC_0_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - dsi_pllcc_5nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); + if (prepare) { + rc = dsi_pll_5nm_enable(pll_res); + if (rc) + DSI_PLL_ERR(pll_res, "enable failed: %d\n", rc); } else { - rmap_config->name = "pll_out"; - rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus, - pll_res, rmap_config); - dsi1pll_pll_out_div.clkr.regmap = rmap; - dsi1pll_shadow_pll_out_div.clkr.regmap = rmap; - - rmap_config->name = "bitclk_src"; - rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus, - pll_res, rmap_config); - dsi1pll_bitclk_src.clkr.regmap = rmap; - dsi1pll_shadow_bitclk_src.clkr.regmap = rmap; - - rmap_config->name = "pclk_src"; - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, rmap_config); - dsi1pll_pclk_src.clkr.regmap = rmap; - dsi1pll_cphy_pclk_src.clkr.regmap = rmap; - dsi1pll_shadow_pclk_src.clkr.regmap = rmap; - dsi1pll_shadow_cphy_pclk_src.clkr.regmap = rmap; - - rmap_config->name = "pclk_mux"; - rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, rmap_config); - dsi1pll_pclk_mux.clkr.regmap = rmap; - - rmap_config->name = "pclk_src_mux"; - rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, - pll_res, rmap_config); - dsi1pll_pclk_src_mux.clkr.regmap = rmap; - dsi1pll_shadow_pclk_src_mux.clkr.regmap = rmap; - dsi1pll_shadow_cphy_pclk_src_mux.clkr.regmap = rmap; - - rmap_config->name = "cphy_pclk_src_mux"; - rmap = devm_regmap_init(&pdev->dev, - &cphy_pclk_src_mux_regmap_bus, - pll_res, rmap_config); - dsi1pll_cphy_pclk_src_mux.clkr.regmap = rmap; - - rmap_config->name = "byteclk_mut"; - rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, rmap_config); - dsi1pll_byteclk_mux.clkr.regmap = rmap; - - dsi1pll_vco_clk.priv = pll_res; - dsi1pll_shadow_vco_clk.priv = pll_res; - - if (dsi_pll_5nm_is_hw_revision(pll_res)) { - dsi1pll_vco_clk.min_rate = 600000000; - dsi1pll_vco_clk.max_rate = 5000000000; - dsi1pll_shadow_vco_clk.min_rate = 600000000; - dsi1pll_shadow_vco_clk.max_rate = 5000000000; - } - - for (i = VCO_CLK_1; i <= CPHY_PCLK_SRC_1_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - dsi_pllcc_5nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); + rc = dsi_pll_5nm_disable(pll_res); + if (rc) + DSI_PLL_ERR(pll_res, "disable failed: %d\n", rc); } - if (!rc) { - pr_info("Registered DSI PLL ndx=%d, clocks successfully\n", - ndx); - return rc; - } -clk_register_fail: return rc; } diff --git a/msm/dsi/dsi_pll_5nm.h b/msm/dsi/dsi_pll_5nm.h new file mode 100644 index 0000000000..113a9cdc85 --- /dev/null +++ b/msm/dsi/dsi_pll_5nm.h @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include "dsi_pll.h" + +/* Register Offsets from PLL base address */ +#define PLL_ANALOG_CONTROLS_ONE 0x0000 +#define PLL_ANALOG_CONTROLS_TWO 0x0004 +#define PLL_INT_LOOP_SETTINGS 0x0008 +#define PLL_INT_LOOP_SETTINGS_TWO 0x000C +#define PLL_ANALOG_CONTROLS_THREE 0x0010 +#define PLL_ANALOG_CONTROLS_FOUR 0x0014 +#define PLL_ANALOG_CONTROLS_FIVE 0x0018 +#define PLL_INT_LOOP_CONTROLS 0x001C +#define PLL_DSM_DIVIDER 0x0020 +#define PLL_FEEDBACK_DIVIDER 0x0024 +#define PLL_SYSTEM_MUXES 0x0028 +#define PLL_FREQ_UPDATE_CONTROL_OVERRIDES 0x002C +#define PLL_CMODE 0x0030 +#define PLL_PSM_CTRL 0x0034 +#define PLL_RSM_CTRL 0x0038 +#define PLL_VCO_TUNE_MAP 0x003C +#define PLL_PLL_CNTRL 0x0040 +#define PLL_CALIBRATION_SETTINGS 0x0044 +#define PLL_BAND_SEL_CAL_TIMER_LOW 0x0048 +#define PLL_BAND_SEL_CAL_TIMER_HIGH 0x004C +#define PLL_BAND_SEL_CAL_SETTINGS 0x0050 +#define PLL_BAND_SEL_MIN 0x0054 +#define PLL_BAND_SEL_MAX 0x0058 +#define PLL_BAND_SEL_PFILT 0x005C +#define PLL_BAND_SEL_IFILT 0x0060 +#define PLL_BAND_SEL_CAL_SETTINGS_TWO 0x0064 +#define PLL_BAND_SEL_CAL_SETTINGS_THREE 0x0068 +#define PLL_BAND_SEL_CAL_SETTINGS_FOUR 0x006C +#define PLL_BAND_SEL_ICODE_HIGH 0x0070 +#define PLL_BAND_SEL_ICODE_LOW 0x0074 +#define PLL_FREQ_DETECT_SETTINGS_ONE 0x0078 +#define PLL_FREQ_DETECT_THRESH 0x007C +#define PLL_FREQ_DET_REFCLK_HIGH 0x0080 +#define PLL_FREQ_DET_REFCLK_LOW 0x0084 +#define PLL_FREQ_DET_PLLCLK_HIGH 0x0088 +#define PLL_FREQ_DET_PLLCLK_LOW 0x008C +#define PLL_PFILT 0x0090 +#define PLL_IFILT 0x0094 +#define PLL_PLL_GAIN 0x0098 +#define PLL_ICODE_LOW 0x009C +#define PLL_ICODE_HIGH 0x00A0 +#define PLL_LOCKDET 0x00A4 +#define PLL_OUTDIV 0x00A8 +#define PLL_FASTLOCK_CONTROL 0x00AC +#define PLL_PASS_OUT_OVERRIDE_ONE 0x00B0 +#define PLL_PASS_OUT_OVERRIDE_TWO 0x00B4 +#define PLL_CORE_OVERRIDE 0x00B8 +#define PLL_CORE_INPUT_OVERRIDE 0x00BC +#define PLL_RATE_CHANGE 0x00C0 +#define PLL_PLL_DIGITAL_TIMERS 0x00C4 +#define PLL_PLL_DIGITAL_TIMERS_TWO 0x00C8 +#define PLL_DECIMAL_DIV_START 0x00CC +#define PLL_FRAC_DIV_START_LOW 0x00D0 +#define PLL_FRAC_DIV_START_MID 0x00D4 +#define PLL_FRAC_DIV_START_HIGH 0x00D8 +#define PLL_DEC_FRAC_MUXES 0x00DC +#define PLL_DECIMAL_DIV_START_1 0x00E0 +#define PLL_FRAC_DIV_START_LOW_1 0x00E4 +#define PLL_FRAC_DIV_START_MID_1 0x00E8 +#define PLL_FRAC_DIV_START_HIGH_1 0x00EC +#define PLL_DECIMAL_DIV_START_2 0x00F0 +#define PLL_FRAC_DIV_START_LOW_2 0x00F4 +#define PLL_FRAC_DIV_START_MID_2 0x00F8 +#define PLL_FRAC_DIV_START_HIGH_2 0x00FC +#define PLL_MASH_CONTROL 0x0100 +#define PLL_SSC_STEPSIZE_LOW 0x0104 +#define PLL_SSC_STEPSIZE_HIGH 0x0108 +#define PLL_SSC_DIV_PER_LOW 0x010C +#define PLL_SSC_DIV_PER_HIGH 0x0110 +#define PLL_SSC_ADJPER_LOW 0x0114 +#define PLL_SSC_ADJPER_HIGH 0x0118 +#define PLL_SSC_MUX_CONTROL 0x011C +#define PLL_SSC_STEPSIZE_LOW_1 0x0120 +#define PLL_SSC_STEPSIZE_HIGH_1 0x0124 +#define PLL_SSC_DIV_PER_LOW_1 0x0128 +#define PLL_SSC_DIV_PER_HIGH_1 0x012C +#define PLL_SSC_ADJPER_LOW_1 0x0130 +#define PLL_SSC_ADJPER_HIGH_1 0x0134 +#define PLL_SSC_STEPSIZE_LOW_2 0x0138 +#define PLL_SSC_STEPSIZE_HIGH_2 0x013C +#define PLL_SSC_DIV_PER_LOW_2 0x0140 +#define PLL_SSC_DIV_PER_HIGH_2 0x0144 +#define PLL_SSC_ADJPER_LOW_2 0x0148 +#define PLL_SSC_ADJPER_HIGH_2 0x014C +#define PLL_SSC_CONTROL 0x0150 +#define PLL_PLL_OUTDIV_RATE 0x0154 +#define PLL_PLL_LOCKDET_RATE_1 0x0158 +#define PLL_PLL_LOCKDET_RATE_2 0x015C +#define PLL_PLL_PROP_GAIN_RATE_1 0x0160 +#define PLL_PLL_PROP_GAIN_RATE_2 0x0164 +#define PLL_PLL_BAND_SEL_RATE_1 0x0168 +#define PLL_PLL_BAND_SEL_RATE_2 0x016C +#define PLL_PLL_INT_GAIN_IFILT_BAND_1 0x0170 +#define PLL_PLL_INT_GAIN_IFILT_BAND_2 0x0174 +#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x0178 +#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_2 0x017C +#define PLL_PLL_FASTLOCK_EN_BAND 0x0180 +#define PLL_FREQ_TUNE_ACCUM_INIT_MID 0x0184 +#define PLL_FREQ_TUNE_ACCUM_INIT_HIGH 0x0188 +#define PLL_FREQ_TUNE_ACCUM_INIT_MUX 0x018C +#define PLL_PLL_LOCK_OVERRIDE 0x0190 +#define PLL_PLL_LOCK_DELAY 0x0194 +#define PLL_PLL_LOCK_MIN_DELAY 0x0198 +#define PLL_CLOCK_INVERTERS 0x019C +#define PLL_SPARE_AND_JPC_OVERRIDES 0x01A0 +#define PLL_BIAS_CONTROL_1 0x01A4 +#define PLL_BIAS_CONTROL_2 0x01A8 +#define PLL_ALOG_OBSV_BUS_CTRL_1 0x01AC +#define PLL_COMMON_STATUS_ONE 0x01B0 +#define PLL_COMMON_STATUS_TWO 0x01B4 +#define PLL_BAND_SEL_CAL 0x01B8 +#define PLL_ICODE_ACCUM_STATUS_LOW 0x01BC +#define PLL_ICODE_ACCUM_STATUS_HIGH 0x01C0 +#define PLL_FD_OUT_LOW 0x01C4 +#define PLL_FD_OUT_HIGH 0x01C8 +#define PLL_ALOG_OBSV_BUS_STATUS_1 0x01CC +#define PLL_PLL_MISC_CONFIG 0x01D0 +#define PLL_FLL_CONFIG 0x01D4 +#define PLL_FLL_FREQ_ACQ_TIME 0x01D8 +#define PLL_FLL_CODE0 0x01DC +#define PLL_FLL_CODE1 0x01E0 +#define PLL_FLL_GAIN0 0x01E4 +#define PLL_FLL_GAIN1 0x01E8 +#define PLL_SW_RESET 0x01EC +#define PLL_FAST_PWRUP 0x01F0 +#define PLL_LOCKTIME0 0x01F4 +#define PLL_LOCKTIME1 0x01F8 +#define PLL_DEBUG_BUS_SEL 0x01FC +#define PLL_DEBUG_BUS0 0x0200 +#define PLL_DEBUG_BUS1 0x0204 +#define PLL_DEBUG_BUS2 0x0208 +#define PLL_DEBUG_BUS3 0x020C +#define PLL_ANALOG_FLL_CONTROL_OVERRIDES 0x0210 +#define PLL_VCO_CONFIG 0x0214 +#define PLL_VCO_CAL_CODE1_MODE0_STATUS 0x0218 +#define PLL_VCO_CAL_CODE1_MODE1_STATUS 0x021C +#define PLL_RESET_SM_STATUS 0x0220 +#define PLL_TDC_OFFSET 0x0224 +#define PLL_PS3_PWRDOWN_CONTROLS 0x0228 +#define PLL_PS4_PWRDOWN_CONTROLS 0x022C +#define PLL_PLL_RST_CONTROLS 0x0230 +#define PLL_GEAR_BAND_SELECT_CONTROLS 0x0234 +#define PLL_PSM_CLK_CONTROLS 0x0238 +#define PLL_SYSTEM_MUXES_2 0x023C +#define PLL_VCO_CONFIG_1 0x0240 +#define PLL_VCO_CONFIG_2 0x0244 +#define PLL_CLOCK_INVERTERS_1 0x0248 +#define PLL_CLOCK_INVERTERS_2 0x024C +#define PLL_CMODE_1 0x0250 +#define PLL_CMODE_2 0x0254 +#define PLL_ANALOG_CONTROLS_FIVE_1 0x0258 +#define PLL_ANALOG_CONTROLS_FIVE_2 0x025C +#define PLL_PERF_OPTIMIZE 0x0260 + +/* Register Offsets from PHY base address */ +#define PHY_CMN_CLK_CFG0 0x010 +#define PHY_CMN_CLK_CFG1 0x014 +#define PHY_CMN_GLBL_CTRL 0x018 +#define PHY_CMN_RBUF_CTRL 0x01C +#define PHY_CMN_CTRL_0 0x024 +#define PHY_CMN_CTRL_2 0x02C +#define PHY_CMN_CTRL_3 0x030 +#define PHY_CMN_PLL_CNTRL 0x03C +#define PHY_CMN_GLBL_DIGTOP_SPARE4 0x128 + +/* Bit definition of SSC control registers */ +#define SSC_CENTER BIT(0) +#define SSC_EN BIT(1) +#define SSC_FREQ_UPDATE BIT(2) +#define SSC_FREQ_UPDATE_MUX BIT(3) +#define SSC_UPDATE_SSC BIT(4) +#define SSC_UPDATE_SSC_MUX BIT(5) +#define SSC_START BIT(6) +#define SSC_START_MUX BIT(7) + +/* Dynamic Refresh Control Registers */ +#define DSI_DYNAMIC_REFRESH_PLL_CTRL0 (0x014) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL1 (0x018) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL2 (0x01C) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL3 (0x020) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL4 (0x024) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL5 (0x028) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL6 (0x02C) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL7 (0x030) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL8 (0x034) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL9 (0x038) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL10 (0x03C) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL11 (0x040) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL12 (0x044) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL13 (0x048) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL14 (0x04C) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL15 (0x050) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL16 (0x054) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL17 (0x058) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL18 (0x05C) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL19 (0x060) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL20 (0x064) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL21 (0x068) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL22 (0x06C) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL23 (0x070) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL24 (0x074) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL25 (0x078) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL26 (0x07C) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL27 (0x080) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL28 (0x084) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL29 (0x088) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL30 (0x08C) +#define DSI_DYNAMIC_REFRESH_PLL_CTRL31 (0x090) +#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR (0x094) +#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2 (0x098) + +#define DSI_PHY_TO_PLL_OFFSET (0x500) + +enum { + DSI_PLL_0, + DSI_PLL_1, + DSI_PLL_MAX +}; + +struct dsi_pll_div_table pll_5nm_dphy[] = { + {60000000, 86670000, 2, 5}, + {86670000, 97500000, 1, 9}, + {97500000, 111430000, 8, 1}, + {111430000, 130000000, 1, 7}, + {130000000, 156000000, 2, 3}, + {150000000, 195000000, 1, 5}, + {195000000, 260000000, 4, 1}, + {260000000, 390000000, 1, 3}, + {390000000, 780000000, 2, 1}, + {780000000, 3500000000, 1, 1} +}; + +struct dsi_pll_div_table pll_5nm_cphy[] = { + {60000000, 97500000, 2, 5}, + {97500000, 130000000, 8, 1}, + {130000000, 156000000, 2, 3}, + {156000000, 195000000, 1, 5}, + {195000000, 260000000, 4, 1}, + {260000000, 390000000, 1, 3}, + {390000000, 780000000, 2, 1}, + {780000000, 3500000000, 1, 1} +};