On Fri, Jan 8, 2021 at 05:27 PM, Jeremy Linton wrote: > > Hi, > > On 1/8/21 2:28 AM, Ard Biesheuvel wrote: > >> On 1/8/21 7:16 AM, Jeremy Linton wrote: >> >>> The primarly problem with the rpi Arasan controller working >>> with a default SDHCI driver is the lack of a meaningful >>> capabilities register. As such if we add a _DSD entry >>> to provide that information, we can then bind it to >>> the linux sdhci_iproc driver which already >>> hardcodes the remaining controller bugs. >>> >>> Further we have gotten BRCME88C approved as the HID >>> for the newer eMMC2 controller. So lets define an >>> ACPI object to describe it. >>> >>> Of course both devices are sharing an interrupt so >>> we should also indicate that in the table as well. >>> >>> Signed-off-by: Jeremy Linton >>> --- >>> Platform/RaspberryPi/AcpiTables/Dsdt.asl | 2 + >>> Platform/RaspberryPi/AcpiTables/Sdhc.asl | 86 >>> +++++++++++++++++++++++++++++++- >>> 2 files changed, 86 insertions(+), 2 deletions(-) >>> >>> diff --git a/Platform/RaspberryPi/AcpiTables/Dsdt.asl >>> b/Platform/RaspberryPi/AcpiTables/Dsdt.asl >>> index d116f965e1..cca08c0539 100644 >>> --- a/Platform/RaspberryPi/AcpiTables/Dsdt.asl >>> +++ b/Platform/RaspberryPi/AcpiTables/Dsdt.asl >>> @@ -150,6 +150,7 @@ DefinitionBlock ("Dsdt.aml", "DSDT", 5, "RPIFDN", >>> "RPI", 2) >>> QWORDMEMORYBUF(23) >>> QWORDMEMORYBUF(24) >>> QWORDMEMORYBUF(25) >>> + QWORDMEMORYBUF(26) >>> }) >>> >>> // USB >>> @@ -196,6 +197,7 @@ DefinitionBlock ("Dsdt.aml", "DSDT", 5, "RPIFDN", >>> "RPI", 2) >>> // SDC >>> QWORDMEMORYSET(24, MMCHS1_OFFSET, MMCHS1_LENGTH) >>> QWORDMEMORYSET(25, SDHOST_OFFSET, SDHOST_LENGTH) >>> + QWORDMEMORYSET(26, MMCHS2_OFFSET, MMCHS2_LENGTH) >>> >>> Return (RBUF) >>> } >>> diff --git a/Platform/RaspberryPi/AcpiTables/Sdhc.asl >>> b/Platform/RaspberryPi/AcpiTables/Sdhc.asl >>> index 0ab1ba27f2..a7ac831066 100644 >>> --- a/Platform/RaspberryPi/AcpiTables/Sdhc.asl >>> +++ b/Platform/RaspberryPi/AcpiTables/Sdhc.asl >>> @@ -19,7 +19,7 @@ >>> // Note: UEFI can use either SDHost or Arasan. We expose both to the OS. >>> // >>> >>> -// ArasanSD 3.0 SD Host Controller. >>> +// ArasanSD 3.0 SD Host Controller. (brcm,bcm2835-sdhci) >>> Device (SDC1) >>> { >>> Name (_HID, "BCM2847") >>> @@ -37,7 +37,7 @@ Device (SDC1) >>> Name (RBUF, ResourceTemplate () >>> { >>> MEMORY32FIXED (ReadWrite, 0, MMCHS1_LENGTH, RMEM) >>> - Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { >>> BCM2836_MMCHS1_INTERRUPT } >>> + Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { >>> BCM2836_MMCHS1_INTERRUPT } >>> }) >>> Method (_CRS, 0x0, Serialized) >>> { >>> @@ -45,6 +45,86 @@ Device (SDC1) >>> Return (^RBUF) >>> } >>> >>> + // The standard CAPs registers on this controller >>> + // appear to be 0, lets set some minimal defaults >>> + // Since this cap doesn't indicate DMA capability >>> + // we don't need a _DMA() >>> + Name (_DSD, Package () { >>> + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), >>> + Package () { >>> + Package () { "sdhci-caps", 0x0100fa81 }, >>> + } >>> + }) >>> + >>> + >>> + // >>> + // A child device that represents the >>> + // sd card, which is marked as non-removable. >>> + // >>> + Device (SDMM) >>> + { >>> + Method (_ADR) >>> + { >>> + Return (0) >>> + } >>> + Method (_RMV) // Is removable >>> + { >>> + Return (0) // 0 - fixed >>> + } >>> + } >>> +} >>> + >>> +#if (RPI_MODEL == 4) >>> +// emmc2 Host Controller. (brcm,bcm2711-emmc2) >>> +Device (SDC3) >>> +{ >>> + Name (_HID, "BRCME88C") >>> + Name (_UID, 0x1) >>> + Name (_CCA, 0x0) >>> + Name (_S1D, 0x1) >>> + Name (_S2D, 0x1) >>> + Name (_S3D, 0x1) >>> + Name (_S4D, 0x1) >>> + Method (_STA) >>> + { >>> + Return(0xf) >>> + } >>> + Name (RBUF, ResourceTemplate () >>> + { >>> + MEMORY32FIXED (ReadWrite, 0, MMCHS2_LENGTH, RMEM) >>> + Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { >>> BCM2836_MMCHS1_INTERRUPT } >>> + }) >>> + Method (_CRS, 0x0, Serialized) >>> + { >>> + MEMORY32SETBASE (RBUF, RMEM, RBAS, MMCHS2_OFFSET) >>> + Return (^RBUF) >>> + } >>> + >>> + // forceably limit to 1G >>> + Name (_DMA, ResourceTemplate() { >>> + QWordMemory (ResourceConsumer, >>> + , >>> + MinFixed, >>> + MaxFixed, >>> + NonCacheable, >>> + ReadWrite, >>> + 0x0, >>> + 0x0, // MIN >>> + 0x3fffffff, // MAX >>> + 0x0, // TRA >>> + 0x40000000, // LEN >>> + , >>> + , >>> + ) >>> + }) >>> + >> >> Shouldn't the _DMA method be on a container object instead of on the >> device object itself? > > Pained cough... There is a _DMA on the gpu devs container of which this > device belongs. That doesn't make the DMA work. The spec says that _DMA > is to exist on the bus device, and I think what is happening here is > that the "device" is the SDMM (which isn't directly visible because of > the way diff broke this patch up) contained in the "SDC3 mmc bus". The Linux device tree has 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. * And the dma-ranges property it references is: dma-ranges = <0x0 0xc0000000  0x0 0x00000000  0x40000000>; Not sure how the firmware will adjust this, but it does imply that there is actual translation going on here and it doesn't match the _DMA property you added. > > Frankly, I could be wrong, but what I do know is that without that bit > of ugliness DMA doesn't work in linux on this controller. I just > stripped it out again to verify the failure with 4.11. It does the same > thing, the controller itself seems to be working but the block device > associated with it can't be read. There are few other possibilities > (like maybe this controller shouldn't be a gpudevs child) and i'm fixing > a bug I created..I had kernel instrumentation in 5.9 tracking the dma > mask propagation, and I was fairly confident in this a couple months > ago, less so now. > One question I have is whether _DMA methods should be applied recursively or not. If you have a bus that provides a translating _DMA method that is behind a bus that also has a _DMA method, should the translation specified in that first _DMA method be applied or not? The text in the ACPI spec is far for clear her... If I read the Linux code in drivers/acpi/scan.c correctly, Linux would not apply the translation in this case. Since the _DMA method you add does not specify any translation, I think that means the required address translation isn't happening which means that DMA transactions would fail. I suspect the block device behind the controller would still be detected, but any actual I/O would fail since the right memory isn't addressed. So I think the best thing to do would be to have a separate ACPI0004 container with a translating _DMA method and but the emmc2 device below that. > > >> >>> + Name (_DSD, Package () { >>> + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), >>> + Package () { >>> + Package () { "sdhci-caps-mask", 0x0000000000080000 }, >>> + } >>> + }) >>> + >>> // >>> // A child device that represents the >>> // sd card, which is marked as non-removable. >>> @@ -62,6 +142,7 @@ Device (SDC1) >>> } >>> } >>> >>> +#else // !RPI4 >>> >>> // Broadcom SDHost 2.0 SD Host Controller >>> Device (SDC2) >>> @@ -105,3 +186,4 @@ Device (SDC2) >>> } >>> } >>> } >>> +#endif // !RPI4 >> >> > >