linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 0/7] ARM: rockchip: add smp functionality
@ 2014-01-20 15:41 Heiko Stübner
  2014-01-20 15:42 ` [PATCH v7 1/7] of: add functions to count number of elements in a property Heiko Stübner
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: Heiko Stübner @ 2014-01-20 15:41 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

This series enables the use of the additional cores on Rockchip
Cortex-A9 SoCs.

To achieve this, add the scu, the needed sram and power-management-unit.

Tested on both a BQ Curie2 (rk3066a / dual core) and
on a Radxa Rock (rk3188 / quad core).

changes since v6:
- address comments from Mark Rutland
  - using of_property_read_u32_index instead of parsing the list manually
  - include v4 of "of: add functions to count number of elements in a property"
    to not have to count property-elements manually anymore
changes since v5:
- Grant Likely liked it better to "specify reserved regions of the
  memory instead of the valid ranges", so go back to the mmio-sram-reserved
  property originally suggested by Rob Herring

changes since v4:
- rebase on top of the recent rk3188 board support
- implement suggestion from Matt Sealey in moving the sram-limit from
  marking reserved regions to marking available regions - hopefully
  I got the usage right 
- remove __CPUINIT as suggested by Fabio Estevam

changes since v3:
- address comments from Rob Herring:
  - split the gathering of the reserve-data into a separate loop
  - spelling and style fixes
- first patch only included for reference, already part of the
  char-misc git tree

changes since v2:
- rework the sram allocation following the suggestion from Philipp Zabel

changes since v1:
- add reserved block feature for mmio-sram, to not use two logical
  sram nodes
- the sram content is kept intact while the device is running, so
  copying the trampoline is only needed once

Heiko Stuebner (7):
  of: add functions to count number of elements in a property
  dt-bindings: sram: describe option to reserve parts of the memory
  misc: sram: implement mmio-sram-reserved option
  ARM: rockchip: add snoop-control-unit
  ARM: rockchip: add sram dt nodes and documentation
  ARM: rockchip: add power-management-unit
  ARM: rockchip: add smp bringup code

 .../devicetree/bindings/arm/rockchip/pmu.txt       |   16 ++
 .../devicetree/bindings/arm/rockchip/smp-sram.txt  |   23 +++
 Documentation/devicetree/bindings/misc/sram.txt    |    8 +
 arch/arm/boot/dts/rk3066a.dtsi                     |    6 +
 arch/arm/boot/dts/rk3188.dtsi                      |    6 +
 arch/arm/boot/dts/rk3xxx.dtsi                      |   10 +
 arch/arm/mach-rockchip/Kconfig                     |    1 +
 arch/arm/mach-rockchip/Makefile                    |    1 +
 arch/arm/mach-rockchip/core.h                      |   22 +++
 arch/arm/mach-rockchip/headsmp.S                   |   30 +++
 arch/arm/mach-rockchip/platsmp.c                   |  208 ++++++++++++++++++++
 arch/arm/mach-rockchip/rockchip.c                  |    2 +
 drivers/misc/sram.c                                |  121 +++++++++++-
 drivers/of/base.c                                  |   32 +++
 include/linux/of.h                                 |   76 +++++++
 15 files changed, 554 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/rockchip/pmu.txt
 create mode 100644 Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt
 create mode 100644 arch/arm/mach-rockchip/core.h
 create mode 100644 arch/arm/mach-rockchip/headsmp.S
 create mode 100644 arch/arm/mach-rockchip/platsmp.c

-- 
1.7.10.4



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

* [PATCH v7 1/7] of: add functions to count number of elements in a property
  2014-01-20 15:41 [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
@ 2014-01-20 15:42 ` Heiko Stübner
  2014-01-20 15:42 ` [PATCH v7 2/7] dt-bindings: sram: describe option to reserve parts of the memory Heiko Stübner
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Heiko Stübner @ 2014-01-20 15:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

The need to know the number of array elements in a property is
a common pattern. To prevent duplication of open-coded implementations
add a helper static function that also centralises strict sanity
checking and DTB format details, as well as a set of wrapper functions
for u8, u16, u32 and u64.

Suggested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
This is the same as v4 when this patch was separate, that was a result of the
discussion in in v6 of the rockchip-smp series.

 drivers/of/base.c  |   32 ++++++++++++++++++++++
 include/linux/of.h |   76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 8d007d8..d08acbc 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -883,6 +883,38 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 EXPORT_SYMBOL(of_find_node_by_phandle);
 
 /**
+ * of_property_count_elems_of_size - Count the number of elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @elem_size:	size of the individual element
+ *
+ * Search for a property in a device node and count the number of elements of
+ * size elem_size in it. Returns number of elements on sucess, -EINVAL if the
+ * property does not exist or its length does not match a multiple of elem_size
+ * and -ENODATA if the property does not have a value.
+ */
+int of_property_count_elems_of_size(const struct device_node *np,
+				const char *propname, int elem_size)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+
+	if (prop->length % elem_size != 0) {
+		pr_err("size of %s in node %s is not a multiple of %d\n",
+		       propname, np->full_name, elem_size);
+		return -EINVAL;
+	}
+
+	return prop->length / elem_size;
+}
+EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
+
+/**
  * of_find_property_value_of_size
  *
  * @np:		device node from which the property value is to be read.
diff --git a/include/linux/of.h b/include/linux/of.h
index 70c64ba..b59f2e4 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -250,6 +250,8 @@ extern struct device_node *of_find_node_with_property(
 extern struct property *of_find_property(const struct device_node *np,
 					 const char *name,
 					 int *lenp);
+extern int of_property_count_elems_of_size(const struct device_node *np,
+				const char *propname, int elem_size);
 extern int of_property_read_u32_index(const struct device_node *np,
 				       const char *propname,
 				       u32 index, u32 *out_value);
@@ -431,6 +433,12 @@ static inline struct device_node *of_find_compatible_node(
 	return NULL;
 }
 
+static inline int of_property_count_elems_of_size(const struct device_node *np,
+			const char *propname, int elem_size)
+{
+	return -ENOSYS;
+}
+
 static inline int of_property_read_u32_index(const struct device_node *np,
 			const char *propname, u32 index, u32 *out_value)
 {
@@ -570,6 +578,74 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
 #endif
 
 /**
+ * of_property_count_u8_elems - Count the number of u8 elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u8 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u8 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u8_elems(const struct device_node *np,
+				const char *propname)
+{
+	return of_property_count_elems_of_size(np, propname, sizeof(u8));
+}
+
+/**
+ * of_property_count_u16_elems - Count the number of u16 elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u16 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u16 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u16_elems(const struct device_node *np,
+				const char *propname)
+{
+	return of_property_count_elems_of_size(np, propname, sizeof(u16));
+}
+
+/**
+ * of_property_count_u32_elems - Count the number of u32 elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u32 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u32 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u32_elems(const struct device_node *np,
+				const char *propname)
+{
+	return of_property_count_elems_of_size(np, propname, sizeof(u32));
+}
+
+/**
+ * of_property_count_u64_elems - Count the number of u64 elements in a property
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u64 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u64 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u64_elems(const struct device_node *np,
+				const char *propname)
+{
+	return of_property_count_elems_of_size(np, propname, sizeof(u64));
+}
+
+/**
  * of_property_read_bool - Findfrom a property
  * @np:		device node from which the property value is to be read.
  * @propname:	name of the property to be searched.
-- 
1.7.10.4



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

* [PATCH v7 2/7] dt-bindings: sram: describe option to reserve parts of the memory
  2014-01-20 15:41 [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
  2014-01-20 15:42 ` [PATCH v7 1/7] of: add functions to count number of elements in a property Heiko Stübner
