Ath79: SD-card on SPI-bus(Deep MMC Mod)

This topic for porting Deep MMC Mod(OpenWRT) on LEDE Project.
And there some problem with loading mmc and mmc-spi modules <- its stuck and stuck kernel boot after.

Patch(with GPIO2 as CS)
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c
index e53d97d..269e469 100644
--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c
+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c
@@ -7,8 +7,10 @@
  */
 
 #include <linux/init.h>
+#include <linux/mmc/host.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
+#include <linux/spi/mmc_spi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/concat.h>
@@ -16,6 +18,11 @@
 #include "dev-spi.h"
 #include "dev-m25p80.h"
 
+static struct mmc_spi_platform_data ath79_mmc_data = {
+	.detect_delay = 100, /* msecs */
+	.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
 static struct spi_board_info ath79_spi_info[] = {
 	{
 		.bus_num	= 0,
@@ -27,18 +34,25 @@ static struct spi_board_info ath79_spi_info[] = {
 		.bus_num	= 0,
 		.chip_select	= 1,
 		.max_speed_hz   = 25000000,
-		.modalias	= "m25p80",
+		.modalias	= "mmc_spi",
+		.platform_data	= &ath79_mmc_data,
 	}
 };
 
+static int device_spi_cs_gpios[2] = {
+	-ENOENT,
+	2, /* GPIO Number */
+};
+
 static struct ath79_spi_platform_data ath79_spi_data;
 
 void __init ath79_register_m25p80(struct flash_platform_data *pdata)
 {
 	ath79_spi_data.bus_num = 0;
-	ath79_spi_data.num_chipselect = 1;
+	ath79_spi_data.num_chipselect = 2;
+	ath79_spi_data.cs_gpios = device_spi_cs_gpios;
 	ath79_spi_info[0].platform_data = pdata;
-	ath79_register_spi(&ath79_spi_data, ath79_spi_info, 1);
+	ath79_register_spi(&ath79_spi_data, ath79_spi_info, 2);
 }
 
 static struct flash_platform_data *multi_pdata;

The same problem is described in this issue.
But now, OpenWRT works fine with this mod.
Something with packages i guess.

1 Like

I compiled fresh LEDE from trunk and now this mod fine works (up to kernel version update).

My bootlog
BusyBox v1.27.2 () built-in shell (ash)

     _________
    /        /\      _    ___ ___  ___
   /  LE    /  \    | |  | __|   \| __|
  /    DE  /    \   | |__| _|| |) | _|
 /________/  LE  \  |____|___|___/|___|                      lede-project.org
 \        \   DE /
  \    LE  \    /  -----------------------------------------------------------
   \  DE    \  /    Reboot (SNAPSHOT, r5121-c84b7ea)
    \________\/    -----------------------------------------------------------

=== WARNING! =====================================
There is no root password defined on this device!
Use the "passwd" command to set up a new password
in order to prevent unauthorized SSH logins.
--------------------------------------------------
root@LEDE:~# dmesg | tail
...
[   14.122923] mmc_spi spi0.1: SD/MMC host mmc0, no DMA, no WP, no poweroff
[   14.146943] PPP generic driver version 2.4.2
[   14.154816] NET: Registered protocol family 24
[   14.211657] PCI: Enabling device 0000:00:00.0 (0000 -> 0002)
[   14.222523] ath: phy0: Ignoring endianness difference in EEPROM magic bytes.
[   14.229715] ath: phy0: Enable LNA combining
[   14.235395] ath: EEPROM regdomain: 0x0
[   14.235402] ath: EEPROM indicates default country code should be used
[   14.235406] ath: doing EEPROM country->regdmn map search
[   14.235425] ath: country maps to regdmn code: 0x3a
[   14.235432] ath: Country alpha2 being used: US
[   14.235438] ath: Regpair used: 0x3a
[   14.250230] ieee80211 phy0: Selected rate control algorithm 'minstrel_ht'
[   14.258833] ieee80211 phy0: Atheros AR9285 Rev:2 mem=0xb0000000, irq=40
[   14.299196] mmc0: host does not support reading read-only switch, assuming write-enable
[   14.307307] mmc0: new SD card on SPI
[   14.441568] mmcblk0: mmc0:0000 00000 1.90 GiB
[   14.464620] kmodloader: done loading kernel modules from /etc/modules.d/*
[   14.522462]  mmcblk0: p1
[   23.127329] jffs2_scan_eraseblock(): End of filesystem marker found at 0x0
[   23.143305] jffs2_build_filesystem(): unlocking the mtd device... 
[   23.149354] done.
[   23.151293] jffs2_build_filesystem(): erasing all blocks after the end marker... 
[   26.923068] done.
[   26.925072] jffs2: notice: (881) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) found.
[   29.516095] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[   29.547994] br-lan: port 1(eth0.1) entered blocking state
[   29.553519] br-lan: port 1(eth0.1) entered disabled state
[   29.559468] device eth0.1 entered promiscuous mode
[   29.564356] device eth0 entered promiscuous mode
[   29.653174] IPv6: ADDRCONF(NETDEV_UP): br-lan: link is not ready
[   29.697528] IPv6: ADDRCONF(NETDEV_UP): eth1: link is not ready
[   31.154183] eth0: link up (1000Mbps/Full duplex)
[   31.158870] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[   31.208529] br-lan: port 1(eth0.1) entered blocking state
[   31.214045] br-lan: port 1(eth0.1) entered forwarding state
[   31.409814] IPv6: ADDRCONF(NETDEV_CHANGE): br-lan: link becomes ready
[  109.512970] random: crng init done
root@LEDE:~# 
root@LEDE:~# cat /sys/kernel/debug/gpio 
GPIOs 0-19, platform/ath79-gpio, ath79:
 gpio-0   (                    |tp-link:green:qss   ) out hi    
 gpio-1   (                    |tp-link:green:system) out lo    
 gpio-2   (                    |spi0.1              ) out hi    
 gpio-6   (                    |USB power           ) out hi    
 gpio-8   (                    |tp-link:green:3g    ) out hi    
 gpio-11  (                    |reset               ) in  hi    
 gpio-12  (                    |qss                 ) in  hi    

GPIOs 500-511, pci/0000:00:00.0, ath9k-phy0:
 gpio-501 (                    |ath9k-phy0          ) out hi    
root@LEDE:~#

I've been playing with this on a TL-WR741ND v1 on the lede-17.01 branch and, as mentioned previously, the mmc-spi driver just hangs. I tried both HW SPI + internal CS1 and bitbang SPI with the same result.

While troubleshooting the problem I wrote an SD card block device driver in user-space. It uses NBD and SPIDev. I think this might help when troubleshooting in the future and thought I'd share.

Patch against lede-17.01: https://gitlab.com/snippets/1731679
Driver code (SDABUSE): https://gitlab.com/ar2000jp/SDABUSE
Example build script: snippet #1731700 (Can't add more links :frowning:)

Enable these in OpenWRT's make menuconfig:-

  • For GPIO bitbang SPI:
    Global build settings -> [*] /dev/mem virtual device support

  • For SPIDev SPI:
    Kernel modules -> SPI Support -> <*> kmod-spi-dev

  • Always required:
    Kernel modules -> Block Devices -> <*> kmod-nbd

  • F2FS support:
    Kernel modules -> Filesystems -> <> kmod-fs-f2fs
    Utilities -> Filesystem -> <
    > f2fs-tools

Because on the 4.14+ kernel, the ar71xx platform switches to dts profiles (platform ath79).
Here's the update link.

Also in the near future, will be tested the CS(n) expansion scheme(will be used the popular shift register 74HC595) - i.e. for only one SPI bus (spi0.0), you can hang many-many devices without GPIO usage.CS-switch

1 Like

Thank you @Deoptim for this hack!

Just to register, I've tested the first and the second way with success in an old WR941ND v3.6 (8MB flash modded) using a custom build of 19.07.4/ath79.

1 Like