• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch_helpers.h>
8 
9 #include "emmc_config.h"
10 #include "emmc_def.h"
11 #include "emmc_hal.h"
12 #include "emmc_registers.h"
13 #include "emmc_std.h"
14 
15 #define MIN_EMMC(a, b)	(((a) < (b)) ? (a) : (b))
16 #define EMMC_RW_SECTOR_COUNT_MAX	0x0000ffffU
17 
emmc_multiple_block_read(uint32_t * buff_address_virtual,uint32_t sector_number,uint32_t count,HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode)18 static 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 	/* SD_BUF Read/Write DMA Transfer enable */
43 	SETR_32(CC_EXT_MODE, (CC_EXT_MODE_CLEAR | CC_EXT_MODE_DMASDRW_ENABLE));
44 
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 
emmc_read_sector(uint32_t * buff_address_virtual,uint32_t sector_number,uint32_t count,uint32_t feature_flags)85 EMMC_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 }
131