2017-11-02 07:03:03

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH V3 00/11] add clock driver for Spreadtrum platforms

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


From 1583704521984576166@xxx Fri Nov 10 18:25:27 +0000 2017
X-GM-THRID: 1583555501604787298
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread


2017-11-02 07:04:36

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH V3 07/11] clk: sprd: add composite clock support

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 <[email protected]>
---
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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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


From 1582915656967103546@xxx Thu Nov 02 01:26:47 +0000 2017
X-GM-THRID: 1582915656967103546
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-02 07:03:34

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH V3 01/11] drivers: move clock common macros out from vendor directories

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 <[email protected]>
---
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


From 1584419788600138964@xxx Sat Nov 18 15:54:18 +0000 2017
X-GM-THRID: 1584347621593014254
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-02 07:05:29

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH V3 05/11] clk: sprd: add mux clock support

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 <[email protected]>
---
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 <[email protected]>
+ *
+ * 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, &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);
+ 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 <[email protected]>
+ *
+ * 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


From 1582932671022909347@xxx Thu Nov 02 05:57:12 +0000 2017
X-GM-THRID: 1582159648805349431
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-02 07:05:19

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH V3 11/11] arm64: dts: add clocks for SC9860

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 <[email protected]>
---
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


From 1582914552891769382@xxx Thu Nov 02 01:09:14 +0000 2017
X-GM-THRID: 1582884059549901177
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-02 07:06:09

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH V3 08/11] clk: sprd: add adjustable pll support

Introduced a common adjustable pll clock driver for Spreadtrum SoCs.

Signed-off-by: Chunyan Zhang <[email protected]>
---
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 <[email protected]>
+ *
+ * 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, &reg);
+ 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 <[email protected]>
+ *
+ * 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


From 1583342345373144332@xxx Mon Nov 06 18:28:48 +0000 2017
X-GM-THRID: 1583342345373144332
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-02 07:06:13

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH V3 03/11] clk: sprd: Add common infrastructure

Added Spreadtrum's clock driver framework together with common
structures and interface functions.

Signed-off-by: Chunyan Zhang <[email protected]>
---
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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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


From 1583576415245908082@xxx Thu Nov 09 08:29:15 +0000 2017
X-GM-THRID: 1583576415245908082
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-02 07:05:17

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH V3 10/11] arm64: dts: add syscon for whale2 platform

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 <[email protected]>
---
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


From 1583462616583539733@xxx Wed Nov 08 02:20:28 +0000 2017
X-GM-THRID: 1583462616583539733
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-02 07:05:24

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH V3 02/11] dt-bindings: Add Spreadtrum clock binding documentation

Introduce a new binding with its documentation for Spreadtrum clock
sub-framework.

Signed-off-by: Chunyan Zhang <[email protected]>
---
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


From 1584507042791899136@xxx Sun Nov 19 15:01:10 +0000 2017
X-GM-THRID: 1583250039816445493
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread