1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
/** @file
WINBOND W25*** family SPI flash support
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/SpiFlashPart.h>
#include <Library/DebugLib.h>
//
// Initialization data that can be used to identify SPI flash part
// DeviceId0 Device ID0 of the SPI device
// DeviceId1 Device ID1 of the SPI device
//
typedef struct _SPI_CHIP_ID {
UINT8 DeviceId0;
UINT8 DeviceId1;
} SPI_CHIP_ID;
//
// Flash VendorId and DeviceId
//
#define SF_VENDOR_ID_WINBOND 0xEF
#define SF_DEVICE_ID0_W25XXX 0x30
#define SF_DEVICE_ID1_W25X32 0x16
#define SF_DEVICE_ID1_W25X64 0x17
#define SF_DEVICE_ID0_W25QXX 0x60
#define SF_DEVICE_ID0_W25QXX2 0x40
#define SF_DEVICE_ID1_W25Q16 0x15
#define SF_DEVICE_ID1_W25Q32 0x16
#define SF_DEVICE_ID1_W25Q64 0x17
#define SF_DEVICE_ID1_W25Q128 0x18
//
// Generic SPI flash part description
//
CONST FLASH_PART_DESCRIPTION mFlashDescription = {
L"WINBOND W25Q*** family", // Part number
1, // Number of status bytes
0x06, // Write enable
0x50, // Write status enable
3, // Length of JEDEC ID response
8, // Number of opcodes in the table
// Opcode table
{
{33000000, 3, FALSE, 0x9f, 0, SPI_FLASH_PART_OPCODE_JEDEC_ID},
{50000000, 1, FALSE, 0x05, 0, SPI_FLASH_PART_OPCODE_READ_STATUS},
{50000000, 1, TRUE, 0x01, 0, SPI_FLASH_PART_OPCODE_WRITE_STATUS},
{33000000, 0xffffffff, FALSE, 0x03, 3, SPI_FLASH_PART_OPCODE_READ_BYTES},
{50000000, 1, TRUE, 0x02, 3, SPI_FLASH_PART_OPCODE_WRITE_256_BYTE_PAGE},
{50000000, 0, TRUE, 0x20, 3, SPI_FLASH_PART_OPCODE_ERASE_4K_BYTE_BLOCK},
{50000000, 0, TRUE, 0xd8, 3, SPI_FLASH_PART_OPCODE_ERASE_64K_BYTE_BLOCK},
{50000000, 0, TRUE, 0x5a, 0, SPI_FLASH_PART_OPCODE_WRITE_DISABLE_DISCOVERY}
}
};
SPI_CHIP_ID mSpiChipIdTable[] = {
{
SF_DEVICE_ID0_W25QXX, // DeviceId 0
SF_DEVICE_ID1_W25Q64 // DeviceId 1
},
{
SF_DEVICE_ID0_W25QXX2, // DeviceId 0
SF_DEVICE_ID1_W25Q64 // DeviceId 1
}
};
/**
Get the flash part size and opcode table.
Validate support for this flash part and determine
the flash part size and opcode description table
from the JEDEC ID information provided.
@param[in] This Pointer to a SPI_FLASH_DATA_PROTOCOL
data structure.
@param[in] JedecId Pointer to a three byte buffer containing
the JEDEC ID returned by the flash part.
If the input value is NULL then a
table containing the description for the
JEDEC ID opcode is returned by this
routine.
@param[out] FlashSize Pointer to receive the size of the flash
part in bytes. Zero (0) is returned when
JedecId is NULL.
@returns When JedecId is not NULL, this routine returns a pointer
to a FLASH_PART_DESCRIPTION data structure which supports
this flash part. The returned value is NULL if the flash
part is not supported.
When JedecId is NULL, this routine returns a pointer to
a FLASH_PART_DESCRIPTION structure which supports the
JEDEC ID command. This opcode description may be used
to determine the manufacture and product data for the
SPI flash part.
**/
CONST FLASH_PART_DESCRIPTION *
EFIAPI
GetFlashDescription (
IN SPI_FLASH_PART_PROTOCOL *This,
IN UINT8 *JedecId OPTIONAL,
OUT UINT64 *FlashSize OPTIONAL
)
{
CONST FLASH_PART_DESCRIPTION *FlashDescription;
UINT8 Shift;
UINT64 Size;
UINTN Index;
//
// Determine if the SPI flash device is supported
//
Size = 0;
FlashDescription = &mFlashDescription;
if (JedecId != NULL) {
FlashDescription = NULL;
if (JedecId [0] != SF_VENDOR_ID_WINBOND)
return NULL;
for (Index = 0;Index < (sizeof (mSpiChipIdTable) / sizeof (SPI_CHIP_ID));Index++) {
if ((JedecId [1] == mSpiChipIdTable[Index].DeviceId0)
&& (JedecId [2] == mSpiChipIdTable[Index].DeviceId1))
break;
}
if (Index >= (sizeof (mSpiChipIdTable) / sizeof (SPI_CHIP_ID)))
return NULL;
Shift = JedecId[2];
if (Shift < 64) {
Size = LShiftU64 (1, Shift);
FlashDescription = &mFlashDescription;
}
}
//
// Return the flash size
//
if (FlashSize != NULL) {
*FlashSize = Size;
}
return FlashDescription;
}
SPI_FLASH_PART_PROTOCOL mSpiFlashPartProtocol = {
0xC0000000, /// SPI flash part family priority
GetFlashDescription
};
/**
Indicate that all the SPI devices are available
@retval EFI_SUCCESS SPI flash part protocol installed successfully
**/
EFI_STATUS
EFIAPI
SpiFlashPart (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
//
// Install the SPI flash part protocol
//
Status = gBS->InstallMultipleProtocolInterfaces (
&gImageHandle,
&gSpiFlashPartProtocolGuid,
&mSpiFlashPartProtocol,
NULL
);
return Status;
}
|