This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM620-Q1: MCU GPIO Raising And Failing edge trigger issue from low power mode

Part Number: AM620-Q1


Tool/software:

Dear Expert.

Customer follow this link to test MCU GPIO wakeup from "deep sleep" or "MCU only" mode.

https://software-dl.ti.com/processor-sdk-linux/esd/AM62X/11_00_09_04/exports/docs/linux/Foundational_Components/Power_Management/pm_low_power_modes.html

-> 3.3.5.4. Deep Sleep
-> 3.3.5.5. MCU Only

Both of them use same linux device tree code. (k3-am62x-sk-lpm-wkup-sources.dtso)

wake up gpio are MCU_GPIO0_19 / MCU_GPIO0_20 / MCU_GPIO0_3 / MCU_GPIO0_14

all of these gpio has Raising and Failing edge wakeup trigger issue even software setting "Failing trigger edge" only.

 

Here is device tree,

// SPDX-License-Identifier: GPL-2.0
/**
 * AM62 family of devices can wakeup from Low Power Modes via
 * multiple wakeup sources. This overlay enables MAIN GPIO, MCU GPIO,
 * and MCU MCAN pins.
 *
 * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
 */

/dts-v1/;
/plugin/;

#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>

#include "k3-pinctrl.h"

&{/} {
	gpio_key {
		compatible = "gpio-keys";
		autorepeat;
		pinctrl-names = "default";
		pinctrl-0 = <&main_gpio1_pins_default>;
		//switch {
		//	label = "CAN1_INH_WKGPIO";
		//	linux,code = <KEY_WAKEUP>;
		//	interrupts-extended = <&main_gpio0 4 IRQ_TYPE_LEVEL_LOW>,
		//		<&main_pmx0 0x010>;
		//	interrupt-names = "irq", "wakeup";
		//};
//
		//switch1 {
		//	label = "CAN0_INH_WKGPIO";
		//	linux,code = <144>;
		//	interrupts-extended = <&main_gpio0 5 IRQ_TYPE_LEVEL_LOW>,
		//		<&main_pmx0 0x014>;
		//	interrupt-names = "irq", "wakeup";
		//};
	};

	mcu_gpio_key {
		compatible = "gpio-keys";
			autorepeat;
		pinctrl-names = "default";
		pinctrl-0 = <&wake_mcugpio1_pins_default>;
		interrupt-parent = <&mcu_gpio0>;
		interrupts = <19 IRQ_TYPE_EDGE_FALLING>,
					<20 IRQ_TYPE_EDGE_FALLING>,
					<3 IRQ_TYPE_EDGE_FALLING>,
					<14 IRQ_TYPE_EDGE_FALLING>;
		switch {
			label = "WNC_SOC_MCUGPIO";
			linux,code = <143>;
			gpios = <&mcu_gpio0 19 GPIO_ACTIVE_LOW>;
			wakeup-source;
		};
		//mark test this
		switch1 {
			label = "IG_ON_MCUGPIO";
			linux,code = <144>;
			gpios = <&mcu_gpio0 20 GPIO_ACTIVE_LOW>;
			wakeup-source;
		};

		switch2 {
			label = "ECALL_MCUGPIO";
			linux,code = <145>;
			gpios = <&mcu_gpio0 3 GPIO_ACTIVE_LOW>;
			wakeup-source;
		};

		switch3 {
			label = "INH_MCUGPIO";
			linux,code = <146>;
			gpios = <&mcu_gpio0 14 GPIO_ACTIVE_LOW>;
			wakeup-source;
		};
	};
};

&main_pmx0 {
	main_gpio1_pins_default: main-gpio1-pins-default {
		pinctrl-single,pins = <
			//AM62X_IOPAD(0x010, 0x28054187, 7) /* (G17) OSPI0_D1.GPIO0_4 */
			//AM62X_IOPAD(0x014, 0x28054187, 7) /* (F21) OSPI0_D2.GPIO0_5 */
		>;
	};
};

