linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/4] drivers: firmware: xilinx: Add firmware driver support
@ 2018-02-20 19:21 Jolly Shah
  2018-02-20 19:21 ` [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware Jolly Shah
                   ` (3 more replies)
  0 siblings, 4 replies; 24+ messages in thread
From: Jolly Shah @ 2018-02-20 19:21 UTC (permalink / raw)
  To: ard.biesheuvel, mingo, gregkh, matt, sudeep.holla, hkallweit1,
	keescook, dmitry.torokhov, michal.simek, robh+dt, mark.rutland
  Cc: rajanv, linux-arm-kernel, linux-kernel, devicetree, Jolly Shah

v5:
 - Added ATF version check support
 - Updated some functions to be static 
 - Minor function name corrections

v4:
 - Changed clock setrate/getrate API prototype to support 64 bit rate
 - Defined macros for get_node_status return values
 - Moved DT node as a child of firmware
 - Changed debugfs APIs to return data to debugfs buffer instead of dumping to kernel log
 - Minor changes to incorporate other review comments from v3 patch series

v3:
 - added some fixes to firmware-ggs.c
 - updated pinmux get/set function argument names to specify function id instead of node id
 - added new pinctrl query macros
 - incorporated review comments from v2 patch series

v2:
 - change SPDX-License-Identifier license text style
 - split patch into multiple patches
 - Updated copyrights
 - Added ABI documentation
 - incorporated logical review comments from previuos patch. Discussed below:
	https://patchwork.kernel.org/patch/10150665/

Jolly Shah (4):
  dt-bindings: firmware: Add bindings for ZynqMP firmware
  drivers: firmware: xilinx: Add ZynqMP firmware driver
  drivers: firmware: xilinx: Add sysfs interface
  drivers: firmware: xilinx: Add debugfs interface

 .../ABI/stable/sysfs-driver-zynqmp-firmware        |   50 +
 .../firmware/xilinx/xlnx,zynqmp-firmware.txt       |   24 +
 arch/arm64/Kconfig.platforms                       |    1 +
 drivers/firmware/Kconfig                           |    1 +
 drivers/firmware/Makefile                          |    1 +
 drivers/firmware/xilinx/Kconfig                    |    4 +
 drivers/firmware/xilinx/Makefile                   |    4 +
 drivers/firmware/xilinx/zynqmp/Kconfig             |   23 +
 drivers/firmware/xilinx/zynqmp/Makefile            |    5 +
 drivers/firmware/xilinx/zynqmp/firmware-debug.c    |  482 +++++++++
 drivers/firmware/xilinx/zynqmp/firmware-ggs.c      |  297 ++++++
 drivers/firmware/xilinx/zynqmp/firmware.c          | 1069 ++++++++++++++++++++
 .../linux/firmware/xilinx/zynqmp/firmware-debug.h  |   22 +
 include/linux/firmware/xilinx/zynqmp/firmware.h    |  592 +++++++++++
 14 files changed, 2575 insertions(+)
 create mode 100644 Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
 create mode 100644 Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
 create mode 100644 drivers/firmware/xilinx/Kconfig
 create mode 100644 drivers/firmware/xilinx/Makefile
 create mode 100644 drivers/firmware/xilinx/zynqmp/Kconfig
 create mode 100644 drivers/firmware/xilinx/zynqmp/Makefile
 create mode 100644 drivers/firmware/xilinx/zynqmp/firmware-debug.c
 create mode 100644 drivers/firmware/xilinx/zynqmp/firmware-ggs.c
 create mode 100644 drivers/firmware/xilinx/zynqmp/firmware.c
 create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware-debug.h
 create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware.h

-- 
2.7.4

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

