Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/7] ARM: imx: add timer stop flag to ARM power off state
From: Lucas Stach @ 2018-01-09 14:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bacee8fe00b0ab54dfa6692bfc956ffd@agner.ch>

Am Dienstag, den 09.01.2018, 14:37 +0100 schrieb Stefan Agner:
> On 2018-01-09 11:13, Lucas Stach wrote:
> > Am Dienstag, den 09.01.2018, 09:25 +0000 schrieb Anson Huang:
> > > 
> > > Best Regards!
> > > Anson Huang
> > > 
> > > 
> > > > -----Original Message-----
> > > > From: Dong Aisheng [mailto:dongas86 at gmail.com]
> > > > Sent: 2018-01-09 5:23 PM
> > > > To: Stefan Agner <stefan@agner.ch>
> > > > Cc: shawnguo at kernel.org; kernel at pengutronix.de; Fabio Estevam
> > > > <fabio.estevam@nxp.com>; robh+dt at kernel.org; mark.rutland at arm.c
> > > > om;
> > > > linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.or
> > > > g;
> > > > linux-
> > > > kernel at vger.kernel.org; Anson Huang <anson.huang@nxp.com>; dl-
> > > > linux-imx
> > > > <linux-imx@nxp.com>
> > > > Subject: Re: [PATCH 1/7] ARM: imx: add timer stop flag to ARM
> > > > power
> > > > off state
> > > > 
> > > > On Tue, Jan 02, 2018 at 05:42:17PM +0100, Stefan Agner wrote:
> > > > > When the CPU is in ARM power off state the ARM architected
> > > > > timers
> > > > > are
> > > > > stopped. The flag is already present in the higher power WAIT
> > > > > mode.
> > > > > 
> > > > > This allows to use the ARM generic timer on i.MX 6UL/6ULL
> > > > > SoC.
> > > > > Without the flag the kernel freezes when the timer enters the
> > > > > first
> > > > > time ARM power off mode.
> > > > > 
> > > > > Cc: Anson Huang <anson.huang@nxp.com>
> > > > > Signed-off-by: Stefan Agner <stefan@agner.ch>
> > > > 
> > > > It seems ok at my side.
> > > > Did you meet the real issue? If yes, how to reproduce?
> > > > 
> > > > Both mx6sx and mx6ul are using GPT which do not need that flag,
> > > > suppose we
> > > > should remove it, right?
> > > > Anson can help confirm it.
> > > 
> > > For UP system like i.MX6SX, we do NOT enable "cortex-a9-twd-
> > > timer",
> > > so local
> > > timer is NOT used, GPT is used instead, GPT's clock is NOT
> > > disabled
> > > when cpuidle,
> > > so I think we should remove all these Timer stop flag for 6SX
> > > CPUIDLE.
> > 
> > It's correct to set the flag even on UP systems, as the flag means
> > the
> > CPU _local_ timer is stopped in this sleep mode. Also there are
> > systems
> > out there which are using the TWD on UP, as it operates at a higher
> > frequency leading to better wakeup granularity.
> 
> Documentation/devicetree/bindings/arm/twd.txt states that TWD
> provides
> "per-cpu local timer". But as far as I can see TWD still uses SPI
> interrupts, routed through GIC, so is this the differentiation?

Maybe what I wrote wasn't entirely clear. I completely agree with this
patch.

