• 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 "ComPhyLib.h"
36 
37 CHAR16 * TypeStringTable [] = {L"unconnected", L"PCIE0", L"PCIE1", L"PCIE2",
38                            L"PCIE3", L"SATA0", L"SATA1", L"SATA2", L"SATA3",
39                            L"SGMII0", L"SGMII1", L"SGMII2", L"SGMII3",
40                            L"QSGMII", L"USB3_HOST0", L"USB3_HOST1",
41                            L"USB3_DEVICE", L"XAUI0", L"XAUI1", L"XAUI2",
42                            L"XAUI3", L"RXAUI0", L"RXAUI1", L"KR"};
43 
44 CHAR16 * SpeedStringTable [] = {L"-", L"1.25 Gbps", L"1.5 Gbps", L"2.5 Gbps",
45                                 L"3.0 Gbps", L"3.125 Gbps", L"5 Gbps",
46                                 L"6 Gbps", L"6.25 Gbps", L"10.31 Gbps"};
47 
48 CHIP_COMPHY_CONFIG ChipCfgTbl[] = {
49   {
50     .ChipType = L"Cp110",
51     .Init = ComPhyCp110Init
52   }
53 };
54 
55 VOID
RegSet(IN EFI_PHYSICAL_ADDRESS Addr,IN UINT32 Data,IN UINT32 Mask)56 RegSet (
57   IN EFI_PHYSICAL_ADDRESS Addr,
58   IN UINT32 Data,
59   IN UINT32 Mask
60   )
61 {
62   DEBUG((DEBUG_INFO, "Write to address = %10x, data = %10x (mask = %10x)"
63     "- ", Addr, Data, Mask));
64   DEBUG((DEBUG_INFO, "old value = %10x ==> ", MmioRead32 (Addr)));
65   RegSetSilent (Addr, Data, Mask);
66   DEBUG((DEBUG_INFO, "new value %10x\n", MmioRead32 (Addr)));
67 }
68 
69 VOID
RegSetSilent(IN EFI_PHYSICAL_ADDRESS Addr,IN UINT32 Data,IN UINT32 Mask)70 RegSetSilent (
71   IN EFI_PHYSICAL_ADDRESS Addr,
72   IN UINT32 Data,
73   IN UINT32 Mask
74   )
75 {
76   UINT32 RegData;
77 
78   RegData = MmioRead32 (Addr);
79   RegData &= ~Mask;
80   RegData |= Data;
81   MmioWrite32 (Addr, RegData);
82 }
83 
84 VOID
RegSet16(IN EFI_PHYSICAL_ADDRESS Addr,IN UINT16 Data,IN UINT16 Mask)85 RegSet16 (
86   IN EFI_PHYSICAL_ADDRESS Addr,
87   IN UINT16 Data,
88   IN UINT16 Mask
89   )
90 {
91   DEBUG((DEBUG_INFO, "Write to address = %#010lx, Data = %#06x (mask = %#06x)"
92     "- ", Addr, Data, Mask));
93   DEBUG((DEBUG_INFO, "old value = %#06x ==> ", MmioRead16 (Addr)));
94   RegSetSilent16 (Addr, Data, Mask);
95   DEBUG((DEBUG_INFO, "new value %#06x\n", MmioRead16 (Addr)));
96 }
97 
98 VOID
RegSetSilent16(IN EFI_PHYSICAL_ADDRESS Addr,IN UINT16 Data,IN UINT16 Mask)99 RegSetSilent16(
100   IN EFI_PHYSICAL_ADDRESS Addr,
101   IN UINT16 Data,
102   IN UINT16 Mask
103   )
104 {
105   UINT16 RegData;
106   RegData = MmioRead16(Addr);
107   RegData &= ~Mask;
108   RegData |= Data;
109   MmioWrite16 (Addr, RegData);
110 }
111 
112 /* This function returns enum with SerDesType */
113 UINT32
ParseSerdesTypeString(CHAR16 * String)114 ParseSerdesTypeString (
115   CHAR16* String
116   )
117 {
118   UINT32 i;
119 
120   if (String == NULL)
121     return PHY_TYPE_INVALID;
122 
123   for (i = 0; i < PHY_TYPE_MAX; i++) {
124     if (StrCmp (String, TypeStringTable[i]) == 0) {
125       return i;
126     }
127   }
128 
129   /* PCD string doesn't match any supported SerDes Type */
130   return PHY_TYPE_INVALID;
131 }
132 
133 /* This function converts SerDes speed in MHz to enum with SerDesSpeed */
134 UINT32
ParseSerdesSpeed(UINT32 Value)135 ParseSerdesSpeed (
136   UINT32 Value
137   )
138 {
139   UINT32 i;
140   UINT32 ValueTable [] = {0, 1250, 1500, 2500, 3000, 3125,
141                           5000, 6000, 6250, 10310};
142 
143   for (i = 0; i < 10; i++) {
144     if (Value == ValueTable[i]) {
145       return i;
146     }
147   }
148 
149   /* PCD SerDes speed value doesn't match any supported SerDes speed */
150   return PHY_SPEED_INVALID;
151 }
152 
153 CHAR16 *
GetTypeString(UINT32 Type)154 GetTypeString (
155   UINT32 Type
156   )
157 {
158 
159   if (Type < 0 || Type > PHY_TYPE_MAX) {
160     return L"invalid";
161   }
162 
163   return TypeStringTable[Type];
164 }
165 
166 CHAR16 *
GetSpeedString(UINT32 Speed)167 GetSpeedString (
168   UINT32 Speed
169   )
170 {
171 
172   if (Speed < 0 || Speed > 10) {
173     return L"invalid";
174   }
175 
176   return SpeedStringTable[Speed];
177 }
178 
179 VOID
ComPhyPrint(IN CHIP_COMPHY_CONFIG * PtrChipCfg)180 ComPhyPrint (
181   IN CHIP_COMPHY_CONFIG *PtrChipCfg
182   )
183 {
184   UINT32 Lane;
185   CHAR16 *SpeedStr, *TypeStr;
186 
187   for (Lane = 0; Lane < PtrChipCfg->LanesCount; Lane++) {
188     SpeedStr = GetSpeedString(PtrChipCfg->MapData[Lane].Speed);
189     TypeStr = GetTypeString(PtrChipCfg->MapData[Lane].Type);
190     DEBUG((DEBUG_ERROR, "Comphy-%d: %-13s %-10s\n", Lane, TypeStr, SpeedStr));
191   }
192 
193   DEBUG((DEBUG_ERROR, "\n"));
194 }
195 
196 EFI_STATUS
GetChipComPhyInit(IN CHIP_COMPHY_CONFIG * PtrChipCfg)197 GetChipComPhyInit (
198   IN CHIP_COMPHY_CONFIG *PtrChipCfg
199   )
200 {
201   UINTN i, TblSize;
202 
203 
204   TblSize = sizeof(ChipCfgTbl) / sizeof(ChipCfgTbl[0]);
205 
206   for (i = 0; i < TblSize ; i++) {
207     if (StrCmp (PtrChipCfg->ChipType, ChipCfgTbl[i].ChipType) == 0) {
208       PtrChipCfg->Init = ChipCfgTbl[i].Init;
209       return EFI_SUCCESS;
210     }
211   }
212 
213   DEBUG((DEBUG_ERROR, "ComPhy: Empty ChipType string\n"));
214   return EFI_D_ERROR;
215 }
216 
217 STATIC
218 VOID
InitComPhyConfig(IN OUT CHIP_COMPHY_CONFIG * ChipConfig,IN OUT PCD_LANE_MAP * LaneData)219 InitComPhyConfig (
220   IN  OUT  CHIP_COMPHY_CONFIG *ChipConfig,
221   IN  OUT  PCD_LANE_MAP       *LaneData
222   )
223 {
224   /*
225    * Below macro contains variable name concatenation (used to form PCD's name)
226    * and that's why invoking it cannot be automated, e.g. using for loop.
227    * Currently up to 4 ComPhys might be configured.
228    */
229   GetComPhyPcd(ChipConfig, LaneData, 0);
230   GetComPhyPcd(ChipConfig, LaneData, 1);
231   GetComPhyPcd(ChipConfig, LaneData, 2);
232   GetComPhyPcd(ChipConfig, LaneData, 3);
233 }
234 
235 EFI_STATUS
MvComPhyInit(VOID)236 MvComPhyInit (
237   VOID
238   )
239 {
240   EFI_STATUS Status;
241   CHIP_COMPHY_CONFIG ChipConfig[MAX_CHIPS], *PtrChipCfg;
242   PCD_LANE_MAP LaneData[MAX_CHIPS];
243   UINT32 Lane, ChipCount, i, MaxComphyCount;
244 
245   ChipCount = PcdGet32 (PcdComPhyChipCount);
246 
247   InitComPhyConfig(ChipConfig, LaneData);
248 
249   if (ChipCount <= 0 || ChipCount > MAX_CHIPS)
250     return EFI_INVALID_PARAMETER;
251 
252   for (i = 0; i < ChipCount ; i++) {
253     PtrChipCfg = &ChipConfig[i];
254 
255     /* Get the count of the SerDes of the specific chip */
256     MaxComphyCount = PtrChipCfg->LanesCount;
257     for (Lane = 0; Lane < MaxComphyCount; Lane++) {
258       /* Parse PCD with string indicating SerDes Type */
259       PtrChipCfg->MapData[Lane].Type =
260         ParseSerdesTypeString (LaneData[i].TypeStr[Lane]);
261       PtrChipCfg->MapData[Lane].Speed =
262         ParseSerdesSpeed (LaneData[i].SpeedValue[Lane]);
263       PtrChipCfg->MapData[Lane].Invert = (UINT32) LaneData[i].InvFlag[Lane];
264 
265       if ((PtrChipCfg->MapData[Lane].Speed == PHY_SPEED_INVALID) ||
266           (PtrChipCfg->MapData[Lane].Speed == PHY_SPEED_ERROR) ||
267           (PtrChipCfg->MapData[Lane].Type == PHY_TYPE_INVALID)) {
268         DEBUG((DEBUG_ERROR, "ComPhy: No valid phy speed or type for lane %d, "
269           "setting lane as unconnected\n", Lane + 1));
270         PtrChipCfg->MapData[Lane].Type = PHY_TYPE_UNCONNECTED;
271         PtrChipCfg->MapData[Lane].Speed = PHY_SPEED_INVALID;
272       }
273     };
274 
275     Status = GetChipComPhyInit (PtrChipCfg);
276     if (EFI_ERROR(Status)) {
277      DEBUG((DEBUG_ERROR, "ComPhy: Invalid Chip%dType name\n", i));
278      return Status;
279     }
280 
281     ComPhyPrint (PtrChipCfg);
282 
283     /* PHY power UP sequence */
284     PtrChipCfg->Init (PtrChipCfg);
285   }
286 
287   return EFI_SUCCESS;
288 }
289