SD/MMC for WRT54G

SD/MMC storage add-on for WRT54G v2.2

Around 2010, the OpenWRT versions like kamikaze and backfire left very little flash for apps. So it was time to give the good old router some extra storage.

The unit discussed here is a WRT54G version 2.2 (Broadcom 4712, 200 MHz CPU, 4 MB flash and 16 MB DDR-SDRAM). It is the first WRT54G model with the BCM5325 switch. Previous models contained the ADM6996L.

It lacks the extra button on the front panel that was introduced in v3.0. The v3 button can be illuminated by either an amber or a white LED. Although these components are missing from the v2.2 model, the circuit board is already prepared for this. If you have a look at the board, you can find on the left corner, near the power LED, an empty place for a button and some components (labeled as SW2).

The SD/MMC card extension works by bit-banging general purpose IO (GPIO) lines that are either not used or not essential to the operation of the router. On a v2.2 router the following four GPIO lines can be used.

SD CARDGPIOpurposedirection
CSGPIO7DMZ LEDOUTPUT
DIGPIO5UNKNOWNOUTPUT
DOGPIO4FRONT BUTTON (not used on a v2.2)INPUT
CLKGPIO3AMBER LED (not used on a v2.2)OUTPUT

The hardware connections are straight forward, with only the connection to GPIO3 requiring some soldering skills. OpenWRT provides a package containing a kernel module for this hardware modification. You can install it using the opkg package manager.

opkg install kmod-mmc-over-gpio

The kernel module requires a configuration file (/etc/config/mmc_over_gpio) describing which GPIO ports are used and how they are connected:

config 'mmc_over_gpio'
	option 'name'    'default'
	option 'mode'    '0'
	option 'CS_pin'  '7'
	option 'DI_pin'  '5'
	option 'DO_pin'  '4'
	option 'CLK_pin' '3'

After installing the kernel module I ran into two problems and had to make some modification to the init.d script to get it to work. This may apply to other versions of the WRT54G as well.

The first problem I ran into was that GPIO3 (CLK) was not working. Neither with the driver nor with gpioctl. All other pins I could control manually with gpioctl, but not GPIO3.

Then it dawned on me that GPIO3 controls the amber led in newer models of the WRT54G. I tried to control GPIO3 using /proc/diag/led/ses_orange instead of gpioctl. And it worked! More importantly, it even enabled the control of GPIO3 using gpioctl and the mmc kernel module after that. So to cut a long story short, all we have to do is enable the amber led using the diag module before starting the mmc driver:

echo 1 > /proc/diag/led/ses_orange

Then I ran into the following problem. Reading and writing a larger file on a 2GB SD card crashed the router. A 4GB SDHC even crashed the router while loading the driver. Browsing the OpenWRT issue database provided the solution here. There is a conflict between the diag and mmc module. You have to disable the use of these GPIO lines by the diag module. As follows for the GPIO3/4/5/7 combination:

echo 0xb8 > /proc/diag/gpiomask

After this the module worked reliable. There is still a minor issue that using the sd card may lead to a flashing power led (just as if the router is booting). This can be addressed by

echo 1 > /proc/diag/led/power

Kernel logging when the module gets loaded:

# dmesg
gpio-mmc: Failed to request mmc_spi module.
mmc_spi spi32766.0: ASSUMING 3.2-3.4 V slot power
mmc_spi spi32766.0: SD/MMC host mmc0, no DMA, no WP, no poweroff
gpio-mmc: MMC-Card "default" attached to GPIO pins di=5, do=4, clk=3, cs=7
mmc_spi spi32766.0: can't change chip-select polarity
mmc0: host does not support reading read-only switch. assuming write-enable.
mmc0: new SD card on SPI
mmcblk0: mmc0:0000 SD    1.85 GiB
 mmcblk0: p1

OpenWRT Backfire 10.3 mount structure and available space:

# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root                 1.9M      1.9M         0 100% /rom
tmpfs                     6.6M      1.1M      5.4M  17% /tmp
tmpfs                   512.0K         0    512.0K   0% /dev
/dev/mtdblock3            1.0M    716.0K    308.0K  70% /overlay
mini_fo:/overlay          1.9M      1.9M         0 100% /
/dev/mmcblk0p1            1.8G      5.3M      1.7G   0% /mnt
# free
              total         used         free       shared      buffers
  Mem:        13416        12364         1052            0         1272
 Swap:            0            0            0
Total:        13416        12364         1052

And now some pictures:

The WRT54G v2.2 with the completed SD/MMC add-on
The WRT54G v2.2 with the completed SD/MMC add-on
The trickiest part is the connection of CLK (GPIO3) to pin 3 of RP4. The other wire (on the left) is DI connected to GPIO5
The trickiest part is the connection of CLK (GPIO3) to pin 3 of RP4. The other wire (on the left) is DI connected to GPIO5