1/** @file
2  Differentiated System Description Table Fields (SSDT)
3
4  Copyright (c) 2014-2015, ARM Ltd. All rights reserved.<BR>
5    This program and the accompanying materials
6  are licensed and made available under the terms and conditions of the BSD License
7  which accompanies this distribution.  The full text of the license may be found at
8  http://opensource.org/licenses/bsd-license.php
9
10  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "ArmPlatform.h"
16
17/*
18  See Reference [1] 6.2.12
19  "There are two ways that _PRT can be used. ...
20  In the second model, the PCI interrupts are hardwired to specific interrupt
21  inputs on the interrupt controller and are not configurable. In this case,
22  the Source field in _PRT does not reference a device, but instead contains
23  the value zero, and the Source Index field contains the global system
24  interrupt to which the PCI interrupt is hardwired."
25*/
26#define PRT_ENTRY(Address, Pin, Interrupt)                                                       \
27          Package (4) {                                                                           \
28            Address,    /* uses the same format as _ADR */                                        \
29            Pin,        /* The PCI pin number of the device (0-INTA, 1-INTB, 2-INTC, 3-INTD). */  \
30            Zero,       /* allocated from the global interrupt pool. */                           \
31            Interrupt   /* global system interrupt number */                                      \
32          }
33
34/*
35  See Reference [1] 6.1.1
36  "High word–Device #, Low word–Function #. (for example, device 3, function 2 is
37   0x00030002). To refer to all the functions on a device #, use a function number of FFFF)."
38*/
39#define ROOT_PRT_ENTRY(Pin, Interrupt)   PRT_ENTRY(0x0000FFFF, Pin, Interrupt)
40                                                    // Device 0 for Bridge.
41
42
43DefinitionBlock("SsdtPci.aml", "SSDT", 1, "ARMLTD", "ARM-JUNO", EFI_ACPI_ARM_OEM_REVISION) {
44  Scope(_SB) {
45	//
46	// PCI Root Complex
47	//
48	Device(PCI0)
49    {
50  		Name(_HID, EISAID("PNP0A08")) // PCI Express Root Bridge
51  		Name(_CID, EISAID("PNP0A03")) // Compatible PCI Root Bridge
52  		Name(_SEG, Zero) // PCI Segment Group number
53  		Name(_BBN, Zero) // PCI Base Bus Number
54  		Name(_CCA, 1)    // Initially mark the PCI coherent (for JunoR1)
55
56        // Root Complex 0
57        Device (RP0) {
58            Name(_ADR, 0xF0000000)    // Dev 0, Func 0
59        }
60
61		// PCI Routing Table
62		Name(_PRT, Package() {
63			ROOT_PRT_ENTRY(0, 168),   // INTA
64			ROOT_PRT_ENTRY(1, 169),   // INTB
65			ROOT_PRT_ENTRY(2, 170),   // INTC
66			ROOT_PRT_ENTRY(3, 171),   // INTD
67		})
68        // Root complex resources
69		Method (_CRS, 0, Serialized) {
70			Name (RBUF, ResourceTemplate () {
71				WordBusNumber ( // Bus numbers assigned to this root
72					ResourceProducer,
73					MinFixed, MaxFixed, PosDecode,
74					0,   // AddressGranularity
75					0,   // AddressMinimum - Minimum Bus Number
76					255, // AddressMaximum - Maximum Bus Number
77					0,   // AddressTranslation - Set to 0
78					256  // RangeLength - Number of Busses
79				)
80
81				DWordMemory ( // 32-bit BAR Windows
82					ResourceProducer, PosDecode,
83					MinFixed, MaxFixed,
84					Cacheable, ReadWrite,
85					0x00000000, 							// Granularity
86					0x50000000, 							// Min Base Address
87					0x57FFFFFF, 							// Max Base Address
88					0x00000000, 							// Translate
89					0x08000000								// Length
90				)
91
92				QWordMemory ( // 64-bit BAR Windows
93					ResourceProducer, PosDecode,
94					MinFixed, MaxFixed,
95					Cacheable, ReadWrite,
96					0x00000000, 							// Granularity
97					0x4000000000, 							// Min Base Address
98					0x40FFFFFFFF, 							// Max Base Address
99					0x00000000, 							// Translate
100					0x100000000								// Length
101				)
102
103				DWordIo ( // IO window
104					ResourceProducer,
105					MinFixed,
106					MaxFixed,
107					PosDecode,
108					EntireRange,
109					0x00000000, 							// Granularity
110					0x5f800000, 							// Min Base Address
111					0x5fffffff, 							// Max Base Address
112					0x5f800000, 							// Translate
113					0x00800000  							// Length
114				)
115			}) // Name(RBUF)
116
117			Return (RBUF)
118		} // Method(_CRS)
119
120		//
121		// OS Control Handoff
122		//
123		Name(SUPP, Zero) // PCI _OSC Support Field value
124		Name(CTRL, Zero) // PCI _OSC Control Field value
125
126		/*
127	  See [1] 6.2.10, [2] 4.5
128		*/
129		Method(_OSC,4) {
130			// Check for proper UUID
131			If(LEqual(Arg0,ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
132				// Create DWord-adressable fields from the Capabilities Buffer
133				CreateDWordField(Arg3,0,CDW1)
134				CreateDWordField(Arg3,4,CDW2)
135				CreateDWordField(Arg3,8,CDW3)
136
137				// Save Capabilities DWord2 & 3
138				Store(CDW2,SUPP)
139				Store(CDW3,CTRL)
140
141				// Only allow native hot plug control if OS supports:
142				// * ASPM
143				// * Clock PM
144				// * MSI/MSI-X
145				If(LNotEqual(And(SUPP, 0x16), 0x16)) {
146					And(CTRL,0x1E,CTRL) // Mask bit 0 (and undefined bits)
147				}
148
149				// Always allow native PME, AER (no dependencies)
150
151				// Never allow SHPC (no SHPC controller in this system)
152				And(CTRL,0x1D,CTRL)
153
154#if 0
155				If(LNot(And(CDW1,1))) {		// Query flag clear?
156					// Disable GPEs for features granted native control.
157					If(And(CTRL,0x01)) {	// Hot plug control granted?
158						Store(0,HPCE)		// clear the hot plug SCI enable bit
159						Store(1,HPCS)		// clear the hot plug SCI status bit
160					}
161					If(And(CTRL,0x04)) {	// PME control granted?
162						Store(0,PMCE)		// clear the PME SCI enable bit
163						Store(1,PMCS)		// clear the PME SCI status bit
164					}
165					If(And(CTRL,0x10)) {	// OS restoring PCIe cap structure?
166						// Set status to not restore PCIe cap structure
167						// upon resume from S3
168						Store(1,S3CR)
169					}
170				}
171#endif
172
173				If(LNotEqual(Arg1,One)) {	// Unknown revision
174					Or(CDW1,0x08,CDW1)
175				}
176
177				If(LNotEqual(CDW3,CTRL)) {	// Capabilities bits were masked
178					Or(CDW1,0x10,CDW1)
179				}
180				// Update DWORD3 in the buffer
181				Store(CTRL,CDW3)
182				Return(Arg3)
183			} Else {
184				Or(CDW1,4,CDW1) // Unrecognized UUID
185				Return(Arg3)
186			}
187		} // End _OSC
188    } // PCI0
189  }
190}
191