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 <ddk/trace/event.h>
14 #include <hw/sdmmc.h>
15
16 #include <stdbool.h>
17
18 #include "sdio.h"
19 #include <threads.h>
20
21 __BEGIN_CDECLS;
22
23 typedef enum sdmmc_type {
24 SDMMC_TYPE_UNKNOWN,
25 SDMMC_TYPE_SD,
26 SDMMC_TYPE_MMC,
27 SDMMC_TYPE_SDIO,
28 } sdmmc_type_t;
29
30 #define SDMMC_REQ_COUNT 16
31
32 // If enabled, gather stats on concurrent io ops,
33 // pending txns, etc. Print them whenever the block
34 // info is queried (lsblk will provoke this)
35 #define WITH_STATS 1
36
37 typedef struct sdmmc_device {
38 trace_async_id_t async_id;
39
40 zx_device_t* zxdev;
41 zx_device_t* child_zxdev;
42
43 sdmmc_protocol_t host;
44 sdmmc_host_info_t host_info;
45
46 sdmmc_type_t type;
47
48 sdmmc_bus_width_t bus_width;
49 sdmmc_voltage_t signal_voltage;
50 sdmmc_timing_t timing;
51
52 unsigned clock_rate; // Bus clock rate
53 uint64_t capacity; // Card capacity
54
55 uint16_t rca; // Relative address
56
57 // mmc
58 uint32_t raw_cid[4];
59 uint32_t raw_csd[4];
60 uint8_t raw_ext_csd[512];
61
62 // sdio
63 sdio_device_t sdio_dev;
64
65 mtx_t lock;
66
67 // blockio requests
68 list_node_t txn_list;
69
70 // outstanding request (1 right now)
71 sdmmc_req_t req;
72
73 thrd_t worker_thread;
74 zx_handle_t worker_event;
75
76 //Requires lock to be acquired.
77 //TODO(ravoorir): When converting to c++ use
78 //clang thread annotations.
79 bool worker_thread_started;
80 bool dead;
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
sdmmc_use_dma(sdmmc_device_t * dev)94 static inline bool sdmmc_use_dma(sdmmc_device_t* dev) {
95 return (dev->host_info.caps & (SDMMC_HOST_CAP_ADMA2 | SDMMC_HOST_CAP_SIXTY_FOUR_BIT));
96 }
97
98 // SD/MMC shared ops
99
100 zx_status_t sdmmc_go_idle(sdmmc_device_t* dev);
101 zx_status_t sdmmc_send_status(sdmmc_device_t* dev, uint32_t* response);
102 zx_status_t sdmmc_stop_transmission(sdmmc_device_t* dev);
103
104 // SD ops
105
106 zx_status_t sd_send_if_cond(sdmmc_device_t* dev);
107
108 // SD/SDIO shared ops
109 zx_status_t sd_switch_uhs_voltage(sdmmc_device_t *dev, uint32_t ocr);
110 zx_status_t sd_send_relative_addr(sdmmc_device_t* dev, uint16_t *rca);
111
112 // SDIO ops
113 zx_status_t sdio_send_op_cond(sdmmc_device_t* dev, uint32_t ocr, uint32_t* rocr);
114 zx_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);
116 zx_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);
120 zx_status_t sdio_enable_interrupt(void *ctx, uint8_t fn_idx);
121 zx_status_t sdio_disable_interrupt(void *ctx, uint8_t fn_idx);
122 zx_status_t sdio_enable_function(void *ctx, uint8_t fn_idx);
123 zx_status_t sdio_disable_function(void *ctx, uint8_t fn_idx);
124 zx_status_t sdio_modify_block_size(void *ctx, uint8_t fn_idx, uint16_t blk_sz, bool deflt);
125 zx_status_t sdio_rw_data(void *ctx, uint8_t fn_idx, sdio_rw_txn_t *txn);
126 zx_status_t sdio_rw_byte(void *ctx, bool write, uint8_t fn_idx, uint32_t addr,
127 uint8_t write_byte, uint8_t *read_byte);
128 zx_status_t sdio_get_device_hw_info(void *ctx, sdio_hw_info_t *dev_info);
129 zx_status_t sdio_get_cur_block_size(void *ctx, uint8_t fn_idx,
130 uint16_t *cur_blk_size);
131
132 // MMC ops
133
134 zx_status_t mmc_send_op_cond(sdmmc_device_t* dev, uint32_t ocr, uint32_t* rocr);
135 zx_status_t mmc_all_send_cid(sdmmc_device_t* dev, uint32_t cid[4]);
136 zx_status_t mmc_set_relative_addr(sdmmc_device_t* dev, uint16_t rca);
137 zx_status_t mmc_send_csd(sdmmc_device_t* dev, uint32_t csd[4]);
138 zx_status_t mmc_send_ext_csd(sdmmc_device_t* dev, uint8_t ext_csd[512]);
139 zx_status_t mmc_select_card(sdmmc_device_t* dev);
140 zx_status_t mmc_switch(sdmmc_device_t* dev, uint8_t index, uint8_t value);
141
142 zx_status_t sdmmc_probe_sd(sdmmc_device_t* dev);
143 zx_status_t sdmmc_probe_mmc(sdmmc_device_t* dev);
144 zx_status_t sdmmc_probe_sdio(sdmmc_device_t* dev);
145
146 __END_CDECLS;
147