Linux Usb: Turning the Power on and Off

Controlling a USB power supply (on/off) with Linux

Note. The information in this answer is relevant for the older kernels (up to 2.6.32). See tlwhitec's answer for the information on the newer kernels.

# disable external wake-up; do this only once
echo disabled > /sys/bus/usb/devices/usb1/power/wakeup

echo on > /sys/bus/usb/devices/usb1/power/level # turn on
echo suspend > /sys/bus/usb/devices/usb1/power/level # turn off

(You may need to change usb1 to usb n)

Source: Documentation/usb/power-management.txt.gz

Linux USB: turning the power on and off?

Digs through bookmarks

http://blog.andrew.net.au/2009/01/01#usb_power_control

Seems like you need to connect it to a hub and control the hub's power. None of the root hubs I have seen seems to be able to support power control.

How to turn USB port power on and off in Raspberry PI 4

Yes, uhubctl supports RPi4B, I have recently added support for it - you need to use uhubctl version 2.4.0 or later (or build it from master branch). It is also necessary to update USB firmware using sudo rpi-eeprom-update to make power switching actually work.

Note that you are missing out by using sysfs method to turn USB off on RPi3B+ - using uhubctl you can control either all 4 ports, or 2 of them independently. RPi4B only supports turning off all ports at once.

Turn off power to a USB port

Indeed, that other question did have a technique that worked for what I was trying to do. Note this isn't a generic Linux answer, it will only work on BeagleBone Black and similar devices. (I tested on a BeagleBone Green.) Working backwards from the devmem2 example, this block of C++ code turns the USB power off, then back on:

const size_t page_size_in_bytes = getpagesize();
const size_t address_gpio3_13 = 0x47401c60; // see comment below
const size_t address_start = address_gpio3_13 / page_size_in_bytes * page_size_in_bytes;
const size_t address_offset = address_gpio3_13 - address_start;

int fd = open("/dev/mem", O_RDWR);
void *addr = mmap( 0, page_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, address_start );

uint8_t *byte_ptr = reinterpret_cast<uint8_t*>(addr);

byte_ptr[address_offset] = 0x00; // turn off USB
std::this_thread::sleep_for( std::chrono::milliseconds(500) );
byte_ptr[address_offset] = 0x01; // turn on USB

munmap( addr, page_size_in_bytes );

close(fd);

(Error handling not included.)

The magic number 0x47401c60 really is a magic number. According to some posts, it looks like a NDA needs to be signed to get access to some of the USB-related documentation. In the ARM335X Technical Reference Manual, the only mention of the 0x47401Cxx address space is the following on page 156:

Block Name    Start Address    End Address
USB1 Core 0x4740_1C00 0x4740_1FFF


Related Topics



Leave a reply



Submit