Re: Trying to write data to i2c bus

2024-02-25 Thread Paz Offer
Thank you Corey,


  *   You can look at the git commits in hw/i2c around 37fa5ca42623 "hw/i2c:
support multiple masters" for the changes that were done to support
this.


I saw a very good presentation in youtube about implementing i2c multi-master 
(I2C Multi-master and Controller Slave Mode in QEMU).
I noticed that the commit you referred me to was implemented by the same person 
from the presentation πŸ™‚.

Would you know if there was any example that was done at the time to test this 
new capability?
Maybe one that was used for the creation of the presentation?   [adding Mr. 
Jensen]

Context:
I implemented i2c-slave device, and now I want to use the bus to send 
information back, so my side will function as a master.
Will help me if I can see a small example that does this.

Thanks,
Paz


From: Corey Minyard  on behalf of Corey Minyard 

Sent: Monday, February 19, 2024 7:14 PM
To: Paz Offer 
Cc: qemu-devel@nongnu.org 
Subject: Re: Trying to write data to i2c bus

External email: Use caution opening links or attachments


On Mon, Feb 19, 2024 at 04:53:47PM +, Paz Offer wrote:
> Thank you very much Corey,
>
> I am simulating an external module that wants to communicate with the board 
> management controller (BMC).
> The real device will be connected to the board using i2c bus, and could 
> initiate communication at any time, by sending bytes over the bus.

And you have a simulated BMC that can do this?  Or is the system running
in qemu the BMC.

>
> I am not sure whether the 'Master-side' (the side the initiating 
> communication) needs to simulate a full i2c-master device, or whether my code 
> could 'simply' write directly to the appropriate registers of the guest OS.
> Are there some examples or documentation on how to implement something like 
> this?

The aspeed i2c controller is capable of having another bus master on an
I2C but, but it is the only host that can currently do it.

It is doable, the code is ther for multiple bus masters, but there is no
device currently that does it.  I assume that is coming at some point,
but no documentation exists on how to do it.

You can look at the git commits in hw/i2c around 37fa5ca42623 "hw/i2c:
support multiple masters" for the changes that were done to support
this.

I haven't done it, and I don't remember exactly how it works.

>
> Sorry for my lacking knowledge on this, but I am quite new to QEMU...

You have a lot more to learn than this to make a qemu device.  And i2c
bus mastering in qemu is pretty esoteric, not many people know anything
about it.

-corey

>
> Thanks again,
> Paz
>
>
>
>
> 
> From: Corey Minyard  on behalf of Corey Minyard 
> 
> Sent: Monday, February 19, 2024 6:32 PM
> To: Paz Offer 
> Cc: qemu-devel@nongnu.org 
> Subject: Re: Trying to write data to i2c bus
>
> External email: Use caution opening links or attachments
>
>
> On Mon, Feb 19, 2024 at 01:49:44PM +, Paz Offer wrote:
> > Hi,
> >
> > I am new to QEMU development, so please excuse if I my direction here is 
> > wrong:
> >
> > I am trying to implement an i2c slave device.
> > My device should be able to read/write data from its i2c bus.
> >
> > I defined my device-state object like so:
> >
> > typedef struct {
> >   I2CSlave i2c;
> >   void *my_data;
> >
> > }   MyI2CSlave;
> >
> >
> > In my implementation occasionally I may have to send data on the bus, due 
> > to an internal event on my side.
> > For this I implemented the following code:
> >
> > //  Get bus pointer:
> > BusState *parentBus = qdev_get_parent_bus(DEVICE(&obj->i2c));
> > I2CBus   *i2cBus= I2C_BUS(parentBus);
> >   
> > //  Try to send data on bus:  
> > if (i2c_start_send(i2cBus, address)) {
> > //  error?
> > return;
> > }
> > for (int i = 0; i < size; i++) {
> > i2c_send(i2cBus, data[i]);
> > }
> > i2c_end_transfer(i2cBus);
> >
> >   
> > The problem is that 'i2c_start_send()' always fails here:
> >
> > if (QLIST_EMPTY(&bus->current_devs)) {
> > return 1;
> > }
> >
> > The member 'i2cBus->current_devs.lh_first' is always null.
> >
> > I will add that in my QEMU execution I specify the bus 'aspeed.i2c.bus.0' 
> > to be used with my device.
> > In my 'realize' method I can see that a bus is connected to my device, as 
> > 'qdev_get_parent_bus()' does return a valid pointer.
> >
> > My question:
> > 1. Am 

