summaryrefslogtreecommitdiff
path: root/Platform/ARM/JunoPkg/ConfigurationManager/PlatformASLTablesLib/SsdtPci.asl
blob: 2d47b4dfc013a9830b9e1d8fc51c9794f24ad379 (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
209
210
211
212
213
214
215
216
217
218
/** @file
  SSDT for Juno PCIe

  Copyright (c) 2014-2017, ARM Ltd. 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 "ArmPlatform.h"

/*
  See ACPI 6.1 Section 6.2.13

  There are two ways that _PRT can be used. ...

  In the first model, a PCI Link device is used to provide additional
  configuration information such as whether the interrupt is Level or
  Edge triggered, it is active High or Low, Shared or Exclusive, etc.

  In the second model, the PCI interrupts are hardwired to specific
  interrupt inputs on the interrupt controller and are not
  configurable. In this case, the Source field in _PRT does not
  reference a device, but instead contains the value zero, and the
  Source Index field contains the global system interrupt to which the
  PCI interrupt is hardwired.

  We use the first model with link indirection to set the correct
  interrupt type as PCI defaults (Level Triggered, Active Low) are not
  compatible with GICv2.
*/
#define LNK_DEVICE(Unique_Id, Link_Name, irq)                                                \
        Device(Link_Name) {                                                                  \
            Name(_HID, EISAID("PNP0C0F"))                                                    \
            Name(_UID, Unique_Id)                                                            \
            Name(_PRS, ResourceTemplate() {                                                  \
                Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive) { irq }            \
            })                                                                               \
            Method (_CRS, 0) { Return (_PRS) }                                               \
            Method (_SRS, 1) { }                                                             \
            Method (_DIS) { }                                                                \
        }

#define PRT_ENTRY(Address, Pin, Link)                                                             \
        Package (4) {                                                                             \
            Address,    /* uses the same format as _ADR */                                        \
            Pin,        /* The PCI pin number of the device (0-INTA, 1-INTB, 2-INTC, 3-INTD). */  \
            Link,       /* Interrupt allocated via Link device. */                                \
            Zero        /* global system interrupt number (no used) */                            \
          }

/*
  See Reference [1] 6.1.1
  "High word–Device #, Low word–Function #. (for example, device 3, function 2 is
   0x00030002). To refer to all the functions on a device #, use a function number of FFFF)."
*/
#define ROOT_PRT_ENTRY(Pin, Link)   PRT_ENTRY(0x0000FFFF, Pin, Link)
                                                    // Device 0 for Bridge.

