User avatar
DougieLawson
Posts: 42760
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK

Re: devicetree overlay for MCP23017 GPIO expander

Tue Jan 24, 2017 12:38 pm

I hate to appear stupid, but where's the documentation for using this overlay?

What are the names/numbers needed for echo commands in /sys/class/gpio? What do you have to echo to /sys/class/gpio/export to use the various MCP23017 pins (just plain GPIOA/OLATA & GPIOB/OLATB not the funky INTA/INTB stuff)?
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5577
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: devicetree overlay for MCP23017 GPIO expander

Tue Jan 24, 2017 12:48 pm

/boot/overlays/README (or "dtoverlay -h mcp23017") documents the overlay, but the overlay documentation is not the documentation for using the device under Linux - that would be duplication.

You may get some hints from the start of this thread: viewtopic.php?t=104638&p=739043

User avatar
DougieLawson
Posts: 42760
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK

Re: devicetree overlay for MCP23017 GPIO expander

Tue Jan 24, 2017 1:49 pm

PhilE wrote:/boot/overlays/README (or "dtoverlay -h mcp23017") documents the overlay, but the overlay documentation is not the documentation for using the device under Linux - that would be duplication.

You may get some hints from this thread: viewtopic.php?t=104638&p=739043
That's my exact point. There is NO documentation for it (I'd already studied that other thread). If I want to use this thing I'm going to have to start reading Linux kernel source and understanding the device tree overlay. That means it's 100% unusable for regular users.

Also it's not clear what happens if I have more than one MCP23017 connected on the same Raspberry (which curiously I do have). Can they both be driven with the overlay. If one is 0x20 and the other is 0x27 how does that affect the /sys/class/gpio stuff?
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5577
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: devicetree overlay for MCP23017 GPIO expander

Tue Jan 24, 2017 2:04 pm

There is a Device Tree parameter to enable the SPI interface, but the documentation for it doesn't tell you how to use SPI. The overlay documentation only tells you how to use the overlays, not how to use the things enabled by the overlays.

> If I want to use this thing I'm going to have to start reading Linux kernel source and understanding the device tree overlay

How the driver functions is completely independent of how it is loaded. If you don't want to use the overlay, you can still load mcp23017 like any other I2C driver - the overlay just makes it more convenient.

Like most other users, if you want to use the mcp23017 you are going to have to read around or find a tutorial somebody else has written. Most of the modules shipped with the Pi kernels will never be used by most users, and making use of them requires locating external resources. That doesn't mean we shouldn't include them, and it doesn't mean that by including them we are taking on the burden of supporting and documenting them.

User avatar
DougieLawson
Posts: 42760
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK

Re: devicetree overlay for MCP23017 GPIO expander

Tue Jan 24, 2017 3:17 pm

I've started reading the code.

sudo -i
cd /sys/class/gpio
for i in $(seq $(cat gpiochip496/base) $(($(cat gpiochip496/base) + $(cat gpiochip496/ngpio) -1))); do echo $i > export; done

gets the device at 0x20 set up.
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.

wavelet
Posts: 17
Joined: Mon Mar 21, 2016 7:15 pm

Re: devicetree overlay for MCP23017 GPIO expander

Sun Jan 29, 2017 4:32 pm

Sorry, I haven't visited this forum in a while. To answer some of DougieLawson's questions:

- The documentation for the sysfs interface to GPIO (i.e. all those 'echo' commands) is here: http://www.kernel.org/doc/Documentation/gpio/sysfs.txt. I'm sure there are other tutorials out there on the web.