The TWD on Cortex-A9 is a CPU local timer, same as the architected
timer in later cores. It doesn't provide all the benefits of the
architected timer (the clock frequency varies with CPU core clock and
it's not virt capable), but some systems still prefer it over the i.MX
GPT, as it provides much better wakeup granularity.

So annotating the CPU idle states with the timer stop flag is the right
thing to do. This flag has nothing to with the usage of GPT or TWD on a
specific system.

Regards,
Lucas

^ permalink raw reply

* [PATCH] drivers: firmware: xilinx: Add ZynqMP firmware driver
From: Julien Thierry @ 2018-01-09 14:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515449227-5096-1-git-send-email-jollys@xilinx.com>

Hi Jolly,

On 08/01/18 22:07, 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.
> Firmware-debug provides debugfs interface to all APIs.
> Firmware-ggs provides read/write interface to
> global storage registers.
> 
> Signed-off-by: Jolly Shah <jollys@xilinx.com>
> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> ---
>   .../firmware/xilinx/xlnx,zynqmp-firmware.txt       |   16 +
>   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    |  540 +++++++++++
>   drivers/firmware/xilinx/zynqmp/firmware-ggs.c      |  298 ++++++
>   drivers/firmware/xilinx/zynqmp/firmware.c          | 1024 ++++++++++++++++++++
>   .../linux/firmware/xilinx/zynqmp/firmware-debug.h  |   32 +
>   include/linux/firmware/xilinx/zynqmp/firmware.h    |  573 +++++++++++
>   13 files changed, 2522 insertions(+)
>   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
> 

[...]

> diff --git a/drivers/firmware/xilinx/zynqmp/firmware-debug.c b/drivers/firmware/xilinx/zynqmp/firmware-debug.c
> new file mode 100644
> index 0000000..83b1c45
> --- /dev/null
> +++ b/drivers/firmware/xilinx/zynqmp/firmware-debug.c
> @@ -0,0 +1,540 @@
> +/*
> + * Xilinx Zynq MPSoC Firmware layer for debugfs APIs
> + *
> + *  Copyright (C) 2014-2017 Xilinx, Inc.
> + *
> + *  Michal Simek <michal.simek@xilinx.com>
> + *  Davorin Mista <davorin.mista@aggios.com>
> + *  Jolly Shah <jollys@xilinx.com>
> + *  Rajan Vaja <rajanv@xilinx.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#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 DRIVER_NAME	"zynqmp-firmware"
> +
> +/**
> + * 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
> + */
> +int zynqmp_pm_self_suspend(const u32 node,
> +			   const u32 latency,
> +			   const u32 state)
> +{
> +	return invoke_pm_fn(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
> + */
> +int zynqmp_pm_abort_suspend(const enum zynqmp_pm_abort_reason reason)
> +{
> +	return invoke_pm_fn(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
> + */
> +int zynqmp_pm_register_notifier(const u32 node, const u32 event,
> +				const u32 wake, const u32 enable)
> +{
> +	return invoke_pm_fn(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 struct dentry *zynqmp_pm_debugfs_dir;
> +static struct dentry *zynqmp_pm_debugfs_power;
> +static struct dentry *zynqmp_pm_debugfs_api_version;
> +
> +/**
> + * 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];
> +	/* Return values from PM APIs calls */
> +	u32 pm_api_ret[4] = {0, 0, 0, 0};
> +	u32 pm_api_version;
> +
> +	int ret;
> +	int i = 0;
> +	const struct zynqmp_eemi_ops *eemi_ops = get_eemi_ops();
> +
> +	if (!eemi_ops)
> +		return -ENXIO;
> +
> +	if (*off != 0 || len <= 0)

len is unsigned and cannot be negative.

> +		return -EINVAL;
> +
> +	kern_buff = kzalloc(len, GFP_KERNEL);
> +	if (!kern_buff)
> +		return -ENOMEM;
> +	tmp_buff = kern_buff;
> +
> +	while (i < ARRAY_SIZE(pm_api_arg))
> +		pm_api_arg[i++] = 0;

Why not initialize it the same way you did for pm_api_ret?

> +
> +	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, " ");
> +
> +	if (strncasecmp(pm_api_req, "REQUEST_SUSPEND", 15) == 0)
> +		pm_id = REQUEST_SUSPEND;
> +	else if (strncasecmp(pm_api_req, "SELF_SUSPEND", 12) == 0)
> +		pm_id = SELF_SUSPEND;
> +	else if (strncasecmp(pm_api_req, "FORCE_POWERDOWN", 15) == 0)
> +		pm_id = FORCE_POWERDOWN;
> +	else if (strncasecmp(pm_api_req, "ABORT_SUSPEND", 13) == 0)
> +		pm_id = ABORT_SUSPEND;
> +	else if (strncasecmp(pm_api_req, "REQUEST_WAKEUP", 14) == 0)
> +		pm_id = REQUEST_WAKEUP;
> +	else if (strncasecmp(pm_api_req, "SET_WAKEUP_SOURCE", 17) == 0)
> +		pm_id = SET_WAKEUP_SOURCE;
> +	else if (strncasecmp(pm_api_req, "SYSTEM_SHUTDOWN", 15) == 0)
> +		pm_id = SYSTEM_SHUTDOWN;
> +	else if (strncasecmp(pm_api_req, "REQUEST_NODE", 12) == 0)
> +		pm_id = REQUEST_NODE;
> +	else if (strncasecmp(pm_api_req, "RELEASE_NODE", 12) == 0)
> +		pm_id = RELEASE_NODE;
> +	else if (strncasecmp(pm_api_req, "SET_REQUIREMENT", 15) == 0)
> +		pm_id = SET_REQUIREMENT;
> +	else if (strncasecmp(pm_api_req, "SET_MAX_LATENCY", 15) == 0)
> +		pm_id = SET_MAX_LATENCY;
> +	else if (strncasecmp(pm_api_req, "GET_API_VERSION", 15) == 0)
> +		pm_id = GET_API_VERSION;
> +	else if (strncasecmp(pm_api_req, "SET_CONFIGURATION", 17) == 0)
> +		pm_id = SET_CONFIGURATION;
> +	else if (strncasecmp(pm_api_req, "GET_NODE_STATUS", 15) == 0)
> +		pm_id = GET_NODE_STATUS;
> +	else if (strncasecmp(pm_api_req,
> +			     "GET_OPERATING_CHARACTERISTIC", 28) == 0)
> +		pm_id = GET_OPERATING_CHARACTERISTIC;
> +	else if (strncasecmp(pm_api_req, "REGISTER_NOTIFIER", 17) == 0)
> +		pm_id = REGISTER_NOTIFIER;
> +	else if (strncasecmp(pm_api_req, "RESET_ASSERT", 12) == 0)
> +		pm_id = RESET_ASSERT;
> +	else if (strncasecmp(pm_api_req, "RESET_GET_STATUS", 16) == 0)
> +		pm_id = RESET_GET_STATUS;
> +	else if (strncasecmp(pm_api_req, "MMIO_READ", 9) == 0)
> +		pm_id = MMIO_READ;
> +	else if (strncasecmp(pm_api_req, "MMIO_WRITE", 10) == 0)
> +		pm_id = MMIO_WRITE;
> +	else if (strncasecmp(pm_api_req, "GET_CHIPID", 9) == 0)
> +		pm_id = GET_CHIPID;
> +	else if (strncasecmp(pm_api_req, "PINCTRL_GET_FUNCTION", 21) == 0)
> +		pm_id = PINCTRL_GET_FUNCTION;
> +	else if (strncasecmp(pm_api_req, "PINCTRL_SET_FUNCTION", 21) == 0)
> +		pm_id = PINCTRL_SET_FUNCTION;
> +	else if (strncasecmp(pm_api_req,
> +			     "PINCTRL_CONFIG_PARAM_GET", 25) == 0)
> +		pm_id = PINCTRL_CONFIG_PARAM_GET;
> +	else if (strncasecmp(pm_api_req,
> +			     "PINCTRL_CONFIG_PARAM_SET", 25) == 0)
> +		pm_id = PINCTRL_CONFIG_PARAM_SET;
> +	else if (strncasecmp(pm_api_req, "IOCTL", 6) == 0)
> +		pm_id = IOCTL;
> +	else if (strncasecmp(pm_api_req, "CLOCK_ENABLE", 12) == 0)
> +		pm_id = CLOCK_ENABLE;
> +	else if (strncasecmp(pm_api_req, "CLOCK_DISABLE", 13) == 0)
> +		pm_id = CLOCK_DISABLE;
> +	else if (strncasecmp(pm_api_req, "CLOCK_GETSTATE", 14) == 0)
> +		pm_id = CLOCK_GETSTATE;
> +	else if (strncasecmp(pm_api_req, "CLOCK_SETDIVIDER", 16) == 0)
> +		pm_id = CLOCK_SETDIVIDER;
> +	else if (strncasecmp(pm_api_req, "CLOCK_GETDIVIDER", 16) == 0)
> +		pm_id = CLOCK_GETDIVIDER;
> +	else if (strncasecmp(pm_api_req, "CLOCK_SETRATE", 13) == 0)
> +		pm_id = CLOCK_SETRATE;
> +	else if (strncasecmp(pm_api_req, "CLOCK_GETRATE", 13) == 0)
> +		pm_id = CLOCK_GETRATE;
> +	else if (strncasecmp(pm_api_req, "CLOCK_SETPARENT", 15) == 0)
> +		pm_id = CLOCK_SETPARENT;
> +	else if (strncasecmp(pm_api_req, "CLOCK_GETPARENT", 15) == 0)
> +		pm_id = CLOCK_GETPARENT;
> +	else if (strncasecmp(pm_api_req, "QUERY_DATA", 22) == 0)
> +		pm_id = QUERY_DATA;
> +
> +	/* If no name was entered look for PM-API ID instead */
> +	else if (kstrtouint(pm_api_req, 10, &pm_id))
> +		ret = -EINVAL;

"goto err" ?

otherwise you'll try to parse the arguments for not reason.

> +

Could the function be split in two? One to fetch the pm_id, the other to 
process the request?

> +	/* Read node_id and arguments from the PM-API request */
> +	i = 0;
> +	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, " ");
> +	}
> +

Nit: This could go in the switch statement, knowing in each case how 
many times strsep needs to be called. And you could add an argument to 
zynqmp_pm_argument_value to specify the default value you want returned 
when a pm_argument is missing/invalid.

> +	switch (pm_id) {
> +	case GET_API_VERSION:
> +		eemi_ops->get_api_version(&pm_api_version);
> +		pr_info("%s PM-API Version = %d.%d\n", __func__,
> +			pm_api_version >> 16, pm_api_version & 0xffff);
> +		break;
> +	case 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 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 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 ABORT_SUSPEND:
> +		ret = zynqmp_pm_abort_suspend(pm_api_arg[0] ? pm_api_arg[0] :
> +					      ZYNQMP_PM_ABORT_REASON_UNKNOWN);
> +		break;
> +	case 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 SET_WAKEUP_SOURCE:
> +		ret = eemi_ops->set_wakeup_source(pm_api_arg[0], pm_api_arg[1],
> +						  pm_api_arg[2]);
> +		break;
> +	case SYSTEM_SHUTDOWN:
> +		ret = eemi_ops->system_shutdown(pm_api_arg[0], pm_api_arg[1]);
> +		break;
> +	case 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 RELEASE_NODE:
> +		ret = eemi_ops->release_node(pm_api_arg[0]);
> +		break;
> +	case 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 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 SET_CONFIGURATION:
> +		ret = eemi_ops->set_configuration(pm_api_arg[0]);
> +		break;
> +	case 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)
> +			pr_info("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 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)
> +			pr_info("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 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 RESET_ASSERT:
> +		ret = eemi_ops->reset_assert(pm_api_arg[0], pm_api_arg[1]);
> +		break;
> +	case RESET_GET_STATUS:
> +		ret = eemi_ops->reset_get_status(pm_api_arg[0], &pm_api_ret[0]);
> +		pr_info("%s Reset status: %u\n", __func__, pm_api_ret[0]);
> +		break;
> +	case GET_CHIPID:
> +		ret = eemi_ops->get_chipid(&pm_api_ret[0], &pm_api_ret[1]);
> +		pr_info("%s idcode: %#x, version:%#x\n",
> +			__func__, pm_api_ret[0], pm_api_ret[1]);
> +		break;
> +	case PINCTRL_GET_FUNCTION:
> +		ret = eemi_ops->pinctrl_get_function(pm_api_arg[0],
> +						     &pm_api_ret[0]);
> +		pr_info("%s Current set function for the pin: %u\n",
> +			__func__, pm_api_ret[0]);
> +		break;
> +	case PINCTRL_SET_FUNCTION:
> +		ret = eemi_ops->pinctrl_set_function(pm_api_arg[0],
> +						     pm_api_arg[1]);
> +		break;
> +	case PINCTRL_CONFIG_PARAM_GET:
> +		ret = eemi_ops->pinctrl_get_config(pm_api_arg[0], pm_api_arg[1],
> +						   &pm_api_ret[0]);
> +		pr_info("%s pin: %llu, param: %llu, value: %u\n",
> +			__func__, pm_api_arg[0], pm_api_arg[1],
> +			pm_api_ret[0]);
> +		break;
> +	case PINCTRL_CONFIG_PARAM_SET:
> +		ret = eemi_ops->pinctrl_set_config(pm_api_arg[0],
> +						   pm_api_arg[1],
> +						   pm_api_arg[2]);
> +		break;
> +	case 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 (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)
> +			pr_info("%s Value: %u\n",
> +				__func__, pm_api_ret[1]);
> +		break;
> +	case CLOCK_ENABLE:
> +		ret = eemi_ops->clock_enable(pm_api_arg[0]);
> +		break;
> +	case CLOCK_DISABLE:
> +		ret = eemi_ops->clock_disable(pm_api_arg[0]);
> +		break;
> +	case CLOCK_GETSTATE:
> +		ret = eemi_ops->clock_getstate(pm_api_arg[0], &pm_api_ret[0]);
> +		pr_info("%s state: %u\n", __func__, pm_api_ret[0]);
> +		break;
> +	case CLOCK_SETDIVIDER:
> +		ret = eemi_ops->clock_setdivider(pm_api_arg[0], pm_api_arg[1]);
> +		break;
> +	case CLOCK_GETDIVIDER:
> +		ret = eemi_ops->clock_getdivider(pm_api_arg[0], &pm_api_ret[0]);
> +		pr_info("%s Divider Value: %d\n", __func__, pm_api_ret[0]);
> +		break;
> +	case CLOCK_SETRATE:
> +		ret = eemi_ops->clock_setrate(pm_api_arg[0], pm_api_arg[1]);
> +		break;
> +	case CLOCK_GETRATE:
> +		ret = eemi_ops->clock_getrate(pm_api_arg[0], &pm_api_ret[0]);
> +		pr_info("%s Rate Value: %u\n", __func__, pm_api_ret[0]);
> +		break;
> +	case CLOCK_SETPARENT:
> +		ret = eemi_ops->clock_setparent(pm_api_arg[0], pm_api_arg[1]);
> +		break;
> +	case CLOCK_GETPARENT:
> +		ret = eemi_ops->clock_getparent(pm_api_arg[0], &pm_api_ret[0]);
> +		pr_info("%s Parent Index: %u\n", __func__, pm_api_ret[0]);
> +		break;
> +	case 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);
> +
> +		pr_info("%s: data[0] = 0x%08x\n", __func__, pm_api_ret[0]);
> +		pr_info("%s: data[1] = 0x%08x\n", __func__, pm_api_ret[1]);
> +		pr_info("%s: data[2] = 0x%08x\n", __func__, pm_api_ret[2]);
> +		pr_info("%s: data[3] = 0x%08x\n", __func__, pm_api_ret[3]);
> +		break;
> +	}
> +	default:
> +		pr_err("%s Unsupported PM-API request\n", __func__);
> +		ret = -EINVAL;
> +	}
> +
> +err:
> +	kfree(tmp_buff);
> +	if (ret)
> +		return ret;
> +
> +	return len;
> +}
> +
> +/**
> + * zynqmp_pm_debugfs_api_version_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
> + *		-EFAULT otherwise
> + *
> + * Used to display the pm api version.
> + * cat /sys/kernel/debug/zynqmp_pm/pm_api_version
> + */
> +static ssize_t zynqmp_pm_debugfs_api_version_read(struct file *file,
> +						  char __user *ptr, size_t len,
> +						  loff_t *off)
> +{
> +	char *kern_buff;
> +	int ret;
> +	int kern_buff_len;
> +	u32 pm_api_version;
> +	const struct zynqmp_eemi_ops *eemi_ops = get_eemi_ops();
> +
> +	if (!eemi_ops || !eemi_ops->get_api_version)
> +		return -ENXIO;
> +
> +	if (len <= 0)

len is unsigned and cannot be negative

> +		return -EINVAL;
> +
> +	if (*off != 0)
> +		return 0;
> +
> +	kern_buff = kzalloc(len, GFP_KERNEL);

If "len < 24 + strlen(<major and minor version numbers>)", kern_buff is 
too small for what the sprintf will write in it. I guess this need to be 
checked above with "len == 0".


> +	if (!kern_buff)
> +		return -ENOMEM;
> +
> +	eemi_ops->get_api_version(&pm_api_version);
> +	sprintf(kern_buff, "PM-API Version = %d.%d\n",
> +		pm_api_version >> 16, pm_api_version & 0xff > +	kern_buff_len = strlen(kern_buff) + 1;
> +
> +	if (len > kern_buff_len)
> +		len = kern_buff_len;
> +	ret = copy_to_user(ptr, kern_buff, len); > +
> +	kfree(kern_buff);
> +	if (ret)
> +		return -EFAULT;
> +
> +	*off = len + 1;
> +
> +	return len;
> +}
> +
> +/* 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_version_read,
> +};
> +
> +/**
> + * zynqmp_pm_api_debugfs_init - Initialize debugfs interface
> + *
> + * Return:      Returns 0 on success
> + *		Corresponding error code otherwise
> + */
> +int zynqmp_pm_api_debugfs_init(void)
> +{
> +	int err;
> +
> +	/* Initialize debugfs interface */
> +	zynqmp_pm_debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
> +	if (!zynqmp_pm_debugfs_dir) {
> +		pr_err("debugfs_create_dir failed\n");
> +		return -ENODEV;
> +	}
> +
> +	zynqmp_pm_debugfs_power =
> +		debugfs_create_file("pm", 0220,
> +				    zynqmp_pm_debugfs_dir, NULL,
> +				    &fops_zynqmp_pm_dbgfs);
> +	if (!zynqmp_pm_debugfs_power) {
> +		pr_err("debugfs_create_file power failed\n");
> +		err = -ENODEV;
> +		goto err_dbgfs;
> +	}
> +
> +	zynqmp_pm_debugfs_api_version =
> +		debugfs_create_file("api_version", 0444,
> +				    zynqmp_pm_debugfs_dir, NULL,
> +				    &fops_zynqmp_pm_dbgfs);
> +	if (!zynqmp_pm_debugfs_api_version) {
> +		pr_err("debugfs_create_file api_version failed\n");
> +		err = -ENODEV;
> +		goto err_dbgfs;
> +	}
> +
> +	return 0;
> +
> +err_dbgfs:
> +	debugfs_remove_recursive(zynqmp_pm_debugfs_dir);
> +	zynqmp_pm_debugfs_dir = NULL;
> +
> +	return err;
> +}
> diff --git a/drivers/firmware/xilinx/zynqmp/firmware-ggs.c b/drivers/firmware/xilinx/zynqmp/firmware-ggs.c
> new file mode 100644
> index 0000000..feb6148
> --- /dev/null
> +++ b/drivers/firmware/xilinx/zynqmp/firmware-ggs.c
> @@ -0,0 +1,298 @@
> +/*
> + * Xilinx Zynq MPSoC Firmware layer
> + *
> + *  Copyright (C) 2014-2017 Xilinx, Inc.
> + *
> + *  Rajan Vaja <rajanv@xilinx.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#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/platform_device.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 = get_eemi_ops();
> +
> +	if (!eemi_ops || !eemi_ops->ioctl)
> +		return 0;
> +
> +	ret = eemi_ops->ioctl(0, ioctl_id, reg, 0, ret_payload);
> +	if (ret)
> +		return ret;
> +
> +	return snprintf(buf, PAGE_SIZE, "0x%x\n", ret_payload[1]);
> +}
> +
> +static ssize_t write_register(const char *buf, size_t count,
> +			      u32 ioctl_id, u32 reg)
> +{
> +	char *kern_buff;
> +	char *inbuf;
> +	char *tok;
> +	long mask;
> +	long value;
> +	int ret;
> +	u32 ret_payload[PAYLOAD_ARG_CNT];
> +	const struct zynqmp_eemi_ops *eemi_ops = 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, ioctl_id, 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, ioctl_id, 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
> + * @dev: Device structure
> + * @attr: Device 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/devices/platform/firmware/ggs0
> + */
> +static ssize_t ggs_show(struct device *dev,
> +			struct device_attribute *attr,
> +			char *buf,
> +			u32 reg)
> +{
> +	return read_register(buf, IOCTL_READ_GGS, reg);
> +}
> +
> +/**
> + * ggs_store - Store global general storage (ggs) sysfs attribute
> + * @dev: Device structure
> + * @attr: Device 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/devices/platform/firmware/ggs0
> + */
> +static ssize_t ggs_store(struct device *dev,
> +			 struct device_attribute *attr,
> +			 const char *buf,
> +			 size_t count,
> +			 u32 reg)
> +{
> +	if (!dev || !attr || !buf || !count || reg >= GSS_NUM_REGS)
> +		return -EINVAL;
> +
> +	return write_register(buf, count, IOCTL_WRITE_GGS, reg);
> +}
> +
> +/* GGS register show functions */
> +#define GGS0_SHOW(N) \
> +	ssize_t ggs##N##_show(struct device *dev, \
> +			 struct device_attribute *attr, \
> +			 char *buf) \
> +	{ \
> +		return ggs_show(dev, 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 device *dev, \
> +				   struct device_attribute *attr, \
> +				   const char *buf, \
> +				   size_t count) \
> +	{ \
> +		return ggs_store(dev, attr, buf, count, N); \
> +	}
> +
> +static GGS0_STORE(0);
> +static GGS0_STORE(1);
> +static GGS0_STORE(2);
> +static GGS0_STORE(3);
> +
> +/* GGS register device attributes */
> +static DEVICE_ATTR_RW(ggs0);
> +static DEVICE_ATTR_RW(ggs1);
> +static DEVICE_ATTR_RW(ggs2);
> +static DEVICE_ATTR_RW(ggs3);
> +
> +#define CREATE_GGS_DEVICE(dev, N) \
> +do { \
> +	if (device_create_file(dev, &dev_attr_ggs##N)) \
> +		dev_err(dev, "unable to create ggs%d attribute\n", N); \
> +} while (0)
> +
> +/**
> + * pggs_show - Show persistent global general storage (pggs) sysfs attribute
> + * @dev: Device structure
> + * @attr: Device 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 device *dev,
> +			 struct device_attribute *attr,
> +			 char *buf,
> +			 u32 reg)
> +{
> +	return read_register(buf, IOCTL_READ_GGS, reg);
> +}
> +
> +/**
> + * pggs_store - Store persistent global general storage (pggs) sysfs attribute
> + * @dev: Device structure
> + * @attr: Device 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 device *dev,
> +			  struct device_attribute *attr,
> +			  const char *buf,
> +			  size_t count,
> +			  u32 reg)
> +{
> +	return write_register(buf, count, IOCTL_WRITE_PGGS, reg);
> +}
> +
> +#define PGGS0_SHOW(N) \
> +	ssize_t pggs##N##_show(struct device *dev, \
> +			 struct device_attribute *attr, \
> +			 char *buf) \
> +	{ \
> +		return pggs_show(dev, attr, buf, N); \
> +	}
> +
> +/* PGGS register show functions */
> +static PGGS0_SHOW(0);
> +static PGGS0_SHOW(1);
> +static PGGS0_SHOW(2);
> +static PGGS0_SHOW(3);
> +
> +#define PGGS0_STORE(N) \
> +	ssize_t pggs##N##_store(struct device *dev, \
> +				   struct device_attribute *attr, \
> +				   const char *buf, \
> +				   size_t count) \
> +	{ \
> +		return pggs_store(dev, attr, buf, count, N); \
> +	}
> +
> +/* PGGS register store functions */
> +static PGGS0_STORE(0);
> +static PGGS0_STORE(1);
> +static PGGS0_STORE(2);
> +static PGGS0_STORE(3);
> +
> +/* PGGS register device attributes */
> +static DEVICE_ATTR_RW(pggs0);
> +static DEVICE_ATTR_RW(pggs1);
> +static DEVICE_ATTR_RW(pggs2);
> +static DEVICE_ATTR_RW(pggs3);
> +
> +#define CREATE_PGGS_DEVICE(dev, N) \
> +do { \
> +	if (device_create_file(dev, &dev_attr_pggs##N)) \
> +		dev_err(dev, "unable to create pggs%d attribute\n", N); \
> +} while (0)
> +
> +void zynqmp_pm_ggs_init(struct device *dev)
> +{
> +	/* Create Global General Storage register. */
> +	CREATE_GGS_DEVICE(dev, 0);
> +	CREATE_GGS_DEVICE(dev, 1);
> +	CREATE_GGS_DEVICE(dev, 2);
> +	CREATE_GGS_DEVICE(dev, 3);
> +
> +	/* Create Persistent Global General Storage register. */
> +	CREATE_PGGS_DEVICE(dev, 0);
> +	CREATE_PGGS_DEVICE(dev, 1);
> +	CREATE_PGGS_DEVICE(dev, 2);
> +	CREATE_PGGS_DEVICE(dev, 3);
> +}
> diff --git a/drivers/firmware/xilinx/zynqmp/firmware.c b/drivers/firmware/xilinx/zynqmp/firmware.c
> new file mode 100644
> index 0000000..edce5eb
> --- /dev/null
> +++ b/drivers/firmware/xilinx/zynqmp/firmware.c
> @@ -0,0 +1,1024 @@
> +/*
> + * Xilinx Zynq MPSoC Firmware layer
> + *
> + *  Copyright (C) 2014-2017 Xilinx, Inc.
> + *
> + *  Michal Simek <michal.simek@xilinx.com>
> + *  Davorin Mista <davorin.mista@aggios.com>
> + *  Jolly Shah <jollys@xilinx.com>
> + *  Rajan Vaja <rajanv@xilinx.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <linux/compiler.h>
> +#include <linux/arm-smccc.h>
> +#include <linux/of.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/interrupt.h>
> +#include <linux/uaccess.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/platform_device.h>
> +
> +#include <linux/firmware/xilinx/zynqmp/firmware.h>
> +#include <linux/firmware/xilinx/zynqmp/firmware-debug.h>
> +
> +#define DRIVER_NAME	"zynqmp_firmware"
> +
> +/**
> + * zynqmp_pm_ret_code - Convert PMU-FW error codes to Linux error codes
> + * @ret_status:		PMUFW return code
> + *
> + * Return:		corresponding Linux error code
> + */
> +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 power 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 power 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 power 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 power 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);
> +}
> +
> +/**
> + * invoke_pm_fn - Invoke the system-level power 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 power 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   - Power Management API ID
> + */
> +int invoke_pm_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;
> +
> +/**
> + * 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];
> +
> +	if (!version)
> +		return zynqmp_pm_ret_code(XST_PM_CONFLICT);
> +
> +	/* Check is PM API version already verified */
> +	if (pm_api_version > 0) {
> +		*version = pm_api_version;
> +		return XST_PM_SUCCESS;
> +	}
> +	invoke_pm_fn(GET_API_VERSION, 0, 0, 0, 0, ret_payload);
> +	*version = ret_payload[1];
> +

I think you forgot to save the result to pm_api_version, unless I am 
missing something.

> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * 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];
> +
> +	if (!idcode || !version)
> +		return -EINVAL;
> +
> +	invoke_pm_fn(GET_CHIPID, 0, 0, 0, 0, ret_payload);
> +	*idcode = ret_payload[1];
> +	*version = ret_payload[2];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * 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
> + */
> +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 invoke_pm_fn(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];
> +
> +	if (!status)
> +		return zynqmp_pm_ret_code(XST_PM_CONFLICT);
> +
> +	invoke_pm_fn(RESET_GET_STATUS, reset, 0, 0, 0, ret_payload);
> +	*status = ret_payload[1];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * 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 invoke_pm_fn(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];
> +
> +	if (!value)
> +		return -EINVAL;
> +
> +	invoke_pm_fn(FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
> +	*value = ret_payload[1];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * 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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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:
> + *			0 - No master is currently using the node
> + *			1 - Only requesting master is currently using the node
> + *			2 - Only other masters are currently using the node
> + *			3 - 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];
> +
> +	if (!status)
> +		return -EINVAL;
> +
> +	invoke_pm_fn(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 zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * 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];
> +
> +	if (!result)
> +		return -EINVAL;
> +
> +	invoke_pm_fn(GET_OPERATING_CHARACTERISTIC,
> +		     node, type, 0, 0, ret_payload);
> +	if (ret_payload[0] == XST_PM_SUCCESS)
> +		*result = ret_payload[1];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * 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 invoke_pm_fn(PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
> +}
> +
> +/**
> + * zynqmp_pm_get_callback_data - Get callback data from firmware
> + * @buf:	Buffer to store payload data
> + *
> + * Return:	Returns status, either success or error+reason
> + */
> +static int zynqmp_pm_get_callback_data(u32 *buf)
> +{
> +	return invoke_pm_fn(GET_CALLBACK_DATA, 0, 0, 0, 0, buf);
> +}
> +
> +/**
> + * 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 invoke_pm_fn(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) - Sha3 init (Here address and size inputs can be NULL)
> + *	BIT(1) - Sha3 update (address should holds the )
> + *	BIT(2) - Sha3 final (address should hold the address of
> + *		 buffer to store hash)
> + *
> + * 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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(PINCTRL_RELEASE, pin, 0, 0, 0, NULL);
> +}
> +
> +/**
> + * zynqmp_pm_pinctrl_get_function() - Read function id set for the given pin
> + * @pin:	Pin number
> + * @node:	Buffer to store node ID matching current function
> + *
> + * 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 *node)
> +{
> +	u32 ret_payload[PAYLOAD_ARG_CNT];
> +
> +	if (!node)
> +		return -EINVAL;
> +
> +	invoke_pm_fn(PINCTRL_GET_FUNCTION, pin, 0, 0, 0, ret_payload);
> +	*node = ret_payload[1];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
> + * @pin:	Pin number
> + * @node:	Node ID mapped with the requested function
> + *
> + * 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 node)
> +{
> +	return invoke_pm_fn(PINCTRL_SET_FUNCTION, pin, node, 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];
> +
> +	if (!value)
> +		return -EINVAL;
> +
> +	invoke_pm_fn(PINCTRL_CONFIG_PARAM_GET, pin,
> +		     param, 0, 0, ret_payload);
> +	*value = ret_payload[1];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * 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 invoke_pm_fn(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.
> + */
> +static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2,
> +			   u32 *out)
> +{
> +	return invoke_pm_fn(IOCTL, node_id, ioctl_id, arg1, arg2, out);
> +}
> +
> +static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
> +{
> +	return invoke_pm_fn(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 invoke_pm_fn(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 invoke_pm_fn(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];
> +
> +	invoke_pm_fn(CLOCK_GETSTATE, clock_id, 0, 0, 0, ret_payload);
> +	*state = ret_payload[1];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * zynqmp_pm_clock_setdivider - Set the clock divider for given id
> + * @clock_id:	ID of the clock
> + * @div_type:	TYPE_DIV1: div1
> + *		TYPE_DIV2: div2
> + * @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 invoke_pm_fn(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
> + * @div_type:	TYPE_DIV1: div1
> + *		TYPE_DIV2: div2
> + * @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];
> +
> +	invoke_pm_fn(CLOCK_GETDIVIDER, clock_id, 0, 0, 0, ret_payload);
> +	*divider = ret_payload[1];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * 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, u32 rate)
> +{
> +	return invoke_pm_fn(CLOCK_SETRATE, clock_id, rate, 0, 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, u32 *rate)
> +{
> +	u32 ret_payload[PAYLOAD_ARG_CNT];
> +
> +	invoke_pm_fn(CLOCK_GETRATE, clock_id, 0, 0, 0, ret_payload);
> +	*rate = ret_payload[1];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +/**
> + * 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 invoke_pm_fn(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];
> +
> +	invoke_pm_fn(CLOCK_GETPARENT, clock_id, 0, 0, 0, ret_payload);
> +	*parent_id = ret_payload[1];
> +
> +	return zynqmp_pm_ret_code((enum pm_ret_status)ret_payload[0]);
> +}
> +
> +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,
> +	.get_callback_data = zynqmp_pm_get_callback_data,
> +	.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,
> +};
> +
> +/**
> + * get_eemi_ops	- Get eemi ops functions
> + *
> + * Return:	- pointer of eemi_ops structure
> + */
> +const struct zynqmp_eemi_ops *get_eemi_ops(void)
> +{
> +	return &eemi_ops;
> +}
> +EXPORT_SYMBOL_GPL(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 power 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 Power management API v%d.%d\n", __func__,
> +		ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR);
> +
> +	of_node_put(np);
> +
> +	return ret;
> +}
> +
> +static const struct of_device_id firmware_of_match[] = {
> +	{ .compatible = "xlnx,zynqmp-firmware", },
> +	{ /* end of table */ },
> +};
> +
> +MODULE_DEVICE_TABLE(of, firmware_of_match);
> +
> +static int zynqmp_firmware_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +
> +	ret = zynqmp_pm_api_debugfs_init();
> +	if (ret) {
> +		pr_err("%s() debugfs init fail with error %d\n", __func__, ret);
> +		return ret;
> +	}
> +
> +	zynqmp_pm_ggs_init(&pdev->dev);
> +
> +	return ret;
> +}
> +
> +static struct platform_driver zynqmp_firmware_platform_driver = {
> +	.probe   = zynqmp_firmware_probe,
> +	.driver  = {
> +			.name             = DRIVER_NAME,
> +			.of_match_table   = firmware_of_match,
> +		   },
> +};
> +builtin_platform_driver(zynqmp_firmware_platform_driver);
> +
> +early_initcall(zynqmp_plat_init);
> 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..a388621
> --- /dev/null
> +++ b/include/linux/firmware/xilinx/zynqmp/firmware-debug.h
> @@ -0,0 +1,32 @@
> +/*
> + * Xilinx Zynq MPSoC Firmware layer
> + *
> + *  Copyright (C) 2014-2017 Xilinx
> + *
> + *  Michal Simek <michal.simek@xilinx.com>
> + *  Davorin Mista <davorin.mista@aggios.com>
> + *  Jolly Shah <jollys@xilinx.com>
> + *  Rajan Vaja <rajanv@xilinx.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef __SOC_ZYNQMP_FIRMWARE_DEBUG_H__
> +#define __SOC_ZYNQMP_FIRMWARE_DEBUG_H__
> +
> +#include <linux/firmware/xilinx/zynqmp/firmware.h>
> +
> +int zynqmp_pm_self_suspend(const u32 node,
> +			   const u32 latency,
> +			   const u32 state);
> +int zynqmp_pm_abort_suspend(const enum zynqmp_pm_abort_reason reason);
> +int zynqmp_pm_register_notifier(const u32 node, const u32 event,
> +				const u32 wake, const u32 enable);
> +
> +#if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE_DEBUG)
> +int zynqmp_pm_api_debugfs_init(void);
> +#else
> +static inline int zynqmp_pm_api_debugfs_init(void) { return 0; }
> +#endif
> +
> +#endif /* __SOC_ZYNQMP_FIRMWARE_DEBUG_H__ */
> diff --git a/include/linux/firmware/xilinx/zynqmp/firmware.h b/include/linux/firmware/xilinx/zynqmp/firmware.h
> new file mode 100644
> index 0000000..2088b15
> --- /dev/null
> +++ b/include/linux/firmware/xilinx/zynqmp/firmware.h
> @@ -0,0 +1,573 @@
> +/*
> + * Xilinx Zynq MPSoC Firmware layer
> + *
> + *  Copyright (C) 2014-2017 Xilinx
> + *
> + *  Michal Simek <michal.simek@xilinx.com>
> + *  Davorin Mista <davorin.mista@aggios.com>
> + *  Jolly Shah <jollys@xilinx.com>
> + *  Rajan Vaja <rajanv@xilinx.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#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_PM_MAX_LATENCY	(~0U)
> +#define ZYNQMP_PM_MAX_QOS	100U
> +
> +/* SMC SIP service Call Function Identifier Prefix */
> +#define PM_SIP_SVC	0xC2000000
> +#define GET_CALLBACK_DATA 0xa01
> +#define SET_SUSPEND_MODE  0xa02
> +
> +/* 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)
> +
> +/* 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: */
> +	GET_API_VERSION = 1,
> +	SET_CONFIGURATION,
> +	GET_NODE_STATUS,
> +	GET_OPERATING_CHARACTERISTIC,
> +	REGISTER_NOTIFIER,
> +	/* API for suspending of PUs: */
> +	REQUEST_SUSPEND,
> +	SELF_SUSPEND,
> +	FORCE_POWERDOWN,
> +	ABORT_SUSPEND,
> +	REQUEST_WAKEUP,
> +	SET_WAKEUP_SOURCE,
> +	SYSTEM_SHUTDOWN,
> +	/* API for managing PM slaves: */
> +	REQUEST_NODE,
> +	RELEASE_NODE,
> +	SET_REQUIREMENT,
> +	SET_MAX_LATENCY,
> +	/* Direct control API functions: */
> +	RESET_ASSERT,
> +	RESET_GET_STATUS,
> +	MMIO_WRITE,
> +	MMIO_READ,
> +	PM_INIT_FINALIZE,
> +	FPGA_LOAD,
> +	FPGA_GET_STATUS,
> +	GET_CHIPID,
> +	/* ID 25 is been used by U-boot to process secure boot images */
> +	/* Secure library generic API functions */
> +	SECURE_SHA = 26,
> +	SECURE_RSA,
> +	/* Pin control API functions */
> +	PINCTRL_REQUEST,
> +	PINCTRL_RELEASE,
> +	PINCTRL_GET_FUNCTION,
> +	PINCTRL_SET_FUNCTION,
> +	PINCTRL_CONFIG_PARAM_GET,
> +	PINCTRL_CONFIG_PARAM_SET,
> +	/* PM IOCTL API */
> +	IOCTL,
> +	/* API to query information from firmware */
> +	QUERY_DATA,
> +	/* Clock control API functions */
> +	CLOCK_ENABLE,
> +	CLOCK_DISABLE,
> +	CLOCK_GETSTATE,
> +	CLOCK_SETDIVIDER,
> +	CLOCK_GETDIVIDER,
> +	CLOCK_SETRATE,
> +	CLOCK_GETRATE,
> +	CLOCK_SETPARENT,
> +	CLOCK_GETPARENT,
> +};

Sould there be a prefix to these IDs? (I can imagine things like "IOCTL" 
easily conflicting with other definitions)

Cheers,

-- 
Julien Thierry

^ permalink raw reply

* [PATCH v3 00/13] arm64 kpti hardening and variant 2 workarounds
From: Matthias Brugger @ 2018-01-09 14:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108185353.sung5ovk65au3kge@armageddon.cambridge.arm.com>

Hi Catalin,

On 01/08/2018 07:53 PM, Catalin Marinas wrote:
> On Mon, Jan 08, 2018 at 05:32:25PM +0000, Will Deacon wrote:
>> Jayachandran C (1):
>>   arm64: cputype: Add MIDR values for Cavium ThunderX2 CPUs
>>
>> Marc Zyngier (3):
>>   arm64: Move post_ttbr_update_workaround to C code
>>   arm64: KVM: Use per-CPU vector when BP hardening is enabled
>>   arm64: KVM: Make PSCI_VERSION a fast path
>>
>> Shanker Donthineni (1):
>>   arm64: Implement branch predictor hardening for Falkor
>>
>> Will Deacon (8):
>>   arm64: use RET instruction for exiting the trampoline
>>   arm64: Kconfig: Reword UNMAP_KERNEL_AT_EL0 kconfig entry
>>   arm64: Take into account ID_AA64PFR0_EL1.CSV3
>>   arm64: cpufeature: Pass capability structure to ->enable callback
>>   drivers/firmware: Expose psci_get_version through psci_ops structure
>>   arm64: Add skeleton to harden the branch predictor against aliasing
>>     attacks
>>   arm64: cputype: Add missing MIDR values for Cortex-A72 and Cortex-A75
>>   arm64: Implement branch predictor hardening for affected Cortex-A CPUs
> 
> I'm queuing these into the arm64 for-next/core (after some overnight
> testing). Any additional fixes should be done on top.
> 

I see these patches are not yet pushed to:
git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git

Did you hit any problems in the overnight tests?

Regards,
Matthias

^ permalink raw reply

* [PATCH v2 5/5] pinctrl: imx6ul: add IOMUXC SNVS pinctrl driver for i.MX 6ULL
From: Linus Walleij @ 2018-01-09 14:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180106142553.15322-6-stefan@agner.ch>

On Sat, Jan 6, 2018 at 3:25 PM, Stefan Agner <stefan@agner.ch> wrote:

> From: Bai Ping <ping.bai@nxp.com>
>
> On i.MX 6ULL, the BOOT_MODEx and TAMPERx pin MUX and CTRL registers
> are available in a separate IOMUXC_SNVS module. Add support for the
> IOMUXC_SNVS module to the i.MX 6UL pinctrl driver.
>
> Signed-off-by: Bai Ping <ping.bai@nxp.com>
> Signed-off-by: Stefan Agner <stefan@agner.ch>
> Reviewed-by: Rob Herring <robh@kernel.org>

Patch applied.

I need clear maintainership for Freescale pin controllers.

Stefan, would you consider making a patch adding you, Dong
Aisheng and Shawn Guo as maintainers in
MAINTAINERS for
drivers/pinctrl/freescale/*
Documentation/devicetree/bindings/pinctrl/fsl,*
?

I don't know if Shawn want to be added, but he wrote the first
version so unless he says explicitly no I think he should be
included.

Sascha, do you also wanna be included?

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH v2 5/5] pinctrl: imx6ul: add IOMUXC SNVS pinctrl driver for i.MX 6ULL
From: Fabio Estevam @ 2018-01-09 14:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdYJcS3Ng=uR-iPgJ22ABfbiVENjWGsaWwShUfbg1hU4+g@mail.gmail.com>

Hi Linus,

On Tue, Jan 9, 2018 at 12:07 PM, Linus Walleij <linus.walleij@linaro.org> wrote:

> Patch applied.
>
> I need clear maintainership for Freescale pin controllers.
>
> Stefan, would you consider making a patch adding you, Dong
> Aisheng and Shawn Guo as maintainers in
> MAINTAINERS for
> drivers/pinctrl/freescale/*
> Documentation/devicetree/bindings/pinctrl/fsl,*
> ?
>
> I don't know if Shawn want to be added, but he wrote the first
> version so unless he says explicitly no I think he should be
> included.
>
> Sascha, do you also wanna be included?

I would also like to be included, if possible.

Thanks

^ permalink raw reply

* [PATCH 3/9] soc: samsung: pmu: Add the PMU data of exynos5433 to support low-power state
From: Sudeep Holla @ 2018-01-09 14:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515484746-10656-4-git-send-email-cw00.choi@samsung.com>



On 09/01/18 07:59, Chanwoo Choi wrote:
> This patch adds the PMU (Power Management Unit) data of exynos5433 SoC
> in order to support the various power modes. Each power mode has
> the different value for reducing the power-consumption.
> 
> Signed-off-by: Jonghwa Lee <jonghwa3.lee@samsung.com>
> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
> ---
>  arch/arm/mach-exynos/common.h               |   2 -
>  drivers/soc/samsung/Makefile                |   3 +-
>  drivers/soc/samsung/exynos-pmu.c            |   1 +
>  drivers/soc/samsung/exynos-pmu.h            |   2 +
>  drivers/soc/samsung/exynos5433-pmu.c        | 286 ++++++++++++++++++++++++++++
>  include/linux/soc/samsung/exynos-regs-pmu.h | 148 ++++++++++++++
>  6 files changed, 439 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/soc/samsung/exynos5433-pmu.c
> 

> diff --git a/drivers/soc/samsung/exynos5433-pmu.c b/drivers/soc/samsung/exynos5433-pmu.c
> new file mode 100644
> index 000000000000..2571e61522f0
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos5433-pmu.c
> @@ -0,0 +1,286 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// Copyright (c) 2018 Samsung Electronics Co., Ltd.
> +// Copyright (c) Jonghwa Lee <jonghwa3.lee@samsung.com>
> +// Copyright (c) Chanwoo Choi <cw00.choi@samsung.com>
> +//
> +// EXYNOS5433 - CPU PMU (Power Management Unit) support
> +
> +#include <linux/soc/samsung/exynos-regs-pmu.h>
> +#include <linux/soc/samsung/exynos-pmu.h>
> +
> +#include "exynos-pmu.h"
> +
> +static struct exynos_pmu_conf exynos5433_pmu_config[] = {
> +	/* { .offset = address,	.val = { AFTR, LPA, SLEEP } } */
> +	{ EXYNOS5433_ATLAS_CPU0_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },
> +	{ EXYNOS5433_DIS_IRQ_ATLAS_CPU0_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0 } },
> +	{ EXYNOS5433_ATLAS_CPU1_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },
> +	{ EXYNOS5433_DIS_IRQ_ATLAS_CPU1_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0 } },
> +	{ EXYNOS5433_ATLAS_CPU2_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },
> +	{ EXYNOS5433_DIS_IRQ_ATLAS_CPU2_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0 } },
> +	{ EXYNOS5433_ATLAS_CPU3_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },
> +	{ EXYNOS5433_DIS_IRQ_ATLAS_CPU3_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0 } },
> +	{ EXYNOS5433_APOLLO_CPU0_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },
> +	{ EXYNOS5433_DIS_IRQ_APOLLO_CPU0_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0 } },
> +	{ EXYNOS5433_APOLLO_CPU1_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },
> +	{ EXYNOS5433_DIS_IRQ_APOLLO_CPU1_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0 } },
> +	{ EXYNOS5433_APOLLO_CPU2_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },
> +	{ EXYNOS5433_DIS_IRQ_APOLLO_CPU2_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0 } },
> +	{ EXYNOS5433_APOLLO_CPU3_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },
> +	{ EXYNOS5433_DIS_IRQ_APOLLO_CPU3_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0 } },
> +	{ EXYNOS5433_ATLAS_NONCPU_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },
> +	{ EXYNOS5433_APOLLO_NONCPU_SYS_PWR_REG,			{ 0x0, 0x0, 0x8 } },


