Commit da3d0b77 authored by Michal Wilczynski's avatar Michal Wilczynski Committed by Ulf Hansson
Browse files

pmdomain: thead: Instantiate GPU power sequencer via auxiliary bus



In order to support the complex power sequencing required by the TH1520
GPU, the AON power domain driver must be responsible for initiating the
corresponding sequencer driver. This functionality is specific to
platforms where the GPU power sequencing hardware is controlled by the
AON block.

Extend the AON power domain driver to check for the presence of the
"gpu-clkgen" reset in its own device tree node.

If the property is found, create and register a new auxiliary device.
This device acts as a proxy that allows the dedicated `pwrseq-thead-gpu`
auxiliary driver to bind and take control of the sequencing logic.

Reviewed-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Reviewed-by: default avatarBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: default avatarMichal Wilczynski <m.wilczynski@samsung.com>
Link: https://lore.kernel.org/r/20250623-apr_14_for_sending-v6-3-6583ce0f6c25@samsung.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent c7ba7a92
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ config TH1520_PM_DOMAINS
	tristate "Support TH1520 Power Domains"
	depends on TH1520_AON_PROTOCOL
	select REGMAP_MMIO
	select AUXILIARY_BUS
	help
	  This driver enables power domain management for the T-HEAD
	  TH-1520 SoC. On this SoC there are number of power domains,
+51 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 * Author: Michal Wilczynski <m.wilczynski@samsung.com>
 */

#include <linux/auxiliary_bus.h>
#include <linux/firmware/thead/thead,th1520-aon.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
@@ -128,6 +129,50 @@ static void th1520_pd_init_all_off(struct generic_pm_domain **domains,
	}
}

static void th1520_pd_pwrseq_unregister_adev(void *adev)
{
	auxiliary_device_delete(adev);
	auxiliary_device_uninit(adev);
}

static int th1520_pd_pwrseq_gpu_init(struct device *dev)
{
	struct auxiliary_device *adev;
	int ret;

	/*
	 * Correctly check only for the property's existence in the DT node.
	 * We don't need to get/claim the reset here; that is the job of
	 * the auxiliary driver that we are about to spawn.
	 */
	if (device_property_match_string(dev, "reset-names", "gpu-clkgen") < 0)
		/*
		 * This is not an error. It simply means the optional sequencer
		 * is not described in the device tree.
		 */
		return 0;

	adev = devm_kzalloc(dev, sizeof(*adev), GFP_KERNEL);
	if (!adev)
		return -ENOMEM;

	adev->name = "pwrseq-gpu";
	adev->dev.parent = dev;

	ret = auxiliary_device_init(adev);
	if (ret)
		return ret;

	ret = auxiliary_device_add(adev);
	if (ret) {
		auxiliary_device_uninit(adev);
		return ret;
	}

	return devm_add_action_or_reset(dev, th1520_pd_pwrseq_unregister_adev,
					adev);
}

static int th1520_pd_probe(struct platform_device *pdev)
{
	struct generic_pm_domain **domains;
@@ -186,8 +231,14 @@ static int th1520_pd_probe(struct platform_device *pdev)
	if (ret)
		goto err_clean_genpd;

	ret = th1520_pd_pwrseq_gpu_init(dev);
	if (ret)
		goto err_clean_provider;

	return 0;

err_clean_provider:
	of_genpd_del_provider(dev->of_node);
err_clean_genpd:
	for (i--; i >= 0; i--)
		pm_genpd_remove(domains[i]);