Merge "clk: qcom: Add the debug mux information for SM8150"

This commit is contained in:
qctecmdr 2020-11-15 17:44:56 -08:00 committed by Gerrit - the friendly Code Review server
commit 58329ca148
10 changed files with 8477 additions and 431 deletions

View File

@ -291,13 +291,78 @@ config SDM_LPASSCC_845
Say Y if you want to use the LPASS branch clocks of the LPASS clock
controller to reset the LPASS subsystem.
config SM_CAMCC_8150
tristate "SM8150 Camera Clock Controller"
select SM_GCC_8150
help
Support for the camera clock controller on Qualcomm Technologies, Inc
SM8150 devices.
Say Y if you want to support camera devices and functionality such as
capturing pictures.
config SM_DEBUGCC_8150
tristate "SM8150 Debug Clock Controller"
depends on COMMON_CLK_QCOM
help
Support for the debug clock controller on Qualcomm Technologies, Inc
SM8150 devices.
Say Y if you want to support the debug clocks such as
clock measurement functionality.
config SM_DISPCC_8150
tristate "SM8150 Display Clock Controller"
select SM_GCC_8150
help
Support for the display clock controller on Qualcomm Technologies, Inc
SM8150 devices.
Say Y if you want to support display devices and functionality such as
splash pictures.
config SM_GCC_8150
tristate "SM8150 Global Clock Controller"
depends on COMMON_CLK_QCOM
help
Support for the global clock controller on SM8150 devices.
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
config SM_GPUCC_8150
tristate "SM8150 Graphics Clock Controller"
select SM_GCC_8150
help
Support for the graphics clock controller on Qualcomm Technologies, Inc.
sm8150 devices.
Say Y if you want to support graphics controller devices and
functionality such as 3D graphics.
config SM_NPUCC_8150
tristate "SM8150 NPU Clock Controller"
select SM_GCC_8150
help
Support for the NPU Clock Controller on Qualcomm Technologies, Inc.
sm8150 devices.
Say Y if you want to enable use of the Network Processing Unit in
order to speed up certain types of calculations.
config SM_SCC_8150
tristate "SM8150 Sensor Clock Controller"
select SM_GCC_8150
help
Support for the sensor clock controller on Qualcomm Technologies, Inc.
SM8150 devices. The sensor controller contains several QUP clocks
which can be managed using DFS. This controller is typically owned by
the sensor processor. However, on some systems it is instead owned
by the application processor.
config SM_VIDEOCC_8150
tristate "SM8150 Video Clock Controller"
select SM_GCC_8150
help
Support for the video clock controller on Qualcomm Technologies, Inc.
SM8150 devices.
Say Y if you want to support video devices and functionality such as
video encode/decode.
config SPMI_PMIC_CLKDIV
tristate "SPMI PMIC clkdiv Support"
depends on SPMI || COMPILE_TEST

View File

