]>
Commit | Line | Data |
---|---|---|
33ac4566 AB |
1 | /** @file\r |
2 | FDT client library for consumers of PCI related dynamic PCDs\r | |
3 | \r | |
4 | Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r | |
5 | \r | |
6 | This program and the accompanying materials\r | |
7 | are licensed and made available under the terms and conditions of the BSD License\r | |
8 | which accompanies this distribution. The full text of the license may be found at\r | |
9 | http://opensource.org/licenses/bsd-license.php\r | |
10 | \r | |
11 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
12 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
13 | \r | |
14 | **/\r | |
15 | \r | |
16 | #include <Uefi.h>\r | |
17 | \r | |
18 | #include <Library/BaseLib.h>\r | |
19 | #include <Library/DebugLib.h>\r | |
20 | #include <Library/PcdLib.h>\r | |
21 | #include <Library/UefiBootServicesTableLib.h>\r | |
22 | \r | |
23 | #include <Protocol/FdtClient.h>\r | |
24 | \r | |
c8f1a75a AB |
25 | //\r |
26 | // We expect the "ranges" property of "pci-host-ecam-generic" to consist of\r | |
27 | // records like this.\r | |
28 | //\r | |
29 | #pragma pack (1)\r | |
30 | typedef struct {\r | |
31 | UINT32 Type;\r | |
32 | UINT64 ChildBase;\r | |
33 | UINT64 CpuBase;\r | |
34 | UINT64 Size;\r | |
35 | } DTB_PCI_HOST_RANGE_RECORD;\r | |
36 | #pragma pack ()\r | |
37 | \r | |
38 | #define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31\r | |
39 | #define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30\r | |
40 | #define DTB_PCI_HOST_RANGE_ALIASED BIT29\r | |
41 | #define DTB_PCI_HOST_RANGE_MMIO32 BIT25\r | |
42 | #define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24)\r | |
43 | #define DTB_PCI_HOST_RANGE_IO BIT24\r | |
44 | #define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)\r | |
45 | \r | |
46 | STATIC\r | |
47 | RETURN_STATUS\r | |
48 | GetPciIoTranslation (\r | |
49 | IN FDT_CLIENT_PROTOCOL *FdtClient,\r | |
50 | IN INT32 Node,\r | |
51 | OUT UINT64 *IoTranslation\r | |
52 | )\r | |
53 | {\r | |
54 | UINT32 RecordIdx;\r | |
55 | CONST VOID *Prop;\r | |
56 | UINT32 Len;\r | |
57 | EFI_STATUS Status;\r | |
58 | UINT64 IoBase;\r | |
59 | \r | |
60 | //\r | |
61 | // Iterate over "ranges".\r | |
62 | //\r | |
63 | Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);\r | |
64 | if (EFI_ERROR (Status) || Len == 0 ||\r | |
65 | Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {\r | |
66 | DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));\r | |
67 | return RETURN_PROTOCOL_ERROR;\r | |
68 | }\r | |
69 | \r | |
70 | for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);\r | |
71 | ++RecordIdx) {\r | |
72 | CONST DTB_PCI_HOST_RANGE_RECORD *Record;\r | |
73 | UINT32 Type;\r | |
74 | \r | |
75 | Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;\r | |
76 | Type = SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK;\r | |
77 | if (Type == DTB_PCI_HOST_RANGE_IO) {\r | |
78 | IoBase = SwapBytes64 (Record->ChildBase);\r | |
79 | *IoTranslation = SwapBytes64 (Record->CpuBase) - IoBase;\r | |
80 | \r | |
81 | return RETURN_SUCCESS;\r | |
82 | }\r | |
83 | }\r | |
84 | return RETURN_NOT_FOUND;\r | |
85 | }\r | |
86 | \r | |
33ac4566 AB |
87 | RETURN_STATUS\r |
88 | EFIAPI\r | |
89 | FdtPciPcdProducerLibConstructor (\r | |
90 | VOID\r | |
91 | )\r | |
92 | {\r | |
93 | UINT64 PciExpressBaseAddress;\r | |
94 | FDT_CLIENT_PROTOCOL *FdtClient;\r | |
95 | CONST UINT64 *Reg;\r | |
c8f1a75a | 96 | UINT32 RegSize;\r |
33ac4566 | 97 | EFI_STATUS Status;\r |
c8f1a75a AB |
98 | INT32 Node;\r |
99 | RETURN_STATUS RetStatus;\r | |
100 | UINT64 IoTranslation;\r | |
5d1546b4 | 101 | RETURN_STATUS PcdStatus;\r |
33ac4566 AB |
102 | \r |
103 | PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress);\r | |
104 | if (PciExpressBaseAddress != MAX_UINT64) {\r | |
c8f1a75a AB |
105 | //\r |
106 | // Assume that the fact that PciExpressBaseAddress has been changed from\r | |
107 | // its default value of MAX_UINT64 implies that this code has been\r | |
108 | // executed already, in the context of another module. That means we can\r | |
109 | // assume that PcdPciIoTranslation has been discovered from the DT node\r | |
110 | // as well.\r | |
111 | //\r | |
33ac4566 AB |
112 | return EFI_SUCCESS;\r |
113 | }\r | |
114 | \r | |
115 | Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r | |
116 | (VOID **)&FdtClient);\r | |
117 | ASSERT_EFI_ERROR (Status);\r | |
118 | \r | |
c8f1a75a AB |
119 | PciExpressBaseAddress = 0;\r |
120 | Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",\r | |
121 | &Node);\r | |
122 | \r | |
123 | if (!EFI_ERROR (Status)) {\r | |
124 | Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg",\r | |
125 | (CONST VOID **)&Reg, &RegSize);\r | |
126 | \r | |
127 | if (!EFI_ERROR (Status) && RegSize == 2 * sizeof (UINT64)) {\r | |
128 | PciExpressBaseAddress = SwapBytes64 (*Reg);\r | |
33ac4566 | 129 | \r |
5d1546b4 LE |
130 | PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, FALSE);\r |
131 | ASSERT_RETURN_ERROR (PcdStatus);\r | |
33ac4566 | 132 | \r |
70c368e2 | 133 | IoTranslation = 0;\r |
c8f1a75a AB |
134 | RetStatus = GetPciIoTranslation (FdtClient, Node, &IoTranslation);\r |
135 | if (!RETURN_ERROR (RetStatus)) {\r | |
5d1546b4 LE |
136 | PcdStatus = PcdSet64S (PcdPciIoTranslation, IoTranslation);\r |
137 | ASSERT_RETURN_ERROR (PcdStatus);\r | |
c8f1a75a AB |
138 | } else {\r |
139 | //\r | |
140 | // Support for I/O BARs is not mandatory, and so it does not make sense\r | |
141 | // to abort in the general case. So leave it up to the actual driver to\r | |
142 | // complain about this if it wants to, and just issue a warning here.\r | |
143 | //\r | |
144 | DEBUG ((EFI_D_WARN,\r | |
145 | "%a: 'pci-host-ecam-generic' device encountered with no I/O range\n",\r | |
146 | __FUNCTION__));\r | |
147 | }\r | |
148 | }\r | |
33ac4566 AB |
149 | }\r |
150 | \r | |
5d1546b4 LE |
151 | PcdStatus = PcdSet64S (PcdPciExpressBaseAddress, PciExpressBaseAddress);\r |
152 | ASSERT_RETURN_ERROR (PcdStatus);\r | |
33ac4566 AB |
153 | \r |
154 | return RETURN_SUCCESS;\r | |
155 | }\r |