summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-ipq4019.yaml53
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml2
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml58
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml64
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml60
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm7150-gcc.yaml52
-rw-r--r--drivers/clk/qcom/Kconfig35
-rw-r--r--drivers/clk/qcom/Makefile4
-rw-r--r--drivers/clk/qcom/apcs-msm8916.c6
-rw-r--r--drivers/clk/qcom/apcs-sdx55.c6
-rw-r--r--drivers/clk/qcom/clk-branch.c15
-rw-r--r--drivers/clk/qcom/clk-branch.h44
-rw-r--r--drivers/clk/qcom/clk-hfpll.c14
-rw-r--r--drivers/clk/qcom/clk-krait.c10
-rw-r--r--drivers/clk/qcom/clk-rpm.c5
-rw-r--r--drivers/clk/qcom/gcc-ipq4019.c1175
-rw-r--r--drivers/clk/qcom/gcc-msm8960.c6
-rw-r--r--drivers/clk/qcom/gcc-qcm2290.c3
-rw-r--r--drivers/clk/qcom/gcc-sm7150.c3048
-rw-r--r--drivers/clk/qcom/gpucc-sm6115.c503
-rw-r--r--drivers/clk/qcom/gpucc-sm6125.c424
-rw-r--r--drivers/clk/qcom/gpucc-sm6375.c457
-rw-r--r--include/dt-bindings/clock/qcom,sm6115-gpucc.h36
-rw-r--r--include/dt-bindings/clock/qcom,sm6125-gpucc.h31
-rw-r--r--include/dt-bindings/clock/qcom,sm6375-gpucc.h36
-rw-r--r--include/dt-bindings/clock/qcom,sm7150-gcc.h186
26 files changed, 5695 insertions, 638 deletions
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq4019.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq4019.yaml
new file mode 100644
index 000000000000..6ebaef2288fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq4019.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,gcc-ipq4019.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller on IPQ4019
+
+maintainers:
+ - Stephen Boyd <sboyd@kernel.org>
+ - Taniya Das <tdas@codeaurora.org>
+ - Robert Marko <robert.markoo@sartura.hr>
+
+description: |
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on IPQ4019.
+
+ See also:: include/dt-bindings/clock/qcom,gcc-ipq4019.h
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+properties:
+ compatible:
+ const: qcom,gcc-ipq4019
+
+ clocks:
+ items:
+ - description: board XO clock
+ - description: sleep clock
+
+ clock-names:
+ items:
+ - const: xo
+ - const: sleep_clk
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ clock-controller@1800000 {
+ compatible = "qcom,gcc-ipq4019";
+ reg = <0x1800000 0x60000>;
+ #clock-cells = <1>;
+ #power-domain-cells = <1>;
+ #reset-cells = <1>;
+ clocks = <&xo>, <&sleep_clk>;
+ clock-names = "xo", "sleep_clk";
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml
index 2e8acca64af1..ae01e7749534 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml
@@ -15,7 +15,6 @@ description: |
domains.
See also::
- include/dt-bindings/clock/qcom,gcc-ipq4019.h
include/dt-bindings/clock/qcom,gcc-ipq6018.h
include/dt-bindings/reset/qcom,gcc-ipq6018.h
include/dt-bindings/clock/qcom,gcc-msm8953.h
@@ -29,7 +28,6 @@ allOf:
properties:
compatible:
enum:
- - qcom,gcc-ipq4019
- qcom,gcc-ipq6018
- qcom,gcc-mdm9607
- qcom,gcc-msm8953
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml
new file mode 100644
index 000000000000..cf19f44af774
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sm6115-gpucc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Graphics Clock & Reset Controller on SM6115
+
+maintainers:
+ - Konrad Dybcio <konrad.dybcio@linaro.org>
+
+description: |
+ Qualcomm graphics clock control module provides clocks, resets and power
+ domains on Qualcomm SoCs.
+
+ See also:: include/dt-bindings/clock/qcom,sm6115-gpucc.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,sm6115-gpucc
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: GPLL0 main branch source
+ - description: GPLL0 main div source
+
+required:
+ - compatible
+ - clocks
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-sm6115.h>
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ clock-controller@5990000 {
+ compatible = "qcom,sm6115-gpucc";
+ reg = <0x05990000 0x9000>;
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml
new file mode 100644
index 000000000000..374a1844a159
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sm6125-gpucc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Graphics Clock & Reset Controller on SM6125
+
+maintainers:
+ - Konrad Dybcio <konrad.dybcio@linaro.org>
+
+description: |
+ Qualcomm graphics clock control module provides clocks and power domains on
+ Qualcomm SoCs.
+
+ See also:: include/dt-bindings/clock/qcom,sm6125-gpucc.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,sm6125-gpucc
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: GPLL0 main branch source
+
+ '#clock-cells':
+ const: 1
+
+ '#power-domain-cells':
+ const: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - '#clock-cells'
+ - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-sm6125.h>
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ clock-controller@5990000 {
+ compatible = "qcom,sm6125-gpucc";
+ reg = <0x05990000 0x9000>;
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_CLK_SRC>;
+ #clock-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml
new file mode 100644
index 000000000000..b480ead5bd69
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sm6375-gpucc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Graphics Clock & Reset Controller on SM6375
+
+maintainers:
+ - Konrad Dybcio <konrad.dybcio@linaro.org>
+
+description: |
+ Qualcomm graphics clock control module provides clocks, resets and power
+ domains on Qualcomm SoCs.
+
+ See also:: include/dt-bindings/clock/qcom,sm6375-gpucc.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,sm6375-gpucc
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: GPLL0 main branch source
+ - description: GPLL0 div branch source
+ - description: SNoC DVM GFX source
+
+required:
+ - compatible
+ - clocks
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,sm6375-gcc.h>
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clock-controller@5990000 {
+ compatible = "qcom,sm6375-gpucc";
+ reg = <0 0x05990000 0 0x9000>;
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>,
+ <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm7150-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm7150-gcc.yaml
new file mode 100644
index 000000000000..0eb76d9d51c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sm7150-gcc.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sm7150-gcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller on SM7150
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Danila Tikhonov <danila@jiaxyga.com>
+ - David Wronek <davidwronek@gmail.com>
+
+description: |
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM7150
+
+ See also:: include/dt-bindings/clock/qcom,sm7150-gcc.h
+
+properties:
+ compatible:
+ const: qcom,sm7150-gcc
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: Board XO Active-Only source
+ - description: Sleep clock source
+
+required:
+ - compatible
+ - clocks
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ clock-controller@100000 {
+ compatible = "qcom,sm7150-gcc";
+ reg = <0x00100000 0x001f0000>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&rpmhcc RPMH_CXO_CLK_A>,
+ <&sleep_clk>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 5ab4b7dfe3c2..1897ce5c9291 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -759,6 +759,14 @@ config SM_GCC_6375
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS etc.
+config SM_GCC_7150
+ tristate "SM7150 Global Clock Controller"
+ select QCOM_GDSC
+ help
+ Support for the global clock controller on SM7150 devices.
+ Say Y if you want to use peripheral devices such as UART,
+ SPI, I2C, USB, SD/UFS, PCIe etc.
+
config SM_GCC_8150
tristate "SM8150 Global Clock Controller"
help
@@ -798,6 +806,33 @@ config SM_GCC_8550
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
+config SM_GPUCC_6115
+ tristate "SM6115 Graphics Clock Controller"
+ select SM_GCC_6115
+ depends on ARM64 || COMPILE_TEST
+ help
+ Support for the graphics clock controller on SM6115 devices.
+ Say Y if you want to support graphics controller devices and
+ functionality such as 3D graphics.
+
+config SM_GPUCC_6125
+ tristate "SM6125 Graphics Clock Controller"
+ select SM_GCC_6125
+ depends on ARM64 || COMPILE_TEST
+ help
+ Support for the graphics clock controller on SM6125 devices.
+ Say Y if you want to support graphics controller devices and
+ functionality such as 3D graphics.
+
+config SM_GPUCC_6375
+ tristate "SM6375 Graphics Clock Controller"
+ select SM_GCC_6375
+ depends on ARM64 || COMPILE_TEST
+ help
+ Support for the graphics clock controller on SM6375 devices.
+ Say Y if you want to support graphics controller devices and
+ functionality such as 3D graphics.
+
config SM_GPUCC_6350
tristate "SM6350 Graphics Clock Controller"
select SM_GCC_6350
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index c743805a9cbb..04d97a3297e2 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -107,12 +107,16 @@ obj-$(CONFIG_SM_GCC_6115) += gcc-sm6115.o
obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o
obj-$(CONFIG_SM_GCC_6350) += gcc-sm6350.o
obj-$(CONFIG_SM_GCC_6375) += gcc-sm6375.o
+obj-$(CONFIG_SM_GCC_7150) += gcc-sm7150.o
obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
obj-$(CONFIG_SM_GCC_8350) += gcc-sm8350.o
obj-$(CONFIG_SM_GCC_8450) += gcc-sm8450.o
obj-$(CONFIG_SM_GCC_8550) += gcc-sm8550.o
+obj-$(CONFIG_SM_GPUCC_6115) += gpucc-sm6115.o
+obj-$(CONFIG_SM_GPUCC_6125) += gpucc-sm6125.o
obj-$(CONFIG_SM_GPUCC_6350) += gpucc-sm6350.o
+obj-$(CONFIG_SM_GPUCC_6375) += gpucc-sm6375.o
obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
obj-$(CONFIG_SM_GPUCC_8350) += gpucc-sm8350.o
diff --git a/drivers/clk/qcom/apcs-msm8916.c b/drivers/clk/qcom/apcs-msm8916.c
index 89e0730810ac..ce57b333ec99 100644
--- a/drivers/clk/qcom/apcs-msm8916.c
+++ b/drivers/clk/qcom/apcs-msm8916.c
@@ -119,18 +119,16 @@ err:
return ret;
}
-static int qcom_apcs_msm8916_clk_remove(struct platform_device *pdev)
+static void qcom_apcs_msm8916_clk_remove(struct platform_device *pdev)
{
struct clk_regmap_mux_div *a53cc = platform_get_drvdata(pdev);
clk_notifier_unregister(a53cc->pclk, &a53cc->clk_nb);
-
- return 0;
}
static struct platform_driver qcom_apcs_msm8916_clk_driver = {
.probe = qcom_apcs_msm8916_clk_probe,
- .remove = qcom_apcs_msm8916_clk_remove,
+ .remove_new = qcom_apcs_msm8916_clk_remove,
.driver = {
.name = "qcom-apcs-msm8916-clk",
},
diff --git a/drivers/clk/qcom/apcs-sdx55.c b/drivers/clk/qcom/apcs-sdx55.c
index e599f862ec44..d644e6e1f8b7 100644
--- a/drivers/clk/qcom/apcs-sdx55.c
+++ b/drivers/clk/qcom/apcs-sdx55.c
@@ -120,20 +120,18 @@ err:
return ret;
}
-static int qcom_apcs_sdx55_clk_remove(struct platform_device *pdev)
+static void qcom_apcs_sdx55_clk_remove(struct platform_device *pdev)
{
struct device *cpu_dev = get_cpu_device(0);
struct clk_regmap_mux_div *a7cc = platform_get_drvdata(pdev);
clk_notifier_unregister(a7cc->pclk, &a7cc->clk_nb);
dev_pm_domain_detach(cpu_dev, true);
-
- return 0;
}
static struct platform_driver qcom_apcs_sdx55_clk_driver = {
.probe = qcom_apcs_sdx55_clk_probe,
- .remove = qcom_apcs_sdx55_clk_remove,
+ .remove_new = qcom_apcs_sdx55_clk_remove,
.driver = {
.name = "qcom-sdx55-acps-clk",
},
diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c
index f869fc6aaed6..ca896ebf7e1b 100644
--- a/drivers/clk/qcom/clk-branch.c
+++ b/drivers/clk/qcom/clk-branch.c
@@ -39,27 +39,22 @@ static bool clk_branch_check_halt(const struct clk_branch *br, bool enabling)
return !!val == !enabling;
}
-#define BRANCH_CLK_OFF BIT(31)
-#define BRANCH_NOC_FSM_STATUS_SHIFT 28
-#define BRANCH_NOC_FSM_STATUS_MASK 0x7
-#define BRANCH_NOC_FSM_STATUS_ON (0x2 << BRANCH_NOC_FSM_STATUS_SHIFT)
-
static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling)
{
u32 val;
u32 mask;
- mask = BRANCH_NOC_FSM_STATUS_MASK << BRANCH_NOC_FSM_STATUS_SHIFT;
- mask |= BRANCH_CLK_OFF;
+ mask = CBCR_NOC_FSM_STATUS;
+ mask |= CBCR_CLK_OFF;
regmap_read(br->clkr.regmap, br->halt_reg, &val);
if (enabling) {
val &= mask;
- return (val & BRANCH_CLK_OFF) == 0 ||
- val == BRANCH_NOC_FSM_STATUS_ON;
+ return (val & CBCR_CLK_OFF) == 0 ||
+ FIELD_GET(CBCR_NOC_FSM_STATUS, val) == FSM_STATUS_ON;
} else {
- return val & BRANCH_CLK_OFF;
+ return val & CBCR_CLK_OFF;
}
}
diff --git a/drivers/clk/qcom/clk-branch.h b/drivers/clk/qcom/clk-branch.h
index 17a58119165e..0cf800b9d08d 100644
--- a/drivers/clk/qcom/clk-branch.h
+++ b/drivers/clk/qcom/clk-branch.h
@@ -4,6 +4,7 @@
#ifndef __QCOM_CLK_BRANCH_H__
#define __QCOM_CLK_BRANCH_H__
+#include <linux/bitfield.h>
#include <linux/clk-provider.h>
#include "clk-regmap.h"
@@ -37,6 +38,49 @@ struct clk_branch {
struct clk_regmap clkr;
};
+/* Branch clock common bits for HLOS-owned clocks */
+#define CBCR_CLK_OFF BIT(31)
+#define CBCR_NOC_FSM_STATUS GENMASK(30, 28)
+ #define FSM_STATUS_ON BIT(1)
+#define CBCR_FORCE_MEM_CORE_ON BIT(14)
+#define CBCR_FORCE_MEM_PERIPH_ON BIT(13)
+#define CBCR_FORCE_MEM_PERIPH_OFF BIT(12)
+#define CBCR_WAKEUP GENMASK(11, 8)
+#define CBCR_SLEEP GENMASK(7, 4)
+
+static inline void qcom_branch_set_force_mem_core(struct regmap *regmap,
+ struct clk_branch clk, bool on)
+{
+ regmap_update_bits(regmap, clk.halt_reg, CBCR_FORCE_MEM_CORE_ON,
+ on ? CBCR_FORCE_MEM_CORE_ON : 0);
+}
+
+static inline void qcom_branch_set_force_periph_on(struct regmap *regmap,
+ struct clk_branch clk, bool on)
+{
+ regmap_update_bits(regmap, clk.halt_reg, CBCR_FORCE_MEM_PERIPH_ON,
+ on ? CBCR_FORCE_MEM_PERIPH_ON : 0);
+}
+
+static inline void qcom_branch_set_force_periph_off(struct regmap *regmap,
+ struct clk_branch clk, bool on)
+{
+ regmap_update_bits(regmap, clk.halt_reg, CBCR_FORCE_MEM_PERIPH_OFF,
+ on ? CBCR_FORCE_MEM_PERIPH_OFF : 0);
+}
+
+static inline void qcom_branch_set_wakeup(struct regmap *regmap, struct clk_branch clk, u32 val)
+{
+ regmap_update_bits(regmap, clk.halt_reg, CBCR_WAKEUP,
+ FIELD_PREP(CBCR_WAKEUP, val));
+}
+
+static inline void qcom_branch_set_sleep(struct regmap *regmap, struct clk_branch clk, u32 val)
+{
+ regmap_update_bits(regmap, clk.halt_reg, CBCR_SLEEP,
+ FIELD_PREP(CBCR_SLEEP, val));
+}
+
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;
diff --git a/drivers/clk/qcom/clk-hfpll.c b/drivers/clk/qcom/clk-hfpll.c
index 7dd17c184b69..86f728dc69e5 100644
--- a/drivers/clk/qcom/clk-hfpll.c
+++ b/drivers/clk/qcom/clk-hfpll.c
@@ -128,20 +128,20 @@ static void clk_hfpll_disable(struct clk_hw *hw)
spin_unlock_irqrestore(&h->lock, flags);
}
-static long clk_hfpll_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int clk_hfpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
struct clk_hfpll *h = to_clk_hfpll(hw);
struct hfpll_data const *hd = h->d;
unsigned long rrate;
- rate = clamp(rate, hd->min_rate, hd->max_rate);
+ req->rate = clamp(req->rate, hd->min_rate, hd->max_rate);
- rrate = DIV_ROUND_UP(rate, *parent_rate) * *parent_rate;
+ rrate = DIV_ROUND_UP(req->rate, req->best_parent_rate) * req->best_parent_rate;
if (rrate > hd->max_rate)
- rrate -= *parent_rate;
+ rrate -= req->best_parent_rate;
- return rrate;
+ req->rate = rrate;
+ return 0;
}
/*
@@ -241,7 +241,7 @@ const struct clk_ops clk_ops_hfpll = {
.enable = clk_hfpll_enable,
.disable = clk_hfpll_disable,
.is_enabled = hfpll_is_enabled,
- .round_rate = clk_hfpll_round_rate,
+ .determine_rate = clk_hfpll_determine_rate,
.set_rate = clk_hfpll_set_rate,
.recalc_rate = clk_hfpll_recalc_rate,
.init = clk_hfpll_init,
diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c
index 293a9dfa7151..f5ce403e1e27 100644
--- a/drivers/clk/qcom/clk-krait.c
+++ b/drivers/clk/qcom/clk-krait.c
@@ -97,11 +97,11 @@ const struct clk_ops krait_mux_clk_ops = {
EXPORT_SYMBOL_GPL(krait_mux_clk_ops);
/* The divider can divide by 2, 4, 6 and 8. But we only really need div-2. */
-static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int krait_div2_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
- *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), rate * 2);
- return DIV_ROUND_UP(*parent_rate, 2);
+ req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), req->rate * 2);
+ req->rate = DIV_ROUND_UP(req->best_parent_rate, 2);
+ return 0;
}
static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -142,7 +142,7 @@ krait_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
}
const struct clk_ops krait_div2_clk_ops = {
- .round_rate = krait_div2_round_rate,
+ .determine_rate = krait_div2_determine_rate,
.set_rate = krait_div2_set_rate,
.recalc_rate = krait_div2_recalc_rate,
};
diff --git a/drivers/clk/qcom/clk-rpm.c b/drivers/clk/qcom/clk-rpm.c
index b1be5b664bf3..e723ddb99a44 100644
--- a/drivers/clk/qcom/clk-rpm.c
+++ b/drivers/clk/qcom/clk-rpm.c
@@ -591,10 +591,9 @@ err:
return ret;
}
-static int rpm_clk_remove(struct platform_device *pdev)
+static void rpm_clk_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
- return 0;
}
static struct platform_driver rpm_clk_driver = {
@@ -603,7 +602,7 @@ static struct platform_driver rpm_clk_driver = {
.of_match_table = rpm_clk_match_table,
},
.probe = rpm_clk_probe,
- .remove = rpm_clk_remove,
+ .remove_new = rpm_clk_remove,
};
static int __init rpm_clk_init(void)
diff --git a/drivers/clk/qcom/gcc-ipq4019.c b/drivers/clk/qcom/gcc-ipq4019.c
index 5675c60525a7..5657e29464ad 100644
--- a/drivers/clk/qcom/gcc-ipq4019.c
+++ b/drivers/clk/qcom/gcc-ipq4019.c
@@ -77,98 +77,397 @@ struct clk_fepll {
const struct freq_tbl *freq_tbl;
};
-static struct parent_map gcc_xo_200_500_map[] = {
- { P_XO, 0 },
- { P_FEPLL200, 1 },
- { P_FEPLL500, 2 },
+/*
+ * Contains index for safe clock during APSS freq change.
+ * fepll500 is being used as safe clock so initialize it
+ * with its index in parents list gcc_xo_ddr_500_200.
+ */
+static const int gcc_ipq4019_cpu_safe_parent = 2;
+
+/* Calculates the VCO rate for FEPLL. */
+static u64 clk_fepll_vco_calc_rate(struct clk_fepll *pll_div,
+ unsigned long parent_rate)
+{
+ const struct clk_fepll_vco *pll_vco = pll_div->pll_vco;
+ u32 fdbkdiv, refclkdiv, cdiv;
+ u64 vco;
+
+ regmap_read(pll_div->cdiv.clkr.regmap, pll_vco->reg, &cdiv);
+ refclkdiv = (cdiv >> pll_vco->refclkdiv_shift) &
+ (BIT(pll_vco->refclkdiv_width) - 1);
+ fdbkdiv = (cdiv >> pll_vco->fdbkdiv_shift) &
+ (BIT(pll_vco->fdbkdiv_width) - 1);
+
+ vco = parent_rate / refclkdiv;
+ vco *= 2;
+ vco *= fdbkdiv;
+
+ return vco;
+}
+
+static const struct clk_fepll_vco gcc_apss_ddrpll_vco = {
+ .fdbkdiv_shift = 16,
+ .fdbkdiv_width = 8,
+ .refclkdiv_shift = 24,
+ .refclkdiv_width = 5,
+ .reg = 0x2e020,
};
-static const char * const gcc_xo_200_500[] = {
- "xo",
- "fepll200",
- "fepll500",
+static const struct clk_fepll_vco gcc_fepll_vco = {
+ .fdbkdiv_shift = 16,
+ .fdbkdiv_width = 8,
+ .refclkdiv_shift = 24,
+ .refclkdiv_width = 5,
+ .reg = 0x2f020,
};
-static struct parent_map gcc_xo_200_map[] = {
- { P_XO, 0 },
- { P_FEPLL200, 1 },
+/*
+ * Round rate function for APSS CPU PLL Clock divider.
+ * It looks up the frequency table and returns the next higher frequency
+ * supported in hardware.
+ */
+static long clk_cpu_div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *p_rate)
+{
+ struct clk_fepll *pll = to_clk_fepll(hw);
+ struct clk_hw *p_hw;
+ const struct freq_tbl *f;
+
+ f = qcom_find_freq(pll->freq_tbl, rate);
+ if (!f)
+ return -EINVAL;
+
+ p_hw = clk_hw_get_parent_by_index(hw, f->src);
+ *p_rate = clk_hw_get_rate(p_hw);
+
+ return f->freq;
};
-static const char * const gcc_xo_200[] = {
- "xo",
- "fepll200",
+/*
+ * Clock set rate function for APSS CPU PLL Clock divider.
+ * It looks up the frequency table and updates the PLL divider to corresponding
+ * divider value.
+ */
+static int clk_cpu_div_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_fepll *pll = to_clk_fepll(hw);
+ const struct freq_tbl *f;
+ u32 mask;
+
+ f = qcom_find_freq(pll->freq_tbl, rate);
+ if (!f)
+ return -EINVAL;
+
+ mask = (BIT(pll->cdiv.width) - 1) << pll->cdiv.shift;
+ regmap_update_bits(pll->cdiv.clkr.regmap,
+ pll->cdiv.reg, mask,
+ f->pre_div << pll->cdiv.shift);
+ /*
+ * There is no status bit which can be checked for successful CPU
+ * divider update operation so using delay for the same.
+ */
+ udelay(1);
+
+ return 0;
};
-static struct parent_map gcc_xo_200_spi_map[] = {
- { P_XO, 0 },
- { P_FEPLL200, 2 },
+/*
+ * Clock frequency calculation function for APSS CPU PLL Clock divider.
+ * This clock divider is nonlinear so this function calculates the actual
+ * divider and returns the output frequency by dividing VCO Frequency
+ * with this actual divider value.
+ */
+static unsigned long
+clk_cpu_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_fepll *pll = to_clk_fepll(hw);
+ u32 cdiv, pre_div;
+ u64 rate;
+
+ regmap_read(pll->cdiv.clkr.regmap, pll->cdiv.reg, &cdiv);
+ cdiv = (cdiv >> pll->cdiv.shift) & (BIT(pll->cdiv.width) - 1);
+
+ /*
+ * Some dividers have value in 0.5 fraction so multiply both VCO
+ * frequency(parent_rate) and pre_div with 2 to make integer
+ * calculation.
+ */
+ if (cdiv > 10)
+ pre_div = (cdiv + 1) * 2;
+ else
+ pre_div = cdiv + 12;
+
+ rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2;
+ do_div(rate, pre_div);
+
+ return rate;
};
-static const char * const gcc_xo_200_spi[] = {
- "xo",
- "fepll200",
+static const struct clk_ops clk_regmap_cpu_div_ops = {
+ .round_rate = clk_cpu_div_round_rate,
+ .set_rate = clk_cpu_div_set_rate,
+ .recalc_rate = clk_cpu_div_recalc_rate,
};
-static struct parent_map gcc_xo_sdcc1_500_map[] = {
- { P_XO, 0 },
- { P_DDRPLL, 1 },
- { P_FEPLL500, 2 },
+static const struct freq_tbl ftbl_apss_ddr_pll[] = {
+ { 384000000, P_XO, 0xd, 0, 0 },
+ { 413000000, P_XO, 0xc, 0, 0 },
+ { 448000000, P_XO, 0xb, 0, 0 },
+ { 488000000, P_XO, 0xa, 0, 0 },
+ { 512000000, P_XO, 0x9, 0, 0 },
+ { 537000000, P_XO, 0x8, 0, 0 },
+ { 565000000, P_XO, 0x7, 0, 0 },
+ { 597000000, P_XO, 0x6, 0, 0 },
+ { 632000000, P_XO, 0x5, 0, 0 },
+ { 672000000, P_XO, 0x4, 0, 0 },<