blob: 860a42e99240e4990febbc2e86035f57255715bf [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2 *
3 * (C)Copyright 2005 - 2011 Marvell. All Rights Reserved.
4 *
5 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
6 * The copyright notice above does not evidence any actual or intended
7 * publication of such source code.
8 * This Module contains Proprietary Information of Marvell and should be
9 * treated as Confidential.
10 * The information in this file is provided for the exclusive use of the
11 * licensees of Marvell.
12 * Such users have the right to use, modify, and incorporate this code into
13 * products for purposes authorized by the license agreement provided they
14 * include this notice and the associated copyright notice with any such
15 * product.
16 * The information in this file is provided "AS IS" without warranty.
17 *
18 ******************************************************************************/
19
20/******************************************************************************
21**
22** FILENAME: sdhc_controller.c
23**
24** PURPOSE: MMC and SD specific low level controller routines for the MM4 controller
25**
26**
27**
28**
29******************************************************************************/
30#include "sdhc2_controller.h"
31#include "misc.h"
32#include "Errors.h"
33#include "timer.h"
34
35void MMC4Gen74Clocks(P_MM4_SDMMC_CONTEXT_T pContext)
36{
37 P_MM4_SD_LEGACY_CTRL_REG pMM4_SD_LEGACY_CTRL_REG;
38 P_MM4_CTRL_REG pP_MM4_CTRL_REG;
39 UINT_T startTime, endTime;
40 UINT_T retval = NoError;
41
42 pMM4_SD_LEGACY_CTRL_REG = (P_MM4_SD_LEGACY_CTRL_REG)&pContext->pMMC4Reg->mm4_legacy_ctrl_reg;
43 pP_MM4_CTRL_REG = (P_MM4_CTRL_REG)&pContext->pMMC4Reg->mm4_mmc_ctrl_reg;
44
45 // Enable capturing status for sending out 74 clock cycles.
46 pP_MM4_CTRL_REG->misc_int_en = 1;
47 pP_MM4_CTRL_REG->misc_int = 1;
48
49 // Enable and start 74 clock cycles
50 pMM4_SD_LEGACY_CTRL_REG->gen_pad_clk_cnt = 74; // 74 clock cycles.
51 pMM4_SD_LEGACY_CTRL_REG->gen_pad_clk_on = 1; // Start generating the clocks.
52
53 // Wait for the 74 clock cycles to be generated.
54 startTime = GetOSCR0();
55 startTime = GetOSCR0();
56 do
57 {
58 if (pP_MM4_CTRL_REG->misc_int)
59 break; // 74 clock cycles have been generated.
60
61 endTime = GetOSCR0();
62
63 if (OSCR0IntervalInMilli(startTime, endTime) >= 10)
64 return SDMMCInitializationError;
65 }while(1);
66
67 return retval;
68}
69
70/******************************************************************************
71 Description:
72 Start MMC/SD Internal bus clock. MUST be done to start MM4CLK!
73 Only after starting bus clock, communication between
74 controller and card is possible
75 Input Parameters:
76 pContext--Pointer to MMC context structure
77 Output Parameters:
78 None
79 Returns:
80 None
81*******************************************************************************/
82void MMC4StartInternalBusClock(P_MM4_SDMMC_CONTEXT_T pContext)
83{
84 P_MM4_CNTL2 pMM4_CNTL2;
85 MM4_CNTL2_UNION MM4_cntl2;
86
87 pMM4_CNTL2 = (P_MM4_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_cntl2);
88 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
89 MM4_cntl2.mm4_cntl2_bits.inter_clk_en = 1;
90 *(VUINT_T *)pMM4_CNTL2 = MM4_cntl2.mm4_cntl2_value;
91
92 // Wait for clock to become stable. * TBD * Add timeout
93 do
94 {
95 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
96 } while (!(MM4_cntl2.mm4_cntl2_bits.inter_clk_stable));
97
98 return;
99}
100
101/******************************************************************************
102 Description:
103 Stops the MMC/SD Internal bus clock.
104 Input Parameters:
105 pContext--Pointer to MMC context structure
106 Output Parameters:
107 None
108 Returns:
109 None
110*******************************************************************************/
111void MMC4StopInternalBusClock(P_MM4_SDMMC_CONTEXT_T pContext)
112{
113 P_MM4_CNTL2 pMM4_CNTL2;
114 MM4_CNTL2_UNION MM4_cntl2;
115
116 pMM4_CNTL2 = (P_MM4_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_cntl2);
117 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
118 MM4_cntl2.mm4_cntl2_bits.inter_clk_en = 0;
119 *(VUINT_T *)pMM4_CNTL2 = MM4_cntl2.mm4_cntl2_value;
120
121 // Wait for clock to become stable. * TBD * Add timeout
122 do
123 {
124 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
125 } while (MM4_cntl2.mm4_cntl2_bits.inter_clk_stable);
126
127 return;
128}
129
130
131/******************************************************************************
132 Description:
133 Start MMC bus clock. Only after starting bus clock, communication between
134 controller and card is possible
135 Input Parameters:
136 pContext--Pointer to MMC context structure
137 Output Parameters:
138 None
139 Returns:
140 None
141*******************************************************************************/
142void MMC4StartBusClock(P_MM4_SDMMC_CONTEXT_T pContext)
143{
144 P_MM4_CNTL2 pMM4_CNTL2;
145 MM4_CNTL2_UNION MM4_cntl2;
146
147 pMM4_CNTL2 = (P_MM4_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_cntl2);
148 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
149 MM4_cntl2.mm4_cntl2_bits.mm4clken = 1;
150
151 *(VUINT_T *)pMM4_CNTL2 = MM4_cntl2.mm4_cntl2_value;
152 return;
153}
154
155/******************************************************************************
156 Description:
157 Stops MMC bus clock.
158 Input Parameters:
159 pContext--Pointer to MMC context structure
160 Output Parameters:
161 None
162 Returns:
163 None
164*******************************************************************************/
165void MMC4StopBusClock (P_MM4_SDMMC_CONTEXT_T pContext)
166{
167 P_MM4_CNTL2 pMM4_CNTL2;
168 MM4_CNTL2_UNION MM4_cntl2;
169
170 // Request bus clock stop
171 pMM4_CNTL2 = (P_MM4_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_cntl2);
172 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
173 MM4_cntl2.mm4_cntl2_bits.mm4clken = 0;
174 *(VUINT_T *)pMM4_CNTL2 = MM4_cntl2.mm4_cntl2_value;
175
176 return;
177}
178
179/******************************************************************************
180 Description:
181 Set a new MMC bus clock rate. This function stops and resumes bus clock.
182 Input Parameters:
183 pContext
184 Pointer to MMC context structure
185 rate
186 bus clock speed
187 Output Parameters:
188 None
189 Returns:
190 None
191*******************************************************************************/
192void MMC4SetBusRate(P_MM4_SDMMC_CONTEXT_T pContext, UINT_T rate)
193{
194 P_MM4_CNTL2 pMM4_CNTL2;
195 MM4_CNTL2_UNION MM4_cntl2;
196
197 // Request bus clock stop, set rate, start clock.
198 MMC4StopBusClock (pContext);
199 pMM4_CNTL2 = (P_MM4_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_cntl2);
200 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
201
202 // Update the rate and start the clock.
203 MM4_cntl2.mm4_cntl2_bits.sd_freq_sel_lo = (rate & 0xFF);
204 MM4_cntl2.mm4_cntl2_bits.sd_freq_sel_hi = ((rate >> 8) & 3);
205 MM4_cntl2.mm4_cntl2_bits.mm4clken = 1;
206 *(VUINT_T *)pMM4_CNTL2 = MM4_cntl2.mm4_cntl2_value;
207
208 // Make sure internal bus clock also enabled.
209 MMC4StartInternalBusClock(pContext);
210
211 return;
212}
213
214void MMC4SelectUHSMode(P_MM4_SDMMC_CONTEXT_T pContext, UINT8_T mode)
215{
216 UINT8_T ctrl = 0;
217 P_MM4_HOST_CNTL2_UNION pMM4_host_CNTL2;
218 MM4_HOST_CNTL2_UNION MM4_host_cntl2;
219
220 MMC4StopBusClock (pContext);
221
222 pMM4_host_CNTL2 = (P_MM4_HOST_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_acmd12_er);
223 MM4_host_cntl2.mm4_host_cntl2_value = *(VUINT_T *)pMM4_host_CNTL2;
224
225 if (mode & SDH_BUS_SPEED_SDR_CLK_208M) {
226 ctrl |= 0x03;
227 } else if (mode & SDH_BUS_SPEED_SDR_CLK_100M) {
228 ctrl |= 0x02;
229 } else if (mode & SDH_BUS_SPEED_DDR_CLK_50M) {
230 ctrl |= 0x04;
231 } else if (mode & SDH_BUS_SPEED_SDR_CLK_50M) {
232 ctrl |= 0x01;
233 } else if (mode & SDH_BUS_SPEED_DEFAULT) {
234 ctrl |= 0x00;
235 }
236
237 MM4_host_cntl2.mm4_host_cntl2_bits.uhs_mode_sel = ctrl;
238 *(VUINT_T *)pMM4_host_CNTL2 = MM4_host_cntl2.mm4_host_cntl2_value;
239
240 MMC4StartBusClock(pContext);
241
242 return;
243}
244
245void MMC4SetTXIntCLKSet(P_MM4_SDMMC_CONTEXT_T pContext, UINT_T mode1, UINT_T mode2)
246{
247 P_MM4_TX_CFG pMM4_TX_CFG;
248
249 pMM4_TX_CFG = (P_MM4_TX_CFG)&pContext->pMMC4Reg->mm4_sd_tx_cfg_reg;
250
251 //set the tx_int_clk_sel that makes the Tih dependant on bus clock rather than base clock
252 pMM4_TX_CFG->tx_int_clk = mode1;
253 pMM4_TX_CFG->tx_mux_sel = mode2;
254}
255
256void MMC4SetRXConfig(P_MM4_SDMMC_CONTEXT_T pContext)
257{
258 UINT_T value = 0;
259 P_MM4_RX_CFG_UNION pMM4_RX_CFG_UNION;
260 P_MM4_SD_DLINE_CTRL p_MM4_SD_DLINE_CTRL;
261 P_MM4_SD_DLINE_CFG p_MM4_SD_DLINE_CFG;
262
263 pMM4_RX_CFG_UNION = (P_MM4_RX_CFG)&pContext->pMMC4Reg->mm4_sd_rx_cfg_reg;
264 p_MM4_SD_DLINE_CTRL = (P_MM4_SD_DLINE_CTRL)&pContext->pMMC4Reg->mm4_sd_dline_ctrl_reg;
265 p_MM4_SD_DLINE_CFG = (P_MM4_SD_DLINE_CFG)&pContext->pMMC4Reg->mm4_sd_dline_cfg_reg;
266
267 value = pMM4_RX_CFG_UNION->MM4_RX_CFG_value;
268 value &= ~(RX_SDCLK_SEL1_MASK << RX_SDCLK_SEL1_SHIFT);
269 /* clock by SDCLK_SEL0, so it is default setting */
270 value |= 0x1 << RX_SDCLK_SEL1_SHIFT;
271 *(VUINT_T *)pMM4_RX_CFG_UNION = value;
272
273 p_MM4_SD_DLINE_CFG->rx_dline_reg = 0x0;
274 p_MM4_SD_DLINE_CTRL->rx_dline_code = DDR_RX_DELAY;
275 p_MM4_SD_DLINE_CTRL->dline_pu = 1;
276}
277
278void MMC4SetTXConfig(P_MM4_SDMMC_CONTEXT_T pContext)
279{
280 UINT_T value = 0;
281 UINT_T tx_delay = DDR_TX_DELAY;
282 P_MM4_TX_CFG_UNION pMM4_TX_CFG_UNION;
283 P_MM4_SD_DLINE_CTRL p_MM4_SD_DLINE_CTRL;
284 P_MM4_SD_DLINE_CFG p_MM4_SD_DLINE_CFG;
285
286 pMM4_TX_CFG_UNION = (P_MM4_TX_CFG)&pContext->pMMC4Reg->mm4_sd_tx_cfg_reg;
287 p_MM4_SD_DLINE_CTRL = (P_MM4_SD_DLINE_CTRL)&pContext->pMMC4Reg->mm4_sd_dline_ctrl_reg;
288 p_MM4_SD_DLINE_CFG = (P_MM4_SD_DLINE_CFG)&pContext->pMMC4Reg->mm4_sd_dline_cfg_reg;
289
290 value = pMM4_TX_CFG_UNION->MM4_TX_CFG_value;
291 if (tx_delay)
292 {
293 value &= ~TX_SEL_BUS_CLK; //clr bit 30
294 value |= TX_MUX_SEL; //set bit 31 select DDLL
295 }
296
297 *(VUINT_T *)pMM4_TX_CFG_UNION = value;
298 p_MM4_SD_DLINE_CFG->tx_dline_reg = 0x0;
299 p_MM4_SD_DLINE_CTRL->tx_dline_code = tx_delay & TX_DELAY_MASK;
300 p_MM4_SD_DLINE_CTRL->dline_pu = 1;
301}
302
303/******************************************************************************
304 Description:
305 This routine unmasks and enables or masks and disables required interrupts
306 needed by the driver
307 Input Parameters:
308 pContext
309 Pointer to MMC context structure
310 Desire - Enable or Disable the interrupts
311 Output Parameters:
312 None
313 Returns:
314 None
315*******************************************************************************/
316void MMC4EnableDisableIntSources(P_MM4_SDMMC_CONTEXT_T pContext, UINT8_T Desire)
317{
318 P_MM4_I_STAT pMM4_I_STAT;
319 MM4_I_STAT_UNION MM4_i_stat;
320
321 // Capture existing Value
322 pMM4_I_STAT = (P_MM4_I_STAT)((VUINT32_T) &pContext->pMMC4Reg->mm4_i_sig_en);
323
324 MM4_i_stat.mm4_i_stat_value = *(VUINT_T*)pMM4_I_STAT;
325 // Route the interrupt signal enable register
326 MM4_i_stat.mm4_i_stat_bits.cmdcomp = Desire;
327 MM4_i_stat.mm4_i_stat_bits.xfrcomp = Desire;
328 MM4_i_stat.mm4_i_stat_bits.dmaint = Desire;
329 MM4_i_stat.mm4_i_stat_bits.bufwrrdy = Desire;
330 MM4_i_stat.mm4_i_stat_bits.bufrdrdy = Desire;
331 MM4_i_stat.mm4_i_stat_bits.errint = Desire;
332 MM4_i_stat.mm4_i_stat_bits.ctoerr = Desire;
333 MM4_i_stat.mm4_i_stat_bits.cenderr = Desire;
334 MM4_i_stat.mm4_i_stat_bits.dtoerr = Desire;
335 MM4_i_stat.mm4_i_stat_bits.dcrcerr = Desire;
336 MM4_i_stat.mm4_i_stat_bits.denderr = Desire;
337 MM4_i_stat.mm4_i_stat_bits.admaerr = Desire;
338 MM4_i_stat.mm4_i_stat_bits.crc_stat_err = Desire;
339
340 // Write it out
341 *(VUINT_T*)pMM4_I_STAT = MM4_i_stat.mm4_i_stat_value;
342
343 // Now remove the masks
344 pMM4_I_STAT = (P_MM4_I_STAT)((VUINT32_T) &pContext->pMMC4Reg->mm4_i_stat_en);
345 MM4_i_stat.mm4_i_stat_value = *(VUINT_T*)pMM4_I_STAT;
346 MM4_i_stat.mm4_i_stat_bits.cmdcomp = Desire;
347 MM4_i_stat.mm4_i_stat_bits.xfrcomp = Desire;
348 MM4_i_stat.mm4_i_stat_bits.dmaint = Desire;
349 MM4_i_stat.mm4_i_stat_bits.bufwrrdy = Desire;
350 MM4_i_stat.mm4_i_stat_bits.bufrdrdy = Desire;
351 MM4_i_stat.mm4_i_stat_bits.errint = Desire;
352 MM4_i_stat.mm4_i_stat_bits.ctoerr = Desire;
353 MM4_i_stat.mm4_i_stat_bits.cenderr = Desire;
354 MM4_i_stat.mm4_i_stat_bits.dtoerr = Desire;
355 MM4_i_stat.mm4_i_stat_bits.dcrcerr = Desire;
356 MM4_i_stat.mm4_i_stat_bits.denderr = Desire;
357 MM4_i_stat.mm4_i_stat_bits.admaerr = Desire;
358 MM4_i_stat.mm4_i_stat_bits.crc_stat_err = Desire;
359
360 // Write it out
361 *(VUINT_T*)pMM4_I_STAT = MM4_i_stat.mm4_i_stat_value;
362
363 return;
364}
365
366/******************************************************************************
367 Description:
368 Set the data response timeout value.
369 Input Parameters:
370 pContext
371 Pointer to MMC context structure
372 CounterValue
373 the value which will be written into DTOCNTR
374 Output Parameters:
375 None
376 Returns:
377 None
378*******************************************************************************/
379void MMC4SetDataTimeout(P_MM4_SDMMC_CONTEXT_T pContext, UINT8_T CounterValue)
380{
381 P_MM4_CNTL2 pMM4_CNTL2;
382 MM4_CNTL2_UNION MM4_cntl2;
383
384 // Set the register
385 pMM4_CNTL2 = (P_MM4_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_cntl2);
386 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
387 MM4_cntl2.mm4_cntl2_bits.dtocntr = CounterValue;
388
389 // Write Back
390 *(VUINT_T *)pMM4_CNTL2 = MM4_cntl2.mm4_cntl2_value;
391 return;
392}
393
394/******************************************************************************
395 Description:
396 This function will induce a software reset of all MMC4 data lines
397 Input Parameters:
398 pContext
399 Pointer to MMC context structure
400 Output Parameters:
401 None
402 Returns:
403 None
404*******************************************************************************/
405void MMC4CMDSWReset(P_MM4_SDMMC_CONTEXT_T pContext)
406{
407 P_MM4_CNTL2 pMM4_CNTL2;
408 MM4_CNTL2_UNION MM4_cntl2;
409
410 // Set the register
411 pMM4_CNTL2 = (P_MM4_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_cntl2);
412 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
413 MM4_cntl2.mm4_cntl2_bits.cmdswrst = 1;
414
415 // Write Back
416 *(VUINT_T *)pMM4_CNTL2 = MM4_cntl2.mm4_cntl2_value;
417 return;
418}
419
420/******************************************************************************
421 Description:
422 This function will induce a software reset of all MMC4 data lines
423 Input Parameters:
424 pContext
425 Pointer to MMC context structure
426 Output Parameters:
427 None
428 Returns:
429 None
430*******************************************************************************/
431void MMC4DataSWReset(P_MM4_SDMMC_CONTEXT_T pContext)
432{
433 P_MM4_CNTL2 pMM4_CNTL2;
434 MM4_CNTL2_UNION MM4_cntl2;
435
436 // Set the register
437 pMM4_CNTL2 = (P_MM4_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_cntl2);
438 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
439 MM4_cntl2.mm4_cntl2_bits.datswrst = 1;
440
441 // Write Back
442 *(VUINT_T *)pMM4_CNTL2 = MM4_cntl2.mm4_cntl2_value;
443 return;
444}
445
446/******************************************************************************
447 Description:
448 This function will induce a full software reset of all MMC4 components except
449 MM4_CAPX
450 Input Parameters:
451 pContext
452 Pointer to MMC context structure
453 Output Parameters:
454 None
455 Returns:
456 None
457*******************************************************************************/
458void MMC4FullSWReset(P_MM4_SDMMC_CONTEXT_T pContext)
459{
460 P_MM4_CNTL2 pMM4_CNTL2;
461 MM4_CNTL2_UNION MM4_cntl2;
462
463 // Set the register
464 pMM4_CNTL2 = (P_MM4_CNTL2)((VUINT32_T) &pContext->pMMC4Reg->mm4_cntl2);
465 MM4_cntl2.mm4_cntl2_value = *(VUINT_T *)pMM4_CNTL2;
466 MM4_cntl2.mm4_cntl2_bits.mswrst = 1;
467
468 // Write Back
469 *(VUINT_T *)pMM4_CNTL2 = MM4_cntl2.mm4_cntl2_value;
470 return;
471}
472
473/******************************************************************************
474 Description:
475 Set up the registers of the controller to start the transaction to
476 communicate to the card for data related command. The commands are clearly defined in the MMC
477 specification.
478 Input Parameters:
479 pContext
480 Pointer to MMC context structure
481 Cmd
482 Command Index - See MMC or SD specification
483 argument
484 the argument of the command. MSW is for ARGH and LSW is for ARGL
485 BlockType
486 Multiple or Single Block Type
487 ResType
488 Expected response type
489 Output Parameters:
490 None
491 Returns:
492 None
493*******************************************************************************/
494void MMC4SendDataCommand(P_MM4_SDMMC_CONTEXT_T pContext,
495 UINT_T Cmd,
496 UINT_T Argument,
497 UINT_T BlockType,
498 UINT_T DataDirection,
499 UINT_T ResType,
500 UINT_T DMAMode,
501 UINT_T AutoCmd23En)
502{
503 MM4_CMD_XFRMD_UNION xfrmd;
504 P_MM4_STATE pMM4_STATE;
505 MM4_STATE_UNION MM4_state;
506
507 // Make sure the controller is ready to accept the next command
508 pMM4_STATE = (P_MM4_STATE) &pContext->pMMC4Reg->mm4_state;
509 MM4_state.mm4_state_value = *(VUINT_T *)pMM4_STATE;
510
511 do
512 {
513 MM4_state.mm4_state_value = *(VUINT_T *)pMM4_STATE;
514 } while (MM4_state.mm4_state_bits.dcmdinhbt);
515
516 // Set the Argument Field
517 pContext->pMMC4Reg->mm4_arg = Argument;
518
519 // Set the Data Transfer Command fields.
520 xfrmd.mm4_cmd_xfrmd_value = 0;
521 xfrmd.mm4_cmd_xfrmd_bits.cmd_idx = Cmd;
522 xfrmd.mm4_cmd_xfrmd_bits.cmd_type = MM4_CMD_TYPE_NORMAL;
523 xfrmd.mm4_cmd_xfrmd_bits.dpsel = MM4_CMD_DATA;
524// xfrmd.mm4_cmd_xfrmd_bits.idxchken = TRUE;
525// xfrmd.mm4_cmd_xfrmd_bits.crcchken = TRUE;
526 xfrmd.mm4_cmd_xfrmd_bits.res_type = ResType;
527 xfrmd.mm4_cmd_xfrmd_bits.ms_blksel = BlockType;
528 xfrmd.mm4_cmd_xfrmd_bits.dxfrdir = DataDirection;
529
530 //if SDMA/ADMA2
531 if (DMAMode)
532 xfrmd.mm4_cmd_xfrmd_bits.dma_en = TRUE;
533 //CMD23 -> Lets the card know about number of blocks to transfer for the upcoming read/write transaction
534 //AutoCMD23 should be sent prior to CMD18 or CMD25 if ADMA2 is used and BLK_CNT is disabled for ADMA2
535 //Since AutoCMD23 is sent, AutoCMD12 is not required
536 if(AutoCmd23En)
537 {
538 xfrmd.mm4_cmd_xfrmd_bits.autocmd23 = TRUE;
539 xfrmd.mm4_cmd_xfrmd_bits.blkcnten = TRUE; // block counter is a better choice than send stop command
540 }
541 else
542 {
543 //For PIO and SDMA mode
544 xfrmd.mm4_cmd_xfrmd_bits.autocmd12 = TRUE;
545 xfrmd.mm4_cmd_xfrmd_bits.blkcnten = TRUE;
546 }
547
548 // Kick off the command
549 pContext->pMMC4Reg->mm4_cmd_xfrmd = xfrmd.mm4_cmd_xfrmd_value;
550
551 return;
552}
553
554
555/******************************************************************************
556 Description:
557 Set up the registers of the controller to start the transaction to
558 communicate to the card for data related command. The commands are clearly defined in the MMC
559 specification.
560 Input Parameters:
561 pContext
562 Pointer to MMC context structure
563 Cmd
564 Command Index - See MMC or SD specification
565 argument
566 the argument of the command. MSW is for ARGH and LSW is for ARGL
567 BlockType
568 Multiple or Single Block Type
569 ResType
570 Expected response type
571 Output Parameters:
572 None
573 Returns:
574 None
575*******************************************************************************/
576void MMC4SendDataCommandNoAuto12(P_MM4_SDMMC_CONTEXT_T pContext,
577 UINT_T Cmd,
578 UINT_T Argument,
579 UINT_T BlockType,
580 UINT_T DataDirection,
581 UINT_T ResType,
582 UINT_T DMAMode,
583 UINT_T Blk_Cnt_Enable)
584{
585 MM4_CMD_XFRMD_UNION xfrmd;
586 P_MM4_STATE pMM4_STATE;
587 MM4_STATE_UNION MM4_state;
588
589 // Make sure the controller is ready to accept the next command
590 pMM4_STATE = (P_MM4_STATE) &pContext->pMMC4Reg->mm4_state;
591 MM4_state.mm4_state_value = *(VUINT_T *)pMM4_STATE;
592
593 do
594 {
595 MM4_state.mm4_state_value = *(VUINT_T *)pMM4_STATE;
596 } while (MM4_state.mm4_state_bits.dcmdinhbt);
597 // Set the Argument Field
598 pContext->pMMC4Reg->mm4_arg = Argument;
599
600 // Set the Data Transfer Command fields.
601 xfrmd.mm4_cmd_xfrmd_value = 0;
602 xfrmd.mm4_cmd_xfrmd_bits.cmd_idx = Cmd;
603 xfrmd.mm4_cmd_xfrmd_bits.cmd_type = MM4_CMD_TYPE_NORMAL;
604 xfrmd.mm4_cmd_xfrmd_bits.dpsel = MM4_CMD_DATA;
605// xfrmd.mm4_cmd_xfrmd_bits.idxchken = TRUE;
606// xfrmd.mm4_cmd_xfrmd_bits.crcchken = TRUE;
607 xfrmd.mm4_cmd_xfrmd_bits.res_type = ResType;
608 xfrmd.mm4_cmd_xfrmd_bits.ms_blksel = BlockType;
609 xfrmd.mm4_cmd_xfrmd_bits.dxfrdir = DataDirection;
610 xfrmd.mm4_cmd_xfrmd_bits.autocmd12 = FALSE;
611
612 if (DMAMode)
613 xfrmd.mm4_cmd_xfrmd_bits.dma_en = TRUE;
614
615 if(Blk_Cnt_Enable) //Blk_Cnt is not enabled for ADMA2
616 xfrmd.mm4_cmd_xfrmd_bits.blkcnten = TRUE;
617
618 // Kick off the command
619 pContext->pMMC4Reg->mm4_cmd_xfrmd = xfrmd.mm4_cmd_xfrmd_value;
620 return;
621}
622
623/******************************************************************************
624 Description:
625 Set up the registers of the controller to start the transaction to
626 communicate to the card for setup related commands.
627 The commands are clearly defined in the MMC specification.
628 Input Parameters:
629 pContext
630 Pointer to MMC context structure
631 Cmd
632 Command Index - See MMC or SD specification
633 argument
634 the argument of the command. MSW is for ARGH and LSW is for ARGL
635 ResType
636 Expected response type
637 Output Parameters:
638 None
639 Returns:
640 None
641*******************************************************************************/
642void MMC4SendSetupCommand(P_MM4_SDMMC_CONTEXT_T pContext,
643 UINT_T Cmd,
644 UINT_T CmdType,
645 UINT_T Argument,
646 UINT_T ResType)
647{
648 MM4_CMD_XFRMD_UNION xfrmd;
649 P_MM4_STATE pMM4_STATE;
650 MM4_STATE_UNION MM4_state;
651 UINT_T startTime, endTime;
652
653 startTime = GetOSCR0(); // get the start time
654 startTime = GetOSCR0(); // get the start time
655 endTime = startTime;
656
657 // Make sure the controller is ready to accept the next command
658 pMM4_STATE = (P_MM4_STATE) &pContext->pMMC4Reg->mm4_state;
659 MM4_state.mm4_state_value = *(VUINT_T *)pMM4_STATE;
660
661 do
662 {
663 endTime = GetOSCR0();
664
665 if (OSCR0IntervalInMilli(startTime, endTime) > 200)
666 return; // Let the getresponse routine catch the error
667
668 MM4_state.mm4_state_value = *(VUINT_T *)pMM4_STATE;
669 } while (MM4_state.mm4_state_bits.ccmdinhbt);
670
671 // Set the Argument Field
672 pContext->pMMC4Reg->mm4_arg = Argument;
673
674 // Set the Data Transfer Command fields.
675 xfrmd.mm4_cmd_xfrmd_value = 0;
676 xfrmd.mm4_cmd_xfrmd_bits.cmd_idx = Cmd;
677 xfrmd.mm4_cmd_xfrmd_bits.cmd_type = CmdType;
678// xfrmd.mm4_cmd_xfrmd_bits.idxchken = TRUE;
679 xfrmd.mm4_cmd_xfrmd_bits.crcchken = TRUE;
680 xfrmd.mm4_cmd_xfrmd_bits.res_type = ResType;
681
682 // Kick off the command
683 pContext->pMMC4Reg->mm4_cmd_xfrmd = xfrmd.mm4_cmd_xfrmd_value;
684 return;
685}