openwrt/target/linux/ipq806x
Shane Synan 9f0575a130 ipq806x: revert SDC clock changes for NBG6817 MMC
Revert the SDC "CLK_SET_RATE_GATE" changes to the SDC clock regulator
structures.

See https://elinux.org/images/b/b8/Elc2013_Clement.pdf
> if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
>
> For this particular clock, setting its rate is possible only if the
> clock is ungated (not yet prepared)

This fixes the MMC failing to initialize on newer ZyXEL NBG6817
hardware revisions with Kingston MMC.  Older revisions should
hopefully be unaffected.

Check MMC hardware details with:
cd /sys/block/mmcblk0/device/ && \
  tail -v cid date name manfid fwrev hwrev oemid rev

Known problematic MMC names (broken before this commit):
* M62704 (dated 12/2018) via myself
* M62704 (dated 11/2018) via Drake Stefani

Known unaffected MMC names (already working without this commit):
* S10004 (dated 12/2015) via slh

Without enabling dynamic debugging, this error manifests in the kernel
hardware serial console as the following:

[    2.746605] mmc0: error -110 whilst initialising MMC card
[…trimmed other messages…]
[    2.877832] Waiting for root device /dev/mmcblk0p5...

Enabling Linux dynamic kernel debugging provides additional messages.
For guidance, see the Linux kernel documentation:
https://www.kernel.org/doc/html/latest/admin-guide/dynamic-debug-howto.html

First, enable dynamic debugging in OpenWRT's configuration:

1.  Run "make menuconfig"

2.  Select "Global build settings --->"

3.  Select "Kernel build options --->"

4.  Enable "Compile the kernel with dynamic printk" via spacebar

5.  Save and exit (arrow key to "Exit" until prompted to save, save)

Alternatively, set "CONFIG_KERNEL_DYNAMIC_DEBUG=y" in your .config.

Then, turn on dynamic debugging at boot:

Modify bootargs in
target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts
to add…

bootargs = "[…existing bootargs…] dyndbg=\"file drivers/mmc/* +p\" dynamic_debug.verbose=1 loglevel=8";

