From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 9504 invoked from network); 6 Nov 2021 03:26:36 -0000 Received: from 4ess.inri.net (216.126.196.42) by inbox.vuxu.org with ESMTPUTF8; 6 Nov 2021 03:26:36 -0000 Received: from duke.felloff.net ([216.126.196.34]) by 4ess; Fri Nov 5 23:18:15 -0400 2021 Message-ID: <201AE9BC6F65A8E579C32A6761D6BD32@felloff.net> Date: Sat, 06 Nov 2021 04:18:04 +0100 From: cinap_lenrek@felloff.net To: 9front@9front.org MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit List-ID: <9front.9front.org> List-Help: X-Glyph: ➈ X-Bullshit: replication-scale cloud Subject: [9front] pi 400 and cm4 mmc issues Reply-To: 9front@9front.org Precedence: bulk Mack Wallace sent me some kernel prints of the emmc errors on raspberry pi 400 and cm4 compute module, which look like this: sdhc: read error intr 2008002 stat 1fff0000 this means theres a DMA error there because bit 25 is set in the interrupt status. checking the linux device tree, i found the following comment: /* * emmc2 has different DMA constraints based on SoC revisions. It was * moved into its own bus, so as for RPi4's firmware to update them. * The firmware will find whether the emmc2bus alias is defined, and if * so, it'll edit the dma-ranges property below accordingly. */ emmc2bus: emmc2bus { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <1>; ranges = <0x0 0x7e000000 0x0 0xfe000000 0x01800000>; dma-ranges = <0x0 0xc0000000 0x0 0x00000000 0x40000000>; emmc2: mmc@7e340000 { compatible = "brcm,bcm2711-emmc2"; reg = <0x0 0x7e340000 0x100>; interrupts = ; clocks = <&clocks BCM2711_CLOCK_EMMC2>; status = "disabled"; }; }; this means the dram bus address for adma changes depending on the moon phase and is only discoverable using the device tree blob. so i wrote the following patch, adding a *emmc2bus kernel parameter, which we can eigther set manually, or will be discovered from the device tree. the issue with device tree is that linux people like to pointlessly re-arrange stuff all the time so it constantly breaks with firmware updates. so first experiment is to apply the patches and see if we created the *emmc2bus parameter like: cat '#ec/*emmc2bus' expected value should be eigther: c0000000 or 0 if the file isnt found, then my bootargs.c patch doesnt work. we can still manually override the offset by putting *emmc2bus=0 in config.txt and then see if the mmc errors go away. anyone with a pi 400 or cm4 can try this out please? --- /mnt/git/object/6c70026fa4b2ff235f60c883db15f55b4096bf6b/tree/sys/src/9/bcm/bootargs.c +++ sys/src/9/bcm/bootargs.c @@ -12,6 +12,7 @@ static char *confval[MAXCONF]; static int nconf; static char maxmem[256]; +static char emmc2bus[32]; static char pciwin[38], pcidmawin[38]; static int @@ -111,6 +112,15 @@ len -= 3*4; } addconf("*maxmem", maxmem); + } + return; + } + if(strcmp(path, "/emmc2bus") == 0 && strcmp(key, "dma-ranges") == 0 + && len == (2*4 + 2*4 + 1*4) && (beget4(p+2*4) | beget4(p+3*4)) == 0){ + if(findconf("*emmc2bus") < 0){ + addr = (uvlong)beget4(p+0*4)<<32 | beget4(p+1*4); + snprint(emmc2bus, sizeof(emmc2bus), "%llux", addr); + addconf("*emmc2bus", emmc2bus); } return; } --- /mnt/git/object/6c70026fa4b2ff235f60c883db15f55b4096bf6b/tree/sys/src/9/bcm64/sdhc.c +++ sys/src/9/bcm64/sdhc.c @@ -204,6 +204,7 @@ ulong extclk; int appcmd; Adma *dma; + uintptr busdram; }; static Ctlr emmc; @@ -247,7 +248,7 @@ p->desc |= len<desc |= Maxdma<addr = dmaaddr((void*)a); + p->addr = emmc.busdram + (PADDR(a) - PHYSDRAM); a += Maxdma; len -= Maxdma; n--; @@ -293,7 +294,11 @@ { u32int *r; ulong clk; + char *s; + emmc.busdram = soc.busdram; + if((s = getconf("*emmc2bus")) != nil) + emmc.busdram = strtoul(s, nil, 16); clk = getclkrate(ClkEmmc2); if(clk == 0){ clk = Extfreq; @@ -507,7 +512,7 @@ cachedwbse(buf, len); else cachedwbinvse(buf, len); - WR(Dmadesc, dmaaddr(emmc.dma)); + WR(Dmadesc, emmc.busdram + (PADDR(emmc.dma) - PHYSDRAM)); okay(1); } -- cinap