[U-Boot] Driving GPIO in SPL

Chris LaRocque clarocq at gmail.com
Thu Sep 19 16:10:50 UTC 2019


Hello

I am trying to resolve an issue with a board based on the Beaglebone black.
I am using U-Boot 2015.10, it is being built with Buildroot 2016.2 on
OpenSuSE Leap 42.3 in a Virtualbox VM on a Windows 10 host. I want to set
the pad registers for the mii interface to GPIO (mode 7), configure the
pads as outputs, and drive the pins. I chose "enable_board_pin_mux" in
"/board/ti/am335x/mux.c" as a the location to accomplish this task.

However, I found that although I can change the state of a pin assigned to
GPIO1 I could not change ones assigned to GPIO2 or GPIO3. I can read
DATAOUT reg for all three GPIO modules and it reflects the requested
setting but the pins do not reflect the reg state. I suspected that the
pinmux was not being set by the call to "configure_module_pin_mux" so I
used "__raw_write" to set the pad configuration registers. This did not
change the situation.

Here are some relevant code snippets.


// CEL: Include necessary for timer
#include <common.h>

// CEL: Create static pin mux configurations for
// PHY configuration logic.

static struct module_pin_mux phy_config_pin_mux[] = {
{OFFSET(mii1_rxd3), MODE(7) | PULLUDDIS}, /* MII1_RXD3 */
{OFFSET(mii1_rxd2), MODE(7) | PULLUDDIS}, /* MII1_RXD2 */
{OFFSET(mii1_rxd1), MODE(7) | PULLUDDIS}, /* MII1_RXD1 */
{OFFSET(mii1_rxd0), MODE(7) | PULLUDDIS}, /* MII1_RXD0 */
    {OFFSET(mii1_rxclk), MODE(7) | PULLUDDIS}, /* MII1_RXCLK */
{OFFSET(mii1_rxerr), MODE(7) | PULLUDDIS}, /* MII1_RXERR */
{OFFSET(mii1_col), MODE(7) | PULLUDDIS}, /* MII1_RXERR */
{OFFSET(gpmc_ad2), MODE(7) | PULLUDDIS}, /* GPIO 1_2 The PHY Reset Line */
{-1},
};


-------------------

unsigned long reg, en_gpio1, en_gpio2, en_gpio3;

udelay(500000);

// CEL: Write pinmux directly
// instead of relying on inline functions
//configure_module_pin_mux(phy_config_pin_mux);

// OFFSET(mii1_rxd3), MODE(7) | PULLUDDIS
__raw_writel((0x7 + (1 << 3)), (0x44E10800 + 0x134));
// OFFSET(mii1_rxd2), MODE(7) | PULLUDDIS
__raw_writel((0x7 + (1 << 3)), (0x44E10800 + 0x139));
// OFFSET(mii1_rxd1), MODE(7) | PULLUDDIS
__raw_writel((0x7 + (1 << 3)), (0x44E10800 + 0x13C));
// OFFSET(mii1_rxd0), MODE(7) | PULLUDDIS
__raw_writel((0x7 + (1 << 3)), (0x44E10800 + 0x140));
 // OFFSET(mii1_rxclk), MODE(7) | PULLUDDIS
__raw_writel((0x7 + (1 << 3)), (0x44E10800 + 0x130));
 // OFFSET(mii1_rxerr), MODE(7) | PULLUDDIS
__raw_writel((0x7 + (1 << 3)), (0x44E10800 + 0x110));
 // OFFSET(mii1_col), MODE(7) | PULLUDDIS
__raw_writel((0x7 + (1 << 3)), (0x44E10800 + 0x108));
// OFFSET(gpmc_ad2), MODE(7) | PULLUDDIS
__raw_writel((0x7 + (1 << 3)), (0x44E10800 + 0x08));

udelay(500000);

//CM_PER_GPIO1_CLKCTRL
__raw_writel(0x00000002, (0x44E00000 + 0xAC));

//CM_PER_GPIO2_CLKCTRL

__raw_writel(0x00000002, (0x44E00000 + 0xB0));
 //CM_PER_GPIO3_CLKCTRL
__raw_writel(0x00000002, (0x44E00000 + 0xB4));

//udelay(100000);

//puts("In measArmCard Pinmux Configure.");

// CEL: Turn off clock gating and enable
// GPIO Modules GPIO_CTRL
en_gpio1 = __raw_readl((GPIO1_BASE + 0x130));
__raw_writel(0x0, (GPIO1_BASE + 0x130));

en_gpio2 = __raw_readl((GPIO2_BASE + 0x130));
__raw_writel(0x0, (GPIO2_BASE + 0x130));