1. First of all why do you need any of these CPU related PMU config
   registers in kernel ? From the information I gathered this is ARM64
   SoC using PSCI. These are needed just in PSCI implementation and not
   in kernel. So can you elaborate on why there are present here ?

2. Are there any public documents that these names map to ?
   If there is none, please replace these codenames(ATLAS, APOLLO) with
   appropriately.

Sorry if these are already answered, just point me to those threads.

-- 
Regards,
Sudeep

^ permalink raw reply

* [PATCH net-next v3 4/4] net: mvpp2: 2500baseX support
From: Andrew Lunn @ 2018-01-09 14:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180109085945.11916-5-antoine.tenart@free-electrons.com>

On Tue, Jan 09, 2018 at 09:59:45AM +0100, Antoine Tenart wrote:
> This patch adds the 2500Base-X PHY mode support in the Marvell PPv2
> driver. 2500Base-X is quite close to 1000Base-X and SGMII modes and uses
> nearly the same code path.
> 
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>

Thanks for adding the comment.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply

* [PATCH v2 1/6] arm: Add BTB invalidation on switch_mm for Cortex-A9, A12 and A17
From: Andre Przywara @ 2018-01-09 14:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108185533.9698-2-marc.zyngier@arm.com>

Hi,

On 08/01/18 18:55, Marc Zyngier wrote:
> In order to avoid aliasing attacks against the branch predictor,
> some implementations require to invalidate the BTB when switching
> from one user context to another.
> 
> For this, we reuse the existing implementation for Cortex-A8, and
> apply it to A9, A12 and A17.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/mm/proc-v7-2level.S |  4 ++--
>  arch/arm/mm/proc-v7-3level.S |  6 ++++++
>  arch/arm/mm/proc-v7.S        | 30 +++++++++++++++---------------
>  3 files changed, 23 insertions(+), 17 deletions(-)
> 
> diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
> index c6141a5435c3..0422e58b74e8 100644
> --- a/arch/arm/mm/proc-v7-2level.S
> +++ b/arch/arm/mm/proc-v7-2level.S
> @@ -41,7 +41,7 @@
>   *	even on Cortex-A8 revisions not affected by 430973.
>   *	If IBE is not set, the flush BTAC/BTB won't do anything.
>   */
> -ENTRY(cpu_ca8_switch_mm)
> +ENTRY(cpu_v7_btbinv_switch_mm)
>  #ifdef CONFIG_MMU
>  	mov	r2, #0
>  	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
> @@ -66,7 +66,7 @@ ENTRY(cpu_v7_switch_mm)
>  #endif
>  	bx	lr
>  ENDPROC(cpu_v7_switch_mm)
> -ENDPROC(cpu_ca8_switch_mm)
> +ENDPROC(cpu_v7_btbinv_switch_mm)
>  
>  /*
>   *	cpu_v7_set_pte_ext(ptep, pte)
> diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
> index 7d16bbc4102b..f6adfe88ead2 100644
> --- a/arch/arm/mm/proc-v7-3level.S
> +++ b/arch/arm/mm/proc-v7-3level.S
> @@ -54,6 +54,11 @@
>   * Set the translation table base pointer to be pgd_phys (physical address of
>   * the new TTB).
>   */
> +ENTRY(cpu_v7_btbinv_switch_mm)
> +#ifdef CONFIG_MMU
> +	mov	r3, #0

