Commit b94d3ff9 authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'zynqmp-soc-for-v5.2' of https://github.com/Xilinx/linux-xlnx into arm/drivers

arm64: zynqmp: SoC changes for v5.2

- Add support for ZynqMP fpga manager
- Defer some probes which depends on firmware driver to be ready
- Debugfs fix

* tag 'zynqmp-soc-for-v5.2' of https://github.com/Xilinx/linux-xlnx

:
  fpga manager: Adding FPGA Manager support for Xilinx zynqmp
  dt-bindings: fpga: Add bindings for ZynqMP fpga driver
  firmware: xilinx: Add fpga API's
  drivers: Defer probe if firmware is not ready
  firmware: xilinx: fix debugfs write handler

Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 0065198e c09f7471
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
Devicetree bindings for Zynq Ultrascale MPSoC FPGA Manager.
The ZynqMP SoC uses the PCAP (Processor configuration Port) to configure the
Programmable Logic (PL). The configuration uses  the firmware interface.

Required properties:
- compatible: should contain "xlnx,zynqmp-pcap-fpga"

Example for full FPGA configuration:

	fpga-region0 {
		compatible = "fpga-region";
		fpga-mgr = <&zynqmp_pcap>;
		#address-cells = <0x1>;
		#size-cells = <0x1>;
	};

	firmware {
		zynqmp_firmware: zynqmp-firmware {
			compatible = "xlnx,zynqmp-firmware";
			method = "smc";
			zynqmp_pcap: pcap {
				compatible = "xlnx,zynqmp-pcap-fpga";
			};
		};
	};
+2 −2
Original line number Diff line number Diff line
@@ -41,8 +41,8 @@ Example of EEMI ops usage:
	int ret;

	eemi_ops = zynqmp_pm_get_eemi_ops();
	if (!eemi_ops)
		return -ENXIO;
	if (IS_ERR(eemi_ops))
		return PTR_ERR(eemi_ops);

	ret = eemi_ops->query_data(qdata, ret_payload);

+2 −2
Original line number Diff line number Diff line
@@ -695,8 +695,8 @@ static int zynqmp_clock_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;

	eemi_ops = zynqmp_pm_get_eemi_ops();
	if (!eemi_ops)
		return -ENXIO;
	if (IS_ERR(eemi_ops))
		return PTR_ERR(eemi_ops);

	ret = zynqmp_clk_setup(dev->of_node);

+4 −14
Original line number Diff line number Diff line
@@ -90,9 +90,6 @@ static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret)
	int ret;
	struct zynqmp_pm_query_data qdata = {0};

	if (!eemi_ops)
		return -ENXIO;

	switch (pm_id) {
	case PM_GET_API_VERSION:
		ret = eemi_ops->get_api_version(&pm_api_version);
@@ -163,21 +160,14 @@ static ssize_t zynqmp_pm_debugfs_api_write(struct file *file,

	strcpy(debugfs_buf, "");

	if (*off != 0 || len == 0)
	if (*off != 0 || len <= 1 || len > PAGE_SIZE - 1)
		return -EINVAL;

	kern_buff = kzalloc(len, GFP_KERNEL);
	if (!kern_buff)
		return -ENOMEM;

	kern_buff = memdup_user_nul(ptr, len);
	if (IS_ERR(kern_buff))
		return PTR_ERR(kern_buff);
	tmp_buff = kern_buff;

	ret = strncpy_from_user(kern_buff, ptr, len);
	if (ret < 0) {
		ret = -EFAULT;
		goto err;
	}

	/* Read the API name from a user request */
	pm_api_req = strsep(&kern_buff, " ");

+55 −1
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@
#include <linux/firmware/xlnx-zynqmp.h>
#include "zynqmp-debug.h"

static const struct zynqmp_eemi_ops *eemi_ops_tbl;

static const struct mfd_cell firmware_devs[] = {
	{
		.name = "zynqmp_power_controller",
@@ -537,6 +539,49 @@ static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
	return ret;
}

/**
 * zynqmp_pm_fpga_load - Perform the fpga load
 * @address:	Address to write to
 * @size:	pl bitstream size
 * @flags:	Bitstream type
 *	-XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
 *	-XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
 *
 * This function provides access to pmufw. To transfer
 * the required bitstream into PL.
 *
 * Return: Returns status, either success or error+reason
 */
static int zynqmp_pm_fpga_load(const u64 address, const u32 size,
			       const u32 flags)
{
	return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
				   upper_32_bits(address), size, flags, NULL);
}

/**
 * zynqmp_pm_fpga_get_status - Read value from PCAP status register
 * @value: Value to read
 *
 * This function provides access to the pmufw to get the PCAP
 * status
 *
 * Return: Returns status, either success or error+reason
 */
static int zynqmp_pm_fpga_get_status(u32 *value)
{
	u32 ret_payload[PAYLOAD_ARG_CNT];
	int ret;

	if (!value)
		return -EINVAL;

	ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
	*value = ret_payload[1];

	return ret;
}

/**
 * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
 *			       master has initialized its own power management
@@ -640,6 +685,8 @@ static const struct zynqmp_eemi_ops eemi_ops = {
	.request_node = zynqmp_pm_request_node,
	.release_node = zynqmp_pm_release_node,
	.set_requirement = zynqmp_pm_set_requirement,
	.fpga_load = zynqmp_pm_fpga_load,
	.fpga_get_status = zynqmp_pm_fpga_get_status,
};

/**
@@ -649,7 +696,11 @@ static const struct zynqmp_eemi_ops eemi_ops = {
 */
const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void)
{
	return &eemi_ops;
	if (eemi_ops_tbl)
		return eemi_ops_tbl;
	else
		return ERR_PTR(-EPROBE_DEFER);

}
EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops);

@@ -694,6 +745,9 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
	pr_info("%s Trustzone version v%d.%d\n", __func__,
		pm_tz_version >> 16, pm_tz_version & 0xFFFF);

	/* Assign eemi_ops_table */
	eemi_ops_tbl = &eemi_ops;

	zynqmp_pm_api_debugfs_init();

	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
Loading