DefinitionBlock("SsdtPci.aml", "SSDT", 1, "ARMLTD", "ARM-JUNO", EFI_ACPI_ARM_OEM_REVISION) {
  Scope(_SB) {
        //
        // PCI Root Complex
        //
        LNK_DEVICE(1, LNKA, 168)
        LNK_DEVICE(2, LNKB, 169)
        LNK_DEVICE(3, LNKC, 170)
        LNK_DEVICE(4, LNKD, 171)

        Device(PCI0)
    {
                  Name(_HID, EISAID("PNP0A08")) // PCI Express Root Bridge
                  Name(_CID, EISAID("PNP0A03")) // Compatible PCI Root Bridge
                  Name(_SEG, Zero) // PCI Segment Group number
                  Name(_BBN, Zero) // PCI Base Bus Number
                  Name(_CCA, 1)    // Initially mark the PCI coherent (for JunoR1)

        // Root Complex 0
        Device (RP0) {
            Name(_ADR, 0xF0000000)    // Dev 0, Func 0
        }

                // PCI Routing Table
                Name(_PRT, Package() {
                        ROOT_PRT_ENTRY(0, LNKA),   // INTA
                        ROOT_PRT_ENTRY(1, LNKB),   // INTB
                        ROOT_PRT_ENTRY(2, LNKC),   // INTC
                        ROOT_PRT_ENTRY(3, LNKD),   // INTD
                })
        // Root complex resources
                Method (_CRS, 0, Serialized) {
                        Name (RBUF, ResourceTemplate () {
                                WordBusNumber ( // Bus numbers assigned to this root
                                        ResourceProducer,
                                        MinFixed, MaxFixed, PosDecode,
                                        0,   // AddressGranularity
                                        0,   // AddressMinimum - Minimum Bus Number
                                        255, // AddressMaximum - Maximum Bus Number
                                        0,   // AddressTranslation - Set to 0
                                        256  // RangeLength - Number of Busses
                                )

                                DWordMemory ( // 32-bit BAR Windows
                                        ResourceProducer, PosDecode,
                                        MinFixed, MaxFixed,
                                        Cacheable, ReadWrite,
                                        0x00000000,                                                         // Granularity
                                        0x50000000,                                                         // Min Base Address
                                        0x57FFFFFF,                                                         // Max Base Address
                                        0x00000000,                                                         // Translate
                                        0x08000000                                                                // Length
                                )

                                QWordMemory ( // 64-bit BAR Windows
                                        ResourceProducer, PosDecode,
                                        MinFixed, MaxFixed,
                                        Cacheable, ReadWrite,
                                        0x00000000,                                                         // Granularity
                                        0x4000000000,                                                         // Min Base Address
                                        0x40FFFFFFFF,                                                         // Max Base Address
                                        0x00000000,                                                         // Translate
                                        0x100000000                                                                // Length
                                )

                                DWordIo ( // IO window
                                        ResourceProducer,
                                        MinFixed,
                                        MaxFixed,
                                        PosDecode,
                                        EntireRange,
                                        0x00000000,                                                         // Granularity
                                        0x00000000,                                                         // Min Base Address
                                        0x007fffff,                                                         // Max Base Address
                                        0x5f800000,                                                         // Translate
                                        0x00800000,                                                          // Length
                                        ,,,TypeTranslation
                                )
                        }) // Name(RBUF)

                        Return (RBUF)
                } // Method(_CRS)

                //
                // OS Control Handoff
                //
                Name(SUPP, Zero) // PCI _OSC Support Field value
                Name(CTRL, Zero) // PCI _OSC Control Field value

                /*
          See [1] 6.2.10, [2] 4.5
                */
                Method(_OSC,4) {
                        // Check for proper UUID
                        If(LEqual(Arg0,ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
                                // Create DWord-adressable fields from the Capabilities Buffer
                                CreateDWordField(Arg3,0,CDW1)
                                CreateDWordField(Arg3,4,CDW2)
                                CreateDWordField(Arg3,8,CDW3)

                                // Save Capabilities DWord2 & 3
                                Store(CDW2,SUPP)
                                Store(CDW3,CTRL)

                                // Only allow native hot plug control if OS supports:
                                // * ASPM
                                // * Clock PM
                                // * MSI/MSI-X
                                If(LNotEqual(And(SUPP, 0x16), 0x16)) {
                                        And(CTRL,0x1E,CTRL) // Mask bit 0 (and undefined bits)
                                }

                                // Always allow native PME, AER (no dependencies)

                                // Never allow SHPC (no SHPC controller in this system)
                                And(CTRL,0x1D,CTRL)

#if 0
                                If(LNot(And(CDW1,1))) {                // Query flag clear?
                                        // Disable GPEs for features granted native control.
                                        If(And(CTRL,0x01)) {        // Hot plug control granted?
                                                Store(0,HPCE)                // clear the hot plug SCI enable bit
                                                Store(1,HPCS)                // clear the hot plug SCI status bit
                                        }
                                        If(And(CTRL,0x04)) {        // PME control granted?
                                                Store(0,PMCE)                // clear the PME SCI enable bit
                                                Store(1,PMCS)                // clear the PME SCI status bit
                                        }
                                        If(And(CTRL,0x10)) {        // OS restoring PCIe cap structure?
                                                // Set status to not restore PCIe cap structure
                                                // upon resume from S3
                                                Store(1,S3CR)
                                        }
                                }
#endif

                                If(LNotEqual(Arg1,One)) {        // Unknown revision
                                        Or(CDW1,0x08,CDW1)
                                }

                                If(LNotEqual(CDW3,CTRL)) {        // Capabilities bits were masked
                                        Or(CDW1,0x10,CDW1)
                                }
                                // Update DWORD3 in the buffer
                                Store(CTRL,CDW3)
                                Return(Arg3)
                        } Else {
                                Or(CDW1,4,CDW1) // Unrecognized UUID
                                Return(Arg3)
                        }
                } // End _OSC
    } // PCI0
  }
}