@ 2014-01-20 15:42 ` Heiko Stübner
       [not found]   ` <20140205111247.476B7C40A89@trevor.secretlab.ca>
  2014-01-20 15:43 ` [PATCH v7 3/7] misc: sram: implement mmio-sram-reserved option Heiko Stübner
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: Heiko Stübner @ 2014-01-20 15:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

Some SoCs need parts of their sram for special purposes. So while being part
of the peripheral, it should not be part of the genpool controlling the sram.

Therefore add an option mmio-sram-reserved to keep arbitrary portions of the
sram from general usage.

Suggested-by: Rob Herring <robherring2@gmail.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/misc/sram.txt |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/sram.txt b/Documentation/devicetree/bindings/misc/sram.txt
index 4d0a00e..09ee7a3 100644
--- a/Documentation/devicetree/bindings/misc/sram.txt
+++ b/Documentation/devicetree/bindings/misc/sram.txt
@@ -8,9 +8,17 @@ Required properties:
 
 - reg : SRAM iomem address range
 
+Optional properties:
+
+- mmio-sram-reserved: ordered list of reserved chunks inside the sram that
+  should not be used by the operating system.
+  Format is <base size>, <base size>, ...; with base being relative to the
+  reg property base.
+
 Example:
 
 sram: sram@5c000000 {
 	compatible = "mmio-sram";
 	reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */
+	mmio-sram-reserved = <0x0 0x100>; /* reserve 0x5c000000-0x5c000100 */
 };
-- 
1.7.10.4



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

* [PATCH v7 3/7] misc: sram: implement mmio-sram-reserved option
  2014-01-20 15:41 [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
  2014-01-20 15:42 ` [PATCH v7 1/7] of: add functions to count number of elements in a property Heiko Stübner
  2014-01-20 15:42 ` [PATCH v7 2/7] dt-bindings: sram: describe option to reserve parts of the memory Heiko Stübner
@ 2014-01-20 15:43 ` Heiko Stübner
  2014-01-20 15:44 ` [PATCH v7 4/7] ARM: rockchip: add snoop-control-unit Heiko Stübner
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Heiko Stübner @ 2014-01-20 15:43 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

This implements support for the mmio-sram-reserved option to keep the
genpool from using these areas.

Suggested-by: Rob Herring <robherring2@gmail.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
---
 drivers/misc/sram.c |  121 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 113 insertions(+), 8 deletions(-)

diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index afe66571..8681961 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -36,13 +36,23 @@ struct sram_dev {
 	struct clk *clk;
 };
 
+struct sram_reserve {
+	u32 start;
+	u32 size;
+};
+
 static int sram_probe(struct platform_device *pdev)
 {
 	void __iomem *virt_base;
 	struct sram_dev *sram;
 	struct resource *res;
-	unsigned long size;
-	int ret;
+	struct device_node *np = pdev->dev.of_node;
+	unsigned long size, cur_start, cur_size;
+	int reserved_size = 0;
+	struct sram_reserve *rblocks;
+	unsigned int nblocks;
+	int ret = 0;
+	int i;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	virt_base = devm_ioremap_resource(&pdev->dev, res);
@@ -65,19 +75,114 @@ static int sram_probe(struct platform_device *pdev)
 	if (!sram->pool)
 		return -ENOMEM;
 
-	ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base,
-				res->start, size, -1);
-	if (ret < 0) {
-		if (sram->clk)
-			clk_disable_unprepare(sram->clk);
-		return ret;
+	if (np) {
+		reserved_size = of_property_count_u32_elems(np,
+							"mmio-sram-reserved");
+
+		/* mmio-sram-reserved is optional, so its absence is no error */
+		if (reserved_size < 0)
+			reserved_size = 0;
+
+		if (reserved_size % 2) {
+			dev_warn(&pdev->dev, "wrong number of arguments in mmio-sram-reserved\n");
+			reserved_size = 0;
+		}
+	}
+
+	/*
+	 * We need an additional block to mark the end of the memory region
+	 * after the reserved blocks from the dt are processed.
+	 */
+	nblocks = reserved_size / 2 + 1;
+	rblocks = kmalloc((nblocks) * sizeof(*rblocks), GFP_KERNEL);
+	if (!rblocks) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	cur_start = 0;
+	for (i = 0; i < nblocks - 1; i++) {
+		/* checked the property exists above so can skip return vals */
+		of_property_read_u32_index(np, "mmio-sram-reserved",
+					   2 * i, &rblocks[i].start);
+		of_property_read_u32_index(np, "mmio-sram-reserved",
+					   2 * i + 1, &rblocks[i].size);
+
+		if (rblocks[i].start < cur_start) {
+			dev_err(&pdev->dev,
+				"unsorted reserved list (0x%x before current 0x%lx)\n",
+				rblocks[i].start, cur_start);
+			ret = -EINVAL;
+			goto err_chunks;
+		}
+
+		if (rblocks[i].start >= size) {
+			dev_err(&pdev->dev,
+				"reserved block at 0x%x outside the sram size 0x%lx\n",
+				rblocks[i].start, size);
+			ret = -EINVAL;
+			goto err_chunks;
+		}
+
+		if (rblocks[i].start + rblocks[i].size > size) {
+			dev_warn(&pdev->dev,
+				 "reserved block at 0x%x to large, trimming\n",
+				 rblocks[i].start);
+			rblocks[i].size = size - rblocks[i].start;
+		}
+
+		cur_start = rblocks[i].start + rblocks[i].size;
+
+		dev_dbg(&pdev->dev, "found reserved block 0x%x-0x%x\n",
+			rblocks[i].start,
+			rblocks[i].start + rblocks[i].size);
+	}
+
+	/* the last chunk marks the end of the region */
+	rblocks[nblocks - 1].start = size;
+	rblocks[nblocks - 1].size = 0;
+
+	cur_start = 0;
+	for (i = 0; i < nblocks; i++) {
+		/* current start is in a reserved block, so continue after it */
+		if (rblocks[i].start == cur_start) {
+			cur_start = rblocks[i].start + rblocks[i].size;
+			continue;
+		}
+
+		/*
+		 * allocate the space between the current starting
+		 * address and the following reserved block, or the
+		 * end of the region.
+		 */
+		cur_size = rblocks[i].start - cur_start;
+
+		dev_dbg(&pdev->dev, "adding chunk 0x%lx-0x%lx\n",
+			cur_start, cur_start + cur_size);
+		ret = gen_pool_add_virt(sram->pool,
+				(unsigned long)virt_base + cur_start,
+				res->start + cur_start, cur_size, -1);
+		if (ret < 0)
+			goto err_chunks;
+
+		/* next allocation after this reserved block */
+		cur_start = rblocks[i].start + rblocks[i].size;
 	}
 
+	kfree(rblocks);
+
 	platform_set_drvdata(pdev, sram);
 
 	dev_dbg(&pdev->dev, "SRAM pool: %ld KiB @ 0x%p\n", size / 1024, virt_base);
 
 	return 0;
+
+err_chunks:
+	kfree(rblocks);
+err_alloc:
+	if (sram->clk)
+		clk_disable_unprepare(sram->clk);
+	return ret;
 }
 
 static int sram_remove(struct platform_device *pdev)
-- 
1.7.10.4



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

* [PATCH v7 4/7] ARM: rockchip: add snoop-control-unit
  2014-01-20 15:41 [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
                   ` (2 preceding siblings ...)
  2014-01-20 15:43 ` [PATCH v7 3/7] misc: sram: implement mmio-sram-reserved option Heiko Stübner
@ 2014-01-20 15:44 ` Heiko Stübner
  2014-01-20 15:44 ` [PATCH v7 5/7] ARM: rockchip: add sram dt nodes and documentation Heiko Stübner
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Heiko Stübner @ 2014-01-20 15:44 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

This adds the device-node and config select to enable the
scu in all Rockchip Cortex-A9 SoCs.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
---
 arch/arm/boot/dts/rk3xxx.dtsi  |    5 +++++
 arch/arm/mach-rockchip/Kconfig |    1 +
 2 files changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi
index 0fcbcfd..0a3d5b1 100644
--- a/arch/arm/boot/dts/rk3xxx.dtsi
+++ b/arch/arm/boot/dts/rk3xxx.dtsi
@@ -26,6 +26,11 @@
 		compatible = "simple-bus";
 		ranges;
 
+		scu@1013c000 {
+			compatible = "arm,cortex-a9-scu";
+			reg = <0x1013c000 0x100>;
+		};
+
 		gic: interrupt-controller@1013d000 {
 			compatible = "arm,cortex-a9-gic";
 			interrupt-controller;
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index cf073de..412cbcf 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -5,6 +5,7 @@ config ARCH_ROCKCHIP
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_GIC
 	select CACHE_L2X0
+	select HAVE_ARM_SCU
 	select HAVE_ARM_TWD if SMP
 	select HAVE_SMP
 	select COMMON_CLK
-- 
1.7.10.4



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

* [PATCH v7 5/7] ARM: rockchip: add sram dt nodes and documentation
  2014-01-20 15:41 [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
                   ` (3 preceding siblings ...)
  2014-01-20 15:44 ` [PATCH v7 4/7] ARM: rockchip: add snoop-control-unit Heiko Stübner
@ 2014-01-20 15:44 ` Heiko Stübner
  2014-01-20 15:45 ` [PATCH v7 6/7] ARM: rockchip: add power-management-unit Heiko Stübner
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Heiko Stübner @ 2014-01-20 15:44 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

Add dt-nodes for the sram on rk3066 and rk3188 including the reserved section
needed for smp bringup.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
---
 .../devicetree/bindings/arm/rockchip/smp-sram.txt  |   23 ++++++++++++++++++++
 arch/arm/boot/dts/rk3066a.dtsi                     |    6 +++++
 arch/arm/boot/dts/rk3188.dtsi                      |    6 +++++
 3 files changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt

diff --git a/Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt b/Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt
new file mode 100644
index 0000000..80c878e
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt
@@ -0,0 +1,23 @@
+Rockchip SRAM for smp bringup:
+------------------------------
+
+Rockchip's smp-capable SoCs use the first part of the sram for the bringup
+of the cores. Once the core gets powered up it executes the code that is
+residing at the very beginning of the sram.
+
+Therefore a reserved section has to be added to the mmio-sram declaration.
+
+Required node properties:
+- compatible : should contain both "rockchip,rk3066-sram", "mmio-sram"
+  so that the smp code can select the correct sram node.
+
+The rest of the properties should follow the generic mmio-sram discription
+found in ../../misc/sram.txt
+
+Example:
+
+	sram: sram@10080000 {
+		compatible = "rockchip,rk3066-sram", "mmio-sram";
+		reg = <0x10080000 0x10000>;
+		mmio-sram-reserved = <0x0 0x50>;
+	};
diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index be5d2b0..0dfb680 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -64,6 +64,12 @@
 			clock-names = "timer", "pclk";
 		};
 
+		sram: sram@10080000 {
+			compatible = "rockchip,rk3066-sram", "mmio-sram";
+			reg = <0x10080000 0x10000>;
+			mmio-sram-reserved = <0x0 0x50>;
+		};
+
 		pinctrl@20008000 {
 			compatible = "rockchip,rk3066a-pinctrl";
 			reg = <0x20008000 0x150>;
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 1a26b03..1fc7eda 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -60,6 +60,12 @@
 			interrupts = <GIC_PPI 13 0xf04>;
 		};
 
+		sram: sram@10080000 {
+			compatible = "rockchip,rk3066-sram", "mmio-sram";
+			reg = <0x10080000 0x8000>;
+			mmio-sram-reserved = <0x0 0x50>;
+		};
+
 		pinctrl@20008000 {
 			compatible = "rockchip,rk3188-pinctrl";
 			reg = <0x20008000 0xa0>,
-- 
1.7.10.4



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

* [PATCH v7 6/7] ARM: rockchip: add power-management-unit
  2014-01-20 15:41 [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
                   ` (4 preceding siblings ...)
  2014-01-20 15:44 ` [PATCH v7 5/7] ARM: rockchip: add sram dt nodes and documentation Heiko Stübner
@ 2014-01-20 15:45 ` Heiko Stübner
  2014-01-20 15:46 ` [PATCH v7 7/7] ARM: rockchip: add smp bringup code Heiko Stübner
  2014-01-31 22:03 ` [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
  7 siblings, 0 replies; 13+ messages in thread
From: Heiko Stübner @ 2014-01-20 15:45 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

The pmu is needed to bring up the cores during smp operations and later
also other system parts. Therefore add a node and documentation for it.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
---
 Documentation/devicetree/bindings/arm/rockchip/pmu.txt |   16 ++++++++++++++++
 arch/arm/boot/dts/rk3xxx.dtsi                          |    5 +++++
 2 files changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/rockchip/pmu.txt

diff --git a/Documentation/devicetree/bindings/arm/rockchip/pmu.txt b/Documentation/devicetree/bindings/arm/rockchip/pmu.txt
new file mode 100644
index 0000000..3ee9b42
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/rockchip/pmu.txt
@@ -0,0 +1,16 @@
+Rockchip power-management-unit:
+-------------------------------
+
+The pmu is used to turn off and on different power domains of the SoCs
+This includes the power to the CPU cores.
+
+Required node properties:
+- compatible value : = "rockchip,rk3066-pmu";
+- reg : physical base address and the size of the registers window
+
+Example:
+
+	pmu@20004000 {
+		compatible = "rockchip,rk3066-pmu";
+		reg = <0x20004000 0x100>;
+	};
diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi
index 0a3d5b1..26e5a96 100644
--- a/arch/arm/boot/dts/rk3xxx.dtsi
+++ b/arch/arm/boot/dts/rk3xxx.dtsi
@@ -31,6 +31,11 @@
 			reg = <0x1013c000 0x100>;
 		};
 
