Home  >  Edison  >  Setting Up

ACPI

ACPI or no-ACPI?

The factory supplied kernel allowed setting pinmuxes from user space through debugfs. The vanilla linux kernel does not allow this. Of course it is allowed to write a driver or modify platform code to make sure that it configures pinmuxes as required for your application.

What are pinmuxes and why do I care?

A pinmux is like a switch that allows a certain CPU pin to have multiple functions. In linux pinmuxes are controlled from the pinctrl subsystem that can not be controlled from user space without a driver. Other aspects of a CPU pin are controlled from the gpio subsystem and can be controlled from user space. From the linux Documentation/driver-api/pinctl.rst:

From a kernel point of view, however, these are different aspects of the hardware and shall be put into different subsystems:

  • Registers (or fields within registers) that control electrical properties of the pin such as biasing and drive strength should be exposed through the pinctrl subsystem, as “pin configuration” settings.
  • Registers (or fields within registers) that control muxing of signals from various other HW blocks (e.g. I2C, MMC, or GPIO) onto pins should be exposed through the pinctrl subsystem, as mux functions.
  • Registers (or fields within registers) that control GPIO functionality such as setting a GPIO’s output value, reading a GPIO’s input value, or setting GPIO pin direction should be exposed through the GPIO subsystem, and if they also support interrupt capabilities, through the irqchip abstraction.

Information on pinmux modes can be found Hardware Guide for the Intel® Edison Kit for Arduino*.

The Edison Arduino also has muxes on the PCB that are controlled by setting GPIO pins high or low as well as I2C GPIO expanders that provide additional GPIO’s.

To access functions like the UART, I2C-6 and SPI bus the pinmux mode must be set by the kernel from the default function set by Edison firmware (GPIO) to the desired function through platform code which sets the desired mode permanently.

And ACPI?

Ultimately this type of platform code should go into ACPI tables. ACPI tables are normally served by BIOS. However U-Boot can also do this. Further, additional ACPI tables can be loaded into the kernel at a later time. We can build an ACPI enabled version of U-Boot with tables describing the SoC and additional ACPI tables describing the Edison Arduino. The latter are installed into the initramfs and loaded through configfs right after boot and prior to switching the rootfs.

  • ACPI tables can be loaded at any time, it is not a requirement to put them into the initramfs. Putting them in initramfs and loading through configfs does load them as early as possible without resorting to a seperate initrd. Also, loading from configfs has the advantage that the tables can be unloaded/reloaded at run time.

Enabling the UART as a 2 wire (RX/TX), 4 wire (RX/TX/CTS/RTS) device as well as the SPI and I2C device are build options in meta-acpi. We set these options in meta-intel-edison-bsp/conf/machine/edison.conf. Currently we have:

ACPI_TABLES ?= "arduino.asl spidev.asl"
ACPI_FEATURES ?= "uart_2w spi"

ACPI_TABLES has the list of asl’s compiled amd built into the initramfs and loaded at boot.
ACPI_FEATURES sets the options used when compiling the asl. Currently supported are uart_2w, uart_4w, i2c, spi

In the future, additional ACPI tables can be added to meta-acpi.

The ACPI enabled U-Boot only has effect when the ACPI enabled kernel is also built and used. Note the following points:

  1. The kernel called non-acpi is a vanilla kernel and actually does have ACPI. What we mean is that it is missing some additional patches that will allow it to work with the ACPI enabled U-Boot.
  2. When you flash the generated image using flashall or Flash Tool Lite you will always have a matching U-Boot and kernel.
  3. When you flash U-Boot manually or boot a kernel manually using edsboot or usbboot you can get combinations of ACPI and non-ACPI U-Boot and kernel. This will have the following effect:
U-Boot kernel boot result
non-acpi non-acpi boots, with i2c-6, uses SFI
non-acpi acpi boots, no i2c-6, uses SFI
acpi non-acpi boots only with ‘acpi=off’ on kernel command line, with i2c-6, uses SFI
acpi acpi boots, with i2c-6, uses ACPI

