summaryrefslogtreecommitdiff
path: root/BraswellPlatformPkg/Common/Flash/SpiFlashParts/MX25/MX25.c
blob: 424dcc318621fe7d027263811206ca15f60c6b6a (plain)
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/** @file
  MACRONIX MX25*** 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>

//
// 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;

//
// Serial Flash VendorId and DeviceId
//
#define SF_VENDOR_ID_MACRONIX     0xC2
#define SF_DEVICE_ID0_MX25LXX     0x20
#define SF_DEVICE_ID0_MX25UXX     0x25
#define SF_DEVICE_ID1_MX25L16     0x15
#define SF_DEVICE_ID1_MX25L32     0x16
#define SF_DEVICE_ID1_MX25L64     0x17
#define SF_DEVICE_ID1_MX25L128    0x18
#define SF_DEVICE_ID1_MX25U32     0x36
#define SF_DEVICE_ID1_MX25U64     0x37

//
// Generic SPI flash part description
//
CONST FLASH_PART_DESCRIPTION mFlashDescription = {
  L"MACRONIX MX25*** 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_MX25LXX,      // DeviceId 0
    SF_DEVICE_ID1_MX25L16       // DeviceId 1
  },
  {
    SF_DEVICE_ID0_MX25LXX,      // DeviceId 0
    SF_DEVICE_ID1_MX25L32       // DeviceId 1
  },
  {
    SF_DEVICE_ID0_MX25LXX,      // DeviceId 0
    SF_DEVICE_ID1_MX25L64       // DeviceId 1
  },
  {
    SF_DEVICE_ID0_MX25LXX,      // DeviceId 0
    SF_DEVICE_ID1_MX25L128      // DeviceId 1
  },
  {
    SF_DEVICE_ID0_MX25UXX,      // DeviceId 0
    SF_DEVICE_ID1_MX25U32       // DeviceId 1
  },
  {
    SF_DEVICE_ID0_MX25UXX,      // DeviceId 0
    SF_DEVICE_ID1_MX25U64       // 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_MACRONIX)
      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 (JedecId [1] == SF_DEVICE_ID0_MX25UXX)
      Shift-= 0x20;

    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;
}