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.

Setting a GPIO from U-Boot

Other Parts Discussed in Thread: AM3359

Here I have a custom AM3359 based board. I'm using the TI Sitara SDK 05.05.01.00. My task is to set a GPIO to output and let it output a high signal. This should be done from U-Boot.

The problem is that U-Boot stops running as soon as I call gpio_direction_output(). If I do exactly the same in the board file for the Linux kernel, it works perfectly fine. But from U-Boot - no chance.

Here is the code from the U-Boot board file (evm.c customized, the function board_init() should be enough):

int board_init(void)
{
    int ret;
    /* Configure the i2c0 pin mux */
    enable_i2c0_pin_mux();

    i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);

    board_id = BONE_BOARD;

    //configure_evm_pin_mux(board_id);
    enable_minimum_pinmux();
    
    /* my changes... */
    printf("--- GPIO Pinmux enable now calling...\n");
    enable_gpio3_10_pin_mux();
    printf("--- GPIO request now calling...\n");
    ret = gpio_request(GPIO_TO_PIN(3, 10), "ETH_RESET");
    printf("--- return value: %d. GPIO direction_output now calling...\n", ret);
    ret = gpio_direction_output(GPIO_TO_PIN(3, 10), 1); // 1: disables the ethernet reset signal
    printf("--- return value: %d. GPIO complete!\n", ret);
    /* ...end */
    
#ifndef CONFIG_SPL_BUILD
    board_evm_init();
#endif

    gpmc_init();

    return 0;
}

This is in mux.c:

void enable_gpio3_10_pin_mux(void)
{
    configure_module_pin_mux(gpio3_10_pin_mux);
}

void enable_minimum_pinmux(void)
{
    configure_module_pin_mux(uart0_pin_mux);
    configure_module_pin_mux(i2c1_pin_mux);
    configure_module_pin_mux(mmc0_pin_mux);
    configure_module_pin_mux(mmc1_pin_mux);
    configure_module_pin_mux(spi0_pin_mux);
}
static struct module_pin_mux gpio3_10_pin_mux[] = {
    {OFFSET(mii1_rxclk), MODE(7)},    /* GPIO3_10, ETH-RESET */
    {-1},
};

This results in this output from U-Boot:

CCCCCCCC
U-Boot SPL 2011.09-dirty (Feb 26 2013 - 17:45:54)
Texas Instruments Revision detection unimplemented
--- GPIO Pinmux enable now calling...
--- GPIO request now calling...
--- return value: 0. GPIO direction_output now calling...

So what am I doing wrong here?

  • Hi Andre,

    I can't manage to see anything wrong with your code right now.  Can you please post what exactly does your macro GPIO_TO_PIN() expand to. You may want to put some more debug prints in the functions called by gpio_direction_output(): _set_gpio_dataout() and _set_gpio_direction(). This may help pin down where exactly the system hangs and what is causing the issue.

    Best regards,
    Miroslav

  • Have you also tried manually setting the GPIO registers to rule out a bug in U-Boot ?

    i.e. comment out your code and use "md.l xxxx" at the U-boot prompt.

    Look at section 25 of the TRM for all the GPIO register details.

    Mark J.

  • Miroslav Kiradzhiyski XID said:

    Hi Andre,

    I can't manage to see anything wrong with your code right now.  Can you please post what exactly does your macro GPIO_TO_PIN() expand to. You may want to put some more debug prints in the functions called by gpio_direction_output(): _set_gpio_dataout() and _set_gpio_direction(). This may help pin down where exactly the system hangs and what is causing the issue.

    Best regards,
    Miroslav

    This is the macro, it's the same TI provided in the Linux kernel:

    #define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))

    Thanks for your hints, I will put some more debug outputs and will keep you informed!

  • Mark Jackson99390 said:

    Have you also tried manually setting the GPIO registers to rule out a bug in U-Boot ?

    i.e. comment out your code and use "md.l xxxx" at the U-boot prompt.

    Look at section 25 of the TRM for all the GPIO register details.

    Mark J.

    Excuse me, what is TRM?

  • Hi,

    TRM means Technical Reference Manual. You can download it from here: http://www.ti.com/product/am3359

    Best regards,
    Miroslav

  • Hi Andre,

    According to Table 8-21. Bus Interface Clocks (page 523) and Table 25-3. GPIO Clock Signals (page 4013) from the TRM, the L4_PER_CLK is the functional/interface clock for GPIO1, GPIO2 and GPIO3 modules. Since the GPIO pin you want to use is contained within gpio bank number 3 (GPIO3) you need to have this clock enabled. Please check section 8.1.12 Clock Module Registers (page 544) from the TRM about the PER_L4LS registers (sections 8.1.12.1.1 and 8.1.12.1.20). If you read bit 8 from the CM_PER_L4LS_CLKSTCTRL register you will find out if the L4LS_GCLK clock is enabled.

    Best regards,
    Miroslav

  • Hello

    I added these lines to u-boot, because md (memory dump) with GPIO bank 1..3 configuration registers was not possible and led to a crash. With these modification accessing GPIOs in bank 1..3 worked for me.

    File: arch/arm/include/asm/arch-ti81xx/cpu.h

     #define CM_PER_I2C1_CLKCTRL        (CM_PER + 0x48) /* I2C1 */
     #define CM_PER_I2C2_CLKCTRL        (CM_PER + 0x44) /* I2C2 */
     #define CM_WKUP_GPIO0_CLKCTRL        (CM_WKUP + 0x8) /* GPIO0 */
    +#define CM_PER_GPIO1_CLKCTRL        (CM_PER + 0xAC) /* GPIO1 */
    +#define CM_PER_GPIO2_CLKCTRL        (CM_PER + 0xB0) /* GPIO2 */
    +#define CM_PER_GPIO3_CLKCTRL        (CM_PER + 0xB4) /* GPIO3 */
    +
     #define CM_RTC_RTC_CLKCTRL        (CM_RTC + 0x0) /* RTC */
     
     #define CM_PER_MMC0_CLKCTRL         (CM_PER + 0x3C)

    File: pll.c

         /* GPIO0 */
         writel(PRCM_MOD_EN, CM_WKUP_GPIO0_CLKCTRL);
         while (readl(CM_WKUP_GPIO0_CLKCTRL) != PRCM_MOD_EN);
    +
    +    /* GPIO1 */
    +    writel(PRCM_MOD_EN, CM_PER_GPIO1_CLKCTRL);
    +    while (readl(CM_PER_GPIO1_CLKCTRL) != PRCM_MOD_EN);
    +
    +    /* GPIO2 */
    +    writel(PRCM_MOD_EN, CM_PER_GPIO2_CLKCTRL);
    +    while (readl(CM_PER_GPIO2_CLKCTRL) != PRCM_MOD_EN);
    +
    +    /* GPIO3 */
    +    writel(PRCM_MOD_EN, CM_PER_GPIO3_CLKCTRL);
    +    while (readl(CM_PER_GPIO3_CLKCTRL) != PRCM_MOD_EN);
     }
     
     static void power_domain_transition_enable(void)