en_gpio3 = __raw_readl((GPIO3_BASE + 0x130));
__raw_writel(0x0, (GPIO3_BASE + 0x130));

// CEL: Output Enable GPIO1, GPIO2, and GPIO3
// For the necessary GPIO Pins GPIO_OE
reg = __raw_readl((GPIO1_BASE + 0x134));
__raw_writel((reg & 0xFFFFFFFB), (GPIO1_BASE + 0x134));

reg = __raw_readl((GPIO2_BASE + 0x134));
__raw_writel((reg & 0xFFC3FFFF), (GPIO2_BASE + 0x134));

reg = __raw_readl((GPIO3_BASE + 0x134));
__raw_writel((reg & 0xFFFFFBFA), (GPIO3_BASE + 0x134));

// CEL: Set Output State for
// TPX2 = 0 GPIO_DATAOUT
reg = __raw_readl((GPIO1_BASE + 0x13C));

// CEL: Mask off the bits I want to set
reg = (reg & 0xFFFFFFFB);

// CEL: Set the bits I want
__raw_writel((reg | 0x00000000), (GPIO1_BASE + 0x13C));

// CEL: Set Output State for
// RXD3 = 0, RXD2 = 0, RXD1 = 1, RXD0 = 1
// GPIO_DATAOUT
reg = __raw_readl((GPIO2_BASE + 0x13C));

// CEL: Mask off the bits I want to set
reg = (reg & 0xFFC3FFFF);

// CEL: Set the bits I want
__raw_writel((reg | 0x00300000), (GPIO2_BASE + 0x13C));

// CEL: Set Output State for
// RXCLK = 0, RXERR = 0, COL = 1
// GPIO_DATAOUT
reg = __raw_readl((GPIO3_BASE + 0x13C));

// CEL: Mask off the bits I want to set
reg = (reg & 0xFFFFFBFA);

// CEL: Set the bits I want
__raw_writel((reg | 0x00000001), (GPIO3_BASE + 0x13C));

//puts("In pinmux configure: TPX2 = 0, RXD3 = 0, RXD2 = 0, RXD1 = 1, RXD0 =
1, RXCLK = 0, RXERR = 0, COL = 1.\n");

udelay(500000);


// CEL: Set Output State for
// TPX2 = 1
// GPIO_DATAOUT
reg = __raw_readl((GPIO1_BASE + 0x13C));

// CEL: Mask off the bits I want to set
reg = (reg & 0xFFFFFFFB);

// CEL: Set the bits I want
__raw_writel((reg | 0x00000004), (GPIO1_BASE + 0x13C));

//puts("In Pinmux Configure: TPX2 = 1, RXD3 = 0, RXD2 = 0, RXD1 = 1, RXD0 =
1, RXCLK = 0, RXERR = 0, COL = 1.\n");

udelay(500000);

// CEL: Set Output State for
// TPX2 = 0
// GPIO_DATAOUT
reg = __raw_readl((GPIO1_BASE + 0x13C));

// CEL: Mask off the bits I want to set
reg = (reg & 0xFFFFFFFB);

// CEL: Set the bits I want
__raw_writel((reg | 0x00000000), (GPIO1_BASE + 0x13C));

udelay(500000);

// CEL: Set Output State for
// TPX2 = 1
// GPIO_DATAOUT
reg = __raw_readl((GPIO1_BASE + 0x13C));

// CEL: Mask off the bits I want to set
reg = (reg & 0xFFFFFFFB);

// CEL: Set the bits I want
__raw_writel((reg | 0x00000004), (GPIO1_BASE + 0x13C));

//udelay(100000);

puts("In Pinmux Configure. Releasing mii interface\n");


-------------------------------------------------

Questions:

I believe that the SPL is a sequential application and that it does (can?)
not lock access to the pinmux (pad configuration). Is this true. Shouldn't
I be able to set the pad configurations for any pin?

The pin designated "TPX2" is configured as GPIO1_2 and it is changing state
as expected. The remaining pins GPIO2_18, GPIO2_19, GPIO2_20, GPIO2_21,
GPIO3_0, GPIO3_2, and  GPIO3_10 do not.

The "puts " commands do not print to console. I see that the unmodified
code in this function calls "puts" and expected console to be up. Is this
an incorrect assumption?

Adding all of this code caused u-boot to not come up and i had to remove
some lines to get it to come back. Is it possible for the SPL to be too
large and overwrite the available Static Ram in the AM3358 SOC?

Your guidance  and assistance is appreciated.

Also, can someone suggest a good reference for the "legacy" build system
for u-boot. At the moment the buildroot configuration for my board
specifies the "legacy" build system and though it does allow selection of
Kconfig that selection does not work in my case.

Thank You in Advance

Chris LaRocque


More information about the U-Boot mailing list