The Adreno GPU on MSM8998 has its own clock controller, which is a
dependency for bringing up the GPU. This series gets the gpucc all in
place as another step on the road to getting the GPU enabled.
Jeffrey Hugo (3):
dt-bindings: clock: Document gpucc for msm8998
clk: qcom: Add MSM8998 GPU Clock Controller (GPUCC) driver
arm64: dts: qcom: msm8998: Add gpucc node
.../devicetree/bindings/clock/qcom,gpucc.txt | 4 +-
arch/arm64/boot/dts/qcom/msm8998.dtsi | 15 +
drivers/clk/qcom/Kconfig | 8 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/gpucc-msm8998.c | 364 ++++++++++++++++++
.../dt-bindings/clock/qcom,gpucc-msm8998.h | 29 ++
6 files changed, 420 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/qcom/gpucc-msm8998.c
create mode 100644 include/dt-bindings/clock/qcom,gpucc-msm8998.h
--
2.17.1
The GPU for msm8998 has its own clock controller. Document it.
Signed-off-by: Jeffrey Hugo <[email protected]>
---
.../devicetree/bindings/clock/qcom,gpucc.txt | 4 ++-
.../dt-bindings/clock/qcom,gpucc-msm8998.h | 29 +++++++++++++++++++
2 files changed, 32 insertions(+), 1 deletion(-)
create mode 100644 include/dt-bindings/clock/qcom,gpucc-msm8998.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.txt b/Documentation/devicetree/bindings/clock/qcom,gpucc.txt
index 4e5215ef1acd..269afe8a757e 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gpucc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.txt
@@ -2,13 +2,15 @@ Qualcomm Graphics Clock & Reset Controller Binding
--------------------------------------------------
Required properties :
-- compatible : shall contain "qcom,sdm845-gpucc"
+- compatible : shall contain "qcom,sdm845-gpucc" or "qcom,msm8998-gpucc"
- reg : shall contain base register location and length
- #clock-cells : from common clock binding, shall contain 1
- #reset-cells : from common reset binding, shall contain 1
- #power-domain-cells : from generic power domain binding, shall contain 1
- clocks : shall contain the XO clock
+ shall contain the gpll0 out main clock (msm8998)
- clock-names : shall be "xo"
+ shall be "gpll0" (msm8998)
Example:
gpucc: clock-controller@5090000 {
diff --git a/include/dt-bindings/clock/qcom,gpucc-msm8998.h b/include/dt-bindings/clock/qcom,gpucc-msm8998.h
new file mode 100644
index 000000000000..2623570ee974
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gpucc-msm8998.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019, Jeffrey Hugo
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GPUCC_8998_H
+#define _DT_BINDINGS_CLK_MSM_GPUCC_8998_H
+
+#define GPUPLL0 0
+#define GPUPLL0_OUT_EVEN 1
+#define RBCPR_CLK_SRC 2
+#define GFX3D_CLK_SRC 3
+#define RBBMTIMER_CLK_SRC 4
+#define GFX3D_ISENSE_CLK_SRC 5
+#define RBCPR_CLK 6
+#define GFX3D_CLK 7
+#define RBBMTIMER_CLK 8
+#define GFX3D_ISENSE_CLK 9
+#define GPUCC_CXO_CLK 10
+
+#define GPU_CX_BCR 0
+#define RBCPR_BCR 1
+#define GPU_GX_BCR 2
+#define GPU_ISENSE_BCR 3
+
+#define GPU_CX_GDSC 1
+#define GPU_GX_GDSC 2
+
+#endif
--
2.17.1
The GPUCC manages the clocks for the Adreno GPU found on MSM8998.
Signed-off-by: Jeffrey Hugo <[email protected]>
---
drivers/clk/qcom/Kconfig | 8 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/gpucc-msm8998.c | 364 +++++++++++++++++++++++++++++++
3 files changed, 373 insertions(+)
create mode 100644 drivers/clk/qcom/gpucc-msm8998.c
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index e1ff83cc361e..e992682fb9eb 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -222,6 +222,14 @@ config MSM_GCC_8998
Say Y if you want to use peripheral devices such as UART, SPI,
i2c, USB, UFS, SD/eMMC, PCIe, etc.
+config MSM_GPUCC_8998
+ tristate "MSM8998 Graphics Clock Controller"
+ select MSM_GCC_8998
+ help
+ Support for the graphics clock controller on MSM8998 devices.
+ Say Y if you want to support graphics controller devices and
+ functionality such as 3D graphics.
+
config QCS_GCC_404
tristate "QCS404 Global Clock Controller"
help
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index f0768fb1f037..b8b6ffbdbd62 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o
obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o
obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
obj-$(CONFIG_MSM_GCC_8998) += gcc-msm8998.o
+obj-$(CONFIG_MSM_GPUCC_8998) += gpucc-msm8998.o
obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
diff --git a/drivers/clk/qcom/gpucc-msm8998.c b/drivers/clk/qcom/gpucc-msm8998.c
new file mode 100644
index 000000000000..e45062e40718
--- /dev/null
+++ b/drivers/clk/qcom/gpucc-msm8998.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, Jeffrey Hugo
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/clk.h>
+
+#include <dt-bindings/clock/qcom,gpucc-msm8998.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+#include "gdsc.h"
+
+enum {
+ P_XO,
+ P_GPLL0,
+ P_GPUPLL0_OUT_EVEN,
+};
+
+/* Instead of going directly to the block, XO is routed through this branch */
+static struct clk_branch gpucc_cxo_clk = {
+ .halt_reg = 0x1020,
+ .clkr = {
+ .enable_reg = 0x1020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpucc_cxo_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ .name = "xo"
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_IS_CRITICAL,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_fabia_even[] = {
+ { 0x0, 1 },
+ { 0x1, 2 },
+ { 0x3, 4 },
+ { 0x7, 8 },
+ { }
+};
+
+static struct clk_alpha_pll gpupll0 = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpupll0",
+ .parent_hws = (const struct clk_hw *[]){ &gpucc_cxo_clk.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_fabia_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpupll0_out_even = {
+ .offset = 0x0,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_fabia_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_fabia_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpupll0_out_even",
+ .parent_hws = (const struct clk_hw *[]){ &gpupll0.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_fabia_ops,
+ },
+};
+
+static const struct parent_map gpu_xo_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 5 },
+};
+
+static const struct clk_parent_data gpu_xo_gpll0[] = {
+ { .hw = &gpucc_cxo_clk.clkr.hw },
+ { .fw_name = "gpll0", .name = "gpll0" },
+};
+
+static const struct parent_map gpu_xo_gpupll0_map[] = {
+ { P_XO, 0 },
+ { P_GPUPLL0_OUT_EVEN, 1 },
+};
+
+static const struct clk_parent_data gpu_xo_gpupll0[] = {
+ { .hw = &gpucc_cxo_clk.clkr.hw },
+ { .hw = &gpupll0_out_even.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_rbcpr_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 rbcpr_clk_src = {
+ .cmd_rcgr = 0x1030,
+ .hid_width = 5,
+ .parent_map = gpu_xo_gpll0_map,
+ .freq_tbl = ftbl_rbcpr_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "rbcpr_clk_src",
+ .parent_data = gpu_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gfx3d_clk_src[] = {
+ F(180000000, P_GPUPLL0_OUT_EVEN, 2, 0, 0),
+ F(257000000, P_GPUPLL0_OUT_EVEN, 2, 0, 0),
+ F(342000000, P_GPUPLL0_OUT_EVEN, 2, 0, 0),
+ F(414000000, P_GPUPLL0_OUT_EVEN, 2, 0, 0),
+ F(515000000, P_GPUPLL0_OUT_EVEN, 2, 0, 0),
+ F(596000000, P_GPUPLL0_OUT_EVEN, 2, 0, 0),
+ F(670000000, P_GPUPLL0_OUT_EVEN, 2, 0, 0),
+ F(710000000, P_GPUPLL0_OUT_EVEN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gfx3d_clk_src = {
+ .cmd_rcgr = 0x1070,
+ .hid_width = 5,
+ .parent_map = gpu_xo_gpupll0_map,
+ .freq_tbl = ftbl_gfx3d_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gfx3d_clk_src",
+ .parent_data = gpu_xo_gpupll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ .flags = CLK_OPS_PARENT_ENABLE,
+ },
+};
+
+static const struct freq_tbl ftbl_rbbmtimer_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 rbbmtimer_clk_src = {
+ .cmd_rcgr = 0x10b0,
+ .hid_width = 5,
+ .parent_map = gpu_xo_gpll0_map,
+ .freq_tbl = ftbl_rbbmtimer_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "rbbmtimer_clk_src",
+ .parent_data = gpu_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gfx3d_isense_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(40000000, P_GPLL0, 15, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gfx3d_isense_clk_src = {
+ .cmd_rcgr = 0x1100,
+ .hid_width = 5,
+ .parent_map = gpu_xo_gpll0_map,
+ .freq_tbl = ftbl_gfx3d_isense_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gfx3d_isense_clk_src",
+ .parent_data = gpu_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch rbcpr_clk = {
+ .halt_reg = 0x1054,
+ .clkr = {
+ .enable_reg = 0x1054,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "rbcpr_clk",
+ .parent_hws = (const struct clk_hw *[]){ &rbcpr_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch gfx3d_clk = {
+ .halt_reg = 0x1098,
+ .clkr = {
+ .enable_reg = 0x1098,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gfx3d_clk",
+ .parent_hws = (const struct clk_hw *[]){ &gfx3d_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch rbbmtimer_clk = {
+ .halt_reg = 0x10d0,
+ .clkr = {
+ .enable_reg = 0x10d0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "rbbmtimer_clk",
+ .parent_hws = (const struct clk_hw *[]){ &rbbmtimer_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch gfx3d_isense_clk = {
+ .halt_reg = 0x1124,
+ .clkr = {
+ .enable_reg = 0x1124,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gfx3d_isense_clk",
+ .parent_hws = (const struct clk_hw *[]){ &gfx3d_isense_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+//static struct clk_hw *gpucc_msm8998_hws[] = {
+// &gpucc_cxo_clk.clkr.hw,
+//};
+
+static struct gdsc gpu_cx_gdsc = {
+ .gdscr = 0x1004,
+ .pd = {
+ .name = "gpu_cx",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc gpu_gx_gdsc = {
+ .gdscr = 0x1094,
+ .clamp_io_ctrl = 0x130,
+ //.cxcs = (unsigned int []){ 0x1098 },
+ //.cxc_count = 1,
+ .pd = {
+ .name = "gpu_gx",
+ },
+ .parent = &gpu_cx_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = CLAMP_IO | AON_RESET,
+};
+
+static struct clk_regmap *gpucc_msm8998_clocks[] = {
+ [GPUPLL0] = &gpupll0.clkr,
+ [GPUPLL0_OUT_EVEN] = &gpupll0_out_even.clkr,
+ [RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,
+ [GFX3D_CLK_SRC] = &gfx3d_clk_src.clkr,
+ [RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr,
+ [GFX3D_ISENSE_CLK_SRC] = &gfx3d_isense_clk_src.clkr,
+ [RBCPR_CLK] = &rbcpr_clk.clkr,
+ [GFX3D_CLK] = &gfx3d_clk.clkr,
+ [RBBMTIMER_CLK] = &rbbmtimer_clk.clkr,
+ [GFX3D_ISENSE_CLK] = &gfx3d_isense_clk.clkr,
+ [GPUCC_CXO_CLK] = &gpucc_cxo_clk.clkr,
+};
+
+static struct gdsc *gpucc_msm8998_gdscs[] = {
+ [GPU_CX_GDSC] = &gpu_cx_gdsc,
+ [GPU_GX_GDSC] = &gpu_gx_gdsc,
+};
+
+static const struct qcom_reset_map gpucc_msm8998_resets[] = {
+ [GPU_CX_BCR] = { 0x1000 },
+ [RBCPR_BCR] = { 0x1050 },
+ [GPU_GX_BCR] = { 0x1090 },
+ [GPU_ISENSE_BCR] = { 0x1120 },
+};
+
+static const struct regmap_config gpucc_msm8998_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x9000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gpucc_msm8998_desc = {
+ .config = &gpucc_msm8998_regmap_config,
+ .clks = gpucc_msm8998_clocks,
+ .num_clks = ARRAY_SIZE(gpucc_msm8998_clocks),
+ .resets = gpucc_msm8998_resets,
+ .num_resets = ARRAY_SIZE(gpucc_msm8998_resets),
+ .gdscs = gpucc_msm8998_gdscs,
+ .num_gdscs = ARRAY_SIZE(gpucc_msm8998_gdscs),
+ //.clk_hws = gpucc_msm8998_hws,
+ //.num_clk_hws = ARRAY_SIZE(gpucc_msm8998_hws),
+};
+
+static const struct of_device_id gpucc_msm8998_match_table[] = {
+ { .compatible = "qcom,gpucc-msm8998" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gpucc_msm8998_match_table);
+
+static int gpucc_msm8998_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ struct clk *xo;
+
+ /*
+ * We must have a valid XO to continue until orphan probe defer is
+ * implemented.
+ */
+ xo = clk_get(&pdev->dev, "xo");
+ if (IS_ERR(xo))
+ return PTR_ERR(xo);
+ clk_put(xo);
+
+ regmap = qcom_cc_map(pdev, &gpucc_msm8998_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /* force periph logic on to acoid perf counter corruption */
+ regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(13), BIT(13));
+ /* tweak droop detector (GPUCC_GPU_DD_WRAP_CTRL) to reduce leakage */
+ regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(0), BIT(0));
+
+ return qcom_cc_really_probe(pdev, &gpucc_msm8998_desc, regmap);
+}
+
+static struct platform_driver gpucc_msm8998_driver = {
+ .probe = gpucc_msm8998_probe,
+ .driver = {
+ .name = "gpucc-msm8998",
+ .of_match_table = gpucc_msm8998_match_table,
+ },
+};
+module_platform_driver(gpucc_msm8998_driver);
+
+MODULE_DESCRIPTION("QCOM GPUCC MSM8998 Driver");
+MODULE_LICENSE("GPL v2");
--
2.17.1
Add MSM8998 GPU Clock Controller DT node.
Signed-off-by: Jeffrey Hugo <[email protected]>
---
arch/arm64/boot/dts/qcom/msm8998.dtsi | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
index 574be78a936e..cf00bfeec6b3 100644
--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
@@ -3,6 +3,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-msm8998.h>
+#include <dt-bindings/clock/qcom,gpucc-msm8998.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/gpio/gpio.h>
@@ -763,6 +764,20 @@
reg = <0x1f40000 0x20000>;
};
+ gpucc: clock-controller@5065000 {
+ compatible = "qcom,gpucc-msm8998";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ reg = <0x05065000 0x9000>;
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&gcc GPLL0_OUT_MAIN>;
+ clock-names = "xo",
+ "gpll0";
+ };
+
+
apcs_glb: mailbox@9820000 {
compatible = "qcom,msm8998-apcs-hmss-global";
reg = <0x17911000 0x1000>;
--
2.17.1
Quoting Jeffrey Hugo (2019-05-28 09:48:03)
> diff --git a/drivers/clk/qcom/gpucc-msm8998.c b/drivers/clk/qcom/gpucc-msm8998.c
> new file mode 100644
> index 000000000000..e45062e40718
> --- /dev/null
> +++ b/drivers/clk/qcom/gpucc-msm8998.c
> +
> +static int gpucc_msm8998_probe(struct platform_device *pdev)
> +{
> + struct regmap *regmap;
> + struct clk *xo;
> +
> + /*
> + * We must have a valid XO to continue until orphan probe defer is
> + * implemented.
> + */
> + xo = clk_get(&pdev->dev, "xo");
Why is this necessary?
> + if (IS_ERR(xo))
> + return PTR_ERR(xo);
> + clk_put(xo);
> +
> + regmap = qcom_cc_map(pdev, &gpucc_msm8998_desc);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + /* force periph logic on to acoid perf counter corruption */
avoid?
> + regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(13), BIT(13));
> + /* tweak droop detector (GPUCC_GPU_DD_WRAP_CTRL) to reduce leakage */
> + regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(0), BIT(0));
> +
> + return qcom_cc_really_probe(pdev, &gpucc_msm8998_desc, regmap);
> +}
> +
Quoting Jeffrey Hugo (2019-05-28 09:47:40)
> The GPU for msm8998 has its own clock controller. Document it.
>
> Signed-off-by: Jeffrey Hugo <[email protected]>
> ---
Applied to clk-next
On Thu, Jun 6, 2019 at 5:00 PM Stephen Boyd <[email protected]> wrote:
>
> Quoting Jeffrey Hugo (2019-05-28 09:48:03)
> > diff --git a/drivers/clk/qcom/gpucc-msm8998.c b/drivers/clk/qcom/gpucc-msm8998.c
> > new file mode 100644
> > index 000000000000..e45062e40718
> > --- /dev/null
> > +++ b/drivers/clk/qcom/gpucc-msm8998.c
> > +
> > +static int gpucc_msm8998_probe(struct platform_device *pdev)
> > +{
> > + struct regmap *regmap;
> > + struct clk *xo;
> > +
> > + /*
> > + * We must have a valid XO to continue until orphan probe defer is
> > + * implemented.
> > + */
> > + xo = clk_get(&pdev->dev, "xo");
>
> Why is this necessary?
As you well know, XO is the root clock for pretty much everything on
Qualcomm platforms. We are trying to do things "properly" on 8998.
We are planning on having rpmcc manage it (see my other series), and
all the other components consume xo from there. Unfortunately we
cannot control the probe order, particularly when things are built as
modules, so its possible gpucc might be the first thing to probe.
Currently, the clock framework will allow that since everything in
gpucc will just be an orphan. However that doesn't prevent gpucc
consumers from grabbing their clocks, and we've seen that cause
issues.
As you've previously explained, you have a ton of work to do to
refactor things so that a clock will probe defer if its dependencies
are not present. We'd prefer that functionality, but are not really
willing to wait for it. Thus, we are implementing the same
functionality in the driver until the framework handles it for us, at
which point we'll gladly rip this out.
>
> > + if (IS_ERR(xo))
> > + return PTR_ERR(xo);
> > + clk_put(xo);
> > +
> > + regmap = qcom_cc_map(pdev, &gpucc_msm8998_desc);
> > + if (IS_ERR(regmap))
> > + return PTR_ERR(regmap);
> > +
> > + /* force periph logic on to acoid perf counter corruption */
>
> avoid?
Yes. Do you want a v3 with this fixed?
>
> > + regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(13), BIT(13));
> > + /* tweak droop detector (GPUCC_GPU_DD_WRAP_CTRL) to reduce leakage */
> > + regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(0), BIT(0));
> > +
> > + return qcom_cc_really_probe(pdev, &gpucc_msm8998_desc, regmap);
> > +}
> > +
Quoting Jeffrey Hugo (2019-06-07 07:08:46)
>
> As you well know, XO is the root clock for pretty much everything on
> Qualcomm platforms. We are trying to do things "properly" on 8998.
> We are planning on having rpmcc manage it (see my other series), and
I don't have the rpmcc series in my queue. I think it needs a resend?
> all the other components consume xo from there. Unfortunately we
> cannot control the probe order, particularly when things are built as
> modules, so its possible gpucc might be the first thing to probe.
> Currently, the clock framework will allow that since everything in
> gpucc will just be an orphan. However that doesn't prevent gpucc
> consumers from grabbing their clocks, and we've seen that cause
> issues.
>
> As you've previously explained, you have a ton of work to do to
> refactor things so that a clock will probe defer if its dependencies
> are not present. We'd prefer that functionality, but are not really
> willing to wait for it. Thus, we are implementing the same
> functionality in the driver until the framework handles it for us, at
> which point we'll gladly rip this out.
Can you add more to the comment? Right now it doesn't explain the _why_
part that you describe in the first paragraph here. That's what I'm
asking to be put here as a comment. Also, GCC is the one exporting the
XO clk on this platform so I'm a little lost why we're talking about rpm
here.
I guess I'm left to do the ton of work myself and get to have clk
providers like this be clk consumers so that probe ordering is correct
and clks aren't exposed until the whole parent chain exists. This is
taking a step backwards and causes me to be sad.
>
> >
> > > + if (IS_ERR(xo))
> > > + return PTR_ERR(xo);
> > > + clk_put(xo);
> > > +
> > > + regmap = qcom_cc_map(pdev, &gpucc_msm8998_desc);
> > > + if (IS_ERR(regmap))
> > > + return PTR_ERR(regmap);
> > > +
> > > + /* force periph logic on to acoid perf counter corruption */
> >
> > avoid?
>
> Yes. Do you want a v3 with this fixed?
Yes, please resend without the binding patch that I've already applied.
On Fri, Jun 7, 2019 at 2:32 PM Stephen Boyd <[email protected]> wrote:
>
> Quoting Jeffrey Hugo (2019-06-07 07:08:46)
> >
> > As you well know, XO is the root clock for pretty much everything on
> > Qualcomm platforms. We are trying to do things "properly" on 8998.
> > We are planning on having rpmcc manage it (see my other series), and
>
> I don't have the rpmcc series in my queue. I think it needs a resend?
See the "[PATCH v4 0/6] MSM8998 Multimedia Clock Controller" series.
>
> > all the other components consume xo from there. Unfortunately we
> > cannot control the probe order, particularly when things are built as
> > modules, so its possible gpucc might be the first thing to probe.
> > Currently, the clock framework will allow that since everything in
> > gpucc will just be an orphan. However that doesn't prevent gpucc
> > consumers from grabbing their clocks, and we've seen that cause
> > issues.
> >
> > As you've previously explained, you have a ton of work to do to
> > refactor things so that a clock will probe defer if its dependencies
> > are not present. We'd prefer that functionality, but are not really
> > willing to wait for it. Thus, we are implementing the same
> > functionality in the driver until the framework handles it for us, at
> > which point we'll gladly rip this out.
>
> Can you add more to the comment? Right now it doesn't explain the _why_
> part that you describe in the first paragraph here. That's what I'm
> asking to be put here as a comment. Also, GCC is the one exporting the
> XO clk on this platform so I'm a little lost why we're talking about rpm
> here.
Oh, I see, you wanted the comment expanded. Sorry I didn't understand
that earlier. Will do.
>
> I guess I'm left to do the ton of work myself and get to have clk
> providers like this be clk consumers so that probe ordering is correct
> and clks aren't exposed until the whole parent chain exists. This is
> taking a step backwards and causes me to be sad.
I'll take a second look at the list of tasks you outlined, but what I
recall was that most of them went over my head, so I wasn't really
confident in poking my nose in there.
>
> >
> > >
> > > > + if (IS_ERR(xo))
> > > > + return PTR_ERR(xo);
> > > > + clk_put(xo);
> > > > +
> > > > + regmap = qcom_cc_map(pdev, &gpucc_msm8998_desc);
> > > > + if (IS_ERR(regmap))
> > > > + return PTR_ERR(regmap);
> > > > +
> > > > + /* force periph logic on to acoid perf counter corruption */
> > >
> > > avoid?
> >
> > Yes. Do you want a v3 with this fixed?
>
> Yes, please resend without the binding patch that I've already applied.
>
Will do.