I2C GPIO expander boards on Torizon SBCs

Good Morning,
I’ve read the articles on how to program I2C on Torizon container(s). Basically, it all starts by installing I2Ctools which are then run on a shell commandline.

Has anybody had any experience with a Colibri (or other Toradex) board, implementing some common GPIO expander board (I need to have more IOs, and they shall be 5V tolerant) like those used for Raspberry or similar - e.g. based on Microchip MCP23017 silicon?

My target would be to make something similar to “libgpiod” and toggle/request I/O states by using shell commands. Then in turn, achieve the I/O toggling from within Nodered (this is easier maybe).

Thank you for any hint you can give me.
Kind Regards


Greetings @flavio.f,

An expander should certainly be doable, in fact we have other customers who’ve done something similar. One example is this thread here: Enable MCP23S17 driver on TorizonCore

This customer used a MCP23S17 16-Bit I/O Expander with SPI Interface. The one thing to keep in mind is making sure a driver for whatever expander you choose is available. If it’s available in the Linux kernel you can request we enable the driver if it’s not already available, similar to what the customer in this other thread did.

I don’t have too much other details to provide than that since I personally haven’t integrated such an expander myself. But judging from other customers it does seem certainly possible.

Best Regards,

Hi @jeremias.tx , thank you.

I was a bit puzzled from your reply, I try to explain why but as a premise consider that I am a newbie of Toradex (and very often… Linux) matters. I read all the links you sent me:

  • I understood it’s doable. I also have seen in attached files that’s already done, I mean: the same config/driver files managing MCP23S08 have also the companion expander chips, in my use case I’m interested in MCP23017 - so no worry to have I2C instead of SPI. That’s explained in the link inside the attached reply: pinctrl-mcp23s08.c
  • I also understand that probably last version of Torizon, which I’m using (5.7.1) already includes those configs and drivers and “they have been enabled”
  • given the above… still I don’t understand how to cope with that, i.e. how to manage those information and reach the target goal, that is to have a set of (shell) commands useful to act on expanded IO’s produced from GPIO expander board. Is there something regarding “device tree”? I’m completely ignorant about that…

I will go on and experiment today and in the next days; please if somebody can give me some other suggestions to progress the topic I’d be very much grateful.

Thanks again, Kind regards

Update after experimentation today

  • it’s confirmed pinctrl-mcp23s08 does exist in Linux kernel, and it can be enabled by modprobe pinctrl-mcp23s08; moreover it’s for sure compatible with my board (IO Pi Zero) that is based on MCP23017; but this way I’m not able to go any further
  • inside /sys/bus/i2c/drivers I was able to obtain new directory mcp230xx, but it’s probably not bound to the right device (that is electrically connected to pin 194/196 which is I2C out on IRIS carrier) - i2cdetect shows its address 0x20 on i2c–3, probably not the default that is i2c-1
  • there is another similar driver already present in my Torizon ( i found this directory: /sys/bus/i2c/drivers/pca953x ) that’s right the one of one other GPIO expander we bought. That one comes pre-installed (no modprobe) so I will try that also - even if I don’t know then how to access the device from kernel space. Maybe it’s better to revert to some code from user-space
    (in relation to article: How to use I2C on Torizon ).

So in the end, which is the best way to install these drivers and access these peripherals? “best” means lowest effort in programming… Even though maybe I’m missing how to properly work with i2c-3 since the booting of the device…

Hope someone can help.
Thanks again, kind regards.


The first step to adding any peripheral is to modify the device tree so that the kernel knows about the existence of your peripheral. The Linux kernel source has documentation on how the device tree bindings for this peripheral should be formatted: pinctrl-mcp23s08.txt « pinctrl « bindings « devicetree « Documentation - linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules

However, seeing as you’re new to Linux you probably are not familiar with the device tree. We have some documentation on device trees on our developer site, but it’s not really an intro topic for someone new to Linux. Since the peripheral here is a not a Toradex peripheral, our own knowledge on it’s use and function is quite limited so the best i can do is refer you to existing kernel documentation like above.

Best Regards,

Hi @jeremias.tx
Thanks for your hints and link. I would like to go deeper into this topic, if you think I should read some other tutorial or Toradex’s document about how to cope with “device trees” please I would be glad to have other links.
Consider that I’m working on Toradex iMX7D 1Gb with Torizon and evaluation containers at the moment.

Thanks again and Kind Regards,

Hi @flavio.f !

I would like to share some links with you about device tree:

Maybe those will help you.

Best regards,