For example:
 	chosen {
-		bootargs = "rootfstype=squashfs,ext4 rootwait noinitrd fstools_ignore_partname=1";
+		bootargs = "rootfstype=squashfs,ext4 rootwait noinitrd fstools_ignore_partname=1 dyndbg=\"file drivers/mmc/* +p\" dynamic_debug.verbose=1 loglevel=8";
 		append-rootblock = "root=/dev/mmcblk0p";

Then, compile and flash the resulting build.  If you are testing
before this commit on newer MMC hardware, be prepared to recover!

NOTE: If you have hardware serial console access, you don't need to
use TFTP recovery to change the active boot partition.

Reboot to working alternative partition via serial console:

1.  Connect to hardware serial console
    * See https://openwrt.org/toh/zyxel/nbg6817#serial

2.  Interrupt boot at "Hit any key to stop autoboot:"

3.  Run "ATSE NBG6817"

4.  Copy the result (e.g. "001976FE4B04")
    * Changes with **every boot** - can't reuse this

5.  On your local system, run
    "./zyxel-uboot-password-tool.sh <copied value here>"
    * Example: "./zyxel-uboot-password-tool.sh 001976FE4B04"

6.  Run the command provided by the password tool
    * Example: "ATEN 1,910F129B"
    * Changes with **every boot** - can't reuse this

7.  Run "ATGU"
    * You now have full u-boot shell until next boot - unlocking is
       not remembered

8.  Run either "run boot_mmc" (for booting partition set "FF") or
    "run boot_mmc_1" (for booting partition set "01")
    * These commands are not affected by dual-boot partition flags

NOTE: This will NOT set the dual-boot partition flag.  You'll need to
fix that manually.  The "nbg6817-dualboot" script may help:
https://github.com/pkgadd/nbg6817/blob/master/nbg6817-dualboot

zyxel-uboot-password-tool.sh - sourced from
commit 459c8c9ef8:

ror32() {
  echo $(( ($1 >> $2) | (($1 << (32 - $2) & (2**32-1)) ) ))
}

v="0x$1"
a="0x${v:2:6}"
b=$(( a + 0x10F0A563))
c=$(( 0x${v:12:14} & 7 ))
p=$(( $(ror32 $b $c) ^ a ))
printf "ATEN 1,%X\n" $p

Kernel serial console log BEFORE commit with dynamic debug enabled:
[…trimmed…]
[    3.171343] mmci-pl18x 12400000.sdcc: designer ID = 0x51
[    3.171397] mmci-pl18x 12400000.sdcc: revision = 0x0
[    3.175811] mmci-pl18x 12400000.sdcc: clocking block at 96000000 Hz
[    3.181134] mmci-pl18x 12400000.sdcc: No vqmmc regulator found
[    3.186788] mmci-pl18x 12400000.sdcc: mmc0: PL180 manf 51 rev0 at 0x12400000 irq 41,0 (pio)
[    3.192902] mmci-pl18x 12400000.sdcc: DMA channels RX dma1chan1, TX dma1chan2
[    3.215609] mmc0: clock 0Hz busmode 2 powermode 1 cs 0 Vdd 21 width 1 timing 0
[    3.227532] mmci-pl18x 12400000.sdcc: Initial signal voltage of 3.3v
[    3.247518] mmc0: clock 52000000Hz busmode 2 powermode 2 cs 0 Vdd 21 width 1 timing 0
[…trimmed…]
[    3.997725] mmc0: req done (CMD2): -110: 00000000 00000000 00000000 00000000
[    4.003631] mmci-pl18x 12400000.sdcc: irq0 (data+cmd) 00000000
[    4.003659] mmc0: error -110 whilst initialising MMC card
[    4.016481] mmc0: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0

Notice how the initial clock is 52 MHz, which is incorrect - MMC
requires negotiation to enable higher speeds.

Kernel serial console log AFTER commit with dynamic debug enabled:
[…trimmed…]
[    3.168996] mmci-pl18x 12400000.sdcc: designer ID = 0x51
[    3.169051] mmci-pl18x 12400000.sdcc: revision = 0x0
[    3.173492] mmci-pl18x 12400000.sdcc: clocking block at 96000000 Hz
[    3.178808] mmci-pl18x 12400000.sdcc: No vqmmc regulator found
[    3.184702] mmci-pl18x 12400000.sdcc: mmc0: PL180 manf 51 rev0 at 0x12400000 irq 41,0 (pio)
[    3.190573] mmci-pl18x 12400000.sdcc: DMA channels RX dma1chan1, TX dma1chan2
[    3.217873] mmc0: clock 0Hz busmode 2 powermode 1 cs 0 Vdd 21 width 1 timing 0
[    3.229250] mmci-pl18x 12400000.sdcc: Initial signal voltage of 3.3v
[    3.249111] mmc0: clock 400000Hz busmode 2 powermode 2 cs 0 Vdd 21 width 1 timing 0
[…trimmed…]
[    4.392652] mmci-pl18x 12400000.sdcc: irq0 (data+cmd) 00000000
[    4.392785] mmc0: clock 52000000Hz busmode 2 powermode 2 cs 0 Vdd 21 width 1 timing 1
[    4.406554] mmc0: starting CMD6 arg 03b70201 flags 0000049d
[…trimmed…]

Now, the MMC properly initializes and later switches to high speed.

Thanks to:
* Ansuel for maintaining/help with the IPQ806x platform, kernel code
* slh for additional debugging and suggestions
* dwfreed for confirming newer MMC details, clock frequency
* robimarko for device driver debug printing help, clock debugging
* Drake for testing and confirmation with their own newer NBG6817
...and anyone else I missed!

Signed-off-by: Shane Synan <digitalcircuit36939@gmail.com>
Tested-by: Shane Synan <digitalcircuit36939@gmail.com>
2021-12-05 18:49:14 +01:00
..
base-files ipq806x: sysupgrade: drop unnecessary UBI to UBI logic 2021-12-03 12:23:02 +01:00
files/arch/arm/boot/dts ipq806x: add support for Cisco Meraki MR42/MR52 2021-11-28 17:51:52 +01:00
generic ipqx0xx: add Generic subtarget 2019-08-22 21:15:28 +02:00
image ipq806x: add support for Cisco Meraki MR42/MR52 2021-11-28 17:51:52 +01:00
patches-5.10 ipq806x: revert SDC clock changes for NBG6817 MMC 2021-12-05 18:49:14 +01:00
config-5.10 kernel: 5.10: packet mangling code only for ar8216 driver 2021-11-02 22:36:41 +01:00
Makefile ipq806x: switch to kernel 5.10 2021-09-12 18:52:30 +02:00
modules.mk kernel: usb: move phy-qcom-ipq806x-usb to ipq806x modules.mk 2020-08-13 02:12:12 +02:00