* [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware
  2018-02-20 19:21 [PATCH v5 0/4] drivers: firmware: xilinx: Add firmware driver support Jolly Shah
@ 2018-02-20 19:21 ` Jolly Shah
  2018-03-01 14:15   ` Sudeep Holla
  2018-03-01 21:18   ` Rob Herring
  2018-02-20 19:21 ` [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver Jolly Shah
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 24+ messages in thread
From: Jolly Shah @ 2018-02-20 19:21 UTC (permalink / raw)
  To: ard.biesheuvel, mingo, gregkh, matt, sudeep.holla, hkallweit1,
	keescook, dmitry.torokhov, michal.simek, robh+dt, mark.rutland
  Cc: rajanv, linux-arm-kernel, linux-kernel, devicetree, Jolly Shah

Add documentation to describe Xilinx ZynqMP firmware driver
bindings. Firmware driver provides an interface to firmware
APIs. Interface APIs can be used by any driver to communicate
to PMUFW (Platform Management Unit).

Signed-off-by: Jolly Shah <jollys@xilinx.com>
Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
---
 .../firmware/xilinx/xlnx,zynqmp-firmware.txt       | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt

diff --git a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
new file mode 100644
index 0000000..99434ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
@@ -0,0 +1,24 @@
+Xilinx Zynq MPSoC Firmware Device Tree Bindings
+
+The zynqmp-firmware node describes the interface to platform firmware.
+ZynqMP has an interface to communicate with secure firmware. Firmware
+driver provides an interface to firmware APIs. Interface APIs can be
+used by any driver to communicate to PMUFW(Platform Management Unit).
+These requests include clock management, pin control, device control,
+power management service, FPGA service and other platform management
+services.
+
+Required properties:
+ - compatible:	Must contain:  "xlnx,zynqmp-firmware"
+ - method:	The method of calling the PM-API firmware layer.
+		Permitted values are:
+		  - "smc" : SMC #0, following the SMCCC
+		  - "hvc" : HVC #0, following the SMCCC
+
+Examples:
+	firmware {
+		zynqmp_firmware: zynqmp-firmware {
+			compatible = "xlnx,zynqmp-firmware";
+			method = "smc";
+		};
+	};
-- 
2.7.4

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

* [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
  2018-02-20 19:21 [PATCH v5 0/4] drivers: firmware: xilinx: Add firmware driver support Jolly Shah
  2018-02-20 19:21 ` [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware Jolly Shah
@ 2018-02-20 19:21 ` Jolly Shah
  2018-03-01 14:27   ` Sudeep Holla
  2018-03-14 13:22   ` Greg KH
  2018-02-20 19:21 ` [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface Jolly Shah
  2018-02-20 19:21 ` [PATCH v5 4/4] drivers: firmware: xilinx: Add debugfs interface Jolly Shah
  3 siblings, 2 replies; 24+ messages in thread
From: Jolly Shah @ 2018-02-20 19:21 UTC (permalink / raw)
  To: ard.biesheuvel, mingo, gregkh, matt, sudeep.holla, hkallweit1,
	keescook, dmitry.torokhov, michal.simek, robh+dt, mark.rutland
  Cc: rajanv, linux-arm-kernel, linux-kernel, devicetree, Jolly Shah

This patch is adding communication layer with firmware.
Firmware driver provides an interface to firmware APIs.
Interface APIs can be used by any driver to communicate to
PMUFW(Platform Management Unit). All requests go through ATF.

Signed-off-by: Jolly Shah <jollys@xilinx.com>
Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
---
 arch/arm64/Kconfig.platforms                    |    1 +
 drivers/firmware/Kconfig                        |    1 +
 drivers/firmware/Makefile                       |    1 +
 drivers/firmware/xilinx/Kconfig                 |    4 +
 drivers/firmware/xilinx/Makefile                |    4 +
 drivers/firmware/xilinx/zynqmp/Kconfig          |   16 +
 drivers/firmware/xilinx/zynqmp/Makefile         |    4 +
 drivers/firmware/xilinx/zynqmp/firmware.c       | 1051 +++++++++++++++++++++++
 include/linux/firmware/xilinx/zynqmp/firmware.h |  590 +++++++++++++
 9 files changed, 1672 insertions(+)
 create mode 100644 drivers/firmware/xilinx/Kconfig
 create mode 100644 drivers/firmware/xilinx/Makefile
 create mode 100644 drivers/firmware/xilinx/zynqmp/Kconfig
 create mode 100644 drivers/firmware/xilinx/zynqmp/Makefile
 create mode 100644 drivers/firmware/xilinx/zynqmp/firmware.c
 create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware.h

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index fbedbd8..6454458 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -274,6 +274,7 @@ config ARCH_ZX
 
 config ARCH_ZYNQMP
 	bool "Xilinx ZynqMP Family"
+	select ZYNQMP_FIRMWARE
 	help
 	  This enables support for Xilinx ZynqMP Family
 
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index b7c7482..f41eb0d 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -257,5 +257,6 @@ source "drivers/firmware/google/Kconfig"
 source "drivers/firmware/efi/Kconfig"
 source "drivers/firmware/meson/Kconfig"
 source "drivers/firmware/tegra/Kconfig"
+source "drivers/firmware/xilinx/Kconfig"
 
 endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index b248238..f90363e 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
 obj-$(CONFIG_EFI)		+= efi/
 obj-$(CONFIG_UEFI_CPER)		+= efi/
 obj-y				+= tegra/
+obj-y				+= xilinx/
diff --git a/drivers/firmware/xilinx/Kconfig b/drivers/firmware/xilinx/Kconfig
new file mode 100644
index 0000000..eb4cdcf
--- /dev/null
+++ b/drivers/firmware/xilinx/Kconfig
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Kconfig for Xilinx firmwares
+
+source "drivers/firmware/xilinx/zynqmp/Kconfig"
diff --git a/drivers/firmware/xilinx/Makefile b/drivers/firmware/xilinx/Makefile
new file mode 100644
index 0000000..beff5dc
--- /dev/null
+++ b/drivers/firmware/xilinx/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Makefile for Xilinx firmwares
+
+obj-$(CONFIG_ARCH_ZYNQMP) += zynqmp/
diff --git a/drivers/firmware/xilinx/zynqmp/Kconfig b/drivers/firmware/xilinx/zynqmp/Kconfig
new file mode 100644
index 0000000..5054b80
--- /dev/null
+++ b/drivers/firmware/xilinx/zynqmp/Kconfig
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Kconfig for Xilinx ZynqMP firmware
+
+menu "Zynq MPSoC Firmware Drivers"
+	depends on ARCH_ZYNQMP
+
+config ZYNQMP_FIRMWARE
+	bool "Enable Xilinx Zynq MPSoC firmware interface"
+	help
+	  Firmware interface driver is used by different to
+	  communicate with the firmware for various platform
+	  management services.
+	  Say yes to enable ZynqMP firmware interface driver.
+	  In doubt, say N
+
+endmenu
diff --git a/drivers/firmware/xilinx/zynqmp/Makefile b/drivers/firmware/xilinx/zynqmp/Makefile
new file mode 100644
index 0000000..c3ec669
--- /dev/null
+++ b/drivers/firmware/xilinx/zynqmp/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Makefile for Xilinx firmwares
+
+obj-$(CONFIG_ZYNQMP_FIRMWARE) += firmware.o
diff --git a/drivers/firmware/xilinx/zynqmp/firmware.c b/drivers/firmware/xilinx/zynqmp/firmware.c
new file mode 100644
index 0000000..6979f4b
--- /dev/null
+++ b/drivers/firmware/xilinx/zynqmp/firmware.c
@@ -0,0 +1,1051 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Xilinx Zynq MPSoC Firmware layer
+ *
+ *  Copyright (C) 2014-2018 Xilinx, Inc.
+ *
+ *  Michal Simek <michal.simek@xilinx.com>
+ *  Davorin Mista <davorin.mista@aggios.com>
+ *  Jolly Shah <jollys@xilinx.com>
+ *  Rajan Vaja <rajanv@xilinx.com>
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <linux/firmware/xilinx/zynqmp/firmware.h>
+
+/**
+ * zynqmp_pm_ret_code - Convert PMU-FW error codes to Linux error codes
+ * @ret_status:		PMUFW return code
+ *
+ * Return:		corresponding Linux error code
+ */
+static int zynqmp_pm_ret_code(u32 ret_status)
+{
+	switch (ret_status) {
+	case XST_PM_SUCCESS:
+	case XST_PM_DOUBLE_REQ:
+		return 0;
+	case XST_PM_NO_ACCESS:
+		return -EACCES;
+	case XST_PM_ABORT_SUSPEND:
+		return -ECANCELED;
+	case XST_PM_INTERNAL:
+	case XST_PM_CONFLICT:
+	case XST_PM_INVALID_NODE:
+	default:
+		return -EINVAL;
+	}
+}
+
+static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2,
+				    u32 *ret_payload)
+{
+	return -ENODEV;
+}
+
+/*
+ * PM function call wrapper
+ * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
+ */
+static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail;
+
+/**
+ * do_fw_call_smc - Call system-level platform management layer (SMC)
+ * @arg0:		Argument 0 to SMC call
+ * @arg1:		Argument 1 to SMC call
+ * @arg2:		Argument 2 to SMC call
+ * @ret_payload:	Returned value array
+ *
+ * Return:		Returns status, either success or error+reason
+ *
+ * Invoke platform management function via SMC call (no hypervisor present)
+ */
+static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2,
+				   u32 *ret_payload)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
+
+	if (ret_payload) {
+		ret_payload[0] = lower_32_bits(res.a0);
+		ret_payload[1] = upper_32_bits(res.a0);
+		ret_payload[2] = lower_32_bits(res.a1);
+		ret_payload[3] = upper_32_bits(res.a1);
+		ret_payload[4] = lower_32_bits(res.a2);
+	}
+
+	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
+}
+
+/**
+ * do_fw_call_hvc - Call system-level platform management layer (HVC)
+ * @arg0:		Argument 0 to HVC call
+ * @arg1:		Argument 1 to HVC call
+ * @arg2:		Argument 2 to HVC call
+ * @ret_payload:	Returned value array
+ *
+ * Return:		Returns status, either success or error+reason
+ *
+ * Invoke platform management function via HVC
+ * HVC-based for communication through hypervisor
+ * (no direct communication with ATF)
+ */
+static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2,
+				   u32 *ret_payload)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
+
+	if (ret_payload) {
+		ret_payload[0] = lower_32_bits(res.a0);
+		ret_payload[1] = upper_32_bits(res.a0);
+		ret_payload[2] = lower_32_bits(res.a1);
+		ret_payload[3] = upper_32_bits(res.a1);
+		ret_payload[4] = lower_32_bits(res.a2);
+	}
+
+	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
+}
+
+/**
+ * zynqmp_pm_invoke_fn - Invoke the system-level platform management layer
+ *			 caller function depending on the configuration
+ * @pm_api_id:		Requested PM-API call
+ * @arg0:		Argument 0 to requested PM-API call
+ * @arg1:		Argument 1 to requested PM-API call
+ * @arg2:		Argument 2 to requested PM-API call
+ * @arg3:		Argument 3 to requested PM-API call
+ * @ret_payload:	Returned value array
+ *
+ * Return:		Returns status, either success or error+reason
+ *
+ * Invoke platform management function for SMC or HVC call, depending on
+ * configuration
+ * Following SMC Calling Convention (SMCCC) for SMC64:
+ * Pm Function Identifier,
+ * PM_SIP_SVC + PM_API_ID =
+ *	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
+ *	((SMC_64) << FUNCID_CC_SHIFT)
+ *	((SIP_START) << FUNCID_OEN_SHIFT)
+ *	((PM_API_ID) & FUNCID_NUM_MASK))
+ *
+ * PM_SIP_SVC	- Registered ZynqMP SIP Service Call
+ * PM_API_ID	- Platform Management API ID
+ */
+int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
+			u32 arg2, u32 arg3, u32 *ret_payload)
+{
+	/*
+	 * Added SIP service call Function Identifier
+	 * Make sure to stay in x0 register
+	 */
+	u64 smc_arg[4];
+
+	smc_arg[0] = PM_SIP_SVC | pm_api_id;
+	smc_arg[1] = ((u64)arg1 << 32) | arg0;
+	smc_arg[2] = ((u64)arg3 << 32) | arg2;
+
+	return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload);
+}
+
+static u32 pm_api_version;
+static u32 pm_tz_version;
+
+/**
+ * zynqmp_pm_get_api_version - Get version number of PMU PM firmware
+ * @version:	Returned version value
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_get_api_version(u32 *version)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!version)
+		return -EINVAL;
+
+	/* Check is PM API version already verified */
+	if (pm_api_version > 0) {
+		*version = pm_api_version;
+		return 0;
+	}
+	ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload);
+	*version = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_get_trustzone_version - Get secure trustzone firmware version
+ * @version:	Returned version value
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_get_trustzone_version(u32 *version)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!version)
+		return -EINVAL;
+
+	/* Check is PM trustzone version already verified */
+	if (pm_tz_version > 0) {
+		*version = pm_tz_version;
+		return 0;
+	}
+	ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0,
+				  0, 0, ret_payload);
+	*version = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_get_chipid - Get silicon ID registers
+ * @idcode:	IDCODE register
+ * @version:	version register
+ *
+ * Return:	Returns the status of the operation and the idcode and version
+ *		registers in @idcode and @version.
+ */
+static int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!idcode || !version)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
+	*idcode = ret_payload[1];
+	*version = ret_payload[2];
+
+	return ret;
+}
+
+/**
+ * get_set_conduit_method - Choose SMC or HVC based communication
+ * @np:		Pointer to the device_node structure
+ *
+ * Use SMC or HVC-based functions to communicate with EL2/EL3
+ *
+ * Return:	Returns 0 on success or error code
+ */
+static int get_set_conduit_method(struct device_node *np)
+{
+	const char *method;
+
+	if (of_property_read_string(np, "method", &method)) {
+		pr_warn("%s missing \"method\" property\n", __func__);
+		return -ENXIO;
+	}
+
+	if (!strcmp("hvc", method)) {
+		do_fw_call = do_fw_call_hvc;
+	} else if (!strcmp("smc", method)) {
+		do_fw_call = do_fw_call_smc;
+	} else {
+		pr_warn("%s Invalid \"method\" property: %s\n",
+			__func__, method);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
+ * @reset:		Reset to be configured
+ * @assert_flag:	Flag stating should reset be asserted (1) or
+ *			released (0)
+ *
+ * Return:		Returns status, either success or error+reason
+ */
+static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
+				  const enum zynqmp_pm_reset_action assert_flag)
+{
+	return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_reset_get_status - Get status of the reset
+ * @reset:	Reset whose status should be returned
+ * @status:	Returned status
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
+				      u32 *status)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!status)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
+				  0, 0, ret_payload);
+	*status = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_fpga_load - Perform the fpga load
+ * @address:	Address to write to
+ * @size:	pl bitstream size
+ * @flags:
+ *	BIT(0) - Bit-stream type.
+ *		 0 - Full Bit-stream.
+ *		 1 - Partial Bit-stream.
+ *	BIT(1) - Authentication.
+ *		 1 - Enable.
+ *		 0 - Disable.
+ *	BIT(2) - Encryption.
+ *		 1 - Enable.
+ *		 0 - Disable.
+ * NOTE -
+ *	The current implementation supports only Full Bit-stream.
+ *
+ * This function provides access to xilfpga library to transfer
+ * the required bitstream into PL.
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_fpga_load(const u64 address, const u32 size,
+			       const u32 flags)
+{
+	return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, (u32)address,
+				   ((u32)(address >> 32)), size, flags, NULL);
+}
+
+/**
+ * zynqmp_pm_fpga_get_status - Read value from PCAP status register
+ * @value:	Value to read
+ *
+ * This function provides access to the xilfpga library to get
+ * the PCAP status
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_fpga_get_status(u32 *value)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!value)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
+	*value = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_request_suspend - PM call to request for another PU or subsystem to
+ *					be suspended gracefully.
+ * @node:	Node ID of the targeted PU or subsystem
+ * @ack:	Flag to specify whether acknowledge is requested
+ * @latency:	Requested wakeup latency (not supported)
+ * @state:	Requested state (not supported)
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_request_suspend(const u32 node,
+				     const enum zynqmp_pm_request_ack ack,
+				     const u32 latency,
+				     const u32 state)
+{
+	return zynqmp_pm_invoke_fn(PM_REQUEST_SUSPEND, node, ack,
+				   latency, state, NULL);
+}
+
+/**
+ * zynqmp_pm_force_powerdown - PM call to request for another PU or subsystem to
+ *				be powered down forcefully
+ * @target:	Node ID of the targeted PU or subsystem
+ * @ack:	Flag to specify whether acknowledge is requested
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_force_powerdown(const u32 target,
+				     const enum zynqmp_pm_request_ack ack)
+{
+	return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, target, ack, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_request_wakeup - PM call to wake up selected master or subsystem
+ * @node:	Node ID of the master or subsystem
+ * @set_addr:	Specifies whether the address argument is relevant
+ * @address:	Address from which to resume when woken up
+ * @ack:	Flag to specify whether acknowledge requested
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_request_wakeup(const u32 node,
+				    const bool set_addr,
+				    const u64 address,
+				    const enum zynqmp_pm_request_ack ack)
+{
+	/* set_addr flag is encoded into 1st bit of address */
+	return zynqmp_pm_invoke_fn(PM_REQUEST_WAKEUP, node, address | set_addr,
+				   address >> 32, ack, NULL);
+}
+
+/**
+ * zynqmp_pm_set_wakeup_source - PM call to specify the wakeup source
+ *					while suspended
+ * @target:	Node ID of the targeted PU or subsystem
+ * @wakeup_node:Node ID of the wakeup peripheral
+ * @enable:	Enable or disable the specified peripheral as wake source
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_wakeup_source(const u32 target,
+				       const u32 wakeup_node,
+				       const u32 enable)
+{
+	return zynqmp_pm_invoke_fn(PM_SET_WAKEUP_SOURCE, target,
+				   wakeup_node, enable, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
+ * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
+ * @subtype:	Specifies which system should be restarted or shut down
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
+{
+	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_request_node - PM call to request a node with specific capabilities
+ * @node:		Node ID of the slave
+ * @capabilities:	Requested capabilities of the slave
+ * @qos:		Quality of service (not supported)
+ * @ack:		Flag to specify whether acknowledge is requested
+ *
+ * Return:		Returns status, either success or error+reason
+ */
+static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
+				  const u32 qos,
+				  const enum zynqmp_pm_request_ack ack)
+{
+	return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
+				   qos, ack, NULL);
+}
+
+/**
+ * zynqmp_pm_release_node - PM call to release a node
+ * @node:	Node ID of the slave
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_release_node(const u32 node)
+{
+	return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_set_requirement - PM call to set requirement for PM slaves
+ * @node:		Node ID of the slave
+ * @capabilities:	Requested capabilities of the slave
+ * @qos:		Quality of service (not supported)
+ * @ack:		Flag to specify whether acknowledge is requested
+ *
+ * This API function is to be used for slaves a PU already has requested
+ *
+ * Return:		Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
+				     const u32 qos,
+				     const enum zynqmp_pm_request_ack ack)
+{
+	return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
+				   qos, ack, NULL);
+}
+
+/**
+ * zynqmp_pm_set_max_latency - PM call to set wakeup latency requirements
+ * @node:	Node ID of the slave
+ * @latency:	Requested maximum wakeup latency
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_max_latency(const u32 node, const u32 latency)
+{
+	return zynqmp_pm_invoke_fn(PM_SET_MAX_LATENCY, node, latency,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_set_configuration - PM call to set system configuration
+ * @physical_addr:	Physical 32-bit address of data structure in memory
+ *
+ * Return:		Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_configuration(const u32 physical_addr)
+{
+	return zynqmp_pm_invoke_fn(PM_SET_CONFIGURATION, physical_addr, 0,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_get_node_status - PM call to request a node's current power state
+ * @node:		ID of the component or sub-system in question
+ * @status:		Current operating state of the requested node
+ * @requirements:	Current requirements asserted on the node,
+ *			used for slave nodes only.
+ * @usage:		Usage information, used for slave nodes only:
+ *			PM_USAGE_NO_MASTER	- No master is currently using
+ *						  the node
+ *			PM_USAGE_CURRENT_MASTER	- Only requesting master is
+ *						  currently using the node
+ *			PM_USAGE_OTHER_MASTER	- Only other masters are
+ *						  currently using the node
+ *			PM_USAGE_BOTH_MASTERS	- Both the current and at least
+ *						  one other master is currently
+ *						  using the node
+ *
+ * Return:		Returns status, either success or error+reason
+ */
+static int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
+				     u32 *const requirements, u32 *const usage)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!status)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_GET_NODE_STATUS, node, 0, 0,
+				  0, ret_payload);
+	if (ret_payload[0] == XST_PM_SUCCESS) {
+		*status = ret_payload[1];
+		if (requirements)
+			*requirements = ret_payload[2];
+		if (usage)
+			*usage = ret_payload[3];
+	}
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_get_operating_characteristic - PM call to request operating
+ *						characteristic information
+ * @node:	Node ID of the slave
+ * @type:	Type of the operating characteristic requested
+ * @result:	Used to return the requsted operating characteristic
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_get_operating_characteristic(const u32 node,
+		const enum zynqmp_pm_opchar_type type,
+		u32 *const result)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!result)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_GET_OPERATING_CHARACTERISTIC,
+				  node, type, 0, 0, ret_payload);
+	if (ret_payload[0] == XST_PM_SUCCESS)
+		*result = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_init_finalize - PM call to informi firmware that the caller master
+ *				has initialized its own power management
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_init_finalize(void)
+{
+	return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_set_suspend_mode	- Set system suspend mode
+ *
+ * @mode:	Mode to set for system suspend
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_suspend_mode(u32 mode)
+{
+	return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
+ * @address:	Address of the data/ Address of output buffer where
+ *		hash should be stored.
+ * @size:	Size of the data.
+ * @flags:
+ *	BIT(0) - for initializing csudma driver and SHA3(Here address
+ *		 and size inputs can be NULL).
+ *	BIT(1) - to call Sha3_Update API which can be called multiple
+ *		 times when data is not contiguous.
+ *	BIT(2) - to get final hash of the whole updated data.
+ *		 Hash will be overwritten at provided address with
+ *		 48 bytes.
+ *
+ * Return:	Returns status, either success or error code.
+ */
+static int zynqmp_pm_sha_hash(const u64 address, const u32 size,
+			      const u32 flags)
+{
+	u32 lower_32_bits = (u32)address;
+	u32 upper_32_bits = (u32)(address >> 32);
+
+	return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_32_bits, lower_32_bits,
+				   size, flags, NULL);
+}
+
+/**
+ * zynqmp_pm_rsa - Access RSA hardware to encrypt/decrypt the data with RSA.
+ * @address:	Address of the data
+ * @size:	Size of the data.
+ * @flags:
+ *		BIT(0) - Encryption/Decryption
+ *			 0 - RSA decryption with private key
+ *			 1 - RSA encryption with public key.
+ *
+ * Return:	Returns status, either success or error code.
+ */
+static int zynqmp_pm_rsa(const u64 address, const u32 size, const u32 flags)
+{
+	u32 lower_32_bits = (u32)address;
+	u32 upper_32_bits = (u32)(address >> 32);
+
+	return zynqmp_pm_invoke_fn(PM_SECURE_RSA, upper_32_bits, lower_32_bits,
+				   size, flags, NULL);
+}
+
+/**
+ * zynqmp_pm_pinctrl_request - Request Pin from firmware
+ * @pin:	Pin number to request
+ *
+ * This function requests pin from firmware.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_request(const u32 pin)
+{
+	return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
+ * @pin:	Pin number to release
+ *
+ * This function release pin from firmware.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_release(const u32 pin)
+{
+	return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin
+ * @pin:	Pin number
+ * @id:		Buffer to store function ID
+ *
+ * This function provides the function currently set for the given pin.
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!id)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0,
+				  0, 0, ret_payload);
+	*id = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
+ * @pin:	Pin number
+ * @id:		Function ID to set
+ *
+ * This function sets requested function for the given pin.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
+{
+	return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
+ * @pin:	Pin number
+ * @param:	Parameter to get
+ * @value:	Buffer to store parameter value
+ *
+ * This function gets requested configuration parameter for the given pin.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
+					u32 *value)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!value)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param,
+				  0, 0, ret_payload);
+	*value = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
+ * @pin:	Pin number
+ * @param:	Parameter to set
+ * @value:	Parameter value to set
+ *
+ * This function sets requested configuration parameter for the given pin.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
+					u32 value)
+{
+	return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin,
+				   param, value, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_ioctl - PM IOCTL API for device control and configs
+ * @node_id:	Node ID of the device
+ * @ioctl_id:	ID of the requested IOCTL
+ * @arg1:	Argument 1 to requested IOCTL call
+ * @arg2:	Argument 2 to requested IOCTL call
+ * @out:	Returned output value
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2,
+			   u32 *out)
+{
+	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, ioctl_id,
+				   arg1, arg2, out);
+}
+
+static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
+{
+	return zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1,
+				   qdata.arg2, qdata.arg3, out);
+}
+
+/**
+ * zynqmp_pm_clock_enable - Enable the clock for given id
+ * @clock_id:	ID of the clock to be enabled
+ *
+ * This function is used by master to enable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_clock_enable(u32 clock_id)
+{
+	return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_clock_disable - Disable the clock for given id
+ * @clock_id:	ID of the clock to be disable
+ *
+ * This function is used by master to disable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_clock_disable(u32 clock_id)
+{
+	return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_clock_getstate - Get the clock state for given id
+ * @clock_id:	ID of the clock to be queried
+ * @state:	1/0 (Enabled/Disabled)
+ *
+ * This function is used by master to get the state of clock
+ * including peripherals and PLL clocks.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0,
+				  0, 0, ret_payload);
+	*state = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_clock_setdivider - Set the clock divider for given id
+ * @clock_id:	ID of the clock
+ * @divider:	divider value.
+ *
+ * This function is used by master to set divider for any clock
+ * to achieve desired rate.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
+{
+	return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_clock_getdivider - Get the clock divider for given id
+ * @clock_id:	ID of the clock
+ * @divider:	divider value.
+ *
+ * This function is used by master to get divider values
+ * for any clock.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0,
+				  0, 0, ret_payload);
+	*divider = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_clock_setrate - Set the clock rate for given id
+ * @clock_id:	ID of the clock
+ * @rate:	rate value in hz
+ *
+ * This function is used by master to set rate for any clock.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
+{
+	return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
+				   rate & 0xFFFFFFFF,
+				   (rate >> 32) & 0xFFFFFFFF,
+				   0, NULL);
+}
+
+/**
+ * zynqmp_pm_clock_getrate - Get the clock rate for given id
+ * @clock_id:	ID of the clock
+ * @rate:	rate value in hz
+ *
+ * This function is used by master to get rate
+ * for any clock.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0,
+				  0, 0, ret_payload);
+	*rate = ((u64)ret_payload[2] << 32) | ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_clock_setparent - Set the clock parent for given id
+ * @clock_id:	ID of the clock
+ * @parent_id:	parent id
+ *
+ * This function is used by master to set parent for any clock.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
+{
+	return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
+				   parent_id, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_clock_getparent - Get the clock parent for given id
+ * @clock_id:	ID of the clock
+ * @parent_id:	parent id
+ *
+ * This function is used by master to get parent index
+ * for any clock.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0,
+				  0, 0, ret_payload);
+	*parent_id = ret_payload[1];
+
+	return ret;
+}
+
+static const struct zynqmp_eemi_ops eemi_ops = {
+	.get_api_version = zynqmp_pm_get_api_version,
+	.get_chipid = zynqmp_pm_get_chipid,
+	.reset_assert = zynqmp_pm_reset_assert,
+	.reset_get_status = zynqmp_pm_reset_get_status,
+	.fpga_load = zynqmp_pm_fpga_load,
+	.fpga_get_status = zynqmp_pm_fpga_get_status,
+	.sha_hash = zynqmp_pm_sha_hash,
+	.rsa = zynqmp_pm_rsa,
+	.request_suspend = zynqmp_pm_request_suspend,
+	.force_powerdown = zynqmp_pm_force_powerdown,
+	.request_wakeup = zynqmp_pm_request_wakeup,
+	.set_wakeup_source = zynqmp_pm_set_wakeup_source,
+	.system_shutdown = zynqmp_pm_system_shutdown,
+	.request_node = zynqmp_pm_request_node,
+	.release_node = zynqmp_pm_release_node,
+	.set_requirement = zynqmp_pm_set_requirement,
+	.set_max_latency = zynqmp_pm_set_max_latency,
+	.set_configuration = zynqmp_pm_set_configuration,
+	.get_node_status = zynqmp_pm_get_node_status,
+	.get_operating_characteristic = zynqmp_pm_get_operating_characteristic,
+	.init_finalize = zynqmp_pm_init_finalize,
+	.set_suspend_mode = zynqmp_pm_set_suspend_mode,
+	.ioctl = zynqmp_pm_ioctl,
+	.query_data = zynqmp_pm_query_data,
+	.pinctrl_request = zynqmp_pm_pinctrl_request,
+	.pinctrl_release = zynqmp_pm_pinctrl_release,
+	.pinctrl_get_function = zynqmp_pm_pinctrl_get_function,
+	.pinctrl_set_function = zynqmp_pm_pinctrl_set_function,
+	.pinctrl_get_config = zynqmp_pm_pinctrl_get_config,
+	.pinctrl_set_config = zynqmp_pm_pinctrl_set_config,
+	.clock_enable = zynqmp_pm_clock_enable,
+	.clock_disable = zynqmp_pm_clock_disable,
+	.clock_getstate = zynqmp_pm_clock_getstate,
+	.clock_setdivider = zynqmp_pm_clock_setdivider,
+	.clock_getdivider = zynqmp_pm_clock_getdivider,
+	.clock_setrate = zynqmp_pm_clock_setrate,
+	.clock_getrate = zynqmp_pm_clock_getrate,
+	.clock_setparent = zynqmp_pm_clock_setparent,
+	.clock_getparent = zynqmp_pm_clock_getparent,
+};
+
+/**
+ * zynqmp_pm_get_eemi_ops - Get eemi ops functions
+ *
+ * Return:	- pointer of eemi_ops structure
+ */
+const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void)
+{
+	return &eemi_ops;
+}
+EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops);
+
+static int __init zynqmp_plat_init(void)
+{
+	struct device_node *np;
+	int ret = 0;
+
+	np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp");
+	if (!np)
+		return 0;
+	of_node_put(np);
+
+	/* We're running on a ZynqMP machine, the PM node is mandatory. */
+	np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp-firmware");
+	if (!np) {
+		pr_warn("%s: pm node not found\n", __func__);
+		return -ENXIO;
+	}
+
+	ret = get_set_conduit_method(np);
+	if (ret) {
+		of_node_put(np);
+		return ret;
+	}
+
+	/* Check PM API version number */
+	zynqmp_pm_get_api_version(&pm_api_version);
+	if (pm_api_version < ZYNQMP_PM_VERSION) {
+		panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
+		      __func__,
+		      ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
+		      pm_api_version >> 16, pm_api_version & 0xFFFF);
+	}
+
+	pr_info("%s Platform Management API v%d.%d\n", __func__,
+		pm_api_version >> 16, pm_api_version & 0xFFFF);
+
+	/* Check trustzone version number */
+	ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
+	if (ret)
+		panic("Legacy trustzone found without version support\n");
+
+	if (pm_tz_version < ZYNQMP_TZ_VERSION)
+		panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
+		      __func__,
+		      ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
+		      pm_tz_version >> 16, pm_tz_version & 0xFFFF);
+
+	pr_info("%s Trustzone version v%d.%d\n", __func__,
+		pm_tz_version >> 16, pm_tz_version & 0xFFFF);
+
+	of_node_put(np);
+
+	return ret;
+}
+early_initcall(zynqmp_plat_init);
diff --git a/include/linux/firmware/xilinx/zynqmp/firmware.h b/include/linux/firmware/xilinx/zynqmp/firmware.h
new file mode 100644
index 0000000..859d809
--- /dev/null
+++ b/include/linux/firmware/xilinx/zynqmp/firmware.h
@@ -0,0 +1,590 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Xilinx Zynq MPSoC Firmware layer
+ *
+ *  Copyright (C) 2014-2018 Xilinx
+ *
+ *  Michal Simek <michal.simek@xilinx.com>
+ *  Davorin Mista <davorin.mista@aggios.com>
+ *  Jolly Shah <jollys@xilinx.com>
+ *  Rajan Vaja <rajanv@xilinx.com>
+ */
+
+#ifndef __SOC_ZYNQMP_FIRMWARE_H__
+#define __SOC_ZYNQMP_FIRMWARE_H__
+
+#include <linux/device.h>
+
+#define ZYNQMP_PM_VERSION_MAJOR	1
+#define ZYNQMP_PM_VERSION_MINOR	0
+
+#define ZYNQMP_PM_VERSION	((ZYNQMP_PM_VERSION_MAJOR << 16) | \
+					ZYNQMP_PM_VERSION_MINOR)
+
+#define ZYNQMP_TZ_VERSION_MAJOR	1
+#define ZYNQMP_TZ_VERSION_MINOR	0
+
+#define ZYNQMP_TZ_VERSION	((ZYNQMP_TZ_VERSION_MAJOR << 16) | \
+					ZYNQMP_TZ_VERSION_MINOR)
+
+#define ZYNQMP_PM_MAX_LATENCY	(~0U)
+#define ZYNQMP_PM_MAX_QOS	100U
+
+/* SMC SIP service Call Function Identifier Prefix */
+#define PM_SIP_SVC			0xC2000000
+#define PM_SET_SUSPEND_MODE		0xa02
+#define PM_GET_TRUSTZONE_VERSION	0xa03
+
+/* Number of 32bits values in payload */
+#define PAYLOAD_ARG_CNT	5U
+
+/* Number of arguments for a callback */
+#define CB_ARG_CNT	4
+
+/* Payload size (consists of callback API ID + arguments) */
+#define CB_PAYLOAD_SIZE	(CB_ARG_CNT + 1)
+
+/* Usage status, returned by PmGetNodeStatus */
+#define PM_USAGE_NO_MASTER			0x0U
+#define PM_USAGE_CURRENT_MASTER			0x1U
+#define PM_USAGE_OTHER_MASTER			0x2U
+#define PM_USAGE_BOTH_MASTERS			(PM_USAGE_CURRENT_MASTER | \
+						 PM_USAGE_OTHER_MASTER)
+
+/* Global general storage register base address */
+#define GGS_BASEADDR	(0xFFD80030U)
+#define GSS_NUM_REGS	(4)
+
+/* Persistent global general storage register base address */
+#define PGGS_BASEADDR	(0xFFD80050U)
+#define PGSS_NUM_REGS	(4)
+
+/* Capabilities for RAM */
+#define	ZYNQMP_PM_CAPABILITY_ACCESS	0x1U
+#define	ZYNQMP_PM_CAPABILITY_CONTEXT	0x2U
+#define	ZYNQMP_PM_CAPABILITY_WAKEUP	0x4U
+#define	ZYNQMP_PM_CAPABILITY_POWER	0x8U
+
+/* Clock APIs payload parameters */
+#define CLK_GET_NAME_RESP_LEN				16
+#define CLK_GET_TOPOLOGY_RESP_WORDS			3
+#define CLK_GET_FIXEDFACTOR_RESP_WORDS			2
+#define CLK_GET_PARENTS_RESP_WORDS			3
+#define CLK_GET_ATTR_RESP_WORDS				1
+
+enum pm_api_id {
+	/* Miscellaneous API functions: */
+	PM_GET_API_VERSION = 1,
+	PM_SET_CONFIGURATION,
+	PM_GET_NODE_STATUS,
+	PM_GET_OPERATING_CHARACTERISTIC,
+	PM_REGISTER_NOTIFIER,
+	/* API for suspending of PUs: */
+	PM_REQUEST_SUSPEND,
+	PM_SELF_SUSPEND,
+	PM_FORCE_POWERDOWN,
+	PM_ABORT_SUSPEND,
+	PM_REQUEST_WAKEUP,
+	PM_SET_WAKEUP_SOURCE,
+	PM_SYSTEM_SHUTDOWN,
+	/* API for managing PM slaves: */
+	PM_REQUEST_NODE,
+	PM_RELEASE_NODE,
+	PM_SET_REQUIREMENT,
+	PM_SET_MAX_LATENCY,
+	/* Direct control API functions: */
+	PM_RESET_ASSERT,
+	PM_RESET_GET_STATUS,
+	PM_MMIO_WRITE,
+	PM_MMIO_READ,
+	PM_PM_INIT_FINALIZE,
+	PM_FPGA_LOAD,
+	PM_FPGA_GET_STATUS,
+	PM_GET_CHIPID,
+	/* ID 25 is been used by U-boot to process secure boot images */
+	/* Secure library generic API functions */
+	PM_SECURE_SHA = 26,
+	PM_SECURE_RSA,
+	/* Pin control API functions */
+	PM_PINCTRL_REQUEST,
+	PM_PINCTRL_RELEASE,
+	PM_PINCTRL_GET_FUNCTION,
+	PM_PINCTRL_SET_FUNCTION,
+	PM_PINCTRL_CONFIG_PARAM_GET,
+	PM_PINCTRL_CONFIG_PARAM_SET,
+	/* PM IOCTL API */
+	PM_IOCTL,
+	/* API to query information from firmware */
+	PM_QUERY_DATA,
+	/* Clock control API functions */
+	PM_CLOCK_ENABLE,
+	PM_CLOCK_DISABLE,
+	PM_CLOCK_GETSTATE,
+	PM_CLOCK_SETDIVIDER,
+	PM_CLOCK_GETDIVIDER,
+	PM_CLOCK_SETRATE,
+	PM_CLOCK_GETRATE,
+	PM_CLOCK_SETPARENT,
+	PM_CLOCK_GETPARENT,
+};
+
+/* PMU-FW return status codes */
+enum pm_ret_status {
+	XST_PM_SUCCESS = 0,
+	XST_PM_INTERNAL = 2000,
+	XST_PM_CONFLICT,
+	XST_PM_NO_ACCESS,
+	XST_PM_INVALID_NODE,
+	XST_PM_DOUBLE_REQ,
+	XST_PM_ABORT_SUSPEND,
+};
+
+enum zynqmp_pm_reset_action {
+	PM_RESET_ACTION_RELEASE,
+	PM_RESET_ACTION_ASSERT,
+	PM_RESET_ACTION_PULSE,
+};
+
+enum zynqmp_pm_reset {
+	ZYNQMP_PM_RESET_START = 999,
+	ZYNQMP_PM_RESET_PCIE_CFG,
+	ZYNQMP_PM_RESET_PCIE_BRIDGE,
+	ZYNQMP_PM_RESET_PCIE_CTRL,
+	ZYNQMP_PM_RESET_DP,
+	ZYNQMP_PM_RESET_SWDT_CRF,
+	ZYNQMP_PM_RESET_AFI_FM5,
+	ZYNQMP_PM_RESET_AFI_FM4,
+	ZYNQMP_PM_RESET_AFI_FM3,
+	ZYNQMP_PM_RESET_AFI_FM2,
+	ZYNQMP_PM_RESET_AFI_FM1,
+	ZYNQMP_PM_RESET_AFI_FM0,
+	ZYNQMP_PM_RESET_GDMA,
+	ZYNQMP_PM_RESET_GPU_PP1,
+	ZYNQMP_PM_RESET_GPU_PP0,
+	ZYNQMP_PM_RESET_GPU,
+	ZYNQMP_PM_RESET_GT,
+	ZYNQMP_PM_RESET_SATA,
+	ZYNQMP_PM_RESET_ACPU3_PWRON,
+	ZYNQMP_PM_RESET_ACPU2_PWRON,
+	ZYNQMP_PM_RESET_ACPU1_PWRON,
+	ZYNQMP_PM_RESET_ACPU0_PWRON,
+	ZYNQMP_PM_RESET_APU_L2,
+	ZYNQMP_PM_RESET_ACPU3,
+	ZYNQMP_PM_RESET_ACPU2,
+	ZYNQMP_PM_RESET_ACPU1,
+	ZYNQMP_PM_RESET_ACPU0,
+	ZYNQMP_PM_RESET_DDR,
+	ZYNQMP_PM_RESET_APM_FPD,
+	ZYNQMP_PM_RESET_SOFT,
+	ZYNQMP_PM_RESET_GEM0,
+	ZYNQMP_PM_RESET_GEM1,
+	ZYNQMP_PM_RESET_GEM2,
+	ZYNQMP_PM_RESET_GEM3,
+	ZYNQMP_PM_RESET_QSPI,
+	ZYNQMP_PM_RESET_UART0,
+	ZYNQMP_PM_RESET_UART1,
+	ZYNQMP_PM_RESET_SPI0,
+	ZYNQMP_PM_RESET_SPI1,
+	ZYNQMP_PM_RESET_SDIO0,
+	ZYNQMP_PM_RESET_SDIO1,
+	ZYNQMP_PM_RESET_CAN0,
+	ZYNQMP_PM_RESET_CAN1,
+	ZYNQMP_PM_RESET_I2C0,
+	ZYNQMP_PM_RESET_I2C1,
+	ZYNQMP_PM_RESET_TTC0,
+	ZYNQMP_PM_RESET_TTC1,
+	ZYNQMP_PM_RESET_TTC2,
+	ZYNQMP_PM_RESET_TTC3,
+	ZYNQMP_PM_RESET_SWDT_CRL,
+	ZYNQMP_PM_RESET_NAND,
+	ZYNQMP_PM_RESET_ADMA,
+	ZYNQMP_PM_RESET_GPIO,
+	ZYNQMP_PM_RESET_IOU_CC,
+	ZYNQMP_PM_RESET_TIMESTAMP,
+	ZYNQMP_PM_RESET_RPU_R50,
+	ZYNQMP_PM_RESET_RPU_R51,
+	ZYNQMP_PM_RESET_RPU_AMBA,
+	ZYNQMP_PM_RESET_OCM,
+	ZYNQMP_PM_RESET_RPU_PGE,
+	ZYNQMP_PM_RESET_USB0_CORERESET,
+	ZYNQMP_PM_RESET_USB1_CORERESET,
+	ZYNQMP_PM_RESET_USB0_HIBERRESET,
+	ZYNQMP_PM_RESET_USB1_HIBERRESET,
+	ZYNQMP_PM_RESET_USB0_APB,
+	ZYNQMP_PM_RESET_USB1_APB,
+	ZYNQMP_PM_RESET_IPI,
+	ZYNQMP_PM_RESET_APM_LPD,
+	ZYNQMP_PM_RESET_RTC,
+	ZYNQMP_PM_RESET_SYSMON,
+	ZYNQMP_PM_RESET_AFI_FM6,
+	ZYNQMP_PM_RESET_LPD_SWDT,
+	ZYNQMP_PM_RESET_FPD,
+	ZYNQMP_PM_RESET_RPU_DBG1,
+	ZYNQMP_PM_RESET_RPU_DBG0,
+	ZYNQMP_PM_RESET_DBG_LPD,
+	ZYNQMP_PM_RESET_DBG_FPD,
+	ZYNQMP_PM_RESET_APLL,
+	ZYNQMP_PM_RESET_DPLL,
+	ZYNQMP_PM_RESET_VPLL,
+	ZYNQMP_PM_RESET_IOPLL,
+	ZYNQMP_PM_RESET_RPLL,
+	ZYNQMP_PM_RESET_GPO3_PL_0,
+	ZYNQMP_PM_RESET_GPO3_PL_1,
+	ZYNQMP_PM_RESET_GPO3_PL_2,
+	ZYNQMP_PM_RESET_GPO3_PL_3,
+	ZYNQMP_PM_RESET_GPO3_PL_4,
+	ZYNQMP_PM_RESET_GPO3_PL_5,
+	ZYNQMP_PM_RESET_GPO3_PL_6,
+	ZYNQMP_PM_RESET_GPO3_PL_7,
+	ZYNQMP_PM_RESET_GPO3_PL_8,
+	ZYNQMP_PM_RESET_GPO3_PL_9,
+	ZYNQMP_PM_RESET_GPO3_PL_10,
+	ZYNQMP_PM_RESET_GPO3_PL_11,
+	ZYNQMP_PM_RESET_GPO3_PL_12,
+	ZYNQMP_PM_RESET_GPO3_PL_13,
+	ZYNQMP_PM_RESET_GPO3_PL_14,
+	ZYNQMP_PM_RESET_GPO3_PL_15,
+	ZYNQMP_PM_RESET_GPO3_PL_16,
+	ZYNQMP_PM_RESET_GPO3_PL_17,
+	ZYNQMP_PM_RESET_GPO3_PL_18,
+	ZYNQMP_PM_RESET_GPO3_PL_19,
+	ZYNQMP_PM_RESET_GPO3_PL_20,
+	ZYNQMP_PM_RESET_GPO3_PL_21,
+	ZYNQMP_PM_RESET_GPO3_PL_22,
+	ZYNQMP_PM_RESET_GPO3_PL_23,
+	ZYNQMP_PM_RESET_GPO3_PL_24,
+	ZYNQMP_PM_RESET_GPO3_PL_25,
+	ZYNQMP_PM_RESET_GPO3_PL_26,
+	ZYNQMP_PM_RESET_GPO3_PL_27,
+	ZYNQMP_PM_RESET_GPO3_PL_28,
+	ZYNQMP_PM_RESET_GPO3_PL_29,
+	ZYNQMP_PM_RESET_GPO3_PL_30,
+	ZYNQMP_PM_RESET_GPO3_PL_31,
+	ZYNQMP_PM_RESET_RPU_LS,
+	ZYNQMP_PM_RESET_PS_ONLY,
+	ZYNQMP_PM_RESET_PL,
+	ZYNQMP_PM_RESET_END
+};
+
+enum zynqmp_pm_request_ack {
+	ZYNQMP_PM_REQUEST_ACK_NO = 1,
+	ZYNQMP_PM_REQUEST_ACK_BLOCKING,
+	ZYNQMP_PM_REQUEST_ACK_NON_BLOCKING,
+};
+
+enum zynqmp_pm_abort_reason {
+	ZYNQMP_PM_ABORT_REASON_WAKEUP_EVENT = 100,
+	ZYNQMP_PM_ABORT_REASON_POWER_UNIT_BUSY,
+	ZYNQMP_PM_ABORT_REASON_NO_POWERDOWN,
+	ZYNQMP_PM_ABORT_REASON_UNKNOWN,
+};
+
+enum zynqmp_pm_suspend_reason {
+	ZYNQMP_PM_SUSPEND_REASON_POWER_UNIT_REQUEST = 201,
+	ZYNQMP_PM_SUSPEND_REASON_ALERT,
+	ZYNQMP_PM_SUSPEND_REASON_SYSTEM_SHUTDOWN,
+};
+
+enum zynqmp_pm_ram_state {
+	ZYNQMP_PM_RAM_STATE_OFF = 1,
+	ZYNQMP_PM_RAM_STATE_RETENTION,
+	ZYNQMP_PM_RAM_STATE_ON,
+};
+
+enum zynqmp_pm_opchar_type {
+	ZYNQMP_PM_OPERATING_CHARACTERISTIC_POWER = 1,
+	ZYNQMP_PM_OPERATING_CHARACTERISTIC_ENERGY,
+	ZYNQMP_PM_OPERATING_CHARACTERISTIC_TEMPERATURE,
+};
+
+enum pm_node_id {
+	NODE_UNKNOWN = 0,
+	NODE_APU,
+	NODE_APU_0,
+	NODE_APU_1,
+	NODE_APU_2,
+	NODE_APU_3,
+	NODE_RPU,
+	NODE_RPU_0,
+	NODE_RPU_1,
+	NODE_PLD,
+	NODE_FPD,
+	NODE_OCM_BANK_0,
+	NODE_OCM_BANK_1,
+	NODE_OCM_BANK_2,
+	NODE_OCM_BANK_3,
+	NODE_TCM_0_A,
+	NODE_TCM_0_B,
+	NODE_TCM_1_A,
+	NODE_TCM_1_B,
+	NODE_L2,
+	NODE_GPU_PP_0,
+	NODE_GPU_PP_1,
+	NODE_USB_0,
+	NODE_USB_1,
+	NODE_TTC_0,
+	NODE_TTC_1,
+	NODE_TTC_2,
+	NODE_TTC_3,
+	NODE_SATA,
+	NODE_ETH_0,
+	NODE_ETH_1,
+	NODE_ETH_2,
+	NODE_ETH_3,
+	NODE_UART_0,
+	NODE_UART_1,
+	NODE_SPI_0,
+	NODE_SPI_1,
+	NODE_I2C_0,
+	NODE_I2C_1,
+	NODE_SD_0,
+	NODE_SD_1,
+	NODE_DP,
+	NODE_GDMA,
+	NODE_ADMA,
+	NODE_NAND,
+	NODE_QSPI,
+	NODE_GPIO,
+	NODE_CAN_0,
+	NODE_CAN_1,
+	NODE_EXTERN,
+	NODE_APLL,
+	NODE_VPLL,
+	NODE_DPLL,
+	NODE_RPLL,
+	NODE_IOPLL,
+	NODE_DDR,
+	NODE_IPI_APU,
+	NODE_IPI_RPU_0,
+	NODE_GPU,
+	NODE_PCIE,
+	NODE_PCAP,
+	NODE_RTC,
+	NODE_LPD,
+	NODE_VCU,
+	NODE_IPI_RPU_1,
+	NODE_IPI_PL_0,
+	NODE_IPI_PL_1,
+	NODE_IPI_PL_2,
+	NODE_IPI_PL_3,
+	NODE_PL,
+	NODE_GEM_TSU,
+	NODE_SWDT_0,
+	NODE_SWDT_1,
+	NODE_CSU,
+	NODE_PJTAG,
+	NODE_TRACE,
+	NODE_TESTSCAN,
+	NODE_PMU,
+	NODE_MAX,
+};
+
+enum pm_pinctrl_config_param {
+	PM_PINCTRL_CONFIG_SLEW_RATE,
+	PM_PINCTRL_CONFIG_BIAS_STATUS,
+	PM_PINCTRL_CONFIG_PULL_CTRL,
+	PM_PINCTRL_CONFIG_SCHMITT_CMOS,
+	PM_PINCTRL_CONFIG_DRIVE_STRENGTH,
+	PM_PINCTRL_CONFIG_VOLTAGE_STATUS,
+	PM_PINCTRL_CONFIG_MAX,
+};
+
+enum pm_pinctrl_slew_rate {
+	PM_PINCTRL_SLEW_RATE_FAST,
+	PM_PINCTRL_SLEW_RATE_SLOW,
+};
+
+enum pm_pinctrl_bias_status {
+	PM_PINCTRL_BIAS_DISABLE,
+	PM_PINCTRL_BIAS_ENABLE,
+};
+
+enum pm_pinctrl_pull_ctrl {
+	PM_PINCTRL_BIAS_PULL_DOWN,
+	PM_PINCTRL_BIAS_PULL_UP,
+};
+
+enum pm_pinctrl_schmitt_cmos {
+	PM_PINCTRL_INPUT_TYPE_CMOS,
+	PM_PINCTRL_INPUT_TYPE_SCHMITT,
+};
+
+enum pm_pinctrl_drive_strength {
+	PM_PINCTRL_DRIVE_STRENGTH_2MA,
+	PM_PINCTRL_DRIVE_STRENGTH_4MA,
+	PM_PINCTRL_DRIVE_STRENGTH_8MA,
+	PM_PINCTRL_DRIVE_STRENGTH_12MA,
+};
+
+enum pm_ioctl_id {
+	IOCTL_GET_RPU_OPER_MODE,
+	IOCTL_SET_RPU_OPER_MODE,
+	IOCTL_RPU_BOOT_ADDR_CONFIG,
+	IOCTL_TCM_COMB_CONFIG,
+	IOCTL_SET_TAPDELAY_BYPASS,
+	IOCTL_SET_SGMII_MODE,
+	IOCTL_SD_DLL_RESET,
+	IOCTL_SET_SD_TAPDELAY,
+	/* Ioctl for clock driver */
+	IOCTL_SET_PLL_FRAC_MODE,
+	IOCTL_GET_PLL_FRAC_MODE,
+	IOCTL_SET_PLL_FRAC_DATA,
+	IOCTL_GET_PLL_FRAC_DATA,
+	IOCTL_WRITE_GGS,
+	IOCTL_READ_GGS,
+	IOCTL_WRITE_PGGS,
+	IOCTL_READ_PGGS,
+};
+
+enum rpu_oper_mode {
+	PM_RPU_MODE_LOCKSTEP,
+	PM_RPU_MODE_SPLIT,
+};
+
+enum rpu_boot_mem {
+	PM_RPU_BOOTMEM_LOVEC,
+	PM_RPU_BOOTMEM_HIVEC,
+};
+
+enum rpu_tcm_comb {
+	PM_RPU_TCM_SPLIT,
+	PM_RPU_TCM_COMB,
+};
+
+enum tap_delay_signal_type {
+	PM_TAPDELAY_NAND_DQS_IN,
+	PM_TAPDELAY_NAND_DQS_OUT,
+	PM_TAPDELAY_QSPI,
+	PM_TAPDELAY_MAX,
+};
+
+enum tap_delay_bypass_ctrl {
+	PM_TAPDELAY_BYPASS_DISABLE,
+	PM_TAPDELAY_BYPASS_ENABLE,
+};
+
+enum sgmii_mode {
+	PM_SGMII_DISABLE,
+	PM_SGMII_ENABLE,
+};
+
+enum tap_delay_type {
+	PM_TAPDELAY_INPUT,
+	PM_TAPDELAY_OUTPUT,
+};
+
+enum dll_reset_type {
+	PM_DLL_RESET_ASSERT,
+	PM_DLL_RESET_RELEASE,
+	PM_DLL_RESET_PULSE,
+};
+
+enum topology_type {
+	TYPE_INVALID,
+	TYPE_MUX,
+	TYPE_PLL,
+	TYPE_FIXEDFACTOR,
+	TYPE_DIV1,
+	TYPE_DIV2,
+	TYPE_GATE,
+};
+
+enum pm_query_id {
+	PM_QID_INVALID,
+	PM_QID_CLOCK_GET_NAME,
+	PM_QID_CLOCK_GET_TOPOLOGY,
+	PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS,
+	PM_QID_CLOCK_GET_PARENTS,
+	PM_QID_CLOCK_GET_ATTRIBUTES,
+	PM_QID_PINCTRL_GET_NUM_PINS,
+	PM_QID_PINCTRL_GET_NUM_FUNCTIONS,
+	PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
+	PM_QID_PINCTRL_GET_FUNCTION_NAME,
+	PM_QID_PINCTRL_GET_FUNCTION_GROUPS,
+	PM_QID_PINCTRL_GET_PIN_GROUPS,
+};
+
+struct zynqmp_pm_query_data {
+	u32 qid;
+	u32 arg1;
+	u32 arg2;
+	u32 arg3;
+};
+
+struct zynqmp_eemi_ops {
+	int (*get_api_version)(u32 *version);
+	int (*get_chipid)(u32 *idcode, u32 *version);
+	int (*reset_assert)(const enum zynqmp_pm_reset reset,
+			    const enum zynqmp_pm_reset_action assert_flag);
+	int (*reset_get_status)(const enum zynqmp_pm_reset reset, u32 *status);
+	int (*fpga_load)(const u64 address, const u32 size, const u32 flags);
+	int (*fpga_get_status)(u32 *value);
+	int (*sha_hash)(const u64 address, const u32 size, const u32 flags);
+	int (*rsa)(const u64 address, const u32 size, const u32 flags);
+	int (*request_suspend)(const u32 node,
+			       const enum zynqmp_pm_request_ack ack,
+			       const u32 latency,
+			       const u32 state);
+	int (*force_powerdown)(const u32 target,
+			       const enum zynqmp_pm_request_ack ack);
+	int (*request_wakeup)(const u32 node,
+			      const bool set_addr,
+			      const u64 address,
+			      const enum zynqmp_pm_request_ack ack);
+	int (*set_wakeup_source)(const u32 target,
+				 const u32 wakeup_node,
+				 const u32 enable);
+	int (*system_shutdown)(const u32 type, const u32 subtype);
+	int (*request_node)(const u32 node,
+			    const u32 capabilities,
+			    const u32 qos,
+			    const enum zynqmp_pm_request_ack ack);
+	int (*release_node)(const u32 node);
+	int (*set_requirement)(const u32 node,
+			       const u32 capabilities,
+			       const u32 qos,
+			       const enum zynqmp_pm_request_ack ack);
+	int (*set_max_latency)(const u32 node, const u32 latency);
+	int (*set_configuration)(const u32 physical_addr);
+	int (*get_node_status)(const u32 node, u32 *const status,
+			       u32 *const requirements, u32 *const usage);
+	int (*get_operating_characteristic)(const u32 node,
+					    const enum zynqmp_pm_opchar_type
+					    type, u32 *const result);
+	int (*init_finalize)(void);
+	int (*set_suspend_mode)(u32 mode);
+	int (*ioctl)(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, u32 *out);
+	int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out);
+	int (*pinctrl_request)(const u32 pin);
+	int (*pinctrl_release)(const u32 pin);
+	int (*pinctrl_get_function)(const u32 pin, u32 *id);
+	int (*pinctrl_set_function)(const u32 pin, const u32 id);
+	int (*pinctrl_get_config)(const u32 pin, const u32 param, u32 *value);
+	int (*pinctrl_set_config)(const u32 pin, const u32 param, u32 value);
+	int (*clock_enable)(u32 clock_id);
+	int (*clock_disable)(u32 clock_id);
+	int (*clock_getstate)(u32 clock_id, u32 *state);
+	int (*clock_setdivider)(u32 clock_id, u32 divider);
+	int (*clock_getdivider)(u32 clock_id, u32 *divider);
+	int (*clock_setrate)(u32 clock_id, u64 rate);
+	int (*clock_getrate)(u32 clock_id, u64 *rate);
+	int (*clock_setparent)(u32 clock_id, u32 parent_id);
+	int (*clock_getparent)(u32 clock_id, u32 *parent_id);
+};
+
+/*
+ * Internal functions
+ */
+int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
+			u32 arg2, u32 arg3, u32 *ret_payload);
+
+#if IS_REACHABLE(CONFIG_ARCH_ZYNQMP)
+const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void);
+#else
+static inline struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void)
+{
+	return NULL;
+}
+#endif
+
+#endif /* __SOC_ZYNQMP_FIRMWARE_H__ */
-- 
2.7.4

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

