hw/bus: Add write_read function to bus_dev_ops
Bus driver is often used to access devices when
short writes are followed by short reads.
Function to use in such a case bus_node_write_read_transact()
can benefit in same cases about 50% when underlying driver
also supports those write read transactions.
This introduces optional function that allow to build more
robust SPI and I2C transactions.
diff --git a/hw/bus/include/bus/bus_driver.h b/hw/bus/include/bus/bus_driver.h
index c3c77d3..8429ab6 100644
--- a/hw/bus/include/bus/bus_driver.h
+++ b/hw/bus/include/bus/bus_driver.h
@@ -63,6 +63,11 @@
uint16_t length, os_time_t timeout, uint16_t flags);
/* Disable bus device */
int (* disable)(struct bus_dev *bus);
+ /* Write data to node */
+ int (* write_read)(struct bus_dev *dev, struct bus_node *node,
+ const uint8_t *wbuf, uint16_t wlength,
+ uint8_t *rbuf, uint16_t rlength,
+ os_time_t timeout, uint16_t flags);
};
/**
diff --git a/hw/bus/src/bus.c b/hw/bus/src/bus.c
index b7619fc..2998754 100644
--- a/hw/bus/src/bus.c
+++ b/hw/bus/src/bus.c
@@ -420,24 +420,34 @@
goto done;
}
- /*
- * XXX we probably should pass flags here but with some of them stripped,
- * e.g. BUS_F_NOSTOP should not be present here, but since we do not have
- * too many flags now (like we literally have only one flag) let's just pass
- * no flags for now
- */
- BUS_STATS_INC(bdev, bnode, write_ops);
- rc = bdev->dops->write(bdev, bnode, wbuf, wlength, timeout, BUS_F_NOSTOP);
- if (rc) {
- BUS_STATS_INC(bdev, bnode, write_errors);
- goto done;
- }
+ if (bdev->dops->write_read) {
+ BUS_STATS_INC(bdev, bnode, write_ops);
+ BUS_STATS_INC(bdev, bnode, read_ops);
+ rc = bdev->dops->write_read(bdev, bnode, wbuf, wlength, rbuf, rlength, timeout, flags);
+ if (rc) {
+ BUS_STATS_INC(bdev, bnode, write_errors);
+ BUS_STATS_INC(bdev, bnode, read_errors);
+ }
+ } else {
+ /*
+ * XXX we probably should pass flags here but with some of them stripped,
+ * e.g. BUS_F_NOSTOP should not be present here, but since we do not have
+ * too many flags now (like we literally have only one flag) let's just pass
+ * no flags for now
+ */
+ BUS_STATS_INC(bdev, bnode, write_ops);
+ rc = bdev->dops->write(bdev, bnode, wbuf, wlength, timeout, BUS_F_NOSTOP);
+ if (rc) {
+ BUS_STATS_INC(bdev, bnode, write_errors);
+ goto done;
+ }
- BUS_STATS_INC(bdev, bnode, read_ops);
- rc = bdev->dops->read(bdev, bnode, rbuf, rlength, timeout, flags);
- if (rc) {
- BUS_STATS_INC(bdev, bnode, read_errors);
- goto done;
+ BUS_STATS_INC(bdev, bnode, read_ops);
+ rc = bdev->dops->read(bdev, bnode, rbuf, rlength, timeout, flags);
+ if (rc) {
+ BUS_STATS_INC(bdev, bnode, read_errors);
+ goto done;
+ }
}
done: