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.

AM4376: GPIO inputs in U-boot

Part Number: AM4376
Other Parts Discussed in Thread: AM4372

On our target board we have three am4376 targets.  Each is using GPIO Bank 0 inputs 1 and 2 (Not 0 and 1) to identify which CPU instance any executable code environment may be running. Each is pulled either high or low using a 1K pull up/down resisters. (We have checked the specs and this is a strong enough resister to overcome the internal pullup if used.)  

At present I can test this functionality on 2 of the three targets using SPL and U-boot. Using U-boot it appears that I am not getting the expected input values on the GPIO0 inputs. 

This is the expected result:

CPU A = 0x00000002  // input 1 is low and input 2 is high

CPU C = 0x00000003 // input 1 is high and input 2 is high

This the code snippet, mux and DTS that I am using in SPL/U-Boot  ( I have attached the source files as well.)

in board/ti/am43xx/board.c

#define CPUTYPE_MASK 0x0000006
#define CPUTYPE_MSB 2
#define CPUTYPE_LSB 1
#define GPIO0_DATAIN (AM33XX_GPIO0_BASE + OMAP_GPIO_DATAIN)
#define GPIO0_OE (AM33XX_GPIO0_BASE + OMAP_GPIO_OE)

static void set_bank0_direction(int gpio,int is_input)
{
void *reg = GPIO0_OE;
u32 l;

l = __raw_readl(reg);
if (is_input)
l |= 1 << gpio;
else
l &= ~(1 << gpio);
__raw_writel(l, reg);
}

static int get_bank0_value(int gpio)
{
void *reg = GPIO0_DATAIN;

return (__raw_readl(reg) & (1 << gpio)) != 0;
}

unsigned int get_bank0val(void)
{
u32 Bank0Val = 0;

enable_cpu_gpio_pin_mux();
set_bank0_direction(CPUTYPE_LSB,1);
set_bank0_direction(CPUTYPE_MSB,1);

if( get_bank0_value(CPUTYPE_LSB) > 0)
{
Bank0Val += 1;
}

if( get_bank0_value(CPUTYPE_MSB) > 0)
{
Bank0Val += 2;
}

return Bank0Val;
}

unsigned int get_cputype(void)
{
u32 Bank0Val = 0;
unsigned int RetVal;

enable_cpu_gpio_pin_mux();
Bank0Val = get_bank0val();

switch(Bank0Val)
{
case CPU_A:
{
RetVal = CPU_A;
break;
}

case CPU_B:
{
RetVal = CPU_B;
break;
}
case CPU_C:
{
RetVal = CPU_C;
break;
}

default:
RetVal = CPU_A;
}

return RetVal;
}

void sentenv_cputype(void)
{
int cpu_type = get_cputype();

printf("get_bank0val() : 0x%08X\n",get_bank0val());

// Set env varible cputype
switch(cpu_type)
{
case CPU_A:
env_set("cputype","A");
break;
case CPU_B:
env_set("cputype","B");
break;
case CPU_C:
env_set("cputype","C");
break;
default:
// Unknown
env_set("cputype","1");
}

}

in board/ti/am43xx/mux.c

static struct module_pin_mux gpio0_pin_mux[] = {
{OFFSET(mii1_rxdv), (MODE(9) | PULLUP_EN)}, /* GPIO0_1 */
{OFFSET(mcasp0_axr1), (MODE(9) | PULLUP_EN)},/* GPIO0_2 */
{-1},
};

void enable_cpu_gpio_pin_mux(void)
{
configure_module_pin_mux(gpio0_pin_mux);
}

Devicetree for u-boot: /arch/arm/dts/am437x-idk-evm.dts

gpio0_pins_default: gpio0_pins_default {
pinctrl-single,pins = <
AM4372_IOPAD(0x118, PIN_INPUT | MUX_MODE9) /* (A15) mii1_rx_dv.gpio0[1] */
AM4372_IOPAD(0x1a8, PIN_INPUT | MUX_MODE9) /* (M25) mcasp0_axr1.gpio0[2] */
>;
};

This is the result when setenv_cputype() is called from board_eth_init() in board.c

(I have confirmed, using a meter, that the inputs on 1 and 2 are being driven to the expected levels)

From CPU A:

get_bank0val() : 0x00000002
<ethaddr> set to CoreACE CPU C

