linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms
@ 2018-08-31  3:52 Ran Wang
  2018-08-31  3:52 ` [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM Ran Wang
                   ` (3 more replies)
  0 siblings, 4 replies; 24+ messages in thread
From: Ran Wang @ 2018-08-31  3:52 UTC (permalink / raw)
  To: Leo Li, Rob Herring, Mark Rutland
  Cc: linuxppc-dev, linux-arm-kernel, devicetree, linux-kernel, Ran Wang

This driver is to provide a independent framework for PM service
provider and consumer to configure system level wake up feature. For
example, RCPM driver could register a callback function on this
platform first, and Flex timer driver who want to enable timer wake
up feature, will call generic API provided by this platform driver,
and then it will trigger RCPM driver to do it. The benefit is to
isolate the user and service, such as flex timer driver will not have
to know the implement details of wakeup function it require. Besides,
it is also easy for service side to upgrade its logic when design is
changed and remain user side unchanged.

Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
---
 drivers/soc/fsl/Kconfig   |   14 +++++
 drivers/soc/fsl/Makefile  |    1 +
 drivers/soc/fsl/plat_pm.c |  144 +++++++++++++++++++++++++++++++++++++++++++++
 include/soc/fsl/plat_pm.h |   22 +++++++
 4 files changed, 181 insertions(+), 0 deletions(-)
 create mode 100644 drivers/soc/fsl/plat_pm.c
 create mode 100644 include/soc/fsl/plat_pm.h

diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index 7a9fb9b..6517412 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -16,3 +16,17 @@ config FSL_GUTS
 	  Initially only reading SVR and registering soc device are supported.
 	  Other guts accesses, such as reading RCW, should eventually be moved
 	  into this driver as well.
+
+config FSL_PLAT_PM
+	bool "Freescale platform PM framework"
+	help
+	  This driver is to provide a independent framework for PM service
+	  provider and consumer to configure system level wake up feature. For
+	  example, RCPM driver could register a callback function on this
+	  platform first, and Flex timer driver who want to enable timer wake
+	  up feature, will call generic API provided by this platform driver,
+	  and then it will trigger RCPM driver to do it. The benefit is to
+	  isolate the user and service, such as  flex timer driver will not
+	  have to know the implement details of wakeup function it require.
+	  Besides, it is also easy for service side to upgrade its logic when
+	  design changed and remain user side unchanged.
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 44b3beb..8f9db23 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_FSL_DPAA)                 += qbman/
 obj-$(CONFIG_QUICC_ENGINE)		+= qe/
 obj-$(CONFIG_CPM)			+= qe/
 obj-$(CONFIG_FSL_GUTS)			+= guts.o
