Skip to content

Commit 95ac758

Browse files
Include the i2c-xiic driver and add kernel patches
Patches accepted upstream: - https://lore.kernel.org/all/20260223-i2c-xiic-v12-6-b6c9ce4e4f3c@nexthop.ai/ `b4 am 20260223-i2c-xiic-v12-6-b6c9ce4e4f3c@nexthop.ai` Resolves [#543](#543) Resolves [#544](#544) Signed-off-by: Domingo Hui <domingo@nexthop.ai>
1 parent 0535397 commit 95ac758

7 files changed

Lines changed: 446 additions & 0 deletions
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
From 50c63491ff267f2860a6d8cb70c9a30ab701b9d3 Mon Sep 17 00:00:00 2001
2+
From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
3+
Date: Mon, 23 Feb 2026 15:59:16 +0000
4+
Subject: [PATCH 1/7] i2c: xiic: switch to devres managed APIs
5+
6+
Simplify the error code paths by switching to devres managed helper
7+
functions.
8+
9+
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
10+
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
11+
---
12+
drivers/i2c/busses/i2c-xiic.c | 32 +++++++++++++-------------------
13+
1 file changed, 13 insertions(+), 19 deletions(-)
14+
15+
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
16+
index 1d68177241a6..7dcb57dbd8c9 100644
17+
--- a/drivers/i2c/busses/i2c-xiic.c
18+
+++ b/drivers/i2c/busses/i2c-xiic.c
19+
@@ -1229,6 +1229,7 @@ MODULE_DEVICE_TABLE(of, xiic_of_match);
20+
21+
static int xiic_i2c_probe(struct platform_device *pdev)
22+
{
23+
+ struct device *dev = &pdev->dev;
24+
struct xiic_i2c *i2c;
25+
struct xiic_i2c_platform_data *pdata;
26+
const struct of_device_id *match;
27+
@@ -1267,7 +1268,9 @@ static int xiic_i2c_probe(struct platform_device *pdev)
28+
snprintf(i2c->adap.name, sizeof(i2c->adap.name),
29+
DRIVER_NAME " %s", pdev->name);
30+
31+
- mutex_init(&i2c->lock);
32+
+ ret = devm_mutex_init(dev, &i2c->lock);
33+
+ if (ret)
34+
+ return ret;
35+
36+
i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL);
37+
if (IS_ERR(i2c->clk))
38+
@@ -1277,8 +1280,10 @@ static int xiic_i2c_probe(struct platform_device *pdev)
39+
i2c->dev = &pdev->dev;
40+
pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT);
41+
pm_runtime_use_autosuspend(i2c->dev);
42+
- pm_runtime_set_active(i2c->dev);
43+
- pm_runtime_enable(i2c->dev);
44+
+ pm_runtime_set_active(dev);
45+
+ ret = devm_pm_runtime_enable(dev);
46+
+ if (ret)
47+
+ return ret;
48+
49+
/* SCL frequency configuration */
50+
i2c->input_clk = clk_get_rate(i2c->clk);
51+
@@ -1293,8 +1298,8 @@ static int xiic_i2c_probe(struct platform_device *pdev)
52+
pdev->name, i2c);
53+
54+
if (ret < 0) {
55+
- dev_err(&pdev->dev, "Cannot claim IRQ\n");
56+
- goto err_pm_disable;
57+
+ dev_err_probe(&pdev->dev, ret, "Cannot claim IRQ\n");
58+
+ return ret;
59+
}
60+
61+
i2c->singlemaster =
62+
@@ -1313,16 +1318,14 @@ static int xiic_i2c_probe(struct platform_device *pdev)
63+
i2c->endianness = BIG;
64+
65+
ret = xiic_reinit(i2c);
66+
- if (ret < 0) {
67+
- dev_err(&pdev->dev, "Cannot xiic_reinit\n");
68+
- goto err_pm_disable;
69+
- }
70+
+ if (ret)
71+
+ return dev_err_probe(dev, ret, "Cannot xiic_reinit\n");
72+
73+
/* add i2c adapter to i2c tree */
74+
ret = i2c_add_adapter(&i2c->adap);
75+
if (ret) {
76+
xiic_deinit(i2c);
77+
- goto err_pm_disable;
78+
+ return ret;
79+
}
80+
81+
if (pdata) {
82+
@@ -1335,12 +1338,6 @@ static int xiic_i2c_probe(struct platform_device *pdev)
83+
(unsigned long)res->start, irq, i2c->i2c_clk);
84+
85+
return 0;
86+
-
87+
-err_pm_disable:
88+
- pm_runtime_disable(&pdev->dev);
89+
- pm_runtime_set_suspended(&pdev->dev);
90+
-
91+
- return ret;
92+
}
93+
94+
static void xiic_i2c_remove(struct platform_device *pdev)
95+
@@ -1360,9 +1357,6 @@ static void xiic_i2c_remove(struct platform_device *pdev)
96+
xiic_deinit(i2c);
97+
98+
pm_runtime_put_sync(i2c->dev);
99+
- pm_runtime_disable(&pdev->dev);
100+
- pm_runtime_set_suspended(&pdev->dev);
101+
- pm_runtime_dont_use_autosuspend(&pdev->dev);
102+
}
103+
104+
static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev)
105+
--
106+
2.43.0
107+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
From e1d98e42b4b701b193f7c2142901f553734acc6a Mon Sep 17 00:00:00 2001
2+
From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
3+
Date: Mon, 23 Feb 2026 15:59:17 +0000
4+
Subject: [PATCH 2/7] i2c: xiic: remove duplicate error message
5+
6+
The devm_request_threaded_irq() already prints an error message. Remove
7+
the duplicate.
8+
9+
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
10+
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
11+
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
12+
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
13+
---
14+
drivers/i2c/busses/i2c-xiic.c | 5 +----
15+
1 file changed, 1 insertion(+), 4 deletions(-)
16+
17+
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
18+
index 7dcb57dbd8c9..8678962e4ec2 100644
19+
--- a/drivers/i2c/busses/i2c-xiic.c
20+
+++ b/drivers/i2c/busses/i2c-xiic.c
21+
@@ -1296,11 +1296,8 @@ static int xiic_i2c_probe(struct platform_device *pdev)
22+
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
23+
xiic_process, IRQF_ONESHOT,
24+
pdev->name, i2c);
25+
-
26+
- if (ret < 0) {
27+
- dev_err_probe(&pdev->dev, ret, "Cannot claim IRQ\n");
28+
+ if (ret)
29+
return ret;
30+
- }
31+
32+
i2c->singlemaster =
33+
of_property_read_bool(pdev->dev.of_node, "single-master");
34+
--
35+
2.43.0
36+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
From b621a966fbe6b937792a5ec43dc2c5dd68898c60 Mon Sep 17 00:00:00 2001
2+
From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
3+
Date: Mon, 23 Feb 2026 15:59:18 +0000
4+
Subject: [PATCH 3/7] i2c: xiic: switch to generic device property accessors
5+
6+
Use generic device property accessors making them work for ACPI
7+
platforms.
8+
9+
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
10+
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
11+
---
12+
drivers/i2c/busses/i2c-xiic.c | 21 +++++++--------------
13+
1 file changed, 7 insertions(+), 14 deletions(-)
14+
15+
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
16+
index 8678962e4ec2..271f932b23a0 100644
17+
--- a/drivers/i2c/busses/i2c-xiic.c
18+
+++ b/drivers/i2c/busses/i2c-xiic.c
19+
@@ -27,7 +27,6 @@
20+
#include <linux/platform_data/i2c-xiic.h>
21+
#include <linux/io.h>
22+
#include <linux/slab.h>
23+
-#include <linux/of.h>
24+
#include <linux/clk.h>
25+
#include <linux/pm_runtime.h>
26+
27+
@@ -1214,7 +1213,6 @@ static const struct i2c_adapter xiic_adapter = {
28+
.algo = &xiic_algorithm,
29+
};
30+
31+
-#if defined(CONFIG_OF)
32+
static const struct xiic_version_data xiic_2_00 = {
33+
.quirks = DYNAMIC_MODE_READ_BROKEN_BIT,
34+
};
35+
@@ -1225,14 +1223,14 @@ static const struct of_device_id xiic_of_match[] = {
36+
{},
37+
};
38+
MODULE_DEVICE_TABLE(of, xiic_of_match);
39+
-#endif
40+
41+
static int xiic_i2c_probe(struct platform_device *pdev)
42+
{
43+
struct device *dev = &pdev->dev;
44+
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
45+
struct xiic_i2c *i2c;
46+
struct xiic_i2c_platform_data *pdata;
47+
- const struct of_device_id *match;
48+
+ const struct xiic_version_data *data;
49+
struct resource *res;
50+
int ret, irq;
51+
u8 i;
52+
@@ -1242,12 +1240,9 @@ static int xiic_i2c_probe(struct platform_device *pdev)
53+
if (!i2c)
54+
return -ENOMEM;
55+
56+
- match = of_match_node(xiic_of_match, pdev->dev.of_node);
57+
- if (match && match->data) {
58+
- const struct xiic_version_data *data = match->data;
59+
-
60+
+ data = device_get_match_data(dev);
61+
+ if (data)
62+
i2c->quirks = data->quirks;
63+
- }
64+
65+
i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
66+
if (IS_ERR(i2c->base))
67+
@@ -1264,7 +1259,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
68+
i2c->adap = xiic_adapter;
69+
i2c_set_adapdata(&i2c->adap, i2c);
70+
i2c->adap.dev.parent = &pdev->dev;
71+
- i2c->adap.dev.of_node = pdev->dev.of_node;
72+
+ device_set_node(&i2c->adap.dev, fwnode);
73+
snprintf(i2c->adap.name, sizeof(i2c->adap.name),
74+
DRIVER_NAME " %s", pdev->name);
75+
76+
@@ -1287,8 +1282,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
77+
78+
/* SCL frequency configuration */
79+
i2c->input_clk = clk_get_rate(i2c->clk);
80+
- ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
81+
- &i2c->i2c_clk);
82+
+ ret = device_property_read_u32(dev, "clock-frequency", &i2c->i2c_clk);
83+
/* If clock-frequency not specified in DT, do not configure in SW */
84+
if (ret || i2c->i2c_clk > I2C_MAX_FAST_MODE_PLUS_FREQ)
85+
i2c->i2c_clk = 0;
86+
@@ -1299,8 +1293,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
87+
if (ret)
88+
return ret;
89+
90+
- i2c->singlemaster =
91+
- of_property_read_bool(pdev->dev.of_node, "single-master");
92+
+ i2c->singlemaster = device_property_read_bool(dev, "single-master");
93+
94+
/*
95+
* Detect endianness
96+
--
97+
2.43.0
98+
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
From b698377976bc4de60360bbde104e50c503c3a330 Mon Sep 17 00:00:00 2001
2+
From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
3+
Date: Mon, 23 Feb 2026 15:59:19 +0000
4+
Subject: [PATCH 4/7] i2c: xiic: cosmetic cleanup
5+
6+
Re-use dev pointer instead of referencing &pdev->dev everywhere.
7+
8+
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
9+
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
10+
---
11+
drivers/i2c/busses/i2c-xiic.c | 24 ++++++++++++------------
12+
1 file changed, 12 insertions(+), 12 deletions(-)
13+
14+
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
15+
index 271f932b23a0..aeaf6a4d841d 100644
16+
--- a/drivers/i2c/busses/i2c-xiic.c
17+
+++ b/drivers/i2c/busses/i2c-xiic.c
18+
@@ -1236,7 +1236,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
19+
u8 i;
20+
u32 sr;
21+
22+
- i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
23+
+ i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
24+
if (!i2c)
25+
return -ENOMEM;
26+
27+
@@ -1252,7 +1252,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
28+
if (irq < 0)
29+
return irq;
30+
31+
- pdata = dev_get_platdata(&pdev->dev);
32+
+ pdata = dev_get_platdata(dev);
33+
34+
/* hook up driver to tree */
35+
platform_set_drvdata(pdev, i2c);
36+
@@ -1272,9 +1272,10 @@ static int xiic_i2c_probe(struct platform_device *pdev)
37+
return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk),
38+
"failed to enable input clock.\n");
39+
40+
- i2c->dev = &pdev->dev;
41+
- pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT);
42+
- pm_runtime_use_autosuspend(i2c->dev);
43+
+ i2c->dev = dev;
44+
+
45+
+ pm_runtime_set_autosuspend_delay(dev, XIIC_PM_TIMEOUT);
46+
+ pm_runtime_use_autosuspend(dev);
47+
pm_runtime_set_active(dev);
48+
ret = devm_pm_runtime_enable(dev);
49+
if (ret)
50+
@@ -1287,9 +1288,8 @@ static int xiic_i2c_probe(struct platform_device *pdev)
51+
if (ret || i2c->i2c_clk > I2C_MAX_FAST_MODE_PLUS_FREQ)
52+
i2c->i2c_clk = 0;
53+
54+
- ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
55+
- xiic_process, IRQF_ONESHOT,
56+
- pdev->name, i2c);
57+
+ ret = devm_request_threaded_irq(dev, irq, NULL, xiic_process,
58+
+ IRQF_ONESHOT, pdev->name, i2c);
59+
if (ret)
60+
return ret;
61+
62+
@@ -1332,21 +1332,21 @@ static int xiic_i2c_probe(struct platform_device *pdev)
63+
64+
static void xiic_i2c_remove(struct platform_device *pdev)
65+
{
66+
+ struct device *dev = &pdev->dev;
67+
struct xiic_i2c *i2c = platform_get_drvdata(pdev);
68+
int ret;
69+
70+
/* remove adapter & data */
71+
i2c_del_adapter(&i2c->adap);
72+
73+
- ret = pm_runtime_get_sync(i2c->dev);
74+
-
75+
+ ret = pm_runtime_get_sync(dev);
76+
if (ret < 0)
77+
- dev_warn(&pdev->dev, "Failed to activate device for removal (%pe)\n",
78+
+ dev_warn(dev, "Failed to activate device for removal (%pe)\n",
79+
ERR_PTR(ret));
80+
else
81+
xiic_deinit(i2c);
82+
83+
- pm_runtime_put_sync(i2c->dev);
84+
+ pm_runtime_put_sync(dev);
85+
}
86+
87+
static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev)
88+
--
89+
2.43.0
90+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
From f715b059d442d524d45f8ec91ebe63c4c0d0ad00 Mon Sep 17 00:00:00 2001
2+
From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
3+
Date: Mon, 23 Feb 2026 15:59:20 +0000
4+
Subject: [PATCH 5/7] i2c: xiic: cosmetic: use resource format specifier in
5+
debug log
6+
7+
Use standard resource format specifier %pR in debug log.
8+
9+
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
10+
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
11+
---
12+
drivers/i2c/busses/i2c-xiic.c | 4 ++--
13+
1 file changed, 2 insertions(+), 2 deletions(-)
14+
15+
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
16+
index aeaf6a4d841d..63165050cf0d 100644
17+
--- a/drivers/i2c/busses/i2c-xiic.c
18+
+++ b/drivers/i2c/busses/i2c-xiic.c
19+
@@ -1324,8 +1324,8 @@ static int xiic_i2c_probe(struct platform_device *pdev)
20+
i2c_new_client_device(&i2c->adap, pdata->devices + i);
21+
}
22+
23+
- dev_dbg(&pdev->dev, "mmio %08lx irq %d scl clock frequency %d\n",
24+
- (unsigned long)res->start, irq, i2c->i2c_clk);
25+
+ dev_dbg(dev, "mmio %pR irq %d scl clock frequency %d\n",
26+
+ res, irq, i2c->i2c_clk);
27+
28+
return 0;
29+
}
30+
--
31+
2.43.0
32+

0 commit comments

Comments
 (0)