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