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.

[FAQ] SK-AM64: HOWTO: Enable Power on the Pi HAT connector on the AM64x SK EVM board

Part Number: SK-AM64

Am sharing this in case it helps others.

I have spent about two days trying to

  • First, figure out why there was no power on the 3V3 and 5V0 pins of the RPi-compatible user expansion connector J4
  • Second, figure out how to turn on the GPIO's that turn on the power on those pins
  • Third, how to automatically turn on power at boot.

It is a bit remarkable to me that a board with a RPi-compatible connector has the power disabled by default in the as-provided boot images and meta-ti layer.

I had to teach myself a bunch of things which many folks probably already know, but maybe some do not.  These are the things I wish I had known.

How Power Is Switched on the AM64x SK Board

3.3V and 5V power to the connector are switched by a pair of GPIO's that are attached to a TCA9538PWR I2C GPIO expander chip.  This is on p. 38 of the board schematic.  The signals of interest are RPI_PS_3V3_En and RPI_PS_5V0_En. 

The good news is that this expander and these pins are defined in the device tree supplied by TI; you just need to figure out how to get to them.

How to Toggle the GPIO's

If you come from a Beaglebone world, you are used to what's called the "sysfs GPIO interface".  This is not supported in the as-shipped resources, which is somewhat to be expected, as you can find repeatedly on the internet that the sysfs interface has been deprecated.

What's not often specified very clearly is what has replaced it.  The answer is libgpiod.  Now, libgpiod is just a set of libraries, no utilities.  But there is also libgpiod-tools, and those include utilities like "gpioinfo", "gpioset", and so on, that you can use to access the GPIO's.

So, if you're building an OS image with Arago / Yocto, you want to include this in your image's recipe or in a packagegroup that it uses:

RDEPENDS_${PN} = "\
    libgpiod \
    libgpiod-tools \
    ...

Then once you bitbake and flash that image, to turn on the power, you can use this command.

gpioset 1-0070 5=1 6=1

Breaking it down,

  • 1-0070 is the "GPIO chip"
  • 5 is the 5th bit of the chip (starting from 0), and we set its value to 1.  This is the 3.3V enable.
  • 6 is the 6th bit of the chip, and we set its value to 1.  This is the 5V enable.

Now, if you read the man page for gpioset, you find that the values you have set are not guaranteed to persist once gpioset returns.  So your enabling of these pins might persist, but it may well simply be transient.  You can get around this with the --mode=wait flag, but that ties up your command line.

Most likely what you want is to get your command line back yet have the values persist.  You can use "gpioset --mode=wait ... &", but that's not really what you want - it does work, but it goes to sleep in the background waiting for user input.

Most likely what you want, at least in the case of a pin setting that that you want to be pseudo-permanent like power enable, is

gpioset --background --mode=signal 1-0070 5=1 6=1

The --background flag is similar to the "&", but it is compatible with "--mode=signal".  This line will turn on the GPIO's, then the task will go into the background as a daemon, basically doing nothing but keeping its hold on the GPIO character device so that the pins do not revert to their default values.

If you do want to revert to 0 (power off), you simply kill the process and then just to be sure, follow up with

gpioset 1-0070 5=0 6=0

Where did the 1-0070 come from?

gpiodetect is a useful command (shown here on my machine segB1):

root@segB1:~# gpiodetect
gpiochip0 [omap-gpmc] (2 lines)
gpiochip1 [1-0070] (8 lines)
gpiochip2 [600000.gpio] (87 lines)
gpiochip3 [601000.gpio] (88 lines)
gpiochip4 [tpic2810] (8 lines)

We see the 1-0070.

You can then do this to see the individual lines that are available on that device

root@segB1:~# gpioinfo 1-0070
gpiochip1 - 8 lines:
        line 0: "GPIO_CPSW2_RST" unused input active-high
        line 1: "GPIO_CPSW1_RST" unused input active-high
        line 2: "PRU_DETECT" unused input active-high
        line 3: "MMC1_SD_EN" "fixed-regulator-sd" output active-high [used]
        line 4: "VPP_LDO_EN" unused input active-high
        line 5: "RPI_PS_3V3_En" "gpioset" output active-high [used]
        line 6: "RPI_PS_5V0_En" "gpioset" output active-high [used]
        line 7: "RPI_HAT_DETECT" unused input active-high

