Skip to content

Commit 2e88b91

Browse files
authored
PR request #244 from Nir-Az: Align R/1.0.1.25 to dev 20/11/2024
2 parents 3911747 + 35a7136 commit 2e88b91

File tree

2 files changed

+181
-8
lines changed

2 files changed

+181
-8
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
From ce6faaedef68204e8b132bf44a0e4d2432dfb7ad Mon Sep 17 00:00:00 2001
2+
From: Arun-Prasad-V <[email protected]>
3+
Date: Mon, 4 Nov 2024 12:52:39 +0530
4+
Subject: [PATCH] Support for dynamic change of i2c bus-clk-rate
5+
6+
Signed-off-by: Arun Prasad V <[email protected]>
7+
---
8+
drivers/i2c/busses/i2c-tegra.c | 42 +++++++++++++++++++++++++++++++
9+
drivers/i2c/i2c-core-base.c | 45 ++++++++++++++++++++++++++++++++++
10+
include/linux/i2c.h | 5 ++++
11+
3 files changed, 92 insertions(+)
12+
13+
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
14+
index cd50436e5734..4269343266c2 100644
15+
--- a/drivers/i2c/busses/i2c-tegra.c
16+
+++ b/drivers/i2c/busses/i2c-tegra.c
17+
@@ -1484,6 +1484,37 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
18+
return 0;
19+
}
20+
21+
+static int tegra_i2c_change_clock_rate(struct tegra_i2c_dev *i2c_dev)
22+
+{
23+
+ u32 val;
24+
+ int err;
25+
+
26+
+ val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
27+
+ FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 2);
28+
+
29+
+ if (i2c_dev->hw->has_multi_master_mode)
30+
+ val |= I2C_CNFG_MULTI_MASTER_MODE;
31+
+
32+
+ i2c_writel(i2c_dev, val, I2C_CNFG);
33+
+
34+
+ if (i2c_dev->prod_list)
35+
+ tegra_i2c_config_prod_settings(i2c_dev);
36+
+ else
37+
+ tegra_i2c_set_clk_params(i2c_dev);
38+
+
39+
+ err = tegra_i2c_set_div_clk(i2c_dev);
40+
+ if (err) {
41+
+ dev_err(i2c_dev->dev, "failed to set div-clk rate: %d\n", err);
42+
+ return err;
43+
+ }
44+
+
45+
+ err = tegra_i2c_wait_for_config_load(i2c_dev);
46+
+ if (err)
47+
+ return err;
48+
+
49+
+ return err;
50+
+}
51+
+
52+
static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
53+
int num)
54+
{
55+
@@ -1497,6 +1528,16 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
56+
return ret;
57+
}
58+
59+
+ if (adap->bus_clk_rate != i2c_dev->bus_clk_rate) {
60+
+ i2c_dev->bus_clk_rate = adap->bus_clk_rate;
61+
+ ret = tegra_i2c_change_clock_rate(i2c_dev);
62+
+ if (ret) {
63+
+ dev_err(i2c_dev->dev,
64+
+ "failed changing clock rate: %d\n", ret);
65+
+ return ret;
66+
+ }
67+
+ }
68+
+
69+
for (i = 0; i < num; i++) {
70+
enum msg_end_type end_type = MSG_END_STOP;
71+
72+
@@ -1957,6 +1998,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
73+
i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
74+
i2c_dev->adapter.algo = &tegra_i2c_algo;
75+
i2c_dev->adapter.nr = pdev->id;
76+
+ i2c_dev->adapter.bus_clk_rate = i2c_dev->bus_clk_rate;
77+
78+
if (i2c_dev->hw->supports_bus_clear)
79+
i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
80+
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
81+
index c232535ca8f4..2edd24973cca 100644
82+
--- a/drivers/i2c/i2c-core-base.c
83+
+++ b/drivers/i2c/i2c-core-base.c
84+
@@ -1285,10 +1285,33 @@ delete_device_store(struct device *dev, struct device_attribute *attr,
85+
static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL,
86+
delete_device_store);
87+
88+
+static ssize_t show_bus_clk_rate(struct device *dev,
89+
+ struct device_attribute *attr, char *buf)
90+
+{
91+
+ struct i2c_adapter *adap = to_i2c_adapter(dev);
92+
+
93+
+ return sprintf(buf, "%ld\n", adap->bus_clk_rate);
94+
+}
95+
+
96+
+static ssize_t set_bus_clk_rate(struct device *dev,
97+
+ struct device_attribute *attr, const char *buf, size_t count)
98+
+{
99+
+ struct i2c_adapter *adap = to_i2c_adapter(dev);
100+
+ char *p = (char *)buf;
101+
+ int bus_clk_rate;
102+
+
103+
+ bus_clk_rate = memparse(p, &p);
104+
+ dev_info(dev, "Setting clock rate %d on next transfer\n", bus_clk_rate);
105+
+ adap->bus_clk_rate = bus_clk_rate;
106+
+ return count;
107+
+}
108+
+static DEVICE_ATTR(bus_clk_rate, 0644, show_bus_clk_rate, set_bus_clk_rate);
109+
+
110+
static struct attribute *i2c_adapter_attrs[] = {
111+
&dev_attr_name.attr,
112+
&dev_attr_new_device.attr,
113+
&dev_attr_delete_device.attr,
114+
+ &dev_attr_bus_clk_rate.attr,
115+
NULL
116+
};
117+
ATTRIBUTE_GROUPS(i2c_adapter);
118+
@@ -1401,6 +1424,28 @@ static int i2c_setup_host_notify_irq_domain(struct i2c_adapter *adap)
119+
return 0;
120+
}
121+
122+
+int i2c_set_adapter_bus_clk_rate(struct i2c_adapter *adap, int bus_rate)
123+
+{
124+
+ i2c_lock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
125+
+ adap->bus_clk_rate = bus_rate;
126+
+ i2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
127+
+
128+
+ return 0;
129+
+}
130+
+EXPORT_SYMBOL_GPL(i2c_set_adapter_bus_clk_rate);
131+
+
132+
+int i2c_get_adapter_bus_clk_rate(struct i2c_adapter *adap)
133+
+{
134+
+ int bus_clk_rate;
135+
+
136+
+ i2c_lock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
137+
+ bus_clk_rate = adap->bus_clk_rate;
138+
+ i2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
139+
+
140+
+ return bus_clk_rate;
141+
+}
142+
+EXPORT_SYMBOL_GPL(i2c_get_adapter_bus_clk_rate);
143+
+
144+
/**
145+
* i2c_handle_smbus_host_notify - Forward a Host Notify event to the correct
146+
* I2C client.
147+
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
148+
index 2ce3efbe9198..9d876ad6373c 100644
149+
--- a/include/linux/i2c.h
150+
+++ b/include/linux/i2c.h
151+
@@ -131,6 +131,10 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
152+
/* Unlocked flavor */
153+
int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
154+
155+
+/* Change bus clock rate for i2c adapter */
156+
+extern int i2c_set_adapter_bus_clk_rate(struct i2c_adapter *adap, int bus_rate);
157+
+extern int i2c_get_adapter_bus_clk_rate(struct i2c_adapter *adap);
158+
+
159+
/* This is the very generalized SMBus access routine. You probably do not
160+
want to use this, though; one of the functions below may be much easier,
161+
and probably just as fast.
162+
@@ -737,6 +741,7 @@ struct i2c_adapter {
163+
const struct i2c_adapter_quirks *quirks;
164+
165+
struct irq_domain *host_notify_domain;
166+
+ unsigned long bus_clk_rate;
167+
struct regulator *bus_regulator;
168+
};
169+
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
170+
--
171+
2.34.1
172+

kernel/realsense/d4xx.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2827,9 +2827,16 @@ static int ds5_mux_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
28272827
struct ds5 *state = v4l2_get_subdevdata(sd);
28282828

28292829
dev_dbg(sd->dev, "%s(): %s (%p)\n", __func__, sd->name, fh);
2830+
2831+
mutex_lock(&state->lock);
28302832
if (state->dfu_dev.dfu_state_flag)
2833+
{
2834+
mutex_unlock(&state->lock);
28312835
return -EBUSY;
2836+
}
2837+
28322838
state->dfu_dev.device_open_count++;
2839+
mutex_unlock(&state->lock);
28332840

28342841
return 0;
28352842
};
@@ -2839,7 +2846,9 @@ static int ds5_mux_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
28392846
struct ds5 *state = v4l2_get_subdevdata(sd);
28402847

28412848
dev_dbg(sd->dev, "%s(): %s (%p)\n", __func__, sd->name, fh);
2849+
mutex_lock(&state->lock);
28422850
state->dfu_dev.device_open_count--;
2851+
mutex_unlock(&state->lock);
28432852
return 0;
28442853
};
28452854

@@ -4962,10 +4971,8 @@ static int ds5_dfu_device_open(struct inode *inode, struct file *file)
49624971
struct ds5 *state = container_of(inode->i_cdev, struct ds5,
49634972
dfu_dev.ds5_cdev);
49644973
#ifdef CONFIG_TEGRA_CAMERA_PLATFORM
4965-
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 10)
49664974
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(
49674975
state->client->adapter);
4968-
#endif
49694976
#endif
49704977
mutex_lock(&state->lock);
49714978
if (state->dfu_dev.device_open_count) {
@@ -4983,7 +4990,6 @@ static int ds5_dfu_device_open(struct inode *inode, struct file *file)
49834990
}
49844991
file->private_data = state;
49854992
#ifdef CONFIG_TEGRA_CAMERA_PLATFORM
4986-
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 10)
49874993
/* get i2c controller and set dfu bus clock rate */
49884994
while (parent && i2c_parent_is_i2c_adapter(parent))
49894995
parent = i2c_parent_is_i2c_adapter(state->client->adapter);
@@ -5000,7 +5006,6 @@ static int ds5_dfu_device_open(struct inode *inode, struct file *file)
50005006

