8
8
9
9
#include <generated/utsrelease.h>
10
10
#include <linux/bitops.h>
11
+ #include <linux/completion.h>
12
+ #include <linux/gpio/consumer.h>
11
13
#include <linux/i2c.h>
12
14
#include <linux/init.h>
13
15
#include <linux/module.h>
@@ -22,6 +24,7 @@ enum testunit_cmds {
22
24
TU_CMD_SMBUS_HOST_NOTIFY ,
23
25
TU_CMD_SMBUS_BLOCK_PROC_CALL ,
24
26
TU_CMD_GET_VERSION_WITH_REP_START ,
27
+ TU_CMD_SMBUS_ALERT_REQUEST ,
25
28
TU_NUM_CMDS
26
29
};
27
30
@@ -44,10 +47,37 @@ struct testunit_data {
44
47
u8 read_idx ;
45
48
struct i2c_client * client ;
46
49
struct delayed_work worker ;
50
+ struct gpio_desc * gpio ;
51
+ struct completion alert_done ;
47
52
};
48
53
49
54
static char tu_version_info [] = "v" UTS_RELEASE "\n\0" ;
50
55
56
+ static int i2c_slave_testunit_smbalert_cb (struct i2c_client * client ,
57
+ enum i2c_slave_event event , u8 * val )
58
+ {
59
+ struct testunit_data * tu = i2c_get_clientdata (client );
60
+
61
+ switch (event ) {
62
+ case I2C_SLAVE_READ_PROCESSED :
63
+ gpiod_set_value (tu -> gpio , 0 );
64
+ fallthrough ;
65
+ case I2C_SLAVE_READ_REQUESTED :
66
+ * val = tu -> regs [TU_REG_DATAL ];
67
+ break ;
68
+
69
+ case I2C_SLAVE_STOP :
70
+ complete (& tu -> alert_done );
71
+ break ;
72
+
73
+ case I2C_SLAVE_WRITE_REQUESTED :
74
+ case I2C_SLAVE_WRITE_RECEIVED :
75
+ return - EOPNOTSUPP ;
76
+ }
77
+
78
+ return 0 ;
79
+ }
80
+
51
81
static int i2c_slave_testunit_slave_cb (struct i2c_client * client ,
52
82
enum i2c_slave_event event , u8 * val )
53
83
{
@@ -127,8 +157,10 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
127
157
static void i2c_slave_testunit_work (struct work_struct * work )
128
158
{
129
159
struct testunit_data * tu = container_of (work , struct testunit_data , worker .work );
160
+ unsigned long time_left ;
130
161
struct i2c_msg msg ;
131
162
u8 msgbuf [256 ];
163
+ u16 orig_addr ;
132
164
int ret = 0 ;
133
165
134
166
msg .addr = I2C_CLIENT_END ;
@@ -150,6 +182,26 @@ static void i2c_slave_testunit_work(struct work_struct *work)
150
182
msgbuf [2 ] = tu -> regs [TU_REG_DATAH ];
151
183
break ;
152
184
185
+ case TU_CMD_SMBUS_ALERT_REQUEST :
186
+ i2c_slave_unregister (tu -> client );
187
+ orig_addr = tu -> client -> addr ;
188
+ tu -> client -> addr = 0x0c ;
189
+ ret = i2c_slave_register (tu -> client , i2c_slave_testunit_smbalert_cb );
190
+ if (ret )
191
+ goto out_smbalert ;
192
+
193
+ reinit_completion (& tu -> alert_done );
194
+ gpiod_set_value (tu -> gpio , 1 );
195
+ time_left = wait_for_completion_timeout (& tu -> alert_done , HZ );
196
+ if (!time_left )
197
+ ret = - ETIMEDOUT ;
198
+
199
+ i2c_slave_unregister (tu -> client );
200
+ out_smbalert :
201
+ tu -> client -> addr = orig_addr ;
202
+ i2c_slave_register (tu -> client , i2c_slave_testunit_slave_cb );
203
+ break ;
204
+
153
205
default :
154
206
break ;
155
207
}
@@ -176,8 +228,15 @@ static int i2c_slave_testunit_probe(struct i2c_client *client)
176
228
177
229
tu -> client = client ;
178
230
i2c_set_clientdata (client , tu );
231
+ init_completion (& tu -> alert_done );
179
232
INIT_DELAYED_WORK (& tu -> worker , i2c_slave_testunit_work );
180
233
234
+ tu -> gpio = devm_gpiod_get_index_optional (& client -> dev , NULL , 0 , GPIOD_OUT_LOW );
235
+ if (gpiod_cansleep (tu -> gpio )) {
236
+ dev_err (& client -> dev , "GPIO access which may sleep is not allowed\n" );
237
+ return - EDEADLK ;
238
+ }
239
+
181
240
if (sizeof (tu_version_info ) > TU_VERSION_MAX_LENGTH )
182
241
tu_version_info [TU_VERSION_MAX_LENGTH - 1 ] = 0 ;
183
242
0 commit comments