+obj-$(CONFIG_FSL_PLAT_PM)	+= plat_pm.o
diff --git a/drivers/soc/fsl/plat_pm.c b/drivers/soc/fsl/plat_pm.c
new file mode 100644
index 0000000..19ea14e
--- /dev/null
+++ b/drivers/soc/fsl/plat_pm.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// plat_pm.c - Freescale platform PM framework
+//
+// Copyright 2018 NXP
+//
+// Author: Ran Wang <ran.wang_1@nxp.com>,
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <soc/fsl/plat_pm.h>
+
+
+struct plat_pm_t {
+	struct list_head node;
+	fsl_plat_pm_handle handle;
+	void *handle_priv;
+	spinlock_t	lock;
+};
+
+static struct plat_pm_t plat_pm;
+
+// register_fsl_platform_wakeup_source - Register callback function to plat_pm
+// @handle: Pointer to handle PM feature requirement
+// @handle_priv: Handler specific data struct
+//
+// Return 0 on success other negative errno
+int register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
+		void *handle_priv)
+{
+	struct plat_pm_t *p;
+	unsigned long	flags;
+
+	if (!handle) {
+		pr_err("FSL plat_pm: Handler invalid, reject\n");
+		return -EINVAL;
+	}
+
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	p->handle = handle;
+	p->handle_priv = handle_priv;
+
+	spin_lock_irqsave(&plat_pm.lock, flags);
+	list_add_tail(&p->node, &plat_pm.node);
+	spin_unlock_irqrestore(&plat_pm.lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(register_fsl_platform_wakeup_source);
+
+// Deregister_fsl_platform_wakeup_source - deregister callback function
+// @handle_priv: Handler specific data struct
+//
+// Return 0 on success other negative errno
+int deregister_fsl_platform_wakeup_source(void *handle_priv)
+{
+	struct plat_pm_t *p, *tmp;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&plat_pm.lock, flags);
+	list_for_each_entry_safe(p, tmp, &plat_pm.node, node) {
+		if (p->handle_priv == handle_priv) {
+			list_del(&p->node);
+			kfree(p);
+		}
+	}
+	spin_unlock_irqrestore(&plat_pm.lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(deregister_fsl_platform_wakeup_source);
+
+// fsl_platform_wakeup_config - Configure wakeup source by calling handlers
+// @dev: pointer to user's device struct
+// @flag: to tell enable or disable wakeup source
+//
+// Return 0 on success other negative errno
+int fsl_platform_wakeup_config(struct device *dev, bool flag)
+{
+	struct plat_pm_t *p;
+	int ret;
+	bool success_handled;
+	unsigned long	flags;
+
+	success_handled = false;
+
+	// Will consider success if at least one callback return 0.
+	// Also, rest handles still get oppertunity to be executed
+	spin_lock_irqsave(&plat_pm.lock, flags);
+	list_for_each_entry(p, &plat_pm.node, node) {
+		if (p->handle) {
+			ret = p->handle(dev, flag, p->handle_priv);
+			if (!ret)
+				success_handled = true;
+			else if (ret != -ENODEV) {
+				pr_err("FSL plat_pm: Failed to config wakeup source:%d\n", ret);
+				return ret;
+			}
+		} else
+			pr_warn("FSL plat_pm: Invalid handler detected, skip\n");
+	}
+	spin_unlock_irqrestore(&plat_pm.lock, flags);
+
+	if (success_handled == false) {
+		pr_err("FSL plat_pm: Cannot find the matchhed handler for wakeup source config\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+// fsl_platform_wakeup_enable - Enable wakeup source
+// @dev: pointer to user's device struct
+//
+// Return 0 on success other negative errno
+int fsl_platform_wakeup_enable(struct device *dev)
+{
+	return fsl_platform_wakeup_config(dev, true);
+}
+EXPORT_SYMBOL_GPL(fsl_platform_wakeup_enable);
+
+// fsl_platform_wakeup_disable - Disable wakeup source
+// @dev: pointer to user's device struct
+//
+// Return 0 on success other negative errno
+int fsl_platform_wakeup_disable(struct device *dev)
+{
+	return fsl_platform_wakeup_config(dev, false);
+}
+EXPORT_SYMBOL_GPL(fsl_platform_wakeup_disable);
+
+static int __init fsl_plat_pm_init(void)
+{
+	spin_lock_init(&plat_pm.lock);
+	INIT_LIST_HEAD(&plat_pm.node);
+	return 0;
+}
+
+core_initcall(fsl_plat_pm_init);
diff --git a/include/soc/fsl/plat_pm.h b/include/soc/fsl/plat_pm.h
new file mode 100644
index 0000000..bbe151e
--- /dev/null
+++ b/include/soc/fsl/plat_pm.h
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// plat_pm.h - Freescale platform PM Header
+//
+// Copyright 2018 NXP
+//
+// Author: Ran Wang <ran.wang_1@nxp.com>,
+
+#ifndef __FSL_PLAT_PM_H
+#define __FSL_PLAT_PM_H
+
+typedef int (*fsl_plat_pm_handle)(struct device *dev, bool flag,
+		void *handle_priv);
+
+int register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
+		void *handle_priv);
+int deregister_fsl_platform_wakeup_source(void *handle_priv);
+int fsl_platform_wakeup_config(struct device *dev, bool flag);
+int fsl_platform_wakeup_enable(struct device *dev);
+int fsl_platform_wakeup_disable(struct device *dev);
+
+#endif	// __FSL_PLAT_PM_H
-- 
1.7.1


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

* [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM
  2018-08-31  3:52 [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms Ran Wang
@ 2018-08-31  3:52 ` Ran Wang
       [not found]   ` <5b8e8a71.1c69fb81.d966f.1ca1@mx.google.com>
  2018-09-07 20:22   ` Scott Wood
  2018-08-31  3:52 ` [PATCH 3/3] soc: fsl: add RCPM driver Ran Wang
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 24+ messages in thread
From: Ran Wang @ 2018-08-31  3:52 UTC (permalink / raw)
  To: Leo Li, Rob Herring, Mark Rutland
  Cc: linuxppc-dev, linux-arm-kernel, devicetree, linux-kernel, Ran Wang

Add property 'big-endian' and supportted IP's configuration info.
Remove property 'fsl,#rcpm-wakeup-cell'.

Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
---
 Documentation/devicetree/bindings/soc/fsl/rcpm.txt |   42 ++++++-------------
 1 files changed, 13 insertions(+), 29 deletions(-)

diff --git a/Documentation/devicetree/bindings/soc/fsl/rcpm.txt b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt
index e284e4e..7fc630a 100644
--- a/Documentation/devicetree/bindings/soc/fsl/rcpm.txt
+++ b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt
@@ -5,8 +5,6 @@ and power management.
 
 Required properites:
   - reg : Offset and length of the register set of the RCPM block.
-  - fsl,#rcpm-wakeup-cells : The number of IPPDEXPCR register cells in the
-	fsl,rcpm-wakeup property.
   - compatible : Must contain a chip-specific RCPM block compatible string
 	and (if applicable) may contain a chassis-version RCPM compatible
 	string. Chip-specific strings are of the form "fsl,<chip>-rcpm",
@@ -27,37 +25,23 @@ Chassis Version		Example Chips
 ---------------		-------------------------------
 1.0				p4080, p5020, p5040, p2041, p3041
 2.0				t4240, b4860, b4420
-2.1				t1040, ls1021
+2.1				t1040, ls1021, ls1012
+
+Optional properties:
+ - big-endian : Indicate RCPM registers is big-endian. A RCPM node
+   that doesn't have this property will be regarded as little-endian.
+ - <property 'compatible' string of consumer device> : This string
+   is referred by RCPM driver to judge if the consumer (such as flex timer)
+   is able to be regards as wakeup source or not, such as 'fsl,ls1012a-ftm'.
+   Further, this property will carry the bit mask info to control
+   coresponding wake up source.
 
 Example:
 The RCPM node for T4240:
 	rcpm: global-utilities@e2000 {
 		compatible = "fsl,t4240-rcpm", "fsl,qoriq-rcpm-2.0";
 		reg = <0xe2000 0x1000>;
-		fsl,#rcpm-wakeup-cells = <2>;
-	};
-
-* Freescale RCPM Wakeup Source Device Tree Bindings
--------------------------------------------
-Required fsl,rcpm-wakeup property should be added to a device node if the device
-can be used as a wakeup source.
-
-  - fsl,rcpm-wakeup: Consists of a phandle to the rcpm node and the IPPDEXPCR
-	register cells. The number of IPPDEXPCR register cells is defined in
-	"fsl,#rcpm-wakeup-cells" in the rcpm node. The first register cell is
-	the bit mask that should be set in IPPDEXPCR0, and the second register
-	cell is for IPPDEXPCR1, and so on.
-
-	Note: IPPDEXPCR(IP Powerdown Exception Control Register) provides a
-	mechanism for keeping certain blocks awake during STANDBY and MEM, in
-	order to use them as wake-up sources.
-
-Example:
-	lpuart0: serial@2950000 {
-		compatible = "fsl,ls1021a-lpuart";
-		reg = <0x0 0x2950000 0x0 0x1000>;
-		interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&sysclk>;
-		clock-names = "ipg";
-		fsl,rcpm-wakeup = <&rcpm 0x0 0x40000000>;
+		big-endian;
+		fsl,ls1012a-ftm = <0x20000>;
+		fsl,pfe = <0xf0000020>;
 	};
-- 
1.7.1


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

* [PATCH 3/3] soc: fsl: add RCPM driver
  2018-08-31  3:52 [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms Ran Wang
  2018-08-31  3:52 ` [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM Ran Wang
@ 2018-08-31  3:52 ` Ran Wang
  2018-09-05  2:57   ` Wang, Dongsheng
  2018-09-07 20:25   ` Scott Wood
  2018-09-05  3:04 ` [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms Wang, Dongsheng
  2018-09-07 20:35 ` Scott Wood
  3 siblings, 2 replies; 24+ messages in thread
From: Ran Wang @ 2018-08-31  3:52 UTC (permalink / raw)
  To: Leo Li, Rob Herring, Mark Rutland
  Cc: linuxppc-dev, linux-arm-kernel, devicetree, linux-kernel, Ran Wang

The NXP's QorIQ Processors based on ARM Core have RCPM module (Run
Control and Power Management), which performs all device-level
tasks associated with power management such as wakeup source control.

This driver depends on FSL platform PM driver framework which help to
isolate user and PM service provider (such as RCPM driver).

Signed-off-by: Chenhui Zhao <chenhui.zhao@nxp.com>
Signed-off-by: Ying Zhang <ying.zhang22455@nxp.com>
Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
---
 drivers/soc/fsl/Kconfig   |    6 ++
 drivers/soc/fsl/Makefile  |    1 +
 drivers/soc/fsl/ls-rcpm.c |  153 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 160 insertions(+), 0 deletions(-)
 create mode 100644 drivers/soc/fsl/ls-rcpm.c

diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index 6517412..882330d 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -30,3 +30,9 @@ config FSL_PLAT_PM
 	  have to know the implement details of wakeup function it require.
 	  Besides, it is also easy for service side to upgrade its logic when
 	  design changed and remain user side unchanged.
+
+config LS_RCPM
+	bool "Freescale RCPM support"
+	depends on (FSL_PLAT_PM)
+	help
+	  This feature is to enable specified wakeup source for system sleep.
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 8f9db23..43ff71a 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_QUICC_ENGINE)		+= qe/
 obj-$(CONFIG_CPM)			+= qe/
 obj-$(CONFIG_FSL_GUTS)			+= guts.o
 obj-$(CONFIG_FSL_PLAT_PM)	+= plat_pm.o
+obj-$(CONFIG_LS_RCPM)		+= ls-rcpm.o
diff --git a/drivers/soc/fsl/ls-rcpm.c b/drivers/soc/fsl/ls-rcpm.c
new file mode 100644
index 0000000..b0feb88
--- /dev/null
+++ b/drivers/soc/fsl/ls-rcpm.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// plat_pm.c - Freescale Layerscape RCPM driver
+//
+// Copyright 2018 NXP
+//
+// Author: Ran Wang <ran.wang_1@nxp.com>,
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <soc/fsl/plat_pm.h>
+
+#define MAX_COMPATIBLE_NUM	10
+
+struct rcpm_t {
+	struct device *dev;
+	void __iomem *ippdexpcr_addr;
+	bool big_endian;	/* Big/Little endian of RCPM module */
+};
+
+// rcpm_handle - Configure RCPM reg according to wake up source request
+// @user_dev: pointer to user's device struct
+// @flag: to enable(true) or disable(false) wakeup source
+// @handle_priv: pointer to struct rcpm_t instance
+//
+// Return 0 on success other negative errno
+static int rcpm_handle(struct device *user_dev, bool flag, void *handle_priv)
+{
+	struct rcpm_t *rcpm;
+	bool big_endian;
+	const char  *dev_compatible_array[MAX_COMPATIBLE_NUM];
+	void __iomem *ippdexpcr_addr;
+	u32 ippdexpcr;
+	u32 set_bit;
+	int ret, num, i;
+
+	rcpm = handle_priv;
+	big_endian = rcpm->big_endian;
+	ippdexpcr_addr = rcpm->ippdexpcr_addr;
+
+	num = device_property_read_string_array(user_dev, "compatible",
+			dev_compatible_array, MAX_COMPATIBLE_NUM);
+	if (num < 0)
+		return num;
+
+	for (i = 0; i < num; i++) {
+		if (!device_property_present(rcpm->dev,
+					dev_compatible_array[i]))
+			continue;
+		else {
+			ret = device_property_read_u32(rcpm->dev,
+					dev_compatible_array[i], &set_bit);
+			if (ret)
+				return ret;
+
+			if (!device_property_present(rcpm->dev,
+						dev_compatible_array[i]))
+				return -ENODEV;
+			else {
+				ret = device_property_read_u32(rcpm->dev,
+						dev_compatible_array[i], &set_bit);
+				if (ret)
+					return ret;
+
+				if (big_endian)
+					ippdexpcr = ioread32be(ippdexpcr_addr);
+				else
+					ippdexpcr = ioread32(ippdexpcr_addr);
+
+				if (flag)
+					ippdexpcr |= set_bit;
+				else
+					ippdexpcr &= ~set_bit;
+
+				if (big_endian) {
+					iowrite32be(ippdexpcr, ippdexpcr_addr);
+					ippdexpcr = ioread32be(ippdexpcr_addr);
+				} else
+					iowrite32(ippdexpcr, ippdexpcr_addr);
+
+				return 0;
+			}
+		}
+	}
+
+	return -ENODEV;
+}
+
+static int ls_rcpm_probe(struct platform_device *pdev)
+{
+	struct resource *r;
+	struct rcpm_t *rcpm;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	rcpm = kmalloc(sizeof(*rcpm), GFP_KERNEL);
+	if (!rcpm)
+		return -ENOMEM;
+
+	rcpm->big_endian = device_property_read_bool(&pdev->dev, "big-endian");
+
+	rcpm->ippdexpcr_addr = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(rcpm->ippdexpcr_addr))
+		return PTR_ERR(rcpm->ippdexpcr_addr);
+
+	rcpm->dev = &pdev->dev;
+	platform_set_drvdata(pdev, rcpm);
+
+	return register_fsl_platform_wakeup_source(rcpm_handle, rcpm);
+}
+
+static int ls_rcpm_remove(struct platform_device *pdev)
+{
+	struct rcpm_t	*rcpm;
+
+	rcpm = platform_get_drvdata(pdev);
+	deregister_fsl_platform_wakeup_source(rcpm);
+	kfree(rcpm);
+
+	return 0;
+}
+
+static const struct of_device_id ls_rcpm_of_match[] = {
+	{ .compatible = "fsl,qoriq-rcpm-2.1", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, ls_rcpm_of_match);
+
+static struct platform_driver ls_rcpm_driver = {
+	.driver = {
+		.name = "ls-rcpm",
+		.of_match_table = ls_rcpm_of_match,
+	},
+	.probe = ls_rcpm_probe,
+	.remove = ls_rcpm_remove,
+};
+
+static int __init ls_rcpm_init(void)
+{
+	return platform_driver_register(&ls_rcpm_driver);
+}
+subsys_initcall(ls_rcpm_init);
+
+static void __exit ls_rcpm_exit(void)
+{
+	platform_driver_unregister(&ls_rcpm_driver);
+}
+module_exit(ls_rcpm_exit);
-- 
1.7.1


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

* RE: [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM
       [not found]   ` <5b8e8a71.1c69fb81.d966f.1ca1@mx.google.com>
@ 2018-09-05  2:22     ` Ran Wang
  0 siblings, 0 replies; 24+ messages in thread
From: Ran Wang @ 2018-09-05  2:22 UTC (permalink / raw)
  To: Rob Herring
  Cc: Leo Li, Mark Rutland, linuxppc-dev, linux-arm-kernel, devicetree,
	linux-kernel

Hi Rob

> -----Original Message-----
> From: Rob Herring <robh@kernel.org>
> Sent: Tuesday, September 04, 2018 09:25
> To: Ran Wang <ran.wang_1@nxp.com>
> Cc: Leo Li <leoyang.li@nxp.com>; Mark Rutland <mark.rutland@arm.com>;
> linuxppc-dev@lists.ozlabs.org; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 2/3] Documentation: dt: binding: fsl: update property
> description for RCPM
> 
> On Fri, Aug 31, 2018 at 11:52:18AM +0800, Ran Wang wrote:
> > Add property 'big-endian' and supportted IP's configuration info.
> > Remove property 'fsl,#rcpm-wakeup-cell'.
> 
> "dt-bindings: soc: ..." for the subject
> 
> It is obvious reading the diff you are removing fsl,#rcpm-wakeup-cell.
> What is not obvious is why? The commit msg should answer that.

Sure, I will add this in next version patch.

> You also are mixing several things in this patch like adding ls1012 which you
> don't mention. Please split.

Got it, will split them and add more information in next version.
 
Ran
> >
> > Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> > ---
> >  Documentation/devicetree/bindings/soc/fsl/rcpm.txt |   42 ++++++-----------
> --
> >  1 files changed, 13 insertions(+), 29 deletions(-)


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

* Re: [PATCH 3/3] soc: fsl: add RCPM driver
  2018-08-31  3:52 ` [PATCH 3/3] soc: fsl: add RCPM driver Ran Wang
@ 2018-09-05  2:57   ` Wang, Dongsheng
  2018-09-05  3:21     ` Li Yang
  2018-09-07  9:32     ` Ran Wang
  2018-09-07 20:25   ` Scott Wood
  1 sibling, 2 replies; 24+ messages in thread
From: Wang, Dongsheng @ 2018-09-05  2:57 UTC (permalink / raw)
  To: Ran Wang, Leo Li, Rob Herring, Mark Rutland
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel

Please change your comments style.

On 2018/8/31 11:56, Ran Wang wrote:
> The NXP's QorIQ Processors based on ARM Core have RCPM module (Run
> Control and Power Management), which performs all device-level
> tasks associated with power management such as wakeup source control.
>
> This driver depends on FSL platform PM driver framework which help to
> isolate user and PM service provider (such as RCPM driver).
>
> Signed-off-by: Chenhui Zhao <chenhui.zhao@nxp.com>
> Signed-off-by: Ying Zhang <ying.zhang22455@nxp.com>
> Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> ---
>  drivers/soc/fsl/Kconfig   |    6 ++
>  drivers/soc/fsl/Makefile  |    1 +
>  drivers/soc/fsl/ls-rcpm.c |  153 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 160 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/soc/fsl/ls-rcpm.c
>
> diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
> index 6517412..882330d 100644
> --- a/drivers/soc/fsl/Kconfig
> +++ b/drivers/soc/fsl/Kconfig
> @@ -30,3 +30,9 @@ config FSL_PLAT_PM
>  	  have to know the implement details of wakeup function it require.
>  	  Besides, it is also easy for service side to upgrade its logic when
>  	  design changed and remain user side unchanged.
> +
> +config LS_RCPM
> +	bool "Freescale RCPM support"
> +	depends on (FSL_PLAT_PM)
> +	help
> +	  This feature is to enable specified wakeup source for system sleep.
> diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
> index 8f9db23..43ff71a 100644
> --- a/drivers/soc/fsl/Makefile
> +++ b/drivers/soc/fsl/Makefile
> @@ -7,3 +7,4 @@ obj-$(CONFIG_QUICC_ENGINE)		+= qe/
>  obj-$(CONFIG_CPM)			+= qe/
>  obj-$(CONFIG_FSL_GUTS)			+= guts.o
>  obj-$(CONFIG_FSL_PLAT_PM)	+= plat_pm.o
> +obj-$(CONFIG_LS_RCPM)		+= ls-rcpm.o
> diff --git a/drivers/soc/fsl/ls-rcpm.c b/drivers/soc/fsl/ls-rcpm.c
> new file mode 100644
> index 0000000..b0feb88
> --- /dev/null
> +++ b/drivers/soc/fsl/ls-rcpm.c
> @@ -0,0 +1,153 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// plat_pm.c - Freescale Layerscape RCPM driver
> +//
> +// Copyright 2018 NXP
> +//
> +// Author: Ran Wang <ran.wang_1@nxp.com>,
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <soc/fsl/plat_pm.h>
> +
> +#define MAX_COMPATIBLE_NUM	10
> +
> +struct rcpm_t {
> +	struct device *dev;
> +	void __iomem *ippdexpcr_addr;
> +	bool big_endian;	/* Big/Little endian of RCPM module */
> +};
> +
> +// rcpm_handle - Configure RCPM reg according to wake up source request
> +// @user_dev: pointer to user's device struct
> +// @flag: to enable(true) or disable(false) wakeup source
> +// @handle_priv: pointer to struct rcpm_t instance
> +//
> +// Return 0 on success other negative errno
> +static int rcpm_handle(struct device *user_dev, bool flag, void *handle_priv)
> +{
> +	struct rcpm_t *rcpm;
> +	bool big_endian;
> +	const char  *dev_compatible_array[MAX_COMPATIBLE_NUM];
> +	void __iomem *ippdexpcr_addr;
> +	u32 ippdexpcr;
> +	u32 set_bit;
> +	int ret, num, i;
> +
> +	rcpm = handle_priv;
> +	big_endian = rcpm->big_endian;
> +	ippdexpcr_addr = rcpm->ippdexpcr_addr;
> +
> +	num = device_property_read_string_array(user_dev, "compatible",
> +			dev_compatible_array, MAX_COMPATIBLE_NUM);
> +	if (num < 0)
> +		return num;
> +
> +	for (i = 0; i < num; i++) {
> +		if (!device_property_present(rcpm->dev,
> +					dev_compatible_array[i]))
> +			continue;
> +		else {
Remove this else.
> +			ret = device_property_read_u32(rcpm->dev,
> +					dev_compatible_array[i], &set_bit);
> +			if (ret)
> +				return ret;
> +
> +			if (!device_property_present(rcpm->dev,
> +						dev_compatible_array[i]))
This has been checked. Continue ? or return ENODEV?
> +				return -ENODEV;
> +			else {
Remove this else.
> +				ret = device_property_read_u32(rcpm->dev,
> +						dev_compatible_array[i], &set_bit);
> +				if (ret)
> +					return ret;
> +
> +				if (big_endian)
> +					ippdexpcr = ioread32be(ippdexpcr_addr);
> +				else
> +					ippdexpcr = ioread32(ippdexpcr_addr);
> +
> +				if (flag)
> +					ippdexpcr |= set_bit;
> +				else
> +					ippdexpcr &= ~set_bit;
> +
> +				if (big_endian) {
> +					iowrite32be(ippdexpcr, ippdexpcr_addr);
> +					ippdexpcr = ioread32be(ippdexpcr_addr);
> +				} else
if (x) {
...
...
}  else {

}
> +					iowrite32(ippdexpcr, ippdexpcr_addr);
> +
> +				return 0;
> +			}
> +		}
> +	}
> +
> +	return -ENODEV;
> +}
> +
> +static int ls_rcpm_probe(struct platform_device *pdev)
> +{
> +	struct resource *r;
> +	struct rcpm_t *rcpm;
> +
> +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!r)
> +		return -ENODEV;
> +
> +	rcpm = kmalloc(sizeof(*rcpm), GFP_KERNEL);
kzalloc is better.
> +	if (!rcpm)
> +		return -ENOMEM;
> +
> +	rcpm->big_endian = device_property_read_bool(&pdev->dev, "big-endian");
> +
> +	rcpm->ippdexpcr_addr = devm_ioremap_resource(&pdev->dev, r);
> +	if (IS_ERR(rcpm->ippdexpcr_addr))
> +		return PTR_ERR(rcpm->ippdexpcr_addr);
> +
> +	rcpm->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, rcpm);
> +
> +	return register_fsl_platform_wakeup_source(rcpm_handle, rcpm);
> +}
> +
> +static int ls_rcpm_remove(struct platform_device *pdev)
> +{
> +	struct rcpm_t	*rcpm;
Not need a table.

Cheers,
-Dongsheng

> +
> +	rcpm = platform_get_drvdata(pdev);
> +	deregister_fsl_platform_wakeup_source(rcpm);
> +	kfree(rcpm);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id ls_rcpm_of_match[] = {
> +	{ .compatible = "fsl,qoriq-rcpm-2.1", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, ls_rcpm_of_match);
> +
> +static struct platform_driver ls_rcpm_driver = {
> +	.driver = {
> +		.name = "ls-rcpm",
> +		.of_match_table = ls_rcpm_of_match,
> +	},
> +	.probe = ls_rcpm_probe,
> +	.remove = ls_rcpm_remove,
> +};
> +
> +static int __init ls_rcpm_init(void)
> +{
> +	return platform_driver_register(&ls_rcpm_driver);
> +}
> +subsys_initcall(ls_rcpm_init);
> +
> +static void __exit ls_rcpm_exit(void)
> +{
> +	platform_driver_unregister(&ls_rcpm_driver);
> +}
> +module_exit(ls_rcpm_exit);



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

* Re: [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms
  2018-08-31  3:52 [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms Ran Wang
  2018-08-31  3:52 ` [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM Ran Wang
  2018-08-31  3:52 ` [PATCH 3/3] soc: fsl: add RCPM driver Ran Wang
@ 2018-09-05  3:04 ` Wang, Dongsheng
  2018-09-07  8:41   ` Ran Wang
  2018-09-07 20:35 ` Scott Wood
  3 siblings, 1 reply; 24+ messages in thread
From: Wang, Dongsheng @ 2018-09-05  3:04 UTC (permalink / raw)
  To: Ran Wang, Leo Li, Rob Herring, Mark Rutland
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel

Please change your comments style.

On 2018/8/31 11:57, Ran Wang wrote:
> This driver is to provide a independent framework for PM service
> provider and consumer to configure system level wake up feature. For
> example, RCPM driver could register a callback function on this
> platform first, and Flex timer driver who want to enable timer wake
> up feature, will call generic API provided by this platform driver,
> and then it will trigger RCPM driver to do it. The benefit is to
> isolate the user and service, such as flex timer driver will not have
> to know the implement details of wakeup function it require. Besides,
> it is also easy for service side to upgrade its logic when design is
> changed and remain user side unchanged.
>
> Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> ---
>  drivers/soc/fsl/Kconfig   |   14 +++++
>  drivers/soc/fsl/Makefile  |    1 +
>  drivers/soc/fsl/plat_pm.c |  144 +++++++++++++++++++++++++++++++++++++++++++++
>  include/soc/fsl/plat_pm.h |   22 +++++++
>  4 files changed, 181 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/soc/fsl/plat_pm.c
>  create mode 100644 include/soc/fsl/plat_pm.h
>
> diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
> index 7a9fb9b..6517412 100644
> --- a/drivers/soc/fsl/Kconfig
> +++ b/drivers/soc/fsl/Kconfig
> @@ -16,3 +16,17 @@ config FSL_GUTS
>  	  Initially only reading SVR and registering soc device are supported.
>  	  Other guts accesses, such as reading RCW, should eventually be moved
>  	  into this driver as well.
> +
> +config FSL_PLAT_PM
> +	bool "Freescale platform PM framework"
> +	help
> +	  This driver is to provide a independent framework for PM service
> +	  provider and consumer to configure system level wake up feature. For
> +	  example, RCPM driver could register a callback function on this
> +	  platform first, and Flex timer driver who want to enable timer wake
> +	  up feature, will call generic API provided by this platform driver,
> +	  and then it will trigger RCPM driver to do it. The benefit is to
> +	  isolate the user and service, such as  flex timer driver will not
> +	  have to know the implement details of wakeup function it require.
> +	  Besides, it is also easy for service side to upgrade its logic when
> +	  design changed and remain user side unchanged.
> diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
> index 44b3beb..8f9db23 100644
> --- a/drivers/soc/fsl/Makefile
> +++ b/drivers/soc/fsl/Makefile
> @@ -6,3 +6,4 @@ obj-$(CONFIG_FSL_DPAA)                 += qbman/
>  obj-$(CONFIG_QUICC_ENGINE)		+= qe/
>  obj-$(CONFIG_CPM)			+= qe/
>  obj-$(CONFIG_FSL_GUTS)			+= guts.o
> +obj-$(CONFIG_FSL_PLAT_PM)	+= plat_pm.o
> diff --git a/drivers/soc/fsl/plat_pm.c b/drivers/soc/fsl/plat_pm.c
> new file mode 100644
> index 0000000..19ea14e
> --- /dev/null
> +++ b/drivers/soc/fsl/plat_pm.c
> @@ -0,0 +1,144 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// plat_pm.c - Freescale platform PM framework
> +//
> +// Copyright 2018 NXP
> +//
> +// Author: Ran Wang <ran.wang_1@nxp.com>,
> +
> +#include <linux/kernel.h>
> +#include <linux/device.h>
> +#include <linux/list.h>
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +#include <soc/fsl/plat_pm.h>
> +
> +
> +struct plat_pm_t {
> +	struct list_head node;
> +	fsl_plat_pm_handle handle;
> +	void *handle_priv;
> +	spinlock_t	lock;
> +};
> +
> +static struct plat_pm_t plat_pm;
> +
> +// register_fsl_platform_wakeup_source - Register callback function to plat_pm
> +// @handle: Pointer to handle PM feature requirement
> +// @handle_priv: Handler specific data struct
> +//
> +// Return 0 on success other negative errno
> +int register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
> +		void *handle_priv)
> +{
> +	struct plat_pm_t *p;
> +	unsigned long	flags;
> +
> +	if (!handle) {
> +		pr_err("FSL plat_pm: Handler invalid, reject\n");
> +		return -EINVAL;
> +	}
> +
> +	p = kmalloc(sizeof(*p), GFP_KERNEL);
> +	if (!p)
> +		return -ENOMEM;
> +
> +	p->handle = handle;
> +	p->handle_priv = handle_priv;
> +
> +	spin_lock_irqsave(&plat_pm.lock, flags);
> +	list_add_tail(&p->node, &plat_pm.node);
> +	spin_unlock_irqrestore(&plat_pm.lock, flags);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(register_fsl_platform_wakeup_source);
> +
> +// Deregister_fsl_platform_wakeup_source - deregister callback function
> +// @handle_priv: Handler specific data struct
> +//
> +// Return 0 on success other negative errno
> +int deregister_fsl_platform_wakeup_source(void *handle_priv)
> +{
> +	struct plat_pm_t *p, *tmp;
> +	unsigned long	flags;
> +
> +	spin_lock_irqsave(&plat_pm.lock, flags);
> +	list_for_each_entry_safe(p, tmp, &plat_pm.node, node) {
> +		if (p->handle_priv == handle_priv) {
> +			list_del(&p->node);
> +			kfree(p);
> +		}
> +	}
> +	spin_unlock_irqrestore(&plat_pm.lock, flags);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(deregister_fsl_platform_wakeup_source);
> +
> +// fsl_platform_wakeup_config - Configure wakeup source by calling handlers
> +// @dev: pointer to user's device struct
> +// @flag: to tell enable or disable wakeup source
> +//
> +// Return 0 on success other negative errno
> +int fsl_platform_wakeup_config(struct device *dev, bool flag)
> +{
> +	struct plat_pm_t *p;
> +	int ret;
> +	bool success_handled;
> +	unsigned long	flags;
> +
> +	success_handled = false;
> +
> +	// Will consider success if at least one callback return 0.
> +	// Also, rest handles still get oppertunity to be executed
> +	spin_lock_irqsave(&plat_pm.lock, flags);
> +	list_for_each_entry(p, &plat_pm.node, node) {
> +		if (p->handle) {
> +			ret = p->handle(dev, flag, p->handle_priv);
> +			if (!ret)
> +				success_handled = true;
Miss a break?

> +			else if (ret != -ENODEV) {
> +				pr_err("FSL plat_pm: Failed to config wakeup source:%d\n", ret);
Please unlock before return.

> +				return ret;
> +			}
> +		} else
> +			pr_warn("FSL plat_pm: Invalid handler detected, skip\n");
> +	}
> +	spin_unlock_irqrestore(&plat_pm.lock, flags);
> +
> +	if (success_handled == false) {
> +		pr_err("FSL plat_pm: Cannot find the matchhed handler for wakeup source config\n");
> +		return -ENODEV;
> +	}
Add this into the loop.
> +
> +	return 0;
> +}
> +
> +// fsl_platform_wakeup_enable - Enable wakeup source
> +// @dev: pointer to user's device struct
> +//
> +// Return 0 on success other negative errno
> +int fsl_platform_wakeup_enable(struct device *dev)
> +{
> +	return fsl_platform_wakeup_config(dev, true);
> +}
> +EXPORT_SYMBOL_GPL(fsl_platform_wakeup_enable);
> +
> +// fsl_platform_wakeup_disable - Disable wakeup source
> +// @dev: pointer to user's device struct
> +//
> +// Return 0 on success other negative errno
> +int fsl_platform_wakeup_disable(struct device *dev)
> +{
> +	return fsl_platform_wakeup_config(dev, false);
> +}
> +EXPORT_SYMBOL_GPL(fsl_platform_wakeup_disable);
> +
> +static int __init fsl_plat_pm_init(void)
> +{
> +	spin_lock_init(&plat_pm.lock);
> +	INIT_LIST_HEAD(&plat_pm.node);
> +	return 0;
> +}
> +
> +core_initcall(fsl_plat_pm_init);
> diff --git a/include/soc/fsl/plat_pm.h b/include/soc/fsl/plat_pm.h
> new file mode 100644
> index 0000000..bbe151e
> --- /dev/null
> +++ b/include/soc/fsl/plat_pm.h
> @@ -0,0 +1,22 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// plat_pm.h - Freescale platform PM Header
> +//
> +// Copyright 2018 NXP
> +//
> +// Author: Ran Wang <ran.wang_1@nxp.com>,
> +
> +#ifndef __FSL_PLAT_PM_H
> +#define __FSL_PLAT_PM_H
> +
> +typedef int (*fsl_plat_pm_handle)(struct device *dev, bool flag,
> +		void *handle_priv);
> +
> +int register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
> +		void *handle_priv);
> +int deregister_fsl_platform_wakeup_source(void *handle_priv);
> +int fsl_platform_wakeup_config(struct device *dev, bool flag);
> +int fsl_platform_wakeup_enable(struct device *dev);
> +int fsl_platform_wakeup_disable(struct device *dev);
> +
> +#endif	// __FSL_PLAT_PM_H



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

* Re: [PATCH 3/3] soc: fsl: add RCPM driver
  2018-09-05  2:57   ` Wang, Dongsheng
@ 2018-09-05  3:21     ` Li Yang
  2018-09-07  9:48       ` Ran Wang
  2018-09-07  9:32     ` Ran Wang
  1 sibling, 1 reply; 24+ messages in thread
From: Li Yang @ 2018-09-05  3:21 UTC (permalink / raw)
  To: dongsheng.wang
  Cc: Ran Wang, Rob Herring, Mark Rutland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linuxppc-dev, lkml,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On Tue, Sep 4, 2018 at 9:58 PM Wang, Dongsheng
<dongsheng.wang@hxt-semitech.com> wrote:
>
> Please change your comments style.

Although this doesn't get into the Linux kernel coding style
documentation yet, Linus seems changed his mind to prefer // than /*
*/ comment style now.  https://lkml.org/lkml/2017/11/25/133   So the
// style should be acceptable for now.

>
> On 2018/8/31 11:56, Ran Wang wrote:
> > The NXP's QorIQ Processors based on ARM Core have RCPM module (Run
> > Control and Power Management), which performs all device-level
> > tasks associated with power management such as wakeup source control.
> >
> > This driver depends on FSL platform PM driver framework which help to
> > isolate user and PM service provider (such as RCPM driver).
> >
> > Signed-off-by: Chenhui Zhao <chenhui.zhao@nxp.com>
> > Signed-off-by: Ying Zhang <ying.zhang22455@nxp.com>
> > Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> > ---
> >  drivers/soc/fsl/Kconfig   |    6 ++
> >  drivers/soc/fsl/Makefile  |    1 +
> >  drivers/soc/fsl/ls-rcpm.c |  153 +++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 160 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/soc/fsl/ls-rcpm.c
> >
> > diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
> > index 6517412..882330d 100644
> > --- a/drivers/soc/fsl/Kconfig
> > +++ b/drivers/soc/fsl/Kconfig
> > @@ -30,3 +30,9 @@ config FSL_PLAT_PM
> >         have to know the implement details of wakeup function it require.
> >         Besides, it is also easy for service side to upgrade its logic when
> >         design changed and remain user side unchanged.
> > +
> > +config LS_RCPM
> > +     bool "Freescale RCPM support"
> > +     depends on (FSL_PLAT_PM)
> > +     help
> > +       This feature is to enable specified wakeup source for system sleep.
> > diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
> > index 8f9db23..43ff71a 100644
> > --- a/drivers/soc/fsl/Makefile
> > +++ b/drivers/soc/fsl/Makefile
> > @@ -7,3 +7,4 @@ obj-$(CONFIG_QUICC_ENGINE)            += qe/
> >  obj-$(CONFIG_CPM)                    += qe/
> >  obj-$(CONFIG_FSL_GUTS)                       += guts.o
> >  obj-$(CONFIG_FSL_PLAT_PM)    += plat_pm.o
> > +obj-$(CONFIG_LS_RCPM)                += ls-rcpm.o

Probably use "_" instead of "-" for alignment.

> > diff --git a/drivers/soc/fsl/ls-rcpm.c b/drivers/soc/fsl/ls-rcpm.c
> > new file mode 100644
> > index 0000000..b0feb88
> > --- /dev/null
> > +++ b/drivers/soc/fsl/ls-rcpm.c
> > @@ -0,0 +1,153 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// plat_pm.c - Freescale Layerscape RCPM driver

The file name here is not the same as the real file name.

> > +//
> > +// Copyright 2018 NXP
> > +//
> > +// Author: Ran Wang <ran.wang_1@nxp.com>,

Where do you need the comma in the end?

> > +
> > +#include <linux/init.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/of_address.h>
> > +#include <linux/slab.h>
> > +#include <soc/fsl/plat_pm.h>
> > +
> > +#define MAX_COMPATIBLE_NUM   10
> > +
> > +struct rcpm_t {
> > +     struct device *dev;
> > +     void __iomem *ippdexpcr_addr;
> > +     bool big_endian;        /* Big/Little endian of RCPM module */
> > +};
> > +
> > +// rcpm_handle - Configure RCPM reg according to wake up source request
> > +// @user_dev: pointer to user's device struct
> > +// @flag: to enable(true) or disable(false) wakeup source
> > +// @handle_priv: pointer to struct rcpm_t instance
> > +//
> > +// Return 0 on success other negative errno

Although Linus preferred this // comment style.  I'm not sure if this
will be handled correctly by the kernel-doc compiler.
https://www.kernel.org/doc/html/v4.18/doc-guide/kernel-doc.html

> > +static int rcpm_handle(struct device *user_dev, bool flag, void *handle_priv)
> > +{
> > +     struct rcpm_t *rcpm;
> > +     bool big_endian;
> > +     const char  *dev_compatible_array[MAX_COMPATIBLE_NUM];
> > +     void __iomem *ippdexpcr_addr;
> > +     u32 ippdexpcr;
> > +     u32 set_bit;
> > +     int ret, num, i;
> > +
> > +     rcpm = handle_priv;
> > +     big_endian = rcpm->big_endian;
> > +     ippdexpcr_addr = rcpm->ippdexpcr_addr;
> > +
> > +     num = device_property_read_string_array(user_dev, "compatible",
> > +                     dev_compatible_array, MAX_COMPATIBLE_NUM);
> > +     if (num < 0)
> > +             return num;
> > +
> > +     for (i = 0; i < num; i++) {
> > +             if (!device_property_present(rcpm->dev,
> > +                                     dev_compatible_array[i]))
> > +                     continue;
> > +             else {
> Remove this else.
> > +                     ret = device_property_read_u32(rcpm->dev,
> > +                                     dev_compatible_array[i], &set_bit);
> > +                     if (ret)
> > +                             return ret;
> > +
> > +                     if (!device_property_present(rcpm->dev,
> > +                                             dev_compatible_array[i]))
> This has been checked. Continue ? or return ENODEV?
> > +                             return -ENODEV;
> > +                     else {
> Remove this else.
> > +                             ret = device_property_read_u32(rcpm->dev,
> > +                                             dev_compatible_array[i], &set_bit);
> > +                             if (ret)
> > +                                     return ret;
> > +
> > +                             if (big_endian)
> > +                                     ippdexpcr = ioread32be(ippdexpcr_addr);
> > +                             else
> > +                                     ippdexpcr = ioread32(ippdexpcr_addr);
> > +
> > +                             if (flag)
> > +                                     ippdexpcr |= set_bit;
> > +                             else
> > +                                     ippdexpcr &= ~set_bit;
> > +
> > +                             if (big_endian) {
> > +                                     iowrite32be(ippdexpcr, ippdexpcr_addr);
> > +                                     ippdexpcr = ioread32be(ippdexpcr_addr);
> > +                             } else
> if (x) {
> ....
> ....
> }  else {
>
> }
> > +                                     iowrite32(ippdexpcr, ippdexpcr_addr);
> > +
> > +                             return 0;
> > +                     }
> > +             }
> > +     }
> > +
> > +     return -ENODEV;
> > +}
> > +
> > +static int ls_rcpm_probe(struct platform_device *pdev)
> > +{
> > +     struct resource *r;
> > +     struct rcpm_t *rcpm;
> > +
> > +     r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +     if (!r)
> > +             return -ENODEV;
> > +
> > +     rcpm = kmalloc(sizeof(*rcpm), GFP_KERNEL);
> kzalloc is better.
> > +     if (!rcpm)
> > +             return -ENOMEM;
> > +
> > +     rcpm->big_endian = device_property_read_bool(&pdev->dev, "big-endian");
> > +
> > +     rcpm->ippdexpcr_addr = devm_ioremap_resource(&pdev->dev, r);
> > +     if (IS_ERR(rcpm->ippdexpcr_addr))
> > +             return PTR_ERR(rcpm->ippdexpcr_addr);
> > +
> > +     rcpm->dev = &pdev->dev;
> > +     platform_set_drvdata(pdev, rcpm);
> > +
> > +     return register_fsl_platform_wakeup_source(rcpm_handle, rcpm);
> > +}
> > +
> > +static int ls_rcpm_remove(struct platform_device *pdev)
> > +{
> > +     struct rcpm_t   *rcpm;
> Not need a table.
>
> Cheers,
> -Dongsheng
>
> > +
> > +     rcpm = platform_get_drvdata(pdev);
> > +     deregister_fsl_platform_wakeup_source(rcpm);
> > +     kfree(rcpm);
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct of_device_id ls_rcpm_of_match[] = {
> > +     { .compatible = "fsl,qoriq-rcpm-2.1", },
> > +     {}
> > +};
> > +MODULE_DEVICE_TABLE(of, ls_rcpm_of_match);
> > +
> > +static struct platform_driver ls_rcpm_driver = {
> > +     .driver = {
> > +             .name = "ls-rcpm",
> > +             .of_match_table = ls_rcpm_of_match,
> > +     },
> > +     .probe = ls_rcpm_probe,
> > +     .remove = ls_rcpm_remove,
> > +};
> > +
> > +static int __init ls_rcpm_init(void)
> > +{
> > +     return platform_driver_register(&ls_rcpm_driver);
> > +}
> > +subsys_initcall(ls_rcpm_init);
> > +
> > +static void __exit ls_rcpm_exit(void)
> > +{
> > +     platform_driver_unregister(&ls_rcpm_driver);
> > +}
> > +module_exit(ls_rcpm_exit);
>
>

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

* RE: [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms
  2018-09-05  3:04 ` [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms Wang, Dongsheng
@ 2018-09-07  8:41   ` Ran Wang
  2018-09-07 10:15     ` Wang, Dongsheng
  0 siblings, 1 reply; 24+ messages in thread
From: Ran Wang @ 2018-09-07  8:41 UTC (permalink / raw)
  To: Wang, Dongsheng
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel, Leo Li,
	Rob Herring, Mark Rutland

Hi Dongsheng

> On 2018/9/5 11:05, Dongsheng Wang wrote:
> 
> Please change your comments style.
> 
> On 2018/8/31 11:57, Ran Wang wrote:
> > This driver is to provide a independent framework for PM service
> > provider and consumer to configure system level wake up feature. For
> > example, RCPM driver could register a callback function on this
> > platform first, and Flex timer driver who want to enable timer wake up
> > feature, will call generic API provided by this platform driver, and
> > then it will trigger RCPM driver to do it. The benefit is to isolate
> > the user and service, such as flex timer driver will not have to know
> > the implement details of wakeup function it require. Besides, it is
> > also easy for service side to upgrade its logic when design is changed
> > and remain user side unchanged.
> >
> > Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> > ---
> >  drivers/soc/fsl/Kconfig   |   14 +++++
> >  drivers/soc/fsl/Makefile  |    1 +
> >  drivers/soc/fsl/plat_pm.c |  144
> +++++++++++++++++++++++++++++++++++++++++++++
> >  include/soc/fsl/plat_pm.h |   22 +++++++
> >  4 files changed, 181 insertions(+), 0 deletions(-)  create mode
> > 100644 drivers/soc/fsl/plat_pm.c  create mode 100644
> > include/soc/fsl/plat_pm.h
> >
> > diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig index
> > 7a9fb9b..6517412 100644
> > --- a/drivers/soc/fsl/Kconfig
> > +++ b/drivers/soc/fsl/Kconfig
> > @@ -16,3 +16,17 @@ config FSL_GUTS
> >  	  Initially only reading SVR and registering soc device are supported.
> >  	  Other guts accesses, such as reading RCW, should eventually be
> moved
> >  	  into this driver as well.
> > +
> > +config FSL_PLAT_PM
> > +	bool "Freescale platform PM framework"
> > +	help
> > +	  This driver is to provide a independent framework for PM service
> > +	  provider and consumer to configure system level wake up feature.
> For
> > +	  example, RCPM driver could register a callback function on this
> > +	  platform first, and Flex timer driver who want to enable timer wake
> > +	  up feature, will call generic API provided by this platform driver,
> > +	  and then it will trigger RCPM driver to do it. The benefit is to
> > +	  isolate the user and service, such as  flex timer driver will not
> > +	  have to know the implement details of wakeup function it require.
> > +	  Besides, it is also easy for service side to upgrade its logic when
> > +	  design changed and remain user side unchanged.
> > diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile index
> > 44b3beb..8f9db23 100644
> > --- a/drivers/soc/fsl/Makefile
> > +++ b/drivers/soc/fsl/Makefile
> > @@ -6,3 +6,4 @@ obj-$(CONFIG_FSL_DPAA)                 += qbman/
> >  obj-$(CONFIG_QUICC_ENGINE)		+= qe/
> >  obj-$(CONFIG_CPM)			+= qe/
> >  obj-$(CONFIG_FSL_GUTS)			+= guts.o
> > +obj-$(CONFIG_FSL_PLAT_PM)	+= plat_pm.o
> > diff --git a/drivers/soc/fsl/plat_pm.c b/drivers/soc/fsl/plat_pm.c new
> > file mode 100644 index 0000000..19ea14e
> > --- /dev/null
> > +++ b/drivers/soc/fsl/plat_pm.c
> > @@ -0,0 +1,144 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// plat_pm.c - Freescale platform PM framework // // Copyright 2018
> > +NXP // // Author: Ran Wang <ran.wang_1@nxp.com>,
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/device.h>
> > +#include <linux/list.h>
> > +#include <linux/slab.h>
> > +#include <linux/err.h>
> > +#include <soc/fsl/plat_pm.h>
> > +
> > +
> > +struct plat_pm_t {
> > +	struct list_head node;
> > +	fsl_plat_pm_handle handle;
> > +	void *handle_priv;
> > +	spinlock_t	lock;
> > +};
> > +
> > +static struct plat_pm_t plat_pm;
> > +
> > +// register_fsl_platform_wakeup_source - Register callback function
> > +to plat_pm // @handle: Pointer to handle PM feature requirement //
> > +@handle_priv: Handler specific data struct // // Return 0 on success
> > +other negative errno int
> > +register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
> > +		void *handle_priv)
> > +{
> > +	struct plat_pm_t *p;
> > +	unsigned long	flags;
> > +
> > +	if (!handle) {
> > +		pr_err("FSL plat_pm: Handler invalid, reject\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	p = kmalloc(sizeof(*p), GFP_KERNEL);
> > +	if (!p)
> > +		return -ENOMEM;
> > +
> > +	p->handle = handle;
> > +	p->handle_priv = handle_priv;
> > +
> > +	spin_lock_irqsave(&plat_pm.lock, flags);
> > +	list_add_tail(&p->node, &plat_pm.node);
> > +	spin_unlock_irqrestore(&plat_pm.lock, flags);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(register_fsl_platform_wakeup_source);
> > +
> > +// Deregister_fsl_platform_wakeup_source - deregister callback
> > +function // @handle_priv: Handler specific data struct // // Return 0
> > +on success other negative errno int
> > +deregister_fsl_platform_wakeup_source(void *handle_priv) {
> > +	struct plat_pm_t *p, *tmp;
> > +	unsigned long	flags;
> > +
> > +	spin_lock_irqsave(&plat_pm.lock, flags);
> > +	list_for_each_entry_safe(p, tmp, &plat_pm.node, node) {
> > +		if (p->handle_priv == handle_priv) {
> > +			list_del(&p->node);
> > +			kfree(p);
> > +		}
> > +	}
> > +	spin_unlock_irqrestore(&plat_pm.lock, flags);
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(deregister_fsl_platform_wakeup_source);
> > +
> > +// fsl_platform_wakeup_config - Configure wakeup source by calling
> > +handlers // @dev: pointer to user's device struct // @flag: to tell
> > +enable or disable wakeup source // // Return 0 on success other
> > +negative errno int fsl_platform_wakeup_config(struct device *dev,
> > +bool flag) {
> > +	struct plat_pm_t *p;
> > +	int ret;
> > +	bool success_handled;
> > +	unsigned long	flags;
> > +
> > +	success_handled = false;
> > +
> > +	// Will consider success if at least one callback return 0.
> > +	// Also, rest handles still get oppertunity to be executed
> > +	spin_lock_irqsave(&plat_pm.lock, flags);
> > +	list_for_each_entry(p, &plat_pm.node, node) {
> > +		if (p->handle) {
> > +			ret = p->handle(dev, flag, p->handle_priv);
> > +			if (!ret)
> > +				success_handled = true;
> Miss a break?

Actually my idea is to allow more than one registered handler to handle this
request, so I define a flag rather than return to indicated if there is at least one handler successfully
do it. This design might give more flexibility to framework when running.

> > +			else if (ret != -ENODEV) {
> > +				pr_err("FSL plat_pm: Failed to config wakeup
> source:%d\n", ret);
> Please unlock before return.

Yes, will fix it in next version, thanks for pointing out!

> > +				return ret;
> > +			}
> > +		} else
> > +			pr_warn("FSL plat_pm: Invalid handler detected,
> skip\n");
> > +	}
> > +	spin_unlock_irqrestore(&plat_pm.lock, flags);
> > +
> > +	if (success_handled == false) {
> > +		pr_err("FSL plat_pm: Cannot find the matchhed handler for
> wakeup source config\n");
> > +		return -ENODEV;
> > +	}
> Add this into the loop.

My design is that if the 1st handler return -ENODEV to indicated this device it doesn't support, 
then the framework will continue try 2nd handler...

So I think it is needed to place this checking out of loop, what do you say?

Regards,
Ran
> > +
> > +	return 0;
> > +}
> > +
> > +// fsl_platform_wakeup_enable - Enable wakeup source // @dev: pointer
> > +to user's device struct // // Return 0 on success other negative
> > +errno int fsl_platform_wakeup_enable(struct device *dev) {
> > +	return fsl_platform_wakeup_config(dev, true); }
> > +EXPORT_SYMBOL_GPL(fsl_platform_wakeup_enable);
> > +
> > +// fsl_platform_wakeup_disable - Disable wakeup source // @dev:
> > +pointer to user's device struct // // Return 0 on success other
> > +negative errno int fsl_platform_wakeup_disable(struct device *dev) {
> > +	return fsl_platform_wakeup_config(dev, false); }
> > +EXPORT_SYMBOL_GPL(fsl_platform_wakeup_disable);
> > +
> > +static int __init fsl_plat_pm_init(void) {
> > +	spin_lock_init(&plat_pm.lock);
> > +	INIT_LIST_HEAD(&plat_pm.node);
> > +	return 0;
> > +}
> > +
> > +core_initcall(fsl_plat_pm_init);
> > diff --git a/include/soc/fsl/plat_pm.h b/include/soc/fsl/plat_pm.h new
> > file mode 100644 index 0000000..bbe151e
> > --- /dev/null
> > +++ b/include/soc/fsl/plat_pm.h
> > @@ -0,0 +1,22 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// plat_pm.h - Freescale platform PM Header // // Copyright 2018 NXP
> > +// // Author: Ran Wang <ran.wang_1@nxp.com>,
> > +
> > +#ifndef __FSL_PLAT_PM_H
> > +#define __FSL_PLAT_PM_H
> > +
> > +typedef int (*fsl_plat_pm_handle)(struct device *dev, bool flag,
> > +		void *handle_priv);
> > +
> > +int register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
> > +		void *handle_priv);
> > +int deregister_fsl_platform_wakeup_source(void *handle_priv); int
> > +fsl_platform_wakeup_config(struct device *dev, bool flag); int
> > +fsl_platform_wakeup_enable(struct device *dev); int
> > +fsl_platform_wakeup_disable(struct device *dev);
> > +
> > +#endif	// __FSL_PLAT_PM_H
> 


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

* RE: [PATCH 3/3] soc: fsl: add RCPM driver
  2018-09-05  2:57   ` Wang, Dongsheng
  2018-09-05  3:21     ` Li Yang
@ 2018-09-07  9:32     ` Ran Wang
  1 sibling, 0 replies; 24+ messages in thread
From: Ran Wang @ 2018-09-07  9:32 UTC (permalink / raw)
  To: Wang, Dongsheng, Leo Li, Rob Herring, Mark Rutland
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel

Hi Dongsheng,

On 2018/9/5 10:58, Dongsheng Wang wrote:
> 
> Please change your comments style.
> 
> On 2018/8/31 11:56, Ran Wang wrote:
> > The NXP's QorIQ Processors based on ARM Core have RCPM module (Run
> > Control and Power Management), which performs all device-level tasks
> > associated with power management such as wakeup source control.
> >
> > This driver depends on FSL platform PM driver framework which help to
> > isolate user and PM service provider (such as RCPM driver).
> >
> > Signed-off-by: Chenhui Zhao <chenhui.zhao@nxp.com>
> > Signed-off-by: Ying Zhang <ying.zhang22455@nxp.com>
> > Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> > ---
> >  drivers/soc/fsl/Kconfig   |    6 ++
> >  drivers/soc/fsl/Makefile  |    1 +
> >  drivers/soc/fsl/ls-rcpm.c |  153
> > +++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 160 insertions(+), 0 deletions(-)  create mode
> > 100644 drivers/soc/fsl/ls-rcpm.c
> >
> > diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig index
> > 6517412..882330d 100644
> > --- a/drivers/soc/fsl/Kconfig
> > +++ b/drivers/soc/fsl/Kconfig
> > @@ -30,3 +30,9 @@ config FSL_PLAT_PM
> >  	  have to know the implement details of wakeup function it require.
> >  	  Besides, it is also easy for service side to upgrade its logic when
> >  	  design changed and remain user side unchanged.
> > +
> > +config LS_RCPM
> > +	bool "Freescale RCPM support"
> > +	depends on (FSL_PLAT_PM)
> > +	help
> > +	  This feature is to enable specified wakeup source for system sleep.
> > diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile index
> > 8f9db23..43ff71a 100644
> > --- a/drivers/soc/fsl/Makefile
> > +++ b/drivers/soc/fsl/Makefile
> > @@ -7,3 +7,4 @@ obj-$(CONFIG_QUICC_ENGINE)		+= qe/
> >  obj-$(CONFIG_CPM)			+= qe/
> >  obj-$(CONFIG_FSL_GUTS)			+= guts.o
> >  obj-$(CONFIG_FSL_PLAT_PM)	+= plat_pm.o
> > +obj-$(CONFIG_LS_RCPM)		+= ls-rcpm.o
> > diff --git a/drivers/soc/fsl/ls-rcpm.c b/drivers/soc/fsl/ls-rcpm.c new
> > file mode 100644 index 0000000..b0feb88
> > --- /dev/null
> > +++ b/drivers/soc/fsl/ls-rcpm.c
> > @@ -0,0 +1,153 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// plat_pm.c - Freescale Layerscape RCPM driver // // Copyright 2018
> > +NXP // // Author: Ran Wang <ran.wang_1@nxp.com>,
> > +
> > +#include <linux/init.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/of_address.h>
> > +#include <linux/slab.h>
> > +#include <soc/fsl/plat_pm.h>
> > +
> > +#define MAX_COMPATIBLE_NUM	10
> > +
> > +struct rcpm_t {
> > +	struct device *dev;
> > +	void __iomem *ippdexpcr_addr;
> > +	bool big_endian;	/* Big/Little endian of RCPM module */
> > +};
> > +
> > +// rcpm_handle - Configure RCPM reg according to wake up source
> > +request // @user_dev: pointer to user's device struct // @flag: to
> > +enable(true) or disable(false) wakeup source // @handle_priv: pointer
> > +to struct rcpm_t instance // // Return 0 on success other negative
> > +errno static int rcpm_handle(struct device *user_dev, bool flag, void
> > +*handle_priv) {
> > +	struct rcpm_t *rcpm;
> > +	bool big_endian;
> > +	const char  *dev_compatible_array[MAX_COMPATIBLE_NUM];
> > +	void __iomem *ippdexpcr_addr;
> > +	u32 ippdexpcr;
> > +	u32 set_bit;
> > +	int ret, num, i;
> > +
> > +	rcpm = handle_priv;
> > +	big_endian = rcpm->big_endian;
> > +	ippdexpcr_addr = rcpm->ippdexpcr_addr;
> > +
> > +	num = device_property_read_string_array(user_dev, "compatible",
> > +			dev_compatible_array, MAX_COMPATIBLE_NUM);
> > +	if (num < 0)
> > +		return num;
> > +
> > +	for (i = 0; i < num; i++) {
> > +		if (!device_property_present(rcpm->dev,
> > +					dev_compatible_array[i]))
> > +			continue;
> > +		else {
> Remove this else.

Got it! Will update in next version.

> > +			ret = device_property_read_u32(rcpm->dev,
> > +					dev_compatible_array[i], &set_bit);
> > +			if (ret)
> > +				return ret;
> > +
> > +			if (!device_property_present(rcpm->dev,
> > +						dev_compatible_array[i]))
> This has been checked. Continue ? or return ENODEV?

Yes, this checking is not necessary, will remove in next version

> > +				return -ENODEV;
> > +			else {
> Remove this else.

OK

> > +				ret = device_property_read_u32(rcpm->dev,
> > +						dev_compatible_array[i],
> &set_bit);
> > +				if (ret)
> > +					return ret;
> > +
> > +				if (big_endian)
> > +					ippdexpcr =
> ioread32be(ippdexpcr_addr);
> > +				else
> > +					ippdexpcr =
> ioread32(ippdexpcr_addr);
> > +
> > +				if (flag)
> > +					ippdexpcr |= set_bit;
> > +				else
> > +					ippdexpcr &= ~set_bit;
> > +
> > +				if (big_endian) {
> > +					iowrite32be(ippdexpcr,
> ippdexpcr_addr);
> > +					ippdexpcr =
> ioread32be(ippdexpcr_addr);
> > +				} else
> if (x) {
> ....
> ....
> }  else {
> 
> }

Got it!

> > +					iowrite32(ippdexpcr, ippdexpcr_addr);
> > +
> > +				return 0;
> > +			}
> > +		}
> > +	}
> > +
> > +	return -ENODEV;
> > +}
> > +
> > +static int ls_rcpm_probe(struct platform_device *pdev) {
> > +	struct resource *r;
> > +	struct rcpm_t *rcpm;
> > +
> > +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	if (!r)
> > +		return -ENODEV;
> > +
> > +	rcpm = kmalloc(sizeof(*rcpm), GFP_KERNEL);
> kzalloc is better.

OK

> > +	if (!rcpm)
> > +		return -ENOMEM;
> > +
> > +	rcpm->big_endian = device_property_read_bool(&pdev->dev,
> > +"big-endian");
> > +
> > +	rcpm->ippdexpcr_addr = devm_ioremap_resource(&pdev->dev, r);
> > +	if (IS_ERR(rcpm->ippdexpcr_addr))
> > +		return PTR_ERR(rcpm->ippdexpcr_addr);
> > +
> > +	rcpm->dev = &pdev->dev;
> > +	platform_set_drvdata(pdev, rcpm);
> > +
> > +	return register_fsl_platform_wakeup_source(rcpm_handle, rcpm); }
> > +
> > +static int ls_rcpm_remove(struct platform_device *pdev) {
> > +	struct rcpm_t	*rcpm;
> Not need a table.

OK, thanks for your careful review.

Regards,
Ran
 

> Cheers,
> -Dongsheng
> 
> > +
> > +	rcpm = platform_get_drvdata(pdev);
> > +	deregister_fsl_platform_wakeup_source(rcpm);
> > +	kfree(rcpm);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id ls_rcpm_of_match[] = {
> > +	{ .compatible = "fsl,qoriq-rcpm-2.1", },
> > +	{}
> > +};
> > +MODULE_DEVICE_TABLE(of, ls_rcpm_of_match);
> > +
> > +static struct platform_driver ls_rcpm_driver = {
> > +	.driver = {
> > +		.name = "ls-rcpm",
> > +		.of_match_table = ls_rcpm_of_match,
> > +	},
> > +	.probe = ls_rcpm_probe,
> > +	.remove = ls_rcpm_remove,
> > +};
> > +
> > +static int __init ls_rcpm_init(void)
> > +{
> > +	return platform_driver_register(&ls_rcpm_driver);
> > +}
> > +subsys_initcall(ls_rcpm_init);
> > +
> > +static void __exit ls_rcpm_exit(void) {
> > +	platform_driver_unregister(&ls_rcpm_driver);
> > +}
> > +module_exit(ls_rcpm_exit);
> 


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

* RE: [PATCH 3/3] soc: fsl: add RCPM driver
  2018-09-05  3:21     ` Li Yang
@ 2018-09-07  9:48       ` Ran Wang
  2018-09-07 18:56         ` Li Yang
  0 siblings, 1 reply; 24+ messages in thread
From: Ran Wang @ 2018-09-07  9:48 UTC (permalink / raw)
  To: Leo Li
  Cc: dongsheng.wang, Rob Herring, Mark Rutland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linuxppc-dev, lkml,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

Hi Leo,

On September 05, 2018 at 11:22 Yang Li wrote:
> -----Original Message-----
> From: Li Yang <leoyang.li@nxp.com>
> Sent: Wednesday, September 05, 2018 11:22
> To: dongsheng.wang@hxt-semitech.com
> Cc: Ran Wang <ran.wang_1@nxp.com>; Rob Herring <robh+dt@kernel.org>;
> Mark Rutland <mark.rutland@arm.com>; open list:OPEN FIRMWARE AND
> FLATTENED DEVICE TREE BINDINGS <devicetree@vger.kernel.org>; linuxppc-
> dev <linuxppc-dev@lists.ozlabs.org>; lkml <linux-kernel@vger.kernel.org>;
> moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE <linux-arm-
> kernel@lists.infradead.org>
> Subject: Re: [PATCH 3/3] soc: fsl: add RCPM driver
> 
> On Tue, Sep 4, 2018 at 9:58 PM Wang, Dongsheng <dongsheng.wang@hxt-
> semitech.com> wrote:
> >
> > Please change your comments style.
> 
> Although this doesn't get into the Linux kernel coding style documentation
> yet, Linus seems changed his mind to prefer // than /*
> */ comment style now.
> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml
> .org%2Flkml%2F2017%2F11%2F25%2F133&amp;data=02%7C01%7Cran.wang_
> 1%40nxp.com%7Cc0d88e6690384e02b95108d612dec235%7C686ea1d3bc2b4c
> 6fa92cd99c5c301635%7C0%7C0%7C636717145285126200&amp;sdata=JIoCZp
> WhRyW76EqgSflfTDA1f0gMQGKa%2FcbvSc5CO%2Fw%3D&amp;reserved=0
> So the
> // style should be acceptable for now.
> 
> >
> > On 2018/8/31 11:56, Ran Wang wrote:
> > > The NXP's QorIQ Processors based on ARM Core have RCPM module (Run
> > > Control and Power Management), which performs all device-level tasks
> > > associated with power management such as wakeup source control.
> > >
> > > This driver depends on FSL platform PM driver framework which help
> > > to isolate user and PM service provider (such as RCPM driver).
> > >
> > > Signed-off-by: Chenhui Zhao <chenhui.zhao@nxp.com>
> > > Signed-off-by: Ying Zhang <ying.zhang22455@nxp.com>
> > > Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> > > ---
> > >  drivers/soc/fsl/Kconfig   |    6 ++
> > >  drivers/soc/fsl/Makefile  |    1 +
> > >  drivers/soc/fsl/ls-rcpm.c |  153
> > > +++++++++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 160 insertions(+), 0 deletions(-)  create mode
> > > 100644 drivers/soc/fsl/ls-rcpm.c
> > >
> > > diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig index
> > > 6517412..882330d 100644
> > > --- a/drivers/soc/fsl/Kconfig
> > > +++ b/drivers/soc/fsl/Kconfig
> > > @@ -30,3 +30,9 @@ config FSL_PLAT_PM
> > >         have to know the implement details of wakeup function it require.
> > >         Besides, it is also easy for service side to upgrade its logic when
> > >         design changed and remain user side unchanged.
> > > +
> > > +config LS_RCPM
> > > +     bool "Freescale RCPM support"
> > > +     depends on (FSL_PLAT_PM)
> > > +     help
> > > +       This feature is to enable specified wakeup source for system sleep.
> > > diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
> > > index 8f9db23..43ff71a 100644
> > > --- a/drivers/soc/fsl/Makefile
> > > +++ b/drivers/soc/fsl/Makefile
> > > @@ -7,3 +7,4 @@ obj-$(CONFIG_QUICC_ENGINE)            += qe/
> > >  obj-$(CONFIG_CPM)                    += qe/
> > >  obj-$(CONFIG_FSL_GUTS)                       += guts.o
> > >  obj-$(CONFIG_FSL_PLAT_PM)    += plat_pm.o
> > > +obj-$(CONFIG_LS_RCPM)                += ls-rcpm.o
> 
> Probably use "_" instead of "-" for alignment.

OK, will update in next version

> > > diff --git a/drivers/soc/fsl/ls-rcpm.c b/drivers/soc/fsl/ls-rcpm.c
> > > new file mode 100644 index 0000000..b0feb88
> > > --- /dev/null
> > > +++ b/drivers/soc/fsl/ls-rcpm.c
> > > @@ -0,0 +1,153 @@
> > > +// SPDX-License-Identifier: GPL-2.0 // // plat_pm.c - Freescale
> > > +Layerscape RCPM driver
> 
> The file name here is not the same as the real file name.

Got it, will correct it.

> > > +//
> > > +// Copyright 2018 NXP
> > > +//
> > > +// Author: Ran Wang <ran.wang_1@nxp.com>,
> 
> Where do you need the comma in the end?

My bad, will remove comma in next version.

> > > +
> > > +#include <linux/init.h>
> > > +#include <linux/module.h>
> > > +#include <linux/platform_device.h>
> > > +#include <linux/of_address.h>
> > > +#include <linux/slab.h>
> > > +#include <soc/fsl/plat_pm.h>
> > > +
> > > +#define MAX_COMPATIBLE_NUM   10
> > > +
> > > +struct rcpm_t {
> > > +     struct device *dev;
> > > +     void __iomem *ippdexpcr_addr;
> > > +     bool big_endian;        /* Big/Little endian of RCPM module */
> > > +};
> > > +
> > > +// rcpm_handle - Configure RCPM reg according to wake up source
> > > +request // @user_dev: pointer to user's device struct // @flag: to
> > > +enable(true) or disable(false) wakeup source // @handle_priv:
> > > +pointer to struct rcpm_t instance // // Return 0 on success other
> > > +negative errno
> 
> Although Linus preferred this // comment style.  I'm not sure if this will be
> handled correctly by the kernel-doc compiler.
> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fww
> w.kernel.org%2Fdoc%2Fhtml%2Fv4.18%2Fdoc-guide%2Fkernel-
> doc.html&amp;data=02%7C01%7Cran.wang_1%40nxp.com%7Cc0d88e669038
> 4e02b95108d612dec235%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C636717145285126200&amp;sdata=H7GkUNOLVG%2FCcZESzhtHBeHCbO9
> %2FK4k9EdH30Cxq2%2BM%3D&amp;reserved=0

So, do you think I need to change all comment style back to '/* ... */' ?
Actually I feel a little bit confused here.

Regards,
Ran

> > > +static int rcpm_handle(struct device *user_dev, bool flag, void
> > > +*handle_priv) {
> > > +     struct rcpm_t *rcpm;
> > > +     bool big_endian;
> > > +     const char  *dev_compatible_array[MAX_COMPATIBLE_NUM];
> > > +     void __iomem *ippdexpcr_addr;
> > > +     u32 ippdexpcr;
> > > +     u32 set_bit;
> > > +     int ret, num, i;
> > > +
> > > +     rcpm = handle_priv;
> > > +     big_endian = rcpm->big_endian;
> > > +     ippdexpcr_addr = rcpm->ippdexpcr_addr;
> > > +
> > > +     num = device_property_read_string_array(user_dev, "compatible",
> > > +                     dev_compatible_array, MAX_COMPATIBLE_NUM);
> > > +     if (num < 0)
> > > +             return num;
> > > +
> > > +     for (i = 0; i < num; i++) {
> > > +             if (!device_property_present(rcpm->dev,
> > > +                                     dev_compatible_array[i]))
> > > +                     continue;
> > > +             else {
> > Remove this else.
> > > +                     ret = device_property_read_u32(rcpm->dev,
> > > +                                     dev_compatible_array[i], &set_bit);
> > > +                     if (ret)
> > > +                             return ret;
> > > +
> > > +                     if (!device_property_present(rcpm->dev,
> > > +
> > > + dev_compatible_array[i]))
> > This has been checked. Continue ? or return ENODEV?
> > > +                             return -ENODEV;
> > > +                     else {
> > Remove this else.
> > > +                             ret = device_property_read_u32(rcpm->dev,
> > > +                                             dev_compatible_array[i], &set_bit);
> > > +                             if (ret)
> > > +                                     return ret;
> > > +
> > > +                             if (big_endian)
> > > +                                     ippdexpcr = ioread32be(ippdexpcr_addr);
> > > +                             else
> > > +                                     ippdexpcr =
> > > + ioread32(ippdexpcr_addr);
> > > +
> > > +                             if (flag)
> > > +                                     ippdexpcr |= set_bit;
> > > +                             else
> > > +                                     ippdexpcr &= ~set_bit;
> > > +
> > > +                             if (big_endian) {
> > > +                                     iowrite32be(ippdexpcr, ippdexpcr_addr);
> > > +                                     ippdexpcr = ioread32be(ippdexpcr_addr);
> > > +                             } else
> > if (x) {
> > ....
> > ....
> > }  else {
> >
> > }
> > > +                                     iowrite32(ippdexpcr,
> > > + ippdexpcr_addr);
> > > +
> > > +                             return 0;
> > > +                     }
> > > +             }
> > > +     }
> > > +
> > > +     return -ENODEV;
> > > +}
> > > +
> > > +static int ls_rcpm_probe(struct platform_device *pdev) {
> > > +     struct resource *r;
> > > +     struct rcpm_t *rcpm;
> > > +
> > > +     r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > +     if (!r)
> > > +             return -ENODEV;
> > > +
> > > +     rcpm = kmalloc(sizeof(*rcpm), GFP_KERNEL);
> > kzalloc is better.
> > > +     if (!rcpm)
> > > +             return -ENOMEM;
> > > +
> > > +     rcpm->big_endian = device_property_read_bool(&pdev->dev,
> > > + "big-endian");
> > > +
> > > +     rcpm->ippdexpcr_addr = devm_ioremap_resource(&pdev->dev, r);
> > > +     if (IS_ERR(rcpm->ippdexpcr_addr))
> > > +             return PTR_ERR(rcpm->ippdexpcr_addr);
> > > +
> > > +     rcpm->dev = &pdev->dev;
> > > +     platform_set_drvdata(pdev, rcpm);
> > > +
> > > +     return register_fsl_platform_wakeup_source(rcpm_handle, rcpm);
> > > +}
> > > +
> > > +static int ls_rcpm_remove(struct platform_device *pdev) {
> > > +     struct rcpm_t   *rcpm;
> > Not need a table.
> >
> > Cheers,
> > -Dongsheng
> >
> > > +
> > > +     rcpm = platform_get_drvdata(pdev);
> > > +     deregister_fsl_platform_wakeup_source(rcpm);
> > > +     kfree(rcpm);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static const struct of_device_id ls_rcpm_of_match[] = {
> > > +     { .compatible = "fsl,qoriq-rcpm-2.1", },
> > > +     {}
> > > +};
> > > +MODULE_DEVICE_TABLE(of, ls_rcpm_of_match);
> > > +
> > > +static struct platform_driver ls_rcpm_driver = {
> > > +     .driver = {
> > > +             .name = "ls-rcpm",
> > > +             .of_match_table = ls_rcpm_of_match,
> > > +     },
> > > +     .probe = ls_rcpm_probe,
> > > +     .remove = ls_rcpm_remove,
> > > +};
> > > +
> > > +static int __init ls_rcpm_init(void) {
> > > +     return platform_driver_register(&ls_rcpm_driver);
> > > +}
> > > +subsys_initcall(ls_rcpm_init);
> > > +
> > > +static void __exit ls_rcpm_exit(void) {
> > > +     platform_driver_unregister(&ls_rcpm_driver);
> > > +}
> > > +module_exit(ls_rcpm_exit);
> >
> >

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

* Re: [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms
  2018-09-07  8:41   ` Ran Wang
@ 2018-09-07 10:15     ` Wang, Dongsheng
  2018-09-10  3:27       ` Ran Wang
  0 siblings, 1 reply; 24+ messages in thread
From: Wang, Dongsheng @ 2018-09-07 10:15 UTC (permalink / raw)
  To: Ran Wang
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel, Leo Li,
	Rob Herring, Mark Rutland

On 2018/9/7 16:49, Ran Wang wrote:
> Hi Dongsheng
>
>> On 2018/9/5 11:05, Dongsheng Wang wrote:
>>
>> Please change your comments style.
>>
>> On 2018/8/31 11:57, Ran Wang wrote:
>>> This driver is to provide a independent framework for PM service
>>> provider and consumer to configure system level wake up feature. For
>>> example, RCPM driver could register a callback function on this
>>> platform first, and Flex timer driver who want to enable timer wake up
>>> feature, will call generic API provided by this platform driver, and
>>> then it will trigger RCPM driver to do it. The benefit is to isolate
>>> the user and service, such as flex timer driver will not have to know
>>> the implement details of wakeup function it require. Besides, it is
>>> also easy for service side to upgrade its logic when design is changed
>>> and remain user side unchanged.
>>>
>>> Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
>>> ---
>>>  drivers/soc/fsl/Kconfig   |   14 +++++
>>>  drivers/soc/fsl/Makefile  |    1 +
>>>  drivers/soc/fsl/plat_pm.c |  144
>> +++++++++++++++++++++++++++++++++++++++++++++
>>>  include/soc/fsl/plat_pm.h |   22 +++++++
>>>  4 files changed, 181 insertions(+), 0 deletions(-)  create mode
>>> 100644 drivers/soc/fsl/plat_pm.c  create mode 100644
>>> include/soc/fsl/plat_pm.h
>>>
>>> diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig index
>>> 7a9fb9b..6517412 100644
>>> --- a/drivers/soc/fsl/Kconfig
>>> +++ b/drivers/soc/fsl/Kconfig
>>> @@ -16,3 +16,17 @@ config FSL_GUTS
>>>  	  Initially only reading SVR and registering soc device are supported.
>>>  	  Other guts accesses, such as reading RCW, should eventually be
>> moved
>>>  	  into this driver as well.
>>> +
>>> +config FSL_PLAT_PM
>>> +	bool "Freescale platform PM framework"
>>> +	help
>>> +	  This driver is to provide a independent framework for PM service
>>> +	  provider and consumer to configure system level wake up feature.
>> For
>>> +	  example, RCPM driver could register a callback function on this
>>> +	  platform first, and Flex timer driver who want to enable timer wake
>>> +	  up feature, will call generic API provided by this platform driver,
>>> +	  and then it will trigger RCPM driver to do it. The benefit is to
>>> +	  isolate the user and service, such as  flex timer driver will not
>>> +	  have to know the implement details of wakeup function it require.
>>> +	  Besides, it is also easy for service side to upgrade its logic when
>>> +	  design changed and remain user side unchanged.
>>> diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile index
>>> 44b3beb..8f9db23 100644
>>> --- a/drivers/soc/fsl/Makefile
>>> +++ b/drivers/soc/fsl/Makefile
>>> @@ -6,3 +6,4 @@ obj-$(CONFIG_FSL_DPAA)                 += qbman/
>>>  obj-$(CONFIG_QUICC_ENGINE)		+= qe/
>>>  obj-$(CONFIG_CPM)			+= qe/
>>>  obj-$(CONFIG_FSL_GUTS)			+= guts.o
>>> +obj-$(CONFIG_FSL_PLAT_PM)	+= plat_pm.o
>>> diff --git a/drivers/soc/fsl/plat_pm.c b/drivers/soc/fsl/plat_pm.c new
>>> file mode 100644 index 0000000..19ea14e
>>> --- /dev/null
>>> +++ b/drivers/soc/fsl/plat_pm.c
>>> @@ -0,0 +1,144 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +//
>>> +// plat_pm.c - Freescale platform PM framework // // Copyright 2018
>>> +NXP // // Author: Ran Wang <ran.wang_1@nxp.com>,
>>> +
>>> +#include <linux/kernel.h>
>>> +#include <linux/device.h>
>>> +#include <linux/list.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/err.h>
>>> +#include <soc/fsl/plat_pm.h>
>>> +
>>> +
>>> +struct plat_pm_t {
>>> +	struct list_head node;
>>> +	fsl_plat_pm_handle handle;
>>> +	void *handle_priv;
>>> +	spinlock_t	lock;
>>> +};
>>> +
>>> +static struct plat_pm_t plat_pm;
>>> +
>>> +// register_fsl_platform_wakeup_source - Register callback function
>>> +to plat_pm // @handle: Pointer to handle PM feature requirement //
>>> +@handle_priv: Handler specific data struct // // Return 0 on success
>>> +other negative errno int
>>> +register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
>>> +		void *handle_priv)
>>> +{
>>> +	struct plat_pm_t *p;
>>> +	unsigned long	flags;
>>> +
>>> +	if (!handle) {
>>> +		pr_err("FSL plat_pm: Handler invalid, reject\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	p = kmalloc(sizeof(*p), GFP_KERNEL);
>>> +	if (!p)
>>> +		return -ENOMEM;
>>> +
>>> +	p->handle = handle;
>>> +	p->handle_priv = handle_priv;
>>> +
>>> +	spin_lock_irqsave(&plat_pm.lock, flags);
>>> +	list_add_tail(&p->node, &plat_pm.node);
>>> +	spin_unlock_irqrestore(&plat_pm.lock, flags);
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(register_fsl_platform_wakeup_source);
>>> +
>>> +// Deregister_fsl_platform_wakeup_source - deregister callback
>>> +function // @handle_priv: Handler specific data struct // // Return 0
>>> +on success other negative errno int
>>> +deregister_fsl_platform_wakeup_source(void *handle_priv) {
>>> +	struct plat_pm_t *p, *tmp;
>>> +	unsigned long	flags;
>>> +
>>> +	spin_lock_irqsave(&plat_pm.lock, flags);
>>> +	list_for_each_entry_safe(p, tmp, &plat_pm.node, node) {
>>> +		if (p->handle_priv == handle_priv) {
>>> +			list_del(&p->node);
>>> +			kfree(p);
>>> +		}
>>> +	}
>>> +	spin_unlock_irqrestore(&plat_pm.lock, flags);
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(deregister_fsl_platform_wakeup_source);
>>> +
>>> +// fsl_platform_wakeup_config - Configure wakeup source by calling
>>> +handlers // @dev: pointer to user's device struct // @flag: to tell
>>> +enable or disable wakeup source // // Return 0 on success other
>>> +negative errno int fsl_platform_wakeup_config(struct device *dev,
>>> +bool flag) {
>>> +	struct plat_pm_t *p;
>>> +	int ret;
>>> +	bool success_handled;
>>> +	unsigned long	flags;
>>> +
>>> +	success_handled = false;
>>> +
>>> +	// Will consider success if at least one callback return 0.
>>> +	// Also, rest handles still get oppertunity to be executed
>>> +	spin_lock_irqsave(&plat_pm.lock, flags);
>>> +	list_for_each_entry(p, &plat_pm.node, node) {
>>> +		if (p->handle) {
>>> +			ret = p->handle(dev, flag, p->handle_priv);
>>> +			if (!ret)
>>> +				success_handled = true;
>> Miss a break?
> Actually my idea is to allow more than one registered handler to handle this
> request, so I define a flag rather than return to indicated if there is at least one handler successfully
> do it. This design might give more flexibility to framework when running.
There is only one flag(success_handled) here, how did know which handler
failed?

BTW, I don't think we need this flag. We can only use the return value.

Cheers,
Dongsheng

>>> +			else if (ret != -ENODEV) {
>>> +				pr_err("FSL plat_pm: Failed to config wakeup
>> source:%d\n", ret);
>> Please unlock before return.
> Yes, will fix it in next version, thanks for pointing out!
>
>>> +				return ret;
>>> +			}
>>> +		} else
>>> +			pr_warn("FSL plat_pm: Invalid handler detected,
>> skip\n");
>>> +	}
>>> +	spin_unlock_irqrestore(&plat_pm.lock, flags);
>>> +
>>> +	if (success_handled == false) {
>>> +		pr_err("FSL plat_pm: Cannot find the matchhed handler for
>> wakeup source config\n");
>>> +		return -ENODEV;
>>> +	}
>> Add this into the loop.
> My design is that if the 1st handler return -ENODEV to indicated this device it doesn't support, 
> then the framework will continue try 2nd handler...
>
> So I think it is needed to place this checking out of loop, what do you say?
>
> Regards,
> Ran
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +// fsl_platform_wakeup_enable - Enable wakeup source // @dev: pointer
>>> +to user's device struct // // Return 0 on success other negative
>>> +errno int fsl_platform_wakeup_enable(struct device *dev) {
>>> +	return fsl_platform_wakeup_config(dev, true); }
>>> +EXPORT_SYMBOL_GPL(fsl_platform_wakeup_enable);
>>> +
>>> +// fsl_platform_wakeup_disable - Disable wakeup source // @dev:
>>> +pointer to user's device struct // // Return 0 on success other
>>> +negative errno int fsl_platform_wakeup_disable(struct device *dev) {
>>> +	return fsl_platform_wakeup_config(dev, false); }
>>> +EXPORT_SYMBOL_GPL(fsl_platform_wakeup_disable);
>>> +
>>> +static int __init fsl_plat_pm_init(void) {
>>> +	spin_lock_init(&plat_pm.lock);
>>> +	INIT_LIST_HEAD(&plat_pm.node);
>>> +	return 0;
>>> +}
>>> +
>>> +core_initcall(fsl_plat_pm_init);
>>> diff --git a/include/soc/fsl/plat_pm.h b/include/soc/fsl/plat_pm.h new
>>> file mode 100644 index 0000000..bbe151e
>>> --- /dev/null
>>> +++ b/include/soc/fsl/plat_pm.h
>>> @@ -0,0 +1,22 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +//
>>> +// plat_pm.h - Freescale platform PM Header // // Copyright 2018 NXP
>>> +// // Author: Ran Wang <ran.wang_1@nxp.com>,
>>> +
>>> +#ifndef __FSL_PLAT_PM_H
>>> +#define __FSL_PLAT_PM_H
>>> +
>>> +typedef int (*fsl_plat_pm_handle)(struct device *dev, bool flag,
>>> +		void *handle_priv);
>>> +
>>> +int register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
>>> +		void *handle_priv);
>>> +int deregister_fsl_platform_wakeup_source(void *handle_priv); int
>>> +fsl_platform_wakeup_config(struct device *dev, bool flag); int
>>> +fsl_platform_wakeup_enable(struct device *dev); int
>>> +fsl_platform_wakeup_disable(struct device *dev);
>>> +
>>> +#endif	// __FSL_PLAT_PM_H
>


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

* Re: [PATCH 3/3] soc: fsl: add RCPM driver
  2018-09-07  9:48       ` Ran Wang
@ 2018-09-07 18:56         ` Li Yang
  2018-09-10  3:31           ` Ran Wang
  0 siblings, 1 reply; 24+ messages in thread
From: Li Yang @ 2018-09-07 18:56 UTC (permalink / raw)
  To: Ran Wang
  Cc: Mark Rutland, dongsheng.wang,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, lkml,
	Rob Herring, linuxppc-dev,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On Fri, Sep 7, 2018 at 4:51 AM Ran Wang <ran.wang_1@nxp.com> wrote:
>
> Hi Leo,
>
> On September 05, 2018 at 11:22 Yang Li wrote:
> > -----Original Message-----
> > From: Li Yang <leoyang.li@nxp.com>
> > Sent: Wednesday, September 05, 2018 11:22
> > To: dongsheng.wang@hxt-semitech.com
> > Cc: Ran Wang <ran.wang_1@nxp.com>; Rob Herring <robh+dt@kernel.org>;
> > Mark Rutland <mark.rutland@arm.com>; open list:OPEN FIRMWARE AND
> > FLATTENED DEVICE TREE BINDINGS <devicetree@vger.kernel.org>; linuxppc-
> > dev <linuxppc-dev@lists.ozlabs.org>; lkml <linux-kernel@vger.kernel.org>;
> > moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE <linux-arm-
> > kernel@lists.infradead.org>
> > Subject: Re: [PATCH 3/3] soc: fsl: add RCPM driver
> >
> > On Tue, Sep 4, 2018 at 9:58 PM Wang, Dongsheng <dongsheng.wang@hxt-
> > semitech.com> wrote:
> > >
> > > Please change your comments style.
> >
> > Although this doesn't get into the Linux kernel coding style documentation
> > yet, Linus seems changed his mind to prefer // than /*
> > */ comment style now.
> > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml
> > .org%2Flkml%2F2017%2F11%2F25%2F133&amp;data=02%7C01%7Cran.wang_
> > 1%40nxp.com%7Cc0d88e6690384e02b95108d612dec235%7C686ea1d3bc2b4c
> > 6fa92cd99c5c301635%7C0%7C0%7C636717145285126200&amp;sdata=JIoCZp
> > WhRyW76EqgSflfTDA1f0gMQGKa%2FcbvSc5CO%2Fw%3D&amp;reserved=0
> > So the
> > // style should be acceptable for now.
> >
> > >
> > > On 2018/8/31 11:56, Ran Wang wrote:
> > > > The NXP's QorIQ Processors based on ARM Core have RCPM module (Run
> > > > Control and Power Management), which performs all device-level tasks
> > > > associated with power management such as wakeup source control.
> > > >
> > > > This driver depends on FSL platform PM driver framework which help
> > > > to isolate user and PM service provider (such as RCPM driver).
> > > >
> > > > Signed-off-by: Chenhui Zhao <chenhui.zhao@nxp.com>
> > > > Signed-off-by: Ying Zhang <ying.zhang22455@nxp.com>
> > > > Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> > > > ---
> > > >  drivers/soc/fsl/Kconfig   |    6 ++
> > > >  drivers/soc/fsl/Makefile  |    1 +
> > > >  drivers/soc/fsl/ls-rcpm.c |  153
> > > > +++++++++++++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 160 insertions(+), 0 deletions(-)  create mode
> > > > 100644 drivers/soc/fsl/ls-rcpm.c
> > > >
> > > > diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig index
> > > > 6517412..882330d 100644
> > > > --- a/drivers/soc/fsl/Kconfig
> > > > +++ b/drivers/soc/fsl/Kconfig
> > > > @@ -30,3 +30,9 @@ config FSL_PLAT_PM
> > > >         have to know the implement details of wakeup function it require.
> > > >         Besides, it is also easy for service side to upgrade its logic when
> > > >         design changed and remain user side unchanged.
> > > > +
> > > > +config LS_RCPM
> > > > +     bool "Freescale RCPM support"
> > > > +     depends on (FSL_PLAT_PM)
> > > > +     help
> > > > +       This feature is to enable specified wakeup source for system sleep.
> > > > diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
> > > > index 8f9db23..43ff71a 100644
> > > > --- a/drivers/soc/fsl/Makefile
> > > > +++ b/drivers/soc/fsl/Makefile
> > > > @@ -7,3 +7,4 @@ obj-$(CONFIG_QUICC_ENGINE)            += qe/
> > > >  obj-$(CONFIG_CPM)                    += qe/
> > > >  obj-$(CONFIG_FSL_GUTS)                       += guts.o
> > > >  obj-$(CONFIG_FSL_PLAT_PM)    += plat_pm.o
> > > > +obj-$(CONFIG_LS_RCPM)                += ls-rcpm.o
> >
> > Probably use "_" instead of "-" for alignment.
>
> OK, will update in next version
>
> > > > diff --git a/drivers/soc/fsl/ls-rcpm.c b/drivers/soc/fsl/ls-rcpm.c
> > > > new file mode 100644 index 0000000..b0feb88
> > > > --- /dev/null
> > > > +++ b/drivers/soc/fsl/ls-rcpm.c
> > > > @@ -0,0 +1,153 @@
> > > > +// SPDX-License-Identifier: GPL-2.0 // // plat_pm.c - Freescale
> > > > +Layerscape RCPM driver
> >
> > The file name here is not the same as the real file name.
>
> Got it, will correct it.
>
> > > > +//
> > > > +// Copyright 2018 NXP
> > > > +//
> > > > +// Author: Ran Wang <ran.wang_1@nxp.com>,
> >
> > Where do you need the comma in the end?
>
> My bad, will remove comma in next version.
>
> > > > +
> > > > +#include <linux/init.h>
> > > > +#include <linux/module.h>
> > > > +#include <linux/platform_device.h>
> > > > +#include <linux/of_address.h>
> > > > +#include <linux/slab.h>
> > > > +#include <soc/fsl/plat_pm.h>
> > > > +
> > > > +#define MAX_COMPATIBLE_NUM   10
> > > > +
> > > > +struct rcpm_t {
> > > > +     struct device *dev;
> > > > +     void __iomem *ippdexpcr_addr;
> > > > +     bool big_endian;        /* Big/Little endian of RCPM module */
> > > > +};
> > > > +
> > > > +// rcpm_handle - Configure RCPM reg according to wake up source
> > > > +request // @user_dev: pointer to user's device struct // @flag: to
> > > > +enable(true) or disable(false) wakeup source // @handle_priv:
> > > > +pointer to struct rcpm_t instance // // Return 0 on success other
> > > > +negative errno
> >
> > Although Linus preferred this // comment style.  I'm not sure if this will be
> > handled correctly by the kernel-doc compiler.
> > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fww
> > w.kernel.org%2Fdoc%2Fhtml%2Fv4.18%2Fdoc-guide%2Fkernel-
> > doc.html&amp;data=02%7C01%7Cran.wang_1%40nxp.com%7Cc0d88e669038
> > 4e02b95108d612dec235%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> > %7C636717145285126200&amp;sdata=H7GkUNOLVG%2FCcZESzhtHBeHCbO9
> > %2FK4k9EdH30Cxq2%2BM%3D&amp;reserved=0
>
> So, do you think I need to change all comment style back to '/* ... */' ?
> Actually I feel a little bit confused here.

I think Linus's comment about // comment style applies to normal code
comment.  But kernel-doc comment is a special kind of code comment
that needs to meet certain requirements.  People can use the
scripts/kernel-doc tool to generate readable API documents from the
source code.  It looks like you wanted to make the function
description aligned with the kernel-doc format, but kernel-doc
specifically requires to use the /* */ style(at least for now).

Regards,
Leo

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

* Re: [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM
  2018-08-31  3:52 ` [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM Ran Wang
       [not found]   ` <5b8e8a71.1c69fb81.d966f.1ca1@mx.google.com>
@ 2018-09-07 20:22   ` Scott Wood
  2018-09-10  8:44     ` Ran Wang
  1 sibling, 1 reply; 24+ messages in thread
From: Scott Wood @ 2018-09-07 20:22 UTC (permalink / raw)
  To: Ran Wang, Leo Li, Rob Herring, Mark Rutland
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel

On Fri, 2018-08-31 at 11:52 +0800, Ran Wang wrote:
> +Optional properties:
> + - big-endian : Indicate RCPM registers is big-endian. A RCPM node
> +   that doesn't have this property will be regarded as little-endian.

You've just broken all the existing powerpc device trees that are big-endian
and have no big-endian property.

> + - <property 'compatible' string of consumer device> : This string
> +   is referred by RCPM driver to judge if the consumer (such as flex timer)
> +   is able to be regards as wakeup source or not, such as 'fsl,ls1012a-
> ftm'.
> +   Further, this property will carry the bit mask info to control
> +   coresponding wake up source.

What will you do if there are multiple instances of a device with the same
compatible, and different wakeup bits?  Plus, it's an awkward design in
general, and you don't describe what the value actually means (bits in which
register?).  What was wrong with the existing binding?  Alternatively, use the
clock bindings.

> -
> -Example:
> -	lpuart0: serial@2950000 {
> -		compatible = "fsl,ls1021a-lpuart";
> -		reg = <0x0 0x2950000 0x0 0x1000>;
> -		interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&sysclk>;
> -		clock-names = "ipg";
> -		fsl,rcpm-wakeup = <&rcpm 0x0 0x40000000>;
> +		big-endian;
> +		fsl,ls1012a-ftm = <0x20000>;
> +		fsl,pfe = <0xf0000020>;

fsl,pfe is not documented.

-Scott


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

* Re: [PATCH 3/3] soc: fsl: add RCPM driver
  2018-08-31  3:52 ` [PATCH 3/3] soc: fsl: add RCPM driver Ran Wang
  2018-09-05  2:57   ` Wang, Dongsheng
@ 2018-09-07 20:25   ` Scott Wood
  2018-09-10  9:09     ` Ran Wang
  1 sibling, 1 reply; 24+ messages in thread
From: Scott Wood @ 2018-09-07 20:25 UTC (permalink / raw)
  To: Ran Wang, Leo Li, Rob Herring, Mark Rutland
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel

On Fri, 2018-08-31 at 11:52 +0800, Ran Wang wrote:
> The NXP's QorIQ Processors based on ARM Core have RCPM module (Run
> Control and Power Management), which performs all device-level
> tasks associated with power management such as wakeup source control.
> 
> This driver depends on FSL platform PM driver framework which help to
> isolate user and PM service provider (such as RCPM driver).
> 
> Signed-off-by: Chenhui Zhao <chenhui.zhao@nxp.com>
> Signed-off-by: Ying Zhang <ying.zhang22455@nxp.com>
> Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> ---
>  drivers/soc/fsl/Kconfig   |    6 ++
>  drivers/soc/fsl/Makefile  |    1 +
>  drivers/soc/fsl/ls-rcpm.c |  153
> +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 160 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/soc/fsl/ls-rcpm.c

Is there a reason why this is LS-specific, or could it be used with PPC RCPM
blocks?

> diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
> index 6517412..882330d 100644
> --- a/drivers/soc/fsl/Kconfig
> +++ b/drivers/soc/fsl/Kconfig
> @@ -30,3 +30,9 @@ config FSL_PLAT_PM
>  	  have to know the implement details of wakeup function it require.
>  	  Besides, it is also easy for service side to upgrade its logic
> when
>  	  design changed and remain user side unchanged.
> +
> +config LS_RCPM
> +	bool "Freescale RCPM support"
> +	depends on (FSL_PLAT_PM)

Why is this parenthesized?

-Scott


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

* Re: [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms
  2018-08-31  3:52 [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms Ran Wang
                   ` (2 preceding siblings ...)
  2018-09-05  3:04 ` [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms Wang, Dongsheng
@ 2018-09-07 20:35 ` Scott Wood
  2018-09-10  9:26   ` Ran Wang
  3 siblings, 1 reply; 24+ messages in thread
From: Scott Wood @ 2018-09-07 20:35 UTC (permalink / raw)
  To: Ran Wang, Leo Li, Rob Herring, Mark Rutland
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel

On Fri, 2018-08-31 at 11:52 +0800, Ran Wang wrote:
> This driver is to provide a independent framework for PM service
> provider and consumer to configure system level wake up feature. For
> example, RCPM driver could register a callback function on this
> platform first, and Flex timer driver who want to enable timer wake
> up feature, will call generic API provided by this platform driver,
> and then it will trigger RCPM driver to do it. The benefit is to
> isolate the user and service, such as flex timer driver will not have
> to know the implement details of wakeup function it require. Besides,
> it is also easy for service side to upgrade its logic when design is
> changed and remain user side unchanged.
> 
> Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> ---
>  drivers/soc/fsl/Kconfig   |   14 +++++
>  drivers/soc/fsl/Makefile  |    1 +
>  drivers/soc/fsl/plat_pm.c |  144
> +++++++++++++++++++++++++++++++++++++++++++++
>  include/soc/fsl/plat_pm.h |   22 +++++++
>  4 files changed, 181 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/soc/fsl/plat_pm.c
>  create mode 100644 include/soc/fsl/plat_pm.h
> 
> diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
> index 7a9fb9b..6517412 100644
> --- a/drivers/soc/fsl/Kconfig
> +++ b/drivers/soc/fsl/Kconfig
> @@ -16,3 +16,17 @@ config FSL_GUTS
>  	  Initially only reading SVR and registering soc device are
> supported.
>  	  Other guts accesses, such as reading RCW, should eventually be
> moved
>  	  into this driver as well.
+
> +config FSL_PLAT_PM
> +	bool "Freescale platform PM framework"

This name seems to be simultaneously too generic (for something that is likely
intended only for use with certain Freescale/NXP chip families) and too
specific (for something that seems to be general infrastructure with no real
hardware dependencies).

What specific problems with Linux's generic wakeup infrastructure is this
trying to solve, and why would those problems not be better solved there?

Also, you should CC linux-pm on these patches.

-Scott


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

* RE: [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms
  2018-09-07 10:15     ` Wang, Dongsheng
@ 2018-09-10  3:27       ` Ran Wang
  0 siblings, 0 replies; 24+ messages in thread
From: Ran Wang @ 2018-09-10  3:27 UTC (permalink / raw)
  To: Wang, Dongsheng
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel, Leo Li,
	Rob Herring, Mark Rutland, linux-pm

Hi Dongsheng,

On 2018/9/7 18:16, Dongsheng Wang wrote:
> 
> On 2018/9/7 16:49, Ran Wang wrote:
> > Hi Dongsheng
> >
> >> On 2018/9/5 11:05, Dongsheng Wang wrote:
> >>
> >> Please change your comments style.
> >>
> >> On 2018/8/31 11:57, Ran Wang wrote:
> >>> This driver is to provide a independent framework for PM service
> >>> provider and consumer to configure system level wake up feature. For
> >>> example, RCPM driver could register a callback function on this
> >>> platform first, and Flex timer driver who want to enable timer wake
> >>> up feature, will call generic API provided by this platform driver,
> >>> and then it will trigger RCPM driver to do it. The benefit is to
> >>> isolate the user and service, such as flex timer driver will not
> >>> have to know the implement details of wakeup function it require.
> >>> Besides, it is also easy for service side to upgrade its logic when
> >>> design is changed and remain user side unchanged.
> >>>
> >>> Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> >>> ---
> >>>  drivers/soc/fsl/Kconfig   |   14 +++++
> >>>  drivers/soc/fsl/Makefile  |    1 +
> >>>  drivers/soc/fsl/plat_pm.c |  144
> >> +++++++++++++++++++++++++++++++++++++++++++++
> >>>  include/soc/fsl/plat_pm.h |   22 +++++++
> >>>  4 files changed, 181 insertions(+), 0 deletions(-)  create mode
> >>> 100644 drivers/soc/fsl/plat_pm.c  create mode 100644
> >>> include/soc/fsl/plat_pm.h
> >>>
> >>> diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig index
> >>> 7a9fb9b..6517412 100644
> >>> --- a/drivers/soc/fsl/Kconfig
> >>> +++ b/drivers/soc/fsl/Kconfig
> >>> @@ -16,3 +16,17 @@ config FSL_GUTS
> >>>  	  Initially only reading SVR and registering soc device are supported.
> >>>  	  Other guts accesses, such as reading RCW, should eventually be
> >> moved
> >>>  	  into this driver as well.
> >>> +
> >>> +config FSL_PLAT_PM
> >>> +	bool "Freescale platform PM framework"
> >>> +	help
> >>> +	  This driver is to provide a independent framework for PM service
> >>> +	  provider and consumer to configure system level wake up feature.
> >> For
> >>> +	  example, RCPM driver could register a callback function on this
> >>> +	  platform first, and Flex timer driver who want to enable timer wake
> >>> +	  up feature, will call generic API provided by this platform driver,
> >>> +	  and then it will trigger RCPM driver to do it. The benefit is to
> >>> +	  isolate the user and service, such as  flex timer driver will not
> >>> +	  have to know the implement details of wakeup function it require.
> >>> +	  Besides, it is also easy for service side to upgrade its logic when
> >>> +	  design changed and remain user side unchanged.
> >>> diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
> >>> index
> >>> 44b3beb..8f9db23 100644
> >>> --- a/drivers/soc/fsl/Makefile
> >>> +++ b/drivers/soc/fsl/Makefile
> >>> @@ -6,3 +6,4 @@ obj-$(CONFIG_FSL_DPAA)                 += qbman/
> >>>  obj-$(CONFIG_QUICC_ENGINE)		+= qe/
> >>>  obj-$(CONFIG_CPM)			+= qe/
> >>>  obj-$(CONFIG_FSL_GUTS)			+= guts.o
> >>> +obj-$(CONFIG_FSL_PLAT_PM)	+= plat_pm.o
> >>> diff --git a/drivers/soc/fsl/plat_pm.c b/drivers/soc/fsl/plat_pm.c
> >>> new file mode 100644 index 0000000..19ea14e
> >>> --- /dev/null
> >>> +++ b/drivers/soc/fsl/plat_pm.c
> >>> @@ -0,0 +1,144 @@
> >>> +// SPDX-License-Identifier: GPL-2.0 // // plat_pm.c - Freescale
> >>> +platform PM framework // // Copyright 2018 NXP // // Author: Ran
> >>> +Wang <ran.wang_1@nxp.com>,
> >>> +
> >>> +#include <linux/kernel.h>
> >>> +#include <linux/device.h>
> >>> +#include <linux/list.h>
> >>> +#include <linux/slab.h>
> >>> +#include <linux/err.h>
> >>> +#include <soc/fsl/plat_pm.h>
> >>> +
> >>> +
> >>> +struct plat_pm_t {
> >>> +	struct list_head node;
> >>> +	fsl_plat_pm_handle handle;
> >>> +	void *handle_priv;
> >>> +	spinlock_t	lock;
> >>> +};
> >>> +
> >>> +static struct plat_pm_t plat_pm;
> >>> +
> >>> +// register_fsl_platform_wakeup_source - Register callback function
> >>> +to plat_pm // @handle: Pointer to handle PM feature requirement //
> >>> +@handle_priv: Handler specific data struct // // Return 0 on
> >>> +success other negative errno int
> >>> +register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
> >>> +		void *handle_priv)
> >>> +{
> >>> +	struct plat_pm_t *p;
> >>> +	unsigned long	flags;
> >>> +
> >>> +	if (!handle) {
> >>> +		pr_err("FSL plat_pm: Handler invalid, reject\n");
> >>> +		return -EINVAL;
> >>> +	}
> >>> +
> >>> +	p = kmalloc(sizeof(*p), GFP_KERNEL);
> >>> +	if (!p)
> >>> +		return -ENOMEM;
> >>> +
> >>> +	p->handle = handle;
> >>> +	p->handle_priv = handle_priv;
> >>> +
> >>> +	spin_lock_irqsave(&plat_pm.lock, flags);
> >>> +	list_add_tail(&p->node, &plat_pm.node);
> >>> +	spin_unlock_irqrestore(&plat_pm.lock, flags);
> >>> +
> >>> +	return 0;
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(register_fsl_platform_wakeup_source);
> >>> +
> >>> +// Deregister_fsl_platform_wakeup_source - deregister callback
> >>> +function // @handle_priv: Handler specific data struct // // Return
> >>> +0 on success other negative errno int
> >>> +deregister_fsl_platform_wakeup_source(void *handle_priv) {
> >>> +	struct plat_pm_t *p, *tmp;
> >>> +	unsigned long	flags;
> >>> +
> >>> +	spin_lock_irqsave(&plat_pm.lock, flags);
> >>> +	list_for_each_entry_safe(p, tmp, &plat_pm.node, node) {
> >>> +		if (p->handle_priv == handle_priv) {
> >>> +			list_del(&p->node);
> >>> +			kfree(p);
> >>> +		}
> >>> +	}
> >>> +	spin_unlock_irqrestore(&plat_pm.lock, flags);
> >>> +	return 0;
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(deregister_fsl_platform_wakeup_source);
> >>> +
> >>> +// fsl_platform_wakeup_config - Configure wakeup source by calling
> >>> +handlers // @dev: pointer to user's device struct // @flag: to tell
> >>> +enable or disable wakeup source // // Return 0 on success other
> >>> +negative errno int fsl_platform_wakeup_config(struct device *dev,
> >>> +bool flag) {
> >>> +	struct plat_pm_t *p;
> >>> +	int ret;
> >>> +	bool success_handled;
> >>> +	unsigned long	flags;
> >>> +
> >>> +	success_handled = false;
> >>> +
> >>> +	// Will consider success if at least one callback return 0.
> >>> +	// Also, rest handles still get oppertunity to be executed
> >>> +	spin_lock_irqsave(&plat_pm.lock, flags);
> >>> +	list_for_each_entry(p, &plat_pm.node, node) {
> >>> +		if (p->handle) {
> >>> +			ret = p->handle(dev, flag, p->handle_priv);
> >>> +			if (!ret)
> >>> +				success_handled = true;
> >> Miss a break?
> > Actually my idea is to allow more than one registered handler to
> > handle this request, so I define a flag rather than return to
> > indicated if there is at least one handler successfully do it. This design
> might give more flexibility to framework when running.
> There is only one flag(success_handled) here, how did know which handler
> failed?
> 
> BTW, I don't think we need this flag. We can only use the return value.

Well, the plat_pm driver will not handle most errors returned by registered
handlers, except -NODEV. For -NODEV, plat_pm driver consider that handler
cannot support this request and will go to call next one. 

Besides, actually it doesn't restrict that request can be served by only one 
handler. So I add that flag to cover the case of more than one handler can 
successfully support and others might return -NODEV.

Regards,
Ran

> Cheers,
> Dongsheng
> 
> >>> +			else if (ret != -ENODEV) {
> >>> +				pr_err("FSL plat_pm: Failed to config wakeup
> >> source:%d\n", ret);
> >> Please unlock before return.
> > Yes, will fix it in next version, thanks for pointing out!
> >
> >>> +				return ret;
> >>> +			}
> >>> +		} else
> >>> +			pr_warn("FSL plat_pm: Invalid handler detected,
> >> skip\n");
> >>> +	}
> >>> +	spin_unlock_irqrestore(&plat_pm.lock, flags);
> >>> +
> >>> +	if (success_handled == false) {
> >>> +		pr_err("FSL plat_pm: Cannot find the matchhed handler for
> >> wakeup source config\n");
> >>> +		return -ENODEV;
> >>> +	}
> >> Add this into the loop.
> > My design is that if the 1st handler return -ENODEV to indicated this
> > device it doesn't support, then the framework will continue try 2nd
> handler...
> >
> > So I think it is needed to place this checking out of loop, what do you say?
> >
> > Regards,
> > Ran
> >>> +
> >>> +	return 0;
> >>> +}
> >>> +
> >>> +// fsl_platform_wakeup_enable - Enable wakeup source // @dev:
> >>> +pointer to user's device struct // // Return 0 on success other
> >>> +negative errno int fsl_platform_wakeup_enable(struct device *dev) {
> >>> +	return fsl_platform_wakeup_config(dev, true); }
> >>> +EXPORT_SYMBOL_GPL(fsl_platform_wakeup_enable);
> >>> +
> >>> +// fsl_platform_wakeup_disable - Disable wakeup source // @dev:
> >>> +pointer to user's device struct // // Return 0 on success other
> >>> +negative errno int fsl_platform_wakeup_disable(struct device *dev) {
> >>> +	return fsl_platform_wakeup_config(dev, false); }
> >>> +EXPORT_SYMBOL_GPL(fsl_platform_wakeup_disable);
> >>> +
> >>> +static int __init fsl_plat_pm_init(void) {
> >>> +	spin_lock_init(&plat_pm.lock);
> >>> +	INIT_LIST_HEAD(&plat_pm.node);
> >>> +	return 0;
> >>> +}
> >>> +
> >>> +core_initcall(fsl_plat_pm_init);
> >>> diff --git a/include/soc/fsl/plat_pm.h b/include/soc/fsl/plat_pm.h
> >>> new file mode 100644 index 0000000..bbe151e
> >>> --- /dev/null
> >>> +++ b/include/soc/fsl/plat_pm.h
> >>> @@ -0,0 +1,22 @@
> >>> +// SPDX-License-Identifier: GPL-2.0 // // plat_pm.h - Freescale
> >>> +platform PM Header // // Copyright 2018 NXP // // Author: Ran Wang
> >>> +<ran.wang_1@nxp.com>,
> >>> +
> >>> +#ifndef __FSL_PLAT_PM_H
> >>> +#define __FSL_PLAT_PM_H
> >>> +
> >>> +typedef int (*fsl_plat_pm_handle)(struct device *dev, bool flag,
> >>> +		void *handle_priv);
> >>> +
> >>> +int register_fsl_platform_wakeup_source(fsl_plat_pm_handle handle,
> >>> +		void *handle_priv);
> >>> +int deregister_fsl_platform_wakeup_source(void *handle_priv); int
> >>> +fsl_platform_wakeup_config(struct device *dev, bool flag); int
> >>> +fsl_platform_wakeup_enable(struct device *dev); int
> >>> +fsl_platform_wakeup_disable(struct device *dev);
> >>> +
> >>> +#endif	// __FSL_PLAT_PM_H
> >


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

* RE: [PATCH 3/3] soc: fsl: add RCPM driver
  2018-09-07 18:56         ` Li Yang
@ 2018-09-10  3:31           ` Ran Wang
  0 siblings, 0 replies; 24+ messages in thread
From: Ran Wang @ 2018-09-10  3:31 UTC (permalink / raw)
  To: Leo Li
  Cc: Mark Rutland, dongsheng.wang,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, lkml,
	Rob Herring, linuxppc-dev,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

Hi Leo,

On 2018/9/7 4:51, Yang Li wrote:
> 
> On Fri, Sep 7, 2018 at 4:51 AM Ran Wang <ran.wang_1@nxp.com> wrote:
> >
> > Hi Leo,
> >
> > On September 05, 2018 at 11:22 Yang Li wrote:
> > > -----Original Message-----
> > > From: Li Yang <leoyang.li@nxp.com>
> > > Sent: Wednesday, September 05, 2018 11:22
> > > To: dongsheng.wang@hxt-semitech.com
> > > Cc: Ran Wang <ran.wang_1@nxp.com>; Rob Herring
> <robh+dt@kernel.org>;
> > > Mark Rutland <mark.rutland@arm.com>; open list:OPEN FIRMWARE AND
> > > FLATTENED DEVICE TREE BINDINGS <devicetree@vger.kernel.org>;
> > > linuxppc- dev <linuxppc-dev@lists.ozlabs.org>; lkml
> > > <linux-kernel@vger.kernel.org>; moderated list:ARM/FREESCALE IMX /
> > > MXC ARM ARCHITECTURE <linux-arm- kernel@lists.infradead.org>
> > > Subject: Re: [PATCH 3/3] soc: fsl: add RCPM driver
> > >
> > > On Tue, Sep 4, 2018 at 9:58 PM Wang, Dongsheng
> <dongsheng.wang@hxt-
> > > semitech.com> wrote:
> > > >
> > > > Please change your comments style.
> > >
> > > Although this doesn't get into the Linux kernel coding style
> > > documentation yet, Linus seems changed his mind to prefer // than /*
> > > */ comment style now.
> > > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fl
> > >
> kml .org%2Flkml%2F2017%2F11%2F25%2F133&amp;data=02%7C01%7Cran.w
> ang_
> > >
> 1%40nxp.com%7Cc0d88e6690384e02b95108d612dec235%7C686ea1d3bc2b4c
> > >
> 6fa92cd99c5c301635%7C0%7C0%7C636717145285126200&amp;sdata=JIoCZp
> > >
> WhRyW76EqgSflfTDA1f0gMQGKa%2FcbvSc5CO%2Fw%3D&amp;reserved=0
> > > So the
> > > // style should be acceptable for now.
> > >
> > > >
> > > > On 2018/8/31 11:56, Ran Wang wrote:
> > > > > The NXP's QorIQ Processors based on ARM Core have RCPM module
> > > > > (Run Control and Power Management), which performs all
> > > > > device-level tasks associated with power management such as
> wakeup source control.
> > > > >
> > > > > This driver depends on FSL platform PM driver framework which
> > > > > help to isolate user and PM service provider (such as RCPM driver).
> > > > >
> > > > > Signed-off-by: Chenhui Zhao <chenhui.zhao@nxp.com>
> > > > > Signed-off-by: Ying Zhang <ying.zhang22455@nxp.com>
> > > > > Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> > > > > ---
> > > > >  drivers/soc/fsl/Kconfig   |    6 ++
> > > > >  drivers/soc/fsl/Makefile  |    1 +
> > > > >  drivers/soc/fsl/ls-rcpm.c |  153
> > > > > +++++++++++++++++++++++++++++++++++++++++++++
> > > > >  3 files changed, 160 insertions(+), 0 deletions(-)  create mode
> > > > > 100644 drivers/soc/fsl/ls-rcpm.c
> > > > >
> > > > > diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
> > > > > index 6517412..882330d 100644
> > > > > --- a/drivers/soc/fsl/Kconfig
> > > > > +++ b/drivers/soc/fsl/Kconfig
> > > > > @@ -30,3 +30,9 @@ config FSL_PLAT_PM
> > > > >         have to know the implement details of wakeup function it
> require.
> > > > >         Besides, it is also easy for service side to upgrade its logic when
> > > > >         design changed and remain user side unchanged.
> > > > > +
> > > > > +config LS_RCPM
> > > > > +     bool "Freescale RCPM support"
> > > > > +     depends on (FSL_PLAT_PM)
> > > > > +     help
> > > > > +       This feature is to enable specified wakeup source for system
> sleep.
> > > > > diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
> > > > > index 8f9db23..43ff71a 100644
> > > > > --- a/drivers/soc/fsl/Makefile
> > > > > +++ b/drivers/soc/fsl/Makefile
> > > > > @@ -7,3 +7,4 @@ obj-$(CONFIG_QUICC_ENGINE)            += qe/
> > > > >  obj-$(CONFIG_CPM)                    += qe/
> > > > >  obj-$(CONFIG_FSL_GUTS)                       += guts.o
> > > > >  obj-$(CONFIG_FSL_PLAT_PM)    += plat_pm.o
> > > > > +obj-$(CONFIG_LS_RCPM)                += ls-rcpm.o
> > >
> > > Probably use "_" instead of "-" for alignment.
> >
> > OK, will update in next version
> >
> > > > > diff --git a/drivers/soc/fsl/ls-rcpm.c
> > > > > b/drivers/soc/fsl/ls-rcpm.c new file mode 100644 index
> > > > > 0000000..b0feb88
> > > > > --- /dev/null
> > > > > +++ b/drivers/soc/fsl/ls-rcpm.c
> > > > > @@ -0,0 +1,153 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0 // // plat_pm.c - Freescale
> > > > > +Layerscape RCPM driver
> > >
> > > The file name here is not the same as the real file name.
> >
> > Got it, will correct it.
> >
> > > > > +//
> > > > > +// Copyright 2018 NXP
> > > > > +//
> > > > > +// Author: Ran Wang <ran.wang_1@nxp.com>,
> > >
> > > Where do you need the comma in the end?
> >
> > My bad, will remove comma in next version.
> >
> > > > > +
> > > > > +#include <linux/init.h>
> > > > > +#include <linux/module.h>
> > > > > +#include <linux/platform_device.h> #include
> > > > > +<linux/of_address.h> #include <linux/slab.h> #include
> > > > > +<soc/fsl/plat_pm.h>
> > > > > +
> > > > > +#define MAX_COMPATIBLE_NUM   10
> > > > > +
> > > > > +struct rcpm_t {
> > > > > +     struct device *dev;
> > > > > +     void __iomem *ippdexpcr_addr;
> > > > > +     bool big_endian;        /* Big/Little endian of RCPM module */
> > > > > +};
> > > > > +
> > > > > +// rcpm_handle - Configure RCPM reg according to wake up source
> > > > > +request // @user_dev: pointer to user's device struct // @flag:
> > > > > +to
> > > > > +enable(true) or disable(false) wakeup source // @handle_priv:
> > > > > +pointer to struct rcpm_t instance // // Return 0 on success
> > > > > +other negative errno
> > >
> > > Although Linus preferred this // comment style.  I'm not sure if
> > > this will be handled correctly by the kernel-doc compiler.
> > >
> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fw
> > > w
> > > w.kernel.org%2Fdoc%2Fhtml%2Fv4.18%2Fdoc-guide%2Fkernel-
> > >
> doc.html&amp;data=02%7C01%7Cran.wang_1%40nxp.com%7Cc0d88e669038
> > >
> 4e02b95108d612dec235%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> > > %7C636717145285126200&amp;sdata=H7GkUNOLVG%2FCcZESzhtHBeHC
> bO9
> > > %2FK4k9EdH30Cxq2%2BM%3D&amp;reserved=0
> >
> > So, do you think I need to change all comment style back to '/* ... */' ?
> > Actually I feel a little bit confused here.
> 
> I think Linus's comment about // comment style applies to normal code
> comment.  But kernel-doc comment is a special kind of code comment that
> needs to meet certain requirements.  People can use the scripts/kernel-doc
> tool to generate readable API documents from the source code.  It looks like
> you wanted to make the function description aligned with the kernel-doc
> format, but kernel-doc specifically requires to use the /* */ style(at least for
> now).

OK, will change style back to /* */.

Regards,
Ran

> Regards,
> Leo

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

* RE: [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM
  2018-09-07 20:22   ` Scott Wood
@ 2018-09-10  8:44     ` Ran Wang
  2018-09-11 22:42       ` Li Yang
  0 siblings, 1 reply; 24+ messages in thread
From: Ran Wang @ 2018-09-10  8:44 UTC (permalink / raw)
  To: Scott Wood, Leo Li, Rob Herring, Mark Rutland
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel, linux-pm

Hi Scott,

On 2018/9/8 4:23, Scott Wood wrote:
> 
> On Fri, 2018-08-31 at 11:52 +0800, Ran Wang wrote:
> > +Optional properties:
> > + - big-endian : Indicate RCPM registers is big-endian. A RCPM node
> > +   that doesn't have this property will be regarded as little-endian.
> 
> You've just broken all the existing powerpc device trees that are big-endian
> and have no big-endian property.

Yes, powerpc RCPM driver (arch/powerpc/sysdev/fsl_rcpm.c) will not refer
to big-endian. However, I think if Layerscape RCPM driver use different compatible
id (such as ' fsl,qoriq-rcpm-2.2'), it might be safe. Is that OK?

> > + - <property 'compatible' string of consumer device> : This string
> > +   is referred by RCPM driver to judge if the consumer (such as flex timer)
> > +   is able to be regards as wakeup source or not, such as
> > + 'fsl,ls1012a-
> > ftm'.
> > +   Further, this property will carry the bit mask info to control
> > +   coresponding wake up source.
> 
> What will you do if there are multiple instances of a device with the same
> compatible, and different wakeup bits?  

You got me! This is a problem in current version. Well, we have to decouple wake up
source IP and RCPM driver. That's why I add a plat_pm driver to prevent wake up IP
knowing any information of RCPM. So in current context, one idea come to me is to
redesign property ' fsl,ls1012a-ftm = <0x20000>;', change to 'fsl,ls1012a-ftm = <&ftm0 0x20000>;'
What do you say? And could you tell me which API I can use to check if that device's
name is ftm0 (for example we want to find a node ftm0: ftm@29d000)?

>Plus, it's an awkward design in
> general, and you don't describe what the value actually means (bits in which
> register?). 

Yes, I admit my design looks ugly and not flexible and extensible enough. However, for above reason, 
do you have any good idea, please? :)

As to the register information, I can explain here in details (will add to commit
message of next version): There is a RCPM HW block which has register named IPPDEXPCR.
It controls whether prevent certain IP (such as timer, usb, etc) from entering low
power mode when system suspended. So it's necessary to program it if we want one
of those IP work as a wakeup source. However, different Layerscape SoCs have different bit vs.
IP mapping  layout. So I have to record this information in device tree and fetched by RCPM driver
directly.

Do I need to list all SoC's mapping information in this binding doc for reference?

>What was wrong with the existing binding?  

There was one version of RCPM patch which requiring property 'fsl,#rcpm-wakeup-cells' but was not
accepted by upstream finally. Now we will no need it any longer due to new design allow case of multiple
RCPM devices existing case.

>Alternatively, use the clock bindings.

Sorry I didn't get your point.

> > -
> > -Example:
> > -	lpuart0: serial@2950000 {
> > -		compatible = "fsl,ls1021a-lpuart";
> > -		reg = <0x0 0x2950000 0x0 0x1000>;
> > -		interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
> > -		clocks = <&sysclk>;
> > -		clock-names = "ipg";
> > -		fsl,rcpm-wakeup = <&rcpm 0x0 0x40000000>;
> > +		big-endian;
> > +		fsl,ls1012a-ftm = <0x20000>;
> > +		fsl,pfe = <0xf0000020>;
> 
> fsl,pfe is not documented.

pfe patch is not upstream yet, will remove it.

Regards,
Ran

> -Scott


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

* RE: [PATCH 3/3] soc: fsl: add RCPM driver
  2018-09-07 20:25   ` Scott Wood
@ 2018-09-10  9:09     ` Ran Wang
  0 siblings, 0 replies; 24+ messages in thread
From: Ran Wang @ 2018-09-10  9:09 UTC (permalink / raw)
  To: Scott Wood, Leo Li, Rob Herring, Mark Rutland
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel, linux-pm

Hi Scott,

On 2018/9/8 18:16, Scott Wood wrote:
> 
> On Fri, 2018-08-31 at 11:52 +0800, Ran Wang wrote:
> > The NXP's QorIQ Processors based on ARM Core have RCPM module (Run
> > Control and Power Management), which performs all device-level tasks
> > associated with power management such as wakeup source control.
> >
> > This driver depends on FSL platform PM driver framework which help to
> > isolate user and PM service provider (such as RCPM driver).
> >
> > Signed-off-by: Chenhui Zhao <chenhui.zhao@nxp.com>
> > Signed-off-by: Ying Zhang <ying.zhang22455@nxp.com>
> > Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> > ---
> >  drivers/soc/fsl/Kconfig   |    6 ++
> >  drivers/soc/fsl/Makefile  |    1 +
> >  drivers/soc/fsl/ls-rcpm.c |  153
> > +++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 160 insertions(+), 0 deletions(-)  create mode
> > 100644 drivers/soc/fsl/ls-rcpm.c
> 
> Is there a reason why this is LS-specific, or could it be used with PPC RCPM
> blocks?

They have different SW arch design on low power operation: PPC RCPM
driver has taken care of most things of suspend enter & exit. And LS RCPM driver
will only handle wakeup source configure and left rest work to system firmware
to do. So you might be aware that LS RCPM will only get call whenever plat_pm
driver API is called rather than system suspend begin where.

> 
> > diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig index
> > 6517412..882330d 100644
> > --- a/drivers/soc/fsl/Kconfig
> > +++ b/drivers/soc/fsl/Kconfig
> > @@ -30,3 +30,9 @@ config FSL_PLAT_PM
> >  	  have to know the implement details of wakeup function it require.
> >  	  Besides, it is also easy for service side to upgrade its logic
> > when
> >  	  design changed and remain user side unchanged.
> > +
> > +config LS_RCPM
> > +	bool "Freescale RCPM support"
> > +	depends on (FSL_PLAT_PM)
> 
> Why is this parenthesized?

Because we'd like to decouple RCPM driver and its user.
Benefit is that will allow user doesn't have to know who will serve it for some PM
features (such as wake up source control), and provide some kind of flexibility when
either RCMP or user driver evolve in the future. So I add a plat_pm driver to prevent
wake up IP knowing any information of RCPM.

Regards,
Ran

> 
> -Scott


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

* RE: [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms
  2018-09-07 20:35 ` Scott Wood
@ 2018-09-10  9:26   ` Ran Wang
  0 siblings, 0 replies; 24+ messages in thread
From: Ran Wang @ 2018-09-10  9:26 UTC (permalink / raw)
  To: Scott Wood, Leo Li, Rob Herring, Mark Rutland
  Cc: devicetree, linuxppc-dev, linux-kernel, linux-arm-kernel, linux-pm

Hi Scott,

On 2018/9/8 4:35, Scott Wood wrote:
> 
> On Fri, 2018-08-31 at 11:52 +0800, Ran Wang wrote:
> > This driver is to provide a independent framework for PM service
> > provider and consumer to configure system level wake up feature. For
> > example, RCPM driver could register a callback function on this
> > platform first, and Flex timer driver who want to enable timer wake up
> > feature, will call generic API provided by this platform driver, and
> > then it will trigger RCPM driver to do it. The benefit is to isolate
> > the user and service, such as flex timer driver will not have to know
> > the implement details of wakeup function it require. Besides, it is
> > also easy for service side to upgrade its logic when design is changed
> > and remain user side unchanged.
> >
> > Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> > ---
> >  drivers/soc/fsl/Kconfig   |   14 +++++
> >  drivers/soc/fsl/Makefile  |    1 +
> >  drivers/soc/fsl/plat_pm.c |  144
> > +++++++++++++++++++++++++++++++++++++++++++++
> >  include/soc/fsl/plat_pm.h |   22 +++++++
> >  4 files changed, 181 insertions(+), 0 deletions(-)  create mode
> > 100644 drivers/soc/fsl/plat_pm.c  create mode 100644
> > include/soc/fsl/plat_pm.h
> >
> > diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig index
> > 7a9fb9b..6517412 100644
> > --- a/drivers/soc/fsl/Kconfig
> > +++ b/drivers/soc/fsl/Kconfig
> > @@ -16,3 +16,17 @@ config FSL_GUTS
> >  	  Initially only reading SVR and registering soc device are
> > supported.
> >  	  Other guts accesses, such as reading RCW, should eventually be
> > moved
> >  	  into this driver as well.
> +
> > +config FSL_PLAT_PM
> > +	bool "Freescale platform PM framework"
> 
> This name seems to be simultaneously too generic (for something that is
> likely intended only for use with certain Freescale/NXP chip families) and too
> specific (for something that seems to be general infrastructure with no real
> hardware dependencies).

Yes, this driver has no real HW dependencies at all. But we'd like to introduce it
to help providing more flexibility & generic on FSL PM feature configure (so far 
we have RCPM on system wakeup source control). I think it's good
for driver/IP porting among different SoC in the future. As to the name, do you
have better suggestion?

> What specific problems with Linux's generic wakeup infrastructure is this
> trying to solve, and why would those problems not be better solved there?

Actually, I am not sure if generic wakeup infrastructure have this kind of PM feature
(keep specific IP alive during system suspend, could you please show me?).
And I think it is not common requirement, so I decide to put it in FSL folder. 

> Also, you should CC linux-pm on these patches.

Yes, thanks for suggestion

Regards,
Ran

> -Scott


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

* Re: [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM
  2018-09-10  8:44     ` Ran Wang
@ 2018-09-11 22:42       ` Li Yang
  0 siblings, 0 replies; 24+ messages in thread
From: Li Yang @ 2018-09-11 22:42 UTC (permalink / raw)
  To: Ran Wang
  Cc: Scott Wood, Rob Herring, Mark Rutland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linuxppc-dev, lkml,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	linux-pm

On Mon, Sep 10, 2018 at 3:46 AM Ran Wang <ran.wang_1@nxp.com> wrote:
>
> Hi Scott,
>
> On 2018/9/8 4:23, Scott Wood wrote:
> >
> > On Fri, 2018-08-31 at 11:52 +0800, Ran Wang wrote:
> > > +Optional properties:
> > > + - big-endian : Indicate RCPM registers is big-endian. A RCPM node
> > > +   that doesn't have this property will be regarded as little-endian.
> >
> > You've just broken all the existing powerpc device trees that are big-endian
> > and have no big-endian property.
>
> Yes, powerpc RCPM driver (arch/powerpc/sysdev/fsl_rcpm.c) will not refer
> to big-endian. However, I think if Layerscape RCPM driver use different compatible
> id (such as ' fsl,qoriq-rcpm-2.2'), it might be safe. Is that OK?

For Layerscape Chassis(gen3) based chips, the Reference Manual named
the power management IP as COP_PMU instead of RCPM which makes sense
to me as the register map is also quite different from the reg map of
RCPM.  So I think it is reasonable to create a new binding and driver
for the Chassis Gen3 based PMU.  However, the
arch/powerpc/sysdev/fsl_rcpm.c driver probably should be moved to
drivers/soc/fsl, as the Gen2.x Chassis and RCPM IP are also used in
some non-PowerPC Layerscape SoCs.  From what I know, all the RCPM
based IP are all big endian, so there is no need to add this property
for the old binding.

>
> > > + - <property 'compatible' string of consumer device> : This string
> > > +   is referred by RCPM driver to judge if the consumer (such as flex timer)
> > > +   is able to be regards as wakeup source or not, such as
> > > + 'fsl,ls1012a-
> > > ftm'.
> > > +   Further, this property will carry the bit mask info to control
> > > +   coresponding wake up source.
> >
> > What will you do if there are multiple instances of a device with the same
> > compatible, and different wakeup bits?
>
> You got me! This is a problem in current version. Well, we have to decouple wake up
> source IP and RCPM driver. That's why I add a plat_pm driver to prevent wake up IP
> knowing any information of RCPM. So in current context, one idea come to me is to
> redesign property ' fsl,ls1012a-ftm = <0x20000>;', change to 'fsl,ls1012a-ftm = <&ftm0 0x20000>;'
> What do you say? And could you tell me which API I can use to check if that device's
> name is ftm0 (for example we want to find a node ftm0: ftm@29d000)?
>
> >Plus, it's an awkward design in
> > general, and you don't describe what the value actually means (bits in which
> > register?).
>
> Yes, I admit my design looks ugly and not flexible and extensible enough. However, for above reason,
> do you have any good idea, please? :)

Why do you have to move the wakeup information from device nodes to
the RCPM/PMU node?  For information related to both on-chip device and
SoC integration, the information normally goes into the node of
on-chip device instead of the integration IP's device node.  Existing
example like: interrupt, clock, memory map, and etc.  It is much
cleaner than listing all the interrupts in the interrupt controller's
node, right?

>
> As to the register information, I can explain here in details (will add to commit
> message of next version): There is a RCPM HW block which has register named IPPDEXPCR.
> It controls whether prevent certain IP (such as timer, usb, etc) from entering low
> power mode when system suspended. So it's necessary to program it if we want one
> of those IP work as a wakeup source. However, different Layerscape SoCs have different bit vs.
> IP mapping  layout. So I have to record this information in device tree and fetched by RCPM driver
> directly.
>
> Do I need to list all SoC's mapping information in this binding doc for reference?
>
> >What was wrong with the existing binding?
>
> There was one version of RCPM patch which requiring property 'fsl,#rcpm-wakeup-cells' but was not
> accepted by upstream finally. Now we will no need it any longer due to new design allow case of multiple
> RCPM devices existing case.
>
> >Alternatively, use the clock bindings.
>
> Sorry I didn't get your point.
>
> > > -
> > > -Example:
> > > -   lpuart0: serial@2950000 {
> > > -           compatible = "fsl,ls1021a-lpuart";
> > > -           reg = <0x0 0x2950000 0x0 0x1000>;
> > > -           interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
> > > -           clocks = <&sysclk>;
> > > -           clock-names = "ipg";
> > > -           fsl,rcpm-wakeup = <&rcpm 0x0 0x40000000>;
> > > +           big-endian;
> > > +           fsl,ls1012a-ftm = <0x20000>;
> > > +           fsl,pfe = <0xf0000020>;
> >
> > fsl,pfe is not documented.
>
> pfe patch is not upstream yet, will remove it.
>
> Regards,
> Ran
>
> > -Scott
>

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

* Re: [PATCH 3/3] soc: fsl: add RCPM driver
  2019-10-22  7:51 ` [PATCH 3/3] soc: fsl: add RCPM driver Ran Wang
@ 2019-10-22  9:18   ` Rafael J. Wysocki
  0 siblings, 0 replies; 24+ messages in thread
From: Rafael J. Wysocki @ 2019-10-22  9:18 UTC (permalink / raw)
  To: Ran Wang
  Cc: Rafael J . Wysocki, Rob Herring, Li Yang, Mark Rutland,
	Pavel Machek, Huang Anson, Li Biwen, Len Brown,
	Greg Kroah-Hartman, linuxppc-dev, Linux ARM, devicetree,
	Linux Kernel Mailing List, Linux PM

On Tue, Oct 22, 2019 at 9:52 AM Ran Wang <ran.wang_1@nxp.com> wrote:
>
> The NXP's QorIQ Processors based on ARM Core have RCPM module
> (Run Control and Power Management), which performs system level
> tasks associated with power management such as wakeup source control.
>
> This driver depends on PM wakeup source framework which help to
> collect wake information.
>
> Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
> ---
> Change in v8:
>         - Adjust related API usage to meet wakeup.c's update in patch 1/3.
>         - Add sanity checking for the case of ws->dev or ws->dev->parent
>           is null.
>
> Change in v7:
>         - Replace 'ws->dev' with 'ws->dev->parent' to get aligned with
>         c8377adfa781 ("PM / wakeup: Show wakeup sources stats in sysfs")
>         - Remove '+obj-y += ftm_alarm.o' since it is wrong.
>         - Cosmetic work.
>
> Change in v6:
>         - Adjust related API usage to meet wakeup.c's update in patch 1/3.
>
> Change in v5:
>         - Fix v4 regression of the return value of wakeup_source_get_next()
>         didn't pass to ws in while loop.
>         - Rename wakeup_source member 'attached_dev' to 'dev'.
>         - Rename property 'fsl,#rcpm-wakeup-cells' to '#fsl,rcpm-wakeup-cells'.
>         please see https://lore.kernel.org/patchwork/patch/1101022/
>
> Change in v4:
>         - Remove extra ',' in author line of rcpm.c
>         - Update usage of wakeup_source_get_next() to be less confusing to the
> reader, code logic remain the same.
>
> Change in v3:
>         - Some whitespace ajdustment.
>
> Change in v2:
>         - Rebase Kconfig and Makefile update to latest mainline.
>
>  drivers/soc/fsl/Kconfig  |   8 +++
>  drivers/soc/fsl/Makefile |   1 +
>  drivers/soc/fsl/rcpm.c   | 133 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 142 insertions(+)
>  create mode 100644 drivers/soc/fsl/rcpm.c
>
> diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
> index f9ad8ad..4918856 100644
> --- a/drivers/soc/fsl/Kconfig
> +++ b/drivers/soc/fsl/Kconfig
> @@ -40,4 +40,12 @@ config DPAA2_CONSOLE
>           /dev/dpaa2_mc_console and /dev/dpaa2_aiop_console,
>           which can be used to dump the Management Complex and AIOP
>           firmware logs.
> +
> +config FSL_RCPM
> +       bool "Freescale RCPM support"
> +       depends on PM_SLEEP
> +       help
> +         The NXP QorIQ Processors based on ARM Core have RCPM module
> +         (Run Control and Power Management), which performs all device-level
> +         tasks associated with power management, such as wakeup source control.
>  endmenu
> diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
> index 71dee8d..906f1cd 100644
> --- a/drivers/soc/fsl/Makefile
> +++ b/drivers/soc/fsl/Makefile
> @@ -6,6 +6,7 @@
>  obj-$(CONFIG_FSL_DPAA)                 += qbman/
>  obj-$(CONFIG_QUICC_ENGINE)             += qe/
>  obj-$(CONFIG_CPM)                      += qe/
> +obj-$(CONFIG_FSL_RCPM)                 += rcpm.o
>  obj-$(CONFIG_FSL_GUTS)                 += guts.o
>  obj-$(CONFIG_FSL_MC_DPIO)              += dpio/
>  obj-$(CONFIG_DPAA2_CONSOLE)            += dpaa2-console.o
> diff --git a/drivers/soc/fsl/rcpm.c b/drivers/soc/fsl/rcpm.c
> new file mode 100644
> index 0000000..3ed135e
> --- /dev/null
> +++ b/drivers/soc/fsl/rcpm.c
> @@ -0,0 +1,133 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// rcpm.c - Freescale QorIQ RCPM driver
> +//
> +// Copyright 2019 NXP
> +//
> +// Author: Ran Wang <ran.wang_1@nxp.com>
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/suspend.h>
> +#include <linux/kernel.h>
> +
> +#define RCPM_WAKEUP_CELL_MAX_SIZE      7
> +
> +struct rcpm {
> +       unsigned int    wakeup_cells;
> +       void __iomem    *ippdexpcr_base;
> +       bool            little_endian;
> +};
> +

Please add a kerneldoc comment describing this routine.

> +static int rcpm_pm_prepare(struct device *dev)
> +{
> +       int i, ret, idx;
> +       void __iomem *base;
> +       struct wakeup_source    *ws;
> +       struct rcpm             *rcpm;
> +       struct device_node      *np = dev->of_node;
> +       u32 value[RCPM_WAKEUP_CELL_MAX_SIZE + 1], tmp;
> +
> +       rcpm = dev_get_drvdata(dev);
> +       if (!rcpm)
> +               return -EINVAL;
> +
> +       base = rcpm->ippdexpcr_base;
> +       idx = wakeup_sources_read_lock();
> +
> +       /* Begin with first registered wakeup source */
> +       for_each_wakeup_source(ws) {
> +
> +               /* skip object which is not attached to device */
> +               if (!ws->dev || !ws->dev->parent)
> +                       continue;
> +
> +               ret = device_property_read_u32_array(ws->dev->parent,
> +                               "fsl,rcpm-wakeup", value,
> +                               rcpm->wakeup_cells + 1);
> +
> +               /*  Wakeup source should refer to current rcpm device */
> +               if (ret || (np->phandle != value[0])) {
> +                       dev_info(dev, "%s doesn't refer to this rcpm\n",
> +                                       ws->name);

IMO printing this message is not useful in general, because it looks
like you just want to skip wakeup sources that aren't associated with
rcpm devices.

Maybe use pr_debug() to print it?  Or maybe use pr_debug() to print a
message if you have found a suitable device?  Wouldn't that be more
useful?

> +                       continue;
> +               }
> +

It would be good to add a comment explaining what the code below does
here.  Or explain that in the function's kerneldoc comment.

> +               for (i = 0; i < rcpm->wakeup_cells; i++) {

It looks like 'tmp' can be defined in this block.

And I would store the value of value[i+1] in tmp upfront, that is

u32 tmp = value[i+1];

> +                       /* We can only OR related bits */
> +                       if (value[i + 1]) {

Also I would do

if (!tmp)
        continue;

to reduce the indentation level.

> +                               if (rcpm->little_endian) {
> +                                       tmp = ioread32(base + i * 4);
> +                                       tmp |= value[i + 1];
> +                                       iowrite32(tmp, base + i * 4);

So it is sufficient to do

tmp |= ioread32(base + i * 4);
iowrite32(tmp, base + i * 4);

here and analogously below.

You may as well define

void __iomem *address = base + i * 4;

and use it everywhere in this block instead of the (base + I * 4) expression.

> +                               } else {
> +                                       tmp = ioread32be(base + i * 4);
> +                                       tmp |= value[i + 1];
> +                                       iowrite32be(tmp, base + i * 4);
> +                               }
> +                       }
> +               }
> +       }
> +
> +       wakeup_sources_read_unlock(idx);
> +
> +       return 0;
> +}
> +
> +static const struct dev_pm_ops rcpm_pm_ops = {
> +       .prepare =  rcpm_pm_prepare,
> +};
> +

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

* [PATCH 3/3] soc: fsl: add RCPM driver
  2019-10-22  7:51 [PATCH 1/3] PM: wakeup: Add routine to help fetch wakeup source object Ran Wang
@ 2019-10-22  7:51 ` Ran Wang
  2019-10-22  9:18   ` Rafael J. Wysocki
  0 siblings, 1 reply; 24+ messages in thread
From: Ran Wang @ 2019-10-22  7:51 UTC (permalink / raw)
  To: Rafael J . Wysocki, Rob Herring, Li Yang, Mark Rutland,
	Pavel Machek, Huang Anson
  Cc: Li Biwen, Len Brown, Greg Kroah-Hartman, linuxppc-dev,
	linux-arm-kernel, devicetree, linux-kernel, linux-pm, Ran Wang

The NXP's QorIQ Processors based on ARM Core have RCPM module
(Run Control and Power Management), which performs system level
tasks associated with power management such as wakeup source control.

This driver depends on PM wakeup source framework which help to
collect wake information.

Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
---
Change in v8:
	- Adjust related API usage to meet wakeup.c's update in patch 1/3.
	- Add sanity checking for the case of ws->dev or ws->dev->parent
	  is null.

Change in v7:
	- Replace 'ws->dev' with 'ws->dev->parent' to get aligned with
	c8377adfa781 ("PM / wakeup: Show wakeup sources stats in sysfs")
	- Remove '+obj-y += ftm_alarm.o' since it is wrong.
	- Cosmetic work.

Change in v6:
	- Adjust related API usage to meet wakeup.c's update in patch 1/3.

Change in v5:
	- Fix v4 regression of the return value of wakeup_source_get_next()
	didn't pass to ws in while loop.
	- Rename wakeup_source member 'attached_dev' to 'dev'.
	- Rename property 'fsl,#rcpm-wakeup-cells' to '#fsl,rcpm-wakeup-cells'.
	please see https://lore.kernel.org/patchwork/patch/1101022/

Change in v4:
	- Remove extra ',' in author line of rcpm.c
	- Update usage of wakeup_source_get_next() to be less confusing to the
reader, code logic remain the same.

Change in v3:
	- Some whitespace ajdustment.

Change in v2:
	- Rebase Kconfig and Makefile update to latest mainline.

 drivers/soc/fsl/Kconfig  |   8 +++
 drivers/soc/fsl/Makefile |   1 +
 drivers/soc/fsl/rcpm.c   | 133 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 142 insertions(+)
 create mode 100644 drivers/soc/fsl/rcpm.c

diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index f9ad8ad..4918856 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -40,4 +40,12 @@ config DPAA2_CONSOLE
 	  /dev/dpaa2_mc_console and /dev/dpaa2_aiop_console,
 	  which can be used to dump the Management Complex and AIOP
 	  firmware logs.
+
+config FSL_RCPM
+	bool "Freescale RCPM support"
+	depends on PM_SLEEP
+	help
+	  The NXP QorIQ Processors based on ARM Core have RCPM module
+	  (Run Control and Power Management), which performs all device-level
+	  tasks associated with power management, such as wakeup source control.
 endmenu
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 71dee8d..906f1cd 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_FSL_DPAA)                 += qbman/
 obj-$(CONFIG_QUICC_ENGINE)		+= qe/
 obj-$(CONFIG_CPM)			+= qe/
+obj-$(CONFIG_FSL_RCPM)			+= rcpm.o
 obj-$(CONFIG_FSL_GUTS)			+= guts.o
 obj-$(CONFIG_FSL_MC_DPIO) 		+= dpio/
 obj-$(CONFIG_DPAA2_CONSOLE)		+= dpaa2-console.o
diff --git a/drivers/soc/fsl/rcpm.c b/drivers/soc/fsl/rcpm.c
new file mode 100644
index 0000000..3ed135e
--- /dev/null
+++ b/drivers/soc/fsl/rcpm.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// rcpm.c - Freescale QorIQ RCPM driver
+//
+// Copyright 2019 NXP
+//
+// Author: Ran Wang <ran.wang_1@nxp.com>
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+#include <linux/kernel.h>
+
+#define RCPM_WAKEUP_CELL_MAX_SIZE	7
+
+struct rcpm {
+	unsigned int	wakeup_cells;
+	void __iomem	*ippdexpcr_base;
+	bool		little_endian;
+};
+
+static int rcpm_pm_prepare(struct device *dev)
+{
+	int i, ret, idx;
+	void __iomem *base;
+	struct wakeup_source	*ws;
+	struct rcpm		*rcpm;
+	struct device_node	*np = dev->of_node;
+	u32 value[RCPM_WAKEUP_CELL_MAX_SIZE + 1], tmp;
+
+	rcpm = dev_get_drvdata(dev);
+	if (!rcpm)
+		return -EINVAL;
+
+	base = rcpm->ippdexpcr_base;
+	idx = wakeup_sources_read_lock();
+
+	/* Begin with first registered wakeup source */
+	for_each_wakeup_source(ws) {
+
+		/* skip object which is not attached to device */
+		if (!ws->dev || !ws->dev->parent)
+			continue;
+
+		ret = device_property_read_u32_array(ws->dev->parent,
+				"fsl,rcpm-wakeup", value,
+				rcpm->wakeup_cells + 1);
+
+		/*  Wakeup source should refer to current rcpm device */
+		if (ret || (np->phandle != value[0])) {
+			dev_info(dev, "%s doesn't refer to this rcpm\n",
+					ws->name);
+			continue;
+		}
+
+		for (i = 0; i < rcpm->wakeup_cells; i++) {
+			/* We can only OR related bits */
+			if (value[i + 1]) {
+				if (rcpm->little_endian) {
+					tmp = ioread32(base + i * 4);
+					tmp |= value[i + 1];
+					iowrite32(tmp, base + i * 4);
+				} else {
+					tmp = ioread32be(base + i * 4);
+					tmp |= value[i + 1];
+					iowrite32be(tmp, base + i * 4);
+				}
+			}
+		}
+	}
+
+	wakeup_sources_read_unlock(idx);
+
+	return 0;
+}
+
+static const struct dev_pm_ops rcpm_pm_ops = {
+	.prepare =  rcpm_pm_prepare,
+};
+
+static int rcpm_probe(struct platform_device *pdev)
+{
+	struct device	*dev = &pdev->dev;
+	struct resource *r;
+	struct rcpm	*rcpm;
+	int ret;
+
+	rcpm = devm_kzalloc(dev, sizeof(*rcpm), GFP_KERNEL);
+	if (!rcpm)
+		return -ENOMEM;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	rcpm->ippdexpcr_base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(rcpm->ippdexpcr_base)) {
+		ret =  PTR_ERR(rcpm->ippdexpcr_base);
+		return ret;
+	}
+
+	rcpm->little_endian = device_property_read_bool(
+			&pdev->dev, "little-endian");
+
+	ret = device_property_read_u32(&pdev->dev,
+			"#fsl,rcpm-wakeup-cells", &rcpm->wakeup_cells);
+	if (ret)
+		return ret;
+
+	dev_set_drvdata(&pdev->dev, rcpm);
+
+	return 0;
+}
+
+static const struct of_device_id rcpm_of_match[] = {
+	{ .compatible = "fsl,qoriq-rcpm-2.1+", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, rcpm_of_match);
+
+static struct platform_driver rcpm_driver = {
+	.driver = {
+		.name = "rcpm",
+		.of_match_table = rcpm_of_match,
+		.pm	= &rcpm_pm_ops,
+	},
+	.probe = rcpm_probe,
+};
+
+module_platform_driver(rcpm_driver);
-- 
2.7.4


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

* [PATCH 3/3] soc: fsl: add RCPM driver
  2019-05-17  2:47 [PATCH 1/3] PM: wakeup: Add routine to help fetch wakeup source object Ran Wang
@ 2019-05-17  2:47 ` Ran Wang
  0 siblings, 0 replies; 24+ messages in thread
From: Ran Wang @ 2019-05-17  2:47 UTC (permalink / raw)
  To: Li Yang, Rob Herring, Mark Rutland
  Cc: Rafael J . Wysocki, Pavel Machek, Len Brown, Greg Kroah-Hartman,
	linuxppc-dev, linux-arm-kernel, devicetree, linux-kernel,
	linux-pm, Ran Wang

The NXP's QorIQ Processors based on ARM Core have RCPM module
(Run Control and Power Management), which performs all device-level
tasks associated with power management such as wakeup source control.

This driver depends on PM wakeup source framework which help to
collect wake information.

Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
---
 drivers/soc/fsl/Kconfig  |    8 +++
 drivers/soc/fsl/Makefile |    1 +
 drivers/soc/fsl/rcpm.c   |  124 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 133 insertions(+), 0 deletions(-)
 create mode 100644 drivers/soc/fsl/rcpm.c

diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index 3b85e18..a25e05b 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -50,4 +50,12 @@ config FSL_SLEEP_FSM
 if ARM || ARM64
 source "drivers/soc/fsl/Kconfig.arm"
 endif
+
+config FSL_RCPM
+	bool "Freescale RCPM support"
+	depends on PM_SLEEP
+	help
+	  The NXP's QorIQ Processors based on ARM Core have RCPM module
+	  (Run Control and Power Management), which performs all device-level
+	  tasks associated with power management, such as wakeup source control.
 endmenu
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index db7b09b..aab9f9b 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_FSL_MC_DPIO) 		+= dpio/
 obj-$(CONFIG_FSL_LS2_CONSOLE)		+= ls2-console/
 obj-$(CONFIG_LS_SOC_DRIVERS)		+= layerscape/
 obj-$(CONFIG_FSL_SLEEP_FSM)	+= sleep_fsm.o
+obj-$(CONFIG_FSL_RCPM)		+= rcpm.o
diff --git a/drivers/soc/fsl/rcpm.c b/drivers/soc/fsl/rcpm.c
new file mode 100644
index 0000000..b817319
--- /dev/null
+++ b/drivers/soc/fsl/rcpm.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// rcpm.c - Freescale QorIQ RCPM driver
+//
+// Copyright 2019 NXP
+//
+// Author: Ran Wang <ran.wang_1@nxp.com>,
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+#include <linux/kernel.h>
+
+#define RCPM_WAKEUP_CELL_MAX_SIZE	7
+
+struct rcpm {
+	unsigned int wakeup_cells;
+	void __iomem *ippdexpcr_base;
+	bool	little_endian;
+};
+
+static int rcpm_pm_prepare(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct wakeup_source *ws;
+	struct rcpm *rcpm;
+	u32 value[RCPM_WAKEUP_CELL_MAX_SIZE + 1], tmp;
+	int i, ret;
+
+	rcpm = dev_get_drvdata(dev);
+	if (!rcpm)
+		return -EINVAL;
+
+	/* Begin with first registered wakeup source */
+	ws = wakeup_source_get_next(NULL);
+	while (ws) {
+		ret = device_property_read_u32_array(ws->attached_dev,
+				"fsl,rcpm-wakeup", value, rcpm->wakeup_cells + 1);
+
+		/*  Wakeup source should refer to current rcpm device */
+		if (ret || (np->phandle != value[0])) {
+			dev_info(dev, "%s doesn't refer to this rcpm\n",
+					ws->name);
+			ws = wakeup_source_get_next(ws);
+			continue;
+		}
+
+		for (i = 0; i < rcpm->wakeup_cells; i++) {
+			/* We can only OR related bits */
+			if (value[i + 1]) {
+				if (rcpm->little_endian) {
+					tmp = ioread32(rcpm->ippdexpcr_base + i * 4);
+					tmp |= value[i + 1];
+					iowrite32(tmp, rcpm->ippdexpcr_base + i * 4);
+				} else {
+					tmp = ioread32be(rcpm->ippdexpcr_base + i * 4);
+					tmp |= value[i + 1];
+					iowrite32be(tmp, rcpm->ippdexpcr_base + i * 4);
+				}
+			}
+		}
+		ws = wakeup_source_get_next(ws);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops rcpm_pm_ops = {
+	.prepare =  rcpm_pm_prepare,
+};
+
+static int rcpm_probe(struct platform_device *pdev)
+{
+	struct device	*dev = &pdev->dev;
+	struct resource *r;
+	struct rcpm		*rcpm;
+	int ret;
+
+	rcpm = devm_kzalloc(dev, sizeof(*rcpm), GFP_KERNEL);
+	if (!rcpm)
+		return -ENOMEM;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	rcpm->ippdexpcr_base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(rcpm->ippdexpcr_base)) {
+		ret =  PTR_ERR(rcpm->ippdexpcr_base);
+		return ret;
+	}
+
+	rcpm->little_endian = device_property_read_bool(
+			&pdev->dev, "little-endian");
+
+	ret = device_property_read_u32(&pdev->dev,
+			"fsl,#rcpm-wakeup-cells", &rcpm->wakeup_cells);
+	if (ret)
+		return ret;
+
+	dev_set_drvdata(&pdev->dev, rcpm);
+
+	return 0;
+}
+
+static const struct of_device_id rcpm_of_match[] = {
+	{ .compatible = "fsl,qoriq-rcpm-2.1+", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, rcpm_of_match);
+
+static struct platform_driver rcpm_driver = {
+	.driver = {
+		.name = "rcpm",
+		.of_match_table = rcpm_of_match,
+		.pm	= &rcpm_pm_ops,
+	},
+	.probe = rcpm_probe,
+};
+
+module_platform_driver(rcpm_driver);
-- 
1.7.1


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

end of thread, other threads:[~2019-10-22  9:18 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-31  3:52 [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms Ran Wang
2018-08-31  3:52 ` [PATCH 2/3] Documentation: dt: binding: fsl: update property description for RCPM Ran Wang
     [not found]   ` <5b8e8a71.1c69fb81.d966f.1ca1@mx.google.com>
2018-09-05  2:22     ` Ran Wang
2018-09-07 20:22   ` Scott Wood
2018-09-10  8:44     ` Ran Wang
2018-09-11 22:42       ` Li Yang
2018-08-31  3:52 ` [PATCH 3/3] soc: fsl: add RCPM driver Ran Wang
2018-09-05  2:57   ` Wang, Dongsheng
2018-09-05  3:21     ` Li Yang
2018-09-07  9:48       ` Ran Wang
2018-09-07 18:56         ` Li Yang
2018-09-10  3:31           ` Ran Wang
2018-09-07  9:32     ` Ran Wang
2018-09-07 20:25   ` Scott Wood
2018-09-10  9:09     ` Ran Wang
2018-09-05  3:04 ` [PATCH 1/3] soc: fsl: add Platform PM driver QorIQ platforms Wang, Dongsheng
2018-09-07  8:41   ` Ran Wang
2018-09-07 10:15     ` Wang, Dongsheng
2018-09-10  3:27       ` Ran Wang
2018-09-07 20:35 ` Scott Wood
2018-09-10  9:26   ` Ran Wang
2019-05-17  2:47 [PATCH 1/3] PM: wakeup: Add routine to help fetch wakeup source object Ran Wang
2019-05-17  2:47 ` [PATCH 3/3] soc: fsl: add RCPM driver Ran Wang
2019-10-22  7:51 [PATCH 1/3] PM: wakeup: Add routine to help fetch wakeup source object Ran Wang
2019-10-22  7:51 ` [PATCH 3/3] soc: fsl: add RCPM driver Ran Wang
2019-10-22  9:18   ` Rafael J. Wysocki

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).