Navigation

  1. Home
  2. Projects
  3. Blog
  4. Music
  5. Photos
  6. Contact
  1. Internal

glxiic - FreeBSD I2C driver for Geode LX

This is the project homepage for glxiic(4), a FreeBSD I2C bus driver for systems based on the AMD Geode LX chipset. The website hosts the driver and the corresponding documentation as well as a few patches for FreeBSD that were created when writing the driver.

Last updated: $Date: 2013/02/19 16:33:03 $.

Updates

Feb 19th, 2013

Make glxiic(4) work if loaded at boot time, too.

Jan 5th, 2013

HTML changes related to my home-grown "CMS."

Dec 20th, 2012

Found and corrected a few issues when trying to re-create my setup on FreeBSD 9.1, the latest release at this time.

Hardware

Some (most? all?) AMD Geode LX based designs use the AMD Geode CS5536 southbridge which integrates an I2C/SMBus master function. Alternatively, the same logic can be programmed to behave as an I2C/SMBus slave device. The glxiic(4) driver supports the I2C/SMBus master functionality in the CS5536 chip. The driver has been tested on an Alix 1.C board running FreeBSD 8.2 - other boards, similar chips and different versions of FreeBSD have not been tested.

Download

The source code of the glxisab as well as the glxiic driver can be downloaded from this location.

Installation

Update Dec 20th, 2012: I've found that loading the glxisab(4) driver as a module doesn't work on FreeBSD 9.1 anymore. Actually, I'm not sure if this ever worked. The solution is to compile the device into the kernel. The instructions below reflect that.

Here's a step-by-step tutorial on how to compile the driver into the kernel:

dev/glx/glx.c optional glx
dev/glx/glx_isab.c optional glx
hint.glxiic.0.at="isa"
hint.glxiic.0.irq="12"

Here is the same procedure in a more condensed version:

$ tar -xzvf glxiic.tgz
$ ln -s ./glxiic /usr/src/sys/modules/glx
$ ln -s ./glxiic /usr/src/sys/dev/glx
$ echo 'dev/glx/glx.c optional glx' >> /usr/src/sys/conf/files.i386
$ echo 'dev/glx/glx_isab.c optional glx' >> /usr/src/sys/conf/files.i386
$ cp /usr/src/sys/i386/conf/GENERIC /usr/src/sys/i386/conf/ALIX1C
$ echo 'glx' >> /usr/src/sys/i386/conf/ALIX1C
$ ( cd /usr/src && sudo make buildkernel KERNCONF=ALIX1C )
$ ( cd /usr/src && sudo make installkernel KERNCONF=ALIX1C )
$ cd glxiic
$ make && sudo make install
$ echo 'glxiic_load="YES"' >> /boot/loader.conf
$ echo 'hint.glxiic.0.at="isa"' >> /boot/device.hints
$ echo 'hint.glxiic.0.irq="12"' >> /boot/device.hints
$ sudo reboot
$ sudo kldload glxiic

Please note that in order to use the driver, you also need iicbus(4) as well as iic(4). Their usage is documented in the appropriate manual pages.

Architecture

The AMD Geode CS5536 contains what the data sheet calls "diverse integration logic" (DIVIL). The DIVIL block contains a bunch of devices that respond to legacy I/O ports such as a Programmable Interrupt Controller (PIC), AT Keyboard Controller, Real-time Clock (RTC) or Low Pin Count (LPC) bus controller. Those devices, if enabled, respond to the well known I/O port addresses of those functions.

In addition to the legacy devices, the DIVIL also contains the I2C/SMBus controller and a few other functions that respond to I/O ports configured in a Base Address Register (BAR).

To system software running on the host CPU, i.e. the host firmware or operating system, the DIVIL is represented as a function of a PCI device, a PCI-ISA bridge. Each of the BARs in the bridge's PCI configuration space configures the base address of one logic block in the DIVIL block.

On FreeBSD, the PCI bus code scans the configuration space of all PCI devices it finds and resumes responsibility for the resources announced in the device's configuration space. In addition to that, there is a generic PCI-ISA bridge driver that attaches to all PCI devices that announce themselves as a PCI-ISA bridge.

Because only direct child devices of the PCI bus driver can allocate those resources that a PCI device announces in its configuration space, and because the DIVIL block of the CS5536 south bridge announces a PCI-ISA bridge with a set of set up BARs, the glxiic(4) device driver needs to be split in two parts.

Geode LX PCI-ISA Bridge Driver

The glxisab driver is a replacement of the generic PCI-ISA bridge driver. It attaches to the device and vendor ID of the DIVIL function in the CS5536 south bridge. The driver assumes responsibility of all resources announced in the BARs and makes sure that child drivers of the ISA bus can allocate those resources. To prevent the generic PCI-ISA bridge driver from attaching to the device, the glxisab driver must be compiled into the kernel. Loading the module through /boot/loader.conf does not work for unkown reasons.

Geode LX I2C/SMBus Driver

The glxiic(4) driver is an ISA device driver. As such, it relies on information provided by the user via the /boot/device.hints file. Contrary to most ISA device drivers, the glxiic(4) driver can probe for the device and find out its I/O space addresses, but still requires the user to assign an interrupt.

The glxiic(4) driver provides an interface to the generic iicbus(4) driver which in turn provides an interface to the generic iic(4) driver which in turn creates a device node in /dev. This device node can be used from userland, e.g. via the i2c(8) utility, to control I2C devices attached to the bus.

In versions prior to v1.2, the glxiic(4) driver failed to allocate the required interrupt from the ISA bus when loaded at boot time. The work around was to load the kernel module after the kernel has booted up, either manually or through an init script. This issue has been fixed in v1.2 and the regular mechanism, i.e. loading the module at boot time via /boot/loader.conf works. For completeness, here's the line you need to add to /boot/loader.conf:

glxiic_load="YES"

Patches

When writing the device driver, a few patches to FreeBSD were created. All of them should apply to FreeBSD 8.2 but may also work for other versions of the FreeBSD source tree. All patches mentioned below can be applied by this command:

$ cd /usr/src
$ patch -p1 < /path/to/patch/file

i2c Utility

The i2c(8) utility is a little program using the iic(4) interface to access I2C devices. In my opinion, it lacked three features:

These issues are addressed by this patch.

Links

Here are a few links related to this project.

Contact

Contact the author Philip Schulz by Email.

Share