3
3
// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
4
4
5
5
#include <linux/crc8.h>
6
+ #include <linux/delay.h>
6
7
#include <linux/err.h>
7
8
#include <linux/i2c.h>
8
9
#include <linux/input.h>
9
10
#include <linux/input/matrix_keypad.h>
10
11
#include <linux/interrupt.h>
11
12
#include <linux/module.h>
12
13
#include <linux/mod_devicetable.h>
14
+ #include <linux/of.h>
13
15
#include <linux/regulator/consumer.h>
14
16
#include <linux/types.h>
15
17
28
30
#define PPKB_SCAN_DATA 0x08
29
31
#define PPKB_SYS_CONFIG 0x20
30
32
#define PPKB_SYS_CONFIG_DISABLE_SCAN BIT(0)
33
+ #define PPKB_SYS_SMBUS_COMMAND 0x21
34
+ #define PPKB_SYS_SMBUS_DATA 0x22
35
+ #define PPKB_SYS_COMMAND 0x23
36
+ #define PPKB_SYS_COMMAND_SMBUS_READ 0x91
37
+ #define PPKB_SYS_COMMAND_SMBUS_WRITE 0xa1
31
38
32
39
#define PPKB_ROWS 6
33
40
#define PPKB_COLS 12
@@ -136,6 +143,7 @@ static const struct matrix_keymap_data ppkb_keymap_data = {
136
143
};
137
144
138
145
struct pinephone_keyboard {
146
+ struct i2c_adapter adapter ;
139
147
struct input_dev * input ;
140
148
u8 buf [2 ][PPKB_BUF_LEN ];
141
149
u8 crc_table [CRC8_TABLE_SIZE ];
@@ -144,6 +152,57 @@ struct pinephone_keyboard {
144
152
bool fn_pressed ;
145
153
};
146
154
155
+ static int ppkb_adap_smbus_xfer (struct i2c_adapter * adap , u16 addr ,
156
+ unsigned short flags , char read_write ,
157
+ u8 command , int size ,
158
+ union i2c_smbus_data * data )
159
+ {
160
+ struct i2c_client * client = adap -> algo_data ;
161
+ u8 buf [3 ];
162
+ int ret ;
163
+
164
+ buf [0 ] = command ;
165
+ buf [1 ] = data -> byte ;
166
+ buf [2 ] = read_write == I2C_SMBUS_READ ? PPKB_SYS_COMMAND_SMBUS_READ
167
+ : PPKB_SYS_COMMAND_SMBUS_WRITE ;
168
+
169
+ ret = i2c_smbus_write_i2c_block_data (client , PPKB_SYS_SMBUS_COMMAND ,
170
+ sizeof (buf ), buf );
171
+ if (ret )
172
+ return ret ;
173
+
174
+ /* Read back the command status until it passes or fails. */
175
+ do {
176
+ usleep_range (300 , 500 );
177
+ ret = i2c_smbus_read_byte_data (client , PPKB_SYS_COMMAND );
178
+ } while (ret == buf [2 ]);
179
+ if (ret < 0 )
180
+ return ret ;
181
+ /* Commands return 0x00 on success and 0xff on failure. */
182
+ if (ret )
183
+ return - EIO ;
184
+
185
+ if (read_write == I2C_SMBUS_READ ) {
186
+ ret = i2c_smbus_read_byte_data (client , PPKB_SYS_SMBUS_DATA );
187
+ if (ret < 0 )
188
+ return ret ;
189
+
190
+ data -> byte = ret ;
191
+ }
192
+
193
+ return 0 ;
194
+ }
195
+
196
+ static u32 ppkg_adap_functionality (struct i2c_adapter * adap )
197
+ {
198
+ return I2C_FUNC_SMBUS_BYTE_DATA ;
199
+ }
200
+
201
+ static const struct i2c_algorithm ppkb_adap_algo = {
202
+ .smbus_xfer = ppkb_adap_smbus_xfer ,
203
+ .functionality = ppkg_adap_functionality ,
204
+ };
205
+
147
206
static void ppkb_update (struct i2c_client * client )
148
207
{
149
208
struct pinephone_keyboard * ppkb = i2c_get_clientdata (client );
@@ -271,6 +330,7 @@ static int ppkb_probe(struct i2c_client *client)
271
330
struct pinephone_keyboard * ppkb ;
272
331
struct regulator * vbat_supply ;
273
332
u8 info [PPKB_MATRIX_SIZE + 1 ];
333
+ struct device_node * i2c_bus ;
274
334
int ret ;
275
335
int error ;
276
336
@@ -330,6 +390,22 @@ static int ppkb_probe(struct i2c_client *client)
330
390
331
391
i2c_set_clientdata (client , ppkb );
332
392
393
+ i2c_bus = of_get_child_by_name (dev -> of_node , "i2c" );
394
+ if (i2c_bus ) {
395
+ ppkb -> adapter .owner = THIS_MODULE ;
396
+ ppkb -> adapter .algo = & ppkb_adap_algo ;
397
+ ppkb -> adapter .algo_data = client ;
398
+ ppkb -> adapter .dev .parent = dev ;
399
+ ppkb -> adapter .dev .of_node = i2c_bus ;
400
+ strscpy (ppkb -> adapter .name , DRV_NAME , sizeof (ppkb -> adapter .name ));
401
+
402
+ error = devm_i2c_add_adapter (dev , & ppkb -> adapter );
403
+ if (error ) {
404
+ dev_err (dev , "Failed to add I2C adapter: %d\n" , error );
405
+ return error ;
406
+ }
407
+ }
408
+
333
409
crc8_populate_msb (ppkb -> crc_table , PPKB_CRC8_POLYNOMIAL );
334
410
335
411
ppkb -> input = devm_input_allocate_device (dev );
0 commit comments