* [PATCH V3 00/11] add clock driver for Spreadtrum platforms @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This series adds Spreadtrum clock support together with its binding documentation and devicetree data. Any comments would be greatly appreciated. Thanks, Chunyan Changes from V2: (http://lkml.iu.edu/hypermail/linux/kernel/1707.1/01504.html) * Switch to use regmap to access registers; * Splited all clocks into 16 separated nodes, for each belongs to a single address area; * Rearranged the order of clock declaration in sc9860-clk.c, sorted them upon the address area; * Added syscon device tree nodes which will be quoted by the node of clocks which are in the same address area with the syscon device; * Revised the binding documentation according to the dt modification. Changes from V1: (https://lkml.org/lkml/2017/6/17/356) * Address Stephen's comments: - Switch to use platform device driver instead of the DT probing mechanism. - Move the common clock macro out from vendor directory, but need to remove those overlap code from other vendors (such as sunxi-ng) once this get merged. - Add support to be built as a module. - Add 'sprd_' prefix for all spin locks used in these drivers. - Mark input parameter of sprd_x with const. - Remove unreasonable dependencies to CONFIG_64BIT. - Add readl() after writing the same register. - Remove CLK_IS_BASIC which is no longer used. - Remove unnecessery CLK_IGNORE_UNUSED when defining a clock. - Change to expose all clock index. - Use clk_ instead of ccu. - Add Kconfig for sprd clocks. - Move the fixed clocks out from the soc node. - Switch to use 64-bit math in pll driver instead of 32-bit math. * Revise binding documentation according to dt modification. * Rename sc9860.c to sc9860-clk.c Chunyan Zhang (11): drivers: move clock common macros out from vendor directories dt-bindings: Add Spreadtrum clock binding documentation clk: sprd: Add common infrastructure clk: sprd: add gate clock support clk: sprd: add mux clock support clk: sprd: add divider clock support clk: sprd: add composite clock support clk: sprd: add adjustable pll support clk: sprd: add clocks support for SC9860 arm64: dts: add syscon for whale2 platform arm64: dts: add clocks for SC9860 Documentation/devicetree/bindings/clock/sprd.txt | 55 + arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 ++ arch/arm64/boot/dts/sprd/whale2.dtsi | 48 +- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/clk_common.h | 60 + drivers/clk/sprd/Kconfig | 14 + drivers/clk/sprd/Makefile | 11 + drivers/clk/sprd/common.c | 112 ++ drivers/clk/sprd/common.h | 57 + drivers/clk/sprd/composite.c | 65 + drivers/clk/sprd/composite.h | 49 + drivers/clk/sprd/div.c | 100 ++ drivers/clk/sprd/div.h | 79 + drivers/clk/sprd/gate.c | 106 ++ drivers/clk/sprd/gate.h | 54 + drivers/clk/sprd/mux.c | 89 + drivers/clk/sprd/mux.h | 65 + drivers/clk/sprd/pll.c | 268 +++ drivers/clk/sprd/pll.h | 110 ++ drivers/clk/sprd/sc9860-clk.c | 1987 ++++++++++++++++++++++ include/dt-bindings/clock/sprd,sc9860-clk.h | 408 +++++ 22 files changed, 3852 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt create mode 100644 drivers/clk/clk_common.h create mode 100644 drivers/clk/sprd/Kconfig create mode 100644 drivers/clk/sprd/Makefile create mode 100644 drivers/clk/sprd/common.c create mode 100644 drivers/clk/sprd/common.h create mode 100644 drivers/clk/sprd/composite.c create mode 100644 drivers/clk/sprd/composite.h create mode 100644 drivers/clk/sprd/div.c create mode 100644 drivers/clk/sprd/div.h create mode 100644 drivers/clk/sprd/gate.c create mode 100644 drivers/clk/sprd/gate.h create mode 100644 drivers/clk/sprd/mux.c create mode 100644 drivers/clk/sprd/mux.h create mode 100644 drivers/clk/sprd/pll.c create mode 100644 drivers/clk/sprd/pll.h create mode 100644 drivers/clk/sprd/sc9860-clk.c create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h -- 2.7.4 ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 00/11] add clock driver for Spreadtrum platforms @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel This series adds Spreadtrum clock support together with its binding documentation and devicetree data. Any comments would be greatly appreciated. Thanks, Chunyan Changes from V2: (http://lkml.iu.edu/hypermail/linux/kernel/1707.1/01504.html) * Switch to use regmap to access registers; * Splited all clocks into 16 separated nodes, for each belongs to a single address area; * Rearranged the order of clock declaration in sc9860-clk.c, sorted them upon the address area; * Added syscon device tree nodes which will be quoted by the node of clocks which are in the same address area with the syscon device; * Revised the binding documentation according to the dt modification. Changes from V1: (https://lkml.org/lkml/2017/6/17/356) * Address Stephen's comments: - Switch to use platform device driver instead of the DT probing mechanism. - Move the common clock macro out from vendor directory, but need to remove those overlap code from other vendors (such as sunxi-ng) once this get merged. - Add support to be built as a module. - Add 'sprd_' prefix for all spin locks used in these drivers. - Mark input parameter of sprd_x with const. - Remove unreasonable dependencies to CONFIG_64BIT. - Add readl() after writing the same register. - Remove CLK_IS_BASIC which is no longer used. - Remove unnecessery CLK_IGNORE_UNUSED when defining a clock. - Change to expose all clock index. - Use clk_ instead of ccu. - Add Kconfig for sprd clocks. - Move the fixed clocks out from the soc node. - Switch to use 64-bit math in pll driver instead of 32-bit math. * Revise binding documentation according to dt modification. * Rename sc9860.c to sc9860-clk.c Chunyan Zhang (11): drivers: move clock common macros out from vendor directories dt-bindings: Add Spreadtrum clock binding documentation clk: sprd: Add common infrastructure clk: sprd: add gate clock support clk: sprd: add mux clock support clk: sprd: add divider clock support clk: sprd: add composite clock support clk: sprd: add adjustable pll support clk: sprd: add clocks support for SC9860 arm64: dts: add syscon for whale2 platform arm64: dts: add clocks for SC9860 Documentation/devicetree/bindings/clock/sprd.txt | 55 + arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 ++ arch/arm64/boot/dts/sprd/whale2.dtsi | 48 +- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/clk_common.h | 60 + drivers/clk/sprd/Kconfig | 14 + drivers/clk/sprd/Makefile | 11 + drivers/clk/sprd/common.c | 112 ++ drivers/clk/sprd/common.h | 57 + drivers/clk/sprd/composite.c | 65 + drivers/clk/sprd/composite.h | 49 + drivers/clk/sprd/div.c | 100 ++ drivers/clk/sprd/div.h | 79 + drivers/clk/sprd/gate.c | 106 ++ drivers/clk/sprd/gate.h | 54 + drivers/clk/sprd/mux.c | 89 + drivers/clk/sprd/mux.h | 65 + drivers/clk/sprd/pll.c | 268 +++ drivers/clk/sprd/pll.h | 110 ++ drivers/clk/sprd/sc9860-clk.c | 1987 ++++++++++++++++++++++ include/dt-bindings/clock/sprd,sc9860-clk.h | 408 +++++ 22 files changed, 3852 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt create mode 100644 drivers/clk/clk_common.h create mode 100644 drivers/clk/sprd/Kconfig create mode 100644 drivers/clk/sprd/Makefile create mode 100644 drivers/clk/sprd/common.c create mode 100644 drivers/clk/sprd/common.h create mode 100644 drivers/clk/sprd/composite.c create mode 100644 drivers/clk/sprd/composite.h create mode 100644 drivers/clk/sprd/div.c create mode 100644 drivers/clk/sprd/div.h create mode 100644 drivers/clk/sprd/gate.c create mode 100644 drivers/clk/sprd/gate.h create mode 100644 drivers/clk/sprd/mux.c create mode 100644 drivers/clk/sprd/mux.h create mode 100644 drivers/clk/sprd/pll.c create mode 100644 drivers/clk/sprd/pll.h create mode 100644 drivers/clk/sprd/sc9860-clk.c create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h -- 2.7.4 ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 00/11] add clock driver for Spreadtrum platforms @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This series adds Spreadtrum clock support together with its binding documentation and devicetree data. Any comments would be greatly appreciated. Thanks, Chunyan Changes from V2: (http://lkml.iu.edu/hypermail/linux/kernel/1707.1/01504.html) * Switch to use regmap to access registers; * Splited all clocks into 16 separated nodes, for each belongs to a single address area; * Rearranged the order of clock declaration in sc9860-clk.c, sorted them upon the address area; * Added syscon device tree nodes which will be quoted by the node of clocks which are in the same address area with the syscon device; * Revised the binding documentation according to the dt modification. Changes from V1: (https://lkml.org/lkml/2017/6/17/356) * Address Stephen's comments: - Switch to use platform device driver instead of the DT probing mechanism. - Move the common clock macro out from vendor directory, but need to remove those overlap code from other vendors (such as sunxi-ng) once this get merged. - Add support to be built as a module. - Add 'sprd_' prefix for all spin locks used in these drivers. - Mark input parameter of sprd_x with const. - Remove unreasonable dependencies to CONFIG_64BIT. - Add readl() after writing the same register. - Remove CLK_IS_BASIC which is no longer used. - Remove unnecessery CLK_IGNORE_UNUSED when defining a clock. - Change to expose all clock index. - Use clk_ instead of ccu. - Add Kconfig for sprd clocks. - Move the fixed clocks out from the soc node. - Switch to use 64-bit math in pll driver instead of 32-bit math. * Revise binding documentation according to dt modification. * Rename sc9860.c to sc9860-clk.c Chunyan Zhang (11): drivers: move clock common macros out from vendor directories dt-bindings: Add Spreadtrum clock binding documentation clk: sprd: Add common infrastructure clk: sprd: add gate clock support clk: sprd: add mux clock support clk: sprd: add divider clock support clk: sprd: add composite clock support clk: sprd: add adjustable pll support clk: sprd: add clocks support for SC9860 arm64: dts: add syscon for whale2 platform arm64: dts: add clocks for SC9860 Documentation/devicetree/bindings/clock/sprd.txt | 55 + arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 ++ arch/arm64/boot/dts/sprd/whale2.dtsi | 48 +- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/clk_common.h | 60 + drivers/clk/sprd/Kconfig | 14 + drivers/clk/sprd/Makefile | 11 + drivers/clk/sprd/common.c | 112 ++ drivers/clk/sprd/common.h | 57 + drivers/clk/sprd/composite.c | 65 + drivers/clk/sprd/composite.h | 49 + drivers/clk/sprd/div.c | 100 ++ drivers/clk/sprd/div.h | 79 + drivers/clk/sprd/gate.c | 106 ++ drivers/clk/sprd/gate.h | 54 + drivers/clk/sprd/mux.c | 89 + drivers/clk/sprd/mux.h | 65 + drivers/clk/sprd/pll.c | 268 +++ drivers/clk/sprd/pll.h | 110 ++ drivers/clk/sprd/sc9860-clk.c | 1987 ++++++++++++++++++++++ include/dt-bindings/clock/sprd,sc9860-clk.h | 408 +++++ 22 files changed, 3852 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt create mode 100644 drivers/clk/clk_common.h create mode 100644 drivers/clk/sprd/Kconfig create mode 100644 drivers/clk/sprd/Makefile create mode 100644 drivers/clk/sprd/common.c create mode 100644 drivers/clk/sprd/common.h create mode 100644 drivers/clk/sprd/composite.c create mode 100644 drivers/clk/sprd/composite.h create mode 100644 drivers/clk/sprd/div.c create mode 100644 drivers/clk/sprd/div.h create mode 100644 drivers/clk/sprd/gate.c create mode 100644 drivers/clk/sprd/gate.h create mode 100644 drivers/clk/sprd/mux.c create mode 100644 drivers/clk/sprd/mux.h create mode 100644 drivers/clk/sprd/pll.c create mode 100644 drivers/clk/sprd/pll.h create mode 100644 drivers/clk/sprd/sc9860-clk.c create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h -- 2.7.4 ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 01/11] drivers: move clock common macros out from vendor directories 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang These macros are used by more than one SoC vendor platforms, avoid to have many copies of these code, this patch moves them to the common clock directory which every clock drivers can access to. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/clk_common.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 drivers/clk/clk_common.h diff --git a/drivers/clk/clk_common.h b/drivers/clk/clk_common.h new file mode 100644 index 0000000..21e93d2 --- /dev/null +++ b/drivers/clk/clk_common.h @@ -0,0 +1,60 @@ +/* + * drivers/clk/clk_common.h + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _CLK_COMMON_H_ +#define _CLK_COMMON_H_ + +#include <linux/clk-provider.h> + +#define CLK_HW_INIT(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = (const char *[]) { _parent }, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = NULL, \ + .num_parents = 0, \ + .ops = _ops, \ + }) + +#define CLK_FIXED_FACTOR(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +#define CLK_FIXED_RATE(_struct, _name, _flags, \ + _fixed_rate, _fixed_accuracy) \ + struct clk_fixed_rate _struct = { \ + .fixed_rate = _fixed_rate, \ + .fixed_accuracy = _fixed_accuracy, \ + .hw.init = CLK_HW_INIT_NO_PARENT(_name, \ + &clk_fixed_rate_ops, \ + _flags), \ + } + +#endif /* _CLK_COMMON_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 01/11] drivers: move clock common macros out from vendor directories @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel These macros are used by more than one SoC vendor platforms, avoid to have many copies of these code, this patch moves them to the common clock directory which every clock drivers can access to. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/clk_common.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 drivers/clk/clk_common.h diff --git a/drivers/clk/clk_common.h b/drivers/clk/clk_common.h new file mode 100644 index 0000000..21e93d2 --- /dev/null +++ b/drivers/clk/clk_common.h @@ -0,0 +1,60 @@ +/* + * drivers/clk/clk_common.h + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _CLK_COMMON_H_ +#define _CLK_COMMON_H_ + +#include <linux/clk-provider.h> + +#define CLK_HW_INIT(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = (const char *[]) { _parent }, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = NULL, \ + .num_parents = 0, \ + .ops = _ops, \ + }) + +#define CLK_FIXED_FACTOR(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +#define CLK_FIXED_RATE(_struct, _name, _flags, \ + _fixed_rate, _fixed_accuracy) \ + struct clk_fixed_rate _struct = { \ + .fixed_rate = _fixed_rate, \ + .fixed_accuracy = _fixed_accuracy, \ + .hw.init = CLK_HW_INIT_NO_PARENT(_name, \ + &clk_fixed_rate_ops, \ + _flags), \ + } + +#endif /* _CLK_COMMON_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 01/11] drivers: move clock common macros out from vendor directories @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang These macros are used by more than one SoC vendor platforms, avoid to have many copies of these code, this patch moves them to the common clock directory which every clock drivers can access to. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/clk_common.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 drivers/clk/clk_common.h diff --git a/drivers/clk/clk_common.h b/drivers/clk/clk_common.h new file mode 100644 index 0000000..21e93d2 --- /dev/null +++ b/drivers/clk/clk_common.h @@ -0,0 +1,60 @@ +/* + * drivers/clk/clk_common.h + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _CLK_COMMON_H_ +#define _CLK_COMMON_H_ + +#include <linux/clk-provider.h> + +#define CLK_HW_INIT(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = (const char *[]) { _parent }, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = NULL, \ + .num_parents = 0, \ + .ops = _ops, \ + }) + +#define CLK_FIXED_FACTOR(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +#define CLK_FIXED_RATE(_struct, _name, _flags, \ + _fixed_rate, _fixed_accuracy) \ + struct clk_fixed_rate _struct = { \ + .fixed_rate = _fixed_rate, \ + .fixed_accuracy = _fixed_accuracy, \ + .hw.init = CLK_HW_INIT_NO_PARENT(_name, \ + &clk_fixed_rate_ops, \ + _flags), \ + } + +#endif /* _CLK_COMMON_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Introduce a new binding with its documentation for Spreadtrum clock sub-framework. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- Documentation/devicetree/bindings/clock/sprd.txt | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt new file mode 100644 index 0000000..5c09529 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sprd.txt @@ -0,0 +1,55 @@ +Spreadtrum Clock Binding +------------------------ + +Required properties: +- compatible: should contain the following compatible strings: + - "sprd,sc9860-pmu-gate" + - "sprd,sc9860-pll" + - "sprd,sc9860-ap-clk" + - "sprd,sc9860-aon-prediv" + - "sprd,sc9860-apahb-gate" + - "sprd,sc9860-aon-gate" + - "sprd,sc9860-aonsecure-clk" + - "sprd,sc9860-agcp-gate" + - "sprd,sc9860-gpu-clk" + - "sprd,sc9860-vsp-clk" + - "sprd,sc9860-vsp-gate" + - "sprd,sc9860-cam-clk" + - "sprd,sc9860-cam-gate" + - "sprd,sc9860-disp-clk" + - "sprd,sc9860-disp-gate" + - "sprd,sc9860-apapb-gate" + +- #clock-cells: must be 1 + +- clocks : shall be the input parent clock(s) phandle for the clock. + +Optional properties: + +- reg: Contain the registers base address and length. It must be configured only if no 'sprd,syscon' under the node. + +- sprd,syscon: phandle to the syscon which is in the same address area with the clock. + +Example: + + pmu_gate: pmu-gate { + compatible = "sprd,sc9860-pmu-gate"; + sprd,syscon = <&pmu_apb>; + clocks = <&ext_26m>; + #clock-cells = <1>; + }; + + pll: pll { + compatible = "sprd,sc9860-pll"; + sprd,syscon = <&ana_apb>; + clocks = <&pmu_gate 0>; + #clock-cells = <1>; + }; + + ap_clk: clock-controller@20000000 { + compatible = "sprd,sc9860-ap-clk"; + reg = <0 0x20000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>, + <&pmu_gate 0>; + #clock-cells = <1>; + }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel Introduce a new binding with its documentation for Spreadtrum clock sub-framework. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- Documentation/devicetree/bindings/clock/sprd.txt | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt new file mode 100644 index 0000000..5c09529 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sprd.txt @@ -0,0 +1,55 @@ +Spreadtrum Clock Binding +------------------------ + +Required properties: +- compatible: should contain the following compatible strings: + - "sprd,sc9860-pmu-gate" + - "sprd,sc9860-pll" + - "sprd,sc9860-ap-clk" + - "sprd,sc9860-aon-prediv" + - "sprd,sc9860-apahb-gate" + - "sprd,sc9860-aon-gate" + - "sprd,sc9860-aonsecure-clk" + - "sprd,sc9860-agcp-gate" + - "sprd,sc9860-gpu-clk" + - "sprd,sc9860-vsp-clk" + - "sprd,sc9860-vsp-gate" + - "sprd,sc9860-cam-clk" + - "sprd,sc9860-cam-gate" + - "sprd,sc9860-disp-clk" + - "sprd,sc9860-disp-gate" + - "sprd,sc9860-apapb-gate" + +- #clock-cells: must be 1 + +- clocks : shall be the input parent clock(s) phandle for the clock. + +Optional properties: + +- reg: Contain the registers base address and length. It must be configured only if no 'sprd,syscon' under the node. + +- sprd,syscon: phandle to the syscon which is in the same address area with the clock. + +Example: + + pmu_gate: pmu-gate { + compatible = "sprd,sc9860-pmu-gate"; + sprd,syscon = <&pmu_apb>; + clocks = <&ext_26m>; + #clock-cells = <1>; + }; + + pll: pll { + compatible = "sprd,sc9860-pll"; + sprd,syscon = <&ana_apb>; + clocks = <&pmu_gate 0>; + #clock-cells = <1>; + }; + + ap_clk: clock-controller at 20000000 { + compatible = "sprd,sc9860-ap-clk"; + reg = <0 0x20000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>, + <&pmu_gate 0>; + #clock-cells = <1>; + }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Introduce a new binding with its documentation for Spreadtrum clock sub-framework. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- Documentation/devicetree/bindings/clock/sprd.txt | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt new file mode 100644 index 0000000..5c09529 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sprd.txt @@ -0,0 +1,55 @@ +Spreadtrum Clock Binding +------------------------ + +Required properties: +- compatible: should contain the following compatible strings: + - "sprd,sc9860-pmu-gate" + - "sprd,sc9860-pll" + - "sprd,sc9860-ap-clk" + - "sprd,sc9860-aon-prediv" + - "sprd,sc9860-apahb-gate" + - "sprd,sc9860-aon-gate" + - "sprd,sc9860-aonsecure-clk" + - "sprd,sc9860-agcp-gate" + - "sprd,sc9860-gpu-clk" + - "sprd,sc9860-vsp-clk" + - "sprd,sc9860-vsp-gate" + - "sprd,sc9860-cam-clk" + - "sprd,sc9860-cam-gate" + - "sprd,sc9860-disp-clk" + - "sprd,sc9860-disp-gate" + - "sprd,sc9860-apapb-gate" + +- #clock-cells: must be 1 + +- clocks : shall be the input parent clock(s) phandle for the clock. + +Optional properties: + +- reg: Contain the registers base address and length. It must be configured only if no 'sprd,syscon' under the node. + +- sprd,syscon: phandle to the syscon which is in the same address area with the clock. + +Example: + + pmu_gate: pmu-gate { + compatible = "sprd,sc9860-pmu-gate"; + sprd,syscon = <&pmu_apb>; + clocks = <&ext_26m>; + #clock-cells = <1>; + }; + + pll: pll { + compatible = "sprd,sc9860-pll"; + sprd,syscon = <&ana_apb>; + clocks = <&pmu_gate 0>; + #clock-cells = <1>; + }; + + ap_clk: clock-controller@20000000 { + compatible = "sprd,sc9860-ap-clk"; + reg = <0 0x20000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>, + <&pmu_gate 0>; + #clock-cells = <1>; + }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation @ 2017-11-06 17:15 ` Rob Herring 0 siblings, 0 replies; 68+ messages in thread From: Rob Herring @ 2017-11-06 17:15 UTC (permalink / raw) To: Chunyan Zhang Cc: Stephen Boyd, Michael Turquette, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang On Thu, Nov 02, 2017 at 02:56:17PM +0800, Chunyan Zhang wrote: > Introduce a new binding with its documentation for Spreadtrum clock > sub-framework. > > Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > --- > Documentation/devicetree/bindings/clock/sprd.txt | 55 ++++++++++++++++++++++++ > 1 file changed, 55 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt > > diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt > new file mode 100644 > index 0000000..5c09529 > --- /dev/null > +++ b/Documentation/devicetree/bindings/clock/sprd.txt > @@ -0,0 +1,55 @@ > +Spreadtrum Clock Binding > +------------------------ > + > +Required properties: > +- compatible: should contain the following compatible strings: > + - "sprd,sc9860-pmu-gate" > + - "sprd,sc9860-pll" > + - "sprd,sc9860-ap-clk" > + - "sprd,sc9860-aon-prediv" > + - "sprd,sc9860-apahb-gate" > + - "sprd,sc9860-aon-gate" > + - "sprd,sc9860-aonsecure-clk" > + - "sprd,sc9860-agcp-gate" > + - "sprd,sc9860-gpu-clk" > + - "sprd,sc9860-vsp-clk" > + - "sprd,sc9860-vsp-gate" > + - "sprd,sc9860-cam-clk" > + - "sprd,sc9860-cam-gate" > + - "sprd,sc9860-disp-clk" > + - "sprd,sc9860-disp-gate" > + - "sprd,sc9860-apapb-gate" > + > +- #clock-cells: must be 1 > + > +- clocks : shall be the input parent clock(s) phandle for the clock. You need to document how many clocks for each block. > + > +Optional properties: > + > +- reg: Contain the registers base address and length. It must be configured only if no 'sprd,syscon' under the node. > + > +- sprd,syscon: phandle to the syscon which is in the same address area with the clock. > + > +Example: > + > + pmu_gate: pmu-gate { > + compatible = "sprd,sc9860-pmu-gate"; > + sprd,syscon = <&pmu_apb>; Ideally, the pmu-gate node would be a child of pmu_apb and use the reg property if clock registers are a contiguous range. Then you don't need this phandle. > + clocks = <&ext_26m>; > + #clock-cells = <1>; > + }; > + > + pll: pll { > + compatible = "sprd,sc9860-pll"; > + sprd,syscon = <&ana_apb>; Same here. > + clocks = <&pmu_gate 0>; > + #clock-cells = <1>; > + }; > + > + ap_clk: clock-controller@20000000 { > + compatible = "sprd,sc9860-ap-clk"; > + reg = <0 0x20000000 0 0x400>; > + clocks = <&ext_26m>, <&pll 0>, > + <&pmu_gate 0>; > + #clock-cells = <1>; > + }; > -- > 2.7.4 > ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation @ 2017-11-06 17:15 ` Rob Herring 0 siblings, 0 replies; 68+ messages in thread From: Rob Herring @ 2017-11-06 17:15 UTC (permalink / raw) To: linux-arm-kernel On Thu, Nov 02, 2017 at 02:56:17PM +0800, Chunyan Zhang wrote: > Introduce a new binding with its documentation for Spreadtrum clock > sub-framework. > > Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > --- > Documentation/devicetree/bindings/clock/sprd.txt | 55 ++++++++++++++++++++++++ > 1 file changed, 55 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt > > diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt > new file mode 100644 > index 0000000..5c09529 > --- /dev/null > +++ b/Documentation/devicetree/bindings/clock/sprd.txt > @@ -0,0 +1,55 @@ > +Spreadtrum Clock Binding > +------------------------ > + > +Required properties: > +- compatible: should contain the following compatible strings: > + - "sprd,sc9860-pmu-gate" > + - "sprd,sc9860-pll" > + - "sprd,sc9860-ap-clk" > + - "sprd,sc9860-aon-prediv" > + - "sprd,sc9860-apahb-gate" > + - "sprd,sc9860-aon-gate" > + - "sprd,sc9860-aonsecure-clk" > + - "sprd,sc9860-agcp-gate" > + - "sprd,sc9860-gpu-clk" > + - "sprd,sc9860-vsp-clk" > + - "sprd,sc9860-vsp-gate" > + - "sprd,sc9860-cam-clk" > + - "sprd,sc9860-cam-gate" > + - "sprd,sc9860-disp-clk" > + - "sprd,sc9860-disp-gate" > + - "sprd,sc9860-apapb-gate" > + > +- #clock-cells: must be 1 > + > +- clocks : shall be the input parent clock(s) phandle for the clock. You need to document how many clocks for each block. > + > +Optional properties: > + > +- reg: Contain the registers base address and length. It must be configured only if no 'sprd,syscon' under the node. > + > +- sprd,syscon: phandle to the syscon which is in the same address area with the clock. > + > +Example: > + > + pmu_gate: pmu-gate { > + compatible = "sprd,sc9860-pmu-gate"; > + sprd,syscon = <&pmu_apb>; Ideally, the pmu-gate node would be a child of pmu_apb and use the reg property if clock registers are a contiguous range. Then you don't need this phandle. > + clocks = <&ext_26m>; > + #clock-cells = <1>; > + }; > + > + pll: pll { > + compatible = "sprd,sc9860-pll"; > + sprd,syscon = <&ana_apb>; Same here. > + clocks = <&pmu_gate 0>; > + #clock-cells = <1>; > + }; > + > + ap_clk: clock-controller at 20000000 { > + compatible = "sprd,sc9860-ap-clk"; > + reg = <0 0x20000000 0 0x400>; > + clocks = <&ext_26m>, <&pll 0>, > + <&pmu_gate 0>; > + #clock-cells = <1>; > + }; > -- > 2.7.4 > ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation @ 2017-11-06 17:15 ` Rob Herring 0 siblings, 0 replies; 68+ messages in thread From: Rob Herring @ 2017-11-06 17:15 UTC (permalink / raw) To: Chunyan Zhang Cc: Stephen Boyd, Michael Turquette, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Orson Zhai, Chunyan Zhang On Thu, Nov 02, 2017 at 02:56:17PM +0800, Chunyan Zhang wrote: > Introduce a new binding with its documentation for Spreadtrum clock > sub-framework. > > Signed-off-by: Chunyan Zhang <chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org> > --- > Documentation/devicetree/bindings/clock/sprd.txt | 55 ++++++++++++++++++++++++ > 1 file changed, 55 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt > > diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt > new file mode 100644 > index 0000000..5c09529 > --- /dev/null > +++ b/Documentation/devicetree/bindings/clock/sprd.txt > @@ -0,0 +1,55 @@ > +Spreadtrum Clock Binding > +------------------------ > + > +Required properties: > +- compatible: should contain the following compatible strings: > + - "sprd,sc9860-pmu-gate" > + - "sprd,sc9860-pll" > + - "sprd,sc9860-ap-clk" > + - "sprd,sc9860-aon-prediv" > + - "sprd,sc9860-apahb-gate" > + - "sprd,sc9860-aon-gate" > + - "sprd,sc9860-aonsecure-clk" > + - "sprd,sc9860-agcp-gate" > + - "sprd,sc9860-gpu-clk" > + - "sprd,sc9860-vsp-clk" > + - "sprd,sc9860-vsp-gate" > + - "sprd,sc9860-cam-clk" > + - "sprd,sc9860-cam-gate" > + - "sprd,sc9860-disp-clk" > + - "sprd,sc9860-disp-gate" > + - "sprd,sc9860-apapb-gate" > + > +- #clock-cells: must be 1 > + > +- clocks : shall be the input parent clock(s) phandle for the clock. You need to document how many clocks for each block. > + > +Optional properties: > + > +- reg: Contain the registers base address and length. It must be configured only if no 'sprd,syscon' under the node. > + > +- sprd,syscon: phandle to the syscon which is in the same address area with the clock. > + > +Example: > + > + pmu_gate: pmu-gate { > + compatible = "sprd,sc9860-pmu-gate"; > + sprd,syscon = <&pmu_apb>; Ideally, the pmu-gate node would be a child of pmu_apb and use the reg property if clock registers are a contiguous range. Then you don't need this phandle. > + clocks = <&ext_26m>; > + #clock-cells = <1>; > + }; > + > + pll: pll { > + compatible = "sprd,sc9860-pll"; > + sprd,syscon = <&ana_apb>; Same here. > + clocks = <&pmu_gate 0>; > + #clock-cells = <1>; > + }; > + > + ap_clk: clock-controller@20000000 { > + compatible = "sprd,sc9860-ap-clk"; > + reg = <0 0x20000000 0 0x400>; > + clocks = <&ext_26m>, <&pll 0>, > + <&pmu_gate 0>; > + #clock-cells = <1>; > + }; > -- > 2.7.4 > -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation 2017-11-06 17:15 ` Rob Herring (?) @ 2017-11-07 7:01 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-07 7:01 UTC (permalink / raw) To: Rob Herring Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai Hi Rob, On 7 November 2017 at 01:15, Rob Herring <robh@kernel.org> wrote: > On Thu, Nov 02, 2017 at 02:56:17PM +0800, Chunyan Zhang wrote: >> Introduce a new binding with its documentation for Spreadtrum clock >> sub-framework. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> Documentation/devicetree/bindings/clock/sprd.txt | 55 ++++++++++++++++++++++++ >> 1 file changed, 55 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt >> >> diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt >> new file mode 100644 >> index 0000000..5c09529 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/clock/sprd.txt >> @@ -0,0 +1,55 @@ >> +Spreadtrum Clock Binding >> +------------------------ >> + >> +Required properties: >> +- compatible: should contain the following compatible strings: >> + - "sprd,sc9860-pmu-gate" >> + - "sprd,sc9860-pll" >> + - "sprd,sc9860-ap-clk" >> + - "sprd,sc9860-aon-prediv" >> + - "sprd,sc9860-apahb-gate" >> + - "sprd,sc9860-aon-gate" >> + - "sprd,sc9860-aonsecure-clk" >> + - "sprd,sc9860-agcp-gate" >> + - "sprd,sc9860-gpu-clk" >> + - "sprd,sc9860-vsp-clk" >> + - "sprd,sc9860-vsp-gate" >> + - "sprd,sc9860-cam-clk" >> + - "sprd,sc9860-cam-gate" >> + - "sprd,sc9860-disp-clk" >> + - "sprd,sc9860-disp-gate" >> + - "sprd,sc9860-apapb-gate" >> + >> +- #clock-cells: must be 1 >> + >> +- clocks : shall be the input parent clock(s) phandle for the clock. > > You need to document how many clocks for each block. It depends, "clocks" property here just simply shows which clock group the clock's parents are in. The detailed dependency relationship (i.e. how many parents and which are the parents) are implemented in driver code. Ok, I should address more, will do in the next version. > >> + >> +Optional properties: >> + >> +- reg: Contain the registers base address and length. It must be configured only if no 'sprd,syscon' under the node. >> + >> +- sprd,syscon: phandle to the syscon which is in the same address area with the clock. >> + >> +Example: >> + >> + pmu_gate: pmu-gate { >> + compatible = "sprd,sc9860-pmu-gate"; >> + sprd,syscon = <&pmu_apb>; > > Ideally, the pmu-gate node would be a child of pmu_apb and use the reg > property if clock registers are a contiguous range. Then you don't need > this phandle. The pmu-gate is actually a clock independent from the 'pmu_apb' syscon device, using a reference to syscon node instead of a reg property is just to avoid mapping the same address areas repeatedly. Spreadtrum's clock h/w design is a little complicated, after discussing with Arnd and Stephen, I then chose to implement in this way. I guess the name of 'pmu_apb' might be confused, it's actually not a bus, but a global address area stored a lot of registers shared by a few devices including some clocks. I think I'd better use another name instead of pmu_apb :) Please let me know if I'm missing something here. Thanks, Chunyan > >> + clocks = <&ext_26m>; >> + #clock-cells = <1>; >> + }; >> + >> + pll: pll { >> + compatible = "sprd,sc9860-pll"; >> + sprd,syscon = <&ana_apb>; > > Same here. > >> + clocks = <&pmu_gate 0>; >> + #clock-cells = <1>; >> + }; >> + >> + ap_clk: clock-controller@20000000 { >> + compatible = "sprd,sc9860-ap-clk"; >> + reg = <0 0x20000000 0 0x400>; >> + clocks = <&ext_26m>, <&pll 0>, >> + <&pmu_gate 0>; >> + #clock-cells = <1>; >> + }; >> -- >> 2.7.4 >> ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation @ 2017-11-07 7:01 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-07 7:01 UTC (permalink / raw) To: linux-arm-kernel Hi Rob, On 7 November 2017 at 01:15, Rob Herring <robh@kernel.org> wrote: > On Thu, Nov 02, 2017 at 02:56:17PM +0800, Chunyan Zhang wrote: >> Introduce a new binding with its documentation for Spreadtrum clock >> sub-framework. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> Documentation/devicetree/bindings/clock/sprd.txt | 55 ++++++++++++++++++++++++ >> 1 file changed, 55 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt >> >> diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt >> new file mode 100644 >> index 0000000..5c09529 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/clock/sprd.txt >> @@ -0,0 +1,55 @@ >> +Spreadtrum Clock Binding >> +------------------------ >> + >> +Required properties: >> +- compatible: should contain the following compatible strings: >> + - "sprd,sc9860-pmu-gate" >> + - "sprd,sc9860-pll" >> + - "sprd,sc9860-ap-clk" >> + - "sprd,sc9860-aon-prediv" >> + - "sprd,sc9860-apahb-gate" >> + - "sprd,sc9860-aon-gate" >> + - "sprd,sc9860-aonsecure-clk" >> + - "sprd,sc9860-agcp-gate" >> + - "sprd,sc9860-gpu-clk" >> + - "sprd,sc9860-vsp-clk" >> + - "sprd,sc9860-vsp-gate" >> + - "sprd,sc9860-cam-clk" >> + - "sprd,sc9860-cam-gate" >> + - "sprd,sc9860-disp-clk" >> + - "sprd,sc9860-disp-gate" >> + - "sprd,sc9860-apapb-gate" >> + >> +- #clock-cells: must be 1 >> + >> +- clocks : shall be the input parent clock(s) phandle for the clock. > > You need to document how many clocks for each block. It depends, "clocks" property here just simply shows which clock group the clock's parents are in. The detailed dependency relationship (i.e. how many parents and which are the parents) are implemented in driver code. Ok, I should address more, will do in the next version. > >> + >> +Optional properties: >> + >> +- reg: Contain the registers base address and length. It must be configured only if no 'sprd,syscon' under the node. >> + >> +- sprd,syscon: phandle to the syscon which is in the same address area with the clock. >> + >> +Example: >> + >> + pmu_gate: pmu-gate { >> + compatible = "sprd,sc9860-pmu-gate"; >> + sprd,syscon = <&pmu_apb>; > > Ideally, the pmu-gate node would be a child of pmu_apb and use the reg > property if clock registers are a contiguous range. Then you don't need > this phandle. The pmu-gate is actually a clock independent from the 'pmu_apb' syscon device, using a reference to syscon node instead of a reg property is just to avoid mapping the same address areas repeatedly. Spreadtrum's clock h/w design is a little complicated, after discussing with Arnd and Stephen, I then chose to implement in this way. I guess the name of 'pmu_apb' might be confused, it's actually not a bus, but a global address area stored a lot of registers shared by a few devices including some clocks. I think I'd better use another name instead of pmu_apb :) Please let me know if I'm missing something here. Thanks, Chunyan > >> + clocks = <&ext_26m>; >> + #clock-cells = <1>; >> + }; >> + >> + pll: pll { >> + compatible = "sprd,sc9860-pll"; >> + sprd,syscon = <&ana_apb>; > > Same here. > >> + clocks = <&pmu_gate 0>; >> + #clock-cells = <1>; >> + }; >> + >> + ap_clk: clock-controller at 20000000 { >> + compatible = "sprd,sc9860-ap-clk"; >> + reg = <0 0x20000000 0 0x400>; >> + clocks = <&ext_26m>, <&pll 0>, >> + <&pmu_gate 0>; >> + #clock-cells = <1>; >> + }; >> -- >> 2.7.4 >> ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation @ 2017-11-07 7:01 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-07 7:01 UTC (permalink / raw) To: Rob Herring Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai Hi Rob, On 7 November 2017 at 01:15, Rob Herring <robh@kernel.org> wrote: > On Thu, Nov 02, 2017 at 02:56:17PM +0800, Chunyan Zhang wrote: >> Introduce a new binding with its documentation for Spreadtrum clock >> sub-framework. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> Documentation/devicetree/bindings/clock/sprd.txt | 55 ++++++++++++++++++++++++ >> 1 file changed, 55 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt >> >> diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt >> new file mode 100644 >> index 0000000..5c09529 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/clock/sprd.txt >> @@ -0,0 +1,55 @@ >> +Spreadtrum Clock Binding >> +------------------------ >> + >> +Required properties: >> +- compatible: should contain the following compatible strings: >> + - "sprd,sc9860-pmu-gate" >> + - "sprd,sc9860-pll" >> + - "sprd,sc9860-ap-clk" >> + - "sprd,sc9860-aon-prediv" >> + - "sprd,sc9860-apahb-gate" >> + - "sprd,sc9860-aon-gate" >> + - "sprd,sc9860-aonsecure-clk" >> + - "sprd,sc9860-agcp-gate" >> + - "sprd,sc9860-gpu-clk" >> + - "sprd,sc9860-vsp-clk" >> + - "sprd,sc9860-vsp-gate" >> + - "sprd,sc9860-cam-clk" >> + - "sprd,sc9860-cam-gate" >> + - "sprd,sc9860-disp-clk" >> + - "sprd,sc9860-disp-gate" >> + - "sprd,sc9860-apapb-gate" >> + >> +- #clock-cells: must be 1 >> + >> +- clocks : shall be the input parent clock(s) phandle for the clock. > > You need to document how many clocks for each block. It depends, "clocks" property here just simply shows which clock group the clock's parents are in. The detailed dependency relationship (i.e. how many parents and which are the parents) are implemented in driver code. Ok, I should address more, will do in the next version. > >> + >> +Optional properties: >> + >> +- reg: Contain the registers base address and length. It must be configured only if no 'sprd,syscon' under the node. >> + >> +- sprd,syscon: phandle to the syscon which is in the same address area with the clock. >> + >> +Example: >> + >> + pmu_gate: pmu-gate { >> + compatible = "sprd,sc9860-pmu-gate"; >> + sprd,syscon = <&pmu_apb>; > > Ideally, the pmu-gate node would be a child of pmu_apb and use the reg > property if clock registers are a contiguous range. Then you don't need > this phandle. The pmu-gate is actually a clock independent from the 'pmu_apb' syscon device, using a reference to syscon node instead of a reg property is just to avoid mapping the same address areas repeatedly. Spreadtrum's clock h/w design is a little complicated, after discussing with Arnd and Stephen, I then chose to implement in this way. I guess the name of 'pmu_apb' might be confused, it's actually not a bus, but a global address area stored a lot of registers shared by a few devices including some clocks. I think I'd better use another name instead of pmu_apb :) Please let me know if I'm missing something here. Thanks, Chunyan > >> + clocks = <&ext_26m>; >> + #clock-cells = <1>; >> + }; >> + >> + pll: pll { >> + compatible = "sprd,sc9860-pll"; >> + sprd,syscon = <&ana_apb>; > > Same here. > >> + clocks = <&pmu_gate 0>; >> + #clock-cells = <1>; >> + }; >> + >> + ap_clk: clock-controller@20000000 { >> + compatible = "sprd,sc9860-ap-clk"; >> + reg = <0 0x20000000 0 0x400>; >> + clocks = <&ext_26m>, <&pll 0>, >> + <&pmu_gate 0>; >> + #clock-cells = <1>; >> + }; >> -- >> 2.7.4 >> ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 03/11] clk: sprd: Add common infrastructure 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Added Spreadtrum's clock driver framework together with common structures and interface functions. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sprd/Kconfig | 4 ++ drivers/clk/sprd/Makefile | 3 ++ drivers/clk/sprd/common.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/common.h | 57 +++++++++++++++++++++++ 6 files changed, 178 insertions(+) create mode 100644 drivers/clk/sprd/Kconfig create mode 100644 drivers/clk/sprd/Makefile create mode 100644 drivers/clk/sprd/common.c create mode 100644 drivers/clk/sprd/common.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 1c4e1aa..ce1a32be 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -236,6 +236,7 @@ source "drivers/clk/mvebu/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" source "drivers/clk/samsung/Kconfig" +source "drivers/clk/sprd/Kconfig" source "drivers/clk/sunxi-ng/Kconfig" source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c99f363..fa33891 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_ARCH_SIRF) += sirf/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ obj-$(CONFIG_PLAT_SPEAR) += spear/ +obj-$(CONFIG_ARCH_SPRD) += sprd/ obj-$(CONFIG_ARCH_STI) += st/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/ diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig new file mode 100644 index 0000000..67a3287 --- /dev/null +++ b/drivers/clk/sprd/Kconfig @@ -0,0 +1,4 @@ +config SPRD_COMMON_CLK + tristate "Clock support for Spreadtrum SoCs" + depends on ARCH_SPRD || COMPILE_TEST + default ARCH_SPRD diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile new file mode 100644 index 0000000..74f4b80 --- /dev/null +++ b/drivers/clk/sprd/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o + +clk-sprd-y += common.o diff --git a/drivers/clk/sprd/common.c b/drivers/clk/sprd/common.c new file mode 100644 index 0000000..9ae5932 --- /dev/null +++ b/drivers/clk/sprd/common.c @@ -0,0 +1,112 @@ +/* + * Spreadtrum clock infrastructure + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> +#include <linux/regmap.h> + +#include "common.h" + +static const struct regmap_config sprdclk_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xffff, + .fast_io = true, +}; + +void sprd_clk_set_regmap(const struct sprd_clk_desc *desc, + struct regmap *regmap) +{ + int i; + struct sprd_clk_common *cclk; + + for (i = 0; i < desc->num_clk_clks; i++) { + cclk = desc->clk_clks[i]; + if (!cclk) + continue; + + cclk->regmap = regmap; + } +} + +int sprd_clk_regmap_init(struct platform_device *pdev, + const struct sprd_clk_desc *desc) +{ + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + struct regmap *regmap = NULL; + + if (of_find_property(node, "sprd,syscon", NULL)) { + regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon"); + if (IS_ERR(regmap)) { + pr_err("%s: failed to get syscon regmap\n", __func__); + return PTR_ERR(regmap); + } + } else { + base = of_iomap(node, 0); + regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sprdclk_regmap_config); + if (IS_ERR(regmap)) { + pr_err("failed to init regmap.\n"); + return PTR_ERR(regmap); + } + } + + sprd_clk_set_regmap(desc, regmap); + + return 0; +} + +int sprd_clk_probe(struct device_node *node, + struct clk_hw_onecell_data *clkhw) +{ + int i, ret = 0; + struct clk_hw *hw; + + for (i = 0; i < clkhw->num; i++) { + + hw = clkhw->hws[i]; + + if (!hw) + continue; + + ret = clk_hw_register(NULL, hw); + if (ret) { + pr_err("Couldn't register clock %d - %s\n", + i, hw->init->name); + goto err_clk_unreg; + } + } + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + clkhw); + if (ret) { + pr_err("Failed to add clock provider.\n"); + goto err_clk_unreg; + } + + return 0; + +err_clk_unreg: + while (--i >= 0) { + hw = clkhw->hws[i]; + if (!hw) + continue; + + clk_hw_unregister(hw); + } + + return ret; +} +EXPORT_SYMBOL_GPL(sprd_clk_probe); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/sprd/common.h b/drivers/clk/sprd/common.h new file mode 100644 index 0000000..7283387 --- /dev/null +++ b/drivers/clk/sprd/common.h @@ -0,0 +1,57 @@ +/* + * Spreadtrum clock infrastructure + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_CLK_COMMON_H_ +#define _SPRD_CLK_COMMON_H_ + +#include <linux/clk-provider.h> +#include <linux/of_platform.h> +#include <linux/regmap.h> + +#include "../clk_common.h" + +struct device_node; + +struct sprd_clk_common { + struct regmap *regmap; + u32 reg; + spinlock_t *lock; + struct clk_hw hw; +}; + +struct sprd_clk_desc { + struct sprd_clk_common **clk_clks; + unsigned long num_clk_clks; + struct clk_hw_onecell_data *hw_clks; +}; + +#define sprd_regmap_read(map, reg, val) \ +({ \ + (map) ? regmap_read((map), (reg), (val)) : (-EINVAL); \ +}) + +#define sprd_regmap_write(map, reg, val) \ +({ \ + (map) ? regmap_write((map), (reg), (val)) : (-EINVAL); \ +}) + +static inline struct sprd_clk_common * + hw_to_sprd_clk_common(const struct clk_hw *hw) +{ + return container_of(hw, struct sprd_clk_common, hw); +} + +void sprd_clk_set_regmap(const struct sprd_clk_desc *desc, + struct regmap *regmap); +int sprd_clk_regmap_init(struct platform_device *pdev, + const struct sprd_clk_desc *desc); +int sprd_clk_probe(struct device_node *node, + struct clk_hw_onecell_data *clkhw); + +#endif /* _SPRD_CLK_COMMON_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 03/11] clk: sprd: Add common infrastructure @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel Added Spreadtrum's clock driver framework together with common structures and interface functions. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sprd/Kconfig | 4 ++ drivers/clk/sprd/Makefile | 3 ++ drivers/clk/sprd/common.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/common.h | 57 +++++++++++++++++++++++ 6 files changed, 178 insertions(+) create mode 100644 drivers/clk/sprd/Kconfig create mode 100644 drivers/clk/sprd/Makefile create mode 100644 drivers/clk/sprd/common.c create mode 100644 drivers/clk/sprd/common.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 1c4e1aa..ce1a32be 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -236,6 +236,7 @@ source "drivers/clk/mvebu/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" source "drivers/clk/samsung/Kconfig" +source "drivers/clk/sprd/Kconfig" source "drivers/clk/sunxi-ng/Kconfig" source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c99f363..fa33891 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_ARCH_SIRF) += sirf/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ obj-$(CONFIG_PLAT_SPEAR) += spear/ +obj-$(CONFIG_ARCH_SPRD) += sprd/ obj-$(CONFIG_ARCH_STI) += st/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/ diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig new file mode 100644 index 0000000..67a3287 --- /dev/null +++ b/drivers/clk/sprd/Kconfig @@ -0,0 +1,4 @@ +config SPRD_COMMON_CLK + tristate "Clock support for Spreadtrum SoCs" + depends on ARCH_SPRD || COMPILE_TEST + default ARCH_SPRD diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile new file mode 100644 index 0000000..74f4b80 --- /dev/null +++ b/drivers/clk/sprd/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o + +clk-sprd-y += common.o diff --git a/drivers/clk/sprd/common.c b/drivers/clk/sprd/common.c new file mode 100644 index 0000000..9ae5932 --- /dev/null +++ b/drivers/clk/sprd/common.c @@ -0,0 +1,112 @@ +/* + * Spreadtrum clock infrastructure + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> +#include <linux/regmap.h> + +#include "common.h" + +static const struct regmap_config sprdclk_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xffff, + .fast_io = true, +}; + +void sprd_clk_set_regmap(const struct sprd_clk_desc *desc, + struct regmap *regmap) +{ + int i; + struct sprd_clk_common *cclk; + + for (i = 0; i < desc->num_clk_clks; i++) { + cclk = desc->clk_clks[i]; + if (!cclk) + continue; + + cclk->regmap = regmap; + } +} + +int sprd_clk_regmap_init(struct platform_device *pdev, + const struct sprd_clk_desc *desc) +{ + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + struct regmap *regmap = NULL; + + if (of_find_property(node, "sprd,syscon", NULL)) { + regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon"); + if (IS_ERR(regmap)) { + pr_err("%s: failed to get syscon regmap\n", __func__); + return PTR_ERR(regmap); + } + } else { + base = of_iomap(node, 0); + regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sprdclk_regmap_config); + if (IS_ERR(regmap)) { + pr_err("failed to init regmap.\n"); + return PTR_ERR(regmap); + } + } + + sprd_clk_set_regmap(desc, regmap); + + return 0; +} + +int sprd_clk_probe(struct device_node *node, + struct clk_hw_onecell_data *clkhw) +{ + int i, ret = 0; + struct clk_hw *hw; + + for (i = 0; i < clkhw->num; i++) { + + hw = clkhw->hws[i]; + + if (!hw) + continue; + + ret = clk_hw_register(NULL, hw); + if (ret) { + pr_err("Couldn't register clock %d - %s\n", + i, hw->init->name); + goto err_clk_unreg; + } + } + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + clkhw); + if (ret) { + pr_err("Failed to add clock provider.\n"); + goto err_clk_unreg; + } + + return 0; + +err_clk_unreg: + while (--i >= 0) { + hw = clkhw->hws[i]; + if (!hw) + continue; + + clk_hw_unregister(hw); + } + + return ret; +} +EXPORT_SYMBOL_GPL(sprd_clk_probe); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/sprd/common.h b/drivers/clk/sprd/common.h new file mode 100644 index 0000000..7283387 --- /dev/null +++ b/drivers/clk/sprd/common.h @@ -0,0 +1,57 @@ +/* + * Spreadtrum clock infrastructure + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_CLK_COMMON_H_ +#define _SPRD_CLK_COMMON_H_ + +#include <linux/clk-provider.h> +#include <linux/of_platform.h> +#include <linux/regmap.h> + +#include "../clk_common.h" + +struct device_node; + +struct sprd_clk_common { + struct regmap *regmap; + u32 reg; + spinlock_t *lock; + struct clk_hw hw; +}; + +struct sprd_clk_desc { + struct sprd_clk_common **clk_clks; + unsigned long num_clk_clks; + struct clk_hw_onecell_data *hw_clks; +}; + +#define sprd_regmap_read(map, reg, val) \ +({ \ + (map) ? regmap_read((map), (reg), (val)) : (-EINVAL); \ +}) + +#define sprd_regmap_write(map, reg, val) \ +({ \ + (map) ? regmap_write((map), (reg), (val)) : (-EINVAL); \ +}) + +static inline struct sprd_clk_common * + hw_to_sprd_clk_common(const struct clk_hw *hw) +{ + return container_of(hw, struct sprd_clk_common, hw); +} + +void sprd_clk_set_regmap(const struct sprd_clk_desc *desc, + struct regmap *regmap); +int sprd_clk_regmap_init(struct platform_device *pdev, + const struct sprd_clk_desc *desc); +int sprd_clk_probe(struct device_node *node, + struct clk_hw_onecell_data *clkhw); + +#endif /* _SPRD_CLK_COMMON_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 03/11] clk: sprd: Add common infrastructure @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Added Spreadtrum's clock driver framework together with common structures and interface functions. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sprd/Kconfig | 4 ++ drivers/clk/sprd/Makefile | 3 ++ drivers/clk/sprd/common.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/common.h | 57 +++++++++++++++++++++++ 6 files changed, 178 insertions(+) create mode 100644 drivers/clk/sprd/Kconfig create mode 100644 drivers/clk/sprd/Makefile create mode 100644 drivers/clk/sprd/common.c create mode 100644 drivers/clk/sprd/common.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 1c4e1aa..ce1a32be 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -236,6 +236,7 @@ source "drivers/clk/mvebu/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" source "drivers/clk/samsung/Kconfig" +source "drivers/clk/sprd/Kconfig" source "drivers/clk/sunxi-ng/Kconfig" source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c99f363..fa33891 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_ARCH_SIRF) += sirf/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ obj-$(CONFIG_PLAT_SPEAR) += spear/ +obj-$(CONFIG_ARCH_SPRD) += sprd/ obj-$(CONFIG_ARCH_STI) += st/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/ diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig new file mode 100644 index 0000000..67a3287 --- /dev/null +++ b/drivers/clk/sprd/Kconfig @@ -0,0 +1,4 @@ +config SPRD_COMMON_CLK + tristate "Clock support for Spreadtrum SoCs" + depends on ARCH_SPRD || COMPILE_TEST + default ARCH_SPRD diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile new file mode 100644 index 0000000..74f4b80 --- /dev/null +++ b/drivers/clk/sprd/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o + +clk-sprd-y += common.o diff --git a/drivers/clk/sprd/common.c b/drivers/clk/sprd/common.c new file mode 100644 index 0000000..9ae5932 --- /dev/null +++ b/drivers/clk/sprd/common.c @@ -0,0 +1,112 @@ +/* + * Spreadtrum clock infrastructure + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> +#include <linux/regmap.h> + +#include "common.h" + +static const struct regmap_config sprdclk_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xffff, + .fast_io = true, +}; + +void sprd_clk_set_regmap(const struct sprd_clk_desc *desc, + struct regmap *regmap) +{ + int i; + struct sprd_clk_common *cclk; + + for (i = 0; i < desc->num_clk_clks; i++) { + cclk = desc->clk_clks[i]; + if (!cclk) + continue; + + cclk->regmap = regmap; + } +} + +int sprd_clk_regmap_init(struct platform_device *pdev, + const struct sprd_clk_desc *desc) +{ + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + struct regmap *regmap = NULL; + + if (of_find_property(node, "sprd,syscon", NULL)) { + regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon"); + if (IS_ERR(regmap)) { + pr_err("%s: failed to get syscon regmap\n", __func__); + return PTR_ERR(regmap); + } + } else { + base = of_iomap(node, 0); + regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sprdclk_regmap_config); + if (IS_ERR(regmap)) { + pr_err("failed to init regmap.\n"); + return PTR_ERR(regmap); + } + } + + sprd_clk_set_regmap(desc, regmap); + + return 0; +} + +int sprd_clk_probe(struct device_node *node, + struct clk_hw_onecell_data *clkhw) +{ + int i, ret = 0; + struct clk_hw *hw; + + for (i = 0; i < clkhw->num; i++) { + + hw = clkhw->hws[i]; + + if (!hw) + continue; + + ret = clk_hw_register(NULL, hw); + if (ret) { + pr_err("Couldn't register clock %d - %s\n", + i, hw->init->name); + goto err_clk_unreg; + } + } + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + clkhw); + if (ret) { + pr_err("Failed to add clock provider.\n"); + goto err_clk_unreg; + } + + return 0; + +err_clk_unreg: + while (--i >= 0) { + hw = clkhw->hws[i]; + if (!hw) + continue; + + clk_hw_unregister(hw); + } + + return ret; +} +EXPORT_SYMBOL_GPL(sprd_clk_probe); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/sprd/common.h b/drivers/clk/sprd/common.h new file mode 100644 index 0000000..7283387 --- /dev/null +++ b/drivers/clk/sprd/common.h @@ -0,0 +1,57 @@ +/* + * Spreadtrum clock infrastructure + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_CLK_COMMON_H_ +#define _SPRD_CLK_COMMON_H_ + +#include <linux/clk-provider.h> +#include <linux/of_platform.h> +#include <linux/regmap.h> + +#include "../clk_common.h" + +struct device_node; + +struct sprd_clk_common { + struct regmap *regmap; + u32 reg; + spinlock_t *lock; + struct clk_hw hw; +}; + +struct sprd_clk_desc { + struct sprd_clk_common **clk_clks; + unsigned long num_clk_clks; + struct clk_hw_onecell_data *hw_clks; +}; + +#define sprd_regmap_read(map, reg, val) \ +({ \ + (map) ? regmap_read((map), (reg), (val)) : (-EINVAL); \ +}) + +#define sprd_regmap_write(map, reg, val) \ +({ \ + (map) ? regmap_write((map), (reg), (val)) : (-EINVAL); \ +}) + +static inline struct sprd_clk_common * + hw_to_sprd_clk_common(const struct clk_hw *hw) +{ + return container_of(hw, struct sprd_clk_common, hw); +} + +void sprd_clk_set_regmap(const struct sprd_clk_desc *desc, + struct regmap *regmap); +int sprd_clk_regmap_init(struct platform_device *pdev, + const struct sprd_clk_desc *desc); +int sprd_clk_probe(struct device_node *node, + struct clk_hw_onecell_data *clkhw); + +#endif /* _SPRD_CLK_COMMON_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 04/11] clk: sprd: add gate clock support 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Some clocks on the Spreadtrum's SoCs are just simple gates. Add support for those clocks. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/gate.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/gate.h | 54 +++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 drivers/clk/sprd/gate.c create mode 100644 drivers/clk/sprd/gate.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 74f4b80..8cd5592 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o clk-sprd-y += common.o +clk-sprd-y += gate.o diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c new file mode 100644 index 0000000..831ef81 --- /dev/null +++ b/drivers/clk/sprd/gate.c @@ -0,0 +1,106 @@ +/* + * Spreadtrum gate clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> +#include <linux/regmap.h> + +#include "gate.h" + +DEFINE_SPINLOCK(sprd_gate_lock); +EXPORT_SYMBOL_GPL(sprd_gate_lock); + +static void sprd_gate_endisable(const struct sprd_gate *sg, u32 en) +{ + const struct sprd_clk_common *common = &sg->common; + unsigned long flags = 0; + unsigned int reg; + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; + + set ^= en; + + spin_lock_irqsave(common->lock, flags); + + sprd_regmap_read(common->regmap, common->reg, ®); + + if (set) + reg |= sg->op_bit; + else + reg &= ~sg->op_bit; + + sprd_regmap_write(common->regmap, common->reg, reg); + + spin_unlock_irqrestore(common->lock, flags); +} + +static void clk_sc_gate_endisable(const struct sprd_gate *sg, u32 en) +{ + const struct sprd_clk_common *common = &sg->common; + unsigned long flags = 0; + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; + unsigned int offset; + + set ^= en; + + /* + * Each set/clear gate clock has three registers: + * common->reg - base register + * common->reg + offset - set register + * common->reg + 2 * offset - clear register + */ + offset = set ? sg->sc_offset : sg->sc_offset * 2; + + spin_lock_irqsave(common->lock, flags); + sprd_regmap_write(common->regmap, common->reg + offset, sg->op_bit); + spin_unlock_irqrestore(common->lock, flags); +} + +static void sprd_gate_disable(struct clk_hw *hw) +{ + struct sprd_gate *sg = hw_to_sprd_gate(hw); + + if (sg->sc_offset) + clk_sc_gate_endisable(sg, 0); + else + sprd_gate_endisable(sg, 0); +} + +static int sprd_gate_enable(struct clk_hw *hw) +{ + struct sprd_gate *sg = hw_to_sprd_gate(hw); + + if (sg->sc_offset) + clk_sc_gate_endisable(sg, 1); + else + sprd_gate_endisable(sg, 1); + + return 0; +} + +static int sprd_gate_is_enabled(struct clk_hw *hw) +{ + struct sprd_gate *sg = hw_to_sprd_gate(hw); + struct sprd_clk_common *common = &sg->common; + unsigned int reg; + + sprd_regmap_read(common->regmap, common->reg, ®); + + if (sg->flags & CLK_GATE_SET_TO_DISABLE) + reg ^= sg->op_bit; + + reg &= sg->op_bit; + + return reg ? 1 : 0; +} + +const struct clk_ops sprd_gate_ops = { + .disable = sprd_gate_disable, + .enable = sprd_gate_enable, + .is_enabled = sprd_gate_is_enabled, +}; +EXPORT_SYMBOL_GPL(sprd_gate_ops); diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h new file mode 100644 index 0000000..5aeb53c --- /dev/null +++ b/drivers/clk/sprd/gate.h @@ -0,0 +1,54 @@ +/* + * Spreadtrum gate clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_GATE_H_ +#define _SPRD_GATE_H_ + +#include "common.h" + +struct sprd_gate { + u32 op_bit; + u16 flags; + u16 sc_offset; + + struct sprd_clk_common common; +}; + +#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \ + _op_bit, _flags, _gate_flags) \ + struct sprd_gate _struct = { \ + .op_bit = _op_bit, \ + .sc_offset = _sc_offset, \ + .flags = _gate_flags, \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_gate_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &sprd_gate_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_gate, common); +} + +void sprd_gate_helper_disable(struct sprd_clk_common *common, u32 gate); +int sprd_gate_helper_enable(struct sprd_clk_common *common, u32 gate); +int sprd_gate_helper_is_enabled(struct sprd_clk_common *common, u32 gate); + +extern const struct clk_ops sprd_gate_ops; +extern spinlock_t sprd_gate_lock; + +#endif /* _SPRD_GATE_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 04/11] clk: sprd: add gate clock support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel Some clocks on the Spreadtrum's SoCs are just simple gates. Add support for those clocks. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/gate.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/gate.h | 54 +++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 drivers/clk/sprd/gate.c create mode 100644 drivers/clk/sprd/gate.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 74f4b80..8cd5592 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o clk-sprd-y += common.o +clk-sprd-y += gate.o diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c new file mode 100644 index 0000000..831ef81 --- /dev/null +++ b/drivers/clk/sprd/gate.c @@ -0,0 +1,106 @@ +/* + * Spreadtrum gate clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> +#include <linux/regmap.h> + +#include "gate.h" + +DEFINE_SPINLOCK(sprd_gate_lock); +EXPORT_SYMBOL_GPL(sprd_gate_lock); + +static void sprd_gate_endisable(const struct sprd_gate *sg, u32 en) +{ + const struct sprd_clk_common *common = &sg->common; + unsigned long flags = 0; + unsigned int reg; + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; + + set ^= en; + + spin_lock_irqsave(common->lock, flags); + + sprd_regmap_read(common->regmap, common->reg, ®); + + if (set) + reg |= sg->op_bit; + else + reg &= ~sg->op_bit; + + sprd_regmap_write(common->regmap, common->reg, reg); + + spin_unlock_irqrestore(common->lock, flags); +} + +static void clk_sc_gate_endisable(const struct sprd_gate *sg, u32 en) +{ + const struct sprd_clk_common *common = &sg->common; + unsigned long flags = 0; + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; + unsigned int offset; + + set ^= en; + + /* + * Each set/clear gate clock has three registers: + * common->reg - base register + * common->reg + offset - set register + * common->reg + 2 * offset - clear register + */ + offset = set ? sg->sc_offset : sg->sc_offset * 2; + + spin_lock_irqsave(common->lock, flags); + sprd_regmap_write(common->regmap, common->reg + offset, sg->op_bit); + spin_unlock_irqrestore(common->lock, flags); +} + +static void sprd_gate_disable(struct clk_hw *hw) +{ + struct sprd_gate *sg = hw_to_sprd_gate(hw); + + if (sg->sc_offset) + clk_sc_gate_endisable(sg, 0); + else + sprd_gate_endisable(sg, 0); +} + +static int sprd_gate_enable(struct clk_hw *hw) +{ + struct sprd_gate *sg = hw_to_sprd_gate(hw); + + if (sg->sc_offset) + clk_sc_gate_endisable(sg, 1); + else + sprd_gate_endisable(sg, 1); + + return 0; +} + +static int sprd_gate_is_enabled(struct clk_hw *hw) +{ + struct sprd_gate *sg = hw_to_sprd_gate(hw); + struct sprd_clk_common *common = &sg->common; + unsigned int reg; + + sprd_regmap_read(common->regmap, common->reg, ®); + + if (sg->flags & CLK_GATE_SET_TO_DISABLE) + reg ^= sg->op_bit; + + reg &= sg->op_bit; + + return reg ? 1 : 0; +} + +const struct clk_ops sprd_gate_ops = { + .disable = sprd_gate_disable, + .enable = sprd_gate_enable, + .is_enabled = sprd_gate_is_enabled, +}; +EXPORT_SYMBOL_GPL(sprd_gate_ops); diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h new file mode 100644 index 0000000..5aeb53c --- /dev/null +++ b/drivers/clk/sprd/gate.h @@ -0,0 +1,54 @@ +/* + * Spreadtrum gate clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_GATE_H_ +#define _SPRD_GATE_H_ + +#include "common.h" + +struct sprd_gate { + u32 op_bit; + u16 flags; + u16 sc_offset; + + struct sprd_clk_common common; +}; + +#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \ + _op_bit, _flags, _gate_flags) \ + struct sprd_gate _struct = { \ + .op_bit = _op_bit, \ + .sc_offset = _sc_offset, \ + .flags = _gate_flags, \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_gate_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &sprd_gate_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_gate, common); +} + +void sprd_gate_helper_disable(struct sprd_clk_common *common, u32 gate); +int sprd_gate_helper_enable(struct sprd_clk_common *common, u32 gate); +int sprd_gate_helper_is_enabled(struct sprd_clk_common *common, u32 gate); + +extern const struct clk_ops sprd_gate_ops; +extern spinlock_t sprd_gate_lock; + +#endif /* _SPRD_GATE_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 04/11] clk: sprd: add gate clock support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Some clocks on the Spreadtrum's SoCs are just simple gates. Add support for those clocks. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/gate.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/gate.h | 54 +++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 drivers/clk/sprd/gate.c create mode 100644 drivers/clk/sprd/gate.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 74f4b80..8cd5592 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o clk-sprd-y += common.o +clk-sprd-y += gate.o diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c new file mode 100644 index 0000000..831ef81 --- /dev/null +++ b/drivers/clk/sprd/gate.c @@ -0,0 +1,106 @@ +/* + * Spreadtrum gate clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> +#include <linux/regmap.h> + +#include "gate.h" + +DEFINE_SPINLOCK(sprd_gate_lock); +EXPORT_SYMBOL_GPL(sprd_gate_lock); + +static void sprd_gate_endisable(const struct sprd_gate *sg, u32 en) +{ + const struct sprd_clk_common *common = &sg->common; + unsigned long flags = 0; + unsigned int reg; + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; + + set ^= en; + + spin_lock_irqsave(common->lock, flags); + + sprd_regmap_read(common->regmap, common->reg, ®); + + if (set) + reg |= sg->op_bit; + else + reg &= ~sg->op_bit; + + sprd_regmap_write(common->regmap, common->reg, reg); + + spin_unlock_irqrestore(common->lock, flags); +} + +static void clk_sc_gate_endisable(const struct sprd_gate *sg, u32 en) +{ + const struct sprd_clk_common *common = &sg->common; + unsigned long flags = 0; + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; + unsigned int offset; + + set ^= en; + + /* + * Each set/clear gate clock has three registers: + * common->reg - base register + * common->reg + offset - set register + * common->reg + 2 * offset - clear register + */ + offset = set ? sg->sc_offset : sg->sc_offset * 2; + + spin_lock_irqsave(common->lock, flags); + sprd_regmap_write(common->regmap, common->reg + offset, sg->op_bit); + spin_unlock_irqrestore(common->lock, flags); +} + +static void sprd_gate_disable(struct clk_hw *hw) +{ + struct sprd_gate *sg = hw_to_sprd_gate(hw); + + if (sg->sc_offset) + clk_sc_gate_endisable(sg, 0); + else + sprd_gate_endisable(sg, 0); +} + +static int sprd_gate_enable(struct clk_hw *hw) +{ + struct sprd_gate *sg = hw_to_sprd_gate(hw); + + if (sg->sc_offset) + clk_sc_gate_endisable(sg, 1); + else + sprd_gate_endisable(sg, 1); + + return 0; +} + +static int sprd_gate_is_enabled(struct clk_hw *hw) +{ + struct sprd_gate *sg = hw_to_sprd_gate(hw); + struct sprd_clk_common *common = &sg->common; + unsigned int reg; + + sprd_regmap_read(common->regmap, common->reg, ®); + + if (sg->flags & CLK_GATE_SET_TO_DISABLE) + reg ^= sg->op_bit; + + reg &= sg->op_bit; + + return reg ? 1 : 0; +} + +const struct clk_ops sprd_gate_ops = { + .disable = sprd_gate_disable, + .enable = sprd_gate_enable, + .is_enabled = sprd_gate_is_enabled, +}; +EXPORT_SYMBOL_GPL(sprd_gate_ops); diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h new file mode 100644 index 0000000..5aeb53c --- /dev/null +++ b/drivers/clk/sprd/gate.h @@ -0,0 +1,54 @@ +/* + * Spreadtrum gate clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_GATE_H_ +#define _SPRD_GATE_H_ + +#include "common.h" + +struct sprd_gate { + u32 op_bit; + u16 flags; + u16 sc_offset; + + struct sprd_clk_common common; +}; + +#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \ + _op_bit, _flags, _gate_flags) \ + struct sprd_gate _struct = { \ + .op_bit = _op_bit, \ + .sc_offset = _sc_offset, \ + .flags = _gate_flags, \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_gate_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &sprd_gate_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_gate, common); +} + +void sprd_gate_helper_disable(struct sprd_clk_common *common, u32 gate); +int sprd_gate_helper_enable(struct sprd_clk_common *common, u32 gate); +int sprd_gate_helper_is_enabled(struct sprd_clk_common *common, u32 gate); + +extern const struct clk_ops sprd_gate_ops; +extern spinlock_t sprd_gate_lock; + +#endif /* _SPRD_GATE_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH V3 04/11] clk: sprd: add gate clock support 2017-11-02 6:56 ` Chunyan Zhang @ 2017-11-02 17:45 ` Julien Thierry -1 siblings, 0 replies; 68+ messages in thread From: Julien Thierry @ 2017-11-02 17:45 UTC (permalink / raw) To: Chunyan Zhang, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Hi, On 02/11/17 06:56, Chunyan Zhang wrote: > Some clocks on the Spreadtrum's SoCs are just simple gates. Add > support for those clocks. > > Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > --- > drivers/clk/sprd/Makefile | 1 + > drivers/clk/sprd/gate.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ > drivers/clk/sprd/gate.h | 54 +++++++++++++++++++++++ > 3 files changed, 161 insertions(+) > create mode 100644 drivers/clk/sprd/gate.c > create mode 100644 drivers/clk/sprd/gate.h > > diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile > index 74f4b80..8cd5592 100644 > --- a/drivers/clk/sprd/Makefile > +++ b/drivers/clk/sprd/Makefile > @@ -1,3 +1,4 @@ > obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o > > clk-sprd-y += common.o > +clk-sprd-y += gate.o > diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c > new file mode 100644 > index 0000000..831ef81 > --- /dev/null > +++ b/drivers/clk/sprd/gate.c > @@ -0,0 +1,106 @@ > +/* > + * Spreadtrum gate clock driver > + * > + * Copyright (C) 2017 Spreadtrum, Inc. > + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#include <linux/clk-provider.h> > +#include <linux/regmap.h> > + > +#include "gate.h" > + > +DEFINE_SPINLOCK(sprd_gate_lock); > +EXPORT_SYMBOL_GPL(sprd_gate_lock); > + > +static void sprd_gate_endisable(const struct sprd_gate *sg, u32 en) > +{ > + const struct sprd_clk_common *common = &sg->common; > + unsigned long flags = 0; > + unsigned int reg; > + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; > + > + set ^= en; > + > + spin_lock_irqsave(common->lock, flags); > + > + sprd_regmap_read(common->regmap, common->reg, ®); > + > + if (set) > + reg |= sg->op_bit; > + else > + reg &= ~sg->op_bit; > + > + sprd_regmap_write(common->regmap, common->reg, reg); > + > + spin_unlock_irqrestore(common->lock, flags); > +} > + > +static void clk_sc_gate_endisable(const struct sprd_gate *sg, u32 en) > +{ > + const struct sprd_clk_common *common = &sg->common; > + unsigned long flags = 0; > + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; > + unsigned int offset; > + > + set ^= en; > + > + /* > + * Each set/clear gate clock has three registers: > + * common->reg - base register > + * common->reg + offset - set register > + * common->reg + 2 * offset - clear register > + */ > + offset = set ? sg->sc_offset : sg->sc_offset * 2; > + > + spin_lock_irqsave(common->lock, flags); > + sprd_regmap_write(common->regmap, common->reg + offset, sg->op_bit); > + spin_unlock_irqrestore(common->lock, flags); > +} > + > +static void sprd_gate_disable(struct clk_hw *hw) > +{ > + struct sprd_gate *sg = hw_to_sprd_gate(hw); > + > + if (sg->sc_offset) > + clk_sc_gate_endisable(sg, 0); > + else > + sprd_gate_endisable(sg, 0); > +} > + > +static int sprd_gate_enable(struct clk_hw *hw) > +{ > + struct sprd_gate *sg = hw_to_sprd_gate(hw); > + > + if (sg->sc_offset) > + clk_sc_gate_endisable(sg, 1); > + else > + sprd_gate_endisable(sg, 1); > + > + return 0; > +} > + > +static int sprd_gate_is_enabled(struct clk_hw *hw) > +{ > + struct sprd_gate *sg = hw_to_sprd_gate(hw); > + struct sprd_clk_common *common = &sg->common; > + unsigned int reg; > + > + sprd_regmap_read(common->regmap, common->reg, ®); > + > + if (sg->flags & CLK_GATE_SET_TO_DISABLE) > + reg ^= sg->op_bit; > + > + reg &= sg->op_bit; > + > + return reg ? 1 : 0; > +} > + > +const struct clk_ops sprd_gate_ops = { > + .disable = sprd_gate_disable, > + .enable = sprd_gate_enable, > + .is_enabled = sprd_gate_is_enabled, > +}; > +EXPORT_SYMBOL_GPL(sprd_gate_ops); I think it would be better to have a set of ops for each mode, sprd_gate_ops and sprd_sc_gate_ops rather than have each function decide whether it should use set/clear registers or the base registers. So you can have a macro SPRD_GATE_CLK that doesn't take an sc_offet and selects the sprd_gate_ops and another one that SPRD_SC_GATE_CLK using sprd_sc_gate_ops that takes the sc_offset as parameter. Also, I feel keeping enable/disable function separate would be nicer instead of having "endisable" functions. Cheers, > diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h > new file mode 100644 > index 0000000..5aeb53c > --- /dev/null > +++ b/drivers/clk/sprd/gate.h > @@ -0,0 +1,54 @@ > +/* > + * Spreadtrum gate clock driver > + * > + * Copyright (C) 2017 Spreadtrum, Inc. > + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#ifndef _SPRD_GATE_H_ > +#define _SPRD_GATE_H_ > + > +#include "common.h" > + > +struct sprd_gate { > + u32 op_bit; > + u16 flags; > + u16 sc_offset; > + > + struct sprd_clk_common common; > +}; > + > +#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \ > + _op_bit, _flags, _gate_flags) \ > + struct sprd_gate _struct = { \ > + .op_bit = _op_bit, \ > + .sc_offset = _sc_offset, \ > + .flags = _gate_flags, \ > + .common = { \ > + .regmap = NULL, \ > + .reg = _reg, \ > + .lock = &sprd_gate_lock, \ > + .hw.init = CLK_HW_INIT(_name, \ > + _parent, \ > + &sprd_gate_ops, \ > + _flags), \ > + } \ > + } > + > +static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw) > +{ > + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); > + > + return container_of(common, struct sprd_gate, common); > +} > + > +void sprd_gate_helper_disable(struct sprd_clk_common *common, u32 gate); > +int sprd_gate_helper_enable(struct sprd_clk_common *common, u32 gate); > +int sprd_gate_helper_is_enabled(struct sprd_clk_common *common, u32 gate); > + > +extern const struct clk_ops sprd_gate_ops; > +extern spinlock_t sprd_gate_lock; > + > +#endif /* _SPRD_GATE_H_ */ > -- Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 04/11] clk: sprd: add gate clock support @ 2017-11-02 17:45 ` Julien Thierry 0 siblings, 0 replies; 68+ messages in thread From: Julien Thierry @ 2017-11-02 17:45 UTC (permalink / raw) To: linux-arm-kernel Hi, On 02/11/17 06:56, Chunyan Zhang wrote: > Some clocks on the Spreadtrum's SoCs are just simple gates. Add > support for those clocks. > > Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > --- > drivers/clk/sprd/Makefile | 1 + > drivers/clk/sprd/gate.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ > drivers/clk/sprd/gate.h | 54 +++++++++++++++++++++++ > 3 files changed, 161 insertions(+) > create mode 100644 drivers/clk/sprd/gate.c > create mode 100644 drivers/clk/sprd/gate.h > > diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile > index 74f4b80..8cd5592 100644 > --- a/drivers/clk/sprd/Makefile > +++ b/drivers/clk/sprd/Makefile > @@ -1,3 +1,4 @@ > obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o > > clk-sprd-y += common.o > +clk-sprd-y += gate.o > diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c > new file mode 100644 > index 0000000..831ef81 > --- /dev/null > +++ b/drivers/clk/sprd/gate.c > @@ -0,0 +1,106 @@ > +/* > + * Spreadtrum gate clock driver > + * > + * Copyright (C) 2017 Spreadtrum, Inc. > + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#include <linux/clk-provider.h> > +#include <linux/regmap.h> > + > +#include "gate.h" > + > +DEFINE_SPINLOCK(sprd_gate_lock); > +EXPORT_SYMBOL_GPL(sprd_gate_lock); > + > +static void sprd_gate_endisable(const struct sprd_gate *sg, u32 en) > +{ > + const struct sprd_clk_common *common = &sg->common; > + unsigned long flags = 0; > + unsigned int reg; > + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; > + > + set ^= en; > + > + spin_lock_irqsave(common->lock, flags); > + > + sprd_regmap_read(common->regmap, common->reg, ®); > + > + if (set) > + reg |= sg->op_bit; > + else > + reg &= ~sg->op_bit; > + > + sprd_regmap_write(common->regmap, common->reg, reg); > + > + spin_unlock_irqrestore(common->lock, flags); > +} > + > +static void clk_sc_gate_endisable(const struct sprd_gate *sg, u32 en) > +{ > + const struct sprd_clk_common *common = &sg->common; > + unsigned long flags = 0; > + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; > + unsigned int offset; > + > + set ^= en; > + > + /* > + * Each set/clear gate clock has three registers: > + * common->reg - base register > + * common->reg + offset - set register > + * common->reg + 2 * offset - clear register > + */ > + offset = set ? sg->sc_offset : sg->sc_offset * 2; > + > + spin_lock_irqsave(common->lock, flags); > + sprd_regmap_write(common->regmap, common->reg + offset, sg->op_bit); > + spin_unlock_irqrestore(common->lock, flags); > +} > + > +static void sprd_gate_disable(struct clk_hw *hw) > +{ > + struct sprd_gate *sg = hw_to_sprd_gate(hw); > + > + if (sg->sc_offset) > + clk_sc_gate_endisable(sg, 0); > + else > + sprd_gate_endisable(sg, 0); > +} > + > +static int sprd_gate_enable(struct clk_hw *hw) > +{ > + struct sprd_gate *sg = hw_to_sprd_gate(hw); > + > + if (sg->sc_offset) > + clk_sc_gate_endisable(sg, 1); > + else > + sprd_gate_endisable(sg, 1); > + > + return 0; > +} > + > +static int sprd_gate_is_enabled(struct clk_hw *hw) > +{ > + struct sprd_gate *sg = hw_to_sprd_gate(hw); > + struct sprd_clk_common *common = &sg->common; > + unsigned int reg; > + > + sprd_regmap_read(common->regmap, common->reg, ®); > + > + if (sg->flags & CLK_GATE_SET_TO_DISABLE) > + reg ^= sg->op_bit; > + > + reg &= sg->op_bit; > + > + return reg ? 1 : 0; > +} > + > +const struct clk_ops sprd_gate_ops = { > + .disable = sprd_gate_disable, > + .enable = sprd_gate_enable, > + .is_enabled = sprd_gate_is_enabled, > +}; > +EXPORT_SYMBOL_GPL(sprd_gate_ops); I think it would be better to have a set of ops for each mode, sprd_gate_ops and sprd_sc_gate_ops rather than have each function decide whether it should use set/clear registers or the base registers. So you can have a macro SPRD_GATE_CLK that doesn't take an sc_offet and selects the sprd_gate_ops and another one that SPRD_SC_GATE_CLK using sprd_sc_gate_ops that takes the sc_offset as parameter. Also, I feel keeping enable/disable function separate would be nicer instead of having "endisable" functions. Cheers, > diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h > new file mode 100644 > index 0000000..5aeb53c > --- /dev/null > +++ b/drivers/clk/sprd/gate.h > @@ -0,0 +1,54 @@ > +/* > + * Spreadtrum gate clock driver > + * > + * Copyright (C) 2017 Spreadtrum, Inc. > + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#ifndef _SPRD_GATE_H_ > +#define _SPRD_GATE_H_ > + > +#include "common.h" > + > +struct sprd_gate { > + u32 op_bit; > + u16 flags; > + u16 sc_offset; > + > + struct sprd_clk_common common; > +}; > + > +#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \ > + _op_bit, _flags, _gate_flags) \ > + struct sprd_gate _struct = { \ > + .op_bit = _op_bit, \ > + .sc_offset = _sc_offset, \ > + .flags = _gate_flags, \ > + .common = { \ > + .regmap = NULL, \ > + .reg = _reg, \ > + .lock = &sprd_gate_lock, \ > + .hw.init = CLK_HW_INIT(_name, \ > + _parent, \ > + &sprd_gate_ops, \ > + _flags), \ > + } \ > + } > + > +static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw) > +{ > + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); > + > + return container_of(common, struct sprd_gate, common); > +} > + > +void sprd_gate_helper_disable(struct sprd_clk_common *common, u32 gate); > +int sprd_gate_helper_enable(struct sprd_clk_common *common, u32 gate); > +int sprd_gate_helper_is_enabled(struct sprd_clk_common *common, u32 gate); > + > +extern const struct clk_ops sprd_gate_ops; > +extern spinlock_t sprd_gate_lock; > + > +#endif /* _SPRD_GATE_H_ */ > -- Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 04/11] clk: sprd: add gate clock support 2017-11-02 17:45 ` Julien Thierry (?) @ 2017-11-03 12:12 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-03 12:12 UTC (permalink / raw) To: Julien Thierry Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai Hi Julien, On 3 November 2017 at 01:45, Julien Thierry <julien.thierry@arm.com> wrote: > Hi, > > > On 02/11/17 06:56, Chunyan Zhang wrote: >> >> Some clocks on the Spreadtrum's SoCs are just simple gates. Add >> support for those clocks. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Makefile | 1 + >> drivers/clk/sprd/gate.c | 106 >> ++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/clk/sprd/gate.h | 54 +++++++++++++++++++++++ >> 3 files changed, 161 insertions(+) >> create mode 100644 drivers/clk/sprd/gate.c >> create mode 100644 drivers/clk/sprd/gate.h >> >> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >> index 74f4b80..8cd5592 100644 >> --- a/drivers/clk/sprd/Makefile >> +++ b/drivers/clk/sprd/Makefile >> @@ -1,3 +1,4 @@ >> obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >> clk-sprd-y += common.o >> +clk-sprd-y += gate.o >> diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c >> new file mode 100644 >> index 0000000..831ef81 >> --- /dev/null >> +++ b/drivers/clk/sprd/gate.c >> @@ -0,0 +1,106 @@ >> +/* >> + * Spreadtrum gate clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#include <linux/clk-provider.h> >> +#include <linux/regmap.h> >> + >> +#include "gate.h" >> + >> +DEFINE_SPINLOCK(sprd_gate_lock); >> +EXPORT_SYMBOL_GPL(sprd_gate_lock); >> + >> +static void sprd_gate_endisable(const struct sprd_gate *sg, u32 en) >> +{ >> + const struct sprd_clk_common *common = &sg->common; >> + unsigned long flags = 0; >> + unsigned int reg; >> + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; >> + >> + set ^= en; >> + >> + spin_lock_irqsave(common->lock, flags); >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + >> + if (set) >> + reg |= sg->op_bit; >> + else >> + reg &= ~sg->op_bit; >> + >> + sprd_regmap_write(common->regmap, common->reg, reg); >> + >> + spin_unlock_irqrestore(common->lock, flags); >> +} >> + >> +static void clk_sc_gate_endisable(const struct sprd_gate *sg, u32 en) >> +{ >> + const struct sprd_clk_common *common = &sg->common; >> + unsigned long flags = 0; >> + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; >> + unsigned int offset; >> + >> + set ^= en; >> + >> + /* >> + * Each set/clear gate clock has three registers: >> + * common->reg - base register >> + * common->reg + offset - set register >> + * common->reg + 2 * offset - clear register >> + */ >> + offset = set ? sg->sc_offset : sg->sc_offset * 2; >> + >> + spin_lock_irqsave(common->lock, flags); >> + sprd_regmap_write(common->regmap, common->reg + offset, >> sg->op_bit); >> + spin_unlock_irqrestore(common->lock, flags); >> +} >> + >> +static void sprd_gate_disable(struct clk_hw *hw) >> +{ >> + struct sprd_gate *sg = hw_to_sprd_gate(hw); >> + >> + if (sg->sc_offset) >> + clk_sc_gate_endisable(sg, 0); >> + else >> + sprd_gate_endisable(sg, 0); >> +} >> + >> +static int sprd_gate_enable(struct clk_hw *hw) >> +{ >> + struct sprd_gate *sg = hw_to_sprd_gate(hw); >> + >> + if (sg->sc_offset) >> + clk_sc_gate_endisable(sg, 1); >> + else >> + sprd_gate_endisable(sg, 1); >> + >> + return 0; >> +} >> + >> +static int sprd_gate_is_enabled(struct clk_hw *hw) >> +{ >> + struct sprd_gate *sg = hw_to_sprd_gate(hw); >> + struct sprd_clk_common *common = &sg->common; >> + unsigned int reg; >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + >> + if (sg->flags & CLK_GATE_SET_TO_DISABLE) >> + reg ^= sg->op_bit; >> + >> + reg &= sg->op_bit; >> + >> + return reg ? 1 : 0; >> +} >> + >> +const struct clk_ops sprd_gate_ops = { >> + .disable = sprd_gate_disable, >> + .enable = sprd_gate_enable, >> + .is_enabled = sprd_gate_is_enabled, >> +}; >> +EXPORT_SYMBOL_GPL(sprd_gate_ops); > > > I think it would be better to have a set of ops for each mode, > sprd_gate_ops and sprd_sc_gate_ops rather than have each function decide > whether it should use set/clear registers or the base registers. > > So you can have a macro SPRD_GATE_CLK that doesn't take an sc_offet and > selects the sprd_gate_ops and another one that SPRD_SC_GATE_CLK using > sprd_sc_gate_ops that takes the sc_offset as parameter. > That makes more sense, I will revise in the next version. > Also, I feel keeping enable/disable function separate would be nicer instead > of having "endisable" functions. To avoid duplicate code, I prefer to keep the enable and disable functions together, but I agree that 'endisable' is indeed not good name for the function, I will revise the name to 'toggle' which I saw qcom clk drivers use, it might make more sense. Thanks, Chunyan > > Cheers, > > >> diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h >> new file mode 100644 >> index 0000000..5aeb53c >> --- /dev/null >> +++ b/drivers/clk/sprd/gate.h >> @@ -0,0 +1,54 @@ >> +/* >> + * Spreadtrum gate clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#ifndef _SPRD_GATE_H_ >> +#define _SPRD_GATE_H_ >> + >> +#include "common.h" >> + >> +struct sprd_gate { >> + u32 op_bit; >> + u16 flags; >> + u16 sc_offset; >> + >> + struct sprd_clk_common common; >> +}; >> + >> +#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \ >> + _op_bit, _flags, _gate_flags) \ >> + struct sprd_gate _struct = { \ >> + .op_bit = _op_bit, \ >> + .sc_offset = _sc_offset, \ >> + .flags = _gate_flags, \ >> + .common = { \ >> + .regmap = NULL, \ >> + .reg = _reg, \ >> + .lock = &sprd_gate_lock, \ >> + .hw.init = CLK_HW_INIT(_name, \ >> + _parent, \ >> + &sprd_gate_ops, \ >> + _flags), \ >> + } \ >> + } >> + >> +static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw) >> +{ >> + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); >> + >> + return container_of(common, struct sprd_gate, common); >> +} >> + >> +void sprd_gate_helper_disable(struct sprd_clk_common *common, u32 gate); >> +int sprd_gate_helper_enable(struct sprd_clk_common *common, u32 gate); >> +int sprd_gate_helper_is_enabled(struct sprd_clk_common *common, u32 >> gate); >> + >> +extern const struct clk_ops sprd_gate_ops; >> +extern spinlock_t sprd_gate_lock; >> + >> +#endif /* _SPRD_GATE_H_ */ >> > > -- > Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 04/11] clk: sprd: add gate clock support @ 2017-11-03 12:12 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-03 12:12 UTC (permalink / raw) To: linux-arm-kernel Hi Julien, On 3 November 2017 at 01:45, Julien Thierry <julien.thierry@arm.com> wrote: > Hi, > > > On 02/11/17 06:56, Chunyan Zhang wrote: >> >> Some clocks on the Spreadtrum's SoCs are just simple gates. Add >> support for those clocks. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Makefile | 1 + >> drivers/clk/sprd/gate.c | 106 >> ++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/clk/sprd/gate.h | 54 +++++++++++++++++++++++ >> 3 files changed, 161 insertions(+) >> create mode 100644 drivers/clk/sprd/gate.c >> create mode 100644 drivers/clk/sprd/gate.h >> >> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >> index 74f4b80..8cd5592 100644 >> --- a/drivers/clk/sprd/Makefile >> +++ b/drivers/clk/sprd/Makefile >> @@ -1,3 +1,4 @@ >> obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >> clk-sprd-y += common.o >> +clk-sprd-y += gate.o >> diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c >> new file mode 100644 >> index 0000000..831ef81 >> --- /dev/null >> +++ b/drivers/clk/sprd/gate.c >> @@ -0,0 +1,106 @@ >> +/* >> + * Spreadtrum gate clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#include <linux/clk-provider.h> >> +#include <linux/regmap.h> >> + >> +#include "gate.h" >> + >> +DEFINE_SPINLOCK(sprd_gate_lock); >> +EXPORT_SYMBOL_GPL(sprd_gate_lock); >> + >> +static void sprd_gate_endisable(const struct sprd_gate *sg, u32 en) >> +{ >> + const struct sprd_clk_common *common = &sg->common; >> + unsigned long flags = 0; >> + unsigned int reg; >> + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; >> + >> + set ^= en; >> + >> + spin_lock_irqsave(common->lock, flags); >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + >> + if (set) >> + reg |= sg->op_bit; >> + else >> + reg &= ~sg->op_bit; >> + >> + sprd_regmap_write(common->regmap, common->reg, reg); >> + >> + spin_unlock_irqrestore(common->lock, flags); >> +} >> + >> +static void clk_sc_gate_endisable(const struct sprd_gate *sg, u32 en) >> +{ >> + const struct sprd_clk_common *common = &sg->common; >> + unsigned long flags = 0; >> + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; >> + unsigned int offset; >> + >> + set ^= en; >> + >> + /* >> + * Each set/clear gate clock has three registers: >> + * common->reg - base register >> + * common->reg + offset - set register >> + * common->reg + 2 * offset - clear register >> + */ >> + offset = set ? sg->sc_offset : sg->sc_offset * 2; >> + >> + spin_lock_irqsave(common->lock, flags); >> + sprd_regmap_write(common->regmap, common->reg + offset, >> sg->op_bit); >> + spin_unlock_irqrestore(common->lock, flags); >> +} >> + >> +static void sprd_gate_disable(struct clk_hw *hw) >> +{ >> + struct sprd_gate *sg = hw_to_sprd_gate(hw); >> + >> + if (sg->sc_offset) >> + clk_sc_gate_endisable(sg, 0); >> + else >> + sprd_gate_endisable(sg, 0); >> +} >> + >> +static int sprd_gate_enable(struct clk_hw *hw) >> +{ >> + struct sprd_gate *sg = hw_to_sprd_gate(hw); >> + >> + if (sg->sc_offset) >> + clk_sc_gate_endisable(sg, 1); >> + else >> + sprd_gate_endisable(sg, 1); >> + >> + return 0; >> +} >> + >> +static int sprd_gate_is_enabled(struct clk_hw *hw) >> +{ >> + struct sprd_gate *sg = hw_to_sprd_gate(hw); >> + struct sprd_clk_common *common = &sg->common; >> + unsigned int reg; >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + >> + if (sg->flags & CLK_GATE_SET_TO_DISABLE) >> + reg ^= sg->op_bit; >> + >> + reg &= sg->op_bit; >> + >> + return reg ? 1 : 0; >> +} >> + >> +const struct clk_ops sprd_gate_ops = { >> + .disable = sprd_gate_disable, >> + .enable = sprd_gate_enable, >> + .is_enabled = sprd_gate_is_enabled, >> +}; >> +EXPORT_SYMBOL_GPL(sprd_gate_ops); > > > I think it would be better to have a set of ops for each mode, > sprd_gate_ops and sprd_sc_gate_ops rather than have each function decide > whether it should use set/clear registers or the base registers. > > So you can have a macro SPRD_GATE_CLK that doesn't take an sc_offet and > selects the sprd_gate_ops and another one that SPRD_SC_GATE_CLK using > sprd_sc_gate_ops that takes the sc_offset as parameter. > That makes more sense, I will revise in the next version. > Also, I feel keeping enable/disable function separate would be nicer instead > of having "endisable" functions. To avoid duplicate code, I prefer to keep the enable and disable functions together, but I agree that 'endisable' is indeed not good name for the function, I will revise the name to 'toggle' which I saw qcom clk drivers use, it might make more sense. Thanks, Chunyan > > Cheers, > > >> diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h >> new file mode 100644 >> index 0000000..5aeb53c >> --- /dev/null >> +++ b/drivers/clk/sprd/gate.h >> @@ -0,0 +1,54 @@ >> +/* >> + * Spreadtrum gate clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#ifndef _SPRD_GATE_H_ >> +#define _SPRD_GATE_H_ >> + >> +#include "common.h" >> + >> +struct sprd_gate { >> + u32 op_bit; >> + u16 flags; >> + u16 sc_offset; >> + >> + struct sprd_clk_common common; >> +}; >> + >> +#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \ >> + _op_bit, _flags, _gate_flags) \ >> + struct sprd_gate _struct = { \ >> + .op_bit = _op_bit, \ >> + .sc_offset = _sc_offset, \ >> + .flags = _gate_flags, \ >> + .common = { \ >> + .regmap = NULL, \ >> + .reg = _reg, \ >> + .lock = &sprd_gate_lock, \ >> + .hw.init = CLK_HW_INIT(_name, \ >> + _parent, \ >> + &sprd_gate_ops, \ >> + _flags), \ >> + } \ >> + } >> + >> +static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw) >> +{ >> + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); >> + >> + return container_of(common, struct sprd_gate, common); >> +} >> + >> +void sprd_gate_helper_disable(struct sprd_clk_common *common, u32 gate); >> +int sprd_gate_helper_enable(struct sprd_clk_common *common, u32 gate); >> +int sprd_gate_helper_is_enabled(struct sprd_clk_common *common, u32 >> gate); >> + >> +extern const struct clk_ops sprd_gate_ops; >> +extern spinlock_t sprd_gate_lock; >> + >> +#endif /* _SPRD_GATE_H_ */ >> > > -- > Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 04/11] clk: sprd: add gate clock support @ 2017-11-03 12:12 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-03 12:12 UTC (permalink / raw) To: Julien Thierry Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai Hi Julien, On 3 November 2017 at 01:45, Julien Thierry <julien.thierry@arm.com> wrote: > Hi, > > > On 02/11/17 06:56, Chunyan Zhang wrote: >> >> Some clocks on the Spreadtrum's SoCs are just simple gates. Add >> support for those clocks. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Makefile | 1 + >> drivers/clk/sprd/gate.c | 106 >> ++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/clk/sprd/gate.h | 54 +++++++++++++++++++++++ >> 3 files changed, 161 insertions(+) >> create mode 100644 drivers/clk/sprd/gate.c >> create mode 100644 drivers/clk/sprd/gate.h >> >> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >> index 74f4b80..8cd5592 100644 >> --- a/drivers/clk/sprd/Makefile >> +++ b/drivers/clk/sprd/Makefile >> @@ -1,3 +1,4 @@ >> obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >> clk-sprd-y += common.o >> +clk-sprd-y += gate.o >> diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c >> new file mode 100644 >> index 0000000..831ef81 >> --- /dev/null >> +++ b/drivers/clk/sprd/gate.c >> @@ -0,0 +1,106 @@ >> +/* >> + * Spreadtrum gate clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#include <linux/clk-provider.h> >> +#include <linux/regmap.h> >> + >> +#include "gate.h" >> + >> +DEFINE_SPINLOCK(sprd_gate_lock); >> +EXPORT_SYMBOL_GPL(sprd_gate_lock); >> + >> +static void sprd_gate_endisable(const struct sprd_gate *sg, u32 en) >> +{ >> + const struct sprd_clk_common *common = &sg->common; >> + unsigned long flags = 0; >> + unsigned int reg; >> + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; >> + >> + set ^= en; >> + >> + spin_lock_irqsave(common->lock, flags); >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + >> + if (set) >> + reg |= sg->op_bit; >> + else >> + reg &= ~sg->op_bit; >> + >> + sprd_regmap_write(common->regmap, common->reg, reg); >> + >> + spin_unlock_irqrestore(common->lock, flags); >> +} >> + >> +static void clk_sc_gate_endisable(const struct sprd_gate *sg, u32 en) >> +{ >> + const struct sprd_clk_common *common = &sg->common; >> + unsigned long flags = 0; >> + int set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; >> + unsigned int offset; >> + >> + set ^= en; >> + >> + /* >> + * Each set/clear gate clock has three registers: >> + * common->reg - base register >> + * common->reg + offset - set register >> + * common->reg + 2 * offset - clear register >> + */ >> + offset = set ? sg->sc_offset : sg->sc_offset * 2; >> + >> + spin_lock_irqsave(common->lock, flags); >> + sprd_regmap_write(common->regmap, common->reg + offset, >> sg->op_bit); >> + spin_unlock_irqrestore(common->lock, flags); >> +} >> + >> +static void sprd_gate_disable(struct clk_hw *hw) >> +{ >> + struct sprd_gate *sg = hw_to_sprd_gate(hw); >> + >> + if (sg->sc_offset) >> + clk_sc_gate_endisable(sg, 0); >> + else >> + sprd_gate_endisable(sg, 0); >> +} >> + >> +static int sprd_gate_enable(struct clk_hw *hw) >> +{ >> + struct sprd_gate *sg = hw_to_sprd_gate(hw); >> + >> + if (sg->sc_offset) >> + clk_sc_gate_endisable(sg, 1); >> + else >> + sprd_gate_endisable(sg, 1); >> + >> + return 0; >> +} >> + >> +static int sprd_gate_is_enabled(struct clk_hw *hw) >> +{ >> + struct sprd_gate *sg = hw_to_sprd_gate(hw); >> + struct sprd_clk_common *common = &sg->common; >> + unsigned int reg; >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + >> + if (sg->flags & CLK_GATE_SET_TO_DISABLE) >> + reg ^= sg->op_bit; >> + >> + reg &= sg->op_bit; >> + >> + return reg ? 1 : 0; >> +} >> + >> +const struct clk_ops sprd_gate_ops = { >> + .disable = sprd_gate_disable, >> + .enable = sprd_gate_enable, >> + .is_enabled = sprd_gate_is_enabled, >> +}; >> +EXPORT_SYMBOL_GPL(sprd_gate_ops); > > > I think it would be better to have a set of ops for each mode, > sprd_gate_ops and sprd_sc_gate_ops rather than have each function decide > whether it should use set/clear registers or the base registers. > > So you can have a macro SPRD_GATE_CLK that doesn't take an sc_offet and > selects the sprd_gate_ops and another one that SPRD_SC_GATE_CLK using > sprd_sc_gate_ops that takes the sc_offset as parameter. > That makes more sense, I will revise in the next version. > Also, I feel keeping enable/disable function separate would be nicer instead > of having "endisable" functions. To avoid duplicate code, I prefer to keep the enable and disable functions together, but I agree that 'endisable' is indeed not good name for the function, I will revise the name to 'toggle' which I saw qcom clk drivers use, it might make more sense. Thanks, Chunyan > > Cheers, > > >> diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h >> new file mode 100644 >> index 0000000..5aeb53c >> --- /dev/null >> +++ b/drivers/clk/sprd/gate.h >> @@ -0,0 +1,54 @@ >> +/* >> + * Spreadtrum gate clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#ifndef _SPRD_GATE_H_ >> +#define _SPRD_GATE_H_ >> + >> +#include "common.h" >> + >> +struct sprd_gate { >> + u32 op_bit; >> + u16 flags; >> + u16 sc_offset; >> + >> + struct sprd_clk_common common; >> +}; >> + >> +#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \ >> + _op_bit, _flags, _gate_flags) \ >> + struct sprd_gate _struct = { \ >> + .op_bit = _op_bit, \ >> + .sc_offset = _sc_offset, \ >> + .flags = _gate_flags, \ >> + .common = { \ >> + .regmap = NULL, \ >> + .reg = _reg, \ >> + .lock = &sprd_gate_lock, \ >> + .hw.init = CLK_HW_INIT(_name, \ >> + _parent, \ >> + &sprd_gate_ops, \ >> + _flags), \ >> + } \ >> + } >> + >> +static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw) >> +{ >> + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); >> + >> + return container_of(common, struct sprd_gate, common); >> +} >> + >> +void sprd_gate_helper_disable(struct sprd_clk_common *common, u32 gate); >> +int sprd_gate_helper_enable(struct sprd_clk_common *common, u32 gate); >> +int sprd_gate_helper_is_enabled(struct sprd_clk_common *common, u32 >> gate); >> + >> +extern const struct clk_ops sprd_gate_ops; >> +extern spinlock_t sprd_gate_lock; >> + >> +#endif /* _SPRD_GATE_H_ */ >> > > -- > Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 05/11] clk: sprd: add mux clock support 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This patch adds clock multiplexor support for Spreadtrum platforms, the mux clocks also can be found in sprd composite clocks, so provides two helpers that can be reused later on. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/mux.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 drivers/clk/sprd/mux.c create mode 100644 drivers/clk/sprd/mux.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 8cd5592..cee36b5 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o clk-sprd-y += common.o clk-sprd-y += gate.o +clk-sprd-y += mux.o diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c new file mode 100644 index 0000000..5a344e0 --- /dev/null +++ b/drivers/clk/sprd/mux.c @@ -0,0 +1,89 @@ +/* + * Spreadtrum multiplexer clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> + +#include "mux.h" + +DEFINE_SPINLOCK(sprd_mux_lock); +EXPORT_SYMBOL_GPL(sprd_mux_lock); + +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux) +{ + unsigned int reg; + u8 parent; + int num_parents; + int i; + + sprd_regmap_read(common->regmap, common->reg, ®); + parent = reg >> mux->shift; + parent &= (1 << mux->width) - 1; + + if (mux->table) { + num_parents = clk_hw_get_num_parents(&common->hw); + + for (i = 0; i < num_parents; i++) + if (parent == mux->table[i] || + (i < (num_parents - 1) && parent > mux->table[i] && + parent < mux->table[i + 1])) + return i; + if (i == num_parents) + return i - 1; + } + + return parent; +} +EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent); + +static u8 sprd_mux_get_parent(struct clk_hw *hw) +{ + struct sprd_mux *cm = hw_to_sprd_mux(hw); + + return sprd_mux_helper_get_parent(&cm->common, &cm->mux); +} + +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux, + u8 index) +{ + unsigned long flags = 0; + unsigned int reg; + + if (mux->table) + index = mux->table[index]; + + spin_lock_irqsave(common->lock, flags); + + sprd_regmap_read(common->regmap, common->reg, ®); + reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift); + sprd_regmap_write(common->regmap, common->reg, + reg | (index << mux->shift)); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent); + +static int sprd_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct sprd_mux *cm = hw_to_sprd_mux(hw); + + return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index); +} + +const struct clk_ops sprd_mux_ops = { + .get_parent = sprd_mux_get_parent, + .set_parent = sprd_mux_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; +EXPORT_SYMBOL_GPL(sprd_mux_ops); diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h new file mode 100644 index 0000000..148ca8c --- /dev/null +++ b/drivers/clk/sprd/mux.h @@ -0,0 +1,65 @@ +/* + * Spreadtrum multiplexer clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_MUX_H_ +#define _SPRD_MUX_H_ + +#include "common.h" + +struct sprd_mux_internal { + u8 shift; + u8 width; + const u8 *table; +}; + +struct sprd_mux { + struct sprd_mux_internal mux; + struct sprd_clk_common common; +}; + +#define _SPRD_MUX_CLK(_shift, _width, _table) \ + { \ + .shift = _shift, \ + .width = _width, \ + .table = _table, \ + } + +#define SPRD_MUX_CLK(_struct, _name, _parents, _table, \ + _reg, _shift, _width, \ + _flags) \ + struct sprd_mux _struct = { \ + .mux = _SPRD_MUX_CLK(_shift, _width, _table), \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_mux_lock, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parents, \ + &sprd_mux_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_mux, common); +} + +extern const struct clk_ops sprd_mux_ops; +extern spinlock_t sprd_mux_lock; + +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux); +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux, + u8 index); + +#endif /* _SPRD_MUX_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 05/11] clk: sprd: add mux clock support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel This patch adds clock multiplexor support for Spreadtrum platforms, the mux clocks also can be found in sprd composite clocks, so provides two helpers that can be reused later on. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/mux.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 drivers/clk/sprd/mux.c create mode 100644 drivers/clk/sprd/mux.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 8cd5592..cee36b5 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o clk-sprd-y += common.o clk-sprd-y += gate.o +clk-sprd-y += mux.o diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c new file mode 100644 index 0000000..5a344e0 --- /dev/null +++ b/drivers/clk/sprd/mux.c @@ -0,0 +1,89 @@ +/* + * Spreadtrum multiplexer clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> + +#include "mux.h" + +DEFINE_SPINLOCK(sprd_mux_lock); +EXPORT_SYMBOL_GPL(sprd_mux_lock); + +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux) +{ + unsigned int reg; + u8 parent; + int num_parents; + int i; + + sprd_regmap_read(common->regmap, common->reg, ®); + parent = reg >> mux->shift; + parent &= (1 << mux->width) - 1; + + if (mux->table) { + num_parents = clk_hw_get_num_parents(&common->hw); + + for (i = 0; i < num_parents; i++) + if (parent == mux->table[i] || + (i < (num_parents - 1) && parent > mux->table[i] && + parent < mux->table[i + 1])) + return i; + if (i == num_parents) + return i - 1; + } + + return parent; +} +EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent); + +static u8 sprd_mux_get_parent(struct clk_hw *hw) +{ + struct sprd_mux *cm = hw_to_sprd_mux(hw); + + return sprd_mux_helper_get_parent(&cm->common, &cm->mux); +} + +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux, + u8 index) +{ + unsigned long flags = 0; + unsigned int reg; + + if (mux->table) + index = mux->table[index]; + + spin_lock_irqsave(common->lock, flags); + + sprd_regmap_read(common->regmap, common->reg, ®); + reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift); + sprd_regmap_write(common->regmap, common->reg, + reg | (index << mux->shift)); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent); + +static int sprd_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct sprd_mux *cm = hw_to_sprd_mux(hw); + + return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index); +} + +const struct clk_ops sprd_mux_ops = { + .get_parent = sprd_mux_get_parent, + .set_parent = sprd_mux_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; +EXPORT_SYMBOL_GPL(sprd_mux_ops); diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h new file mode 100644 index 0000000..148ca8c --- /dev/null +++ b/drivers/clk/sprd/mux.h @@ -0,0 +1,65 @@ +/* + * Spreadtrum multiplexer clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_MUX_H_ +#define _SPRD_MUX_H_ + +#include "common.h" + +struct sprd_mux_internal { + u8 shift; + u8 width; + const u8 *table; +}; + +struct sprd_mux { + struct sprd_mux_internal mux; + struct sprd_clk_common common; +}; + +#define _SPRD_MUX_CLK(_shift, _width, _table) \ + { \ + .shift = _shift, \ + .width = _width, \ + .table = _table, \ + } + +#define SPRD_MUX_CLK(_struct, _name, _parents, _table, \ + _reg, _shift, _width, \ + _flags) \ + struct sprd_mux _struct = { \ + .mux = _SPRD_MUX_CLK(_shift, _width, _table), \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_mux_lock, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parents, \ + &sprd_mux_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_mux, common); +} + +extern const struct clk_ops sprd_mux_ops; +extern spinlock_t sprd_mux_lock; + +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux); +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux, + u8 index); + +#endif /* _SPRD_MUX_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 05/11] clk: sprd: add mux clock support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This patch adds clock multiplexor support for Spreadtrum platforms, the mux clocks also can be found in sprd composite clocks, so provides two helpers that can be reused later on. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/mux.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 drivers/clk/sprd/mux.c create mode 100644 drivers/clk/sprd/mux.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 8cd5592..cee36b5 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o clk-sprd-y += common.o clk-sprd-y += gate.o +clk-sprd-y += mux.o diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c new file mode 100644 index 0000000..5a344e0 --- /dev/null +++ b/drivers/clk/sprd/mux.c @@ -0,0 +1,89 @@ +/* + * Spreadtrum multiplexer clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> + +#include "mux.h" + +DEFINE_SPINLOCK(sprd_mux_lock); +EXPORT_SYMBOL_GPL(sprd_mux_lock); + +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux) +{ + unsigned int reg; + u8 parent; + int num_parents; + int i; + + sprd_regmap_read(common->regmap, common->reg, ®); + parent = reg >> mux->shift; + parent &= (1 << mux->width) - 1; + + if (mux->table) { + num_parents = clk_hw_get_num_parents(&common->hw); + + for (i = 0; i < num_parents; i++) + if (parent == mux->table[i] || + (i < (num_parents - 1) && parent > mux->table[i] && + parent < mux->table[i + 1])) + return i; + if (i == num_parents) + return i - 1; + } + + return parent; +} +EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent); + +static u8 sprd_mux_get_parent(struct clk_hw *hw) +{ + struct sprd_mux *cm = hw_to_sprd_mux(hw); + + return sprd_mux_helper_get_parent(&cm->common, &cm->mux); +} + +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux, + u8 index) +{ + unsigned long flags = 0; + unsigned int reg; + + if (mux->table) + index = mux->table[index]; + + spin_lock_irqsave(common->lock, flags); + + sprd_regmap_read(common->regmap, common->reg, ®); + reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift); + sprd_regmap_write(common->regmap, common->reg, + reg | (index << mux->shift)); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent); + +static int sprd_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct sprd_mux *cm = hw_to_sprd_mux(hw); + + return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index); +} + +const struct clk_ops sprd_mux_ops = { + .get_parent = sprd_mux_get_parent, + .set_parent = sprd_mux_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; +EXPORT_SYMBOL_GPL(sprd_mux_ops); diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h new file mode 100644 index 0000000..148ca8c --- /dev/null +++ b/drivers/clk/sprd/mux.h @@ -0,0 +1,65 @@ +/* + * Spreadtrum multiplexer clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_MUX_H_ +#define _SPRD_MUX_H_ + +#include "common.h" + +struct sprd_mux_internal { + u8 shift; + u8 width; + const u8 *table; +}; + +struct sprd_mux { + struct sprd_mux_internal mux; + struct sprd_clk_common common; +}; + +#define _SPRD_MUX_CLK(_shift, _width, _table) \ + { \ + .shift = _shift, \ + .width = _width, \ + .table = _table, \ + } + +#define SPRD_MUX_CLK(_struct, _name, _parents, _table, \ + _reg, _shift, _width, \ + _flags) \ + struct sprd_mux _struct = { \ + .mux = _SPRD_MUX_CLK(_shift, _width, _table), \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_mux_lock, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parents, \ + &sprd_mux_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_mux, common); +} + +extern const struct clk_ops sprd_mux_ops; +extern spinlock_t sprd_mux_lock; + +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux); +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, + const struct sprd_mux_internal *mux, + u8 index); + +#endif /* _SPRD_MUX_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH V3 05/11] clk: sprd: add mux clock support 2017-11-02 6:56 ` Chunyan Zhang @ 2017-11-02 18:11 ` Julien Thierry -1 siblings, 0 replies; 68+ messages in thread From: Julien Thierry @ 2017-11-02 18:11 UTC (permalink / raw) To: Chunyan Zhang, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Hi, On 02/11/17 06:56, Chunyan Zhang wrote: > This patch adds clock multiplexor support for Spreadtrum platforms, > the mux clocks also can be found in sprd composite clocks, so > provides two helpers that can be reused later on. > > Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > --- > drivers/clk/sprd/Makefile | 1 + > drivers/clk/sprd/mux.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ > drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ > 3 files changed, 155 insertions(+) > create mode 100644 drivers/clk/sprd/mux.c > create mode 100644 drivers/clk/sprd/mux.h > > diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile > index 8cd5592..cee36b5 100644 > --- a/drivers/clk/sprd/Makefile > +++ b/drivers/clk/sprd/Makefile > @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o > > clk-sprd-y += common.o > clk-sprd-y += gate.o > +clk-sprd-y += mux.o > diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c > new file mode 100644 > index 0000000..5a344e0 > --- /dev/null > +++ b/drivers/clk/sprd/mux.c > @@ -0,0 +1,89 @@ > +/* > + * Spreadtrum multiplexer clock driver > + * > + * Copyright (C) 2017 Spreadtrum, Inc. > + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#include <linux/clk.h> > +#include <linux/clk-provider.h> > +#include <linux/regmap.h> > + > +#include "mux.h" > + > +DEFINE_SPINLOCK(sprd_mux_lock); > +EXPORT_SYMBOL_GPL(sprd_mux_lock); > + > +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, > + const struct sprd_mux_internal *mux) > +{ > + unsigned int reg; > + u8 parent; > + int num_parents; > + int i; > + > + sprd_regmap_read(common->regmap, common->reg, ®); > + parent = reg >> mux->shift; > + parent &= (1 << mux->width) - 1; > + > + if (mux->table) { > + num_parents = clk_hw_get_num_parents(&common->hw); > + > + for (i = 0; i < num_parents; i++) > + if (parent == mux->table[i] || > + (i < (num_parents - 1) && parent > mux->table[i] && > + parent < mux->table[i + 1])) > + return i; > + if (i == num_parents) > + return i - 1; The if branch is not necessary since you only get there when the loop has finished, so the condition is always true. And the loop can be simplified to: for (i = 0; i < num_parents - 1; i++) if (parent >= mux->table[i] && parent < mux->table[i + 1]) return i; return num_parents; > + } > + > + return parent; > +} > +EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent); > + > +static u8 sprd_mux_get_parent(struct clk_hw *hw) > +{ > + struct sprd_mux *cm = hw_to_sprd_mux(hw); > + > + return sprd_mux_helper_get_parent(&cm->common, &cm->mux); > +} > + > +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, > + const struct sprd_mux_internal *mux, > + u8 index) > +{ > + unsigned long flags = 0; > + unsigned int reg; > + > + if (mux->table) > + index = mux->table[index]; > + > + spin_lock_irqsave(common->lock, flags); > + > + sprd_regmap_read(common->regmap, common->reg, ®); > + reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift); > + sprd_regmap_write(common->regmap, common->reg, > + reg | (index << mux->shift)); > + > + spin_unlock_irqrestore(common->lock, flags); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent); > + > +static int sprd_mux_set_parent(struct clk_hw *hw, u8 index) > +{ > + struct sprd_mux *cm = hw_to_sprd_mux(hw); > + > + return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index); > +} > + > +const struct clk_ops sprd_mux_ops = { > + .get_parent = sprd_mux_get_parent, > + .set_parent = sprd_mux_set_parent, > + .determine_rate = __clk_mux_determine_rate, > +}; > +EXPORT_SYMBOL_GPL(sprd_mux_ops); Same as with the other patch, I'd recommend have one set of ops for direct mux and another one for a mux using a table to map the parents. Keeping functions for both modes separate. Cheers, > diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h > new file mode 100644 > index 0000000..148ca8c > --- /dev/null > +++ b/drivers/clk/sprd/mux.h > @@ -0,0 +1,65 @@ > +/* > + * Spreadtrum multiplexer clock driver > + * > + * Copyright (C) 2017 Spreadtrum, Inc. > + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#ifndef _SPRD_MUX_H_ > +#define _SPRD_MUX_H_ > + > +#include "common.h" > + > +struct sprd_mux_internal { > + u8 shift; > + u8 width; > + const u8 *table; > +}; > + > +struct sprd_mux { > + struct sprd_mux_internal mux; > + struct sprd_clk_common common; > +}; > + > +#define _SPRD_MUX_CLK(_shift, _width, _table) \ > + { \ > + .shift = _shift, \ > + .width = _width, \ > + .table = _table, \ > + } > + > +#define SPRD_MUX_CLK(_struct, _name, _parents, _table, \ > + _reg, _shift, _width, \ > + _flags) \ > + struct sprd_mux _struct = { \ > + .mux = _SPRD_MUX_CLK(_shift, _width, _table), \ > + .common = { \ > + .regmap = NULL, \ > + .reg = _reg, \ > + .lock = &sprd_mux_lock, \ > + .hw.init = CLK_HW_INIT_PARENTS(_name, \ > + _parents, \ > + &sprd_mux_ops, \ > + _flags), \ > + } \ > + } > + > +static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw) > +{ > + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); > + > + return container_of(common, struct sprd_mux, common); > +} > + > +extern const struct clk_ops sprd_mux_ops; > +extern spinlock_t sprd_mux_lock; > + > +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, > + const struct sprd_mux_internal *mux); > +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, > + const struct sprd_mux_internal *mux, > + u8 index); > + > +#endif /* _SPRD_MUX_H_ */ > -- Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 05/11] clk: sprd: add mux clock support @ 2017-11-02 18:11 ` Julien Thierry 0 siblings, 0 replies; 68+ messages in thread From: Julien Thierry @ 2017-11-02 18:11 UTC (permalink / raw) To: linux-arm-kernel Hi, On 02/11/17 06:56, Chunyan Zhang wrote: > This patch adds clock multiplexor support for Spreadtrum platforms, > the mux clocks also can be found in sprd composite clocks, so > provides two helpers that can be reused later on. > > Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > --- > drivers/clk/sprd/Makefile | 1 + > drivers/clk/sprd/mux.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ > drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ > 3 files changed, 155 insertions(+) > create mode 100644 drivers/clk/sprd/mux.c > create mode 100644 drivers/clk/sprd/mux.h > > diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile > index 8cd5592..cee36b5 100644 > --- a/drivers/clk/sprd/Makefile > +++ b/drivers/clk/sprd/Makefile > @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o > > clk-sprd-y += common.o > clk-sprd-y += gate.o > +clk-sprd-y += mux.o > diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c > new file mode 100644 > index 0000000..5a344e0 > --- /dev/null > +++ b/drivers/clk/sprd/mux.c > @@ -0,0 +1,89 @@ > +/* > + * Spreadtrum multiplexer clock driver > + * > + * Copyright (C) 2017 Spreadtrum, Inc. > + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#include <linux/clk.h> > +#include <linux/clk-provider.h> > +#include <linux/regmap.h> > + > +#include "mux.h" > + > +DEFINE_SPINLOCK(sprd_mux_lock); > +EXPORT_SYMBOL_GPL(sprd_mux_lock); > + > +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, > + const struct sprd_mux_internal *mux) > +{ > + unsigned int reg; > + u8 parent; > + int num_parents; > + int i; > + > + sprd_regmap_read(common->regmap, common->reg, ®); > + parent = reg >> mux->shift; > + parent &= (1 << mux->width) - 1; > + > + if (mux->table) { > + num_parents = clk_hw_get_num_parents(&common->hw); > + > + for (i = 0; i < num_parents; i++) > + if (parent == mux->table[i] || > + (i < (num_parents - 1) && parent > mux->table[i] && > + parent < mux->table[i + 1])) > + return i; > + if (i == num_parents) > + return i - 1; The if branch is not necessary since you only get there when the loop has finished, so the condition is always true. And the loop can be simplified to: for (i = 0; i < num_parents - 1; i++) if (parent >= mux->table[i] && parent < mux->table[i + 1]) return i; return num_parents; > + } > + > + return parent; > +} > +EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent); > + > +static u8 sprd_mux_get_parent(struct clk_hw *hw) > +{ > + struct sprd_mux *cm = hw_to_sprd_mux(hw); > + > + return sprd_mux_helper_get_parent(&cm->common, &cm->mux); > +} > + > +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, > + const struct sprd_mux_internal *mux, > + u8 index) > +{ > + unsigned long flags = 0; > + unsigned int reg; > + > + if (mux->table) > + index = mux->table[index]; > + > + spin_lock_irqsave(common->lock, flags); > + > + sprd_regmap_read(common->regmap, common->reg, ®); > + reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift); > + sprd_regmap_write(common->regmap, common->reg, > + reg | (index << mux->shift)); > + > + spin_unlock_irqrestore(common->lock, flags); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent); > + > +static int sprd_mux_set_parent(struct clk_hw *hw, u8 index) > +{ > + struct sprd_mux *cm = hw_to_sprd_mux(hw); > + > + return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index); > +} > + > +const struct clk_ops sprd_mux_ops = { > + .get_parent = sprd_mux_get_parent, > + .set_parent = sprd_mux_set_parent, > + .determine_rate = __clk_mux_determine_rate, > +}; > +EXPORT_SYMBOL_GPL(sprd_mux_ops); Same as with the other patch, I'd recommend have one set of ops for direct mux and another one for a mux using a table to map the parents. Keeping functions for both modes separate. Cheers, > diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h > new file mode 100644 > index 0000000..148ca8c > --- /dev/null > +++ b/drivers/clk/sprd/mux.h > @@ -0,0 +1,65 @@ > +/* > + * Spreadtrum multiplexer clock driver > + * > + * Copyright (C) 2017 Spreadtrum, Inc. > + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#ifndef _SPRD_MUX_H_ > +#define _SPRD_MUX_H_ > + > +#include "common.h" > + > +struct sprd_mux_internal { > + u8 shift; > + u8 width; > + const u8 *table; > +}; > + > +struct sprd_mux { > + struct sprd_mux_internal mux; > + struct sprd_clk_common common; > +}; > + > +#define _SPRD_MUX_CLK(_shift, _width, _table) \ > + { \ > + .shift = _shift, \ > + .width = _width, \ > + .table = _table, \ > + } > + > +#define SPRD_MUX_CLK(_struct, _name, _parents, _table, \ > + _reg, _shift, _width, \ > + _flags) \ > + struct sprd_mux _struct = { \ > + .mux = _SPRD_MUX_CLK(_shift, _width, _table), \ > + .common = { \ > + .regmap = NULL, \ > + .reg = _reg, \ > + .lock = &sprd_mux_lock, \ > + .hw.init = CLK_HW_INIT_PARENTS(_name, \ > + _parents, \ > + &sprd_mux_ops, \ > + _flags), \ > + } \ > + } > + > +static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw) > +{ > + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); > + > + return container_of(common, struct sprd_mux, common); > +} > + > +extern const struct clk_ops sprd_mux_ops; > +extern spinlock_t sprd_mux_lock; > + > +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, > + const struct sprd_mux_internal *mux); > +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, > + const struct sprd_mux_internal *mux, > + u8 index); > + > +#endif /* _SPRD_MUX_H_ */ > -- Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 05/11] clk: sprd: add mux clock support 2017-11-02 18:11 ` Julien Thierry @ 2017-11-02 18:22 ` Julien Thierry -1 siblings, 0 replies; 68+ messages in thread From: Julien Thierry @ 2017-11-02 18:22 UTC (permalink / raw) To: Chunyan Zhang, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang On 02/11/17 18:11, Julien Thierry wrote: > Hi, > > On 02/11/17 06:56, Chunyan Zhang wrote: >> This patch adds clock multiplexor support for Spreadtrum platforms, >> the mux clocks also can be found in sprd composite clocks, so >> provides two helpers that can be reused later on. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Makefile | 1 + >> drivers/clk/sprd/mux.c | 89 >> +++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ >> 3 files changed, 155 insertions(+) >> create mode 100644 drivers/clk/sprd/mux.c >> create mode 100644 drivers/clk/sprd/mux.h >> >> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >> index 8cd5592..cee36b5 100644 >> --- a/drivers/clk/sprd/Makefile >> +++ b/drivers/clk/sprd/Makefile >> @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >> clk-sprd-y += common.o >> clk-sprd-y += gate.o >> +clk-sprd-y += mux.o >> diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c >> new file mode 100644 >> index 0000000..5a344e0 >> --- /dev/null >> +++ b/drivers/clk/sprd/mux.c >> @@ -0,0 +1,89 @@ >> +/* >> + * Spreadtrum multiplexer clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#include <linux/clk.h> >> +#include <linux/clk-provider.h> >> +#include <linux/regmap.h> >> + >> +#include "mux.h" >> + >> +DEFINE_SPINLOCK(sprd_mux_lock); >> +EXPORT_SYMBOL_GPL(sprd_mux_lock); >> + >> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux) >> +{ >> + unsigned int reg; >> + u8 parent; >> + int num_parents; >> + int i; >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + parent = reg >> mux->shift; >> + parent &= (1 << mux->width) - 1; >> + >> + if (mux->table) { >> + num_parents = clk_hw_get_num_parents(&common->hw); >> + >> + for (i = 0; i < num_parents; i++) >> + if (parent == mux->table[i] || >> + (i < (num_parents - 1) && parent > mux->table[i] && >> + parent < mux->table[i + 1])) >> + return i; >> + if (i == num_parents) >> + return i - 1; > > The if branch is not necessary since you only get there when the loop > has finished, so the condition is always true. And the loop can be > simplified to: > > for (i = 0; i < num_parents - 1; i++) > if (parent >= mux->table[i] && parent < mux->table[i + 1]) > return i; > > return num_parents; Oops, meant to say "return num_parents - 1;" on that last line. -- Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 05/11] clk: sprd: add mux clock support @ 2017-11-02 18:22 ` Julien Thierry 0 siblings, 0 replies; 68+ messages in thread From: Julien Thierry @ 2017-11-02 18:22 UTC (permalink / raw) To: linux-arm-kernel On 02/11/17 18:11, Julien Thierry wrote: > Hi, > > On 02/11/17 06:56, Chunyan Zhang wrote: >> This patch adds clock multiplexor support for Spreadtrum platforms, >> the mux clocks also can be found in sprd composite clocks, so >> provides two helpers that can be reused later on. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Makefile | 1 + >> drivers/clk/sprd/mux.c | 89 >> +++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ >> 3 files changed, 155 insertions(+) >> create mode 100644 drivers/clk/sprd/mux.c >> create mode 100644 drivers/clk/sprd/mux.h >> >> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >> index 8cd5592..cee36b5 100644 >> --- a/drivers/clk/sprd/Makefile >> +++ b/drivers/clk/sprd/Makefile >> @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >> clk-sprd-y += common.o >> clk-sprd-y += gate.o >> +clk-sprd-y += mux.o >> diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c >> new file mode 100644 >> index 0000000..5a344e0 >> --- /dev/null >> +++ b/drivers/clk/sprd/mux.c >> @@ -0,0 +1,89 @@ >> +/* >> + * Spreadtrum multiplexer clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#include <linux/clk.h> >> +#include <linux/clk-provider.h> >> +#include <linux/regmap.h> >> + >> +#include "mux.h" >> + >> +DEFINE_SPINLOCK(sprd_mux_lock); >> +EXPORT_SYMBOL_GPL(sprd_mux_lock); >> + >> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux) >> +{ >> + unsigned int reg; >> + u8 parent; >> + int num_parents; >> + int i; >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + parent = reg >> mux->shift; >> + parent &= (1 << mux->width) - 1; >> + >> + if (mux->table) { >> + num_parents = clk_hw_get_num_parents(&common->hw); >> + >> + for (i = 0; i < num_parents; i++) >> + if (parent == mux->table[i] || >> + (i < (num_parents - 1) && parent > mux->table[i] && >> + parent < mux->table[i + 1])) >> + return i; >> + if (i == num_parents) >> + return i - 1; > > The if branch is not necessary since you only get there when the loop > has finished, so the condition is always true. And the loop can be > simplified to: > > for (i = 0; i < num_parents - 1; i++) > if (parent >= mux->table[i] && parent < mux->table[i + 1]) > return i; > > return num_parents; Oops, meant to say "return num_parents - 1;" on that last line. -- Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 05/11] clk: sprd: add mux clock support 2017-11-02 18:22 ` Julien Thierry (?) @ 2017-11-03 12:12 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-03 12:12 UTC (permalink / raw) To: Julien Thierry Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai On 3 November 2017 at 02:22, Julien Thierry <julien.thierry@arm.com> wrote: > > > On 02/11/17 18:11, Julien Thierry wrote: >> >> Hi, >> >> On 02/11/17 06:56, Chunyan Zhang wrote: >>> >>> This patch adds clock multiplexor support for Spreadtrum platforms, >>> the mux clocks also can be found in sprd composite clocks, so >>> provides two helpers that can be reused later on. >>> >>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >>> --- >>> drivers/clk/sprd/Makefile | 1 + >>> drivers/clk/sprd/mux.c | 89 >>> +++++++++++++++++++++++++++++++++++++++++++++++ >>> drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ >>> 3 files changed, 155 insertions(+) >>> create mode 100644 drivers/clk/sprd/mux.c >>> create mode 100644 drivers/clk/sprd/mux.h >>> >>> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >>> index 8cd5592..cee36b5 100644 >>> --- a/drivers/clk/sprd/Makefile >>> +++ b/drivers/clk/sprd/Makefile >>> @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >>> clk-sprd-y += common.o >>> clk-sprd-y += gate.o >>> +clk-sprd-y += mux.o >>> diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c >>> new file mode 100644 >>> index 0000000..5a344e0 >>> --- /dev/null >>> +++ b/drivers/clk/sprd/mux.c >>> @@ -0,0 +1,89 @@ >>> +/* >>> + * Spreadtrum multiplexer clock driver >>> + * >>> + * Copyright (C) 2017 Spreadtrum, Inc. >>> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >>> + * >>> + * SPDX-License-Identifier: GPL-2.0 >>> + */ >>> + >>> +#include <linux/clk.h> >>> +#include <linux/clk-provider.h> >>> +#include <linux/regmap.h> >>> + >>> +#include "mux.h" >>> + >>> +DEFINE_SPINLOCK(sprd_mux_lock); >>> +EXPORT_SYMBOL_GPL(sprd_mux_lock); >>> + >>> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >>> + const struct sprd_mux_internal *mux) >>> +{ >>> + unsigned int reg; >>> + u8 parent; >>> + int num_parents; >>> + int i; >>> + >>> + sprd_regmap_read(common->regmap, common->reg, ®); >>> + parent = reg >> mux->shift; >>> + parent &= (1 << mux->width) - 1; >>> + >>> + if (mux->table) { >>> + num_parents = clk_hw_get_num_parents(&common->hw); >>> + >>> + for (i = 0; i < num_parents; i++) >>> + if (parent == mux->table[i] || >>> + (i < (num_parents - 1) && parent > mux->table[i] && >>> + parent < mux->table[i + 1])) >>> + return i; >>> + if (i == num_parents) >>> + return i - 1; >> >> >> The if branch is not necessary since you only get there when the loop has >> finished, so the condition is always true. And the loop can be simplified >> to: >> >> for (i = 0; i < num_parents - 1; i++) >> if (parent >= mux->table[i] && parent < mux->table[i + 1]) >> return i; >> >> return num_parents; > > > Oops, meant to say "return num_parents - 1;" on that last line. Yes, that makes the code nicer, and thanks to your reminder, I even make it more clean by moving the check for 'mux->table' up. Thanks, Chunyan > > -- > Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 05/11] clk: sprd: add mux clock support @ 2017-11-03 12:12 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-03 12:12 UTC (permalink / raw) To: linux-arm-kernel On 3 November 2017 at 02:22, Julien Thierry <julien.thierry@arm.com> wrote: > > > On 02/11/17 18:11, Julien Thierry wrote: >> >> Hi, >> >> On 02/11/17 06:56, Chunyan Zhang wrote: >>> >>> This patch adds clock multiplexor support for Spreadtrum platforms, >>> the mux clocks also can be found in sprd composite clocks, so >>> provides two helpers that can be reused later on. >>> >>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >>> --- >>> drivers/clk/sprd/Makefile | 1 + >>> drivers/clk/sprd/mux.c | 89 >>> +++++++++++++++++++++++++++++++++++++++++++++++ >>> drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ >>> 3 files changed, 155 insertions(+) >>> create mode 100644 drivers/clk/sprd/mux.c >>> create mode 100644 drivers/clk/sprd/mux.h >>> >>> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >>> index 8cd5592..cee36b5 100644 >>> --- a/drivers/clk/sprd/Makefile >>> +++ b/drivers/clk/sprd/Makefile >>> @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >>> clk-sprd-y += common.o >>> clk-sprd-y += gate.o >>> +clk-sprd-y += mux.o >>> diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c >>> new file mode 100644 >>> index 0000000..5a344e0 >>> --- /dev/null >>> +++ b/drivers/clk/sprd/mux.c >>> @@ -0,0 +1,89 @@ >>> +/* >>> + * Spreadtrum multiplexer clock driver >>> + * >>> + * Copyright (C) 2017 Spreadtrum, Inc. >>> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >>> + * >>> + * SPDX-License-Identifier: GPL-2.0 >>> + */ >>> + >>> +#include <linux/clk.h> >>> +#include <linux/clk-provider.h> >>> +#include <linux/regmap.h> >>> + >>> +#include "mux.h" >>> + >>> +DEFINE_SPINLOCK(sprd_mux_lock); >>> +EXPORT_SYMBOL_GPL(sprd_mux_lock); >>> + >>> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >>> + const struct sprd_mux_internal *mux) >>> +{ >>> + unsigned int reg; >>> + u8 parent; >>> + int num_parents; >>> + int i; >>> + >>> + sprd_regmap_read(common->regmap, common->reg, ®); >>> + parent = reg >> mux->shift; >>> + parent &= (1 << mux->width) - 1; >>> + >>> + if (mux->table) { >>> + num_parents = clk_hw_get_num_parents(&common->hw); >>> + >>> + for (i = 0; i < num_parents; i++) >>> + if (parent == mux->table[i] || >>> + (i < (num_parents - 1) && parent > mux->table[i] && >>> + parent < mux->table[i + 1])) >>> + return i; >>> + if (i == num_parents) >>> + return i - 1; >> >> >> The if branch is not necessary since you only get there when the loop has >> finished, so the condition is always true. And the loop can be simplified >> to: >> >> for (i = 0; i < num_parents - 1; i++) >> if (parent >= mux->table[i] && parent < mux->table[i + 1]) >> return i; >> >> return num_parents; > > > Oops, meant to say "return num_parents - 1;" on that last line. Yes, that makes the code nicer, and thanks to your reminder, I even make it more clean by moving the check for 'mux->table' up. Thanks, Chunyan > > -- > Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 05/11] clk: sprd: add mux clock support @ 2017-11-03 12:12 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-03 12:12 UTC (permalink / raw) To: Julien Thierry Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai On 3 November 2017 at 02:22, Julien Thierry <julien.thierry@arm.com> wrote: > > > On 02/11/17 18:11, Julien Thierry wrote: >> >> Hi, >> >> On 02/11/17 06:56, Chunyan Zhang wrote: >>> >>> This patch adds clock multiplexor support for Spreadtrum platforms, >>> the mux clocks also can be found in sprd composite clocks, so >>> provides two helpers that can be reused later on. >>> >>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >>> --- >>> drivers/clk/sprd/Makefile | 1 + >>> drivers/clk/sprd/mux.c | 89 >>> +++++++++++++++++++++++++++++++++++++++++++++++ >>> drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ >>> 3 files changed, 155 insertions(+) >>> create mode 100644 drivers/clk/sprd/mux.c >>> create mode 100644 drivers/clk/sprd/mux.h >>> >>> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >>> index 8cd5592..cee36b5 100644 >>> --- a/drivers/clk/sprd/Makefile >>> +++ b/drivers/clk/sprd/Makefile >>> @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >>> clk-sprd-y += common.o >>> clk-sprd-y += gate.o >>> +clk-sprd-y += mux.o >>> diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c >>> new file mode 100644 >>> index 0000000..5a344e0 >>> --- /dev/null >>> +++ b/drivers/clk/sprd/mux.c >>> @@ -0,0 +1,89 @@ >>> +/* >>> + * Spreadtrum multiplexer clock driver >>> + * >>> + * Copyright (C) 2017 Spreadtrum, Inc. >>> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >>> + * >>> + * SPDX-License-Identifier: GPL-2.0 >>> + */ >>> + >>> +#include <linux/clk.h> >>> +#include <linux/clk-provider.h> >>> +#include <linux/regmap.h> >>> + >>> +#include "mux.h" >>> + >>> +DEFINE_SPINLOCK(sprd_mux_lock); >>> +EXPORT_SYMBOL_GPL(sprd_mux_lock); >>> + >>> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >>> + const struct sprd_mux_internal *mux) >>> +{ >>> + unsigned int reg; >>> + u8 parent; >>> + int num_parents; >>> + int i; >>> + >>> + sprd_regmap_read(common->regmap, common->reg, ®); >>> + parent = reg >> mux->shift; >>> + parent &= (1 << mux->width) - 1; >>> + >>> + if (mux->table) { >>> + num_parents = clk_hw_get_num_parents(&common->hw); >>> + >>> + for (i = 0; i < num_parents; i++) >>> + if (parent == mux->table[i] || >>> + (i < (num_parents - 1) && parent > mux->table[i] && >>> + parent < mux->table[i + 1])) >>> + return i; >>> + if (i == num_parents) >>> + return i - 1; >> >> >> The if branch is not necessary since you only get there when the loop has >> finished, so the condition is always true. And the loop can be simplified >> to: >> >> for (i = 0; i < num_parents - 1; i++) >> if (parent >= mux->table[i] && parent < mux->table[i + 1]) >> return i; >> >> return num_parents; > > > Oops, meant to say "return num_parents - 1;" on that last line. Yes, that makes the code nicer, and thanks to your reminder, I even make it more clean by moving the check for 'mux->table' up. Thanks, Chunyan > > -- > Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 05/11] clk: sprd: add mux clock support 2017-11-02 18:11 ` Julien Thierry (?) @ 2017-11-03 12:12 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-03 12:12 UTC (permalink / raw) To: Julien Thierry Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai Hi Julien, On 3 November 2017 at 02:11, Julien Thierry <julien.thierry@arm.com> wrote: > Hi, > > > On 02/11/17 06:56, Chunyan Zhang wrote: >> >> This patch adds clock multiplexor support for Spreadtrum platforms, >> the mux clocks also can be found in sprd composite clocks, so >> provides two helpers that can be reused later on. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Makefile | 1 + >> drivers/clk/sprd/mux.c | 89 >> +++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ >> 3 files changed, 155 insertions(+) >> create mode 100644 drivers/clk/sprd/mux.c >> create mode 100644 drivers/clk/sprd/mux.h >> >> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >> index 8cd5592..cee36b5 100644 >> --- a/drivers/clk/sprd/Makefile >> +++ b/drivers/clk/sprd/Makefile >> @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >> clk-sprd-y += common.o >> clk-sprd-y += gate.o >> +clk-sprd-y += mux.o >> diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c >> new file mode 100644 >> index 0000000..5a344e0 >> --- /dev/null >> +++ b/drivers/clk/sprd/mux.c >> @@ -0,0 +1,89 @@ >> +/* >> + * Spreadtrum multiplexer clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#include <linux/clk.h> >> +#include <linux/clk-provider.h> >> +#include <linux/regmap.h> >> + >> +#include "mux.h" >> + >> +DEFINE_SPINLOCK(sprd_mux_lock); >> +EXPORT_SYMBOL_GPL(sprd_mux_lock); >> + >> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux) >> +{ >> + unsigned int reg; >> + u8 parent; >> + int num_parents; >> + int i; >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + parent = reg >> mux->shift; >> + parent &= (1 << mux->width) - 1; >> + >> + if (mux->table) { >> + num_parents = clk_hw_get_num_parents(&common->hw); >> + >> + for (i = 0; i < num_parents; i++) >> + if (parent == mux->table[i] || >> + (i < (num_parents - 1) && parent > >> mux->table[i] && >> + parent < mux->table[i + 1])) >> + return i; >> + if (i == num_parents) >> + return i - 1; > > > The if branch is not necessary since you only get there when the loop has > finished, so the condition is always true. And the loop can be simplified > to: > > for (i = 0; i < num_parents - 1; i++) > if (parent >= mux->table[i] && parent < mux->table[i + 1]) > return i; > > return num_parents; > > > >> + } >> + >> + return parent; >> +} >> +EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent); >> + >> +static u8 sprd_mux_get_parent(struct clk_hw *hw) >> +{ >> + struct sprd_mux *cm = hw_to_sprd_mux(hw); >> + >> + return sprd_mux_helper_get_parent(&cm->common, &cm->mux); >> +} >> + >> +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux, >> + u8 index) >> +{ >> + unsigned long flags = 0; >> + unsigned int reg; >> + >> + if (mux->table) >> + index = mux->table[index]; >> + >> + spin_lock_irqsave(common->lock, flags); >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift); >> + sprd_regmap_write(common->regmap, common->reg, >> + reg | (index << mux->shift)); >> + >> + spin_unlock_irqrestore(common->lock, flags); >> + >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent); >> + >> +static int sprd_mux_set_parent(struct clk_hw *hw, u8 index) >> +{ >> + struct sprd_mux *cm = hw_to_sprd_mux(hw); >> + >> + return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index); >> +} >> + >> +const struct clk_ops sprd_mux_ops = { >> + .get_parent = sprd_mux_get_parent, >> + .set_parent = sprd_mux_set_parent, >> + .determine_rate = __clk_mux_determine_rate, >> +}; >> +EXPORT_SYMBOL_GPL(sprd_mux_ops); > > > Same as with the other patch, I'd recommend have one set of ops for direct > mux and another one for a mux using a table to map the parents. Keeping > functions for both modes separate. > I might prefer to keep them together, since separating them will increase many lines of code for maintaining :) And will export double of these functions, not only for mux driver but also for composite driver. And I think the name like "sprd_mux_helper_set_parent_table" is a little long. Thanks, Chunyan > Cheers, > > >> diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h >> new file mode 100644 >> index 0000000..148ca8c >> --- /dev/null >> +++ b/drivers/clk/sprd/mux.h >> @@ -0,0 +1,65 @@ >> +/* >> + * Spreadtrum multiplexer clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#ifndef _SPRD_MUX_H_ >> +#define _SPRD_MUX_H_ >> + >> +#include "common.h" >> + >> +struct sprd_mux_internal { >> + u8 shift; >> + u8 width; >> + const u8 *table; >> +}; >> + >> +struct sprd_mux { >> + struct sprd_mux_internal mux; >> + struct sprd_clk_common common; >> +}; >> + >> +#define _SPRD_MUX_CLK(_shift, _width, _table) \ >> + { \ >> + .shift = _shift, \ >> + .width = _width, \ >> + .table = _table, \ >> + } >> + >> +#define SPRD_MUX_CLK(_struct, _name, _parents, _table, \ >> + _reg, _shift, _width, \ >> + _flags) \ >> + struct sprd_mux _struct = { \ >> + .mux = _SPRD_MUX_CLK(_shift, _width, _table), \ >> + .common = { \ >> + .regmap = NULL, \ >> + .reg = _reg, \ >> + .lock = &sprd_mux_lock, \ >> + .hw.init = CLK_HW_INIT_PARENTS(_name, \ >> + _parents, \ >> + &sprd_mux_ops, \ >> + _flags), \ >> + } \ >> + } >> + >> +static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw) >> +{ >> + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); >> + >> + return container_of(common, struct sprd_mux, common); >> +} >> + >> +extern const struct clk_ops sprd_mux_ops; >> +extern spinlock_t sprd_mux_lock; >> + >> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux); >> +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux, >> + u8 index); >> + >> +#endif /* _SPRD_MUX_H_ */ >> > > -- > Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 05/11] clk: sprd: add mux clock support @ 2017-11-03 12:12 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-03 12:12 UTC (permalink / raw) To: linux-arm-kernel Hi Julien, On 3 November 2017 at 02:11, Julien Thierry <julien.thierry@arm.com> wrote: > Hi, > > > On 02/11/17 06:56, Chunyan Zhang wrote: >> >> This patch adds clock multiplexor support for Spreadtrum platforms, >> the mux clocks also can be found in sprd composite clocks, so >> provides two helpers that can be reused later on. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Makefile | 1 + >> drivers/clk/sprd/mux.c | 89 >> +++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ >> 3 files changed, 155 insertions(+) >> create mode 100644 drivers/clk/sprd/mux.c >> create mode 100644 drivers/clk/sprd/mux.h >> >> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >> index 8cd5592..cee36b5 100644 >> --- a/drivers/clk/sprd/Makefile >> +++ b/drivers/clk/sprd/Makefile >> @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >> clk-sprd-y += common.o >> clk-sprd-y += gate.o >> +clk-sprd-y += mux.o >> diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c >> new file mode 100644 >> index 0000000..5a344e0 >> --- /dev/null >> +++ b/drivers/clk/sprd/mux.c >> @@ -0,0 +1,89 @@ >> +/* >> + * Spreadtrum multiplexer clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#include <linux/clk.h> >> +#include <linux/clk-provider.h> >> +#include <linux/regmap.h> >> + >> +#include "mux.h" >> + >> +DEFINE_SPINLOCK(sprd_mux_lock); >> +EXPORT_SYMBOL_GPL(sprd_mux_lock); >> + >> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux) >> +{ >> + unsigned int reg; >> + u8 parent; >> + int num_parents; >> + int i; >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + parent = reg >> mux->shift; >> + parent &= (1 << mux->width) - 1; >> + >> + if (mux->table) { >> + num_parents = clk_hw_get_num_parents(&common->hw); >> + >> + for (i = 0; i < num_parents; i++) >> + if (parent == mux->table[i] || >> + (i < (num_parents - 1) && parent > >> mux->table[i] && >> + parent < mux->table[i + 1])) >> + return i; >> + if (i == num_parents) >> + return i - 1; > > > The if branch is not necessary since you only get there when the loop has > finished, so the condition is always true. And the loop can be simplified > to: > > for (i = 0; i < num_parents - 1; i++) > if (parent >= mux->table[i] && parent < mux->table[i + 1]) > return i; > > return num_parents; > > > >> + } >> + >> + return parent; >> +} >> +EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent); >> + >> +static u8 sprd_mux_get_parent(struct clk_hw *hw) >> +{ >> + struct sprd_mux *cm = hw_to_sprd_mux(hw); >> + >> + return sprd_mux_helper_get_parent(&cm->common, &cm->mux); >> +} >> + >> +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux, >> + u8 index) >> +{ >> + unsigned long flags = 0; >> + unsigned int reg; >> + >> + if (mux->table) >> + index = mux->table[index]; >> + >> + spin_lock_irqsave(common->lock, flags); >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift); >> + sprd_regmap_write(common->regmap, common->reg, >> + reg | (index << mux->shift)); >> + >> + spin_unlock_irqrestore(common->lock, flags); >> + >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent); >> + >> +static int sprd_mux_set_parent(struct clk_hw *hw, u8 index) >> +{ >> + struct sprd_mux *cm = hw_to_sprd_mux(hw); >> + >> + return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index); >> +} >> + >> +const struct clk_ops sprd_mux_ops = { >> + .get_parent = sprd_mux_get_parent, >> + .set_parent = sprd_mux_set_parent, >> + .determine_rate = __clk_mux_determine_rate, >> +}; >> +EXPORT_SYMBOL_GPL(sprd_mux_ops); > > > Same as with the other patch, I'd recommend have one set of ops for direct > mux and another one for a mux using a table to map the parents. Keeping > functions for both modes separate. > I might prefer to keep them together, since separating them will increase many lines of code for maintaining :) And will export double of these functions, not only for mux driver but also for composite driver. And I think the name like "sprd_mux_helper_set_parent_table" is a little long. Thanks, Chunyan > Cheers, > > >> diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h >> new file mode 100644 >> index 0000000..148ca8c >> --- /dev/null >> +++ b/drivers/clk/sprd/mux.h >> @@ -0,0 +1,65 @@ >> +/* >> + * Spreadtrum multiplexer clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#ifndef _SPRD_MUX_H_ >> +#define _SPRD_MUX_H_ >> + >> +#include "common.h" >> + >> +struct sprd_mux_internal { >> + u8 shift; >> + u8 width; >> + const u8 *table; >> +}; >> + >> +struct sprd_mux { >> + struct sprd_mux_internal mux; >> + struct sprd_clk_common common; >> +}; >> + >> +#define _SPRD_MUX_CLK(_shift, _width, _table) \ >> + { \ >> + .shift = _shift, \ >> + .width = _width, \ >> + .table = _table, \ >> + } >> + >> +#define SPRD_MUX_CLK(_struct, _name, _parents, _table, \ >> + _reg, _shift, _width, \ >> + _flags) \ >> + struct sprd_mux _struct = { \ >> + .mux = _SPRD_MUX_CLK(_shift, _width, _table), \ >> + .common = { \ >> + .regmap = NULL, \ >> + .reg = _reg, \ >> + .lock = &sprd_mux_lock, \ >> + .hw.init = CLK_HW_INIT_PARENTS(_name, \ >> + _parents, \ >> + &sprd_mux_ops, \ >> + _flags), \ >> + } \ >> + } >> + >> +static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw) >> +{ >> + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); >> + >> + return container_of(common, struct sprd_mux, common); >> +} >> + >> +extern const struct clk_ops sprd_mux_ops; >> +extern spinlock_t sprd_mux_lock; >> + >> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux); >> +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux, >> + u8 index); >> + >> +#endif /* _SPRD_MUX_H_ */ >> > > -- > Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 05/11] clk: sprd: add mux clock support @ 2017-11-03 12:12 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-03 12:12 UTC (permalink / raw) To: Julien Thierry Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai Hi Julien, On 3 November 2017 at 02:11, Julien Thierry <julien.thierry@arm.com> wrote: > Hi, > > > On 02/11/17 06:56, Chunyan Zhang wrote: >> >> This patch adds clock multiplexor support for Spreadtrum platforms, >> the mux clocks also can be found in sprd composite clocks, so >> provides two helpers that can be reused later on. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Makefile | 1 + >> drivers/clk/sprd/mux.c | 89 >> +++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/clk/sprd/mux.h | 65 ++++++++++++++++++++++++++++++++++ >> 3 files changed, 155 insertions(+) >> create mode 100644 drivers/clk/sprd/mux.c >> create mode 100644 drivers/clk/sprd/mux.h >> >> diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile >> index 8cd5592..cee36b5 100644 >> --- a/drivers/clk/sprd/Makefile >> +++ b/drivers/clk/sprd/Makefile >> @@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o >> clk-sprd-y += common.o >> clk-sprd-y += gate.o >> +clk-sprd-y += mux.o >> diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c >> new file mode 100644 >> index 0000000..5a344e0 >> --- /dev/null >> +++ b/drivers/clk/sprd/mux.c >> @@ -0,0 +1,89 @@ >> +/* >> + * Spreadtrum multiplexer clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#include <linux/clk.h> >> +#include <linux/clk-provider.h> >> +#include <linux/regmap.h> >> + >> +#include "mux.h" >> + >> +DEFINE_SPINLOCK(sprd_mux_lock); >> +EXPORT_SYMBOL_GPL(sprd_mux_lock); >> + >> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux) >> +{ >> + unsigned int reg; >> + u8 parent; >> + int num_parents; >> + int i; >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + parent = reg >> mux->shift; >> + parent &= (1 << mux->width) - 1; >> + >> + if (mux->table) { >> + num_parents = clk_hw_get_num_parents(&common->hw); >> + >> + for (i = 0; i < num_parents; i++) >> + if (parent == mux->table[i] || >> + (i < (num_parents - 1) && parent > >> mux->table[i] && >> + parent < mux->table[i + 1])) >> + return i; >> + if (i == num_parents) >> + return i - 1; > > > The if branch is not necessary since you only get there when the loop has > finished, so the condition is always true. And the loop can be simplified > to: > > for (i = 0; i < num_parents - 1; i++) > if (parent >= mux->table[i] && parent < mux->table[i + 1]) > return i; > > return num_parents; > > > >> + } >> + >> + return parent; >> +} >> +EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent); >> + >> +static u8 sprd_mux_get_parent(struct clk_hw *hw) >> +{ >> + struct sprd_mux *cm = hw_to_sprd_mux(hw); >> + >> + return sprd_mux_helper_get_parent(&cm->common, &cm->mux); >> +} >> + >> +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux, >> + u8 index) >> +{ >> + unsigned long flags = 0; >> + unsigned int reg; >> + >> + if (mux->table) >> + index = mux->table[index]; >> + >> + spin_lock_irqsave(common->lock, flags); >> + >> + sprd_regmap_read(common->regmap, common->reg, ®); >> + reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift); >> + sprd_regmap_write(common->regmap, common->reg, >> + reg | (index << mux->shift)); >> + >> + spin_unlock_irqrestore(common->lock, flags); >> + >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent); >> + >> +static int sprd_mux_set_parent(struct clk_hw *hw, u8 index) >> +{ >> + struct sprd_mux *cm = hw_to_sprd_mux(hw); >> + >> + return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index); >> +} >> + >> +const struct clk_ops sprd_mux_ops = { >> + .get_parent = sprd_mux_get_parent, >> + .set_parent = sprd_mux_set_parent, >> + .determine_rate = __clk_mux_determine_rate, >> +}; >> +EXPORT_SYMBOL_GPL(sprd_mux_ops); > > > Same as with the other patch, I'd recommend have one set of ops for direct > mux and another one for a mux using a table to map the parents. Keeping > functions for both modes separate. > I might prefer to keep them together, since separating them will increase many lines of code for maintaining :) And will export double of these functions, not only for mux driver but also for composite driver. And I think the name like "sprd_mux_helper_set_parent_table" is a little long. Thanks, Chunyan > Cheers, > > >> diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h >> new file mode 100644 >> index 0000000..148ca8c >> --- /dev/null >> +++ b/drivers/clk/sprd/mux.h >> @@ -0,0 +1,65 @@ >> +/* >> + * Spreadtrum multiplexer clock driver >> + * >> + * Copyright (C) 2017 Spreadtrum, Inc. >> + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> + * >> + * SPDX-License-Identifier: GPL-2.0 >> + */ >> + >> +#ifndef _SPRD_MUX_H_ >> +#define _SPRD_MUX_H_ >> + >> +#include "common.h" >> + >> +struct sprd_mux_internal { >> + u8 shift; >> + u8 width; >> + const u8 *table; >> +}; >> + >> +struct sprd_mux { >> + struct sprd_mux_internal mux; >> + struct sprd_clk_common common; >> +}; >> + >> +#define _SPRD_MUX_CLK(_shift, _width, _table) \ >> + { \ >> + .shift = _shift, \ >> + .width = _width, \ >> + .table = _table, \ >> + } >> + >> +#define SPRD_MUX_CLK(_struct, _name, _parents, _table, \ >> + _reg, _shift, _width, \ >> + _flags) \ >> + struct sprd_mux _struct = { \ >> + .mux = _SPRD_MUX_CLK(_shift, _width, _table), \ >> + .common = { \ >> + .regmap = NULL, \ >> + .reg = _reg, \ >> + .lock = &sprd_mux_lock, \ >> + .hw.init = CLK_HW_INIT_PARENTS(_name, \ >> + _parents, \ >> + &sprd_mux_ops, \ >> + _flags), \ >> + } \ >> + } >> + >> +static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw) >> +{ >> + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); >> + >> + return container_of(common, struct sprd_mux, common); >> +} >> + >> +extern const struct clk_ops sprd_mux_ops; >> +extern spinlock_t sprd_mux_lock; >> + >> +u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux); >> +int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, >> + const struct sprd_mux_internal *mux, >> + u8 index); >> + >> +#endif /* _SPRD_MUX_H_ */ >> > > -- > Julien Thierry ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 06/11] clk: sprd: add divider clock support 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This is a feature that can also be found in sprd composite clocks, provide a bunch of helpers that can be reused later on. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/div.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/div.h | 79 ++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/clk/sprd/div.c create mode 100644 drivers/clk/sprd/div.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index cee36b5..80e6039 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o clk-sprd-y += common.o clk-sprd-y += gate.o clk-sprd-y += mux.o +clk-sprd-y += div.o diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c new file mode 100644 index 0000000..3e08dcd --- /dev/null +++ b/drivers/clk/sprd/div.c @@ -0,0 +1,100 @@ +/* + * Spreadtrum divider clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> + +#include "div.h" + +DEFINE_SPINLOCK(sprd_div_lock); +EXPORT_SYMBOL_GPL(sprd_div_lock); + +long sprd_div_helper_round_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long *parent_rate) +{ + return divider_round_rate(&common->hw, rate, parent_rate, + NULL, div->width, 0); +} +EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate); + +static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct sprd_div *cd = hw_to_sprd_div(hw); + + return sprd_div_helper_round_rate(&cd->common, &cd->div, + rate, parent_rate); +} + +unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long parent_rate) +{ + unsigned long val; + unsigned int reg; + + sprd_regmap_read(common->regmap, common->reg, ®); + val = reg >> div->shift; + val &= (1 << div->width) - 1; + + return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0); +} +EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate); + +static unsigned long sprd_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_div *cd = hw_to_sprd_div(hw); + + return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate); +} + +int sprd_div_helper_set_rate(const struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long parent_rate) +{ + unsigned long flags; + unsigned long val; + unsigned int reg; + + val = divider_get_val(rate, parent_rate, NULL, + div->width, 0); + + spin_lock_irqsave(common->lock, flags); + + sprd_regmap_read(common->regmap, common->reg, ®); + reg &= ~GENMASK(div->width + div->shift - 1, div->shift); + + sprd_regmap_write(common->regmap, common->reg, + reg | (val << div->shift)); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; + +} +EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate); + +static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_div *cd = hw_to_sprd_div(hw); + + return sprd_div_helper_set_rate(&cd->common, &cd->div, + rate, parent_rate); +} + +const struct clk_ops sprd_div_ops = { + .recalc_rate = sprd_div_recalc_rate, + .round_rate = sprd_div_round_rate, + .set_rate = sprd_div_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_div_ops); diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h new file mode 100644 index 0000000..fa47773 --- /dev/null +++ b/drivers/clk/sprd/div.h @@ -0,0 +1,79 @@ +/* + * Spreadtrum divider clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_DIV_H_ +#define _SPRD_DIV_H_ + +#include "common.h" + +/** + * struct sprd_div_internal - Internal divider description + * @shift: Bit offset of the divider in its register + * @width: Width of the divider field in its register + * + * That structure represents a single divider, and is meant to be + * embedded in other structures representing the various clock + * classes. + */ +struct sprd_div_internal { + u8 shift; + u8 width; +}; + +#define _SPRD_DIV_CLK(_shift, _width) \ + { \ + .shift = _shift, \ + .width = _width, \ + } + +struct sprd_div { + struct sprd_div_internal div; + struct sprd_clk_common common; +}; + +#define SPRD_DIV_CLK(_struct, _name, _parent, _reg, \ + _shift, _width, _flags) \ + struct sprd_div _struct = { \ + .div = _SPRD_DIV_CLK(_shift, _width), \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_div_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &sprd_div_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_div, common); +} + +long sprd_div_helper_round_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long *parent_rate); + +unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long parent_rate); + +int sprd_div_helper_set_rate(const struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long parent_rate); + +extern const struct clk_ops sprd_div_ops; +extern spinlock_t sprd_div_lock; + +#endif /* _SPRD_DIV_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 06/11] clk: sprd: add divider clock support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel This is a feature that can also be found in sprd composite clocks, provide a bunch of helpers that can be reused later on. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/div.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/div.h | 79 ++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/clk/sprd/div.c create mode 100644 drivers/clk/sprd/div.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index cee36b5..80e6039 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o clk-sprd-y += common.o clk-sprd-y += gate.o clk-sprd-y += mux.o +clk-sprd-y += div.o diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c new file mode 100644 index 0000000..3e08dcd --- /dev/null +++ b/drivers/clk/sprd/div.c @@ -0,0 +1,100 @@ +/* + * Spreadtrum divider clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> + +#include "div.h" + +DEFINE_SPINLOCK(sprd_div_lock); +EXPORT_SYMBOL_GPL(sprd_div_lock); + +long sprd_div_helper_round_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long *parent_rate) +{ + return divider_round_rate(&common->hw, rate, parent_rate, + NULL, div->width, 0); +} +EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate); + +static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct sprd_div *cd = hw_to_sprd_div(hw); + + return sprd_div_helper_round_rate(&cd->common, &cd->div, + rate, parent_rate); +} + +unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long parent_rate) +{ + unsigned long val; + unsigned int reg; + + sprd_regmap_read(common->regmap, common->reg, ®); + val = reg >> div->shift; + val &= (1 << div->width) - 1; + + return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0); +} +EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate); + +static unsigned long sprd_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_div *cd = hw_to_sprd_div(hw); + + return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate); +} + +int sprd_div_helper_set_rate(const struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long parent_rate) +{ + unsigned long flags; + unsigned long val; + unsigned int reg; + + val = divider_get_val(rate, parent_rate, NULL, + div->width, 0); + + spin_lock_irqsave(common->lock, flags); + + sprd_regmap_read(common->regmap, common->reg, ®); + reg &= ~GENMASK(div->width + div->shift - 1, div->shift); + + sprd_regmap_write(common->regmap, common->reg, + reg | (val << div->shift)); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; + +} +EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate); + +static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_div *cd = hw_to_sprd_div(hw); + + return sprd_div_helper_set_rate(&cd->common, &cd->div, + rate, parent_rate); +} + +const struct clk_ops sprd_div_ops = { + .recalc_rate = sprd_div_recalc_rate, + .round_rate = sprd_div_round_rate, + .set_rate = sprd_div_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_div_ops); diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h new file mode 100644 index 0000000..fa47773 --- /dev/null +++ b/drivers/clk/sprd/div.h @@ -0,0 +1,79 @@ +/* + * Spreadtrum divider clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_DIV_H_ +#define _SPRD_DIV_H_ + +#include "common.h" + +/** + * struct sprd_div_internal - Internal divider description + * @shift: Bit offset of the divider in its register + * @width: Width of the divider field in its register + * + * That structure represents a single divider, and is meant to be + * embedded in other structures representing the various clock + * classes. + */ +struct sprd_div_internal { + u8 shift; + u8 width; +}; + +#define _SPRD_DIV_CLK(_shift, _width) \ + { \ + .shift = _shift, \ + .width = _width, \ + } + +struct sprd_div { + struct sprd_div_internal div; + struct sprd_clk_common common; +}; + +#define SPRD_DIV_CLK(_struct, _name, _parent, _reg, \ + _shift, _width, _flags) \ + struct sprd_div _struct = { \ + .div = _SPRD_DIV_CLK(_shift, _width), \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_div_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &sprd_div_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_div, common); +} + +long sprd_div_helper_round_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long *parent_rate); + +unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long parent_rate); + +int sprd_div_helper_set_rate(const struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long parent_rate); + +extern const struct clk_ops sprd_div_ops; +extern spinlock_t sprd_div_lock; + +#endif /* _SPRD_DIV_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 06/11] clk: sprd: add divider clock support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This is a feature that can also be found in sprd composite clocks, provide a bunch of helpers that can be reused later on. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/div.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/div.h | 79 ++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/clk/sprd/div.c create mode 100644 drivers/clk/sprd/div.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index cee36b5..80e6039 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o clk-sprd-y += common.o clk-sprd-y += gate.o clk-sprd-y += mux.o +clk-sprd-y += div.o diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c new file mode 100644 index 0000000..3e08dcd --- /dev/null +++ b/drivers/clk/sprd/div.c @@ -0,0 +1,100 @@ +/* + * Spreadtrum divider clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> + +#include "div.h" + +DEFINE_SPINLOCK(sprd_div_lock); +EXPORT_SYMBOL_GPL(sprd_div_lock); + +long sprd_div_helper_round_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long *parent_rate) +{ + return divider_round_rate(&common->hw, rate, parent_rate, + NULL, div->width, 0); +} +EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate); + +static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct sprd_div *cd = hw_to_sprd_div(hw); + + return sprd_div_helper_round_rate(&cd->common, &cd->div, + rate, parent_rate); +} + +unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long parent_rate) +{ + unsigned long val; + unsigned int reg; + + sprd_regmap_read(common->regmap, common->reg, ®); + val = reg >> div->shift; + val &= (1 << div->width) - 1; + + return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0); +} +EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate); + +static unsigned long sprd_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_div *cd = hw_to_sprd_div(hw); + + return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate); +} + +int sprd_div_helper_set_rate(const struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long parent_rate) +{ + unsigned long flags; + unsigned long val; + unsigned int reg; + + val = divider_get_val(rate, parent_rate, NULL, + div->width, 0); + + spin_lock_irqsave(common->lock, flags); + + sprd_regmap_read(common->regmap, common->reg, ®); + reg &= ~GENMASK(div->width + div->shift - 1, div->shift); + + sprd_regmap_write(common->regmap, common->reg, + reg | (val << div->shift)); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; + +} +EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate); + +static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_div *cd = hw_to_sprd_div(hw); + + return sprd_div_helper_set_rate(&cd->common, &cd->div, + rate, parent_rate); +} + +const struct clk_ops sprd_div_ops = { + .recalc_rate = sprd_div_recalc_rate, + .round_rate = sprd_div_round_rate, + .set_rate = sprd_div_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_div_ops); diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h new file mode 100644 index 0000000..fa47773 --- /dev/null +++ b/drivers/clk/sprd/div.h @@ -0,0 +1,79 @@ +/* + * Spreadtrum divider clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_DIV_H_ +#define _SPRD_DIV_H_ + +#include "common.h" + +/** + * struct sprd_div_internal - Internal divider description + * @shift: Bit offset of the divider in its register + * @width: Width of the divider field in its register + * + * That structure represents a single divider, and is meant to be + * embedded in other structures representing the various clock + * classes. + */ +struct sprd_div_internal { + u8 shift; + u8 width; +}; + +#define _SPRD_DIV_CLK(_shift, _width) \ + { \ + .shift = _shift, \ + .width = _width, \ + } + +struct sprd_div { + struct sprd_div_internal div; + struct sprd_clk_common common; +}; + +#define SPRD_DIV_CLK(_struct, _name, _parent, _reg, \ + _shift, _width, _flags) \ + struct sprd_div _struct = { \ + .div = _SPRD_DIV_CLK(_shift, _width), \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_div_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &sprd_div_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_div, common); +} + +long sprd_div_helper_round_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long *parent_rate); + +unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long parent_rate); + +int sprd_div_helper_set_rate(const struct sprd_clk_common *common, + const struct sprd_div_internal *div, + unsigned long rate, + unsigned long parent_rate); + +extern const struct clk_ops sprd_div_ops; +extern spinlock_t sprd_div_lock; + +#endif /* _SPRD_DIV_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 07/11] clk: sprd: add composite clock support 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This patch introduced composite driver for Spreadtrum's SoCs. The functions of this composite clock simply consist of divider and mux clocks. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/composite.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/composite.h | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 drivers/clk/sprd/composite.c create mode 100644 drivers/clk/sprd/composite.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 80e6039..2262e76 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -4,3 +4,4 @@ clk-sprd-y += common.o clk-sprd-y += gate.o clk-sprd-y += mux.o clk-sprd-y += div.o +clk-sprd-y += composite.o diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c new file mode 100644 index 0000000..30d5b36 --- /dev/null +++ b/drivers/clk/sprd/composite.c @@ -0,0 +1,65 @@ +/* + * Spreadtrum composite clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> + +#include "composite.h" + +DEFINE_SPINLOCK(sprd_comp_lock); +EXPORT_SYMBOL_GPL(sprd_comp_lock); + +static long sprd_comp_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_round_rate(&cc->common, &cc->div, + rate, parent_rate); +} + +static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_recalc_rate(&cc->common, &cc->div, parent_rate); +} + +static int sprd_comp_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_set_rate(&cc->common, &cc->div, + rate, parent_rate); +} + +static u8 sprd_comp_get_parent(struct clk_hw *hw) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_mux_helper_get_parent(&cc->common, &cc->mux); +} + +static int sprd_comp_set_parent(struct clk_hw *hw, u8 index) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_mux_helper_set_parent(&cc->common, &cc->mux, index); +} + +const struct clk_ops sprd_comp_ops = { + .get_parent = sprd_comp_get_parent, + .set_parent = sprd_comp_set_parent, + + .round_rate = sprd_comp_round_rate, + .recalc_rate = sprd_comp_recalc_rate, + .set_rate = sprd_comp_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_comp_ops); diff --git a/drivers/clk/sprd/composite.h b/drivers/clk/sprd/composite.h new file mode 100644 index 0000000..551f274 --- /dev/null +++ b/drivers/clk/sprd/composite.h @@ -0,0 +1,49 @@ +/* + * Spreadtrum composite clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_COMPOSITE_H_ +#define _SPRD_COMPOSITE_H_ + +#include "common.h" +#include "mux.h" +#include "div.h" + +struct sprd_comp { + struct sprd_mux_internal mux; + struct sprd_div_internal div; + struct sprd_clk_common common; +}; + +#define SPRD_COMP_CLK(_struct, _name, _parent, _reg, _table, \ + _mshift, _mwidth, _dshift, _dwidth, _flags) \ + struct sprd_comp _struct = { \ + .mux = _SPRD_MUX_CLK(_mshift, _mwidth, _table), \ + .div = _SPRD_DIV_CLK(_dshift, _dwidth), \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_comp_lock, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parent, \ + &sprd_comp_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_comp *hw_to_sprd_comp(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_comp, common); +} + +extern const struct clk_ops sprd_comp_ops; +extern spinlock_t sprd_comp_lock; + +#endif /* _SPRD_COMPOSITE_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 07/11] clk: sprd: add composite clock support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel This patch introduced composite driver for Spreadtrum's SoCs. The functions of this composite clock simply consist of divider and mux clocks. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/composite.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/composite.h | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 drivers/clk/sprd/composite.c create mode 100644 drivers/clk/sprd/composite.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 80e6039..2262e76 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -4,3 +4,4 @@ clk-sprd-y += common.o clk-sprd-y += gate.o clk-sprd-y += mux.o clk-sprd-y += div.o +clk-sprd-y += composite.o diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c new file mode 100644 index 0000000..30d5b36 --- /dev/null +++ b/drivers/clk/sprd/composite.c @@ -0,0 +1,65 @@ +/* + * Spreadtrum composite clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> + +#include "composite.h" + +DEFINE_SPINLOCK(sprd_comp_lock); +EXPORT_SYMBOL_GPL(sprd_comp_lock); + +static long sprd_comp_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_round_rate(&cc->common, &cc->div, + rate, parent_rate); +} + +static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_recalc_rate(&cc->common, &cc->div, parent_rate); +} + +static int sprd_comp_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_set_rate(&cc->common, &cc->div, + rate, parent_rate); +} + +static u8 sprd_comp_get_parent(struct clk_hw *hw) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_mux_helper_get_parent(&cc->common, &cc->mux); +} + +static int sprd_comp_set_parent(struct clk_hw *hw, u8 index) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_mux_helper_set_parent(&cc->common, &cc->mux, index); +} + +const struct clk_ops sprd_comp_ops = { + .get_parent = sprd_comp_get_parent, + .set_parent = sprd_comp_set_parent, + + .round_rate = sprd_comp_round_rate, + .recalc_rate = sprd_comp_recalc_rate, + .set_rate = sprd_comp_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_comp_ops); diff --git a/drivers/clk/sprd/composite.h b/drivers/clk/sprd/composite.h new file mode 100644 index 0000000..551f274 --- /dev/null +++ b/drivers/clk/sprd/composite.h @@ -0,0 +1,49 @@ +/* + * Spreadtrum composite clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_COMPOSITE_H_ +#define _SPRD_COMPOSITE_H_ + +#include "common.h" +#include "mux.h" +#include "div.h" + +struct sprd_comp { + struct sprd_mux_internal mux; + struct sprd_div_internal div; + struct sprd_clk_common common; +}; + +#define SPRD_COMP_CLK(_struct, _name, _parent, _reg, _table, \ + _mshift, _mwidth, _dshift, _dwidth, _flags) \ + struct sprd_comp _struct = { \ + .mux = _SPRD_MUX_CLK(_mshift, _mwidth, _table), \ + .div = _SPRD_DIV_CLK(_dshift, _dwidth), \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_comp_lock, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parent, \ + &sprd_comp_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_comp *hw_to_sprd_comp(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_comp, common); +} + +extern const struct clk_ops sprd_comp_ops; +extern spinlock_t sprd_comp_lock; + +#endif /* _SPRD_COMPOSITE_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 07/11] clk: sprd: add composite clock support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This patch introduced composite driver for Spreadtrum's SoCs. The functions of this composite clock simply consist of divider and mux clocks. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/composite.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/composite.h | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 drivers/clk/sprd/composite.c create mode 100644 drivers/clk/sprd/composite.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 80e6039..2262e76 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -4,3 +4,4 @@ clk-sprd-y += common.o clk-sprd-y += gate.o clk-sprd-y += mux.o clk-sprd-y += div.o +clk-sprd-y += composite.o diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c new file mode 100644 index 0000000..30d5b36 --- /dev/null +++ b/drivers/clk/sprd/composite.c @@ -0,0 +1,65 @@ +/* + * Spreadtrum composite clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> + +#include "composite.h" + +DEFINE_SPINLOCK(sprd_comp_lock); +EXPORT_SYMBOL_GPL(sprd_comp_lock); + +static long sprd_comp_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_round_rate(&cc->common, &cc->div, + rate, parent_rate); +} + +static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_recalc_rate(&cc->common, &cc->div, parent_rate); +} + +static int sprd_comp_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_set_rate(&cc->common, &cc->div, + rate, parent_rate); +} + +static u8 sprd_comp_get_parent(struct clk_hw *hw) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_mux_helper_get_parent(&cc->common, &cc->mux); +} + +static int sprd_comp_set_parent(struct clk_hw *hw, u8 index) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_mux_helper_set_parent(&cc->common, &cc->mux, index); +} + +const struct clk_ops sprd_comp_ops = { + .get_parent = sprd_comp_get_parent, + .set_parent = sprd_comp_set_parent, + + .round_rate = sprd_comp_round_rate, + .recalc_rate = sprd_comp_recalc_rate, + .set_rate = sprd_comp_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_comp_ops); diff --git a/drivers/clk/sprd/composite.h b/drivers/clk/sprd/composite.h new file mode 100644 index 0000000..551f274 --- /dev/null +++ b/drivers/clk/sprd/composite.h @@ -0,0 +1,49 @@ +/* + * Spreadtrum composite clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_COMPOSITE_H_ +#define _SPRD_COMPOSITE_H_ + +#include "common.h" +#include "mux.h" +#include "div.h" + +struct sprd_comp { + struct sprd_mux_internal mux; + struct sprd_div_internal div; + struct sprd_clk_common common; +}; + +#define SPRD_COMP_CLK(_struct, _name, _parent, _reg, _table, \ + _mshift, _mwidth, _dshift, _dwidth, _flags) \ + struct sprd_comp _struct = { \ + .mux = _SPRD_MUX_CLK(_mshift, _mwidth, _table), \ + .div = _SPRD_DIV_CLK(_dshift, _dwidth), \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .lock = &sprd_comp_lock, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parent, \ + &sprd_comp_ops, \ + _flags), \ + } \ + } + +static inline struct sprd_comp *hw_to_sprd_comp(const struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_comp, common); +} + +extern const struct clk_ops sprd_comp_ops; +extern spinlock_t sprd_comp_lock; + +#endif /* _SPRD_COMPOSITE_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 08/11] clk: sprd: add adjustable pll support 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Introduced a common adjustable pll clock driver for Spreadtrum SoCs. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/pll.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/pll.h | 110 +++++++++++++++++++ 3 files changed, 379 insertions(+) create mode 100644 drivers/clk/sprd/pll.c create mode 100644 drivers/clk/sprd/pll.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 2262e76..d693969 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -5,3 +5,4 @@ clk-sprd-y += gate.o clk-sprd-y += mux.o clk-sprd-y += div.o clk-sprd-y += composite.o +clk-sprd-y += pll.o diff --git a/drivers/clk/sprd/pll.c b/drivers/clk/sprd/pll.c new file mode 100644 index 0000000..1fd8d32 --- /dev/null +++ b/drivers/clk/sprd/pll.c @@ -0,0 +1,268 @@ +/* + * Spreadtrum pll clock driver + * + * Copyright (C) 2015~2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +#include "pll.h" + +#define CLK_PLL_1M 1000000 +#define CLK_PLL_10M (CLK_PLL_1M * 10) + +#define pindex(pll, member) \ + (pll->factors[member].shift / (8 * sizeof(pll->regs_num))) + +#define pshift(pll, member) \ + (pll->factors[member].shift % (8 * sizeof(pll->regs_num))) + +#define pwidth(pll, member) \ + pll->factors[member].width + +#define pmask(pll, member) \ + ((pwidth(pll, member)) ? \ + GENMASK(pwidth(pll, member) + pshift(pll, member) - 1, \ + pshift(pll, member)) : 0) + +#define pinternal(pll, cfg, member) \ + (cfg[pindex(pll, member)] & pmask(pll, member)) + +#define pinternal_val(pll, cfg, member) \ + (pinternal(pll, cfg, member) >> pshift(pll, member)) + +static inline unsigned int +sprd_pll_read(const struct sprd_pll *pll, u8 index) +{ + const struct sprd_clk_common *common = &pll->common; + unsigned int val = 0; + + if (WARN_ON(index >= pll->regs_num)) + return 0; + + sprd_regmap_read(common->regmap, common->reg + index * 4, &val); + + return val; +} + +static inline void +sprd_pll_write(const struct sprd_pll *pll, u8 index, + u32 msk, u32 val) +{ + const struct sprd_clk_common *common = &pll->common; + unsigned int offset, reg; + int ret = 0; + + if (WARN_ON(index >= pll->regs_num)) + return; + + offset = common->reg + index * 4; + ret = sprd_regmap_read(common->regmap, offset, ®); + if (!ret) + sprd_regmap_write(common->regmap, offset, (reg & ~msk) | val); +} + +static unsigned long pll_get_refin(const struct sprd_pll *pll) +{ + u32 shift, mask, index, refin_id = 3; + const unsigned long refin[4] = { 2, 4, 13, 26 }; + + if (pwidth(pll, PLL_REFIN)) { + index = pindex(pll, PLL_REFIN); + shift = pshift(pll, PLL_REFIN); + mask = pmask(pll, PLL_REFIN); + refin_id = (sprd_pll_read(pll, index) & mask) >> shift; + if (refin_id > 3) + refin_id = 3; + } + + return refin[refin_id]; +} + +static u32 pll_get_ibias(u64 rate, const u64 *table) +{ + u32 i, num = table[0]; + + for (i = 1; i < num + 1; i++) + if (rate <= table[i]) + break; + + return (i == num + 1) ? num : i; +} + +static unsigned long _sprd_pll_recalc_rate(const struct sprd_pll *pll, + unsigned long parent_rate) +{ + u32 *cfg; + u32 i, mask, regs_num = pll->regs_num; + unsigned long rate, nint, kint = 0; + u64 refin; + u16 k1, k2; + + cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + + for (i = 0; i < regs_num; i++) + cfg[i] = sprd_pll_read(pll, i); + + refin = pll_get_refin(pll); + + if (pinternal(pll, cfg, PLL_PREDIV)) + refin = refin * 2; + + if (pwidth(pll, PLL_POSTDIV) && + ((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) || + (!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV)))) + refin = refin / 2; + + if (!pinternal(pll, cfg, PLL_DIV_S)) { + rate = refin * pinternal_val(pll, cfg, PLL_N) * CLK_PLL_10M; + } else { + nint = pinternal_val(pll, cfg, PLL_NINT); + if (pinternal(pll, cfg, PLL_SDM_EN)) + kint = pinternal_val(pll, cfg, PLL_KINT); + + mask = pmask(pll, PLL_KINT); + + k1 = pll->k1; + k2 = pll->k2; + rate = DIV_ROUND_CLOSEST_ULL(refin * kint * k1, + ((mask >> __ffs(mask)) + 1)) * + k2 + refin * nint * CLK_PLL_1M; + } + + return rate; +} + +#define SPRD_PLL_WRITE_CHECK(pll, i, mask, val) \ + (((sprd_pll_read(pll, i) & mask) == val) ? 0 : (-EFAULT)) + +static int _sprd_pll_set_rate(const struct sprd_pll *pll, + unsigned long rate, + unsigned long parent_rate) +{ + struct reg_cfg *cfg; + int ret = 0; + u32 mask, shift, width, ibias_val, index; + u32 regs_num = pll->regs_num, i = 0; + unsigned long kint, nint; + u64 tmp, refin, fvco = rate; + + cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + + refin = pll_get_refin(pll); + + mask = pmask(pll, PLL_PREDIV); + index = pindex(pll, PLL_PREDIV); + width = pwidth(pll, PLL_PREDIV); + if (width && (sprd_pll_read(pll, index) & mask)) + refin = refin * 2; + + mask = pmask(pll, PLL_POSTDIV); + index = pindex(pll, PLL_POSTDIV); + width = pwidth(pll, PLL_POSTDIV); + cfg[index].msk = mask; + if (width && ((pll->fflag == 1 && fvco <= pll->fvco) || + (pll->fflag == 0 && fvco > pll->fvco))) + cfg[index].val |= mask; + + if (width && fvco <= pll->fvco) + fvco = fvco * 2; + + mask = pmask(pll, PLL_DIV_S); + index = pindex(pll, PLL_DIV_S); + cfg[index].val |= mask; + cfg[index].msk |= mask; + + mask = pmask(pll, PLL_SDM_EN); + index = pindex(pll, PLL_SDM_EN); + cfg[index].val |= mask; + cfg[index].msk |= mask; + + nint = do_div(fvco, refin * CLK_PLL_1M); + mask = pmask(pll, PLL_NINT); + index = pindex(pll, PLL_NINT); + shift = pshift(pll, PLL_NINT); + cfg[index].val |= (nint << shift) & mask; + cfg[index].msk |= mask; + + mask = pmask(pll, PLL_KINT); + index = pindex(pll, PLL_KINT); + width = pwidth(pll, PLL_KINT); + shift = pshift(pll, PLL_KINT); + tmp = fvco - refin * nint * CLK_PLL_1M; + tmp = do_div(tmp, 10000) * ((mask >> shift) + 1); + kint = DIV_ROUND_CLOSEST_ULL(tmp, refin * 100); + cfg[index].val |= (kint << shift) & mask; + cfg[index].msk |= mask; + + ibias_val = pll_get_ibias(fvco, pll->itable); + + mask = pmask(pll, PLL_IBIAS); + index = pindex(pll, PLL_IBIAS); + shift = pshift(pll, PLL_IBIAS); + cfg[index].val |= ibias_val << shift & mask; + cfg[index].msk |= mask; + + for (i = 0; i < regs_num; i++) { + if (cfg[i].msk) { + sprd_pll_write(pll, i, cfg[i].msk, cfg[i].val); + ret |= SPRD_PLL_WRITE_CHECK(pll, i, cfg[i].msk, + cfg[i].val); + } + } + + if (!ret) + udelay(pll->udelay); + + return ret; +} + +static unsigned long sprd_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_pll *pll = hw_to_sprd_pll(hw); + + return _sprd_pll_recalc_rate(pll, parent_rate); +} + +static int sprd_pll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_pll *pll = hw_to_sprd_pll(hw); + + return _sprd_pll_set_rate(pll, rate, parent_rate); +} + +static int sprd_pll_clk_prepare(struct clk_hw *hw) +{ + struct sprd_pll *pll = hw_to_sprd_pll(hw); + + udelay(pll->udelay); + + return 0; +} + +static long sprd_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + return rate; +} + +const struct clk_ops sprd_pll_ops = { + .prepare = sprd_pll_clk_prepare, + .recalc_rate = sprd_pll_recalc_rate, + .round_rate = sprd_pll_round_rate, + .set_rate = sprd_pll_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_pll_ops); diff --git a/drivers/clk/sprd/pll.h b/drivers/clk/sprd/pll.h new file mode 100644 index 0000000..a25b003 --- /dev/null +++ b/drivers/clk/sprd/pll.h @@ -0,0 +1,110 @@ +/* + * Spreadtrum clock pll configurations + * + * Copyright (C) 2015~2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_PLL_H_ +#define _SPRD_PLL_H_ + +#include "common.h" + +struct reg_cfg { + u32 val; + u32 msk; +}; + +struct clk_bit_field { + u8 shift; + u8 width; +}; + +enum { + PLL_LOCK_DONE, + PLL_DIV_S, + PLL_MOD_EN, + PLL_SDM_EN, + PLL_REFIN, + PLL_IBIAS, + PLL_N, + PLL_NINT, + PLL_KINT, + PLL_PREDIV, + PLL_POSTDIV, + + PLL_FACT_MAX +}; + +/* + * struct sprd_pll - definition of adjustable pll clock + * + * @reg: registers used to set the configuration of pll clock, + * reg[0] shows how many registers this pll clock uses. + * @itable: pll ibias table, itable[0] means how many items this + * table includes + * @udelay delay time after setting rate + * @factors used to calculate the pll clock rate + * @fvco: fvco threshold rate + * @fflag: fvco flag + */ +struct sprd_pll { + u32 regs_num; + const u64 *itable; + const struct clk_bit_field *factors; + u16 udelay; + u16 k1; + u16 k2; + u16 fflag; + u64 fvco; + + struct sprd_clk_common common; +}; + +#define SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, _k1, _k2, _fflag, _fvco) \ + struct sprd_pll _struct = { \ + .regs_num = _regs_num, \ + .itable = _itable, \ + .factors = _factors, \ + .udelay = _udelay, \ + .k1 = _k1, \ + .k2 = _k2, \ + .fflag = _fflag, \ + .fvco = _fvco, \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &sprd_pll_ops, \ + 0), \ + }, \ + } + +#define SPRD_PLL_WITH_ITABLE_K(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, _k1, _k2) \ + SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, _k1, _k2, 0, 0) + +#define SPRD_PLL_WITH_ITABLE_1K(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, _udelay) \ + SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, 1000, 1000, 0, 0) + +static inline struct sprd_pll *hw_to_sprd_pll(struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_pll, common); +} + +extern const struct clk_ops sprd_pll_ops; + +#endif /* _SPRD_PLL_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 08/11] clk: sprd: add adjustable pll support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel Introduced a common adjustable pll clock driver for Spreadtrum SoCs. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/pll.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/pll.h | 110 +++++++++++++++++++ 3 files changed, 379 insertions(+) create mode 100644 drivers/clk/sprd/pll.c create mode 100644 drivers/clk/sprd/pll.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 2262e76..d693969 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -5,3 +5,4 @@ clk-sprd-y += gate.o clk-sprd-y += mux.o clk-sprd-y += div.o clk-sprd-y += composite.o +clk-sprd-y += pll.o diff --git a/drivers/clk/sprd/pll.c b/drivers/clk/sprd/pll.c new file mode 100644 index 0000000..1fd8d32 --- /dev/null +++ b/drivers/clk/sprd/pll.c @@ -0,0 +1,268 @@ +/* + * Spreadtrum pll clock driver + * + * Copyright (C) 2015~2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +#include "pll.h" + +#define CLK_PLL_1M 1000000 +#define CLK_PLL_10M (CLK_PLL_1M * 10) + +#define pindex(pll, member) \ + (pll->factors[member].shift / (8 * sizeof(pll->regs_num))) + +#define pshift(pll, member) \ + (pll->factors[member].shift % (8 * sizeof(pll->regs_num))) + +#define pwidth(pll, member) \ + pll->factors[member].width + +#define pmask(pll, member) \ + ((pwidth(pll, member)) ? \ + GENMASK(pwidth(pll, member) + pshift(pll, member) - 1, \ + pshift(pll, member)) : 0) + +#define pinternal(pll, cfg, member) \ + (cfg[pindex(pll, member)] & pmask(pll, member)) + +#define pinternal_val(pll, cfg, member) \ + (pinternal(pll, cfg, member) >> pshift(pll, member)) + +static inline unsigned int +sprd_pll_read(const struct sprd_pll *pll, u8 index) +{ + const struct sprd_clk_common *common = &pll->common; + unsigned int val = 0; + + if (WARN_ON(index >= pll->regs_num)) + return 0; + + sprd_regmap_read(common->regmap, common->reg + index * 4, &val); + + return val; +} + +static inline void +sprd_pll_write(const struct sprd_pll *pll, u8 index, + u32 msk, u32 val) +{ + const struct sprd_clk_common *common = &pll->common; + unsigned int offset, reg; + int ret = 0; + + if (WARN_ON(index >= pll->regs_num)) + return; + + offset = common->reg + index * 4; + ret = sprd_regmap_read(common->regmap, offset, ®); + if (!ret) + sprd_regmap_write(common->regmap, offset, (reg & ~msk) | val); +} + +static unsigned long pll_get_refin(const struct sprd_pll *pll) +{ + u32 shift, mask, index, refin_id = 3; + const unsigned long refin[4] = { 2, 4, 13, 26 }; + + if (pwidth(pll, PLL_REFIN)) { + index = pindex(pll, PLL_REFIN); + shift = pshift(pll, PLL_REFIN); + mask = pmask(pll, PLL_REFIN); + refin_id = (sprd_pll_read(pll, index) & mask) >> shift; + if (refin_id > 3) + refin_id = 3; + } + + return refin[refin_id]; +} + +static u32 pll_get_ibias(u64 rate, const u64 *table) +{ + u32 i, num = table[0]; + + for (i = 1; i < num + 1; i++) + if (rate <= table[i]) + break; + + return (i == num + 1) ? num : i; +} + +static unsigned long _sprd_pll_recalc_rate(const struct sprd_pll *pll, + unsigned long parent_rate) +{ + u32 *cfg; + u32 i, mask, regs_num = pll->regs_num; + unsigned long rate, nint, kint = 0; + u64 refin; + u16 k1, k2; + + cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + + for (i = 0; i < regs_num; i++) + cfg[i] = sprd_pll_read(pll, i); + + refin = pll_get_refin(pll); + + if (pinternal(pll, cfg, PLL_PREDIV)) + refin = refin * 2; + + if (pwidth(pll, PLL_POSTDIV) && + ((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) || + (!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV)))) + refin = refin / 2; + + if (!pinternal(pll, cfg, PLL_DIV_S)) { + rate = refin * pinternal_val(pll, cfg, PLL_N) * CLK_PLL_10M; + } else { + nint = pinternal_val(pll, cfg, PLL_NINT); + if (pinternal(pll, cfg, PLL_SDM_EN)) + kint = pinternal_val(pll, cfg, PLL_KINT); + + mask = pmask(pll, PLL_KINT); + + k1 = pll->k1; + k2 = pll->k2; + rate = DIV_ROUND_CLOSEST_ULL(refin * kint * k1, + ((mask >> __ffs(mask)) + 1)) * + k2 + refin * nint * CLK_PLL_1M; + } + + return rate; +} + +#define SPRD_PLL_WRITE_CHECK(pll, i, mask, val) \ + (((sprd_pll_read(pll, i) & mask) == val) ? 0 : (-EFAULT)) + +static int _sprd_pll_set_rate(const struct sprd_pll *pll, + unsigned long rate, + unsigned long parent_rate) +{ + struct reg_cfg *cfg; + int ret = 0; + u32 mask, shift, width, ibias_val, index; + u32 regs_num = pll->regs_num, i = 0; + unsigned long kint, nint; + u64 tmp, refin, fvco = rate; + + cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + + refin = pll_get_refin(pll); + + mask = pmask(pll, PLL_PREDIV); + index = pindex(pll, PLL_PREDIV); + width = pwidth(pll, PLL_PREDIV); + if (width && (sprd_pll_read(pll, index) & mask)) + refin = refin * 2; + + mask = pmask(pll, PLL_POSTDIV); + index = pindex(pll, PLL_POSTDIV); + width = pwidth(pll, PLL_POSTDIV); + cfg[index].msk = mask; + if (width && ((pll->fflag == 1 && fvco <= pll->fvco) || + (pll->fflag == 0 && fvco > pll->fvco))) + cfg[index].val |= mask; + + if (width && fvco <= pll->fvco) + fvco = fvco * 2; + + mask = pmask(pll, PLL_DIV_S); + index = pindex(pll, PLL_DIV_S); + cfg[index].val |= mask; + cfg[index].msk |= mask; + + mask = pmask(pll, PLL_SDM_EN); + index = pindex(pll, PLL_SDM_EN); + cfg[index].val |= mask; + cfg[index].msk |= mask; + + nint = do_div(fvco, refin * CLK_PLL_1M); + mask = pmask(pll, PLL_NINT); + index = pindex(pll, PLL_NINT); + shift = pshift(pll, PLL_NINT); + cfg[index].val |= (nint << shift) & mask; + cfg[index].msk |= mask; + + mask = pmask(pll, PLL_KINT); + index = pindex(pll, PLL_KINT); + width = pwidth(pll, PLL_KINT); + shift = pshift(pll, PLL_KINT); + tmp = fvco - refin * nint * CLK_PLL_1M; + tmp = do_div(tmp, 10000) * ((mask >> shift) + 1); + kint = DIV_ROUND_CLOSEST_ULL(tmp, refin * 100); + cfg[index].val |= (kint << shift) & mask; + cfg[index].msk |= mask; + + ibias_val = pll_get_ibias(fvco, pll->itable); + + mask = pmask(pll, PLL_IBIAS); + index = pindex(pll, PLL_IBIAS); + shift = pshift(pll, PLL_IBIAS); + cfg[index].val |= ibias_val << shift & mask; + cfg[index].msk |= mask; + + for (i = 0; i < regs_num; i++) { + if (cfg[i].msk) { + sprd_pll_write(pll, i, cfg[i].msk, cfg[i].val); + ret |= SPRD_PLL_WRITE_CHECK(pll, i, cfg[i].msk, + cfg[i].val); + } + } + + if (!ret) + udelay(pll->udelay); + + return ret; +} + +static unsigned long sprd_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_pll *pll = hw_to_sprd_pll(hw); + + return _sprd_pll_recalc_rate(pll, parent_rate); +} + +static int sprd_pll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_pll *pll = hw_to_sprd_pll(hw); + + return _sprd_pll_set_rate(pll, rate, parent_rate); +} + +static int sprd_pll_clk_prepare(struct clk_hw *hw) +{ + struct sprd_pll *pll = hw_to_sprd_pll(hw); + + udelay(pll->udelay); + + return 0; +} + +static long sprd_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + return rate; +} + +const struct clk_ops sprd_pll_ops = { + .prepare = sprd_pll_clk_prepare, + .recalc_rate = sprd_pll_recalc_rate, + .round_rate = sprd_pll_round_rate, + .set_rate = sprd_pll_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_pll_ops); diff --git a/drivers/clk/sprd/pll.h b/drivers/clk/sprd/pll.h new file mode 100644 index 0000000..a25b003 --- /dev/null +++ b/drivers/clk/sprd/pll.h @@ -0,0 +1,110 @@ +/* + * Spreadtrum clock pll configurations + * + * Copyright (C) 2015~2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_PLL_H_ +#define _SPRD_PLL_H_ + +#include "common.h" + +struct reg_cfg { + u32 val; + u32 msk; +}; + +struct clk_bit_field { + u8 shift; + u8 width; +}; + +enum { + PLL_LOCK_DONE, + PLL_DIV_S, + PLL_MOD_EN, + PLL_SDM_EN, + PLL_REFIN, + PLL_IBIAS, + PLL_N, + PLL_NINT, + PLL_KINT, + PLL_PREDIV, + PLL_POSTDIV, + + PLL_FACT_MAX +}; + +/* + * struct sprd_pll - definition of adjustable pll clock + * + * @reg: registers used to set the configuration of pll clock, + * reg[0] shows how many registers this pll clock uses. + * @itable: pll ibias table, itable[0] means how many items this + * table includes + * @udelay delay time after setting rate + * @factors used to calculate the pll clock rate + * @fvco: fvco threshold rate + * @fflag: fvco flag + */ +struct sprd_pll { + u32 regs_num; + const u64 *itable; + const struct clk_bit_field *factors; + u16 udelay; + u16 k1; + u16 k2; + u16 fflag; + u64 fvco; + + struct sprd_clk_common common; +}; + +#define SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, _k1, _k2, _fflag, _fvco) \ + struct sprd_pll _struct = { \ + .regs_num = _regs_num, \ + .itable = _itable, \ + .factors = _factors, \ + .udelay = _udelay, \ + .k1 = _k1, \ + .k2 = _k2, \ + .fflag = _fflag, \ + .fvco = _fvco, \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &sprd_pll_ops, \ + 0), \ + }, \ + } + +#define SPRD_PLL_WITH_ITABLE_K(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, _k1, _k2) \ + SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, _k1, _k2, 0, 0) + +#define SPRD_PLL_WITH_ITABLE_1K(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, _udelay) \ + SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, 1000, 1000, 0, 0) + +static inline struct sprd_pll *hw_to_sprd_pll(struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_pll, common); +} + +extern const struct clk_ops sprd_pll_ops; + +#endif /* _SPRD_PLL_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 08/11] clk: sprd: add adjustable pll support @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Introduced a common adjustable pll clock driver for Spreadtrum SoCs. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Makefile | 1 + drivers/clk/sprd/pll.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sprd/pll.h | 110 +++++++++++++++++++ 3 files changed, 379 insertions(+) create mode 100644 drivers/clk/sprd/pll.c create mode 100644 drivers/clk/sprd/pll.h diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index 2262e76..d693969 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -5,3 +5,4 @@ clk-sprd-y += gate.o clk-sprd-y += mux.o clk-sprd-y += div.o clk-sprd-y += composite.o +clk-sprd-y += pll.o diff --git a/drivers/clk/sprd/pll.c b/drivers/clk/sprd/pll.c new file mode 100644 index 0000000..1fd8d32 --- /dev/null +++ b/drivers/clk/sprd/pll.c @@ -0,0 +1,268 @@ +/* + * Spreadtrum pll clock driver + * + * Copyright (C) 2015~2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +#include "pll.h" + +#define CLK_PLL_1M 1000000 +#define CLK_PLL_10M (CLK_PLL_1M * 10) + +#define pindex(pll, member) \ + (pll->factors[member].shift / (8 * sizeof(pll->regs_num))) + +#define pshift(pll, member) \ + (pll->factors[member].shift % (8 * sizeof(pll->regs_num))) + +#define pwidth(pll, member) \ + pll->factors[member].width + +#define pmask(pll, member) \ + ((pwidth(pll, member)) ? \ + GENMASK(pwidth(pll, member) + pshift(pll, member) - 1, \ + pshift(pll, member)) : 0) + +#define pinternal(pll, cfg, member) \ + (cfg[pindex(pll, member)] & pmask(pll, member)) + +#define pinternal_val(pll, cfg, member) \ + (pinternal(pll, cfg, member) >> pshift(pll, member)) + +static inline unsigned int +sprd_pll_read(const struct sprd_pll *pll, u8 index) +{ + const struct sprd_clk_common *common = &pll->common; + unsigned int val = 0; + + if (WARN_ON(index >= pll->regs_num)) + return 0; + + sprd_regmap_read(common->regmap, common->reg + index * 4, &val); + + return val; +} + +static inline void +sprd_pll_write(const struct sprd_pll *pll, u8 index, + u32 msk, u32 val) +{ + const struct sprd_clk_common *common = &pll->common; + unsigned int offset, reg; + int ret = 0; + + if (WARN_ON(index >= pll->regs_num)) + return; + + offset = common->reg + index * 4; + ret = sprd_regmap_read(common->regmap, offset, ®); + if (!ret) + sprd_regmap_write(common->regmap, offset, (reg & ~msk) | val); +} + +static unsigned long pll_get_refin(const struct sprd_pll *pll) +{ + u32 shift, mask, index, refin_id = 3; + const unsigned long refin[4] = { 2, 4, 13, 26 }; + + if (pwidth(pll, PLL_REFIN)) { + index = pindex(pll, PLL_REFIN); + shift = pshift(pll, PLL_REFIN); + mask = pmask(pll, PLL_REFIN); + refin_id = (sprd_pll_read(pll, index) & mask) >> shift; + if (refin_id > 3) + refin_id = 3; + } + + return refin[refin_id]; +} + +static u32 pll_get_ibias(u64 rate, const u64 *table) +{ + u32 i, num = table[0]; + + for (i = 1; i < num + 1; i++) + if (rate <= table[i]) + break; + + return (i == num + 1) ? num : i; +} + +static unsigned long _sprd_pll_recalc_rate(const struct sprd_pll *pll, + unsigned long parent_rate) +{ + u32 *cfg; + u32 i, mask, regs_num = pll->regs_num; + unsigned long rate, nint, kint = 0; + u64 refin; + u16 k1, k2; + + cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + + for (i = 0; i < regs_num; i++) + cfg[i] = sprd_pll_read(pll, i); + + refin = pll_get_refin(pll); + + if (pinternal(pll, cfg, PLL_PREDIV)) + refin = refin * 2; + + if (pwidth(pll, PLL_POSTDIV) && + ((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) || + (!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV)))) + refin = refin / 2; + + if (!pinternal(pll, cfg, PLL_DIV_S)) { + rate = refin * pinternal_val(pll, cfg, PLL_N) * CLK_PLL_10M; + } else { + nint = pinternal_val(pll, cfg, PLL_NINT); + if (pinternal(pll, cfg, PLL_SDM_EN)) + kint = pinternal_val(pll, cfg, PLL_KINT); + + mask = pmask(pll, PLL_KINT); + + k1 = pll->k1; + k2 = pll->k2; + rate = DIV_ROUND_CLOSEST_ULL(refin * kint * k1, + ((mask >> __ffs(mask)) + 1)) * + k2 + refin * nint * CLK_PLL_1M; + } + + return rate; +} + +#define SPRD_PLL_WRITE_CHECK(pll, i, mask, val) \ + (((sprd_pll_read(pll, i) & mask) == val) ? 0 : (-EFAULT)) + +static int _sprd_pll_set_rate(const struct sprd_pll *pll, + unsigned long rate, + unsigned long parent_rate) +{ + struct reg_cfg *cfg; + int ret = 0; + u32 mask, shift, width, ibias_val, index; + u32 regs_num = pll->regs_num, i = 0; + unsigned long kint, nint; + u64 tmp, refin, fvco = rate; + + cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + + refin = pll_get_refin(pll); + + mask = pmask(pll, PLL_PREDIV); + index = pindex(pll, PLL_PREDIV); + width = pwidth(pll, PLL_PREDIV); + if (width && (sprd_pll_read(pll, index) & mask)) + refin = refin * 2; + + mask = pmask(pll, PLL_POSTDIV); + index = pindex(pll, PLL_POSTDIV); + width = pwidth(pll, PLL_POSTDIV); + cfg[index].msk = mask; + if (width && ((pll->fflag == 1 && fvco <= pll->fvco) || + (pll->fflag == 0 && fvco > pll->fvco))) + cfg[index].val |= mask; + + if (width && fvco <= pll->fvco) + fvco = fvco * 2; + + mask = pmask(pll, PLL_DIV_S); + index = pindex(pll, PLL_DIV_S); + cfg[index].val |= mask; + cfg[index].msk |= mask; + + mask = pmask(pll, PLL_SDM_EN); + index = pindex(pll, PLL_SDM_EN); + cfg[index].val |= mask; + cfg[index].msk |= mask; + + nint = do_div(fvco, refin * CLK_PLL_1M); + mask = pmask(pll, PLL_NINT); + index = pindex(pll, PLL_NINT); + shift = pshift(pll, PLL_NINT); + cfg[index].val |= (nint << shift) & mask; + cfg[index].msk |= mask; + + mask = pmask(pll, PLL_KINT); + index = pindex(pll, PLL_KINT); + width = pwidth(pll, PLL_KINT); + shift = pshift(pll, PLL_KINT); + tmp = fvco - refin * nint * CLK_PLL_1M; + tmp = do_div(tmp, 10000) * ((mask >> shift) + 1); + kint = DIV_ROUND_CLOSEST_ULL(tmp, refin * 100); + cfg[index].val |= (kint << shift) & mask; + cfg[index].msk |= mask; + + ibias_val = pll_get_ibias(fvco, pll->itable); + + mask = pmask(pll, PLL_IBIAS); + index = pindex(pll, PLL_IBIAS); + shift = pshift(pll, PLL_IBIAS); + cfg[index].val |= ibias_val << shift & mask; + cfg[index].msk |= mask; + + for (i = 0; i < regs_num; i++) { + if (cfg[i].msk) { + sprd_pll_write(pll, i, cfg[i].msk, cfg[i].val); + ret |= SPRD_PLL_WRITE_CHECK(pll, i, cfg[i].msk, + cfg[i].val); + } + } + + if (!ret) + udelay(pll->udelay); + + return ret; +} + +static unsigned long sprd_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_pll *pll = hw_to_sprd_pll(hw); + + return _sprd_pll_recalc_rate(pll, parent_rate); +} + +static int sprd_pll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_pll *pll = hw_to_sprd_pll(hw); + + return _sprd_pll_set_rate(pll, rate, parent_rate); +} + +static int sprd_pll_clk_prepare(struct clk_hw *hw) +{ + struct sprd_pll *pll = hw_to_sprd_pll(hw); + + udelay(pll->udelay); + + return 0; +} + +static long sprd_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + return rate; +} + +const struct clk_ops sprd_pll_ops = { + .prepare = sprd_pll_clk_prepare, + .recalc_rate = sprd_pll_recalc_rate, + .round_rate = sprd_pll_round_rate, + .set_rate = sprd_pll_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_pll_ops); diff --git a/drivers/clk/sprd/pll.h b/drivers/clk/sprd/pll.h new file mode 100644 index 0000000..a25b003 --- /dev/null +++ b/drivers/clk/sprd/pll.h @@ -0,0 +1,110 @@ +/* + * Spreadtrum clock pll configurations + * + * Copyright (C) 2015~2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SPRD_PLL_H_ +#define _SPRD_PLL_H_ + +#include "common.h" + +struct reg_cfg { + u32 val; + u32 msk; +}; + +struct clk_bit_field { + u8 shift; + u8 width; +}; + +enum { + PLL_LOCK_DONE, + PLL_DIV_S, + PLL_MOD_EN, + PLL_SDM_EN, + PLL_REFIN, + PLL_IBIAS, + PLL_N, + PLL_NINT, + PLL_KINT, + PLL_PREDIV, + PLL_POSTDIV, + + PLL_FACT_MAX +}; + +/* + * struct sprd_pll - definition of adjustable pll clock + * + * @reg: registers used to set the configuration of pll clock, + * reg[0] shows how many registers this pll clock uses. + * @itable: pll ibias table, itable[0] means how many items this + * table includes + * @udelay delay time after setting rate + * @factors used to calculate the pll clock rate + * @fvco: fvco threshold rate + * @fflag: fvco flag + */ +struct sprd_pll { + u32 regs_num; + const u64 *itable; + const struct clk_bit_field *factors; + u16 udelay; + u16 k1; + u16 k2; + u16 fflag; + u64 fvco; + + struct sprd_clk_common common; +}; + +#define SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, _k1, _k2, _fflag, _fvco) \ + struct sprd_pll _struct = { \ + .regs_num = _regs_num, \ + .itable = _itable, \ + .factors = _factors, \ + .udelay = _udelay, \ + .k1 = _k1, \ + .k2 = _k2, \ + .fflag = _fflag, \ + .fvco = _fvco, \ + .common = { \ + .regmap = NULL, \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &sprd_pll_ops, \ + 0), \ + }, \ + } + +#define SPRD_PLL_WITH_ITABLE_K(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, _k1, _k2) \ + SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, _k1, _k2, 0, 0) + +#define SPRD_PLL_WITH_ITABLE_1K(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, _udelay) \ + SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \ + _regs_num, _itable, _factors, \ + _udelay, 1000, 1000, 0, 0) + +static inline struct sprd_pll *hw_to_sprd_pll(struct clk_hw *hw) +{ + struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); + + return container_of(common, struct sprd_pll, common); +} + +extern const struct clk_ops sprd_pll_ops; + +#endif /* _SPRD_PLL_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This patch added the list of clocks for Spreadtrum's SC9860 SoC, together with clock initialization code. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Kconfig | 10 + drivers/clk/sprd/Makefile | 3 + drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ 4 files changed, 2408 insertions(+) create mode 100644 drivers/clk/sprd/sc9860-clk.c create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig index 67a3287..8789247 100644 --- a/drivers/clk/sprd/Kconfig +++ b/drivers/clk/sprd/Kconfig @@ -2,3 +2,13 @@ config SPRD_COMMON_CLK tristate "Clock support for Spreadtrum SoCs" depends on ARCH_SPRD || COMPILE_TEST default ARCH_SPRD + +if SPRD_COMMON_CLK + +# SoC Drivers + +config SPRD_SC9860_CLK + tristate "Support for the Spreadtrum SC9860 clocks" + depends on (ARM64 && ARCH_SPRD) || COMPILE_TEST + default ARM64 && ARCH_SPRD +endif diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index d693969..b0d81e5 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -6,3 +6,6 @@ clk-sprd-y += mux.o clk-sprd-y += div.o clk-sprd-y += composite.o clk-sprd-y += pll.o + +## SoC support +obj-$(CONFIG_SPRD_SC9860_CLK) += sc9860-clk.o diff --git a/drivers/clk/sprd/sc9860-clk.c b/drivers/clk/sprd/sc9860-clk.c new file mode 100644 index 0000000..09e19ff --- /dev/null +++ b/drivers/clk/sprd/sc9860-clk.c @@ -0,0 +1,1987 @@ +/* + * Spreatrum SC9860 clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include <dt-bindings/clock/sprd,sc9860-clk.h> + +#include "common.h" +#include "composite.h" +#include "div.h" +#include "gate.h" +#include "mux.h" +#include "pll.h" + +static CLK_FIXED_RATE(ext_rco_100m, "ext-rco-100m", 0, 100000000, 0); +static CLK_FIXED_RATE(ext_32k, "ext-32k", 0, 32768, 0); + +static CLK_FIXED_FACTOR(fac_4m, "fac-4m", "ext-26m", + 6, 1, 0); +static CLK_FIXED_FACTOR(fac_2m, "fac-2m", "ext-26m", + 13, 1, 0); +static CLK_FIXED_FACTOR(fac_1m, "fac-1m", "ext-26m", + 26, 1, 0); +static CLK_FIXED_FACTOR(fac_250k, "fac-250k", "ext-26m", + 104, 1, 0); +static CLK_FIXED_FACTOR(fac_rpll0_26m, "rpll0-26m", "ext-26m", + 1, 1, 0); +static CLK_FIXED_FACTOR(fac_rpll1_26m, "rpll1-26m", "ext-26m", + 1, 1, 0); +static CLK_FIXED_FACTOR(fac_rco_25m, "rco-25m", "ext-rc0-100m", + 4, 1, 0); +static CLK_FIXED_FACTOR(fac_rco_4m, "rco-4m", "ext-rc0-100m", + 25, 1, 0); +static CLK_FIXED_FACTOR(fac_rco_2m, "rco-2m", "ext-rc0-100m", + 50, 1, 0); +static CLK_FIXED_FACTOR(fac_3k2, "fac-3k2", "ext-32k", + 10, 1, 0); +static CLK_FIXED_FACTOR(fac_1k, "fac-1k", "ext-32k", + 32, 1, 0); + +static SPRD_GATE_CLK(mpll0_gate, "mpll0-gate", "ext-26m", 0xb0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mpll1_gate, "mpll1-gate", "ext-26m", 0xb0, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dpll0_gate, "dpll0-gate", "ext-26m", 0xb4, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dpll1_gate, "dpll1-gate", "ext-26m", 0xb4, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ltepll0_gate, "ltepll0-gate", "ext-26m", 0xb8, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(twpll_gate, "twpll-gate", "ext-26m", 0xbc, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ltepll1_gate, "ltepll1-gate", "ext-26m", 0x10c, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rpll0_gate, "rpll0-gate", "ext-26m", 0x16c, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(rpll1_gate, "rpll1-gate", "ext-26m", 0x16c, + 0x1000, BIT(18), 0, 0); +static SPRD_GATE_CLK(cppll_gate, "cppll-gate", "ext-26m", 0x2b4, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpll_gate, "gpll-gate", "ext-26m", 0x32c, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, CLK_GATE_SET_TO_DISABLE); + +static struct sprd_clk_common *sc9860_pmu_gate_clks[] = { + /* address base is 0x402b0000 */ + &mpll0_gate.common, + &mpll1_gate.common, + &dpll0_gate.common, + &dpll1_gate.common, + <epll0_gate.common, + &twpll_gate.common, + <epll1_gate.common, + &rpll0_gate.common, + &rpll1_gate.common, + &cppll_gate.common, + &gpll_gate.common, +}; + +static struct clk_hw_onecell_data sc9860_pmu_gate_hws = { + .hws = { + [CLK_EXT_RCO_100M] = &ext_rco_100m.hw, + [CLK_EXT_32K] = &ext_32k.hw, + [CLK_FAC_4M] = &fac_4m.hw, + [CLK_FAC_2M] = &fac_2m.hw, + [CLK_FAC_1M] = &fac_1m.hw, + [CLK_FAC_250K] = &fac_250k.hw, + [CLK_FAC_RPLL0_26M] = &fac_rpll0_26m.hw, + [CLK_FAC_RPLL1_26M] = &fac_rpll1_26m.hw, + [CLK_FAC_RCO25M] = &fac_rco_25m.hw, + [CLK_FAC_RCO4M] = &fac_rco_4m.hw, + [CLK_FAC_RCO2M] = &fac_rco_2m.hw, + [CLK_FAC_3K2] = &fac_3k2.hw, + [CLK_FAC_1K] = &fac_1k.hw, + [CLK_MPLL0_GATE] = &mpll0_gate.common.hw, + [CLK_MPLL1_GATE] = &mpll1_gate.common.hw, + [CLK_DPLL0_GATE] = &dpll0_gate.common.hw, + [CLK_DPLL1_GATE] = &dpll1_gate.common.hw, + [CLK_LTEPLL0_GATE] = <epll0_gate.common.hw, + [CLK_TWPLL_GATE] = &twpll_gate.common.hw, + [CLK_LTEPLL1_GATE] = <epll1_gate.common.hw, + [CLK_RPLL0_GATE] = &rpll0_gate.common.hw, + [CLK_RPLL1_GATE] = &rpll1_gate.common.hw, + [CLK_CPPLL_GATE] = &cppll_gate.common.hw, + [CLK_GPLL_GATE] = &gpll_gate.common.hw, + }, + .num = CLK_PMU_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_pmu_gate_desc = { + .clk_clks = sc9860_pmu_gate_clks, + .num_clk_clks = ARRAY_SIZE(sc9860_pmu_gate_clks), + .hw_clks = &sc9860_pmu_gate_hws, +}; + +/* GPLL/LPLL/DPLL/RPLL/CPLL */ +static const u64 const itable1[4] = {3, 780000000, 988000000, 1196000000}; + +/* TWPLL/MPLL0/MPLL1 */ +static const u64 itable2[4] = {3, 1638000000, 2080000000, 2600000000UL}; + +static const struct clk_bit_field const f_mpll0[PLL_FACT_MAX] = { + { .shift = 20, .width = 1 }, /* lock_done */ + { .shift = 19, .width = 1 }, /* div_s */ + { .shift = 18, .width = 1 }, /* mod_en */ + { .shift = 17, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 11, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 56, .width = 1 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_K_FVCO(mpll0_clk, "mpll0", "mpll0-gate", 0x24, + 2, itable2, f_mpll0, 200, + 1000, 1000, 1, 1300000000); + +static const struct clk_bit_field const f_mpll1[PLL_FACT_MAX] = { + { .shift = 20, .width = 1 }, /* lock_done */ + { .shift = 19, .width = 1 }, /* div_s */ + { .shift = 18, .width = 1 }, /* mod_en */ + { .shift = 17, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 11, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 56, .width = 1 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(mpll1_clk, "mpll1", "mpll1-gate", 0x2c, + 2, itable2, f_mpll1, 200); + +static const struct clk_bit_field const f_dpll[PLL_FACT_MAX] = { + { .shift = 16, .width = 1 }, /* lock_done */ + { .shift = 15, .width = 1 }, /* div_s */ + { .shift = 14, .width = 1 }, /* mod_en */ + { .shift = 13, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 8, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(dpll0_clk, "dpll0", "dpll0-gate", 0x34, + 2, itable1, f_dpll, 200); + +static SPRD_PLL_WITH_ITABLE_1K(dpll1_clk, "dpll1", "dpll1-gate", 0x3c, + 2, itable1, f_dpll, 200); + +static const struct clk_bit_field const f_rpll[PLL_FACT_MAX] = { + { .shift = 0, .width = 1 }, /* lock_done */ + { .shift = 3, .width = 1 }, /* div_s */ + { .shift = 80, .width = 1 }, /* mod_en */ + { .shift = 81, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 14, .width = 2 }, /* ibias */ + { .shift = 16, .width = 7 }, /* n */ + { .shift = 4, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(rpll0_clk, "rpll0", "rpll0-gate", 0x44, + 3, itable1, f_rpll, 200); + +static SPRD_PLL_WITH_ITABLE_1K(rpll1_clk, "rpll1", "rpll1-gate", 0x50, + 3, itable1, f_rpll, 200); + +static const struct clk_bit_field const f_twpll[PLL_FACT_MAX] = { + { .shift = 21, .width = 1 }, /* lock_done */ + { .shift = 20, .width = 1 }, /* div_s */ + { .shift = 19, .width = 1 }, /* mod_en */ + { .shift = 18, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 13, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(twpll_clk, "twpll", "twpll-gate", 0x5c, + 2, itable2, f_twpll, 200); + +static const struct clk_bit_field const f_ltepll[PLL_FACT_MAX] = { + { .shift = 31, .width = 1 }, /* lock_done */ + { .shift = 27, .width = 1 }, /* div_s */ + { .shift = 26, .width = 1 }, /* mod_en */ + { .shift = 25, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 20, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(ltepll0_clk, "ltepll0", "ltepll0-gate", + 0x64, 2, itable1, + f_ltepll, 200); +static SPRD_PLL_WITH_ITABLE_1K(ltepll1_clk, "ltepll1", "ltepll1-gate", + 0x6c, 2, itable1, + f_ltepll, 200); + +static const struct clk_bit_field const f_gpll[PLL_FACT_MAX] = { + { .shift = 18, .width = 1 }, /* lock_done */ + { .shift = 15, .width = 1 }, /* div_s */ + { .shift = 14, .width = 1 }, /* mod_en */ + { .shift = 13, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 8, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 17, .width = 1 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_K_FVCO(gpll_clk, "gpll", "gpll-gate", 0x9c, + 2, itable1, f_gpll, 200, + 1000, 1000, 1, 600000000); + +static const struct clk_bit_field const f_cppll[PLL_FACT_MAX] = { + { .shift = 17, .width = 1 }, /* lock_done */ + { .shift = 15, .width = 1 }, /* div_s */ + { .shift = 14, .width = 1 }, /* mod_en */ + { .shift = 13, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 8, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(cppll_clk, "cppll", "cppll-gate", 0xc4, + 2, itable1, f_cppll, 200); + +static CLK_FIXED_FACTOR(gpll_42m5, "gpll-42m5", "gpll", 20, 1, 0); +static CLK_FIXED_FACTOR(twpll_768m, "twpll-768m", "twpll", 2, 1, 0); +static CLK_FIXED_FACTOR(twpll_384m, "twpll-384m", "twpll", 4, 1, 0); +static CLK_FIXED_FACTOR(twpll_192m, "twpll-192m", "twpll", 8, 1, 0); +static CLK_FIXED_FACTOR(twpll_96m, "twpll-96m", "twpll", 16, 1, 0); +static CLK_FIXED_FACTOR(twpll_48m, "twpll-48m", "twpll", 32, 1, 0); +static CLK_FIXED_FACTOR(twpll_24m, "twpll-24m", "twpll", 64, 1, 0); +static CLK_FIXED_FACTOR(twpll_12m, "twpll-12m", "twpll", 128, 1, 0); +static CLK_FIXED_FACTOR(twpll_512m, "twpll-512m", "twpll", 3, 1, 0); +static CLK_FIXED_FACTOR(twpll_256m, "twpll-256m", "twpll", 6, 1, 0); +static CLK_FIXED_FACTOR(twpll_128m, "twpll-128m", "twpll", 12, 1, 0); +static CLK_FIXED_FACTOR(twpll_64m, "twpll-64m", "twpll", 24, 1, 0); +static CLK_FIXED_FACTOR(twpll_307m2, "twpll-307m2", "twpll", 5, 1, 0); +static CLK_FIXED_FACTOR(twpll_153m6, "twpll-153m6", "twpll", 10, 1, 0); +static CLK_FIXED_FACTOR(twpll_76m8, "twpll-76m8", "twpll", 20, 1, 0); +static CLK_FIXED_FACTOR(twpll_51m2, "twpll-51m2", "twpll", 30, 1, 0); +static CLK_FIXED_FACTOR(twpll_38m4, "twpll-38m4", "twpll", 40, 1, 0); +static CLK_FIXED_FACTOR(twpll_19m2, "twpll-19m2", "twpll", 80, 1, 0); +static CLK_FIXED_FACTOR(l0_614m4, "l0-614m4", "ltepll0", 2, 1, 0); +static CLK_FIXED_FACTOR(l0_409m6, "l0-409m6", "ltepll0", 3, 1, 0); +static CLK_FIXED_FACTOR(l0_38m, "l0-38m", "ltepll0", 32, 1, 0); +static CLK_FIXED_FACTOR(l1_38m, "l1-38m", "ltepll1", 32, 1, 0); +static CLK_FIXED_FACTOR(rpll0_192m, "rpll0-192m", "rpll0", 6, 1, 0); +static CLK_FIXED_FACTOR(rpll0_96m, "rpll0-96m", "rpll0", 12, 1, 0); +static CLK_FIXED_FACTOR(rpll0_48m, "rpll0-48m", "rpll0", 24, 1, 0); +static CLK_FIXED_FACTOR(rpll1_468m, "rpll1-468m", "rpll1", 2, 1, 0); +static CLK_FIXED_FACTOR(rpll1_192m, "rpll1-192m", "rpll1", 6, 1, 0); +static CLK_FIXED_FACTOR(rpll1_96m, "rpll1-96m", "rpll1", 12, 1, 0); +static CLK_FIXED_FACTOR(rpll1_64m, "rpll1-64m", "rpll1", 18, 1, 0); +static CLK_FIXED_FACTOR(rpll1_48m, "rpll1-48m", "rpll1", 24, 1, 0); +static CLK_FIXED_FACTOR(dpll0_50m, "dpll0-50m", "dpll0", 16, 1, 0); +static CLK_FIXED_FACTOR(dpll1_50m, "dpll1-50m", "dpll1", 16, 1, 0); +static CLK_FIXED_FACTOR(cppll_50m, "cppll-50m", "cppll", 18, 1, 0); +static CLK_FIXED_FACTOR(m0_39m, "m0-39m", "mpll0", 32, 1, 0); +static CLK_FIXED_FACTOR(m1_63m, "m1-63m", "mpll1", 32, 1, 0); + +static struct sprd_clk_common *sc9860_pll_clks[] = { + /* address base is 0x40400000 */ + &mpll0_clk.common, + &mpll1_clk.common, + &dpll0_clk.common, + &dpll1_clk.common, + &rpll0_clk.common, + &rpll1_clk.common, + &twpll_clk.common, + <epll0_clk.common, + <epll1_clk.common, + &gpll_clk.common, + &cppll_clk.common, +}; + +static struct clk_hw_onecell_data sc9860_pll_hws = { + .hws = { + [CLK_MPLL0] = &mpll0_clk.common.hw, + [CLK_MPLL1] = &mpll1_clk.common.hw, + [CLK_DPLL0] = &dpll0_clk.common.hw, + [CLK_DPLL1] = &dpll1_clk.common.hw, + [CLK_RPLL0] = &rpll0_clk.common.hw, + [CLK_RPLL1] = &rpll1_clk.common.hw, + [CLK_TWPLL] = &twpll_clk.common.hw, + [CLK_LTEPLL0] = <epll0_clk.common.hw, + [CLK_LTEPLL1] = <epll1_clk.common.hw, + [CLK_GPLL] = &gpll_clk.common.hw, + [CLK_CPPLL] = &cppll_clk.common.hw, + [CLK_GPLL_42M5] = &gpll_42m5.hw, + [CLK_TWPLL_768M] = &twpll_768m.hw, + [CLK_TWPLL_384M] = &twpll_384m.hw, + [CLK_TWPLL_192M] = &twpll_192m.hw, + [CLK_TWPLL_96M] = &twpll_96m.hw, + [CLK_TWPLL_48M] = &twpll_48m.hw, + [CLK_TWPLL_24M] = &twpll_24m.hw, + [CLK_TWPLL_12M] = &twpll_12m.hw, + [CLK_TWPLL_512M] = &twpll_512m.hw, + [CLK_TWPLL_256M] = &twpll_256m.hw, + [CLK_TWPLL_128M] = &twpll_128m.hw, + [CLK_TWPLL_64M] = &twpll_64m.hw, + [CLK_TWPLL_307M2] = &twpll_307m2.hw, + [CLK_TWPLL_153M6] = &twpll_153m6.hw, + [CLK_TWPLL_76M8] = &twpll_76m8.hw, + [CLK_TWPLL_51M2] = &twpll_51m2.hw, + [CLK_TWPLL_38M4] = &twpll_38m4.hw, + [CLK_TWPLL_19M2] = &twpll_19m2.hw, + [CLK_L0_614M4] = &l0_614m4.hw, + [CLK_L0_409M6] = &l0_409m6.hw, + [CLK_L0_38M] = &l0_38m.hw, + [CLK_L1_38M] = &l1_38m.hw, + [CLK_RPLL0_192M] = &rpll0_192m.hw, + [CLK_RPLL0_96M] = &rpll0_96m.hw, + [CLK_RPLL0_48M] = &rpll0_48m.hw, + [CLK_RPLL1_468M] = &rpll1_468m.hw, + [CLK_RPLL1_192M] = &rpll1_192m.hw, + [CLK_RPLL1_96M] = &rpll1_96m.hw, + [CLK_RPLL1_64M] = &rpll1_64m.hw, + [CLK_RPLL1_48M] = &rpll1_48m.hw, + [CLK_DPLL0_50M] = &dpll0_50m.hw, + [CLK_DPLL1_50M] = &dpll1_50m.hw, + [CLK_CPPLL_50M] = &cppll_50m.hw, + [CLK_M0_39M] = &m0_39m.hw, + [CLK_M1_63M] = &m1_63m.hw, + }, + .num = CLK_PLL_NUM, +}; + +static const struct sprd_clk_desc sc9860_pll_desc = { + .clk_clks = sc9860_pll_clks, + .num_clk_clks = ARRAY_SIZE(sc9860_pll_clks), + .hw_clks = &sc9860_pll_hws, +}; + +#define SC9860_MUX_FLAG \ + (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_NO_REPARENT) + +static const char * const ap_apb_parents[] = { "ext-26m", "twpll-64m", + "twpll-96m", "twpll-128m" }; +static SPRD_MUX_CLK(ap_apb, "ap-apb", ap_apb_parents, NULL, + 0x20, 0, 1, SC9860_MUX_FLAG); + +static const char * const ap_apb_usb3[] = { "ext-32k", "twpll-24m" }; +static SPRD_MUX_CLK(ap_usb3, "ap-usb3", ap_apb_usb3, NULL, + 0x2c, 0, 1, SC9860_MUX_FLAG); + +static const char * const uart_parents[] = { "ext-26m", "twpll-48m", + "twpll-51m2", "twpll-96m" }; +static SPRD_COMP_CLK(uart0_clk, "uart0", uart_parents, 0x30, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart1_clk, "uart1", uart_parents, 0x34, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart2_clk, "uart2", uart_parents, 0x38, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart3_clk, "uart3", uart_parents, 0x3c, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart4_clk, "uart4", uart_parents, 0x40, + 0, 0, 2, 8, 3, 0); + +static const char * const i2c_parents[] = { "ext-26m", "twpll-48m", + "twpll-51m2", "twpll-153m6" }; +static SPRD_COMP_CLK(i2c0_clk, "i2c0", i2c_parents, 0x44, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c1_clk, "i2c1", i2c_parents, 0x48, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c2_clk, "i2c2", i2c_parents, 0x4c, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c3_clk, "i2c3", i2c_parents, 0x50, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c4_clk, "i2c4", i2c_parents, 0x54, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c5_clk, "i2c5", i2c_parents, 0x58, + 0, 0, 2, 8, 3, 0); + +static const char * const spi_parents[] = { "ext-26m", "twpll-128m", + "twpll-153m6", "twpll-192m" }; +static SPRD_COMP_CLK(spi0_clk, "spi0", spi_parents, 0x5c, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(spi1_clk, "spi1", spi_parents, 0x60, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(spi2_clk, "spi2", spi_parents, 0x64, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(spi3_clk, "spi3", spi_parents, 0x68, + 0, 0, 2, 8, 3, 0); + +static const char * const iis_parents[] = { "ext-26m", + "twpll-128m", + "twpll-153m6" }; +static SPRD_COMP_CLK(iis0_clk, "iis0", iis_parents, 0x6c, + 0, 0, 2, 8, 6, 0); +static SPRD_COMP_CLK(iis1_clk, "iis1", iis_parents, 0x70, + 0, 0, 2, 8, 6, 0); +static SPRD_COMP_CLK(iis2_clk, "iis2", iis_parents, 0x74, + 0, 0, 2, 8, 6, 0); +static SPRD_COMP_CLK(iis3_clk, "iis3", iis_parents, 0x78, + 0, 0, 2, 8, 6, 0); + +static struct sprd_clk_common *sc9860_ap_clks[] = { + /* address base is 0x20000000 */ + &ap_apb.common, + &ap_usb3.common, + &uart0_clk.common, + &uart1_clk.common, + &uart2_clk.common, + &uart3_clk.common, + &uart4_clk.common, + &i2c0_clk.common, + &i2c1_clk.common, + &i2c2_clk.common, + &i2c3_clk.common, + &i2c4_clk.common, + &i2c5_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &spi2_clk.common, + &spi3_clk.common, + &iis0_clk.common, + &iis1_clk.common, + &iis2_clk.common, + &iis3_clk.common, +}; + +static struct clk_hw_onecell_data sc9860_ap_clk_hws = { + .hws = { + [CLK_AP_APB] = &ap_apb.common.hw, + [CLK_AP_USB3] = &ap_usb3.common.hw, + [CLK_UART0] = &uart0_clk.common.hw, + [CLK_UART1] = &uart1_clk.common.hw, + [CLK_UART2] = &uart2_clk.common.hw, + [CLK_UART3] = &uart3_clk.common.hw, + [CLK_UART4] = &uart4_clk.common.hw, + [CLK_I2C0] = &i2c0_clk.common.hw, + [CLK_I2C1] = &i2c1_clk.common.hw, + [CLK_I2C2] = &i2c2_clk.common.hw, + [CLK_I2C3] = &i2c3_clk.common.hw, + [CLK_I2C4] = &i2c4_clk.common.hw, + [CLK_I2C5] = &i2c5_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_SPI2] = &spi2_clk.common.hw, + [CLK_SPI3] = &spi3_clk.common.hw, + [CLK_IIS0] = &iis0_clk.common.hw, + [CLK_IIS1] = &iis1_clk.common.hw, + [CLK_IIS2] = &iis2_clk.common.hw, + [CLK_IIS3] = &iis3_clk.common.hw, + }, + .num = CLK_AP_CLK_NUM, +}; + +static const struct sprd_clk_desc sc9860_ap_clk_desc = { + .clk_clks = sc9860_ap_clks, + .num_clk_clks = ARRAY_SIZE(sc9860_ap_clks), + .hw_clks = &sc9860_ap_clk_hws, +}; + +static const char * const aon_apb_parents[] = { "rco-25m", "ext-26m", + "ext-rco-100m", "twpll-96m", + "twpll-128m", + "twpll-153m6" }; +static SPRD_COMP_CLK(aon_apb, "aon-apb", aon_apb_parents, 0x230, + 0, 0, 3, 8, 2, 0); + +static const char * const aux_parents[] = { "ext-32k", "rpll0-26m", + "rpll1-26m", "ext-26m", + "cppll-50m", "rco-25m", + "dpll0-50m", "dpll1-50m", + "gpll-42m5", "twpll-48m", + "m0-39m", "m1-63m", + "l0-38m", "l1-38m" }; + +static SPRD_COMP_CLK(aux0_clk, "aux0", aux_parents, 0x238, + 0, 0, 5, 8, 4, 0); +static SPRD_COMP_CLK(aux1_clk, "aux1", aux_parents, 0x23c, + 0, 0, 5, 8, 4, 0); +static SPRD_COMP_CLK(aux2_clk, "aux2", aux_parents, 0x240, + 0, 0, 5, 8, 4, 0); +static SPRD_COMP_CLK(probe_clk, "probe", aux_parents, 0x244, + 0, 0, 5, 8, 4, 0); + +static const char * const sp_ahb_parents[] = { "rco-4m", "ext-26m", + "ext-rco-100m", "twpll-96m", + "twpll-128m", + "twpll-153m6" }; +static SPRD_COMP_CLK(sp_ahb, "sp-ahb", sp_ahb_parents, 0x2d0, + 0, 0, 3, 8, 2, 0); + +static const char * const cci_parents[] = { "ext-26m", "twpll-384m", + "l0-614m4", "twpll-768m" }; +static SPRD_COMP_CLK(cci_clk, "cci", cci_parents, 0x300, + 0, 0, 2, 8, 2, 0); +static SPRD_COMP_CLK(gic_clk, "gic", cci_parents, 0x304, + 0, 0, 2, 8, 2, 0); +static SPRD_COMP_CLK(cssys_clk, "cssys", cci_parents, 0x310, + 0, 0, 2, 8, 2, 0); + +static const char * const sdio_2x_parents[] = { "fac-1m", "ext-26m", + "twpll-307m2", "twpll-384m", + "l0-409m6" }; +static SPRD_COMP_CLK(sdio0_2x, "sdio0-2x", sdio_2x_parents, 0x328, + 0, 0, 3, 8, 4, 0); +static SPRD_COMP_CLK(sdio1_2x, "sdio1-2x", sdio_2x_parents, 0x330, + 0, 0, 3, 8, 4, 0); +static SPRD_COMP_CLK(sdio2_2x, "sdio2-2x", sdio_2x_parents, 0x338, + 0, 0, 3, 8, 4, 0); +static SPRD_COMP_CLK(emmc_2x, "emmc-2x", sdio_2x_parents, 0x340, + 0, 0, 3, 8, 4, 0); + +static SPRD_DIV_CLK(sdio0_1x, "sdio0-1x", "sdio0-2x", 0x32c, + 8, 1, 0); +static SPRD_DIV_CLK(sdio1_1x, "sdio1-1x", "sdio1-2x", 0x334, + 8, 1, 0); +static SPRD_DIV_CLK(sdio2_1x, "sdio2-1x", "sdio2-2x", 0x33c, + 8, 1, 0); +static SPRD_DIV_CLK(emmc_1x, "emmc-1x", "emmc-2x", 0x344, + 8, 1, 0); + +static const char * const adi_parents[] = { "rco-4m", "ext-26m", + "rco-25m", "twpll-38m4", + "twpll-51m2" }; +static SPRD_MUX_CLK(adi_clk, "adi", adi_parents, NULL, 0x234, + 0, 3, SC9860_MUX_FLAG); + +static const char * const pwm_parents[] = { "ext-32k", "ext-26m", + "rco-4m", "rco-25m", + "twpll-48m" }; +static SPRD_MUX_CLK(pwm0_clk, "pwm0", pwm_parents, NULL, 0x248, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(pwm1_clk, "pwm1", pwm_parents, NULL, 0x24c, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(pwm2_clk, "pwm2", pwm_parents, NULL, 0x250, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(pwm3_clk, "pwm3", pwm_parents, NULL, 0x254, + 0, 3, SC9860_MUX_FLAG); + +static const char * const efuse_parents[] = { "rco-25m", "ext-26m" }; +static SPRD_MUX_CLK(efuse_clk, "efuse", efuse_parents, NULL, 0x258, + 0, 1, SC9860_MUX_FLAG); + +static const char * const cm3_uart_parents[] = { "rco-4m", "ext-26m", + "rco-100m", "twpll-48m", + "twpll-51m2", "twpll-96m", + "twpll-128m" }; +static SPRD_MUX_CLK(cm3_uart0, "cm3-uart0", cm3_uart_parents, NULL, 0x25c, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(cm3_uart1, "cm3-uart1", cm3_uart_parents, NULL, 0x260, + 0, 3, SC9860_MUX_FLAG); + +static const char * const thm_parents[] = { "ext-32k", "fac-250k" }; +static SPRD_MUX_CLK(thm_clk, "thm", thm_parents, NULL, 0x270, + 0, 1, SC9860_MUX_FLAG); + +static const char * const cm3_i2c_parents[] = { "rco-4m", + "ext-26m", + "rco-100m", + "twpll-48m", + "twpll-51m2", + "twpll-153m6" }; +static SPRD_MUX_CLK(cm3_i2c0, "cm3-i2c0", cm3_i2c_parents, NULL, 0x274, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(cm3_i2c1, "cm3-i2c1", cm3_i2c_parents, NULL, 0x278, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(aon_i2c, "aon-i2c", cm3_i2c_parents, NULL, 0x280, + 0, 3, SC9860_MUX_FLAG); + +static const char * const cm4_spi_parents[] = { "ext-26m", "twpll-96m", + "rco-100m", "twpll-128m", + "twpll-153m6", "twpll-192m" }; +static SPRD_MUX_CLK(cm4_spi, "cm4-spi", cm4_spi_parents, NULL, 0x27c, + 0, 3, SC9860_MUX_FLAG); + +static SPRD_MUX_CLK(avs_clk, "avs", uart_parents, NULL, 0x284, + 0, 2, SC9860_MUX_FLAG); + +static const char * const ca53_dap_parents[] = { "ext-26m", "rco-4m", + "rco-100m", "twpll-76m8", + "twpll-128m", "twpll-153m6" }; +static SPRD_MUX_CLK(ca53_dap, "ca53-dap", ca53_dap_parents, NULL, 0x288, + 0, 3, SC9860_MUX_FLAG); + +static const char * const ca53_ts_parents[] = { "ext-32k", "ext-26m", + "clk-twpll-128m", + "clk-twpll-153m6" }; +static SPRD_MUX_CLK(ca53_ts, "ca53-ts", ca53_ts_parents, NULL, 0x290, + 0, 2, SC9860_MUX_FLAG); + +static const char * const djtag_tck_parents[] = { "rco-4m", "ext-26m" }; +static SPRD_MUX_CLK(djtag_tck, "djtag-tck", djtag_tck_parents, NULL, + 0x2c8, 0, 1, SC9860_MUX_FLAG); + +static const char * const pmu_parents[] = { "ext-32k", "rco-4m", "clk-4m" }; +static SPRD_MUX_CLK(pmu_clk, "pmu", pmu_parents, NULL, 0x2e0, + 0, 2, SC9860_MUX_FLAG); + +static const char * const pmu_26m_parents[] = { "rco-25m", "ext-26m" }; +static SPRD_MUX_CLK(pmu_26m, "pmu-26m", pmu_26m_parents, NULL, + 0x2e4, 0, 1, SC9860_MUX_FLAG); + +static const char * const debounce_parents[] = { "ext-32k", "rco-4m", + "rco-25m", "ext-26m" }; +static SPRD_MUX_CLK(debounce_clk, "debounce", debounce_parents, NULL, + 0x2e8, 0, 2, SC9860_MUX_FLAG); + +static const char * const otg2_ref_parents[] = { "twpll-12m", "twpll-24m" }; +static SPRD_MUX_CLK(otg2_ref, "otg2-ref", otg2_ref_parents, NULL, + 0x2f4, 0, 1, SC9860_MUX_FLAG); + +static const char * const usb3_ref_parents[] = { "twpll-24m", "twpll-19m2", + "twpll-48m" }; +static SPRD_MUX_CLK(usb3_ref, "usb3-ref", usb3_ref_parents, NULL, + 0x2f8, 0, 2, SC9860_MUX_FLAG); + +static const char * const ap_axi_parents[] = { "ext-26m", "twpll-76m8", + "twpll-128m", "twpll-256m" }; +static SPRD_MUX_CLK(ap_axi, "ap-axi", ap_axi_parents, NULL, + 0x324, 0, 2, SC9860_MUX_FLAG); + +static struct sprd_clk_common *sc9860_aon_prediv[] = { + /* address base is 0x402d0000 */ + &aon_apb.common, + &aux0_clk.common, + &aux1_clk.common, + &aux2_clk.common, + &probe_clk.common, + &sp_ahb.common, + &cci_clk.common, + &gic_clk.common, + &cssys_clk.common, + &sdio0_2x.common, + &sdio1_2x.common, + &sdio2_2x.common, + &emmc_2x.common, + &sdio0_1x.common, + &sdio1_1x.common, + &sdio2_1x.common, + &emmc_1x.common, + &adi_clk.common, + &pwm0_clk.common, + &pwm1_clk.common, + &pwm2_clk.common, + &pwm3_clk.common, + &efuse_clk.common, + &cm3_uart0.common, + &cm3_uart1.common, + &thm_clk.common, + &cm3_i2c0.common, + &cm3_i2c1.common, + &cm4_spi.common, + &aon_i2c.common, + &avs_clk.common, + &ca53_dap.common, + &ca53_ts.common, + &djtag_tck.common, + &pmu_clk.common, + &pmu_26m.common, + &debounce_clk.common, + &otg2_ref.common, + &usb3_ref.common, + &ap_axi.common, +}; + +static struct clk_hw_onecell_data sc9860_aon_prediv_hws = { + .hws = { + [CLK_AON_APB] = &aon_apb.common.hw, + [CLK_AUX0] = &aux0_clk.common.hw, + [CLK_AUX1] = &aux1_clk.common.hw, + [CLK_AUX2] = &aux2_clk.common.hw, + [CLK_PROBE] = &probe_clk.common.hw, + [CLK_SP_AHB] = &sp_ahb.common.hw, + [CLK_CCI] = &cci_clk.common.hw, + [CLK_GIC] = &gic_clk.common.hw, + [CLK_CSSYS] = &cssys_clk.common.hw, + [CLK_SDIO0_2X] = &sdio0_2x.common.hw, + [CLK_SDIO1_2X] = &sdio1_2x.common.hw, + [CLK_SDIO2_2X] = &sdio2_2x.common.hw, + [CLK_EMMC_2X] = &emmc_2x.common.hw, + [CLK_SDIO0_1X] = &sdio0_1x.common.hw, + [CLK_SDIO1_1X] = &sdio1_1x.common.hw, + [CLK_SDIO2_1X] = &sdio2_1x.common.hw, + [CLK_EMMC_1X] = &emmc_1x.common.hw, + [CLK_ADI] = &adi_clk.common.hw, + [CLK_PWM0] = &pwm0_clk.common.hw, + [CLK_PWM1] = &pwm1_clk.common.hw, + [CLK_PWM2] = &pwm2_clk.common.hw, + [CLK_PWM3] = &pwm3_clk.common.hw, + [CLK_EFUSE] = &efuse_clk.common.hw, + [CLK_CM3_UART0] = &cm3_uart0.common.hw, + [CLK_CM3_UART1] = &cm3_uart1.common.hw, + [CLK_THM] = &thm_clk.common.hw, + [CLK_CM3_I2C0] = &cm3_i2c0.common.hw, + [CLK_CM3_I2C1] = &cm3_i2c1.common.hw, + [CLK_CM4_SPI] = &cm4_spi.common.hw, + [CLK_AON_I2C] = &aon_i2c.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_CA53_DAP] = &ca53_dap.common.hw, + [CLK_CA53_TS] = &ca53_ts.common.hw, + [CLK_DJTAG_TCK] = &djtag_tck.common.hw, + [CLK_PMU] = &pmu_clk.common.hw, + [CLK_PMU_26M] = &pmu_26m.common.hw, + [CLK_DEBOUNCE] = &debounce_clk.common.hw, + [CLK_OTG2_REF] = &otg2_ref.common.hw, + [CLK_USB3_REF] = &usb3_ref.common.hw, + [CLK_AP_AXI] = &ap_axi.common.hw, + }, + .num = CLK_AON_PREDIV_NUM, +}; + +static const struct sprd_clk_desc sc9860_aon_prediv_desc = { + .clk_clks = sc9860_aon_prediv, + .num_clk_clks = ARRAY_SIZE(sc9860_aon_prediv), + .hw_clks = &sc9860_aon_prediv_hws, +}; + +static SPRD_GATE_CLK(usb3_eb, "usb3-eb", "ap-axi", 0x0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(usb3_suspend, "usb3-suspend", "ap-axi", 0x0, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(usb3_ref_eb, "usb3-ref-eb", "ap-axi", 0x0, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dma_eb, "dma-eb", "ap-axi", 0x0, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio0_eb, "sdio0-eb", "ap-axi", 0x0, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio1_eb, "sdio1-eb", "ap-axi", 0x0, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio2_eb, "sdio2-eb", "ap-axi", 0x0, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(emmc_eb, "emmc-eb", "ap-axi", 0x0, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rom_eb, "rom-eb", "ap-axi", 0x0, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(busmon_eb, "busmon-eb", "ap-axi", 0x0, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(cc63s_eb, "cc63s-eb", "ap-axi", 0x0, + 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(cc63p_eb, "cc63p-eb", "ap-axi", 0x0, + 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ce0_eb, "ce0-eb", "ap-axi", 0x0, + 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ce1_eb, "ce1-eb", "ap-axi", 0x0, + 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0); + +static struct sprd_clk_common *sc9860_apahb_gate[] = { + /* address base is 0x20210000 */ + &usb3_eb.common, + &usb3_suspend.common, + &usb3_ref_eb.common, + &dma_eb.common, + &sdio0_eb.common, + &sdio1_eb.common, + &sdio2_eb.common, + &emmc_eb.common, + &rom_eb.common, + &busmon_eb.common, + &cc63s_eb.common, + &cc63p_eb.common, + &ce0_eb.common, + &ce1_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_apahb_gate_hws = { + .hws = { + [CLK_USB3_EB] = &usb3_eb.common.hw, + [CLK_USB3_SUSPEND_EB] = &usb3_suspend.common.hw, + [CLK_USB3_REF_EB] = &usb3_ref_eb.common.hw, + [CLK_DMA_EB] = &dma_eb.common.hw, + [CLK_SDIO0_EB] = &sdio0_eb.common.hw, + [CLK_SDIO1_EB] = &sdio1_eb.common.hw, + [CLK_SDIO2_EB] = &sdio2_eb.common.hw, + [CLK_EMMC_EB] = &emmc_eb.common.hw, + [CLK_ROM_EB] = &rom_eb.common.hw, + [CLK_BUSMON_EB] = &busmon_eb.common.hw, + [CLK_CC63S_EB] = &cc63s_eb.common.hw, + [CLK_CC63P_EB] = &cc63p_eb.common.hw, + [CLK_CE0_EB] = &ce0_eb.common.hw, + [CLK_CE1_EB] = &ce1_eb.common.hw, + }, + .num = CLK_APAHB_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_apahb_gate_desc = { + .clk_clks = sc9860_apahb_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_apahb_gate), + .hw_clks = &sc9860_apahb_gate_hws, +}; + +static SPRD_GATE_CLK(avs_lit_eb, "avs-lit-eb", "aon-apb", 0x0, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(avs_big_eb, "avs-big-eb", "aon-apb", 0x0, + 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc5_eb, "ap-intc5-eb", "aon-apb", 0x0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpio_eb, "gpio-eb", "aon-apb", 0x0, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm0_eb, "pwm0-eb", "aon-apb", 0x0, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm1_eb, "pwm1-eb", "aon-apb", 0x0, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm2_eb, "pwm2-eb", "aon-apb", 0x0, + 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm3_eb, "pwm3-eb", "aon-apb", 0x0, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(kpd_eb, "kpd-eb", "aon-apb", 0x0, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_sys_eb, "aon-sys-eb", "aon-apb", 0x0, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_sys_eb, "ap-sys-eb", "aon-apb", 0x0, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_tmr_eb, "aon-tmr-eb", "aon-apb", 0x0, + 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_tmr0_eb, "ap-tmr0-eb", "aon-apb", 0x0, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(efuse_eb, "efuse-eb", "aon-apb", 0x0, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(eic_eb, "eic-eb", "aon-apb", 0x0, + 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pub1_reg_eb, "pub1-reg-eb", "aon-apb", 0x0, + 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(adi_eb, "adi-eb", "aon-apb", 0x0, + 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc0_eb, "ap-intc0-eb", "aon-apb", 0x0, + 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc1_eb, "ap-intc1-eb", "aon-apb", 0x0, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc2_eb, "ap-intc2-eb", "aon-apb", 0x0, + 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc3_eb, "ap-intc3-eb", "aon-apb", 0x0, + 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc4_eb, "ap-intc4-eb", "aon-apb", 0x0, + 0x1000, BIT(21), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(splk_eb, "splk-eb", "aon-apb", 0x0, + 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mspi_eb, "mspi-eb", "aon-apb", 0x0, + 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pub0_reg_eb, "pub0-reg-eb", "aon-apb", 0x0, + 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pin_eb, "pin-eb", "aon-apb", 0x0, + 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_ckg_eb, "aon-ckg-eb", "aon-apb", 0x0, + 0x1000, BIT(26), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpu_eb, "gpu-eb", "aon-apb", 0x0, + 0x1000, BIT(27), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(apcpu_ts0_eb, "apcpu-ts0-eb", "aon-apb", 0x0, + 0x1000, BIT(28), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(apcpu_ts1_eb, "apcpu-ts1-eb", "aon-apb", 0x0, + 0x1000, BIT(29), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dap_eb, "dap-eb", "aon-apb", 0x0, + 0x1000, BIT(30), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c_eb, "i2c-eb", "aon-apb", 0x0, + 0x1000, BIT(31), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pmu_eb, "pmu-eb", "aon-apb", 0x4, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(thm_eb, "thm-eb", "aon-apb", 0x4, + 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aux0_eb, "aux0-eb", "aon-apb", 0x4, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aux1_eb, "aux1-eb", "aon-apb", 0x4, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aux2_eb, "aux2-eb", "aon-apb", 0x4, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(probe_eb, "probe-eb", "aon-apb", 0x4, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpu0_avs_eb, "gpu0-avs-eb", "aon-apb", 0x4, + 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpu1_avs_eb, "gpu1-avs-eb", "aon-apb", 0x4, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(apcpu_wdg_eb, "apcpu-wdg-eb", "aon-apb", 0x4, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_tmr1_eb, "ap-tmr1-eb", "aon-apb", 0x4, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_tmr2_eb, "ap-tmr2-eb", "aon-apb", 0x4, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(disp_emc_eb, "disp-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(zip_emc_eb, "zip-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gsp_emc_eb, "gsp-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(osc_aon_eb, "osc-aon-eb", "aon-apb", 0x4, + 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(lvds_trx_eb, "lvds-trx-eb", "aon-apb", 0x4, + 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(lvds_tcxo_eb, "lvds-tcxo-eb", "aon-apb", 0x4, + 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mdar_eb, "mdar-eb", "aon-apb", 0x4, + 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rtc4m0_cal_eb, "rtc4m0-cal-eb", "aon-apb", 0x4, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rct100m_cal_eb, "rct100m-cal-eb", "aon-apb", 0x4, + 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(djtag_eb, "djtag-eb", "aon-apb", 0x4, + 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mbox_eb, "mbox-eb", "aon-apb", 0x4, + 0x1000, BIT(21), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_dma_eb, "aon-dma-eb", "aon-apb", 0x4, + 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dbg_emc_eb, "dbg-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(lvds_pll_div_en, "lvds-pll-div-en", "aon-apb", 0x4, + 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(def_eb, "def-eb", "aon-apb", 0x4, + 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_apb_rsv0, "aon-apb-rsv0", "aon-apb", 0x4, + 0x1000, BIT(26), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(orp_jtag_eb, "orp-jtag-eb", "aon-apb", 0x4, + 0x1000, BIT(27), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(vsp_eb, "vsp-eb", "aon-apb", 0x4, + 0x1000, BIT(28), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(cam_eb, "cam-eb", "aon-apb", 0x4, + 0x1000, BIT(29), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(disp_eb, "disp-eb", "aon-apb", 0x4, + 0x1000, BIT(30), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dbg_axi_if_eb, "dbg-axi-if-eb", "aon-apb", 0x4, + 0x1000, BIT(31), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio0_2x_en, "sdio0-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(sdio1_2x_en, "sdio1-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(sdio2_2x_en, "sdio2-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(emmc_2x_en, "emmc-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(9), 0, 0); + +static struct sprd_clk_common *sc9860_aon_gate[] = { + /* address base is 0x402e0000 */ + &avs_lit_eb.common, + &avs_big_eb.common, + &ap_intc5_eb.common, + &gpio_eb.common, + &pwm0_eb.common, + &pwm1_eb.common, + &pwm2_eb.common, + &pwm3_eb.common, + &kpd_eb.common, + &aon_sys_eb.common, + &ap_sys_eb.common, + &aon_tmr_eb.common, + &ap_tmr0_eb.common, + &efuse_eb.common, + &eic_eb.common, + &pub1_reg_eb.common, + &adi_eb.common, + &ap_intc0_eb.common, + &ap_intc1_eb.common, + &ap_intc2_eb.common, + &ap_intc3_eb.common, + &ap_intc4_eb.common, + &splk_eb.common, + &mspi_eb.common, + &pub0_reg_eb.common, + &pin_eb.common, + &aon_ckg_eb.common, + &gpu_eb.common, + &apcpu_ts0_eb.common, + &apcpu_ts1_eb.common, + &dap_eb.common, + &i2c_eb.common, + &pmu_eb.common, + &thm_eb.common, + &aux0_eb.common, + &aux1_eb.common, + &aux2_eb.common, + &probe_eb.common, + &gpu0_avs_eb.common, + &gpu1_avs_eb.common, + &apcpu_wdg_eb.common, + &ap_tmr1_eb.common, + &ap_tmr2_eb.common, + &disp_emc_eb.common, + &zip_emc_eb.common, + &gsp_emc_eb.common, + &osc_aon_eb.common, + &lvds_trx_eb.common, + &lvds_tcxo_eb.common, + &mdar_eb.common, + &rtc4m0_cal_eb.common, + &rct100m_cal_eb.common, + &djtag_eb.common, + &mbox_eb.common, + &aon_dma_eb.common, + &dbg_emc_eb.common, + &lvds_pll_div_en.common, + &def_eb.common, + &aon_apb_rsv0.common, + &orp_jtag_eb.common, + &vsp_eb.common, + &cam_eb.common, + &disp_eb.common, + &dbg_axi_if_eb.common, + &sdio0_2x_en.common, + &sdio1_2x_en.common, + &sdio2_2x_en.common, + &emmc_2x_en.common, +}; + +static struct clk_hw_onecell_data sc9860_aon_gate_hws = { + .hws = { + [CLK_AVS_LIT_EB] = &avs_lit_eb.common.hw, + [CLK_AVS_BIG_EB] = &avs_big_eb.common.hw, + [CLK_AP_INTC5_EB] = &ap_intc5_eb.common.hw, + [CLK_GPIO_EB] = &gpio_eb.common.hw, + [CLK_PWM0_EB] = &pwm0_eb.common.hw, + [CLK_PWM1_EB] = &pwm1_eb.common.hw, + [CLK_PWM2_EB] = &pwm2_eb.common.hw, + [CLK_PWM3_EB] = &pwm3_eb.common.hw, + [CLK_KPD_EB] = &kpd_eb.common.hw, + [CLK_AON_SYS_EB] = &aon_sys_eb.common.hw, + [CLK_AP_SYS_EB] = &ap_sys_eb.common.hw, + [CLK_AON_TMR_EB] = &aon_tmr_eb.common.hw, + [CLK_AP_TMR0_EB] = &ap_tmr0_eb.common.hw, + [CLK_EFUSE_EB] = &efuse_eb.common.hw, + [CLK_EIC_EB] = &eic_eb.common.hw, + [CLK_PUB1_REG_EB] = &pub1_reg_eb.common.hw, + [CLK_ADI_EB] = &adi_eb.common.hw, + [CLK_AP_INTC0_EB] = &ap_intc0_eb.common.hw, + [CLK_AP_INTC1_EB] = &ap_intc1_eb.common.hw, + [CLK_AP_INTC2_EB] = &ap_intc2_eb.common.hw, + [CLK_AP_INTC3_EB] = &ap_intc3_eb.common.hw, + [CLK_AP_INTC4_EB] = &ap_intc4_eb.common.hw, + [CLK_SPLK_EB] = &splk_eb.common.hw, + [CLK_MSPI_EB] = &mspi_eb.common.hw, + [CLK_PUB0_REG_EB] = &pub0_reg_eb.common.hw, + [CLK_PIN_EB] = &pin_eb.common.hw, + [CLK_AON_CKG_EB] = &aon_ckg_eb.common.hw, + [CLK_GPU_EB] = &gpu_eb.common.hw, + [CLK_APCPU_TS0_EB] = &apcpu_ts0_eb.common.hw, + [CLK_APCPU_TS1_EB] = &apcpu_ts1_eb.common.hw, + [CLK_DAP_EB] = &dap_eb.common.hw, + [CLK_I2C_EB] = &i2c_eb.common.hw, + [CLK_PMU_EB] = &pmu_eb.common.hw, + [CLK_THM_EB] = &thm_eb.common.hw, + [CLK_AUX0_EB] = &aux0_eb.common.hw, + [CLK_AUX1_EB] = &aux1_eb.common.hw, + [CLK_AUX2_EB] = &aux2_eb.common.hw, + [CLK_PROBE_EB] = &probe_eb.common.hw, + [CLK_GPU0_AVS_EB] = &gpu0_avs_eb.common.hw, + [CLK_GPU1_AVS_EB] = &gpu1_avs_eb.common.hw, + [CLK_APCPU_WDG_EB] = &apcpu_wdg_eb.common.hw, + [CLK_AP_TMR1_EB] = &ap_tmr1_eb.common.hw, + [CLK_AP_TMR2_EB] = &ap_tmr2_eb.common.hw, + [CLK_DISP_EMC_EB] = &disp_emc_eb.common.hw, + [CLK_ZIP_EMC_EB] = &zip_emc_eb.common.hw, + [CLK_GSP_EMC_EB] = &gsp_emc_eb.common.hw, + [CLK_OSC_AON_EB] = &osc_aon_eb.common.hw, + [CLK_LVDS_TRX_EB] = &lvds_trx_eb.common.hw, + [CLK_LVDS_TCXO_EB] = &lvds_tcxo_eb.common.hw, + [CLK_MDAR_EB] = &mdar_eb.common.hw, + [CLK_RTC4M0_CAL_EB] = &rtc4m0_cal_eb.common.hw, + [CLK_RCT100M_CAL_EB] = &rct100m_cal_eb.common.hw, + [CLK_DJTAG_EB] = &djtag_eb.common.hw, + [CLK_MBOX_EB] = &mbox_eb.common.hw, + [CLK_AON_DMA_EB] = &aon_dma_eb.common.hw, + [CLK_DBG_EMC_EB] = &dbg_emc_eb.common.hw, + [CLK_LVDS_PLL_DIV_EN] = &lvds_pll_div_en.common.hw, + [CLK_DEF_EB] = &def_eb.common.hw, + [CLK_AON_APB_RSV0] = &aon_apb_rsv0.common.hw, + [CLK_ORP_JTAG_EB] = &orp_jtag_eb.common.hw, + [CLK_VSP_EB] = &vsp_eb.common.hw, + [CLK_CAM_EB] = &cam_eb.common.hw, + [CLK_DISP_EB] = &disp_eb.common.hw, + [CLK_DBG_AXI_IF_EB] = &dbg_axi_if_eb.common.hw, + [CLK_SDIO0_2X_EN] = &sdio0_2x_en.common.hw, + [CLK_SDIO1_2X_EN] = &sdio1_2x_en.common.hw, + [CLK_SDIO2_2X_EN] = &sdio2_2x_en.common.hw, + [CLK_EMMC_2X_EN] = &emmc_2x_en.common.hw, + }, + .num = CLK_AON_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_aon_gate_desc = { + .clk_clks = sc9860_aon_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_aon_gate), + .hw_clks = &sc9860_aon_gate_hws, +}; + +static const u8 mcu_table[] = { 0, 1, 2, 3, 4, 8 }; +static const char * const lit_mcu_parents[] = { "ext-26m", "twpll-512m", + "twpll-768m", "ltepll0", + "twpll", "mpll0" }; +static SPRD_COMP_CLK(lit_mcu, "lit-mcu", lit_mcu_parents, 0x20, + mcu_table, 0, 4, 4, 3, 0); + +static const char * const big_mcu_parents[] = { "ext-26m", "twpll-512m", + "twpll-768m", "ltepll0", + "twpll", "mpll1" }; +static SPRD_COMP_CLK(big_mcu, "big-mcu", big_mcu_parents, 0x24, + mcu_table, 0, 4, 4, 3, 0); + +static struct sprd_clk_common *sc9860_aonsecure_clk[] = { + /* address base is 0x40880000 */ + &lit_mcu.common, + &big_mcu.common, +}; + +static struct clk_hw_onecell_data sc9860_aonsecure_clk_hws = { + .hws = { + [CLK_LIT_MCU] = &lit_mcu.common.hw, + [CLK_BIG_MCU] = &big_mcu.common.hw, + }, + .num = CLK_AONSECURE_NUM, +}; + +static const struct sprd_clk_desc sc9860_aonsecure_clk_desc = { + .clk_clks = sc9860_aonsecure_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_aonsecure_clk), + .hw_clks = &sc9860_aonsecure_clk_hws, +}; + +static SPRD_GATE_CLK(agcp_iis0_eb, "agcp-iis0-eb", "aon-apb", + 0x0, 0x100, BIT(0), 0, 0); +static SPRD_GATE_CLK(agcp_iis1_eb, "agcp-iis1-eb", "aon-apb", + 0x0, 0x100, BIT(1), 0, 0); +static SPRD_GATE_CLK(agcp_iis2_eb, "agcp-iis2-eb", "aon-apb", + 0x0, 0x100, BIT(2), 0, 0); +static SPRD_GATE_CLK(agcp_iis3_eb, "agcp-iis3-eb", "aon-apb", + 0x0, 0x100, BIT(3), 0, 0); +static SPRD_GATE_CLK(agcp_uart_eb, "agcp-uart-eb", "aon-apb", + 0x0, 0x100, BIT(4), 0, 0); +static SPRD_GATE_CLK(agcp_dmacp_eb, "agcp-dmacp-eb", "aon-apb", + 0x0, 0x100, BIT(5), 0, 0); +static SPRD_GATE_CLK(agcp_dmaap_eb, "agcp-dmaap-eb", "aon-apb", + 0x0, 0x100, BIT(6), 0, 0); +static SPRD_GATE_CLK(agcp_arc48k_eb, "agcp-arc48k-eb", "aon-apb", + 0x0, 0x100, BIT(10), 0, 0); +static SPRD_GATE_CLK(agcp_src44p1k_eb, "agcp-src44p1k-eb", "aon-apb", + 0x0, 0x100, BIT(11), 0, 0); +static SPRD_GATE_CLK(agcp_mcdt_eb, "agcp-mcdt-eb", "aon-apb", + 0x0, 0x100, BIT(12), 0, 0); +static SPRD_GATE_CLK(agcp_vbcifd_eb, "agcp-vbcifd-eb", "aon-apb", + 0x0, 0x100, BIT(13), 0, 0); +static SPRD_GATE_CLK(agcp_vbc_eb, "agcp-vbc-eb", "aon-apb", + 0x0, 0x100, BIT(14), 0, 0); +static SPRD_GATE_CLK(agcp_spinlock_eb, "agcp-spinlock-eb", "aon-apb", + 0x0, 0x100, BIT(15), 0, 0); +static SPRD_GATE_CLK(agcp_icu_eb, "agcp-icu-eb", "aon-apb", + 0x0, 0x100, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(agcp_ap_ashb_eb, "agcp-ap-ashb-eb", "aon-apb", + 0x0, 0x100, BIT(17), 0, 0); +static SPRD_GATE_CLK(agcp_cp_ashb_eb, "agcp-cp-ashb-eb", "aon-apb", + 0x0, 0x100, BIT(18), 0, 0); +static SPRD_GATE_CLK(agcp_aud_eb, "agcp-aud-eb", "aon-apb", + 0x0, 0x100, BIT(19), 0, 0); +static SPRD_GATE_CLK(agcp_audif_eb, "agcp-audif-eb", "aon-apb", + 0x0, 0x100, BIT(20), 0, 0); + +static struct sprd_clk_common *sc9860_agcp_gate[] = { + /* address base is 0x415e0000 */ + &agcp_iis0_eb.common, + &agcp_iis1_eb.common, + &agcp_iis2_eb.common, + &agcp_iis3_eb.common, + &agcp_uart_eb.common, + &agcp_dmacp_eb.common, + &agcp_dmaap_eb.common, + &agcp_arc48k_eb.common, + &agcp_src44p1k_eb.common, + &agcp_mcdt_eb.common, + &agcp_vbcifd_eb.common, + &agcp_vbc_eb.common, + &agcp_spinlock_eb.common, + &agcp_icu_eb.common, + &agcp_ap_ashb_eb.common, + &agcp_cp_ashb_eb.common, + &agcp_aud_eb.common, + &agcp_audif_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_agcp_gate_hws = { + .hws = { + [CLK_AGCP_IIS0_EB] = &agcp_iis0_eb.common.hw, + [CLK_AGCP_IIS1_EB] = &agcp_iis1_eb.common.hw, + [CLK_AGCP_IIS2_EB] = &agcp_iis2_eb.common.hw, + [CLK_AGCP_IIS3_EB] = &agcp_iis3_eb.common.hw, + [CLK_AGCP_UART_EB] = &agcp_uart_eb.common.hw, + [CLK_AGCP_DMACP_EB] = &agcp_dmacp_eb.common.hw, + [CLK_AGCP_DMAAP_EB] = &agcp_dmaap_eb.common.hw, + [CLK_AGCP_ARC48K_EB] = &agcp_arc48k_eb.common.hw, + [CLK_AGCP_SRC44P1K_EB] = &agcp_src44p1k_eb.common.hw, + [CLK_AGCP_MCDT_EB] = &agcp_mcdt_eb.common.hw, + [CLK_AGCP_VBCIFD_EB] = &agcp_vbcifd_eb.common.hw, + [CLK_AGCP_VBC_EB] = &agcp_vbc_eb.common.hw, + [CLK_AGCP_SPINLOCK_EB] = &agcp_spinlock_eb.common.hw, + [CLK_AGCP_ICU_EB] = &agcp_icu_eb.common.hw, + [CLK_AGCP_AP_ASHB_EB] = &agcp_ap_ashb_eb.common.hw, + [CLK_AGCP_CP_ASHB_EB] = &agcp_cp_ashb_eb.common.hw, + [CLK_AGCP_AUD_EB] = &agcp_aud_eb.common.hw, + [CLK_AGCP_AUDIF_EB] = &agcp_audif_eb.common.hw, + }, + .num = CLK_AGCP_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_agcp_gate_desc = { + .clk_clks = sc9860_agcp_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_agcp_gate), + .hw_clks = &sc9860_agcp_gate_hws, +}; + +static const char * const gpu_parents[] = { "twpll-512m", + "twpll-768m", + "gpll" }; +static SPRD_COMP_CLK(gpu_clk, "gpu", gpu_parents, 0x20, + 0, 0, 2, 8, 4, 0); + +static struct sprd_clk_common *sc9860_gpu_clk[] = { + /* address base is 0x60200000 */ + &gpu_clk.common, +}; + +static struct clk_hw_onecell_data sc9860_gpu_clk_hws = { + .hws = { + [CLK_GPU] = &gpu_clk.common.hw, + }, + .num = CLK_GPU_NUM, +}; + +static const struct sprd_clk_desc sc9860_gpu_clk_desc = { + .clk_clks = sc9860_gpu_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_gpu_clk), + .hw_clks = &sc9860_gpu_clk_hws, +}; + +static const char * const ahb_parents[] = { "ext-26m", "twpll-96m", + "twpll-128m", "twpll-153m6" }; +static SPRD_MUX_CLK(ahb_vsp, "ahb-vsp", ahb_parents, NULL, + 0x20, 0, 2, SC9860_MUX_FLAG); + +static const char * const vsp_parents[] = { "twpll-76m8", "twpll-128m", + "twpll-256m", "twpll-307m2", + "twpll-384m" }; +static SPRD_COMP_CLK(vsp_clk, "vsp", vsp_parents, 0x24, 0, 0, 3, 8, 2, 0); + +static const char * const dispc_parents[] = { "twpll-76m8", "twpll-128m", + "twpll-256m", "twpll-307m2" }; +static SPRD_COMP_CLK(vsp_enc, "vsp-enc", dispc_parents, 0x28, 0, 0, 2, 8, 2, 0); + +static const char * const vpp_parents[] = { "twpll-96m", "twpll-153m6", + "twpll-192m", "twpll-256m" }; +static SPRD_MUX_CLK(vpp_clk, "vpp", vpp_parents, NULL, 0x2c, + 0, 2, SC9860_MUX_FLAG); +static const char * const vsp_26m_parents[] = { "ext-26m" }; +static SPRD_MUX_CLK(vsp_26m, "vsp-26m", vsp_26m_parents, NULL, 0x30, + 0, 1, SC9860_MUX_FLAG); + +static struct sprd_clk_common *sc9860_vsp_clk[] = { + /* address base is 0x61000000 */ + &ahb_vsp.common, + &vsp_clk.common, + &vsp_enc.common, + &vpp_clk.common, + &vsp_26m.common, +}; + +static struct clk_hw_onecell_data sc9860_vsp_clk_hws = { + .hws = { + [CLK_AHB_VSP] = &ahb_vsp.common.hw, + [CLK_VSP] = &vsp_clk.common.hw, + [CLK_VSP_ENC] = &vsp_enc.common.hw, + [CLK_VPP] = &vpp_clk.common.hw, + [CLK_VSP_26M] = &vsp_26m.common.hw, + }, + .num = CLK_VSP_NUM, +}; + +static const struct sprd_clk_desc sc9860_vsp_clk_desc = { + .clk_clks = sc9860_vsp_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_vsp_clk), + .hw_clks = &sc9860_vsp_clk_hws, +}; + +static SPRD_GATE_CLK(vsp_dec_eb, "vsp-dec-eb", "ahb-vsp", 0x0, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(vsp_ckg_eb, "vsp-ckg-eb", "ahb-vsp", 0x0, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(vsp_mmu_eb, "vsp-mmu-eb", "ahb-vsp", 0x0, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(vsp_enc_eb, "vsp-enc-eb", "ahb-vsp", 0x0, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(vpp_eb, "vpp-eb", "ahb-vsp", 0x0, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(vsp_26m_eb, "vsp-26m-eb", "ahb-vsp", 0x0, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(vsp_axi_gate, "vsp-axi-gate", "ahb-vsp", 0x8, + 0, BIT(0), 0, 0); +static SPRD_GATE_CLK(vsp_enc_gate, "vsp-enc-gate", "ahb-vsp", 0x8, + 0, BIT(1), 0, 0); +static SPRD_GATE_CLK(vpp_axi_gate, "vpp-axi-gate", "ahb-vsp", 0x8, + 0, BIT(2), 0, 0); +static SPRD_GATE_CLK(vsp_bm_gate, "vsp-bm-gate", "ahb-vsp", 0x8, + 0, BIT(8), 0, 0); +static SPRD_GATE_CLK(vsp_enc_bm_gate, "vsp-enc-bm-gate", "ahb-vsp", 0x8, + 0, BIT(9), 0, 0); +static SPRD_GATE_CLK(vpp_bm_gate, "vpp-bm-gate", "ahb-vsp", 0x8, + 0, BIT(10), 0, 0); + +static struct sprd_clk_common *sc9860_vsp_gate[] = { + /* address base is 0x61100000 */ + &vsp_dec_eb.common, + &vsp_ckg_eb.common, + &vsp_mmu_eb.common, + &vsp_enc_eb.common, + &vpp_eb.common, + &vsp_26m_eb.common, + &vsp_axi_gate.common, + &vsp_enc_gate.common, + &vpp_axi_gate.common, + &vsp_bm_gate.common, + &vsp_enc_bm_gate.common, + &vpp_bm_gate.common, +}; + +static struct clk_hw_onecell_data sc9860_vsp_gate_hws = { + .hws = { + [CLK_VSP_DEC_EB] = &vsp_dec_eb.common.hw, + [CLK_VSP_CKG_EB] = &vsp_ckg_eb.common.hw, + [CLK_VSP_MMU_EB] = &vsp_mmu_eb.common.hw, + [CLK_VSP_ENC_EB] = &vsp_enc_eb.common.hw, + [CLK_VPP_EB] = &vpp_eb.common.hw, + [CLK_VSP_26M_EB] = &vsp_26m_eb.common.hw, + [CLK_VSP_AXI_GATE] = &vsp_axi_gate.common.hw, + [CLK_VSP_ENC_GATE] = &vsp_enc_gate.common.hw, + [CLK_VPP_AXI_GATE] = &vpp_axi_gate.common.hw, + [CLK_VSP_BM_GATE] = &vsp_bm_gate.common.hw, + [CLK_VSP_ENC_BM_GATE] = &vsp_enc_bm_gate.common.hw, + [CLK_VPP_BM_GATE] = &vpp_bm_gate.common.hw, + }, + .num = CLK_VSP_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_vsp_gate_desc = { + .clk_clks = sc9860_vsp_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_vsp_gate), + .hw_clks = &sc9860_vsp_gate_hws, +}; + +static SPRD_MUX_CLK(ahb_cam, "ahb-cam", ahb_parents, NULL, + 0x20, 0, 2, SC9860_MUX_FLAG); +static const char * const sensor_parents[] = { "ext-26m", "twpll-48m", + "twpll-76m8", "twpll-96m" }; +static SPRD_COMP_CLK(sensor0_clk, "sensor0", sensor_parents, 0x24, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(sensor1_clk, "sensor1", sensor_parents, 0x28, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(sensor2_clk, "sensor2", sensor_parents, 0x2c, + 0, 0, 2, 8, 3, 0); +static SPRD_GATE_CLK(mipi_csi0_eb, "mipi-csi0-eb", "ahb-cam", 0x4c, + 0, BIT(16), 0, 0); +static SPRD_GATE_CLK(mipi_csi1_eb, "mipi-csi1-eb", "ahb-cam", 0x50, + 0, BIT(16), 0, 0); + +static struct sprd_clk_common *sc9860_cam_clk[] = { + /* address base is 0x62000000 */ + &ahb_cam.common, + &sensor0_clk.common, + &sensor1_clk.common, + &sensor2_clk.common, + &mipi_csi0_eb.common, + &mipi_csi1_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_cam_clk_hws = { + .hws = { + [CLK_AHB_CAM] = &ahb_cam.common.hw, + [CLK_SENSOR0] = &sensor0_clk.common.hw, + [CLK_SENSOR1] = &sensor1_clk.common.hw, + [CLK_SENSOR2] = &sensor2_clk.common.hw, + [CLK_MIPI_CSI0_EB] = &mipi_csi0_eb.common.hw, + [CLK_MIPI_CSI1_EB] = &mipi_csi1_eb.common.hw, + }, + .num = CLK_CAM_NUM, +}; + +static const struct sprd_clk_desc sc9860_cam_clk_desc = { + .clk_clks = sc9860_cam_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_cam_clk), + .hw_clks = &sc9860_cam_clk_hws, +}; + +static SPRD_GATE_CLK(dcam0_eb, "dcam0-eb", "ahb-cam", 0x0, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(dcam1_eb, "dcam1-eb", "ahb-cam", 0x0, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(isp0_eb, "isp0-eb", "ahb-cam", 0x0, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(csi0_eb, "csi0-eb", "ahb-cam", 0x0, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(csi1_eb, "csi1-eb", "ahb-cam", 0x0, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(jpg0_eb, "jpg0-eb", "ahb-cam", 0x0, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(jpg1_eb, "jpg1-eb", "ahb-cam", 0x0, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(cam_ckg_eb, "cam-ckg-eb", "ahb-cam", 0x0, + 0x1000, BIT(7), 0, 0); +static SPRD_GATE_CLK(cam_mmu_eb, "cam-mmu-eb", "ahb-cam", 0x0, + 0x1000, BIT(8), 0, 0); +static SPRD_GATE_CLK(isp1_eb, "isp1-eb", "ahb-cam", 0x0, + 0x1000, BIT(9), 0, 0); +static SPRD_GATE_CLK(cpp_eb, "cpp-eb", "ahb-cam", 0x0, + 0x1000, BIT(10), 0, 0); +static SPRD_GATE_CLK(mmu_pf_eb, "mmu-pf-eb", "ahb-cam", 0x0, + 0x1000, BIT(11), 0, 0); +static SPRD_GATE_CLK(isp2_eb, "isp2-eb", "ahb-cam", 0x0, + 0x1000, BIT(12), 0, 0); +static SPRD_GATE_CLK(dcam2isp_if_eb, "dcam2isp-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(13), 0, 0); +static SPRD_GATE_CLK(isp2dcam_if_eb, "isp2dcam-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(14), 0, 0); +static SPRD_GATE_CLK(isp_lclk_eb, "isp-lclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(15), 0, 0); +static SPRD_GATE_CLK(isp_iclk_eb, "isp-iclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(16), 0, 0); +static SPRD_GATE_CLK(isp_mclk_eb, "isp-mclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(17), 0, 0); +static SPRD_GATE_CLK(isp_pclk_eb, "isp-pclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(18), 0, 0); +static SPRD_GATE_CLK(isp_isp2dcam_eb, "isp-isp2dcam-eb", "ahb-cam", 0x0, + 0x1000, BIT(19), 0, 0); +static SPRD_GATE_CLK(dcam0_if_eb, "dcam0-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(20), 0, 0); +static SPRD_GATE_CLK(clk26m_if_eb, "clk26m-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(21), 0, 0); +static SPRD_GATE_CLK(cphy0_gate, "cphy0-gate", "ahb-cam", 0x8, + 0, BIT(0), 0, 0); +static SPRD_GATE_CLK(mipi_csi0_gate, "mipi-csi0-gate", "ahb-cam", 0x8, + 0, BIT(1), 0, 0); +static SPRD_GATE_CLK(cphy1_gate, "cphy1-gate", "ahb-cam", 0x8, + 0, BIT(2), 0, 0); +static SPRD_GATE_CLK(mipi_csi1, "mipi-csi1", "ahb-cam", 0x8, + 0, BIT(3), 0, 0); +static SPRD_GATE_CLK(dcam0_axi_gate, "dcam0-axi-gate", "ahb-cam", 0x8, + 0, BIT(4), 0, 0); +static SPRD_GATE_CLK(dcam1_axi_gate, "dcam1-axi-gate", "ahb-cam", 0x8, + 0, BIT(5), 0, 0); +static SPRD_GATE_CLK(sensor0_gate, "sensor0-gate", "ahb-cam", 0x8, + 0, BIT(6), 0, 0); +static SPRD_GATE_CLK(sensor1_gate, "sensor1-gate", "ahb-cam", 0x8, + 0, BIT(7), 0, 0); +static SPRD_GATE_CLK(jpg0_axi_gate, "jpg0-axi-gate", "ahb-cam", 0x8, + 0, BIT(8), 0, 0); +static SPRD_GATE_CLK(gpg1_axi_gate, "gpg1-axi-gate", "ahb-cam", 0x8, + 0, BIT(9), 0, 0); +static SPRD_GATE_CLK(isp0_axi_gate, "isp0-axi-gate", "ahb-cam", 0x8, + 0, BIT(10), 0, 0); +static SPRD_GATE_CLK(isp1_axi_gate, "isp1-axi-gate", "ahb-cam", 0x8, + 0, BIT(11), 0, 0); +static SPRD_GATE_CLK(isp2_axi_gate, "isp2-axi-gate", "ahb-cam", 0x8, + 0, BIT(12), 0, 0); +static SPRD_GATE_CLK(cpp_axi_gate, "cpp-axi-gate", "ahb-cam", 0x8, + 0, BIT(13), 0, 0); +static SPRD_GATE_CLK(d0_if_axi_gate, "d0-if-axi-gate", "ahb-cam", 0x8, + 0, BIT(14), 0, 0); +static SPRD_GATE_CLK(d2i_if_axi_gate, "d2i-if-axi-gate", "ahb-cam", 0x8, + 0, BIT(15), 0, 0); +static SPRD_GATE_CLK(i2d_if_axi_gate, "i2d-if-axi-gate", "ahb-cam", 0x8, + 0, BIT(16), 0, 0); +static SPRD_GATE_CLK(spare_axi_gate, "spare-axi-gate", "ahb-cam", 0x8, + 0, BIT(17), 0, 0); +static SPRD_GATE_CLK(sensor2_gate, "sensor2-gate", "ahb-cam", 0x8, + 0, BIT(18), 0, 0); +static SPRD_GATE_CLK(d0if_in_d_en, "d0if-in-d-en", "ahb-cam", 0x28, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(d1if_in_d_en, "d1if-in-d-en", "ahb-cam", 0x28, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(d0if_in_d2i_en, "d0if-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(d1if_in_d2i_en, "d1if-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(ia_in_d2i_en, "ia-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(ib_in_d2i_en, "ib-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(ic_in_d2i_en, "ic-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(ia_in_i_en, "ia-in-i-en", "ahb-cam", 0x28, + 0x1000, BIT(7), 0, 0); +static SPRD_GATE_CLK(ib_in_i_en, "ib-in-i-en", "ahb-cam", 0x28, + 0x1000, BIT(8), 0, 0); +static SPRD_GATE_CLK(ic_in_i_en, "ic-in-i-en", "ahb-cam", 0x28, + 0x1000, BIT(9), 0, 0); + +static struct sprd_clk_common *sc9860_cam_gate[] = { + /* address base is 0x62100000 */ + &dcam0_eb.common, + &dcam1_eb.common, + &isp0_eb.common, + &csi0_eb.common, + &csi1_eb.common, + &jpg0_eb.common, + &jpg1_eb.common, + &cam_ckg_eb.common, + &cam_mmu_eb.common, + &isp1_eb.common, + &cpp_eb.common, + &mmu_pf_eb.common, + &isp2_eb.common, + &dcam2isp_if_eb.common, + &isp2dcam_if_eb.common, + &isp_lclk_eb.common, + &isp_iclk_eb.common, + &isp_mclk_eb.common, + &isp_pclk_eb.common, + &isp_isp2dcam_eb.common, + &dcam0_if_eb.common, + &clk26m_if_eb.common, + &cphy0_gate.common, + &mipi_csi0_gate.common, + &cphy1_gate.common, + &mipi_csi1.common, + &dcam0_axi_gate.common, + &dcam1_axi_gate.common, + &sensor0_gate.common, + &sensor1_gate.common, + &jpg0_axi_gate.common, + &gpg1_axi_gate.common, + &isp0_axi_gate.common, + &isp1_axi_gate.common, + &isp2_axi_gate.common, + &cpp_axi_gate.common, + &d0_if_axi_gate.common, + &d2i_if_axi_gate.common, + &i2d_if_axi_gate.common, + &spare_axi_gate.common, + &sensor2_gate.common, + &d0if_in_d_en.common, + &d1if_in_d_en.common, + &d0if_in_d2i_en.common, + &d1if_in_d2i_en.common, + &ia_in_d2i_en.common, + &ib_in_d2i_en.common, + &ic_in_d2i_en.common, + &ia_in_i_en.common, + &ib_in_i_en.common, + &ic_in_i_en.common, +}; + +static struct clk_hw_onecell_data sc9860_cam_gate_hws = { + .hws = { + [CLK_DCAM0_EB] = &dcam0_eb.common.hw, + [CLK_DCAM1_EB] = &dcam1_eb.common.hw, + [CLK_ISP0_EB] = &isp0_eb.common.hw, + [CLK_CSI0_EB] = &csi0_eb.common.hw, + [CLK_CSI1_EB] = &csi1_eb.common.hw, + [CLK_JPG0_EB] = &jpg0_eb.common.hw, + [CLK_JPG1_EB] = &jpg1_eb.common.hw, + [CLK_CAM_CKG_EB] = &cam_ckg_eb.common.hw, + [CLK_CAM_MMU_EB] = &cam_mmu_eb.common.hw, + [CLK_ISP1_EB] = &isp1_eb.common.hw, + [CLK_CPP_EB] = &cpp_eb.common.hw, + [CLK_MMU_PF_EB] = &mmu_pf_eb.common.hw, + [CLK_ISP2_EB] = &isp2_eb.common.hw, + [CLK_DCAM2ISP_IF_EB] = &dcam2isp_if_eb.common.hw, + [CLK_ISP2DCAM_IF_EB] = &isp2dcam_if_eb.common.hw, + [CLK_ISP_LCLK_EB] = &isp_lclk_eb.common.hw, + [CLK_ISP_ICLK_EB] = &isp_iclk_eb.common.hw, + [CLK_ISP_MCLK_EB] = &isp_mclk_eb.common.hw, + [CLK_ISP_PCLK_EB] = &isp_pclk_eb.common.hw, + [CLK_ISP_ISP2DCAM_EB] = &isp_isp2dcam_eb.common.hw, + [CLK_DCAM0_IF_EB] = &dcam0_if_eb.common.hw, + [CLK_CLK26M_IF_EB] = &clk26m_if_eb.common.hw, + [CLK_CPHY0_GATE] = &cphy0_gate.common.hw, + [CLK_MIPI_CSI0_GATE] = &mipi_csi0_gate.common.hw, + [CLK_CPHY1_GATE] = &cphy1_gate.common.hw, + [CLK_MIPI_CSI1] = &mipi_csi1.common.hw, + [CLK_DCAM0_AXI_GATE] = &dcam0_axi_gate.common.hw, + [CLK_DCAM1_AXI_GATE] = &dcam1_axi_gate.common.hw, + [CLK_SENSOR0_GATE] = &sensor0_gate.common.hw, + [CLK_SENSOR1_GATE] = &sensor1_gate.common.hw, + [CLK_JPG0_AXI_GATE] = &jpg0_axi_gate.common.hw, + [CLK_GPG1_AXI_GATE] = &gpg1_axi_gate.common.hw, + [CLK_ISP0_AXI_GATE] = &isp0_axi_gate.common.hw, + [CLK_ISP1_AXI_GATE] = &isp1_axi_gate.common.hw, + [CLK_ISP2_AXI_GATE] = &isp2_axi_gate.common.hw, + [CLK_CPP_AXI_GATE] = &cpp_axi_gate.common.hw, + [CLK_D0_IF_AXI_GATE] = &d0_if_axi_gate.common.hw, + [CLK_D2I_IF_AXI_GATE] = &d2i_if_axi_gate.common.hw, + [CLK_I2D_IF_AXI_GATE] = &i2d_if_axi_gate.common.hw, + [CLK_SPARE_AXI_GATE] = &spare_axi_gate.common.hw, + [CLK_SENSOR2_GATE] = &sensor2_gate.common.hw, + [CLK_D0IF_IN_D_EN] = &d0if_in_d_en.common.hw, + [CLK_D1IF_IN_D_EN] = &d1if_in_d_en.common.hw, + [CLK_D0IF_IN_D2I_EN] = &d0if_in_d2i_en.common.hw, + [CLK_D1IF_IN_D2I_EN] = &d1if_in_d2i_en.common.hw, + [CLK_IA_IN_D2I_EN] = &ia_in_d2i_en.common.hw, + [CLK_IB_IN_D2I_EN] = &ib_in_d2i_en.common.hw, + [CLK_IC_IN_D2I_EN] = &ic_in_d2i_en.common.hw, + [CLK_IA_IN_I_EN] = &ia_in_i_en.common.hw, + [CLK_IB_IN_I_EN] = &ib_in_i_en.common.hw, + [CLK_IC_IN_I_EN] = &ic_in_i_en.common.hw, + }, + .num = CLK_CAM_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_cam_gate_desc = { + .clk_clks = sc9860_cam_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_cam_gate), + .hw_clks = &sc9860_cam_gate_hws, +}; + +static SPRD_MUX_CLK(ahb_disp, "ahb-disp", ahb_parents, NULL, 0x20, + 0, 2, SC9860_MUX_FLAG); +static SPRD_COMP_CLK(dispc0_dpi, "dispc0-dpi", dispc_parents, 0x34, + 0, 0, 2, 8, 2, 0); +static SPRD_COMP_CLK(dispc1_dpi, "dispc1-dpi", dispc_parents, 0x40, + 0, 0, 2, 8, 2, 0); + +static struct sprd_clk_common *sc9860_disp_clk[] = { + /* address base is 0x63000000 */ + &ahb_disp.common, + &dispc0_dpi.common, + &dispc1_dpi.common, +}; + +static struct clk_hw_onecell_data sc9860_disp_clk_hws = { + .hws = { + [CLK_AHB_DISP] = &ahb_disp.common.hw, + [CLK_DISPC0_DPI] = &dispc0_dpi.common.hw, + [CLK_DISPC1_DPI] = &dispc1_dpi.common.hw, + }, + .num = CLK_DISP_NUM, +}; + +static const struct sprd_clk_desc sc9860_disp_clk_desc = { + .clk_clks = sc9860_disp_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_disp_clk), + .hw_clks = &sc9860_disp_clk_hws, +}; + +static SPRD_GATE_CLK(dispc0_eb, "dispc0-eb", "ahb-disp", 0x0, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(dispc1_eb, "dispc1-eb", "ahb-disp", 0x0, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(dispc_mmu_eb, "dispc-mmu-eb", "ahb-disp", 0x0, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(gsp0_eb, "gsp0-eb", "ahb-disp", 0x0, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(gsp1_eb, "gsp1-eb", "ahb-disp", 0x0, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(gsp0_mmu_eb, "gsp0-mmu-eb", "ahb-disp", 0x0, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(gsp1_mmu_eb, "gsp1-mmu-eb", "ahb-disp", 0x0, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(dsi0_eb, "dsi0-eb", "ahb-disp", 0x0, + 0x1000, BIT(7), 0, 0); +static SPRD_GATE_CLK(dsi1_eb, "dsi1-eb", "ahb-disp", 0x0, + 0x1000, BIT(8), 0, 0); +static SPRD_GATE_CLK(disp_ckg_eb, "disp-ckg-eb", "ahb-disp", 0x0, + 0x1000, BIT(9), 0, 0); +static SPRD_GATE_CLK(disp_gpu_eb, "disp-gpu-eb", "ahb-disp", 0x0, + 0x1000, BIT(10), 0, 0); +static SPRD_GATE_CLK(gpu_mtx_eb, "gpu-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(13), 0, 0); +static SPRD_GATE_CLK(gsp_mtx_eb, "gsp-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(14), 0, 0); +static SPRD_GATE_CLK(tmc_mtx_eb, "tmc-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(15), 0, 0); +static SPRD_GATE_CLK(dispc_mtx_eb, "dispc-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(16), 0, 0); +static SPRD_GATE_CLK(dphy0_gate, "dphy0-gate", "ahb-disp", 0x8, + 0, BIT(0), 0, 0); +static SPRD_GATE_CLK(dphy1_gate, "dphy1-gate", "ahb-disp", 0x8, + 0, BIT(1), 0, 0); +static SPRD_GATE_CLK(gsp0_a_gate, "gsp0-a-gate", "ahb-disp", 0x8, + 0, BIT(2), 0, 0); +static SPRD_GATE_CLK(gsp1_a_gate, "gsp1-a-gate", "ahb-disp", 0x8, + 0, BIT(3), 0, 0); +static SPRD_GATE_CLK(gsp0_f_gate, "gsp0-f-gate", "ahb-disp", 0x8, + 0, BIT(4), 0, 0); +static SPRD_GATE_CLK(gsp1_f_gate, "gsp1-f-gate", "ahb-disp", 0x8, + 0, BIT(5), 0, 0); +static SPRD_GATE_CLK(d_mtx_f_gate, "d-mtx-f-gate", "ahb-disp", 0x8, + 0, BIT(6), 0, 0); +static SPRD_GATE_CLK(d_mtx_a_gate, "d-mtx-a-gate", "ahb-disp", 0x8, + 0, BIT(7), 0, 0); +static SPRD_GATE_CLK(d_noc_f_gate, "d-noc-f-gate", "ahb-disp", 0x8, + 0, BIT(8), 0, 0); +static SPRD_GATE_CLK(d_noc_a_gate, "d-noc-a-gate", "ahb-disp", 0x8, + 0, BIT(9), 0, 0); +static SPRD_GATE_CLK(gsp_mtx_f_gate, "gsp-mtx-f-gate", "ahb-disp", 0x8, + 0, BIT(10), 0, 0); +static SPRD_GATE_CLK(gsp_mtx_a_gate, "gsp-mtx-a-gate", "ahb-disp", 0x8, + 0, BIT(11), 0, 0); +static SPRD_GATE_CLK(gsp_noc_f_gate, "gsp-noc-f-gate", "ahb-disp", 0x8, + 0, BIT(12), 0, 0); +static SPRD_GATE_CLK(gsp_noc_a_gate, "gsp-noc-a-gate", "ahb-disp", 0x8, + 0, BIT(13), 0, 0); +static SPRD_GATE_CLK(dispm0idle_gate, "dispm0idle-gate", "ahb-disp", 0x8, + 0, BIT(14), 0, 0); +static SPRD_GATE_CLK(gspm0idle_gate, "gspm0idle-gate", "ahb-disp", 0x8, + 0, BIT(15), 0, 0); + +static struct sprd_clk_common *sc9860_disp_gate[] = { + /* address base is 0x63100000 */ + &dispc0_eb.common, + &dispc1_eb.common, + &dispc_mmu_eb.common, + &gsp0_eb.common, + &gsp1_eb.common, + &gsp0_mmu_eb.common, + &gsp1_mmu_eb.common, + &dsi0_eb.common, + &dsi1_eb.common, + &disp_ckg_eb.common, + &disp_gpu_eb.common, + &gpu_mtx_eb.common, + &gsp_mtx_eb.common, + &tmc_mtx_eb.common, + &dispc_mtx_eb.common, + &dphy0_gate.common, + &dphy1_gate.common, + &gsp0_a_gate.common, + &gsp1_a_gate.common, + &gsp0_f_gate.common, + &gsp1_f_gate.common, + &d_mtx_f_gate.common, + &d_mtx_a_gate.common, + &d_noc_f_gate.common, + &d_noc_a_gate.common, + &gsp_mtx_f_gate.common, + &gsp_mtx_a_gate.common, + &gsp_noc_f_gate.common, + &gsp_noc_a_gate.common, + &dispm0idle_gate.common, + &gspm0idle_gate.common, +}; + +static struct clk_hw_onecell_data sc9860_disp_gate_hws = { + .hws = { + [CLK_DISPC0_EB] = &dispc0_eb.common.hw, + [CLK_DISPC1_EB] = &dispc1_eb.common.hw, + [CLK_DISPC_MMU_EB] = &dispc_mmu_eb.common.hw, + [CLK_GSP0_EB] = &gsp0_eb.common.hw, + [CLK_GSP1_EB] = &gsp1_eb.common.hw, + [CLK_GSP0_MMU_EB] = &gsp0_mmu_eb.common.hw, + [CLK_GSP1_MMU_EB] = &gsp1_mmu_eb.common.hw, + [CLK_DSI0_EB] = &dsi0_eb.common.hw, + [CLK_DSI1_EB] = &dsi1_eb.common.hw, + [CLK_DISP_CKG_EB] = &disp_ckg_eb.common.hw, + [CLK_DISP_GPU_EB] = &disp_gpu_eb.common.hw, + [CLK_GPU_MTX_EB] = &gpu_mtx_eb.common.hw, + [CLK_GSP_MTX_EB] = &gsp_mtx_eb.common.hw, + [CLK_TMC_MTX_EB] = &tmc_mtx_eb.common.hw, + [CLK_DISPC_MTX_EB] = &dispc_mtx_eb.common.hw, + [CLK_DPHY0_GATE] = &dphy0_gate.common.hw, + [CLK_DPHY1_GATE] = &dphy1_gate.common.hw, + [CLK_GSP0_A_GATE] = &gsp0_a_gate.common.hw, + [CLK_GSP1_A_GATE] = &gsp1_a_gate.common.hw, + [CLK_GSP0_F_GATE] = &gsp0_f_gate.common.hw, + [CLK_GSP1_F_GATE] = &gsp1_f_gate.common.hw, + [CLK_D_MTX_F_GATE] = &d_mtx_f_gate.common.hw, + [CLK_D_MTX_A_GATE] = &d_mtx_a_gate.common.hw, + [CLK_D_NOC_F_GATE] = &d_noc_f_gate.common.hw, + [CLK_D_NOC_A_GATE] = &d_noc_a_gate.common.hw, + [CLK_GSP_MTX_F_GATE] = &gsp_mtx_f_gate.common.hw, + [CLK_GSP_MTX_A_GATE] = &gsp_mtx_a_gate.common.hw, + [CLK_GSP_NOC_F_GATE] = &gsp_noc_f_gate.common.hw, + [CLK_GSP_NOC_A_GATE] = &gsp_noc_a_gate.common.hw, + [CLK_DISPM0IDLE_GATE] = &dispm0idle_gate.common.hw, + [CLK_GSPM0IDLE_GATE] = &gspm0idle_gate.common.hw, + }, + .num = CLK_DISP_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_disp_gate_desc = { + .clk_clks = sc9860_disp_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_disp_gate), + .hw_clks = &sc9860_disp_gate_hws, +}; + +static SPRD_GATE_CLK(sim0_eb, "sim0-eb", "ap-apb", 0x0, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis0_eb, "iis0-eb", "ap-apb", 0x0, + 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis1_eb, "iis1-eb", "ap-apb", 0x0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis2_eb, "iis2-eb", "ap-apb", 0x0, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis3_eb, "iis3-eb", "ap-apb", 0x0, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi0_eb, "spi0-eb", "ap-apb", 0x0, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi1_eb, "spi1-eb", "ap-apb", 0x0, + 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi2_eb, "spi2-eb", "ap-apb", 0x0, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c0_eb, "i2c0-eb", "ap-apb", 0x0, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c1_eb, "i2c1-eb", "ap-apb", 0x0, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c2_eb, "i2c2-eb", "ap-apb", 0x0, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c3_eb, "i2c3-eb", "ap-apb", 0x0, + 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c4_eb, "i2c4-eb", "ap-apb", 0x0, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c5_eb, "i2c5-eb", "ap-apb", 0x0, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart0_eb, "uart0-eb", "ap-apb", 0x0, + 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart1_eb, "uart1-eb", "ap-apb", 0x0, + 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart2_eb, "uart2-eb", "ap-apb", 0x0, + 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart3_eb, "uart3-eb", "ap-apb", 0x0, + 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart4_eb, "uart4-eb", "ap-apb", 0x0, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_ckg_eb, "ap-ckg-eb", "ap-apb", 0x0, + 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi3_eb, "spi3-eb", "ap-apb", 0x0, + 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0); + +static struct sprd_clk_common *sc9860_apapb_gate[] = { + /* address base is 0x70b00000 */ + &sim0_eb.common, + &iis0_eb.common, + &iis1_eb.common, + &iis2_eb.common, + &iis3_eb.common, + &spi0_eb.common, + &spi1_eb.common, + &spi2_eb.common, + &i2c0_eb.common, + &i2c1_eb.common, + &i2c2_eb.common, + &i2c3_eb.common, + &i2c4_eb.common, + &i2c5_eb.common, + &uart0_eb.common, + &uart1_eb.common, + &uart2_eb.common, + &uart3_eb.common, + &uart4_eb.common, + &ap_ckg_eb.common, + &spi3_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_apapb_gate_hws = { + .hws = { + [CLK_SIM0_EB] = &sim0_eb.common.hw, + [CLK_IIS0_EB] = &iis0_eb.common.hw, + [CLK_IIS1_EB] = &iis1_eb.common.hw, + [CLK_IIS2_EB] = &iis2_eb.common.hw, + [CLK_IIS3_EB] = &iis3_eb.common.hw, + [CLK_SPI0_EB] = &spi0_eb.common.hw, + [CLK_SPI1_EB] = &spi1_eb.common.hw, + [CLK_SPI2_EB] = &spi2_eb.common.hw, + [CLK_I2C0_EB] = &i2c0_eb.common.hw, + [CLK_I2C1_EB] = &i2c1_eb.common.hw, + [CLK_I2C2_EB] = &i2c2_eb.common.hw, + [CLK_I2C3_EB] = &i2c3_eb.common.hw, + [CLK_I2C4_EB] = &i2c4_eb.common.hw, + [CLK_I2C5_EB] = &i2c5_eb.common.hw, + [CLK_UART0_EB] = &uart0_eb.common.hw, + [CLK_UART1_EB] = &uart1_eb.common.hw, + [CLK_UART2_EB] = &uart2_eb.common.hw, + [CLK_UART3_EB] = &uart3_eb.common.hw, + [CLK_UART4_EB] = &uart4_eb.common.hw, + [CLK_AP_CKG_EB] = &ap_ckg_eb.common.hw, + [CLK_SPI3_EB] = &spi3_eb.common.hw, + }, + .num = CLK_APAPB_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_apapb_gate_desc = { + .clk_clks = sc9860_apapb_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_apapb_gate), + .hw_clks = &sc9860_apapb_gate_hws, +}; + +static const struct of_device_id sprd_sc9860_clk_ids[] = { + { .compatible = "sprd,sc9860-pmu-gate", /* 0x402b */ + .data = &sc9860_pmu_gate_desc }, + { .compatible = "sprd,sc9860-pll", /* 0x4040 */ + .data = &sc9860_pll_desc }, + { .compatible = "sprd,sc9860-ap-clk", /* 0x2000 */ + .data = &sc9860_ap_clk_desc }, + { .compatible = "sprd,sc9860-aon-prediv", /* 0x402d */ + .data = &sc9860_aon_prediv_desc }, + { .compatible = "sprd,sc9860-apahb-gate", /* 0x2021 */ + .data = &sc9860_apahb_gate_desc }, + { .compatible = "sprd,sc9860-aon-gate", /* 0x402e */ + .data = &sc9860_aon_gate_desc }, + { .compatible = "sprd,sc9860-aonsecure-clk", /* 0x4088 */ + .data = &sc9860_aonsecure_clk_desc }, + { .compatible = "sprd,sc9860-agcp-gate", /* 0x415e */ + .data = &sc9860_agcp_gate_desc }, + { .compatible = "sprd,sc9860-gpu-clk", /* 0x6020 */ + .data = &sc9860_gpu_clk_desc }, + { .compatible = "sprd,sc9860-vsp-clk", /* 0x6100 */ + .data = &sc9860_vsp_clk_desc }, + { .compatible = "sprd,sc9860-vsp-gate", /* 0x6110 */ + .data = &sc9860_vsp_gate_desc }, + { .compatible = "sprd,sc9860-cam-clk", /* 0x6200 */ + .data = &sc9860_cam_clk_desc }, + { .compatible = "sprd,sc9860-cam-gate", /* 0x6210 */ + .data = &sc9860_cam_gate_desc }, + { .compatible = "sprd,sc9860-disp-clk", /* 0x6300 */ + .data = &sc9860_disp_clk_desc }, + { .compatible = "sprd,sc9860-disp-gate", /* 0x6310 */ + .data = &sc9860_disp_gate_desc }, + { .compatible = "sprd,sc9860-apapb-gate", /* 0x70b0 */ + .data = &sc9860_apapb_gate_desc }, + { } +}; +MODULE_DEVICE_TABLE(of, sprd_sc9860_clk_ids); + +static int sc9860_clk_probe(struct platform_device *pdev) +{ + int ret = 0; + const struct of_device_id *match; + const struct sprd_clk_desc *desc; + + match = of_match_node(sprd_sc9860_clk_ids, pdev->dev.of_node); + if (!match) { + pr_err("%s: of_match_node() failed.", __func__); + return -ENODEV; + } + + desc = match->data; + sprd_clk_regmap_init(pdev, desc); + + ret = sprd_clk_probe(pdev->dev.of_node, desc->hw_clks); + if (ret == 0) + pr_info("%s: %u clocks have been registered now.\n", + match->compatible, desc->hw_clks->num); + + return ret; +} + +static struct platform_driver sc9860_clk_driver = { + .probe = sc9860_clk_probe, + .driver = { + .name = "sc9860-clk", + .of_match_table = sprd_sc9860_clk_ids, + }, +}; +module_platform_driver(sc9860_clk_driver); + +MODULE_DESCRIPTION("Spreadtrum SC9860 Clock Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sc9860-clk"); diff --git a/include/dt-bindings/clock/sprd,sc9860-clk.h b/include/dt-bindings/clock/sprd,sc9860-clk.h new file mode 100644 index 0000000..48e6052 --- /dev/null +++ b/include/dt-bindings/clock/sprd,sc9860-clk.h @@ -0,0 +1,408 @@ +/* + * Spreadtrum SC9860 platform clocks + * + * Copyright (C) 2017, Spreadtrum Communications Inc. + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +#ifndef _DT_BINDINGS_CLK_SC9860_H_ +#define _DT_BINDINGS_CLK_SC9860_H_ + +#define CLK_EXT_RCO_100M 0 +#define CLK_EXT_32K 1 +#define CLK_FAC_4M 2 +#define CLK_FAC_2M 3 +#define CLK_FAC_1M 4 +#define CLK_FAC_250K 5 +#define CLK_FAC_RPLL0_26M 6 +#define CLK_FAC_RPLL1_26M 7 +#define CLK_FAC_RCO25M 8 +#define CLK_FAC_RCO4M 9 +#define CLK_FAC_RCO2M 10 +#define CLK_FAC_3K2 11 +#define CLK_FAC_1K 12 +#define CLK_MPLL0_GATE 13 +#define CLK_MPLL1_GATE 14 +#define CLK_DPLL0_GATE 15 +#define CLK_DPLL1_GATE 16 +#define CLK_LTEPLL0_GATE 17 +#define CLK_TWPLL_GATE 18 +#define CLK_LTEPLL1_GATE 19 +#define CLK_RPLL0_GATE 20 +#define CLK_RPLL1_GATE 21 +#define CLK_CPPLL_GATE 22 +#define CLK_GPLL_GATE 23 +#define CLK_PMU_GATE_NUM (CLK_GPLL_GATE + 1) + +#define CLK_MPLL0 0 +#define CLK_MPLL1 1 +#define CLK_DPLL0 2 +#define CLK_DPLL1 3 +#define CLK_RPLL0 4 +#define CLK_RPLL1 5 +#define CLK_TWPLL 6 +#define CLK_LTEPLL0 7 +#define CLK_LTEPLL1 8 +#define CLK_GPLL 9 +#define CLK_CPPLL 10 +#define CLK_GPLL_42M5 11 +#define CLK_TWPLL_768M 12 +#define CLK_TWPLL_384M 13 +#define CLK_TWPLL_192M 14 +#define CLK_TWPLL_96M 15 +#define CLK_TWPLL_48M 16 +#define CLK_TWPLL_24M 17 +#define CLK_TWPLL_12M 18 +#define CLK_TWPLL_512M 19 +#define CLK_TWPLL_256M 20 +#define CLK_TWPLL_128M 21 +#define CLK_TWPLL_64M 22 +#define CLK_TWPLL_307M2 23 +#define CLK_TWPLL_153M6 24 +#define CLK_TWPLL_76M8 25 +#define CLK_TWPLL_51M2 26 +#define CLK_TWPLL_38M4 27 +#define CLK_TWPLL_19M2 28 +#define CLK_L0_614M4 29 +#define CLK_L0_409M6 30 +#define CLK_L0_38M 31 +#define CLK_L1_38M 32 +#define CLK_RPLL0_192M 33 +#define CLK_RPLL0_96M 34 +#define CLK_RPLL0_48M 35 +#define CLK_RPLL1_468M 36 +#define CLK_RPLL1_192M 37 +#define CLK_RPLL1_96M 38 +#define CLK_RPLL1_64M 39 +#define CLK_RPLL1_48M 40 +#define CLK_DPLL0_50M 41 +#define CLK_DPLL1_50M 42 +#define CLK_CPPLL_50M 43 +#define CLK_M0_39M 44 +#define CLK_M1_63M 45 +#define CLK_PLL_NUM (CLK_M1_63M + 1) + + +#define CLK_AP_APB 0 +#define CLK_AP_USB3 1 +#define CLK_UART0 2 +#define CLK_UART1 3 +#define CLK_UART2 4 +#define CLK_UART3 5 +#define CLK_UART4 6 +#define CLK_I2C0 7 +#define CLK_I2C1 8 +#define CLK_I2C2 9 +#define CLK_I2C3 10 +#define CLK_I2C4 11 +#define CLK_I2C5 12 +#define CLK_SPI0 13 +#define CLK_SPI1 14 +#define CLK_SPI2 15 +#define CLK_SPI3 16 +#define CLK_IIS0 17 +#define CLK_IIS1 18 +#define CLK_IIS2 19 +#define CLK_IIS3 20 +#define CLK_AP_CLK_NUM (CLK_IIS3 + 1) + +#define CLK_AON_APB 0 +#define CLK_AUX0 1 +#define CLK_AUX1 2 +#define CLK_AUX2 3 +#define CLK_PROBE 4 +#define CLK_SP_AHB 5 +#define CLK_CCI 6 +#define CLK_GIC 7 +#define CLK_CSSYS 8 +#define CLK_SDIO0_2X 9 +#define CLK_SDIO1_2X 10 +#define CLK_SDIO2_2X 11 +#define CLK_EMMC_2X 12 +#define CLK_SDIO0_1X 13 +#define CLK_SDIO1_1X 14 +#define CLK_SDIO2_1X 15 +#define CLK_EMMC_1X 16 +#define CLK_ADI 17 +#define CLK_PWM0 18 +#define CLK_PWM1 19 +#define CLK_PWM2 20 +#define CLK_PWM3 21 +#define CLK_EFUSE 22 +#define CLK_CM3_UART0 23 +#define CLK_CM3_UART1 24 +#define CLK_THM 25 +#define CLK_CM3_I2C0 26 +#define CLK_CM3_I2C1 27 +#define CLK_CM4_SPI 28 +#define CLK_AON_I2C 29 +#define CLK_AVS 30 +#define CLK_CA53_DAP 31 +#define CLK_CA53_TS 32 +#define CLK_DJTAG_TCK 33 +#define CLK_PMU 34 +#define CLK_PMU_26M 35 +#define CLK_DEBOUNCE 36 +#define CLK_OTG2_REF 37 +#define CLK_USB3_REF 38 +#define CLK_AP_AXI 39 +#define CLK_AON_PREDIV_NUM (CLK_AP_AXI + 1) + +#define CLK_USB3_EB 0 +#define CLK_USB3_SUSPEND_EB 1 +#define CLK_USB3_REF_EB 2 +#define CLK_DMA_EB 3 +#define CLK_SDIO0_EB 4 +#define CLK_SDIO1_EB 5 +#define CLK_SDIO2_EB 6 +#define CLK_EMMC_EB 7 +#define CLK_ROM_EB 8 +#define CLK_BUSMON_EB 9 +#define CLK_CC63S_EB 10 +#define CLK_CC63P_EB 11 +#define CLK_CE0_EB 12 +#define CLK_CE1_EB 13 +#define CLK_APAHB_GATE_NUM (CLK_CE1_EB + 1) + +#define CLK_AVS_LIT_EB 0 +#define CLK_AVS_BIG_EB 1 +#define CLK_AP_INTC5_EB 2 +#define CLK_GPIO_EB 3 +#define CLK_PWM0_EB 4 +#define CLK_PWM1_EB 5 +#define CLK_PWM2_EB 6 +#define CLK_PWM3_EB 7 +#define CLK_KPD_EB 8 +#define CLK_AON_SYS_EB 9 +#define CLK_AP_SYS_EB 10 +#define CLK_AON_TMR_EB 11 +#define CLK_AP_TMR0_EB 12 +#define CLK_EFUSE_EB 13 +#define CLK_EIC_EB 14 +#define CLK_PUB1_REG_EB 15 +#define CLK_ADI_EB 16 +#define CLK_AP_INTC0_EB 17 +#define CLK_AP_INTC1_EB 18 +#define CLK_AP_INTC2_EB 19 +#define CLK_AP_INTC3_EB 20 +#define CLK_AP_INTC4_EB 21 +#define CLK_SPLK_EB 22 +#define CLK_MSPI_EB 23 +#define CLK_PUB0_REG_EB 24 +#define CLK_PIN_EB 25 +#define CLK_AON_CKG_EB 26 +#define CLK_GPU_EB 27 +#define CLK_APCPU_TS0_EB 28 +#define CLK_APCPU_TS1_EB 29 +#define CLK_DAP_EB 30 +#define CLK_I2C_EB 31 +#define CLK_PMU_EB 32 +#define CLK_THM_EB 33 +#define CLK_AUX0_EB 34 +#define CLK_AUX1_EB 35 +#define CLK_AUX2_EB 36 +#define CLK_PROBE_EB 37 +#define CLK_GPU0_AVS_EB 38 +#define CLK_GPU1_AVS_EB 39 +#define CLK_APCPU_WDG_EB 40 +#define CLK_AP_TMR1_EB 41 +#define CLK_AP_TMR2_EB 42 +#define CLK_DISP_EMC_EB 43 +#define CLK_ZIP_EMC_EB 44 +#define CLK_GSP_EMC_EB 45 +#define CLK_OSC_AON_EB 46 +#define CLK_LVDS_TRX_EB 47 +#define CLK_LVDS_TCXO_EB 48 +#define CLK_MDAR_EB 49 +#define CLK_RTC4M0_CAL_EB 50 +#define CLK_RCT100M_CAL_EB 51 +#define CLK_DJTAG_EB 52 +#define CLK_MBOX_EB 53 +#define CLK_AON_DMA_EB 54 +#define CLK_DBG_EMC_EB 55 +#define CLK_LVDS_PLL_DIV_EN 56 +#define CLK_DEF_EB 57 +#define CLK_AON_APB_RSV0 58 +#define CLK_ORP_JTAG_EB 59 +#define CLK_VSP_EB 60 +#define CLK_CAM_EB 61 +#define CLK_DISP_EB 62 +#define CLK_DBG_AXI_IF_EB 63 +#define CLK_SDIO0_2X_EN 64 +#define CLK_SDIO1_2X_EN 65 +#define CLK_SDIO2_2X_EN 66 +#define CLK_EMMC_2X_EN 67 +#define CLK_AON_GATE_NUM (CLK_EMMC_2X_EN + 1) + +#define CLK_LIT_MCU 0 +#define CLK_BIG_MCU 1 +#define CLK_AONSECURE_NUM (CLK_BIG_MCU + 1) + +#define CLK_AGCP_IIS0_EB 0 +#define CLK_AGCP_IIS1_EB 1 +#define CLK_AGCP_IIS2_EB 2 +#define CLK_AGCP_IIS3_EB 3 +#define CLK_AGCP_UART_EB 4 +#define CLK_AGCP_DMACP_EB 5 +#define CLK_AGCP_DMAAP_EB 6 +#define CLK_AGCP_ARC48K_EB 7 +#define CLK_AGCP_SRC44P1K_EB 8 +#define CLK_AGCP_MCDT_EB 9 +#define CLK_AGCP_VBCIFD_EB 10 +#define CLK_AGCP_VBC_EB 11 +#define CLK_AGCP_SPINLOCK_EB 12 +#define CLK_AGCP_ICU_EB 13 +#define CLK_AGCP_AP_ASHB_EB 14 +#define CLK_AGCP_CP_ASHB_EB 15 +#define CLK_AGCP_AUD_EB 16 +#define CLK_AGCP_AUDIF_EB 17 +#define CLK_AGCP_GATE_NUM (CLK_AGCP_AUDIF_EB + 1) + +#define CLK_GPU 0 +#define CLK_GPU_NUM (CLK_GPU + 1) + +#define CLK_AHB_VSP 0 +#define CLK_VSP 1 +#define CLK_VSP_ENC 2 +#define CLK_VPP 3 +#define CLK_VSP_26M 4 +#define CLK_VSP_NUM (CLK_VSP_26M + 1) + +#define CLK_VSP_DEC_EB 0 +#define CLK_VSP_CKG_EB 1 +#define CLK_VSP_MMU_EB 2 +#define CLK_VSP_ENC_EB 3 +#define CLK_VPP_EB 4 +#define CLK_VSP_26M_EB 5 +#define CLK_VSP_AXI_GATE 6 +#define CLK_VSP_ENC_GATE 7 +#define CLK_VPP_AXI_GATE 8 +#define CLK_VSP_BM_GATE 9 +#define CLK_VSP_ENC_BM_GATE 10 +#define CLK_VPP_BM_GATE 11 +#define CLK_VSP_GATE_NUM (CLK_VPP_BM_GATE + 1) + +#define CLK_AHB_CAM 0 +#define CLK_SENSOR0 1 +#define CLK_SENSOR1 2 +#define CLK_SENSOR2 3 +#define CLK_MIPI_CSI0_EB 4 +#define CLK_MIPI_CSI1_EB 5 +#define CLK_CAM_NUM (CLK_MIPI_CSI1_EB + 1) + +#define CLK_DCAM0_EB 0 +#define CLK_DCAM1_EB 1 +#define CLK_ISP0_EB 2 +#define CLK_CSI0_EB 3 +#define CLK_CSI1_EB 4 +#define CLK_JPG0_EB 5 +#define CLK_JPG1_EB 6 +#define CLK_CAM_CKG_EB 7 +#define CLK_CAM_MMU_EB 8 +#define CLK_ISP1_EB 9 +#define CLK_CPP_EB 10 +#define CLK_MMU_PF_EB 11 +#define CLK_ISP2_EB 12 +#define CLK_DCAM2ISP_IF_EB 13 +#define CLK_ISP2DCAM_IF_EB 14 +#define CLK_ISP_LCLK_EB 15 +#define CLK_ISP_ICLK_EB 16 +#define CLK_ISP_MCLK_EB 17 +#define CLK_ISP_PCLK_EB 18 +#define CLK_ISP_ISP2DCAM_EB 19 +#define CLK_DCAM0_IF_EB 20 +#define CLK_CLK26M_IF_EB 21 +#define CLK_CPHY0_GATE 22 +#define CLK_MIPI_CSI0_GATE 23 +#define CLK_CPHY1_GATE 24 +#define CLK_MIPI_CSI1 25 +#define CLK_DCAM0_AXI_GATE 26 +#define CLK_DCAM1_AXI_GATE 27 +#define CLK_SENSOR0_GATE 28 +#define CLK_SENSOR1_GATE 29 +#define CLK_JPG0_AXI_GATE 30 +#define CLK_GPG1_AXI_GATE 31 +#define CLK_ISP0_AXI_GATE 32 +#define CLK_ISP1_AXI_GATE 33 +#define CLK_ISP2_AXI_GATE 34 +#define CLK_CPP_AXI_GATE 35 +#define CLK_D0_IF_AXI_GATE 36 +#define CLK_D2I_IF_AXI_GATE 37 +#define CLK_I2D_IF_AXI_GATE 38 +#define CLK_SPARE_AXI_GATE 39 +#define CLK_SENSOR2_GATE 40 +#define CLK_D0IF_IN_D_EN 41 +#define CLK_D1IF_IN_D_EN 42 +#define CLK_D0IF_IN_D2I_EN 43 +#define CLK_D1IF_IN_D2I_EN 44 +#define CLK_IA_IN_D2I_EN 45 +#define CLK_IB_IN_D2I_EN 46 +#define CLK_IC_IN_D2I_EN 47 +#define CLK_IA_IN_I_EN 48 +#define CLK_IB_IN_I_EN 49 +#define CLK_IC_IN_I_EN 50 +#define CLK_CAM_GATE_NUM (CLK_IC_IN_I_EN + 1) + +#define CLK_AHB_DISP 0 +#define CLK_DISPC0_DPI 1 +#define CLK_DISPC1_DPI 2 +#define CLK_DISP_NUM (CLK_DISPC1_DPI + 1) + +#define CLK_DISPC0_EB 0 +#define CLK_DISPC1_EB 1 +#define CLK_DISPC_MMU_EB 2 +#define CLK_GSP0_EB 3 +#define CLK_GSP1_EB 4 +#define CLK_GSP0_MMU_EB 5 +#define CLK_GSP1_MMU_EB 6 +#define CLK_DSI0_EB 7 +#define CLK_DSI1_EB 8 +#define CLK_DISP_CKG_EB 9 +#define CLK_DISP_GPU_EB 10 +#define CLK_GPU_MTX_EB 11 +#define CLK_GSP_MTX_EB 12 +#define CLK_TMC_MTX_EB 13 +#define CLK_DISPC_MTX_EB 14 +#define CLK_DPHY0_GATE 15 +#define CLK_DPHY1_GATE 16 +#define CLK_GSP0_A_GATE 17 +#define CLK_GSP1_A_GATE 18 +#define CLK_GSP0_F_GATE 19 +#define CLK_GSP1_F_GATE 20 +#define CLK_D_MTX_F_GATE 21 +#define CLK_D_MTX_A_GATE 22 +#define CLK_D_NOC_F_GATE 23 +#define CLK_D_NOC_A_GATE 24 +#define CLK_GSP_MTX_F_GATE 25 +#define CLK_GSP_MTX_A_GATE 26 +#define CLK_GSP_NOC_F_GATE 27 +#define CLK_GSP_NOC_A_GATE 28 +#define CLK_DISPM0IDLE_GATE 29 +#define CLK_GSPM0IDLE_GATE 30 +#define CLK_DISP_GATE_NUM (CLK_GSPM0IDLE_GATE + 1) + +#define CLK_SIM0_EB 0 +#define CLK_IIS0_EB 1 +#define CLK_IIS1_EB 2 +#define CLK_IIS2_EB 3 +#define CLK_IIS3_EB 4 +#define CLK_SPI0_EB 5 +#define CLK_SPI1_EB 6 +#define CLK_SPI2_EB 7 +#define CLK_I2C0_EB 8 +#define CLK_I2C1_EB 9 +#define CLK_I2C2_EB 10 +#define CLK_I2C3_EB 11 +#define CLK_I2C4_EB 12 +#define CLK_I2C5_EB 13 +#define CLK_UART0_EB 14 +#define CLK_UART1_EB 15 +#define CLK_UART2_EB 16 +#define CLK_UART3_EB 17 +#define CLK_UART4_EB 18 +#define CLK_AP_CKG_EB 19 +#define CLK_SPI3_EB 20 +#define CLK_APAPB_GATE_NUM (CLK_SPI3_EB + 1) + +#endif /* _DT_BINDINGS_CLK_SC9860_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel This patch added the list of clocks for Spreadtrum's SC9860 SoC, together with clock initialization code. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Kconfig | 10 + drivers/clk/sprd/Makefile | 3 + drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ 4 files changed, 2408 insertions(+) create mode 100644 drivers/clk/sprd/sc9860-clk.c create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig index 67a3287..8789247 100644 --- a/drivers/clk/sprd/Kconfig +++ b/drivers/clk/sprd/Kconfig @@ -2,3 +2,13 @@ config SPRD_COMMON_CLK tristate "Clock support for Spreadtrum SoCs" depends on ARCH_SPRD || COMPILE_TEST default ARCH_SPRD + +if SPRD_COMMON_CLK + +# SoC Drivers + +config SPRD_SC9860_CLK + tristate "Support for the Spreadtrum SC9860 clocks" + depends on (ARM64 && ARCH_SPRD) || COMPILE_TEST + default ARM64 && ARCH_SPRD +endif diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index d693969..b0d81e5 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -6,3 +6,6 @@ clk-sprd-y += mux.o clk-sprd-y += div.o clk-sprd-y += composite.o clk-sprd-y += pll.o + +## SoC support +obj-$(CONFIG_SPRD_SC9860_CLK) += sc9860-clk.o diff --git a/drivers/clk/sprd/sc9860-clk.c b/drivers/clk/sprd/sc9860-clk.c new file mode 100644 index 0000000..09e19ff --- /dev/null +++ b/drivers/clk/sprd/sc9860-clk.c @@ -0,0 +1,1987 @@ +/* + * Spreatrum SC9860 clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include <dt-bindings/clock/sprd,sc9860-clk.h> + +#include "common.h" +#include "composite.h" +#include "div.h" +#include "gate.h" +#include "mux.h" +#include "pll.h" + +static CLK_FIXED_RATE(ext_rco_100m, "ext-rco-100m", 0, 100000000, 0); +static CLK_FIXED_RATE(ext_32k, "ext-32k", 0, 32768, 0); + +static CLK_FIXED_FACTOR(fac_4m, "fac-4m", "ext-26m", + 6, 1, 0); +static CLK_FIXED_FACTOR(fac_2m, "fac-2m", "ext-26m", + 13, 1, 0); +static CLK_FIXED_FACTOR(fac_1m, "fac-1m", "ext-26m", + 26, 1, 0); +static CLK_FIXED_FACTOR(fac_250k, "fac-250k", "ext-26m", + 104, 1, 0); +static CLK_FIXED_FACTOR(fac_rpll0_26m, "rpll0-26m", "ext-26m", + 1, 1, 0); +static CLK_FIXED_FACTOR(fac_rpll1_26m, "rpll1-26m", "ext-26m", + 1, 1, 0); +static CLK_FIXED_FACTOR(fac_rco_25m, "rco-25m", "ext-rc0-100m", + 4, 1, 0); +static CLK_FIXED_FACTOR(fac_rco_4m, "rco-4m", "ext-rc0-100m", + 25, 1, 0); +static CLK_FIXED_FACTOR(fac_rco_2m, "rco-2m", "ext-rc0-100m", + 50, 1, 0); +static CLK_FIXED_FACTOR(fac_3k2, "fac-3k2", "ext-32k", + 10, 1, 0); +static CLK_FIXED_FACTOR(fac_1k, "fac-1k", "ext-32k", + 32, 1, 0); + +static SPRD_GATE_CLK(mpll0_gate, "mpll0-gate", "ext-26m", 0xb0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mpll1_gate, "mpll1-gate", "ext-26m", 0xb0, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dpll0_gate, "dpll0-gate", "ext-26m", 0xb4, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dpll1_gate, "dpll1-gate", "ext-26m", 0xb4, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ltepll0_gate, "ltepll0-gate", "ext-26m", 0xb8, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(twpll_gate, "twpll-gate", "ext-26m", 0xbc, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ltepll1_gate, "ltepll1-gate", "ext-26m", 0x10c, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rpll0_gate, "rpll0-gate", "ext-26m", 0x16c, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(rpll1_gate, "rpll1-gate", "ext-26m", 0x16c, + 0x1000, BIT(18), 0, 0); +static SPRD_GATE_CLK(cppll_gate, "cppll-gate", "ext-26m", 0x2b4, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpll_gate, "gpll-gate", "ext-26m", 0x32c, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, CLK_GATE_SET_TO_DISABLE); + +static struct sprd_clk_common *sc9860_pmu_gate_clks[] = { + /* address base is 0x402b0000 */ + &mpll0_gate.common, + &mpll1_gate.common, + &dpll0_gate.common, + &dpll1_gate.common, + <epll0_gate.common, + &twpll_gate.common, + <epll1_gate.common, + &rpll0_gate.common, + &rpll1_gate.common, + &cppll_gate.common, + &gpll_gate.common, +}; + +static struct clk_hw_onecell_data sc9860_pmu_gate_hws = { + .hws = { + [CLK_EXT_RCO_100M] = &ext_rco_100m.hw, + [CLK_EXT_32K] = &ext_32k.hw, + [CLK_FAC_4M] = &fac_4m.hw, + [CLK_FAC_2M] = &fac_2m.hw, + [CLK_FAC_1M] = &fac_1m.hw, + [CLK_FAC_250K] = &fac_250k.hw, + [CLK_FAC_RPLL0_26M] = &fac_rpll0_26m.hw, + [CLK_FAC_RPLL1_26M] = &fac_rpll1_26m.hw, + [CLK_FAC_RCO25M] = &fac_rco_25m.hw, + [CLK_FAC_RCO4M] = &fac_rco_4m.hw, + [CLK_FAC_RCO2M] = &fac_rco_2m.hw, + [CLK_FAC_3K2] = &fac_3k2.hw, + [CLK_FAC_1K] = &fac_1k.hw, + [CLK_MPLL0_GATE] = &mpll0_gate.common.hw, + [CLK_MPLL1_GATE] = &mpll1_gate.common.hw, + [CLK_DPLL0_GATE] = &dpll0_gate.common.hw, + [CLK_DPLL1_GATE] = &dpll1_gate.common.hw, + [CLK_LTEPLL0_GATE] = <epll0_gate.common.hw, + [CLK_TWPLL_GATE] = &twpll_gate.common.hw, + [CLK_LTEPLL1_GATE] = <epll1_gate.common.hw, + [CLK_RPLL0_GATE] = &rpll0_gate.common.hw, + [CLK_RPLL1_GATE] = &rpll1_gate.common.hw, + [CLK_CPPLL_GATE] = &cppll_gate.common.hw, + [CLK_GPLL_GATE] = &gpll_gate.common.hw, + }, + .num = CLK_PMU_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_pmu_gate_desc = { + .clk_clks = sc9860_pmu_gate_clks, + .num_clk_clks = ARRAY_SIZE(sc9860_pmu_gate_clks), + .hw_clks = &sc9860_pmu_gate_hws, +}; + +/* GPLL/LPLL/DPLL/RPLL/CPLL */ +static const u64 const itable1[4] = {3, 780000000, 988000000, 1196000000}; + +/* TWPLL/MPLL0/MPLL1 */ +static const u64 itable2[4] = {3, 1638000000, 2080000000, 2600000000UL}; + +static const struct clk_bit_field const f_mpll0[PLL_FACT_MAX] = { + { .shift = 20, .width = 1 }, /* lock_done */ + { .shift = 19, .width = 1 }, /* div_s */ + { .shift = 18, .width = 1 }, /* mod_en */ + { .shift = 17, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 11, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 56, .width = 1 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_K_FVCO(mpll0_clk, "mpll0", "mpll0-gate", 0x24, + 2, itable2, f_mpll0, 200, + 1000, 1000, 1, 1300000000); + +static const struct clk_bit_field const f_mpll1[PLL_FACT_MAX] = { + { .shift = 20, .width = 1 }, /* lock_done */ + { .shift = 19, .width = 1 }, /* div_s */ + { .shift = 18, .width = 1 }, /* mod_en */ + { .shift = 17, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 11, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 56, .width = 1 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(mpll1_clk, "mpll1", "mpll1-gate", 0x2c, + 2, itable2, f_mpll1, 200); + +static const struct clk_bit_field const f_dpll[PLL_FACT_MAX] = { + { .shift = 16, .width = 1 }, /* lock_done */ + { .shift = 15, .width = 1 }, /* div_s */ + { .shift = 14, .width = 1 }, /* mod_en */ + { .shift = 13, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 8, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(dpll0_clk, "dpll0", "dpll0-gate", 0x34, + 2, itable1, f_dpll, 200); + +static SPRD_PLL_WITH_ITABLE_1K(dpll1_clk, "dpll1", "dpll1-gate", 0x3c, + 2, itable1, f_dpll, 200); + +static const struct clk_bit_field const f_rpll[PLL_FACT_MAX] = { + { .shift = 0, .width = 1 }, /* lock_done */ + { .shift = 3, .width = 1 }, /* div_s */ + { .shift = 80, .width = 1 }, /* mod_en */ + { .shift = 81, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 14, .width = 2 }, /* ibias */ + { .shift = 16, .width = 7 }, /* n */ + { .shift = 4, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(rpll0_clk, "rpll0", "rpll0-gate", 0x44, + 3, itable1, f_rpll, 200); + +static SPRD_PLL_WITH_ITABLE_1K(rpll1_clk, "rpll1", "rpll1-gate", 0x50, + 3, itable1, f_rpll, 200); + +static const struct clk_bit_field const f_twpll[PLL_FACT_MAX] = { + { .shift = 21, .width = 1 }, /* lock_done */ + { .shift = 20, .width = 1 }, /* div_s */ + { .shift = 19, .width = 1 }, /* mod_en */ + { .shift = 18, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 13, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(twpll_clk, "twpll", "twpll-gate", 0x5c, + 2, itable2, f_twpll, 200); + +static const struct clk_bit_field const f_ltepll[PLL_FACT_MAX] = { + { .shift = 31, .width = 1 }, /* lock_done */ + { .shift = 27, .width = 1 }, /* div_s */ + { .shift = 26, .width = 1 }, /* mod_en */ + { .shift = 25, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 20, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(ltepll0_clk, "ltepll0", "ltepll0-gate", + 0x64, 2, itable1, + f_ltepll, 200); +static SPRD_PLL_WITH_ITABLE_1K(ltepll1_clk, "ltepll1", "ltepll1-gate", + 0x6c, 2, itable1, + f_ltepll, 200); + +static const struct clk_bit_field const f_gpll[PLL_FACT_MAX] = { + { .shift = 18, .width = 1 }, /* lock_done */ + { .shift = 15, .width = 1 }, /* div_s */ + { .shift = 14, .width = 1 }, /* mod_en */ + { .shift = 13, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 8, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 17, .width = 1 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_K_FVCO(gpll_clk, "gpll", "gpll-gate", 0x9c, + 2, itable1, f_gpll, 200, + 1000, 1000, 1, 600000000); + +static const struct clk_bit_field const f_cppll[PLL_FACT_MAX] = { + { .shift = 17, .width = 1 }, /* lock_done */ + { .shift = 15, .width = 1 }, /* div_s */ + { .shift = 14, .width = 1 }, /* mod_en */ + { .shift = 13, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 8, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(cppll_clk, "cppll", "cppll-gate", 0xc4, + 2, itable1, f_cppll, 200); + +static CLK_FIXED_FACTOR(gpll_42m5, "gpll-42m5", "gpll", 20, 1, 0); +static CLK_FIXED_FACTOR(twpll_768m, "twpll-768m", "twpll", 2, 1, 0); +static CLK_FIXED_FACTOR(twpll_384m, "twpll-384m", "twpll", 4, 1, 0); +static CLK_FIXED_FACTOR(twpll_192m, "twpll-192m", "twpll", 8, 1, 0); +static CLK_FIXED_FACTOR(twpll_96m, "twpll-96m", "twpll", 16, 1, 0); +static CLK_FIXED_FACTOR(twpll_48m, "twpll-48m", "twpll", 32, 1, 0); +static CLK_FIXED_FACTOR(twpll_24m, "twpll-24m", "twpll", 64, 1, 0); +static CLK_FIXED_FACTOR(twpll_12m, "twpll-12m", "twpll", 128, 1, 0); +static CLK_FIXED_FACTOR(twpll_512m, "twpll-512m", "twpll", 3, 1, 0); +static CLK_FIXED_FACTOR(twpll_256m, "twpll-256m", "twpll", 6, 1, 0); +static CLK_FIXED_FACTOR(twpll_128m, "twpll-128m", "twpll", 12, 1, 0); +static CLK_FIXED_FACTOR(twpll_64m, "twpll-64m", "twpll", 24, 1, 0); +static CLK_FIXED_FACTOR(twpll_307m2, "twpll-307m2", "twpll", 5, 1, 0); +static CLK_FIXED_FACTOR(twpll_153m6, "twpll-153m6", "twpll", 10, 1, 0); +static CLK_FIXED_FACTOR(twpll_76m8, "twpll-76m8", "twpll", 20, 1, 0); +static CLK_FIXED_FACTOR(twpll_51m2, "twpll-51m2", "twpll", 30, 1, 0); +static CLK_FIXED_FACTOR(twpll_38m4, "twpll-38m4", "twpll", 40, 1, 0); +static CLK_FIXED_FACTOR(twpll_19m2, "twpll-19m2", "twpll", 80, 1, 0); +static CLK_FIXED_FACTOR(l0_614m4, "l0-614m4", "ltepll0", 2, 1, 0); +static CLK_FIXED_FACTOR(l0_409m6, "l0-409m6", "ltepll0", 3, 1, 0); +static CLK_FIXED_FACTOR(l0_38m, "l0-38m", "ltepll0", 32, 1, 0); +static CLK_FIXED_FACTOR(l1_38m, "l1-38m", "ltepll1", 32, 1, 0); +static CLK_FIXED_FACTOR(rpll0_192m, "rpll0-192m", "rpll0", 6, 1, 0); +static CLK_FIXED_FACTOR(rpll0_96m, "rpll0-96m", "rpll0", 12, 1, 0); +static CLK_FIXED_FACTOR(rpll0_48m, "rpll0-48m", "rpll0", 24, 1, 0); +static CLK_FIXED_FACTOR(rpll1_468m, "rpll1-468m", "rpll1", 2, 1, 0); +static CLK_FIXED_FACTOR(rpll1_192m, "rpll1-192m", "rpll1", 6, 1, 0); +static CLK_FIXED_FACTOR(rpll1_96m, "rpll1-96m", "rpll1", 12, 1, 0); +static CLK_FIXED_FACTOR(rpll1_64m, "rpll1-64m", "rpll1", 18, 1, 0); +static CLK_FIXED_FACTOR(rpll1_48m, "rpll1-48m", "rpll1", 24, 1, 0); +static CLK_FIXED_FACTOR(dpll0_50m, "dpll0-50m", "dpll0", 16, 1, 0); +static CLK_FIXED_FACTOR(dpll1_50m, "dpll1-50m", "dpll1", 16, 1, 0); +static CLK_FIXED_FACTOR(cppll_50m, "cppll-50m", "cppll", 18, 1, 0); +static CLK_FIXED_FACTOR(m0_39m, "m0-39m", "mpll0", 32, 1, 0); +static CLK_FIXED_FACTOR(m1_63m, "m1-63m", "mpll1", 32, 1, 0); + +static struct sprd_clk_common *sc9860_pll_clks[] = { + /* address base is 0x40400000 */ + &mpll0_clk.common, + &mpll1_clk.common, + &dpll0_clk.common, + &dpll1_clk.common, + &rpll0_clk.common, + &rpll1_clk.common, + &twpll_clk.common, + <epll0_clk.common, + <epll1_clk.common, + &gpll_clk.common, + &cppll_clk.common, +}; + +static struct clk_hw_onecell_data sc9860_pll_hws = { + .hws = { + [CLK_MPLL0] = &mpll0_clk.common.hw, + [CLK_MPLL1] = &mpll1_clk.common.hw, + [CLK_DPLL0] = &dpll0_clk.common.hw, + [CLK_DPLL1] = &dpll1_clk.common.hw, + [CLK_RPLL0] = &rpll0_clk.common.hw, + [CLK_RPLL1] = &rpll1_clk.common.hw, + [CLK_TWPLL] = &twpll_clk.common.hw, + [CLK_LTEPLL0] = <epll0_clk.common.hw, + [CLK_LTEPLL1] = <epll1_clk.common.hw, + [CLK_GPLL] = &gpll_clk.common.hw, + [CLK_CPPLL] = &cppll_clk.common.hw, + [CLK_GPLL_42M5] = &gpll_42m5.hw, + [CLK_TWPLL_768M] = &twpll_768m.hw, + [CLK_TWPLL_384M] = &twpll_384m.hw, + [CLK_TWPLL_192M] = &twpll_192m.hw, + [CLK_TWPLL_96M] = &twpll_96m.hw, + [CLK_TWPLL_48M] = &twpll_48m.hw, + [CLK_TWPLL_24M] = &twpll_24m.hw, + [CLK_TWPLL_12M] = &twpll_12m.hw, + [CLK_TWPLL_512M] = &twpll_512m.hw, + [CLK_TWPLL_256M] = &twpll_256m.hw, + [CLK_TWPLL_128M] = &twpll_128m.hw, + [CLK_TWPLL_64M] = &twpll_64m.hw, + [CLK_TWPLL_307M2] = &twpll_307m2.hw, + [CLK_TWPLL_153M6] = &twpll_153m6.hw, + [CLK_TWPLL_76M8] = &twpll_76m8.hw, + [CLK_TWPLL_51M2] = &twpll_51m2.hw, + [CLK_TWPLL_38M4] = &twpll_38m4.hw, + [CLK_TWPLL_19M2] = &twpll_19m2.hw, + [CLK_L0_614M4] = &l0_614m4.hw, + [CLK_L0_409M6] = &l0_409m6.hw, + [CLK_L0_38M] = &l0_38m.hw, + [CLK_L1_38M] = &l1_38m.hw, + [CLK_RPLL0_192M] = &rpll0_192m.hw, + [CLK_RPLL0_96M] = &rpll0_96m.hw, + [CLK_RPLL0_48M] = &rpll0_48m.hw, + [CLK_RPLL1_468M] = &rpll1_468m.hw, + [CLK_RPLL1_192M] = &rpll1_192m.hw, + [CLK_RPLL1_96M] = &rpll1_96m.hw, + [CLK_RPLL1_64M] = &rpll1_64m.hw, + [CLK_RPLL1_48M] = &rpll1_48m.hw, + [CLK_DPLL0_50M] = &dpll0_50m.hw, + [CLK_DPLL1_50M] = &dpll1_50m.hw, + [CLK_CPPLL_50M] = &cppll_50m.hw, + [CLK_M0_39M] = &m0_39m.hw, + [CLK_M1_63M] = &m1_63m.hw, + }, + .num = CLK_PLL_NUM, +}; + +static const struct sprd_clk_desc sc9860_pll_desc = { + .clk_clks = sc9860_pll_clks, + .num_clk_clks = ARRAY_SIZE(sc9860_pll_clks), + .hw_clks = &sc9860_pll_hws, +}; + +#define SC9860_MUX_FLAG \ + (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_NO_REPARENT) + +static const char * const ap_apb_parents[] = { "ext-26m", "twpll-64m", + "twpll-96m", "twpll-128m" }; +static SPRD_MUX_CLK(ap_apb, "ap-apb", ap_apb_parents, NULL, + 0x20, 0, 1, SC9860_MUX_FLAG); + +static const char * const ap_apb_usb3[] = { "ext-32k", "twpll-24m" }; +static SPRD_MUX_CLK(ap_usb3, "ap-usb3", ap_apb_usb3, NULL, + 0x2c, 0, 1, SC9860_MUX_FLAG); + +static const char * const uart_parents[] = { "ext-26m", "twpll-48m", + "twpll-51m2", "twpll-96m" }; +static SPRD_COMP_CLK(uart0_clk, "uart0", uart_parents, 0x30, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart1_clk, "uart1", uart_parents, 0x34, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart2_clk, "uart2", uart_parents, 0x38, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart3_clk, "uart3", uart_parents, 0x3c, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart4_clk, "uart4", uart_parents, 0x40, + 0, 0, 2, 8, 3, 0); + +static const char * const i2c_parents[] = { "ext-26m", "twpll-48m", + "twpll-51m2", "twpll-153m6" }; +static SPRD_COMP_CLK(i2c0_clk, "i2c0", i2c_parents, 0x44, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c1_clk, "i2c1", i2c_parents, 0x48, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c2_clk, "i2c2", i2c_parents, 0x4c, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c3_clk, "i2c3", i2c_parents, 0x50, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c4_clk, "i2c4", i2c_parents, 0x54, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c5_clk, "i2c5", i2c_parents, 0x58, + 0, 0, 2, 8, 3, 0); + +static const char * const spi_parents[] = { "ext-26m", "twpll-128m", + "twpll-153m6", "twpll-192m" }; +static SPRD_COMP_CLK(spi0_clk, "spi0", spi_parents, 0x5c, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(spi1_clk, "spi1", spi_parents, 0x60, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(spi2_clk, "spi2", spi_parents, 0x64, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(spi3_clk, "spi3", spi_parents, 0x68, + 0, 0, 2, 8, 3, 0); + +static const char * const iis_parents[] = { "ext-26m", + "twpll-128m", + "twpll-153m6" }; +static SPRD_COMP_CLK(iis0_clk, "iis0", iis_parents, 0x6c, + 0, 0, 2, 8, 6, 0); +static SPRD_COMP_CLK(iis1_clk, "iis1", iis_parents, 0x70, + 0, 0, 2, 8, 6, 0); +static SPRD_COMP_CLK(iis2_clk, "iis2", iis_parents, 0x74, + 0, 0, 2, 8, 6, 0); +static SPRD_COMP_CLK(iis3_clk, "iis3", iis_parents, 0x78, + 0, 0, 2, 8, 6, 0); + +static struct sprd_clk_common *sc9860_ap_clks[] = { + /* address base is 0x20000000 */ + &ap_apb.common, + &ap_usb3.common, + &uart0_clk.common, + &uart1_clk.common, + &uart2_clk.common, + &uart3_clk.common, + &uart4_clk.common, + &i2c0_clk.common, + &i2c1_clk.common, + &i2c2_clk.common, + &i2c3_clk.common, + &i2c4_clk.common, + &i2c5_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &spi2_clk.common, + &spi3_clk.common, + &iis0_clk.common, + &iis1_clk.common, + &iis2_clk.common, + &iis3_clk.common, +}; + +static struct clk_hw_onecell_data sc9860_ap_clk_hws = { + .hws = { + [CLK_AP_APB] = &ap_apb.common.hw, + [CLK_AP_USB3] = &ap_usb3.common.hw, + [CLK_UART0] = &uart0_clk.common.hw, + [CLK_UART1] = &uart1_clk.common.hw, + [CLK_UART2] = &uart2_clk.common.hw, + [CLK_UART3] = &uart3_clk.common.hw, + [CLK_UART4] = &uart4_clk.common.hw, + [CLK_I2C0] = &i2c0_clk.common.hw, + [CLK_I2C1] = &i2c1_clk.common.hw, + [CLK_I2C2] = &i2c2_clk.common.hw, + [CLK_I2C3] = &i2c3_clk.common.hw, + [CLK_I2C4] = &i2c4_clk.common.hw, + [CLK_I2C5] = &i2c5_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_SPI2] = &spi2_clk.common.hw, + [CLK_SPI3] = &spi3_clk.common.hw, + [CLK_IIS0] = &iis0_clk.common.hw, + [CLK_IIS1] = &iis1_clk.common.hw, + [CLK_IIS2] = &iis2_clk.common.hw, + [CLK_IIS3] = &iis3_clk.common.hw, + }, + .num = CLK_AP_CLK_NUM, +}; + +static const struct sprd_clk_desc sc9860_ap_clk_desc = { + .clk_clks = sc9860_ap_clks, + .num_clk_clks = ARRAY_SIZE(sc9860_ap_clks), + .hw_clks = &sc9860_ap_clk_hws, +}; + +static const char * const aon_apb_parents[] = { "rco-25m", "ext-26m", + "ext-rco-100m", "twpll-96m", + "twpll-128m", + "twpll-153m6" }; +static SPRD_COMP_CLK(aon_apb, "aon-apb", aon_apb_parents, 0x230, + 0, 0, 3, 8, 2, 0); + +static const char * const aux_parents[] = { "ext-32k", "rpll0-26m", + "rpll1-26m", "ext-26m", + "cppll-50m", "rco-25m", + "dpll0-50m", "dpll1-50m", + "gpll-42m5", "twpll-48m", + "m0-39m", "m1-63m", + "l0-38m", "l1-38m" }; + +static SPRD_COMP_CLK(aux0_clk, "aux0", aux_parents, 0x238, + 0, 0, 5, 8, 4, 0); +static SPRD_COMP_CLK(aux1_clk, "aux1", aux_parents, 0x23c, + 0, 0, 5, 8, 4, 0); +static SPRD_COMP_CLK(aux2_clk, "aux2", aux_parents, 0x240, + 0, 0, 5, 8, 4, 0); +static SPRD_COMP_CLK(probe_clk, "probe", aux_parents, 0x244, + 0, 0, 5, 8, 4, 0); + +static const char * const sp_ahb_parents[] = { "rco-4m", "ext-26m", + "ext-rco-100m", "twpll-96m", + "twpll-128m", + "twpll-153m6" }; +static SPRD_COMP_CLK(sp_ahb, "sp-ahb", sp_ahb_parents, 0x2d0, + 0, 0, 3, 8, 2, 0); + +static const char * const cci_parents[] = { "ext-26m", "twpll-384m", + "l0-614m4", "twpll-768m" }; +static SPRD_COMP_CLK(cci_clk, "cci", cci_parents, 0x300, + 0, 0, 2, 8, 2, 0); +static SPRD_COMP_CLK(gic_clk, "gic", cci_parents, 0x304, + 0, 0, 2, 8, 2, 0); +static SPRD_COMP_CLK(cssys_clk, "cssys", cci_parents, 0x310, + 0, 0, 2, 8, 2, 0); + +static const char * const sdio_2x_parents[] = { "fac-1m", "ext-26m", + "twpll-307m2", "twpll-384m", + "l0-409m6" }; +static SPRD_COMP_CLK(sdio0_2x, "sdio0-2x", sdio_2x_parents, 0x328, + 0, 0, 3, 8, 4, 0); +static SPRD_COMP_CLK(sdio1_2x, "sdio1-2x", sdio_2x_parents, 0x330, + 0, 0, 3, 8, 4, 0); +static SPRD_COMP_CLK(sdio2_2x, "sdio2-2x", sdio_2x_parents, 0x338, + 0, 0, 3, 8, 4, 0); +static SPRD_COMP_CLK(emmc_2x, "emmc-2x", sdio_2x_parents, 0x340, + 0, 0, 3, 8, 4, 0); + +static SPRD_DIV_CLK(sdio0_1x, "sdio0-1x", "sdio0-2x", 0x32c, + 8, 1, 0); +static SPRD_DIV_CLK(sdio1_1x, "sdio1-1x", "sdio1-2x", 0x334, + 8, 1, 0); +static SPRD_DIV_CLK(sdio2_1x, "sdio2-1x", "sdio2-2x", 0x33c, + 8, 1, 0); +static SPRD_DIV_CLK(emmc_1x, "emmc-1x", "emmc-2x", 0x344, + 8, 1, 0); + +static const char * const adi_parents[] = { "rco-4m", "ext-26m", + "rco-25m", "twpll-38m4", + "twpll-51m2" }; +static SPRD_MUX_CLK(adi_clk, "adi", adi_parents, NULL, 0x234, + 0, 3, SC9860_MUX_FLAG); + +static const char * const pwm_parents[] = { "ext-32k", "ext-26m", + "rco-4m", "rco-25m", + "twpll-48m" }; +static SPRD_MUX_CLK(pwm0_clk, "pwm0", pwm_parents, NULL, 0x248, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(pwm1_clk, "pwm1", pwm_parents, NULL, 0x24c, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(pwm2_clk, "pwm2", pwm_parents, NULL, 0x250, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(pwm3_clk, "pwm3", pwm_parents, NULL, 0x254, + 0, 3, SC9860_MUX_FLAG); + +static const char * const efuse_parents[] = { "rco-25m", "ext-26m" }; +static SPRD_MUX_CLK(efuse_clk, "efuse", efuse_parents, NULL, 0x258, + 0, 1, SC9860_MUX_FLAG); + +static const char * const cm3_uart_parents[] = { "rco-4m", "ext-26m", + "rco-100m", "twpll-48m", + "twpll-51m2", "twpll-96m", + "twpll-128m" }; +static SPRD_MUX_CLK(cm3_uart0, "cm3-uart0", cm3_uart_parents, NULL, 0x25c, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(cm3_uart1, "cm3-uart1", cm3_uart_parents, NULL, 0x260, + 0, 3, SC9860_MUX_FLAG); + +static const char * const thm_parents[] = { "ext-32k", "fac-250k" }; +static SPRD_MUX_CLK(thm_clk, "thm", thm_parents, NULL, 0x270, + 0, 1, SC9860_MUX_FLAG); + +static const char * const cm3_i2c_parents[] = { "rco-4m", + "ext-26m", + "rco-100m", + "twpll-48m", + "twpll-51m2", + "twpll-153m6" }; +static SPRD_MUX_CLK(cm3_i2c0, "cm3-i2c0", cm3_i2c_parents, NULL, 0x274, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(cm3_i2c1, "cm3-i2c1", cm3_i2c_parents, NULL, 0x278, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(aon_i2c, "aon-i2c", cm3_i2c_parents, NULL, 0x280, + 0, 3, SC9860_MUX_FLAG); + +static const char * const cm4_spi_parents[] = { "ext-26m", "twpll-96m", + "rco-100m", "twpll-128m", + "twpll-153m6", "twpll-192m" }; +static SPRD_MUX_CLK(cm4_spi, "cm4-spi", cm4_spi_parents, NULL, 0x27c, + 0, 3, SC9860_MUX_FLAG); + +static SPRD_MUX_CLK(avs_clk, "avs", uart_parents, NULL, 0x284, + 0, 2, SC9860_MUX_FLAG); + +static const char * const ca53_dap_parents[] = { "ext-26m", "rco-4m", + "rco-100m", "twpll-76m8", + "twpll-128m", "twpll-153m6" }; +static SPRD_MUX_CLK(ca53_dap, "ca53-dap", ca53_dap_parents, NULL, 0x288, + 0, 3, SC9860_MUX_FLAG); + +static const char * const ca53_ts_parents[] = { "ext-32k", "ext-26m", + "clk-twpll-128m", + "clk-twpll-153m6" }; +static SPRD_MUX_CLK(ca53_ts, "ca53-ts", ca53_ts_parents, NULL, 0x290, + 0, 2, SC9860_MUX_FLAG); + +static const char * const djtag_tck_parents[] = { "rco-4m", "ext-26m" }; +static SPRD_MUX_CLK(djtag_tck, "djtag-tck", djtag_tck_parents, NULL, + 0x2c8, 0, 1, SC9860_MUX_FLAG); + +static const char * const pmu_parents[] = { "ext-32k", "rco-4m", "clk-4m" }; +static SPRD_MUX_CLK(pmu_clk, "pmu", pmu_parents, NULL, 0x2e0, + 0, 2, SC9860_MUX_FLAG); + +static const char * const pmu_26m_parents[] = { "rco-25m", "ext-26m" }; +static SPRD_MUX_CLK(pmu_26m, "pmu-26m", pmu_26m_parents, NULL, + 0x2e4, 0, 1, SC9860_MUX_FLAG); + +static const char * const debounce_parents[] = { "ext-32k", "rco-4m", + "rco-25m", "ext-26m" }; +static SPRD_MUX_CLK(debounce_clk, "debounce", debounce_parents, NULL, + 0x2e8, 0, 2, SC9860_MUX_FLAG); + +static const char * const otg2_ref_parents[] = { "twpll-12m", "twpll-24m" }; +static SPRD_MUX_CLK(otg2_ref, "otg2-ref", otg2_ref_parents, NULL, + 0x2f4, 0, 1, SC9860_MUX_FLAG); + +static const char * const usb3_ref_parents[] = { "twpll-24m", "twpll-19m2", + "twpll-48m" }; +static SPRD_MUX_CLK(usb3_ref, "usb3-ref", usb3_ref_parents, NULL, + 0x2f8, 0, 2, SC9860_MUX_FLAG); + +static const char * const ap_axi_parents[] = { "ext-26m", "twpll-76m8", + "twpll-128m", "twpll-256m" }; +static SPRD_MUX_CLK(ap_axi, "ap-axi", ap_axi_parents, NULL, + 0x324, 0, 2, SC9860_MUX_FLAG); + +static struct sprd_clk_common *sc9860_aon_prediv[] = { + /* address base is 0x402d0000 */ + &aon_apb.common, + &aux0_clk.common, + &aux1_clk.common, + &aux2_clk.common, + &probe_clk.common, + &sp_ahb.common, + &cci_clk.common, + &gic_clk.common, + &cssys_clk.common, + &sdio0_2x.common, + &sdio1_2x.common, + &sdio2_2x.common, + &emmc_2x.common, + &sdio0_1x.common, + &sdio1_1x.common, + &sdio2_1x.common, + &emmc_1x.common, + &adi_clk.common, + &pwm0_clk.common, + &pwm1_clk.common, + &pwm2_clk.common, + &pwm3_clk.common, + &efuse_clk.common, + &cm3_uart0.common, + &cm3_uart1.common, + &thm_clk.common, + &cm3_i2c0.common, + &cm3_i2c1.common, + &cm4_spi.common, + &aon_i2c.common, + &avs_clk.common, + &ca53_dap.common, + &ca53_ts.common, + &djtag_tck.common, + &pmu_clk.common, + &pmu_26m.common, + &debounce_clk.common, + &otg2_ref.common, + &usb3_ref.common, + &ap_axi.common, +}; + +static struct clk_hw_onecell_data sc9860_aon_prediv_hws = { + .hws = { + [CLK_AON_APB] = &aon_apb.common.hw, + [CLK_AUX0] = &aux0_clk.common.hw, + [CLK_AUX1] = &aux1_clk.common.hw, + [CLK_AUX2] = &aux2_clk.common.hw, + [CLK_PROBE] = &probe_clk.common.hw, + [CLK_SP_AHB] = &sp_ahb.common.hw, + [CLK_CCI] = &cci_clk.common.hw, + [CLK_GIC] = &gic_clk.common.hw, + [CLK_CSSYS] = &cssys_clk.common.hw, + [CLK_SDIO0_2X] = &sdio0_2x.common.hw, + [CLK_SDIO1_2X] = &sdio1_2x.common.hw, + [CLK_SDIO2_2X] = &sdio2_2x.common.hw, + [CLK_EMMC_2X] = &emmc_2x.common.hw, + [CLK_SDIO0_1X] = &sdio0_1x.common.hw, + [CLK_SDIO1_1X] = &sdio1_1x.common.hw, + [CLK_SDIO2_1X] = &sdio2_1x.common.hw, + [CLK_EMMC_1X] = &emmc_1x.common.hw, + [CLK_ADI] = &adi_clk.common.hw, + [CLK_PWM0] = &pwm0_clk.common.hw, + [CLK_PWM1] = &pwm1_clk.common.hw, + [CLK_PWM2] = &pwm2_clk.common.hw, + [CLK_PWM3] = &pwm3_clk.common.hw, + [CLK_EFUSE] = &efuse_clk.common.hw, + [CLK_CM3_UART0] = &cm3_uart0.common.hw, + [CLK_CM3_UART1] = &cm3_uart1.common.hw, + [CLK_THM] = &thm_clk.common.hw, + [CLK_CM3_I2C0] = &cm3_i2c0.common.hw, + [CLK_CM3_I2C1] = &cm3_i2c1.common.hw, + [CLK_CM4_SPI] = &cm4_spi.common.hw, + [CLK_AON_I2C] = &aon_i2c.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_CA53_DAP] = &ca53_dap.common.hw, + [CLK_CA53_TS] = &ca53_ts.common.hw, + [CLK_DJTAG_TCK] = &djtag_tck.common.hw, + [CLK_PMU] = &pmu_clk.common.hw, + [CLK_PMU_26M] = &pmu_26m.common.hw, + [CLK_DEBOUNCE] = &debounce_clk.common.hw, + [CLK_OTG2_REF] = &otg2_ref.common.hw, + [CLK_USB3_REF] = &usb3_ref.common.hw, + [CLK_AP_AXI] = &ap_axi.common.hw, + }, + .num = CLK_AON_PREDIV_NUM, +}; + +static const struct sprd_clk_desc sc9860_aon_prediv_desc = { + .clk_clks = sc9860_aon_prediv, + .num_clk_clks = ARRAY_SIZE(sc9860_aon_prediv), + .hw_clks = &sc9860_aon_prediv_hws, +}; + +static SPRD_GATE_CLK(usb3_eb, "usb3-eb", "ap-axi", 0x0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(usb3_suspend, "usb3-suspend", "ap-axi", 0x0, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(usb3_ref_eb, "usb3-ref-eb", "ap-axi", 0x0, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dma_eb, "dma-eb", "ap-axi", 0x0, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio0_eb, "sdio0-eb", "ap-axi", 0x0, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio1_eb, "sdio1-eb", "ap-axi", 0x0, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio2_eb, "sdio2-eb", "ap-axi", 0x0, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(emmc_eb, "emmc-eb", "ap-axi", 0x0, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rom_eb, "rom-eb", "ap-axi", 0x0, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(busmon_eb, "busmon-eb", "ap-axi", 0x0, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(cc63s_eb, "cc63s-eb", "ap-axi", 0x0, + 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(cc63p_eb, "cc63p-eb", "ap-axi", 0x0, + 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ce0_eb, "ce0-eb", "ap-axi", 0x0, + 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ce1_eb, "ce1-eb", "ap-axi", 0x0, + 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0); + +static struct sprd_clk_common *sc9860_apahb_gate[] = { + /* address base is 0x20210000 */ + &usb3_eb.common, + &usb3_suspend.common, + &usb3_ref_eb.common, + &dma_eb.common, + &sdio0_eb.common, + &sdio1_eb.common, + &sdio2_eb.common, + &emmc_eb.common, + &rom_eb.common, + &busmon_eb.common, + &cc63s_eb.common, + &cc63p_eb.common, + &ce0_eb.common, + &ce1_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_apahb_gate_hws = { + .hws = { + [CLK_USB3_EB] = &usb3_eb.common.hw, + [CLK_USB3_SUSPEND_EB] = &usb3_suspend.common.hw, + [CLK_USB3_REF_EB] = &usb3_ref_eb.common.hw, + [CLK_DMA_EB] = &dma_eb.common.hw, + [CLK_SDIO0_EB] = &sdio0_eb.common.hw, + [CLK_SDIO1_EB] = &sdio1_eb.common.hw, + [CLK_SDIO2_EB] = &sdio2_eb.common.hw, + [CLK_EMMC_EB] = &emmc_eb.common.hw, + [CLK_ROM_EB] = &rom_eb.common.hw, + [CLK_BUSMON_EB] = &busmon_eb.common.hw, + [CLK_CC63S_EB] = &cc63s_eb.common.hw, + [CLK_CC63P_EB] = &cc63p_eb.common.hw, + [CLK_CE0_EB] = &ce0_eb.common.hw, + [CLK_CE1_EB] = &ce1_eb.common.hw, + }, + .num = CLK_APAHB_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_apahb_gate_desc = { + .clk_clks = sc9860_apahb_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_apahb_gate), + .hw_clks = &sc9860_apahb_gate_hws, +}; + +static SPRD_GATE_CLK(avs_lit_eb, "avs-lit-eb", "aon-apb", 0x0, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(avs_big_eb, "avs-big-eb", "aon-apb", 0x0, + 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc5_eb, "ap-intc5-eb", "aon-apb", 0x0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpio_eb, "gpio-eb", "aon-apb", 0x0, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm0_eb, "pwm0-eb", "aon-apb", 0x0, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm1_eb, "pwm1-eb", "aon-apb", 0x0, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm2_eb, "pwm2-eb", "aon-apb", 0x0, + 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm3_eb, "pwm3-eb", "aon-apb", 0x0, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(kpd_eb, "kpd-eb", "aon-apb", 0x0, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_sys_eb, "aon-sys-eb", "aon-apb", 0x0, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_sys_eb, "ap-sys-eb", "aon-apb", 0x0, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_tmr_eb, "aon-tmr-eb", "aon-apb", 0x0, + 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_tmr0_eb, "ap-tmr0-eb", "aon-apb", 0x0, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(efuse_eb, "efuse-eb", "aon-apb", 0x0, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(eic_eb, "eic-eb", "aon-apb", 0x0, + 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pub1_reg_eb, "pub1-reg-eb", "aon-apb", 0x0, + 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(adi_eb, "adi-eb", "aon-apb", 0x0, + 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc0_eb, "ap-intc0-eb", "aon-apb", 0x0, + 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc1_eb, "ap-intc1-eb", "aon-apb", 0x0, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc2_eb, "ap-intc2-eb", "aon-apb", 0x0, + 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc3_eb, "ap-intc3-eb", "aon-apb", 0x0, + 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc4_eb, "ap-intc4-eb", "aon-apb", 0x0, + 0x1000, BIT(21), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(splk_eb, "splk-eb", "aon-apb", 0x0, + 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mspi_eb, "mspi-eb", "aon-apb", 0x0, + 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pub0_reg_eb, "pub0-reg-eb", "aon-apb", 0x0, + 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pin_eb, "pin-eb", "aon-apb", 0x0, + 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_ckg_eb, "aon-ckg-eb", "aon-apb", 0x0, + 0x1000, BIT(26), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpu_eb, "gpu-eb", "aon-apb", 0x0, + 0x1000, BIT(27), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(apcpu_ts0_eb, "apcpu-ts0-eb", "aon-apb", 0x0, + 0x1000, BIT(28), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(apcpu_ts1_eb, "apcpu-ts1-eb", "aon-apb", 0x0, + 0x1000, BIT(29), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dap_eb, "dap-eb", "aon-apb", 0x0, + 0x1000, BIT(30), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c_eb, "i2c-eb", "aon-apb", 0x0, + 0x1000, BIT(31), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pmu_eb, "pmu-eb", "aon-apb", 0x4, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(thm_eb, "thm-eb", "aon-apb", 0x4, + 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aux0_eb, "aux0-eb", "aon-apb", 0x4, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aux1_eb, "aux1-eb", "aon-apb", 0x4, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aux2_eb, "aux2-eb", "aon-apb", 0x4, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(probe_eb, "probe-eb", "aon-apb", 0x4, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpu0_avs_eb, "gpu0-avs-eb", "aon-apb", 0x4, + 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpu1_avs_eb, "gpu1-avs-eb", "aon-apb", 0x4, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(apcpu_wdg_eb, "apcpu-wdg-eb", "aon-apb", 0x4, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_tmr1_eb, "ap-tmr1-eb", "aon-apb", 0x4, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_tmr2_eb, "ap-tmr2-eb", "aon-apb", 0x4, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(disp_emc_eb, "disp-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(zip_emc_eb, "zip-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gsp_emc_eb, "gsp-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(osc_aon_eb, "osc-aon-eb", "aon-apb", 0x4, + 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(lvds_trx_eb, "lvds-trx-eb", "aon-apb", 0x4, + 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(lvds_tcxo_eb, "lvds-tcxo-eb", "aon-apb", 0x4, + 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mdar_eb, "mdar-eb", "aon-apb", 0x4, + 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rtc4m0_cal_eb, "rtc4m0-cal-eb", "aon-apb", 0x4, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rct100m_cal_eb, "rct100m-cal-eb", "aon-apb", 0x4, + 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(djtag_eb, "djtag-eb", "aon-apb", 0x4, + 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mbox_eb, "mbox-eb", "aon-apb", 0x4, + 0x1000, BIT(21), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_dma_eb, "aon-dma-eb", "aon-apb", 0x4, + 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dbg_emc_eb, "dbg-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(lvds_pll_div_en, "lvds-pll-div-en", "aon-apb", 0x4, + 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(def_eb, "def-eb", "aon-apb", 0x4, + 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_apb_rsv0, "aon-apb-rsv0", "aon-apb", 0x4, + 0x1000, BIT(26), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(orp_jtag_eb, "orp-jtag-eb", "aon-apb", 0x4, + 0x1000, BIT(27), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(vsp_eb, "vsp-eb", "aon-apb", 0x4, + 0x1000, BIT(28), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(cam_eb, "cam-eb", "aon-apb", 0x4, + 0x1000, BIT(29), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(disp_eb, "disp-eb", "aon-apb", 0x4, + 0x1000, BIT(30), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dbg_axi_if_eb, "dbg-axi-if-eb", "aon-apb", 0x4, + 0x1000, BIT(31), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio0_2x_en, "sdio0-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(sdio1_2x_en, "sdio1-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(sdio2_2x_en, "sdio2-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(emmc_2x_en, "emmc-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(9), 0, 0); + +static struct sprd_clk_common *sc9860_aon_gate[] = { + /* address base is 0x402e0000 */ + &avs_lit_eb.common, + &avs_big_eb.common, + &ap_intc5_eb.common, + &gpio_eb.common, + &pwm0_eb.common, + &pwm1_eb.common, + &pwm2_eb.common, + &pwm3_eb.common, + &kpd_eb.common, + &aon_sys_eb.common, + &ap_sys_eb.common, + &aon_tmr_eb.common, + &ap_tmr0_eb.common, + &efuse_eb.common, + &eic_eb.common, + &pub1_reg_eb.common, + &adi_eb.common, + &ap_intc0_eb.common, + &ap_intc1_eb.common, + &ap_intc2_eb.common, + &ap_intc3_eb.common, + &ap_intc4_eb.common, + &splk_eb.common, + &mspi_eb.common, + &pub0_reg_eb.common, + &pin_eb.common, + &aon_ckg_eb.common, + &gpu_eb.common, + &apcpu_ts0_eb.common, + &apcpu_ts1_eb.common, + &dap_eb.common, + &i2c_eb.common, + &pmu_eb.common, + &thm_eb.common, + &aux0_eb.common, + &aux1_eb.common, + &aux2_eb.common, + &probe_eb.common, + &gpu0_avs_eb.common, + &gpu1_avs_eb.common, + &apcpu_wdg_eb.common, + &ap_tmr1_eb.common, + &ap_tmr2_eb.common, + &disp_emc_eb.common, + &zip_emc_eb.common, + &gsp_emc_eb.common, + &osc_aon_eb.common, + &lvds_trx_eb.common, + &lvds_tcxo_eb.common, + &mdar_eb.common, + &rtc4m0_cal_eb.common, + &rct100m_cal_eb.common, + &djtag_eb.common, + &mbox_eb.common, + &aon_dma_eb.common, + &dbg_emc_eb.common, + &lvds_pll_div_en.common, + &def_eb.common, + &aon_apb_rsv0.common, + &orp_jtag_eb.common, + &vsp_eb.common, + &cam_eb.common, + &disp_eb.common, + &dbg_axi_if_eb.common, + &sdio0_2x_en.common, + &sdio1_2x_en.common, + &sdio2_2x_en.common, + &emmc_2x_en.common, +}; + +static struct clk_hw_onecell_data sc9860_aon_gate_hws = { + .hws = { + [CLK_AVS_LIT_EB] = &avs_lit_eb.common.hw, + [CLK_AVS_BIG_EB] = &avs_big_eb.common.hw, + [CLK_AP_INTC5_EB] = &ap_intc5_eb.common.hw, + [CLK_GPIO_EB] = &gpio_eb.common.hw, + [CLK_PWM0_EB] = &pwm0_eb.common.hw, + [CLK_PWM1_EB] = &pwm1_eb.common.hw, + [CLK_PWM2_EB] = &pwm2_eb.common.hw, + [CLK_PWM3_EB] = &pwm3_eb.common.hw, + [CLK_KPD_EB] = &kpd_eb.common.hw, + [CLK_AON_SYS_EB] = &aon_sys_eb.common.hw, + [CLK_AP_SYS_EB] = &ap_sys_eb.common.hw, + [CLK_AON_TMR_EB] = &aon_tmr_eb.common.hw, + [CLK_AP_TMR0_EB] = &ap_tmr0_eb.common.hw, + [CLK_EFUSE_EB] = &efuse_eb.common.hw, + [CLK_EIC_EB] = &eic_eb.common.hw, + [CLK_PUB1_REG_EB] = &pub1_reg_eb.common.hw, + [CLK_ADI_EB] = &adi_eb.common.hw, + [CLK_AP_INTC0_EB] = &ap_intc0_eb.common.hw, + [CLK_AP_INTC1_EB] = &ap_intc1_eb.common.hw, + [CLK_AP_INTC2_EB] = &ap_intc2_eb.common.hw, + [CLK_AP_INTC3_EB] = &ap_intc3_eb.common.hw, + [CLK_AP_INTC4_EB] = &ap_intc4_eb.common.hw, + [CLK_SPLK_EB] = &splk_eb.common.hw, + [CLK_MSPI_EB] = &mspi_eb.common.hw, + [CLK_PUB0_REG_EB] = &pub0_reg_eb.common.hw, + [CLK_PIN_EB] = &pin_eb.common.hw, + [CLK_AON_CKG_EB] = &aon_ckg_eb.common.hw, + [CLK_GPU_EB] = &gpu_eb.common.hw, + [CLK_APCPU_TS0_EB] = &apcpu_ts0_eb.common.hw, + [CLK_APCPU_TS1_EB] = &apcpu_ts1_eb.common.hw, + [CLK_DAP_EB] = &dap_eb.common.hw, + [CLK_I2C_EB] = &i2c_eb.common.hw, + [CLK_PMU_EB] = &pmu_eb.common.hw, + [CLK_THM_EB] = &thm_eb.common.hw, + [CLK_AUX0_EB] = &aux0_eb.common.hw, + [CLK_AUX1_EB] = &aux1_eb.common.hw, + [CLK_AUX2_EB] = &aux2_eb.common.hw, + [CLK_PROBE_EB] = &probe_eb.common.hw, + [CLK_GPU0_AVS_EB] = &gpu0_avs_eb.common.hw, + [CLK_GPU1_AVS_EB] = &gpu1_avs_eb.common.hw, + [CLK_APCPU_WDG_EB] = &apcpu_wdg_eb.common.hw, + [CLK_AP_TMR1_EB] = &ap_tmr1_eb.common.hw, + [CLK_AP_TMR2_EB] = &ap_tmr2_eb.common.hw, + [CLK_DISP_EMC_EB] = &disp_emc_eb.common.hw, + [CLK_ZIP_EMC_EB] = &zip_emc_eb.common.hw, + [CLK_GSP_EMC_EB] = &gsp_emc_eb.common.hw, + [CLK_OSC_AON_EB] = &osc_aon_eb.common.hw, + [CLK_LVDS_TRX_EB] = &lvds_trx_eb.common.hw, + [CLK_LVDS_TCXO_EB] = &lvds_tcxo_eb.common.hw, + [CLK_MDAR_EB] = &mdar_eb.common.hw, + [CLK_RTC4M0_CAL_EB] = &rtc4m0_cal_eb.common.hw, + [CLK_RCT100M_CAL_EB] = &rct100m_cal_eb.common.hw, + [CLK_DJTAG_EB] = &djtag_eb.common.hw, + [CLK_MBOX_EB] = &mbox_eb.common.hw, + [CLK_AON_DMA_EB] = &aon_dma_eb.common.hw, + [CLK_DBG_EMC_EB] = &dbg_emc_eb.common.hw, + [CLK_LVDS_PLL_DIV_EN] = &lvds_pll_div_en.common.hw, + [CLK_DEF_EB] = &def_eb.common.hw, + [CLK_AON_APB_RSV0] = &aon_apb_rsv0.common.hw, + [CLK_ORP_JTAG_EB] = &orp_jtag_eb.common.hw, + [CLK_VSP_EB] = &vsp_eb.common.hw, + [CLK_CAM_EB] = &cam_eb.common.hw, + [CLK_DISP_EB] = &disp_eb.common.hw, + [CLK_DBG_AXI_IF_EB] = &dbg_axi_if_eb.common.hw, + [CLK_SDIO0_2X_EN] = &sdio0_2x_en.common.hw, + [CLK_SDIO1_2X_EN] = &sdio1_2x_en.common.hw, + [CLK_SDIO2_2X_EN] = &sdio2_2x_en.common.hw, + [CLK_EMMC_2X_EN] = &emmc_2x_en.common.hw, + }, + .num = CLK_AON_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_aon_gate_desc = { + .clk_clks = sc9860_aon_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_aon_gate), + .hw_clks = &sc9860_aon_gate_hws, +}; + +static const u8 mcu_table[] = { 0, 1, 2, 3, 4, 8 }; +static const char * const lit_mcu_parents[] = { "ext-26m", "twpll-512m", + "twpll-768m", "ltepll0", + "twpll", "mpll0" }; +static SPRD_COMP_CLK(lit_mcu, "lit-mcu", lit_mcu_parents, 0x20, + mcu_table, 0, 4, 4, 3, 0); + +static const char * const big_mcu_parents[] = { "ext-26m", "twpll-512m", + "twpll-768m", "ltepll0", + "twpll", "mpll1" }; +static SPRD_COMP_CLK(big_mcu, "big-mcu", big_mcu_parents, 0x24, + mcu_table, 0, 4, 4, 3, 0); + +static struct sprd_clk_common *sc9860_aonsecure_clk[] = { + /* address base is 0x40880000 */ + &lit_mcu.common, + &big_mcu.common, +}; + +static struct clk_hw_onecell_data sc9860_aonsecure_clk_hws = { + .hws = { + [CLK_LIT_MCU] = &lit_mcu.common.hw, + [CLK_BIG_MCU] = &big_mcu.common.hw, + }, + .num = CLK_AONSECURE_NUM, +}; + +static const struct sprd_clk_desc sc9860_aonsecure_clk_desc = { + .clk_clks = sc9860_aonsecure_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_aonsecure_clk), + .hw_clks = &sc9860_aonsecure_clk_hws, +}; + +static SPRD_GATE_CLK(agcp_iis0_eb, "agcp-iis0-eb", "aon-apb", + 0x0, 0x100, BIT(0), 0, 0); +static SPRD_GATE_CLK(agcp_iis1_eb, "agcp-iis1-eb", "aon-apb", + 0x0, 0x100, BIT(1), 0, 0); +static SPRD_GATE_CLK(agcp_iis2_eb, "agcp-iis2-eb", "aon-apb", + 0x0, 0x100, BIT(2), 0, 0); +static SPRD_GATE_CLK(agcp_iis3_eb, "agcp-iis3-eb", "aon-apb", + 0x0, 0x100, BIT(3), 0, 0); +static SPRD_GATE_CLK(agcp_uart_eb, "agcp-uart-eb", "aon-apb", + 0x0, 0x100, BIT(4), 0, 0); +static SPRD_GATE_CLK(agcp_dmacp_eb, "agcp-dmacp-eb", "aon-apb", + 0x0, 0x100, BIT(5), 0, 0); +static SPRD_GATE_CLK(agcp_dmaap_eb, "agcp-dmaap-eb", "aon-apb", + 0x0, 0x100, BIT(6), 0, 0); +static SPRD_GATE_CLK(agcp_arc48k_eb, "agcp-arc48k-eb", "aon-apb", + 0x0, 0x100, BIT(10), 0, 0); +static SPRD_GATE_CLK(agcp_src44p1k_eb, "agcp-src44p1k-eb", "aon-apb", + 0x0, 0x100, BIT(11), 0, 0); +static SPRD_GATE_CLK(agcp_mcdt_eb, "agcp-mcdt-eb", "aon-apb", + 0x0, 0x100, BIT(12), 0, 0); +static SPRD_GATE_CLK(agcp_vbcifd_eb, "agcp-vbcifd-eb", "aon-apb", + 0x0, 0x100, BIT(13), 0, 0); +static SPRD_GATE_CLK(agcp_vbc_eb, "agcp-vbc-eb", "aon-apb", + 0x0, 0x100, BIT(14), 0, 0); +static SPRD_GATE_CLK(agcp_spinlock_eb, "agcp-spinlock-eb", "aon-apb", + 0x0, 0x100, BIT(15), 0, 0); +static SPRD_GATE_CLK(agcp_icu_eb, "agcp-icu-eb", "aon-apb", + 0x0, 0x100, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(agcp_ap_ashb_eb, "agcp-ap-ashb-eb", "aon-apb", + 0x0, 0x100, BIT(17), 0, 0); +static SPRD_GATE_CLK(agcp_cp_ashb_eb, "agcp-cp-ashb-eb", "aon-apb", + 0x0, 0x100, BIT(18), 0, 0); +static SPRD_GATE_CLK(agcp_aud_eb, "agcp-aud-eb", "aon-apb", + 0x0, 0x100, BIT(19), 0, 0); +static SPRD_GATE_CLK(agcp_audif_eb, "agcp-audif-eb", "aon-apb", + 0x0, 0x100, BIT(20), 0, 0); + +static struct sprd_clk_common *sc9860_agcp_gate[] = { + /* address base is 0x415e0000 */ + &agcp_iis0_eb.common, + &agcp_iis1_eb.common, + &agcp_iis2_eb.common, + &agcp_iis3_eb.common, + &agcp_uart_eb.common, + &agcp_dmacp_eb.common, + &agcp_dmaap_eb.common, + &agcp_arc48k_eb.common, + &agcp_src44p1k_eb.common, + &agcp_mcdt_eb.common, + &agcp_vbcifd_eb.common, + &agcp_vbc_eb.common, + &agcp_spinlock_eb.common, + &agcp_icu_eb.common, + &agcp_ap_ashb_eb.common, + &agcp_cp_ashb_eb.common, + &agcp_aud_eb.common, + &agcp_audif_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_agcp_gate_hws = { + .hws = { + [CLK_AGCP_IIS0_EB] = &agcp_iis0_eb.common.hw, + [CLK_AGCP_IIS1_EB] = &agcp_iis1_eb.common.hw, + [CLK_AGCP_IIS2_EB] = &agcp_iis2_eb.common.hw, + [CLK_AGCP_IIS3_EB] = &agcp_iis3_eb.common.hw, + [CLK_AGCP_UART_EB] = &agcp_uart_eb.common.hw, + [CLK_AGCP_DMACP_EB] = &agcp_dmacp_eb.common.hw, + [CLK_AGCP_DMAAP_EB] = &agcp_dmaap_eb.common.hw, + [CLK_AGCP_ARC48K_EB] = &agcp_arc48k_eb.common.hw, + [CLK_AGCP_SRC44P1K_EB] = &agcp_src44p1k_eb.common.hw, + [CLK_AGCP_MCDT_EB] = &agcp_mcdt_eb.common.hw, + [CLK_AGCP_VBCIFD_EB] = &agcp_vbcifd_eb.common.hw, + [CLK_AGCP_VBC_EB] = &agcp_vbc_eb.common.hw, + [CLK_AGCP_SPINLOCK_EB] = &agcp_spinlock_eb.common.hw, + [CLK_AGCP_ICU_EB] = &agcp_icu_eb.common.hw, + [CLK_AGCP_AP_ASHB_EB] = &agcp_ap_ashb_eb.common.hw, + [CLK_AGCP_CP_ASHB_EB] = &agcp_cp_ashb_eb.common.hw, + [CLK_AGCP_AUD_EB] = &agcp_aud_eb.common.hw, + [CLK_AGCP_AUDIF_EB] = &agcp_audif_eb.common.hw, + }, + .num = CLK_AGCP_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_agcp_gate_desc = { + .clk_clks = sc9860_agcp_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_agcp_gate), + .hw_clks = &sc9860_agcp_gate_hws, +}; + +static const char * const gpu_parents[] = { "twpll-512m", + "twpll-768m", + "gpll" }; +static SPRD_COMP_CLK(gpu_clk, "gpu", gpu_parents, 0x20, + 0, 0, 2, 8, 4, 0); + +static struct sprd_clk_common *sc9860_gpu_clk[] = { + /* address base is 0x60200000 */ + &gpu_clk.common, +}; + +static struct clk_hw_onecell_data sc9860_gpu_clk_hws = { + .hws = { + [CLK_GPU] = &gpu_clk.common.hw, + }, + .num = CLK_GPU_NUM, +}; + +static const struct sprd_clk_desc sc9860_gpu_clk_desc = { + .clk_clks = sc9860_gpu_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_gpu_clk), + .hw_clks = &sc9860_gpu_clk_hws, +}; + +static const char * const ahb_parents[] = { "ext-26m", "twpll-96m", + "twpll-128m", "twpll-153m6" }; +static SPRD_MUX_CLK(ahb_vsp, "ahb-vsp", ahb_parents, NULL, + 0x20, 0, 2, SC9860_MUX_FLAG); + +static const char * const vsp_parents[] = { "twpll-76m8", "twpll-128m", + "twpll-256m", "twpll-307m2", + "twpll-384m" }; +static SPRD_COMP_CLK(vsp_clk, "vsp", vsp_parents, 0x24, 0, 0, 3, 8, 2, 0); + +static const char * const dispc_parents[] = { "twpll-76m8", "twpll-128m", + "twpll-256m", "twpll-307m2" }; +static SPRD_COMP_CLK(vsp_enc, "vsp-enc", dispc_parents, 0x28, 0, 0, 2, 8, 2, 0); + +static const char * const vpp_parents[] = { "twpll-96m", "twpll-153m6", + "twpll-192m", "twpll-256m" }; +static SPRD_MUX_CLK(vpp_clk, "vpp", vpp_parents, NULL, 0x2c, + 0, 2, SC9860_MUX_FLAG); +static const char * const vsp_26m_parents[] = { "ext-26m" }; +static SPRD_MUX_CLK(vsp_26m, "vsp-26m", vsp_26m_parents, NULL, 0x30, + 0, 1, SC9860_MUX_FLAG); + +static struct sprd_clk_common *sc9860_vsp_clk[] = { + /* address base is 0x61000000 */ + &ahb_vsp.common, + &vsp_clk.common, + &vsp_enc.common, + &vpp_clk.common, + &vsp_26m.common, +}; + +static struct clk_hw_onecell_data sc9860_vsp_clk_hws = { + .hws = { + [CLK_AHB_VSP] = &ahb_vsp.common.hw, + [CLK_VSP] = &vsp_clk.common.hw, + [CLK_VSP_ENC] = &vsp_enc.common.hw, + [CLK_VPP] = &vpp_clk.common.hw, + [CLK_VSP_26M] = &vsp_26m.common.hw, + }, + .num = CLK_VSP_NUM, +}; + +static const struct sprd_clk_desc sc9860_vsp_clk_desc = { + .clk_clks = sc9860_vsp_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_vsp_clk), + .hw_clks = &sc9860_vsp_clk_hws, +}; + +static SPRD_GATE_CLK(vsp_dec_eb, "vsp-dec-eb", "ahb-vsp", 0x0, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(vsp_ckg_eb, "vsp-ckg-eb", "ahb-vsp", 0x0, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(vsp_mmu_eb, "vsp-mmu-eb", "ahb-vsp", 0x0, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(vsp_enc_eb, "vsp-enc-eb", "ahb-vsp", 0x0, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(vpp_eb, "vpp-eb", "ahb-vsp", 0x0, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(vsp_26m_eb, "vsp-26m-eb", "ahb-vsp", 0x0, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(vsp_axi_gate, "vsp-axi-gate", "ahb-vsp", 0x8, + 0, BIT(0), 0, 0); +static SPRD_GATE_CLK(vsp_enc_gate, "vsp-enc-gate", "ahb-vsp", 0x8, + 0, BIT(1), 0, 0); +static SPRD_GATE_CLK(vpp_axi_gate, "vpp-axi-gate", "ahb-vsp", 0x8, + 0, BIT(2), 0, 0); +static SPRD_GATE_CLK(vsp_bm_gate, "vsp-bm-gate", "ahb-vsp", 0x8, + 0, BIT(8), 0, 0); +static SPRD_GATE_CLK(vsp_enc_bm_gate, "vsp-enc-bm-gate", "ahb-vsp", 0x8, + 0, BIT(9), 0, 0); +static SPRD_GATE_CLK(vpp_bm_gate, "vpp-bm-gate", "ahb-vsp", 0x8, + 0, BIT(10), 0, 0); + +static struct sprd_clk_common *sc9860_vsp_gate[] = { + /* address base is 0x61100000 */ + &vsp_dec_eb.common, + &vsp_ckg_eb.common, + &vsp_mmu_eb.common, + &vsp_enc_eb.common, + &vpp_eb.common, + &vsp_26m_eb.common, + &vsp_axi_gate.common, + &vsp_enc_gate.common, + &vpp_axi_gate.common, + &vsp_bm_gate.common, + &vsp_enc_bm_gate.common, + &vpp_bm_gate.common, +}; + +static struct clk_hw_onecell_data sc9860_vsp_gate_hws = { + .hws = { + [CLK_VSP_DEC_EB] = &vsp_dec_eb.common.hw, + [CLK_VSP_CKG_EB] = &vsp_ckg_eb.common.hw, + [CLK_VSP_MMU_EB] = &vsp_mmu_eb.common.hw, + [CLK_VSP_ENC_EB] = &vsp_enc_eb.common.hw, + [CLK_VPP_EB] = &vpp_eb.common.hw, + [CLK_VSP_26M_EB] = &vsp_26m_eb.common.hw, + [CLK_VSP_AXI_GATE] = &vsp_axi_gate.common.hw, + [CLK_VSP_ENC_GATE] = &vsp_enc_gate.common.hw, + [CLK_VPP_AXI_GATE] = &vpp_axi_gate.common.hw, + [CLK_VSP_BM_GATE] = &vsp_bm_gate.common.hw, + [CLK_VSP_ENC_BM_GATE] = &vsp_enc_bm_gate.common.hw, + [CLK_VPP_BM_GATE] = &vpp_bm_gate.common.hw, + }, + .num = CLK_VSP_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_vsp_gate_desc = { + .clk_clks = sc9860_vsp_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_vsp_gate), + .hw_clks = &sc9860_vsp_gate_hws, +}; + +static SPRD_MUX_CLK(ahb_cam, "ahb-cam", ahb_parents, NULL, + 0x20, 0, 2, SC9860_MUX_FLAG); +static const char * const sensor_parents[] = { "ext-26m", "twpll-48m", + "twpll-76m8", "twpll-96m" }; +static SPRD_COMP_CLK(sensor0_clk, "sensor0", sensor_parents, 0x24, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(sensor1_clk, "sensor1", sensor_parents, 0x28, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(sensor2_clk, "sensor2", sensor_parents, 0x2c, + 0, 0, 2, 8, 3, 0); +static SPRD_GATE_CLK(mipi_csi0_eb, "mipi-csi0-eb", "ahb-cam", 0x4c, + 0, BIT(16), 0, 0); +static SPRD_GATE_CLK(mipi_csi1_eb, "mipi-csi1-eb", "ahb-cam", 0x50, + 0, BIT(16), 0, 0); + +static struct sprd_clk_common *sc9860_cam_clk[] = { + /* address base is 0x62000000 */ + &ahb_cam.common, + &sensor0_clk.common, + &sensor1_clk.common, + &sensor2_clk.common, + &mipi_csi0_eb.common, + &mipi_csi1_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_cam_clk_hws = { + .hws = { + [CLK_AHB_CAM] = &ahb_cam.common.hw, + [CLK_SENSOR0] = &sensor0_clk.common.hw, + [CLK_SENSOR1] = &sensor1_clk.common.hw, + [CLK_SENSOR2] = &sensor2_clk.common.hw, + [CLK_MIPI_CSI0_EB] = &mipi_csi0_eb.common.hw, + [CLK_MIPI_CSI1_EB] = &mipi_csi1_eb.common.hw, + }, + .num = CLK_CAM_NUM, +}; + +static const struct sprd_clk_desc sc9860_cam_clk_desc = { + .clk_clks = sc9860_cam_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_cam_clk), + .hw_clks = &sc9860_cam_clk_hws, +}; + +static SPRD_GATE_CLK(dcam0_eb, "dcam0-eb", "ahb-cam", 0x0, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(dcam1_eb, "dcam1-eb", "ahb-cam", 0x0, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(isp0_eb, "isp0-eb", "ahb-cam", 0x0, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(csi0_eb, "csi0-eb", "ahb-cam", 0x0, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(csi1_eb, "csi1-eb", "ahb-cam", 0x0, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(jpg0_eb, "jpg0-eb", "ahb-cam", 0x0, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(jpg1_eb, "jpg1-eb", "ahb-cam", 0x0, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(cam_ckg_eb, "cam-ckg-eb", "ahb-cam", 0x0, + 0x1000, BIT(7), 0, 0); +static SPRD_GATE_CLK(cam_mmu_eb, "cam-mmu-eb", "ahb-cam", 0x0, + 0x1000, BIT(8), 0, 0); +static SPRD_GATE_CLK(isp1_eb, "isp1-eb", "ahb-cam", 0x0, + 0x1000, BIT(9), 0, 0); +static SPRD_GATE_CLK(cpp_eb, "cpp-eb", "ahb-cam", 0x0, + 0x1000, BIT(10), 0, 0); +static SPRD_GATE_CLK(mmu_pf_eb, "mmu-pf-eb", "ahb-cam", 0x0, + 0x1000, BIT(11), 0, 0); +static SPRD_GATE_CLK(isp2_eb, "isp2-eb", "ahb-cam", 0x0, + 0x1000, BIT(12), 0, 0); +static SPRD_GATE_CLK(dcam2isp_if_eb, "dcam2isp-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(13), 0, 0); +static SPRD_GATE_CLK(isp2dcam_if_eb, "isp2dcam-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(14), 0, 0); +static SPRD_GATE_CLK(isp_lclk_eb, "isp-lclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(15), 0, 0); +static SPRD_GATE_CLK(isp_iclk_eb, "isp-iclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(16), 0, 0); +static SPRD_GATE_CLK(isp_mclk_eb, "isp-mclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(17), 0, 0); +static SPRD_GATE_CLK(isp_pclk_eb, "isp-pclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(18), 0, 0); +static SPRD_GATE_CLK(isp_isp2dcam_eb, "isp-isp2dcam-eb", "ahb-cam", 0x0, + 0x1000, BIT(19), 0, 0); +static SPRD_GATE_CLK(dcam0_if_eb, "dcam0-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(20), 0, 0); +static SPRD_GATE_CLK(clk26m_if_eb, "clk26m-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(21), 0, 0); +static SPRD_GATE_CLK(cphy0_gate, "cphy0-gate", "ahb-cam", 0x8, + 0, BIT(0), 0, 0); +static SPRD_GATE_CLK(mipi_csi0_gate, "mipi-csi0-gate", "ahb-cam", 0x8, + 0, BIT(1), 0, 0); +static SPRD_GATE_CLK(cphy1_gate, "cphy1-gate", "ahb-cam", 0x8, + 0, BIT(2), 0, 0); +static SPRD_GATE_CLK(mipi_csi1, "mipi-csi1", "ahb-cam", 0x8, + 0, BIT(3), 0, 0); +static SPRD_GATE_CLK(dcam0_axi_gate, "dcam0-axi-gate", "ahb-cam", 0x8, + 0, BIT(4), 0, 0); +static SPRD_GATE_CLK(dcam1_axi_gate, "dcam1-axi-gate", "ahb-cam", 0x8, + 0, BIT(5), 0, 0); +static SPRD_GATE_CLK(sensor0_gate, "sensor0-gate", "ahb-cam", 0x8, + 0, BIT(6), 0, 0); +static SPRD_GATE_CLK(sensor1_gate, "sensor1-gate", "ahb-cam", 0x8, + 0, BIT(7), 0, 0); +static SPRD_GATE_CLK(jpg0_axi_gate, "jpg0-axi-gate", "ahb-cam", 0x8, + 0, BIT(8), 0, 0); +static SPRD_GATE_CLK(gpg1_axi_gate, "gpg1-axi-gate", "ahb-cam", 0x8, + 0, BIT(9), 0, 0); +static SPRD_GATE_CLK(isp0_axi_gate, "isp0-axi-gate", "ahb-cam", 0x8, + 0, BIT(10), 0, 0); +static SPRD_GATE_CLK(isp1_axi_gate, "isp1-axi-gate", "ahb-cam", 0x8, + 0, BIT(11), 0, 0); +static SPRD_GATE_CLK(isp2_axi_gate, "isp2-axi-gate", "ahb-cam", 0x8, + 0, BIT(12), 0, 0); +static SPRD_GATE_CLK(cpp_axi_gate, "cpp-axi-gate", "ahb-cam", 0x8, + 0, BIT(13), 0, 0); +static SPRD_GATE_CLK(d0_if_axi_gate, "d0-if-axi-gate", "ahb-cam", 0x8, + 0, BIT(14), 0, 0); +static SPRD_GATE_CLK(d2i_if_axi_gate, "d2i-if-axi-gate", "ahb-cam", 0x8, + 0, BIT(15), 0, 0); +static SPRD_GATE_CLK(i2d_if_axi_gate, "i2d-if-axi-gate", "ahb-cam", 0x8, + 0, BIT(16), 0, 0); +static SPRD_GATE_CLK(spare_axi_gate, "spare-axi-gate", "ahb-cam", 0x8, + 0, BIT(17), 0, 0); +static SPRD_GATE_CLK(sensor2_gate, "sensor2-gate", "ahb-cam", 0x8, + 0, BIT(18), 0, 0); +static SPRD_GATE_CLK(d0if_in_d_en, "d0if-in-d-en", "ahb-cam", 0x28, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(d1if_in_d_en, "d1if-in-d-en", "ahb-cam", 0x28, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(d0if_in_d2i_en, "d0if-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(d1if_in_d2i_en, "d1if-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(ia_in_d2i_en, "ia-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(ib_in_d2i_en, "ib-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(ic_in_d2i_en, "ic-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(ia_in_i_en, "ia-in-i-en", "ahb-cam", 0x28, + 0x1000, BIT(7), 0, 0); +static SPRD_GATE_CLK(ib_in_i_en, "ib-in-i-en", "ahb-cam", 0x28, + 0x1000, BIT(8), 0, 0); +static SPRD_GATE_CLK(ic_in_i_en, "ic-in-i-en", "ahb-cam", 0x28, + 0x1000, BIT(9), 0, 0); + +static struct sprd_clk_common *sc9860_cam_gate[] = { + /* address base is 0x62100000 */ + &dcam0_eb.common, + &dcam1_eb.common, + &isp0_eb.common, + &csi0_eb.common, + &csi1_eb.common, + &jpg0_eb.common, + &jpg1_eb.common, + &cam_ckg_eb.common, + &cam_mmu_eb.common, + &isp1_eb.common, + &cpp_eb.common, + &mmu_pf_eb.common, + &isp2_eb.common, + &dcam2isp_if_eb.common, + &isp2dcam_if_eb.common, + &isp_lclk_eb.common, + &isp_iclk_eb.common, + &isp_mclk_eb.common, + &isp_pclk_eb.common, + &isp_isp2dcam_eb.common, + &dcam0_if_eb.common, + &clk26m_if_eb.common, + &cphy0_gate.common, + &mipi_csi0_gate.common, + &cphy1_gate.common, + &mipi_csi1.common, + &dcam0_axi_gate.common, + &dcam1_axi_gate.common, + &sensor0_gate.common, + &sensor1_gate.common, + &jpg0_axi_gate.common, + &gpg1_axi_gate.common, + &isp0_axi_gate.common, + &isp1_axi_gate.common, + &isp2_axi_gate.common, + &cpp_axi_gate.common, + &d0_if_axi_gate.common, + &d2i_if_axi_gate.common, + &i2d_if_axi_gate.common, + &spare_axi_gate.common, + &sensor2_gate.common, + &d0if_in_d_en.common, + &d1if_in_d_en.common, + &d0if_in_d2i_en.common, + &d1if_in_d2i_en.common, + &ia_in_d2i_en.common, + &ib_in_d2i_en.common, + &ic_in_d2i_en.common, + &ia_in_i_en.common, + &ib_in_i_en.common, + &ic_in_i_en.common, +}; + +static struct clk_hw_onecell_data sc9860_cam_gate_hws = { + .hws = { + [CLK_DCAM0_EB] = &dcam0_eb.common.hw, + [CLK_DCAM1_EB] = &dcam1_eb.common.hw, + [CLK_ISP0_EB] = &isp0_eb.common.hw, + [CLK_CSI0_EB] = &csi0_eb.common.hw, + [CLK_CSI1_EB] = &csi1_eb.common.hw, + [CLK_JPG0_EB] = &jpg0_eb.common.hw, + [CLK_JPG1_EB] = &jpg1_eb.common.hw, + [CLK_CAM_CKG_EB] = &cam_ckg_eb.common.hw, + [CLK_CAM_MMU_EB] = &cam_mmu_eb.common.hw, + [CLK_ISP1_EB] = &isp1_eb.common.hw, + [CLK_CPP_EB] = &cpp_eb.common.hw, + [CLK_MMU_PF_EB] = &mmu_pf_eb.common.hw, + [CLK_ISP2_EB] = &isp2_eb.common.hw, + [CLK_DCAM2ISP_IF_EB] = &dcam2isp_if_eb.common.hw, + [CLK_ISP2DCAM_IF_EB] = &isp2dcam_if_eb.common.hw, + [CLK_ISP_LCLK_EB] = &isp_lclk_eb.common.hw, + [CLK_ISP_ICLK_EB] = &isp_iclk_eb.common.hw, + [CLK_ISP_MCLK_EB] = &isp_mclk_eb.common.hw, + [CLK_ISP_PCLK_EB] = &isp_pclk_eb.common.hw, + [CLK_ISP_ISP2DCAM_EB] = &isp_isp2dcam_eb.common.hw, + [CLK_DCAM0_IF_EB] = &dcam0_if_eb.common.hw, + [CLK_CLK26M_IF_EB] = &clk26m_if_eb.common.hw, + [CLK_CPHY0_GATE] = &cphy0_gate.common.hw, + [CLK_MIPI_CSI0_GATE] = &mipi_csi0_gate.common.hw, + [CLK_CPHY1_GATE] = &cphy1_gate.common.hw, + [CLK_MIPI_CSI1] = &mipi_csi1.common.hw, + [CLK_DCAM0_AXI_GATE] = &dcam0_axi_gate.common.hw, + [CLK_DCAM1_AXI_GATE] = &dcam1_axi_gate.common.hw, + [CLK_SENSOR0_GATE] = &sensor0_gate.common.hw, + [CLK_SENSOR1_GATE] = &sensor1_gate.common.hw, + [CLK_JPG0_AXI_GATE] = &jpg0_axi_gate.common.hw, + [CLK_GPG1_AXI_GATE] = &gpg1_axi_gate.common.hw, + [CLK_ISP0_AXI_GATE] = &isp0_axi_gate.common.hw, + [CLK_ISP1_AXI_GATE] = &isp1_axi_gate.common.hw, + [CLK_ISP2_AXI_GATE] = &isp2_axi_gate.common.hw, + [CLK_CPP_AXI_GATE] = &cpp_axi_gate.common.hw, + [CLK_D0_IF_AXI_GATE] = &d0_if_axi_gate.common.hw, + [CLK_D2I_IF_AXI_GATE] = &d2i_if_axi_gate.common.hw, + [CLK_I2D_IF_AXI_GATE] = &i2d_if_axi_gate.common.hw, + [CLK_SPARE_AXI_GATE] = &spare_axi_gate.common.hw, + [CLK_SENSOR2_GATE] = &sensor2_gate.common.hw, + [CLK_D0IF_IN_D_EN] = &d0if_in_d_en.common.hw, + [CLK_D1IF_IN_D_EN] = &d1if_in_d_en.common.hw, + [CLK_D0IF_IN_D2I_EN] = &d0if_in_d2i_en.common.hw, + [CLK_D1IF_IN_D2I_EN] = &d1if_in_d2i_en.common.hw, + [CLK_IA_IN_D2I_EN] = &ia_in_d2i_en.common.hw, + [CLK_IB_IN_D2I_EN] = &ib_in_d2i_en.common.hw, + [CLK_IC_IN_D2I_EN] = &ic_in_d2i_en.common.hw, + [CLK_IA_IN_I_EN] = &ia_in_i_en.common.hw, + [CLK_IB_IN_I_EN] = &ib_in_i_en.common.hw, + [CLK_IC_IN_I_EN] = &ic_in_i_en.common.hw, + }, + .num = CLK_CAM_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_cam_gate_desc = { + .clk_clks = sc9860_cam_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_cam_gate), + .hw_clks = &sc9860_cam_gate_hws, +}; + +static SPRD_MUX_CLK(ahb_disp, "ahb-disp", ahb_parents, NULL, 0x20, + 0, 2, SC9860_MUX_FLAG); +static SPRD_COMP_CLK(dispc0_dpi, "dispc0-dpi", dispc_parents, 0x34, + 0, 0, 2, 8, 2, 0); +static SPRD_COMP_CLK(dispc1_dpi, "dispc1-dpi", dispc_parents, 0x40, + 0, 0, 2, 8, 2, 0); + +static struct sprd_clk_common *sc9860_disp_clk[] = { + /* address base is 0x63000000 */ + &ahb_disp.common, + &dispc0_dpi.common, + &dispc1_dpi.common, +}; + +static struct clk_hw_onecell_data sc9860_disp_clk_hws = { + .hws = { + [CLK_AHB_DISP] = &ahb_disp.common.hw, + [CLK_DISPC0_DPI] = &dispc0_dpi.common.hw, + [CLK_DISPC1_DPI] = &dispc1_dpi.common.hw, + }, + .num = CLK_DISP_NUM, +}; + +static const struct sprd_clk_desc sc9860_disp_clk_desc = { + .clk_clks = sc9860_disp_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_disp_clk), + .hw_clks = &sc9860_disp_clk_hws, +}; + +static SPRD_GATE_CLK(dispc0_eb, "dispc0-eb", "ahb-disp", 0x0, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(dispc1_eb, "dispc1-eb", "ahb-disp", 0x0, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(dispc_mmu_eb, "dispc-mmu-eb", "ahb-disp", 0x0, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(gsp0_eb, "gsp0-eb", "ahb-disp", 0x0, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(gsp1_eb, "gsp1-eb", "ahb-disp", 0x0, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(gsp0_mmu_eb, "gsp0-mmu-eb", "ahb-disp", 0x0, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(gsp1_mmu_eb, "gsp1-mmu-eb", "ahb-disp", 0x0, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(dsi0_eb, "dsi0-eb", "ahb-disp", 0x0, + 0x1000, BIT(7), 0, 0); +static SPRD_GATE_CLK(dsi1_eb, "dsi1-eb", "ahb-disp", 0x0, + 0x1000, BIT(8), 0, 0); +static SPRD_GATE_CLK(disp_ckg_eb, "disp-ckg-eb", "ahb-disp", 0x0, + 0x1000, BIT(9), 0, 0); +static SPRD_GATE_CLK(disp_gpu_eb, "disp-gpu-eb", "ahb-disp", 0x0, + 0x1000, BIT(10), 0, 0); +static SPRD_GATE_CLK(gpu_mtx_eb, "gpu-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(13), 0, 0); +static SPRD_GATE_CLK(gsp_mtx_eb, "gsp-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(14), 0, 0); +static SPRD_GATE_CLK(tmc_mtx_eb, "tmc-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(15), 0, 0); +static SPRD_GATE_CLK(dispc_mtx_eb, "dispc-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(16), 0, 0); +static SPRD_GATE_CLK(dphy0_gate, "dphy0-gate", "ahb-disp", 0x8, + 0, BIT(0), 0, 0); +static SPRD_GATE_CLK(dphy1_gate, "dphy1-gate", "ahb-disp", 0x8, + 0, BIT(1), 0, 0); +static SPRD_GATE_CLK(gsp0_a_gate, "gsp0-a-gate", "ahb-disp", 0x8, + 0, BIT(2), 0, 0); +static SPRD_GATE_CLK(gsp1_a_gate, "gsp1-a-gate", "ahb-disp", 0x8, + 0, BIT(3), 0, 0); +static SPRD_GATE_CLK(gsp0_f_gate, "gsp0-f-gate", "ahb-disp", 0x8, + 0, BIT(4), 0, 0); +static SPRD_GATE_CLK(gsp1_f_gate, "gsp1-f-gate", "ahb-disp", 0x8, + 0, BIT(5), 0, 0); +static SPRD_GATE_CLK(d_mtx_f_gate, "d-mtx-f-gate", "ahb-disp", 0x8, + 0, BIT(6), 0, 0); +static SPRD_GATE_CLK(d_mtx_a_gate, "d-mtx-a-gate", "ahb-disp", 0x8, + 0, BIT(7), 0, 0); +static SPRD_GATE_CLK(d_noc_f_gate, "d-noc-f-gate", "ahb-disp", 0x8, + 0, BIT(8), 0, 0); +static SPRD_GATE_CLK(d_noc_a_gate, "d-noc-a-gate", "ahb-disp", 0x8, + 0, BIT(9), 0, 0); +static SPRD_GATE_CLK(gsp_mtx_f_gate, "gsp-mtx-f-gate", "ahb-disp", 0x8, + 0, BIT(10), 0, 0); +static SPRD_GATE_CLK(gsp_mtx_a_gate, "gsp-mtx-a-gate", "ahb-disp", 0x8, + 0, BIT(11), 0, 0); +static SPRD_GATE_CLK(gsp_noc_f_gate, "gsp-noc-f-gate", "ahb-disp", 0x8, + 0, BIT(12), 0, 0); +static SPRD_GATE_CLK(gsp_noc_a_gate, "gsp-noc-a-gate", "ahb-disp", 0x8, + 0, BIT(13), 0, 0); +static SPRD_GATE_CLK(dispm0idle_gate, "dispm0idle-gate", "ahb-disp", 0x8, + 0, BIT(14), 0, 0); +static SPRD_GATE_CLK(gspm0idle_gate, "gspm0idle-gate", "ahb-disp", 0x8, + 0, BIT(15), 0, 0); + +static struct sprd_clk_common *sc9860_disp_gate[] = { + /* address base is 0x63100000 */ + &dispc0_eb.common, + &dispc1_eb.common, + &dispc_mmu_eb.common, + &gsp0_eb.common, + &gsp1_eb.common, + &gsp0_mmu_eb.common, + &gsp1_mmu_eb.common, + &dsi0_eb.common, + &dsi1_eb.common, + &disp_ckg_eb.common, + &disp_gpu_eb.common, + &gpu_mtx_eb.common, + &gsp_mtx_eb.common, + &tmc_mtx_eb.common, + &dispc_mtx_eb.common, + &dphy0_gate.common, + &dphy1_gate.common, + &gsp0_a_gate.common, + &gsp1_a_gate.common, + &gsp0_f_gate.common, + &gsp1_f_gate.common, + &d_mtx_f_gate.common, + &d_mtx_a_gate.common, + &d_noc_f_gate.common, + &d_noc_a_gate.common, + &gsp_mtx_f_gate.common, + &gsp_mtx_a_gate.common, + &gsp_noc_f_gate.common, + &gsp_noc_a_gate.common, + &dispm0idle_gate.common, + &gspm0idle_gate.common, +}; + +static struct clk_hw_onecell_data sc9860_disp_gate_hws = { + .hws = { + [CLK_DISPC0_EB] = &dispc0_eb.common.hw, + [CLK_DISPC1_EB] = &dispc1_eb.common.hw, + [CLK_DISPC_MMU_EB] = &dispc_mmu_eb.common.hw, + [CLK_GSP0_EB] = &gsp0_eb.common.hw, + [CLK_GSP1_EB] = &gsp1_eb.common.hw, + [CLK_GSP0_MMU_EB] = &gsp0_mmu_eb.common.hw, + [CLK_GSP1_MMU_EB] = &gsp1_mmu_eb.common.hw, + [CLK_DSI0_EB] = &dsi0_eb.common.hw, + [CLK_DSI1_EB] = &dsi1_eb.common.hw, + [CLK_DISP_CKG_EB] = &disp_ckg_eb.common.hw, + [CLK_DISP_GPU_EB] = &disp_gpu_eb.common.hw, + [CLK_GPU_MTX_EB] = &gpu_mtx_eb.common.hw, + [CLK_GSP_MTX_EB] = &gsp_mtx_eb.common.hw, + [CLK_TMC_MTX_EB] = &tmc_mtx_eb.common.hw, + [CLK_DISPC_MTX_EB] = &dispc_mtx_eb.common.hw, + [CLK_DPHY0_GATE] = &dphy0_gate.common.hw, + [CLK_DPHY1_GATE] = &dphy1_gate.common.hw, + [CLK_GSP0_A_GATE] = &gsp0_a_gate.common.hw, + [CLK_GSP1_A_GATE] = &gsp1_a_gate.common.hw, + [CLK_GSP0_F_GATE] = &gsp0_f_gate.common.hw, + [CLK_GSP1_F_GATE] = &gsp1_f_gate.common.hw, + [CLK_D_MTX_F_GATE] = &d_mtx_f_gate.common.hw, + [CLK_D_MTX_A_GATE] = &d_mtx_a_gate.common.hw, + [CLK_D_NOC_F_GATE] = &d_noc_f_gate.common.hw, + [CLK_D_NOC_A_GATE] = &d_noc_a_gate.common.hw, + [CLK_GSP_MTX_F_GATE] = &gsp_mtx_f_gate.common.hw, + [CLK_GSP_MTX_A_GATE] = &gsp_mtx_a_gate.common.hw, + [CLK_GSP_NOC_F_GATE] = &gsp_noc_f_gate.common.hw, + [CLK_GSP_NOC_A_GATE] = &gsp_noc_a_gate.common.hw, + [CLK_DISPM0IDLE_GATE] = &dispm0idle_gate.common.hw, + [CLK_GSPM0IDLE_GATE] = &gspm0idle_gate.common.hw, + }, + .num = CLK_DISP_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_disp_gate_desc = { + .clk_clks = sc9860_disp_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_disp_gate), + .hw_clks = &sc9860_disp_gate_hws, +}; + +static SPRD_GATE_CLK(sim0_eb, "sim0-eb", "ap-apb", 0x0, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis0_eb, "iis0-eb", "ap-apb", 0x0, + 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis1_eb, "iis1-eb", "ap-apb", 0x0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis2_eb, "iis2-eb", "ap-apb", 0x0, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis3_eb, "iis3-eb", "ap-apb", 0x0, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi0_eb, "spi0-eb", "ap-apb", 0x0, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi1_eb, "spi1-eb", "ap-apb", 0x0, + 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi2_eb, "spi2-eb", "ap-apb", 0x0, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c0_eb, "i2c0-eb", "ap-apb", 0x0, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c1_eb, "i2c1-eb", "ap-apb", 0x0, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c2_eb, "i2c2-eb", "ap-apb", 0x0, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c3_eb, "i2c3-eb", "ap-apb", 0x0, + 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c4_eb, "i2c4-eb", "ap-apb", 0x0, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c5_eb, "i2c5-eb", "ap-apb", 0x0, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart0_eb, "uart0-eb", "ap-apb", 0x0, + 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart1_eb, "uart1-eb", "ap-apb", 0x0, + 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart2_eb, "uart2-eb", "ap-apb", 0x0, + 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart3_eb, "uart3-eb", "ap-apb", 0x0, + 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart4_eb, "uart4-eb", "ap-apb", 0x0, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_ckg_eb, "ap-ckg-eb", "ap-apb", 0x0, + 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi3_eb, "spi3-eb", "ap-apb", 0x0, + 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0); + +static struct sprd_clk_common *sc9860_apapb_gate[] = { + /* address base is 0x70b00000 */ + &sim0_eb.common, + &iis0_eb.common, + &iis1_eb.common, + &iis2_eb.common, + &iis3_eb.common, + &spi0_eb.common, + &spi1_eb.common, + &spi2_eb.common, + &i2c0_eb.common, + &i2c1_eb.common, + &i2c2_eb.common, + &i2c3_eb.common, + &i2c4_eb.common, + &i2c5_eb.common, + &uart0_eb.common, + &uart1_eb.common, + &uart2_eb.common, + &uart3_eb.common, + &uart4_eb.common, + &ap_ckg_eb.common, + &spi3_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_apapb_gate_hws = { + .hws = { + [CLK_SIM0_EB] = &sim0_eb.common.hw, + [CLK_IIS0_EB] = &iis0_eb.common.hw, + [CLK_IIS1_EB] = &iis1_eb.common.hw, + [CLK_IIS2_EB] = &iis2_eb.common.hw, + [CLK_IIS3_EB] = &iis3_eb.common.hw, + [CLK_SPI0_EB] = &spi0_eb.common.hw, + [CLK_SPI1_EB] = &spi1_eb.common.hw, + [CLK_SPI2_EB] = &spi2_eb.common.hw, + [CLK_I2C0_EB] = &i2c0_eb.common.hw, + [CLK_I2C1_EB] = &i2c1_eb.common.hw, + [CLK_I2C2_EB] = &i2c2_eb.common.hw, + [CLK_I2C3_EB] = &i2c3_eb.common.hw, + [CLK_I2C4_EB] = &i2c4_eb.common.hw, + [CLK_I2C5_EB] = &i2c5_eb.common.hw, + [CLK_UART0_EB] = &uart0_eb.common.hw, + [CLK_UART1_EB] = &uart1_eb.common.hw, + [CLK_UART2_EB] = &uart2_eb.common.hw, + [CLK_UART3_EB] = &uart3_eb.common.hw, + [CLK_UART4_EB] = &uart4_eb.common.hw, + [CLK_AP_CKG_EB] = &ap_ckg_eb.common.hw, + [CLK_SPI3_EB] = &spi3_eb.common.hw, + }, + .num = CLK_APAPB_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_apapb_gate_desc = { + .clk_clks = sc9860_apapb_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_apapb_gate), + .hw_clks = &sc9860_apapb_gate_hws, +}; + +static const struct of_device_id sprd_sc9860_clk_ids[] = { + { .compatible = "sprd,sc9860-pmu-gate", /* 0x402b */ + .data = &sc9860_pmu_gate_desc }, + { .compatible = "sprd,sc9860-pll", /* 0x4040 */ + .data = &sc9860_pll_desc }, + { .compatible = "sprd,sc9860-ap-clk", /* 0x2000 */ + .data = &sc9860_ap_clk_desc }, + { .compatible = "sprd,sc9860-aon-prediv", /* 0x402d */ + .data = &sc9860_aon_prediv_desc }, + { .compatible = "sprd,sc9860-apahb-gate", /* 0x2021 */ + .data = &sc9860_apahb_gate_desc }, + { .compatible = "sprd,sc9860-aon-gate", /* 0x402e */ + .data = &sc9860_aon_gate_desc }, + { .compatible = "sprd,sc9860-aonsecure-clk", /* 0x4088 */ + .data = &sc9860_aonsecure_clk_desc }, + { .compatible = "sprd,sc9860-agcp-gate", /* 0x415e */ + .data = &sc9860_agcp_gate_desc }, + { .compatible = "sprd,sc9860-gpu-clk", /* 0x6020 */ + .data = &sc9860_gpu_clk_desc }, + { .compatible = "sprd,sc9860-vsp-clk", /* 0x6100 */ + .data = &sc9860_vsp_clk_desc }, + { .compatible = "sprd,sc9860-vsp-gate", /* 0x6110 */ + .data = &sc9860_vsp_gate_desc }, + { .compatible = "sprd,sc9860-cam-clk", /* 0x6200 */ + .data = &sc9860_cam_clk_desc }, + { .compatible = "sprd,sc9860-cam-gate", /* 0x6210 */ + .data = &sc9860_cam_gate_desc }, + { .compatible = "sprd,sc9860-disp-clk", /* 0x6300 */ + .data = &sc9860_disp_clk_desc }, + { .compatible = "sprd,sc9860-disp-gate", /* 0x6310 */ + .data = &sc9860_disp_gate_desc }, + { .compatible = "sprd,sc9860-apapb-gate", /* 0x70b0 */ + .data = &sc9860_apapb_gate_desc }, + { } +}; +MODULE_DEVICE_TABLE(of, sprd_sc9860_clk_ids); + +static int sc9860_clk_probe(struct platform_device *pdev) +{ + int ret = 0; + const struct of_device_id *match; + const struct sprd_clk_desc *desc; + + match = of_match_node(sprd_sc9860_clk_ids, pdev->dev.of_node); + if (!match) { + pr_err("%s: of_match_node() failed.", __func__); + return -ENODEV; + } + + desc = match->data; + sprd_clk_regmap_init(pdev, desc); + + ret = sprd_clk_probe(pdev->dev.of_node, desc->hw_clks); + if (ret == 0) + pr_info("%s: %u clocks have been registered now.\n", + match->compatible, desc->hw_clks->num); + + return ret; +} + +static struct platform_driver sc9860_clk_driver = { + .probe = sc9860_clk_probe, + .driver = { + .name = "sc9860-clk", + .of_match_table = sprd_sc9860_clk_ids, + }, +}; +module_platform_driver(sc9860_clk_driver); + +MODULE_DESCRIPTION("Spreadtrum SC9860 Clock Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sc9860-clk"); diff --git a/include/dt-bindings/clock/sprd,sc9860-clk.h b/include/dt-bindings/clock/sprd,sc9860-clk.h new file mode 100644 index 0000000..48e6052 --- /dev/null +++ b/include/dt-bindings/clock/sprd,sc9860-clk.h @@ -0,0 +1,408 @@ +/* + * Spreadtrum SC9860 platform clocks + * + * Copyright (C) 2017, Spreadtrum Communications Inc. + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +#ifndef _DT_BINDINGS_CLK_SC9860_H_ +#define _DT_BINDINGS_CLK_SC9860_H_ + +#define CLK_EXT_RCO_100M 0 +#define CLK_EXT_32K 1 +#define CLK_FAC_4M 2 +#define CLK_FAC_2M 3 +#define CLK_FAC_1M 4 +#define CLK_FAC_250K 5 +#define CLK_FAC_RPLL0_26M 6 +#define CLK_FAC_RPLL1_26M 7 +#define CLK_FAC_RCO25M 8 +#define CLK_FAC_RCO4M 9 +#define CLK_FAC_RCO2M 10 +#define CLK_FAC_3K2 11 +#define CLK_FAC_1K 12 +#define CLK_MPLL0_GATE 13 +#define CLK_MPLL1_GATE 14 +#define CLK_DPLL0_GATE 15 +#define CLK_DPLL1_GATE 16 +#define CLK_LTEPLL0_GATE 17 +#define CLK_TWPLL_GATE 18 +#define CLK_LTEPLL1_GATE 19 +#define CLK_RPLL0_GATE 20 +#define CLK_RPLL1_GATE 21 +#define CLK_CPPLL_GATE 22 +#define CLK_GPLL_GATE 23 +#define CLK_PMU_GATE_NUM (CLK_GPLL_GATE + 1) + +#define CLK_MPLL0 0 +#define CLK_MPLL1 1 +#define CLK_DPLL0 2 +#define CLK_DPLL1 3 +#define CLK_RPLL0 4 +#define CLK_RPLL1 5 +#define CLK_TWPLL 6 +#define CLK_LTEPLL0 7 +#define CLK_LTEPLL1 8 +#define CLK_GPLL 9 +#define CLK_CPPLL 10 +#define CLK_GPLL_42M5 11 +#define CLK_TWPLL_768M 12 +#define CLK_TWPLL_384M 13 +#define CLK_TWPLL_192M 14 +#define CLK_TWPLL_96M 15 +#define CLK_TWPLL_48M 16 +#define CLK_TWPLL_24M 17 +#define CLK_TWPLL_12M 18 +#define CLK_TWPLL_512M 19 +#define CLK_TWPLL_256M 20 +#define CLK_TWPLL_128M 21 +#define CLK_TWPLL_64M 22 +#define CLK_TWPLL_307M2 23 +#define CLK_TWPLL_153M6 24 +#define CLK_TWPLL_76M8 25 +#define CLK_TWPLL_51M2 26 +#define CLK_TWPLL_38M4 27 +#define CLK_TWPLL_19M2 28 +#define CLK_L0_614M4 29 +#define CLK_L0_409M6 30 +#define CLK_L0_38M 31 +#define CLK_L1_38M 32 +#define CLK_RPLL0_192M 33 +#define CLK_RPLL0_96M 34 +#define CLK_RPLL0_48M 35 +#define CLK_RPLL1_468M 36 +#define CLK_RPLL1_192M 37 +#define CLK_RPLL1_96M 38 +#define CLK_RPLL1_64M 39 +#define CLK_RPLL1_48M 40 +#define CLK_DPLL0_50M 41 +#define CLK_DPLL1_50M 42 +#define CLK_CPPLL_50M 43 +#define CLK_M0_39M 44 +#define CLK_M1_63M 45 +#define CLK_PLL_NUM (CLK_M1_63M + 1) + + +#define CLK_AP_APB 0 +#define CLK_AP_USB3 1 +#define CLK_UART0 2 +#define CLK_UART1 3 +#define CLK_UART2 4 +#define CLK_UART3 5 +#define CLK_UART4 6 +#define CLK_I2C0 7 +#define CLK_I2C1 8 +#define CLK_I2C2 9 +#define CLK_I2C3 10 +#define CLK_I2C4 11 +#define CLK_I2C5 12 +#define CLK_SPI0 13 +#define CLK_SPI1 14 +#define CLK_SPI2 15 +#define CLK_SPI3 16 +#define CLK_IIS0 17 +#define CLK_IIS1 18 +#define CLK_IIS2 19 +#define CLK_IIS3 20 +#define CLK_AP_CLK_NUM (CLK_IIS3 + 1) + +#define CLK_AON_APB 0 +#define CLK_AUX0 1 +#define CLK_AUX1 2 +#define CLK_AUX2 3 +#define CLK_PROBE 4 +#define CLK_SP_AHB 5 +#define CLK_CCI 6 +#define CLK_GIC 7 +#define CLK_CSSYS 8 +#define CLK_SDIO0_2X 9 +#define CLK_SDIO1_2X 10 +#define CLK_SDIO2_2X 11 +#define CLK_EMMC_2X 12 +#define CLK_SDIO0_1X 13 +#define CLK_SDIO1_1X 14 +#define CLK_SDIO2_1X 15 +#define CLK_EMMC_1X 16 +#define CLK_ADI 17 +#define CLK_PWM0 18 +#define CLK_PWM1 19 +#define CLK_PWM2 20 +#define CLK_PWM3 21 +#define CLK_EFUSE 22 +#define CLK_CM3_UART0 23 +#define CLK_CM3_UART1 24 +#define CLK_THM 25 +#define CLK_CM3_I2C0 26 +#define CLK_CM3_I2C1 27 +#define CLK_CM4_SPI 28 +#define CLK_AON_I2C 29 +#define CLK_AVS 30 +#define CLK_CA53_DAP 31 +#define CLK_CA53_TS 32 +#define CLK_DJTAG_TCK 33 +#define CLK_PMU 34 +#define CLK_PMU_26M 35 +#define CLK_DEBOUNCE 36 +#define CLK_OTG2_REF 37 +#define CLK_USB3_REF 38 +#define CLK_AP_AXI 39 +#define CLK_AON_PREDIV_NUM (CLK_AP_AXI + 1) + +#define CLK_USB3_EB 0 +#define CLK_USB3_SUSPEND_EB 1 +#define CLK_USB3_REF_EB 2 +#define CLK_DMA_EB 3 +#define CLK_SDIO0_EB 4 +#define CLK_SDIO1_EB 5 +#define CLK_SDIO2_EB 6 +#define CLK_EMMC_EB 7 +#define CLK_ROM_EB 8 +#define CLK_BUSMON_EB 9 +#define CLK_CC63S_EB 10 +#define CLK_CC63P_EB 11 +#define CLK_CE0_EB 12 +#define CLK_CE1_EB 13 +#define CLK_APAHB_GATE_NUM (CLK_CE1_EB + 1) + +#define CLK_AVS_LIT_EB 0 +#define CLK_AVS_BIG_EB 1 +#define CLK_AP_INTC5_EB 2 +#define CLK_GPIO_EB 3 +#define CLK_PWM0_EB 4 +#define CLK_PWM1_EB 5 +#define CLK_PWM2_EB 6 +#define CLK_PWM3_EB 7 +#define CLK_KPD_EB 8 +#define CLK_AON_SYS_EB 9 +#define CLK_AP_SYS_EB 10 +#define CLK_AON_TMR_EB 11 +#define CLK_AP_TMR0_EB 12 +#define CLK_EFUSE_EB 13 +#define CLK_EIC_EB 14 +#define CLK_PUB1_REG_EB 15 +#define CLK_ADI_EB 16 +#define CLK_AP_INTC0_EB 17 +#define CLK_AP_INTC1_EB 18 +#define CLK_AP_INTC2_EB 19 +#define CLK_AP_INTC3_EB 20 +#define CLK_AP_INTC4_EB 21 +#define CLK_SPLK_EB 22 +#define CLK_MSPI_EB 23 +#define CLK_PUB0_REG_EB 24 +#define CLK_PIN_EB 25 +#define CLK_AON_CKG_EB 26 +#define CLK_GPU_EB 27 +#define CLK_APCPU_TS0_EB 28 +#define CLK_APCPU_TS1_EB 29 +#define CLK_DAP_EB 30 +#define CLK_I2C_EB 31 +#define CLK_PMU_EB 32 +#define CLK_THM_EB 33 +#define CLK_AUX0_EB 34 +#define CLK_AUX1_EB 35 +#define CLK_AUX2_EB 36 +#define CLK_PROBE_EB 37 +#define CLK_GPU0_AVS_EB 38 +#define CLK_GPU1_AVS_EB 39 +#define CLK_APCPU_WDG_EB 40 +#define CLK_AP_TMR1_EB 41 +#define CLK_AP_TMR2_EB 42 +#define CLK_DISP_EMC_EB 43 +#define CLK_ZIP_EMC_EB 44 +#define CLK_GSP_EMC_EB 45 +#define CLK_OSC_AON_EB 46 +#define CLK_LVDS_TRX_EB 47 +#define CLK_LVDS_TCXO_EB 48 +#define CLK_MDAR_EB 49 +#define CLK_RTC4M0_CAL_EB 50 +#define CLK_RCT100M_CAL_EB 51 +#define CLK_DJTAG_EB 52 +#define CLK_MBOX_EB 53 +#define CLK_AON_DMA_EB 54 +#define CLK_DBG_EMC_EB 55 +#define CLK_LVDS_PLL_DIV_EN 56 +#define CLK_DEF_EB 57 +#define CLK_AON_APB_RSV0 58 +#define CLK_ORP_JTAG_EB 59 +#define CLK_VSP_EB 60 +#define CLK_CAM_EB 61 +#define CLK_DISP_EB 62 +#define CLK_DBG_AXI_IF_EB 63 +#define CLK_SDIO0_2X_EN 64 +#define CLK_SDIO1_2X_EN 65 +#define CLK_SDIO2_2X_EN 66 +#define CLK_EMMC_2X_EN 67 +#define CLK_AON_GATE_NUM (CLK_EMMC_2X_EN + 1) + +#define CLK_LIT_MCU 0 +#define CLK_BIG_MCU 1 +#define CLK_AONSECURE_NUM (CLK_BIG_MCU + 1) + +#define CLK_AGCP_IIS0_EB 0 +#define CLK_AGCP_IIS1_EB 1 +#define CLK_AGCP_IIS2_EB 2 +#define CLK_AGCP_IIS3_EB 3 +#define CLK_AGCP_UART_EB 4 +#define CLK_AGCP_DMACP_EB 5 +#define CLK_AGCP_DMAAP_EB 6 +#define CLK_AGCP_ARC48K_EB 7 +#define CLK_AGCP_SRC44P1K_EB 8 +#define CLK_AGCP_MCDT_EB 9 +#define CLK_AGCP_VBCIFD_EB 10 +#define CLK_AGCP_VBC_EB 11 +#define CLK_AGCP_SPINLOCK_EB 12 +#define CLK_AGCP_ICU_EB 13 +#define CLK_AGCP_AP_ASHB_EB 14 +#define CLK_AGCP_CP_ASHB_EB 15 +#define CLK_AGCP_AUD_EB 16 +#define CLK_AGCP_AUDIF_EB 17 +#define CLK_AGCP_GATE_NUM (CLK_AGCP_AUDIF_EB + 1) + +#define CLK_GPU 0 +#define CLK_GPU_NUM (CLK_GPU + 1) + +#define CLK_AHB_VSP 0 +#define CLK_VSP 1 +#define CLK_VSP_ENC 2 +#define CLK_VPP 3 +#define CLK_VSP_26M 4 +#define CLK_VSP_NUM (CLK_VSP_26M + 1) + +#define CLK_VSP_DEC_EB 0 +#define CLK_VSP_CKG_EB 1 +#define CLK_VSP_MMU_EB 2 +#define CLK_VSP_ENC_EB 3 +#define CLK_VPP_EB 4 +#define CLK_VSP_26M_EB 5 +#define CLK_VSP_AXI_GATE 6 +#define CLK_VSP_ENC_GATE 7 +#define CLK_VPP_AXI_GATE 8 +#define CLK_VSP_BM_GATE 9 +#define CLK_VSP_ENC_BM_GATE 10 +#define CLK_VPP_BM_GATE 11 +#define CLK_VSP_GATE_NUM (CLK_VPP_BM_GATE + 1) + +#define CLK_AHB_CAM 0 +#define CLK_SENSOR0 1 +#define CLK_SENSOR1 2 +#define CLK_SENSOR2 3 +#define CLK_MIPI_CSI0_EB 4 +#define CLK_MIPI_CSI1_EB 5 +#define CLK_CAM_NUM (CLK_MIPI_CSI1_EB + 1) + +#define CLK_DCAM0_EB 0 +#define CLK_DCAM1_EB 1 +#define CLK_ISP0_EB 2 +#define CLK_CSI0_EB 3 +#define CLK_CSI1_EB 4 +#define CLK_JPG0_EB 5 +#define CLK_JPG1_EB 6 +#define CLK_CAM_CKG_EB 7 +#define CLK_CAM_MMU_EB 8 +#define CLK_ISP1_EB 9 +#define CLK_CPP_EB 10 +#define CLK_MMU_PF_EB 11 +#define CLK_ISP2_EB 12 +#define CLK_DCAM2ISP_IF_EB 13 +#define CLK_ISP2DCAM_IF_EB 14 +#define CLK_ISP_LCLK_EB 15 +#define CLK_ISP_ICLK_EB 16 +#define CLK_ISP_MCLK_EB 17 +#define CLK_ISP_PCLK_EB 18 +#define CLK_ISP_ISP2DCAM_EB 19 +#define CLK_DCAM0_IF_EB 20 +#define CLK_CLK26M_IF_EB 21 +#define CLK_CPHY0_GATE 22 +#define CLK_MIPI_CSI0_GATE 23 +#define CLK_CPHY1_GATE 24 +#define CLK_MIPI_CSI1 25 +#define CLK_DCAM0_AXI_GATE 26 +#define CLK_DCAM1_AXI_GATE 27 +#define CLK_SENSOR0_GATE 28 +#define CLK_SENSOR1_GATE 29 +#define CLK_JPG0_AXI_GATE 30 +#define CLK_GPG1_AXI_GATE 31 +#define CLK_ISP0_AXI_GATE 32 +#define CLK_ISP1_AXI_GATE 33 +#define CLK_ISP2_AXI_GATE 34 +#define CLK_CPP_AXI_GATE 35 +#define CLK_D0_IF_AXI_GATE 36 +#define CLK_D2I_IF_AXI_GATE 37 +#define CLK_I2D_IF_AXI_GATE 38 +#define CLK_SPARE_AXI_GATE 39 +#define CLK_SENSOR2_GATE 40 +#define CLK_D0IF_IN_D_EN 41 +#define CLK_D1IF_IN_D_EN 42 +#define CLK_D0IF_IN_D2I_EN 43 +#define CLK_D1IF_IN_D2I_EN 44 +#define CLK_IA_IN_D2I_EN 45 +#define CLK_IB_IN_D2I_EN 46 +#define CLK_IC_IN_D2I_EN 47 +#define CLK_IA_IN_I_EN 48 +#define CLK_IB_IN_I_EN 49 +#define CLK_IC_IN_I_EN 50 +#define CLK_CAM_GATE_NUM (CLK_IC_IN_I_EN + 1) + +#define CLK_AHB_DISP 0 +#define CLK_DISPC0_DPI 1 +#define CLK_DISPC1_DPI 2 +#define CLK_DISP_NUM (CLK_DISPC1_DPI + 1) + +#define CLK_DISPC0_EB 0 +#define CLK_DISPC1_EB 1 +#define CLK_DISPC_MMU_EB 2 +#define CLK_GSP0_EB 3 +#define CLK_GSP1_EB 4 +#define CLK_GSP0_MMU_EB 5 +#define CLK_GSP1_MMU_EB 6 +#define CLK_DSI0_EB 7 +#define CLK_DSI1_EB 8 +#define CLK_DISP_CKG_EB 9 +#define CLK_DISP_GPU_EB 10 +#define CLK_GPU_MTX_EB 11 +#define CLK_GSP_MTX_EB 12 +#define CLK_TMC_MTX_EB 13 +#define CLK_DISPC_MTX_EB 14 +#define CLK_DPHY0_GATE 15 +#define CLK_DPHY1_GATE 16 +#define CLK_GSP0_A_GATE 17 +#define CLK_GSP1_A_GATE 18 +#define CLK_GSP0_F_GATE 19 +#define CLK_GSP1_F_GATE 20 +#define CLK_D_MTX_F_GATE 21 +#define CLK_D_MTX_A_GATE 22 +#define CLK_D_NOC_F_GATE 23 +#define CLK_D_NOC_A_GATE 24 +#define CLK_GSP_MTX_F_GATE 25 +#define CLK_GSP_MTX_A_GATE 26 +#define CLK_GSP_NOC_F_GATE 27 +#define CLK_GSP_NOC_A_GATE 28 +#define CLK_DISPM0IDLE_GATE 29 +#define CLK_GSPM0IDLE_GATE 30 +#define CLK_DISP_GATE_NUM (CLK_GSPM0IDLE_GATE + 1) + +#define CLK_SIM0_EB 0 +#define CLK_IIS0_EB 1 +#define CLK_IIS1_EB 2 +#define CLK_IIS2_EB 3 +#define CLK_IIS3_EB 4 +#define CLK_SPI0_EB 5 +#define CLK_SPI1_EB 6 +#define CLK_SPI2_EB 7 +#define CLK_I2C0_EB 8 +#define CLK_I2C1_EB 9 +#define CLK_I2C2_EB 10 +#define CLK_I2C3_EB 11 +#define CLK_I2C4_EB 12 +#define CLK_I2C5_EB 13 +#define CLK_UART0_EB 14 +#define CLK_UART1_EB 15 +#define CLK_UART2_EB 16 +#define CLK_UART3_EB 17 +#define CLK_UART4_EB 18 +#define CLK_AP_CKG_EB 19 +#define CLK_SPI3_EB 20 +#define CLK_APAPB_GATE_NUM (CLK_SPI3_EB + 1) + +#endif /* _DT_BINDINGS_CLK_SC9860_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang This patch added the list of clocks for Spreadtrum's SC9860 SoC, together with clock initialization code. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- drivers/clk/sprd/Kconfig | 10 + drivers/clk/sprd/Makefile | 3 + drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ 4 files changed, 2408 insertions(+) create mode 100644 drivers/clk/sprd/sc9860-clk.c create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig index 67a3287..8789247 100644 --- a/drivers/clk/sprd/Kconfig +++ b/drivers/clk/sprd/Kconfig @@ -2,3 +2,13 @@ config SPRD_COMMON_CLK tristate "Clock support for Spreadtrum SoCs" depends on ARCH_SPRD || COMPILE_TEST default ARCH_SPRD + +if SPRD_COMMON_CLK + +# SoC Drivers + +config SPRD_SC9860_CLK + tristate "Support for the Spreadtrum SC9860 clocks" + depends on (ARM64 && ARCH_SPRD) || COMPILE_TEST + default ARM64 && ARCH_SPRD +endif diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile index d693969..b0d81e5 100644 --- a/drivers/clk/sprd/Makefile +++ b/drivers/clk/sprd/Makefile @@ -6,3 +6,6 @@ clk-sprd-y += mux.o clk-sprd-y += div.o clk-sprd-y += composite.o clk-sprd-y += pll.o + +## SoC support +obj-$(CONFIG_SPRD_SC9860_CLK) += sc9860-clk.o diff --git a/drivers/clk/sprd/sc9860-clk.c b/drivers/clk/sprd/sc9860-clk.c new file mode 100644 index 0000000..09e19ff --- /dev/null +++ b/drivers/clk/sprd/sc9860-clk.c @@ -0,0 +1,1987 @@ +/* + * Spreatrum SC9860 clock driver + * + * Copyright (C) 2017 Spreadtrum, Inc. + * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/clk-provider.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include <dt-bindings/clock/sprd,sc9860-clk.h> + +#include "common.h" +#include "composite.h" +#include "div.h" +#include "gate.h" +#include "mux.h" +#include "pll.h" + +static CLK_FIXED_RATE(ext_rco_100m, "ext-rco-100m", 0, 100000000, 0); +static CLK_FIXED_RATE(ext_32k, "ext-32k", 0, 32768, 0); + +static CLK_FIXED_FACTOR(fac_4m, "fac-4m", "ext-26m", + 6, 1, 0); +static CLK_FIXED_FACTOR(fac_2m, "fac-2m", "ext-26m", + 13, 1, 0); +static CLK_FIXED_FACTOR(fac_1m, "fac-1m", "ext-26m", + 26, 1, 0); +static CLK_FIXED_FACTOR(fac_250k, "fac-250k", "ext-26m", + 104, 1, 0); +static CLK_FIXED_FACTOR(fac_rpll0_26m, "rpll0-26m", "ext-26m", + 1, 1, 0); +static CLK_FIXED_FACTOR(fac_rpll1_26m, "rpll1-26m", "ext-26m", + 1, 1, 0); +static CLK_FIXED_FACTOR(fac_rco_25m, "rco-25m", "ext-rc0-100m", + 4, 1, 0); +static CLK_FIXED_FACTOR(fac_rco_4m, "rco-4m", "ext-rc0-100m", + 25, 1, 0); +static CLK_FIXED_FACTOR(fac_rco_2m, "rco-2m", "ext-rc0-100m", + 50, 1, 0); +static CLK_FIXED_FACTOR(fac_3k2, "fac-3k2", "ext-32k", + 10, 1, 0); +static CLK_FIXED_FACTOR(fac_1k, "fac-1k", "ext-32k", + 32, 1, 0); + +static SPRD_GATE_CLK(mpll0_gate, "mpll0-gate", "ext-26m", 0xb0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mpll1_gate, "mpll1-gate", "ext-26m", 0xb0, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dpll0_gate, "dpll0-gate", "ext-26m", 0xb4, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dpll1_gate, "dpll1-gate", "ext-26m", 0xb4, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ltepll0_gate, "ltepll0-gate", "ext-26m", 0xb8, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(twpll_gate, "twpll-gate", "ext-26m", 0xbc, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ltepll1_gate, "ltepll1-gate", "ext-26m", 0x10c, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rpll0_gate, "rpll0-gate", "ext-26m", 0x16c, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(rpll1_gate, "rpll1-gate", "ext-26m", 0x16c, + 0x1000, BIT(18), 0, 0); +static SPRD_GATE_CLK(cppll_gate, "cppll-gate", "ext-26m", 0x2b4, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpll_gate, "gpll-gate", "ext-26m", 0x32c, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, CLK_GATE_SET_TO_DISABLE); + +static struct sprd_clk_common *sc9860_pmu_gate_clks[] = { + /* address base is 0x402b0000 */ + &mpll0_gate.common, + &mpll1_gate.common, + &dpll0_gate.common, + &dpll1_gate.common, + <epll0_gate.common, + &twpll_gate.common, + <epll1_gate.common, + &rpll0_gate.common, + &rpll1_gate.common, + &cppll_gate.common, + &gpll_gate.common, +}; + +static struct clk_hw_onecell_data sc9860_pmu_gate_hws = { + .hws = { + [CLK_EXT_RCO_100M] = &ext_rco_100m.hw, + [CLK_EXT_32K] = &ext_32k.hw, + [CLK_FAC_4M] = &fac_4m.hw, + [CLK_FAC_2M] = &fac_2m.hw, + [CLK_FAC_1M] = &fac_1m.hw, + [CLK_FAC_250K] = &fac_250k.hw, + [CLK_FAC_RPLL0_26M] = &fac_rpll0_26m.hw, + [CLK_FAC_RPLL1_26M] = &fac_rpll1_26m.hw, + [CLK_FAC_RCO25M] = &fac_rco_25m.hw, + [CLK_FAC_RCO4M] = &fac_rco_4m.hw, + [CLK_FAC_RCO2M] = &fac_rco_2m.hw, + [CLK_FAC_3K2] = &fac_3k2.hw, + [CLK_FAC_1K] = &fac_1k.hw, + [CLK_MPLL0_GATE] = &mpll0_gate.common.hw, + [CLK_MPLL1_GATE] = &mpll1_gate.common.hw, + [CLK_DPLL0_GATE] = &dpll0_gate.common.hw, + [CLK_DPLL1_GATE] = &dpll1_gate.common.hw, + [CLK_LTEPLL0_GATE] = <epll0_gate.common.hw, + [CLK_TWPLL_GATE] = &twpll_gate.common.hw, + [CLK_LTEPLL1_GATE] = <epll1_gate.common.hw, + [CLK_RPLL0_GATE] = &rpll0_gate.common.hw, + [CLK_RPLL1_GATE] = &rpll1_gate.common.hw, + [CLK_CPPLL_GATE] = &cppll_gate.common.hw, + [CLK_GPLL_GATE] = &gpll_gate.common.hw, + }, + .num = CLK_PMU_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_pmu_gate_desc = { + .clk_clks = sc9860_pmu_gate_clks, + .num_clk_clks = ARRAY_SIZE(sc9860_pmu_gate_clks), + .hw_clks = &sc9860_pmu_gate_hws, +}; + +/* GPLL/LPLL/DPLL/RPLL/CPLL */ +static const u64 const itable1[4] = {3, 780000000, 988000000, 1196000000}; + +/* TWPLL/MPLL0/MPLL1 */ +static const u64 itable2[4] = {3, 1638000000, 2080000000, 2600000000UL}; + +static const struct clk_bit_field const f_mpll0[PLL_FACT_MAX] = { + { .shift = 20, .width = 1 }, /* lock_done */ + { .shift = 19, .width = 1 }, /* div_s */ + { .shift = 18, .width = 1 }, /* mod_en */ + { .shift = 17, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 11, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 56, .width = 1 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_K_FVCO(mpll0_clk, "mpll0", "mpll0-gate", 0x24, + 2, itable2, f_mpll0, 200, + 1000, 1000, 1, 1300000000); + +static const struct clk_bit_field const f_mpll1[PLL_FACT_MAX] = { + { .shift = 20, .width = 1 }, /* lock_done */ + { .shift = 19, .width = 1 }, /* div_s */ + { .shift = 18, .width = 1 }, /* mod_en */ + { .shift = 17, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 11, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 56, .width = 1 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(mpll1_clk, "mpll1", "mpll1-gate", 0x2c, + 2, itable2, f_mpll1, 200); + +static const struct clk_bit_field const f_dpll[PLL_FACT_MAX] = { + { .shift = 16, .width = 1 }, /* lock_done */ + { .shift = 15, .width = 1 }, /* div_s */ + { .shift = 14, .width = 1 }, /* mod_en */ + { .shift = 13, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 8, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(dpll0_clk, "dpll0", "dpll0-gate", 0x34, + 2, itable1, f_dpll, 200); + +static SPRD_PLL_WITH_ITABLE_1K(dpll1_clk, "dpll1", "dpll1-gate", 0x3c, + 2, itable1, f_dpll, 200); + +static const struct clk_bit_field const f_rpll[PLL_FACT_MAX] = { + { .shift = 0, .width = 1 }, /* lock_done */ + { .shift = 3, .width = 1 }, /* div_s */ + { .shift = 80, .width = 1 }, /* mod_en */ + { .shift = 81, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 14, .width = 2 }, /* ibias */ + { .shift = 16, .width = 7 }, /* n */ + { .shift = 4, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(rpll0_clk, "rpll0", "rpll0-gate", 0x44, + 3, itable1, f_rpll, 200); + +static SPRD_PLL_WITH_ITABLE_1K(rpll1_clk, "rpll1", "rpll1-gate", 0x50, + 3, itable1, f_rpll, 200); + +static const struct clk_bit_field const f_twpll[PLL_FACT_MAX] = { + { .shift = 21, .width = 1 }, /* lock_done */ + { .shift = 20, .width = 1 }, /* div_s */ + { .shift = 19, .width = 1 }, /* mod_en */ + { .shift = 18, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 13, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(twpll_clk, "twpll", "twpll-gate", 0x5c, + 2, itable2, f_twpll, 200); + +static const struct clk_bit_field const f_ltepll[PLL_FACT_MAX] = { + { .shift = 31, .width = 1 }, /* lock_done */ + { .shift = 27, .width = 1 }, /* div_s */ + { .shift = 26, .width = 1 }, /* mod_en */ + { .shift = 25, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 20, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(ltepll0_clk, "ltepll0", "ltepll0-gate", + 0x64, 2, itable1, + f_ltepll, 200); +static SPRD_PLL_WITH_ITABLE_1K(ltepll1_clk, "ltepll1", "ltepll1-gate", + 0x6c, 2, itable1, + f_ltepll, 200); + +static const struct clk_bit_field const f_gpll[PLL_FACT_MAX] = { + { .shift = 18, .width = 1 }, /* lock_done */ + { .shift = 15, .width = 1 }, /* div_s */ + { .shift = 14, .width = 1 }, /* mod_en */ + { .shift = 13, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 8, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 17, .width = 1 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_K_FVCO(gpll_clk, "gpll", "gpll-gate", 0x9c, + 2, itable1, f_gpll, 200, + 1000, 1000, 1, 600000000); + +static const struct clk_bit_field const f_cppll[PLL_FACT_MAX] = { + { .shift = 17, .width = 1 }, /* lock_done */ + { .shift = 15, .width = 1 }, /* div_s */ + { .shift = 14, .width = 1 }, /* mod_en */ + { .shift = 13, .width = 1 }, /* sdm_en */ + { .shift = 0, .width = 0 }, /* refin */ + { .shift = 8, .width = 2 }, /* ibias */ + { .shift = 0, .width = 7 }, /* n */ + { .shift = 57, .width = 7 }, /* nint */ + { .shift = 32, .width = 23}, /* kint */ + { .shift = 0, .width = 0 }, /* prediv */ + { .shift = 0, .width = 0 }, /* postdiv */ +}; +static SPRD_PLL_WITH_ITABLE_1K(cppll_clk, "cppll", "cppll-gate", 0xc4, + 2, itable1, f_cppll, 200); + +static CLK_FIXED_FACTOR(gpll_42m5, "gpll-42m5", "gpll", 20, 1, 0); +static CLK_FIXED_FACTOR(twpll_768m, "twpll-768m", "twpll", 2, 1, 0); +static CLK_FIXED_FACTOR(twpll_384m, "twpll-384m", "twpll", 4, 1, 0); +static CLK_FIXED_FACTOR(twpll_192m, "twpll-192m", "twpll", 8, 1, 0); +static CLK_FIXED_FACTOR(twpll_96m, "twpll-96m", "twpll", 16, 1, 0); +static CLK_FIXED_FACTOR(twpll_48m, "twpll-48m", "twpll", 32, 1, 0); +static CLK_FIXED_FACTOR(twpll_24m, "twpll-24m", "twpll", 64, 1, 0); +static CLK_FIXED_FACTOR(twpll_12m, "twpll-12m", "twpll", 128, 1, 0); +static CLK_FIXED_FACTOR(twpll_512m, "twpll-512m", "twpll", 3, 1, 0); +static CLK_FIXED_FACTOR(twpll_256m, "twpll-256m", "twpll", 6, 1, 0); +static CLK_FIXED_FACTOR(twpll_128m, "twpll-128m", "twpll", 12, 1, 0); +static CLK_FIXED_FACTOR(twpll_64m, "twpll-64m", "twpll", 24, 1, 0); +static CLK_FIXED_FACTOR(twpll_307m2, "twpll-307m2", "twpll", 5, 1, 0); +static CLK_FIXED_FACTOR(twpll_153m6, "twpll-153m6", "twpll", 10, 1, 0); +static CLK_FIXED_FACTOR(twpll_76m8, "twpll-76m8", "twpll", 20, 1, 0); +static CLK_FIXED_FACTOR(twpll_51m2, "twpll-51m2", "twpll", 30, 1, 0); +static CLK_FIXED_FACTOR(twpll_38m4, "twpll-38m4", "twpll", 40, 1, 0); +static CLK_FIXED_FACTOR(twpll_19m2, "twpll-19m2", "twpll", 80, 1, 0); +static CLK_FIXED_FACTOR(l0_614m4, "l0-614m4", "ltepll0", 2, 1, 0); +static CLK_FIXED_FACTOR(l0_409m6, "l0-409m6", "ltepll0", 3, 1, 0); +static CLK_FIXED_FACTOR(l0_38m, "l0-38m", "ltepll0", 32, 1, 0); +static CLK_FIXED_FACTOR(l1_38m, "l1-38m", "ltepll1", 32, 1, 0); +static CLK_FIXED_FACTOR(rpll0_192m, "rpll0-192m", "rpll0", 6, 1, 0); +static CLK_FIXED_FACTOR(rpll0_96m, "rpll0-96m", "rpll0", 12, 1, 0); +static CLK_FIXED_FACTOR(rpll0_48m, "rpll0-48m", "rpll0", 24, 1, 0); +static CLK_FIXED_FACTOR(rpll1_468m, "rpll1-468m", "rpll1", 2, 1, 0); +static CLK_FIXED_FACTOR(rpll1_192m, "rpll1-192m", "rpll1", 6, 1, 0); +static CLK_FIXED_FACTOR(rpll1_96m, "rpll1-96m", "rpll1", 12, 1, 0); +static CLK_FIXED_FACTOR(rpll1_64m, "rpll1-64m", "rpll1", 18, 1, 0); +static CLK_FIXED_FACTOR(rpll1_48m, "rpll1-48m", "rpll1", 24, 1, 0); +static CLK_FIXED_FACTOR(dpll0_50m, "dpll0-50m", "dpll0", 16, 1, 0); +static CLK_FIXED_FACTOR(dpll1_50m, "dpll1-50m", "dpll1", 16, 1, 0); +static CLK_FIXED_FACTOR(cppll_50m, "cppll-50m", "cppll", 18, 1, 0); +static CLK_FIXED_FACTOR(m0_39m, "m0-39m", "mpll0", 32, 1, 0); +static CLK_FIXED_FACTOR(m1_63m, "m1-63m", "mpll1", 32, 1, 0); + +static struct sprd_clk_common *sc9860_pll_clks[] = { + /* address base is 0x40400000 */ + &mpll0_clk.common, + &mpll1_clk.common, + &dpll0_clk.common, + &dpll1_clk.common, + &rpll0_clk.common, + &rpll1_clk.common, + &twpll_clk.common, + <epll0_clk.common, + <epll1_clk.common, + &gpll_clk.common, + &cppll_clk.common, +}; + +static struct clk_hw_onecell_data sc9860_pll_hws = { + .hws = { + [CLK_MPLL0] = &mpll0_clk.common.hw, + [CLK_MPLL1] = &mpll1_clk.common.hw, + [CLK_DPLL0] = &dpll0_clk.common.hw, + [CLK_DPLL1] = &dpll1_clk.common.hw, + [CLK_RPLL0] = &rpll0_clk.common.hw, + [CLK_RPLL1] = &rpll1_clk.common.hw, + [CLK_TWPLL] = &twpll_clk.common.hw, + [CLK_LTEPLL0] = <epll0_clk.common.hw, + [CLK_LTEPLL1] = <epll1_clk.common.hw, + [CLK_GPLL] = &gpll_clk.common.hw, + [CLK_CPPLL] = &cppll_clk.common.hw, + [CLK_GPLL_42M5] = &gpll_42m5.hw, + [CLK_TWPLL_768M] = &twpll_768m.hw, + [CLK_TWPLL_384M] = &twpll_384m.hw, + [CLK_TWPLL_192M] = &twpll_192m.hw, + [CLK_TWPLL_96M] = &twpll_96m.hw, + [CLK_TWPLL_48M] = &twpll_48m.hw, + [CLK_TWPLL_24M] = &twpll_24m.hw, + [CLK_TWPLL_12M] = &twpll_12m.hw, + [CLK_TWPLL_512M] = &twpll_512m.hw, + [CLK_TWPLL_256M] = &twpll_256m.hw, + [CLK_TWPLL_128M] = &twpll_128m.hw, + [CLK_TWPLL_64M] = &twpll_64m.hw, + [CLK_TWPLL_307M2] = &twpll_307m2.hw, + [CLK_TWPLL_153M6] = &twpll_153m6.hw, + [CLK_TWPLL_76M8] = &twpll_76m8.hw, + [CLK_TWPLL_51M2] = &twpll_51m2.hw, + [CLK_TWPLL_38M4] = &twpll_38m4.hw, + [CLK_TWPLL_19M2] = &twpll_19m2.hw, + [CLK_L0_614M4] = &l0_614m4.hw, + [CLK_L0_409M6] = &l0_409m6.hw, + [CLK_L0_38M] = &l0_38m.hw, + [CLK_L1_38M] = &l1_38m.hw, + [CLK_RPLL0_192M] = &rpll0_192m.hw, + [CLK_RPLL0_96M] = &rpll0_96m.hw, + [CLK_RPLL0_48M] = &rpll0_48m.hw, + [CLK_RPLL1_468M] = &rpll1_468m.hw, + [CLK_RPLL1_192M] = &rpll1_192m.hw, + [CLK_RPLL1_96M] = &rpll1_96m.hw, + [CLK_RPLL1_64M] = &rpll1_64m.hw, + [CLK_RPLL1_48M] = &rpll1_48m.hw, + [CLK_DPLL0_50M] = &dpll0_50m.hw, + [CLK_DPLL1_50M] = &dpll1_50m.hw, + [CLK_CPPLL_50M] = &cppll_50m.hw, + [CLK_M0_39M] = &m0_39m.hw, + [CLK_M1_63M] = &m1_63m.hw, + }, + .num = CLK_PLL_NUM, +}; + +static const struct sprd_clk_desc sc9860_pll_desc = { + .clk_clks = sc9860_pll_clks, + .num_clk_clks = ARRAY_SIZE(sc9860_pll_clks), + .hw_clks = &sc9860_pll_hws, +}; + +#define SC9860_MUX_FLAG \ + (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_NO_REPARENT) + +static const char * const ap_apb_parents[] = { "ext-26m", "twpll-64m", + "twpll-96m", "twpll-128m" }; +static SPRD_MUX_CLK(ap_apb, "ap-apb", ap_apb_parents, NULL, + 0x20, 0, 1, SC9860_MUX_FLAG); + +static const char * const ap_apb_usb3[] = { "ext-32k", "twpll-24m" }; +static SPRD_MUX_CLK(ap_usb3, "ap-usb3", ap_apb_usb3, NULL, + 0x2c, 0, 1, SC9860_MUX_FLAG); + +static const char * const uart_parents[] = { "ext-26m", "twpll-48m", + "twpll-51m2", "twpll-96m" }; +static SPRD_COMP_CLK(uart0_clk, "uart0", uart_parents, 0x30, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart1_clk, "uart1", uart_parents, 0x34, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart2_clk, "uart2", uart_parents, 0x38, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart3_clk, "uart3", uart_parents, 0x3c, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(uart4_clk, "uart4", uart_parents, 0x40, + 0, 0, 2, 8, 3, 0); + +static const char * const i2c_parents[] = { "ext-26m", "twpll-48m", + "twpll-51m2", "twpll-153m6" }; +static SPRD_COMP_CLK(i2c0_clk, "i2c0", i2c_parents, 0x44, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c1_clk, "i2c1", i2c_parents, 0x48, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c2_clk, "i2c2", i2c_parents, 0x4c, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c3_clk, "i2c3", i2c_parents, 0x50, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c4_clk, "i2c4", i2c_parents, 0x54, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(i2c5_clk, "i2c5", i2c_parents, 0x58, + 0, 0, 2, 8, 3, 0); + +static const char * const spi_parents[] = { "ext-26m", "twpll-128m", + "twpll-153m6", "twpll-192m" }; +static SPRD_COMP_CLK(spi0_clk, "spi0", spi_parents, 0x5c, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(spi1_clk, "spi1", spi_parents, 0x60, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(spi2_clk, "spi2", spi_parents, 0x64, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(spi3_clk, "spi3", spi_parents, 0x68, + 0, 0, 2, 8, 3, 0); + +static const char * const iis_parents[] = { "ext-26m", + "twpll-128m", + "twpll-153m6" }; +static SPRD_COMP_CLK(iis0_clk, "iis0", iis_parents, 0x6c, + 0, 0, 2, 8, 6, 0); +static SPRD_COMP_CLK(iis1_clk, "iis1", iis_parents, 0x70, + 0, 0, 2, 8, 6, 0); +static SPRD_COMP_CLK(iis2_clk, "iis2", iis_parents, 0x74, + 0, 0, 2, 8, 6, 0); +static SPRD_COMP_CLK(iis3_clk, "iis3", iis_parents, 0x78, + 0, 0, 2, 8, 6, 0); + +static struct sprd_clk_common *sc9860_ap_clks[] = { + /* address base is 0x20000000 */ + &ap_apb.common, + &ap_usb3.common, + &uart0_clk.common, + &uart1_clk.common, + &uart2_clk.common, + &uart3_clk.common, + &uart4_clk.common, + &i2c0_clk.common, + &i2c1_clk.common, + &i2c2_clk.common, + &i2c3_clk.common, + &i2c4_clk.common, + &i2c5_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &spi2_clk.common, + &spi3_clk.common, + &iis0_clk.common, + &iis1_clk.common, + &iis2_clk.common, + &iis3_clk.common, +}; + +static struct clk_hw_onecell_data sc9860_ap_clk_hws = { + .hws = { + [CLK_AP_APB] = &ap_apb.common.hw, + [CLK_AP_USB3] = &ap_usb3.common.hw, + [CLK_UART0] = &uart0_clk.common.hw, + [CLK_UART1] = &uart1_clk.common.hw, + [CLK_UART2] = &uart2_clk.common.hw, + [CLK_UART3] = &uart3_clk.common.hw, + [CLK_UART4] = &uart4_clk.common.hw, + [CLK_I2C0] = &i2c0_clk.common.hw, + [CLK_I2C1] = &i2c1_clk.common.hw, + [CLK_I2C2] = &i2c2_clk.common.hw, + [CLK_I2C3] = &i2c3_clk.common.hw, + [CLK_I2C4] = &i2c4_clk.common.hw, + [CLK_I2C5] = &i2c5_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_SPI2] = &spi2_clk.common.hw, + [CLK_SPI3] = &spi3_clk.common.hw, + [CLK_IIS0] = &iis0_clk.common.hw, + [CLK_IIS1] = &iis1_clk.common.hw, + [CLK_IIS2] = &iis2_clk.common.hw, + [CLK_IIS3] = &iis3_clk.common.hw, + }, + .num = CLK_AP_CLK_NUM, +}; + +static const struct sprd_clk_desc sc9860_ap_clk_desc = { + .clk_clks = sc9860_ap_clks, + .num_clk_clks = ARRAY_SIZE(sc9860_ap_clks), + .hw_clks = &sc9860_ap_clk_hws, +}; + +static const char * const aon_apb_parents[] = { "rco-25m", "ext-26m", + "ext-rco-100m", "twpll-96m", + "twpll-128m", + "twpll-153m6" }; +static SPRD_COMP_CLK(aon_apb, "aon-apb", aon_apb_parents, 0x230, + 0, 0, 3, 8, 2, 0); + +static const char * const aux_parents[] = { "ext-32k", "rpll0-26m", + "rpll1-26m", "ext-26m", + "cppll-50m", "rco-25m", + "dpll0-50m", "dpll1-50m", + "gpll-42m5", "twpll-48m", + "m0-39m", "m1-63m", + "l0-38m", "l1-38m" }; + +static SPRD_COMP_CLK(aux0_clk, "aux0", aux_parents, 0x238, + 0, 0, 5, 8, 4, 0); +static SPRD_COMP_CLK(aux1_clk, "aux1", aux_parents, 0x23c, + 0, 0, 5, 8, 4, 0); +static SPRD_COMP_CLK(aux2_clk, "aux2", aux_parents, 0x240, + 0, 0, 5, 8, 4, 0); +static SPRD_COMP_CLK(probe_clk, "probe", aux_parents, 0x244, + 0, 0, 5, 8, 4, 0); + +static const char * const sp_ahb_parents[] = { "rco-4m", "ext-26m", + "ext-rco-100m", "twpll-96m", + "twpll-128m", + "twpll-153m6" }; +static SPRD_COMP_CLK(sp_ahb, "sp-ahb", sp_ahb_parents, 0x2d0, + 0, 0, 3, 8, 2, 0); + +static const char * const cci_parents[] = { "ext-26m", "twpll-384m", + "l0-614m4", "twpll-768m" }; +static SPRD_COMP_CLK(cci_clk, "cci", cci_parents, 0x300, + 0, 0, 2, 8, 2, 0); +static SPRD_COMP_CLK(gic_clk, "gic", cci_parents, 0x304, + 0, 0, 2, 8, 2, 0); +static SPRD_COMP_CLK(cssys_clk, "cssys", cci_parents, 0x310, + 0, 0, 2, 8, 2, 0); + +static const char * const sdio_2x_parents[] = { "fac-1m", "ext-26m", + "twpll-307m2", "twpll-384m", + "l0-409m6" }; +static SPRD_COMP_CLK(sdio0_2x, "sdio0-2x", sdio_2x_parents, 0x328, + 0, 0, 3, 8, 4, 0); +static SPRD_COMP_CLK(sdio1_2x, "sdio1-2x", sdio_2x_parents, 0x330, + 0, 0, 3, 8, 4, 0); +static SPRD_COMP_CLK(sdio2_2x, "sdio2-2x", sdio_2x_parents, 0x338, + 0, 0, 3, 8, 4, 0); +static SPRD_COMP_CLK(emmc_2x, "emmc-2x", sdio_2x_parents, 0x340, + 0, 0, 3, 8, 4, 0); + +static SPRD_DIV_CLK(sdio0_1x, "sdio0-1x", "sdio0-2x", 0x32c, + 8, 1, 0); +static SPRD_DIV_CLK(sdio1_1x, "sdio1-1x", "sdio1-2x", 0x334, + 8, 1, 0); +static SPRD_DIV_CLK(sdio2_1x, "sdio2-1x", "sdio2-2x", 0x33c, + 8, 1, 0); +static SPRD_DIV_CLK(emmc_1x, "emmc-1x", "emmc-2x", 0x344, + 8, 1, 0); + +static const char * const adi_parents[] = { "rco-4m", "ext-26m", + "rco-25m", "twpll-38m4", + "twpll-51m2" }; +static SPRD_MUX_CLK(adi_clk, "adi", adi_parents, NULL, 0x234, + 0, 3, SC9860_MUX_FLAG); + +static const char * const pwm_parents[] = { "ext-32k", "ext-26m", + "rco-4m", "rco-25m", + "twpll-48m" }; +static SPRD_MUX_CLK(pwm0_clk, "pwm0", pwm_parents, NULL, 0x248, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(pwm1_clk, "pwm1", pwm_parents, NULL, 0x24c, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(pwm2_clk, "pwm2", pwm_parents, NULL, 0x250, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(pwm3_clk, "pwm3", pwm_parents, NULL, 0x254, + 0, 3, SC9860_MUX_FLAG); + +static const char * const efuse_parents[] = { "rco-25m", "ext-26m" }; +static SPRD_MUX_CLK(efuse_clk, "efuse", efuse_parents, NULL, 0x258, + 0, 1, SC9860_MUX_FLAG); + +static const char * const cm3_uart_parents[] = { "rco-4m", "ext-26m", + "rco-100m", "twpll-48m", + "twpll-51m2", "twpll-96m", + "twpll-128m" }; +static SPRD_MUX_CLK(cm3_uart0, "cm3-uart0", cm3_uart_parents, NULL, 0x25c, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(cm3_uart1, "cm3-uart1", cm3_uart_parents, NULL, 0x260, + 0, 3, SC9860_MUX_FLAG); + +static const char * const thm_parents[] = { "ext-32k", "fac-250k" }; +static SPRD_MUX_CLK(thm_clk, "thm", thm_parents, NULL, 0x270, + 0, 1, SC9860_MUX_FLAG); + +static const char * const cm3_i2c_parents[] = { "rco-4m", + "ext-26m", + "rco-100m", + "twpll-48m", + "twpll-51m2", + "twpll-153m6" }; +static SPRD_MUX_CLK(cm3_i2c0, "cm3-i2c0", cm3_i2c_parents, NULL, 0x274, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(cm3_i2c1, "cm3-i2c1", cm3_i2c_parents, NULL, 0x278, + 0, 3, SC9860_MUX_FLAG); +static SPRD_MUX_CLK(aon_i2c, "aon-i2c", cm3_i2c_parents, NULL, 0x280, + 0, 3, SC9860_MUX_FLAG); + +static const char * const cm4_spi_parents[] = { "ext-26m", "twpll-96m", + "rco-100m", "twpll-128m", + "twpll-153m6", "twpll-192m" }; +static SPRD_MUX_CLK(cm4_spi, "cm4-spi", cm4_spi_parents, NULL, 0x27c, + 0, 3, SC9860_MUX_FLAG); + +static SPRD_MUX_CLK(avs_clk, "avs", uart_parents, NULL, 0x284, + 0, 2, SC9860_MUX_FLAG); + +static const char * const ca53_dap_parents[] = { "ext-26m", "rco-4m", + "rco-100m", "twpll-76m8", + "twpll-128m", "twpll-153m6" }; +static SPRD_MUX_CLK(ca53_dap, "ca53-dap", ca53_dap_parents, NULL, 0x288, + 0, 3, SC9860_MUX_FLAG); + +static const char * const ca53_ts_parents[] = { "ext-32k", "ext-26m", + "clk-twpll-128m", + "clk-twpll-153m6" }; +static SPRD_MUX_CLK(ca53_ts, "ca53-ts", ca53_ts_parents, NULL, 0x290, + 0, 2, SC9860_MUX_FLAG); + +static const char * const djtag_tck_parents[] = { "rco-4m", "ext-26m" }; +static SPRD_MUX_CLK(djtag_tck, "djtag-tck", djtag_tck_parents, NULL, + 0x2c8, 0, 1, SC9860_MUX_FLAG); + +static const char * const pmu_parents[] = { "ext-32k", "rco-4m", "clk-4m" }; +static SPRD_MUX_CLK(pmu_clk, "pmu", pmu_parents, NULL, 0x2e0, + 0, 2, SC9860_MUX_FLAG); + +static const char * const pmu_26m_parents[] = { "rco-25m", "ext-26m" }; +static SPRD_MUX_CLK(pmu_26m, "pmu-26m", pmu_26m_parents, NULL, + 0x2e4, 0, 1, SC9860_MUX_FLAG); + +static const char * const debounce_parents[] = { "ext-32k", "rco-4m", + "rco-25m", "ext-26m" }; +static SPRD_MUX_CLK(debounce_clk, "debounce", debounce_parents, NULL, + 0x2e8, 0, 2, SC9860_MUX_FLAG); + +static const char * const otg2_ref_parents[] = { "twpll-12m", "twpll-24m" }; +static SPRD_MUX_CLK(otg2_ref, "otg2-ref", otg2_ref_parents, NULL, + 0x2f4, 0, 1, SC9860_MUX_FLAG); + +static const char * const usb3_ref_parents[] = { "twpll-24m", "twpll-19m2", + "twpll-48m" }; +static SPRD_MUX_CLK(usb3_ref, "usb3-ref", usb3_ref_parents, NULL, + 0x2f8, 0, 2, SC9860_MUX_FLAG); + +static const char * const ap_axi_parents[] = { "ext-26m", "twpll-76m8", + "twpll-128m", "twpll-256m" }; +static SPRD_MUX_CLK(ap_axi, "ap-axi", ap_axi_parents, NULL, + 0x324, 0, 2, SC9860_MUX_FLAG); + +static struct sprd_clk_common *sc9860_aon_prediv[] = { + /* address base is 0x402d0000 */ + &aon_apb.common, + &aux0_clk.common, + &aux1_clk.common, + &aux2_clk.common, + &probe_clk.common, + &sp_ahb.common, + &cci_clk.common, + &gic_clk.common, + &cssys_clk.common, + &sdio0_2x.common, + &sdio1_2x.common, + &sdio2_2x.common, + &emmc_2x.common, + &sdio0_1x.common, + &sdio1_1x.common, + &sdio2_1x.common, + &emmc_1x.common, + &adi_clk.common, + &pwm0_clk.common, + &pwm1_clk.common, + &pwm2_clk.common, + &pwm3_clk.common, + &efuse_clk.common, + &cm3_uart0.common, + &cm3_uart1.common, + &thm_clk.common, + &cm3_i2c0.common, + &cm3_i2c1.common, + &cm4_spi.common, + &aon_i2c.common, + &avs_clk.common, + &ca53_dap.common, + &ca53_ts.common, + &djtag_tck.common, + &pmu_clk.common, + &pmu_26m.common, + &debounce_clk.common, + &otg2_ref.common, + &usb3_ref.common, + &ap_axi.common, +}; + +static struct clk_hw_onecell_data sc9860_aon_prediv_hws = { + .hws = { + [CLK_AON_APB] = &aon_apb.common.hw, + [CLK_AUX0] = &aux0_clk.common.hw, + [CLK_AUX1] = &aux1_clk.common.hw, + [CLK_AUX2] = &aux2_clk.common.hw, + [CLK_PROBE] = &probe_clk.common.hw, + [CLK_SP_AHB] = &sp_ahb.common.hw, + [CLK_CCI] = &cci_clk.common.hw, + [CLK_GIC] = &gic_clk.common.hw, + [CLK_CSSYS] = &cssys_clk.common.hw, + [CLK_SDIO0_2X] = &sdio0_2x.common.hw, + [CLK_SDIO1_2X] = &sdio1_2x.common.hw, + [CLK_SDIO2_2X] = &sdio2_2x.common.hw, + [CLK_EMMC_2X] = &emmc_2x.common.hw, + [CLK_SDIO0_1X] = &sdio0_1x.common.hw, + [CLK_SDIO1_1X] = &sdio1_1x.common.hw, + [CLK_SDIO2_1X] = &sdio2_1x.common.hw, + [CLK_EMMC_1X] = &emmc_1x.common.hw, + [CLK_ADI] = &adi_clk.common.hw, + [CLK_PWM0] = &pwm0_clk.common.hw, + [CLK_PWM1] = &pwm1_clk.common.hw, + [CLK_PWM2] = &pwm2_clk.common.hw, + [CLK_PWM3] = &pwm3_clk.common.hw, + [CLK_EFUSE] = &efuse_clk.common.hw, + [CLK_CM3_UART0] = &cm3_uart0.common.hw, + [CLK_CM3_UART1] = &cm3_uart1.common.hw, + [CLK_THM] = &thm_clk.common.hw, + [CLK_CM3_I2C0] = &cm3_i2c0.common.hw, + [CLK_CM3_I2C1] = &cm3_i2c1.common.hw, + [CLK_CM4_SPI] = &cm4_spi.common.hw, + [CLK_AON_I2C] = &aon_i2c.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_CA53_DAP] = &ca53_dap.common.hw, + [CLK_CA53_TS] = &ca53_ts.common.hw, + [CLK_DJTAG_TCK] = &djtag_tck.common.hw, + [CLK_PMU] = &pmu_clk.common.hw, + [CLK_PMU_26M] = &pmu_26m.common.hw, + [CLK_DEBOUNCE] = &debounce_clk.common.hw, + [CLK_OTG2_REF] = &otg2_ref.common.hw, + [CLK_USB3_REF] = &usb3_ref.common.hw, + [CLK_AP_AXI] = &ap_axi.common.hw, + }, + .num = CLK_AON_PREDIV_NUM, +}; + +static const struct sprd_clk_desc sc9860_aon_prediv_desc = { + .clk_clks = sc9860_aon_prediv, + .num_clk_clks = ARRAY_SIZE(sc9860_aon_prediv), + .hw_clks = &sc9860_aon_prediv_hws, +}; + +static SPRD_GATE_CLK(usb3_eb, "usb3-eb", "ap-axi", 0x0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(usb3_suspend, "usb3-suspend", "ap-axi", 0x0, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(usb3_ref_eb, "usb3-ref-eb", "ap-axi", 0x0, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dma_eb, "dma-eb", "ap-axi", 0x0, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio0_eb, "sdio0-eb", "ap-axi", 0x0, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio1_eb, "sdio1-eb", "ap-axi", 0x0, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio2_eb, "sdio2-eb", "ap-axi", 0x0, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(emmc_eb, "emmc-eb", "ap-axi", 0x0, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rom_eb, "rom-eb", "ap-axi", 0x0, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(busmon_eb, "busmon-eb", "ap-axi", 0x0, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(cc63s_eb, "cc63s-eb", "ap-axi", 0x0, + 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(cc63p_eb, "cc63p-eb", "ap-axi", 0x0, + 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ce0_eb, "ce0-eb", "ap-axi", 0x0, + 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ce1_eb, "ce1-eb", "ap-axi", 0x0, + 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0); + +static struct sprd_clk_common *sc9860_apahb_gate[] = { + /* address base is 0x20210000 */ + &usb3_eb.common, + &usb3_suspend.common, + &usb3_ref_eb.common, + &dma_eb.common, + &sdio0_eb.common, + &sdio1_eb.common, + &sdio2_eb.common, + &emmc_eb.common, + &rom_eb.common, + &busmon_eb.common, + &cc63s_eb.common, + &cc63p_eb.common, + &ce0_eb.common, + &ce1_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_apahb_gate_hws = { + .hws = { + [CLK_USB3_EB] = &usb3_eb.common.hw, + [CLK_USB3_SUSPEND_EB] = &usb3_suspend.common.hw, + [CLK_USB3_REF_EB] = &usb3_ref_eb.common.hw, + [CLK_DMA_EB] = &dma_eb.common.hw, + [CLK_SDIO0_EB] = &sdio0_eb.common.hw, + [CLK_SDIO1_EB] = &sdio1_eb.common.hw, + [CLK_SDIO2_EB] = &sdio2_eb.common.hw, + [CLK_EMMC_EB] = &emmc_eb.common.hw, + [CLK_ROM_EB] = &rom_eb.common.hw, + [CLK_BUSMON_EB] = &busmon_eb.common.hw, + [CLK_CC63S_EB] = &cc63s_eb.common.hw, + [CLK_CC63P_EB] = &cc63p_eb.common.hw, + [CLK_CE0_EB] = &ce0_eb.common.hw, + [CLK_CE1_EB] = &ce1_eb.common.hw, + }, + .num = CLK_APAHB_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_apahb_gate_desc = { + .clk_clks = sc9860_apahb_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_apahb_gate), + .hw_clks = &sc9860_apahb_gate_hws, +}; + +static SPRD_GATE_CLK(avs_lit_eb, "avs-lit-eb", "aon-apb", 0x0, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(avs_big_eb, "avs-big-eb", "aon-apb", 0x0, + 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc5_eb, "ap-intc5-eb", "aon-apb", 0x0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpio_eb, "gpio-eb", "aon-apb", 0x0, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm0_eb, "pwm0-eb", "aon-apb", 0x0, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm1_eb, "pwm1-eb", "aon-apb", 0x0, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm2_eb, "pwm2-eb", "aon-apb", 0x0, + 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pwm3_eb, "pwm3-eb", "aon-apb", 0x0, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(kpd_eb, "kpd-eb", "aon-apb", 0x0, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_sys_eb, "aon-sys-eb", "aon-apb", 0x0, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_sys_eb, "ap-sys-eb", "aon-apb", 0x0, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_tmr_eb, "aon-tmr-eb", "aon-apb", 0x0, + 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_tmr0_eb, "ap-tmr0-eb", "aon-apb", 0x0, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(efuse_eb, "efuse-eb", "aon-apb", 0x0, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(eic_eb, "eic-eb", "aon-apb", 0x0, + 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pub1_reg_eb, "pub1-reg-eb", "aon-apb", 0x0, + 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(adi_eb, "adi-eb", "aon-apb", 0x0, + 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc0_eb, "ap-intc0-eb", "aon-apb", 0x0, + 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc1_eb, "ap-intc1-eb", "aon-apb", 0x0, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc2_eb, "ap-intc2-eb", "aon-apb", 0x0, + 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc3_eb, "ap-intc3-eb", "aon-apb", 0x0, + 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_intc4_eb, "ap-intc4-eb", "aon-apb", 0x0, + 0x1000, BIT(21), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(splk_eb, "splk-eb", "aon-apb", 0x0, + 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mspi_eb, "mspi-eb", "aon-apb", 0x0, + 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pub0_reg_eb, "pub0-reg-eb", "aon-apb", 0x0, + 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pin_eb, "pin-eb", "aon-apb", 0x0, + 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_ckg_eb, "aon-ckg-eb", "aon-apb", 0x0, + 0x1000, BIT(26), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpu_eb, "gpu-eb", "aon-apb", 0x0, + 0x1000, BIT(27), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(apcpu_ts0_eb, "apcpu-ts0-eb", "aon-apb", 0x0, + 0x1000, BIT(28), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(apcpu_ts1_eb, "apcpu-ts1-eb", "aon-apb", 0x0, + 0x1000, BIT(29), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dap_eb, "dap-eb", "aon-apb", 0x0, + 0x1000, BIT(30), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c_eb, "i2c-eb", "aon-apb", 0x0, + 0x1000, BIT(31), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(pmu_eb, "pmu-eb", "aon-apb", 0x4, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(thm_eb, "thm-eb", "aon-apb", 0x4, + 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aux0_eb, "aux0-eb", "aon-apb", 0x4, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aux1_eb, "aux1-eb", "aon-apb", 0x4, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aux2_eb, "aux2-eb", "aon-apb", 0x4, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(probe_eb, "probe-eb", "aon-apb", 0x4, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpu0_avs_eb, "gpu0-avs-eb", "aon-apb", 0x4, + 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gpu1_avs_eb, "gpu1-avs-eb", "aon-apb", 0x4, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(apcpu_wdg_eb, "apcpu-wdg-eb", "aon-apb", 0x4, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_tmr1_eb, "ap-tmr1-eb", "aon-apb", 0x4, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_tmr2_eb, "ap-tmr2-eb", "aon-apb", 0x4, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(disp_emc_eb, "disp-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(zip_emc_eb, "zip-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(gsp_emc_eb, "gsp-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(osc_aon_eb, "osc-aon-eb", "aon-apb", 0x4, + 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(lvds_trx_eb, "lvds-trx-eb", "aon-apb", 0x4, + 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(lvds_tcxo_eb, "lvds-tcxo-eb", "aon-apb", 0x4, + 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mdar_eb, "mdar-eb", "aon-apb", 0x4, + 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rtc4m0_cal_eb, "rtc4m0-cal-eb", "aon-apb", 0x4, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(rct100m_cal_eb, "rct100m-cal-eb", "aon-apb", 0x4, + 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(djtag_eb, "djtag-eb", "aon-apb", 0x4, + 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(mbox_eb, "mbox-eb", "aon-apb", 0x4, + 0x1000, BIT(21), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_dma_eb, "aon-dma-eb", "aon-apb", 0x4, + 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dbg_emc_eb, "dbg-emc-eb", "aon-apb", 0x4, + 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(lvds_pll_div_en, "lvds-pll-div-en", "aon-apb", 0x4, + 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(def_eb, "def-eb", "aon-apb", 0x4, + 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(aon_apb_rsv0, "aon-apb-rsv0", "aon-apb", 0x4, + 0x1000, BIT(26), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(orp_jtag_eb, "orp-jtag-eb", "aon-apb", 0x4, + 0x1000, BIT(27), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(vsp_eb, "vsp-eb", "aon-apb", 0x4, + 0x1000, BIT(28), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(cam_eb, "cam-eb", "aon-apb", 0x4, + 0x1000, BIT(29), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(disp_eb, "disp-eb", "aon-apb", 0x4, + 0x1000, BIT(30), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(dbg_axi_if_eb, "dbg-axi-if-eb", "aon-apb", 0x4, + 0x1000, BIT(31), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(sdio0_2x_en, "sdio0-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(sdio1_2x_en, "sdio1-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(sdio2_2x_en, "sdio2-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(emmc_2x_en, "emmc-2x-en", "aon-apb", 0x13c, + 0x1000, BIT(9), 0, 0); + +static struct sprd_clk_common *sc9860_aon_gate[] = { + /* address base is 0x402e0000 */ + &avs_lit_eb.common, + &avs_big_eb.common, + &ap_intc5_eb.common, + &gpio_eb.common, + &pwm0_eb.common, + &pwm1_eb.common, + &pwm2_eb.common, + &pwm3_eb.common, + &kpd_eb.common, + &aon_sys_eb.common, + &ap_sys_eb.common, + &aon_tmr_eb.common, + &ap_tmr0_eb.common, + &efuse_eb.common, + &eic_eb.common, + &pub1_reg_eb.common, + &adi_eb.common, + &ap_intc0_eb.common, + &ap_intc1_eb.common, + &ap_intc2_eb.common, + &ap_intc3_eb.common, + &ap_intc4_eb.common, + &splk_eb.common, + &mspi_eb.common, + &pub0_reg_eb.common, + &pin_eb.common, + &aon_ckg_eb.common, + &gpu_eb.common, + &apcpu_ts0_eb.common, + &apcpu_ts1_eb.common, + &dap_eb.common, + &i2c_eb.common, + &pmu_eb.common, + &thm_eb.common, + &aux0_eb.common, + &aux1_eb.common, + &aux2_eb.common, + &probe_eb.common, + &gpu0_avs_eb.common, + &gpu1_avs_eb.common, + &apcpu_wdg_eb.common, + &ap_tmr1_eb.common, + &ap_tmr2_eb.common, + &disp_emc_eb.common, + &zip_emc_eb.common, + &gsp_emc_eb.common, + &osc_aon_eb.common, + &lvds_trx_eb.common, + &lvds_tcxo_eb.common, + &mdar_eb.common, + &rtc4m0_cal_eb.common, + &rct100m_cal_eb.common, + &djtag_eb.common, + &mbox_eb.common, + &aon_dma_eb.common, + &dbg_emc_eb.common, + &lvds_pll_div_en.common, + &def_eb.common, + &aon_apb_rsv0.common, + &orp_jtag_eb.common, + &vsp_eb.common, + &cam_eb.common, + &disp_eb.common, + &dbg_axi_if_eb.common, + &sdio0_2x_en.common, + &sdio1_2x_en.common, + &sdio2_2x_en.common, + &emmc_2x_en.common, +}; + +static struct clk_hw_onecell_data sc9860_aon_gate_hws = { + .hws = { + [CLK_AVS_LIT_EB] = &avs_lit_eb.common.hw, + [CLK_AVS_BIG_EB] = &avs_big_eb.common.hw, + [CLK_AP_INTC5_EB] = &ap_intc5_eb.common.hw, + [CLK_GPIO_EB] = &gpio_eb.common.hw, + [CLK_PWM0_EB] = &pwm0_eb.common.hw, + [CLK_PWM1_EB] = &pwm1_eb.common.hw, + [CLK_PWM2_EB] = &pwm2_eb.common.hw, + [CLK_PWM3_EB] = &pwm3_eb.common.hw, + [CLK_KPD_EB] = &kpd_eb.common.hw, + [CLK_AON_SYS_EB] = &aon_sys_eb.common.hw, + [CLK_AP_SYS_EB] = &ap_sys_eb.common.hw, + [CLK_AON_TMR_EB] = &aon_tmr_eb.common.hw, + [CLK_AP_TMR0_EB] = &ap_tmr0_eb.common.hw, + [CLK_EFUSE_EB] = &efuse_eb.common.hw, + [CLK_EIC_EB] = &eic_eb.common.hw, + [CLK_PUB1_REG_EB] = &pub1_reg_eb.common.hw, + [CLK_ADI_EB] = &adi_eb.common.hw, + [CLK_AP_INTC0_EB] = &ap_intc0_eb.common.hw, + [CLK_AP_INTC1_EB] = &ap_intc1_eb.common.hw, + [CLK_AP_INTC2_EB] = &ap_intc2_eb.common.hw, + [CLK_AP_INTC3_EB] = &ap_intc3_eb.common.hw, + [CLK_AP_INTC4_EB] = &ap_intc4_eb.common.hw, + [CLK_SPLK_EB] = &splk_eb.common.hw, + [CLK_MSPI_EB] = &mspi_eb.common.hw, + [CLK_PUB0_REG_EB] = &pub0_reg_eb.common.hw, + [CLK_PIN_EB] = &pin_eb.common.hw, + [CLK_AON_CKG_EB] = &aon_ckg_eb.common.hw, + [CLK_GPU_EB] = &gpu_eb.common.hw, + [CLK_APCPU_TS0_EB] = &apcpu_ts0_eb.common.hw, + [CLK_APCPU_TS1_EB] = &apcpu_ts1_eb.common.hw, + [CLK_DAP_EB] = &dap_eb.common.hw, + [CLK_I2C_EB] = &i2c_eb.common.hw, + [CLK_PMU_EB] = &pmu_eb.common.hw, + [CLK_THM_EB] = &thm_eb.common.hw, + [CLK_AUX0_EB] = &aux0_eb.common.hw, + [CLK_AUX1_EB] = &aux1_eb.common.hw, + [CLK_AUX2_EB] = &aux2_eb.common.hw, + [CLK_PROBE_EB] = &probe_eb.common.hw, + [CLK_GPU0_AVS_EB] = &gpu0_avs_eb.common.hw, + [CLK_GPU1_AVS_EB] = &gpu1_avs_eb.common.hw, + [CLK_APCPU_WDG_EB] = &apcpu_wdg_eb.common.hw, + [CLK_AP_TMR1_EB] = &ap_tmr1_eb.common.hw, + [CLK_AP_TMR2_EB] = &ap_tmr2_eb.common.hw, + [CLK_DISP_EMC_EB] = &disp_emc_eb.common.hw, + [CLK_ZIP_EMC_EB] = &zip_emc_eb.common.hw, + [CLK_GSP_EMC_EB] = &gsp_emc_eb.common.hw, + [CLK_OSC_AON_EB] = &osc_aon_eb.common.hw, + [CLK_LVDS_TRX_EB] = &lvds_trx_eb.common.hw, + [CLK_LVDS_TCXO_EB] = &lvds_tcxo_eb.common.hw, + [CLK_MDAR_EB] = &mdar_eb.common.hw, + [CLK_RTC4M0_CAL_EB] = &rtc4m0_cal_eb.common.hw, + [CLK_RCT100M_CAL_EB] = &rct100m_cal_eb.common.hw, + [CLK_DJTAG_EB] = &djtag_eb.common.hw, + [CLK_MBOX_EB] = &mbox_eb.common.hw, + [CLK_AON_DMA_EB] = &aon_dma_eb.common.hw, + [CLK_DBG_EMC_EB] = &dbg_emc_eb.common.hw, + [CLK_LVDS_PLL_DIV_EN] = &lvds_pll_div_en.common.hw, + [CLK_DEF_EB] = &def_eb.common.hw, + [CLK_AON_APB_RSV0] = &aon_apb_rsv0.common.hw, + [CLK_ORP_JTAG_EB] = &orp_jtag_eb.common.hw, + [CLK_VSP_EB] = &vsp_eb.common.hw, + [CLK_CAM_EB] = &cam_eb.common.hw, + [CLK_DISP_EB] = &disp_eb.common.hw, + [CLK_DBG_AXI_IF_EB] = &dbg_axi_if_eb.common.hw, + [CLK_SDIO0_2X_EN] = &sdio0_2x_en.common.hw, + [CLK_SDIO1_2X_EN] = &sdio1_2x_en.common.hw, + [CLK_SDIO2_2X_EN] = &sdio2_2x_en.common.hw, + [CLK_EMMC_2X_EN] = &emmc_2x_en.common.hw, + }, + .num = CLK_AON_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_aon_gate_desc = { + .clk_clks = sc9860_aon_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_aon_gate), + .hw_clks = &sc9860_aon_gate_hws, +}; + +static const u8 mcu_table[] = { 0, 1, 2, 3, 4, 8 }; +static const char * const lit_mcu_parents[] = { "ext-26m", "twpll-512m", + "twpll-768m", "ltepll0", + "twpll", "mpll0" }; +static SPRD_COMP_CLK(lit_mcu, "lit-mcu", lit_mcu_parents, 0x20, + mcu_table, 0, 4, 4, 3, 0); + +static const char * const big_mcu_parents[] = { "ext-26m", "twpll-512m", + "twpll-768m", "ltepll0", + "twpll", "mpll1" }; +static SPRD_COMP_CLK(big_mcu, "big-mcu", big_mcu_parents, 0x24, + mcu_table, 0, 4, 4, 3, 0); + +static struct sprd_clk_common *sc9860_aonsecure_clk[] = { + /* address base is 0x40880000 */ + &lit_mcu.common, + &big_mcu.common, +}; + +static struct clk_hw_onecell_data sc9860_aonsecure_clk_hws = { + .hws = { + [CLK_LIT_MCU] = &lit_mcu.common.hw, + [CLK_BIG_MCU] = &big_mcu.common.hw, + }, + .num = CLK_AONSECURE_NUM, +}; + +static const struct sprd_clk_desc sc9860_aonsecure_clk_desc = { + .clk_clks = sc9860_aonsecure_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_aonsecure_clk), + .hw_clks = &sc9860_aonsecure_clk_hws, +}; + +static SPRD_GATE_CLK(agcp_iis0_eb, "agcp-iis0-eb", "aon-apb", + 0x0, 0x100, BIT(0), 0, 0); +static SPRD_GATE_CLK(agcp_iis1_eb, "agcp-iis1-eb", "aon-apb", + 0x0, 0x100, BIT(1), 0, 0); +static SPRD_GATE_CLK(agcp_iis2_eb, "agcp-iis2-eb", "aon-apb", + 0x0, 0x100, BIT(2), 0, 0); +static SPRD_GATE_CLK(agcp_iis3_eb, "agcp-iis3-eb", "aon-apb", + 0x0, 0x100, BIT(3), 0, 0); +static SPRD_GATE_CLK(agcp_uart_eb, "agcp-uart-eb", "aon-apb", + 0x0, 0x100, BIT(4), 0, 0); +static SPRD_GATE_CLK(agcp_dmacp_eb, "agcp-dmacp-eb", "aon-apb", + 0x0, 0x100, BIT(5), 0, 0); +static SPRD_GATE_CLK(agcp_dmaap_eb, "agcp-dmaap-eb", "aon-apb", + 0x0, 0x100, BIT(6), 0, 0); +static SPRD_GATE_CLK(agcp_arc48k_eb, "agcp-arc48k-eb", "aon-apb", + 0x0, 0x100, BIT(10), 0, 0); +static SPRD_GATE_CLK(agcp_src44p1k_eb, "agcp-src44p1k-eb", "aon-apb", + 0x0, 0x100, BIT(11), 0, 0); +static SPRD_GATE_CLK(agcp_mcdt_eb, "agcp-mcdt-eb", "aon-apb", + 0x0, 0x100, BIT(12), 0, 0); +static SPRD_GATE_CLK(agcp_vbcifd_eb, "agcp-vbcifd-eb", "aon-apb", + 0x0, 0x100, BIT(13), 0, 0); +static SPRD_GATE_CLK(agcp_vbc_eb, "agcp-vbc-eb", "aon-apb", + 0x0, 0x100, BIT(14), 0, 0); +static SPRD_GATE_CLK(agcp_spinlock_eb, "agcp-spinlock-eb", "aon-apb", + 0x0, 0x100, BIT(15), 0, 0); +static SPRD_GATE_CLK(agcp_icu_eb, "agcp-icu-eb", "aon-apb", + 0x0, 0x100, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(agcp_ap_ashb_eb, "agcp-ap-ashb-eb", "aon-apb", + 0x0, 0x100, BIT(17), 0, 0); +static SPRD_GATE_CLK(agcp_cp_ashb_eb, "agcp-cp-ashb-eb", "aon-apb", + 0x0, 0x100, BIT(18), 0, 0); +static SPRD_GATE_CLK(agcp_aud_eb, "agcp-aud-eb", "aon-apb", + 0x0, 0x100, BIT(19), 0, 0); +static SPRD_GATE_CLK(agcp_audif_eb, "agcp-audif-eb", "aon-apb", + 0x0, 0x100, BIT(20), 0, 0); + +static struct sprd_clk_common *sc9860_agcp_gate[] = { + /* address base is 0x415e0000 */ + &agcp_iis0_eb.common, + &agcp_iis1_eb.common, + &agcp_iis2_eb.common, + &agcp_iis3_eb.common, + &agcp_uart_eb.common, + &agcp_dmacp_eb.common, + &agcp_dmaap_eb.common, + &agcp_arc48k_eb.common, + &agcp_src44p1k_eb.common, + &agcp_mcdt_eb.common, + &agcp_vbcifd_eb.common, + &agcp_vbc_eb.common, + &agcp_spinlock_eb.common, + &agcp_icu_eb.common, + &agcp_ap_ashb_eb.common, + &agcp_cp_ashb_eb.common, + &agcp_aud_eb.common, + &agcp_audif_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_agcp_gate_hws = { + .hws = { + [CLK_AGCP_IIS0_EB] = &agcp_iis0_eb.common.hw, + [CLK_AGCP_IIS1_EB] = &agcp_iis1_eb.common.hw, + [CLK_AGCP_IIS2_EB] = &agcp_iis2_eb.common.hw, + [CLK_AGCP_IIS3_EB] = &agcp_iis3_eb.common.hw, + [CLK_AGCP_UART_EB] = &agcp_uart_eb.common.hw, + [CLK_AGCP_DMACP_EB] = &agcp_dmacp_eb.common.hw, + [CLK_AGCP_DMAAP_EB] = &agcp_dmaap_eb.common.hw, + [CLK_AGCP_ARC48K_EB] = &agcp_arc48k_eb.common.hw, + [CLK_AGCP_SRC44P1K_EB] = &agcp_src44p1k_eb.common.hw, + [CLK_AGCP_MCDT_EB] = &agcp_mcdt_eb.common.hw, + [CLK_AGCP_VBCIFD_EB] = &agcp_vbcifd_eb.common.hw, + [CLK_AGCP_VBC_EB] = &agcp_vbc_eb.common.hw, + [CLK_AGCP_SPINLOCK_EB] = &agcp_spinlock_eb.common.hw, + [CLK_AGCP_ICU_EB] = &agcp_icu_eb.common.hw, + [CLK_AGCP_AP_ASHB_EB] = &agcp_ap_ashb_eb.common.hw, + [CLK_AGCP_CP_ASHB_EB] = &agcp_cp_ashb_eb.common.hw, + [CLK_AGCP_AUD_EB] = &agcp_aud_eb.common.hw, + [CLK_AGCP_AUDIF_EB] = &agcp_audif_eb.common.hw, + }, + .num = CLK_AGCP_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_agcp_gate_desc = { + .clk_clks = sc9860_agcp_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_agcp_gate), + .hw_clks = &sc9860_agcp_gate_hws, +}; + +static const char * const gpu_parents[] = { "twpll-512m", + "twpll-768m", + "gpll" }; +static SPRD_COMP_CLK(gpu_clk, "gpu", gpu_parents, 0x20, + 0, 0, 2, 8, 4, 0); + +static struct sprd_clk_common *sc9860_gpu_clk[] = { + /* address base is 0x60200000 */ + &gpu_clk.common, +}; + +static struct clk_hw_onecell_data sc9860_gpu_clk_hws = { + .hws = { + [CLK_GPU] = &gpu_clk.common.hw, + }, + .num = CLK_GPU_NUM, +}; + +static const struct sprd_clk_desc sc9860_gpu_clk_desc = { + .clk_clks = sc9860_gpu_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_gpu_clk), + .hw_clks = &sc9860_gpu_clk_hws, +}; + +static const char * const ahb_parents[] = { "ext-26m", "twpll-96m", + "twpll-128m", "twpll-153m6" }; +static SPRD_MUX_CLK(ahb_vsp, "ahb-vsp", ahb_parents, NULL, + 0x20, 0, 2, SC9860_MUX_FLAG); + +static const char * const vsp_parents[] = { "twpll-76m8", "twpll-128m", + "twpll-256m", "twpll-307m2", + "twpll-384m" }; +static SPRD_COMP_CLK(vsp_clk, "vsp", vsp_parents, 0x24, 0, 0, 3, 8, 2, 0); + +static const char * const dispc_parents[] = { "twpll-76m8", "twpll-128m", + "twpll-256m", "twpll-307m2" }; +static SPRD_COMP_CLK(vsp_enc, "vsp-enc", dispc_parents, 0x28, 0, 0, 2, 8, 2, 0); + +static const char * const vpp_parents[] = { "twpll-96m", "twpll-153m6", + "twpll-192m", "twpll-256m" }; +static SPRD_MUX_CLK(vpp_clk, "vpp", vpp_parents, NULL, 0x2c, + 0, 2, SC9860_MUX_FLAG); +static const char * const vsp_26m_parents[] = { "ext-26m" }; +static SPRD_MUX_CLK(vsp_26m, "vsp-26m", vsp_26m_parents, NULL, 0x30, + 0, 1, SC9860_MUX_FLAG); + +static struct sprd_clk_common *sc9860_vsp_clk[] = { + /* address base is 0x61000000 */ + &ahb_vsp.common, + &vsp_clk.common, + &vsp_enc.common, + &vpp_clk.common, + &vsp_26m.common, +}; + +static struct clk_hw_onecell_data sc9860_vsp_clk_hws = { + .hws = { + [CLK_AHB_VSP] = &ahb_vsp.common.hw, + [CLK_VSP] = &vsp_clk.common.hw, + [CLK_VSP_ENC] = &vsp_enc.common.hw, + [CLK_VPP] = &vpp_clk.common.hw, + [CLK_VSP_26M] = &vsp_26m.common.hw, + }, + .num = CLK_VSP_NUM, +}; + +static const struct sprd_clk_desc sc9860_vsp_clk_desc = { + .clk_clks = sc9860_vsp_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_vsp_clk), + .hw_clks = &sc9860_vsp_clk_hws, +}; + +static SPRD_GATE_CLK(vsp_dec_eb, "vsp-dec-eb", "ahb-vsp", 0x0, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(vsp_ckg_eb, "vsp-ckg-eb", "ahb-vsp", 0x0, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(vsp_mmu_eb, "vsp-mmu-eb", "ahb-vsp", 0x0, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(vsp_enc_eb, "vsp-enc-eb", "ahb-vsp", 0x0, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(vpp_eb, "vpp-eb", "ahb-vsp", 0x0, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(vsp_26m_eb, "vsp-26m-eb", "ahb-vsp", 0x0, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(vsp_axi_gate, "vsp-axi-gate", "ahb-vsp", 0x8, + 0, BIT(0), 0, 0); +static SPRD_GATE_CLK(vsp_enc_gate, "vsp-enc-gate", "ahb-vsp", 0x8, + 0, BIT(1), 0, 0); +static SPRD_GATE_CLK(vpp_axi_gate, "vpp-axi-gate", "ahb-vsp", 0x8, + 0, BIT(2), 0, 0); +static SPRD_GATE_CLK(vsp_bm_gate, "vsp-bm-gate", "ahb-vsp", 0x8, + 0, BIT(8), 0, 0); +static SPRD_GATE_CLK(vsp_enc_bm_gate, "vsp-enc-bm-gate", "ahb-vsp", 0x8, + 0, BIT(9), 0, 0); +static SPRD_GATE_CLK(vpp_bm_gate, "vpp-bm-gate", "ahb-vsp", 0x8, + 0, BIT(10), 0, 0); + +static struct sprd_clk_common *sc9860_vsp_gate[] = { + /* address base is 0x61100000 */ + &vsp_dec_eb.common, + &vsp_ckg_eb.common, + &vsp_mmu_eb.common, + &vsp_enc_eb.common, + &vpp_eb.common, + &vsp_26m_eb.common, + &vsp_axi_gate.common, + &vsp_enc_gate.common, + &vpp_axi_gate.common, + &vsp_bm_gate.common, + &vsp_enc_bm_gate.common, + &vpp_bm_gate.common, +}; + +static struct clk_hw_onecell_data sc9860_vsp_gate_hws = { + .hws = { + [CLK_VSP_DEC_EB] = &vsp_dec_eb.common.hw, + [CLK_VSP_CKG_EB] = &vsp_ckg_eb.common.hw, + [CLK_VSP_MMU_EB] = &vsp_mmu_eb.common.hw, + [CLK_VSP_ENC_EB] = &vsp_enc_eb.common.hw, + [CLK_VPP_EB] = &vpp_eb.common.hw, + [CLK_VSP_26M_EB] = &vsp_26m_eb.common.hw, + [CLK_VSP_AXI_GATE] = &vsp_axi_gate.common.hw, + [CLK_VSP_ENC_GATE] = &vsp_enc_gate.common.hw, + [CLK_VPP_AXI_GATE] = &vpp_axi_gate.common.hw, + [CLK_VSP_BM_GATE] = &vsp_bm_gate.common.hw, + [CLK_VSP_ENC_BM_GATE] = &vsp_enc_bm_gate.common.hw, + [CLK_VPP_BM_GATE] = &vpp_bm_gate.common.hw, + }, + .num = CLK_VSP_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_vsp_gate_desc = { + .clk_clks = sc9860_vsp_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_vsp_gate), + .hw_clks = &sc9860_vsp_gate_hws, +}; + +static SPRD_MUX_CLK(ahb_cam, "ahb-cam", ahb_parents, NULL, + 0x20, 0, 2, SC9860_MUX_FLAG); +static const char * const sensor_parents[] = { "ext-26m", "twpll-48m", + "twpll-76m8", "twpll-96m" }; +static SPRD_COMP_CLK(sensor0_clk, "sensor0", sensor_parents, 0x24, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(sensor1_clk, "sensor1", sensor_parents, 0x28, + 0, 0, 2, 8, 3, 0); +static SPRD_COMP_CLK(sensor2_clk, "sensor2", sensor_parents, 0x2c, + 0, 0, 2, 8, 3, 0); +static SPRD_GATE_CLK(mipi_csi0_eb, "mipi-csi0-eb", "ahb-cam", 0x4c, + 0, BIT(16), 0, 0); +static SPRD_GATE_CLK(mipi_csi1_eb, "mipi-csi1-eb", "ahb-cam", 0x50, + 0, BIT(16), 0, 0); + +static struct sprd_clk_common *sc9860_cam_clk[] = { + /* address base is 0x62000000 */ + &ahb_cam.common, + &sensor0_clk.common, + &sensor1_clk.common, + &sensor2_clk.common, + &mipi_csi0_eb.common, + &mipi_csi1_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_cam_clk_hws = { + .hws = { + [CLK_AHB_CAM] = &ahb_cam.common.hw, + [CLK_SENSOR0] = &sensor0_clk.common.hw, + [CLK_SENSOR1] = &sensor1_clk.common.hw, + [CLK_SENSOR2] = &sensor2_clk.common.hw, + [CLK_MIPI_CSI0_EB] = &mipi_csi0_eb.common.hw, + [CLK_MIPI_CSI1_EB] = &mipi_csi1_eb.common.hw, + }, + .num = CLK_CAM_NUM, +}; + +static const struct sprd_clk_desc sc9860_cam_clk_desc = { + .clk_clks = sc9860_cam_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_cam_clk), + .hw_clks = &sc9860_cam_clk_hws, +}; + +static SPRD_GATE_CLK(dcam0_eb, "dcam0-eb", "ahb-cam", 0x0, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(dcam1_eb, "dcam1-eb", "ahb-cam", 0x0, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(isp0_eb, "isp0-eb", "ahb-cam", 0x0, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(csi0_eb, "csi0-eb", "ahb-cam", 0x0, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(csi1_eb, "csi1-eb", "ahb-cam", 0x0, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(jpg0_eb, "jpg0-eb", "ahb-cam", 0x0, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(jpg1_eb, "jpg1-eb", "ahb-cam", 0x0, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(cam_ckg_eb, "cam-ckg-eb", "ahb-cam", 0x0, + 0x1000, BIT(7), 0, 0); +static SPRD_GATE_CLK(cam_mmu_eb, "cam-mmu-eb", "ahb-cam", 0x0, + 0x1000, BIT(8), 0, 0); +static SPRD_GATE_CLK(isp1_eb, "isp1-eb", "ahb-cam", 0x0, + 0x1000, BIT(9), 0, 0); +static SPRD_GATE_CLK(cpp_eb, "cpp-eb", "ahb-cam", 0x0, + 0x1000, BIT(10), 0, 0); +static SPRD_GATE_CLK(mmu_pf_eb, "mmu-pf-eb", "ahb-cam", 0x0, + 0x1000, BIT(11), 0, 0); +static SPRD_GATE_CLK(isp2_eb, "isp2-eb", "ahb-cam", 0x0, + 0x1000, BIT(12), 0, 0); +static SPRD_GATE_CLK(dcam2isp_if_eb, "dcam2isp-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(13), 0, 0); +static SPRD_GATE_CLK(isp2dcam_if_eb, "isp2dcam-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(14), 0, 0); +static SPRD_GATE_CLK(isp_lclk_eb, "isp-lclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(15), 0, 0); +static SPRD_GATE_CLK(isp_iclk_eb, "isp-iclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(16), 0, 0); +static SPRD_GATE_CLK(isp_mclk_eb, "isp-mclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(17), 0, 0); +static SPRD_GATE_CLK(isp_pclk_eb, "isp-pclk-eb", "ahb-cam", 0x0, + 0x1000, BIT(18), 0, 0); +static SPRD_GATE_CLK(isp_isp2dcam_eb, "isp-isp2dcam-eb", "ahb-cam", 0x0, + 0x1000, BIT(19), 0, 0); +static SPRD_GATE_CLK(dcam0_if_eb, "dcam0-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(20), 0, 0); +static SPRD_GATE_CLK(clk26m_if_eb, "clk26m-if-eb", "ahb-cam", 0x0, + 0x1000, BIT(21), 0, 0); +static SPRD_GATE_CLK(cphy0_gate, "cphy0-gate", "ahb-cam", 0x8, + 0, BIT(0), 0, 0); +static SPRD_GATE_CLK(mipi_csi0_gate, "mipi-csi0-gate", "ahb-cam", 0x8, + 0, BIT(1), 0, 0); +static SPRD_GATE_CLK(cphy1_gate, "cphy1-gate", "ahb-cam", 0x8, + 0, BIT(2), 0, 0); +static SPRD_GATE_CLK(mipi_csi1, "mipi-csi1", "ahb-cam", 0x8, + 0, BIT(3), 0, 0); +static SPRD_GATE_CLK(dcam0_axi_gate, "dcam0-axi-gate", "ahb-cam", 0x8, + 0, BIT(4), 0, 0); +static SPRD_GATE_CLK(dcam1_axi_gate, "dcam1-axi-gate", "ahb-cam", 0x8, + 0, BIT(5), 0, 0); +static SPRD_GATE_CLK(sensor0_gate, "sensor0-gate", "ahb-cam", 0x8, + 0, BIT(6), 0, 0); +static SPRD_GATE_CLK(sensor1_gate, "sensor1-gate", "ahb-cam", 0x8, + 0, BIT(7), 0, 0); +static SPRD_GATE_CLK(jpg0_axi_gate, "jpg0-axi-gate", "ahb-cam", 0x8, + 0, BIT(8), 0, 0); +static SPRD_GATE_CLK(gpg1_axi_gate, "gpg1-axi-gate", "ahb-cam", 0x8, + 0, BIT(9), 0, 0); +static SPRD_GATE_CLK(isp0_axi_gate, "isp0-axi-gate", "ahb-cam", 0x8, + 0, BIT(10), 0, 0); +static SPRD_GATE_CLK(isp1_axi_gate, "isp1-axi-gate", "ahb-cam", 0x8, + 0, BIT(11), 0, 0); +static SPRD_GATE_CLK(isp2_axi_gate, "isp2-axi-gate", "ahb-cam", 0x8, + 0, BIT(12), 0, 0); +static SPRD_GATE_CLK(cpp_axi_gate, "cpp-axi-gate", "ahb-cam", 0x8, + 0, BIT(13), 0, 0); +static SPRD_GATE_CLK(d0_if_axi_gate, "d0-if-axi-gate", "ahb-cam", 0x8, + 0, BIT(14), 0, 0); +static SPRD_GATE_CLK(d2i_if_axi_gate, "d2i-if-axi-gate", "ahb-cam", 0x8, + 0, BIT(15), 0, 0); +static SPRD_GATE_CLK(i2d_if_axi_gate, "i2d-if-axi-gate", "ahb-cam", 0x8, + 0, BIT(16), 0, 0); +static SPRD_GATE_CLK(spare_axi_gate, "spare-axi-gate", "ahb-cam", 0x8, + 0, BIT(17), 0, 0); +static SPRD_GATE_CLK(sensor2_gate, "sensor2-gate", "ahb-cam", 0x8, + 0, BIT(18), 0, 0); +static SPRD_GATE_CLK(d0if_in_d_en, "d0if-in-d-en", "ahb-cam", 0x28, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(d1if_in_d_en, "d1if-in-d-en", "ahb-cam", 0x28, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(d0if_in_d2i_en, "d0if-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(d1if_in_d2i_en, "d1if-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(ia_in_d2i_en, "ia-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(ib_in_d2i_en, "ib-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(ic_in_d2i_en, "ic-in-d2i-en", "ahb-cam", 0x28, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(ia_in_i_en, "ia-in-i-en", "ahb-cam", 0x28, + 0x1000, BIT(7), 0, 0); +static SPRD_GATE_CLK(ib_in_i_en, "ib-in-i-en", "ahb-cam", 0x28, + 0x1000, BIT(8), 0, 0); +static SPRD_GATE_CLK(ic_in_i_en, "ic-in-i-en", "ahb-cam", 0x28, + 0x1000, BIT(9), 0, 0); + +static struct sprd_clk_common *sc9860_cam_gate[] = { + /* address base is 0x62100000 */ + &dcam0_eb.common, + &dcam1_eb.common, + &isp0_eb.common, + &csi0_eb.common, + &csi1_eb.common, + &jpg0_eb.common, + &jpg1_eb.common, + &cam_ckg_eb.common, + &cam_mmu_eb.common, + &isp1_eb.common, + &cpp_eb.common, + &mmu_pf_eb.common, + &isp2_eb.common, + &dcam2isp_if_eb.common, + &isp2dcam_if_eb.common, + &isp_lclk_eb.common, + &isp_iclk_eb.common, + &isp_mclk_eb.common, + &isp_pclk_eb.common, + &isp_isp2dcam_eb.common, + &dcam0_if_eb.common, + &clk26m_if_eb.common, + &cphy0_gate.common, + &mipi_csi0_gate.common, + &cphy1_gate.common, + &mipi_csi1.common, + &dcam0_axi_gate.common, + &dcam1_axi_gate.common, + &sensor0_gate.common, + &sensor1_gate.common, + &jpg0_axi_gate.common, + &gpg1_axi_gate.common, + &isp0_axi_gate.common, + &isp1_axi_gate.common, + &isp2_axi_gate.common, + &cpp_axi_gate.common, + &d0_if_axi_gate.common, + &d2i_if_axi_gate.common, + &i2d_if_axi_gate.common, + &spare_axi_gate.common, + &sensor2_gate.common, + &d0if_in_d_en.common, + &d1if_in_d_en.common, + &d0if_in_d2i_en.common, + &d1if_in_d2i_en.common, + &ia_in_d2i_en.common, + &ib_in_d2i_en.common, + &ic_in_d2i_en.common, + &ia_in_i_en.common, + &ib_in_i_en.common, + &ic_in_i_en.common, +}; + +static struct clk_hw_onecell_data sc9860_cam_gate_hws = { + .hws = { + [CLK_DCAM0_EB] = &dcam0_eb.common.hw, + [CLK_DCAM1_EB] = &dcam1_eb.common.hw, + [CLK_ISP0_EB] = &isp0_eb.common.hw, + [CLK_CSI0_EB] = &csi0_eb.common.hw, + [CLK_CSI1_EB] = &csi1_eb.common.hw, + [CLK_JPG0_EB] = &jpg0_eb.common.hw, + [CLK_JPG1_EB] = &jpg1_eb.common.hw, + [CLK_CAM_CKG_EB] = &cam_ckg_eb.common.hw, + [CLK_CAM_MMU_EB] = &cam_mmu_eb.common.hw, + [CLK_ISP1_EB] = &isp1_eb.common.hw, + [CLK_CPP_EB] = &cpp_eb.common.hw, + [CLK_MMU_PF_EB] = &mmu_pf_eb.common.hw, + [CLK_ISP2_EB] = &isp2_eb.common.hw, + [CLK_DCAM2ISP_IF_EB] = &dcam2isp_if_eb.common.hw, + [CLK_ISP2DCAM_IF_EB] = &isp2dcam_if_eb.common.hw, + [CLK_ISP_LCLK_EB] = &isp_lclk_eb.common.hw, + [CLK_ISP_ICLK_EB] = &isp_iclk_eb.common.hw, + [CLK_ISP_MCLK_EB] = &isp_mclk_eb.common.hw, + [CLK_ISP_PCLK_EB] = &isp_pclk_eb.common.hw, + [CLK_ISP_ISP2DCAM_EB] = &isp_isp2dcam_eb.common.hw, + [CLK_DCAM0_IF_EB] = &dcam0_if_eb.common.hw, + [CLK_CLK26M_IF_EB] = &clk26m_if_eb.common.hw, + [CLK_CPHY0_GATE] = &cphy0_gate.common.hw, + [CLK_MIPI_CSI0_GATE] = &mipi_csi0_gate.common.hw, + [CLK_CPHY1_GATE] = &cphy1_gate.common.hw, + [CLK_MIPI_CSI1] = &mipi_csi1.common.hw, + [CLK_DCAM0_AXI_GATE] = &dcam0_axi_gate.common.hw, + [CLK_DCAM1_AXI_GATE] = &dcam1_axi_gate.common.hw, + [CLK_SENSOR0_GATE] = &sensor0_gate.common.hw, + [CLK_SENSOR1_GATE] = &sensor1_gate.common.hw, + [CLK_JPG0_AXI_GATE] = &jpg0_axi_gate.common.hw, + [CLK_GPG1_AXI_GATE] = &gpg1_axi_gate.common.hw, + [CLK_ISP0_AXI_GATE] = &isp0_axi_gate.common.hw, + [CLK_ISP1_AXI_GATE] = &isp1_axi_gate.common.hw, + [CLK_ISP2_AXI_GATE] = &isp2_axi_gate.common.hw, + [CLK_CPP_AXI_GATE] = &cpp_axi_gate.common.hw, + [CLK_D0_IF_AXI_GATE] = &d0_if_axi_gate.common.hw, + [CLK_D2I_IF_AXI_GATE] = &d2i_if_axi_gate.common.hw, + [CLK_I2D_IF_AXI_GATE] = &i2d_if_axi_gate.common.hw, + [CLK_SPARE_AXI_GATE] = &spare_axi_gate.common.hw, + [CLK_SENSOR2_GATE] = &sensor2_gate.common.hw, + [CLK_D0IF_IN_D_EN] = &d0if_in_d_en.common.hw, + [CLK_D1IF_IN_D_EN] = &d1if_in_d_en.common.hw, + [CLK_D0IF_IN_D2I_EN] = &d0if_in_d2i_en.common.hw, + [CLK_D1IF_IN_D2I_EN] = &d1if_in_d2i_en.common.hw, + [CLK_IA_IN_D2I_EN] = &ia_in_d2i_en.common.hw, + [CLK_IB_IN_D2I_EN] = &ib_in_d2i_en.common.hw, + [CLK_IC_IN_D2I_EN] = &ic_in_d2i_en.common.hw, + [CLK_IA_IN_I_EN] = &ia_in_i_en.common.hw, + [CLK_IB_IN_I_EN] = &ib_in_i_en.common.hw, + [CLK_IC_IN_I_EN] = &ic_in_i_en.common.hw, + }, + .num = CLK_CAM_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_cam_gate_desc = { + .clk_clks = sc9860_cam_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_cam_gate), + .hw_clks = &sc9860_cam_gate_hws, +}; + +static SPRD_MUX_CLK(ahb_disp, "ahb-disp", ahb_parents, NULL, 0x20, + 0, 2, SC9860_MUX_FLAG); +static SPRD_COMP_CLK(dispc0_dpi, "dispc0-dpi", dispc_parents, 0x34, + 0, 0, 2, 8, 2, 0); +static SPRD_COMP_CLK(dispc1_dpi, "dispc1-dpi", dispc_parents, 0x40, + 0, 0, 2, 8, 2, 0); + +static struct sprd_clk_common *sc9860_disp_clk[] = { + /* address base is 0x63000000 */ + &ahb_disp.common, + &dispc0_dpi.common, + &dispc1_dpi.common, +}; + +static struct clk_hw_onecell_data sc9860_disp_clk_hws = { + .hws = { + [CLK_AHB_DISP] = &ahb_disp.common.hw, + [CLK_DISPC0_DPI] = &dispc0_dpi.common.hw, + [CLK_DISPC1_DPI] = &dispc1_dpi.common.hw, + }, + .num = CLK_DISP_NUM, +}; + +static const struct sprd_clk_desc sc9860_disp_clk_desc = { + .clk_clks = sc9860_disp_clk, + .num_clk_clks = ARRAY_SIZE(sc9860_disp_clk), + .hw_clks = &sc9860_disp_clk_hws, +}; + +static SPRD_GATE_CLK(dispc0_eb, "dispc0-eb", "ahb-disp", 0x0, + 0x1000, BIT(0), 0, 0); +static SPRD_GATE_CLK(dispc1_eb, "dispc1-eb", "ahb-disp", 0x0, + 0x1000, BIT(1), 0, 0); +static SPRD_GATE_CLK(dispc_mmu_eb, "dispc-mmu-eb", "ahb-disp", 0x0, + 0x1000, BIT(2), 0, 0); +static SPRD_GATE_CLK(gsp0_eb, "gsp0-eb", "ahb-disp", 0x0, + 0x1000, BIT(3), 0, 0); +static SPRD_GATE_CLK(gsp1_eb, "gsp1-eb", "ahb-disp", 0x0, + 0x1000, BIT(4), 0, 0); +static SPRD_GATE_CLK(gsp0_mmu_eb, "gsp0-mmu-eb", "ahb-disp", 0x0, + 0x1000, BIT(5), 0, 0); +static SPRD_GATE_CLK(gsp1_mmu_eb, "gsp1-mmu-eb", "ahb-disp", 0x0, + 0x1000, BIT(6), 0, 0); +static SPRD_GATE_CLK(dsi0_eb, "dsi0-eb", "ahb-disp", 0x0, + 0x1000, BIT(7), 0, 0); +static SPRD_GATE_CLK(dsi1_eb, "dsi1-eb", "ahb-disp", 0x0, + 0x1000, BIT(8), 0, 0); +static SPRD_GATE_CLK(disp_ckg_eb, "disp-ckg-eb", "ahb-disp", 0x0, + 0x1000, BIT(9), 0, 0); +static SPRD_GATE_CLK(disp_gpu_eb, "disp-gpu-eb", "ahb-disp", 0x0, + 0x1000, BIT(10), 0, 0); +static SPRD_GATE_CLK(gpu_mtx_eb, "gpu-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(13), 0, 0); +static SPRD_GATE_CLK(gsp_mtx_eb, "gsp-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(14), 0, 0); +static SPRD_GATE_CLK(tmc_mtx_eb, "tmc-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(15), 0, 0); +static SPRD_GATE_CLK(dispc_mtx_eb, "dispc-mtx-eb", "ahb-disp", 0x0, + 0x1000, BIT(16), 0, 0); +static SPRD_GATE_CLK(dphy0_gate, "dphy0-gate", "ahb-disp", 0x8, + 0, BIT(0), 0, 0); +static SPRD_GATE_CLK(dphy1_gate, "dphy1-gate", "ahb-disp", 0x8, + 0, BIT(1), 0, 0); +static SPRD_GATE_CLK(gsp0_a_gate, "gsp0-a-gate", "ahb-disp", 0x8, + 0, BIT(2), 0, 0); +static SPRD_GATE_CLK(gsp1_a_gate, "gsp1-a-gate", "ahb-disp", 0x8, + 0, BIT(3), 0, 0); +static SPRD_GATE_CLK(gsp0_f_gate, "gsp0-f-gate", "ahb-disp", 0x8, + 0, BIT(4), 0, 0); +static SPRD_GATE_CLK(gsp1_f_gate, "gsp1-f-gate", "ahb-disp", 0x8, + 0, BIT(5), 0, 0); +static SPRD_GATE_CLK(d_mtx_f_gate, "d-mtx-f-gate", "ahb-disp", 0x8, + 0, BIT(6), 0, 0); +static SPRD_GATE_CLK(d_mtx_a_gate, "d-mtx-a-gate", "ahb-disp", 0x8, + 0, BIT(7), 0, 0); +static SPRD_GATE_CLK(d_noc_f_gate, "d-noc-f-gate", "ahb-disp", 0x8, + 0, BIT(8), 0, 0); +static SPRD_GATE_CLK(d_noc_a_gate, "d-noc-a-gate", "ahb-disp", 0x8, + 0, BIT(9), 0, 0); +static SPRD_GATE_CLK(gsp_mtx_f_gate, "gsp-mtx-f-gate", "ahb-disp", 0x8, + 0, BIT(10), 0, 0); +static SPRD_GATE_CLK(gsp_mtx_a_gate, "gsp-mtx-a-gate", "ahb-disp", 0x8, + 0, BIT(11), 0, 0); +static SPRD_GATE_CLK(gsp_noc_f_gate, "gsp-noc-f-gate", "ahb-disp", 0x8, + 0, BIT(12), 0, 0); +static SPRD_GATE_CLK(gsp_noc_a_gate, "gsp-noc-a-gate", "ahb-disp", 0x8, + 0, BIT(13), 0, 0); +static SPRD_GATE_CLK(dispm0idle_gate, "dispm0idle-gate", "ahb-disp", 0x8, + 0, BIT(14), 0, 0); +static SPRD_GATE_CLK(gspm0idle_gate, "gspm0idle-gate", "ahb-disp", 0x8, + 0, BIT(15), 0, 0); + +static struct sprd_clk_common *sc9860_disp_gate[] = { + /* address base is 0x63100000 */ + &dispc0_eb.common, + &dispc1_eb.common, + &dispc_mmu_eb.common, + &gsp0_eb.common, + &gsp1_eb.common, + &gsp0_mmu_eb.common, + &gsp1_mmu_eb.common, + &dsi0_eb.common, + &dsi1_eb.common, + &disp_ckg_eb.common, + &disp_gpu_eb.common, + &gpu_mtx_eb.common, + &gsp_mtx_eb.common, + &tmc_mtx_eb.common, + &dispc_mtx_eb.common, + &dphy0_gate.common, + &dphy1_gate.common, + &gsp0_a_gate.common, + &gsp1_a_gate.common, + &gsp0_f_gate.common, + &gsp1_f_gate.common, + &d_mtx_f_gate.common, + &d_mtx_a_gate.common, + &d_noc_f_gate.common, + &d_noc_a_gate.common, + &gsp_mtx_f_gate.common, + &gsp_mtx_a_gate.common, + &gsp_noc_f_gate.common, + &gsp_noc_a_gate.common, + &dispm0idle_gate.common, + &gspm0idle_gate.common, +}; + +static struct clk_hw_onecell_data sc9860_disp_gate_hws = { + .hws = { + [CLK_DISPC0_EB] = &dispc0_eb.common.hw, + [CLK_DISPC1_EB] = &dispc1_eb.common.hw, + [CLK_DISPC_MMU_EB] = &dispc_mmu_eb.common.hw, + [CLK_GSP0_EB] = &gsp0_eb.common.hw, + [CLK_GSP1_EB] = &gsp1_eb.common.hw, + [CLK_GSP0_MMU_EB] = &gsp0_mmu_eb.common.hw, + [CLK_GSP1_MMU_EB] = &gsp1_mmu_eb.common.hw, + [CLK_DSI0_EB] = &dsi0_eb.common.hw, + [CLK_DSI1_EB] = &dsi1_eb.common.hw, + [CLK_DISP_CKG_EB] = &disp_ckg_eb.common.hw, + [CLK_DISP_GPU_EB] = &disp_gpu_eb.common.hw, + [CLK_GPU_MTX_EB] = &gpu_mtx_eb.common.hw, + [CLK_GSP_MTX_EB] = &gsp_mtx_eb.common.hw, + [CLK_TMC_MTX_EB] = &tmc_mtx_eb.common.hw, + [CLK_DISPC_MTX_EB] = &dispc_mtx_eb.common.hw, + [CLK_DPHY0_GATE] = &dphy0_gate.common.hw, + [CLK_DPHY1_GATE] = &dphy1_gate.common.hw, + [CLK_GSP0_A_GATE] = &gsp0_a_gate.common.hw, + [CLK_GSP1_A_GATE] = &gsp1_a_gate.common.hw, + [CLK_GSP0_F_GATE] = &gsp0_f_gate.common.hw, + [CLK_GSP1_F_GATE] = &gsp1_f_gate.common.hw, + [CLK_D_MTX_F_GATE] = &d_mtx_f_gate.common.hw, + [CLK_D_MTX_A_GATE] = &d_mtx_a_gate.common.hw, + [CLK_D_NOC_F_GATE] = &d_noc_f_gate.common.hw, + [CLK_D_NOC_A_GATE] = &d_noc_a_gate.common.hw, + [CLK_GSP_MTX_F_GATE] = &gsp_mtx_f_gate.common.hw, + [CLK_GSP_MTX_A_GATE] = &gsp_mtx_a_gate.common.hw, + [CLK_GSP_NOC_F_GATE] = &gsp_noc_f_gate.common.hw, + [CLK_GSP_NOC_A_GATE] = &gsp_noc_a_gate.common.hw, + [CLK_DISPM0IDLE_GATE] = &dispm0idle_gate.common.hw, + [CLK_GSPM0IDLE_GATE] = &gspm0idle_gate.common.hw, + }, + .num = CLK_DISP_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_disp_gate_desc = { + .clk_clks = sc9860_disp_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_disp_gate), + .hw_clks = &sc9860_disp_gate_hws, +}; + +static SPRD_GATE_CLK(sim0_eb, "sim0-eb", "ap-apb", 0x0, + 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis0_eb, "iis0-eb", "ap-apb", 0x0, + 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis1_eb, "iis1-eb", "ap-apb", 0x0, + 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis2_eb, "iis2-eb", "ap-apb", 0x0, + 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(iis3_eb, "iis3-eb", "ap-apb", 0x0, + 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi0_eb, "spi0-eb", "ap-apb", 0x0, + 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi1_eb, "spi1-eb", "ap-apb", 0x0, + 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi2_eb, "spi2-eb", "ap-apb", 0x0, + 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c0_eb, "i2c0-eb", "ap-apb", 0x0, + 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c1_eb, "i2c1-eb", "ap-apb", 0x0, + 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c2_eb, "i2c2-eb", "ap-apb", 0x0, + 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c3_eb, "i2c3-eb", "ap-apb", 0x0, + 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c4_eb, "i2c4-eb", "ap-apb", 0x0, + 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(i2c5_eb, "i2c5-eb", "ap-apb", 0x0, + 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart0_eb, "uart0-eb", "ap-apb", 0x0, + 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart1_eb, "uart1-eb", "ap-apb", 0x0, + 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart2_eb, "uart2-eb", "ap-apb", 0x0, + 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart3_eb, "uart3-eb", "ap-apb", 0x0, + 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(uart4_eb, "uart4-eb", "ap-apb", 0x0, + 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(ap_ckg_eb, "ap-ckg-eb", "ap-apb", 0x0, + 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0); +static SPRD_GATE_CLK(spi3_eb, "spi3-eb", "ap-apb", 0x0, + 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0); + +static struct sprd_clk_common *sc9860_apapb_gate[] = { + /* address base is 0x70b00000 */ + &sim0_eb.common, + &iis0_eb.common, + &iis1_eb.common, + &iis2_eb.common, + &iis3_eb.common, + &spi0_eb.common, + &spi1_eb.common, + &spi2_eb.common, + &i2c0_eb.common, + &i2c1_eb.common, + &i2c2_eb.common, + &i2c3_eb.common, + &i2c4_eb.common, + &i2c5_eb.common, + &uart0_eb.common, + &uart1_eb.common, + &uart2_eb.common, + &uart3_eb.common, + &uart4_eb.common, + &ap_ckg_eb.common, + &spi3_eb.common, +}; + +static struct clk_hw_onecell_data sc9860_apapb_gate_hws = { + .hws = { + [CLK_SIM0_EB] = &sim0_eb.common.hw, + [CLK_IIS0_EB] = &iis0_eb.common.hw, + [CLK_IIS1_EB] = &iis1_eb.common.hw, + [CLK_IIS2_EB] = &iis2_eb.common.hw, + [CLK_IIS3_EB] = &iis3_eb.common.hw, + [CLK_SPI0_EB] = &spi0_eb.common.hw, + [CLK_SPI1_EB] = &spi1_eb.common.hw, + [CLK_SPI2_EB] = &spi2_eb.common.hw, + [CLK_I2C0_EB] = &i2c0_eb.common.hw, + [CLK_I2C1_EB] = &i2c1_eb.common.hw, + [CLK_I2C2_EB] = &i2c2_eb.common.hw, + [CLK_I2C3_EB] = &i2c3_eb.common.hw, + [CLK_I2C4_EB] = &i2c4_eb.common.hw, + [CLK_I2C5_EB] = &i2c5_eb.common.hw, + [CLK_UART0_EB] = &uart0_eb.common.hw, + [CLK_UART1_EB] = &uart1_eb.common.hw, + [CLK_UART2_EB] = &uart2_eb.common.hw, + [CLK_UART3_EB] = &uart3_eb.common.hw, + [CLK_UART4_EB] = &uart4_eb.common.hw, + [CLK_AP_CKG_EB] = &ap_ckg_eb.common.hw, + [CLK_SPI3_EB] = &spi3_eb.common.hw, + }, + .num = CLK_APAPB_GATE_NUM, +}; + +static const struct sprd_clk_desc sc9860_apapb_gate_desc = { + .clk_clks = sc9860_apapb_gate, + .num_clk_clks = ARRAY_SIZE(sc9860_apapb_gate), + .hw_clks = &sc9860_apapb_gate_hws, +}; + +static const struct of_device_id sprd_sc9860_clk_ids[] = { + { .compatible = "sprd,sc9860-pmu-gate", /* 0x402b */ + .data = &sc9860_pmu_gate_desc }, + { .compatible = "sprd,sc9860-pll", /* 0x4040 */ + .data = &sc9860_pll_desc }, + { .compatible = "sprd,sc9860-ap-clk", /* 0x2000 */ + .data = &sc9860_ap_clk_desc }, + { .compatible = "sprd,sc9860-aon-prediv", /* 0x402d */ + .data = &sc9860_aon_prediv_desc }, + { .compatible = "sprd,sc9860-apahb-gate", /* 0x2021 */ + .data = &sc9860_apahb_gate_desc }, + { .compatible = "sprd,sc9860-aon-gate", /* 0x402e */ + .data = &sc9860_aon_gate_desc }, + { .compatible = "sprd,sc9860-aonsecure-clk", /* 0x4088 */ + .data = &sc9860_aonsecure_clk_desc }, + { .compatible = "sprd,sc9860-agcp-gate", /* 0x415e */ + .data = &sc9860_agcp_gate_desc }, + { .compatible = "sprd,sc9860-gpu-clk", /* 0x6020 */ + .data = &sc9860_gpu_clk_desc }, + { .compatible = "sprd,sc9860-vsp-clk", /* 0x6100 */ + .data = &sc9860_vsp_clk_desc }, + { .compatible = "sprd,sc9860-vsp-gate", /* 0x6110 */ + .data = &sc9860_vsp_gate_desc }, + { .compatible = "sprd,sc9860-cam-clk", /* 0x6200 */ + .data = &sc9860_cam_clk_desc }, + { .compatible = "sprd,sc9860-cam-gate", /* 0x6210 */ + .data = &sc9860_cam_gate_desc }, + { .compatible = "sprd,sc9860-disp-clk", /* 0x6300 */ + .data = &sc9860_disp_clk_desc }, + { .compatible = "sprd,sc9860-disp-gate", /* 0x6310 */ + .data = &sc9860_disp_gate_desc }, + { .compatible = "sprd,sc9860-apapb-gate", /* 0x70b0 */ + .data = &sc9860_apapb_gate_desc }, + { } +}; +MODULE_DEVICE_TABLE(of, sprd_sc9860_clk_ids); + +static int sc9860_clk_probe(struct platform_device *pdev) +{ + int ret = 0; + const struct of_device_id *match; + const struct sprd_clk_desc *desc; + + match = of_match_node(sprd_sc9860_clk_ids, pdev->dev.of_node); + if (!match) { + pr_err("%s: of_match_node() failed.", __func__); + return -ENODEV; + } + + desc = match->data; + sprd_clk_regmap_init(pdev, desc); + + ret = sprd_clk_probe(pdev->dev.of_node, desc->hw_clks); + if (ret == 0) + pr_info("%s: %u clocks have been registered now.\n", + match->compatible, desc->hw_clks->num); + + return ret; +} + +static struct platform_driver sc9860_clk_driver = { + .probe = sc9860_clk_probe, + .driver = { + .name = "sc9860-clk", + .of_match_table = sprd_sc9860_clk_ids, + }, +}; +module_platform_driver(sc9860_clk_driver); + +MODULE_DESCRIPTION("Spreadtrum SC9860 Clock Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sc9860-clk"); diff --git a/include/dt-bindings/clock/sprd,sc9860-clk.h b/include/dt-bindings/clock/sprd,sc9860-clk.h new file mode 100644 index 0000000..48e6052 --- /dev/null +++ b/include/dt-bindings/clock/sprd,sc9860-clk.h @@ -0,0 +1,408 @@ +/* + * Spreadtrum SC9860 platform clocks + * + * Copyright (C) 2017, Spreadtrum Communications Inc. + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +#ifndef _DT_BINDINGS_CLK_SC9860_H_ +#define _DT_BINDINGS_CLK_SC9860_H_ + +#define CLK_EXT_RCO_100M 0 +#define CLK_EXT_32K 1 +#define CLK_FAC_4M 2 +#define CLK_FAC_2M 3 +#define CLK_FAC_1M 4 +#define CLK_FAC_250K 5 +#define CLK_FAC_RPLL0_26M 6 +#define CLK_FAC_RPLL1_26M 7 +#define CLK_FAC_RCO25M 8 +#define CLK_FAC_RCO4M 9 +#define CLK_FAC_RCO2M 10 +#define CLK_FAC_3K2 11 +#define CLK_FAC_1K 12 +#define CLK_MPLL0_GATE 13 +#define CLK_MPLL1_GATE 14 +#define CLK_DPLL0_GATE 15 +#define CLK_DPLL1_GATE 16 +#define CLK_LTEPLL0_GATE 17 +#define CLK_TWPLL_GATE 18 +#define CLK_LTEPLL1_GATE 19 +#define CLK_RPLL0_GATE 20 +#define CLK_RPLL1_GATE 21 +#define CLK_CPPLL_GATE 22 +#define CLK_GPLL_GATE 23 +#define CLK_PMU_GATE_NUM (CLK_GPLL_GATE + 1) + +#define CLK_MPLL0 0 +#define CLK_MPLL1 1 +#define CLK_DPLL0 2 +#define CLK_DPLL1 3 +#define CLK_RPLL0 4 +#define CLK_RPLL1 5 +#define CLK_TWPLL 6 +#define CLK_LTEPLL0 7 +#define CLK_LTEPLL1 8 +#define CLK_GPLL 9 +#define CLK_CPPLL 10 +#define CLK_GPLL_42M5 11 +#define CLK_TWPLL_768M 12 +#define CLK_TWPLL_384M 13 +#define CLK_TWPLL_192M 14 +#define CLK_TWPLL_96M 15 +#define CLK_TWPLL_48M 16 +#define CLK_TWPLL_24M 17 +#define CLK_TWPLL_12M 18 +#define CLK_TWPLL_512M 19 +#define CLK_TWPLL_256M 20 +#define CLK_TWPLL_128M 21 +#define CLK_TWPLL_64M 22 +#define CLK_TWPLL_307M2 23 +#define CLK_TWPLL_153M6 24 +#define CLK_TWPLL_76M8 25 +#define CLK_TWPLL_51M2 26 +#define CLK_TWPLL_38M4 27 +#define CLK_TWPLL_19M2 28 +#define CLK_L0_614M4 29 +#define CLK_L0_409M6 30 +#define CLK_L0_38M 31 +#define CLK_L1_38M 32 +#define CLK_RPLL0_192M 33 +#define CLK_RPLL0_96M 34 +#define CLK_RPLL0_48M 35 +#define CLK_RPLL1_468M 36 +#define CLK_RPLL1_192M 37 +#define CLK_RPLL1_96M 38 +#define CLK_RPLL1_64M 39 +#define CLK_RPLL1_48M 40 +#define CLK_DPLL0_50M 41 +#define CLK_DPLL1_50M 42 +#define CLK_CPPLL_50M 43 +#define CLK_M0_39M 44 +#define CLK_M1_63M 45 +#define CLK_PLL_NUM (CLK_M1_63M + 1) + + +#define CLK_AP_APB 0 +#define CLK_AP_USB3 1 +#define CLK_UART0 2 +#define CLK_UART1 3 +#define CLK_UART2 4 +#define CLK_UART3 5 +#define CLK_UART4 6 +#define CLK_I2C0 7 +#define CLK_I2C1 8 +#define CLK_I2C2 9 +#define CLK_I2C3 10 +#define CLK_I2C4 11 +#define CLK_I2C5 12 +#define CLK_SPI0 13 +#define CLK_SPI1 14 +#define CLK_SPI2 15 +#define CLK_SPI3 16 +#define CLK_IIS0 17 +#define CLK_IIS1 18 +#define CLK_IIS2 19 +#define CLK_IIS3 20 +#define CLK_AP_CLK_NUM (CLK_IIS3 + 1) + +#define CLK_AON_APB 0 +#define CLK_AUX0 1 +#define CLK_AUX1 2 +#define CLK_AUX2 3 +#define CLK_PROBE 4 +#define CLK_SP_AHB 5 +#define CLK_CCI 6 +#define CLK_GIC 7 +#define CLK_CSSYS 8 +#define CLK_SDIO0_2X 9 +#define CLK_SDIO1_2X 10 +#define CLK_SDIO2_2X 11 +#define CLK_EMMC_2X 12 +#define CLK_SDIO0_1X 13 +#define CLK_SDIO1_1X 14 +#define CLK_SDIO2_1X 15 +#define CLK_EMMC_1X 16 +#define CLK_ADI 17 +#define CLK_PWM0 18 +#define CLK_PWM1 19 +#define CLK_PWM2 20 +#define CLK_PWM3 21 +#define CLK_EFUSE 22 +#define CLK_CM3_UART0 23 +#define CLK_CM3_UART1 24 +#define CLK_THM 25 +#define CLK_CM3_I2C0 26 +#define CLK_CM3_I2C1 27 +#define CLK_CM4_SPI 28 +#define CLK_AON_I2C 29 +#define CLK_AVS 30 +#define CLK_CA53_DAP 31 +#define CLK_CA53_TS 32 +#define CLK_DJTAG_TCK 33 +#define CLK_PMU 34 +#define CLK_PMU_26M 35 +#define CLK_DEBOUNCE 36 +#define CLK_OTG2_REF 37 +#define CLK_USB3_REF 38 +#define CLK_AP_AXI 39 +#define CLK_AON_PREDIV_NUM (CLK_AP_AXI + 1) + +#define CLK_USB3_EB 0 +#define CLK_USB3_SUSPEND_EB 1 +#define CLK_USB3_REF_EB 2 +#define CLK_DMA_EB 3 +#define CLK_SDIO0_EB 4 +#define CLK_SDIO1_EB 5 +#define CLK_SDIO2_EB 6 +#define CLK_EMMC_EB 7 +#define CLK_ROM_EB 8 +#define CLK_BUSMON_EB 9 +#define CLK_CC63S_EB 10 +#define CLK_CC63P_EB 11 +#define CLK_CE0_EB 12 +#define CLK_CE1_EB 13 +#define CLK_APAHB_GATE_NUM (CLK_CE1_EB + 1) + +#define CLK_AVS_LIT_EB 0 +#define CLK_AVS_BIG_EB 1 +#define CLK_AP_INTC5_EB 2 +#define CLK_GPIO_EB 3 +#define CLK_PWM0_EB 4 +#define CLK_PWM1_EB 5 +#define CLK_PWM2_EB 6 +#define CLK_PWM3_EB 7 +#define CLK_KPD_EB 8 +#define CLK_AON_SYS_EB 9 +#define CLK_AP_SYS_EB 10 +#define CLK_AON_TMR_EB 11 +#define CLK_AP_TMR0_EB 12 +#define CLK_EFUSE_EB 13 +#define CLK_EIC_EB 14 +#define CLK_PUB1_REG_EB 15 +#define CLK_ADI_EB 16 +#define CLK_AP_INTC0_EB 17 +#define CLK_AP_INTC1_EB 18 +#define CLK_AP_INTC2_EB 19 +#define CLK_AP_INTC3_EB 20 +#define CLK_AP_INTC4_EB 21 +#define CLK_SPLK_EB 22 +#define CLK_MSPI_EB 23 +#define CLK_PUB0_REG_EB 24 +#define CLK_PIN_EB 25 +#define CLK_AON_CKG_EB 26 +#define CLK_GPU_EB 27 +#define CLK_APCPU_TS0_EB 28 +#define CLK_APCPU_TS1_EB 29 +#define CLK_DAP_EB 30 +#define CLK_I2C_EB 31 +#define CLK_PMU_EB 32 +#define CLK_THM_EB 33 +#define CLK_AUX0_EB 34 +#define CLK_AUX1_EB 35 +#define CLK_AUX2_EB 36 +#define CLK_PROBE_EB 37 +#define CLK_GPU0_AVS_EB 38 +#define CLK_GPU1_AVS_EB 39 +#define CLK_APCPU_WDG_EB 40 +#define CLK_AP_TMR1_EB 41 +#define CLK_AP_TMR2_EB 42 +#define CLK_DISP_EMC_EB 43 +#define CLK_ZIP_EMC_EB 44 +#define CLK_GSP_EMC_EB 45 +#define CLK_OSC_AON_EB 46 +#define CLK_LVDS_TRX_EB 47 +#define CLK_LVDS_TCXO_EB 48 +#define CLK_MDAR_EB 49 +#define CLK_RTC4M0_CAL_EB 50 +#define CLK_RCT100M_CAL_EB 51 +#define CLK_DJTAG_EB 52 +#define CLK_MBOX_EB 53 +#define CLK_AON_DMA_EB 54 +#define CLK_DBG_EMC_EB 55 +#define CLK_LVDS_PLL_DIV_EN 56 +#define CLK_DEF_EB 57 +#define CLK_AON_APB_RSV0 58 +#define CLK_ORP_JTAG_EB 59 +#define CLK_VSP_EB 60 +#define CLK_CAM_EB 61 +#define CLK_DISP_EB 62 +#define CLK_DBG_AXI_IF_EB 63 +#define CLK_SDIO0_2X_EN 64 +#define CLK_SDIO1_2X_EN 65 +#define CLK_SDIO2_2X_EN 66 +#define CLK_EMMC_2X_EN 67 +#define CLK_AON_GATE_NUM (CLK_EMMC_2X_EN + 1) + +#define CLK_LIT_MCU 0 +#define CLK_BIG_MCU 1 +#define CLK_AONSECURE_NUM (CLK_BIG_MCU + 1) + +#define CLK_AGCP_IIS0_EB 0 +#define CLK_AGCP_IIS1_EB 1 +#define CLK_AGCP_IIS2_EB 2 +#define CLK_AGCP_IIS3_EB 3 +#define CLK_AGCP_UART_EB 4 +#define CLK_AGCP_DMACP_EB 5 +#define CLK_AGCP_DMAAP_EB 6 +#define CLK_AGCP_ARC48K_EB 7 +#define CLK_AGCP_SRC44P1K_EB 8 +#define CLK_AGCP_MCDT_EB 9 +#define CLK_AGCP_VBCIFD_EB 10 +#define CLK_AGCP_VBC_EB 11 +#define CLK_AGCP_SPINLOCK_EB 12 +#define CLK_AGCP_ICU_EB 13 +#define CLK_AGCP_AP_ASHB_EB 14 +#define CLK_AGCP_CP_ASHB_EB 15 +#define CLK_AGCP_AUD_EB 16 +#define CLK_AGCP_AUDIF_EB 17 +#define CLK_AGCP_GATE_NUM (CLK_AGCP_AUDIF_EB + 1) + +#define CLK_GPU 0 +#define CLK_GPU_NUM (CLK_GPU + 1) + +#define CLK_AHB_VSP 0 +#define CLK_VSP 1 +#define CLK_VSP_ENC 2 +#define CLK_VPP 3 +#define CLK_VSP_26M 4 +#define CLK_VSP_NUM (CLK_VSP_26M + 1) + +#define CLK_VSP_DEC_EB 0 +#define CLK_VSP_CKG_EB 1 +#define CLK_VSP_MMU_EB 2 +#define CLK_VSP_ENC_EB 3 +#define CLK_VPP_EB 4 +#define CLK_VSP_26M_EB 5 +#define CLK_VSP_AXI_GATE 6 +#define CLK_VSP_ENC_GATE 7 +#define CLK_VPP_AXI_GATE 8 +#define CLK_VSP_BM_GATE 9 +#define CLK_VSP_ENC_BM_GATE 10 +#define CLK_VPP_BM_GATE 11 +#define CLK_VSP_GATE_NUM (CLK_VPP_BM_GATE + 1) + +#define CLK_AHB_CAM 0 +#define CLK_SENSOR0 1 +#define CLK_SENSOR1 2 +#define CLK_SENSOR2 3 +#define CLK_MIPI_CSI0_EB 4 +#define CLK_MIPI_CSI1_EB 5 +#define CLK_CAM_NUM (CLK_MIPI_CSI1_EB + 1) + +#define CLK_DCAM0_EB 0 +#define CLK_DCAM1_EB 1 +#define CLK_ISP0_EB 2 +#define CLK_CSI0_EB 3 +#define CLK_CSI1_EB 4 +#define CLK_JPG0_EB 5 +#define CLK_JPG1_EB 6 +#define CLK_CAM_CKG_EB 7 +#define CLK_CAM_MMU_EB 8 +#define CLK_ISP1_EB 9 +#define CLK_CPP_EB 10 +#define CLK_MMU_PF_EB 11 +#define CLK_ISP2_EB 12 +#define CLK_DCAM2ISP_IF_EB 13 +#define CLK_ISP2DCAM_IF_EB 14 +#define CLK_ISP_LCLK_EB 15 +#define CLK_ISP_ICLK_EB 16 +#define CLK_ISP_MCLK_EB 17 +#define CLK_ISP_PCLK_EB 18 +#define CLK_ISP_ISP2DCAM_EB 19 +#define CLK_DCAM0_IF_EB 20 +#define CLK_CLK26M_IF_EB 21 +#define CLK_CPHY0_GATE 22 +#define CLK_MIPI_CSI0_GATE 23 +#define CLK_CPHY1_GATE 24 +#define CLK_MIPI_CSI1 25 +#define CLK_DCAM0_AXI_GATE 26 +#define CLK_DCAM1_AXI_GATE 27 +#define CLK_SENSOR0_GATE 28 +#define CLK_SENSOR1_GATE 29 +#define CLK_JPG0_AXI_GATE 30 +#define CLK_GPG1_AXI_GATE 31 +#define CLK_ISP0_AXI_GATE 32 +#define CLK_ISP1_AXI_GATE 33 +#define CLK_ISP2_AXI_GATE 34 +#define CLK_CPP_AXI_GATE 35 +#define CLK_D0_IF_AXI_GATE 36 +#define CLK_D2I_IF_AXI_GATE 37 +#define CLK_I2D_IF_AXI_GATE 38 +#define CLK_SPARE_AXI_GATE 39 +#define CLK_SENSOR2_GATE 40 +#define CLK_D0IF_IN_D_EN 41 +#define CLK_D1IF_IN_D_EN 42 +#define CLK_D0IF_IN_D2I_EN 43 +#define CLK_D1IF_IN_D2I_EN 44 +#define CLK_IA_IN_D2I_EN 45 +#define CLK_IB_IN_D2I_EN 46 +#define CLK_IC_IN_D2I_EN 47 +#define CLK_IA_IN_I_EN 48 +#define CLK_IB_IN_I_EN 49 +#define CLK_IC_IN_I_EN 50 +#define CLK_CAM_GATE_NUM (CLK_IC_IN_I_EN + 1) + +#define CLK_AHB_DISP 0 +#define CLK_DISPC0_DPI 1 +#define CLK_DISPC1_DPI 2 +#define CLK_DISP_NUM (CLK_DISPC1_DPI + 1) + +#define CLK_DISPC0_EB 0 +#define CLK_DISPC1_EB 1 +#define CLK_DISPC_MMU_EB 2 +#define CLK_GSP0_EB 3 +#define CLK_GSP1_EB 4 +#define CLK_GSP0_MMU_EB 5 +#define CLK_GSP1_MMU_EB 6 +#define CLK_DSI0_EB 7 +#define CLK_DSI1_EB 8 +#define CLK_DISP_CKG_EB 9 +#define CLK_DISP_GPU_EB 10 +#define CLK_GPU_MTX_EB 11 +#define CLK_GSP_MTX_EB 12 +#define CLK_TMC_MTX_EB 13 +#define CLK_DISPC_MTX_EB 14 +#define CLK_DPHY0_GATE 15 +#define CLK_DPHY1_GATE 16 +#define CLK_GSP0_A_GATE 17 +#define CLK_GSP1_A_GATE 18 +#define CLK_GSP0_F_GATE 19 +#define CLK_GSP1_F_GATE 20 +#define CLK_D_MTX_F_GATE 21 +#define CLK_D_MTX_A_GATE 22 +#define CLK_D_NOC_F_GATE 23 +#define CLK_D_NOC_A_GATE 24 +#define CLK_GSP_MTX_F_GATE 25 +#define CLK_GSP_MTX_A_GATE 26 +#define CLK_GSP_NOC_F_GATE 27 +#define CLK_GSP_NOC_A_GATE 28 +#define CLK_DISPM0IDLE_GATE 29 +#define CLK_GSPM0IDLE_GATE 30 +#define CLK_DISP_GATE_NUM (CLK_GSPM0IDLE_GATE + 1) + +#define CLK_SIM0_EB 0 +#define CLK_IIS0_EB 1 +#define CLK_IIS1_EB 2 +#define CLK_IIS2_EB 3 +#define CLK_IIS3_EB 4 +#define CLK_SPI0_EB 5 +#define CLK_SPI1_EB 6 +#define CLK_SPI2_EB 7 +#define CLK_I2C0_EB 8 +#define CLK_I2C1_EB 9 +#define CLK_I2C2_EB 10 +#define CLK_I2C3_EB 11 +#define CLK_I2C4_EB 12 +#define CLK_I2C5_EB 13 +#define CLK_UART0_EB 14 +#define CLK_UART1_EB 15 +#define CLK_UART2_EB 16 +#define CLK_UART3_EB 17 +#define CLK_UART4_EB 18 +#define CLK_AP_CKG_EB 19 +#define CLK_SPI3_EB 20 +#define CLK_APAPB_GATE_NUM (CLK_SPI3_EB + 1) + +#endif /* _DT_BINDINGS_CLK_SC9860_H_ */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-05 7:59 ` kbuild test robot -1 siblings, 0 replies; 68+ messages in thread From: kbuild test robot @ 2017-11-05 7:59 UTC (permalink / raw) To: Chunyan Zhang Cc: kbuild-all, Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang [-- Attachment #1: Type: text/plain, Size: 1085 bytes --] Hi Chunyan, Thank you for the patch! Yet something to improve: [auto build test ERROR on clk/clk-next] [also build test ERROR on v4.14-rc7 next-20171103] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Chunyan-Zhang/add-clock-driver-for-Spreadtrum-platforms/20171105-035536 base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next config: arm64-allmodconfig (attached as .config) compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm64 All errors (new ones prefixed by >>): >> ERROR: "sprd_clk_regmap_init" [drivers/clk/sprd/sc9860-clk.ko] undefined! --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 57588 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 @ 2017-11-05 7:59 ` kbuild test robot 0 siblings, 0 replies; 68+ messages in thread From: kbuild test robot @ 2017-11-05 7:59 UTC (permalink / raw) To: linux-arm-kernel Hi Chunyan, Thank you for the patch! Yet something to improve: [auto build test ERROR on clk/clk-next] [also build test ERROR on v4.14-rc7 next-20171103] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Chunyan-Zhang/add-clock-driver-for-Spreadtrum-platforms/20171105-035536 base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next config: arm64-allmodconfig (attached as .config) compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm64 All errors (new ones prefixed by >>): >> ERROR: "sprd_clk_regmap_init" [drivers/clk/sprd/sc9860-clk.ko] undefined! --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation -------------- next part -------------- A non-text attachment was scrubbed... Name: .config.gz Type: application/gzip Size: 57588 bytes Desc: not available URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171105/85c43202/attachment-0001.gz> ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 @ 2017-11-05 7:59 ` kbuild test robot 0 siblings, 0 replies; 68+ messages in thread From: kbuild test robot @ 2017-11-05 7:59 UTC (permalink / raw) To: Chunyan Zhang Cc: Mark Rutland, devicetree, Orson Zhai, Arnd Bergmann, Catalin Marinas, Michael Turquette, Ben Li, Stephen Boyd, linux-kernel, Will Deacon, Rob Herring, Mark Brown, kbuild-all, Chunyan Zhang, linux-clk, linux-arm-kernel, Xiaolong Zhang [-- Attachment #1: Type: text/plain, Size: 1085 bytes --] Hi Chunyan, Thank you for the patch! Yet something to improve: [auto build test ERROR on clk/clk-next] [also build test ERROR on v4.14-rc7 next-20171103] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Chunyan-Zhang/add-clock-driver-for-Spreadtrum-platforms/20171105-035536 base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next config: arm64-allmodconfig (attached as .config) compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm64 All errors (new ones prefixed by >>): >> ERROR: "sprd_clk_regmap_init" [drivers/clk/sprd/sc9860-clk.ko] undefined! --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 57588 bytes --] [-- Attachment #3: Type: text/plain, Size: 176 bytes --] _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 2017-11-02 6:56 ` Chunyan Zhang @ 2017-11-06 21:43 ` Rob Herring -1 siblings, 0 replies; 68+ messages in thread From: Rob Herring @ 2017-11-06 21:43 UTC (permalink / raw) To: Chunyan Zhang Cc: Stephen Boyd, Michael Turquette, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang On Thu, Nov 02, 2017 at 02:56:24PM +0800, Chunyan Zhang wrote: > This patch added the list of clocks for Spreadtrum's SC9860 SoC, > together with clock initialization code. > > Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > --- > drivers/clk/sprd/Kconfig | 10 + > drivers/clk/sprd/Makefile | 3 + > drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ > include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ This belongs in the binding doc patch. Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 @ 2017-11-06 21:43 ` Rob Herring 0 siblings, 0 replies; 68+ messages in thread From: Rob Herring @ 2017-11-06 21:43 UTC (permalink / raw) To: linux-arm-kernel On Thu, Nov 02, 2017 at 02:56:24PM +0800, Chunyan Zhang wrote: > This patch added the list of clocks for Spreadtrum's SC9860 SoC, > together with clock initialization code. > > Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> > --- > drivers/clk/sprd/Kconfig | 10 + > drivers/clk/sprd/Makefile | 3 + > drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ > include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ This belongs in the binding doc patch. Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 2017-11-06 21:43 ` Rob Herring (?) @ 2017-11-09 8:18 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-09 8:18 UTC (permalink / raw) To: Rob Herring Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai Hi Rob and Stephen, On 7 November 2017 at 05:43, Rob Herring <robh@kernel.org> wrote: > On Thu, Nov 02, 2017 at 02:56:24PM +0800, Chunyan Zhang wrote: >> This patch added the list of clocks for Spreadtrum's SC9860 SoC, >> together with clock initialization code. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Kconfig | 10 + >> drivers/clk/sprd/Makefile | 3 + >> drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ >> include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ > > This belongs in the binding doc patch. I noticed that this kind of files were submitted in driver patch before when adding a new driver, how about I just put it into a single patch in the next version? Thanks, Chunyan > > Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 @ 2017-11-09 8:18 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-09 8:18 UTC (permalink / raw) To: linux-arm-kernel Hi Rob and Stephen, On 7 November 2017 at 05:43, Rob Herring <robh@kernel.org> wrote: > On Thu, Nov 02, 2017 at 02:56:24PM +0800, Chunyan Zhang wrote: >> This patch added the list of clocks for Spreadtrum's SC9860 SoC, >> together with clock initialization code. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Kconfig | 10 + >> drivers/clk/sprd/Makefile | 3 + >> drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ >> include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ > > This belongs in the binding doc patch. I noticed that this kind of files were submitted in driver patch before when adding a new driver, how about I just put it into a single patch in the next version? Thanks, Chunyan > > Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 @ 2017-11-09 8:18 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-09 8:18 UTC (permalink / raw) To: Rob Herring Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai Hi Rob and Stephen, On 7 November 2017 at 05:43, Rob Herring <robh@kernel.org> wrote: > On Thu, Nov 02, 2017 at 02:56:24PM +0800, Chunyan Zhang wrote: >> This patch added the list of clocks for Spreadtrum's SC9860 SoC, >> together with clock initialization code. >> >> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >> --- >> drivers/clk/sprd/Kconfig | 10 + >> drivers/clk/sprd/Makefile | 3 + >> drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ >> include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ > > This belongs in the binding doc patch. I noticed that this kind of files were submitted in driver patch before when adding a new driver, how about I just put it into a single patch in the next version? Thanks, Chunyan > > Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 2017-11-09 8:18 ` Chunyan Zhang (?) @ 2017-11-10 21:10 ` Rob Herring -1 siblings, 0 replies; 68+ messages in thread From: Rob Herring @ 2017-11-10 21:10 UTC (permalink / raw) To: Chunyan Zhang Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai On Thu, Nov 9, 2017 at 2:18 AM, Chunyan Zhang <zhang.lyra@gmail.com> wrote: > Hi Rob and Stephen, > > On 7 November 2017 at 05:43, Rob Herring <robh@kernel.org> wrote: >> On Thu, Nov 02, 2017 at 02:56:24PM +0800, Chunyan Zhang wrote: >>> This patch added the list of clocks for Spreadtrum's SC9860 SoC, >>> together with clock initialization code. >>> >>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >>> --- >>> drivers/clk/sprd/Kconfig | 10 + >>> drivers/clk/sprd/Makefile | 3 + >>> drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ >>> include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ >> >> This belongs in the binding doc patch. > > I noticed that this kind of files were submitted in driver patch > before when adding a new driver, how about I just put it into a single > patch in the next version? It's been done all ways, but the correct way is as I told you. Binding doc and header in one, driver in another patch. Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 @ 2017-11-10 21:10 ` Rob Herring 0 siblings, 0 replies; 68+ messages in thread From: Rob Herring @ 2017-11-10 21:10 UTC (permalink / raw) To: linux-arm-kernel On Thu, Nov 9, 2017 at 2:18 AM, Chunyan Zhang <zhang.lyra@gmail.com> wrote: > Hi Rob and Stephen, > > On 7 November 2017 at 05:43, Rob Herring <robh@kernel.org> wrote: >> On Thu, Nov 02, 2017 at 02:56:24PM +0800, Chunyan Zhang wrote: >>> This patch added the list of clocks for Spreadtrum's SC9860 SoC, >>> together with clock initialization code. >>> >>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >>> --- >>> drivers/clk/sprd/Kconfig | 10 + >>> drivers/clk/sprd/Makefile | 3 + >>> drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ >>> include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ >> >> This belongs in the binding doc patch. > > I noticed that this kind of files were submitted in driver patch > before when adding a new driver, how about I just put it into a single > patch in the next version? It's been done all ways, but the correct way is as I told you. Binding doc and header in one, driver in another patch. Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 @ 2017-11-10 21:10 ` Rob Herring 0 siblings, 0 replies; 68+ messages in thread From: Rob Herring @ 2017-11-10 21:10 UTC (permalink / raw) To: Chunyan Zhang Cc: Chunyan Zhang, Stephen Boyd, Michael Turquette, Mark Rutland, Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai On Thu, Nov 9, 2017 at 2:18 AM, Chunyan Zhang <zhang.lyra@gmail.com> wrote: > Hi Rob and Stephen, > > On 7 November 2017 at 05:43, Rob Herring <robh@kernel.org> wrote: >> On Thu, Nov 02, 2017 at 02:56:24PM +0800, Chunyan Zhang wrote: >>> This patch added the list of clocks for Spreadtrum's SC9860 SoC, >>> together with clock initialization code. >>> >>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> >>> --- >>> drivers/clk/sprd/Kconfig | 10 + >>> drivers/clk/sprd/Makefile | 3 + >>> drivers/clk/sprd/sc9860-clk.c | 1987 +++++++++++++++++++++++++++ >>> include/dt-bindings/clock/sprd,sc9860-clk.h | 408 ++++++ >> >> This belongs in the binding doc patch. > > I noticed that this kind of files were submitted in driver patch > before when adding a new driver, how about I just put it into a single > patch in the next version? It's been done all ways, but the correct way is as I told you. Binding doc and header in one, driver in another patch. Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH V3 10/11] arm64: dts: add syscon for whale2 platform 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Some clocks on the SoC of Whale2 families (e.g. SC9860) are in the same address area with syscon devices, the proper syscon node will be quoted under the definitions of those clocks in DT. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- arch/arm64/boot/dts/sprd/whale2.dtsi | 46 +++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi index 7c217c5..a9995fa 100644 --- a/arch/arm64/boot/dts/sprd/whale2.dtsi +++ b/arch/arm64/boot/dts/sprd/whale2.dtsi @@ -17,6 +17,51 @@ #size-cells = <2>; ranges; + ap_ahb: syscon@20210000 { + compatible = "syscon"; + reg = <0 0x20210000 0 0x10000>; + }; + + pmu_apb: syscon@402b0000 { + compatible = "syscon"; + reg = <0 0x402b0000 0 0x10000>; + }; + + aon_apb: syscon@402e0000 { + compatible = "syscon"; + reg = <0 0x402e0000 0 0x10000>; + }; + + ana_apb: syscon@40400000 { + compatible = "syscon"; + reg = <0 0x40400000 0 0x10000>; + }; + + agcp_ahb: syscon@415e0000 { + compatible = "syscon"; + reg = <0 0x415e0000 0 0x1000000>; + }; + + vsp_ahb: syscon@61100000 { + compatible = "syscon"; + reg = <0 0x61100000 0 0x10000>; + }; + + cam_ahb: syscon@62100000 { + compatible = "syscon"; + reg = <0 0x62100000 0 0x10000>; + }; + + disp_ahb: syscon@63100000 { + compatible = "syscon"; + reg = <0 0x63100000 0 0x10000>; + }; + + ap_apb: syscon@70b00000 { + compatible = "syscon"; + reg = <0 0x70b00000 0 0x40000>; + }; + ap-apb { compatible = "simple-bus"; #address-cells = <1>; @@ -59,7 +104,6 @@ status = "disabled"; }; }; - }; ext_26m: ext-26m { -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 10/11] arm64: dts: add syscon for whale2 platform @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel Some clocks on the SoC of Whale2 families (e.g. SC9860) are in the same address area with syscon devices, the proper syscon node will be quoted under the definitions of those clocks in DT. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- arch/arm64/boot/dts/sprd/whale2.dtsi | 46 +++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi index 7c217c5..a9995fa 100644 --- a/arch/arm64/boot/dts/sprd/whale2.dtsi +++ b/arch/arm64/boot/dts/sprd/whale2.dtsi @@ -17,6 +17,51 @@ #size-cells = <2>; ranges; + ap_ahb: syscon at 20210000 { + compatible = "syscon"; + reg = <0 0x20210000 0 0x10000>; + }; + + pmu_apb: syscon at 402b0000 { + compatible = "syscon"; + reg = <0 0x402b0000 0 0x10000>; + }; + + aon_apb: syscon at 402e0000 { + compatible = "syscon"; + reg = <0 0x402e0000 0 0x10000>; + }; + + ana_apb: syscon at 40400000 { + compatible = "syscon"; + reg = <0 0x40400000 0 0x10000>; + }; + + agcp_ahb: syscon at 415e0000 { + compatible = "syscon"; + reg = <0 0x415e0000 0 0x1000000>; + }; + + vsp_ahb: syscon at 61100000 { + compatible = "syscon"; + reg = <0 0x61100000 0 0x10000>; + }; + + cam_ahb: syscon at 62100000 { + compatible = "syscon"; + reg = <0 0x62100000 0 0x10000>; + }; + + disp_ahb: syscon at 63100000 { + compatible = "syscon"; + reg = <0 0x63100000 0 0x10000>; + }; + + ap_apb: syscon at 70b00000 { + compatible = "syscon"; + reg = <0 0x70b00000 0 0x40000>; + }; + ap-apb { compatible = "simple-bus"; #address-cells = <1>; @@ -59,7 +104,6 @@ status = "disabled"; }; }; - }; ext_26m: ext-26m { -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 10/11] arm64: dts: add syscon for whale2 platform @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Some clocks on the SoC of Whale2 families (e.g. SC9860) are in the same address area with syscon devices, the proper syscon node will be quoted under the definitions of those clocks in DT. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- arch/arm64/boot/dts/sprd/whale2.dtsi | 46 +++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi index 7c217c5..a9995fa 100644 --- a/arch/arm64/boot/dts/sprd/whale2.dtsi +++ b/arch/arm64/boot/dts/sprd/whale2.dtsi @@ -17,6 +17,51 @@ #size-cells = <2>; ranges; + ap_ahb: syscon@20210000 { + compatible = "syscon"; + reg = <0 0x20210000 0 0x10000>; + }; + + pmu_apb: syscon@402b0000 { + compatible = "syscon"; + reg = <0 0x402b0000 0 0x10000>; + }; + + aon_apb: syscon@402e0000 { + compatible = "syscon"; + reg = <0 0x402e0000 0 0x10000>; + }; + + ana_apb: syscon@40400000 { + compatible = "syscon"; + reg = <0 0x40400000 0 0x10000>; + }; + + agcp_ahb: syscon@415e0000 { + compatible = "syscon"; + reg = <0 0x415e0000 0 0x1000000>; + }; + + vsp_ahb: syscon@61100000 { + compatible = "syscon"; + reg = <0 0x61100000 0 0x10000>; + }; + + cam_ahb: syscon@62100000 { + compatible = "syscon"; + reg = <0 0x62100000 0 0x10000>; + }; + + disp_ahb: syscon@63100000 { + compatible = "syscon"; + reg = <0 0x63100000 0 0x10000>; + }; + + ap_apb: syscon@70b00000 { + compatible = "syscon"; + reg = <0 0x70b00000 0 0x40000>; + }; + ap-apb { compatible = "simple-bus"; #address-cells = <1>; @@ -59,7 +104,6 @@ status = "disabled"; }; }; - }; ext_26m: ext-26m { -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 11/11] arm64: dts: add clocks for SC9860 2017-11-02 6:56 ` Chunyan Zhang (?) @ 2017-11-02 6:56 ` Chunyan Zhang -1 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Some clocks on SC9860 are in the same address area with syscon devices, those are what have a property of 'sprd,syscon' which would refer to syscon devices, others would have a reg property indicated their address ranges. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 +++++++++++++++++++++++++++++++++++ arch/arm64/boot/dts/sprd/whale2.dtsi | 2 +- 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi index 7b7d8ce..95746b2 100644 --- a/arch/arm64/boot/dts/sprd/sc9860.dtsi +++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi @@ -7,6 +7,7 @@ */ #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/sprd,sc9860-clk.h> #include "whale2.dtsi" / { @@ -183,6 +184,120 @@ }; soc { + pmu_gate: pmu-gate { + compatible = "sprd,sc9860-pmu-gate"; + sprd,syscon = <&pmu_apb>; /* 0x402b0000 */ + clocks = <&ext_26m>; + #clock-cells = <1>; + }; + + pll: pll { + compatible = "sprd,sc9860-pll"; + sprd,syscon = <&ana_apb>; /* 0x40400000 */ + clocks = <&pmu_gate 0>; + #clock-cells = <1>; + }; + + ap_clk: clock-controller@20000000 { + compatible = "sprd,sc9860-ap-clk"; + reg = <0 0x20000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>, + <&pmu_gate 0>; + #clock-cells = <1>; + }; + + aon_prediv: aon-prediv { + compatible = "sprd,sc9860-aon-prediv"; + reg = <0 0x402d0000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>, + <&pmu_gate 0>; + #clock-cells = <1>; + }; + + apahb_gate: apahb-gate { + compatible = "sprd,sc9860-apahb-gate"; + sprd,syscon = <&ap_ahb>; /* 0x20210000 */ + clocks = <&aon_prediv 0>; + #clock-cells = <1>; + }; + + aon_gate: aon-gate { + compatible = "sprd,sc9860-aon-gate"; + sprd,syscon = <&aon_apb>; /* 0x402e0000 */ + clocks = <&aon_prediv 0>; + #clock-cells = <1>; + }; + + aonsecure_clk: clock-controller@40880000 { + compatible = "sprd,sc9860-aonsecure-clk"; + reg = <0 0x40880000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + agcp_gate: agcp-gate { + compatible = "sprd,sc9860-agcp-gate"; + sprd,syscon = <&agcp_ahb>; /* 0x415e0000 */ + clocks = <&aon_prediv 0>; + #clock-cells = <1>; + }; + + gpu_clk: clock-controller@60200000 { + compatible = "sprd,sc9860-gpu-clk"; + reg = <0 0x60200000 0 0x400>; + clocks = <&pll 0>; + #clock-cells = <1>; + }; + + vsp_clk: clock-controller@61000000 { + compatible = "sprd,sc9860-vsp-clk"; + reg = <0 0x61000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + vsp_gate: vsp-gate { + compatible = "sprd,sc9860-vsp-gate"; + sprd,syscon = <&vsp_ahb>; /* 0x61100000 */ + clocks = <&vsp_clk 0>; + #clock-cells = <1>; + }; + + cam_clk: clock-controller@62000000 { + compatible = "sprd,sc9860-cam-clk"; + reg = <0 0x62000000 0 0x4000>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + cam_gate: cam-gate { + compatible = "sprd,sc9860-cam-gate"; + sprd,syscon = <&cam_ahb>; /* 0x62100000 */ + clocks = <&cam_clk 0>; + #clock-cells = <1>; + }; + + disp_clk: clock-controller@63000000 { + compatible = "sprd,sc9860-disp-clk"; + reg = <0 0x63000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + disp_gate: disp-gate { + compatible = "sprd,sc9860-disp-gate"; + sprd,syscon = <&disp_ahb>; /* 0x63100000 */ + clocks = <&disp_clk 0>; + #clock-cells = <1>; + }; + + apapb_gate: apapb-gate { + compatible = "sprd,sc9860-apapb-gate"; + sprd,syscon = <&ap_apb>; /* 0x70b00000 */ + clocks = <&ap_clk 0>; + #clock-cells = <1>; + }; + funnel@10001000 { /* SoC Funnel */ compatible = "arm,coresight-funnel", "arm,primecell"; reg = <0 0x10001000 0 0x1000>; diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi index a9995fa..206aaf1 100644 --- a/arch/arm64/boot/dts/sprd/whale2.dtsi +++ b/arch/arm64/boot/dts/sprd/whale2.dtsi @@ -110,6 +110,6 @@ compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <26000000>; - clock-output-names = "ext_26m"; + clock-output-names = "ext-26m"; }; }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 11/11] arm64: dts: add clocks for SC9860 @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: linux-arm-kernel Some clocks on SC9860 are in the same address area with syscon devices, those are what have a property of 'sprd,syscon' which would refer to syscon devices, others would have a reg property indicated their address ranges. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 +++++++++++++++++++++++++++++++++++ arch/arm64/boot/dts/sprd/whale2.dtsi | 2 +- 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi index 7b7d8ce..95746b2 100644 --- a/arch/arm64/boot/dts/sprd/sc9860.dtsi +++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi @@ -7,6 +7,7 @@ */ #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/sprd,sc9860-clk.h> #include "whale2.dtsi" / { @@ -183,6 +184,120 @@ }; soc { + pmu_gate: pmu-gate { + compatible = "sprd,sc9860-pmu-gate"; + sprd,syscon = <&pmu_apb>; /* 0x402b0000 */ + clocks = <&ext_26m>; + #clock-cells = <1>; + }; + + pll: pll { + compatible = "sprd,sc9860-pll"; + sprd,syscon = <&ana_apb>; /* 0x40400000 */ + clocks = <&pmu_gate 0>; + #clock-cells = <1>; + }; + + ap_clk: clock-controller at 20000000 { + compatible = "sprd,sc9860-ap-clk"; + reg = <0 0x20000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>, + <&pmu_gate 0>; + #clock-cells = <1>; + }; + + aon_prediv: aon-prediv { + compatible = "sprd,sc9860-aon-prediv"; + reg = <0 0x402d0000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>, + <&pmu_gate 0>; + #clock-cells = <1>; + }; + + apahb_gate: apahb-gate { + compatible = "sprd,sc9860-apahb-gate"; + sprd,syscon = <&ap_ahb>; /* 0x20210000 */ + clocks = <&aon_prediv 0>; + #clock-cells = <1>; + }; + + aon_gate: aon-gate { + compatible = "sprd,sc9860-aon-gate"; + sprd,syscon = <&aon_apb>; /* 0x402e0000 */ + clocks = <&aon_prediv 0>; + #clock-cells = <1>; + }; + + aonsecure_clk: clock-controller at 40880000 { + compatible = "sprd,sc9860-aonsecure-clk"; + reg = <0 0x40880000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + agcp_gate: agcp-gate { + compatible = "sprd,sc9860-agcp-gate"; + sprd,syscon = <&agcp_ahb>; /* 0x415e0000 */ + clocks = <&aon_prediv 0>; + #clock-cells = <1>; + }; + + gpu_clk: clock-controller at 60200000 { + compatible = "sprd,sc9860-gpu-clk"; + reg = <0 0x60200000 0 0x400>; + clocks = <&pll 0>; + #clock-cells = <1>; + }; + + vsp_clk: clock-controller at 61000000 { + compatible = "sprd,sc9860-vsp-clk"; + reg = <0 0x61000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + vsp_gate: vsp-gate { + compatible = "sprd,sc9860-vsp-gate"; + sprd,syscon = <&vsp_ahb>; /* 0x61100000 */ + clocks = <&vsp_clk 0>; + #clock-cells = <1>; + }; + + cam_clk: clock-controller at 62000000 { + compatible = "sprd,sc9860-cam-clk"; + reg = <0 0x62000000 0 0x4000>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + cam_gate: cam-gate { + compatible = "sprd,sc9860-cam-gate"; + sprd,syscon = <&cam_ahb>; /* 0x62100000 */ + clocks = <&cam_clk 0>; + #clock-cells = <1>; + }; + + disp_clk: clock-controller at 63000000 { + compatible = "sprd,sc9860-disp-clk"; + reg = <0 0x63000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + disp_gate: disp-gate { + compatible = "sprd,sc9860-disp-gate"; + sprd,syscon = <&disp_ahb>; /* 0x63100000 */ + clocks = <&disp_clk 0>; + #clock-cells = <1>; + }; + + apapb_gate: apapb-gate { + compatible = "sprd,sc9860-apapb-gate"; + sprd,syscon = <&ap_apb>; /* 0x70b00000 */ + clocks = <&ap_clk 0>; + #clock-cells = <1>; + }; + funnel at 10001000 { /* SoC Funnel */ compatible = "arm,coresight-funnel", "arm,primecell"; reg = <0 0x10001000 0 0x1000>; diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi index a9995fa..206aaf1 100644 --- a/arch/arm64/boot/dts/sprd/whale2.dtsi +++ b/arch/arm64/boot/dts/sprd/whale2.dtsi @@ -110,6 +110,6 @@ compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <26000000>; - clock-output-names = "ext_26m"; + clock-output-names = "ext-26m"; }; }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH V3 11/11] arm64: dts: add clocks for SC9860 @ 2017-11-02 6:56 ` Chunyan Zhang 0 siblings, 0 replies; 68+ messages in thread From: Chunyan Zhang @ 2017-11-02 6:56 UTC (permalink / raw) To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland Cc: Catalin Marinas, Will Deacon, linux-clk, devicetree, Arnd Bergmann, Mark Brown, Xiaolong Zhang, Ben Li, linux-arm-kernel, linux-kernel, Orson Zhai, Chunyan Zhang Some clocks on SC9860 are in the same address area with syscon devices, those are what have a property of 'sprd,syscon' which would refer to syscon devices, others would have a reg property indicated their address ranges. Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com> --- arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 +++++++++++++++++++++++++++++++++++ arch/arm64/boot/dts/sprd/whale2.dtsi | 2 +- 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi index 7b7d8ce..95746b2 100644 --- a/arch/arm64/boot/dts/sprd/sc9860.dtsi +++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi @@ -7,6 +7,7 @@ */ #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/sprd,sc9860-clk.h> #include "whale2.dtsi" / { @@ -183,6 +184,120 @@ }; soc { + pmu_gate: pmu-gate { + compatible = "sprd,sc9860-pmu-gate"; + sprd,syscon = <&pmu_apb>; /* 0x402b0000 */ + clocks = <&ext_26m>; + #clock-cells = <1>; + }; + + pll: pll { + compatible = "sprd,sc9860-pll"; + sprd,syscon = <&ana_apb>; /* 0x40400000 */ + clocks = <&pmu_gate 0>; + #clock-cells = <1>; + }; + + ap_clk: clock-controller@20000000 { + compatible = "sprd,sc9860-ap-clk"; + reg = <0 0x20000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>, + <&pmu_gate 0>; + #clock-cells = <1>; + }; + + aon_prediv: aon-prediv { + compatible = "sprd,sc9860-aon-prediv"; + reg = <0 0x402d0000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>, + <&pmu_gate 0>; + #clock-cells = <1>; + }; + + apahb_gate: apahb-gate { + compatible = "sprd,sc9860-apahb-gate"; + sprd,syscon = <&ap_ahb>; /* 0x20210000 */ + clocks = <&aon_prediv 0>; + #clock-cells = <1>; + }; + + aon_gate: aon-gate { + compatible = "sprd,sc9860-aon-gate"; + sprd,syscon = <&aon_apb>; /* 0x402e0000 */ + clocks = <&aon_prediv 0>; + #clock-cells = <1>; + }; + + aonsecure_clk: clock-controller@40880000 { + compatible = "sprd,sc9860-aonsecure-clk"; + reg = <0 0x40880000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + agcp_gate: agcp-gate { + compatible = "sprd,sc9860-agcp-gate"; + sprd,syscon = <&agcp_ahb>; /* 0x415e0000 */ + clocks = <&aon_prediv 0>; + #clock-cells = <1>; + }; + + gpu_clk: clock-controller@60200000 { + compatible = "sprd,sc9860-gpu-clk"; + reg = <0 0x60200000 0 0x400>; + clocks = <&pll 0>; + #clock-cells = <1>; + }; + + vsp_clk: clock-controller@61000000 { + compatible = "sprd,sc9860-vsp-clk"; + reg = <0 0x61000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + vsp_gate: vsp-gate { + compatible = "sprd,sc9860-vsp-gate"; + sprd,syscon = <&vsp_ahb>; /* 0x61100000 */ + clocks = <&vsp_clk 0>; + #clock-cells = <1>; + }; + + cam_clk: clock-controller@62000000 { + compatible = "sprd,sc9860-cam-clk"; + reg = <0 0x62000000 0 0x4000>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + cam_gate: cam-gate { + compatible = "sprd,sc9860-cam-gate"; + sprd,syscon = <&cam_ahb>; /* 0x62100000 */ + clocks = <&cam_clk 0>; + #clock-cells = <1>; + }; + + disp_clk: clock-controller@63000000 { + compatible = "sprd,sc9860-disp-clk"; + reg = <0 0x63000000 0 0x400>; + clocks = <&ext_26m>, <&pll 0>; + #clock-cells = <1>; + }; + + disp_gate: disp-gate { + compatible = "sprd,sc9860-disp-gate"; + sprd,syscon = <&disp_ahb>; /* 0x63100000 */ + clocks = <&disp_clk 0>; + #clock-cells = <1>; + }; + + apapb_gate: apapb-gate { + compatible = "sprd,sc9860-apapb-gate"; + sprd,syscon = <&ap_apb>; /* 0x70b00000 */ + clocks = <&ap_clk 0>; + #clock-cells = <1>; + }; + funnel@10001000 { /* SoC Funnel */ compatible = "arm,coresight-funnel", "arm,primecell"; reg = <0 0x10001000 0 0x1000>; diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi index a9995fa..206aaf1 100644 --- a/arch/arm64/boot/dts/sprd/whale2.dtsi +++ b/arch/arm64/boot/dts/sprd/whale2.dtsi @@ -110,6 +110,6 @@ compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <26000000>; - clock-output-names = "ext_26m"; + clock-output-names = "ext-26m"; }; }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 68+ messages in thread
end of thread, other threads:[~2017-11-10 21:10 UTC | newest] Thread overview: 68+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-11-02 6:56 [PATCH V3 00/11] add clock driver for Spreadtrum platforms Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 01/11] drivers: move clock common macros out from vendor directories Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-06 17:15 ` Rob Herring 2017-11-06 17:15 ` Rob Herring 2017-11-06 17:15 ` Rob Herring 2017-11-07 7:01 ` Chunyan Zhang 2017-11-07 7:01 ` Chunyan Zhang 2017-11-07 7:01 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 03/11] clk: sprd: Add common infrastructure Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 04/11] clk: sprd: add gate clock support Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 17:45 ` Julien Thierry 2017-11-02 17:45 ` Julien Thierry 2017-11-03 12:12 ` Chunyan Zhang 2017-11-03 12:12 ` Chunyan Zhang 2017-11-03 12:12 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 05/11] clk: sprd: add mux " Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 18:11 ` Julien Thierry 2017-11-02 18:11 ` Julien Thierry 2017-11-02 18:22 ` Julien Thierry 2017-11-02 18:22 ` Julien Thierry 2017-11-03 12:12 ` Chunyan Zhang 2017-11-03 12:12 ` Chunyan Zhang 2017-11-03 12:12 ` Chunyan Zhang 2017-11-03 12:12 ` Chunyan Zhang 2017-11-03 12:12 ` Chunyan Zhang 2017-11-03 12:12 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 06/11] clk: sprd: add divider " Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 07/11] clk: sprd: add composite " Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 08/11] clk: sprd: add adjustable pll support Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 09/11] clk: sprd: add clocks support for SC9860 Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-05 7:59 ` kbuild test robot 2017-11-05 7:59 ` kbuild test robot 2017-11-05 7:59 ` kbuild test robot 2017-11-06 21:43 ` Rob Herring 2017-11-06 21:43 ` Rob Herring 2017-11-09 8:18 ` Chunyan Zhang 2017-11-09 8:18 ` Chunyan Zhang 2017-11-09 8:18 ` Chunyan Zhang 2017-11-10 21:10 ` Rob Herring 2017-11-10 21:10 ` Rob Herring 2017-11-10 21:10 ` Rob Herring 2017-11-02 6:56 ` [PATCH V3 10/11] arm64: dts: add syscon for whale2 platform Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` [PATCH V3 11/11] arm64: dts: add clocks for SC9860 Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang 2017-11-02 6:56 ` Chunyan Zhang
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.