[U-Boot] Driving GPIO in SPL
Chris LaRocque
clarocq at gmail.com
Fri Sep 20 14:53:18 UTC 2019
On Thu, Sep 19, 2019 at 12:10 PM Chris LaRocque <clarocq at gmail.com> wrote:
> 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
>
>
Update, I found that the PHY chip I was trying to configure was contending
with the GPIO pins. When I asserted the reset line I was able to set the
configuration lines for the PHY without issue. So the note about the GPIO
not changing state can be ignored.
I would still appreciate comments about the Console and the limit of the
code size for the SPL.
Thank You
Chris LaRocque
More information about the U-Boot
mailing list