• Ben Avison's avatar
    SDIO card interrupt support · 3d84c6d3
    Ben Avison authored
    The SDIO specification allows IO cards to request servicing by driver
    software on the host by repurposing the DAT1 pin when it is not being used to
    transfer data blocks, i.e. during the "interrupt period". SD controllers
    typically take care of sampling DAT1 appropriately, and proxy the interrupt
    to the CPU by piggybacking on the SD host controller's interrupt. Thus
    SDIODriver needs to be involved in disambiguating card interrupts from other
    host controller interrupts. However, the servicing action required on a card
    interrupt varies from card to card, so SDIODriver needs to delegate this
    to individual card drivers.
    
    To achieve this, implement SWIs SDIO_ClaimDeviceVector and
    SDIO_ReleaseDeviceVector as previously specified. Note that these are
    function-specific, so for example a combined WiFi/Bluetooth card would have
    separate handlers for its WiFi and Bluetooth functions, potentially in
    separate driver modules.
    
    The fact that DAT1 interrupts are level-sensitive, and that servicing any
    interrupt by issuing further operations over the same SD bus - a lengthy
    process that requires the use of other SD controller interrupts - means that
    the card interrupt must be masked until servicing is complete. The card
    driver therefore needs some way to signal to SDIODriver that servicing is
    complete and DAT1 interrupts can be unmasked again. This is achieved using
    new SWI SDIOControl 7.
    
    To accelerate interrupt dispatch, SDIODriver has two optimisations:
    
    * If only one function has an installed handler for a given card, it skips
      polling the "Int Pending" register in the card, and immediately dispatches
      to the one handler.
    * SDIODriver now snoops the results of operations for each slot to keep track
      of which RCA (if any) is selected. This means if multiple functions have
      installed handlers, it only needs to issue CMD7 if the card is not
      selected. This facility appears to be beneficial more generally for driver
      code ported from other OSes, and so it is exposed via new SWI SDIO_Status 0.
    
    At the low level, any standard SDHCI controller is automatically supported,
    providing SDIODriver trusts its interrupt device number (i.e. minor version
    2 or above). Soft controllers are supported via two additional functions:
    EnableCardInterrupt() and CardInterruptStatus(). These are assumed to be
    defined for all type-2 soft controllers (since these are being added at the
    same version of SDIOController as type-2 soft controllers were introduced,
    there's no need to test for their presence at runtime). Type-1 soft
    controllers are superseded by type-2 soft controllers, so there's no need to
    add equivalent functions to them.
    
    This commit also adds a test module which was used in development for testing
    card interrupt dispatch in a way that doesn't rely on having a genuine SDIO
    card interrupt working (which would require a card driver to be in a more
    advanced state than they are at the current time). This relies on a backdoor
    SWI in SDIODriver - SDIO_Control &100. Support for this is wrapped in #if
    conditionals, and may be disabled in future, once the system has been proved
    in real-world usage.
    3d84c6d3