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