xref: /rk3399_ARM-atf/drivers/brcm/emmc/emmc_csl_sdcard.c (revision 4ce3e99a336b74611349595ea7fd5ed0277c3eeb)
1bffde63dSSheetal Tigadoli /*
2bffde63dSSheetal Tigadoli  * Copyright (c) 2016 - 2020, Broadcom
3bffde63dSSheetal Tigadoli  *
4bffde63dSSheetal Tigadoli  * SPDX-License-Identifier: BSD-3-Clause
5bffde63dSSheetal Tigadoli  */
6bffde63dSSheetal Tigadoli 
7*4ce3e99aSScott Branden #include <inttypes.h>
8*4ce3e99aSScott Branden #include <stddef.h>
9*4ce3e99aSScott 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 
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 
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  */
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  */
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
247bffde63dSSheetal Tigadoli  * into the host contollers 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  */
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  */
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 /*
321bffde63dSSheetal Tigadoli  * The function initalizes 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  */
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 /*
396bffde63dSSheetal Tigadoli  * The function handles MMC/CEATA card initalization.
397bffde63dSSheetal Tigadoli  */
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 
482bffde63dSSheetal Tigadoli 		if (handle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
483bffde63dSSheetal Tigadoli 			EMMC_TRACE("Sector addressing\n");
484bffde63dSSheetal Tigadoli 		else
485bffde63dSSheetal Tigadoli 			EMMC_TRACE("Byte addressing\n");
486bffde63dSSheetal Tigadoli 
487bffde63dSSheetal Tigadoli 		EMMC_TRACE("Ext_CSD_storage[162]: 0x%02X  Ext_CSD_storage[179]: 0x%02X\n",
488bffde63dSSheetal Tigadoli 			   emmc_global_buf_ptr->u.Ext_CSD_storage[162],
489bffde63dSSheetal Tigadoli 			   emmc_global_buf_ptr->u.Ext_CSD_storage[179]);
490bffde63dSSheetal Tigadoli 	}
491bffde63dSSheetal Tigadoli 
492bffde63dSSheetal Tigadoli 	return handle->card->type;
493bffde63dSSheetal Tigadoli }
494bffde63dSSheetal Tigadoli 
495bffde63dSSheetal Tigadoli 
496bffde63dSSheetal Tigadoli /*
497bffde63dSSheetal Tigadoli  * The function send reset command to the card.
498bffde63dSSheetal Tigadoli  * The card will be in ready status after the reset.
499bffde63dSSheetal Tigadoli  */
500bffde63dSSheetal Tigadoli int reset_card(struct sd_handle *handle)
501bffde63dSSheetal Tigadoli {
502bffde63dSSheetal Tigadoli 	int res = SD_OK;
503bffde63dSSheetal Tigadoli 
504bffde63dSSheetal Tigadoli 	/* on reset, card's RCA should return to 0 */
505bffde63dSSheetal Tigadoli 	handle->device->ctrl.rca = 0;
506bffde63dSSheetal Tigadoli 
507bffde63dSSheetal Tigadoli 	res = sd_cmd0(handle);
508bffde63dSSheetal Tigadoli 
509bffde63dSSheetal Tigadoli 	if (res != SD_OK)
510bffde63dSSheetal Tigadoli 		return SD_RESET_ERROR;
511bffde63dSSheetal Tigadoli 
512bffde63dSSheetal Tigadoli 	return res;
513bffde63dSSheetal Tigadoli }
514bffde63dSSheetal Tigadoli 
515bffde63dSSheetal Tigadoli 
516bffde63dSSheetal Tigadoli /*
517bffde63dSSheetal Tigadoli  * The function sends command to the card and starts
518bffde63dSSheetal Tigadoli  * data transmission.
519bffde63dSSheetal Tigadoli  */
520bffde63dSSheetal Tigadoli static int xfer_data(struct sd_handle *handle,
521bffde63dSSheetal Tigadoli 		     uint32_t mode,
522bffde63dSSheetal Tigadoli 		     uint32_t addr, uint32_t length, uint8_t *base)
523bffde63dSSheetal Tigadoli {
524bffde63dSSheetal Tigadoli 	int rc = SD_OK;
525bffde63dSSheetal Tigadoli 
526*4ce3e99aSScott Branden 	VERBOSE("XFER: dest: 0x%" PRIx64 ", addr: 0x%x, size: 0x%x bytes\n",
527bffde63dSSheetal Tigadoli 		(uint64_t)base, addr, length);
528bffde63dSSheetal Tigadoli 
529bffde63dSSheetal Tigadoli 	if ((length / handle->device->cfg.blockSize) > 1) {
530bffde63dSSheetal Tigadoli 		if (mode == SD_OP_READ) {
531bffde63dSSheetal Tigadoli 			inv_dcache_range((uintptr_t)base, (uint64_t)length);
532bffde63dSSheetal Tigadoli 			rc = sd_cmd18(handle, addr, length, base);
533bffde63dSSheetal Tigadoli 		} else {
534bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
535bffde63dSSheetal Tigadoli 			flush_dcache_range((uintptr_t)base, (uint64_t)length);
536bffde63dSSheetal Tigadoli 			rc = sd_cmd25(handle, addr, length, base);
537bffde63dSSheetal Tigadoli #else
538bffde63dSSheetal Tigadoli 			rc = SD_DATA_XFER_ERROR;
539bffde63dSSheetal Tigadoli #endif
540bffde63dSSheetal Tigadoli 		}
541bffde63dSSheetal Tigadoli 	} else {
542bffde63dSSheetal Tigadoli 		if (mode == SD_OP_READ) {
543bffde63dSSheetal Tigadoli 			inv_dcache_range((uintptr_t)base, (uint64_t)length);
544bffde63dSSheetal Tigadoli 			rc = sd_cmd17(handle, addr,
545bffde63dSSheetal Tigadoli 				      handle->device->cfg.blockSize, base);
546bffde63dSSheetal Tigadoli 		} else {
547bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
548bffde63dSSheetal Tigadoli 			flush_dcache_range((uintptr_t)base, (uint64_t)length);
549bffde63dSSheetal Tigadoli 			rc = sd_cmd24(handle, addr,
550bffde63dSSheetal Tigadoli 				      handle->device->cfg.blockSize, base);
551bffde63dSSheetal Tigadoli #else
552bffde63dSSheetal Tigadoli 			rc = SD_DATA_XFER_ERROR;
553bffde63dSSheetal Tigadoli #endif
554bffde63dSSheetal Tigadoli 		}
555bffde63dSSheetal Tigadoli 	}
556bffde63dSSheetal Tigadoli 
557bffde63dSSheetal Tigadoli 	if (rc != SD_OK)
558bffde63dSSheetal Tigadoli 		return SD_DATA_XFER_ERROR;
559bffde63dSSheetal Tigadoli 
560bffde63dSSheetal Tigadoli 	return SD_OK;
561bffde63dSSheetal Tigadoli }
562bffde63dSSheetal Tigadoli 
563bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
564bffde63dSSheetal Tigadoli int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks)
565bffde63dSSheetal Tigadoli {
566bffde63dSSheetal Tigadoli 	uint32_t end_addr;
567bffde63dSSheetal Tigadoli 
568bffde63dSSheetal Tigadoli 	INFO("ERASE: addr: 0x%x, num of sectors: 0x%x\n", addr, blocks);
569bffde63dSSheetal Tigadoli 
570bffde63dSSheetal Tigadoli 	if (sd_cmd35(handle, addr) != SD_OK)
571bffde63dSSheetal Tigadoli 		return SD_FAIL;
572bffde63dSSheetal Tigadoli 
573bffde63dSSheetal Tigadoli 	end_addr = addr + blocks - 1;
574bffde63dSSheetal Tigadoli 	if (sd_cmd36(handle, end_addr) != SD_OK)
575bffde63dSSheetal Tigadoli 		return SD_FAIL;
576bffde63dSSheetal Tigadoli 
577bffde63dSSheetal Tigadoli 	if (sd_cmd38(handle) != SD_OK)
578bffde63dSSheetal Tigadoli 		return SD_FAIL;
579bffde63dSSheetal Tigadoli 
580bffde63dSSheetal Tigadoli 	return SD_OK;
581bffde63dSSheetal Tigadoli }
582bffde63dSSheetal Tigadoli #endif
583bffde63dSSheetal Tigadoli 
584bffde63dSSheetal Tigadoli /*
585bffde63dSSheetal Tigadoli  * The function reads block data from a card.
586bffde63dSSheetal Tigadoli  */
587bffde63dSSheetal Tigadoli #ifdef USE_EMMC_FIP_TOC_CACHE
588bffde63dSSheetal Tigadoli int read_block(struct sd_handle *handle,
589bffde63dSSheetal Tigadoli 	       uint8_t *dst, uint32_t addr, uint32_t len)
590bffde63dSSheetal Tigadoli {
591bffde63dSSheetal Tigadoli 	int rel = SD_OK;
592bffde63dSSheetal Tigadoli 
593bffde63dSSheetal Tigadoli 	/*
594bffde63dSSheetal Tigadoli 	 * Avoid doing repeated reads of the partition block
595bffde63dSSheetal Tigadoli 	 * by caching.
596bffde63dSSheetal Tigadoli 	 */
597bffde63dSSheetal Tigadoli 	if (cached_partition_block &&
598bffde63dSSheetal Tigadoli 	    addr == PARTITION_BLOCK_ADDR &&
599bffde63dSSheetal Tigadoli 	    len == CACHE_SIZE) {
600bffde63dSSheetal Tigadoli 		memcpy(dst, cached_block, len);
601bffde63dSSheetal Tigadoli 	} else {
602bffde63dSSheetal Tigadoli 		rel = xfer_data(handle, SD_OP_READ, addr, len, dst);
603bffde63dSSheetal Tigadoli 
604bffde63dSSheetal Tigadoli 		if (len == CACHE_SIZE && addr == PARTITION_BLOCK_ADDR) {
605bffde63dSSheetal Tigadoli 			cached_partition_block = 1;
606bffde63dSSheetal Tigadoli 			memcpy(cached_block, dst, len);
607bffde63dSSheetal Tigadoli 		}
608bffde63dSSheetal Tigadoli 	}
609bffde63dSSheetal Tigadoli 
610bffde63dSSheetal Tigadoli 	return rel;
611bffde63dSSheetal Tigadoli }
612bffde63dSSheetal Tigadoli #else
613bffde63dSSheetal Tigadoli int read_block(struct sd_handle *handle,
614bffde63dSSheetal Tigadoli 	       uint8_t *dst, uint32_t addr, uint32_t len)
615bffde63dSSheetal Tigadoli {
616bffde63dSSheetal Tigadoli 	return xfer_data(handle, SD_OP_READ, addr, len, dst);
617bffde63dSSheetal Tigadoli }
618bffde63dSSheetal Tigadoli #endif
619bffde63dSSheetal Tigadoli 
620bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
621bffde63dSSheetal Tigadoli 
622bffde63dSSheetal Tigadoli /*
623bffde63dSSheetal Tigadoli  * The function writes block data to a card.
624bffde63dSSheetal Tigadoli  */
625bffde63dSSheetal Tigadoli int write_block(struct sd_handle *handle,
626bffde63dSSheetal Tigadoli 		uint8_t *src, uint32_t addr, uint32_t len)
627bffde63dSSheetal Tigadoli {
628bffde63dSSheetal Tigadoli 	int rel = SD_OK;
629bffde63dSSheetal Tigadoli 
630bffde63dSSheetal Tigadoli 	/*
631bffde63dSSheetal Tigadoli 	 * Current HC has problem to get response of cmd16 after cmd12,
632bffde63dSSheetal Tigadoli 	 * the delay is necessary to sure the next cmd16 will not be timed out.
633bffde63dSSheetal Tigadoli 	 * The delay has to be at least 4 ms.
634bffde63dSSheetal Tigadoli 	 * The code removed cmd16 and use cmd13 to get card status before
635bffde63dSSheetal Tigadoli 	 * sending cmd18 or cmd25 to make sure the card is ready and thus
636bffde63dSSheetal Tigadoli 	 * no need to have delay here.
637bffde63dSSheetal Tigadoli 	 */
638bffde63dSSheetal Tigadoli 
639bffde63dSSheetal Tigadoli 	rel = xfer_data(handle, SD_OP_WRITE, addr, len, src);
640bffde63dSSheetal Tigadoli 
641bffde63dSSheetal Tigadoli 	EMMC_TRACE("wr_blk addr:0x%08X src:0x%08X len:0x%08X result:%d\n",
642bffde63dSSheetal Tigadoli 		   addr, src, len, rel);
643bffde63dSSheetal Tigadoli 
644bffde63dSSheetal Tigadoli 	return rel;
645bffde63dSSheetal Tigadoli }
646bffde63dSSheetal Tigadoli 
647bffde63dSSheetal Tigadoli 
648bffde63dSSheetal Tigadoli /*
649bffde63dSSheetal Tigadoli  * The function is called to write one block data directly to
650bffde63dSSheetal Tigadoli  * a card's data buffer.
651bffde63dSSheetal Tigadoli  * it is used in Non-DMA mode for card data transmission.
652bffde63dSSheetal Tigadoli  */
653bffde63dSSheetal Tigadoli int write_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data)
654bffde63dSSheetal Tigadoli {
655bffde63dSSheetal Tigadoli 	uint32_t rem, blockSize, event;
656bffde63dSSheetal Tigadoli 	uint8_t *pData = data;
657bffde63dSSheetal Tigadoli 
658bffde63dSSheetal Tigadoli 	blockSize = handle->device->cfg.blockSize;
659bffde63dSSheetal Tigadoli 	rem = length;
660bffde63dSSheetal Tigadoli 
661bffde63dSSheetal Tigadoli 	if (rem == 0)
662bffde63dSSheetal Tigadoli 		return SD_OK;
663bffde63dSSheetal Tigadoli 
664bffde63dSSheetal Tigadoli 	while (rem > 0) {
665bffde63dSSheetal Tigadoli 
666bffde63dSSheetal Tigadoli 		event = wait_for_event(handle,
667bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_INTR_BWRDY_MASK |
668bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS,
669bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
670bffde63dSSheetal Tigadoli 
671bffde63dSSheetal Tigadoli 		if (handle->device->ctrl.cmdStatus) {
672bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
673bffde63dSSheetal Tigadoli 			return SD_WRITE_ERROR;
674bffde63dSSheetal Tigadoli 		}
675bffde63dSSheetal Tigadoli 
676bffde63dSSheetal Tigadoli 		if (rem >= blockSize)
677bffde63dSSheetal Tigadoli 			chal_sd_write_buffer((CHAL_HANDLE *) handle->device,
678bffde63dSSheetal Tigadoli 					     blockSize, pData);
679bffde63dSSheetal Tigadoli 		else
680bffde63dSSheetal Tigadoli 			chal_sd_write_buffer((CHAL_HANDLE *) handle->device,
681bffde63dSSheetal Tigadoli 					     rem, pData);
682bffde63dSSheetal Tigadoli 
683bffde63dSSheetal Tigadoli 		if (rem > blockSize) {
684bffde63dSSheetal Tigadoli 			rem -= blockSize;
685bffde63dSSheetal Tigadoli 			pData += blockSize;
686bffde63dSSheetal Tigadoli 		} else {
687bffde63dSSheetal Tigadoli 			pData += rem;
688bffde63dSSheetal Tigadoli 			rem = 0;
689bffde63dSSheetal Tigadoli 		}
690bffde63dSSheetal Tigadoli 	}
691bffde63dSSheetal Tigadoli 
692bffde63dSSheetal Tigadoli 	if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) !=
693bffde63dSSheetal Tigadoli 	    SD4_EMMC_TOP_INTR_TXDONE_MASK) {
694bffde63dSSheetal Tigadoli 		event = wait_for_event(handle,
695bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_INTR_TXDONE_MASK |
696bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS,
697bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
698bffde63dSSheetal Tigadoli 
699bffde63dSSheetal Tigadoli 		if (handle->device->ctrl.cmdStatus != SD_OK) {
700bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
701bffde63dSSheetal Tigadoli 			return SD_WRITE_ERROR;
702bffde63dSSheetal Tigadoli 		}
703bffde63dSSheetal Tigadoli 	} else {
704bffde63dSSheetal Tigadoli 		handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK;
705bffde63dSSheetal Tigadoli 	}
706bffde63dSSheetal Tigadoli 
707bffde63dSSheetal Tigadoli 	return SD_OK;
708bffde63dSSheetal Tigadoli }
709bffde63dSSheetal Tigadoli #endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
710bffde63dSSheetal Tigadoli 
711bffde63dSSheetal Tigadoli 
712bffde63dSSheetal Tigadoli /*
713bffde63dSSheetal Tigadoli  * The function is called to read maximal one block data
714bffde63dSSheetal Tigadoli  * directly from a card
715bffde63dSSheetal Tigadoli  * It is used in Non-DMA mode for card data transmission.
716bffde63dSSheetal Tigadoli  */
717bffde63dSSheetal Tigadoli int read_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data)
718bffde63dSSheetal Tigadoli {
719bffde63dSSheetal Tigadoli 	uint32_t rem, blockSize, event = 0;
720bffde63dSSheetal Tigadoli 	uint8_t *pData = data;
721bffde63dSSheetal Tigadoli 
722bffde63dSSheetal Tigadoli 	blockSize = handle->device->cfg.blockSize;
723bffde63dSSheetal Tigadoli 	rem = length;
724bffde63dSSheetal Tigadoli 
725bffde63dSSheetal Tigadoli 	if (rem == 0)
726bffde63dSSheetal Tigadoli 		return SD_OK;
727bffde63dSSheetal Tigadoli 
728bffde63dSSheetal Tigadoli 	while (rem > 0) {
729bffde63dSSheetal Tigadoli 		event = wait_for_event(handle,
730bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_INTR_BRRDY_MASK |
731bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS,
732bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
733bffde63dSSheetal Tigadoli 
734bffde63dSSheetal Tigadoli 		if (handle->device->ctrl.cmdStatus) {
735bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
736bffde63dSSheetal Tigadoli 			return SD_READ_ERROR;
737bffde63dSSheetal Tigadoli 		}
738bffde63dSSheetal Tigadoli 
739bffde63dSSheetal Tigadoli 		if (rem >= blockSize)
740bffde63dSSheetal Tigadoli 			chal_sd_read_buffer((CHAL_HANDLE *) handle->device,
741bffde63dSSheetal Tigadoli 					    blockSize, pData);
742bffde63dSSheetal Tigadoli 		else
743bffde63dSSheetal Tigadoli 			chal_sd_read_buffer((CHAL_HANDLE *) handle->device, rem,
744bffde63dSSheetal Tigadoli 					    pData);
745bffde63dSSheetal Tigadoli 
746bffde63dSSheetal Tigadoli 		if (rem > blockSize) {
747bffde63dSSheetal Tigadoli 			rem -= blockSize;
748bffde63dSSheetal Tigadoli 			pData += blockSize;
749bffde63dSSheetal Tigadoli 		} else {
750bffde63dSSheetal Tigadoli 			pData += rem;
751bffde63dSSheetal Tigadoli 			rem = 0;
752bffde63dSSheetal Tigadoli 		}
753bffde63dSSheetal Tigadoli 	}
754bffde63dSSheetal Tigadoli 
755bffde63dSSheetal Tigadoli 	/* In case, there are extra data in the SD FIFO, just dump them. */
756bffde63dSSheetal Tigadoli 	chal_sd_dump_fifo((CHAL_HANDLE *) handle->device);
757bffde63dSSheetal Tigadoli 
758bffde63dSSheetal Tigadoli 	if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) !=
759bffde63dSSheetal Tigadoli 	    SD4_EMMC_TOP_INTR_TXDONE_MASK) {
760bffde63dSSheetal Tigadoli 		event = wait_for_event(handle, SD4_EMMC_TOP_INTR_TXDONE_MASK,
761bffde63dSSheetal Tigadoli 				       handle->device->cfg.wfe_retry);
762bffde63dSSheetal Tigadoli 
763bffde63dSSheetal Tigadoli 		if (handle->device->ctrl.cmdStatus) {
764bffde63dSSheetal Tigadoli 			check_error(handle, handle->device->ctrl.cmdStatus);
765bffde63dSSheetal Tigadoli 			return SD_READ_ERROR;
766bffde63dSSheetal Tigadoli 		}
767bffde63dSSheetal Tigadoli 	} else {
768bffde63dSSheetal Tigadoli 		handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK;
769bffde63dSSheetal Tigadoli 	}
770bffde63dSSheetal Tigadoli 
771bffde63dSSheetal Tigadoli 	return SD_OK;
772bffde63dSSheetal Tigadoli }
773bffde63dSSheetal Tigadoli 
774bffde63dSSheetal Tigadoli 
775bffde63dSSheetal Tigadoli /*
776bffde63dSSheetal Tigadoli  * Error handling routine.
777bffde63dSSheetal Tigadoli  * The function just reset the DAT
778bffde63dSSheetal Tigadoli  * and CMD line if an error occures during data transmission.
779bffde63dSSheetal Tigadoli  */
780bffde63dSSheetal Tigadoli int check_error(struct sd_handle *handle, uint32_t ints)
781bffde63dSSheetal Tigadoli {
782bffde63dSSheetal Tigadoli 	uint32_t rel;
783bffde63dSSheetal Tigadoli 
784bffde63dSSheetal Tigadoli 	chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
785bffde63dSSheetal Tigadoli 			       SD_ERR_INTERRUPTS, 0);
786bffde63dSSheetal Tigadoli 
787bffde63dSSheetal Tigadoli 	if (ints & SD4_EMMC_TOP_INTR_CMDERROR_MASK) {
788bffde63dSSheetal Tigadoli 
789bffde63dSSheetal Tigadoli 		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
790bffde63dSSheetal Tigadoli 				   SD4_EMMC_TOP_CTRL1_CMDRST_MASK);
791bffde63dSSheetal Tigadoli 		rel = abort_err(handle);
792bffde63dSSheetal Tigadoli 
793bffde63dSSheetal Tigadoli 		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
794bffde63dSSheetal Tigadoli 				   SD4_EMMC_TOP_CTRL1_DATRST_MASK);
795bffde63dSSheetal Tigadoli 		chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
796bffde63dSSheetal Tigadoli 				       SD_ERR_INTERRUPTS, 1);
797bffde63dSSheetal Tigadoli 
798bffde63dSSheetal Tigadoli 		return (rel == SD_ERROR_NON_RECOVERABLE) ?
799bffde63dSSheetal Tigadoli 				SD_ERROR_NON_RECOVERABLE : SD_ERROR_RECOVERABLE;
800bffde63dSSheetal Tigadoli 	} else {
801bffde63dSSheetal Tigadoli 		rel = err_recovery(handle, ints);
802bffde63dSSheetal Tigadoli 	}
803bffde63dSSheetal Tigadoli 
804bffde63dSSheetal Tigadoli 	chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
805bffde63dSSheetal Tigadoli 			       SD_ERR_INTERRUPTS, 1);
806bffde63dSSheetal Tigadoli 
807bffde63dSSheetal Tigadoli 	return rel;
808bffde63dSSheetal Tigadoli }
809bffde63dSSheetal Tigadoli 
810bffde63dSSheetal Tigadoli 
811bffde63dSSheetal Tigadoli /*
812bffde63dSSheetal Tigadoli  * Error recovery routine.
813bffde63dSSheetal Tigadoli  * Try to recover from the error.
814bffde63dSSheetal Tigadoli  */
815bffde63dSSheetal Tigadoli static int err_recovery(struct sd_handle *handle, uint32_t errors)
816bffde63dSSheetal Tigadoli {
817bffde63dSSheetal Tigadoli 	uint32_t rel = 0;
818bffde63dSSheetal Tigadoli 
819bffde63dSSheetal Tigadoli 	/*
820bffde63dSSheetal Tigadoli 	 * In case of timeout error, the cmd line and data line maybe
821bffde63dSSheetal Tigadoli 	 * still active or stuck at atcitve so it is needed to reset
822bffde63dSSheetal Tigadoli 	 * either data line or cmd line to make sure a new cmd can be sent.
823bffde63dSSheetal Tigadoli 	 */
824bffde63dSSheetal Tigadoli 
825bffde63dSSheetal Tigadoli 	if (errors & SD_CMD_ERROR_INT)
826bffde63dSSheetal Tigadoli 		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
827bffde63dSSheetal Tigadoli 				   SD4_EMMC_TOP_CTRL1_CMDRST_MASK);
828bffde63dSSheetal Tigadoli 
829bffde63dSSheetal Tigadoli 	if (errors & SD_DAT_ERROR_INT)
830bffde63dSSheetal Tigadoli 		chal_sd_reset_line((CHAL_HANDLE *) handle->device,
831bffde63dSSheetal Tigadoli 				   SD4_EMMC_TOP_CTRL1_DATRST_MASK);
832bffde63dSSheetal Tigadoli 
833bffde63dSSheetal Tigadoli 	/* Abort transaction by sending out stop command */
834bffde63dSSheetal Tigadoli 	if ((handle->device->ctrl.cmdIndex == 18) ||
835bffde63dSSheetal Tigadoli 	    (handle->device->ctrl.cmdIndex == 25))
836bffde63dSSheetal Tigadoli 		rel = abort_err(handle);
837bffde63dSSheetal Tigadoli 
838bffde63dSSheetal Tigadoli 	return rel;
839bffde63dSSheetal Tigadoli }
840bffde63dSSheetal Tigadoli 
841bffde63dSSheetal Tigadoli 
842bffde63dSSheetal Tigadoli /*
843bffde63dSSheetal Tigadoli  * The function is called to read one block data directly from a card.
844bffde63dSSheetal Tigadoli  * It is used in Non-DMA mode for card data transmission.
845bffde63dSSheetal Tigadoli  */
846bffde63dSSheetal Tigadoli int process_cmd_response(struct sd_handle *handle,
847bffde63dSSheetal Tigadoli 			 uint32_t cmdIndex,
848bffde63dSSheetal Tigadoli 			 uint32_t rsp0,
849bffde63dSSheetal Tigadoli 			 uint32_t rsp1,
850bffde63dSSheetal Tigadoli 			 uint32_t rsp2, uint32_t rsp3, struct sd_resp *resp)
851bffde63dSSheetal Tigadoli {
852bffde63dSSheetal Tigadoli 	int result = SD_OK;
853bffde63dSSheetal Tigadoli 
854bffde63dSSheetal Tigadoli 	/* R6 */
855bffde63dSSheetal Tigadoli 	uint32_t rca = (rsp0 >> 16) & 0xffff;
856bffde63dSSheetal Tigadoli 	uint32_t cardStatus = rsp0;
857bffde63dSSheetal Tigadoli 
858bffde63dSSheetal Tigadoli 	/* R4 */
859bffde63dSSheetal Tigadoli 	uint32_t cBit = (rsp0 >> 31) & 0x1;
860bffde63dSSheetal Tigadoli 	uint32_t funcs = (rsp0 >> 28) & 0x7;
861bffde63dSSheetal Tigadoli 	uint32_t memPresent = (rsp0 >> 27) & 0x1;
862bffde63dSSheetal Tigadoli 
863bffde63dSSheetal Tigadoli 	resp->r1 = 0x3f;
864bffde63dSSheetal Tigadoli 	resp->cardStatus = cardStatus;
865bffde63dSSheetal Tigadoli 
866bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_IO_SEND_OP_COND) {
867bffde63dSSheetal Tigadoli 		resp->data.r4.cardReady = cBit;
868bffde63dSSheetal Tigadoli 		resp->data.r4.funcs = funcs;
869bffde63dSSheetal Tigadoli 		resp->data.r4.memPresent = memPresent;
870bffde63dSSheetal Tigadoli 		resp->data.r4.ocr = cardStatus;
871bffde63dSSheetal Tigadoli 	}
872bffde63dSSheetal Tigadoli 
873bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_MMC_SET_RCA) {
874bffde63dSSheetal Tigadoli 		resp->data.r6.rca = rca;
875bffde63dSSheetal Tigadoli 		resp->data.r6.cardStatus = cardStatus & 0xFFFF;
876bffde63dSSheetal Tigadoli 	}
877bffde63dSSheetal Tigadoli 
878bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_SELECT_DESELECT_CARD) {
879bffde63dSSheetal Tigadoli 		resp->data.r7.rca = rca;
880bffde63dSSheetal Tigadoli 	}
881bffde63dSSheetal Tigadoli 
882bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_IO_RW_DIRECT) {
883bffde63dSSheetal Tigadoli 		if (((rsp0 >> 16) & 0xffff) != 0)
884bffde63dSSheetal Tigadoli 			result = SD_CMD_ERR_INVALID_RESPONSE;
885bffde63dSSheetal Tigadoli 
886bffde63dSSheetal Tigadoli 		resp->data.r5.data = rsp0 & 0xff;
887bffde63dSSheetal Tigadoli 	}
888bffde63dSSheetal Tigadoli 
889bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_IO_RW_EXTENDED) {
890bffde63dSSheetal Tigadoli 		if (((rsp0 >> 16) & 0xffff) != 0)
891bffde63dSSheetal Tigadoli 			result = SD_CMD_ERR_INVALID_RESPONSE;
892bffde63dSSheetal Tigadoli 
893bffde63dSSheetal Tigadoli 		resp->data.r5.data = rsp0 & 0xff;
894bffde63dSSheetal Tigadoli 	}
895bffde63dSSheetal Tigadoli 
896bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_ACMD_SD_SEND_OP_COND ||
897bffde63dSSheetal Tigadoli 	    cmdIndex == SD_CMD_SEND_OPCOND)
898bffde63dSSheetal Tigadoli 		resp->data.r3.ocr = cardStatus;
899bffde63dSSheetal Tigadoli 
900bffde63dSSheetal Tigadoli 	if (cmdIndex == SD_CMD_SEND_CSD ||
901bffde63dSSheetal Tigadoli 	    cmdIndex == SD_CMD_SEND_CID ||
902bffde63dSSheetal Tigadoli 	    cmdIndex == SD_CMD_ALL_SEND_CID) {
903bffde63dSSheetal Tigadoli 		resp->data.r2.rsp4 = rsp3;
904bffde63dSSheetal Tigadoli 		resp->data.r2.rsp3 = rsp2;
905bffde63dSSheetal Tigadoli 		resp->data.r2.rsp2 = rsp1;
906bffde63dSSheetal Tigadoli 		resp->data.r2.rsp1 = rsp0;
907bffde63dSSheetal Tigadoli 	}
908bffde63dSSheetal Tigadoli 
909bffde63dSSheetal Tigadoli 	if ((cmdIndex == SD_CMD_READ_EXT_CSD) &&
910bffde63dSSheetal Tigadoli 	    (handle->card->type == SD_CARD_SD)) {
911bffde63dSSheetal Tigadoli 		if ((resp->cardStatus & 0xAA) != 0xAA) {
912bffde63dSSheetal Tigadoli 			result = SD_CMD_ERR_INVALID_RESPONSE;
913bffde63dSSheetal Tigadoli 		}
914bffde63dSSheetal Tigadoli 	}
915bffde63dSSheetal Tigadoli 
916bffde63dSSheetal Tigadoli 	return result;
917bffde63dSSheetal Tigadoli }
918bffde63dSSheetal Tigadoli 
919bffde63dSSheetal Tigadoli 
920bffde63dSSheetal Tigadoli /*
921bffde63dSSheetal Tigadoli  * The function sets DMA buffer and data length, process
922bffde63dSSheetal Tigadoli  * block size and the number of blocks to be transferred.
923bffde63dSSheetal Tigadoli  * It returns the DMA buffer address.
924bffde63dSSheetal Tigadoli  * It copies dma data from user buffer to the DMA buffer
925bffde63dSSheetal Tigadoli  * if the operation is to write data to the SD card.
926bffde63dSSheetal Tigadoli  */
927bffde63dSSheetal Tigadoli void data_xfer_setup(struct sd_handle *handle, uint8_t *data, uint32_t length,
928bffde63dSSheetal Tigadoli 		     int dir)
929bffde63dSSheetal Tigadoli {
930bffde63dSSheetal Tigadoli 	chal_sd_setup_xfer((CHAL_HANDLE *)handle->device, data, length, dir);
931bffde63dSSheetal Tigadoli }
932bffde63dSSheetal Tigadoli 
933bffde63dSSheetal Tigadoli 
934bffde63dSSheetal Tigadoli /*
935bffde63dSSheetal Tigadoli  * The function does soft reset the host SD controller. After
936bffde63dSSheetal Tigadoli  * the function call all host controller's register are reset
937bffde63dSSheetal Tigadoli  * to default vallue;
938bffde63dSSheetal Tigadoli  *
939bffde63dSSheetal Tigadoli  * Note    This function only resets the host controller it does not
940bffde63dSSheetal Tigadoli  *          reset the controller's handler.
941bffde63dSSheetal Tigadoli  */
942bffde63dSSheetal Tigadoli int reset_host_ctrl(struct sd_handle *handle)
943bffde63dSSheetal Tigadoli {
944bffde63dSSheetal Tigadoli 	chal_sd_stop();
945bffde63dSSheetal Tigadoli 
946bffde63dSSheetal Tigadoli 	return SD_OK;
947bffde63dSSheetal Tigadoli }
948bffde63dSSheetal Tigadoli 
949bffde63dSSheetal Tigadoli static void pstate_log(struct sd_handle *handle)
950bffde63dSSheetal Tigadoli {
951bffde63dSSheetal Tigadoli 	ERROR("PSTATE: 0x%x\n", mmio_read_32
952bffde63dSSheetal Tigadoli 		(handle->device->ctrl.sdRegBaseAddr +
953bffde63dSSheetal Tigadoli 			SD4_EMMC_TOP_PSTATE_SD4_OFFSET));
954bffde63dSSheetal Tigadoli 	ERROR("ERRSTAT: 0x%x\n", mmio_read_32
955bffde63dSSheetal Tigadoli 		(handle->device->ctrl.sdRegBaseAddr +
956bffde63dSSheetal Tigadoli 			SD4_EMMC_TOP_ERRSTAT_OFFSET));
957bffde63dSSheetal Tigadoli }
958bffde63dSSheetal Tigadoli 
959bffde63dSSheetal Tigadoli /*
960bffde63dSSheetal Tigadoli  * The function waits for one or a group of interrupts specified
961bffde63dSSheetal Tigadoli  * by mask. The function returns if any one the interrupt status
962bffde63dSSheetal Tigadoli  * is set. If interrupt mode is not enabled then it will poll
963bffde63dSSheetal Tigadoli  * the interrupt status register until a interrupt status is set
964bffde63dSSheetal Tigadoli  * an error interrupt happens. If interrupt mode is enabled then
965bffde63dSSheetal Tigadoli  * this function should be called after the interrupt
966bffde63dSSheetal Tigadoli  * is received by ISR routine.
967bffde63dSSheetal Tigadoli  */
968bffde63dSSheetal Tigadoli uint32_t wait_for_event(struct sd_handle *handle,
969bffde63dSSheetal Tigadoli 			uint32_t mask, uint32_t retry)
970bffde63dSSheetal Tigadoli {
971bffde63dSSheetal Tigadoli 	uint32_t regval, cmd12, time = 0;
972bffde63dSSheetal Tigadoli 
973bffde63dSSheetal Tigadoli 	handle->device->ctrl.cmdStatus = 0;	/* no error */
974bffde63dSSheetal Tigadoli 	EMMC_TRACE("%s %d mask:0x%x timeout:%d irq_status:0x%x\n",
975bffde63dSSheetal Tigadoli 		   __func__, __LINE__, mask, retry,
976bffde63dSSheetal Tigadoli 		   chal_sd_get_irq_status((CHAL_HANDLE *)handle->device));
977bffde63dSSheetal Tigadoli 
978bffde63dSSheetal Tigadoli 	/* Polling mode */
979bffde63dSSheetal Tigadoli 	do {
980bffde63dSSheetal Tigadoli 		regval = chal_sd_get_irq_status((CHAL_HANDLE *)handle->device);
981bffde63dSSheetal Tigadoli 
982bffde63dSSheetal Tigadoli 		if (regval & SD4_EMMC_TOP_INTR_DMAIRQ_MASK) {
983bffde63dSSheetal Tigadoli 			chal_sd_set_dma_addr((CHAL_HANDLE *)handle->device,
984bffde63dSSheetal Tigadoli 					(uintptr_t)
985bffde63dSSheetal Tigadoli 				chal_sd_get_dma_addr((CHAL_HANDLE *)
986bffde63dSSheetal Tigadoli 						handle->device));
987bffde63dSSheetal Tigadoli 			chal_sd_clear_irq((CHAL_HANDLE *)handle->device,
988bffde63dSSheetal Tigadoli 					  SD4_EMMC_TOP_INTR_DMAIRQ_MASK);
989bffde63dSSheetal Tigadoli 		}
990bffde63dSSheetal Tigadoli 
991bffde63dSSheetal Tigadoli 		if (time++ > retry) {
992bffde63dSSheetal Tigadoli 			ERROR("EMMC: No response (cmd%d) after %dus.\n",
993bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex,
994bffde63dSSheetal Tigadoli 			      time * EMMC_WFE_RETRY_DELAY_US);
995bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus = SD_CMD_MISSING;
996bffde63dSSheetal Tigadoli 			pstate_log(handle);
997bffde63dSSheetal Tigadoli 			ERROR("EMMC: INT[0x%x]\n", regval);
998bffde63dSSheetal Tigadoli 			break;
999bffde63dSSheetal Tigadoli 		}
1000bffde63dSSheetal Tigadoli 
1001bffde63dSSheetal Tigadoli 		if (regval & SD4_EMMC_TOP_INTR_CTOERR_MASK) {
1002bffde63dSSheetal Tigadoli 			ERROR("EMMC: Cmd%d timeout INT[0x%x]\n",
1003bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex, regval);
1004bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus =
1005bffde63dSSheetal Tigadoli 			    SD4_EMMC_TOP_INTR_CTOERR_MASK;
1006bffde63dSSheetal Tigadoli 			pstate_log(handle);
1007bffde63dSSheetal Tigadoli 			break;
1008bffde63dSSheetal Tigadoli 		}
1009bffde63dSSheetal Tigadoli 		if (regval & SD_CMD_ERROR_FLAGS) {
1010bffde63dSSheetal Tigadoli 			ERROR("EMMC: Cmd%d error INT[0x%x]\n",
1011bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex, regval);
1012bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus = SD_CMD_ERROR_FLAGS;
1013bffde63dSSheetal Tigadoli 			pstate_log(handle);
1014bffde63dSSheetal Tigadoli 			break;
1015bffde63dSSheetal Tigadoli 		}
1016bffde63dSSheetal Tigadoli 
1017bffde63dSSheetal Tigadoli 		cmd12 = chal_sd_get_atuo12_error((CHAL_HANDLE *)handle->device);
1018bffde63dSSheetal Tigadoli 		if (cmd12) {
1019bffde63dSSheetal Tigadoli 			ERROR("EMMC: Cmd%d auto cmd12 err:0x%x\n",
1020bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex, cmd12);
1021bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus = cmd12;
1022bffde63dSSheetal Tigadoli 			pstate_log(handle);
1023bffde63dSSheetal Tigadoli 			break;
1024bffde63dSSheetal Tigadoli 		}
1025bffde63dSSheetal Tigadoli 
1026bffde63dSSheetal Tigadoli 		if (SD_DATA_ERROR_FLAGS & regval) {
1027bffde63dSSheetal Tigadoli 			ERROR("EMMC: Data for cmd%d error, INT[0x%x]\n",
1028bffde63dSSheetal Tigadoli 			      handle->device->ctrl.cmdIndex, regval);
1029bffde63dSSheetal Tigadoli 			handle->device->ctrl.cmdStatus =
1030bffde63dSSheetal Tigadoli 			    (SD_DATA_ERROR_FLAGS & regval);
1031bffde63dSSheetal Tigadoli 			pstate_log(handle);
1032bffde63dSSheetal Tigadoli 			break;
1033bffde63dSSheetal Tigadoli 		}
1034bffde63dSSheetal Tigadoli 
1035bffde63dSSheetal Tigadoli 		if ((regval & mask) == 0)
1036bffde63dSSheetal Tigadoli 			udelay(EMMC_WFE_RETRY_DELAY_US);
1037bffde63dSSheetal Tigadoli 
1038bffde63dSSheetal Tigadoli 	} while ((regval & mask) == 0);
1039bffde63dSSheetal Tigadoli 
1040bffde63dSSheetal Tigadoli 	/* clear the interrupt since it is processed */
1041bffde63dSSheetal Tigadoli 	chal_sd_clear_irq((CHAL_HANDLE *)handle->device, (regval & mask));
1042bffde63dSSheetal Tigadoli 
1043bffde63dSSheetal Tigadoli 	return (regval & mask);
1044bffde63dSSheetal Tigadoli }
1045bffde63dSSheetal Tigadoli 
1046bffde63dSSheetal Tigadoli int32_t set_config(struct sd_handle *handle, uint32_t speed, uint32_t retry,
1047bffde63dSSheetal Tigadoli 		    uint32_t dma, uint32_t dmaBound, uint32_t blkSize,
1048bffde63dSSheetal Tigadoli 		    uint32_t wfe_retry)
1049bffde63dSSheetal Tigadoli {
1050bffde63dSSheetal Tigadoli 	int32_t rel = 0;
1051bffde63dSSheetal Tigadoli 
1052bffde63dSSheetal Tigadoli 	if (handle == NULL)
1053bffde63dSSheetal Tigadoli 		return SD_FAIL;
1054bffde63dSSheetal Tigadoli 
1055bffde63dSSheetal Tigadoli 	handle->device->cfg.wfe_retry = wfe_retry;
1056bffde63dSSheetal Tigadoli 
1057bffde63dSSheetal Tigadoli 	rel = chal_sd_config((CHAL_HANDLE *)handle->device, speed, retry,
1058bffde63dSSheetal Tigadoli 			     dmaBound, blkSize, dma);
1059bffde63dSSheetal Tigadoli 	return rel;
1060bffde63dSSheetal Tigadoli 
1061bffde63dSSheetal Tigadoli }
1062bffde63dSSheetal Tigadoli 
1063bffde63dSSheetal Tigadoli int mmc_cmd1(struct sd_handle *handle)
1064bffde63dSSheetal Tigadoli {
1065bffde63dSSheetal Tigadoli 	uint32_t newOcr, res;
1066bffde63dSSheetal Tigadoli 	uint32_t cmd1_option = MMC_OCR_OP_VOLT | MMC_OCR_SECTOR_ACCESS_MODE;
1067bffde63dSSheetal Tigadoli 
1068bffde63dSSheetal Tigadoli 	/*
1069bffde63dSSheetal Tigadoli 	 * After Reset, eMMC comes up in 1 Bit Data Width by default.
1070bffde63dSSheetal Tigadoli 	 * Set host side to match.
1071bffde63dSSheetal Tigadoli 	 */
1072bffde63dSSheetal Tigadoli 	chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
1073bffde63dSSheetal Tigadoli 				 SD_BUS_DATA_WIDTH_1BIT);
1074bffde63dSSheetal Tigadoli 
1075bffde63dSSheetal Tigadoli #ifdef USE_EMMC_FIP_TOC_CACHE
1076bffde63dSSheetal Tigadoli 	cached_partition_block = 0;
1077bffde63dSSheetal Tigadoli #endif
1078bffde63dSSheetal Tigadoli 	handle->device->ctrl.present = 0; /* init card present to be no card */
1079bffde63dSSheetal Tigadoli 
1080bffde63dSSheetal Tigadoli 	handle->card->type = SD_CARD_MMC;
1081bffde63dSSheetal Tigadoli 
1082bffde63dSSheetal Tigadoli 	res = sd_cmd1(handle, cmd1_option, &newOcr);
1083bffde63dSSheetal Tigadoli 
1084bffde63dSSheetal Tigadoli 	if (res != SD_OK) {
1085bffde63dSSheetal Tigadoli 		EMMC_TRACE("CMD1 Timeout: Device is not ready\n");
1086bffde63dSSheetal Tigadoli 		res = SD_CARD_UNKNOWN;
1087bffde63dSSheetal Tigadoli 	}
1088bffde63dSSheetal Tigadoli 	return res;
1089bffde63dSSheetal Tigadoli }
1090