MCP23017
Our hackerspace’s access-control-system (for unlocking the door) uses a few mcp23017 port expanders for input/output handling of different sensors and actors. When I started working on this, the mcp23s08 driver (which also supports the mcp23017) was not yet enabled in Debian’s arm build. I requested it to be enabled in Debian Bug #845064, which got recently fixed by Ben Hutchings. As a quick hack to solve the problem I took the driver and ripped it out of the kernel, so that I can build it externally. Fortunately all dependencies were available from Debian’s kernel.
$ uname -a
Linux acs 4.8.0-1-armmp #1 SMP Debian 4.8.5-1 (2016-10-28) armv7l GNU/Linux
$ sudo apt-get install build-essential linux-headers-4.8.0-1-armmp
$ mkdir kernel-extra-module && cd kernel-extra-module
$ cp ~/src/linux/drivers/gpio/gpio-mcp23s08.c .
$ echo "obj-m += gpio-mcp23s08.o" >> Makefile
$ make -C /lib/modules/`uname -r`/build M=$PWD
$ make -C /lib/modules/`uname -r`/build M=$PWD modules_install
$ sudo depmod
Unfortunately I was lazy while soldering the PCB and did not add 32 pull-up resistors. Instead I relied on the port-expander’s built-in ones. Later I noticed, that they are not supported by the kernel driver (there is non-standard support if its probed via boardcode, but RPi uses DT). Instead of fixing it properly I decided to add a quick hack enabling all pull-ups and taking care of a proper patch later.
In the meantime a nasty HW bug occured, which resulted in a short power-loss of the mcp23017. Dumping the register values would have helped to find the issue, so another patch for the mcp23s08 driver on my TODO list was regmap usage inside of the driver. Usage of regmap inside of the driver reduces lines of code and easy debugging via regmap’s debugfs interface:
acs# cat /sys/kernel/debug/regmap/1-0021/registers
00: fffe
02: 0000
04: fffc
06: 0000
08: 0000
0a: 4848
0c: ffff
0e: 0000
10: fff3
12: fff7
14: 0101
I finally got around to do the necessary changes and sent them out, you can find the result here: https://lkml.org/lkml/2017/1/27/530
The DT snippet from below can be used to register the kernel driver with pull-ups enabled on all pins and single IRQ connected to gpio 23 from the SoC.
&i2c {
i2cgpio0: gpio@21 {
compatible = "microchip,mcp23017";
gpio-controller;
#gpio-cells = <0x2>;
reg = <0x21>;
interrupt-parent = <&socgpio>;
interrupts = <0x17 0x8>;
interrupt-controller;
#interrupt-cells = <0x2>;
microchip,irq-mirror;
pinctrl-names = "default";
pinctrl-0 = <&i2cgpio0irq &gpio21_pullups>;
gpio21_pullups: pinmux {
pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15";
bias-pull-up;
};
};
};