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