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

soc: xilinx: move PM_INIT_FINALIZE to zynqmp_pm_domains driver

PM_INIT_FINALIZE tells the PMU FW that Linux is able to handle the power
management nodes that are provided by the PMU FW. Nodes that are not
requested are shut down after this call.

Calling PM_INIT_FINALIZE from the zynqmp_power driver is wrong. The PM
node request mechanism is implemented in the zynqmp_pm_domains driver,
which must also call PM_INIT_FINALIZE.

Due to the behavior of the PMU FW, all devices must be powered up before
PM_INIT_FINALIZE is called, because otherwise the devices might
misbehave. Calling PM_INIT_FINALIZE from the sync_state device callback
ensures that all users probed successfully before the PMU FW is allowed
to power off unused domains.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Acked-by: Michal Simek <michal.simek@xilinx.com>
Acked-by: Rajan Vaja <rajan.vaja@xilinx.com>
Link: https://lore.kernel.org/r/20210825150313.4033156-2-m.tretter@pengutronix.de
Signed-off-by: Michal Simek <michal.simek@xilinx.com>

authored by

Michael Tretter and committed by
Michal Simek
7fd890b8 fa55b7dc

+16 -1
+16
drivers/soc/xilinx/zynqmp_pm_domains.c
··· 152 152 static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain, 153 153 struct device *dev) 154 154 { 155 + struct device_link *link; 155 156 int ret; 156 157 struct zynqmp_pm_domain *pd; 157 158 158 159 pd = container_of(domain, struct zynqmp_pm_domain, gpd); 160 + 161 + link = device_link_add(dev, &domain->dev, DL_FLAG_SYNC_STATE_ONLY); 162 + if (!link) 163 + dev_dbg(&domain->dev, "failed to create device link for %s\n", 164 + dev_name(dev)); 159 165 160 166 /* If this is not the first device to attach there is nothing to do */ 161 167 if (domain->device_count) ··· 305 299 return 0; 306 300 } 307 301 302 + static void zynqmp_gpd_sync_state(struct device *dev) 303 + { 304 + int ret; 305 + 306 + ret = zynqmp_pm_init_finalize(); 307 + if (ret) 308 + dev_warn(dev, "failed to release power management to firmware\n"); 309 + } 310 + 308 311 static struct platform_driver zynqmp_power_domain_driver = { 309 312 .driver = { 310 313 .name = "zynqmp_power_controller", 314 + .sync_state = zynqmp_gpd_sync_state, 311 315 }, 312 316 .probe = zynqmp_gpd_probe, 313 317 .remove = zynqmp_gpd_remove,
-1
drivers/soc/xilinx/zynqmp_power.c
··· 178 178 u32 pm_api_version; 179 179 struct mbox_client *client; 180 180 181 - zynqmp_pm_init_finalize(); 182 181 zynqmp_pm_get_api_version(&pm_api_version); 183 182 184 183 /* Check PM API version number */