Congatec Board Controller support into the upstream Linux Kernel

Introduction

Congatec’s x86 System-on-Modules (SoM) include a Board Controller component connected to the processor via an eSPI bus, and providing various features such as I²C buses, GPIOs, a watchdog timer, and various sensors for monitoring voltage, fan speed, and more.

Conga-SA7 datasheet extract

For their x86 System-on-Modules (SoMs), Congatec provides a Yocto meta-layer: meta-congatec-x86. This meta-layer includes, among other components, a driver, a library, and tools for interfacing with the Board Controller.

The primary issue with the provided driver is its deviation from standard Linux APIs. It exposes a custom character device and relies on custom ioctl() for communication with userspace. This non-standard approach leads to compatibility and portability challenges. For example, an application using the standard Linux GPIO API would need to be adapted to access the GPIOs from Congatec’s Board Controller. Similarly, software designed specifically for the Board Controller’s GPIOs would require changes to work with GPIOs on other platforms.

Additionally, because the driver is out-of-tree, it raises concerns about long-term support and maintainability. Questions naturally arise—will the driver be regularly updated to remain compatible with future Linux kernel versions, given the instability of internal APIs? Will bugs and security vulnerabilities be addressed in a timely manner?

One of our customers, planning to use the Conga-SA7 board in a commercial product, recognized these challenges early on. As a result, they asked us to integrate support for the Congatec Board Controller directly into the mainline Linux kernel. Upstreaming the driver into the kernel would eliminate these issues by ensuring better portability, long-term maintenance, and community support.

Initial support

The project scope was initially focused on meeting specific customer requirements, which was limited to a subset of the Board Controller features: watchdog, I2C and GPIOs.

As mentioned earlier, the Board Controller is interfaced with the processor via an eSPI bus. Thanks to the source code of Congatec custom driver and library being available, it was trivial to figure out the protocol used to communicate with the Board Controller and implement a clean, standard Linux kernel driver.

As the Board Controller offers multiple features, we leveraged the Multi-Function Device subsystem: if you’re not familiar with MFD, we suggest looking at the slides from Bootlin engineer Alexandre Belloni on this topic.

Our MFD driver is located in drivers/mfd/cgbc-core.c and is essentially responsible for:

  • Binding against the Board Controller when it’s detected. Since the Board Controller is not defined in the ACPI tables provided by the Congatec SoC firmware/BIOS, we use the DMI table that identifies the board to recognize that we are on a hardware platform that features this specific Board Controller
  • Providing utility functions that allow to communicate with the Board Controller. These utility functions will be used by the sub-drivers to actually do their work.
  • Instantiating the sub-devices: initially one watchdog device, one GPIO controller and two I2C controllers

The MFD driver itself provides a few sysfs entries that for example allow to retrieve the Board Controller version:

# cat /sys/devices/platform/cgbc/cgbc_version
CGBCP032

On top of this, 3 specific drivers were implemented for each of the 3 functions to support:

Thanks to these drivers, the different functions are now exposed through the standard Linux APIs. For example for watchdog:

# wd_identify
CGBC Watchdog

For GPIO:

# gpiodetect | grep cgbc
gpiochip5 [cgbc-gpio] (14 lines)
# gpioinfo 5
gpiochip5 - 14 lines:
line 0: unnamed unused output active-high
line 1: unnamed unused output active-high
line 2: unnamed unused output active-high
line 3: unnamed unused output active-high
line 4: unnamed unused output active-high
line 5: unnamed unused output active-high
line 6: unnamed unused input active-high
line 7: unnamed unused input active-high
line 8: unnamed unused input active-high
line 9: unnamed unused input active-high
line 10: unnamed unused input active-high
line 11: unnamed unused input active-high
line 12: unnamed unused input active-high
line 13: unnamed unused input active-high

And for I2C:

# i2cdetect -l | grep Congatec
i2c-11 i2c Congatec General Purpose I2C adapter I2C adapter
i2c-13 i2c Congatec Power Management I2C adapter I2C adapter

This initial set of drivers went through 3 iterations on the public Linux kernel mailing lists, and was then merged as part of the Linux 6.13 release. See also the individual commits:

Adding sensors support

In addition to I2C, watchdog and GPIO, the Board Controller has a lot of sensors (voltage, current, fan), and we also wanted to support them. To this end, we created an additional hwmon driver, located in drivers/hwmon/cgbc-hwmon.c, and added an extra sub-device describing those sensors in the MFD driver. With this new driver the sensors are now available through sysfs, which is the standard API for hwmon, and can be read using the sensors command line tool:

$ sensors
cgbc_hwmon-isa-0000
Adapter: ISA adapter
DC Runtime Voltage:    4.93 V
Chipset Temperature:  +48.0 C
Board Temperature:    +44.0 C

This additional driver was merged as of Linux 6.15. See also the individual commits:

Adding conga-SA8 support

As our customer evaluates the conga-SA8, we have also added upstream support for it. Since both the conga-SA7 and conga-SA8 boards feature the same Board Controller, the only modification required to support the new board was adding a new DMI entry in the MFD driver:


static const struct dmi_system_id cgbc_dmi_table[] __initconst = {
	[...]
	{
		.ident = "SA8",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "congatec"),
			DMI_MATCH(DMI_BOARD_NAME, "conga-SA8"),
		},
	},
	{}
};

This change also went into the upstream Linux 6.15 release, see the commit:

Going further

Some features of the Board Controller remain unsupported, such as a backlight PWM or internal EEPROMs. We did some attempts to implement a backlight driver without success for now. There are also plenty of Congatec boards to support (with more or less effort), so feel free to test and contribute!

Leave a Reply