xref: /rk3399_ARM-atf/drivers/brcm/emmc/emmc_csl_sdcard.c (revision 4bd8c929b4bc6e1731c2892b38d4a8c43e8e89dc)
1bffde63dSSheetal Tigadoli /*
2bffde63dSSheetal Tigadoli  * Copyright (c) 2016 - 2020, Broadcom
3bffde63dSSheetal Tigadoli  *
4bffde63dSSheetal Tigadoli  * SPDX-License-Identifier: BSD-3-Clause
5bffde63dSSheetal Tigadoli  */
6bffde63dSSheetal Tigadoli 
74ce3e99aSScott Branden #include <inttypes.h>
84ce3e99aSScott Branden #include <stddef.h>
94ce3e99aSScott Branden #include <stdint.h>
10bffde63dSSheetal Tigadoli #include <stdlib.h>
11bffde63dSSheetal Tigadoli #include <string.h>
12bffde63dSSheetal Tigadoli 
13bffde63dSSheetal Tigadoli #include <arch_helpers.h>
14bffde63dSSheetal Tigadoli #include <lib/mmio.h>
15bffde63dSSheetal Tigadoli 
16bffde63dSSheetal Tigadoli #include "bcm_emmc.h"
17bffde63dSSheetal Tigadoli #include "emmc_chal_types.h"
18bffde63dSSheetal Tigadoli #include "emmc_csl_sdprot.h"
19bffde63dSSheetal Tigadoli #include "emmc_chal_sd.h"
20bffde63dSSheetal Tigadoli #include "emmc_csl_sdcmd.h"
21bffde63dSSheetal Tigadoli #include "emmc_csl_sd.h"
22bffde63dSSheetal Tigadoli #include "emmc_pboot_hal_memory_drv.h"
23bffde63dSSheetal Tigadoli 
24bffde63dSSheetal Tigadoli #define SD_CARD_BUSY                    0x80000000
25bffde63dSSheetal Tigadoli #define SD_CARD_RETRY_LIMIT             1000
26bffde63dSSheetal Tigadoli #define SD_CARD_HIGH_SPEED_PS           13
27bffde63dSSheetal Tigadoli #define SD_CHK_HIGH_SPEED_MODE          0x00FFFFF1
28bffde63dSSheetal Tigadoli #define SD_SET_HIGH_SPEED_MODE          0x80FFFFF1
29bffde63dSSheetal Tigadoli #define SD_MMC_ENABLE_HIGH_SPEED        0x03b90100	//0x03b90103
30bffde63dSSheetal Tigadoli #define SD_MMC_8BIT_MODE                0x03b70200
31bffde63dSSheetal Tigadoli #define SD_MMC_4BIT_MODE                0x03b70100
32bffde63dSSheetal Tigadoli #define SD_MMC_1BIT_MODE                0x03b70000
33bffde63dSSheetal Tigadoli 
34bffde63dSSheetal Tigadoli #define SD_MMC_BOOT_8BIT_MODE           0x03b10200
35bffde63dSSheetal Tigadoli #define SD_MMC_BOOT_4BIT_MODE           0x03b10100
36bffde63dSSheetal Tigadoli #define SD_MMC_BOOT_1BIT_MODE           0x03b10000
37bffde63dSSheetal Tigadoli #define SDIO_HW_EMMC_EXT_CSD_BOOT_CNF   0X03B30000
38bffde63dSSheetal Tigadoli 
39bffde63dSSheetal Tigadoli #ifdef USE_EMMC_FIP_TOC_CACHE
40bffde63dSSheetal Tigadoli /*
41bffde63dSSheetal Tigadoli  * Cache size mirrors the size of the global eMMC temp buffer
42bffde63dSSheetal Tigadoli  * which is used for non-image body reads such as headers, ToC etc.
43bffde63dSSheetal Tigadoli  */
44bffde63dSSheetal Tigadoli #define CACHE_SIZE           ((EMMC_BLOCK_SIZE) * 2)
45bffde63dSSheetal Tigadoli #define PARTITION_BLOCK_ADDR ((PLAT_FIP_ATTEMPT_OFFSET)/(EMMC_BLOCK_SIZE))
46bffde63dSSheetal Tigadoli 
47bffde63dSSheetal Tigadoli static uint32_t cached_partition_block;
48bffde63dSSheetal Tigadoli static uint8_t cached_block[CACHE_SIZE];
49bffde63dSSheetal Tigadoli #endif
50bffde63dSSheetal Tigadoli 
51bffde63dSSheetal Tigadoli static int set_card_data_width(struct sd_handle *handle, int width);
52bffde63dSSheetal Tigadoli static int abort_err(struct sd_handle *handle);
53bffde63dSSheetal Tigadoli static int err_recovery(struct sd_handle *handle, uint32_t errors);
54bffde63dSSheetal Tigadoli static int xfer_data(struct sd_handle *handle, uint32_t mode, uint32_t addr,
55bffde63dSSheetal Tigadoli 		     uint32_t length, uint8_t *base);
56bffde63dSSheetal Tigadoli 
set_boot_config(struct sd_handle * handle,uint32_t config)57bffde63dSSheetal Tigadoli int set_boot_config(struct sd_handle *handle, uint32_t config)
58bffde63dSSheetal Tigadoli {
59bffde63dSSheetal Tigadoli 	return mmc_cmd6(handle, SDIO_HW_EMMC_EXT_CSD_BOOT_CNF | config);
60bffde63dSSheetal Tigadoli }
61bffde63dSSheetal Tigadoli 
process_csd_mmc_speed(struct sd_handle * handle,uint32_t csd_mmc_speed)62bffde63dSSheetal Tigadoli void process_csd_mmc_speed(struct sd_handle *handle, uint32_t csd_mmc_speed)
63bffde63dSSheetal Tigadoli {
64bffde63dSSheetal Tigadoli 	uint32_t div_ctrl_setting;
65bffde63dSSheetal Tigadoli 
66bffde63dSSheetal Tigadoli 	/* CSD field TRAN_SPEED:
67bffde63dSSheetal Tigadoli 	 * Bits [2:0] 0 = 100 KHz
68bffde63dSSheetal Tigadoli 	 *            1 = 1 MHz
69bffde63dSSheetal Tigadoli 	 *            2 = 10 MHz
70bffde63dSSheetal Tigadoli 	 *            3 = 100 MHz
71bffde63dSSheetal Tigadoli 	 *            4...7 Reserved.
72bffde63dSSheetal Tigadoli 	 * Bits [6:3] 0 = Reserved
73bffde63dSSheetal Tigadoli 	 *            1 = 1.0
74bffde63dSSheetal Tigadoli 	 *            2 = 1.2
75bffde63dSSheetal Tigadoli 	 *            3 = 1.3
76bffde63dSSheetal Tigadoli 	 *            4 = 1.5
77bffde63dSSheetal Tigadoli 	 *            5 = 2.0
78bffde63dSSheetal Tigadoli 	 *            6 = 2.6
79bffde63dSSheetal Tigadoli 	 *            7 = 3.0
80bffde63dSSheetal Tigadoli 	 *            8 = 3.5
81bffde63dSSheetal Tigadoli 	 *            9 = 4.0
82bffde63dSSheetal Tigadoli 	 *            A = 4.5
83bffde63dSSheetal Tigadoli 	 *            B = 5.2
84bffde63dSSheetal Tigadoli 	 *            C = 5.5
85bffde63dSSheetal Tigadoli 	 *            D = 6.0
86bffde63dSSheetal Tigadoli 	 *            E = 7.0
87bffde63dSSheetal Tigadoli 	 *            F = 8.0
88bffde63dSSheetal Tigadoli 	 * For cards supporting version 4.0, 4.1, and 4.2 of the standard,
89bffde63dSSheetal Tigadoli 	 * the value shall be 20 MHz (0x2A).
90bffde63dSSheetal Tigadoli 	 * For cards supporting version 4.3 , the value shall be 26 MHz (0x32)
91bffde63dSSheetal Tigadoli 	 */
92bffde63dSSheetal Tigadoli 
93bffde63dSSheetal Tigadoli 	switch (csd_mmc_speed & 0x7F) {
94bffde63dSSheetal Tigadoli 	case 0x2A:
95bffde63dSSheetal Tigadoli 		EMMC_TRACE("Speeding up eMMC clock to 20MHz\n");
96bffde63dSSheetal Tigadoli 		div_ctrl_setting =
97bffde63dSSheetal Tigadoli 		    chal_sd_freq_2_div_ctrl_setting(20 * 1000 * 1000);
98bffde63dSSheetal Tigadoli 		break;
99bffde63dSSheetal Tigadoli 	case 0x32:
100bffde63dSSheetal Tigadoli 		EMMC_TRACE("Speeding up eMMC clock to 26MHz\n");
101bffde63dSSheetal Tigadoli 		div_ctrl_setting =
102bffde63dSSheetal Tigadoli 		    chal_sd_freq_2_div_ctrl_setting(26 * 1000 * 1000);
103bffde63dSSheetal Tigadoli 		break;
104bffde63dSSheetal Tigadoli 	default:
105bffde63dSSheetal Tigadoli 		/* Unknown */
106bffde63dSSheetal Tigadoli 		return;
107bffde63dSSheetal Tigadoli 	}
108bffde63dSSheetal Tigadoli 
109bffde63dSSheetal Tigadoli 	chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 0);
110bffde63dSSheetal Tigadoli 
111bffde63dSSheetal Tigadoli 	chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 1);
112bffde63dSSheetal Tigadoli 
113bffde63dSSheetal Tigadoli 	SD_US_DELAY(1000);
114bffde63dSSheetal Tigadoli }
115bffde63dSSheetal Tigadoli 
116bffde63dSSheetal Tigadoli 
117bffde63dSSheetal Tigadoli /*
118bffde63dSSheetal Tigadoli  * The function changes SD/SDIO/MMC card data width if
119bffde63dSSheetal Tigadoli  * the card support configurable data width. The host controller
120bffde63dSSheetal Tigadoli  * and the card has to be in the same bus data width.
121bffde63dSSheetal Tigadoli  */
set_card_data_width(struct sd_handle * handle,int width)122bffde63dSSheetal Tigadoli int set_card_data_width(struct sd_handle *handle, int width)
123bffde63dSSheetal Tigadoli {
124bffde63dSSheetal Tigadoli 	uint32_t data_width = 0;
125bffde63dSSheetal Tigadoli 	int is_valid_arg = 1;
126bffde63dSSheetal Tigadoli 	int rc = SD_FAIL;
127bffde63dSSheetal Tigadoli 	char *bitwidth_str = " ";
128bffde63dSSheetal Tigadoli 	char *result_str = "failed";
129bffde63dSSheetal Tigadoli 
130bffde63dSSheetal Tigadoli 	switch (width) {
131bffde63dSSheetal Tigadoli #ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT
132bffde63dSSheetal Tigadoli 	case SD_BUS_DATA_WIDTH_8BIT:
133bffde63dSSheetal Tigadoli 		data_width = SD_MMC_8BIT_MODE;
134bffde63dSSheetal Tigadoli #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
135bffde63dSSheetal Tigadoli 		bitwidth_str = "8_BIT";
136bffde63dSSheetal Tigadoli #endif
137bffde63dSSheetal Tigadoli 		break;
138bffde63dSSheetal Tigadoli #endif
139bffde63dSSheetal Tigadoli 	case SD_BUS_DATA_WIDTH_4BIT:
140bffde63dSSheetal Tigadoli 		data_width = SD_MMC_4BIT_MODE;
141bffde63dSSheetal Tigadoli #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
142bffde63dSSheetal Tigadoli 		bitwidth_str = "4_BIT";
143bffde63dSSheetal Tigadoli #endif
144bffde63dSSheetal Tigadoli 		break;
145bffde63dSSheetal Tigadoli 
146bffde63dSSheetal Tigadoli 	case SD_BUS_DATA_WIDTH_1BIT:
147bffde63dSSheetal Tigadoli 		data_width = SD_MMC_1BIT_MODE;
148bffde63dSSheetal Tigadoli #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
149bffde63dSSheetal Tigadoli 		bitwidth_str = "1_BIT";
150bffde63dSSheetal Tigadoli #endif
151bffde63dSSheetal Tigadoli 		break;
152bffde63dSSheetal Tigadoli 
153bffde63dSSheetal Tigadoli 	default:
154bffde63dSSheetal Tigadoli 		is_valid_arg = 0;
155bffde63dSSheetal Tigadoli #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
156bffde63dSSheetal Tigadoli 		bitwidth_str = "unknown";
157bffde63dSSheetal Tigadoli #endif
158bffde63dSSheetal Tigadoli 		break;
159bffde63dSSheetal Tigadoli 	}
160bffde63dSSheetal Tigadoli 
161bffde63dSSheetal Tigadoli 	if (is_valid_arg) {
162bffde63dSSheetal Tigadoli 		rc = mmc_cmd6(handle, data_width);
163bffde63dSSheetal Tigadoli 		if (rc == SD_OK) {
164bffde63dSSheetal Tigadoli #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
165bffde63dSSheetal Tigadoli 			result_str = "succeeded";
166bffde63dSSheetal Tigadoli #endif
167bffde63dSSheetal Tigadoli 			chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
168bffde63dSSheetal Tigadoli 						 width);
169bffde63dSSheetal Tigadoli 		} else {
170bffde63dSSheetal Tigadoli #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
171bffde63dSSheetal Tigadoli 			result_str = "failed";
172bffde63dSSheetal Tigadoli #endif
173bffde63dSSheetal Tigadoli 		}
174bffde63dSSheetal Tigadoli 	} else {
175bffde63dSSheetal Tigadoli 		rc = SD_FAIL;
176bffde63dSSheetal Tigadoli #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
177bffde63dSSheetal Tigadoli 		result_str = "ignored";
178bffde63dSSheetal Tigadoli #endif
179bffde63dSSheetal Tigadoli 	}
180bffde63dSSheetal Tigadoli 
181bffde63dSSheetal Tigadoli 	VERBOSE("SDIO Data Width(%s) %s.\n", bitwidth_str, result_str);
182bffde63dSSheetal Tigadoli 
183bffde63dSSheetal Tigadoli 	return rc;
184bffde63dSSheetal Tigadoli }
185bffde63dSSheetal Tigadoli 
186bffde63dSSheetal Tigadoli 
187bffde63dSSheetal Tigadoli /*
188bffde63dSSheetal Tigadoli  * Error handling routine. Does abort data
189bffde63dSSheetal Tigadoli  * transmission if error is found.
190bffde63dSSheetal Tigadoli  */
abort_err(struct sd_handle * handle)191bffde63dSSheetal Tigadoli static int abort_err(struct sd_handle *handle)
192bffde63dSSheetal Tigadoli {
193bffde63dSSheetal Tigadoli 	uint32_t present, options, event, rel = 0;
194bffde63dSSheetal Tigadoli 	struct sd_resp cmdRsp;
195bffde63dSSheetal Tigadoli 
196bffde63dSSheetal Tigadoli 	handle->device->ctrl.argReg = 0;
197bffde63dSSheetal Tigadoli 	handle->device->ctrl.cmdIndex = SD_CMD_STOP_TRANSMISSION;
198bffde63dSSheetal Tigadoli 
199bffde63dSSheetal Tigadoli 	options = (SD_CMD_STOP_TRANSMISSION << 24) |
200bffde63dSSheetal Tigadoli 		  (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) |
201bffde63dSSheetal Tigadoli 		  SD4_EMMC_TOP_CMD_CRC_EN_MASK |
202bffde63dSSheetal Tigadoli 		  SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
203bffde63dSSheetal Tigadoli 
204bffde63dSSheetal Tigadoli 	chal_sd_send_cmd((CHAL_HANDLE *) handle->device,
205bffde63dSSheetal Tigadoli 			 handle->device->ctrl.cmdIndex,
206bffde63dSSheetal Tigadoli 			 handle->device->ctrl.argReg, options);
207bffde63dSSheetal Tigadoli 
208bffde63dSSheetal Tigadoli 	event = wait_for_event(handle,
209bffde63dSSheetal Tigadoli 			       SD4_EMMC_TOP_INTR_CMDDONE_MASK |
210bffde63dSSheetal Tigadoli 			       SD_ERR_INTERRUPTS,
211bffde63dSSheetal Tigadoli 			       handle->device->cfg.wfe_retry);
212bffde63dSSheetal Tigadoli 
213bffde63dSSheetal Tigadoli 	if (event & SD_CMD_ERROR_INT) {
214bffde63dSSheetal Tigadoli 		rel = SD_ERROR_NON_RECOVERABLE;
215bffde63dSSheetal Tigadoli 	} else {
216bffde63dSSheetal Tigadoli 		if (event & SD_DAT_TIMEOUT) {
217bffde63dSSheetal Tigadoli 			return SD_ERROR_NON_RECOVERABLE;
218bffde63dSSheetal Tigadoli 		}
219bffde63dSSheetal Tigadoli 
220bffde63dSSheetal Tigadoli 		chal_sd_get_response((CHAL_HANDLE *) handle->device,
221bffde63dSSheetal Tigadoli 				     (uint32_t *)&cmdRsp);
222bffde63dSSheetal Tigadoli 
223bffde63dSSheetal Tigadoli 		process_cmd_response(handle, handle->device->ctrl.cmdIndex,
224bffde63dSSheetal Tigadoli 				     cmdRsp.data.r2.rsp1, cmdRsp.data.r2.rsp2,
225bffde63dSSheetal Tigadoli 				     cmdRsp.data.r2.rsp3, cmdRsp.data.r2.rsp4,
226bffde63dSSheetal Tigadoli 				     &cmdRsp);
227bffde63dSSheetal Tigadoli 
228bffde63dSSheetal Tigadoli 		SD_US_DELAY(2000);
229bffde63dSSheetal Tigadoli 
230bffde63dSSheetal Tigadoli 		present =
231bffde63dSSheetal Tigadoli 		    chal_sd_get_present_status((CHAL_HANDLE *) handle->device);
232bffde63dSSheetal Tigadoli 
233bffde63dSSheetal Tigadoli 		if ((present & 0x00F00000) == 0x00F00000)
234bffde63dSSheetal Tigadoli 			rel = SD_ERROR_RECOVERABLE;
235bffde63dSSheetal Tigadoli 		else
236bffde63dSSheetal Tigadoli 			rel = SD_ERROR_NON_RECOVERABLE;
237bffde63dSSheetal Tigadoli 	}
238bffde63dSSheetal Tigadoli 
239bffde63dSSheetal Tigadoli 	return rel;
240bffde63dSSheetal Tigadoli }
241bffde63dSSheetal Tigadoli 
242bffde63dSSheetal Tigadoli 
243bffde63dSSheetal Tigadoli /*
244bffde63dSSheetal Tigadoli  * The function handles real data transmission on both DMA and
245bffde63dSSheetal Tigadoli  * none DMA mode, In None DMA mode the data transfer starts
246bffde63dSSheetal Tigadoli  * when the command is sent to the card, data has to be written
247*1b491eeaSElyes Haouas  * into the host controllers buffer at this time one block
248bffde63dSSheetal Tigadoli  * at a time.
249bffde63dSSheetal Tigadoli  * In DMA mode, the real data transfer is done by the DMA engine
250bffde63dSSheetal Tigadoli  * and this functions just waits for the data transfer to complete.
251bffde63dSSheetal Tigadoli  *
252bffde63dSSheetal Tigadoli  */
process_data_xfer(struct sd_handle * handle,uint8_t * buffer,uint32_t addr,uint32_t length,int dir)253bffde63dSSheetal Tigadoli int process_data_xfer(struct sd_handle *handle, uint8_t *buffer, uint32_t addr,
254bffde63dSSheetal Tigadoli 		      uint32_t length, int dir)
255bffde63dSSheetal Tigadoli {
256bffde63dSSheetal Tigadoli 	if (dir == SD_XFER_HOST_TO_CARD) {
257bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
258bffde63dSSheetal Tigadoli 		if (handle->device->cfg.dma == SD_DMA_OFF) {
259bffde63dSSheetal Tigadoli 			/*
260bffde63dSSheetal Tigadoli 			 * In NON DMA mode, the real data xfer starts from here
261bffde63dSSheetal Tigadoli 			 */
262bffde63dSSheetal Tigadoli 			if (write_buffer(handle, length, buffer))
263bffde63dSSheetal Tigadoli 				return SD_WRITE_ERROR;
264bffde63dSSheetal Tigadoli 		} else {
265bffde63dSSheetal Tigadoli 			wait_for_event(handle,
266bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_INTR_TXDONE_MASK |
267bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS,
268bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
269bffde63dSSheetal Tigadoli 
270bffde63dSSheetal Tigadoli 			if (handle->device->ctrl.cmdStatus == SD_OK)
271bffde63dSSheetal Tigadoli 				return SD_OK;
272bffde63dSSheetal Tigadoli 
273bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
274bffde63dSSheetal Tigadoli 			return SD_WRITE_ERROR;
275bffde63dSSheetal Tigadoli 		}
276bffde63dSSheetal Tigadoli #else
277bffde63dSSheetal Tigadoli 		return SD_WRITE_ERROR;
278bffde63dSSheetal Tigadoli #endif
279bffde63dSSheetal Tigadoli 	} else {		/* SD_XFER_CARD_TO_HOST */
280bffde63dSSheetal Tigadoli 
281bffde63dSSheetal Tigadoli 		if (handle->device->cfg.dma == SD_DMA_OFF) {
282bffde63dSSheetal Tigadoli 			/* In NON DMA mode, the real data
283bffde63dSSheetal Tigadoli 			 * transfer starts from here
284bffde63dSSheetal Tigadoli 			 */
285bffde63dSSheetal Tigadoli 			if (read_buffer(handle, length, buffer))
286bffde63dSSheetal Tigadoli 				return SD_READ_ERROR;
287bffde63dSSheetal Tigadoli 
288bffde63dSSheetal Tigadoli 		} else {	/* for DMA mode */
289bffde63dSSheetal Tigadoli 
290bffde63dSSheetal Tigadoli 			/*
291bffde63dSSheetal Tigadoli 			 * once the data transmission is done
292bffde63dSSheetal Tigadoli 			 * copy data to the host buffer.
293bffde63dSSheetal Tigadoli 			 */
294bffde63dSSheetal Tigadoli 			wait_for_event(handle,
295bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_INTR_TXDONE_MASK |
296bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS,
297bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
298bffde63dSSheetal Tigadoli 
299bffde63dSSheetal Tigadoli 			if (handle->device->ctrl.cmdStatus == SD_OK)
300bffde63dSSheetal Tigadoli 				return SD_OK;
301bffde63dSSheetal Tigadoli 
302bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
303bffde63dSSheetal Tigadoli 			return SD_READ_ERROR;
304bffde63dSSheetal Tigadoli 		}
305bffde63dSSheetal Tigadoli 	}
306bffde63dSSheetal Tigadoli 	return SD_OK;
307bffde63dSSheetal Tigadoli }
308bffde63dSSheetal Tigadoli 
309bffde63dSSheetal Tigadoli 
310bffde63dSSheetal Tigadoli /*
311bffde63dSSheetal Tigadoli  * The function sets block size for the next SD/SDIO/MMC
312bffde63dSSheetal Tigadoli  * card read/write command.
313bffde63dSSheetal Tigadoli  */
select_blk_sz(struct sd_handle * handle,uint16_t size)314bffde63dSSheetal Tigadoli int select_blk_sz(struct sd_handle *handle, uint16_t size)
315bffde63dSSheetal Tigadoli {
316bffde63dSSheetal Tigadoli 	return sd_cmd16(handle, size);
317bffde63dSSheetal Tigadoli }
318bffde63dSSheetal Tigadoli 
319bffde63dSSheetal Tigadoli 
320bffde63dSSheetal Tigadoli /*
321*1b491eeaSElyes Haouas  * The function initializes the SD/SDIO/MMC/CEATA and detects
322bffde63dSSheetal Tigadoli  * the card according to the flag of detection.
323bffde63dSSheetal Tigadoli  * Once this function is called, the card is put into ready state
324bffde63dSSheetal Tigadoli  * so application can do data transfer to and from the card.
325bffde63dSSheetal Tigadoli  */
init_card(struct sd_handle * handle,int detection)326bffde63dSSheetal Tigadoli int init_card(struct sd_handle *handle, int detection)
327bffde63dSSheetal Tigadoli {
328bffde63dSSheetal Tigadoli 	/*
329bffde63dSSheetal Tigadoli 	 * After Reset, eMMC comes up in 1 Bit Data Width by default.
330bffde63dSSheetal Tigadoli 	 * Set host side to match.
331bffde63dSSheetal Tigadoli 	 */
332bffde63dSSheetal Tigadoli 	chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
333bffde63dSSheetal Tigadoli 				 SD_BUS_DATA_WIDTH_1BIT);
334bffde63dSSheetal Tigadoli 
335bffde63dSSheetal Tigadoli #ifdef USE_EMMC_FIP_TOC_CACHE
336bffde63dSSheetal Tigadoli 	cached_partition_block = 0;
337bffde63dSSheetal Tigadoli #endif
338bffde63dSSheetal Tigadoli 	handle->device->ctrl.present = 0; /* init card present to be no card */
339bffde63dSSheetal Tigadoli 
340bffde63dSSheetal Tigadoli 	init_mmc_card(handle);
341bffde63dSSheetal Tigadoli 
342bffde63dSSheetal Tigadoli 	handle->device->ctrl.present = 1; /* card is detected */
343bffde63dSSheetal Tigadoli 
344bffde63dSSheetal Tigadoli 	/* switch the data width back */
345bffde63dSSheetal Tigadoli 	if (handle->card->type != SD_CARD_MMC)
346bffde63dSSheetal Tigadoli 		return SD_FAIL;
347bffde63dSSheetal Tigadoli 
348bffde63dSSheetal Tigadoli 	/*
349bffde63dSSheetal Tigadoli 	 * Dynamically set Data Width to highest supported value.
350bffde63dSSheetal Tigadoli 	 * Try different data width settings (highest to lowest).
351bffde63dSSheetal Tigadoli 	 * Verify each setting by reading EXT_CSD and comparing
352bffde63dSSheetal Tigadoli 	 * against the EXT_CSD contents previously read in call to
353bffde63dSSheetal Tigadoli 	 * init_mmc_card() earlier. Stop at first verified data width
354bffde63dSSheetal Tigadoli 	 * setting.
355bffde63dSSheetal Tigadoli 	 */
356bffde63dSSheetal Tigadoli 	{
357bffde63dSSheetal Tigadoli #define EXT_CSD_PROPERTIES_SECTION_START_INDEX	192
358bffde63dSSheetal Tigadoli #define EXT_CSD_PROPERTIES_SECTION_END_INDEX	511
359bffde63dSSheetal Tigadoli 		uint8_t buffer[EXT_CSD_SIZE];
360bffde63dSSheetal Tigadoli #ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT
361bffde63dSSheetal Tigadoli 		/* Try 8 Bit Data Width */
362bffde63dSSheetal Tigadoli 		chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
363bffde63dSSheetal Tigadoli 					 SD_BUS_DATA_WIDTH_8BIT);
364bffde63dSSheetal Tigadoli 		if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_8BIT)) &&
365bffde63dSSheetal Tigadoli 		    (!mmc_cmd8(handle, buffer)) &&
366bffde63dSSheetal Tigadoli 		    (!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX],
367bffde63dSSheetal Tigadoli 			     &(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]),
368bffde63dSSheetal Tigadoli 			     EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1)))
369bffde63dSSheetal Tigadoli 
370bffde63dSSheetal Tigadoli 			return SD_OK;
371bffde63dSSheetal Tigadoli #endif
372bffde63dSSheetal Tigadoli 		/* Fall back to 4 Bit Data Width */
373bffde63dSSheetal Tigadoli 		chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
374bffde63dSSheetal Tigadoli 					 SD_BUS_DATA_WIDTH_4BIT);
375bffde63dSSheetal Tigadoli 		if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_4BIT)) &&
376bffde63dSSheetal Tigadoli 		    (!mmc_cmd8(handle, buffer)) &&
377bffde63dSSheetal Tigadoli 		    (!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX],
378bffde63dSSheetal Tigadoli 			     &(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]),
379bffde63dSSheetal Tigadoli 			     EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1)))
380bffde63dSSheetal Tigadoli 
381bffde63dSSheetal Tigadoli 			return SD_OK;
382bffde63dSSheetal Tigadoli 
383bffde63dSSheetal Tigadoli 		/* Fall back to 1 Bit Data Width */
384bffde63dSSheetal Tigadoli 		chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
385bffde63dSSheetal Tigadoli 					 SD_BUS_DATA_WIDTH_1BIT);
386bffde63dSSheetal Tigadoli 		/* Just use 1 Bit Data Width then. */
387bffde63dSSheetal Tigadoli 		if (!set_card_data_width(handle, SD_BUS_DATA_WIDTH_1BIT))
388bffde63dSSheetal Tigadoli 			return SD_OK;
389bffde63dSSheetal Tigadoli 
390bffde63dSSheetal Tigadoli 	}
391bffde63dSSheetal Tigadoli 	return SD_CARD_INIT_ERROR;
392bffde63dSSheetal Tigadoli }
393bffde63dSSheetal Tigadoli 
394bffde63dSSheetal Tigadoli 
395bffde63dSSheetal Tigadoli /*
396*1b491eeaSElyes Haouas  * The function handles MMC/CEATA card initialization.
397bffde63dSSheetal Tigadoli  */
init_mmc_card(struct sd_handle * handle)398bffde63dSSheetal Tigadoli int init_mmc_card(struct sd_handle *handle)
399bffde63dSSheetal Tigadoli {
400bffde63dSSheetal Tigadoli 	uint32_t ocr = 0, newOcr, rc, limit = 0;
401bffde63dSSheetal Tigadoli 	uint32_t cmd1_option = 0x40300000;
402bffde63dSSheetal Tigadoli 	uint32_t sec_count;
403bffde63dSSheetal Tigadoli 
404bffde63dSSheetal Tigadoli 	handle->card->type = SD_CARD_MMC;
405bffde63dSSheetal Tigadoli 
406bffde63dSSheetal Tigadoli 	do {
407bffde63dSSheetal Tigadoli 		SD_US_DELAY(1000);
408bffde63dSSheetal Tigadoli 		newOcr = 0;
409bffde63dSSheetal Tigadoli 		ocr = 0;
410bffde63dSSheetal Tigadoli 		rc = sd_cmd1(handle, cmd1_option, &newOcr);
411bffde63dSSheetal Tigadoli 		limit++;
412bffde63dSSheetal Tigadoli 
413bffde63dSSheetal Tigadoli 		if (rc == SD_OK)
414bffde63dSSheetal Tigadoli 			ocr = newOcr;
415bffde63dSSheetal Tigadoli 
416bffde63dSSheetal Tigadoli 	} while (((ocr & SD_CARD_BUSY) == 0) && (limit < SD_CARD_RETRY_LIMIT));
417bffde63dSSheetal Tigadoli 
418bffde63dSSheetal Tigadoli 	if (limit >= SD_CARD_RETRY_LIMIT) {
419bffde63dSSheetal Tigadoli 		handle->card->type = SD_CARD_UNKNOWN;
420bffde63dSSheetal Tigadoli 		EMMC_TRACE("CMD1 Timeout: Device is not ready\n");
421bffde63dSSheetal Tigadoli 		return SD_CARD_UNKNOWN;
422bffde63dSSheetal Tigadoli 	}
423bffde63dSSheetal Tigadoli 
424bffde63dSSheetal Tigadoli 	/* Save the ocr register */
425bffde63dSSheetal Tigadoli 	handle->device->ctrl.ocr = ocr;
426bffde63dSSheetal Tigadoli 
427bffde63dSSheetal Tigadoli 	/* Ready State */
428bffde63dSSheetal Tigadoli 	rc = sd_cmd2(handle);
429bffde63dSSheetal Tigadoli 	if (rc != SD_OK) {
430bffde63dSSheetal Tigadoli 		handle->card->type = SD_CARD_UNKNOWN;
431bffde63dSSheetal Tigadoli 		return SD_CARD_UNKNOWN;
432bffde63dSSheetal Tigadoli 	}
433bffde63dSSheetal Tigadoli 
434bffde63dSSheetal Tigadoli 	rc = sd_cmd3(handle);
435bffde63dSSheetal Tigadoli 	if (rc != SD_OK) {
436bffde63dSSheetal Tigadoli 		handle->card->type = SD_CARD_UNKNOWN;
437bffde63dSSheetal Tigadoli 		return SD_CARD_UNKNOWN;
438bffde63dSSheetal Tigadoli 	}
439bffde63dSSheetal Tigadoli 	/* read CSD */
440bffde63dSSheetal Tigadoli 	rc = sd_cmd9(handle, &emmc_global_vars_ptr->cardData);
441bffde63dSSheetal Tigadoli 	if (rc != SD_OK) {
442bffde63dSSheetal Tigadoli 		handle->card->type = SD_CARD_UNKNOWN;
443bffde63dSSheetal Tigadoli 		return SD_CARD_UNKNOWN;
444bffde63dSSheetal Tigadoli 	}
445bffde63dSSheetal Tigadoli 
446bffde63dSSheetal Tigadoli 	/* Increase clock frequency according to what the card advertises */
447bffde63dSSheetal Tigadoli 	EMMC_TRACE("From CSD...  cardData.csd.mmc.speed = 0x%X\n",
448bffde63dSSheetal Tigadoli 		   emmc_global_vars_ptr->cardData.csd.mmc.speed);
449bffde63dSSheetal Tigadoli 	process_csd_mmc_speed(handle,
450bffde63dSSheetal Tigadoli 			      emmc_global_vars_ptr->cardData.csd.mmc.speed);
451bffde63dSSheetal Tigadoli 
452bffde63dSSheetal Tigadoli 	/* goto transfer mode */
453bffde63dSSheetal Tigadoli 	rc = sd_cmd7(handle, handle->device->ctrl.rca);
454bffde63dSSheetal Tigadoli 	if (rc != SD_OK) {
455bffde63dSSheetal Tigadoli 		handle->card->type = SD_CARD_UNKNOWN;
456bffde63dSSheetal Tigadoli 		return SD_CARD_UNKNOWN;
457bffde63dSSheetal Tigadoli 	}
458bffde63dSSheetal Tigadoli 
459bffde63dSSheetal Tigadoli 	rc = mmc_cmd8(handle, emmc_global_buf_ptr->u.Ext_CSD_storage);
460bffde63dSSheetal Tigadoli 	if (rc == SD_OK) {
461bffde63dSSheetal Tigadoli 		/* calcul real capacity */
462bffde63dSSheetal Tigadoli 		sec_count = emmc_global_buf_ptr->u.Ext_CSD_storage[212] |
463bffde63dSSheetal Tigadoli 			    emmc_global_buf_ptr->u.Ext_CSD_storage[213] << 8 |
464bffde63dSSheetal Tigadoli 			    emmc_global_buf_ptr->u.Ext_CSD_storage[214] << 16 |
465bffde63dSSheetal Tigadoli 			    emmc_global_buf_ptr->u.Ext_CSD_storage[215] << 24;
466bffde63dSSheetal Tigadoli 
467bffde63dSSheetal Tigadoli 		EMMC_TRACE("Device density = %ldMBytes\n",
468bffde63dSSheetal Tigadoli 			   handle->card->size / (1024 * 1024));
469bffde63dSSheetal Tigadoli 
470bffde63dSSheetal Tigadoli 		if (sec_count > 0) {
471bffde63dSSheetal Tigadoli 			handle->card->size = (uint64_t)sec_count * 512;
472bffde63dSSheetal Tigadoli 
473bffde63dSSheetal Tigadoli 			EMMC_TRACE("Updated Device density = %ldMBytes\n",
474bffde63dSSheetal Tigadoli 				   handle->card->size / (1024 * 1024));
475bffde63dSSheetal Tigadoli 		}
476bffde63dSSheetal Tigadoli 
477bffde63dSSheetal Tigadoli 		if (sec_count > (2u * 1024 * 1024 * 1024) / 512) {
478bffde63dSSheetal Tigadoli 			handle->device->ctrl.ocr |= SD_CARD_HIGH_CAPACITY;
479bffde63dSSheetal Tigadoli 			handle->device->cfg.blockSize = 512;
480bffde63dSSheetal Tigadoli 		}
481bffde63dSSheetal Tigadoli 
4829f58bfbbSBoyan Karatotev 		if (handle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
483bffde63dSSheetal Tigadoli 			EMMC_TRACE("Sector addressing\n");
4849f58bfbbSBoyan Karatotev 		} else {
485bffde63dSSheetal Tigadoli 			EMMC_TRACE("Byte addressing\n");
4869f58bfbbSBoyan Karatotev 		}
487bffde63dSSheetal Tigadoli 
488bffde63dSSheetal Tigadoli 		EMMC_TRACE("Ext_CSD_storage[162]: 0x%02X  Ext_CSD_storage[179]: 0x%02X\n",
489bffde63dSSheetal Tigadoli 			   emmc_global_buf_ptr->u.Ext_CSD_storage[162],
490bffde63dSSheetal Tigadoli 			   emmc_global_buf_ptr->u.Ext_CSD_storage[179]);
491bffde63dSSheetal Tigadoli 	}
492bffde63dSSheetal Tigadoli 
493bffde63dSSheetal Tigadoli 	return handle->card->type;
494bffde63dSSheetal Tigadoli }
495bffde63dSSheetal Tigadoli 
496bffde63dSSheetal Tigadoli 
497bffde63dSSheetal Tigadoli /*
498bffde63dSSheetal Tigadoli  * The function send reset command to the card.
499bffde63dSSheetal Tigadoli  * The card will be in ready status after the reset.
500bffde63dSSheetal Tigadoli  */
reset_card(struct sd_handle * handle)501bffde63dSSheetal Tigadoli int reset_card(struct sd_handle *handle)
502bffde63dSSheetal Tigadoli {
503bffde63dSSheetal Tigadoli 	int res = SD_OK;
504bffde63dSSheetal Tigadoli 
505bffde63dSSheetal Tigadoli 	/* on reset, card's RCA should return to 0 */
506bffde63dSSheetal Tigadoli 	handle->device->ctrl.rca = 0;
507bffde63dSSheetal Tigadoli 
508bffde63dSSheetal Tigadoli 	res = sd_cmd0(handle);
509bffde63dSSheetal Tigadoli 
510bffde63dSSheetal Tigadoli 	if (res != SD_OK)
511bffde63dSSheetal Tigadoli 		return SD_RESET_ERROR;
512bffde63dSSheetal Tigadoli 
513bffde63dSSheetal Tigadoli 	return res;
514bffde63dSSheetal Tigadoli }
515bffde63dSSheetal Tigadoli 
516bffde63dSSheetal Tigadoli 
517bffde63dSSheetal Tigadoli /*
518bffde63dSSheetal Tigadoli  * The function sends command to the card and starts
519bffde63dSSheetal Tigadoli  * data transmission.
520bffde63dSSheetal Tigadoli  */
xfer_data(struct sd_handle * handle,uint32_t mode,uint32_t addr,uint32_t length,uint8_t * base)521bffde63dSSheetal Tigadoli static int xfer_data(struct sd_handle *handle,
522bffde63dSSheetal Tigadoli 		     uint32_t mode,
523bffde63dSSheetal Tigadoli 		     uint32_t addr, uint32_t length, uint8_t *base)
524bffde63dSSheetal Tigadoli {
525bffde63dSSheetal Tigadoli 	int rc = SD_OK;
526bffde63dSSheetal Tigadoli 
5274ce3e99aSScott Branden 	VERBOSE("XFER: dest: 0x%" PRIx64 ", addr: 0x%x, size: 0x%x bytes\n",
528bffde63dSSheetal Tigadoli 		(uint64_t)base, addr, length);
529bffde63dSSheetal Tigadoli 
530bffde63dSSheetal Tigadoli 	if ((length / handle->device->cfg.blockSize) > 1) {
531bffde63dSSheetal Tigadoli 		if (mode == SD_OP_READ) {
532bffde63dSSheetal Tigadoli 			inv_dcache_range((uintptr_t)base, (uint64_t)length);
533bffde63dSSheetal Tigadoli 			rc = sd_cmd18(handle, addr, length, base);
534bffde63dSSheetal Tigadoli 		} else {
535bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
536bffde63dSSheetal Tigadoli 			flush_dcache_range((uintptr_t)base, (uint64_t)length);
537bffde63dSSheetal Tigadoli 			rc = sd_cmd25(handle, addr, length, base);
538bffde63dSSheetal Tigadoli #else
539bffde63dSSheetal Tigadoli 			rc = SD_DATA_XFER_ERROR;
540bffde63dSSheetal Tigadoli #endif
541bffde63dSSheetal Tigadoli 		}
542bffde63dSSheetal Tigadoli 	} else {
543bffde63dSSheetal Tigadoli 		if (mode == SD_OP_READ) {
544bffde63dSSheetal Tigadoli 			inv_dcache_range((uintptr_t)base, (uint64_t)length);
545bffde63dSSheetal Tigadoli 			rc = sd_cmd17(handle, addr,
546bffde63dSSheetal Tigadoli 				      handle->device->cfg.blockSize, base);
547bffde63dSSheetal Tigadoli 		} else {
548bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
549bffde63dSSheetal Tigadoli 			flush_dcache_range((uintptr_t)base, (uint64_t)length);
550bffde63dSSheetal Tigadoli 			rc = sd_cmd24(handle, addr,
551bffde63dSSheetal Tigadoli 				      handle->device->cfg.blockSize, base);
552bffde63dSSheetal Tigadoli #else
553bffde63dSSheetal Tigadoli 			rc = SD_DATA_XFER_ERROR;
554bffde63dSSheetal Tigadoli #endif
555bffde63dSSheetal Tigadoli 		}
556bffde63dSSheetal Tigadoli 	}
557bffde63dSSheetal Tigadoli 
558bffde63dSSheetal Tigadoli 	if (rc != SD_OK)
559bffde63dSSheetal Tigadoli 		return SD_DATA_XFER_ERROR;
560bffde63dSSheetal Tigadoli 
561bffde63dSSheetal Tigadoli 	return SD_OK;
562bffde63dSSheetal Tigadoli }
563bffde63dSSheetal Tigadoli 
564bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
erase_card(struct sd_handle * handle,uint32_t addr,uint32_t blocks)565bffde63dSSheetal Tigadoli int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks)
566bffde63dSSheetal Tigadoli {
567bffde63dSSheetal Tigadoli 	uint32_t end_addr;
568bffde63dSSheetal Tigadoli 
569bffde63dSSheetal Tigadoli 	INFO("ERASE: addr: 0x%x, num of sectors: 0x%x\n", addr, blocks);
570bffde63dSSheetal Tigadoli 
571bffde63dSSheetal Tigadoli 	if (sd_cmd35(handle, addr) != SD_OK)
572bffde63dSSheetal Tigadoli 		return SD_FAIL;
573bffde63dSSheetal Tigadoli 
574bffde63dSSheetal Tigadoli 	end_addr = addr + blocks - 1;
575bffde63dSSheetal Tigadoli 	if (sd_cmd36(handle, end_addr) != SD_OK)
576bffde63dSSheetal Tigadoli 		return SD_FAIL;
577bffde63dSSheetal Tigadoli 
578bffde63dSSheetal Tigadoli 	if (sd_cmd38(handle) != SD_OK)
579bffde63dSSheetal Tigadoli 		return SD_FAIL;
580bffde63dSSheetal Tigadoli 
581bffde63dSSheetal Tigadoli 	return SD_OK;
582bffde63dSSheetal Tigadoli }
583bffde63dSSheetal Tigadoli #endif
584bffde63dSSheetal Tigadoli 
585bffde63dSSheetal Tigadoli /*
586bffde63dSSheetal Tigadoli  * The function reads block data from a card.
587bffde63dSSheetal Tigadoli  */
588bffde63dSSheetal Tigadoli #ifdef USE_EMMC_FIP_TOC_CACHE
read_block(struct sd_handle * handle,uint8_t * dst,uint32_t addr,uint32_t len)589bffde63dSSheetal Tigadoli int read_block(struct sd_handle *handle,
590bffde63dSSheetal Tigadoli 	       uint8_t *dst, uint32_t addr, uint32_t len)
591bffde63dSSheetal Tigadoli {
592bffde63dSSheetal Tigadoli 	int rel = SD_OK;
593bffde63dSSheetal Tigadoli 
594bffde63dSSheetal Tigadoli 	/*
595bffde63dSSheetal Tigadoli 	 * Avoid doing repeated reads of the partition block
596bffde63dSSheetal Tigadoli 	 * by caching.
597bffde63dSSheetal Tigadoli 	 */
598bffde63dSSheetal Tigadoli 	if (cached_partition_block &&
599bffde63dSSheetal Tigadoli 	    addr == PARTITION_BLOCK_ADDR &&
600bffde63dSSheetal Tigadoli 	    len == CACHE_SIZE) {
601bffde63dSSheetal Tigadoli 		memcpy(dst, cached_block, len);
602bffde63dSSheetal Tigadoli 	} else {
603bffde63dSSheetal Tigadoli 		rel = xfer_data(handle, SD_OP_READ, addr, len, dst);
604bffde63dSSheetal Tigadoli 
605bffde63dSSheetal Tigadoli 		if (len == CACHE_SIZE && addr == PARTITION_BLOCK_ADDR) {
606bffde63dSSheetal Tigadoli 			cached_partition_block = 1;
607bffde63dSSheetal Tigadoli 			memcpy(cached_block, dst, len);
608bffde63dSSheetal Tigadoli 		}
609bffde63dSSheetal Tigadoli 	}
610bffde63dSSheetal Tigadoli 
611bffde63dSSheetal Tigadoli 	return rel;
612bffde63dSSheetal Tigadoli }
613bffde63dSSheetal Tigadoli #else
read_block(struct sd_handle * handle,uint8_t * dst,uint32_t addr,uint32_t len)614bffde63dSSheetal Tigadoli int read_block(struct sd_handle *handle,
615bffde63dSSheetal Tigadoli 	       uint8_t *dst, uint32_t addr, uint32_t len)
616bffde63dSSheetal Tigadoli {
617bffde63dSSheetal Tigadoli 	return xfer_data(handle, SD_OP_READ, addr, len, dst);
618bffde63dSSheetal Tigadoli }
619bffde63dSSheetal Tigadoli #endif
620bffde63dSSheetal Tigadoli 
621bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
622bffde63dSSheetal Tigadoli 
623bffde63dSSheetal Tigadoli /*
624bffde63dSSheetal Tigadoli  * The function writes block data to a card.
625bffde63dSSheetal Tigadoli  */
write_block(struct sd_handle * handle,uint8_t * src,uint32_t addr,uint32_t len)626bffde63dSSheetal Tigadoli int write_block(struct sd_handle *handle,
627bffde63dSSheetal Tigadoli 		uint8_t *src, uint32_t addr, uint32_t len)
628bffde63dSSheetal Tigadoli {
629bffde63dSSheetal Tigadoli 	int rel = SD_OK;
630bffde63dSSheetal Tigadoli 
631bffde63dSSheetal Tigadoli 	/*
632bffde63dSSheetal Tigadoli 	 * Current HC has problem to get response of cmd16 after cmd12,
633bffde63dSSheetal Tigadoli 	 * the delay is necessary to sure the next cmd16 will not be timed out.
634bffde63dSSheetal Tigadoli 	 * The delay has to be at least 4 ms.
635bffde63dSSheetal Tigadoli 	 * The code removed cmd16 and use cmd13 to get card status before
636bffde63dSSheetal Tigadoli 	 * sending cmd18 or cmd25 to make sure the card is ready and thus
637bffde63dSSheetal Tigadoli 	 * no need to have delay here.
638bffde63dSSheetal Tigadoli 	 */
639bffde63dSSheetal Tigadoli 
640bffde63dSSheetal Tigadoli 	rel = xfer_data(handle, SD_OP_WRITE, addr, len, src);
641bffde63dSSheetal Tigadoli 
642bffde63dSSheetal Tigadoli 	EMMC_TRACE("wr_blk addr:0x%08X src:0x%08X len:0x%08X result:%d\n",
643bffde63dSSheetal Tigadoli 		   addr, src, len, rel);
644bffde63dSSheetal Tigadoli 
645bffde63dSSheetal Tigadoli 	return rel;
646bffde63dSSheetal Tigadoli }
647bffde63dSSheetal Tigadoli 
648bffde63dSSheetal Tigadoli 
649bffde63dSSheetal Tigadoli /*
650bffde63dSSheetal Tigadoli  * The function is called to write one block data directly to
651bffde63dSSheetal Tigadoli  * a card's data buffer.
652bffde63dSSheetal Tigadoli  * it is used in Non-DMA mode for card data transmission.
653bffde63dSSheetal Tigadoli  */
write_buffer(struct sd_handle * handle,uint32_t length,uint8_t * data)654bffde63dSSheetal Tigadoli int write_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data)
655bffde63dSSheetal Tigadoli {
656bffde63dSSheetal Tigadoli 	uint32_t rem, blockSize, event;
657bffde63dSSheetal Tigadoli 	uint8_t *pData = data;
658bffde63dSSheetal Tigadoli 
659bffde63dSSheetal Tigadoli 	blockSize = handle->device->cfg.blockSize;
660bffde63dSSheetal Tigadoli 	rem = length;
661bffde63dSSheetal Tigadoli 
662bffde63dSSheetal Tigadoli 	if (rem == 0)
663bffde63dSSheetal Tigadoli 		return SD_OK;
664bffde63dSSheetal Tigadoli 
665bffde63dSSheetal Tigadoli 	while (rem > 0) {
666bffde63dSSheetal Tigadoli 
667bffde63dSSheetal Tigadoli 		event = wait_for_event(handle,
668bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_INTR_BWRDY_MASK |
669bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS,
670bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
671bffde63dSSheetal Tigadoli 
672bffde63dSSheetal Tigadoli 		if (handle->device->ctrl.cmdStatus) {
673bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
674bffde63dSSheetal Tigadoli 			return SD_WRITE_ERROR;
675bffde63dSSheetal Tigadoli 		}
676bffde63dSSheetal Tigadoli 
677bffde63dSSheetal Tigadoli 		if (rem >= blockSize)
678bffde63dSSheetal Tigadoli 			chal_sd_write_buffer((CHAL_HANDLE *) handle->device,
679bffde63dSSheetal Tigadoli 					     blockSize, pData);
680bffde63dSSheetal Tigadoli 		else
681bffde63dSSheetal Tigadoli 			chal_sd_write_buffer((CHAL_HANDLE *) handle->device,
682bffde63dSSheetal Tigadoli 					     rem, pData);
683bffde63dSSheetal Tigadoli 
684bffde63dSSheetal Tigadoli 		if (rem > blockSize) {
685bffde63dSSheetal Tigadoli 			rem -= blockSize;
686bffde63dSSheetal Tigadoli 			pData += blockSize;
687bffde63dSSheetal Tigadoli 		} else {
688bffde63dSSheetal Tigadoli 			pData += rem;
689bffde63dSSheetal Tigadoli 			rem = 0;
690bffde63dSSheetal Tigadoli 		}
691bffde63dSSheetal Tigadoli 	}
692bffde63dSSheetal Tigadoli 
693bffde63dSSheetal Tigadoli 	if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) !=
694bffde63dSSheetal Tigadoli 	    SD4_EMMC_TOP_INTR_TXDONE_MASK) {
695bffde63dSSheetal Tigadoli 		event = wait_for_event(handle,
696bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_INTR_TXDONE_MASK |
697bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS,
698bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
699bffde63dSSheetal Tigadoli 
700bffde63dSSheetal Tigadoli 		if (handle->device->ctrl.cmdStatus != SD_OK) {
701bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
702bffde63dSSheetal Tigadoli 			return SD_WRITE_ERROR;
703bffde63dSSheetal Tigadoli 		}
704bffde63dSSheetal Tigadoli 	} else {
705bffde63dSSheetal Tigadoli 		handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK;
706bffde63dSSheetal Tigadoli 	}
707bffde63dSSheetal Tigadoli 
708bffde63dSSheetal Tigadoli 	return SD_OK;
709bffde63dSSheetal Tigadoli }
710bffde63dSSheetal Tigadoli #endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
711bffde63dSSheetal Tigadoli 
712bffde63dSSheetal Tigadoli 
713bffde63dSSheetal Tigadoli /*
714bffde63dSSheetal Tigadoli  * The function is called to read maximal one block data
715bffde63dSSheetal Tigadoli  * directly from a card
716bffde63dSSheetal Tigadoli  * It is used in Non-DMA mode for card data transmission.
717bffde63dSSheetal Tigadoli  */
read_buffer(struct sd_handle * handle,uint32_t length,uint8_t * data)718bffde63dSSheetal Tigadoli int read_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data)
719bffde63dSSheetal Tigadoli {
720bffde63dSSheetal Tigadoli 	uint32_t rem, blockSize, event = 0;
721bffde63dSSheetal Tigadoli 	uint8_t *pData = data;
722bffde63dSSheetal Tigadoli 
723bffde63dSSheetal Tigadoli 	blockSize = handle->device->cfg.blockSize;
724bffde63dSSheetal Tigadoli 	rem = length;
725bffde63dSSheetal Tigadoli 
726bffde63dSSheetal Tigadoli 	if (rem == 0)
727bffde63dSSheetal Tigadoli 		return SD_OK;
728bffde63dSSheetal Tigadoli 
729bffde63dSSheetal Tigadoli 	while (rem > 0) {
730bffde63dSSheetal Tigadoli 		event = wait_for_event(handle,
731bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_INTR_BRRDY_MASK |
732bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS,
733bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
734bffde63dSSheetal Tigadoli 
735bffde63dSSheetal Tigadoli 		if (handle->device->ctrl.cmdStatus) {
736bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
737bffde63dSSheetal Tigadoli 			return SD_READ_ERROR;
738bffde63dSSheetal Tigadoli 		}
739bffde63dSSheetal Tigadoli 
740bffde63dSSheetal Tigadoli 		if (rem >= blockSize)
741bffde63dSSheetal Tigadoli 			chal_sd_read_buffer((CHAL_HANDLE *) handle->device,
742bffde63dSSheetal Tigadoli 					    blockSize, pData);
743bffde63dSSheetal Tigadoli 		else
744bffde63dSSheetal Tigadoli 			chal_sd_read_buffer((CHAL_HANDLE *) handle->device, rem,
745bffde63dSSheetal Tigadoli 					    pData);
746bffde63dSSheetal Tigadoli 
747bffde63dSSheetal Tigadoli 		if (rem > blockSize) {
748bffde63dSSheetal Tigadoli 			rem -= blockSize;
749bffde63dSSheetal Tigadoli 			pData += blockSize;
750bffde63dSSheetal Tigadoli 		} else {
751bffde63dSSheetal Tigadoli 			pData += rem;
752bffde63dSSheetal Tigadoli 			rem = 0;
753bffde63dSSheetal Tigadoli 		}
754bffde63dSSheetal Tigadoli 	}
755bffde63dSSheetal Tigadoli 
756bffde63dSSheetal Tigadoli 	/* In case, there are extra data in the SD FIFO, just dump them. */
757bffde63dSSheetal Tigadoli 	chal_sd_dump_fifo((CHAL_HANDLE *) handle->device);
758bffde63dSSheetal Tigadoli 
759bffde63dSSheetal Tigadoli 	if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) !=
760bffde63dSSheetal Tigadoli 	    SD4_EMMC_TOP_INTR_TXDONE_MASK) {
761bffde63dSSheetal Tigadoli 		event = wait_for_event(handle, SD4_EMMC_TOP_INTR_TXDONE_MASK,
762bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
763bffde63dSSheetal Tigadoli 
764bffde63dSSheetal Tigadoli 		if (handle->device->ctrl.cmdStatus) {
765bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
766bffde63dSSheetal Tigadoli 			return SD_READ_ERROR;
767bffde63dSSheetal Tigadoli 		}
768bffde63dSSheetal Tigadoli 	} else {
769bffde63dSSheetal Tigadoli 		handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK;
770bffde63dSSheetal Tigadoli 	}
771bffde63dSSheetal Tigadoli 
772bffde63dSSheetal Tigadoli 	return SD_OK;
773bffde63dSSheetal Tigadoli }
774bffde63dSSheetal Tigadoli 
775bffde63dSSheetal Tigadoli 
776bffde63dSSheetal Tigadoli /*
777bffde63dSSheetal Tigadoli  * Error handling routine.
778bffde63dSSheetal Tigadoli  * The function just reset the DAT
779bffde63dSSheetal Tigadoli  * and CMD line if an error occures during data transmission.
780bffde63dSSheetal Tigadoli  */
check_error(struct sd_handle * handle,uint32_t ints)781bffde63dSSheetal Tigadoli int check_error(struct sd_handle *handle, uint32_t ints)
782bffde63dSSheetal Tigadoli {
783bffde63dSSheetal Tigadoli 	uint32_t rel;
784bffde63dSSheetal Tigadoli 
785bffde63dSSheetal Tigadoli 	chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
786bffde63dSSheetal Tigadoli 			       SD_ERR_INTERRUPTS, 0);
787bffde63dSSheetal Tigadoli 
788bffde63dSSheetal Tigadoli 	if (ints & SD4_EMMC_TOP_INTR_CMDERROR_MASK) {
789bffde63dSSheetal Tigadoli 
790bffde63dSSheetal Tigadoli 		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
791bffde63dSSheetal Tigadoli 				   SD4_EMMC_TOP_CTRL1_CMDRST_MASK);
792bffde63dSSheetal Tigadoli 		rel = abort_err(handle);
793bffde63dSSheetal Tigadoli 
794bffde63dSSheetal Tigadoli 		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
795bffde63dSSheetal Tigadoli 				   SD4_EMMC_TOP_CTRL1_DATRST_MASK);
796bffde63dSSheetal Tigadoli 		chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
797bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS, 1);
798bffde63dSSheetal Tigadoli 
799bffde63dSSheetal Tigadoli 		return (rel == SD_ERROR_NON_RECOVERABLE) ?
800bffde63dSSheetal Tigadoli 				SD_ERROR_NON_RECOVERABLE : SD_ERROR_RECOVERABLE;
801bffde63dSSheetal Tigadoli 	} else {
802bffde63dSSheetal Tigadoli 		rel = err_recovery(handle, ints);
803bffde63dSSheetal Tigadoli 	}
804bffde63dSSheetal Tigadoli 
805bffde63dSSheetal Tigadoli 	chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
806bffde63dSSheetal Tigadoli 			       SD_ERR_INTERRUPTS, 1);
807bffde63dSSheetal Tigadoli 
808bffde63dSSheetal Tigadoli 	return rel;
809bffde63dSSheetal Tigadoli }
810bffde63dSSheetal Tigadoli 
811bffde63dSSheetal Tigadoli 
812bffde63dSSheetal Tigadoli /*
813bffde63dSSheetal Tigadoli  * Error recovery routine.
814bffde63dSSheetal Tigadoli  * Try to recover from the error.
815bffde63dSSheetal Tigadoli  */
err_recovery(struct sd_handle * handle,uint32_t errors)816bffde63dSSheetal Tigadoli static int err_recovery(struct sd_handle *handle, uint32_t errors)
817bffde63dSSheetal Tigadoli {
818bffde63dSSheetal Tigadoli 	uint32_t rel = 0;
819bffde63dSSheetal Tigadoli 
820bffde63dSSheetal Tigadoli 	/*
821bffde63dSSheetal Tigadoli 	 * In case of timeout error, the cmd line and data line maybe
822bffde63dSSheetal Tigadoli 	 * still active or stuck at atcitve so it is needed to reset
823bffde63dSSheetal Tigadoli 	 * either data line or cmd line to make sure a new cmd can be sent.
824bffde63dSSheetal Tigadoli 	 */
825bffde63dSSheetal Tigadoli 
826bffde63dSSheetal Tigadoli 	if (errors & SD_CMD_ERROR_INT)
827bffde63dSSheetal Tigadoli 		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
828bffde63dSSheetal Tigadoli 				   SD4_EMMC_TOP_CTRL1_CMDRST_MASK);
829bffde63dSSheetal Tigadoli 
830bffde63dSSheetal Tigadoli 	if (errors & SD_DAT_ERROR_INT)
831bffde63dSSheetal Tigadoli 		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
832bffde63dSSheetal Tigadoli 				   SD4_EMMC_TOP_CTRL1_DATRST_MASK);
833bffde63dSSheetal Tigadoli 
834bffde63dSSheetal Tigadoli 	/* Abort transaction by sending out stop command */
835bffde63dSSheetal Tigadoli 	if ((handle->device->ctrl.cmdIndex == 18) ||
836bffde63dSSheetal Tigadoli 	    (handle->device->ctrl.cmdIndex == 25))
837bffde63dSSheetal Tigadoli 		rel = abort_err(handle);
838bffde63dSSheetal Tigadoli 
839bffde63dSSheetal Tigadoli 	return rel;
840bffde63dSSheetal Tigadoli }
841bffde63dSSheetal Tigadoli 
842bffde63dSSheetal Tigadoli 
843bffde63dSSheetal Tigadoli /*
844bffde63dSSheetal Tigadoli  * The function is called to read one block data directly from a card.
845bffde63dSSheetal Tigadoli  * It is used in Non-DMA mode for card data transmission.
846bffde63dSSheetal Tigadoli  */
process_cmd_response(struct sd_handle * handle,uint32_t cmdIndex,uint32_t rsp0,uint32_t rsp1,uint32_t rsp2,uint32_t rsp3,struct sd_resp * resp)847bffde63dSSheetal Tigadoli int process_cmd_response(struct sd_handle *handle,
848bffde63dSSheetal Tigadoli 			 uint32_t cmdIndex,
849bffde63dSSheetal Tigadoli 			 uint32_t rsp0,
850bffde63dSSheetal Tigadoli 			 uint32_t rsp1,
851bffde63dSSheetal Tigadoli 			 uint32_t rsp2, uint32_t rsp3, struct sd_resp *resp)
852bffde63dSSheetal Tigadoli {
853bffde63dSSheetal Tigadoli 	int result = SD_OK;
854bffde63dSSheetal Tigadoli 
855bffde63dSSheetal Tigadoli 	/* R6 */
856bffde63dSSheetal Tigadoli 	uint32_t rca = (rsp0 >> 16) & 0xffff;
857bffde63dSSheetal Tigadoli 	uint32_t cardStatus = rsp0;
858bffde63dSSheetal Tigadoli 
859bffde63dSSheetal Tigadoli 	/* R4 */
860bffde63dSSheetal Tigadoli 	uint32_t cBit = (rsp0 >> 31) & 0x1;
861bffde63dSSheetal Tigadoli 	uint32_t funcs = (rsp0 >> 28) & 0x7;
862bffde63dSSheetal Tigadoli 	uint32_t memPresent = (rsp0 >> 27) & 0x1;
863bffde63dSSheetal Tigadoli 
864bffde63dSSheetal Tigadoli 	resp->r1 = 0x3f;
865bffde63dSSheetal Tigadoli 	resp->cardStatus = cardStatus;
866bffde63dSSheetal Tigadoli 
867bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_IO_SEND_OP_COND) {
868bffde63dSSheetal Tigadoli 		resp->data.r4.cardReady = cBit;
869bffde63dSSheetal Tigadoli 		resp->data.r4.funcs = funcs;
870bffde63dSSheetal Tigadoli 		resp->data.r4.memPresent = memPresent;
871bffde63dSSheetal Tigadoli 		resp->data.r4.ocr = cardStatus;
872bffde63dSSheetal Tigadoli 	}
873bffde63dSSheetal Tigadoli 
874bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_MMC_SET_RCA) {
875bffde63dSSheetal Tigadoli 		resp->data.r6.rca = rca;
876bffde63dSSheetal Tigadoli 		resp->data.r6.cardStatus = cardStatus & 0xFFFF;
877bffde63dSSheetal Tigadoli 	}
878bffde63dSSheetal Tigadoli 
879bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_SELECT_DESELECT_CARD) {
880bffde63dSSheetal Tigadoli 		resp->data.r7.rca = rca;
881bffde63dSSheetal Tigadoli 	}
882bffde63dSSheetal Tigadoli 
883bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_IO_RW_DIRECT) {
884bffde63dSSheetal Tigadoli 		if (((rsp0 >> 16) & 0xffff) != 0)
885bffde63dSSheetal Tigadoli 			result = SD_CMD_ERR_INVALID_RESPONSE;
886bffde63dSSheetal Tigadoli 
887bffde63dSSheetal Tigadoli 		resp->data.r5.data = rsp0 & 0xff;
888bffde63dSSheetal Tigadoli 	}
889bffde63dSSheetal Tigadoli 
890bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_IO_RW_EXTENDED) {
891bffde63dSSheetal Tigadoli 		if (((rsp0 >> 16) & 0xffff) != 0)
892bffde63dSSheetal Tigadoli 			result = SD_CMD_ERR_INVALID_RESPONSE;
893bffde63dSSheetal Tigadoli 
894bffde63dSSheetal Tigadoli 		resp->data.r5.data = rsp0 & 0xff;
895bffde63dSSheetal Tigadoli 	}
896bffde63dSSheetal Tigadoli 
897bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_ACMD_SD_SEND_OP_COND ||
898bffde63dSSheetal Tigadoli 	    cmdIndex == SD_CMD_SEND_OPCOND)
899bffde63dSSheetal Tigadoli 		resp->data.r3.ocr = cardStatus;
900bffde63dSSheetal Tigadoli 
901bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_SEND_CSD ||
902bffde63dSSheetal Tigadoli 	    cmdIndex == SD_CMD_SEND_CID ||
903bffde63dSSheetal Tigadoli 	    cmdIndex == SD_CMD_ALL_SEND_CID) {
904bffde63dSSheetal Tigadoli 		resp->data.r2.rsp4 = rsp3;
905bffde63dSSheetal Tigadoli 		resp->data.r2.rsp3 = rsp2;
906bffde63dSSheetal Tigadoli 		resp->data.r2.rsp2 = rsp1;
907bffde63dSSheetal Tigadoli 		resp->data.r2.rsp1 = rsp0;
908bffde63dSSheetal Tigadoli 	}
909bffde63dSSheetal Tigadoli 
910bffde63dSSheetal Tigadoli 	if ((cmdIndex == SD_CMD_READ_EXT_CSD) &&
911bffde63dSSheetal Tigadoli 	    (handle->card->type == SD_CARD_SD)) {
912bffde63dSSheetal Tigadoli 		if ((resp->cardStatus & 0xAA) != 0xAA) {
913bffde63dSSheetal Tigadoli 			result = SD_CMD_ERR_INVALID_RESPONSE;
914bffde63dSSheetal Tigadoli 		}
915bffde63dSSheetal Tigadoli 	}
916bffde63dSSheetal Tigadoli 
917bffde63dSSheetal Tigadoli 	return result;
918bffde63dSSheetal Tigadoli }
919bffde63dSSheetal Tigadoli 
920bffde63dSSheetal Tigadoli 
921bffde63dSSheetal Tigadoli /*
922bffde63dSSheetal Tigadoli  * The function sets DMA buffer and data length, process
923bffde63dSSheetal Tigadoli  * block size and the number of blocks to be transferred.
924bffde63dSSheetal Tigadoli  * It returns the DMA buffer address.
925bffde63dSSheetal Tigadoli  * It copies dma data from user buffer to the DMA buffer
926bffde63dSSheetal Tigadoli  * if the operation is to write data to the SD card.
927bffde63dSSheetal Tigadoli  */
data_xfer_setup(struct sd_handle * handle,uint8_t * data,uint32_t length,int dir)928bffde63dSSheetal Tigadoli void data_xfer_setup(struct sd_handle *handle, uint8_t *data, uint32_t length,
929bffde63dSSheetal Tigadoli 		     int dir)
930bffde63dSSheetal Tigadoli {
931bffde63dSSheetal Tigadoli 	chal_sd_setup_xfer((CHAL_HANDLE *)handle->device, data, length, dir);
932bffde63dSSheetal Tigadoli }
933bffde63dSSheetal Tigadoli 
934bffde63dSSheetal Tigadoli 
935bffde63dSSheetal Tigadoli /*
936bffde63dSSheetal Tigadoli  * The function does soft reset the host SD controller. After
937bffde63dSSheetal Tigadoli  * the function call all host controller's register are reset
938bffde63dSSheetal Tigadoli  * to default vallue;
939bffde63dSSheetal Tigadoli  *
940bffde63dSSheetal Tigadoli  * Note    This function only resets the host controller it does not
941bffde63dSSheetal Tigadoli  *          reset the controller's handler.
942bffde63dSSheetal Tigadoli  */
reset_host_ctrl(struct sd_handle * handle)943bffde63dSSheetal Tigadoli int reset_host_ctrl(struct sd_handle *handle)
944bffde63dSSheetal Tigadoli {
945bffde63dSSheetal Tigadoli 	chal_sd_stop();
946bffde63dSSheetal Tigadoli 
947bffde63dSSheetal Tigadoli 	return SD_OK;
948bffde63dSSheetal Tigadoli }
949bffde63dSSheetal Tigadoli 
pstate_log(struct sd_handle * handle)950bffde63dSSheetal Tigadoli static void pstate_log(struct sd_handle *handle)
951bffde63dSSheetal Tigadoli {
952bffde63dSSheetal Tigadoli 	ERROR("PSTATE: 0x%x\n", mmio_read_32
953bffde63dSSheetal Tigadoli 		(handle->device->ctrl.sdRegBaseAddr +
954bffde63dSSheetal Tigadoli 			SD4_EMMC_TOP_PSTATE_SD4_OFFSET));
955bffde63dSSheetal Tigadoli 	ERROR("ERRSTAT: 0x%x\n", mmio_read_32
956bffde63dSSheetal Tigadoli 		(handle->device->ctrl.sdRegBaseAddr +
957bffde63dSSheetal Tigadoli 			SD4_EMMC_TOP_ERRSTAT_OFFSET));
958bffde63dSSheetal Tigadoli }
959bffde63dSSheetal Tigadoli 
960bffde63dSSheetal Tigadoli /*
961bffde63dSSheetal Tigadoli  * The function waits for one or a group of interrupts specified
962bffde63dSSheetal Tigadoli  * by mask. The function returns if any one the interrupt status
963bffde63dSSheetal Tigadoli  * is set. If interrupt mode is not enabled then it will poll
964bffde63dSSheetal Tigadoli  * the interrupt status register until a interrupt status is set
965bffde63dSSheetal Tigadoli  * an error interrupt happens. If interrupt mode is enabled then
966bffde63dSSheetal Tigadoli  * this function should be called after the interrupt
967bffde63dSSheetal Tigadoli  * is received by ISR routine.
968bffde63dSSheetal Tigadoli  */
wait_for_event(struct sd_handle * handle,uint32_t mask,uint32_t retry)969bffde63dSSheetal Tigadoli uint32_t wait_for_event(struct sd_handle *handle,
970bffde63dSSheetal Tigadoli 			uint32_t mask, uint32_t retry)
971bffde63dSSheetal Tigadoli {
972bffde63dSSheetal Tigadoli 	uint32_t regval, cmd12, time = 0;
973bffde63dSSheetal Tigadoli 
974bffde63dSSheetal Tigadoli 	handle->device->ctrl.cmdStatus = 0;	/* no error */
975bffde63dSSheetal Tigadoli 	EMMC_TRACE("%s %d mask:0x%x timeout:%d irq_status:0x%x\n",
976bffde63dSSheetal Tigadoli 		   __func__, __LINE__, mask, retry,
977bffde63dSSheetal Tigadoli 		   chal_sd_get_irq_status((CHAL_HANDLE *)handle->device));
978bffde63dSSheetal Tigadoli 
979bffde63dSSheetal Tigadoli 	/* Polling mode */
980bffde63dSSheetal Tigadoli 	do {
981bffde63dSSheetal Tigadoli 		regval = chal_sd_get_irq_status((CHAL_HANDLE *)handle->device);
982bffde63dSSheetal Tigadoli 
983bffde63dSSheetal Tigadoli 		if (regval & SD4_EMMC_TOP_INTR_DMAIRQ_MASK) {
984bffde63dSSheetal Tigadoli 			chal_sd_set_dma_addr((CHAL_HANDLE *)handle->device,
985bffde63dSSheetal Tigadoli 					(uintptr_t)
986bffde63dSSheetal Tigadoli 				chal_sd_get_dma_addr((CHAL_HANDLE *)
987bffde63dSSheetal Tigadoli 						handle->device));
988bffde63dSSheetal Tigadoli 			chal_sd_clear_irq((CHAL_HANDLE *)handle->device,
989bffde63dSSheetal Tigadoli 					  SD4_EMMC_TOP_INTR_DMAIRQ_MASK);
990bffde63dSSheetal Tigadoli 		}
991bffde63dSSheetal Tigadoli 
992bffde63dSSheetal Tigadoli 		if (time++ > retry) {
993bffde63dSSheetal Tigadoli 			ERROR("EMMC: No response (cmd%d) after %dus.\n",
994bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex,
995bffde63dSSheetal Tigadoli 			      time * EMMC_WFE_RETRY_DELAY_US);
996bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus = SD_CMD_MISSING;
997bffde63dSSheetal Tigadoli 			pstate_log(handle);
998bffde63dSSheetal Tigadoli 			ERROR("EMMC: INT[0x%x]\n", regval);
999bffde63dSSheetal Tigadoli 			break;
1000bffde63dSSheetal Tigadoli 		}
1001bffde63dSSheetal Tigadoli 
1002bffde63dSSheetal Tigadoli 		if (regval & SD4_EMMC_TOP_INTR_CTOERR_MASK) {
1003bffde63dSSheetal Tigadoli 			ERROR("EMMC: Cmd%d timeout INT[0x%x]\n",
1004bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex, regval);
1005bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus =
1006bffde63dSSheetal Tigadoli 			    SD4_EMMC_TOP_INTR_CTOERR_MASK;
1007bffde63dSSheetal Tigadoli 			pstate_log(handle);
1008bffde63dSSheetal Tigadoli 			break;
1009bffde63dSSheetal Tigadoli 		}
1010bffde63dSSheetal Tigadoli 		if (regval & SD_CMD_ERROR_FLAGS) {
1011bffde63dSSheetal Tigadoli 			ERROR("EMMC: Cmd%d error INT[0x%x]\n",
1012bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex, regval);
1013bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus = SD_CMD_ERROR_FLAGS;
1014bffde63dSSheetal Tigadoli 			pstate_log(handle);
1015bffde63dSSheetal Tigadoli 			break;
1016bffde63dSSheetal Tigadoli 		}
1017bffde63dSSheetal Tigadoli 
1018bffde63dSSheetal Tigadoli 		cmd12 = chal_sd_get_atuo12_error((CHAL_HANDLE *)handle->device);
1019bffde63dSSheetal Tigadoli 		if (cmd12) {
1020bffde63dSSheetal Tigadoli 			ERROR("EMMC: Cmd%d auto cmd12 err:0x%x\n",
1021bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex, cmd12);
1022bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus = cmd12;
1023bffde63dSSheetal Tigadoli 			pstate_log(handle);
1024bffde63dSSheetal Tigadoli 			break;
1025bffde63dSSheetal Tigadoli 		}
1026bffde63dSSheetal Tigadoli 
1027bffde63dSSheetal Tigadoli 		if (SD_DATA_ERROR_FLAGS & regval) {
1028bffde63dSSheetal Tigadoli 			ERROR("EMMC: Data for cmd%d error, INT[0x%x]\n",
1029bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex, regval);
1030bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus =
1031bffde63dSSheetal Tigadoli 			    (SD_DATA_ERROR_FLAGS & regval);
1032bffde63dSSheetal Tigadoli 			pstate_log(handle);
1033bffde63dSSheetal Tigadoli 			break;
1034bffde63dSSheetal Tigadoli 		}
1035bffde63dSSheetal Tigadoli 
1036bffde63dSSheetal Tigadoli 		if ((regval & mask) == 0)
1037bffde63dSSheetal Tigadoli 			udelay(EMMC_WFE_RETRY_DELAY_US);
1038bffde63dSSheetal Tigadoli 
1039bffde63dSSheetal Tigadoli 	} while ((regval & mask) == 0);
1040bffde63dSSheetal Tigadoli 
1041bffde63dSSheetal Tigadoli 	/* clear the interrupt since it is processed */
1042bffde63dSSheetal Tigadoli 	chal_sd_clear_irq((CHAL_HANDLE *)handle->device, (regval & mask));
1043bffde63dSSheetal Tigadoli 
1044bffde63dSSheetal Tigadoli 	return (regval & mask);
1045bffde63dSSheetal Tigadoli }
1046bffde63dSSheetal Tigadoli 
set_config(struct sd_handle * handle,uint32_t speed,uint32_t retry,uint32_t dma,uint32_t dmaBound,uint32_t blkSize,uint32_t wfe_retry)1047bffde63dSSheetal Tigadoli int32_t set_config(struct sd_handle *handle, uint32_t speed, uint32_t retry,
1048bffde63dSSheetal Tigadoli 		    uint32_t dma, uint32_t dmaBound, uint32_t blkSize,
1049bffde63dSSheetal Tigadoli 		    uint32_t wfe_retry)
1050bffde63dSSheetal Tigadoli {
1051bffde63dSSheetal Tigadoli 	int32_t rel = 0;
1052bffde63dSSheetal Tigadoli 
1053bffde63dSSheetal Tigadoli 	if (handle == NULL)
1054bffde63dSSheetal Tigadoli 		return SD_FAIL;
1055bffde63dSSheetal Tigadoli 
1056bffde63dSSheetal Tigadoli 	handle->device->cfg.wfe_retry = wfe_retry;
1057bffde63dSSheetal Tigadoli 
1058bffde63dSSheetal Tigadoli 	rel = chal_sd_config((CHAL_HANDLE *)handle->device, speed, retry,
1059bffde63dSSheetal Tigadoli 			     dmaBound, blkSize, dma);
1060bffde63dSSheetal Tigadoli 	return rel;
1061bffde63dSSheetal Tigadoli 
1062bffde63dSSheetal Tigadoli }
1063bffde63dSSheetal Tigadoli 
mmc_cmd1(struct sd_handle * handle)1064bffde63dSSheetal Tigadoli int mmc_cmd1(struct sd_handle *handle)
1065bffde63dSSheetal Tigadoli {
1066bffde63dSSheetal Tigadoli 	uint32_t newOcr, res;
1067bffde63dSSheetal Tigadoli 	uint32_t cmd1_option = MMC_OCR_OP_VOLT | MMC_OCR_SECTOR_ACCESS_MODE;
1068bffde63dSSheetal Tigadoli 
1069bffde63dSSheetal Tigadoli 	/*
1070bffde63dSSheetal Tigadoli 	 * After Reset, eMMC comes up in 1 Bit Data Width by default.
1071bffde63dSSheetal Tigadoli 	 * Set host side to match.
1072bffde63dSSheetal Tigadoli 	 */
1073bffde63dSSheetal Tigadoli 	chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
1074bffde63dSSheetal Tigadoli 				 SD_BUS_DATA_WIDTH_1BIT);
1075bffde63dSSheetal Tigadoli 
1076bffde63dSSheetal Tigadoli #ifdef USE_EMMC_FIP_TOC_CACHE
1077bffde63dSSheetal Tigadoli 	cached_partition_block = 0;
1078bffde63dSSheetal Tigadoli #endif
1079bffde63dSSheetal Tigadoli 	handle->device->ctrl.present = 0; /* init card present to be no card */
1080bffde63dSSheetal Tigadoli 
1081bffde63dSSheetal Tigadoli 	handle->card->type = SD_CARD_MMC;
1082bffde63dSSheetal Tigadoli 
1083bffde63dSSheetal Tigadoli 	res = sd_cmd1(handle, cmd1_option, &newOcr);
1084bffde63dSSheetal Tigadoli 
1085bffde63dSSheetal Tigadoli 	if (res != SD_OK) {
1086bffde63dSSheetal Tigadoli 		EMMC_TRACE("CMD1 Timeout: Device is not ready\n");
1087bffde63dSSheetal Tigadoli 		res = SD_CARD_UNKNOWN;
1088bffde63dSSheetal Tigadoli 	}
1089bffde63dSSheetal Tigadoli 	return res;
1090bffde63dSSheetal Tigadoli }
1091