From CPU C:

get_bank0val() : 0x00000002
<ethaddr> set to CoreACE CPU C

We have also used an emulator to break on the get_bank0val() function and read the GPIO Bank 0 register and identified that it contains the data we are seeing.

Also, If I stop u-boot and use the gpio command on the command line I get the same result on CPU A and CPU C.

Have I configured the pins and bank registers correctly? If so, isre more needed to read the input data.


Thanks in advance,

Rob

U-bootSources.zip

  • Hello Rob,

    I am wondering if you could please look at the following registers in Uboot to verify pin mux:
    CTRL_CONF= 0x44E1 0000
    CTRL_CONF_MII1_RXDV Register (Offset = 918h)
    CTRL_CONF_MCASP0_AXR1 Register (Offset = 9A8h) 

    Also, lets confirm if the GPIO module is enabled in the following register:
    GPIO0=0x44E0 7000
    GPIO_CTRL Register (offset = 130h)

    Please use the "md" command to read the register from Uboot.

    Regards,
    Krunal

  • This is the output form Uboot terminal:

    => md.w 0x44E10918 8
    44e10918: 0009 0002 0003 000e 0003 000b 0001 0000 ................
    => md.w 0x44E109A8 8
    44e109a8: 0009 0002 0007 0804 0007 0804 0007 0804 ................
    => md.w 0x44E07130 8
    44e07130: 0002 0000 0306 0000 0004 0100 0000 0100 ................

    Regards,
    Rob

  • Hello Rob,

    Please make sure the following bit is set:

    Regards,
    Krunal

  • Krunal,


    Thanks for you response and apologies that I have taken some time to respond. ( I have been on other priorities.)

    It appears that setting the bit you indicate has addressed this issue. Thanks for the input. 

    For completeness here is the snippet of code that I added to u-boot in my board.c, I call the function set_ctrl_mii1()  before reading the gpio.

    #define CTRL_CONF_MII1_RXDV (CTRL_BASE + 0x0918)

    #define CONF_MII1_RXDV_RXACTIVE 0x00040000

    static void set_ctrl_conf_mii1(void)
    {
    void *reg = CTRL_CONF_MII1_RXDV;
    u32 l;

    l = __raw_readl(reg);
    l |= CONF_MII1_RXDV_RXACTIVE;

    __raw_writel(l, reg);
    }

    Regards,
    Rob

  • Krunal,

    I hate to reopen this issue, but it appears that am running into the same issue with the second bit we are using for the CPU detection. I am using the pin mux below:

    gpio0_pins_default: gpio0_pins_default {
    pinctrl-single,pins = <
    AM4372_IOPAD(0x118, PIN_INPUT | MUX_MODE9) /* (A15) mii1_rx_dv.gpio0[1] */
    AM4372_IOPAD(0x1a8, PIN_INPUT | MUX_MODE9) /* (M25) mcasp0_axr1.gpio0[2] */
    >;
    };

    I appears the mcasp0_axr1.gpio0[2] is not reading the input value. Do you think I need to enable the RX active bit for this pin as well?

    Regards,
    Rob

  • Hi Rob,

    As mentioned in the following thread, the input signal at the IO cell will not propagate to the peripheral function (like gpio). You must configure rxactive=1 for that to occur.

    Regards,
    Krunal

  • Thanks for response and the link, I have reviewed it.

    I have configured the mcasp0_axr1 (M25) pin as specified, but still do not see the expected result. The pins to this CPU are configured in the attached schematic snippet. The expect result is designed to use the internal pullup setting.

    Here is my code snippet I am using the configure/enable the RxActive in the SPL code. (this is identical to the code I am using for the mii1_rxdv (A15) that is mentioned above.) 

    In mux.c I have the pin mux for SPL as:

    static struct module_pin_mux gpio0_pin_mux[] = {
    {OFFSET(mii1_rxdv), (MODE(9) | RXACTIVE | PULLUP_EN)}, /* GPIO0_1 */
    {OFFSET(mcasp0_axr1), (MODE(9) | RXACTIVE | PULLUP_EN)},/* GPIO0_2 */
    {-1},
    };

    In board.c I added this function to set the config register.

    #define CTRL_CONF_MCASP0_AXR1 (CTRL_BASE + 0x09A8)

    #define CONF_MCASP0_AXR1_RXACTIVE 0x00040000

    static int set_ctrl_conf_mcasp0(void)
    {
    int Val;
    void *reg = CTRL_CONF_MCASP0_AXR1;
    u32 l;
    u32 RetVal;

    l = __raw_readl(reg);
    l |= CONF_MCASP0_AXR1_RXACTIVE;
    __raw_writel(l, reg);

    RetVal = __raw_readl(reg);

    return RetVal;
    }

    The return value is being displayed at boot from SPL using the uart0 console output, I have attached screen shot of what I get.

     ve missed another pin configuration in the Bank0 controller?  Any other suggestion you have that my result in using this pin as input I can try as well. 

    Thanks in advance,
    Rob

  • Hello Rob,

    I have asked our driver expert for more suggestions and I will keep you posted on any updates. With regards to the HW connections, could you please tell me the difference between GPIO0_1 and GPIO0_2?

    Regards,
    Krunal

  • Krunal.

    Thanks for the response and your time in looking at this.

    The GPIOs we are using are to identify which CPU (out board has 3) is currently running the SPL instance and are encoded as LSB and MSB as a 2 bit number. (1,2,3)

    GPIO_1 = LSB = mii1_rxdv  (Ball A15 configured pinmux mode 9 )

    GPOI_2 = MSB = mcasp0_axr1 (Ball M25 configured pinmux mode 9)

    I have been looking through the AM437X Technical Manual and found an interesting section on the MCASP (specifilcally it starts on page 3408)  There is a list of registers supporting the MCASP and one of them is labeled as MCASP_PFUNC (offset 0x0010). See table 24-14. The description is pasted below. 

    I suspect that this may need to be setup to change AXR pins to be GPIO before that functionality works. I have been having difficulty finding the base address that I can successfully write to in SPL to change this PFUNC register. The memory map has a MCASP0_DATA and MCASP0_CFG  memory space but I crash when I either of these base addresses as a raw_read or raw_write.

    Any suggestions?  

    Regards,
    Rob

  • Hi Rob,

    As mentioned in the following thread, McASP and GPIO are two separate peripherals and the PINMUX register selects which peripheral controls each pin. Please give me 24-48 hours and I will get back to you with more information.

    Regards,
    Krunal 

  • Hi Rob,

    For the second GPIO, could you please share the value observed at the register GPIO_DATAIN and does it reflect the expected value? 

    Regards,
    Krunal

  • Krunal,

    Thanks for continuing to look into this.

    Here is a screen shot of the terminal from CPU B booting SPL.

    On this CPU the GPIO 1 is expected to be 1 (High) and GPIO 2 is expected to be 0 (Low)  

    The get_bank0_raw is the current value of GPIO_IN register for BANK0. Note 0x03000006 shows bits 1 and 2 are high.

    Regards,
    Rob

  • Hi Rob,

    Could you please share who is setting the value of GPIO2? I just want to confirm that one of the CPU is driving the value low and it is reflected by the get_bank0_value() function. 

    Regards,
    Krunal

  • Krunal,

    GPIO1 and GPIO2 are being set using external resisters solders to the board. There is not a processor driving the level. 

    CPU A is tied as shown below:

    CPU B is tied as shown here and in the previous post.

  • Hi Rob,

    Is the below summary correct:

    CPUA: 

    GPIO1-> Pulled Low -> Uboot reads 0
    GPIO2-> Pulled High -> Uboot reads 1

    CPUB: 

    GPIO1-> Pulled High -> Uboot reads 1
    GPIO2-> Pulled Low-> Uboot reads 1

    CPUC: 

    GPIO1-> Pulled High -> Uboot reads 1
    GPIO2-> Pulled High -> Uboot reads 1

    Please correct me if I am wrong but regardless of the CPU, if GPIO2 is pulled low, Uboot always reads 1.

    Regards,
    Krunal

  • Krunal,

    Thanks for the response. 

    Yes, this is correct. GPIO2 is always reading a 1 from uboot.

    Regards,
    Rob

  • Hi Rob,

    Based on my discussion with our HW expert, could you please disable the internal pullup/pulldow to avoid any contentions? (BIT16 CONF_MCASP0_AXR1_PUDEN)

    Regards,
    Krunal

  • Krunal,

    Apologies for not getting back to you sooner, I have been out of office. 

    I made the change to BIT16, as suggested above, and have found the same result.

    GPIO1 = 1 and GPIO2 = 1

    My terminal output is attached.

    Regards,
    Rob

  • Hi Rob,

    From the SW perspective, it seems like all the registers are configured correctly. I will double check with the hardware experts to make sure we did not miss any registers. In the meantime, I am wondering if it would be possible to pull GPIO2 low on CPUA or CPUC to ensure we are able to replicate the same error. 

    Regards,
    Krunal

  • Hi Rob,

    I am wondering if you could please pull the GPIO low on a different board. Also, if possible, could you please try to toggle the GPIO and share the results? I would like to eliminate any hardware issues. 

    Regards,
    Krunal

  • Krunal,

    As stated above, out board has 3 AM4376 SOCs on it. On each of the SOCs these pins are pulled to different levels. CPU A has GPIO 2 tied high and CPU B has GPIO2 tied low, see the schematic snippets below. I get the same result when I read the pins at either level on both SOCs.  Not sure what would be different if I tied it low using a fly wire?  

    Regards,
    Rob

  • Hi Rob,

    I get the same result when I read the pins at either level on both SOCs. 

    I understand that GPIO2 does not work as expected on CPUB. I just wanted to confirm that if we pull GPIO2 on CPUA low, Uboot reads it low. Have you tried to toggle the GPIO to see if it actually drives low?

    Regards,
    Krunal

  • Krunal,

    This morning we attached a fly wire on GPIO[0]2  (GPIO2) and validated that grounding the pin has not effect on the input value.  I then wrote a test for SPL that would set the pin to an output and drive it high to low and it appears to work?  Below is a snippet of my code and a capture of what I see on the scope.

    static int set_bank0_gpioout(int gpio,int value)
    {
    void *reg = GPIO0_DATAOUT;
    u32 l;

    printf("set_bank0_gpioout() : 0x%02X %d\n",gpio,value);

    if (value)
    l |= 1 << gpio;
    else
    l &= ~(1 << gpio);


    return __raw_writel(l, reg);
    }

    void toggle_bank0outputs(void)
    {
    u32 i;
    u32 Bank0Val = 0;

    enable_cpu_gpio_pin_mux();

    // Bank 0 pins as outputs.
    set_bank0_direction(CPUTYPE_MSB,0);

    for(i=0;i<100;i++)
    {
    set_bank0_gpioout(CPUTYPE_MSB,Bank0Val);

    Bank0Val = 1;

    set_bank0_gpioout(CPUTYPE_MSB,Bank0Val);

    Bank0Val = 0;
    }
    }

    Where:

    #define CPUTYPE_MSB    2

    #define GPIO0_DATAOUT   (AM33XX_GPIO0_BASE + OMAP_GPIO_DATAOUT)

    This is what I see on the scope:

    I really need this to work, let me know if I can test anything more to get to root cause?

    Regards,

    Rob

  • Hi Rob,

    I am checking with our hardware team and please correct me if I am wrong but GPIO2 never seems to be reading low. As an experiment, you have changed GPIO2 configuration on CPUA and pulled it low but Uboot shows GPIO2 value as 1. The same behavior is not observed on GPIO1 regardless of the CPU instance used.

    Regards,
    Krunal

  • Krunal,

    Your observation is correct.

    Thanks,
    Rob

  • Hi Rob,

    I am wondering if we could please perform the same test from the Uboot prompt. For example, I took a BBB and using a fly wire, I pulled a GPIO (GPIO3_21) low. Next, I used the following commands to set the Mux register and GPIO registers:


    1. mw 0x44e109ac 0x27 (0x44E1_0000 -> CTRL_MODULE, 0x9AC -> conf_mcasp0_ahclkx) (0x27 -> GPIO3_21 selected, Receiver enabled, Pullup selected, Pullup/pulldown disabled)

    2. mw 0x481ae134 0x200000 (0x481AE_000 -> GPIO3, 0x134 -> GPIO_OE) (0x200000 -> BIT21 set input)

    3. md 0x481ae138 (0x481AE_000 -> GPIO3, 0x138 -> GPIO_DATAIN)

    I ran the same experiment with the GPIO pulled high and it worked without any problems. Also, as you are modifying the above registers, please read them back to make sure they reflect the correct values.

    Regards,
    Krunal