xref: /openbmc/linux/drivers/input/rmi4/rmi_smbus.c (revision 3684d803)
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