And we see our pins of interest there.  Don't worry if they happen to be listed as inputs instead of outputs.  That's just the OS guessing.  Once you use the pin with gpioset, it will know.

When you're first trying to get your bearings, you can use gpiofind to find a pin by name.  (The pin names are as given in the device tree file k3-sk642-evm.dts in the TI source tree.)

root@segB1:~# gpiofind RPI_PS_3V3_En
gpiochip1 5

It turns out that "gpiochip1" is just an alias for "1-0070" - you can use either term in the gpioset or gpioinfo commands:

Automatically Enabling Pi HAT Power on Boot

Assuming your Yocto/Arago build is using systemd (this is common, I believe), then what we can do is create a system service that turns on the power at boot.  I named my service "rpi-connector-power".  Once you've defined the service, then you can

  • Turn on connector power with systemctl start rpi-connector-power
  • Turn off connector power with systemctl stop rpi-connector-power
  • Configure the system to automatically turn on connector power at boot with  systemctl enable rpi-connector-power
  • (And conversely, disable connector power at boot with  systemctl disable rpi-connector-power)

To define the service, you create a file /lib/systemd/system/rpi-connector-power.service that defines the service.  This file will basically specify the gpioset commands to turn power on and off.

I'll show you that file in a second, but most likely you simply want to have this be installed as part of your Yocto/Arago image.  So here's how to do that.

The rpi-connector-power Recipe

This is what I did.  I created a recipe that automatically sets up systemd with our service and that enables that service by default.  We use the systemd.bbclass class from OpenEmbedded as a helper.

You should create these files and folders in your own custom Yocto layer (a.k.a. folder tree - I wish someone had told me in the beginning that a layer is just a fancy name for a folder tree), that you have added to build/conf/bblayers.conf.