- W.r.t. enabling two MCP23017 devices on an I2C bus, unfortunately the device overlay written by MikeDK (which is now part of the official Raspberry Pi kernel software) only supports one device at address 0x20. Until such time as someone writes a parameterised version of that overlay (I'd be willing to give it a go but have no I2C h/w to test it on), your best option is probably to write your own overlay. For 2 devices at 0x20 and 0x27 and assuming the device at 0x27 will not be generating interrupts, you could try something like:

Code: Select all

/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";

	fragment@0 {
		target = <&i2c1>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@1 {
		target = <&gpio>;
		__overlay__ {
			mcp23017_pins: mcp23017_pins {
				brcm,pins = <4>;
				brcm,function = <0>;
			};
		};
	};

	fragment@2 {
		target = <&i2c1>;
		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;

			mcp23017: mcp@20 {
				compatible = "microchip,mcp23017";
				reg = <0x20>;
				gpio-controller;
				#gpio-cells = <2>;
				#interrupt-cells=<2>;
				interrupt-parent = <&gpio>;
				interrupts = <4 2>;
				interrupt-controller;
				microchip,irq-mirror;

			mcp23017_2: mcp@27 {
				compatible = "microchip,mcp23017";
				reg = <0x27>;
				gpio-controller;
				#gpio-cells = <2>;

				status = "okay";
			};
		};
	};
	
	__overrides__ {
		gpiopin = <&mcp23017_pins>,"brcm,pins:0",
				<&mcp23017>,"interrupts:0";
		addr = <&mcp23017>,"reg:0";
	};
};
Call this file something like mcp23017x2-overlay.dts and compile it as follows:

Code: Select all

sudo apt-get install device-tree-compiler
dtc -@ -I dts -O dtb -o mcp23017x2.dtbo mcp23017x2-overlay.dts
Then copy the mcp23017x2.dtbo file to /boot/overlays and edit your config.txt file to call it rather than mcp23017.dtbo.

(As an aside, the documentation for what needs to go into a devicetree spec for the Microchip devices is here: http://www.kernel.org/doc/Documentation ... p23s08.txt

wavelet

User avatar
DougieLawson
Posts: 42760
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK

Re: devicetree overlay for MCP23017 GPIO expander

Sun Jan 29, 2017 5:23 pm

I tried the overlay with my MCP23017 @ 0x20 and it's just too slow to be usable. I'll stick with python with smbus or writing stuff to /dev/i2c-1 in C programs. That piece got removed from /boot/config.txt on the next reboot.
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.

dloranger
Posts: 53
Joined: Wed Nov 02, 2016 1:56 am
Location: Seattle

Re: devicetree overlay for MCP23017 GPIO expander

Sat May 27, 2017 11:24 pm

I am having some issues trying to use this MCP23017 overlay, specifically how are the pins mapped back into the /sys/class/gpio?

My understanding is that A0 gets mapped to GPIO511, and then counts down, but I can't find where any of this is actually documented. Likely I missed it, but hoping one of the devs can get me pointed in the right direction.

I have the device loading into system controls, but I can't get the pins to actually do anything when using the export and writing to the direction and values fields.

If I remove the overlay and manually write the registers I can get the pins (B1 & B2) to toggle so I know the hardware is fine, but have yet to be able to actually get them to toggle using the export under system control.

Thanks

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5577
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: devicetree overlay for MCP23017 GPIO expander

Tue May 30, 2017 8:44 am

I don't have one of these device to test with, but you should be able to find the information you need from /sys/class/gpio. Try this command:

Code: Select all

pi@raspberrypi ~ $ grep -d skip . /sys/class/gpio/*/*
/sys/class/gpio/gpiochip0/base:0
/sys/class/gpio/gpiochip0/label:pinctrl-bcm2835
/sys/class/gpio/gpiochip0/ngpio:54
/sys/class/gpio/gpiochip100/base:100
/sys/class/gpio/gpiochip100/label:brcmvirt-gpio
/sys/class/gpio/gpiochip100/ngpio:2
/sys/class/gpio/gpiochip128/base:128
/sys/class/gpio/gpiochip128/label:brcmexp-gpio
/sys/class/gpio/gpiochip128/ngpio:8
The grep is just a way of showing file names and contents.

Each "chip" has a label, base and ngpio. The file "label" identifies the driver, "base" contains the number of the first gpio, while "ngpio" tells you how many there are, so the output above tells use that the pinctrl-bcm2835 driver gives access to GPIOs 0-53. I expect the MCP23017 driver to appear as "gpio-mcp23xxx", with ngpio set to 16.

For your application you can either programmatically search for the directory under /sys/class/gpio with the correct label and read the contents of "base" - this is the "right" way to do it - or you can try it once by hand and hard-code the values.

ahmedawad
Posts: 42
Joined: Mon Apr 18, 2016 11:44 am
Location: Bremen, DE

Re: devicetree overlay for MCP23017 GPIO expander

Mon Aug 21, 2017 8:11 am

@wavelet, I tested the interrupt functionality of mcp23s17 and it is not working. please can you refer to my post viewtopic.php?f=107&t=191022

I think that the official mcp23s17.dtbo is exactly the same as your .dts which you previously posted, So if you tested the interrupt functionality, that one should work as well.

Thanks.

wavelet
Posts: 17
Joined: Mon Mar 21, 2016 7:15 pm

Re: devicetree overlay for MCP23017 GPIO expander

Sat Aug 26, 2017 10:56 am

I've posted a reply to that thread suggesting one possibility - you may not have enabled the appropriate edge detection in the input port via the sysfs "edge" path.
The only testing I did was on a device connected to SPI0, I'm afraid.
wavelet

mapart
Posts: 3
Joined: Wed Nov 08, 2017 6:35 am

Re: devicetree overlay for MCP23017 GPIO expander

Wed Nov 08, 2017 7:09 am

Hi,

I'm trying to get buttons connected to the MCP23017 pins to act as keyboard input using gpio-keys. Is this possible?
The mcp23017 overlay loads correctly and I can export and read button values using the /sys/class/gpio(496-511) interface.
But when I load my overlay to get the buttons as keyboard input nothing happens.

Code: Select all

/dts-v1/;
    /plugin/;
    / {
       compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";

       fragment@0 {
          target-path = "/";
          __overlay__ {
             keypad: joystick_keys {
                compatible = "gpio-keys";
                #address-cells = <1>;
                #size-cells = <0>;
                autorepeat;
                button@502 {
                   label = "joystick up";
                   linux,code = <103>;
                   gpios = <&gpio 502 1>;
                };
                button@501 {
                   label = "joystick down";
                   linux,code = <108>;
                   gpios = <&gpio 501 1>;
                };
                button@503 {
                   label = "joystick left";
                   linux,code = <105>;
                   gpios = <&gpio 503 1>;
                };
                button@500 {
                   label = "joystick right";
                   linux,code = <106>;
                   gpios = <&gpio 500 1>;
                };
             };
          };
       };
    };
If I instead use gpios on the raspberry pi (00-53) it works perfectly.
Where should I start looking to debug this?

Many thanks in advance!
/Martin

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5577
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: devicetree overlay for MCP23017 GPIO expander

Wed Nov 08, 2017 11:44 am

GPIO descriptors in device tree comprise a reference to a label/phandle for the controller, an identifier for the GPIO itself and usually a mode (active high/low etc.). The kernel takes the GPIOs from all of the GPIO controllers and maps them into a global "GPIO address space". What you see as GPIO 500 is probably actually GPIO index 0 provided by the MCP23017.

Your overlay needs to reference the mcp23017 GPIO controller node, and to use the indexes understood by the controller. Overlay labels don't normally make it into the global namespace for other overlays to use, so you either need to combine the mcp23017 overlay with the GPIO keys overlay or get the mcp23017 overlay to export its label - the i2c-gpio overlay uses this trick:

Code: Select all

...
	
	fragment@0 {
		target-path = "/";
		__overlay__ {
			i2c_gpio: i2c@0 {
				compatible = "i2c-gpio";
				gpios = <&gpio 23 0 /* sda */
					 &gpio 24 0 /* scl */
					>;
...

	fragment@1 {
		target-path = "/aliases";
		__overlay__ {
			i2c_gpio = "/i2c@0";
		};
	};

	fragment@2 {
		target-path = "/__symbols__";
		__overlay__ {
			i2c_gpio = "/i2c@0";
		};
	};

...
Overlays loaded after i2c-gpio can use "&i2c_gpio" instead of e.g. "&i2c1".

MyTechGuyRI
Posts: 2
Joined: Mon Mar 11, 2019 11:45 am

Re: devicetree overlay for MCP23017 GPIO expander

Mon Mar 11, 2019 11:57 am

Sorry to be resurrecting a long dormant thread, but this seems most relevant to the issue I'm having. Any assistance/guidance is GREATLY appreciated.

So, ive got an mcp23017 expander, the INTA pin is wired to gpio12
Im loading the 23017 overlay, and specifying gpio12 correctly.
I can export the pins and read and write values using sysfs.

The problem that comes is I'm having tremendous difficulty getting edge detect interrupts to work.

I set gpio502 edge to both in sysfs
In /proc/interrupts, i can see the interrupt count going up on gpio12 and gpio502 every time i trigger an event.

But my python code, using RPi.GPIO is not seein any interrupts on gpio12 whatsoever.

Now i do note, i am not able to set /sys/class/gpio/gpio12/edge value at all...once the kernel driver is loaded... Its set to "none" (level) and cannot be changed.... Could this be why RPi.GPIO is not seeing the interrupts, because my code is looking for either edge? I'm also not seeing the value of gpio12 change... Even polling, it remains high all the time regardless of if interrupts are triggered or not, and it never seems to go low.

I really need to get interrupts working, as polling the pins is keeping the cpu at 90%

I'm just at a loss... Everything says this should be working.... It simply doesn't.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5577
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: devicetree overlay for MCP23017 GPIO expander

Mon Mar 11, 2019 12:55 pm

What is your python code trying to do with the interrupt? That pin has already been claimed by the kernel driver, and it is rarely a good idea to have the same hardware driven by multiple bits of software.

MyTechGuyRI
Posts: 2
Joined: Mon Mar 11, 2019 11:45 am

Re: devicetree overlay for MCP23017 GPIO expander

Tue Mar 12, 2019 3:05 am

I'm merely trying to detect the interrupt so that i can read pins when there has been a change... Thats kind if the whole point of the interrupt being there, isn't it?

I simply want to have my code wait for the interrupt, and when detected, execute a callback to read 4 pins of the mcp23017 using sysfs
Otherwise, I'm left polling and eating up cpu resources.

My code is at
https://github.com/mytechguyri/dtmfdeco ... ts?files=1

Whats not working is
GPIO.add_event_detect(12, GPIO.BOTH, callback=getDigit, bouncetime=100)

Its never seeing the interrupt, so never hitting the callback.

User avatar
joan
Posts: 16257
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: devicetree overlay for MCP23017 GPIO expander

Tue Mar 12, 2019 9:20 am

Have you a spare GPIO? Connect a wire from GPIO 12 to the spare GPIO and use the spare GPIO in the add event detect.

Does this let you see the interrupt?

rudiratlos
Posts: 246
Joined: Tue May 01, 2012 8:47 am
Location: Germany (old europe)

Re: devicetree overlay for MCP23017 GPIO expander

Mon Jul 27, 2020 8:09 am

I've got this dmesg error, trying to load mcp23017 overlay (/boot/config.txt entry: dtoverlay=mcp23017,addr=0x20)
root@pump:/home/pi# dtoverlay -l
No overlays loaded
root@pump:/home/pi# uname -a
Linux pump 5.4.51-v7l+ #1326 SMP Fri Jul 17 10:51:18 BST 2020 armv7l GNU/Linux

Code: Select all

[    6.149353] ------------[ cut here ]------------
[    6.149374] WARNING: CPU: 3 PID: 289 at drivers/gpio/gpiolib.c:3969 gpiochip_enable_irq+0x78/0xa4
[    6.149377] Modules linked in: pinctrl_mcp23s08(+) rtc_ds1307 regmap_i2c brcmfmac brcmutil sha256_generic libsha256 raspberrypi_hwmon cfg80211 i2c_mux_pinctrl i2c_mux rfkill snd_bcm2835(C) bcm2835_codec(C) bcm2835_v4l2(C) snd_pcm dwc2 bcm2835_isp(C) v4l2_mem2mem bcm2835_mmal_vchiq(C) snd_timer videobuf2_vmalloc videobuf2_dma_contig videobuf2_memops videobuf2_v4l2 videobuf2_common videodev snd mc vc_sm_cma(C) i2c_bcm2835 spidev rpivid_mem uio_pdrv_genirq uio libcomposite udc_core i2c_dev spi_bcm2835 ip_tables x_tables ipv6 nf_defrag_ipv6
[    6.149432] CPU: 3 PID: 289 Comm: modprobe Tainted: G         C        5.4.51-v7l+ #1326
[    6.149435] Hardware name: BCM2711
[    6.149438] Backtrace: 
[    6.149451] [<c020d46c>] (dump_backtrace) from [<c020d768>] (show_stack+0x20/0x24)
[    6.149456]  r6:e41b2000 r5:00000000 r4:c129c8f8 r3:3ce96370
[    6.149465] [<c020d748>] (show_stack) from [<c0a39984>] (dump_stack+0xe0/0x124)
[    6.149472] [<c0a398a4>] (dump_stack) from [<c0221c50>] (__warn+0xec/0x104)
[    6.149477]  r8:00000f81 r7:00000009 r6:c0df6d98 r5:00000000 r4:00000000 r3:3ce96370
[    6.149484] [<c0221b64>] (__warn) from [<c0221d20>] (warn_slowpath_fmt+0xb8/0xc0)
[    6.149489]  r9:c0df6d98 r8:00000f81 r7:c06a2140 r6:00000009 r5:00000000 r4:c1204f88
[    6.149495] [<c0221c6c>] (warn_slowpath_fmt) from [<c06a2140>] (gpiochip_enable_irq+0x78/0xa4)
[    6.149500]  r9:e41337c8 r8:00000000 r7:00000000 r6:e4133714 r5:efbd0538 r4:efbd0c40
[    6.149505] [<c06a20c8>] (gpiochip_enable_irq) from [<c06a2194>] (gpiochip_irq_enable+0x28/0x48)
[    6.149509]  r4:e4133714 r3:c06a216c
[    6.149517] [<c06a216c>] (gpiochip_irq_enable) from [<c0288b5c>] (irq_enable+0x5c/0x84)
[    6.149521]  r5:00000000 r4:e4133700
[    6.149528] [<c0288b00>] (irq_enable) from [<c0288c04>] (__irq_startup+0x80/0xbc)
[    6.149531]  r4:e4133700 r3:c126623c
[    6.149538] [<c0288b84>] (__irq_startup) from [<c0288c98>] (irq_startup+0x58/0x154)
[    6.149542]  r6:00000001 r5:e4133700 r4:00000000 r3:00000508
[    6.149549] [<c0288c40>] (irq_startup) from [<c0285d3c>] (__setup_irq+0x758/0x828)
[    6.149553]  r8:0000003c r7:00000000 r6:c1204f88 r5:e4eb6740 r4:e4133700 r3:00000508
[    6.149560] [<c02855e4>] (__setup_irq) from [<c0285f98>] (request_threaded_irq+0xe8/0x158)
[    6.149565]  r10:e4133714 r9:bf1a2fc4 r8:0000003c r7:e4133700 r6:c0283b98 r5:e4eb6740
[    6.149568]  r4:00000000
[    6.149574] [<c0285eb0>] (request_threaded_irq) from [<c0289d3c>] (devm_request_threaded_irq+0x74/0xc8)
[    6.149578]  r10:00000000 r9:e4545020 r8:bf1a2fc4 r7:0000003c r6:e4710c40 r5:e4785340
[    6.149582]  r4:e47b1b00 r3:00002088
[    6.149600] [<c0289cc8>] (devm_request_threaded_irq) from [<bf1a2d98>] (mcp23s08_probe_one+0x4ec/0x60c [pinctrl_mcp23s08])
[    6.149605]  r10:e4710c40 r9:00000000 r8:00000000 r7:bf1a6100 r6:00000010 r5:c1204f88
[    6.149608]  r4:00000000
[    6.149619] [<bf1a28ac>] (mcp23s08_probe_one [pinctrl_mcp23s08]) from [<bf1a2f98>] (mcp230xx_probe+0xe0/0x10c [pinctrl_mcp23s08])
[    6.149624]  r10:00000022 r9:00000003 r8:e4545020 r7:e41b3bdc r6:c1204f88 r5:e4545000
[    6.149627]  r4:e4710c40
[    6.149638] [<bf1a2eb8>] (mcp230xx_probe [pinctrl_mcp23s08]) from [<c0855bc4>] (i2c_device_probe+0x200/0x294)
[    6.149643]  r9:bf1a6074 r8:00000000 r7:e4545000 r6:bf1a6074 r5:bf1a2eb8 r4:e4545020
[    6.149652] [<c08559c4>] (i2c_device_probe) from [<c075eee4>] (really_probe+0x1ec/0x360)
[    6.149657]  r8:00000000 r7:c135da78 r6:00000000 r5:e4545020 r4:c135da74 r3:c08559c4
[    6.149664] [<c075ecf8>] (really_probe) from [<c075f254>] (driver_probe_device+0x70/0x1ac)
[    6.149668]  r10:e47ae8e4 r9:e47ae8c0 r8:00000000 r7:c1204f88 r6:bf1a6074 r5:bf1a6074
[    6.149672]  r4:e4545020 r3:00000000
[    6.149678] [<c075f1e4>] (driver_probe_device) from [<c075f588>] (device_driver_attach+0x68/0x70)
[    6.149683]  r9:e47ae8c0 r8:00000000 r7:c1204f88 r6:bf1a6074 r5:e4545020 r4:00000000
[    6.149690] [<c075f520>] (device_driver_attach) from [<c075f620>] (__driver_attach+0x90/0xcc)
[    6.149694]  r6:e4545020 r5:bf1a6074 r4:00000000 r3:c127f7f4
[    6.149700] [<c075f590>] (__driver_attach) from [<c075cc64>] (bus_for_each_dev+0x78/0xc4)
[    6.149705]  r6:c075f590 r5:bf1a6074 r4:00000000 r3:0000001d
[    6.149711] [<c075cbec>] (bus_for_each_dev) from [<c075e740>] (driver_attach+0x2c/0x30)
[    6.149715]  r7:00000000 r6:e4785a80 r5:c127f838 r4:bf1a6074
[    6.149721] [<c075e714>] (driver_attach) from [<c075e0c8>] (bus_add_driver+0x140/0x1f8)
[    6.149727] [<c075df88>] (bus_add_driver) from [<c075fcd8>] (driver_register+0x8c/0x124)
[    6.149732]  r7:c1204f88 r6:e41b2000 r5:bf006000 r4:bf1a6074
[    6.149738] [<c075fc4c>] (driver_register) from [<c085650c>] (i2c_register_driver+0x4c/0x94)
[    6.149742]  r5:bf006000 r4:bf1a6058
[    6.149751] [<c08564c0>] (i2c_register_driver) from [<bf006040>] (mcp23s08_init+0x40/0x1000 [pinctrl_mcp23s08])
[    6.149755]  r5:bf006000 r4:00000000
[    6.149765] [<bf006000>] (mcp23s08_init [pinctrl_mcp23s08]) from [<c02031c8>] (do_one_initcall+0x50/0x23c)
[    6.149768]  r4:bf1a6100 r3:3ce96370
[    6.149776] [<c0203178>] (do_one_initcall) from [<c02c37e4>] (do_init_module+0x70/0x23c)
[    6.149781]  r9:e47ae8c0 r8:00000001 r7:00000001 r6:c1204f88 r5:e47aef80 r4:bf1a6100
[    6.149787] [<c02c3774>] (do_init_module) from [<c02c2714>] (load_module+0x1e78/0x2408)
[    6.149791]  r6:c1204f88 r5:bf1a6100 r4:e41b3f28
[    6.149797] [<c02c089c>] (load_module) from [<c02c2ebc>] (sys_finit_module+0xbc/0xcc)
[    6.149802]  r10:0000017b r9:00000000 r8:7fffffff r7:0002d064 r6:00000003 r5:00000000
[    6.149805]  r4:c1204f88
[    6.149812] [<c02c2e00>] (sys_finit_module) from [<c02011a4>] (__sys_trace_return+0x0/0x1c)
[    6.149815] Exception stack(0xe41b3fa8 to 0xe41b3ff0)
[    6.149820] 3fa0:                   3a42c800 00000000 00000003 0002d064 00000000 0002ec3c
[    6.149825] 3fc0: 3a42c800 00000000 00000000 0000017b 0011f2a8 00000000 0011f100 00000000
[    6.149830] 3fe0: bec89988 bec89978 00022cb8 b6c5aaf0
[    6.149834]  r9:e41b2000 r8:c02011c4 r7:0000017b r6:00000000 r5:00000000 r4:3a42c800
[    6.149838] ---[ end trace 9ae7422efa22c09e ]---

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5577
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: devicetree overlay for MCP23017 GPIO expander

Mon Jul 27, 2020 9:13 am

The kernel is complaining that a GPIO being configured as an interrupt source is an output but not an open-drain output - a reasonable thing to warn about. Interrupt sources are usually inputs (the BCM2835 GPIO block doesn't do open-drain), so this is puzzling.

dloranger
Posts: 53
Joined: Wed Nov 02, 2016 1:56 am
Location: Seattle

Re: devicetree overlay for MCP23017 GPIO expander

Thu Jul 30, 2020 6:43 pm

I use these devices frequently but I keep running up against an issue that I can get around, but hope there is a better approach

I currently have working qty 3 of these devices (0x25,0x26,0x27), and I have hand mapped the GPIO numbers to my circuit board, this is all fine and stable.

now my challenge,

I have an optional accessory board that adds 0x24 to the list. When I updated the overlay to add the new additional device, all my gpio are now not working, they appear to have shifted their assigned offsets (assuming by 16, not yet triaged) in response to the new device.

My question is, Is there a method in the overlay to force set the A0 pin gpio starting point, so I can for example set 0x27/A0 to be at GPIO496, A1=497 (auto incremented, A2 ..B8)

Code: Select all

// Definitions for MCP23017 Gpio Extender from Microchip Semiconductor

/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";

	fragment@0 {
		target = <&i2c1>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@1 {
		target = <&gpio>;
		__overlay__ {
			mcp23017_pins: mcp23017_pins {
				brcm,pins = <4>;
				brcm,function = <0>;
			};
		};
	};

	fragment@2 {
		target = <&i2c1>;
		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;

			mcp23017_27: mcp@27 {
				compatible = "microchip,mcp23017";
				reg = <0x27>;
				gpio-controller;
				#gpio-cells = <2>;
				#interrupt-cells=<2>;
				interrupt-parent = <&gpio>;
				interrupts = <23 2>;
				interrupt-controller;
				microchip,irq-mirror;

				status = "okay";
			};
		};
	};
	
	fragment@3 {
		target = <&i2c1>;
		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;

			mcp23017_26: mcp@26 {
				compatible = "microchip,mcp23017";
				reg = <0x26>;
				gpio-controller;
				#gpio-cells = <2>;
				#interrupt-cells=<2>;
				interrupt-parent = <&gpio>;
				interrupts = <24 2>;
				interrupt-controller;
				microchip,irq-mirror;

				status = "okay";
			};
		};
	};
	
	fragment@4 {
		target = <&i2c1>;
		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;

			mcp23017_25: mcp@25 {
				compatible = "microchip,mcp23017";
				reg = <0x25>;
				gpio-controller;
				#gpio-cells = <2>;
				#interrupt-cells=<2>;
				interrupt-parent = <&gpio>;
				interrupts = <25 2>;
				interrupt-controller;
				microchip,irq-mirror;

				status = "okay";
			};
		};
	};
	
	fragment@5 {
		target = <&i2c1>;
		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;

			mcp23017_24: mcp@24 {
				compatible = "microchip,mcp23017";
				reg = <0x24>;
				gpio-controller;
				#gpio-cells = <2>;
				#interrupt-cells=<2>;
				interrupt-parent = <&gpio>;
				interrupts = <13 2>;
				interrupt-controller;
				microchip,irq-mirror;

				status = "okay";
			};
		};
	};	
	fragment@6 {
        target = <0xffffffff>;
        __overlay__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            status = "okay";
            ads1015_48 {
                compatible = "ti,ads1015";
                status = "okay";
                #address-cells = <0x1>;
                #size-cells = <0x0>;
                reg = <0x48>;
                phandle = <0x1>;
            };
        };
    };
	
	fragment@11 {
        target = <0xffffffff>;
        __overlay__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            status = "okay";
            ads1015_49 {
                compatible = "ti,ads1015";
                status = "okay";
                #address-cells = <0x1>;
                #size-cells = <0x0>;
                reg = <0x49>;
                phandle = <0x10>;
            };
        };
    };
    fragment@7 {
        target-path = "i2c_arm/ads1015_48";
        __overlay__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            channel_a {
                reg = <0x4>;
                ti,gain = <0x2>;
                ti,datarate = <0x4>;
                phandle = <0x2>;
            };
        };
    };
    
    fragment@12 {
        target-path = "i2c_arm/ads1015_49";
        __overlay__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            channel_a {
                reg = <0x4>;
                ti,gain = <0x2>;
                ti,datarate = <0x4>;
                phandle = <0x11>;
            };
        };
    };
    fragment@8 {
        target-path = "i2c_arm/ads1015_48";
        __dormant__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            channel_b {
                reg = <0x5>;
                ti,gain = <0x2>;
                ti,datarate = <0x4>;
                phandle = <0x3>;
            };
        };
    };
    
    fragment@13 {
        target-path = "i2c_arm/ads1015_49";
        __dormant__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            channel_b {
                reg = <0x5>;
                ti,gain = <0x2>;
                ti,datarate = <0x4>;
                phandle = <0x12>;
            };
        };
    };
    fragment@9 {
        target-path = "i2c_arm/ads1015_48";
        __dormant__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            channel_c {
                reg = <0x6>;
                ti,gain = <0x2>;
                ti,datarate = <0x4>;
                phandle = <0x4>;
            };
        };
    };
    
    fragment@14 {
        target-path = "i2c_arm/ads1015_49";
        __dormant__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            channel_c {
                reg = <0x6>;
                ti,gain = <0x2>;
                ti,datarate = <0x4>;
                phandle = <0x13>;
            };
        };
    };
    fragment@10 {
        target-path = "i2c_arm/ads1015_48";
        __dormant__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            channel_d {
                reg = <0x7>;
                ti,gain = <0x2>;
                ti,datarate = <0x4>;
                phandle = <0x5>;
            };
        };
    };
    
    fragment@15 {
        target-path = "i2c_arm/ads1015_49";
        __dormant__ {
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            channel_d {
                reg = <0x7>;
                ti,gain = <0x2>;
                ti,datarate = <0x4>;
                phandle = <0x14>;
            };
        };
    };
    
    __symbols__ {
        ads1015_48 = "/fragment@5/__overlay__/ads1015_48";
        channel_a = "/fragment@6/__overlay__/channel_a";
        channel_b = "/fragment@7/__dormant__/channel_b";
        channel_c = "/fragment@8/__dormant__/channel_c";
        channel_d = "/fragment@9/__dormant__/channel_d";
        
        ads1015_49 = "/fragment@10/__overlay__/ads1015_49";
        channel_e = "/fragment@11/__overlay__/channel_a";
        channel_f = "/fragment@12/__dormant__/channel_b";
        channel_g = "/fragment@13/__dormant__/channel_c";
        channel_h = "/fragment@14/__dormant__/channel_d";
    
    };
    
    __overrides__ {
        addr = [00 00 00 01 72 65 67 3a 30 00];
        cha_enable = [00 00 00 00 3d 31 00];
        cha_cfg = [00 00 00 02 72 65 67 3a 30 00];
        cha_gain = [00 00 00 02 74 69 2c 67 61 69 6e 3a 30 00];
        cha_datarate = [00 00 00 02 74 69 2c 64 61 74 61 72 61 74 65 3a 30 00];
        chb_enable = [00 00 00 00 3d 32 00];
        chb_cfg = [00 00 00 03 72 65 67 3a 30 00];
        chb_gain = [00 00 00 03 74 69 2c 67 61 69 6e 3a 30 00];
        chb_datarate = [00 00 00 03 74 69 2c 64 61 74 61 72 61 74 65 3a 30 00];
        chc_enable = [00 00 00 00 3d 33 00];
        chc_cfg = [00 00 00 04 72 65 67 3a 30 00];
        chc_gain = [00 00 00 04 74 69 2c 67 61 69 6e 3a 30 00];
        chc_datarate = [00 00 00 04 74 69 2c 64 61 74 61 72 61 74 65 3a 30 00];
        chd_enable = [00 00 00 00 3d 34 00];
        chd_cfg = [00 00 00 05 72 65 67 3a 30 00];
        chd_gain = [00 00 00 05 74 69 2c 67 61 69 6e 3a 30 00];
        chd_datarate = [00 00 00 05 74 69 2c 64 61 74 61 72 61 74 65 3a 30 00];
    };
    
    __local_fixups__ {
        __overrides__ {
            addr = <0x0>;
            cha_cfg = <0x0>;
            cha_gain = <0x0>;
            cha_datarate = <0x0>;
            chb_cfg = <0x0>;
            chb_gain = <0x0>;
            chb_datarate = <0x0>;
            chc_cfg = <0x0>;
            chc_gain = <0x0>;
            chc_datarate = <0x0>;
            chd_cfg = <0x0>;
            chd_gain = <0x0>;
            chd_datarate = <0x0>;
        };
    };
	
	__fixups__ {
        i2c_arm = 
        "/fragment@6:target:0",
        "/fragment@11:target:0";
		
	};
		

};

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5577
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: devicetree overlay for MCP23017 GPIO expander

Mon Aug 03, 2020 2:51 pm

The fact that GPIO numbers are as stable as they are now is only because we have a downstream patch to number GPIOs from 0. Upstream is really keen to switch off the sysfs interface to GPIOs. As of 5.4 the Kconfig entry says:

Code: Select all

config GPIO_SYSFS
	bool "/sys/class/gpio/... (sysfs interface)"
	depends on SYSFS
	help
	  Say Y here to add the legacy sysfs interface for GPIOs.

	  This ABI is deprecated. If you want to use GPIO from userspace,
	  use the character device /dev/gpiochipN with the appropriate
	  ioctl() operations instead. The character device is always
	  available.
In the short term you could try to use the sysfs interface properly by looking at the "gpiochip*" entries, locating the one that you want by the value of "label", then reading "base" to calculate the offset.

However, I think your time would be better spent switching over to the higher performance ioctl-base libgpiod API: https://git.kernel.org/pub/scm/libs/lib ... ree/README

"sudo apt install gpiod" to get the new gpio utilities - gpioinfo, gpioset, gpioget, gpiofind etc.

Return to “Advanced users”