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>
This commit is contained in:
Michael Tretter 2021-08-25 17:03:10 +02:00 коммит произвёл Michal Simek
Родитель fa55b7dcdc
Коммит 7fd890b89d
2 изменённых файлов: 16 добавлений и 1 удалений

Просмотреть файл

@ -152,11 +152,17 @@ static int zynqmp_gpd_power_off(struct generic_pm_domain *domain)
static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain, static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain,
struct device *dev) struct device *dev)
{ {
struct device_link *link;
int ret; int ret;
struct zynqmp_pm_domain *pd; struct zynqmp_pm_domain *pd;
pd = container_of(domain, struct zynqmp_pm_domain, gpd); pd = container_of(domain, struct zynqmp_pm_domain, gpd);
link = device_link_add(dev, &domain->dev, DL_FLAG_SYNC_STATE_ONLY);
if (!link)
dev_dbg(&domain->dev, "failed to create device link for %s\n",
dev_name(dev));
/* If this is not the first device to attach there is nothing to do */ /* If this is not the first device to attach there is nothing to do */
if (domain->device_count) if (domain->device_count)
return 0; return 0;
@ -299,9 +305,19 @@ static int zynqmp_gpd_remove(struct platform_device *pdev)
return 0; return 0;
} }
static void zynqmp_gpd_sync_state(struct device *dev)
{
int ret;
ret = zynqmp_pm_init_finalize();
if (ret)
dev_warn(dev, "failed to release power management to firmware\n");
}
static struct platform_driver zynqmp_power_domain_driver = { static struct platform_driver zynqmp_power_domain_driver = {
.driver = { .driver = {
.name = "zynqmp_power_controller", .name = "zynqmp_power_controller",
.sync_state = zynqmp_gpd_sync_state,
}, },
.probe = zynqmp_gpd_probe, .probe = zynqmp_gpd_probe,
.remove = zynqmp_gpd_remove, .remove = zynqmp_gpd_remove,

Просмотреть файл

@ -178,7 +178,6 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
u32 pm_api_version; u32 pm_api_version;
struct mbox_client *client; struct mbox_client *client;
zynqmp_pm_init_finalize();
zynqmp_pm_get_api_version(&pm_api_version); zynqmp_pm_get_api_version(&pm_api_version);
/* Check PM API version number */ /* Check PM API version number */