Re: Trying to write data to i2c bus

2024-02-19 Thread CΓ©dric Le Goater

On 2/19/24 18:14, Corey Minyard wrote:

On Mon, Feb 19, 2024 at 04:53:47PM +, Paz Offer wrote:

Thank you very much Corey,

I am simulating an external module that wants to communicate with the board 
management controller (BMC).
The real device will be connected to the board using i2c bus, and could 
initiate communication at any time, by sending bytes over the bus.


And you have a simulated BMC that can do this?  Or is the system running
in qemu the BMC.



I am not sure whether the 'Master-side' (the side the initiating communication) 
needs to simulate a full i2c-master device, or whether my code could 'simply' 
write directly to the appropriate registers of the guest OS.
Are there some examples or documentation on how to implement something like 
this?


The aspeed i2c controller is capable of having another bus master on an
I2C but, but it is the only host that can currently do it.

It is doable, the code is ther for multiple bus masters, but there is no
device currently that does it.  I assume that is coming at some point,
but no documentation exists on how to do it.

You can look at the git commits in hw/i2c around 37fa5ca42623 "hw/i2c:
support multiple masters" for the changes that were done to support
this.



There is an i2c-echo device implementing an I2C slave  and a test,
test_arm_ast2600_evb_buildroot in tests/avocado/ machine_aspeed.py,
using it on the ast2600-evb.


Thanks,

C.






Re: Trying to write data to i2c bus

2024-02-19 Thread Corey Minyard
On Mon, Feb 19, 2024 at 04:53:47PM +, Paz Offer wrote:
> Thank you very much Corey,
> 
> I am simulating an external module that wants to communicate with the board 
> management controller (BMC).
> The real device will be connected to the board using i2c bus, and could 
> initiate communication at any time, by sending bytes over the bus.

And you have a simulated BMC that can do this?  Or is the system running
in qemu the BMC.

> 
> I am not sure whether the 'Master-side' (the side the initiating 
> communication) needs to simulate a full i2c-master device, or whether my code 
> could 'simply' write directly to the appropriate registers of the guest OS.
> Are there some examples or documentation on how to implement something like 
> this?

The aspeed i2c controller is capable of having another bus master on an
I2C but, but it is the only host that can currently do it.

It is doable, the code is ther for multiple bus masters, but there is no
device currently that does it.  I assume that is coming at some point,
but no documentation exists on how to do it.

You can look at the git commits in hw/i2c around 37fa5ca42623 "hw/i2c:
support multiple masters" for the changes that were done to support
this.

I haven't done it, and I don't remember exactly how it works.

> 
> Sorry for my lacking knowledge on this, but I am quite new to QEMU...

You have a lot more to learn than this to make a qemu device.  And i2c
bus mastering in qemu is pretty esoteric, not many people know anything
about it.

-corey

> 
> Thanks again,
> Paz
> 
> 
> 
> 
> 
> From: Corey Minyard  on behalf of Corey Minyard 
> 
> Sent: Monday, February 19, 2024 6:32 PM
> To: Paz Offer 
> Cc: qemu-devel@nongnu.org 
> Subject: Re: Trying to write data to i2c bus
> 
> External email: Use caution opening links or attachments
> 
> 
> On Mon, Feb 19, 2024 at 01:49:44PM +, Paz Offer wrote:
> > Hi,
> >
> > I am new to QEMU development, so please excuse if I my direction here is 
> > wrong:
> >
> > I am trying to implement an i2c slave device.
> > My device should be able to read/write data from its i2c bus.
> >
> > I defined my device-state object like so:
> >
> > typedef struct {
> >   I2CSlave i2c;
> >   void *my_data;
> >
> > }   MyI2CSlave;
> >
> >
> > In my implementation occasionally I may have to send data on the bus, due 
> > to an internal event on my side.
> > For this I implemented the following code:
> >
> > //  Get bus pointer:
> > BusState *parentBus = qdev_get_parent_bus(DEVICE(&obj->i2c));
> > I2CBus   *i2cBus= I2C_BUS(parentBus);
> >   
> > //  Try to send data on bus:  
> > if (i2c_start_send(i2cBus, address)) {
> > //  error?
> > return;
> > }
> > for (int i = 0; i < size; i++) {
> > i2c_send(i2cBus, data[i]);
> > }
> > i2c_end_transfer(i2cBus);
> >
> >   
> > The problem is that 'i2c_start_send()' always fails here:
> >
> > if (QLIST_EMPTY(&bus->current_devs)) {
> > return 1;
> > }
> >
> > The member 'i2cBus->current_devs.lh_first' is always null.
> >
> > I will add that in my QEMU execution I specify the bus 'aspeed.i2c.bus.0' 
> > to be used with my device.
> > In my 'realize' method I can see that a bus is connected to my device, as 
> > 'qdev_get_parent_bus()' does return a valid pointer.
> >
> > My question:
> > 1. Am I missing some initialization for the bus?
> > 2. Is there other way to send data on the i2c bus, assuming it can happen 
> > anytime due to an internal event on my device side?
> 
> You are missing a lot of stuff, but let's start with basics...
> 
> First of all, this is not how i2c generally works.  Generally you have a
> bus master, the host, that reads and writes to slave devices on the bus.
> The devices on the bus don't asynchronously send data to the host.
> 
> That said, you can have multiple bus masters on the bus.  If that's what
> you are doing, what are you sending your data to?  You have to have
> something that will receive it.
> 
> If you have some slave device that has data it's holding for the host,
> the host has to fetch it.  You could have an interrupt that comes from
> the slave device saying it has data, and there's something called SMBus
> alert that can consolidate interrupts (though it's not implemented in
> QEMU at the moment).
> 
> Are you simulating some real device here?
> 
> -corey
> 
> >
> > Thanks for any tip,
> > Pazo  



