• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2 Copyright (C) 2016 Marvell International Ltd.
3 
4 Marvell BSD License Option
5 
6 If you received this File from Marvell, you may opt to use, redistribute and/or
7 modify this File under the following licensing terms.
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10 
11 * Redistributions of source code must retain the above copyright notice,
12   this list of conditions and the following disclaimer.
13 
14 * Redistributions in binary form must reproduce the above copyright
15   notice, this list of conditions and the following disclaimer in the
16   documentation and/or other materials provided with the distribution.
17 
18 * Neither the name of Marvell nor the names of its contributors may be
19   used to endorse or promote products derived from this software without
20   specific prior written permission.
21 
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
26 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 *******************************************************************************/
34 
35 #include "XenonSdhci.h"
36 
37 STATIC
38 VOID
XenonReadVersion(IN EFI_PCI_IO_PROTOCOL * PciIo,OUT UINT32 * ControllerVersion)39 XenonReadVersion (
40   IN  EFI_PCI_IO_PROTOCOL   *PciIo,
41   OUT UINT32 *ControllerVersion
42   )
43 {
44   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CTRL_VER, TRUE, SDHC_REG_SIZE_2B, ControllerVersion);
45 }
46 
47 STATIC
48 VOID
XenonSetFifo(IN EFI_PCI_IO_PROTOCOL * PciIo)49 XenonSetFifo (
50   IN EFI_PCI_IO_PROTOCOL   *PciIo
51   )
52 {
53   UINTN Data;
54 
55   // Set FIFO_RTC, FIFO_WTC, FIFO_CS and FIFO_PDLVMC
56   Data = SDHC_SLOT_FIFO_DEFAULT_CONFIG;
57 
58   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SLOT_FIFO_CTRL, FALSE, SDHC_REG_SIZE_4B, &Data);
59 }
60 
61 // Auto Clock Gating
62 STATIC
63 VOID
XenonSetAcg(IN EFI_PCI_IO_PROTOCOL * PciIo,IN BOOLEAN Enable)64 XenonSetAcg (
65   IN EFI_PCI_IO_PROTOCOL   *PciIo,
66   IN BOOLEAN Enable
67   )
68 {
69   UINT32 Var;
70 
71   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, TRUE, SDHC_REG_SIZE_4B, &Var);
72 
73   if (Enable) {
74     Var &= ~AUTO_CLKGATE_DISABLE_MASK;
75   } else {
76     Var |= AUTO_CLKGATE_DISABLE_MASK;
77   }
78 
79   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, FALSE, SDHC_REG_SIZE_4B, &Var);
80 }
81 
82 STATIC
83 VOID
XenonSetSlot(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,IN BOOLEAN Enable)84 XenonSetSlot (
85   IN EFI_PCI_IO_PROTOCOL *PciIo,
86   IN UINT8 Slot,
87   IN BOOLEAN Enable
88   )
89 {
90   UINT32 Var;
91 
92   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, TRUE, SDHC_REG_SIZE_4B, &Var);
93   if (Enable) {
94     Var |= ((0x1 << Slot) << SLOT_ENABLE_SHIFT);
95   } else {
96     Var &= ~((0x1 << Slot) << SLOT_ENABLE_SHIFT);
97   }
98 
99   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, FALSE, SDHC_REG_SIZE_4B, &Var);
100 }
101 
102 //
103 // Stub function, which will in future be responsible for
104 // setting SDIO controller in either HIGH (if Voltage parameter
105 // is equal 1) or LOW (if Voltage is equal 0)
106 //
107 STATIC
108 VOID
XenonSetSdio(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINTN Voltage)109 XenonSetSdio (
110   IN EFI_PCI_IO_PROTOCOL *PciIo,
111   IN UINTN Voltage
112   )
113 {
114   // Currently SDIO isn't supported
115   return;
116 }
117 
118 STATIC
119 VOID
XenonSetPower(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT32 Vcc,IN UINT32 Vccq,IN UINT8 Mode)120 XenonSetPower (
121   IN EFI_PCI_IO_PROTOCOL *PciIo,
122   IN UINT32 Vcc,
123   IN UINT32 Vccq,
124   IN UINT8 Mode
125   )
126 {
127   UINT8 Pwr = 0;
128   UINT32 Ctrl = 0;
129 
130   // Below statement calls routine to set voltage for SDIO devices in either HIGH (1) or LOW (0) mode
131   switch (Vcc) {
132   case MMC_VDD_165_195:
133     Pwr = SDHCI_POWER_180;
134     if (Mode == XENON_MMC_MODE_SD_SDIO) {
135       XenonSetSdio (PciIo, 0);
136     }
137     break;
138   case MMC_VDD_29_30:
139   case MMC_VDD_30_31:
140     Pwr = SDHCI_POWER_300;
141     if (Mode == XENON_MMC_MODE_SD_SDIO) {
142       XenonSetSdio (PciIo, 1);
143     }
144     break;
145   case MMC_VDD_32_33:
146   case MMC_VDD_33_34:
147     Pwr = SDHCI_POWER_330;
148     if (Mode == XENON_MMC_MODE_SD_SDIO) {
149       XenonSetSdio (PciIo, 1);
150     }
151     break;
152   default:
153     DEBUG((DEBUG_ERROR, "SD/MMC: Does not support power mode(0x%X)\n", Vcc));
154     break;
155   }
156 
157   if (Pwr == 0) {
158     SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_POWER_CTRL, FALSE, SDHC_REG_SIZE_1B, &Pwr);
159     return;
160   }
161 
162   Pwr |= SDHCI_POWER_ON;
163 
164   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX,SD_MMC_HC_POWER_CTRL, FALSE, SDHC_REG_SIZE_1B, &Pwr);
165 
166   // Set VCCQ
167   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SLOT_eMMC_CTRL, TRUE, SDHC_REG_SIZE_4B, &Ctrl);
168   Ctrl |= Vccq;
169   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SLOT_eMMC_CTRL, FALSE, SDHC_REG_SIZE_4B, &Ctrl);
170 }
171 
172 UINTN
XenonSetClk(IN EFI_PCI_IO_PROTOCOL * PciIo,IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT32 Clock)173 XenonSetClk (
174   IN EFI_PCI_IO_PROTOCOL   *PciIo,
175   IN SD_MMC_HC_PRIVATE_DATA *Private,
176   IN UINT32 Clock
177   )
178 {
179   UINT32 Div;
180   UINT32 Clk;
181   UINT32 Retry;
182   UINT16 Value = 0;
183 
184   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, SDHC_REG_SIZE_2B, &Value);
185 
186   if (Clock == 0) {
187     return 0;
188   }
189 
190   if (Private->ControllerVersion >= SDHCI_SPEC_300) {
191     // Version 3.00 Divisors must be a multiple of 2
192     if (XENON_MMC_MAX_CLK <= Clock) {
193       Div = 1;
194     } else {
195       for (Div = 2; Div < SDHCI_MAX_DIV_SPEC_300; Div += 2) {
196         if ((XENON_MMC_MAX_CLK / Div) <= Clock)
197           break;
198       }
199     }
200   } else {
201     // Version 2.00 Divisors must be a power of 2
202     for (Div = 1; Div < SDHCI_MAX_DIV_SPEC_200; Div *= 2) {
203       if ((XENON_MMC_MAX_CLK / Div) <= Clock)
204         break;
205     }
206   }
207   Div >>= 1;
208 
209   Clk = (Div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
210   Clk |= ((Div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) << SDHCI_DIVIDER_HI_SHIFT;
211   Clk |= SDHCI_CLOCK_INT_EN;
212 
213   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, SDHC_REG_SIZE_2B, &Clk);
214 
215   //
216   // Poll for internal controller clock to be stabilised
217   // Wait up to 200us for this to occur
218   //
219   Retry = 200;
220 
221   do {
222     SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, TRUE, SDHC_REG_SIZE_2B, &Clk);
223     if (Retry == 0) {
224       DEBUG((DEBUG_ERROR, "SD/MMC: Internal Clock never stabilised\n"));
225       return -1;
226     }
227 
228     Retry--;
229 
230     // Wait for internal clock to be stabilised
231     gBS->Stall (1);
232 
233   } while (!(Clk & SDHCI_CLOCK_INT_STABLE));
234 
235   Clk |= SDHCI_CLOCK_CARD_EN;
236   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, SDHC_REG_SIZE_2B, &Clk);
237 
238   return 0;
239 }
240 
241 VOID
XenonPhyInit(IN EFI_PCI_IO_PROTOCOL * PciIo)242 XenonPhyInit (
243   IN EFI_PCI_IO_PROTOCOL   *PciIo
244   )
245 {
246   UINT32 Var, Wait, Time;
247   UINT32 Clock = XENON_MMC_MAX_CLK;
248   UINT16 ClkCtrl;
249 
250   // Need to disable the clock to set EMMC_PHY_TIMING_ADJUST register
251   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, TRUE, SDHC_REG_SIZE_2B, &ClkCtrl);
252   ClkCtrl &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
253   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, SDHC_REG_SIZE_2B, &ClkCtrl);
254 
255   // Enable QSP PHASE SELECT
256   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, SDHC_REG_SIZE_4B, &Var);
257   Var |= SAMPL_INV_QSP_PHASE_SELECT;
258   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, FALSE, SDHC_REG_SIZE_4B, &Var);
259 
260   // Enable internal clock
261   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, TRUE, SDHC_REG_SIZE_2B, &ClkCtrl);
262   ClkCtrl |= SDHCI_CLOCK_INT_EN;
263   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, SDHC_REG_SIZE_2B, &ClkCtrl);
264 
265   //
266   // Poll for host MMC PHY clock init to be stable
267   // Wait up to 100us
268   //
269   Time = 100;
270   while (Time--) {
271     SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, SDHC_REG_SIZE_4B, &Var);
272     if (Var & SDHCI_CLOCK_INT_STABLE) {
273       break;
274     }
275 
276     // Poll interval for MMC PHY clock to be stable is 1us
277     gBS->Stall (1);
278   }
279   if (Time <= 0) {
280     DEBUG((DEBUG_ERROR, "SD/MMC: Failed to enable MMC internal clock in Time\n"));
281     return;
282   }
283 
284   // Enable bus clock
285   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, TRUE, SDHC_REG_SIZE_2B, &ClkCtrl);
286   ClkCtrl |= SDHCI_CLOCK_CARD_EN;
287   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, SDHC_REG_SIZE_2B, &ClkCtrl);
288 
289   // Delay 200us to wait for the completion of bus clock
290   gBS->Stall (200);
291 
292   // Init PHY
293   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, SDHC_REG_SIZE_4B, &Var);
294   Var |= PHY_INITIALIZAION;
295   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, FALSE, SDHC_REG_SIZE_4B, &Var);
296 
297   // Add duration of FC_SYNC_RST
298   Wait = ((Var >> FC_SYNC_RST_DURATION_SHIFT) & FC_SYNC_RST_DURATION_MASK);
299 
300   // Add interval between FC_SYNC_EN and FC_SYNC_RST
301   Wait += ((Var >> FC_SYNC_RST_EN_DURATION_SHIFT) & FC_SYNC_RST_EN_DURATION_MASK);
302 
303   // Add duration of asserting FC_SYNC_EN
304   Wait += ((Var >> FC_SYNC_EN_DURATION_SHIFT) & FC_SYNC_EN_DURATION_MASK);
305 
306   // Add duration of Waiting for PHY
307   Wait += ((Var >> WAIT_CYCLE_BEFORE_USING_SHIFT) & WAIT_CYCLE_BEFORE_USING_MASK);
308 
309   // 4 addtional bus clock and 4 AXI bus clock are required left shift 20 bits
310   Wait += 8;
311   Wait <<= 20;
312 
313   // Use the possibly slowest bus frequency value
314   if (Clock == 0) {
315     Clock = XENON_MMC_MIN_CLK;
316   }
317 
318   // Get the Wait Time in unit of ms
319   Wait = Wait / Clock;
320   Wait++;
321 
322   // Poll for host eMMC PHY init to complete, wait up to 100us
323   Time = 100;
324   while (Time--) {
325     Var = SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, SDHC_REG_SIZE_4B, &Var);
326     Var &= PHY_INITIALIZAION;
327     if (!Var) {
328       break;
329     }
330 
331     // Wait for host eMMC PHY init to complete
332     gBS->Stall (1);
333   }
334 
335   if (Time <= 0) {
336     DEBUG((DEBUG_ERROR, "SD/MMC: Failed to init MMC PHY in Time\n"));
337     return;
338   }
339 
340   return;
341 }
342 
343 STATIC
344 VOID
XenonSetPhy(IN EFI_PCI_IO_PROTOCOL * PciIo,UINT8 Timing)345 XenonSetPhy (
346   IN EFI_PCI_IO_PROTOCOL   *PciIo,
347   UINT8 Timing
348   )
349 {
350   UINT32 Var = 0;
351 
352   // Setup pad, set bit[30], bit[28] and bits[26:24]
353   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_PAD_CONTROL, TRUE, SDHC_REG_SIZE_4B, &Var);
354   Var |= (AUTO_RECEN_CTRL | OEN_QSN | FC_QSP_RECEN | FC_CMD_RECEN | FC_DQ_RECEN);
355   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_PAD_CONTROL, FALSE, SDHC_REG_SIZE_4B, &Var);
356 
357   //
358   // If Timing belongs to high speed, set bit[17] of
359   // EMMC_PHY_TIMING_ADJUST register
360   //
361   if ((Timing == MMC_TIMING_MMC_HS400) ||
362       (Timing == MMC_TIMING_MMC_HS200) ||
363       (Timing == MMC_TIMING_UHS_SDR50) ||
364       (Timing == MMC_TIMING_UHS_SDR104) ||
365       (Timing == MMC_TIMING_UHS_DDR50) ||
366       (Timing == MMC_TIMING_UHS_SDR25)) {
367 
368     SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, SDHC_REG_SIZE_4B, &Var);
369 
370     // Set SLOW_MODE for PHY
371     Var |= OUTPUT_QSN_PHASE_SELECT | QSN_PHASE_SLOW_MODE_BIT;
372     SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, FALSE, SDHC_REG_SIZE_4B, &Var);
373   }
374 
375   SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, TRUE, SDHC_REG_SIZE_4B, &Var);
376   Var |= (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE;
377   SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, FALSE, SDHC_REG_SIZE_4B, &Var);
378 
379   if (Timing == MMC_TIMING_MMC_HS400) {
380     SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, TRUE, SDHC_REG_SIZE_4B, &Var);
381     Var &= ~DQ_ASYNC_MODE;
382     SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, FALSE, SDHC_REG_SIZE_4B, &Var);
383 
384     Var = LOGIC_TIMING_VALUE;
385     SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_LOGIC_TIMING_ADJUST, FALSE, SDHC_REG_SIZE_4B, &Var);
386   }
387 
388   XenonPhyInit (PciIo);
389 }
390 
391 STATIC
392 VOID
XenonConfigureInterrupts(IN EFI_PCI_IO_PROTOCOL * PciIo)393 XenonConfigureInterrupts (
394   IN EFI_PCI_IO_PROTOCOL *PciIo
395   )
396 {
397   UINT32 Var;
398 
399   // Clear interrupt status
400   Var = SDHC_CLR_ALL_IRQ_MASK;
401   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_NOR_INT_STS, FALSE, SDHC_REG_SIZE_4B, &Var);
402   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_NOR_INT_STS, FALSE, SDHC_REG_SIZE_4B, &Var);
403 
404   // Enable only interrupts served by the SD controller
405   Var = SDHC_CLR_ALL_IRQ_MASK & ~(NOR_INT_STS_CARD_INS | NOR_INT_STS_CARD_INT);
406   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_NOR_INT_STS_EN, FALSE, SDHC_REG_SIZE_4B, &Var);
407 
408   // Mask all sdhci interrupt sources
409   Var = SDHC_CLR_ALL_IRQ_MASK & ~NOR_INT_SIG_EN_CARD_INT;
410   SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_NOR_INT_SIG_EN, FALSE, SDHC_REG_SIZE_4B, &Var);
411 }
412 
413 // Enable Parallel Transfer Mode
414 STATIC
415 VOID
XenonSetParallelTransfer(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,IN BOOLEAN Enable)416 XenonSetParallelTransfer (
417   IN EFI_PCI_IO_PROTOCOL *PciIo,
418   IN UINT8 Slot,
419   IN BOOLEAN Enable
420   )
421 {
422   UINT32 Var;
423 
424   SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SYS_EXT_OP_CTRL, TRUE, SDHC_REG_SIZE_4B, &Var);
425 
426   if (Enable) {
427     Var |= (0x1 << Slot);
428   } else {
429     Var &= ~(0x1 << Slot);
430   }
431 
432   SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SYS_EXT_OP_CTRL, FALSE, SDHC_REG_SIZE_4B, &Var);
433 }
434 
435 STATIC
436 VOID
XenonSetTuning(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Slot,IN BOOLEAN Enable)437 XenonSetTuning (
438   IN EFI_PCI_IO_PROTOCOL   *PciIo,
439   IN UINT8 Slot,
440   IN BOOLEAN Enable
441   )
442 {
443   UINT32 Var;
444 
445   // Set the Re-Tuning Request functionality
446   SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SLOT_RETUNING_REQ_CTRL, TRUE, SDHC_REG_SIZE_4B, &Var);
447 
448   if (Enable) {
449     Var |= RETUNING_COMPATIBLE;
450   } else {
451     Var &= ~RETUNING_COMPATIBLE;
452   }
453 
454   SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SLOT_RETUNING_REQ_CTRL, FALSE, SDHC_REG_SIZE_4B, &Var);
455 
456   // Set the Re-tuning Event Signal Enable
457   SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHCI_SIGNAL_ENABLE, TRUE, SDHC_REG_SIZE_4B, &Var);
458 
459   if (Enable) {
460     Var |= SDHCI_RETUNE_EVT_INTSIG;
461   } else {
462     Var &= ~SDHCI_RETUNE_EVT_INTSIG;
463   }
464 
465   SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHCI_SIGNAL_ENABLE, FALSE, SDHC_REG_SIZE_4B, &Var);
466 }
467 
468 VOID
XenonReset(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 Slot,IN UINT8 Mask)469 XenonReset (
470   IN SD_MMC_HC_PRIVATE_DATA *Private,
471   IN UINT8 Slot,
472   IN UINT8 Mask
473   )
474 {
475   UINT32 Retry = 1000;
476   UINT8 SwReset;
477 
478   SwReset = Mask;
479 
480   SdMmcHcRwMmio (
481           Private->PciIo,
482           Slot,
483           SD_MMC_HC_SW_RST,
484           FALSE,
485           sizeof (SwReset),
486           &SwReset
487         );
488 
489   SdMmcHcRwMmio (
490           Private->PciIo,
491           Slot,
492           SD_MMC_HC_SW_RST,
493           TRUE,
494           sizeof (SwReset),
495           &SwReset
496         );
497 
498   while (SwReset & Mask) {
499     if (Retry == 0) {
500       DEBUG((DEBUG_ERROR, "SD/MMC: Reset never completed\n"));
501       return;
502     }
503 
504     Retry--;
505 
506     // Poll interval for SwReset is 100us according to SDHCI spec
507     gBS-> Stall (100);
508     SdMmcHcRwMmio (
509             Private->PciIo,
510             Slot,
511             SD_MMC_HC_SW_RST,
512             TRUE,
513             sizeof (SwReset),
514             &SwReset
515           );
516   }
517 }
518 
519 STATIC
520 VOID
XenonTransferPio(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 Slot,IN OUT VOID * Buffer,IN UINT16 BlockSize,IN BOOLEAN Read)521 XenonTransferPio (
522   IN SD_MMC_HC_PRIVATE_DATA *Private,
523   IN UINT8 Slot,
524   IN OUT VOID *Buffer,
525   IN UINT16 BlockSize,
526   IN BOOLEAN Read
527   )
528 {
529   UINTN Index;
530   UINT8 *Offs;
531 
532   //
533   // SD stack's intrinsic functions cannot perform properly reading/writing from
534   // buffer register, that is why MmioRead/MmioWrite are used. It is temporary
535   // solution.
536   //
537   for (Index = 0; Index < BlockSize; Index += 4) {
538     Offs = Buffer + Index;
539     if (Read) {
540       *(UINT32 *)Offs = MmioRead32 (SDHC_DAT_BUF_PORT_ADDR);
541     } else {
542       MmioWrite32 (SDHC_DAT_BUF_PORT_ADDR, *(UINT32 *)Offs);
543     }
544   }
545 }
546 
547 EFI_STATUS
XenonTransferData(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 Slot,IN OUT VOID * Buffer,IN UINT32 DataLen,IN UINT16 BlockSize,IN UINT16 Blocks,IN BOOLEAN Read)548 XenonTransferData (
549   IN SD_MMC_HC_PRIVATE_DATA *Private,
550   IN UINT8 Slot,
551   IN OUT VOID *Buffer,
552   IN UINT32 DataLen,
553   IN UINT16 BlockSize,
554   IN UINT16 Blocks,
555   IN BOOLEAN Read
556   )
557 {
558   UINT32 IntStatus, PresentState, Rdy, Mask, Retry, Block = 0;
559 
560   if (Buffer == NULL) {
561     return EFI_DEVICE_ERROR;
562   }
563 
564   Retry = SDHC_INT_STATUS_POLL_RETRY_DATA_TRAN;
565   Rdy = NOR_INT_STS_TX_RDY | NOR_INT_STS_RX_RDY;
566   Mask = PRESENT_STATE_BUFFER_RD_EN | PRESENT_STATE_BUFFER_WR_EN;
567 
568   do {
569     SdMmcHcRwMmio (
570             Private->PciIo,
571             Slot,
572             SD_MMC_HC_NOR_INT_STS,
573             TRUE,
574             sizeof (IntStatus),
575             &IntStatus
576           );
577 
578     if (IntStatus & NOR_INT_STS_ERR_INT) {
579       DEBUG((DEBUG_INFO, "SD/MMC: Error detected in status %0x\n", IntStatus));
580       return EFI_DEVICE_ERROR;
581     }
582 
583     if (IntStatus & Rdy) {
584       SdMmcHcRwMmio (
585               Private->PciIo,
586               Slot,
587               SD_MMC_HC_PRESENT_STATE,
588               TRUE,
589               sizeof (PresentState),
590               &PresentState
591             );
592 
593       if (!(PresentState & Mask)) {
594         continue;
595       }
596 
597       SdMmcHcRwMmio (
598               Private->PciIo,
599               Slot,
600               SD_MMC_HC_NOR_INT_STS,
601               FALSE,
602               sizeof (Rdy),
603               &Rdy
604             );
605 
606       XenonTransferPio (Private, Slot, Buffer, BlockSize, Read);
607 
608       Buffer += BlockSize;
609       if (++Block >= Blocks) {
610         break;
611       }
612     }
613 
614     if (Retry-- > 0) {
615 
616       // Poll interval for data transfer complete bit in NOR_INT_STS register is 10us
617       gBS->Stall (10);
618     } else {
619       DEBUG((DEBUG_INFO, "SD/MMC: Transfer data timeout\n"));
620       return EFI_TIMEOUT;
621     }
622   } while (!(IntStatus & NOR_INT_STS_XFER_COMPLETE));
623 
624   return EFI_SUCCESS;
625 }
626 
627 EFI_STATUS
XenonInit(IN SD_MMC_HC_PRIVATE_DATA * Private)628 XenonInit (
629   IN SD_MMC_HC_PRIVATE_DATA *Private
630   )
631 {
632   EFI_PCI_IO_PROTOCOL *PciIo = Private->PciIo;
633 
634   // Read XENON version
635   XenonReadVersion (PciIo, &Private->ControllerVersion);
636 
637   XenonSetFifo (PciIo);
638 
639   // Disable auto clock generator
640   XenonSetAcg (PciIo, FALSE);
641 
642   // XENON has only one port
643   XenonSetSlot (PciIo, XENON_MMC_SLOT_ID, TRUE);
644 
645   XenonSetPower (PciIo, MMC_VDD_165_195, eMMC_VCCQ_1_8V, XENON_MMC_MODE_SD_SDIO);
646 
647   // Set MAX_CLOCK for configuring PHY
648   XenonSetClk (PciIo, Private, XENON_MMC_MAX_CLK);
649   XenonSetPhy (PciIo, MMC_TIMING_UHS_SDR50);
650 
651   XenonConfigureInterrupts (PciIo);
652 
653   // Enable parallel transfer
654   XenonSetParallelTransfer (PciIo, XENON_MMC_SLOT_ID, TRUE);
655   XenonSetTuning (PciIo, XENON_MMC_SLOT_ID, FALSE);
656 
657   // Enable auto clock generator
658   XenonSetAcg (PciIo, TRUE);
659 
660   // Set proper clock for PHY configuration
661   XenonSetClk (PciIo, Private, XENON_MMC_BASE_CLK);
662   XenonPhyInit (PciIo);
663 
664   return EFI_SUCCESS;
665 }
666