Many Thanks @henrique.tx !!!
Will try my best to exploit those links and get to the desided result.

Best Regards

1 Like

Good afternoon,

I’m struggling to get this mcp23017 accepted by the Torizon OS. I’ve read all the aforementioned links. In particular, I found useful (based on this example) to try to customize the Device Tree files by adding my own “carrier board dtsi overlay file” based on an existing file, this way:

  • chosen imx7-colibri-eval-v3.dtsi as DT file to modify, put a correspondingg “include” into father dts file (should be
  • modified &i2c4 section in order to have not only the (Iris, or Colibri v3 carrier) on-board RTC chip, but also my GPIO expander addressed @ 0x20:

&i2c4 {
status = “okay”;

/* M41T0M6 real time clock on carrier board */
rtc: m41t0m6@68 {
compatible = “st,m41t0”;
reg = <0x68>;

/* Microchip MCP23017 GPIO Expander */
gpio20: gpio@20 {
compatible = “microchip,mcp23017”;
#gpio-cells = <2>;
reg = <0x20>;

  status = "okay";


  • then followed other suggested article, to brew the new Torizon image file via torizoncore-builder build and then deployment via SSH on the SBC (imx7d + IRIS)

Then the result is… new Torizon image “built by me” was deployed, happy and running; lsmod also suggested that the needed driver is present, although i2cdetect stills presents the two mcp23017 chips as address 0x20 and 0x21 (my expander has two chips; I supposed at least 0x20 should have been reserved by kernel, hence shown as UU). Comparing file system at address 0x68 (rtc) and 0x20 of I2C bus suggests that… maybe something is missing on 0x20 (my first GPIO expander chip) side.

Probably I’m going nowhere by trying to implement this at kernel level… Still I’m not sure I will be able to use the same gpioset and gpioread standard tools even in the best situation where I’m able to get to the desired goal to have a new /dev/gpiochipXX which is pointing exactly at I2C expander device.
As a last resort I will need to write c or python code to access exp GPIOs from user code.

Hope someone can help…
Thanks, regards


Hi again,
just to give an update: the kernel approach with the customization of device-tree was successful (as described above). I was suffering a hardware problem on expander board, that was the reason the o.s. was unable to talk with expanded gpio’s.
Now (on iMx7d) I can see a “/dev/gpiochip7” which is labeled [mcp23017] and is associated to16 lines, that are right the I/Os i need for my application.
So, thanks indeed for the support!

Now I have another question: i want to run libgpiod and gpiotools outside of the container, on Torizon. I need to access to GPIO’s at a system level, can’t understand why they are not active by default on “torizon with containers” image. Will open a new post however.

kind regards,

imx7d-colibri-emmc-eval-v3.dts (473 Bytes)
imx7-colibri-mycarrier.dtsi (4.5 KB)
tcbuild.yaml (4.9 KB)
Good morning community,
sorry to have to re-open this thread that I thought it was solved.

To be honest, i made an additional test of building a TorizonCore with modified devicetree, and sadly discovered that my MCP23017 gpio expander board is not working anymore. The sad thing is that I used exactly the same device-tree modified files (trying to attach them)… - and the same imx7d board :sob:. I am 100% sure the hardware is ok; the bad symptoms I have are:

  • lsmod: it doesn’t show pinctrl_mcp23s08 after boot
  • when i do modprobe pinctrl_mcp23s08 it gets loaded, but still not handled properly
  • i2cdetect continue to show something attached to i2c-3 at address 0x20, but shows “20” and not “UU”
  • consequently, the loaded driver does only produce corresponding /sys/bus/i2c/drivers/mcp230xx folder, but inside there’s no link to gpiochip
  • gpiochip7 does not appear by itself anymore, so I’m not able to access gpio expander pins from kernel.

Do you have any hints on how to proceed to investigate and try to fix? Unfortulately, I burned two times the TorizonCore on the same board, so there’s no way to recover from past.

Any suggestion is greatly appreciated (…as I’m in big trouble)
Thanks & kind regards


My fault, for some reasons from this page regarding torizoncore-builder I forgot the most important step before deploying (via SSH) to the target: which is the UNPACKing:

$ torizoncore-builder images unpack torizon-core-docker-colibri-imx6-Tezi_5.3.0.CUSTOM

I was burning again and again the same (Toradex’s) image… I only started to suspect something as soon as I realized that what I was deploying had the same sha256 checksum…

It’s all good stuff I learnt however.
Sorry for my continuous “stalking”

Kind Regards,