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