[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC PATCH v2 3/6] hw/i2c: support multiple masters
From: |
Corey Minyard |
Subject: |
Re: [RFC PATCH v2 3/6] hw/i2c: support multiple masters |
Date: |
Wed, 1 Jun 2022 17:00:55 -0500 |
On Wed, Jun 01, 2022 at 11:08:28PM +0200, Klaus Jensen wrote:
> From: Klaus Jensen <k.jensen@samsung.com>
>
> Allow slaves to master the bus by registering a bottom halve. If the bus
> is busy, the bottom halve is queued up. When a slave has succesfully
^ half
> mastered the bus, the bottom halve is scheduled.
^ half
"halve" is a verb that means to split something into two pieces. Yes,
English is a strange language :).
Also, technically from an I2C point of view, masters master the bus and
slaves only respond. The way it's phrased here and elsewhere sounds a
little strange from that point of view.
I'm ok with this patch. It's straightforward.
>
> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
> ---
> hw/i2c/core.c | 34 +++++++++++++++++++++++++++++++++-
> include/hw/i2c/i2c.h | 14 ++++++++++++++
> 2 files changed, 47 insertions(+), 1 deletion(-)
>
> diff --git a/hw/i2c/core.c b/hw/i2c/core.c
> index d0cb2d32fa44..145dce60782a 100644
> --- a/hw/i2c/core.c
> +++ b/hw/i2c/core.c
> @@ -13,6 +13,7 @@
> #include "migration/vmstate.h"
> #include "qapi/error.h"
> #include "qemu/module.h"
> +#include "qemu/main-loop.h"
> #include "trace.h"
>
> #define I2C_BROADCAST 0x00
> @@ -62,6 +63,7 @@ I2CBus *i2c_init_bus(DeviceState *parent, const char *name)
>
> bus = I2C_BUS(qbus_new(TYPE_I2C_BUS, parent, name));
> QLIST_INIT(&bus->current_devs);
> + QSIMPLEQ_INIT(&bus->pending_masters);
> vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_i2c_bus, bus);
> return bus;
> }
> @@ -74,7 +76,7 @@ void i2c_slave_set_address(I2CSlave *dev, uint8_t address)
> /* Return nonzero if bus is busy. */
> int i2c_bus_busy(I2CBus *bus)
> {
> - return !QLIST_EMPTY(&bus->current_devs);
> + return !QLIST_EMPTY(&bus->current_devs) || bus->bh;
> }
>
> bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast,
> @@ -180,6 +182,26 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address,
> bool is_recv)
> : I2C_START_SEND);
> }
>
> +void i2c_bus_master(I2CBus *bus, QEMUBH *bh)
> +{
> + if (i2c_bus_busy(bus)) {
> + I2CPendingMaster *node = g_new(struct I2CPendingMaster, 1);
> + node->bh = bh;
> +
> + QSIMPLEQ_INSERT_TAIL(&bus->pending_masters, node, entry);
> +
> + return;
> + }
> +
> + bus->bh = bh;
> + qemu_bh_schedule(bus->bh);
> +}
> +
> +void i2c_bus_release(I2CBus *bus)
> +{
> + bus->bh = NULL;
> +}
> +
> int i2c_start_recv(I2CBus *bus, uint8_t address)
> {
> return i2c_do_start_transfer(bus, address, I2C_START_RECV);
> @@ -206,6 +228,16 @@ void i2c_end_transfer(I2CBus *bus)
> g_free(node);
> }
> bus->broadcast = false;
> +
> + if (!QSIMPLEQ_EMPTY(&bus->pending_masters)) {
> + I2CPendingMaster *node = QSIMPLEQ_FIRST(&bus->pending_masters);
> + bus->bh = node->bh;
> +
> + QSIMPLEQ_REMOVE_HEAD(&bus->pending_masters, entry);
> + g_free(node);
> +
> + qemu_bh_schedule(bus->bh);
> + }
> }
>
> int i2c_send(I2CBus *bus, uint8_t data)
> diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
> index 5ca3b708c0be..be8bb8b78a60 100644
> --- a/include/hw/i2c/i2c.h
> +++ b/include/hw/i2c/i2c.h
> @@ -69,13 +69,25 @@ struct I2CNode {
> QLIST_ENTRY(I2CNode) next;
> };
>
> +typedef struct I2CPendingMaster I2CPendingMaster;
> +
> +struct I2CPendingMaster {
> + QEMUBH *bh;
> + QSIMPLEQ_ENTRY(I2CPendingMaster) entry;
> +};
> +
> typedef QLIST_HEAD(I2CNodeList, I2CNode) I2CNodeList;
> +typedef QSIMPLEQ_HEAD(I2CPendingMasters, I2CPendingMaster) I2CPendingMasters;
>
> struct I2CBus {
> BusState qbus;
> I2CNodeList current_devs;
> + I2CPendingMasters pending_masters;
> uint8_t saved_address;
> bool broadcast;
> +
> + /* Set from slave currently mastering the bus. */
> + QEMUBH *bh;
> };
>
> I2CBus *i2c_init_bus(DeviceState *parent, const char *name);
> @@ -117,6 +129,8 @@ int i2c_start_send(I2CBus *bus, uint8_t address);
>
> void i2c_end_transfer(I2CBus *bus);
> void i2c_nack(I2CBus *bus);
> +void i2c_bus_master(I2CBus *bus, QEMUBH *bh);
> +void i2c_bus_release(I2CBus *bus);
> int i2c_send(I2CBus *bus, uint8_t data);
> uint8_t i2c_recv(I2CBus *bus);
> bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast,
> --
> 2.36.1
>
smime.p7s
Description: S/MIME Cryptographic Signature