On 1/12/21 8:47 AM, Arnd Bergmann via Stratos-dev wrote:
On Tue, Jan 12, 2021 at 12:24 PM Bill Mills bill.mills@linaro.org wrote:
On 1/12/21 5:57 AM, Viresh Kumar via Stratos-dev wrote:
On 16-12-20, 14:54, Arnd Bergmann wrote:
I've been staying out of this for a bit but I'll offer a few cents' worth now.
The problem we get into though is once we try to make this work for arbitrary i2c or spi devices. The kernel has around 1400 such drivers, and usually we use a device tree description based on a unique string for every such device plus additional properties for things like gpio lines or out-of-band interrupts.
I think what you're saying is that we already have DT-based drivers for existing hardware, and to abstract them with Greybus would likely require a special Greybus shim or something for every one of those.
If we want to use greybus manifests in place of device trees, that means either needing to find a way to map DT properties into the manifest, or have the same data in another format for each device we might want to use behind greybus, and adapting the corresponding drivers to understand this additional format.
Maybe, maybe not. It depends on what level of abstraction the guest/client needs to represent the device (e.g. i2c or spi).
Greybus assumes the device hardware is on a module and not "directly" accessible by the AP. That is, if the AP wants to send a byte over an I2C device on a module, the only way to do that is by encapsulating that request in a Greybus message. It can't use (say) a register interface to cause the byte to be sent.
In a virtualized environment though, you might *want* to expose a more "raw" interface to the hardware. What I mean is you might want the host/server to grant exclusive access to a guest/client to the register space that controls the actual hardware, avoiding the need for a shim layer (and most likely extra memory copies).
For low speed peripherals that probably isn't critical, but I think it's worth considering whether you want to use the latter approach (exclusively, or in addition to something that abstracts hardware like Greybus does).
Note: these comments are about how the Greybus protocols work; the "raw" approach is different from Greybus in that respect. The *discovery* of devices available to guests is a different issue though, and would be more focused on Greybus *manifests* (or some other mechanism).
I am a bit confused about this. I don't think we need to expose all that information over the manifest.
Viresh is saying that Greybus abstracts the hardware, so there's no need to expose the details. The Greybus driver on the host is the only one that needs to know the DT-like details of specific implementations.
The SPI controller will be accessible by the host OS (lets say both host and guest run Linux), the host will give/pass a manifest to the guest and the guest will send simple commands like read/write to the host. The Guest doesn't need minute details of how the controller is getting programmed, which is the responsibility of the host side controller driver which will have all this information from the DT passed from bootloader anyway. And so the manifest shouldn't be required to have equivalent of all DT properties.
Isn't it ?
Yes for the interrupt for the SPI or I2C controller.
I presume Arnd is talking about side band signals from the devices. I2C and SPI don't have a client side concept of interrupt and the originator side (trying to not use the word master) would have to poll otherwise. So many devices hook up a side band interrupt request to a GPIO. Likewise an I2C EEPROM may have a write protect bit that is controlled by a GPIO.
Coordinating this between a virtual I2C and a virtual GPIO bank would be complicated to do in the manifest if each is a separate device.
I might be misunderstanding here but I *think* in the Greybus case, the details of how all signals (including interrupts) are implemented are the host's responsibility, and do not need to be visible to the guest.
However if we expand the definition of "I2C virtual device" to have an interrupt request line and a couple outputs, the details are in fact on the host side and the guest does not need to understand it all.
Yes, for the Greybus I2C protocol (for example) an interrupt is represented as a message originated from the owner of the "real" hardware directed at the user of the hardware. (From the module to the AP, but in this case it would be from the host to the guest.) So these details would be hidden and abstracted.
What would this mean for the 1400 devices in the kernel? Would we need to add a Greybus binding to the existing DT binding? That sounds like the wrong way. It would be nice to leverage the DT binding that was already in the kernel.
I believe the majority of the devices are fairly simple, and the main thing they need is a character string for identification to work around the lack of a device/vendor ID mechanism that PCI or USB use.
If Greybus protocols are used I think all I2C devices would simply be Greybus I2C devices.
-Alex
The kernel supports three string based identification methods at the moment. Take a minimal wrapper like drivers/iio/imu/bmi160/bmi160_i2c.c as an example, where we have
static const struct i2c_device_id bmi160_i2c_id[] = { {"bmi160", 0}, {} }; MODULE_DEVICE_TABLE(i2c, bmi160_i2c_id);
static const struct acpi_device_id bmi160_acpi_match[] = { {"BMI0160", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match);
#ifdef CONFIG_OF static const struct of_device_id bmi160_of_match[] = { { .compatible = "bosch,bmi160" }, { }, }; MODULE_DEVICE_TABLE(of, bmi160_of_match); #endif
static struct i2c_driver bmi160_i2c_driver = { .driver = { .name = "bmi160_i2c", .acpi_match_table = ACPI_PTR(bmi160_acpi_match), .of_match_table = of_match_ptr(bmi160_of_match), }, .probe = bmi160_i2c_probe, .id_table = bmi160_i2c_id, }; module_i2c_driver(bmi160_i2c_driver);
The "i2c_device_id" structure has a list of strings that is unique in the Linux kernel but not standardized. I assume a greybus driver would be used to map the numbers from the manifest into this OS specific string, but this has to be done for each supported device that can be attached to a greybus device.
The "of_device_id" is a similar list but meant to be globally unique through the DT binding.
I hear that ACPI can bind to SPI and I2C. Is this true and how does that work?? (I ask for a reference. I am NOT suggesting we bring ACPI into this.)
The acpi_device_id has the same purpose as of_device_id, but uses a different namespace and is only used on PC-style machines.
$ git grep -wl "i2c_driver|spi_driver" drivers sound | wc -l 1424 $ git grep -wl "i2c_driver|spi_driver" drivers sound | xargs git grep -l of_device_id | wc -l 876 $ git grep -wl "i2c_driver|spi_driver" drivers sound | xargs git grep -l acpi_device_id | wc -l 145
Arnd
On Fri, Jan 15, 2021 at 1:24 PM Alex Elder elder@linaro.org wrote:
On 1/12/21 8:47 AM, Arnd Bergmann via Stratos-dev wrote:
On Tue, Jan 12, 2021 at 12:24 PM Bill Mills bill.mills@linaro.org wrote:
On 1/12/21 5:57 AM, Viresh Kumar via Stratos-dev wrote:
On 16-12-20, 14:54, Arnd Bergmann wrote:
The problem we get into though is once we try to make this work for arbitrary i2c or spi devices. The kernel has around 1400 such drivers, and usually we use a device tree description based on a unique string for every such device plus additional properties for things like gpio lines or out-of-band interrupts.
I think what you're saying is that we already have DT-based drivers for existing hardware, and to abstract them with Greybus would likely require a special Greybus shim or something for every one of those.
Correct
The SPI controller will be accessible by the host OS (lets say both host and guest run Linux), the host will give/pass a manifest to the guest and the guest will send simple commands like read/write to the host. The Guest doesn't need minute details of how the controller is getting programmed, which is the responsibility of the host side controller driver which will have all this information from the DT passed from bootloader anyway. And so the manifest shouldn't be required to have equivalent of all DT properties.
Isn't it ?
Yes for the interrupt for the SPI or I2C controller.
I presume Arnd is talking about side band signals from the devices. I2C and SPI don't have a client side concept of interrupt and the originator side (trying to not use the word master) would have to poll otherwise. So many devices hook up a side band interrupt request to a GPIO. Likewise an I2C EEPROM may have a write protect bit that is controlled by a GPIO.
Coordinating this between a virtual I2C and a virtual GPIO bank would be complicated to do in the manifest if each is a separate device.
I might be misunderstanding here but I *think* in the Greybus case, the details of how all signals (including interrupts) are implemented are the host's responsibility, and do not need to be visible to the guest.
You need a driver in the guest though that understands the device specific signaling and additional data. Let's look at a moderately complex example I picked at random, drivers/leds/leds-lp8501.c:
I assume the idea would be to not replace the entire driver with a greybus specific one, but to reused as much as possible from the existing code. The driver has no interrupts but it needs to access a gpio line and some device specific configuration data, which it can get either from a platform_data or from DT properties.
Passing such a device through greybus then requires at least these steps:
* allocate a unique device:vendor ID pair * create a lp8501 specific manifest binding for that ID * for the host, create an lp8501 specific greybus host driver to - read the device tree in the host, convert into manifest format according to the binding - open the raw i2c device and gpio line from user space - create virtual devices for these two, describe them in the manifest * for the guest, create an lp8501 greybus device driver for the vendor:device ID pair, to - interpret the manifest, convert data into lp55xx_platform_data - instantiate a gpio controller with one gpio line, - allocate a gpio number for that controller, add it to the platform data - instantiate a i2c host - instantiate a i2c device on that host, using the platform_data and the "lp8501" i2c_device_id string.
If a device has no DT properties or platform_data, and no gpio, reset, regulator, clock, or other dependendencies, some of the steps can be skipped, but at the minimum you still need device specific code in the guest to map the vendor:device ID to an i2c_device_id.
Arnd
stratos-dev@op-lists.linaro.org