* [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface
  2018-02-20 19:21 [PATCH v5 0/4] drivers: firmware: xilinx: Add firmware driver support Jolly Shah
  2018-02-20 19:21 ` [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware Jolly Shah
  2018-02-20 19:21 ` [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver Jolly Shah
@ 2018-02-20 19:21 ` Jolly Shah
  2018-03-01 13:32   ` Michal Simek
                     ` (2 more replies)
  2018-02-20 19:21 ` [PATCH v5 4/4] drivers: firmware: xilinx: Add debugfs interface Jolly Shah
  3 siblings, 3 replies; 24+ messages in thread
From: Jolly Shah @ 2018-02-20 19:21 UTC (permalink / raw)
  To: ard.biesheuvel, mingo, gregkh, matt, sudeep.holla, hkallweit1,
	keescook, dmitry.torokhov, michal.simek, robh+dt, mark.rutland
  Cc: rajanv, linux-arm-kernel, linux-kernel, devicetree, Jolly Shah

Add Firmware-ggs sysfs interface which provides read/write
interface to global storage registers.

Signed-off-by: Jolly Shah <jollys@xilinx.com>
Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
---
 .../ABI/stable/sysfs-driver-zynqmp-firmware        |  50 ++++
 drivers/firmware/xilinx/zynqmp/Makefile            |   2 +-
 drivers/firmware/xilinx/zynqmp/firmware-ggs.c      | 297 +++++++++++++++++++++
 drivers/firmware/xilinx/zynqmp/firmware.c          |  13 +
 include/linux/firmware/xilinx/zynqmp/firmware.h    |   2 +
 5 files changed, 363 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
 create mode 100644 drivers/firmware/xilinx/zynqmp/firmware-ggs.c

diff --git a/Documentation/ABI/stable/sysfs-driver-zynqmp-firmware b/Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
new file mode 100644
index 0000000..b04727a
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
@@ -0,0 +1,50 @@
+What:		/sys/devices/platform/zynqmp-firmware/ggs*
+Date:		January 2018
+KernelVersion:	4.15.0
+Contact:	"Jolly Shah" <jollys@xilinx.com>
+Description:
+		Read/Write PMU global general storage register value,
+		GLOBAL_GEN_STORAGE{0:3}.
+		Global general storage register that can be used
+		by system to pass information between masters.
+
+		The register is reset during system or power-on
+		resets. Three registers are used by the FSBL and
+		other Xilinx software products: GLOBAL_GEN_STORAGE{4:6}.
+
+		Usage:
+		# cat /sys/.../zynqmp-firmware/ggs0
+		# echo <mask> <value> > /sys/.../zynqmp-firmware/ggs0
+
+		Example:
+		# cat /sys/.../zynqmp-firmware/ggs0
+		# echo 0xFFFFFFFF 0x1234ABCD > /sys/.../zynqmp-firmware/ggs0
+
+Users:		Xilinx
+
+What:		/sys/devices/platform/zynqmp-firmware/pggs*
+Date:		January 2018
+KernelVersion:	4.15.0
+Contact:	"Jolly Shah" <jollys@xilinx.com>
+Description:
+		Read/Write PMU persistent global general storage register
+		value, PERS_GLOB_GEN_STORAGE{0:3}.
+		Persistent global general storage register that
+		can be used by system to pass information between
+		masters.
+
+		This register is only reset by the power-on reset
+		and maintains its value through a system reset.
+		Four registers are used by the FSBL and other Xilinx
+		software products: PERS_GLOB_GEN_STORAGE{4:7}.
+		Register is reset only by a POR reset.
+
+		Usage:
+		# cat /sys/.../zynqmp-firmware/pggs0
+		# echo <mask> <value> > /sys/.../zynqmp-firmware/pggs0
+
+		Example:
+		# cat /sys/.../zynqmp-firmware/pggs0
+		# echo 0xFFFFFFFF 0x1234ABCD > /sys/.../zynqmp-firmware/pggs0
+
+Users:		Xilinx
diff --git a/drivers/firmware/xilinx/zynqmp/Makefile b/drivers/firmware/xilinx/zynqmp/Makefile
index c3ec669..6629781 100644
--- a/drivers/firmware/xilinx/zynqmp/Makefile
+++ b/drivers/firmware/xilinx/zynqmp/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0+
 # Makefile for Xilinx firmwares
 
-obj-$(CONFIG_ZYNQMP_FIRMWARE) += firmware.o
+obj-$(CONFIG_ZYNQMP_FIRMWARE) += firmware.o firmware-ggs.o
diff --git a/drivers/firmware/xilinx/zynqmp/firmware-ggs.c b/drivers/firmware/xilinx/zynqmp/firmware-ggs.c
new file mode 100644
index 0000000..e08f6a6
--- /dev/null
+++ b/drivers/firmware/xilinx/zynqmp/firmware-ggs.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Xilinx Zynq MPSoC Firmware layer
+ *
+ *  Copyright (C) 2014-2018 Xilinx, Inc.
+ *
+ *  Jolly Shah <jollys@xilinx.com>
+ *  Rajan Vaja <rajanv@xilinx.com>
+ */
+
+#include <linux/compiler.h>
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/firmware/xilinx/zynqmp/firmware.h>
+
+static ssize_t read_register(char *buf, u32 ioctl_id, u32 reg)
+{
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+	if (!eemi_ops || !eemi_ops->ioctl)
+		return -EFAULT;
+
+	ret = eemi_ops->ioctl(0, ioctl_id, reg, 0, ret_payload);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "0x%x\n", ret_payload[1]);
+}
+
+static ssize_t write_register(const char *buf, size_t count, u32 read_ioctl,
+			      u32 write_ioctl, u32 reg)
+{
+	char *kern_buff, *inbuf, *tok;
+	long mask, value;
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+	if (!eemi_ops || !eemi_ops->ioctl)
+		return -EFAULT;
+
+	kern_buff = kzalloc(count, GFP_KERNEL);
+	if (!kern_buff)
+		return -ENOMEM;
+
+	ret = strlcpy(kern_buff, buf, count);
+	if (ret < 0) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	inbuf = kern_buff;
+
+	/* Read the write mask */
+	tok = strsep(&inbuf, " ");
+	if (!tok) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	ret = kstrtol(tok, 16, &mask);
+	if (ret) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	/* Read the write value */
+	tok = strsep(&inbuf, " ");
+	if (!tok) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	ret = kstrtol(tok, 16, &value);
+	if (ret) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	ret = eemi_ops->ioctl(0, read_ioctl, reg, 0, ret_payload);
+	if (ret) {
+		ret = -EFAULT;
+		goto err;
+	}
+	ret_payload[1] &= ~mask;
+	value &= mask;
+	value |= ret_payload[1];
+
+	ret = eemi_ops->ioctl(0, write_ioctl, reg, value, NULL);
+	if (ret)
+		ret = -EFAULT;
+
+err:
+	kfree(kern_buff);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+/**
+ * ggs_show - Show global general storage (ggs) sysfs attribute
+ * @kobj: Kobject structure
+ * @attr: Kobject attribute structure
+ * @buf: Requested available shutdown_scope attributes string
+ * @reg: Register number
+ *
+ * Return:Number of bytes printed into the buffer.
+ *
+ * Helper function for viewing a ggs register value.
+ *
+ * User-space interface for viewing the content of the ggs0 register.
+ * cat /sys/firmware/zynqmp/ggs0
+ */
+static ssize_t ggs_show(struct kobject *kobj,
+			struct kobj_attribute *attr,
+			char *buf,
+			u32 reg)
+{
+	return read_register(buf, IOCTL_READ_GGS, reg);
+}
+
+/**
+ * ggs_store - Store global general storage (ggs) sysfs attribute
+ * @kobj: Kobject structure
+ * @attr: Kobject attribute structure
+ * @buf: User entered shutdown_scope attribute string
+ * @count: Size of buf
+ * @reg: Register number
+ *
+ * Return: count argument if request succeeds, the corresponding
+ * error code otherwise
+ *
+ * Helper function for storing a ggs register value.
+ *
+ * For example, the user-space interface for storing a value to the
+ * ggs0 register:
+ * echo 0xFFFFFFFF 0x1234ABCD > /sys/firmware/zynqmp/ggs0
+ */
+static ssize_t ggs_store(struct kobject *kobj,
+			 struct kobj_attribute *attr,
+			 const char *buf,
+			 size_t count,
+			 u32 reg)
+{
+	if (!kobj || !attr || !buf || !count || reg >= GSS_NUM_REGS)
+		return -EINVAL;
+
+	return write_register(buf, count, IOCTL_READ_GGS, IOCTL_WRITE_GGS, reg);
+}
+
+/* GGS register show functions */
+#define GGS0_SHOW(N)						\
+	ssize_t ggs##N##_show(struct kobject *kobj,		\
+				struct kobj_attribute *attr,	\
+				char *buf)			\
+	{							\
+		return ggs_show(kobj, attr, buf, N);		\
+	}
+
+static GGS0_SHOW(0);
+static GGS0_SHOW(1);
+static GGS0_SHOW(2);
+static GGS0_SHOW(3);
+
+/* GGS register store function */
+#define GGS0_STORE(N)						\
+	ssize_t ggs##N##_store(struct kobject *kobj,		\
+				struct kobj_attribute *attr,	\
+				const char *buf,		\
+				size_t count)			\
+	{							\
+		return ggs_store(kobj, attr, buf, count, N);	\
+	}
+
+static GGS0_STORE(0);
+static GGS0_STORE(1);
+static GGS0_STORE(2);
+static GGS0_STORE(3);
+
+/**
+ * pggs_show - Show persistent global general storage (pggs) sysfs attribute
+ * @kobj: Kobject structure
+ * @attr: Kobject attribute structure
+ * @buf: Requested available shutdown_scope attributes string
+ * @reg: Register number
+ *
+ * Return:Number of bytes printed into the buffer.
+ *
+ * Helper function for viewing a pggs register value.
+ */
+static ssize_t pggs_show(struct kobject *kobj,
+			 struct kobj_attribute *attr,
+			 char *buf,
+			 u32 reg)
+{
+	return read_register(buf, IOCTL_READ_PGGS, reg);
+}
+
+/**
+ * pggs_store - Store persistent global general storage (pggs) sysfs attribute
+ * @kobj: Kobject structure
+ * @attr: Kobject attribute structure
+ * @buf: User entered shutdown_scope attribute string
+ * @count: Size of buf
+ * @reg: Register number
+ *
+ * Return: count argument if request succeeds, the corresponding
+ * error code otherwise
+ *
+ * Helper function for storing a pggs register value.
+ */
+static ssize_t pggs_store(struct kobject *kobj,
+			  struct kobj_attribute *attr,
+			  const char *buf,
+			  size_t count,
+			  u32 reg)
+{
+	return write_register(buf, count, IOCTL_READ_PGGS,
+			      IOCTL_WRITE_PGGS, reg);
+}
+
+#define PGGS0_SHOW(N)						\
+	ssize_t pggs##N##_show(struct kobject *kobj,		\
+				struct kobj_attribute *attr,	\
+				char *buf)			\
+	{							\
+		return pggs_show(kobj, attr, buf, N);		\
+	}
+
+#define PGGS0_STORE(N)						\
+	ssize_t pggs##N##_store(struct kobject *kobj,		\
+				   struct kobj_attribute *attr,	\
+				   const char *buf,		\
+				   size_t count)		\
+	{							\
+		return pggs_store(kobj, attr, buf, count, N);	\
+	}
+
+/* PGGS register show functions */
+static PGGS0_SHOW(0);
+static PGGS0_SHOW(1);
+static PGGS0_SHOW(2);
+static PGGS0_SHOW(3);
+
+/* PGGS register store functions */
+static PGGS0_STORE(0);
+static PGGS0_STORE(1);
+static PGGS0_STORE(2);
+static PGGS0_STORE(3);
+
+/* GGS register attributes */
+static struct kobj_attribute zynqmp_attr_ggs0 = __ATTR_RW(ggs0);
+static struct kobj_attribute zynqmp_attr_ggs1 = __ATTR_RW(ggs1);
+static struct kobj_attribute zynqmp_attr_ggs2 = __ATTR_RW(ggs2);
+static struct kobj_attribute zynqmp_attr_ggs3 = __ATTR_RW(ggs3);
+
+/* PGGS register attributes */
+static struct kobj_attribute zynqmp_attr_pggs0 = __ATTR_RW(pggs0);
+static struct kobj_attribute zynqmp_attr_pggs1 = __ATTR_RW(pggs1);
+static struct kobj_attribute zynqmp_attr_pggs2 = __ATTR_RW(pggs2);
+static struct kobj_attribute zynqmp_attr_pggs3 = __ATTR_RW(pggs3);
+
+static struct attribute *attrs[] = {
+	&zynqmp_attr_ggs0.attr,
+	&zynqmp_attr_ggs1.attr,
+	&zynqmp_attr_ggs2.attr,
+	&zynqmp_attr_ggs3.attr,
+	&zynqmp_attr_pggs0.attr,
+	&zynqmp_attr_pggs1.attr,
+	&zynqmp_attr_pggs2.attr,
+	&zynqmp_attr_pggs3.attr,
+	NULL,
+};
+
+static const struct attribute_group attr_group = {
+	.attrs = attrs,
+	NULL,
+};
+
+int zynqmp_pm_ggs_init(void)
+{
+	struct kobject *zynqmp_kobj;
+
+	zynqmp_kobj = kobject_create_and_add("zynqmp", firmware_kobj);
+	if (!zynqmp_kobj) {
+		pr_err("zynqmp: Firmware kobj add failed.\n");
+		return -ENOMEM;
+	}
+
+	return sysfs_create_group(zynqmp_kobj, &attr_group);
+}
diff --git a/drivers/firmware/xilinx/zynqmp/firmware.c b/drivers/firmware/xilinx/zynqmp/firmware.c
index 6979f4b..02266d9 100644
--- a/drivers/firmware/xilinx/zynqmp/firmware.c
+++ b/drivers/firmware/xilinx/zynqmp/firmware.c
@@ -1049,3 +1049,16 @@ static int __init zynqmp_plat_init(void)
 	return ret;
 }
 early_initcall(zynqmp_plat_init);