Notes

  • Both U-Boot and kernel need to be ACPI enabled for ACPI to work.
  • An ACPI kernel will run with non-ACPI U-Boot. However without the patch that enables I2C-6.
  • An non-ACPI kernel (including the factory provided one) will hang when run with ACPI enabled U-Boot, unless you provide acpi=off on the kernel command line.

Why ACPI and no-ACPI?

Some of the pinmuxes are protected by the SCU (System Controller Unit) and can currently not be changed using ACPI, in particular I2C bus 6. The non-ACPI image has a patch to its kernel platform code that tells the SCU to change the pinmux. The ACPI enabled image has a patch in U-Boot to do the same.

Currently we are working on fixing this for the ACPI case. The status of this work can be followed at the Intel Edison Wiki.

Work on providing non-ACPI U-Boot patches will end with the release of U-Boot v2018.09 1). Efforts will from then on be focussed on the ACPI U-Boot. Eventually this may lead to new non-ACPI kernels to be unsupported.

1) Work on non-ACPI U-Boot is done mainly by Andy Shevshenko and can be tracked here

Enabling ACPI

In meta-intel-edison/meta-intel-edison-distro/conf/distro/poky-edison.conf add acpi to DISTRO_FEATURES.

Alternatively you can checkout sumo64-acpi which will build a x86_64 acpi enabled version.

ACPI tables

Building

Sample ACPI tables are provided by the meta-acpi layer in the recipes-bsp/acpi-tables/samples/edison/ folder. We have tables for defining gpio, i2c, ads7951 and spi through 2 tables: arduino and spidev.

bitbake acpi-tables builds the cpio and puts that in the deploy folder out/current/build/tmp/deploy/images/edison/

Configuring

In meta-intel-edison-bsp/conf/machine/edison.conf we have

ACPI_TABLES ?= "arduino.asl spidev.asl"
ACPI_FEATURES ?= "uart_2w i2c spi"

ACPI_TABLES define which tables to build and include into the cpio, apci-tables.deb and initramfs. ACPI_FEATURES defines options you can turn on during the build, these are translated to the appropriate defines. Choices are:

Option Description
uart_2w Conffigures RxD and TxD for the HSU
uart_4w Configures RxD, TxD, RTS and CTS for the HSU
i2c Configures SCL and SDA for the I2c-6
spi Configures pins for SPI

Loading the ACPI tables

Preloading by U-Boot

You can pre-load the acpi-tables.cpio in the following way:

setenv boot_edsboot 'zboot 0x100000 0 0x3000000 0x1000000'
setenv bootargs_edsboot 'console=tty1 console=ttyS2,115200n8 rootfstype=ramfs rw'
setenv bootcmd_edsboot 'setenv bootargs ${bootargs_edsboot}; run load_edsboot; run boot_edsboot'
setenv load_edsboot 'load mmc 0:9 0x100000 vmlinuz.efi; load mmc 0:9 0x3000000 acpi-tables.cpio'

Run time loading through configfs

Configfs allows to allow to load ssdt tables from user space, see kernel Documentation/acpi/ssdt-overlays.txt. This is done on edison automatically by incorporating the tables into the initramfs and loading them into the kernel as early as possible.

Debugging

In theory ACPI tables loaded through configfs can also be unloaded by using:

rmdir /sys/kernel/config/acpi/table/arduino
rmdir /sys/kernel/config/acpi/table/spidev

To facilitate debugging there is a kernel command line option skiptables that causes loading on the ACPI tables inside the initramfs to be skipped. This allows a quicker debug cycle. Add the option for instance to the bootargs_common environment variable:

fw_setenv bootargs_common 'quiet skiptables'

After building acpi-tables.deb (see above), install it on the image manually using dpkg -i acpi-tables.deb. Alternatively copy the tables to /kernel/firmware/acpi/ manually.

acpi-tables.deb installs acpi-tables-load which can be manually used to load the table.