Within your layer,

  • Create a recipe folder "rpi-connector-power".  Within that folder
    • Create the file rpi-connector-power.bb with the contents shown below
    • Create the file rpi-connector-power/rpi-connector-power.service (that's right, a second rpi-connector-power folder below the first) with the contents shown below.
  • Add rpi-connector-power to your recipe's RDEPENDS.   So it now should look like:
  • RDEPENDS_${PN} = "\
        libgpiod \
        libgpiod-tools \
        rpi-connector-power \
        ...

And lastly, here are the contents of those two files.  Note that I list the license as "CLOSED" for the recipe, but that's just a convenience for me during development.  Feel free to reuse this content and assign whatever license you like to it to your own work product.

rpi-connector-power.bb

DESCRIPTION = "Automatically turn on power to RPi HAT connector at boot"
# See the docs for systemd.bbclass for info

# Turns on the 3.3V power on bit 5, and the 5V power on bit 6, of I2C expander
# GPIO device 1-0070:

# gpioinfo 1-0070
#gpiochip1 - 8 lines:
# line 0: "GPIO_CPSW2_RST" unused input active-high
# line 1: "GPIO_CPSW1_RST" unused input active-high
# line 2: "PRU_DETECT" unused input active-high
# line 3: "MMC1_SD_EN" "fixed-regulator-sd" output active-high [used]
# line 4: "VPP_LDO_EN" unused input active-high
# line 5: "RPI_PS_3V3_En" unused output active-high
# line 6: "RPI_PS_5V0_En" unused input active-high
# line 7: "RPI_HAT_DETECT" unused input active-high

# If the license is anything other than CLOSED, then you have to provide LIC_FILES_CHKSUM.
LICENSE = "CLOSED"
inherit systemd

SYSTEMD_AUTO_ENABLE = "enable"
SYSTEMD_SERVICE:${PN} = "rpi-connector-power.service"

SRC_URI_append = " file://rpi-connector-power.service \
"

RDEPENDS_${PN} += " libgpiod-tools"

do_install() {
install -d ${D}/${systemd_unitdir}/system
install -m 0644 ${WORKDIR}/rpi-connector-power.service ${D}/${systemd_unitdir}/system
}
FILES:${PN} += "${systemd_unitdir}/system/rpi-connector-power.service"

rpi-connector-power.service

# Turns on and off the 3.3V power on bit 5, and the 5V power on bit 6, of I2C expander
# GPIO device 1-0070.

# To turn on the power, you start the service, then stop it to turn it off.

# $ gpioinfo 1-0070
# gpiochip1 - 8 lines:
# line 0: "GPIO_CPSW2_RST" unused input active-high
# line 1: "GPIO_CPSW1_RST" unused input active-high
# line 2: "PRU_DETECT" unused input active-high
# line 3: "MMC1_SD_EN" "fixed-regulator-sd" output active-high [used]
# line 4: "VPP_LDO_EN" unused input active-high
# line 5: "RPI_PS_3V3_En" unused output active-high
# line 6: "RPI_PS_5V0_En" unused input active-high
# line 7: "RPI_HAT_DETECT" unused input active-high
#

[Unit]
Description=Turn power on or off to the Raspberry Pi user connector on the AM64x SK board

[Service]
Type=forking
Restart=no
TimeoutSec=5min
IgnoreSIGPIPE=no
KillMode=process
GuessMainPID=no
RemainAfterExit=yes
ExecStart=/usr/bin/gpioset --background --mode=signal 1-0070 5=1 6=1
ExecStop=/bin/sh -c "/bin/kill -TERM `ps -ef | grep 'gpioset --background --mode=signal 1-0070 5=1 6=1' | grep -v grep | awk '{print $2}'` && gpioset 1-0070 5=0 6=0"

[Install]
WantedBy=multi-user.target

Now bitbake your image and flash it.  On next boot, you can verify that it is working by verifying that the gpioset process is running in the background

root@segB1:~# ps -ef | grep gpioset
root 401 1 0 01:47 ? 00:00:00 /usr/bin/gpioset --background --mode=signal 1-0070 5=1 6=1

and by checking with your voltmeter that there is 3.3V between pins 6 and 1 of the user connector, and 5V between pins 6 and 2.

As stated earlier, you can turn the power off with 

systemctl stop rpi-connector-power

and turn it back on with

systemctl start rpi-connector-power

Hope this has been useful.

 

  • Very COOL!!!  Many many thanks!Grinning

  • It is great to know you worked out a solution, and thanks for sharing the details. It will be useful for other users.

  • Hello Friend,

    In which file of the sdk should I add this line?

    RDEPENDS_${PN} = "\
        libgpiod \
        libgpiod-tools \
        ...

  • Hi Tim,

    I'm not a Yocto expert at all.  But here's my stab.  I actually added that line to a packagegroup I defined for my project called "packagegroup-lseb-full.bb", and then my image file adds that packagegroup to its IMAGE_INSTALL list, like this:


      IMAGE_INSTALL = "\
        packagegroup-lseb-full \
        ${CORE_IMAGE_EXTRA_INSTALL} \
        "

    I think that the level of indirection of using a packagegroup is not necessary.  I believe that you should be able to add libgpiod and libgpiod-tools to your IMAGE_INSTALL instead.

    That is, if you are bitbaking your own image, you can just add that to the image fie that you are specifying on the bitbake command line.  So in my case I am building my SD card image using

      MACHINE=am64xx-evm ARAGO_RT_ENABLE=1 bitbake image-lseb

    so I can add either the packagegroup line or the individual package lines to my file "image-lseb.bb".  

    If you are not bitbaking your own image, sadly you will have to.  If you've not done this before, it is a harrowing process to do the first time, literally the most complicated software build that I've done in my career.  But that's the only way to add features to a boot image.

    There is a blunt-hammer approach that may get you over the hump if you don't want to have to build out your own recipes and layers, which is to add the packages to your build/conf/local.conf file, and then just bitbake whatever as-shipped package you might be using. 

    For example, bitbaking the stock core-image-full-cmdline recipe gives a fairly capable system.  Rather than writing your own recipe that depends on it, you could try adding lipgpiod and lobgpiod-tools to the EXTRA_IMAGE_FEATURES line of local.conf.  (Let me know if you try that and it works.)  Those will then be added to every image you ever build, but that may well be desirable.  

    I am preparing a write-up for our own development team here that describes everything that I have had to do to get to the point of having our own recipes and layer tha supports libgpiod and all the other stuff we use.  I cannot post it, but I might be able to get permission to share it with you individually when it's done in a few days.

    Brad