1/** @file
2*
3*  Copyright (c) 2014-2015, Linaro Limited. All rights reserved.
4*  Copyright (c) 2014-2015, Hisilicon Limited. All rights reserved.
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 <Library/ArmPlatformLib.h>
17#include <Library/DebugLib.h>
18#include <Library/HobLib.h>
19#include <Library/PcdLib.h>
20#include <Library/IoLib.h>
21#include <Library/MemoryAllocationLib.h>
22
23#include <Hi6220.h>
24
25// The total number of descriptors, including the final "end-of-table" descriptor.
26#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 12
27
28// DDR attributes
29#define DDR_ATTRIBUTES_CACHED           ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
30#define DDR_ATTRIBUTES_UNCACHED         ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
31
32#define HIKEY_EXTRA_SYSTEM_MEMORY_BASE  0x40000000
33#define HIKEY_EXTRA_SYSTEM_MEMORY_SIZE  0x40000000
34
35STATIC struct HiKeyReservedMemory {
36  EFI_PHYSICAL_ADDRESS         Offset;
37  EFI_PHYSICAL_ADDRESS         Size;
38} HiKeyReservedMemoryBuffer [] = {
39  { 0x05E00000, 0x00100000 },    // MCU
40  { 0x05F01000, 0x00001000 },    // ADB REBOOT "REASON"
41  { 0x06DFF000, 0x00001000 },    // MAILBOX
42  { 0x0740F000, 0x00001000 },    // MAILBOX
43  { 0x21F00000, 0x00100000 },    // PSTORE/RAMOOPS
44  { 0x3E000000, 0x02000000 }     // TEE OS
45};
46
47STATIC
48UINT64
49EFIAPI
50HiKeyInitMemorySize (
51  IN VOID
52  )
53{
54  UINT32               Count, Data, MemorySize;
55
56  Count = 0;
57  while (MmioRead32 (MDDRC_AXI_BASE + AXI_REGION_MAP_OFFSET (Count)) != 0) {
58    Count++;
59  }
60  Data = MmioRead32 (MDDRC_AXI_BASE + AXI_REGION_MAP_OFFSET (Count - 1));
61  MemorySize = 16 << ((Data >> 8) & 0x7);
62  MemorySize += Data << 24;
63  return (UINT64) (MemorySize << 20);
64}
65
66/**
67  Return the Virtual Memory Map of your platform
68
69  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU on your platform.
70
71  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR describing a Physical-to-
72                                    Virtual Memory mapping. This array must be ended by a zero-filled
73                                    entry
74
75**/
76VOID
77ArmPlatformGetVirtualMemoryMap (
78  IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
79  )
80{
81  ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
82  UINTN                         Index = 0, Count, ReservedTop;
83  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
84  EFI_PEI_HOB_POINTERS          NextHob;
85  EFI_RESOURCE_ATTRIBUTE_TYPE   ResourceAttributes;
86  UINT64                        ResourceLength;
87  EFI_PHYSICAL_ADDRESS          ResourceTop;
88  UINT64                        MemorySize, AdditionalMemorySize;
89
90  MemorySize = HiKeyInitMemorySize ();
91
92  ResourceAttributes = (
93      EFI_RESOURCE_ATTRIBUTE_PRESENT |
94      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
95      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
96      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
97      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
98      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
99      EFI_RESOURCE_ATTRIBUTE_TESTED
100  );
101
102  // Create initial Base Hob for system memory.
103  BuildResourceDescriptorHob (
104      EFI_RESOURCE_SYSTEM_MEMORY,
105      ResourceAttributes,
106      PcdGet64 (PcdSystemMemoryBase),
107      PcdGet64 (PcdSystemMemorySize)
108  );
109
110  NextHob.Raw = GetHobList ();
111  Count = sizeof (HiKeyReservedMemoryBuffer) / sizeof (struct HiKeyReservedMemory);
112  while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL)
113  {
114    if (Index >= Count)
115      break;
116    if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
117        (HiKeyReservedMemoryBuffer[Index].Offset >= NextHob.ResourceDescriptor->PhysicalStart) &&
118        ((HiKeyReservedMemoryBuffer[Index].Offset + HiKeyReservedMemoryBuffer[Index].Size) <=
119         NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength))
120    {
121      ResourceAttributes = NextHob.ResourceDescriptor->ResourceAttribute;
122      ResourceLength = NextHob.ResourceDescriptor->ResourceLength;
123      ResourceTop = NextHob.ResourceDescriptor->PhysicalStart + ResourceLength;
124      ReservedTop = HiKeyReservedMemoryBuffer[Index].Offset + HiKeyReservedMemoryBuffer[Index].Size;
125
126      // Create the System Memory HOB for the reserved buffer
127      BuildResourceDescriptorHob (EFI_RESOURCE_MEMORY_RESERVED,
128                                  EFI_RESOURCE_ATTRIBUTE_PRESENT,
129                                  HiKeyReservedMemoryBuffer[Index].Offset,
130                                  HiKeyReservedMemoryBuffer[Index].Size);
131      // Update the HOB
132      NextHob.ResourceDescriptor->ResourceLength = HiKeyReservedMemoryBuffer[Index].Offset - NextHob.ResourceDescriptor->PhysicalStart;
133
134      // If there is some memory available on the top of the reserved memory then create a HOB
135      if (ReservedTop < ResourceTop)
136      {
137        BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
138                                    ResourceAttributes,
139                                    ReservedTop,
140                                    ResourceTop - ReservedTop);
141      }
142      Index++;
143    }
144    NextHob.Raw = GET_NEXT_HOB (NextHob);
145  }
146
147  AdditionalMemorySize = MemorySize - PcdGet64 (PcdSystemMemorySize);
148  if (AdditionalMemorySize >= SIZE_1GB) {
149    // Declared the additional memory
150    ResourceAttributes =
151        EFI_RESOURCE_ATTRIBUTE_PRESENT |
152        EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
153        EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
154        EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
155        EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
156        EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
157        EFI_RESOURCE_ATTRIBUTE_TESTED;
158
159    BuildResourceDescriptorHob (
160      EFI_RESOURCE_SYSTEM_MEMORY,
161      ResourceAttributes,
162      HIKEY_EXTRA_SYSTEM_MEMORY_BASE,
163      HIKEY_EXTRA_SYSTEM_MEMORY_SIZE);
164  }
165
166  ASSERT (VirtualMemoryMap != NULL);
167
168  VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR*)AllocatePages(EFI_SIZE_TO_PAGES (sizeof(ARM_MEMORY_REGION_DESCRIPTOR) * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
169  if (VirtualMemoryTable == NULL) {
170      return;
171  }
172
173  if (FeaturePcdGet(PcdCacheEnable) == TRUE) {
174      CacheAttributes = DDR_ATTRIBUTES_CACHED;
175  } else {
176      CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
177  }
178
179  Index = 0;
180
181  // Hi6220 SOC peripherals
182  VirtualMemoryTable[Index].PhysicalBase    = HI6220_PERIPH_BASE;
183  VirtualMemoryTable[Index].VirtualBase     = HI6220_PERIPH_BASE;
184  VirtualMemoryTable[Index].Length          = HI6220_PERIPH_SZ;
185  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
186
187  // DDR - predefined 1GB size
188  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet64 (PcdSystemMemoryBase);
189  VirtualMemoryTable[Index].VirtualBase     = PcdGet64 (PcdSystemMemoryBase);
190  VirtualMemoryTable[Index].Length          = PcdGet64 (PcdSystemMemorySize);
191  VirtualMemoryTable[Index].Attributes      = CacheAttributes;
192
193  // If DDR capacity is 2GB size, append a new entry to fill the gap.
194  if (AdditionalMemorySize >= SIZE_1GB) {
195    VirtualMemoryTable[++Index].PhysicalBase = HIKEY_EXTRA_SYSTEM_MEMORY_BASE;
196    VirtualMemoryTable[Index].VirtualBase    = HIKEY_EXTRA_SYSTEM_MEMORY_BASE;
197    VirtualMemoryTable[Index].Length         = HIKEY_EXTRA_SYSTEM_MEMORY_SIZE;
198    VirtualMemoryTable[Index].Attributes     = CacheAttributes;
199  }
200
201  // End of Table
202  VirtualMemoryTable[++Index].PhysicalBase  = 0;
203  VirtualMemoryTable[Index].VirtualBase     = 0;
204  VirtualMemoryTable[Index].Length          = 0;
205  VirtualMemoryTable[Index].Attributes      = (ARM_MEMORY_REGION_ATTRIBUTES)0;
206
207  ASSERT((Index + 1) <= MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS);
208
209  *VirtualMemoryMap = VirtualMemoryTable;
210}
211