xref: /rk3399_ARM-atf/drivers/brcm/emmc/emmc_chal_sd.c (revision 4bd8c929b4bc6e1731c2892b38d4a8c43e8e89dc)
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 <assert.h>
8bffde63dSSheetal Tigadoli #include <string.h>
9bffde63dSSheetal Tigadoli 
10bffde63dSSheetal Tigadoli #include <lib/mmio.h>
11bffde63dSSheetal Tigadoli 
12bffde63dSSheetal Tigadoli #include <platform_def.h>
13bffde63dSSheetal Tigadoli 
14bffde63dSSheetal Tigadoli #include "bcm_emmc.h"
15bffde63dSSheetal Tigadoli #include "emmc_chal_types.h"
16bffde63dSSheetal Tigadoli #include "emmc_chal_sd.h"
17bffde63dSSheetal Tigadoli #include "emmc_pboot_hal_memory_drv.h"
18bffde63dSSheetal Tigadoli 
19bffde63dSSheetal Tigadoli extern void emmc_soft_reset(void);
20bffde63dSSheetal Tigadoli 
21bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_6_TO_1_7        0x00000010	// 1.6 V to 1.7 Volts
22bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_7_TO_1_8        0x00000020	// 1.7 V to 1.8 Volts
23bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_8_TO_1_9        0x00000040	// 1.8 V to 1.9 Volts
24bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_9_TO_2_0        0x00000080	// 1.9 V to 2.0 Volts
25bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_0_TO_2_1        0x00000100	// 2.0 V to 2.1 Volts
26bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_1_TO_2_2        0x00000200	// 2.1 V to 2.2 Volts
27bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_2_TO_2_3        0x00000400	// 2.2 V to 2.3 Volts
28bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_3_TO_2_4        0x00000800	// 2.3 V to 2.4 Volts
29bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_4_TO_2_5        0x00001000	// 2.4 V to 2.5 Volts
30bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_5_TO_2_6        0x00002000	// 2.5 V to 2.6 Volts
31bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_6_TO_2_7        0x00004000	// 2.6 V to 2.7 Volts
32bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_7_TO_2_8        0x00008000	// 2.7 V to 2.8 Volts
33bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_8_TO_2_9        0x00010000	// 2.8 V to 2.9 Volts
34bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_9_TO_3_0        0x00020000	// 2.9 V to 3.0 Volts
35bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_0_TO_3_1        0x00040000	// 3.0 V to 3.1 Volts
36bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_1_TO_3_2        0x00080000	// 3.1 V to 3.2 Volts
37bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_2_TO_3_3        0x00100000	// 3.2 V to 3.3 Volts
38bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_3_TO_3_4        0x00200000	// 3.3 V to 3.4 Volts
39bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_4_TO_3_5        0x00400000	// 3.4 V to 3.5 Volts
40bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_5_TO_3_6        0x00800000	// 3.5 V to 3.6 Volts
41bffde63dSSheetal Tigadoli 
42bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_6_TO_2_6        (SD_VDD_WINDOW_1_6_TO_1_7 |	\
43bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_1_7_TO_1_8 |	\
44bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_1_8_TO_1_9 |	\
45bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_1_9_TO_2_0 |	\
46bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_2_0_TO_2_1 |	\
47bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_2_1_TO_2_2 |	\
48bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_2_2_TO_2_3 |	\
49bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_2_3_TO_2_4 |	\
50bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_2_4_TO_2_5 |	\
51bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_2_5_TO_2_6)
52bffde63dSSheetal Tigadoli 
53bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_6_TO_3_2        (SD_VDD_WINDOW_2_6_TO_2_7 |	\
54bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_2_7_TO_2_8 |	\
55bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_2_8_TO_2_9 |	\
56bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_2_9_TO_3_0 |	\
57bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_3_0_TO_3_1 |	\
58bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_3_1_TO_3_2)
59bffde63dSSheetal Tigadoli 
60bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_2_TO_3_6        (SD_VDD_WINDOW_3_2_TO_3_3 |	\
61bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_3_3_TO_3_4 |	\
62bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_3_4_TO_3_5 |	\
63bffde63dSSheetal Tigadoli 					 SD_VDD_WINDOW_3_5_TO_3_6)
64bffde63dSSheetal Tigadoli 
65bffde63dSSheetal Tigadoli 
66bffde63dSSheetal Tigadoli static int32_t chal_sd_set_power(struct sd_dev *handle,
67bffde63dSSheetal Tigadoli 				 uint32_t voltage, uint32_t state);
68bffde63dSSheetal Tigadoli 
69bffde63dSSheetal Tigadoli static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary);
70bffde63dSSheetal Tigadoli 
71bffde63dSSheetal Tigadoli static int32_t chal_sd_setup_handler(struct sd_dev *handle,
72bffde63dSSheetal Tigadoli 				     uint32_t sdBbase, uint32_t hostBase);
73bffde63dSSheetal Tigadoli 
74bffde63dSSheetal Tigadoli /*
75bffde63dSSheetal Tigadoli  * Configure host controller pwr settings,
76bffde63dSSheetal Tigadoli  * to match voltage requirements by SD Card
77bffde63dSSheetal Tigadoli  */
chal_sd_set_power(struct sd_dev * handle,uint32_t voltage,uint32_t state)78bffde63dSSheetal Tigadoli static int32_t chal_sd_set_power(struct sd_dev *handle,
79bffde63dSSheetal Tigadoli 				 uint32_t voltage, uint32_t state)
80bffde63dSSheetal Tigadoli {
81bffde63dSSheetal Tigadoli 	int32_t rc, rval = SD_FAIL;
82bffde63dSSheetal Tigadoli 	uint32_t time = 0;
83bffde63dSSheetal Tigadoli 
84bffde63dSSheetal Tigadoli 	if (handle == NULL)
85bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
86bffde63dSSheetal Tigadoli 
87bffde63dSSheetal Tigadoli 	mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr +
88bffde63dSSheetal Tigadoli 			   SD4_EMMC_TOP_CTRL_OFFSET,
89bffde63dSSheetal Tigadoli 			   (SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK |
90bffde63dSSheetal Tigadoli 			    SD4_EMMC_TOP_CTRL_SDPWR_MASK),
91bffde63dSSheetal Tigadoli 			   (voltage << 9));
92bffde63dSSheetal Tigadoli 
93bffde63dSSheetal Tigadoli 	/*
94bffde63dSSheetal Tigadoli 	 * Long delay is required here in emulation.  Without this, the initial
95bffde63dSSheetal Tigadoli 	 * commands sent to the eMMC card timeout.  We don't know if this
96bffde63dSSheetal Tigadoli 	 * delay is necessary with silicon, leaving in for safety.
97bffde63dSSheetal Tigadoli 	 * It is observed that 403ms on emulation system and as per the clock
98bffde63dSSheetal Tigadoli 	 * calculations it is expected to complete with in 1ms on chip
99bffde63dSSheetal Tigadoli 	 */
100bffde63dSSheetal Tigadoli 	do {
101bffde63dSSheetal Tigadoli 		rc =  mmio_read_32(handle->ctrl.sdRegBaseAddr +
102bffde63dSSheetal Tigadoli 				   SD4_EMMC_TOP_INTR_OFFSET);
103bffde63dSSheetal Tigadoli 
104bffde63dSSheetal Tigadoli 		if ((rc & SD4_EMMC_TOP_INTR_CRDINS_MASK) ==
105bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_INTR_CRDINS_MASK)
106bffde63dSSheetal Tigadoli 			break;
107bffde63dSSheetal Tigadoli 
108bffde63dSSheetal Tigadoli 		mdelay(1);
109bffde63dSSheetal Tigadoli 	} while (time++ < EMMC_CARD_DETECT_TIMEOUT_MS);
110bffde63dSSheetal Tigadoli 
111bffde63dSSheetal Tigadoli 	if (time >= EMMC_CARD_DETECT_TIMEOUT_MS) {
112bffde63dSSheetal Tigadoli 		ERROR("EMMC: Card insert event detection timeout\n");
113bffde63dSSheetal Tigadoli 		return rval;
114bffde63dSSheetal Tigadoli 	}
115bffde63dSSheetal Tigadoli 
116bffde63dSSheetal Tigadoli 	VERBOSE("EMMC: Card detection delay: %dms\n", time);
117bffde63dSSheetal Tigadoli 
118bffde63dSSheetal Tigadoli 	if (state)
119bffde63dSSheetal Tigadoli 		mmio_setbits_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET,
120bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_CTRL_SDPWR_MASK);
121bffde63dSSheetal Tigadoli 
122*1b491eeaSElyes Haouas 	/* dummy write & ack to verify if the sdio is ready to send commands */
123bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET, 0);
124bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET, 0);
125bffde63dSSheetal Tigadoli 
126bffde63dSSheetal Tigadoli 	/*
127bffde63dSSheetal Tigadoli 	 * 63ms observed on emulation system, As per clock calculations
128bffde63dSSheetal Tigadoli 	 * it will complete  < 1ms on chip.
129bffde63dSSheetal Tigadoli 	 */
130bffde63dSSheetal Tigadoli 	time = 0;
131bffde63dSSheetal Tigadoli 	do {
132bffde63dSSheetal Tigadoli 		rc = mmio_read_32(handle->ctrl.sdRegBaseAddr +
133bffde63dSSheetal Tigadoli 				  SD4_EMMC_TOP_INTR_OFFSET);
134bffde63dSSheetal Tigadoli 
135bffde63dSSheetal Tigadoli 		if (rc & SD4_EMMC_TOP_INTR_ERRIRQ_MASK)
136bffde63dSSheetal Tigadoli 			break;
137bffde63dSSheetal Tigadoli 
138bffde63dSSheetal Tigadoli 		if ((rc & SD4_EMMC_TOP_INTR_CMDDONE_MASK) ==
139bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_INTR_CMDDONE_MASK)
140bffde63dSSheetal Tigadoli 			break;
141bffde63dSSheetal Tigadoli 
142bffde63dSSheetal Tigadoli 		mdelay(1);
143bffde63dSSheetal Tigadoli 	} while (time++ < EMMC_CMD_TIMEOUT_MS);
144bffde63dSSheetal Tigadoli 
145bffde63dSSheetal Tigadoli 	if (time >= EMMC_CMD_TIMEOUT_MS) {
146bffde63dSSheetal Tigadoli 		WARN("%s %d Initial dummy command timeout is happened\n",
147bffde63dSSheetal Tigadoli 		      __func__, __LINE__);
148bffde63dSSheetal Tigadoli 		return rval;
149bffde63dSSheetal Tigadoli 	}
150bffde63dSSheetal Tigadoli 
151bffde63dSSheetal Tigadoli 	VERBOSE("EMMC: Dummy Command delay: %dms\n", time);
152bffde63dSSheetal Tigadoli 
153bffde63dSSheetal Tigadoli 	return SD_OK;
154bffde63dSSheetal Tigadoli }
155bffde63dSSheetal Tigadoli 
156bffde63dSSheetal Tigadoli /*
157bffde63dSSheetal Tigadoli  * Configure DMA Boundaries
158bffde63dSSheetal Tigadoli  */
chal_sd_set_dma_boundary(struct sd_dev * handle,uint32_t boundary)159bffde63dSSheetal Tigadoli static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary)
160bffde63dSSheetal Tigadoli {
161bffde63dSSheetal Tigadoli 	if (handle == NULL)
162bffde63dSSheetal Tigadoli 		return;
163bffde63dSSheetal Tigadoli 
164bffde63dSSheetal Tigadoli 	mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr +
165bffde63dSSheetal Tigadoli 			   SD4_EMMC_TOP_BLOCK_OFFSET,
166bffde63dSSheetal Tigadoli 			   SD4_EMMC_TOP_BLOCK_HSBS_MASK, boundary);
167bffde63dSSheetal Tigadoli }
168bffde63dSSheetal Tigadoli 
chal_sd_setup_handler(struct sd_dev * handle,uint32_t sdBase,uint32_t hostBase)169bffde63dSSheetal Tigadoli static int32_t chal_sd_setup_handler(struct sd_dev *handle, uint32_t sdBase,
170bffde63dSSheetal Tigadoli 				     uint32_t hostBase)
171bffde63dSSheetal Tigadoli {
172bffde63dSSheetal Tigadoli 	if (handle == NULL)
173bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
174bffde63dSSheetal Tigadoli 
175bffde63dSSheetal Tigadoli 	handle->ctrl.sdRegBaseAddr = sdBase;
176bffde63dSSheetal Tigadoli 	handle->ctrl.hostRegBaseAddr = hostBase;
177bffde63dSSheetal Tigadoli 	handle->ctrl.present = 0;
178bffde63dSSheetal Tigadoli 	handle->ctrl.rca = 0;
179bffde63dSSheetal Tigadoli 	handle->ctrl.blkGapEnable = 0;
180bffde63dSSheetal Tigadoli 	handle->ctrl.cmdStatus = 0;
181bffde63dSSheetal Tigadoli 
182bffde63dSSheetal Tigadoli 	return SD_OK;
183bffde63dSSheetal Tigadoli }
184bffde63dSSheetal Tigadoli 
185bffde63dSSheetal Tigadoli /*
186bffde63dSSheetal Tigadoli  * Initialize SD Host controller
187bffde63dSSheetal Tigadoli  */
chal_sd_init(CHAL_HANDLE * sd_handle)188bffde63dSSheetal Tigadoli int32_t chal_sd_init(CHAL_HANDLE *sd_handle)
189bffde63dSSheetal Tigadoli {
190bffde63dSSheetal Tigadoli 	uint32_t cap_val_l = 0;
191bffde63dSSheetal Tigadoli 	uint32_t ctl_val, voltage;
192bffde63dSSheetal Tigadoli 	uint32_t timeout_val;
193bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
194bffde63dSSheetal Tigadoli 	uint32_t reg_val;
195bffde63dSSheetal Tigadoli 	int32_t rval = SD_FAIL;
196bffde63dSSheetal Tigadoli 
197bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
198bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
199bffde63dSSheetal Tigadoli 
200bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *)sd_handle;
201bffde63dSSheetal Tigadoli 
202bffde63dSSheetal Tigadoli 	/*
203bffde63dSSheetal Tigadoli 	 * Set SDIO Host Controller capabilities register
204bffde63dSSheetal Tigadoli 	 */
205bffde63dSSheetal Tigadoli 	EMMC_TRACE("Set Host Controller Capabilities register\n");
206bffde63dSSheetal Tigadoli 
207bffde63dSSheetal Tigadoli 	reg_val = 0;
208bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__SLOT_TYPE_R);
209bffde63dSSheetal Tigadoli 	reg_val |= (0 << ICFG_SDIO0_CAP0__INT_MODE_R);
210bffde63dSSheetal Tigadoli 	reg_val |= (0 << ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R);
211bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R);
212bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R);
213bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R);
214bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__SUSPEND_RESUME_R);
215bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__SDMA_R);
216bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__HIGH_SPEED_R);
217bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__ADMA2_R);
218bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R);
219bffde63dSSheetal Tigadoli 	reg_val |= (2 << ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R);
220bffde63dSSheetal Tigadoli 	reg_val |= (0xd0 << ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R);
221bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R);
222bffde63dSSheetal Tigadoli 	reg_val |= (0x30 << ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R);
223bffde63dSSheetal Tigadoli 
224bffde63dSSheetal Tigadoli 	mmio_write_32(ICFG_SDIO0_CAP0, reg_val);
225bffde63dSSheetal Tigadoli 
226bffde63dSSheetal Tigadoli 	reg_val = 0;
227bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R);
228bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_MODE_R);
229bffde63dSSheetal Tigadoli 	reg_val |= (0 << ICFG_SDIO0_CAP1__CLK_MULT_R);
230bffde63dSSheetal Tigadoli 	reg_val |= (0 << ICFG_SDIO0_CAP1__RETUNING_MODE_R);
231bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__TUNE_SDR50_R);
232bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__TIME_RETUNE_R);
233bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_D_R);
234bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_C_R);
235bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_A_R);
236bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__DDR50_R);
237bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__SDR104_R);
238bffde63dSSheetal Tigadoli 	reg_val |= (1 << ICFG_SDIO0_CAP1__SDR50_R);
239bffde63dSSheetal Tigadoli 
240bffde63dSSheetal Tigadoli 	mmio_write_32(ICFG_SDIO0_CAP1, reg_val);
241bffde63dSSheetal Tigadoli 
242bffde63dSSheetal Tigadoli 	/* Reset the SDIO controller */
243bffde63dSSheetal Tigadoli 	chal_sd_stop();
244bffde63dSSheetal Tigadoli 
245bffde63dSSheetal Tigadoli 	/* Turn on SD clock */
246bffde63dSSheetal Tigadoli 	chal_sd_set_clock(sd_handle,
247bffde63dSSheetal Tigadoli 			  chal_sd_freq_2_div_ctrl_setting(INIT_CLK_FREQ), 1);
248bffde63dSSheetal Tigadoli 
249bffde63dSSheetal Tigadoli 	/* program data time out value to the max */
250bffde63dSSheetal Tigadoli 	timeout_val = SD_HOST_CORE_TIMEOUT;
251bffde63dSSheetal Tigadoli 
252bffde63dSSheetal Tigadoli 	ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
253bffde63dSSheetal Tigadoli 			       SD4_EMMC_TOP_CTRL1_OFFSET);
254bffde63dSSheetal Tigadoli 	ctl_val |= ((timeout_val & 0xf) << SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT);
255bffde63dSSheetal Tigadoli 
256bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
257bffde63dSSheetal Tigadoli 		      ctl_val);
258bffde63dSSheetal Tigadoli 
259bffde63dSSheetal Tigadoli 	/* enable all interrupt status */
260bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET,
261bffde63dSSheetal Tigadoli 		      0);
262bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET,
263bffde63dSSheetal Tigadoli 		      0);
264bffde63dSSheetal Tigadoli 
265bffde63dSSheetal Tigadoli 	SD_US_DELAY(100);
266bffde63dSSheetal Tigadoli 
267bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET,
268bffde63dSSheetal Tigadoli 		      SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS);
269bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET,
270bffde63dSSheetal Tigadoli 		      SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS);
271bffde63dSSheetal Tigadoli 
272bffde63dSSheetal Tigadoli 	/* Select SD bus voltage */
273bffde63dSSheetal Tigadoli 	cap_val_l = mmio_read_32(handle->ctrl.sdRegBaseAddr +
274bffde63dSSheetal Tigadoli 				 SD4_EMMC_TOP_CAPABILITIES1_OFFSET);
275bffde63dSSheetal Tigadoli 	handle->cfg.voltage = 0;
276bffde63dSSheetal Tigadoli 	voltage = 0x7;
277bffde63dSSheetal Tigadoli 
278bffde63dSSheetal Tigadoli 	if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V33_MASK) {
279bffde63dSSheetal Tigadoli 		handle->cfg.voltage |= SD_VDD_WINDOW_3_3_TO_3_4;
280bffde63dSSheetal Tigadoli 		voltage = 0x7;
281bffde63dSSheetal Tigadoli 	} else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V3_MASK) {
282bffde63dSSheetal Tigadoli 		handle->cfg.voltage |= SD_VDD_WINDOW_3_0_TO_3_1;
283bffde63dSSheetal Tigadoli 		voltage = 0x6;
284bffde63dSSheetal Tigadoli 	} else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V18_MASK) {
285bffde63dSSheetal Tigadoli 		handle->cfg.voltage |= SD_VDD_WINDOW_1_8_TO_1_9;
286bffde63dSSheetal Tigadoli 		voltage = 0x5;
287bffde63dSSheetal Tigadoli 	}
288bffde63dSSheetal Tigadoli 
289bffde63dSSheetal Tigadoli 	rval = chal_sd_set_power(handle, voltage, SD4_EMMC_TOP_CTRL_SDPWR_MASK);
290bffde63dSSheetal Tigadoli 
291bffde63dSSheetal Tigadoli 	ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
292bffde63dSSheetal Tigadoli 			       SD4_EMMC_TOP_HCVERSIRQ_OFFSET);
293bffde63dSSheetal Tigadoli 	handle->ctrl.version = ((ctl_val >> 16) & 0xFF);
294bffde63dSSheetal Tigadoli 
295bffde63dSSheetal Tigadoli 	return rval;
296bffde63dSSheetal Tigadoli }
297bffde63dSSheetal Tigadoli 
chal_sd_set_speed(CHAL_HANDLE * sd_handle,uint32_t speed)298bffde63dSSheetal Tigadoli void chal_sd_set_speed(CHAL_HANDLE *sd_handle, uint32_t speed)
299bffde63dSSheetal Tigadoli {
300bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
301bffde63dSSheetal Tigadoli 
302bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
303bffde63dSSheetal Tigadoli 		return;
304bffde63dSSheetal Tigadoli 
305bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
306bffde63dSSheetal Tigadoli 
307bffde63dSSheetal Tigadoli 	if (speed) {
308bffde63dSSheetal Tigadoli 		EMMC_TRACE("enable HighSpeed\n");
309bffde63dSSheetal Tigadoli 		mmio_setbits_32(handle->ctrl.sdRegBaseAddr +
310bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_CTRL_OFFSET,
311bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_CTRL_HSEN_MASK);
312bffde63dSSheetal Tigadoli 	} else {
313bffde63dSSheetal Tigadoli 		EMMC_TRACE("disable HighSpeed\n");
314bffde63dSSheetal Tigadoli 		mmio_clrbits_32(handle->ctrl.sdRegBaseAddr +
315bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_CTRL_OFFSET,
316bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_CTRL_HSEN_MASK);
317bffde63dSSheetal Tigadoli 	}
318bffde63dSSheetal Tigadoli }
319bffde63dSSheetal Tigadoli 
chal_sd_stop(void)320bffde63dSSheetal Tigadoli int32_t chal_sd_stop(void)
321bffde63dSSheetal Tigadoli {
322bffde63dSSheetal Tigadoli 	uintptr_t idm_rst_ctrl_addr = EMMC_IDM_RESET_CTRL_ADDR;
323bffde63dSSheetal Tigadoli 
324bffde63dSSheetal Tigadoli 	/* Configure IO pins */
325bffde63dSSheetal Tigadoli 	emmc_soft_reset();
326bffde63dSSheetal Tigadoli 
327bffde63dSSheetal Tigadoli 	/* Reset the SDIO controller */
328bffde63dSSheetal Tigadoli 	mmio_write_32(idm_rst_ctrl_addr, 1);
329bffde63dSSheetal Tigadoli 	SD_US_DELAY(100);
330bffde63dSSheetal Tigadoli 	mmio_write_32(idm_rst_ctrl_addr, 0);
331bffde63dSSheetal Tigadoli 	SD_US_DELAY(100);
332bffde63dSSheetal Tigadoli 
333bffde63dSSheetal Tigadoli 	return SD_OK;
334bffde63dSSheetal Tigadoli }
335bffde63dSSheetal Tigadoli 
336bffde63dSSheetal Tigadoli /*
337bffde63dSSheetal Tigadoli  * Check if host supports specified capability
338bffde63dSSheetal Tigadoli  * returns -ve val on error, 0 if capability not supported else 1.
339bffde63dSSheetal Tigadoli  */
chal_sd_check_cap(CHAL_HANDLE * sd_handle,uint32_t caps)340bffde63dSSheetal Tigadoli int32_t chal_sd_check_cap(CHAL_HANDLE *sd_handle, uint32_t caps)
341bffde63dSSheetal Tigadoli {
342bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
343bffde63dSSheetal Tigadoli 
344bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
345bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
346bffde63dSSheetal Tigadoli 
347bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
348bffde63dSSheetal Tigadoli 
349bffde63dSSheetal Tigadoli 	if (caps & mmio_read_32(handle->ctrl.sdRegBaseAddr +
350bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_CAPABILITIES1_OFFSET))
351bffde63dSSheetal Tigadoli 		return 1;
352bffde63dSSheetal Tigadoli 	else
353bffde63dSSheetal Tigadoli 		return 0;
354bffde63dSSheetal Tigadoli }
355bffde63dSSheetal Tigadoli 
chal_sd_start(CHAL_HANDLE * sd_handle,uint32_t mode,uint32_t sd_base,uint32_t host_base)356bffde63dSSheetal Tigadoli int32_t chal_sd_start(CHAL_HANDLE *sd_handle,
357bffde63dSSheetal Tigadoli 		      uint32_t mode, uint32_t sd_base, uint32_t host_base)
358bffde63dSSheetal Tigadoli {
359bffde63dSSheetal Tigadoli 
360bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
361bffde63dSSheetal Tigadoli 	int32_t rval = SD_FAIL;
362bffde63dSSheetal Tigadoli 
363bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
364bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
365bffde63dSSheetal Tigadoli 
366bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
367bffde63dSSheetal Tigadoli 
368bffde63dSSheetal Tigadoli 	handle->cfg.mode = SD_PIO_MODE;	/* set to PIO mode first for init */
369bffde63dSSheetal Tigadoli 	handle->cfg.dma = SD_DMA_OFF;
370bffde63dSSheetal Tigadoli 
371bffde63dSSheetal Tigadoli 	chal_sd_setup_handler(handle, sd_base, host_base);
372bffde63dSSheetal Tigadoli 
373bffde63dSSheetal Tigadoli 	/* init and start hw */
374bffde63dSSheetal Tigadoli 	rval = chal_sd_init(sd_handle);
375bffde63dSSheetal Tigadoli 	if (rval != SD_OK)
376bffde63dSSheetal Tigadoli 		return rval;
377bffde63dSSheetal Tigadoli 
378bffde63dSSheetal Tigadoli 	chal_sd_clear_pending_irq(sd_handle);
379bffde63dSSheetal Tigadoli 
380bffde63dSSheetal Tigadoli 	handle->ctrl.eventList = 0;
381bffde63dSSheetal Tigadoli 	handle->cfg.mode = mode;
382bffde63dSSheetal Tigadoli 
383bffde63dSSheetal Tigadoli 	return SD_OK;
384bffde63dSSheetal Tigadoli }
385bffde63dSSheetal Tigadoli 
386bffde63dSSheetal Tigadoli /*
387bffde63dSSheetal Tigadoli  * Function to check 8bits of err generated from auto CMD12
388bffde63dSSheetal Tigadoli  */
chal_sd_get_atuo12_error(CHAL_HANDLE * sd_handle)389bffde63dSSheetal Tigadoli int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sd_handle)
390bffde63dSSheetal Tigadoli {
391bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
392bffde63dSSheetal Tigadoli 
393bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
394bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
395bffde63dSSheetal Tigadoli 
396bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
397bffde63dSSheetal Tigadoli 
398bffde63dSSheetal Tigadoli 	return (mmio_read_32(handle->ctrl.sdRegBaseAddr +
399bffde63dSSheetal Tigadoli 			     SD4_EMMC_TOP_ERRSTAT_OFFSET) & 0xFF);
400bffde63dSSheetal Tigadoli }
401bffde63dSSheetal Tigadoli 
402bffde63dSSheetal Tigadoli /*
403bffde63dSSheetal Tigadoli  * Read present state register
404bffde63dSSheetal Tigadoli  */
chal_sd_get_present_status(CHAL_HANDLE * sd_handle)405bffde63dSSheetal Tigadoli uint32_t chal_sd_get_present_status(CHAL_HANDLE *sd_handle)
406bffde63dSSheetal Tigadoli {
407bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
408bffde63dSSheetal Tigadoli 
409bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
410bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
411bffde63dSSheetal Tigadoli 
412bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
413bffde63dSSheetal Tigadoli 
414bffde63dSSheetal Tigadoli 	return mmio_read_32(handle->ctrl.sdRegBaseAddr +
415bffde63dSSheetal Tigadoli 			    SD4_EMMC_TOP_PSTATE_OFFSET);
416bffde63dSSheetal Tigadoli }
417bffde63dSSheetal Tigadoli 
418bffde63dSSheetal Tigadoli /*
419bffde63dSSheetal Tigadoli  * Set SD bus width
420bffde63dSSheetal Tigadoli  */
chal_sd_config_bus_width(CHAL_HANDLE * sd_handle,int32_t width)421bffde63dSSheetal Tigadoli int32_t chal_sd_config_bus_width(CHAL_HANDLE *sd_handle, int32_t width)
422bffde63dSSheetal Tigadoli {
423bffde63dSSheetal Tigadoli 	uint32_t ctl_val;
424bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
425bffde63dSSheetal Tigadoli 
426bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
427bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
428bffde63dSSheetal Tigadoli 
429bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *)sd_handle;
430bffde63dSSheetal Tigadoli 
431bffde63dSSheetal Tigadoli 	ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
432bffde63dSSheetal Tigadoli 			       SD4_EMMC_TOP_CTRL_OFFSET);
433bffde63dSSheetal Tigadoli 
434bffde63dSSheetal Tigadoli 	switch (width) {
435bffde63dSSheetal Tigadoli #ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT
436bffde63dSSheetal Tigadoli 	case SD_BUS_DATA_WIDTH_8BIT:
437bffde63dSSheetal Tigadoli 		ctl_val &= ~SD_BUS_DATA_WIDTH_4BIT;
438bffde63dSSheetal Tigadoli 		ctl_val |= SD_BUS_DATA_WIDTH_8BIT;
439bffde63dSSheetal Tigadoli 		break;
440bffde63dSSheetal Tigadoli #endif
441bffde63dSSheetal Tigadoli 	case SD_BUS_DATA_WIDTH_4BIT:
442bffde63dSSheetal Tigadoli 		ctl_val &= ~SD_BUS_DATA_WIDTH_8BIT;
443bffde63dSSheetal Tigadoli 		ctl_val |= SD_BUS_DATA_WIDTH_4BIT;
444bffde63dSSheetal Tigadoli 		break;
445bffde63dSSheetal Tigadoli 	case SD_BUS_DATA_WIDTH_1BIT:
446bffde63dSSheetal Tigadoli 		ctl_val &= ~(SD_BUS_DATA_WIDTH_4BIT | SD_BUS_DATA_WIDTH_8BIT);
447bffde63dSSheetal Tigadoli 		break;
448bffde63dSSheetal Tigadoli 	default:
449bffde63dSSheetal Tigadoli 		return SD_INV_DATA_WIDTH;
450bffde63dSSheetal Tigadoli 	};
451bffde63dSSheetal Tigadoli 
452bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET,
453bffde63dSSheetal Tigadoli 		      ctl_val);
454bffde63dSSheetal Tigadoli 
455bffde63dSSheetal Tigadoli 	return SD_OK;
456bffde63dSSheetal Tigadoli }
457bffde63dSSheetal Tigadoli 
458bffde63dSSheetal Tigadoli /*
459bffde63dSSheetal Tigadoli  * Function to enable or disable DMA control.
460bffde63dSSheetal Tigadoli  */
chal_sd_set_dma(CHAL_HANDLE * sd_handle,uint32_t mode)461bffde63dSSheetal Tigadoli int32_t chal_sd_set_dma(CHAL_HANDLE *sd_handle, uint32_t mode)
462bffde63dSSheetal Tigadoli {
463bffde63dSSheetal Tigadoli 	uint32_t val;
464bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
465bffde63dSSheetal Tigadoli 	int32_t rc;
466bffde63dSSheetal Tigadoli 
467bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
468bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
469bffde63dSSheetal Tigadoli 
470bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *)sd_handle;
471bffde63dSSheetal Tigadoli 
472bffde63dSSheetal Tigadoli 	if (mode) {
473bffde63dSSheetal Tigadoli 		rc = chal_sd_check_cap(sd_handle,
474bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK |
475bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK);
476bffde63dSSheetal Tigadoli 		if (rc < 0)
477bffde63dSSheetal Tigadoli 			return rc;
478bffde63dSSheetal Tigadoli 
479bffde63dSSheetal Tigadoli 		if (rc) {
480bffde63dSSheetal Tigadoli 
481bffde63dSSheetal Tigadoli 			handle->cfg.dma = mode;
482bffde63dSSheetal Tigadoli 			val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
483bffde63dSSheetal Tigadoli 					   SD4_EMMC_TOP_CTRL_OFFSET);
484bffde63dSSheetal Tigadoli 			val &= ~(SD4_EMMC_TOP_CTRL_DMASEL_MASK);
485bffde63dSSheetal Tigadoli 			val |= handle->cfg.dma - 1;
486bffde63dSSheetal Tigadoli 			mmio_write_32(handle->ctrl.sdRegBaseAddr +
487bffde63dSSheetal Tigadoli 				      SD4_EMMC_TOP_CTRL_OFFSET, val);
488bffde63dSSheetal Tigadoli 			return SD_OK;
489bffde63dSSheetal Tigadoli 		}
490bffde63dSSheetal Tigadoli 	}
491bffde63dSSheetal Tigadoli 	handle->cfg.dma = 0;
492bffde63dSSheetal Tigadoli 
493bffde63dSSheetal Tigadoli 	return SD_FAIL;
494bffde63dSSheetal Tigadoli }
495bffde63dSSheetal Tigadoli 
496bffde63dSSheetal Tigadoli /*
497bffde63dSSheetal Tigadoli  * Get current DMA address.
498bffde63dSSheetal Tigadoli  * Called only when there is no data transaction activity.
499bffde63dSSheetal Tigadoli  */
chal_sd_get_dma_addr(CHAL_HANDLE * sd_handle)500bffde63dSSheetal Tigadoli uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *sd_handle)
501bffde63dSSheetal Tigadoli {
502bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
503bffde63dSSheetal Tigadoli 
504bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
505bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
506bffde63dSSheetal Tigadoli 
507bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
508bffde63dSSheetal Tigadoli 
509bffde63dSSheetal Tigadoli 	if (handle->cfg.dma == SD_DMA_OFF)
510bffde63dSSheetal Tigadoli 		return 0;
511bffde63dSSheetal Tigadoli 
512bffde63dSSheetal Tigadoli 	return (uintptr_t)mmio_read_32(handle->ctrl.sdRegBaseAddr +
513bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_SYSADDR_OFFSET);
514bffde63dSSheetal Tigadoli }
515bffde63dSSheetal Tigadoli 
chal_sd_send_cmd(CHAL_HANDLE * sd_handle,uint32_t cmd_idx,uint32_t argument,uint32_t options)516bffde63dSSheetal Tigadoli int32_t chal_sd_send_cmd(CHAL_HANDLE *sd_handle, uint32_t cmd_idx,
517bffde63dSSheetal Tigadoli 			 uint32_t argument, uint32_t options)
518bffde63dSSheetal Tigadoli {
519bffde63dSSheetal Tigadoli 	uint32_t cmd_mode_reg = 0;
520bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
521bffde63dSSheetal Tigadoli 
522bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
523bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
524bffde63dSSheetal Tigadoli 
525bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
526bffde63dSSheetal Tigadoli 
527bffde63dSSheetal Tigadoli 	EMMC_TRACE("%s %d cmd:%d argReg:%x options:%x\n",
528bffde63dSSheetal Tigadoli 		   __func__, __LINE__, cmd_idx, argument, options);
529bffde63dSSheetal Tigadoli 
530bffde63dSSheetal Tigadoli 	/* Configure the value for command and mode registers */
531bffde63dSSheetal Tigadoli 	cmd_mode_reg = (cmd_idx << 24) | options;
532bffde63dSSheetal Tigadoli 
533bffde63dSSheetal Tigadoli 	/*
534bffde63dSSheetal Tigadoli 	 * 1. Write block size reg & block count reg,
535bffde63dSSheetal Tigadoli 	 * this is done in the tx or rx setup
536bffde63dSSheetal Tigadoli 	 */
537bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_BLOCK_OFFSET,
538bffde63dSSheetal Tigadoli 		      handle->ctrl.blkReg);
539bffde63dSSheetal Tigadoli 
540bffde63dSSheetal Tigadoli 	/* 2. Write argument reg */
541bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET,
542bffde63dSSheetal Tigadoli 		      argument);
543bffde63dSSheetal Tigadoli 	handle->ctrl.argReg = argument;
544bffde63dSSheetal Tigadoli 
545bffde63dSSheetal Tigadoli 	/*
546bffde63dSSheetal Tigadoli 	 * 3. Write transfer mode reg & command reg, check the DMA bit which is
547bffde63dSSheetal Tigadoli 	 *    set before this function call if it is selected.
548bffde63dSSheetal Tigadoli 	 */
549bffde63dSSheetal Tigadoli 	if (cmd_idx == 24 || cmd_idx == 25 || cmd_idx == 18 || cmd_idx == 17 ||
550bffde63dSSheetal Tigadoli 	    cmd_idx == 42 || cmd_idx == 51 || cmd_idx == 53)
551bffde63dSSheetal Tigadoli 		cmd_mode_reg |= ((handle->cfg.dma) ? 1 : 0);
552bffde63dSSheetal Tigadoli 
553bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET,
554bffde63dSSheetal Tigadoli 		      cmd_mode_reg);
555bffde63dSSheetal Tigadoli 
556bffde63dSSheetal Tigadoli 	handle->ctrl.cmdIndex = cmd_idx;
557bffde63dSSheetal Tigadoli 
558bffde63dSSheetal Tigadoli 	return SD_OK;
559bffde63dSSheetal Tigadoli }
560bffde63dSSheetal Tigadoli 
chal_sd_set_dma_addr(CHAL_HANDLE * sd_handle,uintptr_t address)561bffde63dSSheetal Tigadoli int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sd_handle, uintptr_t address)
562bffde63dSSheetal Tigadoli {
563bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
564bffde63dSSheetal Tigadoli 
565bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
566bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
567bffde63dSSheetal Tigadoli 
568bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
569bffde63dSSheetal Tigadoli 
570bffde63dSSheetal Tigadoli 	if (handle->cfg.dma == SD_DMA_OFF)
571bffde63dSSheetal Tigadoli 		return SD_FAIL;
572bffde63dSSheetal Tigadoli 
573bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET,
574bffde63dSSheetal Tigadoli 		      address);
575bffde63dSSheetal Tigadoli 	return SD_OK;
576bffde63dSSheetal Tigadoli }
577bffde63dSSheetal Tigadoli 
chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq)578bffde63dSSheetal Tigadoli uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq)
579bffde63dSSheetal Tigadoli {
580bffde63dSSheetal Tigadoli 	/*
581bffde63dSSheetal Tigadoli 	 * Divider control setting represents 1/2 of the actual divider value.
582bffde63dSSheetal Tigadoli 	 *
583bffde63dSSheetal Tigadoli 	 * DesiredFreq = BaseClockFreq / (2 * div_ctrl_setting)
584bffde63dSSheetal Tigadoli 	 *
585bffde63dSSheetal Tigadoli 	 * ==> div_ctrl_setting = BaseClockFreq / (2 * DesiredFreq)
586bffde63dSSheetal Tigadoli 	 */
587bffde63dSSheetal Tigadoli 	uint32_t div_ctrl_setting;
588bffde63dSSheetal Tigadoli 	uint32_t actual_freq;
589bffde63dSSheetal Tigadoli 
590bffde63dSSheetal Tigadoli 	assert(desired_freq != 0);
591bffde63dSSheetal Tigadoli 
592bffde63dSSheetal Tigadoli 	/* Special case, 0 = divider of 1. */
593bffde63dSSheetal Tigadoli 	if (desired_freq >= BASE_CLK_FREQ)
594bffde63dSSheetal Tigadoli 		return 0;
595bffde63dSSheetal Tigadoli 
596bffde63dSSheetal Tigadoli 	/* Normal case, desired_freq < BASE_CLK_FREQ */
597bffde63dSSheetal Tigadoli 	div_ctrl_setting = BASE_CLK_FREQ / (2 * desired_freq);
598bffde63dSSheetal Tigadoli 
599bffde63dSSheetal Tigadoli 	actual_freq = BASE_CLK_FREQ / (2 * div_ctrl_setting);
600bffde63dSSheetal Tigadoli 
601bffde63dSSheetal Tigadoli 	if (actual_freq > desired_freq) {
602bffde63dSSheetal Tigadoli 		/*
603*1b491eeaSElyes Haouas 		 * Division does not result in exact frequency match.
604bffde63dSSheetal Tigadoli 		 * Make sure resulting frequency does not exceed requested freq.
605bffde63dSSheetal Tigadoli 		 */
606bffde63dSSheetal Tigadoli 		div_ctrl_setting++;
607bffde63dSSheetal Tigadoli 	}
608bffde63dSSheetal Tigadoli 
609bffde63dSSheetal Tigadoli 	return div_ctrl_setting;
610bffde63dSSheetal Tigadoli }
611bffde63dSSheetal Tigadoli 
chal_sd_set_clock(CHAL_HANDLE * sd_handle,uint32_t div_ctrl_setting,uint32_t on)612bffde63dSSheetal Tigadoli int32_t chal_sd_set_clock(CHAL_HANDLE *sd_handle, uint32_t div_ctrl_setting,
613bffde63dSSheetal Tigadoli 			  uint32_t on)
614bffde63dSSheetal Tigadoli {
615bffde63dSSheetal Tigadoli 	uint32_t value;
616bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
617bffde63dSSheetal Tigadoli 	uint32_t time;
618bffde63dSSheetal Tigadoli 	uint32_t clk_sel_high_byte = 0xFF & (div_ctrl_setting >> 8);
619bffde63dSSheetal Tigadoli 	uint32_t clk_sel_low_byte = 0xFF & div_ctrl_setting;
620bffde63dSSheetal Tigadoli 
621bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
622bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
623bffde63dSSheetal Tigadoli 
624bffde63dSSheetal Tigadoli 	EMMC_TRACE("set_clock(div_ctrl_setting=%d,on=%d)\n",
625bffde63dSSheetal Tigadoli 		   div_ctrl_setting, on);
626bffde63dSSheetal Tigadoli 
627bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
628bffde63dSSheetal Tigadoli 
629bffde63dSSheetal Tigadoli 	/* Read control register content. */
630bffde63dSSheetal Tigadoli 	value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
631bffde63dSSheetal Tigadoli 			     SD4_EMMC_TOP_CTRL1_OFFSET);
632bffde63dSSheetal Tigadoli 
633bffde63dSSheetal Tigadoli 	/* Disable Clock */
634bffde63dSSheetal Tigadoli 	value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK);
635bffde63dSSheetal Tigadoli 
636bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
637bffde63dSSheetal Tigadoli 		      value);
638bffde63dSSheetal Tigadoli 
639bffde63dSSheetal Tigadoli 	/* Clear bits of interest. */
640bffde63dSSheetal Tigadoli 	value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK |
641bffde63dSSheetal Tigadoli 		   SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK);
642bffde63dSSheetal Tigadoli 
643bffde63dSSheetal Tigadoli 	/* Set bits of interest to new value. */
644bffde63dSSheetal Tigadoli 	value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK &
645bffde63dSSheetal Tigadoli 		  (clk_sel_low_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT));
646bffde63dSSheetal Tigadoli 	value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK &
647bffde63dSSheetal Tigadoli 		  (clk_sel_high_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT));
648bffde63dSSheetal Tigadoli 	value |= SD4_EMMC_TOP_CTRL1_ICLKEN_MASK;
649bffde63dSSheetal Tigadoli 
650bffde63dSSheetal Tigadoli 	/* Write updated value back to control register. */
651bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
652bffde63dSSheetal Tigadoli 		      value);
653bffde63dSSheetal Tigadoli 
654bffde63dSSheetal Tigadoli 	time = 0;
655bffde63dSSheetal Tigadoli 	do {
656bffde63dSSheetal Tigadoli 		value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
657bffde63dSSheetal Tigadoli 				     SD4_EMMC_TOP_CTRL1_OFFSET);
658bffde63dSSheetal Tigadoli 
659bffde63dSSheetal Tigadoli 		if ((value & SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK) ==
660bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK)
661bffde63dSSheetal Tigadoli 			break;
662bffde63dSSheetal Tigadoli 
663bffde63dSSheetal Tigadoli 		mdelay(1);
664bffde63dSSheetal Tigadoli 	} while (time++ < EMMC_CLOCK_SETTING_TIMEOUT_MS);
665bffde63dSSheetal Tigadoli 
666bffde63dSSheetal Tigadoli 	if (time >= EMMC_CLOCK_SETTING_TIMEOUT_MS)
667bffde63dSSheetal Tigadoli 		WARN("%s %d clock settings timeout happenedi (%dms)\n",
668bffde63dSSheetal Tigadoli 			 __func__, __LINE__, time);
669bffde63dSSheetal Tigadoli 
670bffde63dSSheetal Tigadoli 	VERBOSE("EMMC: clock settings delay: %dms\n", time);
671bffde63dSSheetal Tigadoli 
672bffde63dSSheetal Tigadoli 	value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
673bffde63dSSheetal Tigadoli 			     SD4_EMMC_TOP_CTRL1_OFFSET);
674bffde63dSSheetal Tigadoli 
675bffde63dSSheetal Tigadoli 	if (on)
676bffde63dSSheetal Tigadoli 		value |= SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK;
677bffde63dSSheetal Tigadoli 
678bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
679bffde63dSSheetal Tigadoli 		      value);
680bffde63dSSheetal Tigadoli 
681bffde63dSSheetal Tigadoli 	return SD_OK;
682bffde63dSSheetal Tigadoli }
683bffde63dSSheetal Tigadoli 
684bffde63dSSheetal Tigadoli /*
685bffde63dSSheetal Tigadoli  * function to setup DMA buffer and data length, calculates block
686bffde63dSSheetal Tigadoli  * size and the number of blocks to be transferred and return
687bffde63dSSheetal Tigadoli  * the DMA buffer address.
688bffde63dSSheetal Tigadoli  */
chal_sd_setup_xfer(CHAL_HANDLE * sd_handle,uint8_t * data,uint32_t length,int32_t dir)689bffde63dSSheetal Tigadoli int32_t chal_sd_setup_xfer(CHAL_HANDLE *sd_handle,
690bffde63dSSheetal Tigadoli 			   uint8_t *data, uint32_t length, int32_t dir)
691bffde63dSSheetal Tigadoli {
692bffde63dSSheetal Tigadoli 	uint32_t blocks = 0;
693bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
694bffde63dSSheetal Tigadoli 
695bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
696bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
697bffde63dSSheetal Tigadoli 
698bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
699bffde63dSSheetal Tigadoli 
700bffde63dSSheetal Tigadoli 	if (length <= handle->cfg.blockSize) {
701bffde63dSSheetal Tigadoli 		handle->ctrl.blkReg = length | handle->cfg.dmaBoundary;
702bffde63dSSheetal Tigadoli 	} else {
703bffde63dSSheetal Tigadoli 		blocks = length / handle->cfg.blockSize;
704bffde63dSSheetal Tigadoli 		handle->ctrl.blkReg = (blocks << 16) | handle->cfg.blockSize |
705bffde63dSSheetal Tigadoli 					handle->cfg.dmaBoundary;
706bffde63dSSheetal Tigadoli 	}
707bffde63dSSheetal Tigadoli 
708bffde63dSSheetal Tigadoli 	if (handle->cfg.dma != SD_DMA_OFF) {
709bffde63dSSheetal Tigadoli 		/* For DMA target address setting, physical address should be used */
710bffde63dSSheetal Tigadoli 		mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET,
711bffde63dSSheetal Tigadoli 				(uintptr_t)data);
712bffde63dSSheetal Tigadoli 	}
713bffde63dSSheetal Tigadoli 
714bffde63dSSheetal Tigadoli 	return SD_OK;
715bffde63dSSheetal Tigadoli }
716bffde63dSSheetal Tigadoli 
717bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
718bffde63dSSheetal Tigadoli /*
719bffde63dSSheetal Tigadoli  * function to write one block data directly to the
720bffde63dSSheetal Tigadoli  * host controller's FIFO which is 1K uint8_t or
721bffde63dSSheetal Tigadoli  * 2K uint8_t in size.
722bffde63dSSheetal Tigadoli  * It is used in Non-DMA mode for data transmission.
723bffde63dSSheetal Tigadoli  */
chal_sd_write_buffer(CHAL_HANDLE * sd_handle,uint32_t length,uint8_t * data)724bffde63dSSheetal Tigadoli int32_t chal_sd_write_buffer(CHAL_HANDLE *sd_handle, uint32_t length,
725bffde63dSSheetal Tigadoli 			     uint8_t *data)
726bffde63dSSheetal Tigadoli {
727bffde63dSSheetal Tigadoli 	uint32_t i, leftOver = 0, blockSize, size, value = 0;
728bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
729bffde63dSSheetal Tigadoli 
730bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
731bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
732bffde63dSSheetal Tigadoli 
733bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
734bffde63dSSheetal Tigadoli 
735bffde63dSSheetal Tigadoli 	blockSize = handle->cfg.blockSize;
736bffde63dSSheetal Tigadoli 
737bffde63dSSheetal Tigadoli 	if (length == 0)
738bffde63dSSheetal Tigadoli 		return SD_OK;
739bffde63dSSheetal Tigadoli 
740bffde63dSSheetal Tigadoli 	/* PIO mode, push into fifo word by word */
741bffde63dSSheetal Tigadoli 	if (length >= blockSize) {
742bffde63dSSheetal Tigadoli 		size = blockSize;
743bffde63dSSheetal Tigadoli 	} else {
744bffde63dSSheetal Tigadoli 		size = ((length >> 2) << 2);
745bffde63dSSheetal Tigadoli 		leftOver = length % 4;
746bffde63dSSheetal Tigadoli 	}
747bffde63dSSheetal Tigadoli 
748bffde63dSSheetal Tigadoli 	for (i = 0; i < size; i += 4) {
749bffde63dSSheetal Tigadoli 		value = *(uint32_t *)(data + i);
750bffde63dSSheetal Tigadoli 		mmio_write_32(handle->ctrl.sdRegBaseAddr +
751bffde63dSSheetal Tigadoli 			      SD4_EMMC_TOP_BUFDAT_OFFSET, value);
752bffde63dSSheetal Tigadoli 	}
753bffde63dSSheetal Tigadoli /*
754bffde63dSSheetal Tigadoli  * BUG ALERT:
755bffde63dSSheetal Tigadoli  *    This implementation has TWO issues that must be addressed before you
756bffde63dSSheetal Tigadoli  *    can safely INCLUDE_EMMC_DRIVER_WRITE_CODE.
757bffde63dSSheetal Tigadoli  *
758bffde63dSSheetal Tigadoli  *    (1) For the last leftOver bytes, driver writes full word, which means
759bffde63dSSheetal Tigadoli  *        some of the eMMC content (i.e. "4 - leftOver" will be erroneously
760bffde63dSSheetal Tigadoli  *        overwritten).
761bffde63dSSheetal Tigadoli  *    (2) eMMC is a block device. What happens when less than a full block of
762bffde63dSSheetal Tigadoli  *        data is submitted???
763bffde63dSSheetal Tigadoli  */
764bffde63dSSheetal Tigadoli 	if (leftOver > 0) {
765bffde63dSSheetal Tigadoli 		value = ((*(uint32_t *)(data + i)) << (4 - leftOver));
766bffde63dSSheetal Tigadoli 		mmio_write_32(handle->ctrl.sdRegBaseAddr +
767bffde63dSSheetal Tigadoli 			      SD4_EMMC_TOP_BUFDAT_OFFSET, value);
768bffde63dSSheetal Tigadoli 	}
769bffde63dSSheetal Tigadoli 
770bffde63dSSheetal Tigadoli 	return SD_OK;
771bffde63dSSheetal Tigadoli }
772bffde63dSSheetal Tigadoli #endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
773bffde63dSSheetal Tigadoli 
774bffde63dSSheetal Tigadoli /*
775bffde63dSSheetal Tigadoli  * Function to read maximal one block data directly
776bffde63dSSheetal Tigadoli  * from the data port of the host controller (FIFO). It is used
777bffde63dSSheetal Tigadoli  * in Non-DMA mode for data transmission.
778bffde63dSSheetal Tigadoli  */
chal_sd_read_buffer(CHAL_HANDLE * sd_handle,uint32_t length,uint8_t * data)779bffde63dSSheetal Tigadoli int32_t chal_sd_read_buffer(CHAL_HANDLE *sd_handle, uint32_t length,
780bffde63dSSheetal Tigadoli 			    uint8_t *data)
781bffde63dSSheetal Tigadoli {
782bffde63dSSheetal Tigadoli 	uint32_t i, size, leftOver, blockSize, value;
783bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
784bffde63dSSheetal Tigadoli 
785bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
786bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
787bffde63dSSheetal Tigadoli 
788bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *)sd_handle;
789bffde63dSSheetal Tigadoli 
790bffde63dSSheetal Tigadoli 	value = 0;
791bffde63dSSheetal Tigadoli 
792bffde63dSSheetal Tigadoli 	blockSize = handle->cfg.blockSize;
793bffde63dSSheetal Tigadoli 
794bffde63dSSheetal Tigadoli 	/* PIO mode, extract fifo word by word */
795bffde63dSSheetal Tigadoli 	if (length >= blockSize) {
796bffde63dSSheetal Tigadoli 		size = blockSize;
797bffde63dSSheetal Tigadoli 		leftOver = 0;
798bffde63dSSheetal Tigadoli 	} else {
799bffde63dSSheetal Tigadoli 		leftOver = length % 4;
800bffde63dSSheetal Tigadoli 		size = ((length >> 2) << 2);
801bffde63dSSheetal Tigadoli 	}
802bffde63dSSheetal Tigadoli 
803bffde63dSSheetal Tigadoli 	for (i = 0; i < size; i += 4) {
804bffde63dSSheetal Tigadoli 		value =
805bffde63dSSheetal Tigadoli 		    mmio_read_32(handle->ctrl.sdRegBaseAddr +
806bffde63dSSheetal Tigadoli 				    SD4_EMMC_TOP_BUFDAT_OFFSET);
807bffde63dSSheetal Tigadoli 		memcpy((void *)(data + i), &value, sizeof(uint32_t));
808bffde63dSSheetal Tigadoli 	}
809bffde63dSSheetal Tigadoli 
810bffde63dSSheetal Tigadoli 	if (leftOver > 0) {
811bffde63dSSheetal Tigadoli 		value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
812bffde63dSSheetal Tigadoli 				     SD4_EMMC_TOP_BUFDAT_OFFSET);
813bffde63dSSheetal Tigadoli 
814bffde63dSSheetal Tigadoli 		/*
815bffde63dSSheetal Tigadoli 		 * Copy remaining non-full word bytes.
816bffde63dSSheetal Tigadoli 		 * (We run ARM as Little Endian)
817bffde63dSSheetal Tigadoli 		 */
818bffde63dSSheetal Tigadoli 		uint8_t j = 0;
819bffde63dSSheetal Tigadoli 
820bffde63dSSheetal Tigadoli 		for (j = 0; j < leftOver; j++) {
821bffde63dSSheetal Tigadoli 			data[i + j] = (value >> (j * 8)) & 0xFF;
822bffde63dSSheetal Tigadoli 		}
823bffde63dSSheetal Tigadoli 	}
824bffde63dSSheetal Tigadoli 
825bffde63dSSheetal Tigadoli 	return SD_OK;
826bffde63dSSheetal Tigadoli }
827bffde63dSSheetal Tigadoli 
828bffde63dSSheetal Tigadoli /*
829bffde63dSSheetal Tigadoli  * Resets both DAT or CMD line.
830bffde63dSSheetal Tigadoli  */
chal_sd_reset_line(CHAL_HANDLE * sd_handle,uint32_t line)831bffde63dSSheetal Tigadoli int32_t chal_sd_reset_line(CHAL_HANDLE *sd_handle, uint32_t line)
832bffde63dSSheetal Tigadoli {
833bffde63dSSheetal Tigadoli 	uint32_t control, flag;
834bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
835bffde63dSSheetal Tigadoli 
836bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
837bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
838bffde63dSSheetal Tigadoli 
839bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
840bffde63dSSheetal Tigadoli 
841bffde63dSSheetal Tigadoli 	flag = SD4_EMMC_TOP_CTRL1_CMDRST_MASK | SD4_EMMC_TOP_CTRL1_DATRST_MASK;
842bffde63dSSheetal Tigadoli 
843bffde63dSSheetal Tigadoli 	if (flag != (line | flag))
844bffde63dSSheetal Tigadoli 		return SD_FAIL;
845bffde63dSSheetal Tigadoli 
846bffde63dSSheetal Tigadoli 	control = mmio_read_32(handle->ctrl.sdRegBaseAddr +
847bffde63dSSheetal Tigadoli 			       SD4_EMMC_TOP_CTRL1_OFFSET);
848bffde63dSSheetal Tigadoli 	control |= line;
849bffde63dSSheetal Tigadoli 	mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
850bffde63dSSheetal Tigadoli 		      control);
851bffde63dSSheetal Tigadoli 
852bffde63dSSheetal Tigadoli 	/* reset CMD and DATA line should always work, no need to timed out */
853bffde63dSSheetal Tigadoli 	do {
854bffde63dSSheetal Tigadoli 		control = mmio_read_32(handle->ctrl.sdRegBaseAddr +
855bffde63dSSheetal Tigadoli 				       SD4_EMMC_TOP_CTRL1_OFFSET);
856bffde63dSSheetal Tigadoli 	} while (control & line);
857bffde63dSSheetal Tigadoli 
858bffde63dSSheetal Tigadoli 	return SD_OK;
859bffde63dSSheetal Tigadoli }
860bffde63dSSheetal Tigadoli 
861bffde63dSSheetal Tigadoli /*
862bffde63dSSheetal Tigadoli  * Function to be called once a SD command is done to read
863bffde63dSSheetal Tigadoli  * back it's response data.
864bffde63dSSheetal Tigadoli  */
chal_sd_get_response(CHAL_HANDLE * sd_handle,uint32_t * resp)865bffde63dSSheetal Tigadoli int32_t chal_sd_get_response(CHAL_HANDLE *sd_handle, uint32_t *resp)
866bffde63dSSheetal Tigadoli {
867bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
868bffde63dSSheetal Tigadoli 
869bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
870bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
871bffde63dSSheetal Tigadoli 
872bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
873bffde63dSSheetal Tigadoli 	resp[0] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
874bffde63dSSheetal Tigadoli 			       SD4_EMMC_TOP_RESP0_OFFSET);
875bffde63dSSheetal Tigadoli 	resp[1] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
876bffde63dSSheetal Tigadoli 			       SD4_EMMC_TOP_RESP2_OFFSET);
877bffde63dSSheetal Tigadoli 	resp[2] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
878bffde63dSSheetal Tigadoli 			       SD4_EMMC_TOP_RESP4_OFFSET);
879bffde63dSSheetal Tigadoli 	resp[3] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
880bffde63dSSheetal Tigadoli 			       SD4_EMMC_TOP_RESP6_OFFSET);
881bffde63dSSheetal Tigadoli 
882bffde63dSSheetal Tigadoli 	return SD_OK;
883bffde63dSSheetal Tigadoli }
884bffde63dSSheetal Tigadoli 
885bffde63dSSheetal Tigadoli /*
886bffde63dSSheetal Tigadoli  * The function is called to clean all the pending interrupts.
887bffde63dSSheetal Tigadoli  */
chal_sd_clear_pending_irq(CHAL_HANDLE * sd_handle)888bffde63dSSheetal Tigadoli int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sd_handle)
889bffde63dSSheetal Tigadoli {
890bffde63dSSheetal Tigadoli 	uint32_t status = SD_OK;
891bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
892bffde63dSSheetal Tigadoli 
893bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
894bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
895bffde63dSSheetal Tigadoli 
896bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *)sd_handle;
897bffde63dSSheetal Tigadoli 
898bffde63dSSheetal Tigadoli 	/* Make sure clean all interrupts */
899bffde63dSSheetal Tigadoli 	do {
900bffde63dSSheetal Tigadoli 		mmio_write_32(handle->ctrl.sdRegBaseAddr +
901bffde63dSSheetal Tigadoli 			      SD4_EMMC_TOP_INTR_OFFSET, 0xFFFFFFFF);
902bffde63dSSheetal Tigadoli 		SD_US_DELAY(10);
903bffde63dSSheetal Tigadoli 	} while (mmio_read_32(handle->ctrl.sdRegBaseAddr +
904bffde63dSSheetal Tigadoli 			      SD4_EMMC_TOP_INTR_OFFSET));
905bffde63dSSheetal Tigadoli 
906bffde63dSSheetal Tigadoli 	return status;
907bffde63dSSheetal Tigadoli }
908bffde63dSSheetal Tigadoli 
909bffde63dSSheetal Tigadoli /*
910bffde63dSSheetal Tigadoli  * The function returns interrupt status register value.
911bffde63dSSheetal Tigadoli  */
chal_sd_get_irq_status(CHAL_HANDLE * sd_handle)912bffde63dSSheetal Tigadoli int32_t chal_sd_get_irq_status(CHAL_HANDLE *sd_handle)
913bffde63dSSheetal Tigadoli {
914bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
915bffde63dSSheetal Tigadoli 
916bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
917bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
918bffde63dSSheetal Tigadoli 
919bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
920bffde63dSSheetal Tigadoli 
921bffde63dSSheetal Tigadoli 	return (mmio_read_32(handle->ctrl.sdRegBaseAddr +
922bffde63dSSheetal Tigadoli 			     SD4_EMMC_TOP_INTR_OFFSET));
923bffde63dSSheetal Tigadoli }
924bffde63dSSheetal Tigadoli 
925bffde63dSSheetal Tigadoli /*
926bffde63dSSheetal Tigadoli  * The function clears interrupt(s) specified in the mask.
927bffde63dSSheetal Tigadoli  */
chal_sd_clear_irq(CHAL_HANDLE * sd_handle,uint32_t mask)928bffde63dSSheetal Tigadoli int32_t chal_sd_clear_irq(CHAL_HANDLE *sd_handle, uint32_t mask)
929bffde63dSSheetal Tigadoli {
930bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
931bffde63dSSheetal Tigadoli 
932bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
933bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
934bffde63dSSheetal Tigadoli 
935bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
936bffde63dSSheetal Tigadoli 
937bffde63dSSheetal Tigadoli 	/* Make sure clean masked interrupts */
938bffde63dSSheetal Tigadoli 	do {
939bffde63dSSheetal Tigadoli 		mmio_write_32(handle->ctrl.sdRegBaseAddr +
940bffde63dSSheetal Tigadoli 			      SD4_EMMC_TOP_INTR_OFFSET, mask);
941bffde63dSSheetal Tigadoli 		SD_US_DELAY(10);
942bffde63dSSheetal Tigadoli 	} while (mask &
943bffde63dSSheetal Tigadoli 		 mmio_read_32(handle->ctrl.sdRegBaseAddr +
944bffde63dSSheetal Tigadoli 			      SD4_EMMC_TOP_INTR_OFFSET));
945bffde63dSSheetal Tigadoli 
946bffde63dSSheetal Tigadoli 	return SD_OK;
947bffde63dSSheetal Tigadoli }
948bffde63dSSheetal Tigadoli 
949bffde63dSSheetal Tigadoli /*
950bffde63dSSheetal Tigadoli  * Description: The function configures the SD host controller.
951bffde63dSSheetal Tigadoli  */
chal_sd_config(CHAL_HANDLE * sd_handle,uint32_t speed,uint32_t retry,uint32_t boundary,uint32_t blkSize,uint32_t dma)952bffde63dSSheetal Tigadoli int32_t chal_sd_config(CHAL_HANDLE *sd_handle, uint32_t speed, uint32_t retry,
953bffde63dSSheetal Tigadoli 		       uint32_t boundary, uint32_t blkSize, uint32_t dma)
954bffde63dSSheetal Tigadoli {
955bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
956bffde63dSSheetal Tigadoli 
957bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
958bffde63dSSheetal Tigadoli 		return SD_INVALID_HANDLE;
959bffde63dSSheetal Tigadoli 
960bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *) sd_handle;
961bffde63dSSheetal Tigadoli 
962bffde63dSSheetal Tigadoli 	handle->cfg.speedMode = speed;
963bffde63dSSheetal Tigadoli 	handle->cfg.retryLimit = retry;
964bffde63dSSheetal Tigadoli 	handle->cfg.dmaBoundary = boundary;
965bffde63dSSheetal Tigadoli 	handle->cfg.blockSize = blkSize;
966bffde63dSSheetal Tigadoli 
967bffde63dSSheetal Tigadoli 	chal_sd_set_dma(sd_handle, dma);
968bffde63dSSheetal Tigadoli 	SD_US_DELAY(100);
969bffde63dSSheetal Tigadoli 	chal_sd_set_dma_boundary(handle, boundary);
970bffde63dSSheetal Tigadoli 	SD_US_DELAY(100);
971bffde63dSSheetal Tigadoli 
972bffde63dSSheetal Tigadoli 	chal_sd_set_speed(sd_handle, speed);
973bffde63dSSheetal Tigadoli 
974bffde63dSSheetal Tigadoli 	SD_US_DELAY(100);
975bffde63dSSheetal Tigadoli 	return SD_OK;
976bffde63dSSheetal Tigadoli }
977bffde63dSSheetal Tigadoli 
978bffde63dSSheetal Tigadoli /*
979bffde63dSSheetal Tigadoli  * Cleans up HC FIFO.
980bffde63dSSheetal Tigadoli  */
chal_sd_dump_fifo(CHAL_HANDLE * sd_handle)981bffde63dSSheetal Tigadoli void chal_sd_dump_fifo(CHAL_HANDLE *sd_handle)
982bffde63dSSheetal Tigadoli {
983bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
984bffde63dSSheetal Tigadoli 
985bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
986bffde63dSSheetal Tigadoli 		return;
987bffde63dSSheetal Tigadoli 
988bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *)sd_handle;
989bffde63dSSheetal Tigadoli 
990bffde63dSSheetal Tigadoli 	/* in case there still data in the host buffer */
991bffde63dSSheetal Tigadoli 	while (mmio_read_32(handle->ctrl.sdRegBaseAddr +
992bffde63dSSheetal Tigadoli 			    SD4_EMMC_TOP_PSTATE_OFFSET) & 0x800) {
993bffde63dSSheetal Tigadoli 		mmio_read_32(handle->ctrl.sdRegBaseAddr +
994bffde63dSSheetal Tigadoli 			     SD4_EMMC_TOP_BUFDAT_OFFSET);
995bffde63dSSheetal Tigadoli 	};
996bffde63dSSheetal Tigadoli }
997bffde63dSSheetal Tigadoli 
998bffde63dSSheetal Tigadoli /*
999bffde63dSSheetal Tigadoli  * Enable or disable a SD interrupt signal.
1000bffde63dSSheetal Tigadoli  */
chal_sd_set_irq_signal(CHAL_HANDLE * sd_handle,uint32_t mask,uint32_t state)1001bffde63dSSheetal Tigadoli void chal_sd_set_irq_signal(CHAL_HANDLE *sd_handle, uint32_t mask,
1002bffde63dSSheetal Tigadoli 			    uint32_t state)
1003bffde63dSSheetal Tigadoli {
1004bffde63dSSheetal Tigadoli 	struct sd_dev *handle;
1005bffde63dSSheetal Tigadoli 
1006bffde63dSSheetal Tigadoli 	if (sd_handle == NULL)
1007bffde63dSSheetal Tigadoli 		return;
1008bffde63dSSheetal Tigadoli 
1009bffde63dSSheetal Tigadoli 	handle = (struct sd_dev *)sd_handle;
1010bffde63dSSheetal Tigadoli 
1011bffde63dSSheetal Tigadoli 	if (state)
1012bffde63dSSheetal Tigadoli 		mmio_setbits_32(handle->ctrl.sdRegBaseAddr +
1013bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_INTREN2_OFFSET, mask);
1014bffde63dSSheetal Tigadoli 	else
1015bffde63dSSheetal Tigadoli 		mmio_clrbits_32(handle->ctrl.sdRegBaseAddr +
1016bffde63dSSheetal Tigadoli 				SD4_EMMC_TOP_INTREN2_OFFSET, mask);
1017bffde63dSSheetal Tigadoli }
1018