Difference between revisions of "Mikrobus"

From eLinux.org
Jump to: navigation, search
(Run-time device tree overlays)
(Fix RFC Patch URL)
 
(37 intermediate revisions by 2 users not shown)
Line 4: Line 4:
  
 
== Usage of mikroBUS compatible add-on boards today ==
 
== Usage of mikroBUS compatible add-on boards today ==
 +
Many drivers for mikroBUS add-on boards already exist in the kernel<ref>[[MikroEClicks with Linux Support]]</ref>, but using them can be a challenge. The most straight-forward method for loading existing drivers is to provide device tree overlay fragments at boot time, which is reasonably supported by mainline Linux. There are some out-of-tree efforts to load device tree overlay fragments at run time or to use the Greybus simulator to generate new instances of the embedded buses used on a mikroBUS socket.
  
 
=== Device tree overlays loaded at boot time ===
 
=== Device tree overlays loaded at boot time ===
Today, there is no mainline solution for enabling mikroBUS add-on boards at run-time, so they must all be configured at boot-time with device-tree.
+
Today, there is no mainline solution for enabling mikroBUS add-on boards at run-time, so they must all be configured at boot-time with device trees<ref group="definitions">[https://elinux.org/Device_Tree_Reference Device tree] is a data structure describing the hardware components of a particular computer so that the operating system's kernel can use and manage those components. See [[Device_Tree_Reference]].</ref>.
  
 
Instructions for PocketBeagle: https://github.com/beagleboard/pocketbeagle/wiki/Click-boards%E2%84%A2
 
Instructions for PocketBeagle: https://github.com/beagleboard/pocketbeagle/wiki/Click-boards%E2%84%A2
Line 12: Line 13:
 
Example overlay: https://github.com/beagleboard/bb.org-overlays/blob/master/src/arm/PB-I2C2-MPU-9DOF-CLICK.dts
 
Example overlay: https://github.com/beagleboard/bb.org-overlays/blob/master/src/arm/PB-I2C2-MPU-9DOF-CLICK.dts
  
This is the primary mechanism for enumerating device drivers for mikroBUS add-on boards today. It suffers from the need to maintain a large out-of-tree database for which you'd need an overlay for every mikroBUS add-on board for every Linux system for every mikroBUS socket on that system. Multiplying 1,000 Click boards by the number of BeagleBoard.org boards by the number of sockets supported on each of those boards ends up being a LOT of device tree overlay fragments.
+
This is the primary mechanism for enumerating device drivers<ref group="definitions">[https://www.tldp.org/LDP/tlk/dd/drivers.html Device Driver] is a software that handles or manages a hardware controller.</ref> for mikroBUS add-on boards today. It suffers from the need to maintain a large out-of-tree database for which you'd need an overlay for every mikroBUS add-on board for every Linux system for every mikroBUS socket on that system. Multiplying 1,000 Click boards by the number of BeagleBoard.org boards by the number of sockets supported on each of those boards ends up being a LOT of device tree overlay fragments.
  
Further, the application of those fragments is rather error prone and can even result in preventing a system from booting.
+
Further, the application of those fragments is rather error-prone and can even result in preventing a system from booting.
  
 
==== Run-time device tree overlays ====
 
==== Run-time device tree overlays ====
 
There are some out-of-tree mechanisms<ref>[https://lore.kernel.org/patchwork/patch/511853/ OF: DT-Overlay configfs interface (v2)]</ref> for loading device-tree overlay fragments via ConfigFS.
 
There are some out-of-tree mechanisms<ref>[https://lore.kernel.org/patchwork/patch/511853/ OF: DT-Overlay configfs interface (v2)]</ref> for loading device-tree overlay fragments via ConfigFS.
  
[https://github.com/beagleboard/linux/commit/c402adbf1ea4443462621a7ff5062b93dbd1d618 This patch] doesn't apply after 4.14 and is not likely to be accepted in mainline. Mainline doesn't want arbitrary device-tree fragments{{Citation needed}}, but there is a chance that this could be considered a "development-only" patch if this is rebased. The solution would allow run-time loading, but would not be automatic and requires authoring of overlay fragments specific to every add-on board, every Linux platform and every mikroBUS socket.
+
[https://github.com/beagleboard/linux/commit/c402adbf1ea4443462621a7ff5062b93dbd1d618 This patch] doesn't apply after 4.14 and is not likely to be accepted in mainline. Mainline doesn't want arbitrary device-tree fragments<ref>[[Frank%27s Evolving Overlay Thoughts]]</ref>, but there is a chance that this could be considered a "development-only" patch if this is rebased. The solution would allow run-time loading, but would not be automatic and requires authoring of overlay fragments specific to every add-on board, every Linux platform and every mikroBUS socket.
  
 
=== Using Greybus simulator to enable software hotplug support ===
 
=== Using Greybus simulator to enable software hotplug support ===
Line 28: Line 29:
 
This approach requires additional platform data<ref group="definitions">[https://www.kernel.org/doc/htmldocs/writing_musb_glue_layer/device-platform-data.html Device platform data] is data describing the hardware capabilities of your controller hardware</ref> for instantiating device drivers for mikroBUS add-on boards with platform data requirements like reset, interrupt-gpio, and other named-gpio, thus the approach needs more refinements to tackle the issues of instantiating devices with additional platform data requirements. A few approaches to solve this problem are discussed [https://elinux.org/BeagleBoard/Mikrobus_Support here].
 
This approach requires additional platform data<ref group="definitions">[https://www.kernel.org/doc/htmldocs/writing_musb_glue_layer/device-platform-data.html Device platform data] is data describing the hardware capabilities of your controller hardware</ref> for instantiating device drivers for mikroBUS add-on boards with platform data requirements like reset, interrupt-gpio, and other named-gpio, thus the approach needs more refinements to tackle the issues of instantiating devices with additional platform data requirements. A few approaches to solve this problem are discussed [https://elinux.org/BeagleBoard/Mikrobus_Support here].
  
Using Greybus to enumerate drivers for mikroBUS add-on boards has an added advantage of using different transports which makes it ideal for [https://www.youtube.com/watch?v=7H50pv-4YXw IoT Applications]. A transport could be a wired or wireless network, in addition to more flexible embedded busses like Unipro.
+
Using Greybus to enumerate drivers for mikroBUS add-on boards has an added advantage of using different transports<ref group="definitions">Need definition of transport</ref> which makes it ideal for IoT applications<ref>[https://www.youtube.com/watch?v=7H50pv-4YXw Using Greybus for IoT]</ref>. A transport could be a wired or wireless network, in addition to more flexible embedded busses like Unipro.
  
 
== Implementation of a mikroBUS socket on an embedded Linux system ==
 
== Implementation of a mikroBUS socket on an embedded Linux system ==
Line 35: Line 36:
  
 
=== Motivation for supporting software hotplug ===
 
=== Motivation for supporting software hotplug ===
 +
By supporting hotplug, the time to develop and debug support for various mikroBUS add-on boards can be greatly reduced. Further, it opens up the possibility for support under dynamically instantiated buses such as with Greybus.
  
 
=== Creation of a mikroBUS bus driver in the Linux kernel ===
 
=== Creation of a mikroBUS bus driver in the Linux kernel ===
This approach does not involve the use of greybus directly but uses the greybus manifests for providing the platform data, it is actually a combination of the [https://elixir.bootlin.com/linux/v4.9.17/source/drivers/staging/greybus/manifest.c#L454 Greybus manifest parsing logic] combined with the working of [https://github.com/beagleboard/linux/blob/3.8/drivers/misc/cape/beaglebone/capemgr.c Bone Cape Manager] used in the previous BB kernels, the Cape Manager used to load the data for a cape from the Device Tree whereas this bus driver takes the data from the manifest blob passed via the SysFS interface.The Mikrobus port information for the device is parsed from the Device Tree(this information only account for the port information and does not have any click specific information).
+
This approach does not involve the use of greybus directly but uses the greybus manifests for providing the platform data, it is actually a combination of the [https://elixir.bootlin.com/linux/v4.9.17/source/drivers/staging/greybus/manifest.c#L454 Greybus manifest parsing logic] combined with the working of [https://github.com/beagleboard/linux/blob/3.8/drivers/misc/cape/beaglebone/capemgr.c Bone Cape Manager] used in the previous BB kernels, the Cape Manager used to load the data for a cape from the Device Tree whereas this bus driver<ref group="definitions">[http://www.staroceans.org/kernel-and-driver/The%20Linux%20Kernel%20Driver%20Model.pdf Bus drivers] maintain a list of devices that are present on all instances of that bus type, and a list of registered drivers</ref> takes the data from the manifest blob passed via the SysFS interface.The Mikrobus port information for the device is parsed from the Device Tree(this information only account for the port information and does not have any click specific information).
 +
 
 
== Improving the mikroBUS standard for better Linux support ==
 
== Improving the mikroBUS standard for better Linux support ==
  
 
=== Identifier ===
 
=== Identifier ===
 +
Adding an identifier<ref group="definitions">Definition of identifier needed</ref> would provide a way to load the device drivers for a mikroBUS add-on board without the need for manual configuration. By fetching the identifier in the mikroBUS bus driver probe<ref group="definitions">[https://static.lwn.net/images/pdf/LDD3/ch12.pdf Probe] function starts the per-device initialization: initializing hardware, allocating resources, and registering the device within the kernel</ref> function, would enable that function to call the probe function in the various device drivers.
 +
 
==== Proposal #1: Use Greybus Manifest binaries ====
 
==== Proposal #1: Use Greybus Manifest binaries ====
 
* Module vendor specified separately from driver usage
 
* Module vendor specified separately from driver usage
 
* Possibility of using existing driver names for invocation
 
* Possibility of using existing driver names for invocation
 +
* Cannot Describe named properties, device-specific details
 +
 
==== Proposal #2: Use simple string identifiers ====
 
==== Proposal #2: Use simple string identifiers ====
 
* Requires table to be kept in kernel
 
* Requires table to be kept in kernel
 
* Fix-ups would be very direct and not "fix-ups" at all, since no driver specific information would be encoded
 
* Fix-ups would be very direct and not "fix-ups" at all, since no driver specific information would be encoded
 +
 +
==== Proposal #3: mikroBUS Specific Manifest Binaries====
 +
* Provides a way to encode all the  device information in click, uses mikrobus specific manifest
 +
* Driver specific platform data passed to the drivers through the [https://events.static.linuxfound.org/sites/events/files/slides/unified_properties_API_0.pdf Unified Device Properties Interface for ACPI and Device Trees]
 +
* Drivers must use the [https://elixir.bootlin.com/linux/v5.7-rc4/source/drivers/staging/fbtft/fbtft-core.c#L1152 device_get_*] calls to read the properties instead of the [https://elixir.bootlin.com/linux/v4.19.94/source/drivers/staging/fbtft/fbtft-core.c#L1264 of_get_*] calls.
 +
* Manifest will be able to encode all the properties under [https://elixir.bootlin.com/linux/latest/source/include/linux/property.h linux/property.h]
 +
 +
The [https://lore.kernel.org/patchwork/patch/1290148/ mikroBUS driver solution] can be seen as a combination of the proposals #1 and #3 where we extended the greybus manifest to add [https://lore.kernel.org/patchwork/patch/1290145/ new descriptors] so as to describe device driver specific details and custom name properties/GPIOs.
 +
  
 
=== Specifics on power function ===
 
=== Specifics on power function ===
 
The direction and accommodations related to the power pins aren't as specific in the mikroBus standard as with Feather.
 
The direction and accommodations related to the power pins aren't as specific in the mikroBus standard as with Feather.
 +
 +
== Usage of improved mikroBUS support in Linux and mikroBUS standard ==
 +
Assuming all of the suggestions above are implemented, what would the resulting usage be?
 +
 +
=== Adding a mikroBUS socket to your Linux system ===
 +
Once the mikroBUS driver is implemented, the device tree fragment for a particular mikroBUS socket will have a basic structure like this:
 +
<pre>
 +
Required properties:
 +
- compatible: Must be "linux,mikrobus"
 +
- i2c-adapter:  phandle to the i2c adapter attached to the mikrobus socket.
 +
- spi-master: spi bus number of the spi-master attached to the mikrobus socket.
 +
- spi-cs: spi chip-select numbers corresponding to the chip-selects
 +
  on the mikrobus socket(0 -> chip select corresponding to CS pin
 +
  1 -> chip select corresponding to RST pin).
 +
- serdev-controller:  phandle to the uart port attached to the mikrobus socket.
 +
- pwms: phandle to the pwm-controller corresponding to the mikroBUS PWM pin.
 +
- mikrobus-gpios: gpios array corresponding to GPIOs on the mikroBUS port,
 +
  for targets not supporting the AN pin on the mikroBUS port as
 +
  GPIO, the length of the gpios array can be 11, otherwise it
 +
  should be 12.
 +
- pinctrl-names: pinctrl state names to support additional pin usage/deviations
 +
from mikroBUS socket standard usage, must be "default",
 +
"pwm_default", "pwm_gpio", "uart_default", "uart_gpio",
 +
"i2c_default", "i2c_gpio", "spi_default", "spi_gpio", these
 +
pinctrl names should have corresponding pinctrl-N entries which
 +
        corresponds to the pinmux state for the pingroup, for example,
 +
i2c_default corresponds to the state where the I2C pin group
 +
(SCL,SDA) are configured in I2C mode and i2c_gpio mode corresponds
 +
to the pinmux state where these pins are configured as GPIO.
 +
- pinctrl-N : pinctrl-(0-8) corresponds to the pinctrl states for the states described
 +
      above.
 +
 +
Example:
 +
mikrobus-0 {
 +
compatible = "linux,mikrobus";
 +
status = "okay";
 +
pinctrl-names = "default", "pwm_default", "pwm_gpio",
 +
"uart_default", "uart_gpio", "i2c_default",
 +
"i2c_gpio", "spi_default", "spi_gpio";
 +
pinctrl-0 = <
 +
&P2_03_gpio_input_pin
 +
&P1_04_gpio_pin
 +
&P1_02_gpio_pin
 +
>;
 +
pinctrl-1 = <&P2_01_pwm_pin>;
 +
pinctrl-2 = <&P2_01_gpio_pin>;
 +
pinctrl-3 = <
 +
&P2_05_uart_pin
 +
&P2_07_uart_pin
 +
>;
 +
pinctrl-4 = <
 +
&P2_05_gpio_pin
 +
&P2_07_gpio_pin
 +
>;
 +
pinctrl-5 = <
 +
&P2_09_i2c_pin
 +
&P2_11_i2c_pin
 +
>;
 +
pinctrl-6 = <
 +
&P2_09_gpio_pin
 +
&P2_11_gpio_pin
 +
>;
 +
pinctrl-7 = <
 +
&P1_12_spi_pin
 +
&P1_10_spi_pin
 +
&P1_08_spi_sclk_pin
 +
&P1_06_spi_cs_pin
 +
>;
 +
pinctrl-8 = <
 +
&P1_12_gpio_pin
 +
&P1_10_gpio_pin
 +
&P1_08_gpio_pin
 +
&P1_06_gpio_pin
 +
>;
 +
i2c-adapter = <&i2c1>;
 +
spi-master = <0>;
 +
spi-cs = <0 1>;
 +
serdev-controller = <&uart4>;
 +
pwms = <&ehrpwm1 0 500000 0>;
 +
mikrobus-gpios = <&gpio1 18 0> , <&gpio0 23 0>,
 +
<&gpio0 30 0> , <&gpio0 31 0>,
 +
<&gpio0 15 0> , <&gpio0 14 0>,
 +
<&gpio0 4 0> , <&gpio0 3 0>,
 +
<&gpio0 2 0> , <&gpio0 5 0>,
 +
<&gpio2 25 0>  , <&gpio2 3 0>;
 +
  };
 +
</pre>
 +
=== Adding support for a mikroBUS add-on board to the Linux kernel ===
 +
 +
==== mikroBUS add-on board device tree fragment ====
 +
Assuming we are using a [https://www.mikroe.com/mpu-9dof-click MPU9DOF Click], the device tree fragment would look something like this:
 +
 +
<pre>
 +
/dts-v1/;
 +
/plugin/;
 +
 +
/ {
 +
&mikrobus_i2c {
 +
status = "okay";
 +
#address-cells = <1>;
 +
#size-cells = <0>;
 +
mpu9150@69 {
 +
compatible = "invensense,mpu9150";
 +
reg = <0x69>;
 +
interrupt-parent = <&mikrobus_int>;
 +
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; /* 0 is the first interrupt signal, next is the type */
 +
i2c-gate {
 +
#address-cells = <1>;
 +
#size-cells = <0>;
 +
ax8975@c {
 +
compatible = "ak,ak8975";
 +
reg = <0x0c>;
 +
};
 +
};
 +
};
 +
};
 +
};
 +
</pre>
 +
 +
Because we have a mikroBUS socket defined, the references to bus drivers and gpio drivers are no longer board or socket dependent, so this can be universal for all consumption of this mikroBUS add-on board. Symbols will need help being resolved against the individual mikroBUS instance as they are left generic.<ref>TODO: How can resolving generic mikroBUS dt symbols to specific socket instance peripherals be made possible?</ref>
 +
 +
The mikroBUS driver will need to know to make any adjustments to pinmux settings to satisfy the interface needs. Those cannot be handled generically across platforms.
 +
 +
==== Extended Greybus Manifest ====
 +
If you are using Greybus to instantiate the embedded buses used for your mikroBUS socket, you'll need to create a Greybus manifest to enumerate those buses to Linux. The Greybus manifest format for a [https://www.mikroe.com/mpu-9dof-click MPU9DOF Click] would be a structure like this:
 +
 +
<pre>
 +
;
 +
; MPU 9DOF CLICK
 +
; https://www.mikroe.com/mpu-9dof-click
 +
; CONFIG_INV_MPU6050_I2C
 +
;
 +
; Copyright 2020 BeagleBoard.org Foundation
 +
; Copyright 2020 Texas Instruments
 +
;
 +
 +
[manifest-header]
 +
version-major = 0
 +
version-minor = 1
 +
 +
[interface-descriptor]
 +
vendor-string-id = 1
 +
product-string-id = 2
 +
 +
[string-descriptor 1]
 +
string = MikroElektronika
 +
 +
[string-descriptor 2]
 +
string = MPU 9DOF Click
 +
 +
[mikrobus-descriptor]
 +
pwm-state = 4
 +
int-state = 1
 +
rx-state = 7
 +
tx-state = 7
 +
scl-state = 6
 +
sda-state = 6
 +
mosi-state = 5
 +
miso-state = 5
 +
sck-state = 5
 +
cs-state = 5
 +
rst-state = 2
 +
an-state = 1
 +
 +
[bundle-descriptor 1]
 +
class = 0xa
 +
 +
[cport-descriptor 1]
 +
bundle = 1
 +
protocol = 0x2
 +
 +
[cport-descriptor 2]
 +
bundle = 1
 +
protocol = 0x3
 +
 +
[device-descriptor 1]
 +
driver-string-id = 3
 +
protocol = 0x3
 +
reg = 0x68
 +
irq = 1
 +
irq-type = 0x1
 +
 +
[string-descriptor 3]
 +
string = mpu9150
 +
 +
</pre>
 +
 +
===== Classes =====
 +
I think the only relevant class for us is "BRIDGED_PHY" as we are just connecting the buses that are defined. We might need to come up with a new class though.
 +
{| class="wikitable"
 +
|-
 +
! Class !! Index
 +
|-
 +
| BRIDGED_PHY || 0x0a
 +
|}
 +
 +
===== Protocols =====
 +
Here are the relavent prototols:<ref>Protocols can be found in [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/greybus/greybus_manifest.h#n28 greybus_manifest.h]</ref>
 +
{| class="wikitable"
 +
|-
 +
! Protocol !! Index
 +
|-
 +
| Control || 0x00
 +
|-
 +
| GPIO || 0x02
 +
|-
 +
| I2C || 0x03
 +
|-
 +
| UART || 0x04
 +
|-
 +
| PWM || 0x09
 +
|-
 +
| SPI || 0x0b
 +
|-
 +
| RAW|| 0x0fe (used for platform devices)
 +
|-
 +
| ADC || N/A
 +
|}
 +
 +
===== mikroBUS Driver Sysfs Entries =====
 +
The mikroBUS driver provides a few SysFS entries, a few of them are just debug interfaces for loading manifest binaries, adding a mikrobus port dynamically .etc, the sysfs directory structure of the mikroBUS driver is as below:
 +
 +
[[File:Mikrobus sysfs Entries.jpg]]
 +
 +
* The new_device entry under the mikrobus adapter is the debug interface for supplying the click manifest to the driver.
 +
* The delete_device entry under the mikrobus adapter is used for removing a registered add-on board.
 +
* The rescan entry under the mikrobus adapter is used to trigger a rescan on the mikrobus board eeprom for new manifest.
  
 
== Comparisons to other popular embedded add-on form-factors ==
 
== Comparisons to other popular embedded add-on form-factors ==
Line 71: Line 314:
 
=== Why should mikroBUS be a bus in the kernel even if these other interfaces aren't? ===
 
=== Why should mikroBUS be a bus in the kernel even if these other interfaces aren't? ===
  
* It's an open standard
+
* mikroBUS is simple, not requiring the need to overlay arbitrary device trees like Capes or other excessively flexible interfaces defined arbitrary collections of microcontroller pins.
* Over 750+ Click add-on boards ranging from wireless connectivity clicks to Human Machine Interface clicks, of which more than 100+ clicks has already support in the linux kernel.
+
* mikroBUS a free standard and not an ad-hoc one.
* Over 140+ Development boards [https://www.mikroe.com/blog/development-boards-that-support-mikrobus supported.]
+
* Over 750+ Click add-on boards ranging from wireless connectivity clicks to Human Machine Interface clicks, of which more than 100+ clicks already have support in the Linux kernel<ref>[https://elinux.org/MikroEClicks_with_Linux_Support Click Boards with Driver Support in Linux Kernel]</ref>.
 +
* Over 140+ Development boards supported<ref>[https://www.mikroe.com/blog/development-boards-that-support-mikrobus Development boards that support mikroBUS]</ref>.
  
 
=== Why aren't we opening pandora's box by adding this as a bus in the kernel? ===
 
=== Why aren't we opening pandora's box by adding this as a bus in the kernel? ===
Line 79: Line 323:
 
== Definitions ==
 
== Definitions ==
 
<references group="definitions" />
 
<references group="definitions" />
* Platform data
 
* Device driver
 
* Bus driver
 
* Probe
 
* Identifier
 
* Device tree
 
  
 
== References ==
 
== References ==
 
<references />
 
<references />

Latest revision as of 15:38, 26 August 2020

mikroBUS is a standard specification by MikroElektronika that can be freely used by anyone following the guidelines. It includes SPI, I2C, UART, PWM, ADC, reset, interrupt, and power (3.3V and 5V) connections to common embedded peripherals.

This page is meant to foster discussion within the embedded Linux community on usage of mikroBUS compatible add-on boards, adding mikroBUS sockets to embedded Linux systems, and ways to improve both Linux support for mikroBUS and the mikroBUS standard.

Usage of mikroBUS compatible add-on boards today

Many drivers for mikroBUS add-on boards already exist in the kernel[1], but using them can be a challenge. The most straight-forward method for loading existing drivers is to provide device tree overlay fragments at boot time, which is reasonably supported by mainline Linux. There are some out-of-tree efforts to load device tree overlay fragments at run time or to use the Greybus simulator to generate new instances of the embedded buses used on a mikroBUS socket.

Device tree overlays loaded at boot time

Today, there is no mainline solution for enabling mikroBUS add-on boards at run-time, so they must all be configured at boot-time with device trees[definitions 1].

Instructions for PocketBeagle: https://github.com/beagleboard/pocketbeagle/wiki/Click-boards%E2%84%A2

Example overlay: https://github.com/beagleboard/bb.org-overlays/blob/master/src/arm/PB-I2C2-MPU-9DOF-CLICK.dts

This is the primary mechanism for enumerating device drivers[definitions 2] for mikroBUS add-on boards today. It suffers from the need to maintain a large out-of-tree database for which you'd need an overlay for every mikroBUS add-on board for every Linux system for every mikroBUS socket on that system. Multiplying 1,000 Click boards by the number of BeagleBoard.org boards by the number of sockets supported on each of those boards ends up being a LOT of device tree overlay fragments.

Further, the application of those fragments is rather error-prone and can even result in preventing a system from booting.

Run-time device tree overlays

There are some out-of-tree mechanisms[2] for loading device-tree overlay fragments via ConfigFS.

This patch doesn't apply after 4.14 and is not likely to be accepted in mainline. Mainline doesn't want arbitrary device-tree fragments[3], but there is a chance that this could be considered a "development-only" patch if this is rebased. The solution would allow run-time loading, but would not be automatic and requires authoring of overlay fragments specific to every add-on board, every Linux platform and every mikroBUS socket.

Using Greybus simulator to enable software hotplug support

It is possible to enumerate some device drivers for mikroBUS add-on boards by running the Greybus simulator, gbsim. Instructions for setting up gbsim and more information can be found in a wiki write-up on a GSoC project. This method uses Greybus simulator to load a manifest blob to the kernel greybus driver where the virtual interfaces(SPI/I2C/other) are created.

gbsim manages the transfers between the physical bus/gpio/interrupt and the virtual Greybus interface. Having a userspace application, gbsim, in the middle of the transactions has a performance and security impact.

This approach requires additional platform data[definitions 3] for instantiating device drivers for mikroBUS add-on boards with platform data requirements like reset, interrupt-gpio, and other named-gpio, thus the approach needs more refinements to tackle the issues of instantiating devices with additional platform data requirements. A few approaches to solve this problem are discussed here.

Using Greybus to enumerate drivers for mikroBUS add-on boards has an added advantage of using different transports[definitions 4] which makes it ideal for IoT applications[4]. A transport could be a wired or wireless network, in addition to more flexible embedded busses like Unipro.

Implementation of a mikroBUS socket on an embedded Linux system

Improving Linux support for mikroBUS

Motivation for supporting software hotplug

By supporting hotplug, the time to develop and debug support for various mikroBUS add-on boards can be greatly reduced. Further, it opens up the possibility for support under dynamically instantiated buses such as with Greybus.

Creation of a mikroBUS bus driver in the Linux kernel

This approach does not involve the use of greybus directly but uses the greybus manifests for providing the platform data, it is actually a combination of the Greybus manifest parsing logic combined with the working of Bone Cape Manager used in the previous BB kernels, the Cape Manager used to load the data for a cape from the Device Tree whereas this bus driver[definitions 5] takes the data from the manifest blob passed via the SysFS interface.The Mikrobus port information for the device is parsed from the Device Tree(this information only account for the port information and does not have any click specific information).

Improving the mikroBUS standard for better Linux support

Identifier

Adding an identifier[definitions 6] would provide a way to load the device drivers for a mikroBUS add-on board without the need for manual configuration. By fetching the identifier in the mikroBUS bus driver probe[definitions 7] function, would enable that function to call the probe function in the various device drivers.

Proposal #1: Use Greybus Manifest binaries

  • Module vendor specified separately from driver usage
  • Possibility of using existing driver names for invocation
  • Cannot Describe named properties, device-specific details

Proposal #2: Use simple string identifiers

  • Requires table to be kept in kernel
  • Fix-ups would be very direct and not "fix-ups" at all, since no driver specific information would be encoded

Proposal #3: mikroBUS Specific Manifest Binaries

The mikroBUS driver solution can be seen as a combination of the proposals #1 and #3 where we extended the greybus manifest to add new descriptors so as to describe device driver specific details and custom name properties/GPIOs.


Specifics on power function

The direction and accommodations related to the power pins aren't as specific in the mikroBus standard as with Feather.

Usage of improved mikroBUS support in Linux and mikroBUS standard

Assuming all of the suggestions above are implemented, what would the resulting usage be?

Adding a mikroBUS socket to your Linux system

Once the mikroBUS driver is implemented, the device tree fragment for a particular mikroBUS socket will have a basic structure like this:

 Required properties:
 - compatible: Must be "linux,mikrobus"
 - i2c-adapter:  phandle to the i2c adapter attached to the mikrobus socket.
 - spi-master: spi bus number of the spi-master attached to the mikrobus socket.
 - spi-cs: spi chip-select numbers corresponding to the chip-selects
 	  on the mikrobus socket(0 -> chip select corresponding to CS pin
 	  1 -> chip select corresponding to RST pin).
 - serdev-controller:  phandle to the uart port attached to the mikrobus socket.
 - pwms: phandle to the pwm-controller corresponding to the mikroBUS PWM pin.
 - mikrobus-gpios: gpios array corresponding to GPIOs on the mikroBUS port,
 		  for targets not supporting the AN pin on the mikroBUS port as
 		  GPIO, the length of the gpios array can be 11, otherwise it
 		  should be 12.
 - pinctrl-names: pinctrl state names to support additional pin usage/deviations
 		 from mikroBUS socket standard usage, must be "default",
 		 "pwm_default", "pwm_gpio", "uart_default", "uart_gpio",
 		 "i2c_default", "i2c_gpio", "spi_default", "spi_gpio", these
 		 pinctrl names should have corresponding pinctrl-N entries which
         	 corresponds to the pinmux state for the pingroup, for example,
 		 i2c_default corresponds to the state where the I2C pin group
 		 (SCL,SDA) are configured in I2C mode and i2c_gpio mode corresponds
 		 to the pinmux state where these pins are configured as GPIO.
 - pinctrl-N : pinctrl-(0-8) corresponds to the pinctrl states for the states described
 	      above.
 
 Example:
 	mikrobus-0 {
 		compatible = "linux,mikrobus";
 		status = "okay";
 		pinctrl-names = "default", "pwm_default", "pwm_gpio",
 				"uart_default", "uart_gpio", "i2c_default",
 				"i2c_gpio", "spi_default", "spi_gpio";
 		pinctrl-0 = <
 			&P2_03_gpio_input_pin
 			&P1_04_gpio_pin
 			&P1_02_gpio_pin
 		>;
 		pinctrl-1 = <&P2_01_pwm_pin>;
 		pinctrl-2 = <&P2_01_gpio_pin>;
 		pinctrl-3 = <
 			&P2_05_uart_pin
 			&P2_07_uart_pin
 		>;
 		pinctrl-4 = <
 			&P2_05_gpio_pin
 			&P2_07_gpio_pin
 		>;
 		pinctrl-5 = <
 			&P2_09_i2c_pin
 			&P2_11_i2c_pin
 		>;
 		pinctrl-6 = <
 			&P2_09_gpio_pin
 			&P2_11_gpio_pin
 		>;
 		pinctrl-7 = <
 			&P1_12_spi_pin
 			&P1_10_spi_pin
 			&P1_08_spi_sclk_pin
 			&P1_06_spi_cs_pin
 		>;
 		pinctrl-8 = <
 			&P1_12_gpio_pin
 			&P1_10_gpio_pin
 			&P1_08_gpio_pin
 			&P1_06_gpio_pin
 		>;
 		i2c-adapter = <&i2c1>;
 		spi-master = <0>;
 		spi-cs = <0 1>;
 		serdev-controller = <&uart4>;
 		pwms = <&ehrpwm1 0 500000 0>;
 		mikrobus-gpios = <&gpio1 18 0> , <&gpio0 23 0>,
 					<&gpio0 30 0> , <&gpio0 31 0>,
 					<&gpio0 15 0> , <&gpio0 14 0>,
 					<&gpio0 4 0> , <&gpio0 3 0>,
 					<&gpio0 2 0> , <&gpio0 5 0>,
 					<&gpio2 25 0>  , <&gpio2 3 0>;
  	};

Adding support for a mikroBUS add-on board to the Linux kernel

mikroBUS add-on board device tree fragment

Assuming we are using a MPU9DOF Click, the device tree fragment would look something like this:

/dts-v1/;
/plugin/;

/ {
	&mikrobus_i2c {
		status = "okay";
		#address-cells = <1>;
		#size-cells = <0>;
		mpu9150@69 {
			compatible = "invensense,mpu9150";
			reg = <0x69>;
			interrupt-parent = <&mikrobus_int>;
			interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; /* 0 is the first interrupt signal, next is the type */
			i2c-gate {
				#address-cells = <1>;
				#size-cells = <0>;
				ax8975@c {
					compatible = "ak,ak8975";
					reg = <0x0c>;
				};
			};
		};
	};
};

Because we have a mikroBUS socket defined, the references to bus drivers and gpio drivers are no longer board or socket dependent, so this can be universal for all consumption of this mikroBUS add-on board. Symbols will need help being resolved against the individual mikroBUS instance as they are left generic.[5]

The mikroBUS driver will need to know to make any adjustments to pinmux settings to satisfy the interface needs. Those cannot be handled generically across platforms.

Extended Greybus Manifest

If you are using Greybus to instantiate the embedded buses used for your mikroBUS socket, you'll need to create a Greybus manifest to enumerate those buses to Linux. The Greybus manifest format for a MPU9DOF Click would be a structure like this:

;
; MPU 9DOF CLICK
; https://www.mikroe.com/mpu-9dof-click
; CONFIG_INV_MPU6050_I2C
;
; Copyright 2020 BeagleBoard.org Foundation 
; Copyright 2020 Texas Instruments 
;

[manifest-header]
version-major = 0
version-minor = 1

[interface-descriptor]
vendor-string-id = 1
product-string-id = 2

[string-descriptor 1]
string = MikroElektronika

[string-descriptor 2]
string = MPU 9DOF Click

[mikrobus-descriptor]
pwm-state = 4
int-state = 1
rx-state = 7
tx-state = 7
scl-state = 6
sda-state = 6
mosi-state = 5
miso-state = 5
sck-state = 5
cs-state = 5
rst-state = 2
an-state = 1

[bundle-descriptor 1]
class = 0xa

[cport-descriptor 1]
bundle = 1
protocol = 0x2

[cport-descriptor 2]
bundle = 1
protocol = 0x3

[device-descriptor 1]
driver-string-id = 3
protocol = 0x3
reg = 0x68
irq = 1
irq-type = 0x1

[string-descriptor 3]
string = mpu9150

Classes

I think the only relevant class for us is "BRIDGED_PHY" as we are just connecting the buses that are defined. We might need to come up with a new class though.

Class Index
BRIDGED_PHY 0x0a
Protocols

Here are the relavent prototols:[6]

Protocol Index
Control 0x00
GPIO 0x02
I2C 0x03
UART 0x04
PWM 0x09
SPI 0x0b
RAW 0x0fe (used for platform devices)
ADC N/A
mikroBUS Driver Sysfs Entries

The mikroBUS driver provides a few SysFS entries, a few of them are just debug interfaces for loading manifest binaries, adding a mikrobus port dynamically .etc, the sysfs directory structure of the mikroBUS driver is as below:

Mikrobus sysfs Entries.jpg

  • The new_device entry under the mikrobus adapter is the debug interface for supplying the click manifest to the driver.
  • The delete_device entry under the mikrobus adapter is used for removing a registered add-on board.
  • The rescan entry under the mikrobus adapter is used to trigger a rescan on the mikrobus board eeprom for new manifest.

Comparisons to other popular embedded add-on form-factors

The purpose of this page is to advance the development of mikroBUS support in Linux. Some distractions may be introduced to either illustrate the effort cannot be sufficiently limited in scope to tackle or that focus should be elsewhere. I'm not assuming these would be introduced with any ill-will, they are just natural concerns that need to be addressed up-front.

Form-factor Size Comments
mikroBUS 1.0" x 1.125"/1.6"/2.25" Example
Feather/Wing 0.9" x 2.0" De-facto standard based on implementation pin-out. Could benefit from some of the efforts for mikroBUS support, but not as cleanly defined with a limited and focused scope. Not as easy to make an impact on the majority of existing designs.
Arduino/Shield XxY Too irregular to make useful as an embedded system bus.
BeagleBone/Cape XxY Far too flexible for a standard outside of the Beagle ecosystem.

Why should mikroBUS be a bus in the kernel even if these other interfaces aren't?

  • mikroBUS is simple, not requiring the need to overlay arbitrary device trees like Capes or other excessively flexible interfaces defined arbitrary collections of microcontroller pins.
  • mikroBUS a free standard and not an ad-hoc one.
  • Over 750+ Click add-on boards ranging from wireless connectivity clicks to Human Machine Interface clicks, of which more than 100+ clicks already have support in the Linux kernel[7].
  • Over 140+ Development boards supported[8].

Why aren't we opening pandora's box by adding this as a bus in the kernel?

Definitions

  1. Device tree is a data structure describing the hardware components of a particular computer so that the operating system's kernel can use and manage those components. See Device_Tree_Reference.
  2. Device Driver is a software that handles or manages a hardware controller.
  3. Device platform data is data describing the hardware capabilities of your controller hardware
  4. Need definition of transport
  5. Bus drivers maintain a list of devices that are present on all instances of that bus type, and a list of registered drivers
  6. Definition of identifier needed
  7. Probe function starts the per-device initialization: initializing hardware, allocating resources, and registering the device within the kernel

References