Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Olof Johansson <olof@lixom.net>

+302 -39
+25
Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt
··· 1 + Devicetree bindings for Zynq Ultrascale MPSoC FPGA Manager. 2 + The ZynqMP SoC uses the PCAP (Processor configuration Port) to configure the 3 + Programmable Logic (PL). The configuration uses the firmware interface. 4 + 5 + Required properties: 6 + - compatible: should contain "xlnx,zynqmp-pcap-fpga" 7 + 8 + Example for full FPGA configuration: 9 + 10 + fpga-region0 { 11 + compatible = "fpga-region"; 12 + fpga-mgr = <&zynqmp_pcap>; 13 + #address-cells = <0x1>; 14 + #size-cells = <0x1>; 15 + }; 16 + 17 + firmware { 18 + zynqmp_firmware: zynqmp-firmware { 19 + compatible = "xlnx,zynqmp-firmware"; 20 + method = "smc"; 21 + zynqmp_pcap: pcap { 22 + compatible = "xlnx,zynqmp-pcap-fpga"; 23 + }; 24 + }; 25 + };
+2 -2
Documentation/xilinx/eemi.txt
··· 41 41 int ret; 42 42 43 43 eemi_ops = zynqmp_pm_get_eemi_ops(); 44 - if (!eemi_ops) 45 - return -ENXIO; 44 + if (IS_ERR(eemi_ops)) 45 + return PTR_ERR(eemi_ops); 46 46 47 47 ret = eemi_ops->query_data(qdata, ret_payload); 48 48
+2 -2
drivers/clk/zynqmp/clkc.c
··· 695 695 struct device *dev = &pdev->dev; 696 696 697 697 eemi_ops = zynqmp_pm_get_eemi_ops(); 698 - if (!eemi_ops) 699 - return -ENXIO; 698 + if (IS_ERR(eemi_ops)) 699 + return PTR_ERR(eemi_ops); 700 700 701 701 ret = zynqmp_clk_setup(dev->of_node); 702 702
+4 -14
drivers/firmware/xilinx/zynqmp-debug.c
··· 90 90 int ret; 91 91 struct zynqmp_pm_query_data qdata = {0}; 92 92 93 - if (!eemi_ops) 94 - return -ENXIO; 95 - 96 93 switch (pm_id) { 97 94 case PM_GET_API_VERSION: 98 95 ret = eemi_ops->get_api_version(&pm_api_version); ··· 160 163 161 164 strcpy(debugfs_buf, ""); 162 165 163 - if (*off != 0 || len == 0) 166 + if (*off != 0 || len <= 1 || len > PAGE_SIZE - 1) 164 167 return -EINVAL; 165 168 166 - kern_buff = kzalloc(len, GFP_KERNEL); 167 - if (!kern_buff) 168 - return -ENOMEM; 169 - 169 + kern_buff = memdup_user_nul(ptr, len); 170 + if (IS_ERR(kern_buff)) 171 + return PTR_ERR(kern_buff); 170 172 tmp_buff = kern_buff; 171 - 172 - ret = strncpy_from_user(kern_buff, ptr, len); 173 - if (ret < 0) { 174 - ret = -EFAULT; 175 - goto err; 176 - } 177 173 178 174 /* Read the API name from a user request */ 179 175 pm_api_req = strsep(&kern_buff, " ");
+55 -1
drivers/firmware/xilinx/zynqmp.c
··· 24 24 #include <linux/firmware/xlnx-zynqmp.h> 25 25 #include "zynqmp-debug.h" 26 26 27 + static const struct zynqmp_eemi_ops *eemi_ops_tbl; 28 + 27 29 static const struct mfd_cell firmware_devs[] = { 28 30 { 29 31 .name = "zynqmp_power_controller", ··· 540 538 } 541 539 542 540 /** 541 + * zynqmp_pm_fpga_load - Perform the fpga load 542 + * @address: Address to write to 543 + * @size: pl bitstream size 544 + * @flags: Bitstream type 545 + * -XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration 546 + * -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration 547 + * 548 + * This function provides access to pmufw. To transfer 549 + * the required bitstream into PL. 550 + * 551 + * Return: Returns status, either success or error+reason 552 + */ 553 + static int zynqmp_pm_fpga_load(const u64 address, const u32 size, 554 + const u32 flags) 555 + { 556 + return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address), 557 + upper_32_bits(address), size, flags, NULL); 558 + } 559 + 560 + /** 561 + * zynqmp_pm_fpga_get_status - Read value from PCAP status register 562 + * @value: Value to read 563 + * 564 + * This function provides access to the pmufw to get the PCAP 565 + * status 566 + * 567 + * Return: Returns status, either success or error+reason 568 + */ 569 + static int zynqmp_pm_fpga_get_status(u32 *value) 570 + { 571 + u32 ret_payload[PAYLOAD_ARG_CNT]; 572 + int ret; 573 + 574 + if (!value) 575 + return -EINVAL; 576 + 577 + ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload); 578 + *value = ret_payload[1]; 579 + 580 + return ret; 581 + } 582 + 583 + /** 543 584 * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller 544 585 * master has initialized its own power management 545 586 * ··· 685 640 .request_node = zynqmp_pm_request_node, 686 641 .release_node = zynqmp_pm_release_node, 687 642 .set_requirement = zynqmp_pm_set_requirement, 643 + .fpga_load = zynqmp_pm_fpga_load, 644 + .fpga_get_status = zynqmp_pm_fpga_get_status, 688 645 }; 689 646 690 647 /** ··· 696 649 */ 697 650 const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) 698 651 { 699 - return &eemi_ops; 652 + if (eemi_ops_tbl) 653 + return eemi_ops_tbl; 654 + else 655 + return ERR_PTR(-EPROBE_DEFER); 656 + 700 657 } 701 658 EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops); 702 659 ··· 744 693 745 694 pr_info("%s Trustzone version v%d.%d\n", __func__, 746 695 pm_tz_version >> 16, pm_tz_version & 0xFFFF); 696 + 697 + /* Assign eemi_ops_table */ 698 + eemi_ops_tbl = &eemi_ops; 747 699 748 700 zynqmp_pm_api_debugfs_init(); 749 701
+9
drivers/fpga/Kconfig
··· 204 204 205 205 To compile this as a module, choose M here. 206 206 207 + config FPGA_MGR_ZYNQMP_FPGA 208 + tristate "Xilinx ZynqMP FPGA" 209 + depends on ARCH_ZYNQMP || COMPILE_TEST 210 + help 211 + FPGA manager driver support for Xilinx ZynqMP FPGAs. 212 + This driver uses the processor configuration port(PCAP) 213 + to configure the programmable logic(PL) through PS 214 + on ZynqMP SoC. 215 + 207 216 endif # FPGA
+1
drivers/fpga/Makefile
··· 17 17 obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o 18 18 obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o 19 19 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o 20 + obj-$(CONFIG_FPGA_MGR_ZYNQMP_FPGA) += zynqmp-fpga.o 20 21 obj-$(CONFIG_ALTERA_PR_IP_CORE) += altera-pr-ip-core.o 21 22 obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT) += altera-pr-ip-core-plat.o 22 23
+159
drivers/fpga/zynqmp-fpga.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (C) 2019 Xilinx, Inc. 4 + */ 5 + 6 + #include <linux/dma-mapping.h> 7 + #include <linux/fpga/fpga-mgr.h> 8 + #include <linux/io.h> 9 + #include <linux/kernel.h> 10 + #include <linux/module.h> 11 + #include <linux/of_address.h> 12 + #include <linux/string.h> 13 + #include <linux/firmware/xlnx-zynqmp.h> 14 + 15 + /* Constant Definitions */ 16 + #define IXR_FPGA_DONE_MASK BIT(3) 17 + 18 + /** 19 + * struct zynqmp_fpga_priv - Private data structure 20 + * @dev: Device data structure 21 + * @flags: flags which is used to identify the bitfile type 22 + */ 23 + struct zynqmp_fpga_priv { 24 + struct device *dev; 25 + u32 flags; 26 + }; 27 + 28 + static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr, 29 + struct fpga_image_info *info, 30 + const char *buf, size_t size) 31 + { 32 + struct zynqmp_fpga_priv *priv; 33 + 34 + priv = mgr->priv; 35 + priv->flags = info->flags; 36 + 37 + return 0; 38 + } 39 + 40 + static int zynqmp_fpga_ops_write(struct fpga_manager *mgr, 41 + const char *buf, size_t size) 42 + { 43 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 44 + struct zynqmp_fpga_priv *priv; 45 + dma_addr_t dma_addr; 46 + u32 eemi_flags = 0; 47 + char *kbuf; 48 + int ret; 49 + 50 + if (!eemi_ops || !eemi_ops->fpga_load) 51 + return -ENXIO; 52 + 53 + priv = mgr->priv; 54 + 55 + kbuf = dma_alloc_coherent(priv->dev, size, &dma_addr, GFP_KERNEL); 56 + if (!kbuf) 57 + return -ENOMEM; 58 + 59 + memcpy(kbuf, buf, size); 60 + 61 + wmb(); /* ensure all writes are done before initiate FW call */ 62 + 63 + if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG) 64 + eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL; 65 + 66 + ret = eemi_ops->fpga_load(dma_addr, size, eemi_flags); 67 + 68 + dma_free_coherent(priv->dev, size, kbuf, dma_addr); 69 + 70 + return ret; 71 + } 72 + 73 + static int zynqmp_fpga_ops_write_complete(struct fpga_manager *mgr, 74 + struct fpga_image_info *info) 75 + { 76 + return 0; 77 + } 78 + 79 + static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr) 80 + { 81 + const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 82 + u32 status; 83 + 84 + if (!eemi_ops || !eemi_ops->fpga_get_status) 85 + return FPGA_MGR_STATE_UNKNOWN; 86 + 87 + eemi_ops->fpga_get_status(&status); 88 + if (status & IXR_FPGA_DONE_MASK) 89 + return FPGA_MGR_STATE_OPERATING; 90 + 91 + return FPGA_MGR_STATE_UNKNOWN; 92 + } 93 + 94 + static const struct fpga_manager_ops zynqmp_fpga_ops = { 95 + .state = zynqmp_fpga_ops_state, 96 + .write_init = zynqmp_fpga_ops_write_init, 97 + .write = zynqmp_fpga_ops_write, 98 + .write_complete = zynqmp_fpga_ops_write_complete, 99 + }; 100 + 101 + static int zynqmp_fpga_probe(struct platform_device *pdev) 102 + { 103 + struct device *dev = &pdev->dev; 104 + struct zynqmp_fpga_priv *priv; 105 + struct fpga_manager *mgr; 106 + int ret; 107 + 108 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 109 + if (!priv) 110 + return -ENOMEM; 111 + 112 + priv->dev = dev; 113 + 114 + mgr = devm_fpga_mgr_create(dev, "Xilinx ZynqMP FPGA Manager", 115 + &zynqmp_fpga_ops, priv); 116 + if (!mgr) 117 + return -ENOMEM; 118 + 119 + platform_set_drvdata(pdev, mgr); 120 + 121 + ret = fpga_mgr_register(mgr); 122 + if (ret) { 123 + dev_err(dev, "unable to register FPGA manager"); 124 + return ret; 125 + } 126 + 127 + return 0; 128 + } 129 + 130 + static int zynqmp_fpga_remove(struct platform_device *pdev) 131 + { 132 + struct fpga_manager *mgr = platform_get_drvdata(pdev); 133 + 134 + fpga_mgr_unregister(mgr); 135 + 136 + return 0; 137 + } 138 + 139 + static const struct of_device_id zynqmp_fpga_of_match[] = { 140 + { .compatible = "xlnx,zynqmp-pcap-fpga", }, 141 + {}, 142 + }; 143 + 144 + MODULE_DEVICE_TABLE(of, zynqmp_fpga_of_match); 145 + 146 + static struct platform_driver zynqmp_fpga_driver = { 147 + .probe = zynqmp_fpga_probe, 148 + .remove = zynqmp_fpga_remove, 149 + .driver = { 150 + .name = "zynqmp_fpga_manager", 151 + .of_match_table = of_match_ptr(zynqmp_fpga_of_match), 152 + }, 153 + }; 154 + 155 + module_platform_driver(zynqmp_fpga_driver); 156 + 157 + MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>"); 158 + MODULE_DESCRIPTION("Xilinx ZynqMp FPGA Manager"); 159 + MODULE_LICENSE("GPL");
+7 -3
drivers/nvmem/zynqmp_nvmem.c
··· 16 16 struct nvmem_device *nvmem; 17 17 }; 18 18 19 + static const struct zynqmp_eemi_ops *eemi_ops; 20 + 19 21 static int zynqmp_nvmem_read(void *context, unsigned int offset, 20 22 void *val, size_t bytes) 21 23 { ··· 25 23 int idcode, version; 26 24 struct zynqmp_nvmem_data *priv = context; 27 25 28 - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 29 - 30 - if (!eemi_ops || !eemi_ops->get_chipid) 26 + if (!eemi_ops->get_chipid) 31 27 return -ENXIO; 32 28 33 29 ret = eemi_ops->get_chipid(&idcode, &version); ··· 60 60 priv = devm_kzalloc(dev, sizeof(struct zynqmp_nvmem_data), GFP_KERNEL); 61 61 if (!priv) 62 62 return -ENOMEM; 63 + 64 + eemi_ops = zynqmp_pm_get_eemi_ops(); 65 + if (IS_ERR(eemi_ops)) 66 + return PTR_ERR(eemi_ops); 63 67 64 68 priv->dev = dev; 65 69 econfig.dev = dev;
+4 -4
drivers/reset/reset-zynqmp.c
··· 79 79 if (!priv) 80 80 return -ENOMEM; 81 81 82 - platform_set_drvdata(pdev, priv); 83 - 84 82 priv->eemi_ops = zynqmp_pm_get_eemi_ops(); 85 - if (!priv->eemi_ops) 86 - return -ENXIO; 83 + if (IS_ERR(priv->eemi_ops)) 84 + return PTR_ERR(priv->eemi_ops); 85 + 86 + platform_set_drvdata(pdev, priv); 87 87 88 88 priv->rcdev.ops = &zynqmp_reset_ops; 89 89 priv->rcdev.owner = THIS_MODULE;
+10 -8
drivers/soc/xilinx/zynqmp_pm_domains.c
··· 23 23 /* Flag stating if PM nodes mapped to the PM domain has been requested */ 24 24 #define ZYNQMP_PM_DOMAIN_REQUESTED BIT(0) 25 25 26 + static const struct zynqmp_eemi_ops *eemi_ops; 27 + 26 28 /** 27 29 * struct zynqmp_pm_domain - Wrapper around struct generic_pm_domain 28 30 * @gpd: Generic power domain ··· 73 71 { 74 72 int ret; 75 73 struct zynqmp_pm_domain *pd; 76 - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 77 74 78 - if (!eemi_ops || !eemi_ops->set_requirement) 75 + if (!eemi_ops->set_requirement) 79 76 return -ENXIO; 80 77 81 78 pd = container_of(domain, struct zynqmp_pm_domain, gpd); ··· 108 107 struct zynqmp_pm_domain *pd; 109 108 u32 capabilities = 0; 110 109 bool may_wakeup; 111 - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 112 110 113 - if (!eemi_ops || !eemi_ops->set_requirement) 111 + if (!eemi_ops->set_requirement) 114 112 return -ENXIO; 115 113 116 114 pd = container_of(domain, struct zynqmp_pm_domain, gpd); ··· 160 160 { 161 161 int ret; 162 162 struct zynqmp_pm_domain *pd; 163 - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 164 163 165 - if (!eemi_ops || !eemi_ops->request_node) 164 + if (!eemi_ops->request_node) 166 165 return -ENXIO; 167 166 168 167 pd = container_of(domain, struct zynqmp_pm_domain, gpd); ··· 196 197 { 197 198 int ret; 198 199 struct zynqmp_pm_domain *pd; 199 - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 200 200 201 - if (!eemi_ops || !eemi_ops->release_node) 201 + if (!eemi_ops->release_node) 202 202 return; 203 203 204 204 pd = container_of(domain, struct zynqmp_pm_domain, gpd); ··· 263 265 struct generic_pm_domain **domains; 264 266 struct zynqmp_pm_domain *pd; 265 267 struct device *dev = &pdev->dev; 268 + 269 + eemi_ops = zynqmp_pm_get_eemi_ops(); 270 + if (IS_ERR(eemi_ops)) 271 + return PTR_ERR(eemi_ops); 266 272 267 273 pd = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*pd), GFP_KERNEL); 268 274 if (!pd)
+6 -4
drivers/soc/xilinx/zynqmp_power.c
··· 31 31 }; 32 32 33 33 static enum pm_suspend_mode suspend_mode = PM_SUSPEND_MODE_STD; 34 + static const struct zynqmp_eemi_ops *eemi_ops; 34 35 35 36 enum pm_api_cb_id { 36 37 PM_INIT_SUSPEND_CB = 30, ··· 93 92 const char *buf, size_t count) 94 93 { 95 94 int md, ret = -EINVAL; 96 - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 97 95 98 - if (!eemi_ops || !eemi_ops->set_suspend_mode) 96 + if (!eemi_ops->set_suspend_mode) 99 97 return ret; 100 98 101 99 for (md = PM_SUSPEND_MODE_FIRST; md < ARRAY_SIZE(suspend_modes); md++) ··· 120 120 int ret, irq; 121 121 u32 pm_api_version; 122 122 123 - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); 123 + eemi_ops = zynqmp_pm_get_eemi_ops(); 124 + if (IS_ERR(eemi_ops)) 125 + return PTR_ERR(eemi_ops); 124 126 125 - if (!eemi_ops || !eemi_ops->get_api_version || !eemi_ops->init_finalize) 127 + if (!eemi_ops->get_api_version || !eemi_ops->init_finalize) 126 128 return -ENXIO; 127 129 128 130 eemi_ops->init_finalize();
+5
drivers/spi/spi-zynqmp-gqspi.c
··· 138 138 139 139 #define SPI_AUTOSUSPEND_TIMEOUT 3000 140 140 enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA}; 141 + static const struct zynqmp_eemi_ops *eemi_ops; 141 142 142 143 /** 143 144 * struct zynqmp_qspi - Defines qspi driver instance ··· 1021 1020 struct zynqmp_qspi *xqspi; 1022 1021 struct resource *res; 1023 1022 struct device *dev = &pdev->dev; 1023 + 1024 + eemi_ops = zynqmp_pm_get_eemi_ops(); 1025 + if (IS_ERR(eemi_ops)) 1026 + return PTR_ERR(eemi_ops); 1024 1027 1025 1028 master = spi_alloc_master(&pdev->dev, sizeof(*xqspi)); 1026 1029 if (!master)
+13 -1
include/linux/firmware/xlnx-zynqmp.h
··· 48 48 #define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U 49 49 #define ZYNQMP_PM_CAPABILITY_POWER 0x8U 50 50 51 + /* 52 + * Firmware FPGA Manager flags 53 + * XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration 54 + * XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration 55 + */ 56 + #define XILINX_ZYNQMP_PM_FPGA_FULL 0x0U 57 + #define XILINX_ZYNQMP_PM_FPGA_PARTIAL BIT(0) 58 + 51 59 enum pm_api_id { 52 60 PM_GET_API_VERSION = 1, 53 61 PM_REQUEST_NODE = 13, ··· 64 56 PM_RESET_ASSERT = 17, 65 57 PM_RESET_GET_STATUS, 66 58 PM_PM_INIT_FINALIZE = 21, 59 + PM_FPGA_LOAD, 60 + PM_FPGA_GET_STATUS, 67 61 PM_GET_CHIPID = 24, 68 62 PM_IOCTL = 34, 69 63 PM_QUERY_DATA, ··· 268 258 struct zynqmp_eemi_ops { 269 259 int (*get_api_version)(u32 *version); 270 260 int (*get_chipid)(u32 *idcode, u32 *version); 261 + int (*fpga_load)(const u64 address, const u32 size, const u32 flags); 262 + int (*fpga_get_status)(u32 *value); 271 263 int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out); 272 264 int (*clock_enable)(u32 clock_id); 273 265 int (*clock_disable)(u32 clock_id); ··· 305 293 #else 306 294 static inline struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) 307 295 { 308 - return NULL; 296 + return ERR_PTR(-ENODEV); 309 297 } 310 298 #endif 311 299