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