@@ -75,6 +75,54 @@ static int panthor_reset_init(struct panthor_device *ptdev)
return 0;
}
+/* Generic power domain handling code, see drivers/gpu/drm/tiny/simpledrm.c */
+static void panthor_detach_genpd(void *res)
+{
+ struct panthor_device *ptdev = res;
+ int i;
+
+ if (ptdev->pwr_dom_count <= 1)
+ return;
+
+ for (i = ptdev->pwr_dom_count - 1; i >= 0; i--)
+ dev_pm_domain_detach(ptdev->pwr_dom_devs[i], true);
+}
+
+static int panthor_genpd_init(struct panthor_device *ptdev)
+{
+ struct device *dev = ptdev->base.dev;
+ int i;
+
+ ptdev->pwr_dom_count = of_count_phandle_with_args(dev->of_node, "power-domains",
+ "#power-domain-cells");
+ /*
+ * Single power-domain devices are handled by driver core nothing to do
+ * here. The same for device nodes without "power-domains" property.
+ */
+ if (ptdev->pwr_dom_count <= 1)
+ return 0;
+
+ if (ptdev->pwr_dom_count > ARRAY_SIZE(ptdev->pwr_dom_devs)) {
+ drm_warn(&ptdev->base, "Too many power domains (%d) for this device\n",
+ ptdev->pwr_dom_count);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ptdev->pwr_dom_count; i++) {
+ ptdev->pwr_dom_devs[i] = dev_pm_domain_attach_by_id(dev, i);
+ if (!IS_ERR(ptdev->pwr_dom_devs[i]))
+ continue;
+
+ /* Missing dependency, try again. */
+ panthor_detach_genpd(ptdev);
+ return dev_err_probe(ptdev->base.dev,
+ PTR_ERR(ptdev->pwr_dom_devs[i]),
+ "pm_domain_attach_by_id(%u) failed\n", i);
+ }
+
+ return devm_add_action_or_reset(dev, panthor_detach_genpd, ptdev);
+}
+
void panthor_device_unplug(struct panthor_device *ptdev)
{
/* This function can be called from two different path: the reset work
@@ -232,6 +280,10 @@ int panthor_device_init(struct panthor_device *ptdev)
if (ret)
return ret;
+ ret = panthor_genpd_init(ptdev);
+ if (ret)
+ return ret;
+
ret = panthor_devfreq_init(ptdev);
if (ret)
return ret;
@@ -114,6 +114,11 @@ struct panthor_device {
/** @resets: GPU reset. */
struct reset_control *resets;
+ /** @pwr_dom_count: Power domain count */
+ int pwr_dom_count;
+ /** @pwr_dom_dev: Power domain devices */
+ struct device *pwr_dom_devs[5];
+
/** @coherent: True if the CPU/GPU are memory coherent. */
bool coherent;
The driver code power domain binding to driver instances only works for single power domain, in case there are multiple power domains, it is necessary to explicitly attach via dev_pm_domain_attach*(). As DT bindings list support for up to 5 power domains, add support for attaching them all. This is useful on Freescale i.MX95 which does have two power domains. Signed-off-by: Marek Vasut <marex@denx.de> --- Cc: Boris Brezillon <boris.brezillon@collabora.com> Cc: Conor Dooley <conor+dt@kernel.org> Cc: David Airlie <airlied@gmail.com> Cc: Fabio Estevam <festevam@gmail.com> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org> Cc: Liviu Dudau <liviu.dudau@arm.com> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Maxime Ripard <mripard@kernel.org> Cc: Pengutronix Kernel Team <kernel@pengutronix.de> Cc: Philipp Zabel <p.zabel@pengutronix.de> Cc: Rob Herring <robh@kernel.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Sebastian Reichel <sre@kernel.org> Cc: Shawn Guo <shawnguo@kernel.org> Cc: Simona Vetter <simona@ffwll.ch> Cc: Steven Price <steven.price@arm.com> Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: devicetree@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: imx@lists.linux.dev Cc: linux-arm-kernel@lists.infradead.org --- V2: Exit from panthor_genpd_init() on any pm_domain_attach_by_id() failure --- drivers/gpu/drm/panthor/panthor_device.c | 52 ++++++++++++++++++++++++ drivers/gpu/drm/panthor/panthor_device.h | 5 +++ 2 files changed, 57 insertions(+)