All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] clk: hisilicon: support stub clock
@ 2015-03-26 11:13 ` Leo Yan
  0 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: Wei Xu, Dan Zhao, zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	Haojian Zhuang, Bintian Wang, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Leo Yan

This series adds support for hisilicon stub clock driver. On hi6220,
the bootloader needs load the firmware image and set info for OPPs;
after run into kernel, the stub clock driver is used to communicate
w/t firmware for cpu dynamic frequency scaling. So finally s/w will
simply write request in sram and send ipc to power controller.

These patches have been tested on 96board hikey and will be used by
cpufreq driver.

Leo Yan (4):
  clk: hisi: add API for allocation clk data struct
  dt-bindings: clk: hisilicon: Document stub clock driver
  clk: hisi: add stub clk driver
  clk: hisi: add stub clock register function

 .../devicetree/bindings/clock/hisi,stub-clock.txt  |  38 +++
 drivers/clk/hisilicon/Makefile                     |   2 +-
 drivers/clk/hisilicon/clk-stub.c                   | 284 +++++++++++++++++++++
 drivers/clk/hisilicon/clk.c                        |  71 ++++--
 drivers/clk/hisilicon/clk.h                        |  17 ++
 include/dt-bindings/clock/hisi,stub-clock.h        |  26 ++
 6 files changed, 422 insertions(+), 16 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hisi,stub-clock.txt
 create mode 100644 drivers/clk/hisilicon/clk-stub.c
 create mode 100644 include/dt-bindings/clock/hisi,stub-clock.h

-- 
1.9.1

--
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] 18+ messages in thread

* [PATCH 0/4] clk: hisilicon: support stub clock
@ 2015-03-26 11:13 ` Leo Yan
  0 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

This series adds support for hisilicon stub clock driver. On hi6220,
the bootloader needs load the firmware image and set info for OPPs;
after run into kernel, the stub clock driver is used to communicate
w/t firmware for cpu dynamic frequency scaling. So finally s/w will
simply write request in sram and send ipc to power controller.

These patches have been tested on 96board hikey and will be used by
cpufreq driver.

Leo Yan (4):
  clk: hisi: add API for allocation clk data struct
  dt-bindings: clk: hisilicon: Document stub clock driver
  clk: hisi: add stub clk driver
  clk: hisi: add stub clock register function

 .../devicetree/bindings/clock/hisi,stub-clock.txt  |  38 +++
 drivers/clk/hisilicon/Makefile                     |   2 +-
 drivers/clk/hisilicon/clk-stub.c                   | 284 +++++++++++++++++++++
 drivers/clk/hisilicon/clk.c                        |  71 ++++--
 drivers/clk/hisilicon/clk.h                        |  17 ++
 include/dt-bindings/clock/hisi,stub-clock.h        |  26 ++
 6 files changed, 422 insertions(+), 16 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hisi,stub-clock.txt
 create mode 100644 drivers/clk/hisilicon/clk-stub.c
 create mode 100644 include/dt-bindings/clock/hisi,stub-clock.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/4] clk: hisi: add API for allocation clk data struct
  2015-03-26 11:13 ` Leo Yan
@ 2015-03-26 11:13     ` Leo Yan
  -1 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: Wei Xu, Dan Zhao, zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	Haojian Zhuang, Bintian Wang, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Leo Yan

In the old clk init function, it will read the register base address
from dts and allocate the clk data structures. But for the some cases,
the clock driver don't need init the reg's base address, which will
directly access mmio region with syscon.

So for clock's initialization, this patch adds one more API which is
only for allocating clock data structure.

Signed-off-by: Leo Yan <leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/clk/hisilicon/clk.c | 42 +++++++++++++++++++++++++++---------------
 drivers/clk/hisilicon/clk.h |  2 ++
 2 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index a078e84..1e4c5c6 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -38,30 +38,17 @@
 
 static DEFINE_SPINLOCK(hisi_clk_lock);
 
-struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
-					     int nr_clks)
+struct hisi_clock_data __init *hisi_clk_alloc_data(struct device_node *np,
+						   int nr_clks)
 {
 	struct hisi_clock_data *clk_data;
 	struct clk **clk_table;
-	void __iomem *base;
-
-	if (np) {
-		base = of_iomap(np, 0);
-		if (!base) {
-			pr_err("failed to map Hisilicon clock registers\n");
-			goto err;
-		}
-	} else {
-		pr_err("failed to find Hisilicon clock node in DTS\n");
-		goto err;
-	}
 
 	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
 	if (!clk_data) {
 		pr_err("%s: could not allocate clock data\n", __func__);
 		goto err;
 	}
-	clk_data->base = base;
 
 	clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
 	if (!clk_table) {
@@ -72,12 +59,37 @@ struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
 	clk_data->clk_data.clk_num = nr_clks;
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
 	return clk_data;
+
 err_data:
 	kfree(clk_data);
 err:
 	return NULL;
 }
 
+struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
+					     int nr_clks)
+{
+	struct hisi_clock_data *clk_data;
+	void __iomem *base;
+
+	if (np) {
+		base = of_iomap(np, 0);
+		if (!base) {
+			pr_err("failed to map Hisilicon clock registers\n");
+			return NULL;
+		}
+		printk("%s: base %p\n", __func__, base);
+	} else {
+		pr_err("failed to find Hisilicon clock node in DTS\n");
+		return NULL;
+	}
+
+	clk_data = hisi_clk_alloc_data(np, nr_clks);
+	if (clk_data)
+		clk_data->base = base;
+	return clk_data;
+}
+
 void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks,
 					 int nums, struct hisi_clock_data *data)
 {
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 31083ff..624f608 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -96,6 +96,8 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				u8, spinlock_t *);
 
 struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
+struct hisi_clock_data __init *hisi_clk_alloc_data(struct device_node *np,
+						   int nr_clks);
 void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
 					int, struct hisi_clock_data *);
 void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
-- 
1.9.1

--
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 related	[flat|nested] 18+ messages in thread

