33// Copyright (C) 2021-2022 Samuel Holland <[email protected] > 44
55#include <linux/crc8.h>
6+ #include <linux/delay.h>
67#include <linux/err.h>
78#include <linux/i2c.h>
89#include <linux/input.h>
910#include <linux/input/matrix_keypad.h>
1011#include <linux/interrupt.h>
1112#include <linux/module.h>
1213#include <linux/mod_devicetable.h>
14+ #include <linux/of.h>
1315#include <linux/regulator/consumer.h>
1416#include <linux/types.h>
1517
2830#define PPKB_SCAN_DATA 0x08
2931#define PPKB_SYS_CONFIG 0x20
3032#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
3138
3239#define PPKB_ROWS 6
3340#define PPKB_COLS 12
@@ -136,6 +143,7 @@ static const struct matrix_keymap_data ppkb_keymap_data = {
136143};
137144
138145struct pinephone_keyboard {
146+ struct i2c_adapter adapter ;
139147 struct input_dev * input ;
140148 u8 buf [2 ][PPKB_BUF_LEN ];
141149 u8 crc_table [CRC8_TABLE_SIZE ];
@@ -144,6 +152,57 @@ struct pinephone_keyboard {
144152 bool fn_pressed ;
145153};
146154
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+
147206static void ppkb_update (struct i2c_client * client )
148207{
149208 struct pinephone_keyboard * ppkb = i2c_get_clientdata (client );
@@ -271,6 +330,7 @@ static int ppkb_probe(struct i2c_client *client)
271330 struct pinephone_keyboard * ppkb ;
272331 struct regulator * vbat_supply ;
273332 u8 info [PPKB_MATRIX_SIZE + 1 ];
333+ struct device_node * i2c_bus ;
274334 int ret ;
275335 int error ;
276336
@@ -330,6 +390,22 @@ static int ppkb_probe(struct i2c_client *client)
330390
331391 i2c_set_clientdata (client , ppkb );
332392
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+
333409 crc8_populate_msb (ppkb -> crc_table , PPKB_CRC8_POLYNOMIAL );
334410
335411 ppkb -> input = devm_input_allocate_device (dev );
0 commit comments