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

drivers: Defer probe if firmware is not ready

Driver needs ZynqMP firmware interface to call EEMI
APIs. In case firmware is not ready, dependent drivers
should wait until the firmware is ready.

Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com>
Signed-off-by: Jolly Shah <jollys@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>

authored by

Rajan Vaja and committed by
Michal Simek
3d031378 b9472f7d

+47 -28
+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
-3
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);
+10 -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", ··· 651 649 */ 652 650 const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) 653 651 { 654 - return &eemi_ops; 652 + if (eemi_ops_tbl) 653 + return eemi_ops_tbl; 654 + else 655 + return ERR_PTR(-EPROBE_DEFER); 656 + 655 657 } 656 658 EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops); 657 659 ··· 699 693 700 694 pr_info("%s Trustzone version v%d.%d\n", __func__, 701 695 pm_tz_version >> 16, pm_tz_version & 0xFFFF); 696 + 697 + /* Assign eemi_ops_table */ 698 + eemi_ops_tbl = &eemi_ops; 702 699 703 700 zynqmp_pm_api_debugfs_init(); 704 701
+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)
+1 -1
include/linux/firmware/xlnx-zynqmp.h
··· 293 293 #else 294 294 static inline struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) 295 295 { 296 - return NULL; 296 + return ERR_PTR(-ENODEV); 297 297 } 298 298 #endif 299 299