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