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