diff options
Diffstat (limited to 'drivers/clk/qcom')
-rw-r--r-- | drivers/clk/qcom/Kconfig | 6 | ||||
-rw-r--r-- | drivers/clk/qcom/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-branch.c | 6 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-branch.h | 1 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-regmap-mux-div.h | 2 | ||||
-rw-r--r-- | drivers/clk/qcom/gcc-msm8998.c | 2 | ||||
-rw-r--r-- | drivers/clk/qcom/gcc-qcs404.c | 90 | ||||
-rw-r--r-- | drivers/clk/qcom/turingcc-qcs404.c | 170 |
8 files changed, 276 insertions, 2 deletions
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 1c04575c118f..18bdf34d5e64 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -243,6 +243,12 @@ config SDM_GCC_660 Say Y if you want to use peripheral devices such as UART, SPI, i2C, USB, UFS, SDDC, PCIe, etc. +config QCS_TURING_404 + tristate "QCS404 Turing Clock Controller" + help + Support for the Turing Clock Controller on QCS404, provides clocks + and resets for the Turing subsystem. + config SDM_GCC_845 tristate "SDM845 Global Clock Controller" select QCOM_GDSC diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index ee8d0698e370..f0768fb1f037 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o +obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 99446bf630aa..f869fc6aaed6 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -146,6 +146,12 @@ const struct clk_ops clk_branch2_ops = { }; EXPORT_SYMBOL_GPL(clk_branch2_ops); +const struct clk_ops clk_branch2_aon_ops = { + .enable = clk_branch2_enable, + .is_enabled = clk_is_enabled_regmap, +}; +EXPORT_SYMBOL_GPL(clk_branch2_aon_ops); + const struct clk_ops clk_branch_simple_ops = { .enable = clk_enable_regmap, .disable = clk_disable_regmap, diff --git a/drivers/clk/qcom/clk-branch.h b/drivers/clk/qcom/clk-branch.h index b3561e0a3984..17a58119165e 100644 --- a/drivers/clk/qcom/clk-branch.h +++ b/drivers/clk/qcom/clk-branch.h @@ -40,6 +40,7 @@ struct clk_branch { extern const struct clk_ops clk_branch_ops; extern const struct clk_ops clk_branch2_ops; extern const struct clk_ops clk_branch_simple_ops; +extern const struct clk_ops clk_branch2_aon_ops; #define to_clk_branch(_hw) \ container_of(to_clk_regmap(_hw), struct clk_branch, clkr) diff --git a/drivers/clk/qcom/clk-regmap-mux-div.h b/drivers/clk/qcom/clk-regmap-mux-div.h index 6cd6261be7ac..4df6c8d24c24 100644 --- a/drivers/clk/qcom/clk-regmap-mux-div.h +++ b/drivers/clk/qcom/clk-regmap-mux-div.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2017, Linaro Limited * Author: Georgi Djakov <georgi.djakov@linaro.org> diff --git a/drivers/clk/qcom/gcc-msm8998.c b/drivers/clk/qcom/gcc-msm8998.c index c240fba794c7..033688264c7b 100644 --- a/drivers/clk/qcom/gcc-msm8998.c +++ b/drivers/clk/qcom/gcc-msm8998.c @@ -2161,7 +2161,7 @@ static struct clk_branch gcc_pcie_0_mstr_axi_clk = { static struct clk_branch gcc_pcie_0_pipe_clk = { .halt_reg = 0x6b018, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x6b018, .enable_mask = BIT(0), diff --git a/drivers/clk/qcom/gcc-qcs404.c b/drivers/clk/qcom/gcc-qcs404.c index 5a62f64ada93..a54807eb3b28 100644 --- a/drivers/clk/qcom/gcc-qcs404.c +++ b/drivers/clk/qcom/gcc-qcs404.c @@ -260,6 +260,20 @@ static const char * const gcc_parent_names_15[] = { "core_bi_pll_test_se", }; +static const struct parent_map gcc_parent_map_16[] = { + { P_XO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL0_OUT_AUX, 2 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_16[] = { + "cxo", + "gpll0_out_main", + "gpll0_out_aux", + "core_bi_pll_test_se", +}; + static struct clk_fixed_factor cxo = { .mult = 1, .div = 1, @@ -1194,6 +1208,28 @@ static struct clk_rcg2 vsync_clk_src = { }, }; +static const struct freq_tbl ftbl_cdsp_bimc_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(133333333, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(266666667, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(320000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 cdsp_bimc_clk_src = { + .cmd_rcgr = 0x5e010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_16, + .freq_tbl = ftbl_cdsp_bimc_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "cdsp_bimc_clk_src", + .parent_names = gcc_parent_names_16, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + static struct clk_branch gcc_apss_ahb_clk = { .halt_reg = 0x4601c, .halt_check = BRANCH_HALT_VOTED, @@ -1255,6 +1291,24 @@ static struct clk_branch gcc_bimc_gpu_clk = { }, }; +static struct clk_branch gcc_bimc_cdsp_clk = { + .halt_reg = 0x31030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x31030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "gcc_bimc_cdsp_clk", + .parent_names = (const char *[]) { + "cdsp_bimc_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_bimc_mdss_clk = { .halt_reg = 0x31038, .halt_check = BRANCH_HALT, @@ -1792,6 +1846,24 @@ static struct clk_branch gcc_gfx_tbu_clk = { }, }; +static struct clk_branch gcc_cdsp_tbu_clk = { + .halt_reg = 0x1203c, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x13020, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data) { + .name = "gcc_cdsp_tbu_clk", + .parent_names = (const char *[]) { + "cdsp_bimc_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_gp1_clk = { .halt_reg = 0x8000, .halt_check = BRANCH_HALT, @@ -2304,6 +2376,19 @@ static struct clk_branch gcc_sdcc1_ice_core_clk = { }, }; +static struct clk_branch gcc_cdsp_cfg_ahb_clk = { + .halt_reg = 0x5e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5e004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "gcc_cdsp_cfg_ahb_cbcr", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_sdcc2_ahb_clk = { .halt_reg = 0x4301c, .halt_check = BRANCH_HALT, @@ -2548,6 +2633,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { [GCC_ESC0_CLK_SRC] = &esc0_clk_src.clkr, [GCC_APSS_AHB_CLK] = &gcc_apss_ahb_clk.clkr, [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr, + [GCC_BIMC_CDSP_CLK] = &gcc_bimc_cdsp_clk.clkr, [GCC_BIMC_MDSS_CLK] = &gcc_bimc_mdss_clk.clkr, [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, [GCC_BLSP1_QUP0_I2C_APPS_CLK] = &gcc_blsp1_qup0_i2c_apps_clk.clkr, @@ -2605,6 +2691,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr, + [GCC_CDSP_CFG_AHB_CLK] = &gcc_cdsp_cfg_ahb_clk.clkr, [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, [GCC_SYS_NOC_USB3_CLK] = &gcc_sys_noc_usb3_clk.clkr, @@ -2645,6 +2732,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { [GCC_USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr, [GCC_USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr, [GCC_VSYNC_CLK_SRC] = &vsync_clk_src.clkr, + [GCC_CDSP_BIMC_CLK_SRC] = &cdsp_bimc_clk_src.clkr, [GCC_USB_HS_INACTIVITY_TIMERS_CLK] = &gcc_usb_hs_inactivity_timers_clk.clkr, [GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr, @@ -2653,6 +2741,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { [GCC_GFX_TBU_CLK] = &gcc_gfx_tbu_clk.clkr, [GCC_SMMU_CFG_CLK] = &gcc_smmu_cfg_clk.clkr, [GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr, + [GCC_CDSP_TBU_CLK] = &gcc_cdsp_tbu_clk.clkr, [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr, [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr, [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr, @@ -2664,6 +2753,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { static const struct qcom_reset_map gcc_qcs404_resets[] = { [GCC_GENI_IR_BCR] = { 0x0F000 }, + [GCC_CDSP_RESTART] = { 0x18000 }, [GCC_USB_HS_BCR] = { 0x41000 }, [GCC_USB2_HS_PHY_ONLY_BCR] = { 0x41034 }, [GCC_QUSB2_PHY_BCR] = { 0x4103c }, diff --git a/drivers/clk/qcom/turingcc-qcs404.c b/drivers/clk/qcom/turingcc-qcs404.c new file mode 100644 index 000000000000..aa859e6ec9bd --- /dev/null +++ b/drivers/clk/qcom/turingcc-qcs404.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019, Linaro Ltd. + */ + +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/pm_clock.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> + +#include <dt-bindings/clock/qcom,turingcc-qcs404.h> + +#include "clk-regmap.h" +#include "clk-branch.h" +#include "common.h" +#include "reset.h" + +static struct clk_branch turing_wrapper_aon_cbcr = { + .halt_reg = 0x5098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_wrapper_aon_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch turing_q6ss_ahbm_aon_cbcr = { + .halt_reg = 0x9000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_q6ss_ahbm_aon_cbcr", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch turing_q6ss_q6_axim_clk = { + .halt_reg = 0xb000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_q6ss_q6_axim_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch turing_q6ss_ahbs_aon_cbcr = { + .halt_reg = 0x10000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_q6ss_ahbs_aon_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch turing_wrapper_qos_ahbs_aon_cbcr = { + .halt_reg = 0x11014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_wrapper_qos_ahbs_aon_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_regmap *turingcc_clocks[] = { + [TURING_WRAPPER_AON_CLK] = &turing_wrapper_aon_cbcr.clkr, + [TURING_Q6SS_AHBM_AON_CLK] = &turing_q6ss_ahbm_aon_cbcr.clkr, + [TURING_Q6SS_Q6_AXIM_CLK] = &turing_q6ss_q6_axim_clk.clkr, + [TURING_Q6SS_AHBS_AON_CLK] = &turing_q6ss_ahbs_aon_cbcr.clkr, + [TURING_WRAPPER_QOS_AHBS_AON_CLK] = &turing_wrapper_qos_ahbs_aon_cbcr.clkr, +}; + +static const struct regmap_config turingcc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x30000, + .fast_io = true, +}; + +static const struct qcom_cc_desc turingcc_desc = { + .config = &turingcc_regmap_config, + .clks = turingcc_clocks, + .num_clks = ARRAY_SIZE(turingcc_clocks), +}; + +static int turingcc_probe(struct platform_device *pdev) +{ + int ret; + + pm_runtime_enable(&pdev->dev); + ret = pm_clk_create(&pdev->dev); + if (ret) + goto disable_pm_runtime; + + ret = pm_clk_add(&pdev->dev, NULL); + if (ret < 0) { + dev_err(&pdev->dev, "failed to acquire iface clock\n"); + goto destroy_pm_clk; + } + + ret = qcom_cc_probe(pdev, &turingcc_desc); + if (ret < 0) + goto destroy_pm_clk; + + return 0; + +destroy_pm_clk: + pm_clk_destroy(&pdev->dev); + +disable_pm_runtime: + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static int turingcc_remove(struct platform_device *pdev) +{ + pm_clk_destroy(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops turingcc_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static const struct of_device_id turingcc_match_table[] = { + { .compatible = "qcom,qcs404-turingcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, turingcc_match_table); + +static struct platform_driver turingcc_driver = { + .probe = turingcc_probe, + .remove = turingcc_remove, + .driver = { + .name = "qcs404-turingcc", + .of_match_table = turingcc_match_table, + .pm = &turingcc_pm_ops, + }, +}; + +module_platform_driver(turingcc_driver); + +MODULE_DESCRIPTION("Qualcomm QCS404 Turing Clock Controller"); +MODULE_LICENSE("GPL v2"); |