0

I am writing an operating system for the raspberry pi. I have a problem with the sdcard driver for the custom sdhost controller (emmc2) of the raspberry-pi 4 (Cortex-A72, ARMv8-A, bcm2711 chipset). Without using sdma everything works. With sdma, read works, but after writing sectors, the data on the sdcard sometimes contains invalid data.

For the sdma data transfer, I use a transfer buffer with a device type memory attribute (nGnRnE). When I use a fresh data buffer for the dma write transfer, the data on the sdcard is correct. But when I reuse the same buffer for the next write, then the sector on the sdcard partially contains data from the previous buffer content.

Maybe this is a cache coherency problem. I have enabled all caches (I and D). In the ARM manuals there is a talk of the SCU (snoop control unit) and I don't know whether I have do bother about the SCU.

My questions are:

  • Is it necessary to enable the SCU on a Cortex-A72 and how can this be done ?
  • What other things have to be kept in mind when using dma for device access ?
ErwinP
  • 402
  • 3
  • 9
  • 1
    The SCU is only to keep data consistent between cores. It will not work for DMA. DMA devices do not access L1/L2 cache, they always do 'memory-to-device' transfers. You must ensure that the buffer is flushed before activating the write DMA command OR you mark the driver memory as non-cacheable. – artless noise Mar 14 '21 at 16:41
  • The buffer is non-cachable. The memory type of the page is Device-nGnRnE (Device non-Gathering, non-Reordering, No Early write acknowledgement. Equivalent to the Strongly-ordered memory type in earlier versions of the architecture). I dumped the value of the L2 translation table entry of the page and it is 0x1279033. The elements of this L2 descriptor are: nG,non Global bit (bit 11) is 0; S,shareble bit (bit 10) is 0; TEX[2:0] (bit 8-6) is 0; C (bit 3) is 0; B (bit 2) is 0. So TEX[2:0],C,B is 000000 and this means Device-nGnRnE. TEX remap is disabled (SCTLR.TRE is 0). – ErwinP Mar 15 '21 at 06:57
  • Since you have no other input on this question, I would suggest you try the flush. It is possible that the tables are not setup properly. It is difficult to get all the bits correct. I agree if the table is correct, the flush is not needed. However, the flush will tell you if you have the tables correct. – artless noise Mar 17 '21 at 10:42
  • I flushed the cache. No success. Then I created a 2nd mapping with another virt.addr. and the phys.addr. of the dma-buffer, I read back the data from the 2nd virt.addr. and the data is correct. So I think that the data reaches the memory. The conclusion is that the sdhci controller does not read all data from memory, maybe it has its own cache? Looks unlikely for me. One thing is noticeable: a wrong 512 byte sector contains 3 32 byte blocks of correct data (16 byte aligned), all other data is old. The line-size of the l2-cache is 16 bytes. Maybe this indicates a relation to the l2-cache. – ErwinP Mar 18 '21 at 20:53

1 Answers1

0

I found the solution for my problem: On the raspberry pi 4 (bcm2711 chip), the physical addresses that are written into the registers of a dma engine must be legacy master addresses. The legacy master addresses are in the range 0xC0000000-0xFFFFFFFF. So I have to add 0xC0000000 to the values of the physical addresses that are written into the registers of the sdhci controller.

The documentation can be found here: https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf 1.2. Address map 1.2.4. Legacy master addresses

The answer to the other SCU question is: it is not necessary to enable the SCU on the Raspberry Pi 4 when the caches are enabled.

ErwinP
  • 402
  • 3
  • 9