SD Host Controller driver (on Raspberry Pi)
Posted: Fri Nov 19, 2021 6:07 am
Hi,
As i'm trying to support the Raspberry Pi in my kernel, i need a way to read the SD Card.
I had never dealt with SD cards before, so i read the SD specifications (https://www.sdcard.org/downloads/pls/, Physical Layer Simplified Specification).
It was a little bit hard to understand everything, but i think i now understand the basics of the SD protocol, how to initialize and enter data transfer mode, ...
(side note: i could not find any information about SD Cards on the wiki, but maybe this is because of the license of this specification ? it seems we don't have any rights to reproduce parts of the specification, and other legal requirements that i did not understand well)
I then read the BCM2835 Arm Peripherals specification (Raspberry Pi soc), available here https://datasheets.raspberrypi.com/bcm2 ... herals.pdf, section 5 : External Mass Media Controller. This describes the Arasan controller, but only the modifications that Broadcom did to it. They refer to the original Arasan documentation, but a quick search on google shows that Arasan never published this documentation nor intended to, as it is supposed to be available for SoC manufacturers only.
Anyway, i read on the specifications, and using the MMIO addresses described, i got a response to an initialization command.
I don't understand how this is possible, and to my understanding Broadcom are completely crazy :
the SD protocol defines 48-bits communication channels to send commands, but Broadcom seems to have split this up in 2 32-bits MMIO registers, CMDTM and ARG1.
You would expect something like : low 32 bits are ARG1, and up 16 bits are the low or high 16 bits of CMDTM (CMDTM meaning Command AND Transfer Mode)
This is basically what my code assumes. It doesnt matter much for init commands as the arguments are pretty much ignored (like controller SDHC capacity/ ..., i will still get a response either way)
(EDIT : i just realized i sent two times CMD0 and not ACMD41, and i can't get a response on ACMD41 ; on double CMD0 i get 0x1 as a response, i think it brings the device in SPI mode, but i'm not intersted in that)
However, Broadcom layout describes fields on the CMDTM register that are not in the SD protocol standard (like CMD_ISDATA, to tell the controller if the command will involve a data transfer),
and these fields are taking place of the bits that would normally be used by other standard arguments. So : they seem to have randomized the 16 bits left over a 32 bits register, adding nonstandard bits in the way. How am i supposed to deal with this ?
I tried to read the linux driver code, but it isn't that easy : the RPI seems to have 2 different host controller (my guess is orginally one for the GPU to load the kernel and one for the ARM). The SD Host Controller that is not the Arasan one seems to be faster, so they have a specific driver for this one in linux (drivers/mmc/host/bcm2835.c). However this is NOT the one i'm interested in. If i understand correctly, for the Arasan one, they use the 'sdhci' driver. I did not understand what sdhci meant as first, but it seems to be 'SD Host Controller Interface', so a generic standard host controller driver.
Maybe i'm living in a fantasy world, but i was under the impression that SD Protocol was standardised enough so that there would be such an universal sd host controller driver, and it is what i'm trying to make (i would like to reuse my driver on other devices that are not the pi later if possible).
Is this real ? Or am i wrong and each SD host controller needs it's own driver ?
But then how does linux do it ? I've seen that they have sdhci over pci (drivers/mmc/host/sdhci-pci-core.c) and even arasan sdhci (drivers/mmc/host/sdhci-pci-arasan.c) specific drivers, but reading them it seems like they only fix some specific performance/bugs on the hardware, but still use the generic driver.
Is this possible to write a generic sdhci driver ? How am i supposed to get the BCM2835 Arasan SD controller to comply to the SD standard, where are the bits that are standard and why would i need to fill the bits that are not ?
I'm a little bit lost in this.
If someone already implemented an SD Card driver, for the PC (i think most of them are accessible through PCI or behind an USB interface ?), or even for the raspberry pi, i would love to hear from you.
(NB: i'm talking about an SD Protocol driver, not an SPI driver)
vhaudiquet
As i'm trying to support the Raspberry Pi in my kernel, i need a way to read the SD Card.
I had never dealt with SD cards before, so i read the SD specifications (https://www.sdcard.org/downloads/pls/, Physical Layer Simplified Specification).
It was a little bit hard to understand everything, but i think i now understand the basics of the SD protocol, how to initialize and enter data transfer mode, ...
(side note: i could not find any information about SD Cards on the wiki, but maybe this is because of the license of this specification ? it seems we don't have any rights to reproduce parts of the specification, and other legal requirements that i did not understand well)
I then read the BCM2835 Arm Peripherals specification (Raspberry Pi soc), available here https://datasheets.raspberrypi.com/bcm2 ... herals.pdf, section 5 : External Mass Media Controller. This describes the Arasan controller, but only the modifications that Broadcom did to it. They refer to the original Arasan documentation, but a quick search on google shows that Arasan never published this documentation nor intended to, as it is supposed to be available for SoC manufacturers only.
Anyway, i read on the specifications, and using the MMIO addresses described, i got a response to an initialization command.
I don't understand how this is possible, and to my understanding Broadcom are completely crazy :
the SD protocol defines 48-bits communication channels to send commands, but Broadcom seems to have split this up in 2 32-bits MMIO registers, CMDTM and ARG1.
You would expect something like : low 32 bits are ARG1, and up 16 bits are the low or high 16 bits of CMDTM (CMDTM meaning Command AND Transfer Mode)
This is basically what my code assumes. It doesnt matter much for init commands as the arguments are pretty much ignored (like controller SDHC capacity/ ..., i will still get a response either way)
(EDIT : i just realized i sent two times CMD0 and not ACMD41, and i can't get a response on ACMD41 ; on double CMD0 i get 0x1 as a response, i think it brings the device in SPI mode, but i'm not intersted in that)
However, Broadcom layout describes fields on the CMDTM register that are not in the SD protocol standard (like CMD_ISDATA, to tell the controller if the command will involve a data transfer),
and these fields are taking place of the bits that would normally be used by other standard arguments. So : they seem to have randomized the 16 bits left over a 32 bits register, adding nonstandard bits in the way. How am i supposed to deal with this ?
I tried to read the linux driver code, but it isn't that easy : the RPI seems to have 2 different host controller (my guess is orginally one for the GPU to load the kernel and one for the ARM). The SD Host Controller that is not the Arasan one seems to be faster, so they have a specific driver for this one in linux (drivers/mmc/host/bcm2835.c). However this is NOT the one i'm interested in. If i understand correctly, for the Arasan one, they use the 'sdhci' driver. I did not understand what sdhci meant as first, but it seems to be 'SD Host Controller Interface', so a generic standard host controller driver.
Maybe i'm living in a fantasy world, but i was under the impression that SD Protocol was standardised enough so that there would be such an universal sd host controller driver, and it is what i'm trying to make (i would like to reuse my driver on other devices that are not the pi later if possible).
Is this real ? Or am i wrong and each SD host controller needs it's own driver ?
But then how does linux do it ? I've seen that they have sdhci over pci (drivers/mmc/host/sdhci-pci-core.c) and even arasan sdhci (drivers/mmc/host/sdhci-pci-arasan.c) specific drivers, but reading them it seems like they only fix some specific performance/bugs on the hardware, but still use the generic driver.
Is this possible to write a generic sdhci driver ? How am i supposed to get the BCM2835 Arasan SD controller to comply to the SD standard, where are the bits that are standard and why would i need to fill the bits that are not ?
I'm a little bit lost in this.
If someone already implemented an SD Card driver, for the PC (i think most of them are accessible through PCI or behind an USB interface ?), or even for the raspberry pi, i would love to hear from you.
(NB: i'm talking about an SD Protocol driver, not an SPI driver)
vhaudiquet