Configuring GPIO Wake

It looks like creating and compiling a new device tree file will be the best way to enable that pin to be used as a wake source. The PMC driver has a function “tegra_pmc_add_wakeup_event” which appears to use OF (Open Firmware = device tree) and looks for “nvidia,pmc-wakeup”.

Example .dts from kernel-4.4/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt

/ SoC dts including file
pmc: pmc {
	compatible = "nvidia,tegra114-pmc";
	reg = <0x7000e400 0x400>;
	clocks = <&tegra_car 261>, <&clk32k_in>;
	clock-names = "pclk", "clk32k_in";
};

/ Tegra board dts file
{
	...
	pmc {
		...
		nvidia,suspend-mode = <0>;
		#nvidia,wake-cells = <3>;
		...
	};
	...
	pmic {
		...
		nvidia,pmc-wakeup = <&pmc
				PMC_WAKE_TYPE_EVENT 18 PMC_TRIGGER_TYPE_LOW>;
		...
	};
	...
	gpio-keys {
		power {
			...
			nvidia,pmc-wakeup = <&pmc
				PMC_WAKE_TYPE_GPIO 16 PMC_TRIGGER_TYPE_NONE>;
			...
		};
	};
};

In kernel-4.4/arch/arm/boot/dts/tegra124-jetson-tk1.dts (and similar tegraxx*.dts files), there is a gpio-keys section that defines a node named power and gives it the property gpio-key,wakeup.

kernel-4.4/arch/arm/boot/dts/tegra124-jetson-tk1.dts

gpio-keys {
	compatible = "gpio-keys";

	power {
		label = "Power";
		gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
		linux,code = <KEY_POWER>;
		debounce-interval = <10>;
		gpio-key,wakeup;
	};
};

I am a complete noob to device tree, but it looks like &gpio, etc., are other nodes defined in the included device tree source files (.dtsi) and used here. The TEGRA_GPIO(bank, offset) macro is defined in one of the header files.

kernel-4.4/arch/arm/boot/dts/include/dt-bindings/gpio/tegra-gpio.h

/*
 * This header provides constants for binding nvidia,tegra*-gpio.
 *
 * The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below
 * provide names for this.
 *
 * The second cell contains standard flag values specified in gpio.h.
 */

#ifndef _DT_BINDINGS_GPIO_TEGRA_GPIO_H
#define _DT_BINDINGS_GPIO_TEGRA_GPIO_H

#include <dt-bindings/gpio/gpio.h>

#define TEGRA_GPIO_BANK_ID_A 0
#define TEGRA_GPIO_BANK_ID_B 1
#define TEGRA_GPIO_BANK_ID_C 2
#define TEGRA_GPIO_BANK_ID_D 3
#define TEGRA_GPIO_BANK_ID_E 4
#define TEGRA_GPIO_BANK_ID_F 5
#define TEGRA_GPIO_BANK_ID_G 6
#define TEGRA_GPIO_BANK_ID_H 7
#define TEGRA_GPIO_BANK_ID_I 8
#define TEGRA_GPIO_BANK_ID_J 9
#define TEGRA_GPIO_BANK_ID_K 10
#define TEGRA_GPIO_BANK_ID_L 11
#define TEGRA_GPIO_BANK_ID_M 12
#define TEGRA_GPIO_BANK_ID_N 13
#define TEGRA_GPIO_BANK_ID_O 14
#define TEGRA_GPIO_BANK_ID_P 15
#define TEGRA_GPIO_BANK_ID_Q 16
#define TEGRA_GPIO_BANK_ID_R 17
#define TEGRA_GPIO_BANK_ID_S 18
#define TEGRA_GPIO_BANK_ID_T 19
#define TEGRA_GPIO_BANK_ID_U 20
#define TEGRA_GPIO_BANK_ID_V 21
#define TEGRA_GPIO_BANK_ID_W 22
#define TEGRA_GPIO_BANK_ID_X 23
#define TEGRA_GPIO_BANK_ID_Y 24
#define TEGRA_GPIO_BANK_ID_Z 25
#define TEGRA_GPIO_BANK_ID_AA 26
#define TEGRA_GPIO_BANK_ID_BB 27
#define TEGRA_GPIO_BANK_ID_CC 28
#define TEGRA_GPIO_BANK_ID_DD 29
#define TEGRA_GPIO_BANK_ID_EE 30
#define TEGRA_GPIO_BANK_ID_FF 31

#define TEGRA_GPIO(bank, offset) \
	((TEGRA_GPIO_BANK_ID_##bank * 8) + offset)

#endif

I’d really appreciate it if somebody could help explain where the bank values are coming from, because I can’t find them in the TRM. I hope I’m just overlooking something simple.