| // Copyright 2018 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. |
| |
| library ddk.protocol.sdmmc; |
| |
| using zx; |
| |
| /// The max value of client_id fields below. There is no known need for more than eight clients at |
| /// the moment, however if that changes later this value will be increased. |
| const uint8 SDMMC_MAX_CLIENT_ID = 7; |
| |
| enum SdmmcVoltage : uint8 { |
| V330 = 0; |
| V180 = 1; |
| MAX = 2; |
| }; |
| |
| enum SdmmcBusWidth : uint8 { |
| ONE = 0; |
| FOUR = 1; |
| EIGHT = 2; |
| MAX = 3; |
| }; |
| |
| enum SdmmcTiming : uint8 { |
| LEGACY = 0; |
| HS = 1; |
| HSDDR = 2; |
| HS200 = 3; |
| HS400 = 4; |
| SDR12 = 5; |
| SDR25 = 6; |
| SDR50 = 7; |
| SDR104 = 8; |
| DDR50 = 9; |
| MAX = 10; |
| }; |
| |
| union SdmmcBuffer { |
| /// The ID of a VMO that was previously registered. |
| uint32 vmo_id; |
| /// An unregistered VMO of which the protocol implementation does not take ownership. The VMO is |
| /// pinned upon entering Request and is unpinned before returning. |
| handle<vmo> vmo; |
| }; |
| |
| enum SdmmcBufferType : uint32 { |
| VMO_ID = 1; |
| VMO_HANDLE = 2; |
| }; |
| |
| struct SdmmcBufferRegion { |
| SdmmcBuffer buffer; |
| SdmmcBufferType type; |
| /// Offset into the VMO to start reading or writing. This is relative to the offset passed to |
| /// RegisterVmo if type is VMO_ID. |
| uint64 offset; |
| /// Number of bytes to read from or write to this buffer region. |
| uint64 size; |
| }; |
| |
| struct SdmmcReqNew { |
| uint32 cmd_idx; |
| uint32 cmd_flags; |
| uint32 arg; |
| |
| uint32 blocksize; |
| |
| /// If true, the SDMMC driver should not print any error messages for this request. This is used |
| /// for initialization and tuning, when some requests are expected to fail. |
| bool probe_tuning_cmd; |
| |
| /// The client ID for this request. Only VMOs registered with this client may be present in |
| /// buffers below. |
| uint8 client_id; |
| vector<SdmmcBufferRegion> buffers; |
| }; |
| |
| /// number of pages per request - 2M per request |
| /// matches DMA_DESC_COUNT in dev/block/sdhci |
| /// (PAGE_SIZE / sizeof(zx_paddr_t)) |
| const uint64 SDMMC_PAGES_COUNT = 512; |
| |
| /// sdmmc requests. one per command |
| struct SdmmcReq { |
| uint32 cmd_idx; |
| uint32 cmd_flags; |
| uint32 arg; |
| |
| /// data command parameters |
| uint16 blockcount; |
| uint16 blocksize; |
| bool use_dma; |
| /// Used if use_dma is true |
| handle<vmo> dma_vmo; |
| /// Used if use_dma is false |
| vector<voidptr>? virt; |
| /// offset into dma_vmo or virt |
| uint64 buf_offset; |
| handle pmt; |
| bool probe_tuning_cmd; |
| |
| /// response data |
| array<uint32>:4 response; |
| |
| /// status |
| zx.status status; |
| }; |
| |
| enum SdmmcHostCap : uint64 { |
| BUS_WIDTH_8 = 0x1; |
| DMA = 0x2; |
| VOLTAGE_330 = 0x4; |
| AUTO_CMD12 = 0x8; |
| SDR104 = 0x10; |
| SDR50 = 0x20; |
| DDR50 = 0x40; |
| /// The host does not require tuning for SDR50. |
| NO_TUNING_SDR50 = 0x80; |
| }; |
| |
| enum SdmmcHostPrefs : uint64 { |
| DISABLE_HS400 = 0x1; |
| DISABLE_HS200 = 0x2; |
| DISABLE_HSDDR = 0x4; |
| }; |
| |
| struct SdmmcHostInfo { |
| /// Controller capabilities |
| uint64 caps; |
| /// Maximum data request size |
| uint64 max_transfer_size; |
| uint64 max_transfer_size_non_dma; |
| /// The number of buffer regions that may be used in a single request. |
| uint64 max_buffer_regions; |
| /// Host specific preferences |
| uint64 prefs; |
| }; |
| |
| enum SdmmcVmoRight : uint32 { |
| READ = 0x1; // The protocol implementation can read from this VMO (used for write requests). |
| WRITE = 0x2; // The protocol implementation can write to this VMO (used for read requests). |
| }; |
| |
| [Layout = "ddk-interface"] |
| protocol InBandInterrupt { |
| Callback() -> (); |
| }; |
| |
| [Layout = "ddk-protocol"] |
| protocol Sdmmc { |
| /// Get host info. |
| HostInfo() -> (zx.status s, SdmmcHostInfo info); |
| /// Set signal voltage. |
| SetSignalVoltage(SdmmcVoltage voltage) -> (zx.status s); |
| /// Set bus width. |
| SetBusWidth(SdmmcBusWidth bus_width) -> (zx.status s); |
| /// Set bus frequency, zero means disable the clock to the card. |
| SetBusFreq(uint32 bus_freq) -> (zx.status s); |
| /// Set mmc timing. |
| SetTiming(SdmmcTiming timing) -> (zx.status s); |
| /// Issue a hw reset. |
| HwReset() -> (); |
| /// Perform tuning. |
| PerformTuning(uint32 cmd_idx) -> (zx.status s); |
| /// Issue a request. |
| Request(SdmmcReq? req) -> (zx.status s); |
| RegisterInBandInterrupt(InBandInterrupt? interrupt_cb) -> (zx.status s); |
| |
| /// In the methods below, vmo_id is used to uniquely identify a VMO that will be passed to |
| /// Request in an SdmmcBufferRegion. VMO IDs are chosen by the caller, and may be any uint32 |
| /// value. |
| |
| /// Registers a VMO and transfers ownership to the protocol implementation. vmo_rights is a bit |
| /// field containing SdmmcVmoRight values, and determines the read/write permissions used by |
| /// the implementation when pinning or mapping the VMO. The implementation may pin vmo during |
| /// this call or any time it is used in a request, and may keep it pinned until the VMO is |
| /// unregistered. client_id may be in [0, SDMMC_MAX_CLIENT_ID] and identifies the ID space for |
| /// this VMO to be registered in (that is, two different VMOs may use the same ID if they are |
| /// registered for different clients). |
| RegisterVmo(uint32 vmo_id, uint8 client_id, handle<vmo> vmo, uint64 offset, |
| uint64 size, uint32 vmo_rights) -> (zx.status status); |
| /// The callee unmaps/unpins the VMO and returns ownership to the caller. |
| UnregisterVmo(uint32 vmo_id, uint8 client_id) -> (zx.status status, handle<vmo> vmo); |
| |
| /// Perform the request. The protocol implementation chooses whether or not to use DMA depending |
| /// on the properties of the request and the capabilities of the controller. |
| /// |
| /// Clients are responsible for performing the following cache operations: |
| /// |
| /// After read requests: |
| /// - Call zx_cache_flush with ZX_CACHE_FLUSH_DATA | ZX_CACHE_FLUSH_INVALIDATE on buffers that |
| /// have been mapped by the client. |
| /// - Call zx_vmo_op_range with ZX_VMO_OP_CACHE_CLEAN_INVALIDATE on all other buffers. |
| /// |
| /// Note that writing to any portion of a buffer before DoRwTxnNew has returned can corrupt the |
| /// received data. |
| /// |
| /// Before write requests: |
| /// - Call zx_cache_flush with ZX_CACHE_FLUSH_DATA on buffers that have been mapped by the |
| /// client. |
| /// - Call zx_vmo_op_range with ZX_VMO_OP_CACHE_CLEAN on all other buffers. |
| RequestNew(SdmmcReqNew req) -> (zx.status status, array<uint32>:4 response); |
| }; |