Re: [PATCH 3/3] fbdev/simplefb: Add support for interconnect paths

From: Thomas Zimmermann
Date: Fri Jun 20 2025 - 07:02:41 EST


Hi

Am 20.06.25 um 12:31 schrieb Luca Weiss:
Some devices might require keeping an interconnect path alive so that
the framebuffer continues working. Add support for that by setting the
bandwidth requirements appropriately for all provided interconnect
paths.

Signed-off-by: Luca Weiss <luca.weiss@xxxxxxxxxxxxx>
---
drivers/video/fbdev/simplefb.c | 83 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)

diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
index be95fcddce4c8ca794826b805cd7dad2985bd637..ca73e079fd13550ddc779e84db80f7f9b743d074 100644
--- a/drivers/video/fbdev/simplefb.c
+++ b/drivers/video/fbdev/simplefb.c
@@ -27,6 +27,7 @@
#include <linux/parser.h>
#include <linux/pm_domain.h>
#include <linux/regulator/consumer.h>
+#include <linux/interconnect.h>

With alphabetical sorting:

Reviewed-by: Thomas Zimmermann <tzimmermann@xxxxxxx>

Best regards
Thomas


static const struct fb_fix_screeninfo simplefb_fix = {
.id = "simple",
@@ -89,6 +90,10 @@ struct simplefb_par {
u32 regulator_count;
struct regulator **regulators;
#endif
+#if defined CONFIG_OF && defined CONFIG_INTERCONNECT
+ unsigned int icc_count;
+ struct icc_path **icc_paths;
+#endif
};
static void simplefb_clocks_destroy(struct simplefb_par *par);
@@ -525,6 +530,80 @@ static int simplefb_attach_genpds(struct simplefb_par *par,
}
#endif
+#if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS
+/*
+ * Generic interconnect path handling code.
+ */
+static void simplefb_detach_icc(void *res)
+{
+ struct simplefb_par *par = res;
+ int i;
+
+ for (i = par->icc_count - 1; i >= 0; i--) {
+ if (!IS_ERR_OR_NULL(par->icc_paths[i]))
+ icc_put(par->icc_paths[i]);
+ }
+}
+
+static int simplefb_attach_icc(struct simplefb_par *par,
+ struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ int ret, count, i;
+
+ count = of_count_phandle_with_args(dev->of_node, "interconnects",
+ "#interconnect-cells");
+ if (count < 0)
+ return 0;
+
+ /* An interconnect path consists of two elements */
+ if (count % 2) {
+ dev_err(dev, "invalid interconnects value\n");
+ return -EINVAL;
+ }
+ par->icc_count = count / 2;
+
+ par->icc_paths = devm_kcalloc(dev, par->icc_count,
+ sizeof(*par->icc_paths),
+ GFP_KERNEL);
+ if (!par->icc_paths)
+ return -ENOMEM;
+
+ for (i = 0; i < par->icc_count; i++) {
+ par->icc_paths[i] = of_icc_get_by_index(dev, i);
+ if (IS_ERR_OR_NULL(par->icc_paths[i])) {
+ ret = PTR_ERR(par->icc_paths[i]);
+ if (ret == -EPROBE_DEFER)
+ goto err;
+ dev_err(dev, "failed to get interconnect path %u: %d\n", i, ret);
+ continue;
+ }
+
+ ret = icc_set_bw(par->icc_paths[i], 0, UINT_MAX);
+ if (ret) {
+ dev_err(dev, "failed to set interconnect bandwidth %u: %d\n", i, ret);
+ continue;
+ }
+ }
+
+ return devm_add_action_or_reset(dev, simplefb_detach_icc, par);
+
+err:
+ while (i) {
+ --i;
+ if (!IS_ERR_OR_NULL(par->icc_paths[i]))
+ icc_put(par->icc_paths[i]);
+ }
+ return ret;
+}
+#else
+static int simplefb_attach_icc(struct simplefb_par *par,
+ struct platform_device *pdev)
+{
+ return 0;
+}
+#endif
+
static int simplefb_probe(struct platform_device *pdev)
{
int ret;
@@ -615,6 +694,10 @@ static int simplefb_probe(struct platform_device *pdev)
if (ret < 0)
goto error_regulators;
+ ret = simplefb_attach_icc(par, pdev);
+ if (ret < 0)
+ goto error_regulators;
+
simplefb_clocks_enable(par, pdev);
simplefb_regulators_enable(par, pdev);


--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)