+
+static int zynqmp_firmware_init(void)
+{
+	int ret;
+
+	ret = zynqmp_pm_ggs_init();
+	if (ret)
+		pr_err("%s() GGS init fail with error %d\n",
+		       __func__, ret);
+
+	return ret;
+}
+device_initcall(zynqmp_firmware_init);
diff --git a/include/linux/firmware/xilinx/zynqmp/firmware.h b/include/linux/firmware/xilinx/zynqmp/firmware.h
index 859d809..94b5a43 100644
--- a/include/linux/firmware/xilinx/zynqmp/firmware.h
+++ b/include/linux/firmware/xilinx/zynqmp/firmware.h
@@ -578,6 +578,8 @@ struct zynqmp_eemi_ops {
 int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
 			u32 arg2, u32 arg3, u32 *ret_payload);
 
+int zynqmp_pm_ggs_init(void);
+
 #if IS_REACHABLE(CONFIG_ARCH_ZYNQMP)
 const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void);
 #else
-- 
2.7.4

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

* [PATCH v5 4/4] drivers: firmware: xilinx: Add debugfs interface
  2018-02-20 19:21 [PATCH v5 0/4] drivers: firmware: xilinx: Add firmware driver support Jolly Shah
                   ` (2 preceding siblings ...)
  2018-02-20 19:21 ` [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface Jolly Shah
@ 2018-02-20 19:21 ` Jolly Shah
  3 siblings, 0 replies; 24+ messages in thread
From: Jolly Shah @ 2018-02-20 19:21 UTC (permalink / raw)
  To: ard.biesheuvel, mingo, gregkh, matt, sudeep.holla, hkallweit1,
	keescook, dmitry.torokhov, michal.simek, robh+dt, mark.rutland
  Cc: rajanv, linux-arm-kernel, linux-kernel, devicetree, Jolly Shah

Firmware-debug provides debugfs interface to all APIs.
Debugfs can be used to call firmware APIs with required
parameters.

Usage:
* Calling firmware API through debugfs:
  # echo "<api-name> <arg1> .. <argn>" > /sys/kernel/debug/zynqmp-firmware/pm

* Read output of last called firmware API:
  # cat /sys/kernel/debug/zynqmp-firmware/pm

Refer ug1200 for more information on these APIs:
  * https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf

Below are supported debugfs APIs:
    * PM_REQUEST_SUSPEND
    * PM_SELF_SUSPEND
    * PM_FORCE_POWERDOWN
    * PM_ABORT_SUSPEND
    * PM_REQUEST_WAKEUP
    * PM_SET_WAKEUP_SOURCE
    * PM_SYSTEM_SHUTDOWN
    * PM_REQUEST_NODE
    * PM_RELEASE_NODE
    * PM_SET_REQUIREMENT
    * PM_SET_MAX_LATENCY
    * PM_GET_API_VERSION
    * PM_SET_CONFIGURATION
    * PM_GET_NODE_STATUS
    * PM_GET_OPERATING_CHARACTERISTIC
    * PM_REGISTER_NOTIFIER
    * PM_RESET_ASSERT
    * PM_RESET_GET_STATUS
    * PM_GET_CHIPID
    * PM_PINCTRL_GET_FUNCTION
    * PM_PINCTRL_SET_FUNCTION
    * PM_PINCTRL_CONFIG_PARAM_GET
    * PM_PINCTRL_CONFIG_PARAM_SET
    * PM_IOCTL
    * PM_CLOCK_ENABLE
    * PM_CLOCK_DISABLE
    * PM_CLOCK_GETSTATE
    * PM_CLOCK_SETDIVIDER
    * PM_CLOCK_GETDIVIDER
    * PM_CLOCK_SETRATE
    * PM_CLOCK_GETRATE
    * PM_CLOCK_SETPARENT
    * PM_CLOCK_GETPARENT
    * PM_QUERY_DATA

Signed-off-by: Jolly Shah <jollys@xilinx.com>
Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
---
 drivers/firmware/xilinx/zynqmp/Kconfig             |   7 +
 drivers/firmware/xilinx/zynqmp/Makefile            |   1 +
 drivers/firmware/xilinx/zynqmp/firmware-debug.c    | 482 +++++++++++++++++++++
 drivers/firmware/xilinx/zynqmp/firmware.c          |   7 +-
 .../linux/firmware/xilinx/zynqmp/firmware-debug.h  |  22 +
 5 files changed, 518 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/xilinx/zynqmp/firmware-debug.c
 create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware-debug.h

diff --git a/drivers/firmware/xilinx/zynqmp/Kconfig b/drivers/firmware/xilinx/zynqmp/Kconfig
index 5054b80..5c22aba 100644
--- a/drivers/firmware/xilinx/zynqmp/Kconfig
+++ b/drivers/firmware/xilinx/zynqmp/Kconfig
@@ -13,4 +13,11 @@ config ZYNQMP_FIRMWARE
 	  Say yes to enable ZynqMP firmware interface driver.
 	  In doubt, say N
 
+config ZYNQMP_FIRMWARE_DEBUG
+	bool "Enable Xilinx Zynq MPSoC firmware debug APIs"
+	depends on ZYNQMP_FIRMWARE && DEBUG_FS
+	help
+	  Say yes to enable ZynqMP firmware interface debug APIs.
+	  In doubt, say N
+
 endmenu
diff --git a/drivers/firmware/xilinx/zynqmp/Makefile b/drivers/firmware/xilinx/zynqmp/Makefile
index 6629781..02f0c9a 100644
--- a/drivers/firmware/xilinx/zynqmp/Makefile
+++ b/drivers/firmware/xilinx/zynqmp/Makefile
@@ -2,3 +2,4 @@
 # Makefile for Xilinx firmwares
 
 obj-$(CONFIG_ZYNQMP_FIRMWARE) += firmware.o firmware-ggs.o
+obj-$(CONFIG_ZYNQMP_FIRMWARE_DEBUG) += firmware-debug.o
diff --git a/drivers/firmware/xilinx/zynqmp/firmware-debug.c b/drivers/firmware/xilinx/zynqmp/firmware-debug.c
new file mode 100644
index 0000000..5dd0d90
--- /dev/null
+++ b/drivers/firmware/xilinx/zynqmp/firmware-debug.c
@@ -0,0 +1,482 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Xilinx Zynq MPSoC Firmware layer for debugfs APIs
+ *
+ *  Copyright (C) 2014-2018 Xilinx, Inc.
+ *
+ *  Michal Simek <michal.simek@xilinx.com>
+ *  Davorin Mista <davorin.mista@aggios.com>
+ *  Jolly Shah <jollys@xilinx.com>
+ *  Rajan Vaja <rajanv@xilinx.com>
+ */
+
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/firmware/xilinx/zynqmp/firmware.h>
+#include <linux/firmware/xilinx/zynqmp/firmware-debug.h>
+
+#define PM_API_NAME_LEN			50
+
+struct pm_api_info {
+	u32 api_id;
+	char api_name[PM_API_NAME_LEN];
+	char api_name_len;
+};
+
+static char debugfs_buf[PAGE_SIZE];
+
+#define PM_API(id)		 {id, #id, strlen(#id)}
+static struct pm_api_info pm_api_list[] = {
+	PM_API(PM_REQUEST_SUSPEND),
+	PM_API(PM_SELF_SUSPEND),
+	PM_API(PM_FORCE_POWERDOWN),
+	PM_API(PM_ABORT_SUSPEND),
+	PM_API(PM_REQUEST_WAKEUP),
+	PM_API(PM_SET_WAKEUP_SOURCE),
+	PM_API(PM_SYSTEM_SHUTDOWN),
+	PM_API(PM_REQUEST_NODE),
+	PM_API(PM_RELEASE_NODE),
+	PM_API(PM_SET_REQUIREMENT),
+	PM_API(PM_SET_MAX_LATENCY),
+	PM_API(PM_GET_API_VERSION),
+	PM_API(PM_SET_CONFIGURATION),
+	PM_API(PM_GET_NODE_STATUS),
+	PM_API(PM_GET_OPERATING_CHARACTERISTIC),
+	PM_API(PM_REGISTER_NOTIFIER),
+	PM_API(PM_RESET_ASSERT),
+	PM_API(PM_RESET_GET_STATUS),
+	PM_API(PM_GET_CHIPID),
+	PM_API(PM_PINCTRL_GET_FUNCTION),
+	PM_API(PM_PINCTRL_SET_FUNCTION),
+	PM_API(PM_PINCTRL_CONFIG_PARAM_GET),
+	PM_API(PM_PINCTRL_CONFIG_PARAM_SET),
+	PM_API(PM_IOCTL),
+	PM_API(PM_CLOCK_ENABLE),
+	PM_API(PM_CLOCK_DISABLE),
+	PM_API(PM_CLOCK_GETSTATE),
+	PM_API(PM_CLOCK_SETDIVIDER),
+	PM_API(PM_CLOCK_GETDIVIDER),
+	PM_API(PM_CLOCK_SETRATE),
+	PM_API(PM_CLOCK_GETRATE),
+	PM_API(PM_CLOCK_SETPARENT),
+	PM_API(PM_CLOCK_GETPARENT),
+	PM_API(PM_QUERY_DATA),
+};
+
+/**
+ * zynqmp_pm_self_suspend - PM call for master to suspend itself
+ * @node:	Node ID of the master or subsystem
+ * @latency:	Requested maximum wakeup latency (not supported)
+ * @state:	Requested state (not supported)
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_self_suspend(const u32 node, const u32 latency,
+				  const u32 state)
+{
+	return zynqmp_pm_invoke_fn(PM_SELF_SUSPEND, node, latency,
+				   state, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_abort_suspend - PM call to announce that a prior suspend request
+ *				is to be aborted.
+ * @reason:	Reason for the abort
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_abort_suspend(const enum zynqmp_pm_abort_reason reason)
+{
+	return zynqmp_pm_invoke_fn(PM_ABORT_SUSPEND, reason, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_register_notifier - Register the PU to be notified of PM events
+ * @node:	Node ID of the slave
+ * @event:	The event to be notified about
+ * @wake:	Wake up on event
+ * @enable:	Enable or disable the notifier
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_register_notifier(const u32 node, const u32 event,
+				       const u32 wake, const u32 enable)
+{
+	return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event,
+				   wake, enable, NULL);
+}
+
+/**
+ * zynqmp_pm_argument_value - Extract argument value from a PM-API request
+ * @arg:	Entered PM-API argument in string format
+ *
+ * Return:	Argument value in unsigned integer format on success
+ *		0 otherwise
+ */
+static u64 zynqmp_pm_argument_value(char *arg)
+{
+	u64 value;
+
+	if (!arg)
+		return 0;
+
+	if (!kstrtou64(arg, 0, &value))
+		return value;
+
+	return 0;
+}
+
+static int get_pm_api_id(char *pm_api_req, u32 *pm_id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pm_api_list) ; i++) {
+		if (!strncasecmp(pm_api_req, pm_api_list[i].api_name,
+				 pm_api_list[i].api_name_len)) {
+			*pm_id = pm_api_list[i].api_id;
+			break;
+		}
+	}
+
+	/* If no name was entered look for PM-API ID instead */
+	if (i == ARRAY_SIZE(pm_api_list) && kstrtouint(pm_api_req, 10, pm_id))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	u32 pm_api_version;
+	u64 rate;
+	int ret;
+
+	if (!eemi_ops)
+		return -ENXIO;
+
+	switch (pm_id) {
+	case PM_GET_API_VERSION:
+		ret = eemi_ops->get_api_version(&pm_api_version);
+		sprintf(debugfs_buf, "PM-API Version = %d.%d\n",
+			pm_api_version >> 16, pm_api_version & 0xffff);
+		break;
+	case PM_REQUEST_SUSPEND:
+		ret = eemi_ops->request_suspend(pm_api_arg[0],
+						pm_api_arg[1] ? pm_api_arg[1] :
+						ZYNQMP_PM_REQUEST_ACK_NO,
+						pm_api_arg[2] ? pm_api_arg[2] :
+						ZYNQMP_PM_MAX_LATENCY, 0);
+		break;
+	case PM_SELF_SUSPEND:
+		ret = zynqmp_pm_self_suspend(pm_api_arg[0],
+					     pm_api_arg[1] ? pm_api_arg[1] :
+					     ZYNQMP_PM_MAX_LATENCY, 0);
+		break;
+	case PM_FORCE_POWERDOWN:
+		ret = eemi_ops->force_powerdown(pm_api_arg[0],
+						pm_api_arg[1] ? pm_api_arg[1] :
+						ZYNQMP_PM_REQUEST_ACK_NO);
+		break;
+	case PM_ABORT_SUSPEND:
+		ret = zynqmp_pm_abort_suspend(pm_api_arg[0] ? pm_api_arg[0] :
+					      ZYNQMP_PM_ABORT_REASON_UNKNOWN);
+		break;
+	case PM_REQUEST_WAKEUP:
+		ret = eemi_ops->request_wakeup(pm_api_arg[0],
+					       pm_api_arg[1], pm_api_arg[2],
+					       pm_api_arg[3] ? pm_api_arg[3] :
+					       ZYNQMP_PM_REQUEST_ACK_NO);
+		break;
+	case PM_SET_WAKEUP_SOURCE:
+		ret = eemi_ops->set_wakeup_source(pm_api_arg[0], pm_api_arg[1],
+						  pm_api_arg[2]);
+		break;
+	case PM_SYSTEM_SHUTDOWN:
+		ret = eemi_ops->system_shutdown(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_REQUEST_NODE:
+		ret = eemi_ops->request_node(pm_api_arg[0],
+					     pm_api_arg[1] ? pm_api_arg[1] :
+					     ZYNQMP_PM_CAPABILITY_ACCESS,
+					     pm_api_arg[2] ? pm_api_arg[2] : 0,
+					     pm_api_arg[3] ? pm_api_arg[3] :
+					     ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+		break;
+	case PM_RELEASE_NODE:
+		ret = eemi_ops->release_node(pm_api_arg[0]);
+		break;
+	case PM_SET_REQUIREMENT:
+		ret = eemi_ops->set_requirement(pm_api_arg[0],
+						pm_api_arg[1] ? pm_api_arg[1] :
+						ZYNQMP_PM_CAPABILITY_CONTEXT,
+						pm_api_arg[2] ?
+						pm_api_arg[2] : 0,
+						pm_api_arg[3] ? pm_api_arg[3] :
+						ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+		break;
+	case PM_SET_MAX_LATENCY:
+		ret = eemi_ops->set_max_latency(pm_api_arg[0],
+						pm_api_arg[1] ? pm_api_arg[1] :
+						ZYNQMP_PM_MAX_LATENCY);
+		break;
+	case PM_SET_CONFIGURATION:
+		ret = eemi_ops->set_configuration(pm_api_arg[0]);
+		break;
+	case PM_GET_NODE_STATUS:
+		ret = eemi_ops->get_node_status(pm_api_arg[0],
+						&pm_api_ret[0],
+						&pm_api_ret[1],
+						&pm_api_ret[2]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"GET_NODE_STATUS:\n\tNodeId: %llu\n\tStatus: %u\n\tRequirements: %u\n\tUsage: %u\n",
+				pm_api_arg[0], pm_api_ret[0],
+				pm_api_ret[1], pm_api_ret[2]);
+		break;
+	case PM_GET_OPERATING_CHARACTERISTIC:
+		ret = eemi_ops->get_operating_characteristic(pm_api_arg[0],
+				pm_api_arg[1] ? pm_api_arg[1] :
+				ZYNQMP_PM_OPERATING_CHARACTERISTIC_POWER,
+				&pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"GET_OPERATING_CHARACTERISTIC:\n\tNodeId: %llu\n\tType: %llu\n\tResult: %u\n",
+				pm_api_arg[0], pm_api_arg[1],
+				pm_api_ret[0]);
+		break;
+	case PM_REGISTER_NOTIFIER:
+		ret = zynqmp_pm_register_notifier(pm_api_arg[0],
+						  pm_api_arg[1] ?
+						  pm_api_arg[1] : 0,
+						  pm_api_arg[2] ?
+						  pm_api_arg[2] : 0,
+						  pm_api_arg[3] ?
+						  pm_api_arg[3] : 0);
+		break;
+	case PM_RESET_ASSERT:
+		ret = eemi_ops->reset_assert(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_RESET_GET_STATUS:
+		ret = eemi_ops->reset_get_status(pm_api_arg[0], &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf, "Reset status: %u\n",
+				pm_api_ret[0]);
+		break;
+	case PM_GET_CHIPID:
+		ret = eemi_ops->get_chipid(&pm_api_ret[0], &pm_api_ret[1]);
+		if (!ret)
+			sprintf(debugfs_buf, "Idcode: %#x, Version:%#x\n",
+				pm_api_ret[0], pm_api_ret[1]);
+		break;
+	case PM_PINCTRL_GET_FUNCTION:
+		ret = eemi_ops->pinctrl_get_function(pm_api_arg[0],
+						     &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"Current set function for the pin: %u\n",
+				pm_api_ret[0]);
+		break;
+	case PM_PINCTRL_SET_FUNCTION:
+		ret = eemi_ops->pinctrl_set_function(pm_api_arg[0],
+						     pm_api_arg[1]);
+		break;
+	case PM_PINCTRL_CONFIG_PARAM_GET:
+		ret = eemi_ops->pinctrl_get_config(pm_api_arg[0], pm_api_arg[1],
+						   &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"Pin: %llu, Param: %llu, Value: %u\n",
+				pm_api_arg[0], pm_api_arg[1],
+				pm_api_ret[0]);
+		break;
+	case PM_PINCTRL_CONFIG_PARAM_SET:
+		ret = eemi_ops->pinctrl_set_config(pm_api_arg[0],
+						   pm_api_arg[1],
+						   pm_api_arg[2]);
+		break;
+	case PM_IOCTL:
+		ret = eemi_ops->ioctl(pm_api_arg[0], pm_api_arg[1],
+				      pm_api_arg[2], pm_api_arg[3],
+				      &pm_api_ret[0]);
+		if (!ret && (pm_api_arg[1] == IOCTL_GET_RPU_OPER_MODE ||
+			     pm_api_arg[1] == IOCTL_GET_PLL_FRAC_MODE ||
+			     pm_api_arg[1] == IOCTL_GET_PLL_FRAC_DATA ||
+			     pm_api_arg[1] == IOCTL_READ_GGS ||
+			     pm_api_arg[1] == IOCTL_READ_PGGS))
+			sprintf(debugfs_buf, "IOCTL return value: %u\n",
+				pm_api_ret[1]);
+		break;
+	case PM_CLOCK_ENABLE:
+		ret = eemi_ops->clock_enable(pm_api_arg[0]);
+		break;
+	case PM_CLOCK_DISABLE:
+		ret = eemi_ops->clock_disable(pm_api_arg[0]);
+		break;
+	case PM_CLOCK_GETSTATE:
+		ret = eemi_ops->clock_getstate(pm_api_arg[0], &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf, "Clock state: %u\n",
+				pm_api_ret[0]);
+		break;
+	case PM_CLOCK_SETDIVIDER:
+		ret = eemi_ops->clock_setdivider(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_CLOCK_GETDIVIDER:
+		ret = eemi_ops->clock_getdivider(pm_api_arg[0], &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf, "Divider Value: %d\n",
+				pm_api_ret[0]);
+		break;
+	case PM_CLOCK_SETRATE:
+		ret = eemi_ops->clock_setrate(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_CLOCK_GETRATE:
+		ret = eemi_ops->clock_getrate(pm_api_arg[0], &rate);
+		if (!ret)
+			sprintf(debugfs_buf, "Clock rate :%llu\n", rate);
+		break;
+	case PM_CLOCK_SETPARENT:
+		ret = eemi_ops->clock_setparent(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_CLOCK_GETPARENT:
+		ret = eemi_ops->clock_getparent(pm_api_arg[0], &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"Clock parent Index: %u\n", pm_api_ret[0]);
+		break;
+	case PM_QUERY_DATA:
+	{
+		struct zynqmp_pm_query_data qdata = {0};
+
+		qdata.qid = pm_api_arg[0];
+		qdata.arg1 = pm_api_arg[1];
+		qdata.arg2 = pm_api_arg[2];
+		qdata.arg3 = pm_api_arg[3];
+
+		ret = eemi_ops->query_data(qdata, pm_api_ret);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"data[0] = 0x%08x\ndata[1] = 0x%08x\n data[2] = 0x%08x\ndata[3] = 0x%08x\n",
+				pm_api_ret[0], pm_api_ret[1],
+				pm_api_ret[2], pm_api_ret[3]);
+		break;
+	}
+	default:
+		sprintf(debugfs_buf, "Unsupported PM-API request\n");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_debugfs_api_write - debugfs write function
+ * @file:	User file structure
+ * @ptr:	User entered PM-API string
+ * @len:	Length of the userspace buffer
+ * @off:	Offset within the file
+ *
+ * Return:	Number of bytes copied if PM-API request succeeds,
+ *		the corresponding error code otherwise
+ *
+ * Used for triggering pm api functions by writing
+ * echo <pm_api_id>	> /sys/kernel/debug/zynqmp_pm/power or
+ * echo <pm_api_name>	> /sys/kernel/debug/zynqmp_pm/power
+ */
+static ssize_t zynqmp_pm_debugfs_api_write(struct file *file,
+					   const char __user *ptr, size_t len,
+					   loff_t *off)
+{
+	char *kern_buff, *tmp_buff;
+	char *pm_api_req;
+	u32 pm_id = 0;
+	u64 pm_api_arg[4] = {0, 0, 0, 0};
+	/* Return values from PM APIs calls */
+	u32 pm_api_ret[4] = {0, 0, 0, 0};
+
+	int ret;
+	int i = 0;
+
+	strcpy(debugfs_buf, "");
+
+	if (*off != 0 || len == 0)
+		return -EINVAL;
+
+	kern_buff = kzalloc(len, GFP_KERNEL);
+	if (!kern_buff)
+		return -ENOMEM;
+
+	tmp_buff = kern_buff;
+
+	ret = strncpy_from_user(kern_buff, ptr, len);
+	if (ret < 0) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	/* Read the API name from a user request */
+	pm_api_req = strsep(&kern_buff, " ");
+
+	ret = get_pm_api_id(pm_api_req, &pm_id);
+	if (ret < 0)
+		goto err;
+
+	/* Read node_id and arguments from the PM-API request */
+	pm_api_req = strsep(&kern_buff, " ");
+	while ((i < ARRAY_SIZE(pm_api_arg)) && pm_api_req) {
+		pm_api_arg[i++] = zynqmp_pm_argument_value(pm_api_req);
+		pm_api_req = strsep(&kern_buff, " ");
+	}
+
+	ret = process_api_request(pm_id, pm_api_arg, pm_api_ret);
+
+err:
+	kfree(tmp_buff);
+	if (ret)
+		return ret;
+
+	return len;
+}
+
+/**
+ * zynqmp_pm_debugfs_api_read - debugfs read function
+ * @file:	User file structure
+ * @ptr:	Requested pm_api_version string
+ * @len:	Length of the userspace buffer
+ * @off:	Offset within the file
+ *
+ * Return:	Length of the version string on success
+ *		else error code.
+ */
+static ssize_t zynqmp_pm_debugfs_api_read(struct file *file, char __user *ptr,
+					  size_t len, loff_t *off)
+{
+	return simple_read_from_buffer(ptr, len, off, debugfs_buf,
+				       strlen(debugfs_buf));
+}
+
+/* Setup debugfs fops */
+static const struct file_operations fops_zynqmp_pm_dbgfs = {
+	.owner = THIS_MODULE,
+	.write = zynqmp_pm_debugfs_api_write,
+	.read = zynqmp_pm_debugfs_api_read,
+};
+
+/**
+ * zynqmp_pm_api_debugfs_init - Initialize debugfs interface
+ *
+ * Return:	None
+ */
+void zynqmp_pm_api_debugfs_init(void)
+{
+	struct dentry *root_dir;
+
+	/* Initialize debugfs interface */
+	root_dir = debugfs_create_dir("zynqmp-firmware", NULL);
+	debugfs_create_file("pm", 0660, root_dir, NULL,
+			    &fops_zynqmp_pm_dbgfs);
+}
diff --git a/drivers/firmware/xilinx/zynqmp/firmware.c b/drivers/firmware/xilinx/zynqmp/firmware.c
index 02266d9..3bb2c8e 100644
--- a/drivers/firmware/xilinx/zynqmp/firmware.c
+++ b/drivers/firmware/xilinx/zynqmp/firmware.c
@@ -19,6 +19,7 @@
 #include <linux/uaccess.h>
 
 #include <linux/firmware/xilinx/zynqmp/firmware.h>
+#include <linux/firmware/xilinx/zynqmp/firmware-debug.h>
 
 /**
  * zynqmp_pm_ret_code - Convert PMU-FW error codes to Linux error codes
@@ -1055,9 +1056,13 @@ static int zynqmp_firmware_init(void)
 	int ret;
 
 	ret = zynqmp_pm_ggs_init();
-	if (ret)
+	if (ret) {
 		pr_err("%s() GGS init fail with error %d\n",
 		       __func__, ret);
+		return ret;
+	}
+
+	zynqmp_pm_api_debugfs_init();
 
 	return ret;
 }
diff --git a/include/linux/firmware/xilinx/zynqmp/firmware-debug.h b/include/linux/firmware/xilinx/zynqmp/firmware-debug.h
new file mode 100644
index 0000000..eff5b53
--- /dev/null
+++ b/include/linux/firmware/xilinx/zynqmp/firmware-debug.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Xilinx Zynq MPSoC Firmware layer
+ *
+ *  Copyright (C) 2014-2018 Xilinx
+ *
+ *  Michal Simek <michal.simek@xilinx.com>
+ *  Davorin Mista <davorin.mista@aggios.com>
+ *  Jolly Shah <jollys@xilinx.com>
+ *  Rajan Vaja <rajanv@xilinx.com>
+ */
+
+#ifndef __SOC_ZYNQMP_FIRMWARE_DEBUG_H__
+#define __SOC_ZYNQMP_FIRMWARE_DEBUG_H__
+
+#if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE_DEBUG)
+void zynqmp_pm_api_debugfs_init(void);
+#else
+static inline void zynqmp_pm_api_debugfs_init(void) { }
+#endif
+
+#endif /* __SOC_ZYNQMP_FIRMWARE_DEBUG_H__ */
-- 
2.7.4

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

* Re: [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface
  2018-02-20 19:21 ` [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface Jolly Shah
@ 2018-03-01 13:32   ` Michal Simek
  2018-03-01 14:09   ` Andy Shevchenko
  2018-03-01 14:44   ` Sudeep Holla
  2 siblings, 0 replies; 24+ messages in thread
From: Michal Simek @ 2018-03-01 13:32 UTC (permalink / raw)
  To: Jolly Shah, ard.biesheuvel, mingo, gregkh, matt, sudeep.holla,
	hkallweit1, keescook, dmitry.torokhov, michal.simek, robh+dt,
	mark.rutland
  Cc: devicetree, rajanv, linux-kernel, linux-arm-kernel, Jolly Shah


[-- Attachment #1.1: Type: text/plain, Size: 756 bytes --]

On 20.2.2018 20:21, Jolly Shah wrote:
> Add Firmware-ggs sysfs interface which provides read/write
> interface to global storage registers.
> 
> Signed-off-by: Jolly Shah <jollys@xilinx.com>
> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> ---
>  .../ABI/stable/sysfs-driver-zynqmp-firmware        |  50 ++++

This file name has changed between v4 and v5. File from v4 was correct.
That's why I am waiting for v6 to be send before this is applied.

Thanks,
Michal


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

* Re: [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface
  2018-02-20 19:21 ` [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface Jolly Shah
  2018-03-01 13:32   ` Michal Simek
@ 2018-03-01 14:09   ` Andy Shevchenko
  2018-03-01 14:44   ` Sudeep Holla
  2 siblings, 0 replies; 24+ messages in thread
From: Andy Shevchenko @ 2018-03-01 14:09 UTC (permalink / raw)
  To: Jolly Shah
  Cc: Ard Biesheuvel, Ingo Molnar, Greg Kroah-Hartman, Matt Fleming,
	Sudeep Holla, Heiner Kallweit, Kees Cook, Dmitry Torokhov,
	Michal Simek, Rob Herring, Mark Rutland, rajanv,
	linux-arm Mailing List, Linux Kernel Mailing List, devicetree,
	Jolly Shah

On Tue, Feb 20, 2018 at 9:21 PM, Jolly Shah <jolly.shah@xilinx.com> wrote:
> Add Firmware-ggs sysfs interface which provides read/write
> interface to global storage registers.

> +#include <linux/compiler.h>
> +#include <linux/of.h>

> +#include <linux/init.h>
> +#include <linux/module.h>

You need to leave one of them.

> +#include <linux/uaccess.h>
> +#include <linux/slab.h>

> +#include <linux/firmware/xilinx/zynqmp/firmware.h>

Keep it in order? Or add an empty line before?

> +       return sprintf(buf, "0x%x\n", ret_payload[1]);

Hmm... No leading zeroes?

> +static ssize_t write_register(const char *buf, size_t count, u32 read_ioctl,
> +                             u32 write_ioctl, u32 reg)
> +{
> +       char *kern_buff, *inbuf, *tok;
> +       long mask, value;
> +       int ret;
> +       u32 ret_payload[PAYLOAD_ARG_CNT];
> +       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
> +
> +       if (!eemi_ops || !eemi_ops->ioctl)
> +               return -EFAULT;

> +       kern_buff = kzalloc(count, GFP_KERNEL);
> +       if (!kern_buff)
> +               return -ENOMEM;
> +
> +       ret = strlcpy(kern_buff, buf, count);
> +       if (ret < 0) {
> +               ret = -EFAULT;
> +               goto err;
> +       }

kstrndup()

> +
> +       inbuf = kern_buff;
> +
> +       /* Read the write mask */
> +       tok = strsep(&inbuf, " ");
> +       if (!tok) {
> +               ret = -EFAULT;
> +               goto err;
> +       }
> +
> +       ret = kstrtol(tok, 16, &mask);
> +       if (ret) {

> +               ret = -EFAULT;

Why to shadow an error?

> +               goto err;
> +       }
> +
> +       /* Read the write value */
> +       tok = strsep(&inbuf, " ");
> +       if (!tok) {
> +               ret = -EFAULT;
> +               goto err;
> +       }
> +
> +       ret = kstrtol(tok, 16, &value);
> +       if (ret) {

> +               ret = -EFAULT;

Ditto.

> +               goto err;
> +       }
> +
> +       ret = eemi_ops->ioctl(0, read_ioctl, reg, 0, ret_payload);
> +       if (ret) {

> +               ret = -EFAULT;

Ditto.

> +               goto err;
> +       }

> +       ret_payload[1] &= ~mask;
> +       value &= mask;
> +       value |= ret_payload[1];

Also canonical one to write in one line:

      value = (value & mask) | (ret_payload[1] & ~mask);

> +
> +       ret = eemi_ops->ioctl(0, write_ioctl, reg, value, NULL);
> +       if (ret)

> +               ret = -EFAULT;

Why to shadow an error?

> +
> +err:
> +       kfree(kern_buff);


> +       if (ret)
> +               return ret;
> +
> +       return count;

return ret ? ret : count;

> +}

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware
  2018-02-20 19:21 ` [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware Jolly Shah
@ 2018-03-01 14:15   ` Sudeep Holla
  2018-03-07 22:25     ` Jolly Shah
  2018-03-01 21:18   ` Rob Herring
  1 sibling, 1 reply; 24+ messages in thread
From: Sudeep Holla @ 2018-03-01 14:15 UTC (permalink / raw)
  To: Jolly Shah, gregkh, matt, hkallweit1, michal.simek, robh+dt,
	mark.rutland
  Cc: ard.biesheuvel, mingo, keescook, dmitry.torokhov, Sudeep Holla,
	rajanv, linux-arm-kernel, linux-kernel, devicetree, Jolly Shah



On 20/02/18 19:21, Jolly Shah wrote:
> Add documentation to describe Xilinx ZynqMP firmware driver
> bindings. Firmware driver provides an interface to firmware
> APIs. Interface APIs can be used by any driver to communicate
> to PMUFW (Platform Management Unit).
> 
> Signed-off-by: Jolly Shah <jollys@xilinx.com>
> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> ---
>  .../firmware/xilinx/xlnx,zynqmp-firmware.txt       | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
> 
> diff --git a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
> new file mode 100644
> index 0000000..99434ba
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
> @@ -0,0 +1,24 @@
> +Xilinx Zynq MPSoC Firmware Device Tree Bindings
> +
> +The zynqmp-firmware node describes the interface to platform firmware.
> +ZynqMP has an interface to communicate with secure firmware. Firmware
> +driver provides an interface to firmware APIs. Interface APIs can be
> +used by any driver to communicate to PMUFW(Platform Management Unit).
> +These requests include clock management, pin control, device control,
> +power management service, FPGA service and other platform management
> +services.
> +
> +Required properties:
> + - compatible:	Must contain:  "xlnx,zynqmp-firmware"
> + - method:	The method of calling the PM-API firmware layer.
> +		Permitted values are:
> +		  - "smc" : SMC #0, following the SMCCC
> +		  - "hvc" : HVC #0, following the SMCCC
> +
> +Examples:
> +	firmware {
> +		zynqmp_firmware: zynqmp-firmware {
> +			compatible = "xlnx,zynqmp-firmware";
> +			method = "smc";
> +		};
> +	};
> 

Do you foresee using SMC/HVC for this firmware even on future platforms?
If not, I suggest to keep the protocol part separate from the transport
i.e. smc/hvc via ATF. It could be replaced with mailbox or some h/w
mechanism in future ?

-- 
Regards,
Sudeep

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

* Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
  2018-02-20 19:21 ` [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver Jolly Shah
@ 2018-03-01 14:27   ` Sudeep Holla
  2018-03-07  0:44     ` Jolly Shah
  2018-03-14 13:22   ` Greg KH
  1 sibling, 1 reply; 24+ messages in thread
From: Sudeep Holla @ 2018-03-01 14:27 UTC (permalink / raw)
  To: Jolly Shah, michal.simek
  Cc: ard.biesheuvel, mingo, gregkh, matt, hkallweit1, keescook,
	dmitry.torokhov, robh+dt, mark.rutland, Sudeep Holla, rajanv,
	linux-arm-kernel, linux-kernel, devicetree, Jolly Shah



On 20/02/18 19:21, Jolly Shah wrote:
> This patch is adding communication layer with firmware.
> Firmware driver provides an interface to firmware APIs.
> Interface APIs can be used by any driver to communicate to
> PMUFW(Platform Management Unit). All requests go through ATF.
> 
> Signed-off-by: Jolly Shah <jollys@xilinx.com>
> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> ---
>  arch/arm64/Kconfig.platforms                    |    1 +
>  drivers/firmware/Kconfig                        |    1 +
>  drivers/firmware/Makefile                       |    1 +
>  drivers/firmware/xilinx/Kconfig                 |    4 +
>  drivers/firmware/xilinx/Makefile                |    4 +
>  drivers/firmware/xilinx/zynqmp/Kconfig          |   16 +
>  drivers/firmware/xilinx/zynqmp/Makefile         |    4 +
>  drivers/firmware/xilinx/zynqmp/firmware.c       | 1051 +++++++++++++++++++++++
>  include/linux/firmware/xilinx/zynqmp/firmware.h |  590 +++++++++++++
>  9 files changed, 1672 insertions(+)
>  create mode 100644 drivers/firmware/xilinx/Kconfig
>  create mode 100644 drivers/firmware/xilinx/Makefile
>  create mode 100644 drivers/firmware/xilinx/zynqmp/Kconfig
>  create mode 100644 drivers/firmware/xilinx/zynqmp/Makefile
>  create mode 100644 drivers/firmware/xilinx/zynqmp/firmware.c
>  create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware.h
> 
> +
> +/**
> + * zynqmp_pm_force_powerdown - PM call to request for another PU or subsystem to
> + *				be powered down forcefully
> + * @target:	Node ID of the targeted PU or subsystem
> + * @ack:	Flag to specify whether acknowledge is requested
> + *
> + * Return:	Returns status, either success or error+reason
> + */
> +static int zynqmp_pm_force_powerdown(const u32 target,
> +				     const enum zynqmp_pm_request_ack ack)
> +{
> +	return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, target, ack, 0, 0, NULL);
> +}
> +

[...]

> +/**
> + * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
> + * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
> + * @subtype:	Specifies which system should be restarted or shut down
> + *
> + * Return:	Returns status, either success or error+reason
> + */
> +static int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
> +{
> +	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
> +				   0, 0, NULL);
> +}
> +

I can't understand why you need above 2 APIs: PM_FORCE_POWERDOWN and
PM_SYSTEM_SHUTDOWN. You should use PSCI_SYSTEM_OFF and PSCI_SYSTEM_RESET
and drop these two.


> +static const struct zynqmp_eemi_ops eemi_ops = {
> +	.get_api_version = zynqmp_pm_get_api_version,
> +	.get_chipid = zynqmp_pm_get_chipid,
> +	.reset_assert = zynqmp_pm_reset_assert,
> +	.reset_get_status = zynqmp_pm_reset_get_status,
> +	.fpga_load = zynqmp_pm_fpga_load,
> +	.fpga_get_status = zynqmp_pm_fpga_get_status,
> +	.sha_hash = zynqmp_pm_sha_hash,
> +	.rsa = zynqmp_pm_rsa,
> +	.request_suspend = zynqmp_pm_request_suspend,
> +	.force_powerdown = zynqmp_pm_force_powerdown,
> +	.request_wakeup = zynqmp_pm_request_wakeup,
> +	.set_wakeup_source = zynqmp_pm_set_wakeup_source,
> +	.system_shutdown = zynqmp_pm_system_shutdown,
> +	.request_node = zynqmp_pm_request_node,
> +	.release_node = zynqmp_pm_release_node,
> +	.set_requirement = zynqmp_pm_set_requirement,
> +	.set_max_latency = zynqmp_pm_set_max_latency,
> +	.set_configuration = zynqmp_pm_set_configuration,
> +	.get_node_status = zynqmp_pm_get_node_status,
> +	.get_operating_characteristic = zynqmp_pm_get_operating_characteristic,
> +	.init_finalize = zynqmp_pm_init_finalize,
> +	.set_suspend_mode = zynqmp_pm_set_suspend_mode,
> +	.ioctl = zynqmp_pm_ioctl,
> +	.query_data = zynqmp_pm_query_data,
> +	.pinctrl_request = zynqmp_pm_pinctrl_request,
> +	.pinctrl_release = zynqmp_pm_pinctrl_release,
> +	.pinctrl_get_function = zynqmp_pm_pinctrl_get_function,
> +	.pinctrl_set_function = zynqmp_pm_pinctrl_set_function,
> +	.pinctrl_get_config = zynqmp_pm_pinctrl_get_config,
> +	.pinctrl_set_config = zynqmp_pm_pinctrl_set_config,
> +	.clock_enable = zynqmp_pm_clock_enable,
> +	.clock_disable = zynqmp_pm_clock_disable,
> +	.clock_getstate = zynqmp_pm_clock_getstate,
> +	.clock_setdivider = zynqmp_pm_clock_setdivider,
> +	.clock_getdivider = zynqmp_pm_clock_getdivider,
> +	.clock_setrate = zynqmp_pm_clock_setrate,
> +	.clock_getrate = zynqmp_pm_clock_getrate,
> +	.clock_setparent = zynqmp_pm_clock_setparent,
> +	.clock_getparent = zynqmp_pm_clock_getparent,
> +};
> +
Instead of introducing all these in oneshot, add them as you have users
of it. IOW, show the users of these functions in the series. Also I
asked to split this into functional changes like clock, pinctrl, power, etc.

-- 
Regards,
Sudeep

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

* Re: [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface
  2018-02-20 19:21 ` [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface Jolly Shah
  2018-03-01 13:32   ` Michal Simek
  2018-03-01 14:09   ` Andy Shevchenko
@ 2018-03-01 14:44   ` Sudeep Holla
  2018-03-07 22:03     ` Jolly Shah
  2 siblings, 1 reply; 24+ messages in thread
From: Sudeep Holla @ 2018-03-01 14:44 UTC (permalink / raw)
  To: Jolly Shah
  Cc: ard.biesheuvel, mingo, gregkh, matt, hkallweit1, keescook,
	dmitry.torokhov, michal.simek, robh+dt, mark.rutland,
	Sudeep Holla, rajanv, linux-arm-kernel, linux-kernel, devicetree,
	Jolly Shah



On 20/02/18 19:21, Jolly Shah wrote:
> Add Firmware-ggs sysfs interface which provides read/write
> interface to global storage registers.
> 
> Signed-off-by: Jolly Shah <jollys@xilinx.com>
> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> ---
>  .../ABI/stable/sysfs-driver-zynqmp-firmware        |  50 ++++
>  drivers/firmware/xilinx/zynqmp/Makefile            |   2 +-
>  drivers/firmware/xilinx/zynqmp/firmware-ggs.c      | 297 +++++++++++++++++++++
>  drivers/firmware/xilinx/zynqmp/firmware.c          |  13 +
>  include/linux/firmware/xilinx/zynqmp/firmware.h    |   2 +
>  5 files changed, 363 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
>  create mode 100644 drivers/firmware/xilinx/zynqmp/firmware-ggs.c
> 
> diff --git a/Documentation/ABI/stable/sysfs-driver-zynqmp-firmware b/Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
> new file mode 100644
> index 0000000..b04727a
> --- /dev/null
> +++ b/Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
> @@ -0,0 +1,50 @@
> +What:		/sys/devices/platform/zynqmp-firmware/ggs> +Date:		January 2018
> +KernelVersion:	4.15.0
> +Contact:	"Jolly Shah" <jollys@xilinx.com>
> +Description:
> +		Read/Write PMU global general storage register value,
> +		GLOBAL_GEN_STORAGE{0:3}.
> +		Global general storage register that can be used
> +		by system to pass information between masters.
> +

What kind of information ? Is there any semantics for that ?
Why does EEMI lack APIs for that if it's critical, giving access to
such information to userspace may not be good idea.

> +		The register is reset during system or power-on
> +		resets. Three registers are used by the FSBL and
> +		other Xilinx software products: GLOBAL_GEN_STORAGE{4:6}.
> +

FSBL ?

For what is it used ?

> +		Usage:
> +		# cat /sys/.../zynqmp-firmware/ggs0
> +		# echo <mask> <value> > /sys/.../zynqmp-firmware/ggs0
> +
> +		Example:
> +		# cat /sys/.../zynqmp-firmware/ggs0
> +		# echo 0xFFFFFFFF 0x1234ABCD > /sys/.../zynqmp-firmware/ggs0
> +
> +Users:		Xilinx
> +
> +What:		/sys/devices/platform/zynqmp-firmware/pggs*
> +Date:		January 2018
> +KernelVersion:	4.15.0
> +Contact:	"Jolly Shah" <jollys@xilinx.com>
> +Description:
> +		Read/Write PMU persistent global general storage register
> +		value, PERS_GLOB_GEN_STORAGE{0:3}.
> +		Persistent global general storage register that
> +		can be used by system to pass information between
> +		masters.
> +

Ditto

> +		This register is only reset by the power-on reset
> +		and maintains its value through a system reset.
> +		Four registers are used by the FSBL and other Xilinx
> +		software products: PERS_GLOB_GEN_STORAGE{4:7}.
> +		Register is reset only by a POR reset.
> +

Ditto

-- 
Regards,
Sudeep

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

* Re: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware
  2018-02-20 19:21 ` [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware Jolly Shah
  2018-03-01 14:15   ` Sudeep Holla
@ 2018-03-01 21:18   ` Rob Herring
  1 sibling, 0 replies; 24+ messages in thread
From: Rob Herring @ 2018-03-01 21:18 UTC (permalink / raw)
  To: Jolly Shah
  Cc: ard.biesheuvel, mingo, gregkh, matt, sudeep.holla, hkallweit1,
	keescook, dmitry.torokhov, michal.simek, mark.rutland,
	devicetree, rajanv, linux-kernel, linux-arm-kernel, Jolly Shah

On Tue, Feb 20, 2018 at 11:21:04AM -0800, Jolly Shah wrote:
> Add documentation to describe Xilinx ZynqMP firmware driver
> bindings. Firmware driver provides an interface to firmware
> APIs. Interface APIs can be used by any driver to communicate
> to PMUFW (Platform Management Unit).
> 
> Signed-off-by: Jolly Shah <jollys@xilinx.com>
> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> ---
>  .../firmware/xilinx/xlnx,zynqmp-firmware.txt       | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt

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

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

* RE: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
  2018-03-01 14:27   ` Sudeep Holla
@ 2018-03-07  0:44     ` Jolly Shah
  2018-03-08 12:18       ` Sudeep Holla
  0 siblings, 1 reply; 24+ messages in thread
From: Jolly Shah @ 2018-03-07  0:44 UTC (permalink / raw)
  To: Sudeep Holla, michal.simek
  Cc: ard.biesheuvel, mingo, gregkh, matt, hkallweit1, keescook,
	dmitry.torokhov, robh+dt, mark.rutland, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree

Hi Sudeep,

Thanks for the review,

> -----Original Message-----
> From: Sudeep Holla [mailto:sudeep.holla@arm.com]
> Sent: Thursday, March 01, 2018 6:28 AM
> To: Jolly Shah <JOLLYS@xilinx.com>; michal.simek@xilinx.com
> Cc: ard.biesheuvel@linaro.org; mingo@kernel.org;
> gregkh@linuxfoundation.org; matt@codeblueprint.co.uk;
> hkallweit1@gmail.com; keescook@chromium.org;
> dmitry.torokhov@gmail.com; robh+dt@kernel.org; mark.rutland@arm.com;
> Sudeep Holla <sudeep.holla@arm.com>; Rajan Vaja <RAJANV@xilinx.com>;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> devicetree@vger.kernel.org; Jolly Shah <JOLLYS@xilinx.com>
> Subject: Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware
> driver
> 
> 
> 
> On 20/02/18 19:21, Jolly Shah wrote:
> > This patch is adding communication layer with firmware.
> > Firmware driver provides an interface to firmware APIs.
> > Interface APIs can be used by any driver to communicate to
> > PMUFW(Platform Management Unit). All requests go through ATF.
> >
> > Signed-off-by: Jolly Shah <jollys@xilinx.com>
> > Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> > ---
> >  arch/arm64/Kconfig.platforms                    |    1 +
> >  drivers/firmware/Kconfig                        |    1 +
> >  drivers/firmware/Makefile                       |    1 +
> >  drivers/firmware/xilinx/Kconfig                 |    4 +
> >  drivers/firmware/xilinx/Makefile                |    4 +
> >  drivers/firmware/xilinx/zynqmp/Kconfig          |   16 +
> >  drivers/firmware/xilinx/zynqmp/Makefile         |    4 +
> >  drivers/firmware/xilinx/zynqmp/firmware.c       | 1051
> +++++++++++++++++++++++
> >  include/linux/firmware/xilinx/zynqmp/firmware.h |  590 +++++++++++++
> >  9 files changed, 1672 insertions(+)
> >  create mode 100644 drivers/firmware/xilinx/Kconfig  create mode
> > 100644 drivers/firmware/xilinx/Makefile  create mode 100644
> > drivers/firmware/xilinx/zynqmp/Kconfig
> >  create mode 100644 drivers/firmware/xilinx/zynqmp/Makefile
> >  create mode 100644 drivers/firmware/xilinx/zynqmp/firmware.c
> >  create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware.h
> >
> > +
> > +/**
> > + * zynqmp_pm_force_powerdown - PM call to request for another PU or
> subsystem to
> > + *				be powered down forcefully
> > + * @target:	Node ID of the targeted PU or subsystem
> > + * @ack:	Flag to specify whether acknowledge is requested
> > + *
> > + * Return:	Returns status, either success or error+reason
> > + */
> > +static int zynqmp_pm_force_powerdown(const u32 target,
> > +				     const enum zynqmp_pm_request_ack ack) {
> > +	return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, target, ack,
> 0, 0,
> > +NULL); }
> > +
> 
> [...]
> 
> > +/**
> > + * zynqmp_pm_system_shutdown - PM call to request a system shutdown or
> restart
> > + * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
> > + * @subtype:	Specifies which system should be restarted or shut down
> > + *
> > + * Return:	Returns status, either success or error+reason
> > + */
> > +static int zynqmp_pm_system_shutdown(const u32 type, const u32
> > +subtype) {
> > +	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
> > +				   0, 0, NULL);
> > +}
> > +
> 
> I can't understand why you need above 2 APIs: PM_FORCE_POWERDOWN and
> PM_SYSTEM_SHUTDOWN. You should use PSCI_SYSTEM_OFF and
> PSCI_SYSTEM_RESET and drop these two.
> 

FORCE_POWERDOWN allows remote master to force power off other node/domain.
SYSTEM_SHUTDOWN provides interface to shutdown/restart the subsystem. It supports system/subsystem restart with argument value. PSCI doesn’t support argument to identify between restart types.

> 
> > +static const struct zynqmp_eemi_ops eemi_ops = {
> > +	.get_api_version = zynqmp_pm_get_api_version,
> > +	.get_chipid = zynqmp_pm_get_chipid,
> > +	.reset_assert = zynqmp_pm_reset_assert,
> > +	.reset_get_status = zynqmp_pm_reset_get_status,
> > +	.fpga_load = zynqmp_pm_fpga_load,
> > +	.fpga_get_status = zynqmp_pm_fpga_get_status,
> > +	.sha_hash = zynqmp_pm_sha_hash,
> > +	.rsa = zynqmp_pm_rsa,
> > +	.request_suspend = zynqmp_pm_request_suspend,
> > +	.force_powerdown = zynqmp_pm_force_powerdown,
> > +	.request_wakeup = zynqmp_pm_request_wakeup,
> > +	.set_wakeup_source = zynqmp_pm_set_wakeup_source,
> > +	.system_shutdown = zynqmp_pm_system_shutdown,
> > +	.request_node = zynqmp_pm_request_node,
> > +	.release_node = zynqmp_pm_release_node,
> > +	.set_requirement = zynqmp_pm_set_requirement,
> > +	.set_max_latency = zynqmp_pm_set_max_latency,
> > +	.set_configuration = zynqmp_pm_set_configuration,
> > +	.get_node_status = zynqmp_pm_get_node_status,
> > +	.get_operating_characteristic =
> zynqmp_pm_get_operating_characteristic,
> > +	.init_finalize = zynqmp_pm_init_finalize,
> > +	.set_suspend_mode = zynqmp_pm_set_suspend_mode,
> > +	.ioctl = zynqmp_pm_ioctl,
> > +	.query_data = zynqmp_pm_query_data,
> > +	.pinctrl_request = zynqmp_pm_pinctrl_request,
> > +	.pinctrl_release = zynqmp_pm_pinctrl_release,
> > +	.pinctrl_get_function = zynqmp_pm_pinctrl_get_function,
> > +	.pinctrl_set_function = zynqmp_pm_pinctrl_set_function,
> > +	.pinctrl_get_config = zynqmp_pm_pinctrl_get_config,
> > +	.pinctrl_set_config = zynqmp_pm_pinctrl_set_config,
> > +	.clock_enable = zynqmp_pm_clock_enable,
> > +	.clock_disable = zynqmp_pm_clock_disable,
> > +	.clock_getstate = zynqmp_pm_clock_getstate,
> > +	.clock_setdivider = zynqmp_pm_clock_setdivider,
> > +	.clock_getdivider = zynqmp_pm_clock_getdivider,
> > +	.clock_setrate = zynqmp_pm_clock_setrate,
> > +	.clock_getrate = zynqmp_pm_clock_getrate,
> > +	.clock_setparent = zynqmp_pm_clock_setparent,
> > +	.clock_getparent = zynqmp_pm_clock_getparent, };
> > +
> Instead of introducing all these in oneshot, add them as you have users of it.
> IOW, show the users of these functions in the series. Also I asked to split this
> into functional changes like clock, pinctrl, power, etc.

It can be split into functional changes in same series but it will be difficult to split between users as there are more than 10 driver users for different EEMI APIs and also multiple driver users using specifc EEMI APIs. They all can't be submitted as single series. 

> 
> --
> Regards,
> Sudeep

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

* RE: [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface
  2018-03-01 14:44   ` Sudeep Holla
@ 2018-03-07 22:03     ` Jolly Shah
  0 siblings, 0 replies; 24+ messages in thread
From: Jolly Shah @ 2018-03-07 22:03 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ard.biesheuvel, mingo, gregkh, matt, hkallweit1, keescook,
	dmitry.torokhov, michal.simek, robh+dt, mark.rutland, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree

Hi Sudeep,


> -----Original Message-----
> From: Sudeep Holla [mailto:sudeep.holla@arm.com]
> Sent: Thursday, March 01, 2018 6:44 AM
> To: Jolly Shah <JOLLYS@xilinx.com>
> Cc: ard.biesheuvel@linaro.org; mingo@kernel.org;
> gregkh@linuxfoundation.org; matt@codeblueprint.co.uk;
> hkallweit1@gmail.com; keescook@chromium.org;
> dmitry.torokhov@gmail.com; michal.simek@xilinx.com; robh+dt@kernel.org;
> mark.rutland@arm.com; Sudeep Holla <sudeep.holla@arm.com>; Rajan Vaja
> <RAJANV@xilinx.com>; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org; devicetree@vger.kernel.org; Jolly Shah
> <JOLLYS@xilinx.com>
> Subject: Re: [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface
> 
> 
> 
> On 20/02/18 19:21, Jolly Shah wrote:
> > Add Firmware-ggs sysfs interface which provides read/write interface
> > to global storage registers.
> >
> > Signed-off-by: Jolly Shah <jollys@xilinx.com>
> > Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> > ---
> >  .../ABI/stable/sysfs-driver-zynqmp-firmware        |  50 ++++
> >  drivers/firmware/xilinx/zynqmp/Makefile            |   2 +-
> >  drivers/firmware/xilinx/zynqmp/firmware-ggs.c      | 297
> +++++++++++++++++++++
> >  drivers/firmware/xilinx/zynqmp/firmware.c          |  13 +
> >  include/linux/firmware/xilinx/zynqmp/firmware.h    |   2 +
> >  5 files changed, 363 insertions(+), 1 deletion(-)  create mode 100644
> > Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
> >  create mode 100644 drivers/firmware/xilinx/zynqmp/firmware-ggs.c
> >
> > diff --git a/Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
> > b/Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
> > new file mode 100644
> > index 0000000..b04727a
> > --- /dev/null
> > +++ b/Documentation/ABI/stable/sysfs-driver-zynqmp-firmware
> > @@ -0,0 +1,50 @@
> > +What:		/sys/devices/platform/zynqmp-firmware/ggs> +Date:
> 		January 2018
> > +KernelVersion:	4.15.0
> > +Contact:	"Jolly Shah" <jollys@xilinx.com>
> > +Description:
> > +		Read/Write PMU global general storage register value,
> > +		GLOBAL_GEN_STORAGE{0:3}.
> > +		Global general storage register that can be used
> > +		by system to pass information between masters.
> > +
> 
> What kind of information ? Is there any semantics for that ?
> Why does EEMI lack APIs for that if it's critical, giving access to such information
> to userspace may not be good idea.
> 	

These are for general use. Information being passed can be application specific.
Sysfs call underneath maps to EEMI ioctl call to read/write these registers.

> > +		The register is reset during system or power-on
> > +		resets. Three registers are used by the FSBL and
> > +		other Xilinx software products: GLOBAL_GEN_STORAGE{4:6}.
> > +
> 
> FSBL ?
> 
> For what is it used ?

There are total 8 such registers. 4 are reserved for customer application. Other 4 are being used by Xilinx sw products like FSBL.
FSBL is using it to pass handoff information to other master.

> 
> > +		Usage:
> > +		# cat /sys/.../zynqmp-firmware/ggs0
> > +		# echo <mask> <value> > /sys/.../zynqmp-firmware/ggs0
> > +
> > +		Example:
> > +		# cat /sys/.../zynqmp-firmware/ggs0
> > +		# echo 0xFFFFFFFF 0x1234ABCD > /sys/.../zynqmp-
> firmware/ggs0
> > +
> > +Users:		Xilinx
> > +
> > +What:		/sys/devices/platform/zynqmp-firmware/pggs*
> > +Date:		January 2018
> > +KernelVersion:	4.15.0
> > +Contact:	"Jolly Shah" <jollys@xilinx.com>
> > +Description:
> > +		Read/Write PMU persistent global general storage register
> > +		value, PERS_GLOB_GEN_STORAGE{0:3}.
> > +		Persistent global general storage register that
> > +		can be used by system to pass information between
> > +		masters.
> > +
> 
> Ditto
> 
> > +		This register is only reset by the power-on reset
> > +		and maintains its value through a system reset.
> > +		Four registers are used by the FSBL and other Xilinx
> > +		software products: PERS_GLOB_GEN_STORAGE{4:7}.
> > +		Register is reset only by a POR reset.
> > +
> 
> Ditto
> 
> --
> Regards,
> Sudeep

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

* RE: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware
  2018-03-01 14:15   ` Sudeep Holla
@ 2018-03-07 22:25     ` Jolly Shah
  2018-03-08 11:48       ` Sudeep Holla
  0 siblings, 1 reply; 24+ messages in thread
From: Jolly Shah @ 2018-03-07 22:25 UTC (permalink / raw)
  To: Sudeep Holla, gregkh, matt, hkallweit1, michal.simek, robh+dt,
	mark.rutland
  Cc: ard.biesheuvel, mingo, keescook, dmitry.torokhov, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree

Hi Sudeep,

> -----Original Message-----
> From: Sudeep Holla [mailto:sudeep.holla@arm.com]
> Sent: Thursday, March 01, 2018 6:15 AM
> To: Jolly Shah <JOLLYS@xilinx.com>; gregkh@linuxfoundation.org;
> matt@codeblueprint.co.uk; hkallweit1@gmail.com; michal.simek@xilinx.com;
> robh+dt@kernel.org; mark.rutland@arm.com
> Cc: ard.biesheuvel@linaro.org; mingo@kernel.org; keescook@chromium.org;
> dmitry.torokhov@gmail.com; Sudeep Holla <sudeep.holla@arm.com>; Rajan
> Vaja <RAJANV@xilinx.com>; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org; devicetree@vger.kernel.org; Jolly Shah
> <JOLLYS@xilinx.com>
> Subject: Re: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP
> firmware
> 
> 
> 
> On 20/02/18 19:21, Jolly Shah wrote:
> > Add documentation to describe Xilinx ZynqMP firmware driver bindings.
> > Firmware driver provides an interface to firmware APIs. Interface APIs
> > can be used by any driver to communicate to PMUFW (Platform Management
> > Unit).
> >
> > Signed-off-by: Jolly Shah <jollys@xilinx.com>
> > Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> > ---
> >  .../firmware/xilinx/xlnx,zynqmp-firmware.txt       | 24
> ++++++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware
> > .txt
> >
> > diff --git
> > a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmwa
> > re.txt
> > b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmwa
> > re.txt
> > new file mode 100644
> > index 0000000..99434ba
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-fi
> > +++ rmware.txt
> > @@ -0,0 +1,24 @@
> > +Xilinx Zynq MPSoC Firmware Device Tree Bindings
> > +
> > +The zynqmp-firmware node describes the interface to platform firmware.
> > +ZynqMP has an interface to communicate with secure firmware. Firmware
> > +driver provides an interface to firmware APIs. Interface APIs can be
> > +used by any driver to communicate to PMUFW(Platform Management Unit).
> > +These requests include clock management, pin control, device control,
> > +power management service, FPGA service and other platform management
> > +services.
> > +
> > +Required properties:
> > + - compatible:	Must contain:  "xlnx,zynqmp-firmware"
> > + - method:	The method of calling the PM-API firmware layer.
> > +		Permitted values are:
> > +		  - "smc" : SMC #0, following the SMCCC
> > +		  - "hvc" : HVC #0, following the SMCCC
> > +
> > +Examples:
> > +	firmware {
> > +		zynqmp_firmware: zynqmp-firmware {
> > +			compatible = "xlnx,zynqmp-firmware";
> > +			method = "smc";
> > +		};
> > +	};
> >
> 
> Do you foresee using SMC/HVC for this firmware even on future platforms?
> If not, I suggest to keep the protocol part separate from the transport i.e.
> smc/hvc via ATF. It could be replaced with mailbox or some h/w mechanism in
> future ?
> 

We have PSCI and EEMI interfaces exposed to linux from ATF.  PSCI is an EEMI client. We do not have current plans to switch to mailbox as it will require 2 communication channels to PMU as PSCI is through ATF. 

> --
> Regards,
> Sudeep

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

* Re: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware
  2018-03-07 22:25     ` Jolly Shah
@ 2018-03-08 11:48       ` Sudeep Holla
  2018-03-12 23:07         ` Jolly Shah
  0 siblings, 1 reply; 24+ messages in thread
From: Sudeep Holla @ 2018-03-08 11:48 UTC (permalink / raw)
  To: Jolly Shah
  Cc: gregkh, matt, hkallweit1, michal.simek, robh+dt, mark.rutland,
	Sudeep Holla, ard.biesheuvel, mingo, keescook, dmitry.torokhov,
	Rajan Vaja, linux-arm-kernel, linux-kernel, devicetree



On 07/03/18 22:25, Jolly Shah wrote:
> Hi Sudeep,
> 

[...]

>>> +Examples:
>>> +	firmware {
>>> +		zynqmp_firmware: zynqmp-firmware {
>>> +			compatible = "xlnx,zynqmp-firmware";
>>> +			method = "smc";
>>> +		};
>>> +	};
>>>
>>
>> Do you foresee using SMC/HVC for this firmware even on future platforms?
>> If not, I suggest to keep the protocol part separate from the transport i.e.
>> smc/hvc via ATF. It could be replaced with mailbox or some h/w mechanism in
>> future ?
>>
> 
> We have PSCI and EEMI interfaces exposed to linux from ATF. PSCI is
> an EEMI client. We do not have current plans to switch to mailbox as it
> will require 2 communication channels to PMU as PSCI is through ATF.
> 

OK, but I just saw some bindings that has mailbox interface, honestly
it's getting too confusing with multiple series on the same thing
floating and hence I requested to put it together as one series.
-- 
Regards,
Sudeep

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

* Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
  2018-03-07  0:44     ` Jolly Shah
@ 2018-03-08 12:18       ` Sudeep Holla
  2018-03-12 23:05         ` Jolly Shah
  0 siblings, 1 reply; 24+ messages in thread
From: Sudeep Holla @ 2018-03-08 12:18 UTC (permalink / raw)
  To: Jolly Shah, michal.simek
  Cc: Sudeep Holla, ard.biesheuvel, mingo, gregkh, matt, hkallweit1,
	keescook, dmitry.torokhov, robh+dt, mark.rutland, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree



On 07/03/18 00:44, Jolly Shah wrote:
> Hi Sudeep,
> 
> Thanks for the review,
> 
>> -----Original Message-----
>> From: Sudeep Holla [mailto:sudeep.holla@arm.com]
>> Sent: Thursday, March 01, 2018 6:28 AM
>> To: Jolly Shah <JOLLYS@xilinx.com>; michal.simek@xilinx.com
>> Cc: ard.biesheuvel@linaro.org; mingo@kernel.org;
>> gregkh@linuxfoundation.org; matt@codeblueprint.co.uk;
>> hkallweit1@gmail.com; keescook@chromium.org;
>> dmitry.torokhov@gmail.com; robh+dt@kernel.org; mark.rutland@arm.com;
>> Sudeep Holla <sudeep.holla@arm.com>; Rajan Vaja <RAJANV@xilinx.com>;
>> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
>> devicetree@vger.kernel.org; Jolly Shah <JOLLYS@xilinx.com>
>> Subject: Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware
>> driver
>>
>>
>>
>> On 20/02/18 19:21, Jolly Shah wrote:
>>> This patch is adding communication layer with firmware.
>>> Firmware driver provides an interface to firmware APIs.
>>> Interface APIs can be used by any driver to communicate to
>>> PMUFW(Platform Management Unit). All requests go through ATF.
>>>
>>> Signed-off-by: Jolly Shah <jollys@xilinx.com>
>>> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
>>> ---
>>>  arch/arm64/Kconfig.platforms                    |    1 +
>>>  drivers/firmware/Kconfig                        |    1 +
>>>  drivers/firmware/Makefile                       |    1 +
>>>  drivers/firmware/xilinx/Kconfig                 |    4 +
>>>  drivers/firmware/xilinx/Makefile                |    4 +
>>>  drivers/firmware/xilinx/zynqmp/Kconfig          |   16 +
>>>  drivers/firmware/xilinx/zynqmp/Makefile         |    4 +
>>>  drivers/firmware/xilinx/zynqmp/firmware.c       | 1051
>> +++++++++++++++++++++++
>>>  include/linux/firmware/xilinx/zynqmp/firmware.h |  590 +++++++++++++
>>>  9 files changed, 1672 insertions(+)
>>>  create mode 100644 drivers/firmware/xilinx/Kconfig  create mode
>>> 100644 drivers/firmware/xilinx/Makefile  create mode 100644
>>> drivers/firmware/xilinx/zynqmp/Kconfig
>>>  create mode 100644 drivers/firmware/xilinx/zynqmp/Makefile
>>>  create mode 100644 drivers/firmware/xilinx/zynqmp/firmware.c
>>>  create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware.h
>>>
>>> +
>>> +/**
>>> + * zynqmp_pm_force_powerdown - PM call to request for another PU or
>> subsystem to
>>> + *				be powered down forcefully
>>> + * @target:	Node ID of the targeted PU or subsystem
>>> + * @ack:	Flag to specify whether acknowledge is requested
>>> + *
>>> + * Return:	Returns status, either success or error+reason
>>> + */
>>> +static int zynqmp_pm_force_powerdown(const u32 target,
>>> +				     const enum zynqmp_pm_request_ack ack) {
>>> +	return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, target, ack,
>> 0, 0,
>>> +NULL); }
>>> +
>>
>> [...]
>>
>>> +/**
>>> + * zynqmp_pm_system_shutdown - PM call to request a system shutdown or
>> restart
>>> + * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
>>> + * @subtype:	Specifies which system should be restarted or shut down
>>> + *
>>> + * Return:	Returns status, either success or error+reason
>>> + */
>>> +static int zynqmp_pm_system_shutdown(const u32 type, const u32
>>> +subtype) {
>>> +	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
>>> +				   0, 0, NULL);
>>> +}
>>> +
>>
>> I can't understand why you need above 2 APIs: PM_FORCE_POWERDOWN and
>> PM_SYSTEM_SHUTDOWN. You should use PSCI_SYSTEM_OFF and
>> PSCI_SYSTEM_RESET and drop these two.
>>
> 
> FORCE_POWERDOWN allows remote master to force power off other
> node/domain. SYSTEM_SHUTDOWN provides interface to shutdown/restart
> the subsystem. It supports system/subsystem restart with argument value.> PSCI doesn’t
support argument to identify between restart types.

OK, what are the types you are referring here ? or why PSCI is not
sufficient ? How do you plan to use these APIs in Linux ?

>>
>>> +static const struct zynqmp_eemi_ops eemi_ops = {
>>> +	.get_api_version = zynqmp_pm_get_api_version,
>>> +	.get_chipid = zynqmp_pm_get_chipid,
>>> +	.reset_assert = zynqmp_pm_reset_assert,
>>> +	.reset_get_status = zynqmp_pm_reset_get_status,
>>> +	.fpga_load = zynqmp_pm_fpga_load,
>>> +	.fpga_get_status = zynqmp_pm_fpga_get_status,
>>> +	.sha_hash = zynqmp_pm_sha_hash,
>>> +	.rsa = zynqmp_pm_rsa,
>>> +	.request_suspend = zynqmp_pm_request_suspend,
>>> +	.force_powerdown = zynqmp_pm_force_powerdown,
>>> +	.request_wakeup = zynqmp_pm_request_wakeup,
>>> +	.set_wakeup_source = zynqmp_pm_set_wakeup_source,
>>> +	.system_shutdown = zynqmp_pm_system_shutdown,
>>> +	.request_node = zynqmp_pm_request_node,
>>> +	.release_node = zynqmp_pm_release_node,
>>> +	.set_requirement = zynqmp_pm_set_requirement,
>>> +	.set_max_latency = zynqmp_pm_set_max_latency,
>>> +	.set_configuration = zynqmp_pm_set_configuration,
>>> +	.get_node_status = zynqmp_pm_get_node_status,
>>> +	.get_operating_characteristic =
>> zynqmp_pm_get_operating_characteristic,
>>> +	.init_finalize = zynqmp_pm_init_finalize,
>>> +	.set_suspend_mode = zynqmp_pm_set_suspend_mode,
>>> +	.ioctl = zynqmp_pm_ioctl,
>>> +	.query_data = zynqmp_pm_query_data,
>>> +	.pinctrl_request = zynqmp_pm_pinctrl_request,
>>> +	.pinctrl_release = zynqmp_pm_pinctrl_release,
>>> +	.pinctrl_get_function = zynqmp_pm_pinctrl_get_function,
>>> +	.pinctrl_set_function = zynqmp_pm_pinctrl_set_function,
>>> +	.pinctrl_get_config = zynqmp_pm_pinctrl_get_config,
>>> +	.pinctrl_set_config = zynqmp_pm_pinctrl_set_config,
>>> +	.clock_enable = zynqmp_pm_clock_enable,
>>> +	.clock_disable = zynqmp_pm_clock_disable,
>>> +	.clock_getstate = zynqmp_pm_clock_getstate,
>>> +	.clock_setdivider = zynqmp_pm_clock_setdivider,
>>> +	.clock_getdivider = zynqmp_pm_clock_getdivider,
>>> +	.clock_setrate = zynqmp_pm_clock_setrate,
>>> +	.clock_getrate = zynqmp_pm_clock_getrate,
>>> +	.clock_setparent = zynqmp_pm_clock_setparent,
>>> +	.clock_getparent = zynqmp_pm_clock_getparent, };
>>> +
>> Instead of introducing all these in oneshot, add them as you have users of it.
>> IOW, show the users of these functions in the series. Also I asked to split this
>> into functional changes like clock, pinctrl, power, etc.
> 
> It can be split into functional changes in same series but it will be
> difficult to split between users as there are more than 10 driver
> users for different EEMI APIs and also multiple driver users using
> specifc EEMI APIs. They all can't be submitted as single series.
> 

Why ? Start with basic EEMI and one functionality with it's user/client
driver in one series. Then you can top up with EEMI changes for other
functionality with it's user. If you introduce API's without the users
in a series it's hard to review and if there are more such unused APIs
I will object it in future versions.

To start with add only clock or power APIs and functionality in this
series, add drivers using then. Drop other functionalities like pinctrl,
fpga control and other functionalities. IOW start something basic and
simple.

-- 
Regards,
Sudeep

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

* RE: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
  2018-03-08 12:18       ` Sudeep Holla
@ 2018-03-12 23:05         ` Jolly Shah
  2018-03-13 10:24           ` Sudeep Holla
  0 siblings, 1 reply; 24+ messages in thread
From: Jolly Shah @ 2018-03-12 23:05 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ard.biesheuvel, mingo, gregkh, matt, hkallweit1, keescook,
	dmitry.torokhov, robh+dt, mark.rutland, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree, michal.simek


Hi Sudeep,

> -----Original Message-----
> From: Sudeep Holla [mailto:sudeep.holla@arm.com]
> Sent: Thursday, March 08, 2018 4:19 AM
> To: Jolly Shah <JOLLYS@xilinx.com>; michal.simek@xilinx.com
> Cc: Sudeep Holla <sudeep.holla@arm.com>; ard.biesheuvel@linaro.org;
> mingo@kernel.org; gregkh@linuxfoundation.org; matt@codeblueprint.co.uk;
> hkallweit1@gmail.com; keescook@chromium.org;
> dmitry.torokhov@gmail.com; robh+dt@kernel.org; mark.rutland@arm.com;
> Rajan Vaja <RAJANV@xilinx.com>; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org; devicetree@vger.kernel.org
> Subject: Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware
> driver
> 
> 
> 
> On 07/03/18 00:44, Jolly Shah wrote:
> > Hi Sudeep,
> >
> > Thanks for the review,
> >
> >> -----Original Message-----
> >> From: Sudeep Holla [mailto:sudeep.holla@arm.com]
> >> Sent: Thursday, March 01, 2018 6:28 AM
> >> To: Jolly Shah <JOLLYS@xilinx.com>; michal.simek@xilinx.com
> >> Cc: ard.biesheuvel@linaro.org; mingo@kernel.org;
> >> gregkh@linuxfoundation.org; matt@codeblueprint.co.uk;
> >> hkallweit1@gmail.com; keescook@chromium.org;
> >> dmitry.torokhov@gmail.com; robh+dt@kernel.org; mark.rutland@arm.com;
> >> Sudeep Holla <sudeep.holla@arm.com>; Rajan Vaja <RAJANV@xilinx.com>;
> >> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> >> devicetree@vger.kernel.org; Jolly Shah <JOLLYS@xilinx.com>
> >> Subject: Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP
> >> firmware driver
> >>
> >>
> >>
> >> On 20/02/18 19:21, Jolly Shah wrote:
> >>> This patch is adding communication layer with firmware.
> >>> Firmware driver provides an interface to firmware APIs.
> >>> Interface APIs can be used by any driver to communicate to
> >>> PMUFW(Platform Management Unit). All requests go through ATF.
> >>>
> >>> Signed-off-by: Jolly Shah <jollys@xilinx.com>
> >>> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> >>> ---
> >>>  arch/arm64/Kconfig.platforms                    |    1 +
> >>>  drivers/firmware/Kconfig                        |    1 +
> >>>  drivers/firmware/Makefile                       |    1 +
> >>>  drivers/firmware/xilinx/Kconfig                 |    4 +
> >>>  drivers/firmware/xilinx/Makefile                |    4 +
> >>>  drivers/firmware/xilinx/zynqmp/Kconfig          |   16 +
> >>>  drivers/firmware/xilinx/zynqmp/Makefile         |    4 +
> >>>  drivers/firmware/xilinx/zynqmp/firmware.c       | 1051
> >> +++++++++++++++++++++++
> >>>  include/linux/firmware/xilinx/zynqmp/firmware.h |  590
> >>> +++++++++++++
> >>>  9 files changed, 1672 insertions(+)  create mode 100644
> >>> drivers/firmware/xilinx/Kconfig  create mode
> >>> 100644 drivers/firmware/xilinx/Makefile  create mode 100644
> >>> drivers/firmware/xilinx/zynqmp/Kconfig
> >>>  create mode 100644 drivers/firmware/xilinx/zynqmp/Makefile
> >>>  create mode 100644 drivers/firmware/xilinx/zynqmp/firmware.c
> >>>  create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware.h
> >>>
> >>> +
> >>> +/**
> >>> + * zynqmp_pm_force_powerdown - PM call to request for another PU or
> >> subsystem to
> >>> + *				be powered down forcefully
> >>> + * @target:	Node ID of the targeted PU or subsystem
> >>> + * @ack:	Flag to specify whether acknowledge is requested
> >>> + *
> >>> + * Return:	Returns status, either success or error+reason
> >>> + */
> >>> +static int zynqmp_pm_force_powerdown(const u32 target,
> >>> +				     const enum zynqmp_pm_request_ack ack) {
> >>> +	return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, target, ack,
> >> 0, 0,
> >>> +NULL); }
> >>> +
> >>
> >> [...]
> >>
> >>> +/**
> >>> + * zynqmp_pm_system_shutdown - PM call to request a system shutdown
> >>> +or
> >> restart
> >>> + * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
> >>> + * @subtype:	Specifies which system should be restarted or shut
> down
> >>> + *
> >>> + * Return:	Returns status, either success or error+reason
> >>> + */
> >>> +static int zynqmp_pm_system_shutdown(const u32 type, const u32
> >>> +subtype) {
> >>> +	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
> >>> +				   0, 0, NULL);
> >>> +}
> >>> +
> >>
> >> I can't understand why you need above 2 APIs: PM_FORCE_POWERDOWN
> and
> >> PM_SYSTEM_SHUTDOWN. You should use PSCI_SYSTEM_OFF and
> >> PSCI_SYSTEM_RESET and drop these two.
> >>
> >
> > FORCE_POWERDOWN allows remote master to force power off other
> > node/domain. SYSTEM_SHUTDOWN provides interface to shutdown/restart
> > the subsystem. It supports system/subsystem restart with argument
> > value.> PSCI doesn’t
> support argument to identify between restart types.
> 
> OK, what are the types you are referring here ? or why PSCI is not sufficient ?
> How do you plan to use these APIs in Linux ?

It supports system/subsystem restart as types. For example, only APU restart, system restart, PS restart for ZynqMP
PSCI doesn’t support any argument to identify these types.
Linux, one can set the reset scope through debug interface and execute "reboot" then. Inside ATF, PSCI_SYSTEM_RESET mapped function will call EEMI API with that scope.

> 
> >>
> >>> +static const struct zynqmp_eemi_ops eemi_ops = {
> >>> +	.get_api_version = zynqmp_pm_get_api_version,
> >>> +	.get_chipid = zynqmp_pm_get_chipid,
> >>> +	.reset_assert = zynqmp_pm_reset_assert,
> >>> +	.reset_get_status = zynqmp_pm_reset_get_status,
> >>> +	.fpga_load = zynqmp_pm_fpga_load,
> >>> +	.fpga_get_status = zynqmp_pm_fpga_get_status,
> >>> +	.sha_hash = zynqmp_pm_sha_hash,
> >>> +	.rsa = zynqmp_pm_rsa,
> >>> +	.request_suspend = zynqmp_pm_request_suspend,
> >>> +	.force_powerdown = zynqmp_pm_force_powerdown,
> >>> +	.request_wakeup = zynqmp_pm_request_wakeup,
> >>> +	.set_wakeup_source = zynqmp_pm_set_wakeup_source,
> >>> +	.system_shutdown = zynqmp_pm_system_shutdown,
> >>> +	.request_node = zynqmp_pm_request_node,
> >>> +	.release_node = zynqmp_pm_release_node,
> >>> +	.set_requirement = zynqmp_pm_set_requirement,
> >>> +	.set_max_latency = zynqmp_pm_set_max_latency,
> >>> +	.set_configuration = zynqmp_pm_set_configuration,
> >>> +	.get_node_status = zynqmp_pm_get_node_status,
> >>> +	.get_operating_characteristic =
> >> zynqmp_pm_get_operating_characteristic,
> >>> +	.init_finalize = zynqmp_pm_init_finalize,
> >>> +	.set_suspend_mode = zynqmp_pm_set_suspend_mode,
> >>> +	.ioctl = zynqmp_pm_ioctl,
> >>> +	.query_data = zynqmp_pm_query_data,
> >>> +	.pinctrl_request = zynqmp_pm_pinctrl_request,
> >>> +	.pinctrl_release = zynqmp_pm_pinctrl_release,
> >>> +	.pinctrl_get_function = zynqmp_pm_pinctrl_get_function,
> >>> +	.pinctrl_set_function = zynqmp_pm_pinctrl_set_function,
> >>> +	.pinctrl_get_config = zynqmp_pm_pinctrl_get_config,
> >>> +	.pinctrl_set_config = zynqmp_pm_pinctrl_set_config,
> >>> +	.clock_enable = zynqmp_pm_clock_enable,
> >>> +	.clock_disable = zynqmp_pm_clock_disable,
> >>> +	.clock_getstate = zynqmp_pm_clock_getstate,
> >>> +	.clock_setdivider = zynqmp_pm_clock_setdivider,
> >>> +	.clock_getdivider = zynqmp_pm_clock_getdivider,
> >>> +	.clock_setrate = zynqmp_pm_clock_setrate,
> >>> +	.clock_getrate = zynqmp_pm_clock_getrate,
> >>> +	.clock_setparent = zynqmp_pm_clock_setparent,
> >>> +	.clock_getparent = zynqmp_pm_clock_getparent, };
> >>> +
> >> Instead of introducing all these in oneshot, add them as you have users of it.
> >> IOW, show the users of these functions in the series. Also I asked to
> >> split this into functional changes like clock, pinctrl, power, etc.
> >
> > It can be split into functional changes in same series but it will be
> > difficult to split between users as there are more than 10 driver
> > users for different EEMI APIs and also multiple driver users using
> > specifc EEMI APIs. They all can't be submitted as single series.
> >
> 
> Why ? Start with basic EEMI and one functionality with it's user/client driver in
> one series. Then you can top up with EEMI changes for other functionality with
> it's user. If you introduce API's without the users in a series it's hard to review
> and if there are more such unused APIs I will object it in future versions.
> 
> To start with add only clock or power APIs and functionality in this series, add
> drivers using then. Drop other functionalities like pinctrl, fpga control and other
> functionalities. IOW start something basic and simple.
> 

I am ok to break it for clock/pinctrl with users but there are multiple users for some APIs. In that case, it will create dependency issues when different owners are involved.
Also, it will hard to visualize a whole EEMI interface if its broken into such pieces. 

> --
> Regards,
> Sudeep

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

* RE: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware
  2018-03-08 11:48       ` Sudeep Holla
@ 2018-03-12 23:07         ` Jolly Shah
  2018-03-13 10:16           ` Sudeep Holla
  0 siblings, 1 reply; 24+ messages in thread
From: Jolly Shah @ 2018-03-12 23:07 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: gregkh, matt, hkallweit1, michal.simek, robh+dt, mark.rutland,
	ard.biesheuvel, mingo, keescook, dmitry.torokhov, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree

Hi Sudeep,

> -----Original Message-----
> From: Sudeep Holla [mailto:sudeep.holla@arm.com]
> Sent: Thursday, March 08, 2018 3:48 AM
> To: Jolly Shah <JOLLYS@xilinx.com>
> Cc: gregkh@linuxfoundation.org; matt@codeblueprint.co.uk;
> hkallweit1@gmail.com; michal.simek@xilinx.com; robh+dt@kernel.org;
> mark.rutland@arm.com; Sudeep Holla <sudeep.holla@arm.com>;
> ard.biesheuvel@linaro.org; mingo@kernel.org; keescook@chromium.org;
> dmitry.torokhov@gmail.com; Rajan Vaja <RAJANV@xilinx.com>; linux-arm-
> kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> devicetree@vger.kernel.org
> Subject: Re: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP
> firmware
> 
> 
> 
> On 07/03/18 22:25, Jolly Shah wrote:
> > Hi Sudeep,
> >
> 
> [...]
> 
> >>> +Examples:
> >>> +	firmware {
> >>> +		zynqmp_firmware: zynqmp-firmware {
> >>> +			compatible = "xlnx,zynqmp-firmware";
> >>> +			method = "smc";
> >>> +		};
> >>> +	};
> >>>
> >>
> >> Do you foresee using SMC/HVC for this firmware even on future platforms?
> >> If not, I suggest to keep the protocol part separate from the transport i.e.
> >> smc/hvc via ATF. It could be replaced with mailbox or some h/w
> >> mechanism in future ?
> >>
> >
> > We have PSCI and EEMI interfaces exposed to linux from ATF. PSCI is an
> > EEMI client. We do not have current plans to switch to mailbox as it
> > will require 2 communication channels to PMU as PSCI is through ATF.
> >
> 
> OK, but I just saw some bindings that has mailbox interface, honestly it's getting
> too confusing with multiple series on the same thing floating and hence I
> requested to put it together as one series.

Mailbox binding is used for power management driver. Mailbox is only used for PMU->APU communication.
APU->PMU communication is always through EEMI firmware interface which is using SMC/HVC.


> --
> Regards,
> Sudeep

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

* Re: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware
  2018-03-12 23:07         ` Jolly Shah
@ 2018-03-13 10:16           ` Sudeep Holla
  2018-03-13 18:56             ` Jolly Shah
  0 siblings, 1 reply; 24+ messages in thread
From: Sudeep Holla @ 2018-03-13 10:16 UTC (permalink / raw)
  To: Jolly Shah
  Cc: Sudeep Holla, gregkh, matt, hkallweit1, michal.simek, robh+dt,
	mark.rutland, ard.biesheuvel, mingo, keescook, dmitry.torokhov,
	Rajan Vaja, linux-arm-kernel, linux-kernel, devicetree



On 12/03/18 23:07, Jolly Shah wrote:
> Hi Sudeep,

>>>> Do you foresee using SMC/HVC for this firmware even on future platforms?
>>>> If not, I suggest to keep the protocol part separate from the transport i.e.
>>>> smc/hvc via ATF. It could be replaced with mailbox or some h/w
>>>> mechanism in future ?
>>>>
>>>
>>> We have PSCI and EEMI interfaces exposed to linux from ATF. PSCI is an
>>> EEMI client. We do not have current plans to switch to mailbox as it
>>> will require 2 communication channels to PMU as PSCI is through ATF.
>>>
>>
>> OK, but I just saw some bindings that has mailbox interface, honestly it's getting
>> too confusing with multiple series on the same thing floating and hence I
>> requested to put it together as one series.
> 
> Mailbox binding is used for power management driver. Mailbox is only
> used for PMU->APU communication. APU->PMU communication is always
> through EEMI firmware interface which is using SMC/HVC.
> 

Ah OK, is it because there's no non-secure mailbox or to avoid races,
all non-secure EEMI is channeled through SMC ?

-- 
Regards,
Sudeep

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

* Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
  2018-03-12 23:05         ` Jolly Shah
@ 2018-03-13 10:24           ` Sudeep Holla
  2018-03-15 17:53             ` Jolly Shah
  0 siblings, 1 reply; 24+ messages in thread
From: Sudeep Holla @ 2018-03-13 10:24 UTC (permalink / raw)
  To: Jolly Shah
  Cc: Sudeep Holla, ard.biesheuvel, mingo, gregkh, matt, hkallweit1,
	keescook, dmitry.torokhov, robh+dt, mark.rutland, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree, michal.simek



On 12/03/18 23:05, Jolly Shah wrote:
> 

[...]

>>
>> OK, what are the types you are referring here ? or why PSCI is not sufficient ?
>> How do you plan to use these APIs in Linux ?
> 
> It supports system/subsystem restart as types. For example, only APU
> restart, system restart, PS restart for ZynqMP
> PSCI doesn’t support any argument to identify these types. Linux, one
> can set the reset scope through debug interface and execute
> "reboot" then. Inside ATF, PSCI_SYSTEM_RESET mapped function will call
> EEMI API with that scope.

OK, I am not sure how you use them in Linux. Please add drivers using
them or just drop them for now and add when you add the users of these
functions.

>>
>>>>
>>>>> +static const struct zynqmp_eemi_ops eemi_ops = {
>>>>> +	.get_api_version = zynqmp_pm_get_api_version,
>>>>> +	.get_chipid = zynqmp_pm_get_chipid,
>>>>> +	.reset_assert = zynqmp_pm_reset_assert,
>>>>> +	.reset_get_status = zynqmp_pm_reset_get_status,
>>>>> +	.fpga_load = zynqmp_pm_fpga_load,
>>>>> +	.fpga_get_status = zynqmp_pm_fpga_get_status,
>>>>> +	.sha_hash = zynqmp_pm_sha_hash,
>>>>> +	.rsa = zynqmp_pm_rsa,
>>>>> +	.request_suspend = zynqmp_pm_request_suspend,
>>>>> +	.force_powerdown = zynqmp_pm_force_powerdown,
>>>>> +	.request_wakeup = zynqmp_pm_request_wakeup,
>>>>> +	.set_wakeup_source = zynqmp_pm_set_wakeup_source,
>>>>> +	.system_shutdown = zynqmp_pm_system_shutdown,
>>>>> +	.request_node = zynqmp_pm_request_node,
>>>>> +	.release_node = zynqmp_pm_release_node,
>>>>> +	.set_requirement = zynqmp_pm_set_requirement,
>>>>> +	.set_max_latency = zynqmp_pm_set_max_latency,
>>>>> +	.set_configuration = zynqmp_pm_set_configuration,
>>>>> +	.get_node_status = zynqmp_pm_get_node_status,
>>>>> +	.get_operating_characteristic =
>>>> zynqmp_pm_get_operating_characteristic,
>>>>> +	.init_finalize = zynqmp_pm_init_finalize,
>>>>> +	.set_suspend_mode = zynqmp_pm_set_suspend_mode,
>>>>> +	.ioctl = zynqmp_pm_ioctl,
>>>>> +	.query_data = zynqmp_pm_query_data,
>>>>> +	.pinctrl_request = zynqmp_pm_pinctrl_request,
>>>>> +	.pinctrl_release = zynqmp_pm_pinctrl_release,
>>>>> +	.pinctrl_get_function = zynqmp_pm_pinctrl_get_function,
>>>>> +	.pinctrl_set_function = zynqmp_pm_pinctrl_set_function,
>>>>> +	.pinctrl_get_config = zynqmp_pm_pinctrl_get_config,
>>>>> +	.pinctrl_set_config = zynqmp_pm_pinctrl_set_config,
>>>>> +	.clock_enable = zynqmp_pm_clock_enable,
>>>>> +	.clock_disable = zynqmp_pm_clock_disable,
>>>>> +	.clock_getstate = zynqmp_pm_clock_getstate,
>>>>> +	.clock_setdivider = zynqmp_pm_clock_setdivider,
>>>>> +	.clock_getdivider = zynqmp_pm_clock_getdivider,
>>>>> +	.clock_setrate = zynqmp_pm_clock_setrate,
>>>>> +	.clock_getrate = zynqmp_pm_clock_getrate,
>>>>> +	.clock_setparent = zynqmp_pm_clock_setparent,
>>>>> +	.clock_getparent = zynqmp_pm_clock_getparent, };
>>>>> +
>>>> Instead of introducing all these in oneshot, add them as you have users of it.
>>>> IOW, show the users of these functions in the series. Also I asked to
>>>> split this into functional changes like clock, pinctrl, power, etc.
>>>
>>> It can be split into functional changes in same series but it will be
>>> difficult to split between users as there are more than 10 driver
>>> users for different EEMI APIs and also multiple driver users using
>>> specifc EEMI APIs. They all can't be submitted as single series.
>>>
>>
>> Why ? Start with basic EEMI and one functionality with it's user/client driver in
>> one series. Then you can top up with EEMI changes for other functionality with
>> it's user. If you introduce API's without the users in a series it's hard to review
>> and if there are more such unused APIs I will object it in future versions.
>>
>> To start with add only clock or power APIs and functionality in this series, add
>> drivers using then. Drop other functionalities like pinctrl, fpga control and other
>> functionalities. IOW start something basic and simple.
>> 

> 
> I am ok to break it for clock/pinctrl with users but there are
> multiple users for some APIs. In that case, it will create dependency
> issues when different owners are involved.
> Also, it will hard to visualize a whole EEMI interface if its broken
> into such pieces.
> 

It's opposite, you are just adding whole lot of functions/APIs here with
out the users of those APIs. I am unable to visualise how they are
getting used. So for me even if you just add handful of above APIs with
drivers making call to each one of them along with it, I can better
understand it. Without any usage of these APIs in this series, I fail
to understand the need of it.
So NACK to this patch without the users of the APIs introduced here.

-- 
Regards,
Sudeep

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

* RE: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware
  2018-03-13 10:16           ` Sudeep Holla
@ 2018-03-13 18:56             ` Jolly Shah
  0 siblings, 0 replies; 24+ messages in thread
From: Jolly Shah @ 2018-03-13 18:56 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: gregkh, matt, hkallweit1, michal.simek, robh+dt, mark.rutland,
	ard.biesheuvel, mingo, keescook, dmitry.torokhov, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree



> -----Original Message-----
> From: Sudeep Holla [mailto:sudeep.holla@arm.com]
> Sent: Tuesday, March 13, 2018 3:16 AM
> To: Jolly Shah <JOLLYS@xilinx.com>
> Cc: Sudeep Holla <sudeep.holla@arm.com>; gregkh@linuxfoundation.org;
> matt@codeblueprint.co.uk; hkallweit1@gmail.com; michal.simek@xilinx.com;
> robh+dt@kernel.org; mark.rutland@arm.com; ard.biesheuvel@linaro.org;
> mingo@kernel.org; keescook@chromium.org; dmitry.torokhov@gmail.com;
> Rajan Vaja <RAJANV@xilinx.com>; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org; devicetree@vger.kernel.org
> Subject: Re: [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP
> firmware
> 
> 
> 
> On 12/03/18 23:07, Jolly Shah wrote:
> > Hi Sudeep,
> 
> >>>> Do you foresee using SMC/HVC for this firmware even on future
> platforms?
> >>>> If not, I suggest to keep the protocol part separate from the transport i.e.
> >>>> smc/hvc via ATF. It could be replaced with mailbox or some h/w
> >>>> mechanism in future ?
> >>>>
> >>>
> >>> We have PSCI and EEMI interfaces exposed to linux from ATF. PSCI is
> >>> an EEMI client. We do not have current plans to switch to mailbox as
> >>> it will require 2 communication channels to PMU as PSCI is through ATF.
> >>>
> >>
> >> OK, but I just saw some bindings that has mailbox interface, honestly
> >> it's getting too confusing with multiple series on the same thing
> >> floating and hence I requested to put it together as one series.
> >
> > Mailbox binding is used for power management driver. Mailbox is only
> > used for PMU->APU communication. APU->PMU communication is always
> > through EEMI firmware interface which is using SMC/HVC.
> >
> 
> Ah OK, is it because there's no non-secure mailbox or to avoid races, all non-
> secure EEMI is channeled through SMC ?
> 

2 reasons:
1> Avoid multiple EEMI communication channels as PSCI is through ATF.
2> We have some secure operations handled in ATF because of memory constraints on PMU

> --
> Regards,
> Sudeep

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

* Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
  2018-02-20 19:21 ` [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver Jolly Shah
  2018-03-01 14:27   ` Sudeep Holla
@ 2018-03-14 13:22   ` Greg KH
  1 sibling, 0 replies; 24+ messages in thread
From: Greg KH @ 2018-03-14 13:22 UTC (permalink / raw)
  To: Jolly Shah
  Cc: ard.biesheuvel, mingo, matt, sudeep.holla, hkallweit1, keescook,
	dmitry.torokhov, michal.simek, robh+dt, mark.rutland, rajanv,
	linux-arm-kernel, linux-kernel, devicetree, Jolly Shah

On Tue, Feb 20, 2018 at 11:21:05AM -0800, Jolly Shah wrote:
> This patch is adding communication layer with firmware.
> Firmware driver provides an interface to firmware APIs.
> Interface APIs can be used by any driver to communicate to
> PMUFW(Platform Management Unit). All requests go through ATF.
> 
> Signed-off-by: Jolly Shah <jollys@xilinx.com>
> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> ---
>  arch/arm64/Kconfig.platforms                    |    1 +
>  drivers/firmware/Kconfig                        |    1 +
>  drivers/firmware/Makefile                       |    1 +
>  drivers/firmware/xilinx/Kconfig                 |    4 +
>  drivers/firmware/xilinx/Makefile                |    4 +
>  drivers/firmware/xilinx/zynqmp/Kconfig          |   16 +
>  drivers/firmware/xilinx/zynqmp/Makefile         |    4 +
>  drivers/firmware/xilinx/zynqmp/firmware.c       | 1051 +++++++++++++++++++++++

Why are you 2 levels deep?  Why not just drivers/firmware/zynqmp.c?  Or
at the worst:
	drivers/firmware/xilinx/zynqmp.c
Don't over do it, if we really get too many firmware drivers, we can
always move things around in the future.

>  include/linux/firmware/xilinx/zynqmp/firmware.h |  590 +++++++++++++

I still think this include directly depth is crazy.  What's wrong with:
	include/linux/firmware/zynqmp.h
?



>  9 files changed, 1672 insertions(+)
>  create mode 100644 drivers/firmware/xilinx/Kconfig
>  create mode 100644 drivers/firmware/xilinx/Makefile
>  create mode 100644 drivers/firmware/xilinx/zynqmp/Kconfig
>  create mode 100644 drivers/firmware/xilinx/zynqmp/Makefile
>  create mode 100644 drivers/firmware/xilinx/zynqmp/firmware.c
>  create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware.h
> 
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index fbedbd8..6454458 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -274,6 +274,7 @@ config ARCH_ZX
>  
>  config ARCH_ZYNQMP
>  	bool "Xilinx ZynqMP Family"
> +	select ZYNQMP_FIRMWARE

Select and not depends?

>  	help
>  	  This enables support for Xilinx ZynqMP Family
>  
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index b7c7482..f41eb0d 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -257,5 +257,6 @@ source "drivers/firmware/google/Kconfig"
>  source "drivers/firmware/efi/Kconfig"
>  source "drivers/firmware/meson/Kconfig"
>  source "drivers/firmware/tegra/Kconfig"
> +source "drivers/firmware/xilinx/Kconfig"
>  
>  endmenu
> diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
> index b248238..f90363e 100644
> --- a/drivers/firmware/Makefile
> +++ b/drivers/firmware/Makefile
> @@ -31,3 +31,4 @@ obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
>  obj-$(CONFIG_EFI)		+= efi/
>  obj-$(CONFIG_UEFI_CPER)		+= efi/
>  obj-y				+= tegra/
> +obj-y				+= xilinx/
> diff --git a/drivers/firmware/xilinx/Kconfig b/drivers/firmware/xilinx/Kconfig
> new file mode 100644
> index 0000000..eb4cdcf
> --- /dev/null
> +++ b/drivers/firmware/xilinx/Kconfig
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0+

2+ for a Kconfig file?

> +# Kconfig for Xilinx firmwares
> +
> +source "drivers/firmware/xilinx/zynqmp/Kconfig"
> diff --git a/drivers/firmware/xilinx/Makefile b/drivers/firmware/xilinx/Makefile
> new file mode 100644
> index 0000000..beff5dc
> --- /dev/null
> +++ b/drivers/firmware/xilinx/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0+

2+ for a Makefile?

> +# Makefile for Xilinx firmwares
> +
> +obj-$(CONFIG_ARCH_ZYNQMP) += zynqmp/
> diff --git a/drivers/firmware/xilinx/zynqmp/Kconfig b/drivers/firmware/xilinx/zynqmp/Kconfig
> new file mode 100644
> index 0000000..5054b80
> --- /dev/null
> +++ b/drivers/firmware/xilinx/zynqmp/Kconfig
> @@ -0,0 +1,16 @@
> +# SPDX-License-Identifier: GPL-2.0+

Again...

> +# Kconfig for Xilinx ZynqMP firmware
> +
> +menu "Zynq MPSoC Firmware Drivers"
> +	depends on ARCH_ZYNQMP
> +
> +config ZYNQMP_FIRMWARE
> +	bool "Enable Xilinx Zynq MPSoC firmware interface"
> +	help
> +	  Firmware interface driver is used by different to
> +	  communicate with the firmware for various platform
> +	  management services.
> +	  Say yes to enable ZynqMP firmware interface driver.
> +	  In doubt, say N
> +
> +endmenu
> diff --git a/drivers/firmware/xilinx/zynqmp/Makefile b/drivers/firmware/xilinx/zynqmp/Makefile
> new file mode 100644
> index 0000000..c3ec669
> --- /dev/null
> +++ b/drivers/firmware/xilinx/zynqmp/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0+

And again?

> +# Makefile for Xilinx firmwares
> +
> +obj-$(CONFIG_ZYNQMP_FIRMWARE) += firmware.o
> diff --git a/drivers/firmware/xilinx/zynqmp/firmware.c b/drivers/firmware/xilinx/zynqmp/firmware.c
> new file mode 100644
> index 0000000..6979f4b
> --- /dev/null
> +++ b/drivers/firmware/xilinx/zynqmp/firmware.c
> @@ -0,0 +1,1051 @@
> +// SPDX-License-Identifier: GPL-2.0+

And I have to ask, you really mean "any future version"?

> +/*
> + * Xilinx Zynq MPSoC Firmware layer
> + *
> + *  Copyright (C) 2014-2018 Xilinx, Inc.
> + *
> + *  Michal Simek <michal.simek@xilinx.com>
> + *  Davorin Mista <davorin.mista@aggios.com>
> + *  Jolly Shah <jollys@xilinx.com>
> + *  Rajan Vaja <rajanv@xilinx.com>
> + */
> +
> +#include <linux/arm-smccc.h>
> +#include <linux/compiler.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +
> +#include <linux/firmware/xilinx/zynqmp/firmware.h>

Why do you need a file in linux/firmware anyway?

> +struct zynqmp_eemi_ops {
> +	int (*get_api_version)(u32 *version);
> +	int (*get_chipid)(u32 *idcode, u32 *version);
> +	int (*reset_assert)(const enum zynqmp_pm_reset reset,
> +			    const enum zynqmp_pm_reset_action assert_flag);
> +	int (*reset_get_status)(const enum zynqmp_pm_reset reset, u32 *status);
> +	int (*fpga_load)(const u64 address, const u32 size, const u32 flags);
> +	int (*fpga_get_status)(u32 *value);
> +	int (*sha_hash)(const u64 address, const u32 size, const u32 flags);
> +	int (*rsa)(const u64 address, const u32 size, const u32 flags);
> +	int (*request_suspend)(const u32 node,
> +			       const enum zynqmp_pm_request_ack ack,
> +			       const u32 latency,
> +			       const u32 state);
> +	int (*force_powerdown)(const u32 target,
> +			       const enum zynqmp_pm_request_ack ack);
> +	int (*request_wakeup)(const u32 node,
> +			      const bool set_addr,
> +			      const u64 address,
> +			      const enum zynqmp_pm_request_ack ack);
> +	int (*set_wakeup_source)(const u32 target,
> +				 const u32 wakeup_node,
> +				 const u32 enable);
> +	int (*system_shutdown)(const u32 type, const u32 subtype);
> +	int (*request_node)(const u32 node,
> +			    const u32 capabilities,
> +			    const u32 qos,
> +			    const enum zynqmp_pm_request_ack ack);
> +	int (*release_node)(const u32 node);
> +	int (*set_requirement)(const u32 node,
> +			       const u32 capabilities,
> +			       const u32 qos,
> +			       const enum zynqmp_pm_request_ack ack);
> +	int (*set_max_latency)(const u32 node, const u32 latency);
> +	int (*set_configuration)(const u32 physical_addr);
> +	int (*get_node_status)(const u32 node, u32 *const status,
> +			       u32 *const requirements, u32 *const usage);
> +	int (*get_operating_characteristic)(const u32 node,
> +					    const enum zynqmp_pm_opchar_type
> +					    type, u32 *const result);
> +	int (*init_finalize)(void);
> +	int (*set_suspend_mode)(u32 mode);
> +	int (*ioctl)(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, u32 *out);
> +	int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out);
> +	int (*pinctrl_request)(const u32 pin);
> +	int (*pinctrl_release)(const u32 pin);
> +	int (*pinctrl_get_function)(const u32 pin, u32 *id);
> +	int (*pinctrl_set_function)(const u32 pin, const u32 id);
> +	int (*pinctrl_get_config)(const u32 pin, const u32 param, u32 *value);
> +	int (*pinctrl_set_config)(const u32 pin, const u32 param, u32 value);
> +	int (*clock_enable)(u32 clock_id);
> +	int (*clock_disable)(u32 clock_id);
> +	int (*clock_getstate)(u32 clock_id, u32 *state);
> +	int (*clock_setdivider)(u32 clock_id, u32 divider);
> +	int (*clock_getdivider)(u32 clock_id, u32 *divider);
> +	int (*clock_setrate)(u32 clock_id, u64 rate);
> +	int (*clock_getrate)(u32 clock_id, u64 *rate);
> +	int (*clock_setparent)(u32 clock_id, u32 parent_id);
> +	int (*clock_getparent)(u32 clock_id, u32 *parent_id);
> +};

Why do you need this huge structure of pointers to functions, when you
only ever set them to 1 value, and no one even calls them?

Why not just export the needed symbols and call them directly?  What is
the indirection getting you here?

thanks,

greg k-h

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

* RE: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
  2018-03-13 10:24           ` Sudeep Holla
@ 2018-03-15 17:53             ` Jolly Shah
  2018-03-15 17:57               ` Sudeep Holla
  0 siblings, 1 reply; 24+ messages in thread
From: Jolly Shah @ 2018-03-15 17:53 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ard.biesheuvel, mingo, gregkh, matt, hkallweit1, keescook,
	dmitry.torokhov, robh+dt, mark.rutland, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree, michal.simek

Hi Sudeep,

> -----Original Message-----
> From: Sudeep Holla [mailto:sudeep.holla@arm.com]
> Sent: Tuesday, March 13, 2018 3:24 AM
> To: Jolly Shah <JOLLYS@xilinx.com>
> Cc: Sudeep Holla <sudeep.holla@arm.com>; ard.biesheuvel@linaro.org;
> mingo@kernel.org; gregkh@linuxfoundation.org; matt@codeblueprint.co.uk;
> hkallweit1@gmail.com; keescook@chromium.org;
> dmitry.torokhov@gmail.com; robh+dt@kernel.org; mark.rutland@arm.com;
> Rajan Vaja <RAJANV@xilinx.com>; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org; devicetree@vger.kernel.org; michal.simek@xilinx.com
> Subject: Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware
> driver
> 
> 
> 
> On 12/03/18 23:05, Jolly Shah wrote:
> >
> 
> [...]
> 
> >>
> >> OK, what are the types you are referring here ? or why PSCI is not sufficient ?
> >> How do you plan to use these APIs in Linux ?
> >
> > It supports system/subsystem restart as types. For example, only APU
> > restart, system restart, PS restart for ZynqMP PSCI doesn’t support
> > any argument to identify these types. Linux, one can set the reset
> > scope through debug interface and execute "reboot" then. Inside ATF,
> > PSCI_SYSTEM_RESET mapped function will call EEMI API with that scope.
> 
> OK, I am not sure how you use them in Linux. Please add drivers using them or
> just drop them for now and add when you add the users of these functions.
> 
> >>
> >>>>
> >>>>> +static const struct zynqmp_eemi_ops eemi_ops = {
> >>>>> +	.get_api_version = zynqmp_pm_get_api_version,
> >>>>> +	.get_chipid = zynqmp_pm_get_chipid,
> >>>>> +	.reset_assert = zynqmp_pm_reset_assert,
> >>>>> +	.reset_get_status = zynqmp_pm_reset_get_status,
> >>>>> +	.fpga_load = zynqmp_pm_fpga_load,
> >>>>> +	.fpga_get_status = zynqmp_pm_fpga_get_status,
> >>>>> +	.sha_hash = zynqmp_pm_sha_hash,
> >>>>> +	.rsa = zynqmp_pm_rsa,
> >>>>> +	.request_suspend = zynqmp_pm_request_suspend,
> >>>>> +	.force_powerdown = zynqmp_pm_force_powerdown,
> >>>>> +	.request_wakeup = zynqmp_pm_request_wakeup,
> >>>>> +	.set_wakeup_source = zynqmp_pm_set_wakeup_source,
> >>>>> +	.system_shutdown = zynqmp_pm_system_shutdown,
> >>>>> +	.request_node = zynqmp_pm_request_node,
> >>>>> +	.release_node = zynqmp_pm_release_node,
> >>>>> +	.set_requirement = zynqmp_pm_set_requirement,
> >>>>> +	.set_max_latency = zynqmp_pm_set_max_latency,
> >>>>> +	.set_configuration = zynqmp_pm_set_configuration,
> >>>>> +	.get_node_status = zynqmp_pm_get_node_status,
> >>>>> +	.get_operating_characteristic =
> >>>> zynqmp_pm_get_operating_characteristic,
> >>>>> +	.init_finalize = zynqmp_pm_init_finalize,
> >>>>> +	.set_suspend_mode = zynqmp_pm_set_suspend_mode,
> >>>>> +	.ioctl = zynqmp_pm_ioctl,
> >>>>> +	.query_data = zynqmp_pm_query_data,
> >>>>> +	.pinctrl_request = zynqmp_pm_pinctrl_request,
> >>>>> +	.pinctrl_release = zynqmp_pm_pinctrl_release,
> >>>>> +	.pinctrl_get_function = zynqmp_pm_pinctrl_get_function,
> >>>>> +	.pinctrl_set_function = zynqmp_pm_pinctrl_set_function,
> >>>>> +	.pinctrl_get_config = zynqmp_pm_pinctrl_get_config,
> >>>>> +	.pinctrl_set_config = zynqmp_pm_pinctrl_set_config,
> >>>>> +	.clock_enable = zynqmp_pm_clock_enable,
> >>>>> +	.clock_disable = zynqmp_pm_clock_disable,
> >>>>> +	.clock_getstate = zynqmp_pm_clock_getstate,
> >>>>> +	.clock_setdivider = zynqmp_pm_clock_setdivider,
> >>>>> +	.clock_getdivider = zynqmp_pm_clock_getdivider,
> >>>>> +	.clock_setrate = zynqmp_pm_clock_setrate,
> >>>>> +	.clock_getrate = zynqmp_pm_clock_getrate,
> >>>>> +	.clock_setparent = zynqmp_pm_clock_setparent,
> >>>>> +	.clock_getparent = zynqmp_pm_clock_getparent, };
> >>>>> +
> >>>> Instead of introducing all these in oneshot, add them as you have users of
> it.
> >>>> IOW, show the users of these functions in the series. Also I asked
> >>>> to split this into functional changes like clock, pinctrl, power, etc.
> >>>
> >>> It can be split into functional changes in same series but it will
> >>> be difficult to split between users as there are more than 10 driver
> >>> users for different EEMI APIs and also multiple driver users using
> >>> specifc EEMI APIs. They all can't be submitted as single series.
> >>>
> >>
> >> Why ? Start with basic EEMI and one functionality with it's
> >> user/client driver in one series. Then you can top up with EEMI
> >> changes for other functionality with it's user. If you introduce
> >> API's without the users in a series it's hard to review and if there are more
> such unused APIs I will object it in future versions.
> >>
> >> To start with add only clock or power APIs and functionality in this
> >> series, add drivers using then. Drop other functionalities like
> >> pinctrl, fpga control and other functionalities. IOW start something basic and
> simple.
> >>
> 
> >
> > I am ok to break it for clock/pinctrl with users but there are
> > multiple users for some APIs. In that case, it will create dependency
> > issues when different owners are involved.
> > Also, it will hard to visualize a whole EEMI interface if its broken
> > into such pieces.
> >
> 
> It's opposite, you are just adding whole lot of functions/APIs here with out the
> users of those APIs. I am unable to visualise how they are getting used. So for
> me even if you just add handful of above APIs with drivers making call to each
> one of them along with it, I can better understand it. Without any usage of these
> APIs in this series, I fail to understand the need of it.
> So NACK to this patch without the users of the APIs introduced here.
> 

Ok. I will break series with users in next version.

> --
> Regards,
> Sudeep

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

* Re: [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver
  2018-03-15 17:53             ` Jolly Shah
@ 2018-03-15 17:57               ` Sudeep Holla
  0 siblings, 0 replies; 24+ messages in thread
From: Sudeep Holla @ 2018-03-15 17:57 UTC (permalink / raw)
  To: Jolly Shah
  Cc: Sudeep Holla, ard.biesheuvel, mingo, gregkh, matt, hkallweit1,
	keescook, dmitry.torokhov, robh+dt, mark.rutland, Rajan Vaja,
	linux-arm-kernel, linux-kernel, devicetree, michal.simek



On 15/03/18 17:53, Jolly Shah wrote:
> Hi Sudeep,
> 

[...]

>>
>> It's opposite, you are just adding whole lot of functions/APIs here with out the
>> users of those APIs. I am unable to visualise how they are getting used. So for
>> me even if you just add handful of above APIs with drivers making call to each
>> one of them along with it, I can better understand it. Without any usage of these
>> APIs in this series, I fail to understand the need of it.
>> So NACK to this patch without the users of the APIs introduced here.
>>
> 
> Ok. I will break series with users in next version.
> 

Thanks. Don't add any APIs which are not used by drivers in the series.
We don't want the whole set of APIs in that structure lying around in
the kernel without users.

-- 
Regards,
Sudeep

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

end of thread, other threads:[~2018-03-15 17:57 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-20 19:21 [PATCH v5 0/4] drivers: firmware: xilinx: Add firmware driver support Jolly Shah
2018-02-20 19:21 ` [PATCH v5 1/4] dt-bindings: firmware: Add bindings for ZynqMP firmware Jolly Shah
2018-03-01 14:15   ` Sudeep Holla
2018-03-07 22:25     ` Jolly Shah
2018-03-08 11:48       ` Sudeep Holla
2018-03-12 23:07         ` Jolly Shah
2018-03-13 10:16           ` Sudeep Holla
2018-03-13 18:56             ` Jolly Shah
2018-03-01 21:18   ` Rob Herring
2018-02-20 19:21 ` [PATCH v5 2/4] drivers: firmware: xilinx: Add ZynqMP firmware driver Jolly Shah
2018-03-01 14:27   ` Sudeep Holla
2018-03-07  0:44     ` Jolly Shah
2018-03-08 12:18       ` Sudeep Holla
2018-03-12 23:05         ` Jolly Shah
2018-03-13 10:24           ` Sudeep Holla
2018-03-15 17:53             ` Jolly Shah
2018-03-15 17:57               ` Sudeep Holla
2018-03-14 13:22   ` Greg KH
2018-02-20 19:21 ` [PATCH v5 3/4] drivers: firmware: xilinx: Add sysfs interface Jolly Shah
2018-03-01 13:32   ` Michal Simek
2018-03-01 14:09   ` Andy Shevchenko
2018-03-01 14:44   ` Sudeep Holla
2018-03-07 22:03     ` Jolly Shah
2018-02-20 19:21 ` [PATCH v5 4/4] drivers: firmware: xilinx: Add debugfs interface Jolly Shah

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