1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#pragma once 6 7#include <zircon/compiler.h> 8 9#include <ddk/device.h> 10#include <ddk/protocol/block.h> 11#include <ddk/protocol/sdmmc.h> 12#include <ddk/protocol/sdio.h> 13#include <hw/sdmmc.h> 14 15// Tracing Includes 16#include <lib/async-loop/loop.h> 17#include <trace-provider/provider.h> 18#include <trace/event.h> 19 20#include <stdbool.h> 21 22#include "sdio.h" 23#include <threads.h> 24 25__BEGIN_CDECLS; 26 27typedef enum sdmmc_type { 28 SDMMC_TYPE_SD, 29 SDMMC_TYPE_MMC, 30 SDMMC_TYPE_SDIO, 31} sdmmc_type_t; 32 33#define SDMMC_REQ_COUNT 16 34 35// If enabled, gather stats on concurrent io ops, 36// pending txns, etc. Print them whenever the block 37// info is queried (lsblk will provoke this) 38#define WITH_STATS 1 39 40typedef struct sdmmc_device { 41 //members for tracing 42 async_loop_t* loop; 43 trace_provider_t* trace_provider; 44 trace_async_id_t async_id; 45 bool trace_on; 46 47 zx_device_t* zxdev; 48 49 sdmmc_protocol_t host; 50 sdmmc_host_info_t host_info; 51 52 sdmmc_type_t type; 53 54 sdmmc_bus_width_t bus_width; 55 sdmmc_voltage_t signal_voltage; 56 sdmmc_timing_t timing; 57 58 unsigned clock_rate; // Bus clock rate 59 uint64_t capacity; // Card capacity 60 61 uint16_t rca; // Relative address 62 63 // mmc 64 uint32_t raw_cid[4]; 65 uint32_t raw_csd[4]; 66 uint8_t raw_ext_csd[512]; 67 68 // sdio 69 sdio_device_t sdio_dev; 70 mtx_t lock; 71 72 // blockio requests 73 list_node_t txn_list; 74 75 // outstanding request (1 right now) 76 sdmmc_req_t req; 77 78 thrd_t worker_thread; 79 zx_handle_t worker_event; 80 bool worker_thread_running; 81 82#if WITH_STATS 83 size_t stat_concur; 84 size_t stat_pending; 85 size_t stat_max_concur; 86 size_t stat_max_pending; 87 size_t stat_total_ops; 88 size_t stat_total_blocks; 89#endif 90 91 block_info_t block_info; 92} sdmmc_device_t; 93 94static inline bool sdmmc_use_dma(sdmmc_device_t* dev) { 95 return (dev->host_info.caps & (SDMMC_HOST_CAP_ADMA2 | SDMMC_HOST_CAP_64BIT)); 96} 97 98// SD/MMC shared ops 99 100zx_status_t sdmmc_go_idle(sdmmc_device_t* dev); 101zx_status_t sdmmc_send_status(sdmmc_device_t* dev, uint32_t* response); 102zx_status_t sdmmc_stop_transmission(sdmmc_device_t* dev); 103 104// SD ops 105 106zx_status_t sd_send_if_cond(sdmmc_device_t* dev); 107 108// SD/SDIO shared ops 109zx_status_t sd_switch_uhs_voltage(sdmmc_device_t *dev, uint32_t ocr); 110zx_status_t sd_send_relative_addr(sdmmc_device_t* dev, uint16_t *rca); 111 112// SDIO ops 113zx_status_t sdio_send_op_cond(sdmmc_device_t* dev, uint32_t ocr, uint32_t* rocr); 114zx_status_t sdio_io_rw_direct(sdmmc_device_t* dev, bool write, uint32_t fn_idx, 115 uint32_t reg_addr, uint8_t write_byte, uint8_t *read_byte); 116zx_status_t sdio_io_rw_extended(sdmmc_device_t *dev, bool write, uint32_t fn_idx, 117 uint32_t reg_addr, bool incr, uint32_t blk_count, 118 uint32_t blk_size, bool use_dma, uint8_t *buf, 119 zx_handle_t dma_vmo, uint64_t buf_offset); 120zx_status_t sdio_enable_interrupt(void *ctx, uint8_t fn_idx); 121zx_status_t sdio_disable_interrupt(void *ctx, uint8_t fn_idx); 122zx_status_t sdio_enable_function(void *ctx, uint8_t fn_idx); 123zx_status_t sdio_disable_function(void *ctx, uint8_t fn_idx); 124zx_status_t sdio_modify_block_size(void *ctx, uint8_t fn_idx, uint16_t blk_sz, bool deflt); 125zx_status_t sdio_rw_data(void *ctx, uint8_t fn_idx, sdio_rw_txn_t *txn); 126zx_status_t sdio_get_device_hw_info(void *ctx, sdio_hw_info_t *dev_info); 127zx_status_t sdio_get_cur_block_size(void *ctx, uint8_t fn_idx, 128 uint16_t *cur_blk_size); 129 130// MMC ops 131 132zx_status_t mmc_send_op_cond(sdmmc_device_t* dev, uint32_t ocr, uint32_t* rocr); 133zx_status_t mmc_all_send_cid(sdmmc_device_t* dev, uint32_t cid[4]); 134zx_status_t mmc_set_relative_addr(sdmmc_device_t* dev, uint16_t rca); 135zx_status_t mmc_send_csd(sdmmc_device_t* dev, uint32_t csd[4]); 136zx_status_t mmc_send_ext_csd(sdmmc_device_t* dev, uint8_t ext_csd[512]); 137zx_status_t mmc_select_card(sdmmc_device_t* dev); 138zx_status_t mmc_switch(sdmmc_device_t* dev, uint8_t index, uint8_t value); 139 140zx_status_t sdmmc_probe_sd(sdmmc_device_t* dev); 141zx_status_t sdmmc_probe_mmc(sdmmc_device_t* dev); 142zx_status_t sdmmc_probe_sdio(sdmmc_device_t* dev); 143 144__END_CDECLS; 145