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