162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci// Copyright (c) 2022, The Linux Foundation. All rights reserved.
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/export.h>
562306a36Sopenharmony_ci#include <linux/module.h>
662306a36Sopenharmony_ci#include <linux/init.h>
762306a36Sopenharmony_ci#include <linux/of_platform.h>
862306a36Sopenharmony_ci#include <linux/platform_device.h>
962306a36Sopenharmony_ci#include <linux/pm_domain.h>
1062306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "lpass-macro-common.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistruct lpass_macro *lpass_macro_pds_init(struct device *dev)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	struct lpass_macro *l_pds;
1762306a36Sopenharmony_ci	int ret;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	if (!of_property_present(dev->of_node, "power-domains"))
2062306a36Sopenharmony_ci		return NULL;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	l_pds = devm_kzalloc(dev, sizeof(*l_pds), GFP_KERNEL);
2362306a36Sopenharmony_ci	if (!l_pds)
2462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	l_pds->macro_pd = dev_pm_domain_attach_by_name(dev, "macro");
2762306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(l_pds->macro_pd)) {
2862306a36Sopenharmony_ci		ret = l_pds->macro_pd ? PTR_ERR(l_pds->macro_pd) : -ENODATA;
2962306a36Sopenharmony_ci		goto macro_err;
3062306a36Sopenharmony_ci	}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(l_pds->macro_pd);
3362306a36Sopenharmony_ci	if (ret < 0)
3462306a36Sopenharmony_ci		goto macro_sync_err;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	l_pds->dcodec_pd = dev_pm_domain_attach_by_name(dev, "dcodec");
3762306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(l_pds->dcodec_pd)) {
3862306a36Sopenharmony_ci		ret = l_pds->dcodec_pd ? PTR_ERR(l_pds->dcodec_pd) : -ENODATA;
3962306a36Sopenharmony_ci		goto dcodec_err;
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(l_pds->dcodec_pd);
4362306a36Sopenharmony_ci	if (ret < 0)
4462306a36Sopenharmony_ci		goto dcodec_sync_err;
4562306a36Sopenharmony_ci	return l_pds;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cidcodec_sync_err:
4862306a36Sopenharmony_ci	dev_pm_domain_detach(l_pds->dcodec_pd, false);
4962306a36Sopenharmony_cidcodec_err:
5062306a36Sopenharmony_ci	pm_runtime_put(l_pds->macro_pd);
5162306a36Sopenharmony_cimacro_sync_err:
5262306a36Sopenharmony_ci	dev_pm_domain_detach(l_pds->macro_pd, false);
5362306a36Sopenharmony_cimacro_err:
5462306a36Sopenharmony_ci	return ERR_PTR(ret);
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(lpass_macro_pds_init);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_civoid lpass_macro_pds_exit(struct lpass_macro *pds)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	if (pds) {
6162306a36Sopenharmony_ci		pm_runtime_put(pds->macro_pd);
6262306a36Sopenharmony_ci		dev_pm_domain_detach(pds->macro_pd, false);
6362306a36Sopenharmony_ci		pm_runtime_put(pds->dcodec_pd);
6462306a36Sopenharmony_ci		dev_pm_domain_detach(pds->dcodec_pd, false);
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(lpass_macro_pds_exit);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ciMODULE_DESCRIPTION("Common macro driver");
7062306a36Sopenharmony_ciMODULE_LICENSE("GPL");
71