1 //
2 // Copyright (c) 2010-2023 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System.Collections.Generic;
8 using Antmicro.Renode.Exceptions;
9 using Antmicro.Renode.Peripherals.Memory;
10 using Antmicro.Renode.Utilities;
11 
12 namespace Antmicro.Renode.Peripherals.SPI
13 {
14     public class Cypress_S25H : GenericSpiFlash
15     {
Cypress_S25H(MappedMemory underlyingMemory, S25HxFamily memoryFamily = S25HxFamily.HS_T)16         public Cypress_S25H(MappedMemory underlyingMemory, S25HxFamily memoryFamily = S25HxFamily.HS_T)
17             : base(underlyingMemory, manufacturerId: ManufacturerId, memoryType: (byte)memoryFamily,
18                    writeStatusCanSetWriteEnable: true, extendedDeviceId: ExtendedDeviceID,
19                    remainingIdBytes: RemainingIDBytes, deviceConfiguration: DeviceConfiguration,
20                    sectorSizeKB: SectorSizeKB)
21         {
22             if(underlyingMemory.Size < 32.MB() || underlyingMemory.Size > 128.MB())
23             {
24                 throw new ConstructionException("Size of the underlying memory must be in range 32MB - 128MB");
25             }
26         }
27 
GetCapacityCode()28         protected override byte GetCapacityCode()
29         {
30             // S25Hx family of flash chips ignore assumption that 64 MB and larger memories
31             // has capacity codes starting from 0x20, leaving a gap from 0x1A to 0x1F.
32             return (byte)BitHelper.GetMostSignificantSetBitIndex((ulong)this.UnderlyingMemory.Size);
33         }
34 
GetSFDPSignature()35         protected override byte[] GetSFDPSignature()
36         {
37             byte[] patchedSFDPSignature = DefaultSFDPSignature;
38             byte capacity = GetCapacityCode();
39 
40             // Some values in parameters differ between flash size variants.
41             // Outer dictionary uses capacity code as a key to select offset-value
42             // pairs applied to default SFDP signature.
43 
44             // Patched DWORDs:
45             // - Basic Flash Parameter DWORD-2 (0x107), DWORD-11 (0x12B)
46             // - Sector Map Parameter DWORD-10 Config-0 Region-2 (0x1EF)
47             // - Sector Map Parameter DWORD-12 Config-3 Region-0 (0x1F7)
48             // - Sector Map Parameter DWORD-18 Config-1 Region-2 (0x20F)
49             // - Sector Map Parameter DWORD-22 Config-4 Region-0 (0x21F)
50             var patchtable = new Dictionary<byte, Dictionary<ulong, byte>>() {
51                 {0x19, new Dictionary<ulong, byte>() {
52                     {0x107, 0x0F},
53                     {0x12B, 0xE1},
54                     {0x1EF, 0x01},
55                     {0x1F7, 0x01},
56                     {0x20F, 0x01},
57                     {0x21F, 0x01}
58                 }},
59                 {0x1a, new Dictionary<ulong, byte>() {
60                     {0x107, 0x1F},
61                     {0x12B, 0xE3},
62                     {0x1EF, 0x03},
63                     {0x1F7, 0x03},
64                     {0x20F, 0x03},
65                     {0x21F, 0x03}
66                 }},
67                 {0x1b, new Dictionary<ulong, byte>() {
68                     {0x107, 0x3F},
69                     {0x12B, 0xE6},
70                     {0x1EF, 0x07},
71                     {0x1F7, 0x07},
72                     {0x20F, 0x07},
73                     {0x21F, 0x07}
74                 }}
75             };
76 
77             foreach(var patch in patchtable[capacity])
78             {
79                 patchedSFDPSignature[patch.Key] = patch.Value;
80             }
81 
82             return patchedSFDPSignature;
83         }
84 
GetDummyBytes(Commands command)85         protected override int GetDummyBytes(Commands command)
86         {
87             switch(command)
88             {
89                 case Commands.ReadSerialFlashDiscoveryParameter:
90                     return 1;
91                 default:
92                     return base.GetDummyBytes(command);
93             }
94         }
95 
96         private const byte ManufacturerId = 0x34;
97         private const byte MemoryType = 0x2B; // HS-T: 0x2B, HL-T: 0x2A
98         private const byte RemainingIDBytes = 0x0F;
99         private const byte ExtendedDeviceID = 0x03;
100         private const byte DeviceConfiguration = 0x90;
101         private const int SectorSizeKB = 256;
102 
103         private readonly byte[] DefaultSFDPSignature = new byte[]
104         {
105             // SFDP Rev D header table
106             0x53, 0x46, 0x44, 0x50, 0x08, 0x01, 0x03, 0xff, 0x00, 0x00,
107             0x01, 0x14, 0x00, 0x01, 0x00, 0xff, 0x84, 0x00, 0x01, 0x02,
108             0x50, 0x01, 0x00, 0xff, 0x81, 0x00, 0x01, 0x16, 0xc8, 0x01,
109             0x00, 0xff, 0x84, 0x00, 0x01, 0x1c, 0x58, 0x01, 0x00, 0xff,
110             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111             // Values below are not consistent with the spec
112             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133             // SFDP Rev D parameter table
134             0xe7, 0x20, 0xfa, 0xff, 0xff, 0xff, 0xff, 0x1F, 0x48, 0xeb, //0x107: 0x0f/1f/3f
135             0x08, 0x6b, 0x00, 0xff, 0x88, 0xbb, 0xfe, 0xff, 0xff, 0xff,
136             0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x48, 0xeb, 0x0c, 0x20,
137             0x00, 0xff, 0x00, 0xff, 0x12, 0xd8, 0x23, 0xfa, 0xff, 0x8b,
138             0x82, 0xe7, 0xff, 0xE3, 0xec, 0x23, 0x19, 0x49, 0x8a, 0x85, //0x12B: 0xe1/e3/e6
139             0x7a, 0x75, 0xf7, 0x66, 0x80, 0x5c, 0x8c, 0xd6, 0xdd, 0xff,
140             0xf9, 0x38, 0xf8, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141             0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0xf5, 0xff, 0xff,
142             0x7b, 0x92, 0x0f, 0xfe, 0x21, 0xff, 0xff, 0xdc, 0x00, 0x00,
143             0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xc3, 0xeb,
144             0xc8, 0xff, 0xe3, 0xeb, 0x00, 0x65, 0x00, 0x90, 0x06, 0x05,
145             0x00, 0xa1, 0x00, 0x65, 0x00, 0x96, 0x00, 0x65, 0x00, 0x65,
146             0x71, 0x65, 0x03, 0xd0, 0x71, 0x65, 0x03, 0xd0, 0x00, 0x00,
147             0x00, 0x00, 0xb0, 0x2e, 0x00, 0x00, 0x88, 0xa4, 0x89, 0xaa,
148             0x71, 0x65, 0x03, 0x96, 0x71, 0x65, 0x03, 0x96, 0x00, 0x00,
149             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x65,
153             0x05, 0xd5, 0x71, 0x65, 0x05, 0xd5, 0x00, 0x00, 0xa0, 0x15,
154             // SFDP rev D sector map parameter table
155             0xFC, 0x65, 0xFF, 0x08, 0x04, 0x00, 0x80, 0x00, 0xFC, 0x65,
156             0xFF, 0x40, 0x02, 0x00, 0x80, 0x00, 0xFD, 0x65, 0xFF, 0x04,
157             0x02, 0x00, 0x80, 0x00, 0xFE, 0x00, 0x02, 0xFF, 0xF1, 0xFF,
158             0x01, 0x00, 0xF8, 0xFF, 0x01, 0x00, 0xF8, 0xFF, 0xFB, 0x03, //0x1EF: 0x01/03/07
159             0xFE, 0x01, 0x02, 0xFF, 0xF8, 0xFF, 0xFB, 0x03, 0xF8, 0xFF, //0x1F7: 0x01/03/07
160             0x01, 0x00, 0xF1, 0xFF, 0x01, 0x00, 0xFE, 0x02, 0x04, 0xFF,
161             0xF1, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x02, 0x00, 0xF8, 0xFF,
162             0xF7, 0x03, 0xF8, 0xFF, 0x02, 0x00, 0xF1, 0xFF, 0x00, 0x00, //0x20F: 0x01/03/07
163             0xFF, 0x04, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0x03              //0x21F: 0x01/03/07
164         };
165 
166         public enum S25HxFamily : byte
167         {
168             HL_T = 0x2A,
169             HS_T = 0x2B
170         }
171     }
172 }
173