]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.c
cbcd63c0366a26f7f7b7c5b509f9998e9b7ad718
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Spi / Common / SpiCommon.c
1 /** @file
2 PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
3
4 Copyright (c) 2013-2015 Intel Corporation.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "PchSpi.h"
11
12 VOID
13 FillOutPublicInfoStruct (
14 SPI_INSTANCE *SpiInstance
15 )
16 /*++
17
18 Routine Description:
19
20 Fillout SpiInstance->InitInfo;
21
22 Arguments:
23
24 SpiInstance - Pointer to SpiInstance to initialize
25
26 Returns:
27
28 NONE
29
30 --*/
31 {
32 UINT8 Index;
33
34 SpiInstance->InitInfo.InitTable = &SpiInstance->SpiInitTable;
35
36 //
37 // Give invalid index in case operation not supported.
38 //
39 SpiInstance->InitInfo.JedecIdOpcodeIndex = 0xff;
40 SpiInstance->InitInfo.OtherOpcodeIndex = 0xff;
41 SpiInstance->InitInfo.WriteStatusOpcodeIndex = 0xff;
42 SpiInstance->InitInfo.ProgramOpcodeIndex = 0xff;
43 SpiInstance->InitInfo.ReadOpcodeIndex = 0xff;
44 SpiInstance->InitInfo.EraseOpcodeIndex = 0xff;
45 SpiInstance->InitInfo.ReadStatusOpcodeIndex = 0xff;
46 SpiInstance->InitInfo.FullChipEraseOpcodeIndex = 0xff;
47 for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
48 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {
49 SpiInstance->InitInfo.JedecIdOpcodeIndex = Index;
50 }
51 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationOther) {
52 SpiInstance->InitInfo.OtherOpcodeIndex = Index;
53 }
54 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {
55 SpiInstance->InitInfo.WriteStatusOpcodeIndex = Index;
56 }
57 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationProgramData_1_Byte ||
58 SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationProgramData_64_Byte) {
59 SpiInstance->InitInfo.ProgramOpcodeIndex = Index;
60 }
61 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData ||
62 SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead ||
63 SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) {
64 SpiInstance->InitInfo.ReadOpcodeIndex = Index;
65 }
66 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_256_Byte ||
67 SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_4K_Byte ||
68 SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_8K_Byte ||
69 SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_64K_Byte) {
70 SpiInstance->InitInfo.EraseOpcodeIndex = Index;
71 }
72 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadStatus) {
73 SpiInstance->InitInfo.ReadStatusOpcodeIndex = Index;
74 }
75 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFullChipErase) {
76 SpiInstance->InitInfo.FullChipEraseOpcodeIndex = Index;
77 }
78 }
79 }
80
81 EFI_STATUS
82 SpiProtocolConstructor (
83 SPI_INSTANCE *SpiInstance
84 )
85 /*++
86
87 Routine Description:
88
89 Initialize an SPI protocol instance.
90 The function will assert in debug if PCH RCBA has not been initialized
91
92 Arguments:
93
94 SpiInstance - Pointer to SpiInstance to initialize
95
96 Returns:
97
98 EFI_SUCCESS The protocol instance was properly initialized
99 EFI_UNSUPPORTED The PCH is not supported by this module
100
101 --*/
102 {
103 SpiInstance->InitDone = FALSE; // Indicate NOT READY.
104
105 //
106 // Check if the current PCH is known and supported by this code
107 //
108 if (!IsQncSupported ()) {
109 DEBUG ((DEBUG_ERROR, "PCH SPI Protocol not supported due to no proper QNC LPC found!\n"));
110 return EFI_UNSUPPORTED;
111 }
112 //
113 // Initialize the SPI protocol instance
114 //
115 SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE;
116 SpiInstance->Handle = NULL;
117 SpiInstance->SpiProtocol.Init = SpiProtocolInit;
118 SpiInstance->SpiProtocol.Lock = SpiProtocolLock;
119 SpiInstance->SpiProtocol.Execute = SpiProtocolExecute;
120 SpiInstance->SpiProtocol.Info = SpiProtocolInfo;
121
122 //
123 // Sanity check to ensure PCH RCBA initialization has occurred previously.
124 //
125 SpiInstance->PchRootComplexBar = MmioRead32 (
126 PciDeviceMmBase (PCI_BUS_NUMBER_QNC,
127 PCI_DEVICE_NUMBER_QNC_LPC,
128 PCI_FUNCTION_NUMBER_QNC_LPC) + R_QNC_LPC_RCBA
129 ) & B_QNC_LPC_RCBA_MASK;
130 ASSERT (SpiInstance->PchRootComplexBar != 0);
131
132 return EFI_SUCCESS;
133 }
134
135 EFI_STATUS
136 EFIAPI
137 UnlockFlashComponents (
138 IN EFI_SPI_PROTOCOL *This,
139 IN UINT8 UnlockCmdOpcodeIndex
140 )
141 /*++
142
143 Routine Description:
144
145 Issue unlock command to disable block protection, this only needs to be done once per SPI power on
146
147 Arguments:
148
149 This A pointer to "EFI_SPI_PROTOCOL" for issuing commands
150 UnlockCmdOpcodeIndex The index of the Unlock command
151
152 Returns:
153
154 EFI_SUCCESS UnLock operation succeed.
155 EFI_DEVICE_ERROR Device error, operation failed.
156
157 --*/
158 {
159 EFI_STATUS Status;
160 SPI_INSTANCE *SpiInstance;
161 UINT8 SpiStatus;
162
163 if (UnlockCmdOpcodeIndex >= SPI_NUM_OPCODE) {
164 return EFI_UNSUPPORTED;
165 }
166
167 SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
168
169 //
170 // Issue unlock command to disable block protection, this only needs to be done once per SPI power on
171 //
172 SpiStatus = 0;
173 //
174 // Issue unlock command to the flash component 1 at first
175 //
176 Status = SpiProtocolExecute (
177 This,
178 UnlockCmdOpcodeIndex,
179 SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_ENABLE ? 0 : 1,
180 TRUE,
181 TRUE,
182 TRUE,
183 (UINTN) 0,
184 sizeof (SpiStatus),
185 &SpiStatus,
186 EnumSpiRegionAll
187 );
188 if (EFI_ERROR (Status)) {
189 DEBUG ((EFI_D_ERROR, "Unlock flash component 1 fail!\n"));
190 return Status;
191 }
192
193 return EFI_SUCCESS;
194 }
195
196 EFI_STATUS
197 EFIAPI
198 SpiProtocolInit (
199 IN EFI_SPI_PROTOCOL *This,
200 IN SPI_INIT_TABLE *InitTable
201 )
202 /*++
203
204 Routine Description:
205
206 Initialize the host controller to execute SPI command.
207
208 Arguments:
209
210 This Pointer to the EFI_SPI_PROTOCOL instance.
211 InitTable Initialization data to be programmed into the SPI host controller.
212
213 Returns:
214
215 EFI_SUCCESS Initialization completed.
216 EFI_ACCESS_DENIED The SPI static configuration interface has been locked-down.
217 EFI_INVALID_PARAMETER Bad input parameters.
218 EFI_UNSUPPORTED Can't get Descriptor mode VSCC values
219 --*/
220 {
221 EFI_STATUS Status;
222 UINT8 Index;
223 UINT16 OpcodeType;
224 SPI_INSTANCE *SpiInstance;
225 UINTN PchRootComplexBar;
226 UINT8 UnlockCmdOpcodeIndex;
227 UINT8 FlashPartId[3];
228
229 SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
230 PchRootComplexBar = SpiInstance->PchRootComplexBar;
231
232 if (InitTable != NULL) {
233 //
234 // Copy table into SPI driver Private data structure
235 //
236 CopyMem (
237 &SpiInstance->SpiInitTable,
238 InitTable,
239 sizeof (SPI_INIT_TABLE)
240 );
241 } else {
242 return EFI_INVALID_PARAMETER;
243 }
244 //
245 // Check if the SPI interface has been locked-down.
246 //
247 if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
248 ASSERT_EFI_ERROR (EFI_ACCESS_DENIED);
249 return EFI_ACCESS_DENIED;
250 }
251 //
252 // Clear all the status bits for status regs.
253 //
254 MmioOr16 (
255 (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
256 (UINT16) ((B_QNC_RCRB_SPIS_CDS | B_QNC_RCRB_SPIS_BAS))
257 );
258 MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);
259
260 //
261 // Set the Prefix Opcode registers.
262 //
263 MmioWrite16 (
264 PchRootComplexBar + R_QNC_RCRB_SPIPREOP,
265 (SpiInstance->SpiInitTable.PrefixOpcode[1] << 8) | InitTable->PrefixOpcode[0]
266 );
267 MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIPREOP);
268
269 //
270 // Set Opcode Type Configuration registers.
271 //
272 for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) {
273 switch (SpiInstance->SpiInitTable.OpcodeMenu[Index].Type) {
274 case EnumSpiOpcodeRead:
275 OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_READ << (Index * 2));
276 break;
277 case EnumSpiOpcodeWrite:
278 OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_WRITE << (Index * 2));
279 break;
280 case EnumSpiOpcodeWriteNoAddr:
281 OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE << (Index * 2));
282 break;
283 default:
284 OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_READ << (Index * 2));
285 break;
286 }
287 }
288 MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE, OpcodeType);
289 MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE);
290
291 //
292 // Setup the Opcode Menu registers.
293 //
294 UnlockCmdOpcodeIndex = SPI_NUM_OPCODE;
295 for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
296 MmioWrite8 (
297 PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index,
298 SpiInstance->SpiInitTable.OpcodeMenu[Index].Code
299 );
300 MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index);
301 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {
302 Status = SpiProtocolExecute (
303 This,
304 Index,
305 0,
306 TRUE,
307 TRUE,
308 FALSE,
309 (UINTN) 0,
310 3,
311 FlashPartId,
312 EnumSpiRegionDescriptor
313 );
314 if (EFI_ERROR (Status)) {
315 return Status;
316 }
317 if (FlashPartId[0] != SpiInstance->SpiInitTable.VendorId ||
318 FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0 ||
319 FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1) {
320 return EFI_INVALID_PARAMETER;
321 }
322 }
323
324 if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {
325 UnlockCmdOpcodeIndex = Index;
326 }
327 }
328
329 Status = UnlockFlashComponents (
330 This,
331 UnlockCmdOpcodeIndex
332 );
333 if (EFI_ERROR (Status)) {
334 DEBUG ((EFI_D_ERROR, "Unlock flash components fail!\n"));
335 }
336
337 SpiPhaseInit ();
338 FillOutPublicInfoStruct (SpiInstance);
339 SpiInstance->InitDone = TRUE;
340 return EFI_SUCCESS;
341 }
342
343 EFI_STATUS
344 EFIAPI
345 SpiProtocolLock (
346 IN EFI_SPI_PROTOCOL *This
347 )
348 /*++
349
350 Routine Description:
351
352 Lock the SPI Static Configuration Interface.
353 Once locked, the interface can not be changed and can only be clear by system reset.
354
355 Arguments:
356
357 This Pointer to the EFI_SPI_PROTOCOL instance.
358
359 Returns:
360
361 EFI_SUCCESS Lock operation succeed.
362 EFI_DEVICE_ERROR Device error, operation failed.
363 EFI_ACCESS_DENIED The interface has already been locked.
364
365 --*/
366 {
367 SPI_INSTANCE *SpiInstance;
368 UINTN PchRootComplexBar;
369
370 SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
371 PchRootComplexBar = SpiInstance->PchRootComplexBar;
372
373 //
374 // Check if the SPI interface has been locked-down.
375 //
376 if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
377 return EFI_ACCESS_DENIED;
378 }
379
380 //
381 // Lock-down the configuration interface.
382 //
383 MmioOr16 ((UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS), (UINT16) (B_QNC_RCRB_SPIS_SCL));
384
385 //
386 // Verify if it's really locked.
387 //
388 if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) == 0) {
389 return EFI_DEVICE_ERROR;
390 } else {
391 //
392 // Save updated register in S3 Boot script.
393 //
394 S3BootScriptSaveMemWrite (
395 S3BootScriptWidthUint16,
396 (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
397 1,
398 (VOID *) (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS)
399 );
400 }
401
402 return EFI_SUCCESS;
403 }
404
405 EFI_STATUS
406 EFIAPI
407 SpiProtocolExecute (
408 IN EFI_SPI_PROTOCOL *This,
409 IN UINT8 OpcodeIndex,
410 IN UINT8 PrefixOpcodeIndex,
411 IN BOOLEAN DataCycle,
412 IN BOOLEAN Atomic,
413 IN BOOLEAN ShiftOut,
414 IN UINTN Address,
415 IN UINT32 DataByteCount,
416 IN OUT UINT8 *Buffer,
417 IN SPI_REGION_TYPE SpiRegionType
418 )
419 /*++
420
421 Routine Description:
422
423 Execute SPI commands from the host controller.
424 This function would be called by runtime driver, please do not use any MMIO marco here
425
426 Arguments:
427
428 This Pointer to the EFI_SPI_PROTOCOL instance.
429 OpcodeIndex Index of the command in the OpCode Menu.
430 PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
431 DataCycle TRUE if the SPI cycle contains data
432 Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
433 ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
434 Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
435 Region, this value specifies the offset from the Region Base; for BIOS Region,
436 this value specifies the offset from the start of the BIOS Image. In Non
437 Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
438 Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
439 Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
440 supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
441 the flash (in Non Descriptor Mode)
442 DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the
443 data transfer into multiple operations. This function ensures each operation does
444 not cross 256 byte flash address boundary.
445 *NOTE: if there is some SPI chip that has a stricter address boundary requirement
446 (e.g., its write page size is < 256 byte), then the caller cannot rely on this
447 function to cut the data transfer at proper address boundaries, and it's the
448 caller's reponsibility to pass in a properly cut DataByteCount parameter.
449 Buffer Pointer to caller-allocated buffer containing the dada received or sent during the
450 SPI cycle.
451 SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
452 EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
453 Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
454 and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
455 to base of the 1st flash device (i.e., it is a Flash Linear Address).
456
457 Returns:
458
459 EFI_SUCCESS Command succeed.
460 EFI_INVALID_PARAMETER The parameters specified are not valid.
461 EFI_UNSUPPORTED Command not supported.
462 EFI_DEVICE_ERROR Device error, command aborts abnormally.
463
464 --*/
465 {
466 EFI_STATUS Status;
467 UINT16 BiosCtlSave;
468 UINT32 SmiEnSave;
469
470 BiosCtlSave = 0;
471 SmiEnSave = 0;
472
473 //
474 // Check if the parameters are valid.
475 //
476 if ((OpcodeIndex >= SPI_NUM_OPCODE) || (PrefixOpcodeIndex >= SPI_NUM_PREFIX_OPCODE)) {
477 return EFI_INVALID_PARAMETER;
478 }
479 //
480 // Make sure it's safe to program the command.
481 //
482 if (!WaitForSpiCycleComplete (This, FALSE)) {
483 return EFI_DEVICE_ERROR;
484 }
485
486 //
487 // Acquire access to the SPI interface is not required any more.
488 //
489 //
490 // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI
491 // whose SMI handler accesses flash (e.g. for error logging)
492 //
493 SmiEnSave = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
494 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, (SmiEnSave & ~SMI_EN));
495
496 //
497 // Save BIOS Ctrl register
498 //
499 BiosCtlSave = PciRead16 (
500 PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
501 PCI_DEVICE_NUMBER_QNC_LPC,
502 PCI_FUNCTION_NUMBER_QNC_LPC,
503 R_QNC_LPC_BIOS_CNTL)
504 ) & (B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE | B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP);
505
506 //
507 // Enable flash writing
508 //
509 PciOr16 (
510 PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
511 PCI_DEVICE_NUMBER_QNC_LPC,
512 PCI_FUNCTION_NUMBER_QNC_LPC,
513 R_QNC_LPC_BIOS_CNTL),
514 (UINT16) (B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP)
515 );
516
517 //
518 // If shifts the data out, disable Prefetching and Caching.
519 //
520 if (ShiftOut) {
521 PciAndThenOr16 (
522 PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
523 PCI_DEVICE_NUMBER_QNC_LPC,
524 PCI_FUNCTION_NUMBER_QNC_LPC,
525 R_QNC_LPC_BIOS_CNTL),
526 (UINT16) (~(B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE)),
527 (UINT16) ((B_QNC_LPC_BIOS_CNTL_BCD))
528 );
529 }
530 //
531 // Sends the command to the SPI interface to execute.
532 //
533 Status = SendSpiCmd (
534 This,
535 OpcodeIndex,
536 PrefixOpcodeIndex,
537 DataCycle,
538 Atomic,
539 ShiftOut,
540 Address,
541 DataByteCount,
542 Buffer,
543 SpiRegionType
544 );
545
546 //
547 // Restore BIOS Ctrl register
548 //
549 PciAndThenOr16 (
550 PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
551 PCI_DEVICE_NUMBER_QNC_LPC,
552 PCI_FUNCTION_NUMBER_QNC_LPC,
553 R_QNC_LPC_BIOS_CNTL),
554 (UINT16) (~(B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE | B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP)),
555 (UINT16) (BiosCtlSave)
556 );
557 //
558 // Restore SMIs.
559 //
560 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, SmiEnSave);
561
562 return Status;
563 }
564
565 VOID
566 SpiOffset2Physical (
567 IN EFI_SPI_PROTOCOL *This,
568 IN UINTN SpiRegionOffset,
569 IN SPI_REGION_TYPE SpiRegionType,
570 OUT UINTN *HardwareSpiAddress,
571 OUT UINTN *BaseAddress,
572 OUT UINTN *LimitAddress
573 )
574 /*++
575
576 Routine Description:
577
578 Convert SPI offset to Physical address of SPI hardware
579
580 Arguments:
581
582 This Pointer to the EFI_SPI_PROTOCOL instance.
583 SpiRegionOffset In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
584 Region, this value specifies the offset from the Region Base; for BIOS Region,
585 this value specifies the offset from the start of the BIOS Image. In Non
586 Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
587 Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
588 Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
589 supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
590 the flash (in Non Descriptor Mode)
591 BaseAddress Base Address of the region.
592 SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
593 EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
594 Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
595 and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
596 to base of the 1st flash device (i.e., it is a Flash Linear Address).
597 HardwareSpiAddress Return absolution SPI address (i.e., Flash Linear Address)
598 BaseAddress Return base address of the region type
599 LimitAddress Return limit address of the region type
600
601 Returns:
602
603 EFI_SUCCESS Command succeed.
604
605 --*/
606 {
607 SPI_INSTANCE *SpiInstance;
608
609 SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
610
611 if (SpiRegionType == EnumSpiRegionAll) {
612 //
613 // EnumSpiRegionAll indicates address is relative to flash device (i.e., address is Flash
614 // Linear Address)
615 //
616 *HardwareSpiAddress = SpiRegionOffset;
617 } else {
618 //
619 // Otherwise address is relative to BIOS image
620 //
621 *HardwareSpiAddress = SpiRegionOffset + SpiInstance->SpiInitTable.BiosStartOffset;
622 }
623 }
624
625 EFI_STATUS
626 SendSpiCmd (
627 IN EFI_SPI_PROTOCOL *This,
628 IN UINT8 OpcodeIndex,
629 IN UINT8 PrefixOpcodeIndex,
630 IN BOOLEAN DataCycle,
631 IN BOOLEAN Atomic,
632 IN BOOLEAN ShiftOut,
633 IN UINTN Address,
634 IN UINT32 DataByteCount,
635 IN OUT UINT8 *Buffer,
636 IN SPI_REGION_TYPE SpiRegionType
637 )
638 /*++
639
640 Routine Description:
641
642 This function sends the programmed SPI command to the slave device.
643
644 Arguments:
645
646 OpcodeIndex Index of the command in the OpCode Menu.
647 PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
648 DataCycle TRUE if the SPI cycle contains data
649 Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
650 ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
651 Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
652 Region, this value specifies the offset from the Region Base; for BIOS Region,
653 this value specifies the offset from the start of the BIOS Image. In Non
654 Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
655 Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
656 Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
657 supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
658 the flash (in Non Descriptor Mode)
659 DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the
660 data transfer into multiple operations. This function ensures each operation does
661 not cross 256 byte flash address boundary.
662 *NOTE: if there is some SPI chip that has a stricter address boundary requirement
663 (e.g., its write page size is < 256 byte), then the caller cannot rely on this
664 function to cut the data transfer at proper address boundaries, and it's the
665 caller's reponsibility to pass in a properly cut DataByteCount parameter.
666 Buffer Data received or sent during the SPI cycle.
667 SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
668 EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
669 Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
670 and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
671 to base of the 1st flash device (i.e., it is a Flash Linear Address).
672
673 Returns:
674
675 EFI_SUCCESS SPI command completes successfully.
676 EFI_DEVICE_ERROR Device error, the command aborts abnormally.
677 EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
678 EFI_INVALID_PARAMETER The parameters specified are not valid.
679
680 --*/
681 {
682 UINT32 Index;
683 SPI_INSTANCE *SpiInstance;
684 UINTN HardwareSpiAddr;
685 UINTN SpiBiosSize;
686 UINTN BaseAddress;
687 UINTN LimitAddress;
688 UINT32 SpiDataCount;
689 UINT8 OpCode;
690 UINTN PchRootComplexBar;
691
692 SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
693 PchRootComplexBar = SpiInstance->PchRootComplexBar;
694 SpiBiosSize = SpiInstance->SpiInitTable.BiosSize;
695 OpCode = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + OpcodeIndex);
696
697 //
698 // Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0
699 //
700 if (OpCode == 0 || SpiBiosSize == 0) {
701 ASSERT (FALSE);
702 return EFI_INVALID_PARAMETER;
703 }
704
705 SpiOffset2Physical (This, Address, SpiRegionType, &HardwareSpiAddr, &BaseAddress, &LimitAddress);
706 //
707 // Have direct access to BIOS region in Descriptor mode,
708 //
709 if (SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Type == EnumSpiOpcodeRead &&
710 SpiRegionType == EnumSpiRegionBios) {
711 CopyMem (
712 Buffer,
713 (UINT8 *) ((HardwareSpiAddr - BaseAddress) + (UINT32) (~(SpiBiosSize - 1))),
714 DataByteCount
715 );
716 return EFI_SUCCESS;
717 }
718 //
719 // DEBUG((EFI_D_ERROR, "SPIADDR %x, %x, %x, %x\n", Address, HardwareSpiAddr, BaseAddress,
720 // LimitAddress));
721 //
722 if ((DataCycle == FALSE) && (DataByteCount > 0)) {
723 DataByteCount = 0;
724 }
725
726 do {
727 //
728 // Trim at 256 byte boundary per operation,
729 // - PCH SPI controller requires trimming at 4KB boundary
730 // - Some SPI chips require trimming at 256 byte boundary for write operation
731 // - Trimming has limited performance impact as we can read / write atmost 64 byte
732 // per operation
733 //
734 if (HardwareSpiAddr + DataByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
735 SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
736 } else {
737 SpiDataCount = DataByteCount;
738 }
739 //
740 // Calculate the number of bytes to shift in/out during the SPI data cycle.
741 // Valid settings for the number of bytes duing each data portion of the
742 // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
743 //
744 if (SpiDataCount >= 64) {
745 SpiDataCount = 64;
746 } else if ((SpiDataCount &~0x07) != 0) {
747 SpiDataCount = SpiDataCount &~0x07;
748 }
749 //
750 // If shifts data out, load data into the SPI data buffer.
751 //
752 if (ShiftOut) {
753 for (Index = 0; Index < SpiDataCount; Index++) {
754 MmioWrite8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index, Buffer[Index]);
755 MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
756 }
757 }
758
759 MmioWrite32 (
760 (PchRootComplexBar + R_QNC_RCRB_SPIA),
761 (UINT32) (HardwareSpiAddr & B_QNC_RCRB_SPIA_MASK)
762 );
763 MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIA);
764
765 //
766 // Execute the command on the SPI compatible mode
767 //
768
769 //
770 // Clear error flags
771 //
772 MmioOr16 ((PchRootComplexBar + R_QNC_RCRB_SPIS), B_QNC_RCRB_SPIS_BAS);
773
774 //
775 // Initialte the SPI cycle
776 //
777 if (DataCycle) {
778 MmioWrite16 (
779 (PchRootComplexBar + R_QNC_RCRB_SPIC),
780 ( (UINT16) (B_QNC_RCRB_SPIC_DC) | (UINT16) (((SpiDataCount - 1) << 8) & B_QNC_RCRB_SPIC_DBC) |
781 (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
782 (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
783 (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
784 (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
785 } else {
786 MmioWrite16 (
787 (PchRootComplexBar + R_QNC_RCRB_SPIC),
788 ( (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
789 (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
790 (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
791 (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
792 }
793
794 MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIC);
795
796 //
797 // end of command execution
798 //
799 // Wait the SPI cycle to complete.
800 //
801 if (!WaitForSpiCycleComplete (This, TRUE)) {
802 return EFI_DEVICE_ERROR;
803 }
804 //
805 // If shifts data in, get data from the SPI data buffer.
806 //
807 if (!ShiftOut) {
808 for (Index = 0; Index < SpiDataCount; Index++) {
809 Buffer[Index] = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
810 }
811 }
812
813 HardwareSpiAddr += SpiDataCount;
814 Buffer += SpiDataCount;
815 DataByteCount -= SpiDataCount;
816 } while (DataByteCount > 0);
817
818 return EFI_SUCCESS;
819 }
820
821 BOOLEAN
822 WaitForSpiCycleComplete (
823 IN EFI_SPI_PROTOCOL *This,
824 IN BOOLEAN ErrorCheck
825 )
826 /*++
827
828 Routine Description:
829
830 Wait execution cycle to complete on the SPI interface. Check both Hardware
831 and Software Sequencing status registers
832
833 Arguments:
834
835 This - The SPI protocol instance
836 UseSoftwareSequence - TRUE if this is a Hardware Sequencing operation
837 ErrorCheck - TRUE if the SpiCycle needs to do the error check
838
839 Returns:
840
841 TRUE SPI cycle completed on the interface.
842 FALSE Time out while waiting the SPI cycle to complete.
843 It's not safe to program the next command on the SPI interface.
844
845 --*/
846 {
847 UINT64 WaitTicks;
848 UINT64 WaitCount;
849 UINT16 Data16;
850 SPI_INSTANCE *SpiInstance;
851 UINTN PchRootComplexBar;
852
853 SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
854 PchRootComplexBar = SpiInstance->PchRootComplexBar;
855
856 //
857 // Convert the wait period allowed into to tick count
858 //
859 WaitCount = WAIT_TIME / WAIT_PERIOD;
860
861 //
862 // Wait for the SPI cycle to complete.
863 //
864 for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
865 Data16 = MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);
866 if ((Data16 & B_QNC_RCRB_SPIS_SCIP) == 0) {
867 MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIS, (B_QNC_RCRB_SPIS_BAS | B_QNC_RCRB_SPIS_CDS));
868 if ((Data16 & B_QNC_RCRB_SPIS_BAS) && (ErrorCheck == TRUE)) {
869 return FALSE;
870 } else {
871 return TRUE;
872 }
873 }
874
875 MicroSecondDelay (WAIT_PERIOD);
876 }
877
878 return FALSE;
879 }
880
881 EFI_STATUS
882 EFIAPI
883 SpiProtocolInfo (
884 IN EFI_SPI_PROTOCOL *This,
885 OUT SPI_INIT_INFO **InitInfoPtr
886 )
887 /*++
888
889 Routine Description:
890
891 Return info about SPI host controller, to help callers usage of Execute
892 service.
893
894 If 0xff is returned as an opcode index in init info struct
895 then device does not support the operation.
896
897 Arguments:
898
899 This Pointer to the EFI_SPI_PROTOCOL instance.
900 InitInfoPtr Pointer to init info written to this memory location.
901
902 Returns:
903
904 EFI_SUCCESS Information returned.
905 EFI_INVALID_PARAMETER Invalid parameter.
906 EFI_NOT_READY Required resources not setup.
907 Others Unexpected error happened.
908
909 --*/
910 {
911 SPI_INSTANCE *SpiInstance;
912
913 if (This == NULL || InitInfoPtr == NULL) {
914 return EFI_INVALID_PARAMETER;
915 }
916 SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
917 if (SpiInstance->Signature != PCH_SPI_PRIVATE_DATA_SIGNATURE) {
918 return EFI_INVALID_PARAMETER;
919 }
920
921 if (!SpiInstance->InitDone) {
922 *InitInfoPtr = NULL;
923 return EFI_NOT_READY;
924 }
925 *InitInfoPtr = &SpiInstance->InitInfo;
926 return EFI_SUCCESS;
927 }