Re: Trying to write data to i2c bus

2024-02-19 Thread Paz Offer
Thank you very much Corey,

I am simulating an external module that wants to communicate with the board 
management controller (BMC).
The real device will be connected to the board using i2c bus, and could 
initiate communication at any time, by sending bytes over the bus.

I am not sure whether the 'Master-side' (the side the initiating communication) 
needs to simulate a full i2c-master device, or whether my code could 'simply' 
write directly to the appropriate registers of the guest OS.
Are there some examples or documentation on how to implement something like 
this?

Sorry for my lacking knowledge on this, but I am quite new to QEMU...

Thanks again,
Paz





From: Corey Minyard  on behalf of Corey Minyard 

Sent: Monday, February 19, 2024 6:32 PM
To: Paz Offer 
Cc: qemu-devel@nongnu.org 
Subject: Re: Trying to write data to i2c bus

External email: Use caution opening links or attachments


On Mon, Feb 19, 2024 at 01:49:44PM +, Paz Offer wrote:
> Hi,
>
> I am new to QEMU development, so please excuse if I my direction here is 
> wrong:
>
> I am trying to implement an i2c slave device.
> My device should be able to read/write data from its i2c bus.
>
> I defined my device-state object like so:
>
> typedef struct {
>   I2CSlave i2c;
>   void *my_data;
>
> }   MyI2CSlave;
>
>
> In my implementation occasionally I may have to send data on the bus, due to 
> an internal event on my side.
> For this I implemented the following code:
>
> //  Get bus pointer:
> BusState *parentBus = qdev_get_parent_bus(DEVICE(&obj->i2c));
> I2CBus   *i2cBus= I2C_BUS(parentBus);
>   
> //  Try to send data on bus:  
> if (i2c_start_send(i2cBus, address)) {
> //  error?
> return;
> }
> for (int i = 0; i < size; i++) {
> i2c_send(i2cBus, data[i]);
> }
> i2c_end_transfer(i2cBus);
>
>   
> The problem is that 'i2c_start_send()' always fails here:
>
> if (QLIST_EMPTY(&bus->current_devs)) {
> return 1;
> }
>
> The member 'i2cBus->current_devs.lh_first' is always null.
>
> I will add that in my QEMU execution I specify the bus 'aspeed.i2c.bus.0' to 
> be used with my device.
> In my 'realize' method I can see that a bus is connected to my device, as 
> 'qdev_get_parent_bus()' does return a valid pointer.
>
> My question:
> 1. Am I missing some initialization for the bus?
> 2. Is there other way to send data on the i2c bus, assuming it can happen 
> anytime due to an internal event on my device side?

You are missing a lot of stuff, but let's start with basics...

First of all, this is not how i2c generally works.  Generally you have a
bus master, the host, that reads and writes to slave devices on the bus.
The devices on the bus don't asynchronously send data to the host.

That said, you can have multiple bus masters on the bus.  If that's what
you are doing, what are you sending your data to?  You have to have
something that will receive it.

