1
- From 07d6fc782dd86ad386e9cc5eb13cbeec20a46db9 Mon Sep 17 00:00:00 2001
2
- From: Ashwin H <Ashwin.H @amd.com>
3
- Date: Tue, 27 Jun 2023 11:13:05 +0000
4
- Subject: [PATCH 02/30 ] i2c: designware: Recover from a stuck SDA line
1
+ From f3c0cb78c3982c60e9a5e2705c9939f1eef84002 Mon Sep 17 00:00:00 2001
2
+ From: Shantanu Shrivastava <shanshri @amd.com>
3
+ Date: Tue, 24 Oct 2023 08:36:35 +0000
4
+ Subject: [PATCH] i2c- designware: Support stuck SDA line recovery
5
5
6
6
This patch supports the Designware I2C stuck bus recovery feature.
7
- The procedure for stuck SDA recovery involves a polling loop in interrupt
7
+ The procedure for stuck SDA recovery involves a polling loop in
8
+ interrupt
8
9
mode. This should last just long enough for transmission of 9 bits,
9
10
after which the hardware should indicate that the recovery attempt is
10
11
complete. There have been examples where this fails, so there is also
11
12
a hard maximum on time in the recovery loop.
12
13
13
- Signed-off-by: David Clear <
[email protected] >
14
- Signed-off-by: Ashwin H <Ashwin.H @amd.com>
14
+ Signed-off-by: David Clear <
[email protected] >
15
+ Signed-off-by: Shantanu Shrivastava <shanshri @amd.com>
15
16
---
16
17
drivers/i2c/busses/i2c-designware-common.c | 2 +
17
- drivers/i2c/busses/i2c-designware-core.h | 10 +++
18
+ drivers/i2c/busses/i2c-designware-core.h | 11 +++
18
19
drivers/i2c/busses/i2c-designware-master.c | 87 ++++++++++++++++++++-
19
20
drivers/i2c/busses/i2c-designware-platdrv.c | 3 +
20
- 4 files changed, 100 insertions(+), 2 deletions(-)
21
+ 4 files changed, 101 insertions(+), 2 deletions(-)
21
22
22
23
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
23
- index 9468c6c89..95b082361 100644
24
+ index 6fdb25a5f..8ac32dd41 100644
24
25
--- a/drivers/i2c/busses/i2c-designware-common.c
25
26
+++ b/drivers/i2c/busses/i2c-designware-common.c
26
- @@ -56 ,6 +56 ,8 @@ static char *abort_sources[] = {
27
+ @@ -57 ,6 +57 ,8 @@ static char *abort_sources[] = {
27
28
"slave lost the bus while transmitting data to a remote master",
28
29
[ABRT_SLAVE_RD_INTX] =
29
30
"incorrect slave-transmitter mode configuration",
@@ -33,18 +34,18 @@ index 9468c6c89..95b082361 100644
33
34
34
35
static int dw_reg_read(void *context, unsigned int reg, unsigned int *val)
35
36
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
36
- index eb5ef4d0f..f0be70e3e 100644
37
+ index 56a029da4..54e6c44e6 100644
37
38
--- a/drivers/i2c/busses/i2c-designware-core.h
38
39
+++ b/drivers/i2c/busses/i2c-designware-core.h
39
40
@@ -37,6 +37,7 @@
40
- #define DW_IC_CON_STOP_DET_IFADDRESSED 0x80
41
- #define DW_IC_CON_TX_EMPTY_CTRL 0x100
42
- #define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL 0x200
43
- + #define DW_IC_CON_BUS_CLEAR_FEATURE_CTL 0x800
44
-
45
- /*
46
- * Registers offset
47
- @@ -75 ,6 +76 ,8 @@
41
+ #define DW_IC_CON_STOP_DET_IFADDRESSED BIT(7)
42
+ #define DW_IC_CON_TX_EMPTY_CTRL BIT(8)
43
+ #define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL BIT(9)
44
+ + #define DW_IC_CON_BUS_CLEAR_FEATURE_CTL BIT(11)
45
+
46
+ #define DW_IC_DATA_CMD_DAT GENMASK(7, 0)
47
+
48
+ @@ -77 ,6 +78 ,8 @@
48
49
#define DW_IC_TX_ABRT_SOURCE 0x80
49
50
#define DW_IC_ENABLE_STATUS 0x9c
50
51
#define DW_IC_CLR_RESTART_DET 0xa8
@@ -53,45 +54,50 @@ index eb5ef4d0f..f0be70e3e 100644
53
54
#define DW_IC_COMP_PARAM_1 0xf4
54
55
#define DW_IC_COMP_VERSION 0xf8
55
56
#define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A
56
- @@ -94 ,6 +97 ,7 @@
57
- #define DW_IC_INTR_START_DET 0x400
58
- #define DW_IC_INTR_GEN_CALL 0x800
59
- #define DW_IC_INTR_RESTART_DET 0x1000
60
- + #define DW_IC_INTR_SCL_STUCK_AT_LOW 0x4000
57
+ @@ -96 ,6 +99 ,7 @@
58
+ #define DW_IC_INTR_START_DET BIT(10)
59
+ #define DW_IC_INTR_GEN_CALL BIT(11)
60
+ #define DW_IC_INTR_RESTART_DET BIT(12)
61
+ + #define DW_IC_INTR_SCL_STUCK_AT_LOW BIT(14)
61
62
62
63
#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
63
64
DW_IC_INTR_TX_ABRT | \
64
- @@ -105,10 +109,13 @@
65
+ @@ -107,14 +111,18 @@
65
66
DW_IC_INTR_RX_UNDER | \
66
67
DW_IC_INTR_RD_REQ)
67
68
68
- + #define DW_IC_SDA_STUCK_RECOVERY_ENABLE 0x8
69
+ + #define DW_IC_SDA_STUCK_RECOVERY_ENABLE BIT(3)
69
70
+
70
- #define DW_IC_STATUS_ACTIVITY 0x1
71
+ #define DW_IC_STATUS_ACTIVITY BIT(0)
71
72
#define DW_IC_STATUS_TFE BIT(2)
72
73
#define DW_IC_STATUS_MASTER_ACTIVITY BIT(5)
73
74
#define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6)
74
75
+ #define DW_IC_STATUS_SDA_STUCK_NOT_RECOVERED BIT(11)
75
76
76
77
#define DW_IC_SDA_HOLD_RX_SHIFT 16
77
- #define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, DW_IC_SDA_HOLD_RX_SHIFT)
78
- @@ -153,6 +160,7 @@
78
+ #define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, 16)
79
+
80
+ +
81
+ #define DW_IC_ERR_TX_ABRT 0x1
82
+
83
+ #define DW_IC_TAR_10BITADDR_MASTER BIT(12)
84
+ @@ -156,6 +164,7 @@
79
85
#define ABRT_SLAVE_FLUSH_TXFIFO 13
80
86
#define ABRT_SLAVE_ARBLOST 14
81
87
#define ABRT_SLAVE_RD_INTX 15
82
88
+ #define ABRT_SDA_STUCK_AT_LOW 17
83
89
84
- #define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK)
85
- #define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK)
86
- @@ -165 ,6 +173 ,7 @@
87
- #define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT)
88
- #define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS)
89
- #define DW_IC_TX_ARB_LOST (1UL << ARB_LOST)
90
- + #define DW_IC_TX_ABRT_SDA_STUCK_AT_LOW (1UL << ABRT_SDA_STUCK_AT_LOW)
91
- #define DW_IC_RX_ABRT_SLAVE_RD_INTX (1UL << ABRT_SLAVE_RD_INTX)
92
- #define DW_IC_RX_ABRT_SLAVE_ARBLOST (1UL << ABRT_SLAVE_ARBLOST)
93
- #define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO (1UL << ABRT_SLAVE_FLUSH_TXFIFO)
94
- @@ -268 ,6 +277 ,7 @@ struct dw_i2c_dev {
90
+ #define DW_IC_TX_ABRT_7B_ADDR_NOACK BIT( ABRT_7B_ADDR_NOACK)
91
+ #define DW_IC_TX_ABRT_10ADDR1_NOACK BIT( ABRT_10ADDR1_NOACK)
92
+ @@ -168 ,6 +177 ,7 @@
93
+ #define DW_IC_TX_ABRT_10B_RD_NORSTRT BIT( ABRT_10B_RD_NORSTRT)
94
+ #define DW_IC_TX_ABRT_MASTER_DIS BIT( ABRT_MASTER_DIS)
95
+ #define DW_IC_TX_ARB_LOST BIT( ARB_LOST)
96
+ + #define DW_IC_TX_ABRT_SDA_STUCK_AT_LOW BIT( ABRT_SDA_STUCK_AT_LOW)
97
+ #define DW_IC_RX_ABRT_SLAVE_RD_INTX BIT( ABRT_SLAVE_RD_INTX)
98
+ #define DW_IC_RX_ABRT_SLAVE_ARBLOST BIT( ABRT_SLAVE_ARBLOST)
99
+ #define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO BIT( ABRT_SLAVE_FLUSH_TXFIFO)
100
+ @@ -277 ,6 +287 ,7 @@ struct dw_i2c_dev {
95
101
int rx_outstanding;
96
102
struct i2c_timings timings;
97
103
u32 sda_hold_time;
@@ -100,10 +106,10 @@ index eb5ef4d0f..f0be70e3e 100644
100
106
u16 ss_lcnt;
101
107
u16 fs_hcnt;
102
108
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
103
- index 2871cf2ee..d678b5ab2 100644
109
+ index dc3c5a15a..9834137a0 100644
104
110
--- a/drivers/i2c/busses/i2c-designware-master.c
105
111
+++ b/drivers/i2c/busses/i2c-designware-master.c
106
- @@ -33 ,6 +33 ,45 @@ static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
112
+ @@ -37 ,6 +37 ,45 @@ static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
107
113
regmap_write(dev->map, DW_IC_CON, dev->master_cfg);
108
114
}
109
115
@@ -148,8 +154,8 @@ index 2871cf2ee..d678b5ab2 100644
148
154
+
149
155
static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
150
156
{
151
- const char *mode_str, *fp_str = "" ;
152
- @@ -500 ,6 +539 ,14 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
157
+ u32 comp_param1 ;
158
+ @@ -599 ,6 +638 ,14 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
153
159
goto done;
154
160
}
155
161
@@ -164,7 +170,7 @@ index 2871cf2ee..d678b5ab2 100644
164
170
/*
165
171
* We must disable the adapter before returning and signaling the end
166
172
* of the current transfer. Otherwise the hardware might continue
167
- @@ -711 ,6 +758 ,39 @@ static void i2c_dw_unprepare_recovery(struct i2c_adapter *adap)
173
+ @@ -826 ,6 +873 ,39 @@ static void i2c_dw_unprepare_recovery(struct i2c_adapter *adap)
168
174
i2c_dw_init_master(dev);
169
175
}
170
176
@@ -204,7 +210,7 @@ index 2871cf2ee..d678b5ab2 100644
204
210
static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
205
211
{
206
212
struct i2c_bus_recovery_info *rinfo = &dev->rinfo;
207
- @@ -718 ,8 +798 ,11 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
213
+ @@ -833 ,8 +913 ,11 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
208
214
struct gpio_desc *gpio;
209
215
210
216
gpio = devm_gpiod_get_optional(dev->dev, "scl", GPIOD_OUT_HIGH);
@@ -219,10 +225,10 @@ index 2871cf2ee..d678b5ab2 100644
219
225
rinfo->scl_gpiod = gpio;
220
226
221
227
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
222
- index ad91c7c0f..d7a6cbd99 100644
228
+ index 74182db03..7466d748b 100644
223
229
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
224
230
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
225
- @@ -135 ,6 +135 ,9 @@ static int dw_i2c_of_configure(struct platform_device *pdev)
231
+ @@ -136 ,6 +136 ,9 @@ static int dw_i2c_of_configure(struct platform_device *pdev)
226
232
{
227
233
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
228
234
@@ -233,5 +239,5 @@ index ad91c7c0f..d7a6cbd99 100644
233
239
case MODEL_MSCC_OCELOT:
234
240
dev->ext = devm_platform_ioremap_resource(pdev, 1);
235
241
- -
236
- 2.17.1
242
+ 2.39.2
237
243
0 commit comments