xref: /rk3399_ARM-atf/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c (revision 601e2d4325a7def628990f4a25889f374c81ca06)
1bffde63dSSheetal Tigadoli /*
2bffde63dSSheetal Tigadoli  * Copyright (c) 2016 - 2020, Broadcom
3bffde63dSSheetal Tigadoli  *
4bffde63dSSheetal Tigadoli  * SPDX-License-Identifier: BSD-3-Clause
5bffde63dSSheetal Tigadoli  */
6bffde63dSSheetal Tigadoli 
7bffde63dSSheetal Tigadoli #include <string.h>
8bffde63dSSheetal Tigadoli 
9bffde63dSSheetal Tigadoli #include <emmc_api.h>
10bffde63dSSheetal Tigadoli #include <cmn_plat_util.h>
11bffde63dSSheetal Tigadoli 
12bffde63dSSheetal Tigadoli #define MAX_CMD_RETRY      10
13bffde63dSSheetal Tigadoli 
14bffde63dSSheetal Tigadoli #if EMMC_USE_DMA
15bffde63dSSheetal Tigadoli #define USE_DMA 1
16bffde63dSSheetal Tigadoli #else
17bffde63dSSheetal Tigadoli #define USE_DMA 0
18bffde63dSSheetal Tigadoli #endif
19bffde63dSSheetal Tigadoli 
20bffde63dSSheetal Tigadoli struct emmc_global_buffer emmc_global_buf;
21bffde63dSSheetal Tigadoli struct emmc_global_buffer *emmc_global_buf_ptr = &emmc_global_buf;
22bffde63dSSheetal Tigadoli 
23bffde63dSSheetal Tigadoli struct emmc_global_vars emmc_global_vars;
24bffde63dSSheetal Tigadoli struct emmc_global_vars *emmc_global_vars_ptr = &emmc_global_vars;
25bffde63dSSheetal Tigadoli 
26bffde63dSSheetal Tigadoli static struct sd_handle *sdio_gethandle(void);
27bffde63dSSheetal Tigadoli static uint32_t sdio_idle(struct sd_handle *p_sdhandle);
28bffde63dSSheetal Tigadoli 
29bffde63dSSheetal Tigadoli static uint32_t sdio_read(struct sd_handle *p_sdhandle,
30bffde63dSSheetal Tigadoli 			  uintptr_t mem_addr,
31bffde63dSSheetal Tigadoli 			  uintptr_t storage_addr,
32bffde63dSSheetal Tigadoli 			  size_t storage_size,
33bffde63dSSheetal Tigadoli 			  size_t bytes_to_read);
34bffde63dSSheetal Tigadoli 
35bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
36bffde63dSSheetal Tigadoli static uint32_t sdio_write(struct sd_handle *p_sdhandle,
37bffde63dSSheetal Tigadoli 			   uintptr_t mem_addr,
38bffde63dSSheetal Tigadoli 			   uintptr_t data_addr,
39bffde63dSSheetal Tigadoli 			   size_t bytes_to_write);
40bffde63dSSheetal Tigadoli #endif
41bffde63dSSheetal Tigadoli 
42bffde63dSSheetal Tigadoli static struct sd_handle *sdio_init(void);
43bffde63dSSheetal Tigadoli static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle);
44bffde63dSSheetal Tigadoli 
init_globals(void)45bffde63dSSheetal Tigadoli static void init_globals(void)
46bffde63dSSheetal Tigadoli {
47bffde63dSSheetal Tigadoli 	memset((void *)emmc_global_buf_ptr, 0, sizeof(*emmc_global_buf_ptr));
48bffde63dSSheetal Tigadoli 	memset((void *)emmc_global_vars_ptr, 0, sizeof(*emmc_global_vars_ptr));
49bffde63dSSheetal Tigadoli }
50bffde63dSSheetal Tigadoli 
51bffde63dSSheetal Tigadoli /*
52bffde63dSSheetal Tigadoli  * This function is used to change partition
53bffde63dSSheetal Tigadoli  */
emmc_partition_select(uint32_t partition)54bffde63dSSheetal Tigadoli uint32_t emmc_partition_select(uint32_t partition)
55bffde63dSSheetal Tigadoli {
56bffde63dSSheetal Tigadoli 	int rc;
57bffde63dSSheetal Tigadoli 	struct sd_handle *sd_handle = sdio_gethandle();
58bffde63dSSheetal Tigadoli 
59bffde63dSSheetal Tigadoli 	if (sd_handle->device == 0) {
60bffde63dSSheetal Tigadoli 		EMMC_TRACE("eMMC init is not done");
61bffde63dSSheetal Tigadoli 		return 0;
62bffde63dSSheetal Tigadoli 	}
63bffde63dSSheetal Tigadoli 
64bffde63dSSheetal Tigadoli 	switch (partition) {
65bffde63dSSheetal Tigadoli 	case EMMC_BOOT_PARTITION1:
66bffde63dSSheetal Tigadoli 		rc = set_boot_config(sd_handle,
67bffde63dSSheetal Tigadoli 				     SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1);
68bffde63dSSheetal Tigadoli 		EMMC_TRACE(
69bffde63dSSheetal Tigadoli 		     "Change to Boot Partition 1 result:%d  (0 means SD_OK)\n",
70bffde63dSSheetal Tigadoli 		     rc);
71bffde63dSSheetal Tigadoli 		break;
72bffde63dSSheetal Tigadoli 
73bffde63dSSheetal Tigadoli 	case EMMC_BOOT_PARTITION2:
74bffde63dSSheetal Tigadoli 		rc = set_boot_config(sd_handle,
75bffde63dSSheetal Tigadoli 				     SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2);
76bffde63dSSheetal Tigadoli 		EMMC_TRACE(
77bffde63dSSheetal Tigadoli 		     "Change to Boot Partition 2 result:%d  (0 means SD_OK)\n",
78bffde63dSSheetal Tigadoli 		     rc);
79bffde63dSSheetal Tigadoli 		break;
80bffde63dSSheetal Tigadoli 
81bffde63dSSheetal Tigadoli 	case EMMC_USE_CURRENT_PARTITION:
82bffde63dSSheetal Tigadoli 		rc = SD_OK;
83bffde63dSSheetal Tigadoli 		EMMC_TRACE("Stay on current partition");
84bffde63dSSheetal Tigadoli 		break;
85bffde63dSSheetal Tigadoli 
86bffde63dSSheetal Tigadoli 	case EMMC_USER_AREA:
87bffde63dSSheetal Tigadoli 	default:
88bffde63dSSheetal Tigadoli 		rc = set_boot_config(sd_handle,
89bffde63dSSheetal Tigadoli 				     SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER);
90bffde63dSSheetal Tigadoli 		EMMC_TRACE("Change to User area result:%d  (0 means SD_OK)\n",
91bffde63dSSheetal Tigadoli 			   rc);
92bffde63dSSheetal Tigadoli 		break;
93bffde63dSSheetal Tigadoli 
94bffde63dSSheetal Tigadoli 	}
95bffde63dSSheetal Tigadoli 	return (rc == SD_OK);
96bffde63dSSheetal Tigadoli }
97bffde63dSSheetal Tigadoli 
98bffde63dSSheetal Tigadoli /*
99bffde63dSSheetal Tigadoli  * Initialize emmc controller for eMMC
100bffde63dSSheetal Tigadoli  * Returns 0 on fail condition
101bffde63dSSheetal Tigadoli  */
bcm_emmc_init(bool card_rdy_only)102bffde63dSSheetal Tigadoli uint32_t bcm_emmc_init(bool card_rdy_only)
103bffde63dSSheetal Tigadoli {
104bffde63dSSheetal Tigadoli 	struct sd_handle *p_sdhandle;
105bffde63dSSheetal Tigadoli 	uint32_t result = 0;
106bffde63dSSheetal Tigadoli 
107bffde63dSSheetal Tigadoli 	EMMC_TRACE("Enter emmc_controller_init()\n");
108bffde63dSSheetal Tigadoli 
109bffde63dSSheetal Tigadoli 	/* If eMMC is already initialized, skip init */
110bffde63dSSheetal Tigadoli 	if (emmc_global_vars_ptr->init_done)
111bffde63dSSheetal Tigadoli 		return 1;
112bffde63dSSheetal Tigadoli 
113bffde63dSSheetal Tigadoli 	init_globals();
114bffde63dSSheetal Tigadoli 
115bffde63dSSheetal Tigadoli 	p_sdhandle = sdio_init();
116bffde63dSSheetal Tigadoli 
117bffde63dSSheetal Tigadoli 	if (p_sdhandle == NULL) {
118bffde63dSSheetal Tigadoli 		ERROR("eMMC init failed");
119bffde63dSSheetal Tigadoli 		return result;
120bffde63dSSheetal Tigadoli 	}
121bffde63dSSheetal Tigadoli 
122bffde63dSSheetal Tigadoli 	if (card_rdy_only) {
123bffde63dSSheetal Tigadoli 		/* Put the card in Ready state, Not complete init */
124bffde63dSSheetal Tigadoli 		result = bcm_emmc_card_ready_state(p_sdhandle);
125bffde63dSSheetal Tigadoli 		return !result;
126bffde63dSSheetal Tigadoli 	}
127bffde63dSSheetal Tigadoli 
128bffde63dSSheetal Tigadoli 	if (sdio_idle(p_sdhandle) == EMMC_BOOT_OK) {
129bffde63dSSheetal Tigadoli 		set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, USE_DMA,
130bffde63dSSheetal Tigadoli 			   SD_DMA_BOUNDARY_256K, EMMC_BLOCK_SIZE,
131bffde63dSSheetal Tigadoli 			   EMMC_WFE_RETRY);
132bffde63dSSheetal Tigadoli 
133bffde63dSSheetal Tigadoli 		if (!select_blk_sz(p_sdhandle,
134bffde63dSSheetal Tigadoli 				   p_sdhandle->device->cfg.blockSize)) {
135bffde63dSSheetal Tigadoli 			emmc_global_vars_ptr->init_done = 1;
136bffde63dSSheetal Tigadoli 			result = 1;
137bffde63dSSheetal Tigadoli 		} else {
138bffde63dSSheetal Tigadoli 			ERROR("Select Block Size failed\n");
139bffde63dSSheetal Tigadoli 		}
140bffde63dSSheetal Tigadoli 	} else {
141bffde63dSSheetal Tigadoli 		ERROR("eMMC init failed");
142bffde63dSSheetal Tigadoli 	}
143bffde63dSSheetal Tigadoli 
144bffde63dSSheetal Tigadoli 	/* Initialization is failed, so deinit HW setting */
145bffde63dSSheetal Tigadoli 	if (result == 0)
146bffde63dSSheetal Tigadoli 		emmc_deinit();
147bffde63dSSheetal Tigadoli 
148bffde63dSSheetal Tigadoli 	return result;
149bffde63dSSheetal Tigadoli }
150bffde63dSSheetal Tigadoli 
151bffde63dSSheetal Tigadoli /*
152bffde63dSSheetal Tigadoli  * Function to de-init SDIO controller for eMMC
153bffde63dSSheetal Tigadoli  */
emmc_deinit(void)154bffde63dSSheetal Tigadoli void emmc_deinit(void)
155bffde63dSSheetal Tigadoli {
156bffde63dSSheetal Tigadoli 	emmc_global_vars_ptr->init_done = 0;
157bffde63dSSheetal Tigadoli 	emmc_global_vars_ptr->sdHandle.card = 0;
158bffde63dSSheetal Tigadoli 	emmc_global_vars_ptr->sdHandle.device = 0;
159bffde63dSSheetal Tigadoli }
160bffde63dSSheetal Tigadoli 
161bffde63dSSheetal Tigadoli /*
162bffde63dSSheetal Tigadoli  * Read eMMC memory
163bffde63dSSheetal Tigadoli  * Returns read_size
164bffde63dSSheetal Tigadoli  */
emmc_read(uintptr_t mem_addr,uintptr_t storage_addr,size_t storage_size,size_t bytes_to_read)165bffde63dSSheetal Tigadoli uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr,
166bffde63dSSheetal Tigadoli 		   size_t storage_size, size_t bytes_to_read)
167bffde63dSSheetal Tigadoli {
168bffde63dSSheetal Tigadoli 	struct sd_handle *sd_handle = sdio_gethandle();
169bffde63dSSheetal Tigadoli 
170bffde63dSSheetal Tigadoli 	if (sd_handle->device == 0) {
171bffde63dSSheetal Tigadoli 		EMMC_TRACE("eMMC init is not done");
172bffde63dSSheetal Tigadoli 		return 0;
173bffde63dSSheetal Tigadoli 	}
174bffde63dSSheetal Tigadoli 
175bffde63dSSheetal Tigadoli 	return sdio_read(sdio_gethandle(), mem_addr, storage_addr,
176bffde63dSSheetal Tigadoli 			 storage_size, bytes_to_read);
177bffde63dSSheetal Tigadoli }
178bffde63dSSheetal Tigadoli 
179bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
180bffde63dSSheetal Tigadoli #define EXT_CSD_ERASE_GRP_SIZE 224
181bffde63dSSheetal Tigadoli 
emmc_block_erase(uintptr_t mem_addr,size_t blocks)182bffde63dSSheetal Tigadoli static int emmc_block_erase(uintptr_t mem_addr, size_t blocks)
183bffde63dSSheetal Tigadoli {
184bffde63dSSheetal Tigadoli 	struct sd_handle *sd_handle = sdio_gethandle();
185bffde63dSSheetal Tigadoli 
186bffde63dSSheetal Tigadoli 	if (sd_handle->device == 0) {
187bffde63dSSheetal Tigadoli 		ERROR("eMMC init is not done");
188bffde63dSSheetal Tigadoli 		return -1;
189bffde63dSSheetal Tigadoli 	}
190bffde63dSSheetal Tigadoli 
191bffde63dSSheetal Tigadoli 	return erase_card(sdio_gethandle(), mem_addr, blocks);
192bffde63dSSheetal Tigadoli }
193bffde63dSSheetal Tigadoli 
emmc_erase(uintptr_t mem_addr,size_t num_of_blocks,uint32_t partition)194bffde63dSSheetal Tigadoli int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition)
195bffde63dSSheetal Tigadoli {
196bffde63dSSheetal Tigadoli 	int err = 0;
197bffde63dSSheetal Tigadoli 	size_t block_count = 0, blocks = 0;
198bffde63dSSheetal Tigadoli 	size_t erase_group = 0;
199bffde63dSSheetal Tigadoli 
200bffde63dSSheetal Tigadoli 	erase_group =
201bffde63dSSheetal Tigadoli 	emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_ERASE_GRP_SIZE]*1024;
202bffde63dSSheetal Tigadoli 
203bffde63dSSheetal Tigadoli 	INFO("eMMC Erase Group Size=0x%lx\n", erase_group);
204bffde63dSSheetal Tigadoli 
205bffde63dSSheetal Tigadoli 	emmc_partition_select(partition);
206bffde63dSSheetal Tigadoli 
207bffde63dSSheetal Tigadoli 	while (block_count < num_of_blocks) {
208bffde63dSSheetal Tigadoli 		blocks = ((num_of_blocks - block_count) > erase_group) ?
209bffde63dSSheetal Tigadoli 				  erase_group : (num_of_blocks - block_count);
210bffde63dSSheetal Tigadoli 			err = emmc_block_erase(mem_addr + block_count, blocks);
211bffde63dSSheetal Tigadoli 		if (err)
212bffde63dSSheetal Tigadoli 			break;
213bffde63dSSheetal Tigadoli 
214bffde63dSSheetal Tigadoli 		block_count += blocks;
215bffde63dSSheetal Tigadoli 	}
216bffde63dSSheetal Tigadoli 
217bffde63dSSheetal Tigadoli 	if (err == 0)
218bffde63dSSheetal Tigadoli 		INFO("eMMC Erase of partition %d successful\n", partition);
219bffde63dSSheetal Tigadoli 	else
220bffde63dSSheetal Tigadoli 		ERROR("eMMC Erase of partition %d Failed(%i)\n", partition, err);
221bffde63dSSheetal Tigadoli 
222bffde63dSSheetal Tigadoli 	return err;
223bffde63dSSheetal Tigadoli }
224bffde63dSSheetal Tigadoli #endif
225bffde63dSSheetal Tigadoli 
226bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
227bffde63dSSheetal Tigadoli /*
228bffde63dSSheetal Tigadoli  * Write to eMMC memory
229bffde63dSSheetal Tigadoli  * Returns written_size
230bffde63dSSheetal Tigadoli  */
emmc_write(uintptr_t mem_addr,uintptr_t data_addr,size_t bytes_to_write)231bffde63dSSheetal Tigadoli uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr,
232bffde63dSSheetal Tigadoli 		    size_t bytes_to_write)
233bffde63dSSheetal Tigadoli {
234bffde63dSSheetal Tigadoli 	struct sd_handle *sd_handle = sdio_gethandle();
235bffde63dSSheetal Tigadoli 
236bffde63dSSheetal Tigadoli 	if (sd_handle->device == 0) {
237bffde63dSSheetal Tigadoli 		EMMC_TRACE("eMMC init is not done");
238bffde63dSSheetal Tigadoli 		return 0;
239bffde63dSSheetal Tigadoli 	}
240bffde63dSSheetal Tigadoli 
241bffde63dSSheetal Tigadoli 	return sdio_write(sd_handle, mem_addr, data_addr, bytes_to_write);
242bffde63dSSheetal Tigadoli }
243bffde63dSSheetal Tigadoli #endif
244bffde63dSSheetal Tigadoli 
245bffde63dSSheetal Tigadoli /*
246bffde63dSSheetal Tigadoli  * Send SDIO Cmd
247bffde63dSSheetal Tigadoli  * Return 0 for pass condition
248bffde63dSSheetal Tigadoli  */
send_sdio_cmd(uint32_t cmdIndex,uint32_t argument,uint32_t options,struct sd_resp * resp)249bffde63dSSheetal Tigadoli uint32_t send_sdio_cmd(uint32_t cmdIndex, uint32_t argument,
250bffde63dSSheetal Tigadoli 		       uint32_t options, struct sd_resp *resp)
251bffde63dSSheetal Tigadoli {
252bffde63dSSheetal Tigadoli 	struct sd_handle *sd_handle = sdio_gethandle();
253bffde63dSSheetal Tigadoli 
254bffde63dSSheetal Tigadoli 	if (sd_handle->device == 0) {
255bffde63dSSheetal Tigadoli 		EMMC_TRACE("eMMC init is not done");
256bffde63dSSheetal Tigadoli 		return 1;
257bffde63dSSheetal Tigadoli 	}
258bffde63dSSheetal Tigadoli 
259bffde63dSSheetal Tigadoli 	return send_cmd(sd_handle, cmdIndex, argument, options, resp);
260bffde63dSSheetal Tigadoli }
261bffde63dSSheetal Tigadoli 
262bffde63dSSheetal Tigadoli 
263bffde63dSSheetal Tigadoli /*
264bffde63dSSheetal Tigadoli  * This function return SDIO handle
265bffde63dSSheetal Tigadoli  */
sdio_gethandle(void)266bffde63dSSheetal Tigadoli struct sd_handle *sdio_gethandle(void)
267bffde63dSSheetal Tigadoli {
268bffde63dSSheetal Tigadoli 	return &emmc_global_vars_ptr->sdHandle;
269bffde63dSSheetal Tigadoli }
270bffde63dSSheetal Tigadoli 
271bffde63dSSheetal Tigadoli /*
272bffde63dSSheetal Tigadoli  * Initialize SDIO controller
273bffde63dSSheetal Tigadoli  */
sdio_init(void)274bffde63dSSheetal Tigadoli struct sd_handle *sdio_init(void)
275bffde63dSSheetal Tigadoli {
276bffde63dSSheetal Tigadoli 	uint32_t SDIO_base;
277bffde63dSSheetal Tigadoli 	struct sd_handle *p_sdhandle = &emmc_global_vars_ptr->sdHandle;
278bffde63dSSheetal Tigadoli 
279bffde63dSSheetal Tigadoli 	SDIO_base = EMMC_CTRL_REGS_BASE_ADDR;
280bffde63dSSheetal Tigadoli 
281*9f58bfbbSBoyan Karatotev 	if (SDIO_base == SDIO0_EMMCSDXC_SYSADDR) {
282bffde63dSSheetal Tigadoli 		EMMC_TRACE(" ---> for SDIO 0 Controller\n\n");
283*9f58bfbbSBoyan Karatotev 	}
284bffde63dSSheetal Tigadoli 
285bffde63dSSheetal Tigadoli 	memset(p_sdhandle, 0, sizeof(struct sd_handle));
286bffde63dSSheetal Tigadoli 
287bffde63dSSheetal Tigadoli 	p_sdhandle->device = &emmc_global_vars_ptr->sdDevice;
288bffde63dSSheetal Tigadoli 	p_sdhandle->card = &emmc_global_vars_ptr->sdCard;
289bffde63dSSheetal Tigadoli 
290bffde63dSSheetal Tigadoli 	memset(p_sdhandle->device, 0, sizeof(struct sd_dev));
291bffde63dSSheetal Tigadoli 	memset(p_sdhandle->card, 0, sizeof(struct sd_card_info));
292bffde63dSSheetal Tigadoli 
293bffde63dSSheetal Tigadoli 	if (chal_sd_start((CHAL_HANDLE *) p_sdhandle->device,
294*9f58bfbbSBoyan Karatotev 			  SD_PIO_MODE, SDIO_base, SDIO_base) != SD_OK) {
295bffde63dSSheetal Tigadoli 		return NULL;
296*9f58bfbbSBoyan Karatotev 	}
297bffde63dSSheetal Tigadoli 
298bffde63dSSheetal Tigadoli 	set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, SD_DMA_OFF,
299bffde63dSSheetal Tigadoli 		   SD_DMA_BOUNDARY_4K, EMMC_BLOCK_SIZE, EMMC_WFE_RETRY);
300bffde63dSSheetal Tigadoli 
301bffde63dSSheetal Tigadoli 	return &emmc_global_vars_ptr->sdHandle;
302bffde63dSSheetal Tigadoli }
303bffde63dSSheetal Tigadoli 
sdio_idle(struct sd_handle * p_sdhandle)304bffde63dSSheetal Tigadoli uint32_t sdio_idle(struct sd_handle *p_sdhandle)
305bffde63dSSheetal Tigadoli {
306bffde63dSSheetal Tigadoli 	reset_card(p_sdhandle);
307bffde63dSSheetal Tigadoli 
308bffde63dSSheetal Tigadoli 	SD_US_DELAY(1000);
309bffde63dSSheetal Tigadoli 
310bffde63dSSheetal Tigadoli 	if (init_card(p_sdhandle, SD_CARD_DETECT_MMC) != SD_OK) {
311bffde63dSSheetal Tigadoli 		reset_card(p_sdhandle);
312bffde63dSSheetal Tigadoli 		reset_host_ctrl(p_sdhandle);
313bffde63dSSheetal Tigadoli 		return EMMC_BOOT_NO_CARD;
314bffde63dSSheetal Tigadoli 	}
315bffde63dSSheetal Tigadoli 
316bffde63dSSheetal Tigadoli 	return EMMC_BOOT_OK;
317bffde63dSSheetal Tigadoli }
318bffde63dSSheetal Tigadoli 
319bffde63dSSheetal Tigadoli /*
320bffde63dSSheetal Tigadoli  * This function read eMMC
321bffde63dSSheetal Tigadoli  */
sdio_read(struct sd_handle * p_sdhandle,uintptr_t mem_addr,uintptr_t storage_addr,size_t storage_size,size_t bytes_to_read)322bffde63dSSheetal Tigadoli uint32_t sdio_read(struct sd_handle *p_sdhandle,
323bffde63dSSheetal Tigadoli 		   uintptr_t mem_addr,
324bffde63dSSheetal Tigadoli 		   uintptr_t storage_addr,
325bffde63dSSheetal Tigadoli 		   size_t storage_size, size_t bytes_to_read)
326bffde63dSSheetal Tigadoli {
327bffde63dSSheetal Tigadoli 	uint32_t offset = 0, blockAddr, readLen = 0, rdCount;
328bffde63dSSheetal Tigadoli 	uint32_t remSize, manual_copy_size;
329bffde63dSSheetal Tigadoli 	uint8_t *outputBuf = (uint8_t *) storage_addr;
330bffde63dSSheetal Tigadoli 	const size_t blockSize = p_sdhandle->device->cfg.blockSize;
331bffde63dSSheetal Tigadoli 
332bffde63dSSheetal Tigadoli 	VERBOSE("EMMC READ: dst=0x%lx, src=0x%lx, size=0x%lx\n",
333bffde63dSSheetal Tigadoli 			storage_addr, mem_addr, bytes_to_read);
334bffde63dSSheetal Tigadoli 
335*9f58bfbbSBoyan Karatotev 	if (storage_size < bytes_to_read) {
336bffde63dSSheetal Tigadoli 		/* Don't have sufficient storage to complete the operation */
337bffde63dSSheetal Tigadoli 		return 0;
338*9f58bfbbSBoyan Karatotev 	}
339bffde63dSSheetal Tigadoli 
340bffde63dSSheetal Tigadoli 	/* Range check non high capacity memory */
341bffde63dSSheetal Tigadoli 	if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
342*9f58bfbbSBoyan Karatotev 		if (mem_addr > 0x80000000) {
343bffde63dSSheetal Tigadoli 			return 0;
344bffde63dSSheetal Tigadoli 		}
345*9f58bfbbSBoyan Karatotev 	}
346bffde63dSSheetal Tigadoli 
347bffde63dSSheetal Tigadoli 	/* High capacity card use block address mode */
348bffde63dSSheetal Tigadoli 	if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
349bffde63dSSheetal Tigadoli 		blockAddr = (uint32_t) (mem_addr / blockSize);
350bffde63dSSheetal Tigadoli 		offset = (uint32_t) (mem_addr - (blockAddr * blockSize));
351bffde63dSSheetal Tigadoli 	} else {
352bffde63dSSheetal Tigadoli 		blockAddr = (uint32_t) (mem_addr / blockSize) * blockSize;
353bffde63dSSheetal Tigadoli 		offset = (uint32_t) (mem_addr - blockAddr);
354bffde63dSSheetal Tigadoli 	}
355bffde63dSSheetal Tigadoli 
356bffde63dSSheetal Tigadoli 	remSize = bytes_to_read;
357bffde63dSSheetal Tigadoli 
358bffde63dSSheetal Tigadoli 	rdCount = 0;
359bffde63dSSheetal Tigadoli 
360bffde63dSSheetal Tigadoli 	/* Process first unaligned block of MAX_READ_LENGTH */
361bffde63dSSheetal Tigadoli 	if (offset > 0) {
362bffde63dSSheetal Tigadoli 		if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
363bffde63dSSheetal Tigadoli 				blockAddr, SD_MAX_READ_LENGTH)) {
364bffde63dSSheetal Tigadoli 
365bffde63dSSheetal Tigadoli 			if (remSize < (blockSize - offset)) {
366bffde63dSSheetal Tigadoli 				rdCount += remSize;
367bffde63dSSheetal Tigadoli 				manual_copy_size = remSize;
368bffde63dSSheetal Tigadoli 				remSize = 0;	/* read is done */
369bffde63dSSheetal Tigadoli 			} else {
370bffde63dSSheetal Tigadoli 				remSize -= (blockSize - offset);
371bffde63dSSheetal Tigadoli 				rdCount += (blockSize - offset);
372bffde63dSSheetal Tigadoli 				manual_copy_size = blockSize - offset;
373bffde63dSSheetal Tigadoli 			}
374bffde63dSSheetal Tigadoli 
375bffde63dSSheetal Tigadoli 			/* Check for overflow */
376bffde63dSSheetal Tigadoli 			if (manual_copy_size > storage_size ||
377bffde63dSSheetal Tigadoli 			    (((uintptr_t)outputBuf + manual_copy_size) >
378bffde63dSSheetal Tigadoli 			     (storage_addr + storage_size))) {
379bffde63dSSheetal Tigadoli 				ERROR("EMMC READ: Overflow 1\n");
380bffde63dSSheetal Tigadoli 				return 0;
381bffde63dSSheetal Tigadoli 			}
382bffde63dSSheetal Tigadoli 
383bffde63dSSheetal Tigadoli 			memcpy(outputBuf,
384bffde63dSSheetal Tigadoli 			       (void *)((uintptr_t)
385bffde63dSSheetal Tigadoli 				(emmc_global_buf_ptr->u.tempbuf + offset)),
386bffde63dSSheetal Tigadoli 			       manual_copy_size);
387bffde63dSSheetal Tigadoli 
388bffde63dSSheetal Tigadoli 			/* Update Physical address */
389bffde63dSSheetal Tigadoli 			outputBuf += manual_copy_size;
390bffde63dSSheetal Tigadoli 
391*9f58bfbbSBoyan Karatotev 			if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
392bffde63dSSheetal Tigadoli 				blockAddr++;
393*9f58bfbbSBoyan Karatotev 			} else {
394bffde63dSSheetal Tigadoli 				blockAddr += blockSize;
395*9f58bfbbSBoyan Karatotev 			}
396bffde63dSSheetal Tigadoli 		} else {
397bffde63dSSheetal Tigadoli 			return 0;
398bffde63dSSheetal Tigadoli 		}
399bffde63dSSheetal Tigadoli 	}
400bffde63dSSheetal Tigadoli 
401bffde63dSSheetal Tigadoli 	while (remSize >= blockSize) {
402bffde63dSSheetal Tigadoli 
403*9f58bfbbSBoyan Karatotev 		if (remSize >= SD_MAX_BLK_TRANSFER_LENGTH) {
404bffde63dSSheetal Tigadoli 			readLen = SD_MAX_BLK_TRANSFER_LENGTH;
405*9f58bfbbSBoyan Karatotev 		} else {
406bffde63dSSheetal Tigadoli 			readLen = (remSize / blockSize) * blockSize;
407*9f58bfbbSBoyan Karatotev 		}
408bffde63dSSheetal Tigadoli 
409bffde63dSSheetal Tigadoli 		/* Check for overflow */
410bffde63dSSheetal Tigadoli 		if ((rdCount + readLen) > storage_size ||
411bffde63dSSheetal Tigadoli 		    (((uintptr_t) outputBuf + readLen) >
412bffde63dSSheetal Tigadoli 		     (storage_addr + storage_size))) {
413bffde63dSSheetal Tigadoli 			ERROR("EMMC READ: Overflow\n");
414bffde63dSSheetal Tigadoli 			return 0;
415bffde63dSSheetal Tigadoli 		}
416bffde63dSSheetal Tigadoli 
417bffde63dSSheetal Tigadoli 		if (!read_block(p_sdhandle, outputBuf, blockAddr, readLen)) {
418*9f58bfbbSBoyan Karatotev 			if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
419bffde63dSSheetal Tigadoli 				blockAddr += (readLen / blockSize);
420*9f58bfbbSBoyan Karatotev 			} else {
421bffde63dSSheetal Tigadoli 				blockAddr += readLen;
422*9f58bfbbSBoyan Karatotev 			}
423bffde63dSSheetal Tigadoli 
424bffde63dSSheetal Tigadoli 			remSize -= readLen;
425bffde63dSSheetal Tigadoli 			rdCount += readLen;
426bffde63dSSheetal Tigadoli 
427bffde63dSSheetal Tigadoli 			/* Update Physical address */
428bffde63dSSheetal Tigadoli 			outputBuf += readLen;
429bffde63dSSheetal Tigadoli 		} else {
430bffde63dSSheetal Tigadoli 			return 0;
431bffde63dSSheetal Tigadoli 		}
432bffde63dSSheetal Tigadoli 	}
433bffde63dSSheetal Tigadoli 
434bffde63dSSheetal Tigadoli 	/* process the last unaligned block reading */
435bffde63dSSheetal Tigadoli 	if (remSize > 0) {
436bffde63dSSheetal Tigadoli 		if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
437bffde63dSSheetal Tigadoli 				blockAddr, SD_MAX_READ_LENGTH)) {
438bffde63dSSheetal Tigadoli 
439bffde63dSSheetal Tigadoli 			rdCount += remSize;
440bffde63dSSheetal Tigadoli 			/* Check for overflow */
441bffde63dSSheetal Tigadoli 			if (rdCount > storage_size ||
442bffde63dSSheetal Tigadoli 			    (((uintptr_t) outputBuf + remSize) >
443bffde63dSSheetal Tigadoli 			     (storage_addr + storage_size))) {
444bffde63dSSheetal Tigadoli 				ERROR("EMMC READ: Overflow\n");
445bffde63dSSheetal Tigadoli 				return 0;
446bffde63dSSheetal Tigadoli 			}
447bffde63dSSheetal Tigadoli 
448bffde63dSSheetal Tigadoli 			memcpy(outputBuf,
449bffde63dSSheetal Tigadoli 				emmc_global_buf_ptr->u.tempbuf, remSize);
450bffde63dSSheetal Tigadoli 
451bffde63dSSheetal Tigadoli 			/* Update Physical address */
452bffde63dSSheetal Tigadoli 			outputBuf += remSize;
453bffde63dSSheetal Tigadoli 		} else {
454bffde63dSSheetal Tigadoli 			rdCount = 0;
455bffde63dSSheetal Tigadoli 		}
456bffde63dSSheetal Tigadoli 	}
457bffde63dSSheetal Tigadoli 
458bffde63dSSheetal Tigadoli 	return rdCount;
459bffde63dSSheetal Tigadoli }
460bffde63dSSheetal Tigadoli 
461bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
sdio_write(struct sd_handle * p_sdhandle,uintptr_t mem_addr,uintptr_t data_addr,size_t bytes_to_write)462bffde63dSSheetal Tigadoli static uint32_t sdio_write(struct sd_handle *p_sdhandle, uintptr_t mem_addr,
463bffde63dSSheetal Tigadoli 			   uintptr_t data_addr, size_t bytes_to_write)
464bffde63dSSheetal Tigadoli {
465bffde63dSSheetal Tigadoli 
466bffde63dSSheetal Tigadoli 	uint32_t offset, blockAddr, writeLen, wtCount = 0;
467bffde63dSSheetal Tigadoli 	uint32_t remSize, manual_copy_size = 0;
468bffde63dSSheetal Tigadoli 
469bffde63dSSheetal Tigadoli 	uint8_t *inputBuf = (uint8_t *)data_addr;
470bffde63dSSheetal Tigadoli 
471bffde63dSSheetal Tigadoli 	/* range check non high capacity memory */
472bffde63dSSheetal Tigadoli 	if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
473*9f58bfbbSBoyan Karatotev 		if (mem_addr > 0x80000000) {
474bffde63dSSheetal Tigadoli 			return 0;
475bffde63dSSheetal Tigadoli 		}
476*9f58bfbbSBoyan Karatotev 	}
477bffde63dSSheetal Tigadoli 
478bffde63dSSheetal Tigadoli 	/* the high capacity card use block address mode */
479bffde63dSSheetal Tigadoli 	if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
480bffde63dSSheetal Tigadoli 		blockAddr =
481bffde63dSSheetal Tigadoli 		    (uint32_t)(mem_addr / p_sdhandle->device->cfg.blockSize);
482bffde63dSSheetal Tigadoli 		offset =
483bffde63dSSheetal Tigadoli 		    (uint32_t)(mem_addr -
484bffde63dSSheetal Tigadoli 			       blockAddr * p_sdhandle->device->cfg.blockSize);
485bffde63dSSheetal Tigadoli 	} else {
486bffde63dSSheetal Tigadoli 		blockAddr =
487bffde63dSSheetal Tigadoli 		    ((uint32_t)mem_addr / p_sdhandle->device->cfg.blockSize) *
488bffde63dSSheetal Tigadoli 		    p_sdhandle->device->cfg.blockSize;
489bffde63dSSheetal Tigadoli 		offset = (uint32_t) mem_addr - blockAddr;
490bffde63dSSheetal Tigadoli 	}
491bffde63dSSheetal Tigadoli 
492bffde63dSSheetal Tigadoli 	remSize = bytes_to_write;
493bffde63dSSheetal Tigadoli 
494bffde63dSSheetal Tigadoli 	wtCount = 0;
495bffde63dSSheetal Tigadoli 
496bffde63dSSheetal Tigadoli 	/* process first unaligned block */
497bffde63dSSheetal Tigadoli 	if (offset > 0) {
498bffde63dSSheetal Tigadoli 		if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
499bffde63dSSheetal Tigadoli 				blockAddr, p_sdhandle->device->cfg.blockSize)) {
500bffde63dSSheetal Tigadoli 
501bffde63dSSheetal Tigadoli 			if (remSize <
502*9f58bfbbSBoyan Karatotev 			    (p_sdhandle->device->cfg.blockSize - offset)) {
503bffde63dSSheetal Tigadoli 				manual_copy_size = remSize;
504*9f58bfbbSBoyan Karatotev 			} else {
505bffde63dSSheetal Tigadoli 				manual_copy_size =
506bffde63dSSheetal Tigadoli 				    p_sdhandle->device->cfg.blockSize - offset;
507*9f58bfbbSBoyan Karatotev 			}
508bffde63dSSheetal Tigadoli 
509bffde63dSSheetal Tigadoli 			memcpy((void *)((uintptr_t)
510bffde63dSSheetal Tigadoli 				(emmc_global_buf_ptr->u.tempbuf + offset)),
511bffde63dSSheetal Tigadoli 			       inputBuf,
512bffde63dSSheetal Tigadoli 			       manual_copy_size);
513bffde63dSSheetal Tigadoli 
514bffde63dSSheetal Tigadoli 			/* Update Physical address */
515bffde63dSSheetal Tigadoli 
516bffde63dSSheetal Tigadoli 			if (!write_block(p_sdhandle,
517bffde63dSSheetal Tigadoli 					 emmc_global_buf_ptr->u.tempbuf,
518bffde63dSSheetal Tigadoli 					 blockAddr,
519bffde63dSSheetal Tigadoli 					 p_sdhandle->device->cfg.blockSize)) {
520bffde63dSSheetal Tigadoli 
521bffde63dSSheetal Tigadoli 				if (remSize <
522bffde63dSSheetal Tigadoli 				    (p_sdhandle->device->cfg.blockSize -
523bffde63dSSheetal Tigadoli 				     offset)) {
524bffde63dSSheetal Tigadoli 					wtCount += remSize;
525bffde63dSSheetal Tigadoli 					manual_copy_size = remSize;
526bffde63dSSheetal Tigadoli 					remSize = 0;	/* read is done */
527bffde63dSSheetal Tigadoli 				} else {
528bffde63dSSheetal Tigadoli 					remSize -=
529bffde63dSSheetal Tigadoli 					    (p_sdhandle->device->cfg.blockSize -
530bffde63dSSheetal Tigadoli 					     offset);
531bffde63dSSheetal Tigadoli 					wtCount +=
532bffde63dSSheetal Tigadoli 					    (p_sdhandle->device->cfg.blockSize -
533bffde63dSSheetal Tigadoli 					     offset);
534bffde63dSSheetal Tigadoli 					manual_copy_size =
535bffde63dSSheetal Tigadoli 					    p_sdhandle->device->cfg.blockSize -
536bffde63dSSheetal Tigadoli 					    offset;
537bffde63dSSheetal Tigadoli 				}
538bffde63dSSheetal Tigadoli 
539bffde63dSSheetal Tigadoli 				inputBuf += manual_copy_size;
540bffde63dSSheetal Tigadoli 
541bffde63dSSheetal Tigadoli 				if (p_sdhandle->device->ctrl.ocr &
542*9f58bfbbSBoyan Karatotev 				    SD_CARD_HIGH_CAPACITY) {
543bffde63dSSheetal Tigadoli 					blockAddr++;
544*9f58bfbbSBoyan Karatotev 				} else {
545bffde63dSSheetal Tigadoli 					blockAddr +=
546bffde63dSSheetal Tigadoli 					    p_sdhandle->device->cfg.blockSize;
547*9f58bfbbSBoyan Karatotev 				}
548bffde63dSSheetal Tigadoli 			} else
549bffde63dSSheetal Tigadoli 				return 0;
550bffde63dSSheetal Tigadoli 		} else {
551bffde63dSSheetal Tigadoli 			return 0;
552bffde63dSSheetal Tigadoli 		}
553bffde63dSSheetal Tigadoli 	}
554bffde63dSSheetal Tigadoli 
555bffde63dSSheetal Tigadoli 	/* process block writing */
556bffde63dSSheetal Tigadoli 	while (remSize >= p_sdhandle->device->cfg.blockSize) {
557bffde63dSSheetal Tigadoli 		if (remSize >= SD_MAX_READ_LENGTH) {
558bffde63dSSheetal Tigadoli 			writeLen = SD_MAX_READ_LENGTH;
559bffde63dSSheetal Tigadoli 		} else {
560bffde63dSSheetal Tigadoli 			writeLen =
561bffde63dSSheetal Tigadoli 			    (remSize / p_sdhandle->device->cfg.blockSize) *
562bffde63dSSheetal Tigadoli 			     p_sdhandle->device->cfg.blockSize;
563bffde63dSSheetal Tigadoli 		}
564bffde63dSSheetal Tigadoli 
565bffde63dSSheetal Tigadoli 		if (!write_block(p_sdhandle, inputBuf, blockAddr, writeLen)) {
566bffde63dSSheetal Tigadoli 			if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
567bffde63dSSheetal Tigadoli 				blockAddr +=
568bffde63dSSheetal Tigadoli 				    (writeLen /
569bffde63dSSheetal Tigadoli 				     p_sdhandle->device->cfg.blockSize);
570bffde63dSSheetal Tigadoli 			else
571bffde63dSSheetal Tigadoli 				blockAddr += writeLen;
572bffde63dSSheetal Tigadoli 
573bffde63dSSheetal Tigadoli 			remSize -= writeLen;
574bffde63dSSheetal Tigadoli 			wtCount += writeLen;
575bffde63dSSheetal Tigadoli 			inputBuf += writeLen;
576bffde63dSSheetal Tigadoli 		} else {
577bffde63dSSheetal Tigadoli 			return 0;
578bffde63dSSheetal Tigadoli 		}
579bffde63dSSheetal Tigadoli 	}
580bffde63dSSheetal Tigadoli 
581bffde63dSSheetal Tigadoli 	/* process the last unaligned block reading */
582bffde63dSSheetal Tigadoli 	if (remSize > 0) {
583bffde63dSSheetal Tigadoli 		if (!read_block(p_sdhandle,
584bffde63dSSheetal Tigadoli 				emmc_global_buf_ptr->u.tempbuf,
585bffde63dSSheetal Tigadoli 				blockAddr, p_sdhandle->device->cfg.blockSize)) {
586bffde63dSSheetal Tigadoli 
587bffde63dSSheetal Tigadoli 			memcpy(emmc_global_buf_ptr->u.tempbuf,
588bffde63dSSheetal Tigadoli 			       inputBuf, remSize);
589bffde63dSSheetal Tigadoli 
590bffde63dSSheetal Tigadoli 			/* Update Physical address */
591bffde63dSSheetal Tigadoli 
592bffde63dSSheetal Tigadoli 			if (!write_block(p_sdhandle,
593bffde63dSSheetal Tigadoli 					 emmc_global_buf_ptr->u.tempbuf,
594bffde63dSSheetal Tigadoli 					 blockAddr,
595bffde63dSSheetal Tigadoli 					 p_sdhandle->device->cfg.blockSize)) {
596bffde63dSSheetal Tigadoli 				wtCount += remSize;
597bffde63dSSheetal Tigadoli 				inputBuf += remSize;
598bffde63dSSheetal Tigadoli 			} else {
599bffde63dSSheetal Tigadoli 				return 0;
600bffde63dSSheetal Tigadoli 			}
601bffde63dSSheetal Tigadoli 		} else {
602bffde63dSSheetal Tigadoli 			wtCount = 0;
603bffde63dSSheetal Tigadoli 		}
604bffde63dSSheetal Tigadoli 	}
605bffde63dSSheetal Tigadoli 
606bffde63dSSheetal Tigadoli 	return wtCount;
607bffde63dSSheetal Tigadoli }
608bffde63dSSheetal Tigadoli #endif
609bffde63dSSheetal Tigadoli 
610bffde63dSSheetal Tigadoli /*
611bffde63dSSheetal Tigadoli  * Function to put the card in Ready state by sending CMD0 and CMD1
612bffde63dSSheetal Tigadoli  */
bcm_emmc_card_ready_state(struct sd_handle * p_sdhandle)613bffde63dSSheetal Tigadoli static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle)
614bffde63dSSheetal Tigadoli {
615bffde63dSSheetal Tigadoli 	int32_t result = 0;
616bffde63dSSheetal Tigadoli 	uint32_t argument = MMC_CMD_IDLE_RESET_ARG; /* Exit from Boot mode */
617bffde63dSSheetal Tigadoli 
618bffde63dSSheetal Tigadoli 	if (p_sdhandle) {
619bffde63dSSheetal Tigadoli 		send_sdio_cmd(SD_CMD_GO_IDLE_STATE, argument, 0, NULL);
620bffde63dSSheetal Tigadoli 
621bffde63dSSheetal Tigadoli 		result = reset_card(p_sdhandle);
622bffde63dSSheetal Tigadoli 		if (result != SD_OK) {
623bffde63dSSheetal Tigadoli 			EMMC_TRACE("eMMC Reset error\n");
624bffde63dSSheetal Tigadoli 			return SD_RESET_ERROR;
625bffde63dSSheetal Tigadoli 		}
626bffde63dSSheetal Tigadoli 		SD_US_DELAY(2000);
627bffde63dSSheetal Tigadoli 		result = mmc_cmd1(p_sdhandle);
628bffde63dSSheetal Tigadoli 	}
629bffde63dSSheetal Tigadoli 
630bffde63dSSheetal Tigadoli 	return result;
631bffde63dSSheetal Tigadoli }
632