diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/qcom/Kconfig | 53 | ||||
-rw-r--r-- | drivers/clk/qcom/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-smd-rpm.c | 45 | ||||
-rw-r--r-- | drivers/clk/qcom/gcc-msm8916.c | 4 | ||||
-rw-r--r-- | drivers/clk/qcom/gdsc.c | 6 | ||||
-rw-r--r-- | drivers/clk/qcom/gpucc-sdm845.c | 252 |
6 files changed, 324 insertions, 37 deletions
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index a611531df115..aca754f09817 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -9,16 +9,17 @@ config QCOM_GDSC config QCOM_RPMCC bool -config COMMON_CLK_QCOM +menuconfig COMMON_CLK_QCOM tristate "Support for Qualcomm's clock controllers" depends on OF depends on ARCH_QCOM || COMPILE_TEST select REGMAP_MMIO select RESET_CONTROLLER +if COMMON_CLK_QCOM + config QCOM_A53PLL tristate "MSM8916 A53 PLL" - depends on COMMON_CLK_QCOM default ARCH_QCOM help Support for the A53 PLL on MSM8916 devices. It provides @@ -28,7 +29,6 @@ config QCOM_A53PLL config QCOM_CLK_APCS_MSM8916 tristate "MSM8916 APCS Clock Controller" - depends on COMMON_CLK_QCOM depends on QCOM_APCS_IPC || COMPILE_TEST default ARCH_QCOM help @@ -39,7 +39,7 @@ config QCOM_CLK_APCS_MSM8916 config QCOM_CLK_RPM tristate "RPM based Clock Controller" - depends on COMMON_CLK_QCOM && MFD_QCOM_RPM + depends on MFD_QCOM_RPM select QCOM_RPMCC help The RPM (Resource Power Manager) is a dedicated hardware engine for @@ -52,7 +52,7 @@ config QCOM_CLK_RPM config QCOM_CLK_SMD_RPM tristate "RPM over SMD based Clock Controller" - depends on COMMON_CLK_QCOM && QCOM_SMD_RPM + depends on QCOM_SMD_RPM select QCOM_RPMCC help The RPM (Resource Power Manager) is a dedicated hardware engine for @@ -65,7 +65,7 @@ config QCOM_CLK_SMD_RPM config QCOM_CLK_RPMH tristate "RPMh Clock Driver" - depends on COMMON_CLK_QCOM && QCOM_RPMH + depends on QCOM_RPMH help RPMh manages shared resources on some Qualcomm Technologies, Inc. SoCs. It accepts requests from other hardware subsystems via RSC. @@ -75,7 +75,6 @@ config QCOM_CLK_RPMH config APQ_GCC_8084 tristate "APQ8084 Global Clock Controller" select QCOM_GDSC - depends on COMMON_CLK_QCOM help Support for the global clock controller on apq8084 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -85,7 +84,6 @@ config APQ_MMCC_8084 tristate "APQ8084 Multimedia Clock Controller" select APQ_GCC_8084 select QCOM_GDSC - depends on COMMON_CLK_QCOM help Support for the multimedia clock controller on apq8084 devices. Say Y if you want to support multimedia devices such as display, @@ -93,7 +91,6 @@ config APQ_MMCC_8084 config IPQ_GCC_4019 tristate "IPQ4019 Global Clock Controller" - depends on COMMON_CLK_QCOM help Support for the global clock controller on ipq4019 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -101,7 +98,6 @@ config IPQ_GCC_4019 config IPQ_GCC_806X tristate "IPQ806x Global Clock Controller" - depends on COMMON_CLK_QCOM help Support for the global clock controller on ipq806x devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -110,7 +106,6 @@ config IPQ_GCC_806X config IPQ_LCC_806X tristate "IPQ806x LPASS Clock Controller" select IPQ_GCC_806X - depends on COMMON_CLK_QCOM help Support for the LPASS clock controller on ipq806x devices. Say Y if you want to use audio devices such as i2s, pcm, @@ -118,7 +113,6 @@ config IPQ_LCC_806X config IPQ_GCC_8074 tristate "IPQ8074 Global Clock Controller" - depends on COMMON_CLK_QCOM help Support for global clock controller on ipq8074 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -127,7 +121,6 @@ config IPQ_GCC_8074 config MSM_GCC_8660 tristate "MSM8660 Global Clock Controller" - depends on COMMON_CLK_QCOM help Support for the global clock controller on msm8660 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -136,7 +129,6 @@ config MSM_GCC_8660 config MSM_GCC_8916 tristate "MSM8916 Global Clock Controller" select QCOM_GDSC - depends on COMMON_CLK_QCOM help Support for the global clock controller on msm8916 devices. Say Y if you want to use devices such as UART, SPI i2c, USB, @@ -144,7 +136,6 @@ config MSM_GCC_8916 config MSM_GCC_8960 tristate "APQ8064/MSM8960 Global Clock Controller" - depends on COMMON_CLK_QCOM help Support for the global clock controller on apq8064/msm8960 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -153,7 +144,6 @@ config MSM_GCC_8960 config MSM_LCC_8960 tristate "APQ8064/MSM8960 LPASS Clock Controller" select MSM_GCC_8960 - depends on COMMON_CLK_QCOM help Support for the LPASS clock controller on apq8064/msm8960 devices. Say Y if you want to use audio devices such as i2s, pcm, @@ -161,7 +151,6 @@ config MSM_LCC_8960 config MDM_GCC_9615 tristate "MDM9615 Global Clock Controller" - depends on COMMON_CLK_QCOM help Support for the global clock controller on mdm9615 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -170,7 +159,6 @@ config MDM_GCC_9615 config MDM_LCC_9615 tristate "MDM9615 LPASS Clock Controller" select MDM_GCC_9615 - depends on COMMON_CLK_QCOM help Support for the LPASS clock controller on mdm9615 devices. Say Y if you want to use audio devices such as i2s, pcm, @@ -179,7 +167,6 @@ config MDM_LCC_9615 config MSM_MMCC_8960 tristate "MSM8960 Multimedia Clock Controller" select MSM_GCC_8960 - depends on COMMON_CLK_QCOM help Support for the multimedia clock controller on msm8960 devices. Say Y if you want to support multimedia devices such as display, @@ -188,7 +175,6 @@ config MSM_MMCC_8960 config MSM_GCC_8974 tristate "MSM8974 Global Clock Controller" select QCOM_GDSC - depends on COMMON_CLK_QCOM help Support for the global clock controller on msm8974 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -198,7 +184,6 @@ config MSM_MMCC_8974 tristate "MSM8974 Multimedia Clock Controller" select MSM_GCC_8974 select QCOM_GDSC - depends on COMMON_CLK_QCOM help Support for the multimedia clock controller on msm8974 devices. Say Y if you want to support multimedia devices such as display, @@ -206,7 +191,6 @@ config MSM_MMCC_8974 config MSM_GCC_8994 tristate "MSM8994 Global Clock Controller" - depends on COMMON_CLK_QCOM help Support for the global clock controller on msm8994 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -215,7 +199,6 @@ config MSM_GCC_8994 config MSM_GCC_8996 tristate "MSM8996 Global Clock Controller" select QCOM_GDSC - depends on COMMON_CLK_QCOM help Support for the global clock controller on msm8996 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -225,7 +208,6 @@ config MSM_MMCC_8996 tristate "MSM8996 Multimedia Clock Controller" select MSM_GCC_8996 select QCOM_GDSC - depends on COMMON_CLK_QCOM help Support for the multimedia clock controller on msm8996 devices. Say Y if you want to support multimedia devices such as display, @@ -233,7 +215,6 @@ config MSM_MMCC_8996 config MSM_GCC_8998 tristate "MSM8998 Global Clock Controller" - depends on COMMON_CLK_QCOM help Support for the global clock controller on msm8998 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -241,7 +222,6 @@ config MSM_GCC_8998 config QCS_GCC_404 tristate "QCS404 Global Clock Controller" - depends on COMMON_CLK_QCOM help Support for the global clock controller on QCS404 devices. Say Y if you want to use multimedia devices or peripheral @@ -249,7 +229,6 @@ config QCS_GCC_404 config SDM_CAMCC_845 tristate "SDM845 Camera Clock Controller" - depends on COMMON_CLK_QCOM select SDM_GCC_845 help Support for the camera clock controller on SDM845 devices. @@ -258,7 +237,6 @@ config SDM_CAMCC_845 config SDM_GCC_660 tristate "SDM660 Global Clock Controller" select QCOM_GDSC - depends on COMMON_CLK_QCOM help Support for the global clock controller on SDM660 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -267,15 +245,21 @@ config SDM_GCC_660 config SDM_GCC_845 tristate "SDM845 Global Clock Controller" select QCOM_GDSC - depends on COMMON_CLK_QCOM help Support for the global clock controller on SDM845 devices. Say Y if you want to use peripheral devices such as UART, SPI, i2C, USB, UFS, SDDC, PCIe, etc. +config SDM_GPUCC_845 + tristate "SDM845 Graphics Clock Controller" + select SDM_GCC_845 + help + Support for the graphics clock controller on SDM845 devices. + Say Y if you want to support graphics controller devices and + functionality such as 3D graphics. + config SDM_VIDEOCC_845 tristate "SDM845 Video Clock Controller" - depends on COMMON_CLK_QCOM select SDM_GCC_845 select QCOM_GDSC help @@ -286,7 +270,6 @@ config SDM_VIDEOCC_845 config SDM_DISPCC_845 tristate "SDM845 Display Clock Controller" select SDM_GCC_845 - depends on COMMON_CLK_QCOM help Support for the display clock controller on Qualcomm Technologies, Inc SDM845 devices. @@ -295,7 +278,7 @@ config SDM_DISPCC_845 config SPMI_PMIC_CLKDIV tristate "SPMI PMIC clkdiv Support" - depends on (COMMON_CLK_QCOM && SPMI) || COMPILE_TEST + depends on SPMI || COMPILE_TEST help This driver supports the clkdiv functionality on the Qualcomm Technologies, Inc. SPMI PMIC. It configures the frequency of @@ -304,7 +287,6 @@ config SPMI_PMIC_CLKDIV config QCOM_HFPLL tristate "High-Frequency PLL (HFPLL) Clock Controller" - depends on COMMON_CLK_QCOM help Support for the high-frequency PLLs present on Qualcomm devices. Say Y if you want to support CPU frequency scaling on devices @@ -312,7 +294,6 @@ config QCOM_HFPLL config KPSS_XCC tristate "KPSS Clock Controller" - depends on COMMON_CLK_QCOM help Support for the Krait ACC and GCC clock controllers. Say Y if you want to support CPU frequency scaling on devices such @@ -320,8 +301,10 @@ config KPSS_XCC config KRAITCC tristate "Krait Clock Controller" - depends on COMMON_CLK_QCOM && ARM + depends on ARM select KRAIT_CLOCKS help Support for the Krait CPU clocks on Qualcomm devices. Say Y if you want to support CPU frequency scaling. + +endif diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 981882e16189..6ed28272e176 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o +obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 850c02a52248..d3aadaeb2903 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -611,10 +611,55 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8996 = { .num_clks = ARRAY_SIZE(msm8996_clks), }; +/* QCS404 */ +DEFINE_CLK_SMD_RPM_QDSS(qcs404, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); + +DEFINE_CLK_SMD_RPM(qcs404, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); +DEFINE_CLK_SMD_RPM(qcs404, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); + +DEFINE_CLK_SMD_RPM(qcs404, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); +DEFINE_CLK_SMD_RPM(qcs404, bimc_gpu_clk, bimc_gpu_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); + +DEFINE_CLK_SMD_RPM(qcs404, qpic_clk, qpic_a_clk, QCOM_SMD_RPM_QPIC_CLK, 0); +DEFINE_CLK_SMD_RPM(qcs404, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); + +DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs404, rf_clk1, rf_clk1_a, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs404, rf_clk1_pin, rf_clk1_a_pin, 4); + +DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs404, ln_bb_clk, ln_bb_a_clk, 8); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs404, ln_bb_clk_pin, ln_bb_clk_a_pin, 8); + +static struct clk_smd_rpm *qcs404_clks[] = { + [RPM_SMD_QDSS_CLK] = &qcs404_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &qcs404_qdss_a_clk, + [RPM_SMD_PNOC_CLK] = &qcs404_pnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &qcs404_pnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &qcs404_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &qcs404_snoc_a_clk, + [RPM_SMD_BIMC_CLK] = &qcs404_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &qcs404_bimc_a_clk, + [RPM_SMD_BIMC_GPU_CLK] = &qcs404_bimc_gpu_clk, + [RPM_SMD_BIMC_GPU_A_CLK] = &qcs404_bimc_gpu_a_clk, + [RPM_SMD_QPIC_CLK] = &qcs404_qpic_clk, + [RPM_SMD_QPIC_CLK_A] = &qcs404_qpic_a_clk, + [RPM_SMD_CE1_CLK] = &qcs404_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &qcs404_ce1_a_clk, + [RPM_SMD_RF_CLK1] = &qcs404_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &qcs404_rf_clk1_a, + [RPM_SMD_LN_BB_CLK] = &qcs404_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &qcs404_ln_bb_a_clk, +}; + +static const struct rpm_smd_clk_desc rpm_clk_qcs404 = { + .clks = qcs404_clks, + .num_clks = ARRAY_SIZE(qcs404_clks), +}; + static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 }, + { .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 }, { } }; MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table); diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index ac2b0aa1e8b5..7d9647cc29f9 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -544,7 +544,11 @@ static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = { }; static const struct freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = { + F(100000, P_XO, 16, 2, 24), + F(250000, P_XO, 16, 5, 24), + F(500000, P_XO, 8, 5, 24), F(960000, P_XO, 10, 1, 2), + F(1000000, P_XO, 4, 5, 24), F(4800000, P_XO, 4, 0, 0), F(9600000, P_XO, 2, 0, 0), F(16000000, P_GPLL0, 10, 1, 5), diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index a077133c7ce3..dd63aa36b092 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -350,8 +350,10 @@ static int gdsc_init(struct gdsc *sc) else gdsc_clear_mem_on(sc); - sc->pd.power_off = gdsc_disable; - sc->pd.power_on = gdsc_enable; + if (!sc->pd.power_off) + sc->pd.power_off = gdsc_disable; + if (!sc->pd.power_on) + sc->pd.power_on = gdsc_enable; pm_genpd_init(&sc->pd, NULL, !on); return 0; diff --git a/drivers/clk/qcom/gpucc-sdm845.c b/drivers/clk/qcom/gpucc-sdm845.c new file mode 100644 index 000000000000..e40efba1bf7d --- /dev/null +++ b/drivers/clk/qcom/gpucc-sdm845.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include <dt-bindings/clock/qcom,gpucc-sdm845.h> + +#include "common.h" +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "gdsc.h" + +#define CX_GMU_CBCR_SLEEP_MASK 0xf +#define CX_GMU_CBCR_SLEEP_SHIFT 4 +#define CX_GMU_CBCR_WAKE_MASK 0xf +#define CX_GMU_CBCR_WAKE_SHIFT 8 +#define CLK_DIS_WAIT_SHIFT 12 +#define CLK_DIS_WAIT_MASK (0xf << CLK_DIS_WAIT_SHIFT) + +enum { + P_BI_TCXO, + P_CORE_BI_PLL_TEST_SE, + P_GPLL0_OUT_MAIN, + P_GPLL0_OUT_MAIN_DIV, + P_GPU_CC_PLL1_OUT_EVEN, + P_GPU_CC_PLL1_OUT_MAIN, + P_GPU_CC_PLL1_OUT_ODD, +}; + +static const struct parent_map gpu_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { 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 char * const gpu_cc_parent_names_0[] = { + "bi_tcxo", + "gpu_cc_pll1", + "gcc_gpu_gpll0_clk_src", + "gcc_gpu_gpll0_div_clk_src", + "core_bi_pll_test_se", +}; + +static const struct alpha_pll_config gpu_cc_pll1_config = { + .l = 0x1a, + .alpha = 0xaab, +}; + +static struct clk_alpha_pll gpu_cc_pll1 = { + .offset = 0x100, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_pll1", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_fabia_ops, + }, + }, +}; + +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, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gmu_clk_src", + .parent_names = gpu_cc_parent_names_0, + .num_parents = 5, + .ops = &clk_rcg2_shared_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_names = (const char *[]){ + "gpu_cc_gmu_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .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 gdsc gpu_cx_gdsc = { + .gdscr = 0x106c, + .gds_hw_ctrl = 0x1540, + .pd = { + .name = "gpu_cx_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +/* + * On SDM845 the GPU GX domain is *almost* entirely controlled by the GMU + * running in the CX domain so the CPU doesn't need to know anything about the + * GX domain EXCEPT.... + * + * Hardware constraints dictate that the GX be powered down before the CX. If + * the GMU crashes it could leave the GX on. In order to successfully bring back + * the device the CPU needs to disable the GX headswitch. There being no sane + * way to reach in and touch that register from deep inside the GPU driver we + * need to set up the infrastructure to be able to ensure that the GPU can + * ensure that the GX is off during this super special case. We do this by + * defining a GX gdsc with a dummy enable function and a "default" disable + * function. + * + * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU + * driver. During power up, nothing will happen from the CPU (and the GMU will + * power up normally but during power down this will ensure that the GX domain + * is *really* off - this gives us a semi standard way of doing what we need. + */ +static int gx_gdsc_enable(struct generic_pm_domain *domain) +{ + /* Do nothing but give genpd the impression that we were successful */ + return 0; +} + +static struct gdsc gpu_gx_gdsc = { + .gdscr = 0x100c, + .clamp_io_ctrl = 0x1508, + .pd = { + .name = "gpu_gx_gdsc", + .power_on = gx_gdsc_enable, + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR, +}; + +static struct clk_regmap *gpu_cc_sdm845_clocks[] = { + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, + [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, +}; + +static struct gdsc *gpu_cc_sdm845_gdscs[] = { + [GPU_CX_GDSC] = &gpu_cx_gdsc, + [GPU_GX_GDSC] = &gpu_gx_gdsc, +}; + +static const struct regmap_config gpu_cc_sdm845_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_sdm845_desc = { + .config = &gpu_cc_sdm845_regmap_config, + .clks = gpu_cc_sdm845_clocks, + .num_clks = ARRAY_SIZE(gpu_cc_sdm845_clocks), + .gdscs = gpu_cc_sdm845_gdscs, + .num_gdscs = ARRAY_SIZE(gpu_cc_sdm845_gdscs), +}; + +static const struct of_device_id gpu_cc_sdm845_match_table[] = { + { .compatible = "qcom,sdm845-gpucc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpu_cc_sdm845_match_table); + +static int gpu_cc_sdm845_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + unsigned int value, mask; + + regmap = qcom_cc_map(pdev, &gpu_cc_sdm845_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_fabia_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); + + /* + * Configure gpu_cc_cx_gmu_clk with recommended + * wakeup/sleep settings + */ + mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT; + mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT; + value = 0xf << CX_GMU_CBCR_WAKE_SHIFT | 0xf << CX_GMU_CBCR_SLEEP_SHIFT; + regmap_update_bits(regmap, 0x1098, mask, value); + + /* Configure clk_dis_wait for gpu_cx_gdsc */ + regmap_update_bits(regmap, 0x106c, CLK_DIS_WAIT_MASK, + 8 << CLK_DIS_WAIT_SHIFT); + + return qcom_cc_really_probe(pdev, &gpu_cc_sdm845_desc, regmap); +} + +static struct platform_driver gpu_cc_sdm845_driver = { + .probe = gpu_cc_sdm845_probe, + .driver = { + .name = "sdm845-gpucc", + .of_match_table = gpu_cc_sdm845_match_table, + }, +}; + +static int __init gpu_cc_sdm845_init(void) +{ + return platform_driver_register(&gpu_cc_sdm845_driver); +} +subsys_initcall(gpu_cc_sdm845_init); + +static void __exit gpu_cc_sdm845_exit(void) +{ + platform_driver_unregister(&gpu_cc_sdm845_driver); +} +module_exit(gpu_cc_sdm845_exit); + +MODULE_DESCRIPTION("QTI GPUCC SDM845 Driver"); +MODULE_LICENSE("GPL v2"); |