162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Virtio I2C Bus Driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * The Virtio I2C Specification: 662306a36Sopenharmony_ci * https://raw.githubusercontent.com/oasis-tcs/virtio-spec/master/virtio-i2c.tex 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (c) 2021 Intel Corporation. All rights reserved. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/acpi.h> 1262306a36Sopenharmony_ci#include <linux/completion.h> 1362306a36Sopenharmony_ci#include <linux/err.h> 1462306a36Sopenharmony_ci#include <linux/i2c.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/virtio.h> 1862306a36Sopenharmony_ci#include <linux/virtio_ids.h> 1962306a36Sopenharmony_ci#include <linux/virtio_config.h> 2062306a36Sopenharmony_ci#include <linux/virtio_i2c.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/** 2362306a36Sopenharmony_ci * struct virtio_i2c - virtio I2C data 2462306a36Sopenharmony_ci * @vdev: virtio device for this controller 2562306a36Sopenharmony_ci * @adap: I2C adapter for this controller 2662306a36Sopenharmony_ci * @vq: the virtio virtqueue for communication 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_cistruct virtio_i2c { 2962306a36Sopenharmony_ci struct virtio_device *vdev; 3062306a36Sopenharmony_ci struct i2c_adapter adap; 3162306a36Sopenharmony_ci struct virtqueue *vq; 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/** 3562306a36Sopenharmony_ci * struct virtio_i2c_req - the virtio I2C request structure 3662306a36Sopenharmony_ci * @completion: completion of virtio I2C message 3762306a36Sopenharmony_ci * @out_hdr: the OUT header of the virtio I2C message 3862306a36Sopenharmony_ci * @buf: the buffer into which data is read, or from which it's written 3962306a36Sopenharmony_ci * @in_hdr: the IN header of the virtio I2C message 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_cistruct virtio_i2c_req { 4262306a36Sopenharmony_ci struct completion completion; 4362306a36Sopenharmony_ci struct virtio_i2c_out_hdr out_hdr ____cacheline_aligned; 4462306a36Sopenharmony_ci uint8_t *buf ____cacheline_aligned; 4562306a36Sopenharmony_ci struct virtio_i2c_in_hdr in_hdr ____cacheline_aligned; 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic void virtio_i2c_msg_done(struct virtqueue *vq) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci struct virtio_i2c_req *req; 5162306a36Sopenharmony_ci unsigned int len; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci while ((req = virtqueue_get_buf(vq, &len))) 5462306a36Sopenharmony_ci complete(&req->completion); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic int virtio_i2c_prepare_reqs(struct virtqueue *vq, 5862306a36Sopenharmony_ci struct virtio_i2c_req *reqs, 5962306a36Sopenharmony_ci struct i2c_msg *msgs, int num) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci struct scatterlist *sgs[3], out_hdr, msg_buf, in_hdr; 6262306a36Sopenharmony_ci int i; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci for (i = 0; i < num; i++) { 6562306a36Sopenharmony_ci int outcnt = 0, incnt = 0; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci init_completion(&reqs[i].completion); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci /* 7062306a36Sopenharmony_ci * Only 7-bit mode supported for this moment. For the address 7162306a36Sopenharmony_ci * format, Please check the Virtio I2C Specification. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_ci reqs[i].out_hdr.addr = cpu_to_le16(msgs[i].addr << 1); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (msgs[i].flags & I2C_M_RD) 7662306a36Sopenharmony_ci reqs[i].out_hdr.flags |= cpu_to_le32(VIRTIO_I2C_FLAGS_M_RD); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (i != num - 1) 7962306a36Sopenharmony_ci reqs[i].out_hdr.flags |= cpu_to_le32(VIRTIO_I2C_FLAGS_FAIL_NEXT); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci sg_init_one(&out_hdr, &reqs[i].out_hdr, sizeof(reqs[i].out_hdr)); 8262306a36Sopenharmony_ci sgs[outcnt++] = &out_hdr; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci if (msgs[i].len) { 8562306a36Sopenharmony_ci reqs[i].buf = i2c_get_dma_safe_msg_buf(&msgs[i], 1); 8662306a36Sopenharmony_ci if (!reqs[i].buf) 8762306a36Sopenharmony_ci break; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci sg_init_one(&msg_buf, reqs[i].buf, msgs[i].len); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (msgs[i].flags & I2C_M_RD) 9262306a36Sopenharmony_ci sgs[outcnt + incnt++] = &msg_buf; 9362306a36Sopenharmony_ci else 9462306a36Sopenharmony_ci sgs[outcnt++] = &msg_buf; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci sg_init_one(&in_hdr, &reqs[i].in_hdr, sizeof(reqs[i].in_hdr)); 9862306a36Sopenharmony_ci sgs[outcnt + incnt++] = &in_hdr; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci if (virtqueue_add_sgs(vq, sgs, outcnt, incnt, &reqs[i], GFP_KERNEL)) { 10162306a36Sopenharmony_ci i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], false); 10262306a36Sopenharmony_ci break; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return i; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic int virtio_i2c_complete_reqs(struct virtqueue *vq, 11062306a36Sopenharmony_ci struct virtio_i2c_req *reqs, 11162306a36Sopenharmony_ci struct i2c_msg *msgs, int num) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci bool failed = false; 11462306a36Sopenharmony_ci int i, j = 0; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci for (i = 0; i < num; i++) { 11762306a36Sopenharmony_ci struct virtio_i2c_req *req = &reqs[i]; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci wait_for_completion(&req->completion); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK) 12262306a36Sopenharmony_ci failed = true; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (!failed) 12762306a36Sopenharmony_ci j++; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci return j; 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 13462306a36Sopenharmony_ci int num) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci struct virtio_i2c *vi = i2c_get_adapdata(adap); 13762306a36Sopenharmony_ci struct virtqueue *vq = vi->vq; 13862306a36Sopenharmony_ci struct virtio_i2c_req *reqs; 13962306a36Sopenharmony_ci int count; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL); 14262306a36Sopenharmony_ci if (!reqs) 14362306a36Sopenharmony_ci return -ENOMEM; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci count = virtio_i2c_prepare_reqs(vq, reqs, msgs, num); 14662306a36Sopenharmony_ci if (!count) 14762306a36Sopenharmony_ci goto err_free; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /* 15062306a36Sopenharmony_ci * For the case where count < num, i.e. we weren't able to queue all the 15162306a36Sopenharmony_ci * msgs, ideally we should abort right away and return early, but some 15262306a36Sopenharmony_ci * of the messages are already sent to the remote I2C controller and the 15362306a36Sopenharmony_ci * virtqueue will be left in undefined state in that case. We kick the 15462306a36Sopenharmony_ci * remote here to clear the virtqueue, so we can try another set of 15562306a36Sopenharmony_ci * messages later on. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci virtqueue_kick(vq); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci count = virtio_i2c_complete_reqs(vq, reqs, msgs, count); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cierr_free: 16262306a36Sopenharmony_ci kfree(reqs); 16362306a36Sopenharmony_ci return count; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic void virtio_i2c_del_vqs(struct virtio_device *vdev) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci virtio_reset_device(vdev); 16962306a36Sopenharmony_ci vdev->config->del_vqs(vdev); 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic int virtio_i2c_setup_vqs(struct virtio_i2c *vi) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci struct virtio_device *vdev = vi->vdev; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci vi->vq = virtio_find_single_vq(vdev, virtio_i2c_msg_done, "msg"); 17762306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(vi->vq); 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic u32 virtio_i2c_func(struct i2c_adapter *adap) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic struct i2c_algorithm virtio_algorithm = { 18662306a36Sopenharmony_ci .master_xfer = virtio_i2c_xfer, 18762306a36Sopenharmony_ci .functionality = virtio_i2c_func, 18862306a36Sopenharmony_ci}; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic int virtio_i2c_probe(struct virtio_device *vdev) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci struct virtio_i2c *vi; 19362306a36Sopenharmony_ci int ret; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (!virtio_has_feature(vdev, VIRTIO_I2C_F_ZERO_LENGTH_REQUEST)) { 19662306a36Sopenharmony_ci dev_err(&vdev->dev, "Zero-length request feature is mandatory\n"); 19762306a36Sopenharmony_ci return -EINVAL; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci vi = devm_kzalloc(&vdev->dev, sizeof(*vi), GFP_KERNEL); 20162306a36Sopenharmony_ci if (!vi) 20262306a36Sopenharmony_ci return -ENOMEM; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci vdev->priv = vi; 20562306a36Sopenharmony_ci vi->vdev = vdev; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci ret = virtio_i2c_setup_vqs(vi); 20862306a36Sopenharmony_ci if (ret) 20962306a36Sopenharmony_ci return ret; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci vi->adap.owner = THIS_MODULE; 21262306a36Sopenharmony_ci snprintf(vi->adap.name, sizeof(vi->adap.name), 21362306a36Sopenharmony_ci "i2c_virtio at virtio bus %d", vdev->index); 21462306a36Sopenharmony_ci vi->adap.algo = &virtio_algorithm; 21562306a36Sopenharmony_ci vi->adap.dev.parent = &vdev->dev; 21662306a36Sopenharmony_ci vi->adap.dev.of_node = vdev->dev.of_node; 21762306a36Sopenharmony_ci i2c_set_adapdata(&vi->adap, vi); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci /* 22062306a36Sopenharmony_ci * Setup ACPI node for controlled devices which will be probed through 22162306a36Sopenharmony_ci * ACPI. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_ci ACPI_COMPANION_SET(&vi->adap.dev, ACPI_COMPANION(vdev->dev.parent)); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci ret = i2c_add_adapter(&vi->adap); 22662306a36Sopenharmony_ci if (ret) 22762306a36Sopenharmony_ci virtio_i2c_del_vqs(vdev); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci return ret; 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistatic void virtio_i2c_remove(struct virtio_device *vdev) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci struct virtio_i2c *vi = vdev->priv; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci i2c_del_adapter(&vi->adap); 23762306a36Sopenharmony_ci virtio_i2c_del_vqs(vdev); 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic struct virtio_device_id id_table[] = { 24162306a36Sopenharmony_ci { VIRTIO_ID_I2C_ADAPTER, VIRTIO_DEV_ANY_ID }, 24262306a36Sopenharmony_ci {} 24362306a36Sopenharmony_ci}; 24462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(virtio, id_table); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic int virtio_i2c_freeze(struct virtio_device *vdev) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci virtio_i2c_del_vqs(vdev); 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic int virtio_i2c_restore(struct virtio_device *vdev) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci return virtio_i2c_setup_vqs(vdev->priv); 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic const unsigned int features[] = { 25862306a36Sopenharmony_ci VIRTIO_I2C_F_ZERO_LENGTH_REQUEST, 25962306a36Sopenharmony_ci}; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic struct virtio_driver virtio_i2c_driver = { 26262306a36Sopenharmony_ci .feature_table = features, 26362306a36Sopenharmony_ci .feature_table_size = ARRAY_SIZE(features), 26462306a36Sopenharmony_ci .id_table = id_table, 26562306a36Sopenharmony_ci .probe = virtio_i2c_probe, 26662306a36Sopenharmony_ci .remove = virtio_i2c_remove, 26762306a36Sopenharmony_ci .driver = { 26862306a36Sopenharmony_ci .name = "i2c_virtio", 26962306a36Sopenharmony_ci }, 27062306a36Sopenharmony_ci .freeze = pm_sleep_ptr(virtio_i2c_freeze), 27162306a36Sopenharmony_ci .restore = pm_sleep_ptr(virtio_i2c_restore), 27262306a36Sopenharmony_ci}; 27362306a36Sopenharmony_cimodule_virtio_driver(virtio_i2c_driver); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ciMODULE_AUTHOR("Jie Deng <jie.deng@intel.com>"); 27662306a36Sopenharmony_ciMODULE_AUTHOR("Conghui Chen <conghui.chen@intel.com>"); 27762306a36Sopenharmony_ciMODULE_DESCRIPTION("Virtio i2c bus driver"); 27862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 279