1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 282264d0cSBenjamin Tissoires /* 382264d0cSBenjamin Tissoires * Copyright (c) 2015 - 2016 Red Hat, Inc 482264d0cSBenjamin Tissoires * Copyright (c) 2011, 2012 Synaptics Incorporated 582264d0cSBenjamin Tissoires * Copyright (c) 2011 Unixphere 682264d0cSBenjamin Tissoires */ 782264d0cSBenjamin Tissoires 882264d0cSBenjamin Tissoires #include <linux/kernel.h> 982264d0cSBenjamin Tissoires #include <linux/delay.h> 1082264d0cSBenjamin Tissoires #include <linux/i2c.h> 1182264d0cSBenjamin Tissoires #include <linux/interrupt.h> 1282264d0cSBenjamin Tissoires #include <linux/kconfig.h> 1382264d0cSBenjamin Tissoires #include <linux/lockdep.h> 1482264d0cSBenjamin Tissoires #include <linux/module.h> 1582264d0cSBenjamin Tissoires #include <linux/pm.h> 1682264d0cSBenjamin Tissoires #include <linux/rmi.h> 1782264d0cSBenjamin Tissoires #include <linux/slab.h> 1882264d0cSBenjamin Tissoires #include "rmi_driver.h" 1982264d0cSBenjamin Tissoires 2082264d0cSBenjamin Tissoires #define SMB_PROTOCOL_VERSION_ADDRESS 0xfd 2182264d0cSBenjamin Tissoires #define SMB_MAX_COUNT 32 2282264d0cSBenjamin Tissoires #define RMI_SMB2_MAP_SIZE 8 /* 8 entry of 4 bytes each */ 2382264d0cSBenjamin Tissoires #define RMI_SMB2_MAP_FLAGS_WE 0x01 2482264d0cSBenjamin Tissoires 2582264d0cSBenjamin Tissoires struct mapping_table_entry { 2682264d0cSBenjamin Tissoires __le16 rmiaddr; 2782264d0cSBenjamin Tissoires u8 readcount; 2882264d0cSBenjamin Tissoires u8 flags; 2982264d0cSBenjamin Tissoires }; 3082264d0cSBenjamin Tissoires 3182264d0cSBenjamin Tissoires struct rmi_smb_xport { 3282264d0cSBenjamin Tissoires struct rmi_transport_dev xport; 3382264d0cSBenjamin Tissoires struct i2c_client *client; 3482264d0cSBenjamin Tissoires 3582264d0cSBenjamin Tissoires struct mutex page_mutex; 3682264d0cSBenjamin Tissoires int page; 3782264d0cSBenjamin Tissoires u8 table_index; 3882264d0cSBenjamin Tissoires struct mutex mappingtable_mutex; 3982264d0cSBenjamin Tissoires struct mapping_table_entry mapping_table[RMI_SMB2_MAP_SIZE]; 4082264d0cSBenjamin Tissoires }; 4182264d0cSBenjamin Tissoires 4282264d0cSBenjamin Tissoires static int rmi_smb_get_version(struct rmi_smb_xport *rmi_smb) 4382264d0cSBenjamin Tissoires { 4482264d0cSBenjamin Tissoires struct i2c_client *client = rmi_smb->client; 4582264d0cSBenjamin Tissoires int retval; 4682264d0cSBenjamin Tissoires 4782264d0cSBenjamin Tissoires /* Check if for SMBus new version device by reading version byte. */ 4882264d0cSBenjamin Tissoires retval = i2c_smbus_read_byte_data(client, SMB_PROTOCOL_VERSION_ADDRESS); 4982264d0cSBenjamin Tissoires if (retval < 0) { 5082264d0cSBenjamin Tissoires dev_err(&client->dev, "failed to get SMBus version number!\n"); 5182264d0cSBenjamin Tissoires return retval; 5282264d0cSBenjamin Tissoires } 5354bf0894SDmitry Torokhov 5482264d0cSBenjamin Tissoires return retval + 1; 5582264d0cSBenjamin Tissoires } 5682264d0cSBenjamin Tissoires 5782264d0cSBenjamin Tissoires /* SMB block write - wrapper over ic2_smb_write_block */ 5882264d0cSBenjamin Tissoires static int smb_block_write(struct rmi_transport_dev *xport, 5982264d0cSBenjamin Tissoires u8 commandcode, const void *buf, size_t len) 6082264d0cSBenjamin Tissoires { 6182264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = 6282264d0cSBenjamin Tissoires container_of(xport, struct rmi_smb_xport, xport); 6382264d0cSBenjamin Tissoires struct i2c_client *client = rmi_smb->client; 6482264d0cSBenjamin Tissoires int retval; 6582264d0cSBenjamin Tissoires 6682264d0cSBenjamin Tissoires retval = i2c_smbus_write_block_data(client, commandcode, len, buf); 6782264d0cSBenjamin Tissoires 6882264d0cSBenjamin Tissoires rmi_dbg(RMI_DEBUG_XPORT, &client->dev, 6982264d0cSBenjamin Tissoires "wrote %zd bytes at %#04x: %d (%*ph)\n", 7082264d0cSBenjamin Tissoires len, commandcode, retval, (int)len, buf); 7182264d0cSBenjamin Tissoires 7282264d0cSBenjamin Tissoires return retval; 7382264d0cSBenjamin Tissoires } 7482264d0cSBenjamin Tissoires 7582264d0cSBenjamin Tissoires /* 7682264d0cSBenjamin Tissoires * The function to get command code for smbus operations and keeps 7782264d0cSBenjamin Tissoires * records to the driver mapping table 7882264d0cSBenjamin Tissoires */ 7982264d0cSBenjamin Tissoires static int rmi_smb_get_command_code(struct rmi_transport_dev *xport, 8082264d0cSBenjamin Tissoires u16 rmiaddr, int bytecount, bool isread, u8 *commandcode) 8182264d0cSBenjamin Tissoires { 8282264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = 8382264d0cSBenjamin Tissoires container_of(xport, struct rmi_smb_xport, xport); 848a7c71aeSDmitry Torokhov struct mapping_table_entry new_map; 8582264d0cSBenjamin Tissoires int i; 868a7c71aeSDmitry Torokhov int retval = 0; 8782264d0cSBenjamin Tissoires 8882264d0cSBenjamin Tissoires mutex_lock(&rmi_smb->mappingtable_mutex); 898a7c71aeSDmitry Torokhov 9082264d0cSBenjamin Tissoires for (i = 0; i < RMI_SMB2_MAP_SIZE; i++) { 912593cd11SDmitry Torokhov struct mapping_table_entry *entry = &rmi_smb->mapping_table[i]; 922593cd11SDmitry Torokhov 932593cd11SDmitry Torokhov if (le16_to_cpu(entry->rmiaddr) == rmiaddr) { 9482264d0cSBenjamin Tissoires if (isread) { 958a7c71aeSDmitry Torokhov if (entry->readcount == bytecount) 9682264d0cSBenjamin Tissoires goto exit; 9782264d0cSBenjamin Tissoires } else { 982593cd11SDmitry Torokhov if (entry->flags & RMI_SMB2_MAP_FLAGS_WE) { 9982264d0cSBenjamin Tissoires goto exit; 10082264d0cSBenjamin Tissoires } 10182264d0cSBenjamin Tissoires } 10282264d0cSBenjamin Tissoires } 10382264d0cSBenjamin Tissoires } 1048a7c71aeSDmitry Torokhov 10582264d0cSBenjamin Tissoires i = rmi_smb->table_index; 10682264d0cSBenjamin Tissoires rmi_smb->table_index = (i + 1) % RMI_SMB2_MAP_SIZE; 10782264d0cSBenjamin Tissoires 10882264d0cSBenjamin Tissoires /* constructs mapping table data entry. 4 bytes each entry */ 1098a7c71aeSDmitry Torokhov memset(&new_map, 0, sizeof(new_map)); 1108a7c71aeSDmitry Torokhov new_map.rmiaddr = cpu_to_le16(rmiaddr); 1118a7c71aeSDmitry Torokhov new_map.readcount = bytecount; 1128a7c71aeSDmitry Torokhov new_map.flags = !isread ? RMI_SMB2_MAP_FLAGS_WE : 0; 11382264d0cSBenjamin Tissoires 1148a7c71aeSDmitry Torokhov retval = smb_block_write(xport, i + 0x80, &new_map, sizeof(new_map)); 11582264d0cSBenjamin Tissoires if (retval < 0) { 11682264d0cSBenjamin Tissoires /* 11782264d0cSBenjamin Tissoires * if not written to device mapping table 11882264d0cSBenjamin Tissoires * clear the driver mapping table records 11982264d0cSBenjamin Tissoires */ 1208a7c71aeSDmitry Torokhov memset(&new_map, 0, sizeof(new_map)); 12182264d0cSBenjamin Tissoires } 1228a7c71aeSDmitry Torokhov 12382264d0cSBenjamin Tissoires /* save to the driver level mapping table */ 1248a7c71aeSDmitry Torokhov rmi_smb->mapping_table[i] = new_map; 12582264d0cSBenjamin Tissoires 12682264d0cSBenjamin Tissoires exit: 12782264d0cSBenjamin Tissoires mutex_unlock(&rmi_smb->mappingtable_mutex); 12882264d0cSBenjamin Tissoires 1298a7c71aeSDmitry Torokhov if (retval < 0) 13082264d0cSBenjamin Tissoires return retval; 1318a7c71aeSDmitry Torokhov 1328a7c71aeSDmitry Torokhov *commandcode = i; 1338a7c71aeSDmitry Torokhov return 0; 13482264d0cSBenjamin Tissoires } 13582264d0cSBenjamin Tissoires 13682264d0cSBenjamin Tissoires static int rmi_smb_write_block(struct rmi_transport_dev *xport, u16 rmiaddr, 13782264d0cSBenjamin Tissoires const void *databuff, size_t len) 13882264d0cSBenjamin Tissoires { 13982264d0cSBenjamin Tissoires int retval = 0; 14082264d0cSBenjamin Tissoires u8 commandcode; 14182264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = 14282264d0cSBenjamin Tissoires container_of(xport, struct rmi_smb_xport, xport); 14382264d0cSBenjamin Tissoires int cur_len = (int)len; 14482264d0cSBenjamin Tissoires 14582264d0cSBenjamin Tissoires mutex_lock(&rmi_smb->page_mutex); 14682264d0cSBenjamin Tissoires 14782264d0cSBenjamin Tissoires while (cur_len > 0) { 14882264d0cSBenjamin Tissoires /* 14982264d0cSBenjamin Tissoires * break into 32 bytes chunks to write get command code 15082264d0cSBenjamin Tissoires */ 15182264d0cSBenjamin Tissoires int block_len = min_t(int, len, SMB_MAX_COUNT); 15282264d0cSBenjamin Tissoires 15382264d0cSBenjamin Tissoires retval = rmi_smb_get_command_code(xport, rmiaddr, block_len, 15482264d0cSBenjamin Tissoires false, &commandcode); 15582264d0cSBenjamin Tissoires if (retval < 0) 15682264d0cSBenjamin Tissoires goto exit; 15782264d0cSBenjamin Tissoires 15882264d0cSBenjamin Tissoires retval = smb_block_write(xport, commandcode, 15982264d0cSBenjamin Tissoires databuff, block_len); 16082264d0cSBenjamin Tissoires if (retval < 0) 16182264d0cSBenjamin Tissoires goto exit; 16282264d0cSBenjamin Tissoires 16382264d0cSBenjamin Tissoires /* prepare to write next block of bytes */ 16482264d0cSBenjamin Tissoires cur_len -= SMB_MAX_COUNT; 16582264d0cSBenjamin Tissoires databuff += SMB_MAX_COUNT; 1668ff771f8SHans Verkuil rmiaddr += SMB_MAX_COUNT; 16782264d0cSBenjamin Tissoires } 16882264d0cSBenjamin Tissoires exit: 16982264d0cSBenjamin Tissoires mutex_unlock(&rmi_smb->page_mutex); 17082264d0cSBenjamin Tissoires return retval; 17182264d0cSBenjamin Tissoires } 17282264d0cSBenjamin Tissoires 17382264d0cSBenjamin Tissoires /* SMB block read - wrapper over ic2_smb_read_block */ 17482264d0cSBenjamin Tissoires static int smb_block_read(struct rmi_transport_dev *xport, 17582264d0cSBenjamin Tissoires u8 commandcode, void *buf, size_t len) 17682264d0cSBenjamin Tissoires { 17782264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = 17882264d0cSBenjamin Tissoires container_of(xport, struct rmi_smb_xport, xport); 17982264d0cSBenjamin Tissoires struct i2c_client *client = rmi_smb->client; 18082264d0cSBenjamin Tissoires int retval; 18182264d0cSBenjamin Tissoires 18282264d0cSBenjamin Tissoires retval = i2c_smbus_read_block_data(client, commandcode, buf); 18382264d0cSBenjamin Tissoires if (retval < 0) 18482264d0cSBenjamin Tissoires return retval; 18582264d0cSBenjamin Tissoires 18682264d0cSBenjamin Tissoires return retval; 18782264d0cSBenjamin Tissoires } 18882264d0cSBenjamin Tissoires 18982264d0cSBenjamin Tissoires static int rmi_smb_read_block(struct rmi_transport_dev *xport, u16 rmiaddr, 19082264d0cSBenjamin Tissoires void *databuff, size_t len) 19182264d0cSBenjamin Tissoires { 19282264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = 19382264d0cSBenjamin Tissoires container_of(xport, struct rmi_smb_xport, xport); 19482264d0cSBenjamin Tissoires int retval; 19582264d0cSBenjamin Tissoires u8 commandcode; 19682264d0cSBenjamin Tissoires int cur_len = (int)len; 19782264d0cSBenjamin Tissoires 19882264d0cSBenjamin Tissoires mutex_lock(&rmi_smb->page_mutex); 19982264d0cSBenjamin Tissoires memset(databuff, 0, len); 20082264d0cSBenjamin Tissoires 20182264d0cSBenjamin Tissoires while (cur_len > 0) { 20282264d0cSBenjamin Tissoires /* break into 32 bytes chunks to write get command code */ 20382264d0cSBenjamin Tissoires int block_len = min_t(int, cur_len, SMB_MAX_COUNT); 20482264d0cSBenjamin Tissoires 20582264d0cSBenjamin Tissoires retval = rmi_smb_get_command_code(xport, rmiaddr, block_len, 20682264d0cSBenjamin Tissoires true, &commandcode); 20782264d0cSBenjamin Tissoires if (retval < 0) 20882264d0cSBenjamin Tissoires goto exit; 20982264d0cSBenjamin Tissoires 21082264d0cSBenjamin Tissoires retval = smb_block_read(xport, commandcode, 21182264d0cSBenjamin Tissoires databuff, block_len); 21282264d0cSBenjamin Tissoires if (retval < 0) 21382264d0cSBenjamin Tissoires goto exit; 21482264d0cSBenjamin Tissoires 21582264d0cSBenjamin Tissoires /* prepare to read next block of bytes */ 21682264d0cSBenjamin Tissoires cur_len -= SMB_MAX_COUNT; 21782264d0cSBenjamin Tissoires databuff += SMB_MAX_COUNT; 2188ff771f8SHans Verkuil rmiaddr += SMB_MAX_COUNT; 21982264d0cSBenjamin Tissoires } 22082264d0cSBenjamin Tissoires 22182264d0cSBenjamin Tissoires retval = 0; 22282264d0cSBenjamin Tissoires 22382264d0cSBenjamin Tissoires exit: 22482264d0cSBenjamin Tissoires mutex_unlock(&rmi_smb->page_mutex); 22582264d0cSBenjamin Tissoires return retval; 22682264d0cSBenjamin Tissoires } 22782264d0cSBenjamin Tissoires 22882264d0cSBenjamin Tissoires static void rmi_smb_clear_state(struct rmi_smb_xport *rmi_smb) 22982264d0cSBenjamin Tissoires { 23082264d0cSBenjamin Tissoires /* the mapping table has been flushed, discard the current one */ 23182264d0cSBenjamin Tissoires mutex_lock(&rmi_smb->mappingtable_mutex); 23282264d0cSBenjamin Tissoires memset(rmi_smb->mapping_table, 0, sizeof(rmi_smb->mapping_table)); 23382264d0cSBenjamin Tissoires mutex_unlock(&rmi_smb->mappingtable_mutex); 23482264d0cSBenjamin Tissoires } 23582264d0cSBenjamin Tissoires 23682264d0cSBenjamin Tissoires static int rmi_smb_enable_smbus_mode(struct rmi_smb_xport *rmi_smb) 23782264d0cSBenjamin Tissoires { 23882264d0cSBenjamin Tissoires int retval; 23982264d0cSBenjamin Tissoires 24082264d0cSBenjamin Tissoires /* we need to get the smbus version to activate the touchpad */ 24182264d0cSBenjamin Tissoires retval = rmi_smb_get_version(rmi_smb); 24282264d0cSBenjamin Tissoires if (retval < 0) 24382264d0cSBenjamin Tissoires return retval; 24482264d0cSBenjamin Tissoires 24582264d0cSBenjamin Tissoires return 0; 24682264d0cSBenjamin Tissoires } 24782264d0cSBenjamin Tissoires 24882264d0cSBenjamin Tissoires static int rmi_smb_reset(struct rmi_transport_dev *xport, u16 reset_addr) 24982264d0cSBenjamin Tissoires { 25082264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = 25182264d0cSBenjamin Tissoires container_of(xport, struct rmi_smb_xport, xport); 25282264d0cSBenjamin Tissoires 25382264d0cSBenjamin Tissoires rmi_smb_clear_state(rmi_smb); 25482264d0cSBenjamin Tissoires 25582264d0cSBenjamin Tissoires /* 25682264d0cSBenjamin Tissoires * we do not call the actual reset command, it has to be handled in 25782264d0cSBenjamin Tissoires * PS/2 or there will be races between PS/2 and SMBus. 25882264d0cSBenjamin Tissoires * PS/2 should ensure that a psmouse_reset is called before 25982264d0cSBenjamin Tissoires * intializing the device and after it has been removed to be in a known 26082264d0cSBenjamin Tissoires * state. 26182264d0cSBenjamin Tissoires */ 26282264d0cSBenjamin Tissoires return rmi_smb_enable_smbus_mode(rmi_smb); 26382264d0cSBenjamin Tissoires } 26482264d0cSBenjamin Tissoires 26582264d0cSBenjamin Tissoires static const struct rmi_transport_ops rmi_smb_ops = { 26682264d0cSBenjamin Tissoires .write_block = rmi_smb_write_block, 26782264d0cSBenjamin Tissoires .read_block = rmi_smb_read_block, 26882264d0cSBenjamin Tissoires .reset = rmi_smb_reset, 26982264d0cSBenjamin Tissoires }; 27082264d0cSBenjamin Tissoires 271*3684d803SUwe Kleine-König static int rmi_smb_probe(struct i2c_client *client) 27282264d0cSBenjamin Tissoires { 27382264d0cSBenjamin Tissoires struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev); 27482264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb; 27582264d0cSBenjamin Tissoires int smbus_version; 27654bf0894SDmitry Torokhov int error; 27754bf0894SDmitry Torokhov 27854bf0894SDmitry Torokhov if (!pdata) { 27954bf0894SDmitry Torokhov dev_err(&client->dev, "no platform data, aborting\n"); 28054bf0894SDmitry Torokhov return -ENOMEM; 28154bf0894SDmitry Torokhov } 28282264d0cSBenjamin Tissoires 28382264d0cSBenjamin Tissoires if (!i2c_check_functionality(client->adapter, 28482264d0cSBenjamin Tissoires I2C_FUNC_SMBUS_READ_BLOCK_DATA | 28582264d0cSBenjamin Tissoires I2C_FUNC_SMBUS_HOST_NOTIFY)) { 28682264d0cSBenjamin Tissoires dev_err(&client->dev, 28754bf0894SDmitry Torokhov "adapter does not support required functionality\n"); 28882264d0cSBenjamin Tissoires return -ENODEV; 28982264d0cSBenjamin Tissoires } 29082264d0cSBenjamin Tissoires 29182264d0cSBenjamin Tissoires if (client->irq <= 0) { 29254bf0894SDmitry Torokhov dev_err(&client->dev, "no IRQ provided, giving up\n"); 29382264d0cSBenjamin Tissoires return client->irq ? client->irq : -ENODEV; 29482264d0cSBenjamin Tissoires } 29582264d0cSBenjamin Tissoires 29682264d0cSBenjamin Tissoires rmi_smb = devm_kzalloc(&client->dev, sizeof(struct rmi_smb_xport), 29782264d0cSBenjamin Tissoires GFP_KERNEL); 29882264d0cSBenjamin Tissoires if (!rmi_smb) 29982264d0cSBenjamin Tissoires return -ENOMEM; 30082264d0cSBenjamin Tissoires 30154bf0894SDmitry Torokhov rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Probing %s\n", 30282264d0cSBenjamin Tissoires dev_name(&client->dev)); 30382264d0cSBenjamin Tissoires 30482264d0cSBenjamin Tissoires rmi_smb->client = client; 30582264d0cSBenjamin Tissoires mutex_init(&rmi_smb->page_mutex); 30682264d0cSBenjamin Tissoires mutex_init(&rmi_smb->mappingtable_mutex); 30782264d0cSBenjamin Tissoires 30882264d0cSBenjamin Tissoires rmi_smb->xport.dev = &client->dev; 30982264d0cSBenjamin Tissoires rmi_smb->xport.pdata = *pdata; 31082264d0cSBenjamin Tissoires rmi_smb->xport.pdata.irq = client->irq; 31126dd633eSYiannis Marangos rmi_smb->xport.proto_name = "smb"; 31282264d0cSBenjamin Tissoires rmi_smb->xport.ops = &rmi_smb_ops; 31382264d0cSBenjamin Tissoires 31454bf0894SDmitry Torokhov smbus_version = rmi_smb_get_version(rmi_smb); 31554bf0894SDmitry Torokhov if (smbus_version < 0) 31654bf0894SDmitry Torokhov return smbus_version; 31782264d0cSBenjamin Tissoires 31882264d0cSBenjamin Tissoires rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d", 31982264d0cSBenjamin Tissoires smbus_version); 32082264d0cSBenjamin Tissoires 32126dd633eSYiannis Marangos if (smbus_version != 2 && smbus_version != 3) { 32254bf0894SDmitry Torokhov dev_err(&client->dev, "Unrecognized SMB version %d\n", 32382264d0cSBenjamin Tissoires smbus_version); 32482264d0cSBenjamin Tissoires return -ENODEV; 32582264d0cSBenjamin Tissoires } 32682264d0cSBenjamin Tissoires 32782264d0cSBenjamin Tissoires i2c_set_clientdata(client, rmi_smb); 32882264d0cSBenjamin Tissoires 32954bf0894SDmitry Torokhov dev_info(&client->dev, "registering SMbus-connected sensor\n"); 33054bf0894SDmitry Torokhov 33154bf0894SDmitry Torokhov error = rmi_register_transport_device(&rmi_smb->xport); 33254bf0894SDmitry Torokhov if (error) { 33354bf0894SDmitry Torokhov dev_err(&client->dev, "failed to register sensor: %d\n", error); 33454bf0894SDmitry Torokhov return error; 33582264d0cSBenjamin Tissoires } 33682264d0cSBenjamin Tissoires 33782264d0cSBenjamin Tissoires return 0; 33882264d0cSBenjamin Tissoires } 33982264d0cSBenjamin Tissoires 340ed5c2f5fSUwe Kleine-König static void rmi_smb_remove(struct i2c_client *client) 34182264d0cSBenjamin Tissoires { 34282264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); 34382264d0cSBenjamin Tissoires 34482264d0cSBenjamin Tissoires rmi_unregister_transport_device(&rmi_smb->xport); 34582264d0cSBenjamin Tissoires } 34682264d0cSBenjamin Tissoires 34782264d0cSBenjamin Tissoires static int __maybe_unused rmi_smb_suspend(struct device *dev) 34882264d0cSBenjamin Tissoires { 34982264d0cSBenjamin Tissoires struct i2c_client *client = to_i2c_client(dev); 35082264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); 35182264d0cSBenjamin Tissoires int ret; 35282264d0cSBenjamin Tissoires 35382264d0cSBenjamin Tissoires ret = rmi_driver_suspend(rmi_smb->xport.rmi_dev, true); 35482264d0cSBenjamin Tissoires if (ret) 35582264d0cSBenjamin Tissoires dev_warn(dev, "Failed to suspend device: %d\n", ret); 35682264d0cSBenjamin Tissoires 35782264d0cSBenjamin Tissoires return ret; 35882264d0cSBenjamin Tissoires } 35982264d0cSBenjamin Tissoires 36082264d0cSBenjamin Tissoires static int __maybe_unused rmi_smb_runtime_suspend(struct device *dev) 36182264d0cSBenjamin Tissoires { 36282264d0cSBenjamin Tissoires struct i2c_client *client = to_i2c_client(dev); 36382264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); 36482264d0cSBenjamin Tissoires int ret; 36582264d0cSBenjamin Tissoires 36682264d0cSBenjamin Tissoires ret = rmi_driver_suspend(rmi_smb->xport.rmi_dev, false); 36782264d0cSBenjamin Tissoires if (ret) 36882264d0cSBenjamin Tissoires dev_warn(dev, "Failed to suspend device: %d\n", ret); 36982264d0cSBenjamin Tissoires 37082264d0cSBenjamin Tissoires return ret; 37182264d0cSBenjamin Tissoires } 37282264d0cSBenjamin Tissoires 37382264d0cSBenjamin Tissoires static int __maybe_unused rmi_smb_resume(struct device *dev) 37482264d0cSBenjamin Tissoires { 37582264d0cSBenjamin Tissoires struct i2c_client *client = container_of(dev, struct i2c_client, dev); 37682264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); 37782264d0cSBenjamin Tissoires struct rmi_device *rmi_dev = rmi_smb->xport.rmi_dev; 37882264d0cSBenjamin Tissoires int ret; 37982264d0cSBenjamin Tissoires 38082264d0cSBenjamin Tissoires rmi_smb_reset(&rmi_smb->xport, 0); 38182264d0cSBenjamin Tissoires 38282264d0cSBenjamin Tissoires rmi_reset(rmi_dev); 38382264d0cSBenjamin Tissoires 38482264d0cSBenjamin Tissoires ret = rmi_driver_resume(rmi_smb->xport.rmi_dev, true); 38582264d0cSBenjamin Tissoires if (ret) 38682264d0cSBenjamin Tissoires dev_warn(dev, "Failed to resume device: %d\n", ret); 38782264d0cSBenjamin Tissoires 38882264d0cSBenjamin Tissoires return 0; 38982264d0cSBenjamin Tissoires } 39082264d0cSBenjamin Tissoires 39182264d0cSBenjamin Tissoires static int __maybe_unused rmi_smb_runtime_resume(struct device *dev) 39282264d0cSBenjamin Tissoires { 39382264d0cSBenjamin Tissoires struct i2c_client *client = to_i2c_client(dev); 39482264d0cSBenjamin Tissoires struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); 39582264d0cSBenjamin Tissoires int ret; 39682264d0cSBenjamin Tissoires 39782264d0cSBenjamin Tissoires ret = rmi_driver_resume(rmi_smb->xport.rmi_dev, false); 39882264d0cSBenjamin Tissoires if (ret) 39982264d0cSBenjamin Tissoires dev_warn(dev, "Failed to resume device: %d\n", ret); 40082264d0cSBenjamin Tissoires 40182264d0cSBenjamin Tissoires return 0; 40282264d0cSBenjamin Tissoires } 40382264d0cSBenjamin Tissoires 40482264d0cSBenjamin Tissoires static const struct dev_pm_ops rmi_smb_pm = { 40582264d0cSBenjamin Tissoires SET_SYSTEM_SLEEP_PM_OPS(rmi_smb_suspend, rmi_smb_resume) 40682264d0cSBenjamin Tissoires SET_RUNTIME_PM_OPS(rmi_smb_runtime_suspend, rmi_smb_runtime_resume, 40782264d0cSBenjamin Tissoires NULL) 40882264d0cSBenjamin Tissoires }; 40982264d0cSBenjamin Tissoires 41082264d0cSBenjamin Tissoires static const struct i2c_device_id rmi_id[] = { 41182264d0cSBenjamin Tissoires { "rmi4_smbus", 0 }, 41282264d0cSBenjamin Tissoires { } 41382264d0cSBenjamin Tissoires }; 41482264d0cSBenjamin Tissoires MODULE_DEVICE_TABLE(i2c, rmi_id); 41582264d0cSBenjamin Tissoires 41682264d0cSBenjamin Tissoires static struct i2c_driver rmi_smb_driver = { 41782264d0cSBenjamin Tissoires .driver = { 41882264d0cSBenjamin Tissoires .name = "rmi4_smbus", 41982264d0cSBenjamin Tissoires .pm = &rmi_smb_pm, 42082264d0cSBenjamin Tissoires }, 42182264d0cSBenjamin Tissoires .id_table = rmi_id, 422*3684d803SUwe Kleine-König .probe_new = rmi_smb_probe, 42382264d0cSBenjamin Tissoires .remove = rmi_smb_remove, 42482264d0cSBenjamin Tissoires }; 42582264d0cSBenjamin Tissoires 42682264d0cSBenjamin Tissoires module_i2c_driver(rmi_smb_driver); 42782264d0cSBenjamin Tissoires 42882264d0cSBenjamin Tissoires MODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com>"); 42982264d0cSBenjamin Tissoires MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@redhat.com>"); 43082264d0cSBenjamin Tissoires MODULE_DESCRIPTION("RMI4 SMBus driver"); 43182264d0cSBenjamin Tissoires MODULE_LICENSE("GPL"); 432