@ -65,16 +65,23 @@ obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
obj-$(CONFIG_SDX_DEBUGCC_LEMUR) += debugcc-sdxlemur.o
obj-$(CONFIG_SDX_GCC_LEMUR) += gcc-sdxlemur.o
obj-$(CONFIG_SM_CAMCC_8150) += camcc-sm8150.o
obj-$(CONFIG_SM_CAMCC_SHIMA) += camcc-shima.o
obj-$(CONFIG_SM_DEBUGCC_8150) += debugcc-sm8150.o
obj-$(CONFIG_SM_DEBUGCC_HOLI) += debugcc-holi.o
obj-$(CONFIG_SM_DEBUGCC_SHIMA) += debugcc-shima.o
obj-$(CONFIG_SM_DISPCC_8150) += dispcc-sm8150.o
obj-$(CONFIG_SM_DISPCC_HOLI) += dispcc-holi.o
obj-$(CONFIG_SM_DISPCC_SHIMA) += dispcc-shima.o
obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
obj-$(CONFIG_SM_GCC_HOLI) += gcc-holi.o
obj-$(CONFIG_SM_GCC_SHIMA) += gcc-shima.o
obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
obj-$(CONFIG_SM_GPUCC_HOLI) += gpucc-holi.o
obj-$(CONFIG_SM_GPUCC_SHIMA) += gpucc-shima.o
obj-$(CONFIG_SM_NPUCC_8150) += npucc-sm8150.o
obj-$(CONFIG_SM_SCC_8150) += scc-sm8150.o
obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o
obj-$(CONFIG_SM_VIDEOCC_SHIMA) += videocc-shima.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,976 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "clk: %s: " fmt, __func__
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include "clk-debug.h"
#include "common.h"
static struct measure_clk_data debug_mux_priv = {
.ctl_reg = 0x62038,
.status_reg = 0x6203C,
.xo_div4_cbcr = 0x43008,
};
static const char *const cpu_cc_debug_mux_parent_names[] = {
"l3_clk",
"perfcl_clk",
"perfpcl_clk",
"pwrcl_clk",
};
static int cpu_cc_debug_mux_sels[] = {
0x41, /* l3_clk */
0x25, /* perfcl_clk */
0x61, /* perfpcl_clk */
0x21, /* pwrcl_clk */
};
static int apss_cc_debug_mux_pre_divs[] = {
0x4, /* l3_clk */
0x8, /* perfcl_clk */
0x8, /* perfpcl_clk */
0x4, /* pwrcl_clk */
};
static struct clk_debug_mux cpu_cc_debug_mux = {
.priv = &debug_mux_priv,
.debug_offset = 0x18,
.post_div_offset = 0x18,
.cbcr_offset = 0x0,
.src_sel_mask = 0x7F0,
.src_sel_shift = 4,
.post_div_mask = 0x7800,
.post_div_shift = 11,
.post_div_val = 1,
.mux_sels = cpu_cc_debug_mux_sels,
.pre_div_vals = apss_cc_debug_mux_pre_divs,
.hw.init = &(struct clk_init_data){
.name = "cpu_cc_debug_mux",
.ops = &clk_debug_mux_ops,
.parent_names = cpu_cc_debug_mux_parent_names,
.num_parents = ARRAY_SIZE(cpu_cc_debug_mux_parent_names),
.flags = CLK_IS_MEASURE,
},
};
static const char *const cam_cc_debug_mux_parent_names[] = {
"cam_cc_bps_ahb_clk",
"cam_cc_bps_areg_clk",
"cam_cc_bps_axi_clk",
"cam_cc_bps_clk",
"cam_cc_camnoc_axi_clk",
"cam_cc_camnoc_dcd_xo_clk",
"cam_cc_cci_0_clk",
"cam_cc_cci_1_clk",
"cam_cc_core_ahb_clk",
"cam_cc_cpas_ahb_clk",
"cam_cc_csi0phytimer_clk",
"cam_cc_csi1phytimer_clk",
"cam_cc_csi2phytimer_clk",
"cam_cc_csi3phytimer_clk",
"cam_cc_csiphy0_clk",
"cam_cc_csiphy1_clk",
"cam_cc_csiphy2_clk",
"cam_cc_csiphy3_clk",
"cam_cc_fd_core_clk",
"cam_cc_fd_core_uar_clk",
"cam_cc_gdsc_clk",
"cam_cc_icp_ahb_clk",
"cam_cc_icp_clk",
"cam_cc_ife_0_axi_clk",
"cam_cc_ife_0_clk",
"cam_cc_ife_0_cphy_rx_clk",
"cam_cc_ife_0_csid_clk",
"cam_cc_ife_0_dsp_clk",
"cam_cc_ife_1_axi_clk",
"cam_cc_ife_1_clk",
"cam_cc_ife_1_cphy_rx_clk",
"cam_cc_ife_1_csid_clk",
"cam_cc_ife_1_dsp_clk",
"cam_cc_ife_lite_0_clk",
"cam_cc_ife_lite_0_cphy_rx_clk",
"cam_cc_ife_lite_0_csid_clk",
"cam_cc_ife_lite_1_clk",
"cam_cc_ife_lite_1_cphy_rx_clk",
"cam_cc_ife_lite_1_csid_clk",
"cam_cc_ipe_0_ahb_clk",
"cam_cc_ipe_0_areg_clk",
"cam_cc_ipe_0_axi_clk",
"cam_cc_ipe_0_clk",
"cam_cc_ipe_1_ahb_clk",
"cam_cc_ipe_1_areg_clk",
"cam_cc_ipe_1_axi_clk",
"cam_cc_ipe_1_clk",
"cam_cc_jpeg_clk",
"cam_cc_lrme_clk",
"cam_cc_mclk0_clk",
"cam_cc_mclk1_clk",
"cam_cc_mclk2_clk",
"cam_cc_mclk3_clk",
};
static int cam_cc_debug_mux_sels[] = {
0xE, /* cam_cc_bps_ahb_clk */
0xD, /* cam_cc_bps_areg_clk */
0xC, /* cam_cc_bps_axi_clk */
0xB, /* cam_cc_bps_clk */
0x27, /* cam_cc_camnoc_axi_clk */
0x33, /* cam_cc_camnoc_dcd_xo_clk */
0x2A, /* cam_cc_cci_0_clk */
0x3B, /* cam_cc_cci_1_clk */
0x2E, /* cam_cc_core_ahb_clk */
0x2C, /* cam_cc_cpas_ahb_clk */
0x5, /* cam_cc_csi0phytimer_clk */
0x7, /* cam_cc_csi1phytimer_clk */
0x9, /* cam_cc_csi2phytimer_clk */
0x35, /* cam_cc_csi3phytimer_clk */
0x6, /* cam_cc_csiphy0_clk */
0x8, /* cam_cc_csiphy1_clk */
0xA, /* cam_cc_csiphy2_clk */
0x36, /* cam_cc_csiphy3_clk */
0x28, /* cam_cc_fd_core_clk */
0x29, /* cam_cc_fd_core_uar_clk */
0x3C, /* cam_cc_gdsc_clk */
0x37, /* cam_cc_icp_ahb_clk */
0x26, /* cam_cc_icp_clk */
0x1B, /* cam_cc_ife_0_axi_clk */
0x17, /* cam_cc_ife_0_clk */
0x1A, /* cam_cc_ife_0_cphy_rx_clk */
0x19, /* cam_cc_ife_0_csid_clk */
0x18, /* cam_cc_ife_0_dsp_clk */
0x21, /* cam_cc_ife_1_axi_clk */
0x1D, /* cam_cc_ife_1_clk */
0x20, /* cam_cc_ife_1_cphy_rx_clk */
0x1F, /* cam_cc_ife_1_csid_clk */
0x1E, /* cam_cc_ife_1_dsp_clk */
0x22, /* cam_cc_ife_lite_0_clk */
0x24, /* cam_cc_ife_lite_0_cphy_rx_clk */
0x23, /* cam_cc_ife_lite_0_csid_clk */
0x38, /* cam_cc_ife_lite_1_clk */
0x3A, /* cam_cc_ife_lite_1_cphy_rx_clk */
0x39, /* cam_cc_ife_lite_1_csid_clk */
0x12, /* cam_cc_ipe_0_ahb_clk */
0x11, /* cam_cc_ipe_0_areg_clk */
0x10, /* cam_cc_ipe_0_axi_clk */
0xF, /* cam_cc_ipe_0_clk */
0x16, /* cam_cc_ipe_1_ahb_clk */
0x15, /* cam_cc_ipe_1_areg_clk */
0x14, /* cam_cc_ipe_1_axi_clk */
0x13, /* cam_cc_ipe_1_clk */
0x25, /* cam_cc_jpeg_clk */
0x2B, /* cam_cc_lrme_clk */
0x1, /* cam_cc_mclk0_clk */
0x2, /* cam_cc_mclk1_clk */
0x3, /* cam_cc_mclk2_clk */
0x4, /* cam_cc_mclk3_clk */
};
static struct clk_debug_mux cam_cc_debug_mux = {
.priv = &debug_mux_priv,
.debug_offset = 0xD000,
.post_div_offset = 0xD004,
.cbcr_offset = 0xD008,
.src_sel_mask = 0xFF,
.src_sel_shift = 0,
.post_div_mask = 0xF,
.post_div_shift = 0,
.post_div_val = 4,
.mux_sels = cam_cc_debug_mux_sels,
.hw.init = &(struct clk_init_data){
.name = "cam_cc_debug_mux",
.ops = &clk_debug_mux_ops,
.parent_names = cam_cc_debug_mux_parent_names,
.num_parents = ARRAY_SIZE(cam_cc_debug_mux_parent_names),
.flags = CLK_IS_MEASURE,
},
};
static const char *const disp_cc_debug_mux_parent_names[] = {
"disp_cc_mdss_ahb_clk",
"disp_cc_mdss_byte0_clk",
"disp_cc_mdss_byte0_intf_clk",
"disp_cc_mdss_byte1_clk",
"disp_cc_mdss_byte1_intf_clk",
"disp_cc_mdss_dp_aux1_clk",
"disp_cc_mdss_dp_aux_clk",
"disp_cc_mdss_dp_crypto1_clk",
"disp_cc_mdss_dp_crypto_clk",
"disp_cc_mdss_dp_link1_clk",
"disp_cc_mdss_dp_link1_intf_clk",
"disp_cc_mdss_dp_link_clk",
"disp_cc_mdss_dp_link_intf_clk",
"disp_cc_mdss_dp_pixel1_clk",
"disp_cc_mdss_dp_pixel2_clk",
"disp_cc_mdss_dp_pixel_clk",
"disp_cc_mdss_edp_aux_clk",
"disp_cc_mdss_edp_gtc_clk",
"disp_cc_mdss_edp_link_clk",
"disp_cc_mdss_edp_link_intf_clk",
"disp_cc_mdss_edp_pixel_clk",
"disp_cc_mdss_esc0_clk",
"disp_cc_mdss_esc1_clk",
"disp_cc_mdss_mdp_clk",
"disp_cc_mdss_mdp_lut_clk",
"disp_cc_mdss_non_gdsc_ahb_clk",
"disp_cc_mdss_pclk0_clk",
"disp_cc_mdss_pclk1_clk",
"disp_cc_mdss_rot_clk",
"disp_cc_mdss_rscc_ahb_clk",
"disp_cc_mdss_rscc_vsync_clk",
"disp_cc_mdss_vsync_clk",
"disp_cc_xo_clk",
};
static int disp_cc_debug_mux_sels[] = {
0x2B, /* disp_cc_mdss_ahb_clk */
0x15, /* disp_cc_mdss_byte0_clk */
0x16, /* disp_cc_mdss_byte0_intf_clk */
0x17, /* disp_cc_mdss_byte1_clk */
0x18, /* disp_cc_mdss_byte1_intf_clk */
0x25, /* disp_cc_mdss_dp_aux1_clk */
0x20, /* disp_cc_mdss_dp_aux_clk */
0x24, /* disp_cc_mdss_dp_crypto1_clk */
0x1D, /* disp_cc_mdss_dp_crypto_clk */
0x22, /* disp_cc_mdss_dp_link1_clk */
0x23, /* disp_cc_mdss_dp_link1_intf_clk */
0x1B, /* disp_cc_mdss_dp_link_clk */
0x1C, /* disp_cc_mdss_dp_link_intf_clk */
0x1F, /* disp_cc_mdss_dp_pixel1_clk */
0x21, /* disp_cc_mdss_dp_pixel2_clk */
0x1E, /* disp_cc_mdss_dp_pixel_clk */
0x29, /* disp_cc_mdss_edp_aux_clk */
0x2A, /* disp_cc_mdss_edp_gtc_clk */
0x27, /* disp_cc_mdss_edp_link_clk */
0x28, /* disp_cc_mdss_edp_link_intf_clk */
0x26, /* disp_cc_mdss_edp_pixel_clk */
0x19, /* disp_cc_mdss_esc0_clk */
0x1A, /* disp_cc_mdss_esc1_clk */
0x11, /* disp_cc_mdss_mdp_clk */
0x13, /* disp_cc_mdss_mdp_lut_clk */
0x2C, /* disp_cc_mdss_non_gdsc_ahb_clk */
0xF, /* disp_cc_mdss_pclk0_clk */
0x10, /* disp_cc_mdss_pclk1_clk */
0x12, /* disp_cc_mdss_rot_clk */
0x2E, /* disp_cc_mdss_rscc_ahb_clk */
0x2D, /* disp_cc_mdss_rscc_vsync_clk */
0x14, /* disp_cc_mdss_vsync_clk */
0x36, /* disp_cc_xo_clk */
};
static struct clk_debug_mux disp_cc_debug_mux = {
.priv = &debug_mux_priv,
.debug_offset = 0x7000,
.post_div_offset = 0x5008,
.cbcr_offset = 0x500C,
.src_sel_mask = 0xFF,
.src_sel_shift = 0,
.post_div_mask = 0x3,
.post_div_shift = 0,
.post_div_val = 4,
.mux_sels = disp_cc_debug_mux_sels,
.hw.init = &(struct clk_init_data){
.name = "disp_cc_debug_mux",
.ops = &clk_debug_mux_ops,
.parent_names = disp_cc_debug_mux_parent_names,
.num_parents = ARRAY_SIZE(disp_cc_debug_mux_parent_names),
.flags = CLK_IS_MEASURE,
},
};
static const char *const gcc_debug_mux_parent_names[] = {
"cpu_cc_debug_mux",
"cam_cc_debug_mux",
"disp_cc_debug_mux",
"gcc_aggre_noc_pcie_tbu_clk",
"gcc_aggre_ufs_card_axi_clk",
"gcc_aggre_ufs_phy_axi_clk",
"gcc_aggre_usb3_prim_axi_clk",
"gcc_aggre_usb3_sec_axi_clk",
"gcc_boot_rom_ahb_clk",
"gcc_camera_ahb_clk",
"gcc_camera_hf_axi_clk",
"gcc_camera_sf_axi_clk",
"gcc_camera_xo_clk",
"gcc_cfg_noc_usb3_prim_axi_clk",
"gcc_cfg_noc_usb3_sec_axi_clk",
"gcc_cpuss_ahb_clk",
"gcc_cpuss_dvm_bus_clk",
"gcc_cpuss_gnoc_clk",
"gcc_cpuss_rbcpr_clk",
"gcc_ddrss_gpu_axi_clk",
"gcc_disp_ahb_clk",
"gcc_disp_hf_axi_clk",
"gcc_disp_sf_axi_clk",
"gcc_disp_xo_clk",
"gcc_emac_axi_clk",
"gcc_emac_ptp_clk",
"gcc_emac_rgmii_clk",
"gcc_emac_slv_ahb_clk",
"gcc_gp1_clk",
"gcc_gp2_clk",
"gcc_gp3_clk",
"gcc_gpu_cfg_ahb_clk",
"gcc_gpu_gpll0_clk_src",
"gcc_gpu_gpll0_div_clk_src",
"gcc_gpu_memnoc_gfx_clk",
"gcc_gpu_snoc_dvm_gfx_clk",
"gcc_npu_at_clk",
"gcc_npu_axi_clk",
"gcc_npu_cfg_ahb_clk",
"gcc_npu_gpll0_clk_src",
"gcc_npu_gpll0_div_clk_src",
"gcc_npu_trig_clk",
"gcc_pcie0_phy_refgen_clk",
"gcc_pcie1_phy_refgen_clk",
"gcc_pcie_0_aux_clk",
"gcc_pcie_0_cfg_ahb_clk",
"gcc_pcie_0_mstr_axi_clk",
"gcc_pcie_0_pipe_clk",
"gcc_pcie_0_slv_axi_clk",
"gcc_pcie_0_slv_q2a_axi_clk",
"gcc_pcie_1_aux_clk",
"gcc_pcie_1_cfg_ahb_clk",
"gcc_pcie_1_mstr_axi_clk",
"gcc_pcie_1_pipe_clk",
"gcc_pcie_1_slv_axi_clk",
"gcc_pcie_1_slv_q2a_axi_clk",
"gcc_pcie_phy_aux_clk",
"gcc_pdm2_clk",
"gcc_pdm_ahb_clk",
"gcc_pdm_xo4_clk",
"gcc_prng_ahb_clk",
"gcc_qmip_camera_nrt_ahb_clk",
"gcc_qmip_camera_rt_ahb_clk",
"gcc_qmip_disp_ahb_clk",
"gcc_qmip_video_cvp_ahb_clk",
"gcc_qmip_video_vcodec_ahb_clk",
"gcc_qspi_cnoc_periph_ahb_clk",
"gcc_qspi_core_clk",
"gcc_qupv3_wrap0_s0_clk",
"gcc_qupv3_wrap0_s1_clk",
"gcc_qupv3_wrap0_s2_clk",
"gcc_qupv3_wrap0_s3_clk",
"gcc_qupv3_wrap0_s4_clk",
"gcc_qupv3_wrap0_s5_clk",
"gcc_qupv3_wrap0_s6_clk",
"gcc_qupv3_wrap0_s7_clk",
"gcc_qupv3_wrap1_s0_clk",
"gcc_qupv3_wrap1_s1_clk",
"gcc_qupv3_wrap1_s2_clk",
"gcc_qupv3_wrap1_s3_clk",
"gcc_qupv3_wrap1_s4_clk",
"gcc_qupv3_wrap1_s5_clk",
"gcc_qupv3_wrap2_s0_clk",
"gcc_qupv3_wrap2_s1_clk",
"gcc_qupv3_wrap2_s2_clk",
"gcc_qupv3_wrap2_s3_clk",
"gcc_qupv3_wrap2_s4_clk",
"gcc_qupv3_wrap2_s5_clk",
"gcc_qupv3_wrap_0_m_ahb_clk",
"gcc_qupv3_wrap_0_s_ahb_clk",
"gcc_qupv3_wrap_1_m_ahb_clk",
"gcc_qupv3_wrap_1_s_ahb_clk",
"gcc_qupv3_wrap_2_m_ahb_clk",
"gcc_qupv3_wrap_2_s_ahb_clk",
"gcc_sdcc2_ahb_clk",
"gcc_sdcc2_apps_clk",
"gcc_sdcc4_ahb_clk",
"gcc_sdcc4_apps_clk",
"gcc_sys_noc_cpuss_ahb_clk",
"gcc_tsif_ahb_clk",
"gcc_tsif_inactivity_timers_clk",
"gcc_tsif_ref_clk",
"gcc_ufs_card_ahb_clk",
"gcc_ufs_card_axi_clk",
"gcc_ufs_card_ice_core_clk",
"gcc_ufs_card_phy_aux_clk",
"gcc_ufs_card_rx_symbol_0_clk",
"gcc_ufs_card_rx_symbol_1_clk",
"gcc_ufs_card_tx_symbol_0_clk",
"gcc_ufs_card_unipro_core_clk",
"gcc_ufs_phy_ahb_clk",
"gcc_ufs_phy_axi_clk",
"gcc_ufs_phy_ice_core_clk",
"gcc_ufs_phy_phy_aux_clk",
"gcc_ufs_phy_rx_symbol_0_clk",
"gcc_ufs_phy_rx_symbol_1_clk",
"gcc_ufs_phy_tx_symbol_0_clk",
"gcc_ufs_phy_unipro_core_clk",
"gcc_usb30_prim_master_clk",
"gcc_usb30_prim_mock_utmi_clk",
"gcc_usb30_prim_sleep_clk",
"gcc_usb30_sec_master_clk",
"gcc_usb30_sec_mock_utmi_clk",
"gcc_usb30_sec_sleep_clk",
"gcc_usb3_prim_phy_aux_clk",
"gcc_usb3_prim_phy_com_aux_clk",
"gcc_usb3_prim_phy_pipe_clk",
"gcc_usb3_sec_phy_aux_clk",
"gcc_usb3_sec_phy_com_aux_clk",
"gcc_usb3_sec_phy_pipe_clk",
"gcc_video_ahb_clk",
"gcc_video_axi0_clk",
"gcc_video_axi1_clk",
"gcc_video_axic_clk",
"gcc_video_xo_clk",
"gpu_cc_debug_mux",
"measure_only_cdsp_clk",
"measure_only_cnoc_clk",
"measure_only_ipa_2x_clk",
"measure_only_snoc_clk",
"npu_cc_debug_mux",
"video_cc_debug_mux",
"mc_cc_debug_mux",
};
static int gcc_debug_mux_sels[] = {
0xE8, /* cpu_cc_debug_mux */
0x55, /* cam_cc_debug_mux */
0x56, /* disp_cc_debug_mux */
0x36, /* gcc_aggre_noc_pcie_tbu_clk */
0x141, /* gcc_aggre_ufs_card_axi_clk */
0x140, /* gcc_aggre_ufs_phy_axi_clk */
0x13E, /* gcc_aggre_usb3_prim_axi_clk */
0x13F, /* gcc_aggre_usb3_sec_axi_clk */
0xA0, /* gcc_boot_rom_ahb_clk */
0x43, /* gcc_camera_ahb_clk */
0x4D, /* gcc_camera_hf_axi_clk */
0x4E, /* gcc_camera_sf_axi_clk */
0x52, /* gcc_camera_xo_clk */
0x22, /* gcc_cfg_noc_usb3_prim_axi_clk */
0x23, /* gcc_cfg_noc_usb3_sec_axi_clk */
0xE0, /* gcc_cpuss_ahb_clk */
0xE5, /* gcc_cpuss_dvm_bus_clk */
0xE1, /* gcc_cpuss_gnoc_clk */
0xE2, /* gcc_cpuss_rbcpr_clk */
0xC0, /* gcc_ddrss_gpu_axi_clk */
0x44, /* gcc_disp_ahb_clk */
0x4F, /* gcc_disp_hf_axi_clk */
0x50, /* gcc_disp_sf_axi_clk */
0x53, /* gcc_disp_xo_clk */
0x18D, /* gcc_emac_axi_clk */
0x190, /* gcc_emac_ptp_clk */
0x18F, /* gcc_emac_rgmii_clk */
0x18E, /* gcc_emac_slv_ahb_clk */
0xF0, /* gcc_gp1_clk */
0xF1, /* gcc_gp2_clk */
0xF2, /* gcc_gp3_clk */
0x160, /* gcc_gpu_cfg_ahb_clk */
0x166, /* gcc_gpu_gpll0_clk_src */
0x167, /* gcc_gpu_gpll0_div_clk_src */
0x163, /* gcc_gpu_memnoc_gfx_clk */
0x165, /* gcc_gpu_snoc_dvm_gfx_clk */
0x17D, /* gcc_npu_at_clk */
0x17B, /* gcc_npu_axi_clk */
0x17A, /* gcc_npu_cfg_ahb_clk */
0x17E, /* gcc_npu_gpll0_clk_src */
0x17F, /* gcc_npu_gpll0_div_clk_src */
0x17C, /* gcc_npu_trig_clk */
0x104, /* gcc_pcie0_phy_refgen_clk */
0x105, /* gcc_pcie1_phy_refgen_clk */
0xF7, /* gcc_pcie_0_aux_clk */
0xF6, /* gcc_pcie_0_cfg_ahb_clk */
0xF5, /* gcc_pcie_0_mstr_axi_clk */
0xF8, /* gcc_pcie_0_pipe_clk */
0xF4, /* gcc_pcie_0_slv_axi_clk */
0xF3, /* gcc_pcie_0_slv_q2a_axi_clk */
0xFF, /* gcc_pcie_1_aux_clk */
0xFE, /* gcc_pcie_1_cfg_ahb_clk */
0xFD, /* gcc_pcie_1_mstr_axi_clk */
0x100, /* gcc_pcie_1_pipe_clk */
0xFC, /* gcc_pcie_1_slv_axi_clk */
0xFB, /* gcc_pcie_1_slv_q2a_axi_clk */
0x103, /* gcc_pcie_phy_aux_clk */
0x9A, /* gcc_pdm2_clk */
0x98, /* gcc_pdm_ahb_clk */
0x99, /* gcc_pdm_xo4_clk */
0x9B, /* gcc_prng_ahb_clk */
0x47, /* gcc_qmip_camera_nrt_ahb_clk */
0x48, /* gcc_qmip_camera_rt_ahb_clk */
0x49, /* gcc_qmip_disp_ahb_clk */
0x45, /* gcc_qmip_video_cvp_ahb_clk */
0x46, /* gcc_qmip_video_vcodec_ahb_clk */
0x178, /* gcc_qspi_cnoc_periph_ahb_clk */
0x179, /* gcc_qspi_core_clk */
0x86, /* gcc_qupv3_wrap0_s0_clk */
0x87, /* gcc_qupv3_wrap0_s1_clk */
0x88, /* gcc_qupv3_wrap0_s2_clk */
0x89, /* gcc_qupv3_wrap0_s3_clk */
0x8A, /* gcc_qupv3_wrap0_s4_clk */
0x8B, /* gcc_qupv3_wrap0_s5_clk */
0x8C, /* gcc_qupv3_wrap0_s6_clk */
0x8D, /* gcc_qupv3_wrap0_s7_clk */
0x92, /* gcc_qupv3_wrap1_s0_clk */
0x93, /* gcc_qupv3_wrap1_s1_clk */
0x94, /* gcc_qupv3_wrap1_s2_clk */
0x95, /* gcc_qupv3_wrap1_s3_clk */
0x96, /* gcc_qupv3_wrap1_s4_clk */
0x97, /* gcc_qupv3_wrap1_s5_clk */
0x185, /* gcc_qupv3_wrap2_s0_clk */
0x186, /* gcc_qupv3_wrap2_s1_clk */
0x187, /* gcc_qupv3_wrap2_s2_clk */
0x188, /* gcc_qupv3_wrap2_s3_clk */
0x189, /* gcc_qupv3_wrap2_s4_clk */
0x18A, /* gcc_qupv3_wrap2_s5_clk */
0x82, /* gcc_qupv3_wrap_0_m_ahb_clk */
0x83, /* gcc_qupv3_wrap_0_s_ahb_clk */
0x8E, /* gcc_qupv3_wrap_1_m_ahb_clk */
0x8F, /* gcc_qupv3_wrap_1_s_ahb_clk */
0x181, /* gcc_qupv3_wrap_2_m_ahb_clk */
0x182, /* gcc_qupv3_wrap_2_s_ahb_clk */
0x7F, /* gcc_sdcc2_ahb_clk */
0x7E, /* gcc_sdcc2_apps_clk */
0x81, /* gcc_sdcc4_ahb_clk */
0x80, /* gcc_sdcc4_apps_clk */
0xC, /* gcc_sys_noc_cpuss_ahb_clk */
0x9C, /* gcc_tsif_ahb_clk */
0x9E, /* gcc_tsif_inactivity_timers_clk */
0x9D, /* gcc_tsif_ref_clk */
0x107, /* gcc_ufs_card_ahb_clk */
0x106, /* gcc_ufs_card_axi_clk */
0x10D, /* gcc_ufs_card_ice_core_clk */
0x10E, /* gcc_ufs_card_phy_aux_clk */
0x109, /* gcc_ufs_card_rx_symbol_0_clk */
0x10F, /* gcc_ufs_card_rx_symbol_1_clk */
0x108, /* gcc_ufs_card_tx_symbol_0_clk */
0x10C, /* gcc_ufs_card_unipro_core_clk */
0x113, /* gcc_ufs_phy_ahb_clk */
0x112, /* gcc_ufs_phy_axi_clk */
0x119, /* gcc_ufs_phy_ice_core_clk */
0x11A, /* gcc_ufs_phy_phy_aux_clk */
0x115, /* gcc_ufs_phy_rx_symbol_0_clk */
0x11B, /* gcc_ufs_phy_rx_symbol_1_clk */
0x114, /* gcc_ufs_phy_tx_symbol_0_clk */
0x118, /* gcc_ufs_phy_unipro_core_clk */
0x6B, /* gcc_usb30_prim_master_clk */
0x6D, /* gcc_usb30_prim_mock_utmi_clk */
0x6C, /* gcc_usb30_prim_sleep_clk */
0x72, /* gcc_usb30_sec_master_clk */
0x74, /* gcc_usb30_sec_mock_utmi_clk */
0x73, /* gcc_usb30_sec_sleep_clk */
0x6E, /* gcc_usb3_prim_phy_aux_clk */
0x6F, /* gcc_usb3_prim_phy_com_aux_clk */
0x70, /* gcc_usb3_prim_phy_pipe_clk */
0x75, /* gcc_usb3_sec_phy_aux_clk */
0x76, /* gcc_usb3_sec_phy_com_aux_clk */
0x77, /* gcc_usb3_sec_phy_pipe_clk */
0x42, /* gcc_video_ahb_clk */
0x4A, /* gcc_video_axi0_clk */
0x4B, /* gcc_video_axi1_clk */
0x4C, /* gcc_video_axic_clk */
0x51, /* gcc_video_xo_clk */
0x162, /* gpu_cc_debug_mux */
0xDB, /* measure_only_cdsp_clk */
0x19, /* measure_only_cnoc_clk */
0x147, /* measure_only_ipa_2x_clk */
0x7, /* measure_only_snoc_clk */
0x180, /* npu_cc_debug_mux */
0x57, /* video_cc_debug_mux */
0xD0, /* mc_cc_debug_mux */
};
static struct clk_debug_mux gcc_debug_mux = {
.priv = &debug_mux_priv,
.debug_offset = 0x62000,
.post_div_offset = 0x62004,
.cbcr_offset = 0x62008,
.src_sel_mask = 0x3FF,
.src_sel_shift = 0,
.post_div_mask = 0xF,
.post_div_shift = 0,
.post_div_val = 2,
.mux_sels = gcc_debug_mux_sels,
.hw.init = &(struct clk_init_data){
.name = "gcc_debug_mux",
.ops = &clk_debug_mux_ops,
.parent_names = gcc_debug_mux_parent_names,
.num_parents = ARRAY_SIZE(gcc_debug_mux_parent_names),
.flags = CLK_IS_MEASURE,
},
};
static const char *const gpu_cc_debug_mux_parent_names[] = {
"gpu_cc_ahb_clk",
"gpu_cc_crc_ahb_clk",
"gpu_cc_cx_gmu_clk",
"gpu_cc_cx_snoc_dvm_clk",
"gpu_cc_cxo_aon_clk",
"gpu_cc_cxo_clk",
"gpu_cc_gx_gmu_clk",
"gpu_cc_sleep_clk",
"measure_only_gpu_cc_cx_gfx3d_clk",
"measure_only_gpu_cc_cx_gfx3d_slv_clk",
"measure_only_gpu_cc_gx_gfx3d_clk",
};
static int gpu_cc_debug_mux_sels[] = {
0x10, /* gpu_cc_ahb_clk */
0x11, /* gpu_cc_crc_ahb_clk */
0x18, /* gpu_cc_cx_gmu_clk */
0x15, /* gpu_cc_cx_snoc_dvm_clk */
0xA, /* gpu_cc_cxo_aon_clk */
0x19, /* gpu_cc_cxo_clk */
0xF, /* gpu_cc_gx_gmu_clk */
0x16, /* gpu_cc_sleep_clk */
0x1A, /* measure_only_gpu_cc_cx_gfx3d_clk */
0x1B, /* measure_only_gpu_cc_cx_gfx3d_slv_clk */
0xB, /* measure_only_gpu_cc_gx_gfx3d_clk */
};
static struct clk_debug_mux gpu_cc_debug_mux = {
.priv = &debug_mux_priv,
.debug_offset = 0x1568,
.post_div_offset = 0x10FC,
.cbcr_offset = 0x1100,
.src_sel_mask = 0xFF,
.src_sel_shift = 0,
.post_div_mask = 0x3,
.post_div_shift = 0,
.post_div_val = 2,
.mux_sels = gpu_cc_debug_mux_sels,
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_debug_mux",
.ops = &clk_debug_mux_ops,
.parent_names = gpu_cc_debug_mux_parent_names,
.num_parents = ARRAY_SIZE(gpu_cc_debug_mux_parent_names),
.flags = CLK_IS_MEASURE,
},
};
static const char *const npu_cc_debug_mux_parent_names[] = {
"npu_cc_armwic_core_clk",
"npu_cc_bto_core_clk",
"npu_cc_bwmon_clk",
"npu_cc_cal_dp_cdc_clk",
"npu_cc_cal_dp_clk",
"npu_cc_comp_noc_axi_clk",
"npu_cc_conf_noc_ahb_clk",
"npu_cc_npu_core_apb_clk",
"npu_cc_npu_core_atb_clk",
"npu_cc_npu_core_clk",
"npu_cc_npu_core_cti_clk",
"npu_cc_npu_cpc_clk",
"npu_cc_npu_cpc_timer_clk",
"npu_cc_perf_cnt_clk",
"npu_cc_qtimer_core_clk",
"npu_cc_sleep_clk",
"npu_cc_xo_clk",
};
static int npu_cc_debug_mux_sels[] = {
0x4, /* npu_cc_armwic_core_clk */
0x12, /* npu_cc_bto_core_clk */
0xF, /* npu_cc_bwmon_clk */
0x8, /* npu_cc_cal_dp_cdc_clk */
0x1, /* npu_cc_cal_dp_clk */
0x9, /* npu_cc_comp_noc_axi_clk */
0xA, /* npu_cc_conf_noc_ahb_clk */
0xE, /* npu_cc_npu_core_apb_clk */
0xB, /* npu_cc_npu_core_atb_clk */
0x2, /* npu_cc_npu_core_clk */
0xC, /* npu_cc_npu_core_cti_clk */
0x3, /* npu_cc_npu_cpc_clk */
0x5, /* npu_cc_npu_cpc_timer_clk */
0x10, /* npu_cc_perf_cnt_clk */
0x6, /* npu_cc_qtimer_core_clk */
0x7, /* npu_cc_sleep_clk */
0x11, /* npu_cc_xo_clk */
};
static struct clk_debug_mux npu_cc_debug_mux = {
.priv = &debug_mux_priv,
.debug_offset = 0x4000,
.post_div_offset = 0x3004,
.cbcr_offset = 0x3008,
.src_sel_mask = 0xFF,
.src_sel_shift = 0,
.post_div_mask = 0x3,
.post_div_shift = 0,
.post_div_val = 2,
.mux_sels = npu_cc_debug_mux_sels,
.hw.init = &(struct clk_init_data){
.name = "npu_cc_debug_mux",
.ops = &clk_debug_mux_ops,
.parent_names = npu_cc_debug_mux_parent_names,
.num_parents = ARRAY_SIZE(npu_cc_debug_mux_parent_names),
.flags = CLK_IS_MEASURE,
},
};
static const char *const video_cc_debug_mux_parent_names[] = {
"video_cc_iris_ahb_clk",
"video_cc_mvs0_core_clk",
"video_cc_mvs1_core_clk",
"video_cc_mvsc_core_clk",
"video_cc_sleep_clk",
"video_cc_xo_clk",
};
static int video_cc_debug_mux_sels[] = {
0x7, /* video_cc_iris_ahb_clk */
0x3, /* video_cc_mvs0_core_clk */
0x5, /* video_cc_mvs1_core_clk */
0x1, /* video_cc_mvsc_core_clk */
0x9, /* video_cc_sleep_clk */
0x8, /* video_cc_xo_clk */
};
static struct clk_debug_mux video_cc_debug_mux = {
.priv = &debug_mux_priv,
.debug_offset = 0xA4C,
.post_div_offset = 0x938,
.cbcr_offset = 0x940,
.src_sel_mask = 0x3F,
.src_sel_shift = 0,
.post_div_mask = 0x7,
.post_div_shift = 0,
.post_div_val = 5,
.mux_sels = video_cc_debug_mux_sels,
.hw.init = &(struct clk_init_data){
.name = "video_cc_debug_mux",
.ops = &clk_debug_mux_ops,
.parent_names = video_cc_debug_mux_parent_names,
.num_parents = ARRAY_SIZE(video_cc_debug_mux_parent_names),
.flags = CLK_IS_MEASURE,
},
};
static const char *const mc_cc_debug_mux_parent_names[] = {
"measure_only_mccc_clk",
};
static struct clk_debug_mux mc_cc_debug_mux = {
.period_offset = 0x50,
.hw.init = &(struct clk_init_data){
.name = "mc_cc_debug_mux",
.ops = &clk_debug_mux_ops,
.parent_names = mc_cc_debug_mux_parent_names,
.num_parents = ARRAY_SIZE(mc_cc_debug_mux_parent_names),
.flags = CLK_IS_MEASURE,
},
};
static struct mux_regmap_names mux_list[] = {
{ .mux = &cpu_cc_debug_mux, .regmap_name = "qcom,cpucc" },
{ .mux = &cam_cc_debug_mux, .regmap_name = "qcom,camcc" },
{ .mux = &disp_cc_debug_mux, .regmap_name = "qcom,dispcc" },
{ .mux = &gcc_debug_mux, .regmap_name = "qcom,gcc" },
{ .mux = &gpu_cc_debug_mux, .regmap_name = "qcom,gpucc" },
{ .mux = &mc_cc_debug_mux, .regmap_name = "qcom,mccc" },
{ .mux = &npu_cc_debug_mux, .regmap_name = "qcom,npucc" },
{ .mux = &video_cc_debug_mux, .regmap_name = "qcom,videocc" },
};
static struct clk_dummy l3_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "l3_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy measure_only_cdsp_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "measure_only_cdsp_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy measure_only_cnoc_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "measure_only_cnoc_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy measure_only_gpu_cc_cx_gfx3d_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "measure_only_gpu_cc_cx_gfx3d_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy measure_only_gpu_cc_cx_gfx3d_slv_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "measure_only_gpu_cc_cx_gfx3d_slv_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy measure_only_gpu_cc_gx_gfx3d_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "measure_only_gpu_cc_gx_gfx3d_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy measure_only_ipa_2x_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "measure_only_ipa_2x_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy measure_only_mccc_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "measure_only_mccc_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy measure_only_snoc_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "measure_only_snoc_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy perfcl_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "perfcl_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy perfpcl_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "perfpcl_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy pwrcl_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "pwrcl_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_hw *debugcc_sm8150_hws[] = {
&l3_clk.hw,
&measure_only_cdsp_clk.hw,
&measure_only_cnoc_clk.hw,
&measure_only_gpu_cc_cx_gfx3d_clk.hw,
&measure_only_gpu_cc_cx_gfx3d_slv_clk.hw,
&measure_only_gpu_cc_gx_gfx3d_clk.hw,
&measure_only_ipa_2x_clk.hw,
&measure_only_mccc_clk.hw,
&measure_only_snoc_clk.hw,
&perfcl_clk.hw,
&perfpcl_clk.hw,
&pwrcl_clk.hw,
};
static const struct of_device_id clk_debug_match_table[] = {
{ .compatible = "qcom,sm8150-debugcc" },
{ }
};
static int clk_debug_sm8150_probe(struct platform_device *pdev)
{
struct clk *clk;
int ret, i;
BUILD_BUG_ON(ARRAY_SIZE(cpu_cc_debug_mux_parent_names) !=
ARRAY_SIZE(cpu_cc_debug_mux_sels));
BUILD_BUG_ON(ARRAY_SIZE(cam_cc_debug_mux_parent_names) !=
ARRAY_SIZE(cam_cc_debug_mux_sels));
BUILD_BUG_ON(ARRAY_SIZE(disp_cc_debug_mux_parent_names) !=
ARRAY_SIZE(disp_cc_debug_mux_sels));
BUILD_BUG_ON(ARRAY_SIZE(gcc_debug_mux_parent_names) !=
ARRAY_SIZE(gcc_debug_mux_sels));
BUILD_BUG_ON(ARRAY_SIZE(gpu_cc_debug_mux_parent_names) !=
ARRAY_SIZE(gpu_cc_debug_mux_sels));
BUILD_BUG_ON(ARRAY_SIZE(npu_cc_debug_mux_parent_names) !=
ARRAY_SIZE(npu_cc_debug_mux_sels));
BUILD_BUG_ON(ARRAY_SIZE(video_cc_debug_mux_parent_names) !=
ARRAY_SIZE(video_cc_debug_mux_sels));
clk = devm_clk_get(&pdev->dev, "xo_clk_src");
if (IS_ERR(clk)) {
if (PTR_ERR(clk) != -EPROBE_DEFER)
dev_err(&pdev->dev, "Unable to get xo clock\n");
return PTR_ERR(clk);
}
debug_mux_priv.cxo = clk;
for (i = 0; i < ARRAY_SIZE(mux_list); i++) {
ret = map_debug_bases(pdev, mux_list[i].regmap_name,
mux_list[i].mux);
if (ret == -EBADR)
continue;
else if (ret)
return ret;
clk = devm_clk_register(&pdev->dev, &mux_list[i].mux->hw);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Unable to register %s, err:(%d)\n",
clk_hw_get_name(&mux_list[i].mux->hw),
PTR_ERR(clk));
return PTR_ERR(clk);
}
}
for (i = 0; i < ARRAY_SIZE(debugcc_sm8150_hws); i++) {
clk = devm_clk_register(&pdev->dev, debugcc_sm8150_hws[i]);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Unable to register %s, err:(%d)\n",
clk_hw_get_name(debugcc_sm8150_hws[i]),
PTR_ERR(clk));
return PTR_ERR(clk);
}
}
ret = clk_debug_measure_register(&gcc_debug_mux.hw);
if (ret) {
dev_err(&pdev->dev, "Could not register Measure clocks\n");
return ret;
}
dev_info(&pdev->dev, "Registered debug measure clocks\n");
return ret;
}
static struct platform_driver clk_debug_driver = {
.probe = clk_debug_sm8150_probe,
.driver = {
.name = "sm8150-debugcc",
.of_match_table = clk_debug_match_table,
},
};
static int __init clk_debug_sm8150_init(void)
{
return platform_driver_register(&clk_debug_driver);
}
fs_initcall(clk_debug_sm8150_init);
MODULE_DESCRIPTION("QTI DEBUG CC SM8150 Driver");
MODULE_LICENSE("GPL v2");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,334 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,gpucc-sm8150.h>
#include "clk-alpha-pll.h"
#include "clk-branch.h"
#include "clk-rcg.h"
#include "clk-regmap.h"
#include "common.h"
#include "vdd-level-sm8150.h"
static DEFINE_VDD_REGULATORS(vdd_cx, VDD_NUM, 1, vdd_corner);
static DEFINE_VDD_REGULATORS(vdd_mx, VDD_NUM, 1, vdd_corner);
enum {
P_BI_TCXO,
P_CORE_BI_PLL_TEST_SE,
P_GPLL0_OUT_MAIN,
P_GPLL0_OUT_MAIN_DIV,
P_GPU_CC_PLL0_OUT_MAIN,
P_GPU_CC_PLL1_OUT_MAIN,
};
static struct pll_vco trion_vco[] = {
{ 249600000, 2000000000, 0 },
};
/* 500MHz configuration */
static struct alpha_pll_config gpu_cc_pll1_config = {
.l = 0x1A,
.alpha = 0xAAA,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00002267,
.config_ctl_hi1_val = 0x00000024,
.test_ctl_val = 0x00000000,
.test_ctl_hi_val = 0x00000000,
.test_ctl_hi1_val = 0x00000020,
.user_ctl_val = 0x00000000,
.user_ctl_hi_val = 0x00000805,
.user_ctl_hi1_val = 0x000000D0,
};
static struct clk_alpha_pll gpu_cc_pll1 = {
.offset = 0x100,
.vco_table = trion_vco,
.num_vco = ARRAY_SIZE(trion_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
.config = &gpu_cc_pll1_config,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_pll1",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_trion_pll_ops,
},
.vdd_data = {
.vdd_class = &vdd_mx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 615000000,
[VDD_LOW] = 1066000000,
[VDD_LOW_L1] = 1600000000,
[VDD_NOMINAL] = 2000000000},
},
},
};
static const struct parent_map gpu_cc_parent_map_0[] = {
{ P_BI_TCXO, 0 },
{ P_GPU_CC_PLL0_OUT_MAIN, 1 },
{ P_GPU_CC_PLL1_OUT_MAIN, 3 },
{ P_GPLL0_OUT_MAIN, 5 },
{ P_GPLL0_OUT_MAIN_DIV, 6 },
{ P_CORE_BI_PLL_TEST_SE, 7 },
};
static const struct clk_parent_data gpu_cc_parent_data_0[] = {
{ .fw_name = "bi_tcxo" },
{ .fw_name = "gpu_cc_pll0", .name = "gpu_cc_pll0" },
{ .hw = &gpu_cc_pll1.clkr.hw },
{ .fw_name = "gcc_gpu_gpll0_clk_src" },
{ .fw_name = "gcc_gpu_gpll0_div_clk_src" },
{ .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
};
static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
{ }
};
static struct clk_rcg2 gpu_cc_gmu_clk_src = {
.cmd_rcgr = 0x1120,
.mnd_width = 0,
.hid_width = 5,
.parent_map = gpu_cc_parent_map_0,
.freq_tbl = ftbl_gpu_cc_gmu_clk_src,
.enable_safe_config = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gpu_cc_gmu_clk_src",
.parent_data = gpu_cc_parent_data_0,
.num_parents = 6,
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 200000000,
[VDD_LOW] = 500000000},
},
};
static struct clk_branch gpu_cc_ahb_clk = {
.halt_reg = 0x1078,
.halt_check = BRANCH_HALT_DELAY,
.clkr = {
.enable_reg = 0x1078,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_ahb_clk",
.flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_crc_ahb_clk = {
.halt_reg = 0x107c,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x107c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_crc_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cx_gmu_clk = {
.halt_reg = 0x1098,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1098,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_cx_gmu_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &gpu_cc_gmu_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
.halt_reg = 0x108c,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x108c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_cx_snoc_dvm_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cxo_aon_clk = {
.halt_reg = 0x1004,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x1004,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_cxo_aon_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cxo_clk = {
.halt_reg = 0x109c,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x109c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_cxo_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_gx_gmu_clk = {
.halt_reg = 0x1064,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1064,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_gx_gmu_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &gpu_cc_gmu_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_sleep_clk = {
.halt_reg = 0x1090,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x1090,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_sleep_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_regmap *gpu_cc_sm8150_clocks[] = {
[GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
[GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
[GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
[GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
[GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
[GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
[GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
[GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
};
static const struct regmap_config gpu_cc_sm8150_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x8008,
.fast_io = true,
};
static const struct qcom_cc_desc gpu_cc_sm8150_desc = {
.config = &gpu_cc_sm8150_regmap_config,
.clks = gpu_cc_sm8150_clocks,
.num_clks = ARRAY_SIZE(gpu_cc_sm8150_clocks),
};
static const struct of_device_id gpu_cc_sm8150_match_table[] = {
{ .compatible = "qcom,sm8150-gpucc" },
{ .compatible = "qcom,sa8155-gpucc" },
{ }
};
MODULE_DEVICE_TABLE(of, gpu_cc_sm8150_match_table);
static int gpu_cc_sm8150_probe(struct platform_device *pdev)
{
struct regmap *regmap;
int ret;
vdd_cx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_cx");
if (IS_ERR(vdd_cx.regulator[0])) {
if (PTR_ERR(vdd_cx.regulator[0]) != -EPROBE_DEFER)
dev_err(&pdev->dev, "Unable to get vdd_cx regulator\n");
return PTR_ERR(vdd_cx.regulator[0]);
}
vdd_mx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_mx");
if (IS_ERR(vdd_mx.regulator[0])) {
if (PTR_ERR(vdd_mx.regulator[0]) != -EPROBE_DEFER)
dev_err(&pdev->dev, "Unable to get vdd_mx regulator\n");
return PTR_ERR(vdd_mx.regulator[0]);
}
regmap = qcom_cc_map(pdev, &gpu_cc_sm8150_desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
clk_trion_pll_configure(&gpu_cc_pll1, regmap, gpu_cc_pll1.config);
ret = qcom_cc_really_probe(pdev, &gpu_cc_sm8150_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register GPU CC clocks\n");
return ret;
}
dev_info(&pdev->dev, "Registered GPU CC clocks\n");
return ret;
}
static struct platform_driver gpu_cc_sm8150_driver = {
.probe = gpu_cc_sm8150_probe,
.driver = {
.name = "gpu_cc-sm8150",
.of_match_table = gpu_cc_sm8150_match_table,
},
};
static int __init gpu_cc_sm8150_init(void)
{
return platform_driver_register(&gpu_cc_sm8150_driver);
}
subsys_initcall(gpu_cc_sm8150_init);
static void __exit gpu_cc_sm8150_exit(void)
{
platform_driver_unregister(&gpu_cc_sm8150_driver);
}
module_exit(gpu_cc_sm8150_exit);
MODULE_DESCRIPTION("QTI GPU_CC SM8150 Driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,715 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,npucc-sm8150.h>
#include "clk-alpha-pll.h"
#include "clk-branch.h"
#include "clk-rcg.h"
#include "clk-regmap.h"
#include "common.h"
#include "reset.h"
#include "vdd-level-sm8150.h"
#define CRC_SID_FSM_CTRL 0x100c
#define CRC_SID_FSM_CTRL_SETTING 0x800000
#define CRC_MND_CFG 0x1010
#define CRC_MND_CFG_SETTING 0x15010
static DEFINE_VDD_REGULATORS(vdd_cx, VDD_NUM, 1, vdd_corner);
enum {
P_BI_TCXO,
P_CORE_BI_PLL_TEST_SE,
P_GPLL0_OUT_MAIN,
P_GPLL0_OUT_MAIN_DIV,
P_NPU_CC_PLL0_OUT_EVEN,
P_NPU_CC_PLL1_OUT_EVEN,
P_NPU_CC_CRC_DIV,
};
static struct pll_vco trion_vco[] = {
{ 249600000, 2000000000, 0 },
};
/* 600MHz configuration */
static struct alpha_pll_config npu_cc_pll0_config = {
.l = 0x1F,
.alpha = 0x4000,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00002267,
.config_ctl_hi1_val = 0x00000024,
.test_ctl_val = 0x00000000,
.test_ctl_hi_val = 0x00000002,
.test_ctl_hi1_val = 0x00000020,
.user_ctl_val = 0x00000000,
.user_ctl_hi_val = 0x00000805,
.user_ctl_hi1_val = 0x000000D0,
};
static struct clk_alpha_pll npu_cc_pll0 = {
.offset = 0x0,
.vco_table = trion_vco,
.num_vco = ARRAY_SIZE(trion_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
.config = &npu_cc_pll0_config,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "npu_cc_pll0",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_trion_pll_ops,
},
.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 615000000,
[VDD_LOW] = 1066000000,
[VDD_LOW_L1] = 1600000000,
[VDD_NOMINAL] = 2000000000},
},
},
};
/* 700MHz configuration */
static struct alpha_pll_config npu_cc_pll1_config = {
.l = 0x24,
.alpha = 0x7555,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00002267,
.config_ctl_hi1_val = 0x00000024,
.test_ctl_val = 0x00000000,
.test_ctl_hi_val = 0x00000002,
.test_ctl_hi1_val = 0x00000020,
.user_ctl_val = 0x00000000,
.user_ctl_hi_val = 0x00000805,
.user_ctl_hi1_val = 0x000000D0,
};
static struct clk_alpha_pll npu_cc_pll1 = {
.offset = 0x400,
.vco_table = trion_vco,
.num_vco = ARRAY_SIZE(trion_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
.config = &npu_cc_pll1_config,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "npu_cc_pll1",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_trion_pll_ops,
},
.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 615000000,
[VDD_LOW] = 1066000000,
[VDD_LOW_L1] = 1600000000,
[VDD_NOMINAL] = 2000000000},
},
},
};
static const struct parent_map npu_cc_parent_map_0[] = {
{ P_BI_TCXO, 0 },
{ P_NPU_CC_PLL1_OUT_EVEN, 1 },
{ P_NPU_CC_PLL0_OUT_EVEN, 2 },
{ P_GPLL0_OUT_MAIN, 4 },
{ P_GPLL0_OUT_MAIN_DIV, 5 },
{ P_CORE_BI_PLL_TEST_SE, 7 },
};
static const struct clk_parent_data npu_cc_parent_data_0[] = {
{ .fw_name = "bi_tcxo", },
{ .hw = &npu_cc_pll1.clkr.hw },
{ .hw = &npu_cc_pll0.clkr.hw },
{ .fw_name = "gcc_npu_gpll0_clk_src", .name = "gcc_npu_gpll0_clk_src" },
{ .fw_name = "gcc_npu_gpll0_div_clk_src", .name =
"gcc_npu_gpll0_div_clk_src" },
{ .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
};
static struct clk_fixed_factor npu_cc_crc_div = {
.mult = 1,
.div = 2,
.hw.init = &(struct clk_init_data){
.name = "npu_cc_crc_div",
.parent_data = &(const struct clk_parent_data){
.hw = &npu_cc_pll0.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_fixed_factor_ops,
},
};
static const struct parent_map npu_cc_parent_map_1[] = {
{ P_BI_TCXO, 0 },
{ P_NPU_CC_PLL1_OUT_EVEN, 1 },
{ P_NPU_CC_CRC_DIV, 2 },
{ P_GPLL0_OUT_MAIN, 4 },
{ P_GPLL0_OUT_MAIN_DIV, 5 },
{ P_CORE_BI_PLL_TEST_SE, 7 },
};
static const struct clk_parent_data npu_cc_parent_data_1[] = {
{ .fw_name = "bi_tcxo", },
{ .hw = &npu_cc_pll1.clkr.hw },
{ .hw = &npu_cc_crc_div.hw },
{ .fw_name = "gcc_npu_gpll0_clk_src", .name = "gcc_npu_gpll0_clk_src" },
{ .fw_name = "gcc_npu_gpll0_div_clk_src", .name =
"gcc_npu_gpll0_div_clk_src" },
{ .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
};
static const struct freq_tbl ftbl_npu_cc_cal_dp_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(300000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(350000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(400000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(600000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(715000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
{ }
};
static const struct freq_tbl ftbl_npu_cc_cal_dp_clk_src_sm8150_v2[] = {
F(125000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(300000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(400000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(487000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(652000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(811000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
F(908000000, P_NPU_CC_CRC_DIV, 1, 0, 0),
{ }
};
static struct clk_rcg2 npu_cc_cal_dp_clk_src = {
.cmd_rcgr = 0x1004,
.mnd_width = 0,
.hid_width = 5,
.parent_map = npu_cc_parent_map_1,
.freq_tbl = ftbl_npu_cc_cal_dp_clk_src,
.enable_safe_config = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "npu_cc_cal_dp_clk_src",
.parent_data = npu_cc_parent_data_1,
.num_parents = 6,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 9600000,
[VDD_LOWER] = 300000000,
[VDD_LOW] = 350000000,
[VDD_LOW_L1] = 400000000,
[VDD_NOMINAL] = 600000000,
[VDD_HIGH] = 715000000},
},
};
static const struct freq_tbl ftbl_npu_cc_npu_core_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
F(350000000, P_NPU_CC_PLL1_OUT_EVEN, 2, 0, 0),
{ }
};
static const struct freq_tbl ftbl_npu_cc_npu_core_clk_src_sm8150_v2[] = {
F(60000000, P_GPLL0_OUT_MAIN_DIV, 5, 0, 0),
F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
F(200000000, P_NPU_CC_PLL1_OUT_EVEN, 4, 0, 0),
F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
F(400000000, P_NPU_CC_PLL1_OUT_EVEN, 2, 0, 0),
{ }
};
static struct clk_rcg2 npu_cc_npu_core_clk_src = {
.cmd_rcgr = 0x1030,
.mnd_width = 0,
.hid_width = 5,
.parent_map = npu_cc_parent_map_0,
.freq_tbl = ftbl_npu_cc_npu_core_clk_src,
.enable_safe_config = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "npu_cc_npu_core_clk_src",
.parent_data = npu_cc_parent_data_0,
.num_parents = 6,
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 100000000,
[VDD_LOW] = 150000000,
[VDD_LOW_L1] = 200000000,
[VDD_NOMINAL] = 300000000,
[VDD_HIGH] = 350000000},
},
};
static struct clk_branch npu_cc_armwic_core_clk = {
.halt_reg = 0x1058,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1058,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_armwic_core_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &npu_cc_npu_core_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_bto_core_clk = {
.halt_reg = 0x1090,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1090,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_bto_core_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_bwmon_clk = {
.halt_reg = 0x1088,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1088,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_bwmon_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_cal_dp_cdc_clk = {
.halt_reg = 0x1068,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1068,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_cal_dp_cdc_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &npu_cc_cal_dp_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_cal_dp_clk = {
.halt_reg = 0x101c,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x101c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_cal_dp_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &npu_cc_cal_dp_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_comp_noc_axi_clk = {
.halt_reg = 0x106c,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x106c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_comp_noc_axi_clk",
.parent_data = &(const struct clk_parent_data){
.fw_name = "gcc_npu_axi_clk",
},
.num_parents = 1,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_conf_noc_ahb_clk = {
.halt_reg = 0x1074,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1074,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_conf_noc_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_npu_core_clk = {
.halt_reg = 0x1048,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1048,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_npu_core_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &npu_cc_npu_core_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_npu_core_cti_clk = {
.halt_reg = 0x107c,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x107c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_npu_core_cti_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_npu_cpc_clk = {
.halt_reg = 0x1050,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1050,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_npu_cpc_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &npu_cc_npu_core_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_npu_cpc_timer_clk = {
.halt_reg = 0x105c,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x105c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_npu_cpc_timer_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_perf_cnt_clk = {
.halt_reg = 0x108c,
.halt_check = BRANCH_HALT_DELAY,
.clkr = {
.enable_reg = 0x108c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_perf_cnt_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &npu_cc_cal_dp_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_qtimer_core_clk = {
.halt_reg = 0x1060,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1060,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_qtimer_core_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_sleep_clk = {
.halt_reg = 0x1064,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1064,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_sleep_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch npu_cc_xo_clk = {
.halt_reg = 0x3020,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x3020,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "npu_cc_xo_clk",
.flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_regmap *npu_cc_sm8150_clocks[] = {
[NPU_CC_PLL0] = &npu_cc_pll0.clkr,
[NPU_CC_PLL1] = &npu_cc_pll1.clkr,
[NPU_CC_ARMWIC_CORE_CLK] = &npu_cc_armwic_core_clk.clkr,
[NPU_CC_BTO_CORE_CLK] = &npu_cc_bto_core_clk.clkr,
[NPU_CC_BWMON_CLK] = &npu_cc_bwmon_clk.clkr,
[NPU_CC_CAL_DP_CDC_CLK] = &npu_cc_cal_dp_cdc_clk.clkr,
[NPU_CC_CAL_DP_CLK] = &npu_cc_cal_dp_clk.clkr,
[NPU_CC_CAL_DP_CLK_SRC] = &npu_cc_cal_dp_clk_src.clkr,
[NPU_CC_COMP_NOC_AXI_CLK] = &npu_cc_comp_noc_axi_clk.clkr,
[NPU_CC_CONF_NOC_AHB_CLK] = &npu_cc_conf_noc_ahb_clk.clkr,
[NPU_CC_NPU_CORE_CLK] = &npu_cc_npu_core_clk.clkr,
[NPU_CC_NPU_CORE_CLK_SRC] = &npu_cc_npu_core_clk_src.clkr,
[NPU_CC_NPU_CORE_CTI_CLK] = &npu_cc_npu_core_cti_clk.clkr,
[NPU_CC_NPU_CPC_CLK] = &npu_cc_npu_cpc_clk.clkr,
[NPU_CC_NPU_CPC_TIMER_CLK] = &npu_cc_npu_cpc_timer_clk.clkr,
[NPU_CC_PERF_CNT_CLK] = &npu_cc_perf_cnt_clk.clkr,
[NPU_CC_QTIMER_CORE_CLK] = &npu_cc_qtimer_core_clk.clkr,
[NPU_CC_SLEEP_CLK] = &npu_cc_sleep_clk.clkr,
[NPU_CC_XO_CLK] = &npu_cc_xo_clk.clkr,
};
static const struct qcom_reset_map npu_cc_sm8150_resets[] = {
[NPU_CC_CAL_DP_BCR] = { 0x1000 },
[NPU_CC_NPU_CORE_BCR] = { 0x1024 },
};
static const struct regmap_config npu_cc_sm8150_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x8000,
.fast_io = true,
};
static const struct qcom_cc_desc npu_cc_sm8150_desc = {
.config = &npu_cc_sm8150_regmap_config,
.clks = npu_cc_sm8150_clocks,
.num_clks = ARRAY_SIZE(npu_cc_sm8150_clocks),
.resets = npu_cc_sm8150_resets,
.num_resets = ARRAY_SIZE(npu_cc_sm8150_resets),
};
static const struct of_device_id npu_cc_sm8150_match_table[] = {
{ .compatible = "qcom,sm8150-npucc" },
{ .compatible = "qcom,sm8150-npucc-v2" },
{ .compatible = "qcom,sa8155-npucc" },
{ .compatible = "qcom,sa8155-npucc-v2" },
{ }
};
MODULE_DEVICE_TABLE(of, npu_cc_sm8150_match_table);
static void npu_cc_sm8150_fixup_sm8150v2(struct regmap *regmap)
{
npu_cc_pll0.config->test_ctl_hi_val = 0x00000000;
npu_cc_pll1.config->test_ctl_hi_val = 0x00000000;
/* 800MHz configuration */
npu_cc_pll1.config->l = 0x29;
npu_cc_pll1.config->alpha = 0xAAAA;
npu_cc_cal_dp_clk_src.freq_tbl = ftbl_npu_cc_cal_dp_clk_src_sm8150_v2;
npu_cc_cal_dp_clk_src.clkr.vdd_data.rate_max[VDD_MIN] = 0;
npu_cc_cal_dp_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 400000000;
npu_cc_cal_dp_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] = 487000000;
npu_cc_cal_dp_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] = 652000000;
npu_cc_cal_dp_clk_src.clkr.vdd_data.rate_max[VDD_HIGH] = 811000000;
npu_cc_cal_dp_clk_src.clkr.vdd_data.rate_max[VDD_HIGH_L1] = 908000000;
npu_cc_npu_core_clk_src.freq_tbl = ftbl_npu_cc_npu_core_clk_src_sm8150_v2;
npu_cc_npu_core_clk_src.clkr.vdd_data.rate_max[VDD_MIN] = 0;
npu_cc_npu_core_clk_src.clkr.vdd_data.rate_max[VDD_HIGH] = 400000000;
}
static int npu_cc_sm8150_fixup(struct platform_device *pdev,
struct regmap *regmap)
{
const char *compat = NULL;
int compatlen = 0;
compat = of_get_property(pdev->dev.of_node, "compatible", &compatlen);
if (!compat || (compatlen <= 0))
return -EINVAL;
if (!strcmp(compat, "qcom,sm8150-npucc-v2") ||
!strcmp(compat, "qcom,sa8155-npucc-v2"))
npu_cc_sm8150_fixup_sm8150v2(regmap);
return 0;
}
struct regulator *vdd_gdsc;
static int enable_npu_crc(struct regmap *regmap)
{
int ret;
/* Set npu_cc_cal_cp_clk to the lowest supported frequency */
clk_set_rate(npu_cc_cal_dp_clk.clkr.hw.clk,
clk_round_rate(npu_cc_cal_dp_clk_src.clkr.hw.clk, 1));
/* Turn on the NPU GDSC */
ret = regulator_enable(vdd_gdsc);
if (ret) {
pr_err("Failed to enable the NPU GDSC during CRC sequence\n");
return ret;
}
/* Enable npu_cc_cal_cp_clk */
ret = clk_prepare_enable(npu_cc_cal_dp_clk.clkr.hw.clk);
if (ret) {
pr_err("Failed to enable npu_cc_cal_dp_clk during CRC sequence\n");
return ret;
}
/* Enable MND RC */
regmap_write(regmap, CRC_MND_CFG, CRC_MND_CFG_SETTING);
regmap_write(regmap, CRC_SID_FSM_CTRL, CRC_SID_FSM_CTRL_SETTING);
/* Wait for 16 cycles before continuing */
udelay(1);
/* Disable npu_cc_cal_cp_clk */
clk_disable_unprepare(npu_cc_cal_dp_clk.clkr.hw.clk);
/* Turn off the NPU GDSC */
regulator_disable(vdd_gdsc);
return ret;
}
static int npu_cc_sm8150_probe(struct platform_device *pdev)
{
struct regmap *regmap;
int ret;
vdd_cx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_cx");
if (IS_ERR(vdd_cx.regulator[0])) {
if (PTR_ERR(vdd_cx.regulator[0]) != -EPROBE_DEFER)
dev_err(&pdev->dev, "Unable to get vdd_cx regulator\n");
return PTR_ERR(vdd_cx.regulator[0]);
}
vdd_gdsc = devm_regulator_get(&pdev->dev, "vdd_gdsc");
if (IS_ERR(vdd_gdsc)) {
if (!(PTR_ERR(vdd_gdsc) == -EPROBE_DEFER))
dev_err(&pdev->dev,
"Unable to get vdd_gdsc regulator\n");
return PTR_ERR(vdd_gdsc);
}
regmap = qcom_cc_map(pdev, &npu_cc_sm8150_desc);
if (IS_ERR(regmap)) {
pr_err("Failed to map the npu CC registers\n");
return PTR_ERR(regmap);
}
ret = npu_cc_sm8150_fixup(pdev, regmap);
if (ret)
return ret;
clk_trion_pll_configure(&npu_cc_pll0, regmap, npu_cc_pll0.config);
clk_trion_pll_configure(&npu_cc_pll1, regmap, npu_cc_pll1.config);
/* Register the fixed factor clock for CRC divide */
ret = devm_clk_hw_register(&pdev->dev, &npu_cc_crc_div.hw);
if (ret) {
dev_err(&pdev->dev, "Failed to register CRC divide clock\n");
return ret;
}
ret = qcom_cc_really_probe(pdev, &npu_cc_sm8150_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register NPU CC clocks\n");
return ret;
}
ret = enable_npu_crc(regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to enable CRC for NPU cal RCG\n");
return ret;
}
dev_info(&pdev->dev, "Registered NPU CC clocks\n");
return ret;
}
static struct platform_driver npu_cc_sm8150_driver = {
.probe = npu_cc_sm8150_probe,
.driver = {
.name = "npu_cc-sm8150",
.of_match_table = npu_cc_sm8150_match_table,
},
};
static int __init npu_cc_sm8150_init(void)
{
return platform_driver_register(&npu_cc_sm8150_driver);
}
subsys_initcall(npu_cc_sm8150_init);
static void __exit npu_cc_sm8150_exit(void)
{
platform_driver_unregister(&npu_cc_sm8150_driver);
}
module_exit(npu_cc_sm8150_exit);
MODULE_DESCRIPTION("QTI NPU_CC SM8150 Driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,742 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,scc-sm8150.h>
#include "clk-alpha-pll.h"
#include "clk-branch.h"
#include "clk-rcg.h"
#include "clk-regmap.h"
#include "common.h"
#include "vdd-level-sm8150.h"
static DEFINE_VDD_REGULATORS(vdd_scc_cx, VDD_NUM, 1, vdd_corner);
enum {
P_AOSS_CC_RO_CLK,
P_AON_SLEEP_CLK,
P_QDSP6SS_PLL_OUT_ODD,
P_SCC_PLL_OUT_EVEN,
P_SCC_PLL_OUT_MAIN,
P_SCC_PLL_OUT_ODD,
P_SSC_BI_PLL_TEST_SE,
P_SSC_BI_TCXO,
};
static struct pll_vco trion_vco[] = {
{ 249600000, 2000000000, 0 },
};
/* 600MHz configuration */
static struct alpha_pll_config scc_pll_config = {
.l = 0x1F,
.alpha = 0x4000,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00002267,
.config_ctl_hi1_val = 0x00000024,
.test_ctl_val = 0x00000000,
.test_ctl_hi_val = 0x00000002,
.test_ctl_hi1_val = 0x00000020,
.user_ctl_val = 0x00000100,
.user_ctl_hi_val = 0x00000805,
.user_ctl_hi1_val = 0x000000D0,
};
static struct clk_alpha_pll scc_pll = {
.offset = 0x0,
.vco_table = trion_vco,
.num_vco = ARRAY_SIZE(trion_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
.config = &scc_pll_config,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "scc_pll",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_trion_pll_ops,
},
.vdd_data = {
.vdd_class = &vdd_scc_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 615000000,
[VDD_LOW] = 1066000000,
[VDD_LOW_L1] = 1600000000,
[VDD_NOMINAL] = 2000000000},
},
},
};
static const struct clk_div_table post_div_table_scc_pll_out_even[] = {
{ 0x1, 2 },
{ }
};
static struct clk_alpha_pll_postdiv scc_pll_out_even = {
.offset = 0x0,
.post_div_shift = 8,
.post_div_table = post_div_table_scc_pll_out_even,
.num_post_div = ARRAY_SIZE(post_div_table_scc_pll_out_even),
.width = 4,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
.clkr.hw.init = &(struct clk_init_data){
.name = "scc_pll_out_even",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_pll.clkr.hw,
},
.num_parents = 1,
.ops = &clk_trion_pll_postdiv_ops,
},
};
static const struct parent_map scc_parent_map_0[] = {
{ P_AOSS_CC_RO_CLK, 0 },
{ P_AON_SLEEP_CLK, 1 },
{ P_SCC_PLL_OUT_EVEN, 2 },
{ P_SSC_BI_TCXO, 3 },
{ P_SCC_PLL_OUT_ODD, 4 },
{ P_QDSP6SS_PLL_OUT_ODD, 5 },
{ P_SCC_PLL_OUT_MAIN, 6 },
{ P_SSC_BI_PLL_TEST_SE, 7 },
};
static const struct clk_parent_data scc_parent_data_0[] = {
{ .fw_name = "bi_tcxo" },
{ .fw_name = "aon_sleep_clk", .name = "aon_sleep_clk" },
{ .hw = &scc_pll_out_even.clkr.hw },
{ .fw_name = "bi_tcxo" },
{ .fw_name = "scc_pll_out_odd", .name = "scc_pll_out_odd" },
{ .fw_name = "qdsp6ss_pll_out_odd", .name = "qdsp6ss_pll_out_odd" },
{ .hw = &scc_pll.clkr.hw },
{ .fw_name = "ssc_bi_pll_test_se", .name = "ssc_bi_pll_test_se" },
};
static const struct freq_tbl ftbl_scc_main_rcg_clk_src[] = {
F(100000000, P_SCC_PLL_OUT_EVEN, 3, 0, 0),
{ }
};
static const struct freq_tbl ftbl_scc_main_rcg_clk_src_sm8150_v2[] = {
F(96000000, P_SCC_PLL_OUT_EVEN, 3, 0, 0),
{ }
};
static struct clk_rcg2 scc_main_rcg_clk_src = {
.cmd_rcgr = 0x1000,
.mnd_width = 0,
.hid_width = 5,
.parent_map = scc_parent_map_0,
.freq_tbl = ftbl_scc_main_rcg_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "scc_main_rcg_clk_src",
.parent_data = scc_parent_data_0,
.num_parents = 8,
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_scc_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 100000000,
[VDD_NOMINAL] = 200000000},
},
};
static const struct freq_tbl ftbl_scc_qupv3_se0_clk_src[] = {
F(7372800, P_SCC_PLL_OUT_EVEN, 1, 384, 15625),
F(14745600, P_SCC_PLL_OUT_EVEN, 1, 768, 15625),
F(19200000, P_SSC_BI_TCXO, 1, 0, 0),
F(29491200, P_SCC_PLL_OUT_EVEN, 1, 1536, 15625),
F(32000000, P_SCC_PLL_OUT_EVEN, 1, 8, 75),
F(48000000, P_SCC_PLL_OUT_EVEN, 1, 4, 25),
F(64000000, P_SCC_PLL_OUT_EVEN, 1, 16, 75),
F(80000000, P_SCC_PLL_OUT_MAIN, 7.5, 0, 0),
F(96000000, P_SCC_PLL_OUT_EVEN, 1, 8, 25),
F(100000000, P_SCC_PLL_OUT_EVEN, 3, 0, 0),
F(102400000, P_SCC_PLL_OUT_EVEN, 1, 128, 375),
F(112000000, P_SCC_PLL_OUT_EVEN, 1, 28, 75),
F(117964800, P_SCC_PLL_OUT_EVEN, 1, 6144, 15625),
F(120000000, P_SCC_PLL_OUT_EVEN, 2.5, 0, 0),
F(128000000, P_SCC_PLL_OUT_EVEN, 1, 32, 75),
{ }
};
static const struct freq_tbl ftbl_scc_qupv3_se0_clk_src_sm8150_v2[] = {
F(7372800, P_SCC_PLL_OUT_EVEN, 1, 16, 625),
F(14745600, P_SCC_PLL_OUT_EVEN, 1, 32, 625),
F(19200000, P_SSC_BI_TCXO, 1, 0, 0),
F(29491200, P_SCC_PLL_OUT_EVEN, 1, 64, 625),
F(32000000, P_SCC_PLL_OUT_EVEN, 9, 0, 0),
F(48000000, P_SCC_PLL_OUT_EVEN, 6, 0, 0),
F(64000000, P_SCC_PLL_OUT_EVEN, 4.5, 0, 0),
F(96000000, P_SCC_PLL_OUT_MAIN, 6, 0, 0),
F(100000000, P_SCC_PLL_OUT_MAIN, 1, 25, 144),
F(102400000, P_SCC_PLL_OUT_MAIN, 1, 8, 45),
F(112000000, P_SCC_PLL_OUT_MAIN, 1, 7, 36),
F(117964800, P_SCC_PLL_OUT_MAIN, 1, 128, 625),
F(120000000, P_SCC_PLL_OUT_MAIN, 1, 5, 24),
F(128000000, P_SCC_PLL_OUT_MAIN, 4.5, 0, 0),
F(144000000, P_SCC_PLL_OUT_MAIN, 4, 0, 0),
F(192000000, P_SCC_PLL_OUT_MAIN, 3, 0, 0),
{ }
};
static struct clk_init_data scc_qupv3_se0_clk_src_init = {
.name = "scc_qupv3_se0_clk_src",
.parent_data = scc_parent_data_0,
.num_parents = 8,
.ops = &clk_rcg2_ops,
};
static struct clk_rcg2 scc_qupv3_se0_clk_src = {
.cmd_rcgr = 0x2004,
.mnd_width = 16,
.hid_width = 5,
.parent_map = scc_parent_map_0,
.freq_tbl = ftbl_scc_qupv3_se0_clk_src,
.clkr.hw.init = &scc_qupv3_se0_clk_src_init,
.clkr.vdd_data = {
.vdd_class = &vdd_scc_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 50000000,
[VDD_LOWER] = 80000000,
[VDD_LOW] = 120000000,
[VDD_NOMINAL] = 150000000},
},
};
static struct clk_init_data scc_qupv3_se1_clk_src_init = {
.name = "scc_qupv3_se1_clk_src",
.parent_data = scc_parent_data_0,
.num_parents = 8,
.ops = &clk_rcg2_ops,
};
static struct clk_rcg2 scc_qupv3_se1_clk_src = {
.cmd_rcgr = 0x3004,
.mnd_width = 16,
.hid_width = 5,
.parent_map = scc_parent_map_0,
.freq_tbl = ftbl_scc_qupv3_se0_clk_src,
.clkr.hw.init = &scc_qupv3_se1_clk_src_init,
.clkr.vdd_data = {
.vdd_class = &vdd_scc_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 50000000,
[VDD_LOWER] = 80000000,
[VDD_LOW] = 120000000,
[VDD_NOMINAL] = 150000000},
},
};
static struct clk_init_data scc_qupv3_se2_clk_src_init = {
.name = "scc_qupv3_se2_clk_src",
.parent_data = scc_parent_data_0,
.num_parents = 8,
.ops = &clk_rcg2_ops,
};
static struct clk_rcg2 scc_qupv3_se2_clk_src = {
.cmd_rcgr = 0x4004,
.mnd_width = 16,
.hid_width = 5,
.parent_map = scc_parent_map_0,
.freq_tbl = ftbl_scc_qupv3_se0_clk_src,
.clkr.hw.init = &scc_qupv3_se2_clk_src_init,
.clkr.vdd_data = {
.vdd_class = &vdd_scc_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 50000000,
[VDD_LOWER] = 80000000,
[VDD_LOW] = 120000000,
[VDD_NOMINAL] = 150000000},
},
};
static struct clk_init_data scc_qupv3_se3_clk_src_init = {
.name = "scc_qupv3_se3_clk_src",
.parent_data = scc_parent_data_0,
.num_parents = 8,
.ops = &clk_rcg2_ops,
};
static struct clk_rcg2 scc_qupv3_se3_clk_src = {
.cmd_rcgr = 0xb004,
.mnd_width = 16,
.hid_width = 5,
.parent_map = scc_parent_map_0,
.freq_tbl = ftbl_scc_qupv3_se0_clk_src,
.clkr.hw.init = &scc_qupv3_se3_clk_src_init,
.clkr.vdd_data = {
.vdd_class = &vdd_scc_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 50000000,
[VDD_LOWER] = 80000000,
[VDD_LOW] = 120000000,
[VDD_NOMINAL] = 150000000},
},
};
static struct clk_init_data scc_qupv3_se4_clk_src_init = {
.name = "scc_qupv3_se4_clk_src",
.parent_data = scc_parent_data_0,
.num_parents = 8,
.ops = &clk_rcg2_ops,
};
static struct clk_rcg2 scc_qupv3_se4_clk_src = {
.cmd_rcgr = 0xc004,
.mnd_width = 16,
.hid_width = 5,
.parent_map = scc_parent_map_0,
.freq_tbl = ftbl_scc_qupv3_se0_clk_src,
.clkr.hw.init = &scc_qupv3_se4_clk_src_init,
.clkr.vdd_data = {
.vdd_class = &vdd_scc_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 50000000,
[VDD_LOWER] = 80000000,
[VDD_LOW] = 120000000,
[VDD_NOMINAL] = 150000000},
},
};
static struct clk_init_data scc_qupv3_se5_clk_src_init = {
.name = "scc_qupv3_se5_clk_src",
.parent_data = scc_parent_data_0,
.num_parents = 8,
.ops = &clk_rcg2_ops,
};
static struct clk_rcg2 scc_qupv3_se5_clk_src = {
.cmd_rcgr = 0xd004,
.mnd_width = 16,
.hid_width = 5,
.parent_map = scc_parent_map_0,
.freq_tbl = ftbl_scc_qupv3_se0_clk_src,
.clkr.hw.init = &scc_qupv3_se5_clk_src_init,
.clkr.vdd_data = {
.vdd_class = &vdd_scc_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 50000000,
[VDD_LOWER] = 80000000,
[VDD_LOW] = 120000000,
[VDD_NOMINAL] = 150000000},
},
};
static struct clk_branch scc_qupv3_2xcore_clk = {
.halt_reg = 0x5008,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(10),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_2xcore_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_main_rcg_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch scc_qupv3_core_clk = {
.halt_reg = 0x5010,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(11),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_core_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_main_rcg_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch scc_qupv3_m_hclk_clk = {
.halt_reg = 0x9064,
.halt_check = BRANCH_HALT_VOTED,
.hwcg_reg = 0x9064,
.hwcg_bit = 1,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_m_hclk_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_main_rcg_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch scc_qupv3_s_hclk_clk = {
.halt_reg = 0x9060,
.halt_check = BRANCH_HALT_VOTED,
.hwcg_reg = 0x9060,
.hwcg_bit = 1,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_s_hclk_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_main_rcg_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch scc_qupv3_se0_clk = {
.halt_reg = 0x2130,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(3),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_se0_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_qupv3_se0_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch scc_qupv3_se1_clk = {
.halt_reg = 0x3130,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(4),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_se1_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_qupv3_se1_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch scc_qupv3_se2_clk = {
.halt_reg = 0x4130,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(5),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_se2_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_qupv3_se2_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch scc_qupv3_se3_clk = {
.halt_reg = 0xb130,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(6),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_se3_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_qupv3_se3_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch scc_qupv3_se4_clk = {
.halt_reg = 0xc130,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(7),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_se4_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_qupv3_se4_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch scc_qupv3_se5_clk = {
.halt_reg = 0xd130,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x21000,
.enable_mask = BIT(8),
.hw.init = &(struct clk_init_data){
.name = "scc_qupv3_se5_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &scc_qupv3_se5_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_regmap *scc_sm8150_clocks[] = {
[SCC_PLL] = &scc_pll.clkr,
[SCC_PLL_OUT_EVEN] = &scc_pll_out_even.clkr,
[SCC_MAIN_RCG_CLK_SRC] = &scc_main_rcg_clk_src.clkr,
[SCC_QUPV3_2XCORE_CLK] = &scc_qupv3_2xcore_clk.clkr,
[SCC_QUPV3_CORE_CLK] = &scc_qupv3_core_clk.clkr,
[SCC_QUPV3_M_HCLK_CLK] = &scc_qupv3_m_hclk_clk.clkr,
[SCC_QUPV3_S_HCLK_CLK] = &scc_qupv3_s_hclk_clk.clkr,
[SCC_QUPV3_SE0_CLK] = &scc_qupv3_se0_clk.clkr,
[SCC_QUPV3_SE0_CLK_SRC] = &scc_qupv3_se0_clk_src.clkr,
[SCC_QUPV3_SE1_CLK] = &scc_qupv3_se1_clk.clkr,
[SCC_QUPV3_SE1_CLK_SRC] = &scc_qupv3_se1_clk_src.clkr,
[SCC_QUPV3_SE2_CLK] = &scc_qupv3_se2_clk.clkr,
[SCC_QUPV3_SE2_CLK_SRC] = &scc_qupv3_se2_clk_src.clkr,
[SCC_QUPV3_SE3_CLK] = &scc_qupv3_se3_clk.clkr,
[SCC_QUPV3_SE3_CLK_SRC] = &scc_qupv3_se3_clk_src.clkr,
[SCC_QUPV3_SE4_CLK] = &scc_qupv3_se4_clk.clkr,
[SCC_QUPV3_SE4_CLK_SRC] = &scc_qupv3_se4_clk_src.clkr,
[SCC_QUPV3_SE5_CLK] = &scc_qupv3_se5_clk.clkr,
[SCC_QUPV3_SE5_CLK_SRC] = &scc_qupv3_se5_clk_src.clkr,
};
static const struct clk_rcg_dfs_data scc_dfs_clocks[] = {
DEFINE_RCG_DFS(scc_qupv3_se0_clk_src),
DEFINE_RCG_DFS(scc_qupv3_se1_clk_src),
DEFINE_RCG_DFS(scc_qupv3_se2_clk_src),
DEFINE_RCG_DFS(scc_qupv3_se3_clk_src),
DEFINE_RCG_DFS(scc_qupv3_se4_clk_src),
DEFINE_RCG_DFS(scc_qupv3_se5_clk_src),
};
static const struct regmap_config scc_sm8150_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x23000,
.fast_io = true,
};
static const struct qcom_cc_desc scc_sm8150_desc = {
.config = &scc_sm8150_regmap_config,
.clks = scc_sm8150_clocks,
.num_clks = ARRAY_SIZE(scc_sm8150_clocks),
};
static const struct of_device_id scc_sm8150_match_table[] = {
{ .compatible = "qcom,sm8150-scc" },
{ .compatible = "qcom,sm8150-scc-v2" },
{ .compatible = "qcom,sa8155-scc" },
{ .compatible = "qcom,sa8155-scc-v2" },
{ }
};
MODULE_DEVICE_TABLE(of, scc_sm8150_match_table);
static int scc_sa8155_resume(struct device *dev)
{
struct regmap *regmap = dev_get_drvdata(dev);
/* Reconfigure the scc pll */
clk_trion_pll_configure(&scc_pll, regmap, scc_pll.config);
return 0;
}
static const struct dev_pm_ops scc_sa8155_pm_ops = {
.restore_early = scc_sa8155_resume,
};
static void scc_sm8150_fixup_sm8150v2(struct regmap *regmap)
{
/* 576 MHz Configuration */
scc_pll.config->l = 0x1E;
scc_pll.config->alpha = 0x0;
scc_pll.config->test_ctl_hi_val = 0x00000000;
scc_main_rcg_clk_src.freq_tbl = ftbl_scc_main_rcg_clk_src_sm8150_v2;
scc_main_rcg_clk_src.clkr.vdd_data.rate_max[VDD_MIN] = 96000000;
scc_main_rcg_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 576000000;
scc_main_rcg_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] = 576000000;
scc_qupv3_se0_clk_src.freq_tbl = ftbl_scc_qupv3_se0_clk_src_sm8150_v2;
scc_qupv3_se0_clk_src.clkr.vdd_data.rate_max[VDD_MIN] = 48000000;
scc_qupv3_se0_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] = 96000000;
scc_qupv3_se0_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 128000000;
scc_qupv3_se0_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] = 144000000;
scc_qupv3_se0_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] = 192000000;
scc_qupv3_se1_clk_src.freq_tbl = ftbl_scc_qupv3_se0_clk_src_sm8150_v2;
scc_qupv3_se1_clk_src.clkr.vdd_data.rate_max[VDD_MIN] = 48000000;
scc_qupv3_se1_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] = 96000000;
scc_qupv3_se1_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 128000000;
scc_qupv3_se1_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] = 144000000;
scc_qupv3_se1_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] = 192000000;
scc_qupv3_se2_clk_src.freq_tbl = ftbl_scc_qupv3_se0_clk_src_sm8150_v2;
scc_qupv3_se2_clk_src.clkr.vdd_data.rate_max[VDD_MIN] = 48000000;
scc_qupv3_se2_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] = 96000000;
scc_qupv3_se2_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 128000000;
scc_qupv3_se2_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] = 144000000;
scc_qupv3_se2_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] = 192000000;
scc_qupv3_se3_clk_src.freq_tbl = ftbl_scc_qupv3_se0_clk_src_sm8150_v2;
scc_qupv3_se3_clk_src.clkr.vdd_data.rate_max[VDD_MIN] = 48000000;
scc_qupv3_se3_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] = 96000000;
scc_qupv3_se3_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 128000000;
scc_qupv3_se3_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] = 144000000;
scc_qupv3_se3_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] = 192000000;
scc_qupv3_se4_clk_src.freq_tbl = ftbl_scc_qupv3_se0_clk_src_sm8150_v2;
scc_qupv3_se4_clk_src.clkr.vdd_data.rate_max[VDD_MIN] = 48000000;
scc_qupv3_se4_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] = 96000000;
scc_qupv3_se4_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 128000000;
scc_qupv3_se4_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] = 144000000;
scc_qupv3_se4_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] = 192000000;
scc_qupv3_se5_clk_src.freq_tbl = ftbl_scc_qupv3_se0_clk_src_sm8150_v2;
scc_qupv3_se5_clk_src.clkr.vdd_data.rate_max[VDD_MIN] = 48000000;
scc_qupv3_se5_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] = 96000000;
scc_qupv3_se5_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 128000000;
scc_qupv3_se5_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] = 144000000;
scc_qupv3_se5_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] = 192000000;
}
static int scc_sm8150_fixup(struct platform_device *pdev, struct regmap *regmap)
{
const char *compat = NULL;
int compatlen = 0;
compat = of_get_property(pdev->dev.of_node, "compatible", &compatlen);
if (!compat || (compatlen <= 0))
return -EINVAL;
if (!strcmp(compat, "qcom,sm8150-scc-v2") ||
!strcmp(compat, "qcom,sa8155-scc-v2"))
scc_sm8150_fixup_sm8150v2(regmap);
if (!strcmp(compat, "qcom,sa8155-scc") ||
!strcmp(compat, "qcom,sa8155-scc-v2")) {
pdev->dev.driver->pm = &scc_sa8155_pm_ops;
dev_set_drvdata(&pdev->dev, regmap);
}
return 0;
}
static int scc_sm8150_probe(struct platform_device *pdev)
{
struct regmap *regmap;
int ret;
vdd_scc_cx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_scc_cx");
if (IS_ERR(vdd_scc_cx.regulator[0])) {
ret = PTR_ERR(vdd_scc_cx.regulator[0]);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "Unable to get vdd_scc_cx regulator, ret=%d\n",
ret);
return ret;
}
regmap = qcom_cc_map(pdev, &scc_sm8150_desc);
if (IS_ERR(regmap)) {
pr_err("Failed to map the scc registers\n");
return PTR_ERR(regmap);
}
ret = scc_sm8150_fixup(pdev, regmap);
if (ret)
return ret;
ret = qcom_cc_register_rcg_dfs(regmap, scc_dfs_clocks,
ARRAY_SIZE(scc_dfs_clocks));
if (ret) {
dev_err(&pdev->dev, "Failed to register with DFS\n");
return ret;
}
clk_trion_pll_configure(&scc_pll, regmap, scc_pll.config);
ret = qcom_cc_really_probe(pdev, &scc_sm8150_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register SCC clocks\n");
return ret;
}
dev_info(&pdev->dev, "Registered SCC clocks\n");
return 0;
}
static struct platform_driver scc_sm8150_driver = {
.probe = scc_sm8150_probe,
.driver = {
.name = "scc-sm8150",
.of_match_table = scc_sm8150_match_table,
},
};
static int __init scc_sm8150_init(void)
{
return platform_driver_register(&scc_sm8150_driver);
}
subsys_initcall(scc_sm8150_init);
static void __exit scc_sm8150_exit(void)
{
platform_driver_unregister(&scc_sm8150_driver);
}
module_exit(scc_sm8150_exit);
MODULE_DESCRIPTION("QTI SCC SM8150 Driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,384 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/pm_clock.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,videocc-sm8150.h>
#include "clk-alpha-pll.h"
#include "clk-branch.h"
#include "clk-rcg.h"
#include "clk-regmap.h"
#include "common.h"
#include "reset.h"
#include "vdd-level-sm8150.h"
static DEFINE_VDD_REGULATORS(vdd_mm, VDD_MM_NUM, 1, vdd_corner);
enum {
P_BI_TCXO,
P_CHIP_SLEEP_CLK,
P_CORE_BI_PLL_TEST_SE,
P_VIDEO_PLL0_OUT_EVEN,
P_VIDEO_PLL0_OUT_MAIN,
P_VIDEO_PLL0_OUT_ODD,
};
static struct pll_vco trion_vco[] = {
{ 249600000, 2000000000, 0 },
};
/* 400 MHz configuration */
static struct alpha_pll_config video_pll0_config = {
.l = 0x14,
.alpha = 0xD555,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00002267,
.config_ctl_hi1_val = 0x00000024,
.test_ctl_val = 0x00000000,
.test_ctl_hi_val = 0x00000002,
.test_ctl_hi1_val = 0x00000020,
.user_ctl_val = 0x00000000,
.user_ctl_hi_val = 0x00000805,
.user_ctl_hi1_val = 0x000000D0,
};
static struct clk_alpha_pll video_pll0 = {
.offset = 0x42c,
.vco_table = trion_vco,
.num_vco = ARRAY_SIZE(trion_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
.config = &video_pll0_config,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "video_pll0",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_trion_pll_ops,
},
.vdd_data = {
.vdd_class = &vdd_mm,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 615000000,
[VDD_LOW] = 1066000000,
[VDD_LOW_L1] = 1600000000,
[VDD_NOMINAL] = 2000000000},
},
},
};
static const struct parent_map video_cc_parent_map_0[] = {
{ P_BI_TCXO, 0 },
{ P_VIDEO_PLL0_OUT_MAIN, 1 },
{ P_VIDEO_PLL0_OUT_EVEN, 2 },
{ P_VIDEO_PLL0_OUT_ODD, 3 },
{ P_CORE_BI_PLL_TEST_SE, 7 },
};
static const struct clk_parent_data video_cc_parent_data_0[] = {
{ .fw_name = "bi_tcxo", },
{ .hw = &video_pll0.clkr.hw },
{ .hw = &video_pll0.clkr.hw },
{ .hw = &video_pll0.clkr.hw },
{ .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
};
static const struct freq_tbl ftbl_video_cc_iris_clk_src[] = {
F(200000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(225000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(300000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(365000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(432000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(480000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
{ }
};
static const struct freq_tbl ftbl_video_cc_iris_clk_src_sm8150_v2[] = {
F(200000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(240000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(338000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(365000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(444000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(533000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
{ }
};
static struct clk_rcg2 video_cc_iris_clk_src = {
.cmd_rcgr = 0x7f0,
.mnd_width = 0,
.hid_width = 5,
.parent_map = video_cc_parent_map_0,
.freq_tbl = ftbl_video_cc_iris_clk_src,
.enable_safe_config = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "video_cc_iris_clk_src",
.parent_data = video_cc_parent_data_0,
.num_parents = 5,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_mm,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 200000000,
[VDD_LOWER] = 225000000,
[VDD_LOW] = 300000000,
[VDD_LOW_L1] = 365000000,
[VDD_NOMINAL] = 432000000,
[VDD_HIGH] = 480000000},
},
};
static struct clk_branch video_cc_iris_ahb_clk = {
.halt_reg = 0x8f4,
.halt_check = BRANCH_VOTED,
.clkr = {
.enable_reg = 0x8f4,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_iris_ahb_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_iris_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch video_cc_mvs0_core_clk = {
.halt_reg = 0x890,
.halt_check = BRANCH_VOTED,
.clkr = {
.enable_reg = 0x890,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_mvs0_core_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_iris_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch video_cc_mvs1_core_clk = {
.halt_reg = 0x8d0,
.halt_check = BRANCH_VOTED,
.clkr = {
.enable_reg = 0x8d0,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_mvs1_core_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_iris_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch video_cc_mvsc_core_clk = {
.halt_reg = 0x850,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x850,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_mvsc_core_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_iris_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch video_cc_xo_clk = {
.halt_reg = 0x984,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x984,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_xo_clk",
.flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_regmap *video_cc_sm8150_clocks[] = {
[VIDEO_PLL0] = &video_pll0.clkr,
[VIDEO_CC_IRIS_AHB_CLK] = &video_cc_iris_ahb_clk.clkr,
[VIDEO_CC_IRIS_CLK_SRC] = &video_cc_iris_clk_src.clkr,
[VIDEO_CC_MVS0_CORE_CLK] = &video_cc_mvs0_core_clk.clkr,
[VIDEO_CC_MVS1_CORE_CLK] = &video_cc_mvs1_core_clk.clkr,
[VIDEO_CC_MVSC_CORE_CLK] = &video_cc_mvsc_core_clk.clkr,
[VIDEO_CC_XO_CLK] = &video_cc_xo_clk.clkr,
};
static const struct qcom_reset_map video_cc_sm8150_resets[] = {
[VIDEO_CC_INTERFACE_BCR] = { 0x8f0 },
[VIDEO_CC_MVS0_BCR] = { 0x870 },
[VIDEO_CC_MVS1_BCR] = { 0x8b0 },
[VIDEO_CC_MVSC_BCR] = { 0x810 },
[VIDEO_CC_MVSC_CORE_CLK_BCR] = { 0x850, 2 },
};
static const struct regmap_config video_cc_sm8150_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0xb94,
.fast_io = true,
};
static const struct qcom_cc_desc video_cc_sm8150_desc = {
.config = &video_cc_sm8150_regmap_config,
.clks = video_cc_sm8150_clocks,
.num_clks = ARRAY_SIZE(video_cc_sm8150_clocks),
.resets = video_cc_sm8150_resets,
.num_resets = ARRAY_SIZE(video_cc_sm8150_resets),
};
static const struct of_device_id video_cc_sm8150_match_table[] = {
{ .compatible = "qcom,sm8150-videocc" },
{ .compatible = "qcom,sm8150-videocc-v2" },
{ .compatible = "qcom,sa8155-videocc" },
{ .compatible = "qcom,sa8155-videocc-v2" },
{ }
};
MODULE_DEVICE_TABLE(of, video_cc_sm8150_match_table);
static void video_cc_sm8150_fixup_sm8150v2(struct regmap *regmap)
{
video_pll0.config->test_ctl_hi_val = 0x00000000;
video_cc_iris_clk_src.freq_tbl = ftbl_video_cc_iris_clk_src_sm8150_v2;
video_cc_iris_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] = 240000000;
video_cc_iris_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 338000000;
video_cc_iris_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] = 444000000;
video_cc_iris_clk_src.clkr.vdd_data.rate_max[VDD_HIGH] = 533000000;
}
static int video_cc_sm8150_fixup(struct platform_device *pdev,
struct regmap *regmap)
{
const char *compat = NULL;
int compatlen = 0;
compat = of_get_property(pdev->dev.of_node, "compatible", &compatlen);
if (!compat || (compatlen <= 0))
return -EINVAL;
if (!strcmp(compat, "qcom,sm8150-videocc-v2") ||
!strcmp(compat, "qcom,sa8155-videocc-v2"))
video_cc_sm8150_fixup_sm8150v2(regmap);
return 0;
}
static int video_cc_sm8150_probe(struct platform_device *pdev)
{
struct regmap *regmap;
int ret;
vdd_mm.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_mm");
if (IS_ERR(vdd_mm.regulator[0])) {
if (PTR_ERR(vdd_mm.regulator[0]) != -EPROBE_DEFER)
dev_err(&pdev->dev, "Unable to get vdd_mm regulator\n");
return PTR_ERR(vdd_mm.regulator[0]);
}
pm_runtime_enable(&pdev->dev);
ret = pm_clk_create(&pdev->dev);
if (ret)
goto disable_pm_runtime;
ret = pm_clk_add(&pdev->dev, "cfg_ahb_clk");
if (ret < 0) {
dev_err(&pdev->dev, "Unable to get ahb clock handle\n");
goto destroy_pm_clk;
}
regmap = qcom_cc_map(pdev, &video_cc_sm8150_desc);
if (IS_ERR(regmap)) {
pr_err("Failed to map the Video CC registers\n");
ret = PTR_ERR(regmap);
goto destroy_pm_clk;
}
ret = video_cc_sm8150_fixup(pdev, regmap);
if (ret)
goto destroy_pm_clk;
clk_trion_pll_configure(&video_pll0, regmap, video_pll0.config);
ret = qcom_cc_really_probe(pdev, &video_cc_sm8150_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register VIDEO CC clocks\n");
goto destroy_pm_clk;
}
dev_info(&pdev->dev, "Registered VIDEO CC clocks\n");
return 0;
destroy_pm_clk:
pm_clk_destroy(&pdev->dev);
disable_pm_runtime:
pm_runtime_disable(&pdev->dev);
return ret;
}
static const struct dev_pm_ops video_cc_sm8150_pm_ops = {
SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
};
static struct platform_driver video_cc_sm8150_driver = {
.probe = video_cc_sm8150_probe,
.driver = {
.name = "video_cc-sm8150",
.of_match_table = video_cc_sm8150_match_table,
.pm = &video_cc_sm8150_pm_ops,
},
};
static int __init video_cc_sm8150_init(void)
{
return platform_driver_register(&video_cc_sm8150_driver);
}
subsys_initcall(video_cc_sm8150_init);
static void __exit video_cc_sm8150_exit(void)
{
platform_driver_unregister(&video_cc_sm8150_driver);
}
module_exit(video_cc_sm8150_exit);
MODULE_DESCRIPTION("QTI VIDEO_CC SM8150 Driver");
MODULE_LICENSE("GPL v2");