blob: 60f7ec7fbf0a7e2e7e8e1a1b928ea61ced431012 [file] [log] [blame]
From c763801e0d53bb79531c7b2a9a7699b95362ad08 Mon Sep 17 00:00:00 2001
From: Eugene Huang <eugene.ty.huang@fii-na.corp-partner.google.com>
Date: Tue, 20 May 2025 16:49:33 +0800
Subject: [PATCH] Fix the i3c hub node mismatch issue
1.Limit the hub driver to finding the hub node within its parent node
Signed-off-by: Eugene Huang <eugene.ty.huang@fii-na.corp-partner.google.com>
---
drivers/i3c/i3c-hub.c | 26 +++++++++++---------------
1 file changed, 11 insertions(+), 15 deletions(-)
diff --git a/drivers/i3c/i3c-hub.c b/drivers/i3c/i3c-hub.c
index 1d2dd05b9..0728e08c8 100644
--- a/drivers/i3c/i3c-hub.c
+++ b/drivers/i3c/i3c-hub.c
@@ -285,7 +285,6 @@
static const bool ibi_paranoia = true;
static DEFINE_MUTEX(hub_lock);
-static struct device_node *last_node;
/* mapping of part_id register to device-specific data */
static const struct i3c_hub_devdata {
@@ -1891,10 +1890,10 @@ static int i3c_hub_read_id(struct i3c_hub *hub)
static struct device_node *i3c_hub_get_dt_hub_node(struct i3c_hub *hub)
{
- struct device_node *node = hub->i3cdev->dev.parent->of_node;
+ struct device_node *dev_node = hub->i3cdev->dev.parent->of_node;
+ struct device_node *hub_node = NULL;
struct device_node *matched_node = NULL;
int max_ids_matched;
- struct device_node *hub_node, *from;
int node_ids_matched;
u8 dcr;
u32 id_csel, id_cp1, id_tpx;
@@ -1902,19 +1901,11 @@ static struct device_node *i3c_hub_get_dt_hub_node(struct i3c_hub *hub)
max_ids_matched = 0;
- from = last_node ? last_node : node;
- hub_node = NULL;
- while (1) {
- hub_node = of_find_node_by_name(from, "hub");
- if (!hub_node)
- break;
-
+ for_each_child_of_node(dev_node, hub_node){
ret = of_property_read_u8(hub_node, "dcr", &dcr);
if (ret || dcr != I3C_DCR_HUB)
continue;
- from = hub_node;
-
node_ids_matched = 1;
ret = of_property_read_u32(hub_node, "id-csel", &id_csel);
if (ret == 0 && id_csel == (u32)hub->hub_pin_sel_id)
@@ -1929,17 +1920,20 @@ static struct device_node *i3c_hub_get_dt_hub_node(struct i3c_hub *hub)
node_ids_matched += 1;
if (node_ids_matched > max_ids_matched) {
- matched_node = hub_node;
+ if (matched_node)
+ of_node_put(matched_node);
+
max_ids_matched = node_ids_matched;
+ of_node_get(hub_node);
+ matched_node = hub_node;
}
}
if (!matched_node) {
dev_err(&hub->i3cdev->dev, "Node NOT matched\n");
- return matched_node;
+ return NULL;
}
- last_node = matched_node;
/* Find the proper node, update the id values in the node*/
ret = of_property_read_u32(matched_node, "id-csel", &id_csel);
hub->hub_dt_sel_id = ret == 0 ? id_csel : -1;
@@ -2297,6 +2291,8 @@ static void i3c_hub_remove(struct i3c_device *i3cdev)
if (hub->ports[i].bridge)
i3c_master_unregister(&hub->ports[i].bridge->i3c);
}
+
+ of_node_put(hub->of_node);
}
static struct i3c_driver i3c_hub = {
--
2.34.1