diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index 87a1d636c0dc..fd3d83745208 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -539,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 @@ -642,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, }; /** diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index 3533ee557043..1262ea6a1f4b 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -48,6 +48,14 @@ #define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U #define ZYNQMP_PM_CAPABILITY_POWER 0x8U +/* + * Firmware FPGA Manager flags + * XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration + * XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration + */ +#define XILINX_ZYNQMP_PM_FPGA_FULL 0x0U +#define XILINX_ZYNQMP_PM_FPGA_PARTIAL BIT(0) + enum pm_api_id { PM_GET_API_VERSION = 1, PM_REQUEST_NODE = 13, @@ -56,6 +64,8 @@ enum pm_api_id { PM_RESET_ASSERT = 17, PM_RESET_GET_STATUS, PM_PM_INIT_FINALIZE = 21, + PM_FPGA_LOAD, + PM_FPGA_GET_STATUS, PM_GET_CHIPID = 24, PM_IOCTL = 34, PM_QUERY_DATA, @@ -258,6 +268,8 @@ struct zynqmp_pm_query_data { struct zynqmp_eemi_ops { int (*get_api_version)(u32 *version); int (*get_chipid)(u32 *idcode, u32 *version); + int (*fpga_load)(const u64 address, const u32 size, const u32 flags); + int (*fpga_get_status)(u32 *value); int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out); int (*clock_enable)(u32 clock_id); int (*clock_disable)(u32 clock_id);