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