| // Copyright 2024 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| @available(added=HEAD) |
| library fuchsia.hardware.sdhci; |
| |
| using fuchsia.hardware.sdmmc; |
| using zx; |
| |
| type Quirk = strict bits : uint64 { |
| /// This is a BCM28xx specific quirk. The bottom 8 bits of the 136 |
| /// bit response are normally filled by 7 CRC bits and 1 reserved bit. |
| /// The BCM controller checks the CRC for us and strips it off in the |
| /// process. |
| /// The higher level stack expects 136B responses to be packed in a |
| /// certain way so we shift all the fields back to their proper offsets. |
| STRIP_RESPONSE_CRC = 0x1; |
| /// BCM28xx quirk: The BCM28xx appears to use its internal DMA engine to |
| /// perform transfers against the SD card. Normally we would use SDMA or |
| /// ADMA (if the part supported it). Since this part doesn't appear to |
| /// support either, we just use PIO. |
| NO_DMA = 0x2; |
| /// The bottom 8 bits of the 136 bit response are normally filled by 7 CRC bits |
| /// and 1 reserved bit. Some controllers strip off the CRC. |
| /// The higher level stack expects 136B responses to be packed in a certain way |
| /// so we shift all the fields back to their proper offsets. |
| STRIP_RESPONSE_CRC_PRESERVE_ORDER = 0x4; |
| /// The controller uses a tuning process that does not follow the SDHCI specification. |
| NON_STANDARD_TUNING = 0x8; |
| /// Don't use DDR modes even if the SDHCI capabilities register indicates it is supported. |
| NO_DDR = 0x10; |
| /// Prevent DMA buffers from crossing boundaries specified by dma_boundary_alignment. For |
| /// example, a boundary alignment of 0x10000 will cause buffers crossing 64K boundaries to be |
| /// split across multiple descriptors. |
| USE_DMA_BOUNDARY_ALIGNMENT = 0x20; |
| NO_HS400_ENHANCED_STROBE = 0x40; |
| /// These bits correspond to the following fuchsia.hardware.sdmmc.Sdmmc methods: |
| /// - `SetSignalVoltage()` |
| /// - `SetBusWidth()` |
| /// - `SetBusFreq()` |
| /// - `SetTiming()` |
| /// - `PerformTuning()` |
| /// |
| /// If the bit for a method is set, it means that the hardware deviates from the SDHCI |
| /// specification, and the SDHCI driver should call `VendorConfigureBus()` or |
| /// `VendorPerformTuning()` to let the vendor driver handle the operation. If the bit is not |
| /// set, the SDHCI will handle the operation as per the specification. |
| VENDOR_SET_SIGNAL_VOLTAGE = 0x80; |
| VENDOR_SET_BUS_WIDTH = 0x100; |
| VENDOR_SET_BUS_FREQ = 0x200; |
| VENDOR_SET_TIMING = 0x400; |
| VENDOR_PERFORM_TUNING = 0x800; |
| }; |
| |
| @discoverable |
| @transport("Driver") |
| closed protocol Device { |
| strict GetInterrupt() -> (resource struct { |
| irq zx.Handle:INTERRUPT; |
| }) error zx.Status; |
| |
| /// Mmio size minus offset must be at least 512 bytes as per the SDHCI specification. |
| strict GetSdhciMmio() -> (resource struct { |
| mmio zx.Handle:VMO; |
| offset zx.Off; |
| }) error zx.Status; |
| |
| /// Mmio size minus offset must be at least 260 bytes as per the CQHCI specification. |
| /// Returns |
| /// - ZX_ERR_NOT_SUPPORTED if the device does not support CQHCI |
| strict GetCqhciMmio() -> (resource struct { |
| mmio zx.Handle:VMO; |
| offset zx.Off; |
| }) error zx.Status; |
| |
| /// Gets a handle to the bus transaction initiator for the device. The caller |
| /// receives ownership of the handle. |
| strict GetBti(struct { |
| index uint32; |
| }) -> (resource struct { |
| bti zx.Handle:BTI; |
| }) error zx.Status; |
| |
| strict GetBaseClock() -> (struct { |
| clock uint32; |
| }); |
| |
| /// Returns device quirks. |
| strict GetQuirks() -> (struct { |
| quirks Quirk; |
| dma_boundary_alignment uint64; |
| }); |
| |
| /// Platform specific HW reset. |
| strict HwReset() -> (); |
| |
| /// This method should be used to handle bus configuration on behalf of the SDHCI driver in |
| /// cases where the hardware deviates from the SDHCI specification. See the `Quirk` bits above. |
| strict VendorConfigureBus(flexible union { |
| 1: voltage fuchsia.hardware.sdmmc.SdmmcVoltage; |
| 2: width fuchsia.hardware.sdmmc.SdmmcBusWidth; |
| |
| /// SDHCI defines two clocks: the clock delivered to the external card ("SD clock") and the |
| /// internal clock (upstream of the SD clock). |
| /// |
| /// `VendorConfigureBus()` with `frequency_hz` always enables the internal clock, and if |
| /// `frequency_hz` is nonzero, enables the SD clock with the given frequency (the SD clock |
| /// is disabled if `frequency_hz` is zero). The driver must wait for all clocks to be stable |
| /// before returning. |
| 3: frequency_hz uint32; |
| 4: timing fuchsia.hardware.sdmmc.SdmmcTiming; |
| }) -> () error zx.Status; |
| |
| /// Perform a vendor-specific tuning sequence. `cmd_idx` is the command that should used to |
| /// receive the tuning pattern from the device. |
| strict VendorPerformTuning(struct { |
| cmd_idx uint32; |
| }) -> () error zx.Status; |
| }; |
| |
| service Service { |
| device client_end:Device; |
| }; |