As Robin pointed out correctly, BPIALL ignores Rt, so you can get rid of
that line entirely (which is not matching the actual Rt below, btw).
Might be worth to add a comment about this.

Cheers,
Andre.

> +	mcr	p15, 0, r2, c7, c5, 6			@ flush BTAC/BTB
> +#endif
>  ENTRY(cpu_v7_switch_mm)
>  #ifdef CONFIG_MMU
>  	mmid	r2, r2
> @@ -64,6 +69,7 @@ ENTRY(cpu_v7_switch_mm)
>  #endif
>  	ret	lr
>  ENDPROC(cpu_v7_switch_mm)
> +ENDPROC(cpu_v7_btbinv_switch_mm)
>  
>  #ifdef __ARMEB__
>  #define rl r3
> diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
> index 01d64c0b2563..0a14967fd400 100644
> --- a/arch/arm/mm/proc-v7.S
> +++ b/arch/arm/mm/proc-v7.S
> @@ -159,18 +159,18 @@ ENDPROC(cpu_v7_do_resume)
>  #endif
>  
>  /*
> - * Cortex-A8
> + * Cortex-A8/A12/A17 that require a BTB invalidation on switch_mm
>   */
> -	globl_equ	cpu_ca8_proc_init,	cpu_v7_proc_init
> -	globl_equ	cpu_ca8_proc_fin,	cpu_v7_proc_fin
> -	globl_equ	cpu_ca8_reset,		cpu_v7_reset
> -	globl_equ	cpu_ca8_do_idle,	cpu_v7_do_idle
> -	globl_equ	cpu_ca8_dcache_clean_area, cpu_v7_dcache_clean_area
> -	globl_equ	cpu_ca8_set_pte_ext,	cpu_v7_set_pte_ext
> -	globl_equ	cpu_ca8_suspend_size,	cpu_v7_suspend_size
> +	globl_equ	cpu_v7_btbinv_proc_init,	cpu_v7_proc_init
> +	globl_equ	cpu_v7_btbinv_proc_fin,		cpu_v7_proc_fin
> +	globl_equ	cpu_v7_btbinv_reset,		cpu_v7_reset
> +	globl_equ	cpu_v7_btbinv_do_idle,		cpu_v7_do_idle
> +	globl_equ	cpu_v7_btbinv_dcache_clean_area, cpu_v7_dcache_clean_area
> +	globl_equ	cpu_v7_btbinv_set_pte_ext,	cpu_v7_set_pte_ext
> +	globl_equ	cpu_v7_btbinv_suspend_size,	cpu_v7_suspend_size
>  #ifdef CONFIG_ARM_CPU_SUSPEND
> -	globl_equ	cpu_ca8_do_suspend,	cpu_v7_do_suspend
> -	globl_equ	cpu_ca8_do_resume,	cpu_v7_do_resume
> +	globl_equ	cpu_v7_btbinv_do_suspend,	cpu_v7_do_suspend
> +	globl_equ	cpu_v7_btbinv_do_resume,	cpu_v7_do_resume
>  #endif
>  
>  /*
> @@ -181,7 +181,7 @@ ENDPROC(cpu_v7_do_resume)
>  	globl_equ	cpu_ca9mp_reset,	cpu_v7_reset
>  	globl_equ	cpu_ca9mp_do_idle,	cpu_v7_do_idle
>  	globl_equ	cpu_ca9mp_dcache_clean_area, cpu_v7_dcache_clean_area
> -	globl_equ	cpu_ca9mp_switch_mm,	cpu_v7_switch_mm
> +	globl_equ	cpu_ca9mp_switch_mm,	cpu_v7_btbinv_switch_mm
>  	globl_equ	cpu_ca9mp_set_pte_ext,	cpu_v7_set_pte_ext
>  .globl	cpu_ca9mp_suspend_size
>  .equ	cpu_ca9mp_suspend_size, cpu_v7_suspend_size + 4 * 2
> @@ -548,8 +548,8 @@ __v7_setup_stack:
>  
>  	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
>  	define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
> +	define_processor_functions v7_btbinv, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
>  #ifndef CONFIG_ARM_LPAE
> -	define_processor_functions ca8, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
>  	define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
>  #endif
>  #ifdef CONFIG_CPU_PJ4B
> @@ -614,7 +614,7 @@ __v7_ca9mp_proc_info:
>  __v7_ca8_proc_info:
>  	.long	0x410fc080
>  	.long	0xff0ffff0
> -	__v7_proc __v7_ca8_proc_info, __v7_setup, proc_fns = ca8_processor_functions
> +	__v7_proc __v7_ca8_proc_info, __v7_setup, proc_fns = v7_btbinv_processor_functions
>  	.size	__v7_ca8_proc_info, . - __v7_ca8_proc_info
>  
>  #endif	/* CONFIG_ARM_LPAE */
> @@ -658,7 +658,7 @@ __v7_ca7mp_proc_info:
>  __v7_ca12mp_proc_info:
>  	.long	0x410fc0d0
>  	.long	0xff0ffff0
> -	__v7_proc __v7_ca12mp_proc_info, __v7_ca12mp_setup
> +	__v7_proc __v7_ca12mp_proc_info, __v7_ca12mp_setup, proc_fns = v7_btbinv_processor_functions
>  	.size	__v7_ca12mp_proc_info, . - __v7_ca12mp_proc_info
>  
>  	/*
> @@ -688,7 +688,7 @@ __v7_b15mp_proc_info:
>  __v7_ca17mp_proc_info:
>  	.long	0x410fc0e0
>  	.long	0xff0ffff0
> -	__v7_proc __v7_ca17mp_proc_info, __v7_ca17mp_setup
> +	__v7_proc __v7_ca17mp_proc_info, __v7_ca17mp_setup, proc_fns = v7_btbinv_processor_functions
>  	.size	__v7_ca17mp_proc_info, . - __v7_ca17mp_proc_info
>  
>  	/*
> 

^ permalink raw reply

* [PATCH v2 1/6] arm: Add BTB invalidation on switch_mm for Cortex-A9, A12 and A17
From: Marc Zyngier @ 2018-01-09 14:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5b7b171c-ea22-7c65-de8d-cb953a6f1ec3@arm.com>

On 09/01/18 14:14, Andre Przywara wrote:
> Hi,
> 
> On 08/01/18 18:55, Marc Zyngier wrote:
>> In order to avoid aliasing attacks against the branch predictor,
>> some implementations require to invalidate the BTB when switching
>> from one user context to another.
>>
>> For this, we reuse the existing implementation for Cortex-A8, and
>> apply it to A9, A12 and A17.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm/mm/proc-v7-2level.S |  4 ++--
>>  arch/arm/mm/proc-v7-3level.S |  6 ++++++
>>  arch/arm/mm/proc-v7.S        | 30 +++++++++++++++---------------
>>  3 files changed, 23 insertions(+), 17 deletions(-)
>>
>> diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
>> index c6141a5435c3..0422e58b74e8 100644
>> --- a/arch/arm/mm/proc-v7-2level.S
>> +++ b/arch/arm/mm/proc-v7-2level.S
>> @@ -41,7 +41,7 @@
>>   *	even on Cortex-A8 revisions not affected by 430973.
>>   *	If IBE is not set, the flush BTAC/BTB won't do anything.
>>   */
>> -ENTRY(cpu_ca8_switch_mm)
>> +ENTRY(cpu_v7_btbinv_switch_mm)
>>  #ifdef CONFIG_MMU
>>  	mov	r2, #0
>>  	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
>> @@ -66,7 +66,7 @@ ENTRY(cpu_v7_switch_mm)
>>  #endif
>>  	bx	lr
>>  ENDPROC(cpu_v7_switch_mm)
>> -ENDPROC(cpu_ca8_switch_mm)
>> +ENDPROC(cpu_v7_btbinv_switch_mm)
>>  
>>  /*
>>   *	cpu_v7_set_pte_ext(ptep, pte)
>> diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
>> index 7d16bbc4102b..f6adfe88ead2 100644
>> --- a/arch/arm/mm/proc-v7-3level.S
>> +++ b/arch/arm/mm/proc-v7-3level.S
>> @@ -54,6 +54,11 @@
>>   * Set the translation table base pointer to be pgd_phys (physical address of
>>   * the new TTB).
>>   */
>> +ENTRY(cpu_v7_btbinv_switch_mm)
>> +#ifdef CONFIG_MMU
>> +	mov	r3, #0
> 
> As Robin pointed out correctly, BPIALL ignores Rt, so you can get rid of
> that line entirely (which is not matching the actual Rt below, btw).
> Might be worth to add a comment about this.
I know. I just kept it out of consistency with the existing Cortex-A8
workaround, which may or may not behave the same way (I don't have one
around to test...).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCH v2 1/6] arm: Add BTB invalidation on switch_mm for Cortex-A9, A12 and A17
From: Marc Zyngier @ 2018-01-09 14:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <06eb2573-ad3f-c980-ca15-8becfa600f62@arm.com>

