Skip to content

Commit 8b9659e

Browse files
committed
WIP UFS boot fix
Signed-off-by: Matt DeVillier <[email protected]>
1 parent 04b39a5 commit 8b9659e

File tree

2 files changed

+280
-2
lines changed

2 files changed

+280
-2
lines changed

UefiPayloadPkg/UfsPlatformDxe/UfsPlatformDxe.c

Lines changed: 278 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,254 @@ UfsDmeSet (
7878
return Status;
7979
}
8080

81+
/**
82+
Execute a UIC DME_GET command to read a UniPro attribute.
83+
84+
@param[in] UfsHcDriver Pointer to UFS HC driver interface.
85+
@param[in] MibAttribute MIB attribute address (upper 16 bits) and
86+
GenSelectorIndex (lower 16 bits).
87+
@param[out] Value Pointer to store the read value.
88+
89+
@retval EFI_SUCCESS Command executed successfully.
90+
@retval Others Command execution failed.
91+
92+
**/
93+
STATIC
94+
EFI_STATUS
95+
UfsDmeGet (
96+
IN EDKII_UFS_HC_DRIVER_INTERFACE *UfsHcDriver,
97+
IN UINT32 MibAttribute,
98+
OUT UINT32 *Value
99+
)
100+
{
101+
EDKII_UIC_COMMAND UicCommand;
102+
EFI_STATUS Status;
103+
104+
ZeroMem (&UicCommand, sizeof (EDKII_UIC_COMMAND));
105+
106+
UicCommand.Opcode = UIC_CMD_DME_GET;
107+
UicCommand.Arg1 = MibAttribute;
108+
UicCommand.Arg2 = 0;
109+
UicCommand.Arg3 = 0;
110+
111+
Status = UfsHcDriver->UfsExecUicCommand (UfsHcDriver, &UicCommand);
112+
if (EFI_ERROR (Status)) {
113+
DEBUG ((
114+
DEBUG_ERROR,
115+
"%a: DME_GET failed for MIB 0x%04x, Status = %r\n",
116+
__FUNCTION__,
117+
(MibAttribute >> 16) & 0xFFFF,
118+
Status
119+
));
120+
return Status;
121+
}
122+
123+
*Value = UicCommand.Arg3;
124+
return EFI_SUCCESS;
125+
}
126+
127+
/**
128+
Execute a UIC DME_PEER_GET command to read a peer UniPro attribute.
129+
130+
@param[in] UfsHcDriver Pointer to UFS HC driver interface.
131+
@param[in] MibAttribute MIB attribute address (upper 16 bits) and
132+
GenSelectorIndex (lower 16 bits).
133+
@param[out] Value Pointer to store the read value.
134+
135+
@retval EFI_SUCCESS Command executed successfully.
136+
@retval Others Command execution failed.
137+
138+
**/
139+
STATIC
140+
EFI_STATUS
141+
UfsDmePeerGet (
142+
IN EDKII_UFS_HC_DRIVER_INTERFACE *UfsHcDriver,
143+
IN UINT32 MibAttribute,
144+
OUT UINT32 *Value
145+
)
146+
{
147+
EDKII_UIC_COMMAND UicCommand;
148+
EFI_STATUS Status;
149+
150+
ZeroMem (&UicCommand, sizeof (EDKII_UIC_COMMAND));
151+
152+
UicCommand.Opcode = UIC_CMD_DME_PEER_GET;
153+
UicCommand.Arg1 = MibAttribute;
154+
UicCommand.Arg2 = 0;
155+
UicCommand.Arg3 = 0;
156+
157+
Status = UfsHcDriver->UfsExecUicCommand (UfsHcDriver, &UicCommand);
158+
if (EFI_ERROR (Status)) {
159+
DEBUG ((
160+
DEBUG_ERROR,
161+
"%a: DME_PEER_GET failed for MIB 0x%04x, Status = %r\n",
162+
__FUNCTION__,
163+
(MibAttribute >> 16) & 0xFFFF,
164+
Status
165+
));
166+
return Status;
167+
}
168+
169+
*Value = UicCommand.Arg3;
170+
return EFI_SUCCESS;
171+
}
172+
173+
/**
174+
Execute a UIC DME_PEER_SET command to configure a peer UniPro attribute.
175+
176+
@param[in] UfsHcDriver Pointer to UFS HC driver interface.
177+
@param[in] MibAttribute MIB attribute address (upper 16 bits) and
178+
GenSelectorIndex (lower 16 bits).
179+
@param[in] Value Value to set.
180+
181+
@retval EFI_SUCCESS Command executed successfully.
182+
@retval Others Command execution failed.
183+
184+
**/
185+
STATIC
186+
EFI_STATUS
187+
UfsDmePeerSet (
188+
IN EDKII_UFS_HC_DRIVER_INTERFACE *UfsHcDriver,
189+
IN UINT32 MibAttribute,
190+
IN UINT32 Value
191+
)
192+
{
193+
EDKII_UIC_COMMAND UicCommand;
194+
EFI_STATUS Status;
195+
196+
ZeroMem (&UicCommand, sizeof (EDKII_UIC_COMMAND));
197+
198+
UicCommand.Opcode = UIC_CMD_DME_PEER_SET;
199+
UicCommand.Arg1 = MibAttribute;
200+
UicCommand.Arg2 = (DME_ATTR_SET_TYPE_NORMAL << 16);
201+
UicCommand.Arg3 = Value;
202+
203+
Status = UfsHcDriver->UfsExecUicCommand (UfsHcDriver, &UicCommand);
204+
if (EFI_ERROR (Status)) {
205+
DEBUG ((
206+
DEBUG_ERROR,
207+
"%a: DME_PEER_SET failed for MIB 0x%04x, Status = %r\n",
208+
__FUNCTION__,
209+
(MibAttribute >> 16) & 0xFFFF,
210+
Status
211+
));
212+
}
213+
214+
return Status;
215+
}
216+
217+
/**
218+
Apply Intel-specific device quirks for proper UFS operation.
219+
220+
This function implements the critical PA_TACTIVATE adjustment required
221+
for Intel Lakefield and later platforms. If the host and device
222+
PA_GRANULARITY values match, the peer PA_TACTIVATE must be increased
223+
to ensure proper timing during power mode changes.
224+
225+
@param[in] UfsHcDriver Pointer to UFS HC driver interface.
226+
227+
@retval EFI_SUCCESS Quirks applied successfully.
228+
@retval Others Failed to apply quirks.
229+
230+
**/
231+
STATIC
232+
EFI_STATUS
233+
ApplyIntelDeviceQuirks (
234+
IN EDKII_UFS_HC_DRIVER_INTERFACE *UfsHcDriver
235+
)
236+
{
237+
EFI_STATUS Status;
238+
UINT32 Granularity;
239+
UINT32 PeerGranularity;
240+
UINT32 PaTactivate;
241+
UINT32 PeerPaTactivate;
242+
UINT32 NewPeerPaTactivate;
243+
UINT32 MibAttribute;
244+
245+
//
246+
// Read PA_GRANULARITY from host
247+
//
248+
MibAttribute = (PA_GRANULARITY << 16);
249+
Status = UfsDmeGet (UfsHcDriver, MibAttribute, &Granularity);
250+
if (EFI_ERROR (Status)) {
251+
return Status;
252+
}
253+
254+
//
255+
// Read PA_GRANULARITY from peer (device)
256+
//
257+
Status = UfsDmePeerGet (UfsHcDriver, MibAttribute, &PeerGranularity);
258+
if (EFI_ERROR (Status)) {
259+
return Status;
260+
}
261+
262+
//
263+
// Read PA_TACTIVATE from host
264+
//
265+
MibAttribute = (PA_TACTIVATE << 16);
266+
Status = UfsDmeGet (UfsHcDriver, MibAttribute, &PaTactivate);
267+
if (EFI_ERROR (Status)) {
268+
return Status;
269+
}
270+
271+
//
272+
// Read PA_TACTIVATE from peer (device)
273+
//
274+
Status = UfsDmePeerGet (UfsHcDriver, MibAttribute, &PeerPaTactivate);
275+
if (EFI_ERROR (Status)) {
276+
return Status;
277+
}
278+
279+
DEBUG ((
280+
DEBUG_INFO,
281+
"%a: Host PA_GRANULARITY=%u, Peer PA_GRANULARITY=%u\n",
282+
__FUNCTION__,
283+
Granularity,
284+
PeerGranularity
285+
));
286+
DEBUG ((
287+
DEBUG_INFO,
288+
"%a: Host PA_TACTIVATE=%u, Peer PA_TACTIVATE=%u\n",
289+
__FUNCTION__,
290+
PaTactivate,
291+
PeerPaTactivate
292+
));
293+
294+
//
295+
// CRITICAL: If granularity values match, adjust peer PA_TACTIVATE
296+
// This is required for proper timing on Intel platforms
297+
//
298+
if (Granularity == PeerGranularity) {
299+
NewPeerPaTactivate = PaTactivate + 2;
300+
301+
DEBUG ((
302+
DEBUG_INFO,
303+
"%a: Granularity match detected, adjusting Peer PA_TACTIVATE to %u\n",
304+
__FUNCTION__,
305+
NewPeerPaTactivate
306+
));
307+
308+
Status = UfsDmePeerSet (UfsHcDriver, MibAttribute, NewPeerPaTactivate);
309+
if (EFI_ERROR (Status)) {
310+
DEBUG ((
311+
DEBUG_ERROR,
312+
"%a: Failed to set Peer PA_TACTIVATE, Status = %r\n",
313+
__FUNCTION__,
314+
Status
315+
));
316+
return Status;
317+
}
318+
319+
DEBUG ((
320+
DEBUG_INFO,
321+
"%a: Successfully adjusted Peer PA_TACTIVATE\n",
322+
__FUNCTION__
323+
));
324+
}
325+
326+
return EFI_SUCCESS;
327+
}
328+
81329
/**
82330
Platform-specific callback function for UFS host controller initialization.
83331
@@ -154,6 +402,11 @@ UfsPlatformCallback (
154402
// Called after Host Controller Enable (HCE)
155403
// No platform-specific configuration needed at this phase for Intel
156404
//
405+
// Note: Crypto enable (CRYPTO_GENERAL_ENABLE) would be done here on
406+
// newer platforms (Lakefield+), but requires direct MMIO access which
407+
// is not available through the current protocol interface. The EDK2
408+
// UFS core driver may handle this automatically on supported platforms.
409+
//
157410
DEBUG ((DEBUG_INFO, "%a: PostHce - No action required\n", __FUNCTION__));
158411
break;
159412

@@ -204,9 +457,32 @@ UfsPlatformCallback (
204457
case EdkiiUfsHcPostLinkStartup:
205458
//
206459
// Called after link startup completes
207-
// No platform-specific configuration needed at this phase for Intel
208460
//
209-
DEBUG ((DEBUG_INFO, "%a: PostLinkStartup - No action required\n", __FUNCTION__));
461+
// CRITICAL: Apply Intel device quirks including PA_TACTIVATE adjustment
462+
// This is required for proper I/O operation and boot functionality
463+
//
464+
DEBUG ((
465+
DEBUG_INFO,
466+
"%a: PostLinkStartup - Applying Intel device quirks\n",
467+
__FUNCTION__
468+
));
469+
470+
Status = ApplyIntelDeviceQuirks (UfsHcDriver);
471+
if (EFI_ERROR (Status)) {
472+
DEBUG ((
473+
DEBUG_ERROR,
474+
"%a: Failed to apply Intel device quirks, Status = %r\n",
475+
__FUNCTION__,
476+
Status
477+
));
478+
return Status;
479+
}
480+
481+
DEBUG ((
482+
DEBUG_INFO,
483+
"%a: Intel device quirks applied successfully\n",
484+
__FUNCTION__
485+
));
210486
break;
211487

212488
default:

UefiPayloadPkg/UfsPlatformDxe/UfsPlatformDxe.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
// Reference: MIPI UniPro v1.6 and UFS Specification
3131
//
3232
#define PA_LOCAL_TX_LCC_ENABLE 0x155E
33+
#define PA_GRANULARITY 0x15AA
34+
#define PA_TACTIVATE 0x15A8
3335

3436
//
3537
// UIC Command Opcodes

0 commit comments

Comments
 (0)