50015007
state->dfu_dev.bus_clk_rate = i2c_get_adapter_bus_clk_rate(parent);
50025008
i2c_set_adapter_bus_clk_rate(parent, DFU_I2C_BUS_CLK_RATE);
5003-
#endif
50045009
#endif
50055010
mutex_unlock(&state->lock);
50065011
return 0;
@@ -5060,10 +5065,8 @@ static int ds5_dfu_device_release(struct inode *inode, struct file *file)
50605065
{
50615066
struct ds5 *state = container_of(inode->i_cdev, struct ds5, dfu_dev.ds5_cdev);
50625067
#ifdef CONFIG_TEGRA_CAMERA_PLATFORM
5063-
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 10)
50645068
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(
50655069
state->client->adapter);
5066-
#endif
50675070
#endif
50685071
int ret = 0, retry = 10;
50695072
mutex_lock(&state->lock);
@@ -5080,7 +5083,6 @@ static int ds5_dfu_device_release(struct inode *inode, struct file *file)
50805083
devm_kfree(&state->client->dev, state->dfu_dev.dfu_msg);
50815084
state->dfu_dev.dfu_msg = NULL;
50825085
#ifdef CONFIG_TEGRA_CAMERA_PLATFORM
5083-
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 10)
50845086
/* get i2c controller and restore bus clock rate */
50855087
while (parent && i2c_parent_is_i2c_adapter(parent))
50865088
parent = i2c_parent_is_i2c_adapter(state->client->adapter);
@@ -5094,7 +5096,6 @@ static int ds5_dfu_device_release(struct inode *inode, struct file *file)
50945096
state->dfu_dev.bus_clk_rate);
50955097

50965098
i2c_set_adapter_bus_clk_rate(parent, state->dfu_dev.bus_clk_rate);
5097-
#endif
50985099
#endif
50995100
/* Verify communication */
51005101
do {

0 commit comments

Comments
 (0)