+		pmu@20004000 {
+			compatible = "rockchip,rk3066-pmu";
+			reg = <0x20004000 0x100>;
+		};
+
 		gic: interrupt-controller@1013d000 {
 			compatible = "arm,cortex-a9-gic";
 			interrupt-controller;
-- 
1.7.10.4



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

* [PATCH v7 7/7] ARM: rockchip: add smp bringup code
  2014-01-20 15:41 [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
                   ` (5 preceding siblings ...)
  2014-01-20 15:45 ` [PATCH v7 6/7] ARM: rockchip: add power-management-unit Heiko Stübner
@ 2014-01-20 15:46 ` Heiko Stübner
  2014-01-20 16:42   ` [PATCH v7.1 " Heiko Stübner
  2014-01-31 22:03 ` [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
  7 siblings, 1 reply; 13+ messages in thread
From: Heiko Stübner @ 2014-01-20 15:46 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

This adds the necessary smp-operations and startup code to use
additional cores on Rockchip SoCs.

We currently hog the power management unit in the smp code, as it is
necessary to control the power to the cpu core and nothing else is
currently using it, so a generic implementation can be done later.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
---
 arch/arm/mach-rockchip/Makefile   |    1 +
 arch/arm/mach-rockchip/core.h     |   22 ++++
 arch/arm/mach-rockchip/headsmp.S  |   30 ++++++
 arch/arm/mach-rockchip/platsmp.c  |  208 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-rockchip/rockchip.c |    2 +
 5 files changed, 263 insertions(+)
 create mode 100644 arch/arm/mach-rockchip/core.h
 create mode 100644 arch/arm/mach-rockchip/headsmp.S
 create mode 100644 arch/arm/mach-rockchip/platsmp.c

diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 1547d4f..4377a14 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-rockchip/core.h b/arch/arm/mach-rockchip/core.h
new file mode 100644
index 0000000..e2e7c9d
--- /dev/null
+++ b/arch/arm/mach-rockchip/core.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+extern char rockchip_secondary_trampoline;
+extern char rockchip_secondary_trampoline_end;
+
+extern unsigned long rockchip_boot_fn;
+extern void rockchip_secondary_startup(void);
+
+extern struct smp_operations rockchip_smp_ops;
diff --git a/arch/arm/mach-rockchip/headsmp.S b/arch/arm/mach-rockchip/headsmp.S
new file mode 100644
index 0000000..73206e3
--- /dev/null
+++ b/arch/arm/mach-rockchip/headsmp.S
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ENTRY(rockchip_secondary_startup)
+	bl	v7_invalidate_l1
+	b	secondary_startup
+ENDPROC(rockchip_secondary_startup)
+
+ENTRY(rockchip_secondary_trampoline)
+	ldr	pc, 1f
+ENDPROC(rockchip_secondary_trampoline)
+	.globl	rockchip_boot_fn
+rockchip_boot_fn:
+1:	.space	4
+
+ENTRY(rockchip_secondary_trampoline_end)
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
new file mode 100644
index 0000000..3459b17
--- /dev/null
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
+#include <asm/mach/map.h>
+
+#include "core.h"
+
+static void __iomem *scu_base_addr;
+static void __iomem *sram_base_addr;
+static int ncores;
+
+#define PMU_PWRDN_CON		0x08
+#define PMU_PWRDN_ST		0x0c
+
+#define PMU_PWRDN_SCU		4
+
+static void __iomem *pmu_base_addr;
+
+static inline bool pmu_power_domain_is_on(int pd)
+{
+	return !(readl_relaxed(pmu_base_addr + PMU_PWRDN_ST) & BIT(pd));
+}
+
+static void pmu_set_power_domain(int pd, bool on)
+{
+	u32 val = readl_relaxed(pmu_base_addr + PMU_PWRDN_CON);
+	if (on)
+		val &= ~BIT(pd);
+	else
+		val |=  BIT(pd);
+	writel(val, pmu_base_addr + PMU_PWRDN_CON);
+
+	while (pmu_power_domain_is_on(pd) != on) { }
+}
+
+/*
+ * Handling of CPU cores
+ */
+
+static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
+					     struct task_struct *idle)
+{
+	if (!sram_base_addr || !pmu_base_addr) {
+		pr_err("%s: sram or pmu missing for cpu boot\n", __func__);
+		return -ENXIO;
+	}
+
+	if (cpu >= ncores) {
+		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
+							__func__, cpu, ncores);
+		return -ENXIO;
+	}
+
+	/* start the core */
+	pmu_set_power_domain(0 + cpu, true);
+
+	return 0;
+}
+
+/**
+ * rockchip_smp_prepare_sram - populate necessary sram block
+ * Starting cores execute the code residing at the start of the on-chip sram
+ * after power-on. Therefore make sure, this sram region is reserved and
+ * big enough. After this check, copy the trampoline code that directs the
+ * core to the real startup code in ram into the sram-region.
+ * @node: mmio-sram device node
+ */
+static int __init rockchip_smp_prepare_sram(struct device_node *node)
+{
+	unsigned int trampoline_sz = &rockchip_secondary_trampoline_end -
+					    &rockchip_secondary_trampoline;
+	const __be32 *reserved_list = NULL;
+	int reserved_size;
+	int rstart = -1;
+	unsigned int rsize;
+	unsigned int i;
+
+	reserved_list = of_get_property(node, "mmio-sram-reserved",
+					&reserved_size);
+	if (!reserved_list) {
+		pr_err("%s: wrong number of arguments in mmio-sram-reserved\n",
+		       __func__);
+		return -ENOENT;
+	}
+
+	reserved_size /= sizeof(*reserved_list);
+	if (!reserved_size || reserved_size % 2) {
+		pr_err("%s: wrong number of arguments in mmio-sram-reserved\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < reserved_size; i += 2) {
+		/* get the next reserved block */
+		rstart = be32_to_cpu(*reserved_list++);
+		rsize = be32_to_cpu(*reserved_list++);
+
+		if (!rstart)
+			break;
+	}
+
+	if (rstart) {
+		pr_err("%s: start of sram is not reserved from mmio-sram\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	if (rsize < trampoline_sz) {
+		pr_err("%s: reserved block with size 0x%x is to small for trampoline size 0x%x\n",
+		       __func__, rsize, trampoline_sz);
+		return -EINVAL;
+	}
+
+	sram_base_addr = of_iomap(node, 0);
+
+	/* set the boot function for the sram code */
+	rockchip_boot_fn = virt_to_phys(rockchip_secondary_startup);
+
+	/* copy the trampoline to sram, that runs during startup of the core */
+	memcpy(sram_base_addr, &rockchip_secondary_trampoline, trampoline_sz);
+	flush_cache_all();
+	outer_clean_range(0, trampoline_sz);
+
+	dsb_sev();
+
+	return 0;
+}
+
+static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *node;
+	unsigned int i;
+
+	node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+	if (!node) {
+		pr_err("%s: missing scu\n", __func__);
+		return;
+	}
+
+	scu_base_addr = of_iomap(node, 0);
+	if (!scu_base_addr) {
+		pr_err("%s: could not map scu registers\n", __func__);
+		return;
+	}
+
+	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-sram");
+	if (!node) {
+		pr_err("%s: could not find sram dt node\n", __func__);
+		return;
+	}
+
+	if (rockchip_smp_prepare_sram(node))
+		return;
+
+	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-pmu");
+	if (!node) {
+		pr_err("%s: could not find sram dt node\n", __func__);
+		return;
+	}
+
+	pmu_base_addr = of_iomap(node, 0);
+	if (!pmu_base_addr) {
+		pr_err("%s: could not map pmu registers\n", __func__);
+		return;
+	}
+
+	/* enable the SCU power domain */
+	pmu_set_power_domain(PMU_PWRDN_SCU, true);
+
+	/*
+	 * While the number of cpus is gathered from dt, also get the number
+	 * of cores from the scu to verify this value when booting the cores.
+	 */
+	ncores = scu_get_core_count(scu_base_addr);
+
+	scu_enable(scu_base_addr);
+
+	/* Make sure that all cores except the first are really off */
+	for (i = 1; i < ncores; i++)
+		pmu_set_power_domain(0 + i, false);
+}
+
+struct smp_operations rockchip_smp_ops __initdata = {
+	.smp_prepare_cpus	= rockchip_smp_prepare_cpus,
+	.smp_boot_secondary	= rockchip_boot_secondary,
+};
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 82c0b07..d211d6f 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -22,6 +22,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/cache-l2x0.h>
+#include "core.h"
 
 static void __init rockchip_dt_init(void)
 {
@@ -38,6 +39,7 @@ static const char * const rockchip_board_dt_compat[] = {
 };
 
 DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+	.smp		= smp_ops(rockchip_smp_ops),
 	.init_machine	= rockchip_dt_init,
 	.dt_compat	= rockchip_board_dt_compat,
 MACHINE_END
-- 
1.7.10.4



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

* [PATCH v7.1 7/7] ARM: rockchip: add smp bringup code
  2014-01-20 15:46 ` [PATCH v7 7/7] ARM: rockchip: add smp bringup code Heiko Stübner
@ 2014-01-20 16:42   ` Heiko Stübner
  0 siblings, 0 replies; 13+ messages in thread
From: Heiko Stübner @ 2014-01-20 16:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

This adds the necessary smp-operations and startup code to use
additional cores on Rockchip SoCs.

We currently hog the power management unit in the smp code, as it is
necessary to control the power to the cpu core and nothing else is
currently using it, so a generic implementation can be done later.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
---
As somehow was to be expected, I forgot to change the second user of the
mmio-reserved data to use of_property_read_u32_index and the newly introduced
element count function. 

 arch/arm/mach-rockchip/Makefile   |    1 +
 arch/arm/mach-rockchip/core.h     |   22 +++++
 arch/arm/mach-rockchip/headsmp.S  |   30 ++++++
 arch/arm/mach-rockchip/platsmp.c  |  196 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-rockchip/rockchip.c |    2 +
 5 files changed, 251 insertions(+)
 create mode 100644 arch/arm/mach-rockchip/core.h
 create mode 100644 arch/arm/mach-rockchip/headsmp.S
 create mode 100644 arch/arm/mach-rockchip/platsmp.c

diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 1547d4f..4377a14 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-rockchip/core.h b/arch/arm/mach-rockchip/core.h
new file mode 100644
index 0000000..e2e7c9d
--- /dev/null
+++ b/arch/arm/mach-rockchip/core.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+extern char rockchip_secondary_trampoline;
+extern char rockchip_secondary_trampoline_end;
+
+extern unsigned long rockchip_boot_fn;
+extern void rockchip_secondary_startup(void);
+
+extern struct smp_operations rockchip_smp_ops;
diff --git a/arch/arm/mach-rockchip/headsmp.S b/arch/arm/mach-rockchip/headsmp.S
new file mode 100644
index 0000000..73206e3
--- /dev/null
+++ b/arch/arm/mach-rockchip/headsmp.S
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ENTRY(rockchip_secondary_startup)
+	bl	v7_invalidate_l1
+	b	secondary_startup
+ENDPROC(rockchip_secondary_startup)
+
+ENTRY(rockchip_secondary_trampoline)
+	ldr	pc, 1f
+ENDPROC(rockchip_secondary_trampoline)
+	.globl	rockchip_boot_fn
+rockchip_boot_fn:
+1:	.space	4
+
+ENTRY(rockchip_secondary_trampoline_end)
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
new file mode 100644
index 0000000..4a49103
--- /dev/null
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
+#include <asm/mach/map.h>
+
+#include "core.h"
+
+static void __iomem *scu_base_addr;
+static void __iomem *sram_base_addr;
+static int ncores;
+
+#define PMU_PWRDN_CON		0x08
+#define PMU_PWRDN_ST		0x0c
+
+#define PMU_PWRDN_SCU		4
+
+static void __iomem *pmu_base_addr;
+
+static inline bool pmu_power_domain_is_on(int pd)
+{
+	return !(readl_relaxed(pmu_base_addr + PMU_PWRDN_ST) & BIT(pd));
+}
+
+static void pmu_set_power_domain(int pd, bool on)
+{
+	u32 val = readl_relaxed(pmu_base_addr + PMU_PWRDN_CON);
+	if (on)
+		val &= ~BIT(pd);
+	else
+		val |=  BIT(pd);
+	writel(val, pmu_base_addr + PMU_PWRDN_CON);
+
+	while (pmu_power_domain_is_on(pd) != on) { }
+}
+
+/*
+ * Handling of CPU cores
+ */
+
+static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
+					     struct task_struct *idle)
+{
+	if (!sram_base_addr || !pmu_base_addr) {
+		pr_err("%s: sram or pmu missing for cpu boot\n", __func__);
+		return -ENXIO;
+	}
+
+	if (cpu >= ncores) {
+		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
+							__func__, cpu, ncores);
+		return -ENXIO;
+	}
+
+	/* start the core */
+	pmu_set_power_domain(0 + cpu, true);
+
+	return 0;
+}
+
+/**
+ * rockchip_smp_prepare_sram - populate necessary sram block
+ * Starting cores execute the code residing at the start of the on-chip sram
+ * after power-on. Therefore make sure, this sram region is reserved and
+ * big enough. After this check, copy the trampoline code that directs the
+ * core to the real startup code in ram into the sram-region.
+ * @node: mmio-sram device node
+ */
+static int __init rockchip_smp_prepare_sram(struct device_node *node)
+{
+	unsigned int trampoline_sz = &rockchip_secondary_trampoline_end -
+					    &rockchip_secondary_trampoline;
+	int reserved_size;
+	int rstart = -1;
+	unsigned int rsize;
+
+	reserved_size = of_property_count_u32_elems(node, "mmio-sram-reserved");
+	if (reserved_size <= 0 || reserved_size % 2) {
+		pr_err("%s: incorrect mmio-sram-reserved property\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	of_property_read_u32_index(node, "mmio-sram-reserved", 0, &rstart);
+	of_property_read_u32_index(node, "mmio-sram-reserved", 1, &rsize);
+
+	/*
+	 * Reserved sections are sorted in ascending order and we need
+	 * the block starting at 0. So everything else is an error.
+	 */
+	if (rstart) {
+		pr_err("%s: start of sram is not reserved from mmio-sram\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	if (rsize < trampoline_sz) {
+		pr_err("%s: reserved block with size 0x%x is to small for trampoline size 0x%x\n",
+		       __func__, rsize, trampoline_sz);
+		return -EINVAL;
+	}
+
+	sram_base_addr = of_iomap(node, 0);
+
+	/* set the boot function for the sram code */
+	rockchip_boot_fn = virt_to_phys(rockchip_secondary_startup);
+
+	/* copy the trampoline to sram, that runs during startup of the core */
+	memcpy(sram_base_addr, &rockchip_secondary_trampoline, trampoline_sz);
+	flush_cache_all();
+	outer_clean_range(0, trampoline_sz);
+
+	dsb_sev();
+
+	return 0;
+}
+
+static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *node;
+	unsigned int i;
+
+	node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+	if (!node) {
+		pr_err("%s: missing scu\n", __func__);
+		return;
+	}
+
+	scu_base_addr = of_iomap(node, 0);
+	if (!scu_base_addr) {
+		pr_err("%s: could not map scu registers\n", __func__);
+		return;
+	}
+
+	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-sram");
+	if (!node) {
+		pr_err("%s: could not find sram dt node\n", __func__);
+		return;
+	}
+
+	if (rockchip_smp_prepare_sram(node))
+		return;
+
+	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-pmu");
+	if (!node) {
+		pr_err("%s: could not find sram dt node\n", __func__);
+		return;
+	}
+
+	pmu_base_addr = of_iomap(node, 0);
+	if (!pmu_base_addr) {
+		pr_err("%s: could not map pmu registers\n", __func__);
+		return;
+	}
+
+	/* enable the SCU power domain */
+	pmu_set_power_domain(PMU_PWRDN_SCU, true);
+
+	/*
+	 * While the number of cpus is gathered from dt, also get the number
+	 * of cores from the scu to verify this value when booting the cores.
+	 */
+	ncores = scu_get_core_count(scu_base_addr);
+
+	scu_enable(scu_base_addr);
+
+	/* Make sure that all cores except the first are really off */
+	for (i = 1; i < ncores; i++)
+		pmu_set_power_domain(0 + i, false);
+}
+
+struct smp_operations rockchip_smp_ops __initdata = {
+	.smp_prepare_cpus	= rockchip_smp_prepare_cpus,
+	.smp_boot_secondary	= rockchip_boot_secondary,
+};
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 82c0b07..d211d6f 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -22,6 +22,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/cache-l2x0.h>
+#include "core.h"
 
 static void __init rockchip_dt_init(void)
 {
@@ -38,6 +39,7 @@ static const char * const rockchip_board_dt_compat[] = {
 };
 
 DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+	.smp		= smp_ops(rockchip_smp_ops),
 	.init_machine	= rockchip_dt_init,
 	.dt_compat	= rockchip_board_dt_compat,
 MACHINE_END
-- 
1.7.10.4



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

* Re: [PATCH v7 0/7] ARM: rockchip: add smp functionality
  2014-01-20 15:41 [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
                   ` (6 preceding siblings ...)
  2014-01-20 15:46 ` [PATCH v7 7/7] ARM: rockchip: add smp bringup code Heiko Stübner
@ 2014-01-31 22:03 ` Heiko Stübner
  2014-01-31 22:12   ` Rob Herring
  2014-02-01 21:51   ` Philipp Zabel
  7 siblings, 2 replies; 13+ messages in thread
From: Heiko Stübner @ 2014-01-31 22:03 UTC (permalink / raw)
  To: linux-arm-kernel, arm, Rob Herring, Philipp Zabel, Mark Rutland
  Cc: Grant Likely, devicetree, linux-kernel, Greg Kroah-Hartman,
	Pawel Moll, Stephen Warren, Ian Campbell

On Monday, 20. January 2014 16:41:43 Heiko Stübner wrote:
> This series enables the use of the additional cores on Rockchip
> Cortex-A9 SoCs.

So, two weeks without any general complaints, but I guess part of the more 
general patches could use an ack.

Going forward, what would be best way to merge them?
As one pull request to arm-soc, or for example splitting them into the first 
three patches going through the misc tree and the rockchip specific stuff going 
through arm-soc? Or something else altogether?


> Heiko Stuebner (7):
>   of: add functions to count number of elements in a property

One of the intermediate versions of this patch got a
	Reviewed-by: Mark Rutland <mark.rutland@arm.com> .
Mark, is this still true for this variant addressing some additional wished 
from Rob?

And this final version got a "Looks good" from Rob Herring in the original 
thread, but a more formal "ack" might be nice :-) .


>   dt-bindings: sram: describe option to reserve parts of the memory
>   misc: sram: implement mmio-sram-reserved option

Philipp, you acked an intermediate version, and this v7 now should also 
contain the two separate loops (1st gathering data and 2nd creating the pool 
parts) you asked for.

Could I persuade you to take a look again?


Thanks
Heiko


>   ARM: rockchip: add snoop-control-unit
>   ARM: rockchip: add sram dt nodes and documentation
>   ARM: rockchip: add power-management-unit
>   ARM: rockchip: add smp bringup code
> 
>  .../devicetree/bindings/arm/rockchip/pmu.txt       |   16 ++
>  .../devicetree/bindings/arm/rockchip/smp-sram.txt  |   23 +++
>  Documentation/devicetree/bindings/misc/sram.txt    |    8 +
>  arch/arm/boot/dts/rk3066a.dtsi                     |    6 +
>  arch/arm/boot/dts/rk3188.dtsi                      |    6 +
>  arch/arm/boot/dts/rk3xxx.dtsi                      |   10 +
>  arch/arm/mach-rockchip/Kconfig                     |    1 +
>  arch/arm/mach-rockchip/Makefile                    |    1 +
>  arch/arm/mach-rockchip/core.h                      |   22 +++
>  arch/arm/mach-rockchip/headsmp.S                   |   30 +++
>  arch/arm/mach-rockchip/platsmp.c                   |  208
> ++++++++++++++++++++ arch/arm/mach-rockchip/rockchip.c                  |  
>  2 +
>  drivers/misc/sram.c                                |  121 +++++++++++-
>  drivers/of/base.c                                  |   32 +++
>  include/linux/of.h                                 |   76 +++++++
>  15 files changed, 554 insertions(+), 8 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/rockchip/pmu.txt
>  create mode 100644
> Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt create mode
> 100644 arch/arm/mach-rockchip/core.h
>  create mode 100644 arch/arm/mach-rockchip/headsmp.S
>  create mode 100644 arch/arm/mach-rockchip/platsmp.c


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

* Re: [PATCH v7 0/7] ARM: rockchip: add smp functionality
  2014-01-31 22:03 ` [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
@ 2014-01-31 22:12   ` Rob Herring
  2014-02-01 21:51   ` Philipp Zabel
  1 sibling, 0 replies; 13+ messages in thread
From: Rob Herring @ 2014-01-31 22:12 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: linux-arm-kernel, arm, Philipp Zabel, Mark Rutland, Grant Likely,
	devicetree, linux-kernel, Greg Kroah-Hartman, Pawel Moll,
	Stephen Warren, Ian Campbell

On Fri, Jan 31, 2014 at 4:03 PM, Heiko Stübner <heiko@sntech.de> wrote:
> On Monday, 20. January 2014 16:41:43 Heiko Stübner wrote:
>> This series enables the use of the additional cores on Rockchip
>> Cortex-A9 SoCs.
>
> So, two weeks without any general complaints, but I guess part of the more
> general patches could use an ack.
>
> Going forward, what would be best way to merge them?
> As one pull request to arm-soc, or for example splitting them into the first
> three patches going through the misc tree and the rockchip specific stuff going
> through arm-soc? Or something else altogether?
>
>
>> Heiko Stuebner (7):
>>   of: add functions to count number of elements in a property
>
> One of the intermediate versions of this patch got a
>         Reviewed-by: Mark Rutland <mark.rutland@arm.com> .
> Mark, is this still true for this variant addressing some additional wished
> from Rob?
>
> And this final version got a "Looks good" from Rob Herring in the original
> thread, but a more formal "ack" might be nice :-) .

Acked-by: Rob Herring <robh@kernel.org>

Rob

>
>
>>   dt-bindings: sram: describe option to reserve parts of the memory
>>   misc: sram: implement mmio-sram-reserved option
>
> Philipp, you acked an intermediate version, and this v7 now should also
> contain the two separate loops (1st gathering data and 2nd creating the pool
> parts) you asked for.
>
> Could I persuade you to take a look again?
>
>
> Thanks
> Heiko
>
>
>>   ARM: rockchip: add snoop-control-unit
>>   ARM: rockchip: add sram dt nodes and documentation
>>   ARM: rockchip: add power-management-unit
>>   ARM: rockchip: add smp bringup code
>>
>>  .../devicetree/bindings/arm/rockchip/pmu.txt       |   16 ++
>>  .../devicetree/bindings/arm/rockchip/smp-sram.txt  |   23 +++
>>  Documentation/devicetree/bindings/misc/sram.txt    |    8 +
>>  arch/arm/boot/dts/rk3066a.dtsi                     |    6 +
>>  arch/arm/boot/dts/rk3188.dtsi                      |    6 +
>>  arch/arm/boot/dts/rk3xxx.dtsi                      |   10 +
>>  arch/arm/mach-rockchip/Kconfig                     |    1 +
>>  arch/arm/mach-rockchip/Makefile                    |    1 +
>>  arch/arm/mach-rockchip/core.h                      |   22 +++
>>  arch/arm/mach-rockchip/headsmp.S                   |   30 +++
>>  arch/arm/mach-rockchip/platsmp.c                   |  208
>> ++++++++++++++++++++ arch/arm/mach-rockchip/rockchip.c                  |
>>  2 +
>>  drivers/misc/sram.c                                |  121 +++++++++++-
>>  drivers/of/base.c                                  |   32 +++
>>  include/linux/of.h                                 |   76 +++++++
>>  15 files changed, 554 insertions(+), 8 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/arm/rockchip/pmu.txt
>>  create mode 100644
>> Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt create mode
>> 100644 arch/arm/mach-rockchip/core.h
>>  create mode 100644 arch/arm/mach-rockchip/headsmp.S
>>  create mode 100644 arch/arm/mach-rockchip/platsmp.c
>

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

* Re: [PATCH v7 0/7] ARM: rockchip: add smp functionality
  2014-01-31 22:03 ` [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
  2014-01-31 22:12   ` Rob Herring
@ 2014-02-01 21:51   ` Philipp Zabel
  1 sibling, 0 replies; 13+ messages in thread
From: Philipp Zabel @ 2014-02-01 21:51 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: linux-arm-kernel, arm, Rob Herring, Philipp Zabel, Mark Rutland,
	Grant Likely, devicetree, linux-kernel, Greg Kroah-Hartman,
	Pawel Moll, Stephen Warren, Ian Campbell

Hi Heiko,

On Fri, Jan 31, 2014 at 11:03:03PM +0100, Heiko Stübner wrote:
> On Monday, 20. January 2014 16:41:43 Heiko Stübner wrote:
> > This series enables the use of the additional cores on Rockchip
> > Cortex-A9 SoCs.
> 
> So, two weeks without any general complaints, but I guess part of the more 
> general patches could use an ack.
> 
> Going forward, what would be best way to merge them?
> As one pull request to arm-soc, or for example splitting them into the first 
> three patches going through the misc tree and the rockchip specific stuff going 
> through arm-soc? Or something else altogether?
> 
> 
> > Heiko Stuebner (7):
> >   of: add functions to count number of elements in a property
> 
> One of the intermediate versions of this patch got a
> 	Reviewed-by: Mark Rutland <mark.rutland@arm.com> .
> Mark, is this still true for this variant addressing some additional wished 
> from Rob?
> 
> And this final version got a "Looks good" from Rob Herring in the original 
> thread, but a more formal "ack" might be nice :-) .
> 
> 
> >   dt-bindings: sram: describe option to reserve parts of the memory
> >   misc: sram: implement mmio-sram-reserved option
> 
> Philipp, you acked an intermediate version, and this v7 now should also 
> contain the two separate loops (1st gathering data and 2nd creating the pool 
> parts) you asked for.
> 
> Could I persuade you to take a look again?

Acked-by: Philipp Zabel <p.zabel@pengutronix.de>

regards
Philipp

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

* Re: [PATCH v7 2/7] dt-bindings: sram: describe option to reserve parts of the memory
       [not found]   ` <20140205111247.476B7C40A89@trevor.secretlab.ca>
@ 2014-02-05 12:05     ` Heiko Stübner
  0 siblings, 0 replies; 13+ messages in thread
From: Heiko Stübner @ 2014-02-05 12:05 UTC (permalink / raw)
  To: Grant Likely
  Cc: linux-arm-kernel, arm, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell

Am Mittwoch, 5. Februar 2014, 11:12:47 schrieb Grant Likely:
> On Mon, 20 Jan 2014 16:42:58 +0100, Heiko Stübner <heiko@sntech.de> wrote:
> > Some SoCs need parts of their sram for special purposes. So while being
> > part of the peripheral, it should not be part of the genpool controlling
> > the sram.
> > 
> > Therefore add an option mmio-sram-reserved to keep arbitrary portions of
> > the sram from general usage.
> > 
> > Suggested-by: Rob Herring <robherring2@gmail.com>
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
> > Acked-by: Rob Herring <robh@kernel.org>
> > ---
> > 
> >  Documentation/devicetree/bindings/misc/sram.txt |    8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/misc/sram.txt
> > b/Documentation/devicetree/bindings/misc/sram.txt index 4d0a00e..09ee7a3
> > 100644
> > --- a/Documentation/devicetree/bindings/misc/sram.txt
> > +++ b/Documentation/devicetree/bindings/misc/sram.txt
> > 
> > @@ -8,9 +8,17 @@ Required properties:
> >  - reg : SRAM iomem address range
> > 
> > +Optional properties:
> > +
> > +- mmio-sram-reserved: ordered list of reserved chunks inside the sram
> > that
> > +  should not be used by the operating system.
> > +  Format is <base size>, <base size>, ...; with base being relative to
> > the
> > +  reg property base.
> > +
> 
> We've now got a draft binding for reserved memory. Can you use the format
> here? Basically each reserved region is a sub node with either a reg
> property or a size property.
> 
> This is specifically for sram, so I won't make a big deal about it, but
> it would be good to have some commonality.

I guess you're talking about "[PATCH v2 0/5] reserved-memory regions/CMA in 
devicetree, again", right?

In general I'm all for commonality :-). So I guess you mean it to look 
something like the following:

	sram: sram@10080000 {
		compatible = "rockchip,rk3066-sram", "mmio-sram";
		reg = <0x10080000 0x8000>;

		reserved-memory {
			#address-cells = <1>;
			#size-cells = <1>;

			smp@200 {
				/* hmm, relative or absolute, aka 0x200 or 0x10080200? */
				reg = <0x200 0x50>;
			};
		};
	};

As it looks like only a slight modification of my "parsing" code this should be 
doable. Do you suggest more changes to the example above?


Heiko



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

end of thread, other threads:[~2014-02-05 12:06 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-20 15:41 [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
2014-01-20 15:42 ` [PATCH v7 1/7] of: add functions to count number of elements in a property Heiko Stübner
2014-01-20 15:42 ` [PATCH v7 2/7] dt-bindings: sram: describe option to reserve parts of the memory Heiko Stübner
     [not found]   ` <20140205111247.476B7C40A89@trevor.secretlab.ca>
2014-02-05 12:05     ` Heiko Stübner
2014-01-20 15:43 ` [PATCH v7 3/7] misc: sram: implement mmio-sram-reserved option Heiko Stübner
2014-01-20 15:44 ` [PATCH v7 4/7] ARM: rockchip: add snoop-control-unit Heiko Stübner
2014-01-20 15:44 ` [PATCH v7 5/7] ARM: rockchip: add sram dt nodes and documentation Heiko Stübner
2014-01-20 15:45 ` [PATCH v7 6/7] ARM: rockchip: add power-management-unit Heiko Stübner
2014-01-20 15:46 ` [PATCH v7 7/7] ARM: rockchip: add smp bringup code Heiko Stübner
2014-01-20 16:42   ` [PATCH v7.1 " Heiko Stübner
2014-01-31 22:03 ` [PATCH v7 0/7] ARM: rockchip: add smp functionality Heiko Stübner
2014-01-31 22:12   ` Rob Herring
2014-02-01 21:51   ` Philipp Zabel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).