blob: 96e73ca56ccdc92283e269e6bb2c6eb35e1659e5 [file] [log] [blame]
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +02001/*
Biju Das08d33082020-12-13 19:41:27 +00002 * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +02003 *
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"
Biju Das08d33082020-12-13 19:41:27 +000010#include "emmc_def.h"
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +020011#include "emmc_hal.h"
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +020012#include "emmc_registers.h"
Biju Das08d33082020-12-13 19:41:27 +000013#include "emmc_std.h"
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +020014
Biju Das08d33082020-12-13 19:41:27 +000015#define MIN_EMMC(a, b) (((a) < (b)) ? (a) : (b))
16#define EMMC_RW_SECTOR_COUNT_MAX 0x0000ffffU
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +020017
Biju Das08d33082020-12-13 19:41:27 +000018static EMMC_ERROR_CODE emmc_multiple_block_read(uint32_t *buff_address_virtual,
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +020019 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);
Biju Das08d33082020-12-13 19:41:27 +000042 /* SD_BUF Read/Write DMA Transfer enable */
43 SETR_32(CC_EXT_MODE, (CC_EXT_MODE_CLEAR | CC_EXT_MODE_DMASDRW_ENABLE));
Jorge Ramirez-Ortiz766263c2018-09-23 09:39:56 +020044
45 /* CMD18 */
46 emmc_make_trans_cmd(CMD18_READ_MULTIPLE_BLOCK, sector_number,
47 buff_address_virtual,
48 count << EMMC_SECTOR_SIZE_SHIFT, HAL_MEMCARD_READ,
49 transfer_mode);
50 result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
51 if (result != EMMC_SUCCESS) {
52 return result; /* CMD18 error code */
53 }
54
55 /* CMD13 */
56 emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16);
57 result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
58 if (result != EMMC_SUCCESS) {
59 return result;
60 }
61#if RCAR_BL2_DCACHE == 1
62 if (transfer_mode == HAL_MEMCARD_NOT_DMA) {
63 flush_dcache_range((uint64_t) buff_address_virtual,
64 ((size_t) count << EMMC_SECTOR_SIZE_SHIFT));
65 }
66#endif /* RCAR_BL2_DCACHE == 1 */
67
68 /* ready status check */
69 if ((mmc_drv_obj.r1_card_status & EMMC_R1_READY) == 0) {
70 emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR,
71 EMMC_ERR_CARD_BUSY);
72 return EMMC_ERR_CARD_BUSY;
73 }
74
75 /* state check */
76 if (mmc_drv_obj.current_state != EMMC_R1_STATE_TRAN) {
77 emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR,
78 EMMC_ERR_CARD_STATE);
79 return EMMC_ERR_CARD_STATE;
80 }
81
82 return EMMC_SUCCESS;
83}
84
85EMMC_ERROR_CODE emmc_read_sector(uint32_t *buff_address_virtual,
86 uint32_t sector_number,
87 uint32_t count, uint32_t feature_flags)
88{
89 uint32_t trans_count;
90 uint32_t remain;
91 EMMC_ERROR_CODE result;
92 HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode;
93
94 /* parameter check */
95 if (count == 0) {
96 emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM);
97 return EMMC_ERR_PARAM;
98 }
99
100 /* state check */
101 if (mmc_drv_obj.mount != TRUE) {
102 emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_STATE);
103 return EMMC_ERR_STATE;
104 }
105
106 /* DMA? */
107 if ((feature_flags & LOADIMAGE_FLAGS_DMA_ENABLE) != 0) {
108 transfer_mode = HAL_MEMCARD_DMA;
109 } else {
110 transfer_mode = HAL_MEMCARD_NOT_DMA;
111 }
112
113 remain = count;
114 while (remain != 0) {
115 trans_count = MIN_EMMC(remain, EMMC_RW_SECTOR_COUNT_MAX);
116 result =
117 emmc_multiple_block_read(buff_address_virtual,
118 sector_number, trans_count,
119 transfer_mode);
120 if (result != EMMC_SUCCESS) {
121 return result;
122 }
123
124 buff_address_virtual += (EMMC_BLOCK_LENGTH_DW * trans_count);
125 sector_number += trans_count;
126 remain -= trans_count;
127 }
128
129 return EMMC_SUCCESS;
130}