1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
|
/*
* Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MMC_H
#define MMC_H
#include <stdint.h>
#include <lib/utils_def.h>
#define MMC_BLOCK_SIZE U(512)
#define MMC_BLOCK_MASK (MMC_BLOCK_SIZE - U(1))
#define MMC_BOOT_CLK_RATE (400 * 1000)
#define MMC_CMD(_x) U(_x)
#define MMC_ACMD(_x) U(_x)
#define OCR_POWERUP BIT(31)
#define OCR_HCS BIT(30)
#define OCR_BYTE_MODE (U(0) << 29)
#define OCR_SECTOR_MODE (U(2) << 29)
#define OCR_ACCESS_MODE_MASK (U(3) << 29)
#define OCR_3_5_3_6 BIT(23)
#define OCR_3_4_3_5 BIT(22)
#define OCR_3_3_3_4 BIT(21)
#define OCR_3_2_3_3 BIT(20)
#define OCR_3_1_3_2 BIT(19)
#define OCR_3_0_3_1 BIT(18)
#define OCR_2_9_3_0 BIT(17)
#define OCR_2_8_2_9 BIT(16)
#define OCR_2_7_2_8 BIT(15)
#define OCR_VDD_MIN_2V7 GENMASK(23, 15)
#define OCR_VDD_MIN_2V0 GENMASK(14, 8)
#define OCR_VDD_MIN_1V7 BIT(7)
#define MMC_RSP_48 BIT(0)
#define MMC_RSP_136 BIT(1) /* 136 bit response */
#define MMC_RSP_CRC BIT(2) /* expect valid crc */
#define MMC_RSP_CMD_IDX BIT(3) /* response contains cmd idx */
#define MMC_RSP_BUSY BIT(4) /* device may be busy */
/* JEDEC 4.51 chapter 6.12 */
#define MMC_RESPONSE_R1 (MMC_RSP_48 | MMC_RSP_CMD_IDX | MMC_RSP_CRC)
#define MMC_RESPONSE_R1B (MMC_RESPONSE_R1 | MMC_RSP_BUSY)
#define MMC_RESPONSE_R2 (MMC_RSP_48 | MMC_RSP_136 | MMC_RSP_CRC)
#define MMC_RESPONSE_R3 (MMC_RSP_48)
#define MMC_RESPONSE_R4 (MMC_RSP_48)
#define MMC_RESPONSE_R5 (MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX)
#define MMC_RESPONSE_R6 (MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX)
#define MMC_RESPONSE_R7 (MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX)
/* Value randomly chosen for eMMC RCA, it should be > 1 */
#define MMC_FIX_RCA 6
#define RCA_SHIFT_OFFSET 16
#define CMD_EXTCSD_PARTITION_CONFIG 179
#define CMD_EXTCSD_BUS_WIDTH 183
#define CMD_EXTCSD_HS_TIMING 185
#define CMD_EXTCSD_PART_SWITCH_TIME 199
#define CMD_EXTCSD_SEC_CNT 212
#define CMD_EXTCSD_BOOT_SIZE_MULT 226
#define EXT_CSD_PART_CONFIG_ACC_MASK GENMASK(2, 0)
#define PART_CFG_BOOT_PARTITION1_ENABLE (U(1) << 3)
#define PART_CFG_BOOT_PARTITION1_ACCESS (U(1) << 0)
#define PART_CFG_BOOT_PARTITION_NO_ACCESS U(0)
#define PART_CFG_BOOT_PART_EN_MASK GENMASK(5, 3)
#define PART_CFG_BOOT_PART_EN_SHIFT 3
#define PART_CFG_CURRENT_BOOT_PARTITION(x) (((x) & PART_CFG_BOOT_PART_EN_MASK) >> \
PART_CFG_BOOT_PART_EN_SHIFT)
/* Values in EXT CSD register */
#define MMC_BUS_WIDTH_1 U(0)
#define MMC_BUS_WIDTH_4 U(1)
#define MMC_BUS_WIDTH_8 U(2)
#define MMC_BUS_WIDTH_DDR_4 U(5)
#define MMC_BUS_WIDTH_DDR_8 U(6)
#define MMC_BOOT_MODE_BACKWARD (U(0) << 3)
#define MMC_BOOT_MODE_HS_TIMING (U(1) << 3)
#define MMC_BOOT_MODE_DDR (U(2) << 3)
#define EXTCSD_SET_CMD (U(0) << 24)
#define EXTCSD_SET_BITS (U(1) << 24)
#define EXTCSD_CLR_BITS (U(2) << 24)
#define EXTCSD_WRITE_BYTES (U(3) << 24)
#define EXTCSD_CMD(x) (((x) & 0xff) << 16)
#define EXTCSD_VALUE(x) (((x) & 0xff) << 8)
#define EXTCSD_CMD_SET_NORMAL U(1)
#define CSD_TRAN_SPEED_UNIT_MASK GENMASK(2, 0)
#define CSD_TRAN_SPEED_MULT_MASK GENMASK(6, 3)
#define CSD_TRAN_SPEED_MULT_SHIFT 3
#define STATUS_CURRENT_STATE(x) (((x) & 0xf) << 9)
#define STATUS_READY_FOR_DATA BIT(8)
#define STATUS_SWITCH_ERROR BIT(7)
#define MMC_GET_STATE(x) (((x) >> 9) & 0xf)
#define MMC_STATE_IDLE 0
#define MMC_STATE_READY 1
#define MMC_STATE_IDENT 2
#define MMC_STATE_STBY 3
#define MMC_STATE_TRAN 4
#define MMC_STATE_DATA 5
#define MMC_STATE_RCV 6
#define MMC_STATE_PRG 7
#define MMC_STATE_DIS 8
#define MMC_STATE_BTST 9
#define MMC_STATE_SLP 10
#define MMC_FLAG_CMD23 (U(1) << 0)
#define MMC_FLAG_SD_CMD6 (U(1) << 1)
#define CMD8_CHECK_PATTERN U(0xAA)
#define VHS_2_7_3_6_V BIT(8)
#define SD_SCR_BUS_WIDTH_1 BIT(8)
#define SD_SCR_BUS_WIDTH_4 BIT(10)
#define SD_SWITCH_FUNC_CHECK 0U
#define SD_SWITCH_FUNC_SWITCH BIT(31)
#define SD_SWITCH_ALL_GROUPS_MASK GENMASK(23, 0)
struct mmc_cmd {
unsigned int cmd_idx;
unsigned int cmd_arg;
unsigned int resp_type;
unsigned int resp_data[4];
};
struct mmc_ops {
void (*init)(void);
int (*send_cmd)(struct mmc_cmd *cmd);
int (*set_ios)(unsigned int clk, unsigned int width);
int (*prepare)(int lba, uintptr_t buf, size_t size);
int (*read)(int lba, uintptr_t buf, size_t size);
int (*write)(int lba, const uintptr_t buf, size_t size);
};
struct mmc_csd_emmc {
unsigned int not_used: 1;
unsigned int crc: 7;
unsigned int ecc: 2;
unsigned int file_format: 2;
unsigned int tmp_write_protect: 1;
unsigned int perm_write_protect: 1;
unsigned int copy: 1;
unsigned int file_format_grp: 1;
unsigned int reserved_1: 5;
unsigned int write_bl_partial: 1;
unsigned int write_bl_len: 4;
unsigned int r2w_factor: 3;
unsigned int default_ecc: 2;
unsigned int wp_grp_enable: 1;
unsigned int wp_grp_size: 5;
unsigned int erase_grp_mult: 5;
unsigned int erase_grp_size: 5;
unsigned int c_size_mult: 3;
unsigned int vdd_w_curr_max: 3;
unsigned int vdd_w_curr_min: 3;
unsigned int vdd_r_curr_max: 3;
unsigned int vdd_r_curr_min: 3;
unsigned int c_size_low: 2;
unsigned int c_size_high: 10;
unsigned int reserved_2: 2;
unsigned int dsr_imp: 1;
unsigned int read_blk_misalign: 1;
unsigned int write_blk_misalign: 1;
unsigned int read_bl_partial: 1;
unsigned int read_bl_len: 4;
unsigned int ccc: 12;
unsigned int tran_speed: 8;
unsigned int nsac: 8;
unsigned int taac: 8;
unsigned int reserved_3: 2;
unsigned int spec_vers: 4;
unsigned int csd_structure: 2;
};
struct mmc_csd_sd_v2 {
unsigned int not_used: 1;
unsigned int crc: 7;
unsigned int reserved_1: 2;
unsigned int file_format: 2;
unsigned int tmp_write_protect: 1;
unsigned int perm_write_protect: 1;
unsigned int copy: 1;
unsigned int file_format_grp: 1;
unsigned int reserved_2: 5;
unsigned int write_bl_partial: 1;
unsigned int write_bl_len: 4;
unsigned int r2w_factor: 3;
unsigned int reserved_3: 2;
unsigned int wp_grp_enable: 1;
unsigned int wp_grp_size: 7;
unsigned int sector_size: 7;
unsigned int erase_block_en: 1;
unsigned int reserved_4: 1;
unsigned int c_size_low: 16;
unsigned int c_size_high: 6;
unsigned int reserved_5: 6;
unsigned int dsr_imp: 1;
unsigned int read_blk_misalign: 1;
unsigned int write_blk_misalign: 1;
unsigned int read_bl_partial: 1;
unsigned int read_bl_len: 4;
unsigned int ccc: 12;
unsigned int tran_speed: 8;
unsigned int nsac: 8;
unsigned int taac: 8;
unsigned int reserved_6: 6;
unsigned int csd_structure: 2;
};
struct sd_switch_status {
unsigned short max_current;
unsigned short support_g6;
unsigned short support_g5;
unsigned short support_g4;
unsigned short support_g3;
unsigned short support_g2;
unsigned short support_g1;
unsigned char sel_g6_g5;
unsigned char sel_g4_g3;
unsigned char sel_g2_g1;
unsigned char data_struct_ver;
unsigned short busy_g6;
unsigned short busy_g5;
unsigned short busy_g4;
unsigned short busy_g3;
unsigned short busy_g2;
unsigned short busy_g1;
unsigned short reserved[17];
};
enum mmc_device_type {
MMC_IS_EMMC,
MMC_IS_SD,
MMC_IS_SD_HC,
};
struct mmc_device_info {
unsigned long long device_size; /* Size of device in bytes */
unsigned int block_size; /* Block size in bytes */
unsigned int max_bus_freq; /* Max bus freq in Hz */
unsigned int ocr_voltage; /* OCR voltage */
enum mmc_device_type mmc_dev_type; /* Type of MMC */
};
size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size);
size_t mmc_write_blocks(int lba, const uintptr_t buf, size_t size);
size_t mmc_erase_blocks(int lba, size_t size);
int mmc_part_switch_current_boot(void);
int mmc_part_switch_user(void);
size_t mmc_boot_part_size(void);
size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size);
int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
unsigned int width, unsigned int flags,
struct mmc_device_info *device_info);
#endif /* MMC_H */
|