On 09/01/18 14:21, Marc Zyngier wrote:
> On 09/01/18 14:14, Andre Przywara wrote:
>> Hi,
>>
>> On 08/01/18 18:55, Marc Zyngier wrote:
>>> In order to avoid aliasing attacks against the branch predictor,
>>> some implementations require to invalidate the BTB when switching
>>> from one user context to another.
>>>
>>> For this, we reuse the existing implementation for Cortex-A8, and
>>> apply it to A9, A12 and A17.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  arch/arm/mm/proc-v7-2level.S |  4 ++--
>>>  arch/arm/mm/proc-v7-3level.S |  6 ++++++
>>>  arch/arm/mm/proc-v7.S        | 30 +++++++++++++++---------------
>>>  3 files changed, 23 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
>>> index c6141a5435c3..0422e58b74e8 100644
>>> --- a/arch/arm/mm/proc-v7-2level.S
>>> +++ b/arch/arm/mm/proc-v7-2level.S
>>> @@ -41,7 +41,7 @@
>>>   *	even on Cortex-A8 revisions not affected by 430973.
>>>   *	If IBE is not set, the flush BTAC/BTB won't do anything.
>>>   */
>>> -ENTRY(cpu_ca8_switch_mm)
>>> +ENTRY(cpu_v7_btbinv_switch_mm)
>>>  #ifdef CONFIG_MMU
>>>  	mov	r2, #0
>>>  	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
>>> @@ -66,7 +66,7 @@ ENTRY(cpu_v7_switch_mm)
>>>  #endif
>>>  	bx	lr
>>>  ENDPROC(cpu_v7_switch_mm)
>>> -ENDPROC(cpu_ca8_switch_mm)
>>> +ENDPROC(cpu_v7_btbinv_switch_mm)
>>>  
>>>  /*
>>>   *	cpu_v7_set_pte_ext(ptep, pte)
>>> diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
>>> index 7d16bbc4102b..f6adfe88ead2 100644
>>> --- a/arch/arm/mm/proc-v7-3level.S
>>> +++ b/arch/arm/mm/proc-v7-3level.S
>>> @@ -54,6 +54,11 @@
>>>   * Set the translation table base pointer to be pgd_phys (physical address of
>>>   * the new TTB).
>>>   */
>>> +ENTRY(cpu_v7_btbinv_switch_mm)
>>> +#ifdef CONFIG_MMU
>>> +	mov	r3, #0
>>
>> As Robin pointed out correctly, BPIALL ignores Rt, so you can get rid of
>> that line entirely (which is not matching the actual Rt below, btw).
>> Might be worth to add a comment about this.
> I know. I just kept it out of consistency with the existing Cortex-A8
> workaround, which may or may not behave the same way (I don't have one
> around to test...).

