xref: /linux/drivers/i2c/busses/i2c-virtio.c (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
13cfc8838SJie Deng // SPDX-License-Identifier: GPL-2.0-or-later
23cfc8838SJie Deng /*
33cfc8838SJie Deng  * Virtio I2C Bus Driver
43cfc8838SJie Deng  *
53cfc8838SJie Deng  * The Virtio I2C Specification:
63cfc8838SJie Deng  * https://raw.githubusercontent.com/oasis-tcs/virtio-spec/master/virtio-i2c.tex
73cfc8838SJie Deng  *
83cfc8838SJie Deng  * Copyright (c) 2021 Intel Corporation. All rights reserved.
93cfc8838SJie Deng  */
103cfc8838SJie Deng 
113cfc8838SJie Deng #include <linux/acpi.h>
123cfc8838SJie Deng #include <linux/completion.h>
133cfc8838SJie Deng #include <linux/err.h>
143cfc8838SJie Deng #include <linux/i2c.h>
153cfc8838SJie Deng #include <linux/kernel.h>
163cfc8838SJie Deng #include <linux/module.h>
173cfc8838SJie Deng #include <linux/virtio.h>
183cfc8838SJie Deng #include <linux/virtio_ids.h>
193cfc8838SJie Deng #include <linux/virtio_config.h>
203cfc8838SJie Deng #include <linux/virtio_i2c.h>
213cfc8838SJie Deng 
223cfc8838SJie Deng /**
233cfc8838SJie Deng  * struct virtio_i2c - virtio I2C data
243cfc8838SJie Deng  * @vdev: virtio device for this controller
253cfc8838SJie Deng  * @adap: I2C adapter for this controller
263cfc8838SJie Deng  * @vq: the virtio virtqueue for communication
273cfc8838SJie Deng  */
283cfc8838SJie Deng struct virtio_i2c {
293cfc8838SJie Deng 	struct virtio_device *vdev;
303cfc8838SJie Deng 	struct i2c_adapter adap;
313cfc8838SJie Deng 	struct virtqueue *vq;
323cfc8838SJie Deng };
333cfc8838SJie Deng 
343cfc8838SJie Deng /**
353cfc8838SJie Deng  * struct virtio_i2c_req - the virtio I2C request structure
36b503de23SVincent Whitchurch  * @completion: completion of virtio I2C message
373cfc8838SJie Deng  * @out_hdr: the OUT header of the virtio I2C message
383cfc8838SJie Deng  * @buf: the buffer into which data is read, or from which it's written
393cfc8838SJie Deng  * @in_hdr: the IN header of the virtio I2C message
403cfc8838SJie Deng  */
413cfc8838SJie Deng struct virtio_i2c_req {
42b503de23SVincent Whitchurch 	struct completion completion;
433cfc8838SJie Deng 	struct virtio_i2c_out_hdr out_hdr	____cacheline_aligned;
443cfc8838SJie Deng 	uint8_t *buf				____cacheline_aligned;
453cfc8838SJie Deng 	struct virtio_i2c_in_hdr in_hdr		____cacheline_aligned;
463cfc8838SJie Deng };
473cfc8838SJie Deng 
483cfc8838SJie Deng static void virtio_i2c_msg_done(struct virtqueue *vq)
493cfc8838SJie Deng {
50b503de23SVincent Whitchurch 	struct virtio_i2c_req *req;
51b503de23SVincent Whitchurch 	unsigned int len;
523cfc8838SJie Deng 
53b503de23SVincent Whitchurch 	while ((req = virtqueue_get_buf(vq, &len)))
54b503de23SVincent Whitchurch 		complete(&req->completion);
553cfc8838SJie Deng }
563cfc8838SJie Deng 
573cfc8838SJie Deng static int virtio_i2c_prepare_reqs(struct virtqueue *vq,
583cfc8838SJie Deng 				   struct virtio_i2c_req *reqs,
593cfc8838SJie Deng 				   struct i2c_msg *msgs, int num)
603cfc8838SJie Deng {
613cfc8838SJie Deng 	struct scatterlist *sgs[3], out_hdr, msg_buf, in_hdr;
623cfc8838SJie Deng 	int i;
633cfc8838SJie Deng 
643cfc8838SJie Deng 	for (i = 0; i < num; i++) {
653cfc8838SJie Deng 		int outcnt = 0, incnt = 0;
663cfc8838SJie Deng 
67b503de23SVincent Whitchurch 		init_completion(&reqs[i].completion);
68b503de23SVincent Whitchurch 
693cfc8838SJie Deng 		/*
703cfc8838SJie Deng 		 * Only 7-bit mode supported for this moment. For the address
713cfc8838SJie Deng 		 * format, Please check the Virtio I2C Specification.
723cfc8838SJie Deng 		 */
733cfc8838SJie Deng 		reqs[i].out_hdr.addr = cpu_to_le16(msgs[i].addr << 1);
743cfc8838SJie Deng 
75dcce1625SViresh Kumar 		if (msgs[i].flags & I2C_M_RD)
76dcce1625SViresh Kumar 			reqs[i].out_hdr.flags |= cpu_to_le32(VIRTIO_I2C_FLAGS_M_RD);
77dcce1625SViresh Kumar 
783cfc8838SJie Deng 		if (i != num - 1)
79dcce1625SViresh Kumar 			reqs[i].out_hdr.flags |= cpu_to_le32(VIRTIO_I2C_FLAGS_FAIL_NEXT);
803cfc8838SJie Deng 
813cfc8838SJie Deng 		sg_init_one(&out_hdr, &reqs[i].out_hdr, sizeof(reqs[i].out_hdr));
823cfc8838SJie Deng 		sgs[outcnt++] = &out_hdr;
833cfc8838SJie Deng 
84dcce1625SViresh Kumar 		if (msgs[i].len) {
853cfc8838SJie Deng 			reqs[i].buf = i2c_get_dma_safe_msg_buf(&msgs[i], 1);
863cfc8838SJie Deng 			if (!reqs[i].buf)
873cfc8838SJie Deng 				break;
883cfc8838SJie Deng 
893cfc8838SJie Deng 			sg_init_one(&msg_buf, reqs[i].buf, msgs[i].len);
903cfc8838SJie Deng 
913cfc8838SJie Deng 			if (msgs[i].flags & I2C_M_RD)
923cfc8838SJie Deng 				sgs[outcnt + incnt++] = &msg_buf;
933cfc8838SJie Deng 			else
943cfc8838SJie Deng 				sgs[outcnt++] = &msg_buf;
95dcce1625SViresh Kumar 		}
963cfc8838SJie Deng 
973cfc8838SJie Deng 		sg_init_one(&in_hdr, &reqs[i].in_hdr, sizeof(reqs[i].in_hdr));
983cfc8838SJie Deng 		sgs[outcnt + incnt++] = &in_hdr;
993cfc8838SJie Deng 
1003cfc8838SJie Deng 		if (virtqueue_add_sgs(vq, sgs, outcnt, incnt, &reqs[i], GFP_KERNEL)) {
1013cfc8838SJie Deng 			i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], false);
1023cfc8838SJie Deng 			break;
1033cfc8838SJie Deng 		}
1043cfc8838SJie Deng 	}
1053cfc8838SJie Deng 
1063cfc8838SJie Deng 	return i;
1073cfc8838SJie Deng }
1083cfc8838SJie Deng 
1093cfc8838SJie Deng static int virtio_i2c_complete_reqs(struct virtqueue *vq,
1103cfc8838SJie Deng 				    struct virtio_i2c_req *reqs,
11184e1d0bfSVincent Whitchurch 				    struct i2c_msg *msgs, int num)
1123cfc8838SJie Deng {
11384e1d0bfSVincent Whitchurch 	bool failed = false;
1143cfc8838SJie Deng 	int i, j = 0;
1153cfc8838SJie Deng 
1163cfc8838SJie Deng 	for (i = 0; i < num; i++) {
117b503de23SVincent Whitchurch 		struct virtio_i2c_req *req = &reqs[i];
1183cfc8838SJie Deng 
119b503de23SVincent Whitchurch 		wait_for_completion(&req->completion);
120b503de23SVincent Whitchurch 
121b503de23SVincent Whitchurch 		if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK)
1223cfc8838SJie Deng 			failed = true;
1233cfc8838SJie Deng 
1243cfc8838SJie Deng 		i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed);
1253cfc8838SJie Deng 
1263cfc8838SJie Deng 		if (!failed)
1273cfc8838SJie Deng 			j++;
1283cfc8838SJie Deng 	}
1293cfc8838SJie Deng 
13084e1d0bfSVincent Whitchurch 	return j;
1313cfc8838SJie Deng }
1323cfc8838SJie Deng 
1333cfc8838SJie Deng static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
1343cfc8838SJie Deng 			   int num)
1353cfc8838SJie Deng {
1363cfc8838SJie Deng 	struct virtio_i2c *vi = i2c_get_adapdata(adap);
1373cfc8838SJie Deng 	struct virtqueue *vq = vi->vq;
1383cfc8838SJie Deng 	struct virtio_i2c_req *reqs;
1393cfc8838SJie Deng 	int count;
1403cfc8838SJie Deng 
1413cfc8838SJie Deng 	reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL);
1423cfc8838SJie Deng 	if (!reqs)
1433cfc8838SJie Deng 		return -ENOMEM;
1443cfc8838SJie Deng 
1453cfc8838SJie Deng 	count = virtio_i2c_prepare_reqs(vq, reqs, msgs, num);
1463cfc8838SJie Deng 	if (!count)
1473cfc8838SJie Deng 		goto err_free;
1483cfc8838SJie Deng 
1493cfc8838SJie Deng 	/*
1503cfc8838SJie Deng 	 * For the case where count < num, i.e. we weren't able to queue all the
1513cfc8838SJie Deng 	 * msgs, ideally we should abort right away and return early, but some
1523cfc8838SJie Deng 	 * of the messages are already sent to the remote I2C controller and the
1533cfc8838SJie Deng 	 * virtqueue will be left in undefined state in that case. We kick the
1543cfc8838SJie Deng 	 * remote here to clear the virtqueue, so we can try another set of
1553cfc8838SJie Deng 	 * messages later on.
1563cfc8838SJie Deng 	 */
1573cfc8838SJie Deng 	virtqueue_kick(vq);
1583cfc8838SJie Deng 
15984e1d0bfSVincent Whitchurch 	count = virtio_i2c_complete_reqs(vq, reqs, msgs, count);
1603cfc8838SJie Deng 
1613cfc8838SJie Deng err_free:
1623cfc8838SJie Deng 	kfree(reqs);
1633cfc8838SJie Deng 	return count;
1643cfc8838SJie Deng }
1653cfc8838SJie Deng 
1663cfc8838SJie Deng static void virtio_i2c_del_vqs(struct virtio_device *vdev)
1673cfc8838SJie Deng {
168d9679d00SMichael S. Tsirkin 	virtio_reset_device(vdev);
1693cfc8838SJie Deng 	vdev->config->del_vqs(vdev);
1703cfc8838SJie Deng }
1713cfc8838SJie Deng 
1723cfc8838SJie Deng static int virtio_i2c_setup_vqs(struct virtio_i2c *vi)
1733cfc8838SJie Deng {
1743cfc8838SJie Deng 	struct virtio_device *vdev = vi->vdev;
1753cfc8838SJie Deng 
1763cfc8838SJie Deng 	vi->vq = virtio_find_single_vq(vdev, virtio_i2c_msg_done, "msg");
1773cfc8838SJie Deng 	return PTR_ERR_OR_ZERO(vi->vq);
1783cfc8838SJie Deng }
1793cfc8838SJie Deng 
1803cfc8838SJie Deng static u32 virtio_i2c_func(struct i2c_adapter *adap)
1813cfc8838SJie Deng {
182dcce1625SViresh Kumar 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
1833cfc8838SJie Deng }
1843cfc8838SJie Deng 
1853cfc8838SJie Deng static struct i2c_algorithm virtio_algorithm = {
186*532cc217SWolfram Sang 	.xfer = virtio_i2c_xfer,
1873cfc8838SJie Deng 	.functionality = virtio_i2c_func,
1883cfc8838SJie Deng };
1893cfc8838SJie Deng 
1903cfc8838SJie Deng static int virtio_i2c_probe(struct virtio_device *vdev)
1913cfc8838SJie Deng {
1923cfc8838SJie Deng 	struct virtio_i2c *vi;
1933cfc8838SJie Deng 	int ret;
1943cfc8838SJie Deng 
195dcce1625SViresh Kumar 	if (!virtio_has_feature(vdev, VIRTIO_I2C_F_ZERO_LENGTH_REQUEST)) {
196dcce1625SViresh Kumar 		dev_err(&vdev->dev, "Zero-length request feature is mandatory\n");
197dcce1625SViresh Kumar 		return -EINVAL;
198dcce1625SViresh Kumar 	}
199dcce1625SViresh Kumar 
2003cfc8838SJie Deng 	vi = devm_kzalloc(&vdev->dev, sizeof(*vi), GFP_KERNEL);
2013cfc8838SJie Deng 	if (!vi)
2023cfc8838SJie Deng 		return -ENOMEM;
2033cfc8838SJie Deng 
2043cfc8838SJie Deng 	vdev->priv = vi;
2053cfc8838SJie Deng 	vi->vdev = vdev;
2063cfc8838SJie Deng 
2073cfc8838SJie Deng 	ret = virtio_i2c_setup_vqs(vi);
2083cfc8838SJie Deng 	if (ret)
2093cfc8838SJie Deng 		return ret;
2103cfc8838SJie Deng 
2113cfc8838SJie Deng 	vi->adap.owner = THIS_MODULE;
2123cfc8838SJie Deng 	snprintf(vi->adap.name, sizeof(vi->adap.name),
2133cfc8838SJie Deng 		 "i2c_virtio at virtio bus %d", vdev->index);
2143cfc8838SJie Deng 	vi->adap.algo = &virtio_algorithm;
2153cfc8838SJie Deng 	vi->adap.dev.parent = &vdev->dev;
2163cfc8838SJie Deng 	vi->adap.dev.of_node = vdev->dev.of_node;
2173cfc8838SJie Deng 	i2c_set_adapdata(&vi->adap, vi);
2183cfc8838SJie Deng 
2193cfc8838SJie Deng 	/*
2203cfc8838SJie Deng 	 * Setup ACPI node for controlled devices which will be probed through
2213cfc8838SJie Deng 	 * ACPI.
2223cfc8838SJie Deng 	 */
2233cfc8838SJie Deng 	ACPI_COMPANION_SET(&vi->adap.dev, ACPI_COMPANION(vdev->dev.parent));
2243cfc8838SJie Deng 
2253cfc8838SJie Deng 	ret = i2c_add_adapter(&vi->adap);
2263cfc8838SJie Deng 	if (ret)
2273cfc8838SJie Deng 		virtio_i2c_del_vqs(vdev);
2283cfc8838SJie Deng 
2293cfc8838SJie Deng 	return ret;
2303cfc8838SJie Deng }
2313cfc8838SJie Deng 
2323cfc8838SJie Deng static void virtio_i2c_remove(struct virtio_device *vdev)
2333cfc8838SJie Deng {
2343cfc8838SJie Deng 	struct virtio_i2c *vi = vdev->priv;
2353cfc8838SJie Deng 
2363cfc8838SJie Deng 	i2c_del_adapter(&vi->adap);
2373cfc8838SJie Deng 	virtio_i2c_del_vqs(vdev);
2383cfc8838SJie Deng }
2393cfc8838SJie Deng 
2403cfc8838SJie Deng static struct virtio_device_id id_table[] = {
2413cfc8838SJie Deng 	{ VIRTIO_ID_I2C_ADAPTER, VIRTIO_DEV_ANY_ID },
2423cfc8838SJie Deng 	{}
2433cfc8838SJie Deng };
2443cfc8838SJie Deng MODULE_DEVICE_TABLE(virtio, id_table);
2453cfc8838SJie Deng 
2463cfc8838SJie Deng static int virtio_i2c_freeze(struct virtio_device *vdev)
2473cfc8838SJie Deng {
2483cfc8838SJie Deng 	virtio_i2c_del_vqs(vdev);
2493cfc8838SJie Deng 	return 0;
2503cfc8838SJie Deng }
2513cfc8838SJie Deng 
2523cfc8838SJie Deng static int virtio_i2c_restore(struct virtio_device *vdev)
2533cfc8838SJie Deng {
2543cfc8838SJie Deng 	return virtio_i2c_setup_vqs(vdev->priv);
2553cfc8838SJie Deng }
2563cfc8838SJie Deng 
257dcce1625SViresh Kumar static const unsigned int features[] = {
258dcce1625SViresh Kumar 	VIRTIO_I2C_F_ZERO_LENGTH_REQUEST,
259dcce1625SViresh Kumar };
260dcce1625SViresh Kumar 
2613cfc8838SJie Deng static struct virtio_driver virtio_i2c_driver = {
262dcce1625SViresh Kumar 	.feature_table		= features,
263dcce1625SViresh Kumar 	.feature_table_size	= ARRAY_SIZE(features),
2643cfc8838SJie Deng 	.id_table		= id_table,
2653cfc8838SJie Deng 	.probe			= virtio_i2c_probe,
2663cfc8838SJie Deng 	.remove			= virtio_i2c_remove,
2673cfc8838SJie Deng 	.driver			= {
2683cfc8838SJie Deng 		.name	= "i2c_virtio",
2693cfc8838SJie Deng 	},
270b221df9cSPaul Cercueil 	.freeze			= pm_sleep_ptr(virtio_i2c_freeze),
271b221df9cSPaul Cercueil 	.restore		= pm_sleep_ptr(virtio_i2c_restore),
2723cfc8838SJie Deng };
2733cfc8838SJie Deng module_virtio_driver(virtio_i2c_driver);
2743cfc8838SJie Deng 
2753cfc8838SJie Deng MODULE_AUTHOR("Jie Deng <jie.deng@intel.com>");
2763cfc8838SJie Deng MODULE_AUTHOR("Conghui Chen <conghui.chen@intel.com>");
2773cfc8838SJie Deng MODULE_DESCRIPTION("Virtio i2c bus driver");
2783cfc8838SJie Deng MODULE_LICENSE("GPL");
279