qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC PATCH v2 4/6] hw/i2c: add asynchronous send


From: Corey Minyard
Subject: Re: [RFC PATCH v2 4/6] hw/i2c: add asynchronous send
Date: Wed, 1 Jun 2022 17:05:21 -0500

On Wed, Jun 01, 2022 at 11:08:29PM +0200, Klaus Jensen wrote:
> From: Klaus Jensen <k.jensen@samsung.com>
> 
> Add an asynchronous version of i2c_send() that requires the slave to
> explicitly acknowledge on the bus with i2c_ack().
> 
> The current master must use the new i2c_start_send_async() to indicate
> that it wants to do an asynchronous transfer. This allows the i2c core
> to check if the target slave supports this or not. This approach relies
> on adding a new enum i2c_event member, which is why a bunch of other
> devices needs changes in their event handling switches.

This would be easier to read if you split out the default return of -1
in all the devices to a separate patch.

You've already pointed out the lack of nack support.

I think this is ok outside of that.

-corey

> 
> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
> ---
>  hw/arm/pxa2xx.c            |  2 ++
>  hw/display/sii9022.c       |  2 ++
>  hw/display/ssd0303.c       |  2 ++
>  hw/i2c/core.c              | 36 +++++++++++++++++++++++++++++++++++-
>  hw/i2c/smbus_slave.c       |  4 ++++
>  hw/i2c/trace-events        |  2 ++
>  hw/misc/ibm-cffps.c        |  2 ++
>  hw/misc/ir35221.c          |  2 ++
>  hw/nvram/eeprom_at24c.c    |  2 ++
>  hw/sensor/lsm303dlhc_mag.c |  2 ++
>  include/hw/i2c/i2c.h       | 16 ++++++++++++++++
>  11 files changed, 71 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
> index f4f687df68ef..93dda83d7aa9 100644
> --- a/hw/arm/pxa2xx.c
> +++ b/hw/arm/pxa2xx.c
> @@ -1305,6 +1305,8 @@ static int pxa2xx_i2c_event(I2CSlave *i2c, enum 
> i2c_event event)
>      case I2C_NACK:
>          s->status |= 1 << 1;                         /* set ACKNAK */
>          break;
> +    default:
> +        return -1;
>      }
>      pxa2xx_i2c_update(s);
>  
> diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c
> index b591a5878901..664fd4046d82 100644
> --- a/hw/display/sii9022.c
> +++ b/hw/display/sii9022.c
> @@ -76,6 +76,8 @@ static int sii9022_event(I2CSlave *i2c, enum i2c_event 
> event)
>          break;
>      case I2C_NACK:
>          break;
> +    default:
> +        return -1;
>      }
>  
>      return 0;
> diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c
> index aeae22da9c29..d67b0ad7b529 100644
> --- a/hw/display/ssd0303.c
> +++ b/hw/display/ssd0303.c
> @@ -196,6 +196,8 @@ static int ssd0303_event(I2CSlave *i2c, enum i2c_event 
> event)
>      case I2C_NACK:
>          /* Nothing to do.  */
>          break;
> +    default:
> +        return -1;
>      }
>  
>      return 0;
> diff --git a/hw/i2c/core.c b/hw/i2c/core.c
> index 145dce60782a..d4ba8146bffb 100644
> --- a/hw/i2c/core.c
> +++ b/hw/i2c/core.c
> @@ -161,7 +161,8 @@ static int i2c_do_start_transfer(I2CBus *bus, uint8_t 
> address,
>             start condition.  */
>  
>          if (sc->event) {
> -            trace_i2c_event("start", s->address);
> +            trace_i2c_event(event == I2C_START_SEND ? "start" : 
> "start_async",
> +                            s->address);
>              rv = sc->event(s, event);
>              if (rv && !bus->broadcast) {
>                  if (bus_scanned) {
> @@ -212,6 +213,11 @@ int i2c_start_send(I2CBus *bus, uint8_t address)
>      return i2c_do_start_transfer(bus, address, I2C_START_SEND);
>  }
>  
> +int i2c_start_send_async(I2CBus *bus, uint8_t address)
> +{
> +    return i2c_do_start_transfer(bus, address, I2C_START_SEND_ASYNC);
> +}
> +
>  void i2c_end_transfer(I2CBus *bus)
>  {
>      I2CSlaveClass *sc;
> @@ -261,6 +267,23 @@ int i2c_send(I2CBus *bus, uint8_t data)
>      return ret ? -1 : 0;
>  }
>  
> +int i2c_send_async(I2CBus *bus, uint8_t data)
> +{
> +    I2CNode *node = QLIST_FIRST(&bus->current_devs);
> +    I2CSlave *slave = node->elt;
> +    I2CSlaveClass *sc = I2C_SLAVE_GET_CLASS(slave);
> +
> +    if (!sc->send_async) {
> +        return -1;
> +    }
> +
> +    trace_i2c_send_async(slave->address, data);
> +
> +    sc->send_async(slave, data);
> +
> +    return 0;
> +}
> +
>  uint8_t i2c_recv(I2CBus *bus)
>  {
>      uint8_t data = 0xff;
> @@ -297,6 +320,17 @@ void i2c_nack(I2CBus *bus)
>      }
>  }
>  
> +void i2c_ack(I2CBus *bus)
> +{
> +    if (!bus->bh) {
> +        return;
> +    }
> +
> +    trace_i2c_ack();
> +
> +    qemu_bh_schedule(bus->bh);
> +}
> +
>  static int i2c_slave_post_load(void *opaque, int version_id)
>  {
>      I2CSlave *dev = opaque;
> diff --git a/hw/i2c/smbus_slave.c b/hw/i2c/smbus_slave.c
> index 5d10e27664db..feb3ec633350 100644
> --- a/hw/i2c/smbus_slave.c
> +++ b/hw/i2c/smbus_slave.c
> @@ -143,6 +143,10 @@ static int smbus_i2c_event(I2CSlave *s, enum i2c_event 
> event)
>              dev->mode = SMBUS_CONFUSED;
>              break;
>          }
> +        break;
> +
> +    default:
> +        return -1;
>      }
>  
>      return 0;
> diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
> index 209275ed2dc8..af181d43ee64 100644
> --- a/hw/i2c/trace-events
> +++ b/hw/i2c/trace-events
> @@ -4,7 +4,9 @@
>  
>  i2c_event(const char *event, uint8_t address) "%s(addr:0x%02x)"
>  i2c_send(uint8_t address, uint8_t data) "send(addr:0x%02x) data:0x%02x"
> +i2c_send_async(uint8_t address, uint8_t data) "send_async(addr:0x%02x) 
> data:0x%02x"
>  i2c_recv(uint8_t address, uint8_t data) "recv(addr:0x%02x) data:0x%02x"
> +i2c_ack(void) ""
>  
>  # aspeed_i2c.c
>  
> diff --git a/hw/misc/ibm-cffps.c b/hw/misc/ibm-cffps.c
> index 042155bb7838..d69a727fd5f9 100644
> --- a/hw/misc/ibm-cffps.c
> +++ b/hw/misc/ibm-cffps.c
> @@ -152,6 +152,8 @@ static int ibm_cffps_event(I2CSlave *i2c, enum i2c_event 
> event)
>      case I2C_FINISH:
>           s->pointer = 0xFF;
>          break;
> +    default:
> +        return -1;
>      }
>  
>      s->len = 0;
> diff --git a/hw/misc/ir35221.c b/hw/misc/ir35221.c
> index 5e01d3655059..c46b9ee1c3bf 100644
> --- a/hw/misc/ir35221.c
> +++ b/hw/misc/ir35221.c
> @@ -117,6 +117,8 @@ static int ir35221_event(I2CSlave *i2c, enum i2c_event 
> event)
>      case I2C_FINISH:
>           s->pointer = 0xFF;
>          break;
> +    default:
> +        return -1;
>      }
>  
>      s->len = 0;
> diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c
> index 01a3093600fa..d695f6ae894a 100644
> --- a/hw/nvram/eeprom_at24c.c
> +++ b/hw/nvram/eeprom_at24c.c
> @@ -75,6 +75,8 @@ int at24c_eeprom_event(I2CSlave *s, enum i2c_event event)
>          break;
>      case I2C_NACK:
>          break;
> +    default:
> +        return -1;
>      }
>      return 0;
>  }
> diff --git a/hw/sensor/lsm303dlhc_mag.c b/hw/sensor/lsm303dlhc_mag.c
> index 4c98ddbf207c..bb8d48b2fdb0 100644
> --- a/hw/sensor/lsm303dlhc_mag.c
> +++ b/hw/sensor/lsm303dlhc_mag.c
> @@ -427,6 +427,8 @@ static int lsm303dlhc_mag_event(I2CSlave *i2c, enum 
> i2c_event event)
>          break;
>      case I2C_NACK:
>          break;
> +    default:
> +        return -1;
>      }
>  
>      s->len = 0;
> diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
> index be8bb8b78a60..9b9581d23097 100644
> --- a/include/hw/i2c/i2c.h
> +++ b/include/hw/i2c/i2c.h
> @@ -12,6 +12,7 @@
>  enum i2c_event {
>      I2C_START_RECV,
>      I2C_START_SEND,
> +    I2C_START_SEND_ASYNC,
>      I2C_FINISH,
>      I2C_NACK /* Masker NACKed a receive byte.  */
>  };
> @@ -28,6 +29,9 @@ struct I2CSlaveClass {
>      /* Master to slave. Returns non-zero for a NAK, 0 for success. */
>      int (*send)(I2CSlave *s, uint8_t data);
>  
> +    /* Master to slave (asynchronous). Receiving slave must call i2c_ack(). 
> */
> +    void (*send_async)(I2CSlave *s, uint8_t data);
> +
>      /*
>       * Slave to master.  This cannot fail, the device should always
>       * return something here.
> @@ -127,11 +131,23 @@ int i2c_start_recv(I2CBus *bus, uint8_t address);
>   */
>  int i2c_start_send(I2CBus *bus, uint8_t address);
>  
> +/**
> + * i2c_start_send_async: start an asynchronous 'send' transfer on an I2C bus.
> + *
> + * @bus: #I2CBus to be used
> + * @address: address of the slave
> + *
> + * Return: 0 on success, -1 on error
> + */
> +int i2c_start_send_async(I2CBus *bus, uint8_t address);
> +
>  void i2c_end_transfer(I2CBus *bus);
>  void i2c_nack(I2CBus *bus);
> +void i2c_ack(I2CBus *bus);
>  void i2c_bus_master(I2CBus *bus, QEMUBH *bh);
>  void i2c_bus_release(I2CBus *bus);
>  int i2c_send(I2CBus *bus, uint8_t data);
> +int i2c_send_async(I2CBus *bus, uint8_t data);
>  uint8_t i2c_recv(I2CBus *bus);
>  bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast,
>                    I2CNodeList *current_devs);
> -- 
> 2.36.1
> 

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]