[pressed send too quickly]

And yes, the r2/r3 business is yet another blunder. Duh.

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* soc: imx: gpcv2: removing and probing fails
From: Lucas Stach @ 2018-01-09 14:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3f836677c6e98aaf01bc1ac8c3410083@agner.ch>

Am Sonntag, den 07.01.2018, 11:48 +0100 schrieb Stefan Agner:
> Hi Andrew,
> 
> I noticed that the driver fails when removing and probing again. As far
> as I can see due to duplicate add of the platform devices.
> 
> As far as I can tell the driver should register the remove callback and
> do a platform_device_unregister on the newly created platform devices.
> However, as far as I can tell we don't hold on to a reference to them...
> I guess we could keep references in imx_gpcv2_probe, but maybe there is
> an easier way?

The GPC v1 driver adds the necessary device dependency between the
power domain devices and the GPC parent device. See the
device_link_add() in imx_pgc_power_domain_probe().

Probably something similar can be done to the GPC v2 driver.

Regards,
Lucas

^ permalink raw reply

* [PATCH 06/19] drm/blend: Add a generic alpha property
From: Daniel Vetter @ 2018-01-09 14:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180109135322.7lb3snbxfcezobhz@flea>

On Tue, Jan 09, 2018 at 02:53:22PM +0100, Maxime Ripard wrote:
> On Tue, Jan 09, 2018 at 01:32:41PM +0100, Daniel Vetter wrote:
> > On Tue, Jan 09, 2018 at 11:56:25AM +0100, Maxime Ripard wrote:
> > > Some drivers duplicate the logic to create a property to store a per-plane
> > > alpha.
> > > 
> > > Let's create a helper in order to move that to the core.
> > > 
> > > Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
> > > Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > 
> > Do we have userspace for this?
> 
> Wayland seems to be on its way to implement this, with ChromeOS using
> it:
> https://lists.freedesktop.org/archives/wayland-devel/2017-August/034741.html
> 
> and more specifically:
> https://chromium.googlesource.com/chromium/src/+/master/third_party/wayland-protocols/unstable/alpha-compositing/alpha-compositing-unstable-v1.xml#118