&mcu_pmx0 {
	wake_mcugpio1_pins_default: wake-mcugpio1-pins-default {
		pinctrl-single,pins = <
			AM62X_MCU_IOPAD(0x0050, PIN_INPUT , 7) /* (A9) WKUP_I2C0_SDA.MCU_GPIO0_20 */
			AM62X_MCU_IOPAD(0x004C, PIN_INPUT , 7) /* (E9) WKUP_I2C0_SCL.MCU_GPIO0_19 */
			AM62X_MCU_IOPAD(0X000C, PIN_INPUT , 7) /* (E8) MCU_SPI0_D0.MCU_GPIO0_3 */
			AM62X_MCU_IOPAD(0x0038, PIN_INPUT , 7) /* (E8) MCU_SPI0_D0.MCU_GPIO0_14 */
		>;
	};

	mcu_mcan0_tx_pins_default: mcu-mcan0-tx-pins-default {
		pinctrl-single,pins = <
			AM62X_IOPAD(0x034, PIN_OUTPUT, 0) /* (D6) MCU_MCAN0_TX */
		>;
	};

	mcu_mcan0_rx_pins_default: mcu-mcan0-rx-pins-default {
		pinctrl-single,pins = <
			AM62X_IOPAD(0x038, PIN_INPUT, 0) /* (B3) MCU_MCAN0_RX */
		>;
	};

	mcu_mcan0_rx_pins_wakeup: mcu-mcan0-rx-pins-wakeup {
		pinctrl-single,pins = <
			AM62X_IOPAD(0x038, PIN_INPUT | WKUP_EN, 0) /* (B3) MCU_MCAN0_RX */
		>;
	};

	mcu_mcan1_tx_pins_default: mcu-mcan1-tx-pins-default {
		pinctrl-single,pins = <
			AM62X_IOPAD(0x03c, PIN_OUTPUT, 0) /* (E5) MCU_MCAN1_TX */
		>;
	};

	mcu_mcan1_rx_pins_default: mcu-mcan1-rx-pins-default {
		pinctrl-single,pins = <
			AM62X_IOPAD(0x040, PIN_INPUT, 0) /* (D4) MCU_MCAN1_RX */
		>;
	};

	mcu_mcan1_rx_pins_wakeup: mcu-mcan1-rx-pins-wakeup {
		pinctrl-single,pins = <
			AM62X_IOPAD(0x040, PIN_INPUT | WKUP_EN, 0) /* (D4) MCU_MCAN1_RX */
		>;
	};

	mcu_uart0_pins_default: mcu-uart0-pins-default {
		pinctrl-single,pins = <
			AM62X_MCU_IOPAD(0x001c, PIN_INPUT, 0) /* MCU_UART0_CTSn */
			AM62X_MCU_IOPAD(0x0020, PIN_OUTPUT, 0) /* MCU_UART0_RTSn */
			AM62X_MCU_IOPAD(0x0018, PIN_OUTPUT, 0) /* MCU_UART0_TXD */
		>;
	};

	mcu_uart0_rxd_pins_default: mcu-uart0-rxd-pins-default {
		pinctrl-single,pins = <
			AM62X_MCU_IOPAD(0x0014, PIN_INPUT, 0) /* MCU_UART0_RXD */
		>;
	};

	mcu_uart0_rxd_pins_wakeup: mcu-uart0-rxd-pins-wakeup {
		pinctrl-single,pins = <
			AM62X_MCU_IOPAD(0x0014, PIN_INPUT | WKUP_EN, 0) /* MCU_UART0_RXD */
		>;
	};
};

&mcu_gpio0 {
	status = "okay";
};

&mcu_gpio_intr {
	status = "okay";
};

&mcu_mcan0 {
	pinctrl-names = "default", "wakeup";
	pinctrl-0 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_default>;
	pinctrl-1 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_wakeup>;
	status = "disabled";
};

&mcu_mcan1 {
	pinctrl-names = "default", "wakeup";
	pinctrl-0 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_default>;
	pinctrl-1 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_wakeup>;
	status = "disabled";
};

&mcu_uart0 {
	pinctrl-names = "default", "wakeup";
	pinctrl-0 = <&mcu_uart0_pins_default>, <&mcu_uart0_rxd_pins_default>;
	pinctrl-1 = <&mcu_uart0_pins_default>, <&mcu_uart0_rxd_pins_wakeup>;
	status = "disabled";
};

We use MCU_GPIO0_20 as example.

I think pinmux is ok.

we let gpio keep low in init state, and then trigger high (Raising edge), it trigger wakeup event even software setting Failing edge.

We can see that is no bounce problems.

And then, we let gpio keep HIGH in init state, and then trigger LOW (falling edge), it trigger wakeup event.

We can also see that is no bounce problems.

SW : 10.0, we set wakup source only in Linux side.

Do I miss any thing?

Thank You Very Much

Gibbs

  • Hi Gibbs,

    Difference between GPIO Interrupt and GPIO Wakeup Event

    As mentioned in the TRM, GPIOs are capable of interrupts caused by rising edge and falling edge. Refer to Section 12.2.1.1.1 GPIO Features in the AM62x TRM: https://www.ti.com/lit/pdf/spruiv7

    This isn't the same case for GPIOs used for wakeup sources from low power modes. When the SoC is in Deep Sleep or MCU Only mode, the pad that is PinMuxed for a GPIO is searching for any change of the signal. This means from a hardware perspective, its not able to distinguish between a rising edge and falling edge, rather it only understands there is a signal change on the pad to cause a wakeup.

    Since the hardware cannot determine a rising edge or a falling edge, then it won't follow whats defined in the device tree overlay.

    The rising edge and falling edge device tree definition will apply for general GPIO interrupts but not wakeup events. 


    Possible Solution

    It should be possible to connect a pull up resistor to the GPIO to keep the signal high. Then ground the signal for a moment to trigger the wakeup event.

    Alternatively, you could try with the internal PADCONFIG Pull resistor as well but be aware that this would be a weak resistor. This can be done by setting Bit 16 = 0 and Bit 17 = 1 (PADCONFIG = 0x60007) so the signal stays high in Deep Sleep, then ground the signal to wakeup the device.

    In either of these solutions, the signal will be high in Deep Sleep so it will ignore any rising edge signal changes and will only respond to falling edge signal changes.

    What will these GPIO signals do when the SoC not in Deep Sleep/MCU Only Mode?

    Thanks,

    Anshu

  • Hi Gibbs,

    If you choose to enable the internal PADCONFIG pull up resistor, it can be enable from the device tree's pinmux node: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/arch/arm64/boot/dts/ti/k3-pinctrl.h?h=ti-linux-6.6.y

    Thanks,

    Anshu