* [PATCH 1/4] clk: hisi: add API for allocation clk data struct
@ 2015-03-26 11:13     ` Leo Yan
  0 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

In the old clk init function, it will read the register base address
from dts and allocate the clk data structures. But for the some cases,
the clock driver don't need init the reg's base address, which will
directly access mmio region with syscon.

So for clock's initialization, this patch adds one more API which is
only for allocating clock data structure.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 drivers/clk/hisilicon/clk.c | 42 +++++++++++++++++++++++++++---------------
 drivers/clk/hisilicon/clk.h |  2 ++
 2 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index a078e84..1e4c5c6 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -38,30 +38,17 @@
 
 static DEFINE_SPINLOCK(hisi_clk_lock);
 
-struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
-					     int nr_clks)
+struct hisi_clock_data __init *hisi_clk_alloc_data(struct device_node *np,
+						   int nr_clks)
 {
 	struct hisi_clock_data *clk_data;
 	struct clk **clk_table;
-	void __iomem *base;
-
-	if (np) {
-		base = of_iomap(np, 0);
-		if (!base) {
-			pr_err("failed to map Hisilicon clock registers\n");
-			goto err;
-		}
-	} else {
-		pr_err("failed to find Hisilicon clock node in DTS\n");
-		goto err;
-	}
 
 	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
 	if (!clk_data) {
 		pr_err("%s: could not allocate clock data\n", __func__);
 		goto err;
 	}
-	clk_data->base = base;
 
 	clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
 	if (!clk_table) {
@@ -72,12 +59,37 @@ struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
 	clk_data->clk_data.clk_num = nr_clks;
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
 	return clk_data;
+
 err_data:
 	kfree(clk_data);
 err:
 	return NULL;
 }
 
+struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
+					     int nr_clks)
+{
+	struct hisi_clock_data *clk_data;
+	void __iomem *base;
+
+	if (np) {
+		base = of_iomap(np, 0);
+		if (!base) {
+			pr_err("failed to map Hisilicon clock registers\n");
+			return NULL;
+		}
+		printk("%s: base %p\n", __func__, base);
+	} else {
+		pr_err("failed to find Hisilicon clock node in DTS\n");
+		return NULL;
+	}
+
+	clk_data = hisi_clk_alloc_data(np, nr_clks);
+	if (clk_data)
+		clk_data->base = base;
+	return clk_data;
+}
+
 void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks,
 					 int nums, struct hisi_clock_data *data)
 {
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 31083ff..624f608 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -96,6 +96,8 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				u8, spinlock_t *);
 
 struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
+struct hisi_clock_data __init *hisi_clk_alloc_data(struct device_node *np,
+						   int nr_clks);
 void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
 					int, struct hisi_clock_data *);
 void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/4] dt-bindings: clk: hisilicon: Document stub clock driver
  2015-03-26 11:13 ` Leo Yan
@ 2015-03-26 11:13     ` Leo Yan
  -1 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: Wei Xu, Dan Zhao, zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	Haojian Zhuang, Bintian Wang, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Leo Yan

Document the new compatible for stub clock driver which is used for CPU
and DDR's dynamic frequency scaling.

Signed-off-by: Leo Yan <leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 .../devicetree/bindings/clock/hisi,stub-clock.txt  | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/hisi,stub-clock.txt

diff --git a/Documentation/devicetree/bindings/clock/hisi,stub-clock.txt b/Documentation/devicetree/bindings/clock/hisi,stub-clock.txt
new file mode 100644
index 0000000..07ef5a11
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hisi,stub-clock.txt
@@ -0,0 +1,38 @@
+* Clock bindings for Hisilicon Stub Clock Driver
+
+The Hisilicon stub clock will directly send dynamic frequency scaling request
+to power controller, then the power controller will handle the request for
+cpu and ddr's frequency change.
+
+Required properties:
+- compatible: must be "hisilicon,hisi-clock-stub"
+- hisilicon,clk-stub-sram: phandle to the syscon managing the SoC internal sram;
+  the driver need use the sram to pass parameters for frequency change.
+- hisilicon,clk-stub-mc: phandle to the syscon managing the multi-cores'
+  communication; need set related register to trigger the dynamic frequency
+  scaling.
+- #clock-cells: should be <1>
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hisi,stub-clock.h>.
+
+Example:
+
+	sram: sram {
+		compatible = "hisilicon,sram", "syscon";
+		reg = <0x0 0xFFF80000 0x0 0x12000>;
+	};
+
+	ipc_s: ipc_s {
+		compatible = "hisilicon,ipc-s", "syscon";
+		reg = <0x0 0xF7510000 0x0 0x1000>;
+	};
+
+	clock_stub: clock_stub {
+		compatible = "hisilicon,hisi-clock-stub";
+		hisilicon,clk-stub-sram = <&sram>;
+		hisilicon,clk-stub-mc = <&ipc_s>;
+		#clock-cells = <1>;
+	};
-- 
1.9.1

--
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 related	[flat|nested] 18+ messages in thread

* [PATCH 2/4] dt-bindings: clk: hisilicon: Document stub clock driver
@ 2015-03-26 11:13     ` Leo Yan
  0 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

Document the new compatible for stub clock driver which is used for CPU
and DDR's dynamic frequency scaling.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 .../devicetree/bindings/clock/hisi,stub-clock.txt  | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/hisi,stub-clock.txt

diff --git a/Documentation/devicetree/bindings/clock/hisi,stub-clock.txt b/Documentation/devicetree/bindings/clock/hisi,stub-clock.txt
new file mode 100644
index 0000000..07ef5a11
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hisi,stub-clock.txt
@@ -0,0 +1,38 @@
+* Clock bindings for Hisilicon Stub Clock Driver
+
+The Hisilicon stub clock will directly send dynamic frequency scaling request
+to power controller, then the power controller will handle the request for
+cpu and ddr's frequency change.
+
+Required properties:
+- compatible: must be "hisilicon,hisi-clock-stub"
+- hisilicon,clk-stub-sram: phandle to the syscon managing the SoC internal sram;
+  the driver need use the sram to pass parameters for frequency change.
+- hisilicon,clk-stub-mc: phandle to the syscon managing the multi-cores'
+  communication; need set related register to trigger the dynamic frequency
+  scaling.
+- #clock-cells: should be <1>
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hisi,stub-clock.h>.
+
+Example:
+
+	sram: sram {
+		compatible = "hisilicon,sram", "syscon";
+		reg = <0x0 0xFFF80000 0x0 0x12000>;
+	};
+
+	ipc_s: ipc_s {
+		compatible = "hisilicon,ipc-s", "syscon";
+		reg = <0x0 0xF7510000 0x0 0x1000>;
+	};
+
+	clock_stub: clock_stub {
+		compatible = "hisilicon,hisi-clock-stub";
+		hisilicon,clk-stub-sram = <&sram>;
+		hisilicon,clk-stub-mc = <&ipc_s>;
+		#clock-cells = <1>;
+	};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/4] clk: hisi: add stub clk driver
  2015-03-26 11:13 ` Leo Yan
@ 2015-03-26 11:13     ` Leo Yan
  -1 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: Wei Xu, Dan Zhao, zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	Haojian Zhuang, Bintian Wang, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Leo Yan

On hisilicon platform, there have some clocks which can directly send
messages to power controller to change frequency; this includes cpu and
ddr's clocks.

For dynamic frequency scaling, firstly need write the frequency value
to sram region, and then write the communication register to trigger
power controller to run the state machine. These two part's addresses
are different and will be shared w/t other module; so use syscon APIs
to pass these two memory region and accessing related registers.

This init driver will support cpu frequency change firstly.

Signed-off-by: Leo Yan <leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/clk/hisilicon/Makefile              |   2 +-
 drivers/clk/hisilicon/clk-stub.c            | 284 ++++++++++++++++++++++++++++
 drivers/clk/hisilicon/clk.h                 |   3 +
 include/dt-bindings/clock/hisi,stub-clock.h |  26 +++
 4 files changed, 314 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/hisilicon/clk-stub.c
 create mode 100644 include/dt-bindings/clock/hisi,stub-clock.h

diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index 038c02f..fb26ac8 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -2,7 +2,7 @@
 # Hisilicon Clock specific Makefile
 #
 
-obj-y	+= clk.o clkgate-separated.o
+obj-y	+= clk.o clkgate-separated.o clk-stub.o
 
 obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
