blob: 390d0caac1e7477b61915bda57a2772c50ae49a5 [file] [log] [blame]
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +02001/*
2 * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00006
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +02007#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +02009#include "emmc_config.h"
10#include "emmc_hal.h"
11#include "emmc_std.h"
12#include "emmc_registers.h"
13#include "emmc_def.h"
14
15#define MIN_EMMC(a, b) (((a) < (b)) ? (a) : (b))
16#define EMMC_RW_SECTOR_COUNT_MAX 0x0000ffffU
17
18static EMMC_ERROR_CODE emmc_multiple_block_read (uint32_t *buff_address_virtual,
19 uint32_t sector_number, uint32_t count,
20 HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode)
21{
22 EMMC_ERROR_CODE result;
23
24 /* parameter check */
25 if ((count > EMMC_RW_SECTOR_COUNT_MAX)
26 || (count == 0)
27 || ((transfer_mode != HAL_MEMCARD_DMA)
28 && (transfer_mode != HAL_MEMCARD_NOT_DMA))
29 ) {
30 emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM);
31 return EMMC_ERR_PARAM;
32 }
33
34 /* CMD23 */
35 emmc_make_nontrans_cmd(CMD23_SET_BLOCK_COUNT, count);
36 result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
37 if (result != EMMC_SUCCESS) {
38 return result;
39 }
40 SETR_32(SD_SECCNT, count);
41 SETR_32(SD_STOP, 0x00000100);
42 SETR_32(CC_EXT_MODE, (CC_EXT_MODE_CLEAR | CC_EXT_MODE_DMASDRW_ENABLE)); /* SD_BUF Read/Write DMA Transfer enable */
43
44 /* CMD18 */
45 emmc_make_trans_cmd(CMD18_READ_MULTIPLE_BLOCK, sector_number,
46 buff_address_virtual,
47 count << EMMC_SECTOR_SIZE_SHIFT, HAL_MEMCARD_READ,
48 transfer_mode);
49 result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
50 if (result != EMMC_SUCCESS) {
51 return result; /* CMD18 error code */
52 }
53
54 /* CMD13 */
55 emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16);
56 result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
57 if (result != EMMC_SUCCESS) {
58 return result;
59 }
60#if RCAR_BL2_DCACHE == 1
61 if (transfer_mode == HAL_MEMCARD_NOT_DMA) {
62 flush_dcache_range((uint64_t) buff_address_virtual,
63 ((size_t) count << EMMC_SECTOR_SIZE_SHIFT));
64 }
65#endif /* RCAR_BL2_DCACHE == 1 */
66
67 /* ready status check */
68 if ((mmc_drv_obj.r1_card_status & EMMC_R1_READY) == 0) {
69 emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR,
70 EMMC_ERR_CARD_BUSY);
71 return EMMC_ERR_CARD_BUSY;
72 }
73
74 /* state check */
75 if (mmc_drv_obj.current_state != EMMC_R1_STATE_TRAN) {
76 emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR,
77 EMMC_ERR_CARD_STATE);
78 return EMMC_ERR_CARD_STATE;
79 }
80
81 return EMMC_SUCCESS;
82}
83
84EMMC_ERROR_CODE emmc_read_sector(uint32_t *buff_address_virtual,
85 uint32_t sector_number,
86 uint32_t count, uint32_t feature_flags)
87{
88 uint32_t trans_count;
89 uint32_t remain;
90 EMMC_ERROR_CODE result;
91 HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode;
92
93 /* parameter check */
94 if (count == 0) {
95 emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM);
96 return EMMC_ERR_PARAM;
97 }
98
99 /* state check */
100 if (mmc_drv_obj.mount != TRUE) {
101 emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_STATE);
102 return EMMC_ERR_STATE;
103 }
104
105 /* DMA? */
106 if ((feature_flags & LOADIMAGE_FLAGS_DMA_ENABLE) != 0) {
107 transfer_mode = HAL_MEMCARD_DMA;
108 } else {
109 transfer_mode = HAL_MEMCARD_NOT_DMA;
110 }
111
112 remain = count;
113 while (remain != 0) {
114 trans_count = MIN_EMMC(remain, EMMC_RW_SECTOR_COUNT_MAX);
115 result =
116 emmc_multiple_block_read(buff_address_virtual,
117 sector_number, trans_count,
118 transfer_mode);
119 if (result != EMMC_SUCCESS) {
120 return result;
121 }
122
123 buff_address_virtual += (EMMC_BLOCK_LENGTH_DW * trans_count);
124 sector_number += trans_count;
125 remain -= trans_count;
126 }
127
128 return EMMC_SUCCESS;
129}