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