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.

Can U-boot access GPIO?

Other Parts Discussed in Thread: AM3874, TPS40041

Hi

We would like to access the TI814x GPIO with U-boot (read the state of GPIO pins set up as inputs in this case).

Is this possible?.

thanks

steve

  • Hi Steve,

    Yes, you can read the GPIO pin status from u-boot.

    Steps for reading the GPIO pins:-

    1. Enable clock for GPIO bank which you are using.

    2. Put the GPIO pins in Input mode

    3. Read the register values to know the status

    Regards

    AnilKumar

  • hello:

     How to configure gpio in the U-boot?

          eg:I want to enbale the ninth pin in the bank 3,and set the pin as output,and output value 1.

         But the U-boot will stop when I use the followings operation:(if I use only the __raw_writel,and the uboot will stop here,eg:  __raw_writel(l,0x481AE134))

     u32 l; 

     l  = __raw_readl(0x481AE13C);

     l |= 1 << 9;

    /*

    0x481AE13C: The GPIO_DATAOUT register is used for setting the value of the GPIO output pins. Data is written to the
    GPIO_DATAOUT register synchronously with the interface clock. This register can be accessed with
    direct read/write operations or using the alternate ‘Set/Clear’ feature. This feature enables to set or clear
    specific bits of this register with a single write access to the set data output register
    (GPIO_SETDATAOUT) or to the clear data output register (GPIO_CLEARDATAOUT) address.

    */
     __raw_writel(l,0x481AE134);//Enable output*/
     __raw_writel(l,0x481AE13C);//Set the out put value 1

     

    /*

    0x481AE194:Writing a 1 to a bit in the GPIO_SETDATAOUT register sets to 1 the corresponding bit in the
    GPIO_DATAOUT register; writing a 0 has no effect. A read of the GPIO_SETDATAOUT register returns
    the value of the data output register (GPIO_DATAOUT).

    */

    __raw_writel(l,0x481AE194);

     

     So,I want to know why I can't use the _raw_writel fun ,and if there is some problem about my register addr?

    as you say,. Enable clock for GPIO bank which you are using.wheather you point the GPIO_CTRL Register ?

    Thanks very much.

  • Hi!

    I'm suffering the same problem... In our custom am3874 boards I'm trying to set the GP3[10] as an output pin in u-boot in order to generate a pulse to reset our ethernet phy controller, with no luck.

    I have not found any example in the ti boards code to access the gpios... Any code example is welcome!

    Thanks!

    Jorge

  • Jorge,

    Jorge Fernandez said:
    I have not found any example in the ti boards code to access the gpios... Any code example is welcome!

    Refer to the voltage_scale_init(void) function in file:

    {EZSDK}/board-support/u-boot-2010.06-psp04.04.00.01/board/ti/ti8168/evm.c

    /*
     * The routine reads the efuse register and programs the GPIO
     * to adjust the TPS40041 core voltage.
     * Assumptions:
     * 1. The efuse data is programmed into TI816X_SMRT_SCALE_ADDR
     * 2. The efuse and gpio clocks are already enabled
     */
    static void voltage_scale_init(void)
    {
        u32 sr_efuse_data;
        u8  gpio_val;
        u32 gpio_reg_val;

        sr_efuse_data = __raw_readl(TI816X_SMRT_SCALE_ADDR);

        gpio_val = voltage_scale_lookup(sr_efuse_data);
        if (gpio_val != 0) {
            gpio_val &= 0xF;

            /* Enable Output on GPIO0[0:3] */
            gpio_reg_val = __raw_readl(TI816X_GPIO0_BASE + 0x134);
            gpio_reg_val &= 0xF;
            __raw_writel(gpio_reg_val, TI816X_GPIO0_BASE + 0x134);

            /* Clear any existing output data */
            gpio_reg_val = __raw_readl(TI816X_GPIO0_BASE + 0x190);
            gpio_reg_val &= 0xF;
            __raw_writel(gpio_reg_val, TI816X_GPIO0_BASE + 0x190);

            /* Program the GPIO to change the TPS40041 Voltage */
            gpio_reg_val = __raw_readl(TI816X_GPIO0_BASE + 0x194);
            gpio_reg_val &= gpio_val;
            __raw_writel(gpio_reg_val, TI816X_GPIO0_BASE + 0x194);
        }
    }

    Note that GPIO0 is used, GPIO0 is enabled in peripheral_enable(void) function:

    /* GPIO0 */
        __raw_writel(0x2, CM_ALWON_GPIO_0_CLKCTRL);
        while(__raw_readl(CM_ALWON_GPIO_0_CLKCTRL) != 0x2);

        __raw_writel((BIT(8)), CM_ALWON_GPIO_0_OPTFCLKEN_DBCLK);

    And GPIO0 base address is defined at:

    {EZSDK}/board-support/u-boot-2010.06-psp04.04.00.01/include/asm/arch-ti81xx/hardware.h

    /* GPIO Base address */
    #define GPIO0_BASE            0x48032000
    #define GPIO1_BASE            0x4804C000

    You need to define the GPIO3_BASE address : 0x481AE000. You also need to enable the GPIO3 in the peripheral_enable(void) function using the CM_ALWON_GPIO_1_CLKCTRL register.

    Regards,
    Pavel


  • And what about calculating TI816X_GPIO0_BASE + 0x134 from GPIO0[0:3] ??

    Regards,

    Jorge

  • Jorge,

    Jorge Fernandez said:
    And what about calculating TI816X_GPIO0_BASE + 0x134 from GPIO0[0:3] ??

    This is equal to 0x48032134, which is the DM816x GPIO0.GPIO_OE register.

    Regards,
    Pavel

  • No luck doing the pulse! This is my code:

    hardware.h

    #define GPIO3_BASE            0x481AE000

    my board.c

        /* GPIO3 */
        __raw_writel(0x2, CM_ALWON_GPIO_1_CLKCTRL);
        while(__raw_readl(CM_ALWON_GPIO_1_CLKCTRL) != 0x2);

        __raw_writel((BIT(8)), CM_ALWON_GPIO_1_OPTFCLKEN_DBCLK);

    ...

    #define GPIO_ETHERNET_NRESET    (1 << 10)


    static void micrel_reset(void)
    {
        u8  gpio_val;
        u32 gpio_reg_val;

        /* Enable Output on GPIO3[10] */
        gpio_reg_val = __raw_readl(GPIO3_BASE + 0x134);  // base + 0x134 = GPIO_OE
        gpio_reg_val &= ~GPIO_ETHERNET_NRESET;
        __raw_writel(gpio_reg_val, GPIO3_BASE + 0x134);

        /* Clear the GPIO */
        gpio_reg_val = __raw_readl(GPIO3_BASE + 0x190);
        gpio_reg_val &= GPIO_ETHERNET_NRESET;
        __raw_writel(gpio_reg_val, GPIO3_BASE + 0x190);

        udelay(500000);

        /* Set the GPIO */
        gpio_reg_val = __raw_readl(GPIO3_BASE + 0x194);
        gpio_reg_val &= GPIO_ETHERNET_NRESET;
        __raw_writel(gpio_reg_val, GPIO3_BASE + 0x194);
    }

    This code is executed when I do 'dhcp' from uboot command line because is the first thing I do on 'phy_init()' method. The scope don't get any pulse on the GPIO3[10] pin and the uboot is frozen when I run the reset...

    It's a mess managing gpio pins with this cpu...

    Regards,

  • Jorge,

    Jorge Fernandez said:
    /* GPIO3 */
        __raw_writel(0x2, CM_ALWON_GPIO_1_CLKCTRL);
        while(__raw_readl(CM_ALWON_GPIO_1_CLKCTRL) != 0x2);

        __raw_writel((BIT(8)), CM_ALWON_GPIO_1_OPTFCLKEN_DBCLK);

    The CM_ALWON_GPIO_1_OPTFCLKEN_DBCLK is not defined by default in the u-boot source. Do you define it yourself? Do you have as result of the above operations the value of 0x00000102 inside the CM_ALWON_GPIO_1_CLKCTRL register?

    Jorge Fernandez said:
    /* Enable Output on GPIO3[10] */
        gpio_reg_val = __raw_readl(GPIO3_BASE + 0x134);  // base + 0x134 = GPIO_OE
        gpio_reg_val &= ~GPIO_ETHERNET_NRESET;
        __raw_writel(gpio_reg_val, GPIO3_BASE + 0x134);

    Do you have as result the value of 0 into the GPIO3.GPIO_OE[10] bit?

    Do you measure the GP3[10] signal on the AH27 physical pin? Do you program the value of 0x80 into the PINCNTL218(0x48140B64) [7:0] MUXMODE bits?

    Regards,
    Pavel

  • Hi!

    Pavel Botev said:

    The CM_ALWON_GPIO_1_OPTFCLKEN_DBCLK is not defined by default in the u-boot source. Do you define it yourself? Do you have as result of the above operations the value of 0x00000102 inside the CM_ALWON_GPIO_1_CLKCTRL register?

    /* Enable Output on GPIO3[10] */
        gpio_reg_val = __raw_readl(GPIO3_BASE + 0x134);  // base + 0x134 = GPIO_OE
        gpio_reg_val &= ~GPIO_ETHERNET_NRESET;
        __raw_writel(gpio_reg_val, GPIO3_BASE + 0x134);

    Do you have as result the value of 0 into the GPIO3.GPIO_OE[10] bit?

    Do you measure the GP3[10] signal on the AH27 physical pin? Do you program the value of 0x80 into the PINCNTL218(0x48140B64) [7:0] MUXMODE bits?

    [/quote]

    Yes, I have edited cpu.h this way:

    #define CM_ALWON_GPIO_0_CLKCTRL        (PRCM_BASE + 0x155c)
    #define CM_ALWON_GPIO_0_OPTFCLKEN_DBCLK (PRCM_BASE + 0x155c)

    #define CM_ALWON_GPIO_1_CLKCTRL        (PRCM_BASE + 0x1560)
    #define CM_ALWON_GPIO_1_OPTFCLKEN_DBCLK (PRCM_BASE + 0x1560)

    But if I print the 'CM_ALWON_GPIO_1_CLKCTRL' register in the 'phy_init()' I get 0x30100 !! In the 'per_clocks_enable()' I can put a printf.

    I have discovered where the code hangs... If I try to do

    gpio_reg_val = __raw_readl(GPIO3_BASE + 0x134);

    the call never returns!

    Any hint?

    Regards,

    Jorge

  • Jorge,

    Jorge Fernandez said:
    But if I print the 'CM_ALWON_GPIO_1_CLKCTRL' register in the 'phy_init()' I get 0x30100 !! In the 'per_clocks_enable()' I can put a printf.

    I suspect that  __raw_writel((BIT(8)), CM_ALWON_GPIO_1_OPTFCLKEN_DBCLK); is setting bit [8] to 0x1, but at the same time is clearing bits [1:0] from 0x2 to 0x0. Which is not good, thus the GPIO3 module is disabled.

    Jorge Fernandez said:

    I have discovered where the code hangs... If I try to do

    gpio_reg_val = __raw_readl(GPIO3_BASE + 0x134);

    the call never returns!

    This is normal, as GPIO3 module is disabled, reading from the GPIO3 registers makes the flow to hang!

    Jorge Fernandez said:
    Any hint?

    You can modify your code as;

    /* GPIO3 */
        __raw_writel(0x102, CM_ALWON_GPIO_1_CLKCTRL);
        while(__raw_readl(CM_ALWON_GPIO_1_CLKCTRL) != 0x102);

       // __raw_writel((BIT(8)), CM_ALWON_GPIO_1_OPTFCLKEN_DBCLK);

    This should work.

    Regards,
    Pavel

  • Pavel Botev said:

    You can modify your code as;

    /* GPIO3 */
        __raw_writel(0x102, CM_ALWON_GPIO_1_CLKCTRL);
        while(__raw_readl(CM_ALWON_GPIO_1_CLKCTRL) != 0x102);

       // __raw_writel((BIT(8)), CM_ALWON_GPIO_1_OPTFCLKEN_DBCLK);

    This should work.

    Yes!! you're right, now it works!

    Thanks!