If you have some slave device that has data it's holding for the host,
the host has to fetch it.  You could have an interrupt that comes from
the slave device saying it has data, and there's something called SMBus
alert that can consolidate interrupts (though it's not implemented in
QEMU at the moment).

Are you simulating some real device here?

-corey

>
> Thanks for any tip,
> Pazo  


Re: Trying to write data to i2c bus

2024-02-19 Thread Corey Minyard
On Mon, Feb 19, 2024 at 01:49:44PM +, Paz Offer wrote:
> Hi,
> 
> I am new to QEMU development, so please excuse if I my direction here is 
> wrong:
> 
> I am trying to implement an i2c slave device.
> My device should be able to read/write data from its i2c bus.
> 
> I defined my device-state object like so:
> 
> typedef struct {
>   I2CSlave i2c;
>   void *my_data;
> 
> }   MyI2CSlave;
> 
> 
> In my implementation occasionally I may have to send data on the bus, due to 
> an internal event on my side.
> For this I implemented the following code:
> 
> //  Get bus pointer:
> BusState *parentBus = qdev_get_parent_bus(DEVICE(&obj->i2c));
> I2CBus   *i2cBus= I2C_BUS(parentBus);
>   
> //  Try to send data on bus:  
> if (i2c_start_send(i2cBus, address)) {
> //  error?
> return;
> }
> for (int i = 0; i < size; i++) {
> i2c_send(i2cBus, data[i]);
> }
> i2c_end_transfer(i2cBus);
> 
>   
> The problem is that 'i2c_start_send()' always fails here:
> 
> if (QLIST_EMPTY(&bus->current_devs)) {
> return 1;
> }
> 
> The member 'i2cBus->current_devs.lh_first' is always null.
> 
> I will add that in my QEMU execution I specify the bus 'aspeed.i2c.bus.0' to 
> be used with my device.
> In my 'realize' method I can see that a bus is connected to my device, as 
> 'qdev_get_parent_bus()' does return a valid pointer.
> 
> My question:
> 1. Am I missing some initialization for the bus?
> 2. Is there other way to send data on the i2c bus, assuming it can happen 
> anytime due to an internal event on my device side?

You are missing a lot of stuff, but let's start with basics...

First of all, this is not how i2c generally works.  Generally you have a
bus master, the host, that reads and writes to slave devices on the bus.
The devices on the bus don't asynchronously send data to the host.

That said, you can have multiple bus masters on the bus.  If that's what
you are doing, what are you sending your data to?  You have to have
something that will receive it.

If you have some slave device that has data it's holding for the host,
the host has to fetch it.  You could have an interrupt that comes from
the slave device saying it has data, and there's something called SMBus
alert that can consolidate interrupts (though it's not implemented in
QEMU at the moment).

Are you simulating some real device here?

-corey

> 
> Thanks for any tip,
> Pazo  



Trying to write data to i2c bus

2024-02-19 Thread Paz Offer
Hi,

I am new to QEMU development, so please excuse if I my direction here is wrong:

I am trying to implement an i2c slave device.
My device should be able to read/write data from its i2c bus.

I defined my device-state object like so:

typedef struct {
  I2CSlave i2c;
  void *my_data;

}   MyI2CSlave;


In my implementation occasionally I may have to send data on the bus, due to an 
internal event on my side.
For this I implemented the following code:

//  Get bus pointer:
BusState *parentBus = qdev_get_parent_bus(DEVICE(&obj->i2c));
I2CBus   *i2cBus= I2C_BUS(parentBus);
  
//  Try to send data on bus:  
if (i2c_start_send(i2cBus, address)) {
//  error?
return;
}
for (int i = 0; i < size; i++) {
i2c_send(i2cBus, data[i]);
}
i2c_end_transfer(i2cBus);

  
The problem is that 'i2c_start_send()' always fails here:

if (QLIST_EMPTY(&bus->current_devs)) {
return 1;
}

The member 'i2cBus->current_devs.lh_first' is always null.

I will add that in my QEMU execution I specify the bus 'aspeed.i2c.bus.0' to be 
used with my device.
In my 'realize' method I can see that a bus is connected to my device, as 
'qdev_get_parent_bus()' does return a valid pointer.

My question:
1. Am I missing some initialization for the bus?
2. Is there other way to send data on the i2c bus, assuming it can happen 
anytime due to an internal event on my device side?

Thanks for any tip,
Pazo