Yay, would be good to include these links in the patch description. Really
happy we're having a real standard now used by multiple people.

> > Is encoding a fixed 0-255 range really the best idea?
> 
> I don't really know, is there hardware or formats where there is more
> than 255? Or did you mean less than that?

30bit I'd assume wants more alpha. In the past we've done some fixed-point
stuff (e.g. for LUT), using the 0.0-1.0 float range. Using that for the
blend equation docs is also what I recommend (and that we map from 0-255
to 0.0-1.0 logically). Ofc the hw might not do any of that ... I think
0.16 fixed point, stored in a u16 is probably best. That's what we're
doing for gamma tables already, and that way drivers can simply throw away
the lower bits.

> > I know other drivers have skimped on the rules here a bit ... But at least
> > internally (i.e. within the drm_plane_state) we probably should restrict
> > ourselves to u8. And this needs real docs (i.e. the full blend equation
> > drivers are supposed to implement).
> 
> You mean straight vs premultiplied? Maybe we should implement this as
> an additional property in read only depending on how the hardware
> behaves?

No need for an additional property right now, but definitely document
whether you mean straight or pre-multiplied. Just writing down the blend
equation is probably best.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply

* [PATCH v2 1/5] pinctrl: imx: use struct imx_pinctrl_soc_info as a const
From: Gary Bisson @ 2018-01-09 14:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <f12aa7b7b3aea7a691a1acd14b8daa58@agner.ch>

Hi Stefan,

On Mon, Jan 08, 2018 at 09:52:36PM +0100, Stefan Agner wrote:
> On 2018-01-08 17:48, Gary Bisson wrote:
> > Hi Stefan,
> > 
> > On Sat, Jan 06, 2018 at 03:25:49PM +0100, Stefan Agner wrote:
> >> For some SoCs the struct imx_pinctrl_soc_info is passed through
> >> of_device_id.data which is const. Most variables are already const
> >> or otherwise not written. However, some fields are modified at
> >> runtime. Move those fields to the dynamically allocated struct
> >> imx_pinctrl.
> >>
> >> Fixes: b3060044e495 ("pinctrl: freescale: imx7d: make of_device_ids const")
> >> Cc: Shawn Guo <shawnguo@kernel.org>
> >> Cc: Arvind Yadav <arvind.yadav.cs@gmail.com>
> >> Cc: Dong Aisheng <aisheng.dong@nxp.com>
> >> Cc: Gary Bisson <gary.bisson@boundarydevices.com>
> >> Signed-off-by: Stefan Agner <stefan@agner.ch>
> > 
> > This is actually more or less a revert of a previous commit:
> > b28742be4709 pinctrl: imx: remove const qualifier of imx_pinctrl_soc_info
> 
> Hm, I see. However, back then imx_pinctrl_probe still consumed a
> non-const struct imx_pinctrl_soc_info pointer. So this constifies all
> the way through. 
> 
> > 
> > Note that the idea for this commit was to get dt-overlays working and
> > able to do pinctrl changes using configfs interface to load an overlay
> > (using Pantelis patch). Not sure where we stand on loading such overlay
> > from user-space, is it still something that will happen?
> 
> I am all for dt-overlays and actually also hope that it will make it
> completely into mainline. So whatever prevents using device tree
> overlays should be addressed.
> 
> It seems that ngroups is now part of struct pinctrl_dev (num_groups),
> which is still writable. So we should be fine?

Correct, I forgot about the generic pinmux/pinctrl patches. Indeed
having the structure as const is perfectly fine now, even with
dt-overlays in mind.

Regards,
Gary

^ permalink raw reply

* [PATCH v2 5/5] pinctrl: imx6ul: add IOMUXC SNVS pinctrl driver for i.MX 6ULL
From: Linus Walleij @ 2018-01-09 14:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAOMZO5CjCv1Lg6sazyJWS_xZvD6bXhW=1poYMEFUbgodAST5Yg@mail.gmail.com>

On Tue, Jan 9, 2018 at 3:11 PM, Fabio Estevam <festevam@gmail.com> wrote:
> On Tue, Jan 9, 2018 at 12:07 PM, Linus Walleij <linus.walleij@linaro.org> wrote:
>
>> Patch applied.
>>
>> I need clear maintainership for Freescale pin controllers.
>>
>> Stefan, would you consider making a patch adding you, Dong
>> Aisheng and Shawn Guo as maintainers in
>> MAINTAINERS for
>> drivers/pinctrl/freescale/*
>> Documentation/devicetree/bindings/pinctrl/fsl,*
>> ?
>>
>> I don't know if Shawn want to be added, but he wrote the first
>> version so unless he says explicitly no I think he should be
>> included.
>>
>> Sascha, do you also wanna be included?
>
> I would also like to be included, if possible.

The more the merrier :D

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH] ARM: locomo: fix free dev incorrectly
From: Xiongwei Song @ 2018-01-09 14:37 UTC (permalink / raw)
  To: linux-arm-kernel

In function locomo_init_one_child, If kzalloc call is failed for dev we
would goto out label, then call kfree for dev, however, dev is NULL, we
shouldn't do this.

Signed-off-by: Xiongwei Song <sxwjean@me.com>
---
 arch/arm/common/locomo.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 51936bde1eb2..fb21b5ade391 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -256,10 +256,9 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
 			NO_IRQ : lchip->irq_base + info->irq[0];
 
 	ret = device_register(&dev->dev);
-	if (ret) {
- out:
+	if (ret)
 		kfree(dev);
-	}
+ out:
 	return ret;
 }
 
-- 
2.15.1

^ permalink raw reply related

* [PATCH] drivers: firmware: xilinx: Add ZynqMP firmware driver
From: Sudeep Holla @ 2018-01-09 14:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515449227-5096-1-git-send-email-jollys@xilinx.com>



On 08/01/18 22:07, 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.
> Firmware-debug provides debugfs interface to all APIs.
> Firmware-ggs provides read/write interface to
> global storage registers.
> 
> Signed-off-by: Jolly Shah <jollys@xilinx.com>
> Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
> ---
>  .../firmware/xilinx/xlnx,zynqmp-firmware.txt       |   16 +
>  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    |  540 +++++++++++
>  drivers/firmware/xilinx/zynqmp/firmware-ggs.c      |  298 ++++++
>  drivers/firmware/xilinx/zynqmp/firmware.c          | 1024 ++++++++++++++++++++
>  .../linux/firmware/xilinx/zynqmp/firmware-debug.h  |   32 +
>  include/linux/firmware/xilinx/zynqmp/firmware.h    |  573 +++++++++++
>  13 files changed, 2522 insertions(+)
>  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
> 
> 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..ace111c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
> @@ -0,0 +1,16 @@
> +Xilinx Zynq MPSoC Firmware Device Tree Bindings
> +
> +The zynqmp-firmware node describes the interface to platform firmware.
> +
> +Required properties:
> + - compatible:	Must contain:  "xlnx,zynqmp-firmware"
> + - method:	The method of calling the PM-API firmware layer.
> +		Permitted values are:
> +		 - "smc" : To be used in configurations without a hypervisor
> +		 - "hvc" : To be used when hypervisor is present
> +

If we are having a mailbox using smc/hvc, then it can be made generic
rather than xilinx specific. I can see other user of the same. As Jassi
pointed out in some other thread, Andre has some generic implementation.
Please see how it can be reused.

Also please keep any bindings separate from the driver changes so that
it can be reviewed separately.

> +Examples:
> +	firmware: firmware {
> +		compatible = "xlnx,zynqmp-firmware";
> +		method = "smc";

Ideally this should point to mailbox if we move to using smc/hvc based
mailbox.

[...]

> +
> +config ZYNQMP_FIRMWARE_DEBUG
> +	bool "Enable Xilinx Zynq MPSoC firmware debug APIs"
> +	depends on ARCH_ZYNQMP && DEBUG_FS

Do you need a separate Kconfig option, can't you just use DEBUG_FS ?

[...]

> +
> +	if (strncasecmp(pm_api_req, "REQUEST_SUSPEND", 15) == 0)
> +		pm_id = REQUEST_SUSPEND;
> +	else if (strncasecmp(pm_api_req, "SELF_SUSPEND", 12) == 0)
> +		pm_id = SELF_SUSPEND;
> +	else if (strncasecmp(pm_api_req, "FORCE_POWERDOWN", 15) == 0)
> +		pm_id = FORCE_POWERDOWN;
> +	else if (strncasecmp(pm_api_req, "ABORT_SUSPEND", 13) == 0)
> +		pm_id = ABORT_SUSPEND;


Can this be changed to a loop with a static structure array containing
{pm_id, pm_string, strlen(pm_string)} ?

Also I see hard-coded string length is wrong in some cases like IOCTL.
Isn't it better to just use strlen("..") instead ?

I will stop here as the patch can be easily split and several features
can be added incrementally making the base patch simpler and shorter.

-- 
Regards,
Sudeep

^ permalink raw reply

* [PATCH net-next v3 4/4] net: mvpp2: 2500baseX support
From: Russell King - ARM Linux @ 2018-01-09 14:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180109085945.11916-5-antoine.tenart@free-electrons.com>

On Tue, Jan 09, 2018 at 09:59:45AM +0100, Antoine Tenart wrote:
> This patch adds the 2500Base-X PHY mode support in the Marvell PPv2
> driver. 2500Base-X is quite close to 1000Base-X and SGMII modes and uses
> nearly the same code path.

For 2500Base-X, do you report a speed of 2500Mbps through ethtool, or
are you reporting 1000Mbps?  I don't see any code in this patch that
deals with that.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply

* soc: imx: gpcv2: removing and probing fails
From: Stefan Agner @ 2018-01-09 14:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515507886.12538.33.camel@pengutronix.de>

On 2018-01-09 15:24, Lucas Stach wrote:
> Am Sonntag, den 07.01.2018, 11:48 +0100 schrieb Stefan Agner:
>> Hi Andrew,
>>
>> I noticed that the driver fails when removing and probing again. As far
>> as I can see due to duplicate add of the platform devices.
>>
>> As far as I can tell the driver should register the remove callback and
>> do a platform_device_unregister on the newly created platform devices.
>> However, as far as I can tell we don't hold on to a reference to them...
>> I guess we could keep references in imx_gpcv2_probe, but maybe there is
>> an easier way?
> 
> The GPC v1 driver adds the necessary device dependency between the
> power domain devices and the GPC parent device. See the
> device_link_add() in imx_pgc_power_domain_probe().

Note that despite device_link_add, GPC v1 seems to cause issue with
CONFIG_DEBUG_TEST_DRIVER_REMOVE=y:
https://marc.info/?l=linux-arm-kernel&m=151544599904423&w=4

(sorry, I made it confusing, by adding a stack trace when using GPC v1
in the gpcv2 thread...)

--
Stefan


> 
> Probably something similar can be done to the GPC v2 driver.
> 
> Regards,
> Lucas

^ permalink raw reply

* [PATCH net-next v3 4/4] net: mvpp2: 2500baseX support
From: Russell King - ARM Linux @ 2018-01-09 14:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180109085945.11916-5-antoine.tenart@free-electrons.com>

On Tue, Jan 09, 2018 at 09:59:45AM +0100, Antoine Tenart wrote:
> This patch adds the 2500Base-X PHY mode support in the Marvell PPv2
> driver. 2500Base-X is quite close to 1000Base-X and SGMII modes and uses
> nearly the same code path.

Sorry, also...

> @@ -4668,6 +4692,10 @@ static void mvpp2_port_mii_gmac_configure_mode(struct mvpp2_port *port)
>  		 */
>  		val |= MVPP2_GMAC_CONFIG_GMII_SPEED |
>  		       MVPP2_GMAC_CONFIG_FULL_DUPLEX;
> +	else if (port->phy_interface == PHY_INTERFACE_MODE_2500BASEX)
> +		val |= MVPP2_GMAC_CONFIG_GMII_SPEED |
> +		       MVPP2_GMAC_CONFIG_MII_SPEED |
> +		       MVPP2_GMAC_CONFIG_FULL_DUPLEX;

