zyzel_a
Posts: 3
Joined: Sun Feb 21, 2021 7:10 am

MCP23017 as a device tree keyboard

Sun Feb 21, 2021 7:20 am

Hi! So my setup is an MCP23017 i2c device that is connected to the &i2c_csi_dsi bus (we needed to do it that way coz we used the gpio to the DPI LCD). And the following device tree source detected the chip properly:

Code: Select all

// Definitions for MCP23017 Gpio Extender from Microchip Semiconductor

/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2835";

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

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

	fragment@2 {
		target = <&i2c_csi_dsi>;
		__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;

				status = "okay";
			};
		};
	};

	fragment@3 {
		target = <&mcp23017>;
		__dormant__ {
			compatible = "microchip,mcp23008";
		};
	};

	__overrides__ {
		gpiopin = <&mcp23017_pins>,"brcm,pins:0",
				<&mcp23017>,"interrupts:0";
		addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0";
		mcp23008 = <0>,"=3";
	};
};

now my question is how can i use `gpio-keys` for it? i kinda want it to detect the button presses and send a keyboard event without using any python and stuff. i really can't figure out where to start on this one and i hope you guys can help me out. thanks!

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

Re: MCP23017 as a device tree keyboard

Sun Feb 21, 2021 4:28 pm

Take a look at the gpio-key overlay and gpio-shutdown overlay. You can probably skip the pinctrl declaration (fragment 0 in both cases, and the properties pinctrl-names and pinctrl-0). What you are left with is a node that declares an instance of gpio-keys, with one or mode subnodes for declaring the keys - the GPIO used and the key code it generates.

The difference in your case is that you want to use GPIOs provided by the mcp23017. Fortunately, this is a simple matter of changing the gpio declarations to use mcp23017 as the GPIO controller; the GPIO number should be as seen by the mcp239017, i.e. a number from 0 to 15. The second parameter - 1 here - indicates that the input is active-low; 0 means active-high.

You should end up with something like this:

Code: Select all

	fragment@4 {
		target-path = "/";
		__overlay__ {
			button: button@0 {
				compatible = "gpio-keys";
				status = "okay";

				key: key_0 {
					gpios = <&mcp23017 0 1>;
					linux,code = <30>;
					label = "KEY_A";
				};
				key: key_1 {
					gpios = <&mcp23017 1 1>;
					linux,code = <48>;
					label = "KEY_B";
				};
				// etc.
			};
		};
	};
I got the key code values from here: https://github.com/torvalds/linux/blob/ ... nt-codes.h

zyzel_a
Posts: 3
Joined: Sun Feb 21, 2021 7:10 am

Re: MCP23017 as a device tree keyboard

Mon Feb 22, 2021 2:54 am

Thanks for the response! But im afraid it isnt working still.. perhaps we need some kind of pin configuration? this is my current dts and it detects the chip fine and even adds the device on the inputs when i use evtest but there's still no input events being detected.

Code: Select all

/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2835";

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

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

	fragment@2 {
		target = <&i2c_csi_dsi>;
		__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;
				status = "okay";
			};
		};
	};

	fragment@3 {
		target = <&mcp23017>;
		__dormant__ {
			compatible = "microchip,mcp23008";
		};
	};

	fragment@4 {
		target-path = "/";
		__overlay__ {
			psp_buttons {
				compatible = "gpio-keys";
				status = "okay";

				key_0 {
					gpios = <&mcp23017 0 1>;
					linux,code = <30>;
					label = "KEY_A";
				};
				key_1 {
					gpios = <&mcp23017 1 1>;
					linux,code = <31>;
					label = "KEY_S";
				};
				key_2 {
					gpios = <&mcp23017 2 1>;
					linux,code = <32>;
					label = "KEY_D";
				};
				key_3 {
					gpios = <&mcp23017 3 1>;
					linux,code = <33>;
					label = "KEY_F";
				};
				key_4 {
					gpios = <&mcp23017 4 1>;
					linux,code = <34>;
					label = "KEY_G";
				};
				key_5 {
					gpios = <&mcp23017 5 1>;
					linux,code = <35>;
					label = "KEY_H";
				};
				key_6 {
					gpios = <&mcp23017 6 1>;
					linux,code = <36>;
					label = "KEY_J";
				};
				key_7 {
					gpios = <&mcp23017 7 1>;
					linux,code = <37>;
					label = "KEY_K";
				};
				key_8 {
					gpios = <&mcp23017 8 1>;
					linux,code = <38>;
					label = "KEY_L";
				};
				key_9 {
					gpios = <&mcp23017 9 1>;
					linux,code = <39>;
					label = "KEY_SEMICOLON";
				};
				key_10 {
					gpios = <&mcp23017 10 1>;
					linux,code = <40>;
					label = "KEY_APOSTROPHE";
				};
				key_11 {
					gpios = <&mcp23017 11 1>;
					linux,code = <41>;
					label = "KEY_GRAVE";
				};
				key_12 {
					gpios = <&mcp23017 12 1>;
					linux,code = <42>;
					label = "KEY_LEFTSHIFT";
				};
				key_13 {
					gpios = <&mcp23017 13 1>;
					linux,code = <43>;
					label = "KEY_BACKSLASH";
				};
				key_14 {
					gpios = <&mcp23017 14 1>;
					linux,code = <44>;
					label = "KEY_Z";
				};
				key_15 {
					gpios = <&mcp23017 15 1>;
					linux,code = <45>;
					label = "KEY_X";
				};
			};
		};
	};


	__overrides__ {
		gpiopin = <&mcp23017_pins>,"brcm,pins:0",
				<&mcp23017>,"interrupts:0";
		addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0";
		mcp23008 = <0>,"=3";
	};
};

Sorry im not really well versed in device tree semantics and thanks alot for your patience.

zyzel_a
Posts: 3
Joined: Sun Feb 21, 2021 7:10 am

Re: MCP23017 as a device tree keyboard

Mon Feb 22, 2021 4:26 am

Okay so i was dumb and i forgot that i hooked the interrupt line to pin 23/GPIO 11 and the device tree is set to GPIO 4. :facepalm: thanks alot and i hope someone learns from my stupid mistakes. :D

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

Re: MCP23017 as a device tree keyboard

Mon Feb 22, 2021 9:51 am

Fragment numbering is not significant, but it is conventional to number them sequentially (or at least have the numbers increasing down the overlay). My use of "fragment@41" was meant to be "fragment@4" - I need to use reading glasses more often. I've "corrected" the numbering now.

Return to “Device Tree”