diff --git a/drivers/clk/hisilicon/clk-stub.c b/drivers/clk/hisilicon/clk-stub.c
new file mode 100644
index 0000000..897d6d3
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-stub.c
@@ -0,0 +1,284 @@
+/*
+ * Hisilicon stub clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ * Copyright (c) 2015 Linaro Limited.
+ *
+ * Author: Leo Yan <leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <asm/compiler.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/hisi,stub-clock.h>
+
+/* CPU dynamic frequency scaling */
+#define ACPU_DFS_FREQ_MAX		(0x1724)
+#define ACPU_DFS_FLAG			(0x1AF4)
+#define ACPU_DFS_FREQ_REQ		(0x1AF8)
+#define ACPU_DFS_FREQ_LMT		(0x1AFC)
+
+#define ACPU_DFS_LOCK_FLAG		(0xAEAEAEAE)
+
+/* Multi-core communication */
+#define MC_CORE_ACPU			0x2
+#define MC_COM_CPU_RAW_INT_OFFSET(i)	(0x400 + (i << 4))
+#define MC_COM_INT_ACPU_DFS		15
+
+#define to_stub_clk(hw) container_of(hw, struct hisi_stub_clk, hw)
+
+struct hisi_stub_clk {
+	struct clk_hw	hw;
+
+	/*
+	 * hi6220:
+	 *  - 0: A53; 1: A53;  2: gpu;  3: ddr;
+	 */
+	u32		id;
+	u32		rate;
+	spinlock_t	*lock;
+};
+
+static int initialized_stub_clk = 0;
+static struct regmap *mc_map = NULL;
+static struct regmap *dfs_map = NULL;
+
+static unsigned int hisi_acpu_get_freq(void)
+{
+	unsigned int freq;
+
+	regmap_read(dfs_map, ACPU_DFS_FREQ_REQ, &freq);
+	return freq;
+}
+
+static int hisi_acpu_set_freq(unsigned int freq)
+{
+	/* set the frequency in sram */
+	regmap_write(dfs_map, ACPU_DFS_FREQ_REQ, freq);
+
+	/* send request to power controller */
+	regmap_write(mc_map, MC_COM_CPU_RAW_INT_OFFSET(MC_CORE_ACPU),
+		     (1 << MC_COM_INT_ACPU_DFS));
+	return 0;
+}
+
+static int hisi_acpu_round_freq(unsigned int freq)
+{
+	unsigned int limit_flag, limit_freq = UINT_MAX;
+	unsigned int max_freq;
+
+	/* check the constrainted frequency */
+	regmap_read(dfs_map, ACPU_DFS_FLAG, &limit_flag);
+	if (limit_flag == ACPU_DFS_LOCK_FLAG)
+		regmap_read(dfs_map, ACPU_DFS_FREQ_LMT, &limit_freq);
+
+	/* check the supported maximum frequency */
+	regmap_read(dfs_map, ACPU_DFS_FREQ_MAX, &max_freq);
+
+	/* calculate the real maximum frequency */
+	max_freq = min(max_freq, limit_freq);
+
+	if (WARN_ON(freq > max_freq))
+		freq = max_freq;
+
+	return freq;
+}
+
+static unsigned long hisi_stub_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	u32 rate = 0;
+	struct hisi_stub_clk *stub_clk = to_stub_clk(hw);
+	unsigned long flags;
+
+	BUG_ON(!stub_clk->lock);
+
+	spin_lock_irqsave(stub_clk->lock, flags);
+
+	switch (stub_clk->id) {
+	case HISI_STUB_ACPU0:
+		rate = hisi_acpu_get_freq();
+
+		/* convert from KHz to Hz */
+		rate *= 1000;
+		break;
+
+	default:
+		pr_err("%s: un-supported clock id %d\n", __func__,
+			stub_clk->id);
+		break;
+	}
+
+	spin_unlock_irqrestore(stub_clk->lock, flags);
+	return rate;
+}
+
+static int hisi_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                    unsigned long parent_rate)
+{
+	struct hisi_stub_clk *stub_clk = to_stub_clk(hw);
+	unsigned long flags;
+	unsigned long new_rate = rate / 1000;  /* Khz */
+	int ret = 0;
+
+	BUG_ON(!stub_clk->lock);
+
+	spin_lock_irqsave(stub_clk->lock, flags);
+
+	switch (stub_clk->id) {
+	case HISI_STUB_ACPU0:
+		ret = hisi_acpu_set_freq(new_rate);
+		if (ret < 0) {
+			spin_unlock_irqrestore(stub_clk->lock, flags);
+			return ret;
+		}
+
+		break;
+
+	default:
+		pr_err("%s: un-supported clock id %d\n", __func__,
+			stub_clk->id);
+		break;
+	}
+
+	stub_clk->rate = new_rate;
+	spin_unlock_irqrestore(stub_clk->lock, flags);
+
+	pr_debug("%s: set rate=%ldKhz\n", __func__, new_rate);
+	return ret;
+}
+
+static long hisi_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	struct hisi_stub_clk *stub_clk = to_stub_clk(hw);
+	unsigned long flags;
+	unsigned long new_rate = rate / 1000;  /* Khz */
+
+	BUG_ON(!stub_clk->lock);
+
+	spin_lock_irqsave(stub_clk->lock, flags);
+
+	switch (stub_clk->id) {
+	case HISI_STUB_ACPU0:
+		new_rate = hisi_acpu_round_freq(new_rate);
+
+		/* convert from KHz to Hz */
+		new_rate *= 1000;
+		break;
+
+	default:
+		pr_err("%s: un-supported clock id %d\n", __func__,
+			stub_clk->id);
+		break;
+	}
+
+	spin_unlock_irqrestore(stub_clk->lock, flags);
+	return new_rate;
+}
+
+static struct clk_ops hisi_stub_clk_ops = {
+	.recalc_rate	= hisi_stub_clk_recalc_rate,
+	.round_rate	= hisi_stub_clk_round_rate,
+	.set_rate	= hisi_stub_clk_set_rate,
+};
+
+static int hisi_stub_clk_init(struct device_node *np)
+{
+	int ret = 0;
+	int max_freq;
+
+	dfs_map = syscon_regmap_lookup_by_phandle(np,
+				"hisilicon,clk-stub-sram");
+	if (IS_ERR(dfs_map)) {
+		ret = PTR_ERR(dfs_map);
+		pr_err("failed to get sram regmap: %d\n", ret);
+		return ret;
+	}
+
+	mc_map = syscon_regmap_lookup_by_phandle(np,
+				"hisilicon,clk-stub-mc");
+	if (IS_ERR(mc_map)) {
+		ret = PTR_ERR(mc_map);
+		pr_err("failed to get multi-core comm regmap: %d\n", ret);
+		return ret;
+	}
+
+	/* initialize buffer to zero */
+	regmap_write(dfs_map, ACPU_DFS_FLAG, 0x0);
+	regmap_write(dfs_map, ACPU_DFS_FREQ_REQ, 0x0);
+	regmap_write(dfs_map, ACPU_DFS_FREQ_LMT, 0x0);
+
+	/* At boot time, set to maximum frequency */
+	regmap_read(dfs_map, ACPU_DFS_FREQ_MAX, &max_freq);
+	hisi_acpu_set_freq(max_freq);
+
+	return ret;
+}
+
+static struct clk *_register_stub_clk(struct device *dev, unsigned int id,
+	const char *name, const char *parent_name, unsigned long flags,
+	spinlock_t *lock)
+{
+	struct hisi_stub_clk *stub_clk;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	stub_clk = kzalloc(sizeof(*stub_clk), GFP_KERNEL);
+	if (!stub_clk) {
+		pr_err("%s: fail to alloc stub clk!\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &hisi_stub_clk_ops;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+	init.flags = flags;
+
+	stub_clk->hw.init = &init;
+	stub_clk->id = id;
+	stub_clk->lock = lock;
+
+	clk = clk_register(dev, &stub_clk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: fail to register stub clk %s!\n", __func__, name);
+		kfree(stub_clk);
+	}
+
+	return clk;
+}
+
+struct clk *hisi_register_stub_clk(struct device_node *np,
+		unsigned int id, const char *name, const char *parent_name,
+		unsigned long flags, spinlock_t *lock)
+{
+	int ret;
+	struct clk *clk;
+
+	pr_debug("[%s]: clk name = %s...\n", __func__, name);
+
+	if (!initialized_stub_clk) {
+		ret = hisi_stub_clk_init(np);
+		if (ret)
+			return ERR_PTR(-EINVAL);
+
+		initialized_stub_clk = 1;
+	}
+
+	clk = _register_stub_clk(NULL, id, name, parent_name, flags, lock);
+	return clk;
+}
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 624f608..e99184a 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -94,6 +94,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				const char *, unsigned long,
 				void __iomem *, u8,
 				u8, spinlock_t *);
+struct clk *hisi_register_stub_clk(struct device_node *np,
+	unsigned int id, const char *name, const char *parent_name,
+	unsigned long flags, spinlock_t *lock);
 
 struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
 struct hisi_clock_data __init *hisi_clk_alloc_data(struct device_node *np,
diff --git a/include/dt-bindings/clock/hisi,stub-clock.h b/include/dt-bindings/clock/hisi,stub-clock.h
new file mode 100644
index 0000000..637d7f5
--- /dev/null
+++ b/include/dt-bindings/clock/hisi,stub-clock.h
@@ -0,0 +1,26 @@
+/*
+ * This header provides constants for Hisilicon stub clock driver.
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ * Copyright (c) 2015 Linaro Limited.
+ *
+ * Author: Leo Yan <leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DT_BINDINGS_HISI_STUB_CLOCK_H
+#define _DT_BINDINGS_HISI_STUB_CLOCK_H
+
+/* Stub Clocks */
+#define HISI_STUB_ACPU0		0
+#define HISI_STUB_ACPU1		1
+#define HISI_STUB_GPU		2
+#define HISI_STUB_DDR_MIN	3
+#define HISI_STUB_DDR_MAX	4
+#define HISI_STUB_DDR		5
+#define HISI_STUB_NR_CLKS	6
+
+#endif /* _DT_BINDINGS_HISI_STUB_CLOCK_H */
-- 
1.9.1

--
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 related	[flat|nested] 18+ messages in thread

* [PATCH 3/4] clk: hisi: add stub clk driver
@ 2015-03-26 11:13     ` Leo Yan
  0 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

On hisilicon platform, there have some clocks which can directly send
messages to power controller to change frequency; this includes cpu and
ddr's clocks.

For dynamic frequency scaling, firstly need write the frequency value
to sram region, and then write the communication register to trigger
power controller to run the state machine. These two part's addresses
are different and will be shared w/t other module; so use syscon APIs
to pass these two memory region and accessing related registers.

This init driver will support cpu frequency change firstly.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 drivers/clk/hisilicon/Makefile              |   2 +-
 drivers/clk/hisilicon/clk-stub.c            | 284 ++++++++++++++++++++++++++++
 drivers/clk/hisilicon/clk.h                 |   3 +
 include/dt-bindings/clock/hisi,stub-clock.h |  26 +++
 4 files changed, 314 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/hisilicon/clk-stub.c
 create mode 100644 include/dt-bindings/clock/hisi,stub-clock.h

diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index 038c02f..fb26ac8 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -2,7 +2,7 @@
 # Hisilicon Clock specific Makefile
 #
 
-obj-y	+= clk.o clkgate-separated.o
+obj-y	+= clk.o clkgate-separated.o clk-stub.o
 
 obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
diff --git a/drivers/clk/hisilicon/clk-stub.c b/drivers/clk/hisilicon/clk-stub.c
new file mode 100644
index 0000000..897d6d3
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-stub.c
@@ -0,0 +1,284 @@
+/*
+ * Hisilicon stub clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ * Copyright (c) 2015 Linaro Limited.
+ *
+ * Author: Leo Yan <leo.yan@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <asm/compiler.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/hisi,stub-clock.h>
+
+/* CPU dynamic frequency scaling */
+#define ACPU_DFS_FREQ_MAX		(0x1724)
+#define ACPU_DFS_FLAG			(0x1AF4)
+#define ACPU_DFS_FREQ_REQ		(0x1AF8)
+#define ACPU_DFS_FREQ_LMT		(0x1AFC)
+
+#define ACPU_DFS_LOCK_FLAG		(0xAEAEAEAE)
+
+/* Multi-core communication */
+#define MC_CORE_ACPU			0x2
+#define MC_COM_CPU_RAW_INT_OFFSET(i)	(0x400 + (i << 4))
+#define MC_COM_INT_ACPU_DFS		15
+
+#define to_stub_clk(hw) container_of(hw, struct hisi_stub_clk, hw)
+
+struct hisi_stub_clk {
+	struct clk_hw	hw;
+
+	/*
+	 * hi6220:
+	 *  - 0: A53; 1: A53;  2: gpu;  3: ddr;
+	 */
+	u32		id;
+	u32		rate;
+	spinlock_t	*lock;
+};
+
+static int initialized_stub_clk = 0;
+static struct regmap *mc_map = NULL;
+static struct regmap *dfs_map = NULL;
+
+static unsigned int hisi_acpu_get_freq(void)
+{
+	unsigned int freq;
+
+	regmap_read(dfs_map, ACPU_DFS_FREQ_REQ, &freq);
+	return freq;
+}
+
+static int hisi_acpu_set_freq(unsigned int freq)
+{
+	/* set the frequency in sram */
+	regmap_write(dfs_map, ACPU_DFS_FREQ_REQ, freq);
+
+	/* send request to power controller */
+	regmap_write(mc_map, MC_COM_CPU_RAW_INT_OFFSET(MC_CORE_ACPU),
+		     (1 << MC_COM_INT_ACPU_DFS));
+	return 0;
+}
+
+static int hisi_acpu_round_freq(unsigned int freq)
+{
+	unsigned int limit_flag, limit_freq = UINT_MAX;
+	unsigned int max_freq;
+
+	/* check the constrainted frequency */
+	regmap_read(dfs_map, ACPU_DFS_FLAG, &limit_flag);
+	if (limit_flag == ACPU_DFS_LOCK_FLAG)
+		regmap_read(dfs_map, ACPU_DFS_FREQ_LMT, &limit_freq);
+
+	/* check the supported maximum frequency */
+	regmap_read(dfs_map, ACPU_DFS_FREQ_MAX, &max_freq);
+
+	/* calculate the real maximum frequency */
+	max_freq = min(max_freq, limit_freq);
+
+	if (WARN_ON(freq > max_freq))
+		freq = max_freq;
+
+	return freq;
+}
+
+static unsigned long hisi_stub_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	u32 rate = 0;
+	struct hisi_stub_clk *stub_clk = to_stub_clk(hw);
+	unsigned long flags;
+
+	BUG_ON(!stub_clk->lock);
+
+	spin_lock_irqsave(stub_clk->lock, flags);
+
+	switch (stub_clk->id) {
+	case HISI_STUB_ACPU0:
+		rate = hisi_acpu_get_freq();
+
+		/* convert from KHz to Hz */
+		rate *= 1000;
+		break;
+
+	default:
+		pr_err("%s: un-supported clock id %d\n", __func__,
+			stub_clk->id);
+		break;
+	}
+
+	spin_unlock_irqrestore(stub_clk->lock, flags);
+	return rate;
+}
+
+static int hisi_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                    unsigned long parent_rate)
+{
+	struct hisi_stub_clk *stub_clk = to_stub_clk(hw);
+	unsigned long flags;
+	unsigned long new_rate = rate / 1000;  /* Khz */
+	int ret = 0;
+
+	BUG_ON(!stub_clk->lock);
+
+	spin_lock_irqsave(stub_clk->lock, flags);
+
+	switch (stub_clk->id) {
+	case HISI_STUB_ACPU0:
+		ret = hisi_acpu_set_freq(new_rate);
+		if (ret < 0) {
+			spin_unlock_irqrestore(stub_clk->lock, flags);
+			return ret;
+		}
+
+		break;
+
+	default:
+		pr_err("%s: un-supported clock id %d\n", __func__,
+			stub_clk->id);
+		break;
+	}
+
+	stub_clk->rate = new_rate;
+	spin_unlock_irqrestore(stub_clk->lock, flags);
+
+	pr_debug("%s: set rate=%ldKhz\n", __func__, new_rate);
+	return ret;
+}
+
+static long hisi_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	struct hisi_stub_clk *stub_clk = to_stub_clk(hw);
+	unsigned long flags;
+	unsigned long new_rate = rate / 1000;  /* Khz */
+
+	BUG_ON(!stub_clk->lock);
+
+	spin_lock_irqsave(stub_clk->lock, flags);
+
+	switch (stub_clk->id) {
+	case HISI_STUB_ACPU0:
+		new_rate = hisi_acpu_round_freq(new_rate);
+
+		/* convert from KHz to Hz */
+		new_rate *= 1000;
+		break;
+
+	default:
+		pr_err("%s: un-supported clock id %d\n", __func__,
+			stub_clk->id);
+		break;
+	}
+
+	spin_unlock_irqrestore(stub_clk->lock, flags);
+	return new_rate;
+}
+
+static struct clk_ops hisi_stub_clk_ops = {
+	.recalc_rate	= hisi_stub_clk_recalc_rate,
+	.round_rate	= hisi_stub_clk_round_rate,
+	.set_rate	= hisi_stub_clk_set_rate,
+};
+
+static int hisi_stub_clk_init(struct device_node *np)
+{
+	int ret = 0;
+	int max_freq;
+
+	dfs_map = syscon_regmap_lookup_by_phandle(np,
+				"hisilicon,clk-stub-sram");
+	if (IS_ERR(dfs_map)) {
+		ret = PTR_ERR(dfs_map);
+		pr_err("failed to get sram regmap: %d\n", ret);
+		return ret;
+	}
+
+	mc_map = syscon_regmap_lookup_by_phandle(np,
+				"hisilicon,clk-stub-mc");
+	if (IS_ERR(mc_map)) {
+		ret = PTR_ERR(mc_map);
+		pr_err("failed to get multi-core comm regmap: %d\n", ret);
+		return ret;
+	}
+
+	/* initialize buffer to zero */
+	regmap_write(dfs_map, ACPU_DFS_FLAG, 0x0);
+	regmap_write(dfs_map, ACPU_DFS_FREQ_REQ, 0x0);
+	regmap_write(dfs_map, ACPU_DFS_FREQ_LMT, 0x0);
+
+	/* At boot time, set to maximum frequency */
+	regmap_read(dfs_map, ACPU_DFS_FREQ_MAX, &max_freq);
+	hisi_acpu_set_freq(max_freq);
+
+	return ret;
+}
+
+static struct clk *_register_stub_clk(struct device *dev, unsigned int id,
+	const char *name, const char *parent_name, unsigned long flags,
+	spinlock_t *lock)
+{
+	struct hisi_stub_clk *stub_clk;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	stub_clk = kzalloc(sizeof(*stub_clk), GFP_KERNEL);
+	if (!stub_clk) {
+		pr_err("%s: fail to alloc stub clk!\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &hisi_stub_clk_ops;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+	init.flags = flags;
+
+	stub_clk->hw.init = &init;
+	stub_clk->id = id;
+	stub_clk->lock = lock;
+
+	clk = clk_register(dev, &stub_clk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: fail to register stub clk %s!\n", __func__, name);
+		kfree(stub_clk);
+	}
+
+	return clk;
+}
+
+struct clk *hisi_register_stub_clk(struct device_node *np,
+		unsigned int id, const char *name, const char *parent_name,
+		unsigned long flags, spinlock_t *lock)
+{
+	int ret;
+	struct clk *clk;
+
+	pr_debug("[%s]: clk name = %s...\n", __func__, name);
+
+	if (!initialized_stub_clk) {
+		ret = hisi_stub_clk_init(np);
+		if (ret)
+			return ERR_PTR(-EINVAL);
+
+		initialized_stub_clk = 1;
+	}
+
+	clk = _register_stub_clk(NULL, id, name, parent_name, flags, lock);
+	return clk;
+}
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 624f608..e99184a 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -94,6 +94,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				const char *, unsigned long,
 				void __iomem *, u8,
 				u8, spinlock_t *);
+struct clk *hisi_register_stub_clk(struct device_node *np,
+	unsigned int id, const char *name, const char *parent_name,
+	unsigned long flags, spinlock_t *lock);
 
 struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
 struct hisi_clock_data __init *hisi_clk_alloc_data(struct device_node *np,
diff --git a/include/dt-bindings/clock/hisi,stub-clock.h b/include/dt-bindings/clock/hisi,stub-clock.h
new file mode 100644
index 0000000..637d7f5
--- /dev/null
+++ b/include/dt-bindings/clock/hisi,stub-clock.h
@@ -0,0 +1,26 @@
+/*
+ * This header provides constants for Hisilicon stub clock driver.
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ * Copyright (c) 2015 Linaro Limited.
+ *
+ * Author: Leo Yan <leo.yan@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DT_BINDINGS_HISI_STUB_CLOCK_H
+#define _DT_BINDINGS_HISI_STUB_CLOCK_H
+
+/* Stub Clocks */
+#define HISI_STUB_ACPU0		0
+#define HISI_STUB_ACPU1		1
+#define HISI_STUB_GPU		2
+#define HISI_STUB_DDR_MIN	3
+#define HISI_STUB_DDR_MAX	4
+#define HISI_STUB_DDR		5
+#define HISI_STUB_NR_CLKS	6
+
+#endif /* _DT_BINDINGS_HISI_STUB_CLOCK_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/4] clk: hisi: add stub clock register function
  2015-03-26 11:13 ` Leo Yan
@ 2015-03-26 11:13     ` Leo Yan
  -1 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: Wei Xu, Dan Zhao, zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	Haojian Zhuang, Bintian Wang, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Leo Yan

Add stub clock register function, so can easily enable stub clock for
platforms.

Signed-off-by: Leo Yan <leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/clk/hisilicon/clk.c | 29 +++++++++++++++++++++++++++++
 drivers/clk/hisilicon/clk.h | 12 ++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index 1e4c5c6..74ce813 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -244,3 +244,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+
+void __init hisi_clk_register_stub(struct hisi_stub_clock *clks, int nums,
+				   struct hisi_clock_data *data,
+				   struct device_node *np)
+{
+	struct clk *clk;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = hisi_register_stub_clk(np,
+					     clks[i].id,
+					     clks[i].name,
+					     clks[i].parent_name,
+					     clks[i].flags,
+					     &hisi_clk_lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+
+		if (clks[i].alias)
+			clk_register_clkdev(clk, clks[i].name, NULL);
+
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return;
+}
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index e99184a..89ce9ad 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -90,6 +90,14 @@ struct hisi_gate_clock {
 	const char		*alias;
 };
 
+struct hisi_stub_clock {
+	unsigned int		id;
+	char			*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	const char		*alias;
+};
+
 struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				const char *, unsigned long,
 				void __iomem *, u8,
@@ -113,4 +121,8 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
 void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
+void __init hisi_clk_register_stub(struct hisi_stub_clock *clks, int nums,
+				   struct hisi_clock_data *data,
+				   struct device_node *np);
+
 #endif	/* __HISI_CLK_H */
-- 
1.9.1

--
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 related	[flat|nested] 18+ messages in thread

* [PATCH 4/4] clk: hisi: add stub clock register function
@ 2015-03-26 11:13     ` Leo Yan
  0 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-26 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

Add stub clock register function, so can easily enable stub clock for
platforms.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 drivers/clk/hisilicon/clk.c | 29 +++++++++++++++++++++++++++++
 drivers/clk/hisilicon/clk.h | 12 ++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index 1e4c5c6..74ce813 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -244,3 +244,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+
+void __init hisi_clk_register_stub(struct hisi_stub_clock *clks, int nums,
+				   struct hisi_clock_data *data,
+				   struct device_node *np)
+{
+	struct clk *clk;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = hisi_register_stub_clk(np,
+					     clks[i].id,
+					     clks[i].name,
+					     clks[i].parent_name,
+					     clks[i].flags,
+					     &hisi_clk_lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+
+		if (clks[i].alias)
+			clk_register_clkdev(clk, clks[i].name, NULL);
+
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return;
+}
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index e99184a..89ce9ad 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -90,6 +90,14 @@ struct hisi_gate_clock {
 	const char		*alias;
 };
 
+struct hisi_stub_clock {
+	unsigned int		id;
+	char			*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	const char		*alias;
+};
+
 struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				const char *, unsigned long,
 				void __iomem *, u8,
@@ -113,4 +121,8 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
 void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
+void __init hisi_clk_register_stub(struct hisi_stub_clock *clks, int nums,
+				   struct hisi_clock_data *data,
+				   struct device_node *np);
+
 #endif	/* __HISI_CLK_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/4] clk: hisi: add API for allocation clk data struct
  2015-03-26 11:13     ` Leo Yan
@ 2015-03-26 14:18         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 18+ messages in thread
From: Russell King - ARM Linux @ 2015-03-26 14:18 UTC (permalink / raw)
  To: Leo Yan
  Cc: Wei Xu, Dan Zhao, zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	Haojian Zhuang, Bintian Wang, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Thu, Mar 26, 2015 at 07:13:36PM +0800, Leo Yan wrote:
> +struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
> +					     int nr_clks)
> +{
> +	struct hisi_clock_data *clk_data;
> +	void __iomem *base;
> +
> +	if (np) {
> +		base = of_iomap(np, 0);
> +		if (!base) {
> +			pr_err("failed to map Hisilicon clock registers\n");
> +			return NULL;
> +		}
> +		printk("%s: base %p\n", __func__, base);

Did you leave your debugging in?

> +	} else {
> +		pr_err("failed to find Hisilicon clock node in DTS\n");
> +		return NULL;
> +	}

I know you're mostly only moving this code, but it would be far better if
it were written:

	if (!np) {
		pr_err("failed to find Hisilicon clock node in DTS\n");
		return NULL;
	}

	base = of_iomap(np, 0);
	if (!base) {
		pr_err("failed to map Hisilicon clock registers\n");
		return NULL;
	}

Possibly do this first as a separate patch, and then move the code.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
--
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] 18+ messages in thread

* [PATCH 1/4] clk: hisi: add API for allocation clk data struct
@ 2015-03-26 14:18         ` Russell King - ARM Linux
  0 siblings, 0 replies; 18+ messages in thread
From: Russell King - ARM Linux @ 2015-03-26 14:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 26, 2015 at 07:13:36PM +0800, Leo Yan wrote:
> +struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
> +					     int nr_clks)
> +{
> +	struct hisi_clock_data *clk_data;
> +	void __iomem *base;
> +
> +	if (np) {
> +		base = of_iomap(np, 0);
> +		if (!base) {
> +			pr_err("failed to map Hisilicon clock registers\n");
> +			return NULL;
> +		}
> +		printk("%s: base %p\n", __func__, base);

Did you leave your debugging in?

> +	} else {
> +		pr_err("failed to find Hisilicon clock node in DTS\n");
> +		return NULL;
> +	}

I know you're mostly only moving this code, but it would be far better if
it were written:

	if (!np) {
		pr_err("failed to find Hisilicon clock node in DTS\n");
		return NULL;
	}

	base = of_iomap(np, 0);
	if (!base) {
		pr_err("failed to map Hisilicon clock registers\n");
		return NULL;
	}

Possibly do this first as a separate patch, and then move the code.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/4] clk: hisi: add stub clk driver
  2015-03-26 11:13     ` Leo Yan
@ 2015-03-26 14:22         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 18+ messages in thread
From: Russell King - ARM Linux @ 2015-03-26 14:22 UTC (permalink / raw)
  To: Leo Yan
  Cc: Wei Xu, Dan Zhao, zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	Haojian Zhuang, Bintian Wang, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Thu, Mar 26, 2015 at 07:13:38PM +0800, Leo Yan wrote:
> +static unsigned long hisi_stub_clk_recalc_rate(struct clk_hw *hw,
> +		unsigned long parent_rate)
> +{
...
> +	BUG_ON(!stub_clk->lock);
...

> +static int hisi_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> +                    unsigned long parent_rate)
> +{
...
> +	BUG_ON(!stub_clk->lock);
...

> +static long hisi_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
> +		unsigned long *parent_rate)
> +{
...
> +	BUG_ON(!stub_clk->lock);
...

> +static struct clk_ops hisi_stub_clk_ops = {
> +	.recalc_rate	= hisi_stub_clk_recalc_rate,
> +	.round_rate	= hisi_stub_clk_round_rate,
> +	.set_rate	= hisi_stub_clk_set_rate,
> +};
...
> +static struct clk *_register_stub_clk(struct device *dev, unsigned int id,
> +	const char *name, const char *parent_name, unsigned long flags,
> +	spinlock_t *lock)
> +{
> +	struct hisi_stub_clk *stub_clk;
> +	struct clk *clk;
> +	struct clk_init_data init;
> +
> +	stub_clk = kzalloc(sizeof(*stub_clk), GFP_KERNEL);
> +	if (!stub_clk) {
> +		pr_err("%s: fail to alloc stub clk!\n", __func__);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	init.name = name;
> +	init.ops = &hisi_stub_clk_ops;
> +	init.parent_names = parent_name ? &parent_name : NULL;
> +	init.num_parents = parent_name ? 1 : 0;
> +	init.flags = flags;
> +
> +	stub_clk->hw.init = &init;
> +	stub_clk->id = id;
> +	stub_clk->lock = lock;

Under what scenario is it safe to call _register_stub_clk() with a NULL
lock argument?

If lock is NULL, then every function callable via the ops structure
will bug.

Rather than doing a test in each method function, do it in
_register_stub_clk() - this means we aren't waiting for a NULL pointer
deref when one of these method functions gets called.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
--
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] 18+ messages in thread

* [PATCH 3/4] clk: hisi: add stub clk driver
@ 2015-03-26 14:22         ` Russell King - ARM Linux
  0 siblings, 0 replies; 18+ messages in thread
From: Russell King - ARM Linux @ 2015-03-26 14:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 26, 2015 at 07:13:38PM +0800, Leo Yan wrote:
> +static unsigned long hisi_stub_clk_recalc_rate(struct clk_hw *hw,
> +		unsigned long parent_rate)
> +{
...
> +	BUG_ON(!stub_clk->lock);
...

> +static int hisi_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> +                    unsigned long parent_rate)
> +{
...
> +	BUG_ON(!stub_clk->lock);
...

> +static long hisi_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
> +		unsigned long *parent_rate)
> +{
...
> +	BUG_ON(!stub_clk->lock);
...

> +static struct clk_ops hisi_stub_clk_ops = {
> +	.recalc_rate	= hisi_stub_clk_recalc_rate,
> +	.round_rate	= hisi_stub_clk_round_rate,
> +	.set_rate	= hisi_stub_clk_set_rate,
> +};
...
> +static struct clk *_register_stub_clk(struct device *dev, unsigned int id,
> +	const char *name, const char *parent_name, unsigned long flags,
> +	spinlock_t *lock)
> +{
> +	struct hisi_stub_clk *stub_clk;
> +	struct clk *clk;
> +	struct clk_init_data init;
> +
> +	stub_clk = kzalloc(sizeof(*stub_clk), GFP_KERNEL);
> +	if (!stub_clk) {
> +		pr_err("%s: fail to alloc stub clk!\n", __func__);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	init.name = name;
> +	init.ops = &hisi_stub_clk_ops;
> +	init.parent_names = parent_name ? &parent_name : NULL;
> +	init.num_parents = parent_name ? 1 : 0;
> +	init.flags = flags;
> +
> +	stub_clk->hw.init = &init;
> +	stub_clk->id = id;
> +	stub_clk->lock = lock;

Under what scenario is it safe to call _register_stub_clk() with a NULL
lock argument?

If lock is NULL, then every function callable via the ops structure
will bug.

Rather than doing a test in each method function, do it in
_register_stub_clk() - this means we aren't waiting for a NULL pointer
deref when one of these method functions gets called.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/4] clk: hisi: add API for allocation clk data struct
  2015-03-26 14:18         ` Russell King - ARM Linux
@ 2015-03-27  1:48             ` Leo Yan
  -1 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-27  1:48 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Wei Xu, Dan Zhao, zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	Haojian Zhuang, Bintian Wang, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA

hi Russell,

On Thu, Mar 26, 2015 at 02:18:34PM +0000, Russell King - ARM Linux wrote:
> On Thu, Mar 26, 2015 at 07:13:36PM +0800, Leo Yan wrote:
> > +struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
> > +					     int nr_clks)
> > +{
> > +	struct hisi_clock_data *clk_data;
> > +	void __iomem *base;
> > +
> > +	if (np) {
> > +		base = of_iomap(np, 0);
> > +		if (!base) {
> > +			pr_err("failed to map Hisilicon clock registers\n");
> > +			return NULL;
> > +		}
> > +		printk("%s: base %p\n", __func__, base);
> 
> Did you leave your debugging in?

Sorry, will remove it.

> > +	} else {
> > +		pr_err("failed to find Hisilicon clock node in DTS\n");
> > +		return NULL;
> > +	}
> 
> I know you're mostly only moving this code, but it would be far better if
> it were written:
> 
> 	if (!np) {
> 		pr_err("failed to find Hisilicon clock node in DTS\n");
> 		return NULL;
> 	}
> 
> 	base = of_iomap(np, 0);
> 	if (!base) {
> 		pr_err("failed to map Hisilicon clock registers\n");
> 		return NULL;
> 	}
> 
> Possibly do this first as a separate patch, and then move the code.

Will do this.

> -- 
> FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
> according to speedtest.net.
--
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] 18+ messages in thread

* [PATCH 1/4] clk: hisi: add API for allocation clk data struct
@ 2015-03-27  1:48             ` Leo Yan
  0 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-27  1:48 UTC (permalink / raw)
  To: linux-arm-kernel

hi Russell,

On Thu, Mar 26, 2015 at 02:18:34PM +0000, Russell King - ARM Linux wrote:
> On Thu, Mar 26, 2015 at 07:13:36PM +0800, Leo Yan wrote:
> > +struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
> > +					     int nr_clks)
> > +{
> > +	struct hisi_clock_data *clk_data;
> > +	void __iomem *base;
> > +
> > +	if (np) {
> > +		base = of_iomap(np, 0);
> > +		if (!base) {
> > +			pr_err("failed to map Hisilicon clock registers\n");
> > +			return NULL;
> > +		}
> > +		printk("%s: base %p\n", __func__, base);
> 
> Did you leave your debugging in?

Sorry, will remove it.

> > +	} else {
> > +		pr_err("failed to find Hisilicon clock node in DTS\n");
> > +		return NULL;
> > +	}
> 
> I know you're mostly only moving this code, but it would be far better if
> it were written:
> 
> 	if (!np) {
> 		pr_err("failed to find Hisilicon clock node in DTS\n");
> 		return NULL;
> 	}
> 
> 	base = of_iomap(np, 0);
> 	if (!base) {
> 		pr_err("failed to map Hisilicon clock registers\n");
> 		return NULL;
> 	}
> 
> Possibly do this first as a separate patch, and then move the code.

Will do this.

> -- 
> FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
> according to speedtest.net.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/4] clk: hisi: add stub clk driver
  2015-03-26 14:22         ` Russell King - ARM Linux
@ 2015-03-27  2:08             ` Leo Yan
  -1 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-27  2:08 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Wei Xu, Dan Zhao, zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	Haojian Zhuang, Bintian Wang, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Thu, Mar 26, 2015 at 02:22:26PM +0000, Russell King - ARM Linux wrote:
> On Thu, Mar 26, 2015 at 07:13:38PM +0800, Leo Yan wrote:
> > +static unsigned long hisi_stub_clk_recalc_rate(struct clk_hw *hw,
> > +		unsigned long parent_rate)
> > +{
> ...
> > +	BUG_ON(!stub_clk->lock);
> ...
> 
> > +static int hisi_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> > +                    unsigned long parent_rate)
> > +{
> ...
> > +	BUG_ON(!stub_clk->lock);
> ...
> 
> > +static long hisi_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
> > +		unsigned long *parent_rate)
> > +{
> ...
> > +	BUG_ON(!stub_clk->lock);
> ...
> 
> > +static struct clk_ops hisi_stub_clk_ops = {
> > +	.recalc_rate	= hisi_stub_clk_recalc_rate,
> > +	.round_rate	= hisi_stub_clk_round_rate,
> > +	.set_rate	= hisi_stub_clk_set_rate,
> > +};
> ...
> > +static struct clk *_register_stub_clk(struct device *dev, unsigned int id,
> > +	const char *name, const char *parent_name, unsigned long flags,
> > +	spinlock_t *lock)
> > +{
> > +	struct hisi_stub_clk *stub_clk;
> > +	struct clk *clk;
> > +	struct clk_init_data init;
> > +
> > +	stub_clk = kzalloc(sizeof(*stub_clk), GFP_KERNEL);
> > +	if (!stub_clk) {
> > +		pr_err("%s: fail to alloc stub clk!\n", __func__);
> > +		return ERR_PTR(-ENOMEM);
> > +	}
> > +
> > +	init.name = name;
> > +	init.ops = &hisi_stub_clk_ops;
> > +	init.parent_names = parent_name ? &parent_name : NULL;
> > +	init.num_parents = parent_name ? 1 : 0;
> > +	init.flags = flags;
> > +
> > +	stub_clk->hw.init = &init;
> > +	stub_clk->id = id;
> > +	stub_clk->lock = lock;
> 
> Under what scenario is it safe to call _register_stub_clk() with a NULL
> lock argument?
> 
> If lock is NULL, then every function callable via the ops structure
> will bug.
> 
> Rather than doing a test in each method function, do it in
> _register_stub_clk() - this means we aren't waiting for a NULL pointer
> deref when one of these method functions gets called.

Will fix to check lock pointer in the function _register_stub_clk().

Thanks,
Leo Yan
--
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] 18+ messages in thread

* [PATCH 3/4] clk: hisi: add stub clk driver
@ 2015-03-27  2:08             ` Leo Yan
  0 siblings, 0 replies; 18+ messages in thread
From: Leo Yan @ 2015-03-27  2:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 26, 2015 at 02:22:26PM +0000, Russell King - ARM Linux wrote:
> On Thu, Mar 26, 2015 at 07:13:38PM +0800, Leo Yan wrote:
> > +static unsigned long hisi_stub_clk_recalc_rate(struct clk_hw *hw,
> > +		unsigned long parent_rate)
> > +{
> ...
> > +	BUG_ON(!stub_clk->lock);
> ...
> 
> > +static int hisi_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> > +                    unsigned long parent_rate)
> > +{
> ...
> > +	BUG_ON(!stub_clk->lock);
> ...
> 
> > +static long hisi_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
> > +		unsigned long *parent_rate)
> > +{
> ...
> > +	BUG_ON(!stub_clk->lock);
> ...
> 
> > +static struct clk_ops hisi_stub_clk_ops = {
> > +	.recalc_rate	= hisi_stub_clk_recalc_rate,
> > +	.round_rate	= hisi_stub_clk_round_rate,
> > +	.set_rate	= hisi_stub_clk_set_rate,
> > +};
> ...
> > +static struct clk *_register_stub_clk(struct device *dev, unsigned int id,
> > +	const char *name, const char *parent_name, unsigned long flags,
> > +	spinlock_t *lock)
> > +{
> > +	struct hisi_stub_clk *stub_clk;
> > +	struct clk *clk;
> > +	struct clk_init_data init;
> > +
> > +	stub_clk = kzalloc(sizeof(*stub_clk), GFP_KERNEL);
> > +	if (!stub_clk) {
> > +		pr_err("%s: fail to alloc stub clk!\n", __func__);
> > +		return ERR_PTR(-ENOMEM);
> > +	}
> > +
> > +	init.name = name;
> > +	init.ops = &hisi_stub_clk_ops;
> > +	init.parent_names = parent_name ? &parent_name : NULL;
> > +	init.num_parents = parent_name ? 1 : 0;
> > +	init.flags = flags;
> > +
> > +	stub_clk->hw.init = &init;
> > +	stub_clk->id = id;
> > +	stub_clk->lock = lock;
> 
> Under what scenario is it safe to call _register_stub_clk() with a NULL
> lock argument?
> 
> If lock is NULL, then every function callable via the ops structure
> will bug.
> 
> Rather than doing a test in each method function, do it in
> _register_stub_clk() - this means we aren't waiting for a NULL pointer
> deref when one of these method functions gets called.

Will fix to check lock pointer in the function _register_stub_clk().

Thanks,
Leo Yan

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2015-03-27  2:08 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-26 11:13 [PATCH 0/4] clk: hisilicon: support stub clock Leo Yan
2015-03-26 11:13 ` Leo Yan
     [not found] ` <1427368419-22222-1-git-send-email-leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-03-26 11:13   ` [PATCH 1/4] clk: hisi: add API for allocation clk data struct Leo Yan
2015-03-26 11:13     ` Leo Yan
     [not found]     ` <1427368419-22222-2-git-send-email-leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-03-26 14:18       ` Russell King - ARM Linux
2015-03-26 14:18         ` Russell King - ARM Linux
     [not found]         ` <20150326141834.GI8656-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-03-27  1:48           ` Leo Yan
2015-03-27  1:48             ` Leo Yan
2015-03-26 11:13   ` [PATCH 2/4] dt-bindings: clk: hisilicon: Document stub clock driver Leo Yan
2015-03-26 11:13     ` Leo Yan
2015-03-26 11:13   ` [PATCH 3/4] clk: hisi: add stub clk driver Leo Yan
2015-03-26 11:13     ` Leo Yan
     [not found]     ` <1427368419-22222-4-git-send-email-leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-03-26 14:22       ` Russell King - ARM Linux
2015-03-26 14:22         ` Russell King - ARM Linux
     [not found]         ` <20150326142226.GJ8656-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-03-27  2:08           ` Leo Yan
2015-03-27  2:08             ` Leo Yan
2015-03-26 11:13   ` [PATCH 4/4] clk: hisi: add stub clock register function Leo Yan
2015-03-26 11:13     ` Leo Yan

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.