I think you'll find you don't need to set MII_SPEED here, since
MII_SPEED selects between 10 and 100, GMII_SPEED always takes
precidence selecting 1000, and 2500 is done by the comphy
increasing the clocks by 2.5x.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply

* arm: Is VFP hotplug notifiers wrong?
From: okuno.kohji at jp.panasonic.com @ 2018-01-09 14:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.20.1801091457210.1766@nanos>

Dear Russel and Thomas,

Thank you for your quick response.
Thomas, do you create the patch?

Best regards,
 Kohji Okuno

> -----Original Message-----
> From: Thomas Gleixner [mailto:tglx at linutronix.de]
> Sent: Tuesday, January 9, 2018 10:58 PM
> To: Russell King - ARM Linux
> Cc: Okuno Kohji (?? ??); linux-arm-kernel at lists.infradead.org
> Subject: Re: arm: Is VFP hotplug notifiers wrong?
> 
> On Tue, 9 Jan 2018, Russell King - ARM Linux wrote:
> 
> > On Tue, Jan 09, 2018 at 08:12:21PM +0900, Kohji Okuno wrote:
> > > Dear Thomas and all,
> > >
> > > Could you please confirm about the following commit, again?
> > >
> > > http://git.armlinux.org.uk/cgit/linux-arm.git/commit/arch/arm/vfp/vf
> > > pmodule.c?id=e5b61bafe70477e05e1dce0d6ca4ec181e23cb2a
> > >
> > >
> > > The avobe commit eliminated the following fix, I think.
> > >
> > > http://git.armlinux.org.uk/cgit/linux-arm.git/commit/arch/arm/vfp/vf
> > > pmodule.c?id=384b38b66947b06999b3e39a596d4f2fb94f77e4
> > >
> > >
> > > vfp_force_reload() called from vfp_dying_cpu() does not clear
> > > vfp_current_hw_state[cpu], because cpu stopper task does not own the
> > > context held in the VFP hardware.
> >
> > You are correct, tglx's patch was wrong, since the state in the CPU
> > may not be the current thread's state, so vfp_force_reload() may not
> > do anything.
> >
> > vfp_force_reload() forces the reload of the specified state for the
> > specified CPU.  What the original hotplug code did was to ensure that
> > the CPU's state would be reloaded when it came back up.
> >
> > I do wish that people wouldn't combine functional changes and cleanups
> > into one patch - it makes this kind of thing harder to spot in review
> > and also means when we encounter crap like this, it means we can't
> > simply revert the cleanup.
> 
> sorry about that....

^ permalink raw reply

* [PATCH] ARM: realview: remove eb-mp clcd IRQ
From: Linus Walleij @ 2018-01-09 14:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3cc1ad94-0a62-2f35-d204-2b89b8ba642b@arm.com>

On Mon, Jan 8, 2018 at 5:31 PM, Robin Murphy <robin.murphy@arm.com> wrote:
> On 21/12/17 22:08, Linus Walleij wrote:

>> I do think the reference design has a character LCD, and I
>> do think it has an interrupt, it's just undocumented so
>> someone with this board would have to test it manually
>> to figure out which line it is. Whoever uses this design
>> will get to it if ever.
>
> FWIW the EB baseboard is *physically* the same regardless of the CPU, it's
> just flashed with a Core-Tile-specific FPGA bitstream.

Aha I always wondered how that works :)

> I've just tried
> firing up an 11MPCore one, and indeed the character LCD does light up with
> the kernel version. I can't convince the recalcitrant beast to actually get
> to userspace, though, so I can't confirm what the interrupt's deal is.

Yeah the driver survives fine without an IRQ too so it just works ...

> The baseboard manual (DUI0303E) says it's interrupt 22 on the board-level
> secondary GICs, and since neither the CT11MP nor its corresponding FPGA
> (AN152) mention any alternate routing direct to the Core Tile GIC, I'd guess
> it probably still is. On the other hand, though, it also says this:
>
>   "... However this interrupt signal is reserved for future use and you
>    must use a polling routine instead of an interrupt service routine."
>
> So maybe it's appropriate to just remove the interrupt everywhere :/

Hm I don't think there will be future releases of these EB
boards anytime soon, so I suspect we could just add it.

But as it works fine without IRQ we can just leave it as well.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH] ARM: locomo: fix free dev incorrectly
From: Russell King - ARM Linux @ 2018-01-09 14:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180109143755.16931-1-sxwjean@me.com>

On Tue, Jan 09, 2018 at 10:37:55PM +0800, Xiongwei Song wrote:
> In function locomo_init_one_child, If kzalloc call is failed for dev we
> would goto out label, then call kfree for dev, however, dev is NULL, we
> shouldn't do this.

kfree() internally checks for NULL pointers so callers don't have to.
Your patch is not necessary.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply

* arm: Is VFP hotplug notifiers wrong?
From: Russell King - ARM Linux @ 2018-01-09 14:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <104db10119fd453ba38edac32a228ab6@JPA000SECMN21.palet.jp.panasonic.com>

On Tue, Jan 09, 2018 at 02:46:30PM +0000, okuno.kohji at jp.panasonic.com wrote:
> Dear Russel and Thomas,
> 
> Thank you for your quick response.
> Thomas, do you create the patch?

I'm afraid to say that I think everyone is super busy with spectre
and meltdown at the moment, sorry.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply

* [PATCH] soc: brcmstb: Only register SoC device on STB platforms
From: Thierry Reding @ 2018-01-09 14:54 UTC (permalink / raw)
  To: linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

After moving the SoC device initialization to an early initcall in
commit f780429adfbc ("soc: brcmstb: biuctrl: Move to early_initcall"),
the Broadcom STB SoC device is registered on all platforms if support
for the device is enabled in the kernel configuration.

This causes an additional SoC device to appear on platforms that already
register a native one. In case of Tegra the STB SoC device is registered
as soc0 (with totally meaningless content in the sysfs attributes) and
causes various scripts and programs to fail because they don't know how
to parse that data.

To fix this, duplicate the check from brcmstb_soc_device_early_init()
that already prevents the code from doing anything nonsensical on non-
STB platforms.

Fixes: f780429adfbc ("soc: brcmstb: biuctrl: Move to early_initcall")
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/soc/bcm/brcmstb/common.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
index 781ada62d0a3..4fe1cb73b39a 100644
--- a/drivers/soc/bcm/brcmstb/common.c
+++ b/drivers/soc/bcm/brcmstb/common.c
@@ -89,8 +89,13 @@ early_initcall(brcmstb_soc_device_early_init);
 static int __init brcmstb_soc_device_init(void)
 {
 	struct soc_device_attribute *soc_dev_attr;
+	struct device_node *sun_top_ctrl;
 	struct soc_device *soc_dev;
 
+	sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
+	if (!sun_top_ctrl)
+		return -ENODEV;
+
 	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
 	if (!soc_dev_attr)
 		return -ENOMEM;
-- 
2.15.1

^ permalink raw reply related

* soc: imx: gpcv2: removing and probing fails
From: Lucas Stach @ 2018-01-09 14:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <d71311e13720724b3b3bccd06fe9309b@agner.ch>

Am Dienstag, den 09.01.2018, 15:44 +0100 schrieb Stefan Agner:
> On 2018-01-09 15:24, Lucas Stach wrote:
> > Am Sonntag, den 07.01.2018, 11:48 +0100 schrieb Stefan Agner:
> > > Hi Andrew,
> > > 
> > > I noticed that the driver fails when removing and probing again.
> > > As far
> > > as I can see due to duplicate add of the platform devices.
> > > 
> > > As far as I can tell the driver should register the remove
> > > callback and
> > > do a platform_device_unregister on the newly created platform
> > > devices.
> > > However, as far as I can tell we don't hold on to a reference to
> > > them...
> > > I guess we could keep references in imx_gpcv2_probe, but maybe
> > > there is
> > > an easier way?
> > 
> > The GPC v1 driver adds the necessary device dependency between the
> > power domain devices and the GPC parent device. See the
> > device_link_add() in imx_pgc_power_domain_probe().
> 
> Note that despite device_link_add, GPC v1 seems to cause issue with
> CONFIG_DEBUG_TEST_DRIVER_REMOVE=y:
> https://marc.info/?l=linux-arm-kernel&m=151544599904423&w=4
> 
> (sorry, I made it confusing, by adding a stack trace when using GPC
> v1
> in the gpcv2 thread...)

IMHO this is an issue with the?CONFIG_DEBUG_TEST_DRIVER_REMOVE option,
as it just blindly calls the remove callback instead of doing a proper
__device_release_driver(). All the regular driver/device unbind paths
will properly unbind the consumer devices before removing the driver.

I think this should be fixed in the device driver core instead of
individual drivers.

Regards,
Lucas

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox