dev: Rework how PCI BARs are set up in python and C++.
[gem5.git] / src / dev / arm / RealView.py
1 # Copyright (c) 2009-2020 ARM Limited
2 # All rights reserved.
3 #
4 # The license below extends only to copyright in the software and shall
5 # not be construed as granting a license to any other intellectual
6 # property including but not limited to intellectual property relating
7 # to a hardware implementation of the functionality of the software
8 # licensed hereunder. You may use the software subject to the license
9 # terms below provided that you ensure that this notice is replicated
10 # unmodified and in its entirety in all distributions of the software,
11 # modified or unmodified, in source code or in binary form.
12 #
13 # Copyright (c) 2006-2007 The Regents of The University of Michigan
14 # All rights reserved.
15 #
16 # Redistribution and use in source and binary forms, with or without
17 # modification, are permitted provided that the following conditions are
18 # met: redistributions of source code must retain the above copyright
19 # notice, this list of conditions and the following disclaimer;
20 # redistributions in binary form must reproduce the above copyright
21 # notice, this list of conditions and the following disclaimer in the
22 # documentation and/or other materials provided with the distribution;
23 # neither the name of the copyright holders nor the names of its
24 # contributors may be used to endorse or promote products derived from
25 # this software without specific prior written permission.
26 #
27 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39 from m5.defines import buildEnv
40 from m5.params import *
41 from m5.proxy import *
42 from m5.util.fdthelper import *
43 from m5.objects.ClockDomain import ClockDomain, SrcClockDomain
44 from m5.objects.VoltageDomain import VoltageDomain
45 from m5.objects.Device import \
46 BasicPioDevice, PioDevice, IsaFake, BadAddr, DmaDevice
47 from m5.objects.PciHost import *
48 from m5.objects.Ethernet import NSGigE, IGbE_igb, IGbE_e1000
49 from m5.objects.Ide import *
50 from m5.objects.Platform import Platform
51 from m5.objects.Terminal import Terminal
52 from m5.objects.Uart import Uart
53 from m5.objects.SimpleMemory import SimpleMemory
54 from m5.objects.GenericTimer import *
55 from m5.objects.Gic import *
56 from m5.objects.EnergyCtrl import EnergyCtrl
57 from m5.objects.ClockedObject import ClockedObject
58 from m5.objects.SubSystem import SubSystem
59 from m5.objects.Graphics import ImageFormat
60 from m5.objects.ClockedObject import ClockedObject
61 from m5.objects.PS2 import *
62 from m5.objects.VirtIOMMIO import MmioVirtIO
63 from m5.objects.Display import Display, Display1080p
64 from m5.objects.SMMUv3 import SMMUv3
65 from m5.objects.PciDevice import PciLegacyIoBar, PciIoBar
66
67 # Platforms with KVM support should generally use in-kernel GIC
68 # emulation. Use a GIC model that automatically switches between
69 # gem5's GIC model and KVM's GIC model if KVM is available.
70 try:
71 from m5.objects.KvmGic import MuxingKvmGic
72 kvm_gicv2_class = MuxingKvmGic
73 except ImportError:
74 # KVM support wasn't compiled into gem5. Fallback to a
75 # software-only GIC.
76 kvm_gicv2_class = Gic400
77 pass
78
79 class AmbaPioDevice(BasicPioDevice):
80 type = 'AmbaPioDevice'
81 abstract = True
82 cxx_header = "dev/arm/amba_device.hh"
83 amba_id = Param.UInt32("ID of AMBA device for kernel detection")
84
85 class AmbaIntDevice(AmbaPioDevice):
86 type = 'AmbaIntDevice'
87 abstract = True
88 cxx_header = "dev/arm/amba_device.hh"
89 interrupt = Param.ArmInterruptPin("Interrupt that connects to GIC")
90 int_delay = Param.Latency("100ns",
91 "Time between action and interrupt generation by device")
92
93 class AmbaDmaDevice(DmaDevice):
94 type = 'AmbaDmaDevice'
95 abstract = True
96 cxx_header = "dev/arm/amba_device.hh"
97 pio_addr = Param.Addr("Address for AMBA responder interface")
98 pio_latency = Param.Latency("10ns", "Time between action and write/read"
99 "result by AMBA DMA Device")
100 interrupt = Param.ArmInterruptPin("Interrupt that connects to GIC")
101 amba_id = Param.UInt32("ID of AMBA device for kernel detection")
102
103 class A9SCU(BasicPioDevice):
104 type = 'A9SCU'
105 cxx_header = "dev/arm/a9scu.hh"
106
107 class ArmPciIntRouting(Enum): vals = [
108 'ARM_PCI_INT_STATIC',
109 'ARM_PCI_INT_DEV',
110 'ARM_PCI_INT_PIN',
111 ]
112
113 class GenericArmPciHost(GenericPciHost):
114 type = 'GenericArmPciHost'
115 cxx_header = "dev/arm/pci_host.hh"
116
117 int_policy = Param.ArmPciIntRouting("PCI interrupt routing policy")
118 int_base = Param.Unsigned("PCI interrupt base")
119 int_count = Param.Unsigned("Maximum number of interrupts used by this host")
120
121 # This python parameter can be used in configuration scripts to turn
122 # on/off the fdt dma-coherent flag when doing dtb autogeneration
123 _dma_coherent = True
124
125 def generateDeviceTree(self, state):
126 local_state = FdtState(
127 addr_cells=3, size_cells=2,
128 cpu_cells=1, interrupt_cells=1)
129
130 node = FdtNode("pci")
131
132 if int(self.conf_device_bits) == 8:
133 node.appendCompatible("pci-host-cam-generic")
134 elif int(self.conf_device_bits) == 12:
135 node.appendCompatible("pci-host-ecam-generic")
136 else:
137 m5.fatal("No compatibility string for the set conf_device_width")
138
139 node.append(FdtPropertyStrings("device_type", ["pci"]))
140
141 # Cell sizes of child nodes/peripherals
142 node.append(local_state.addrCellsProperty())
143 node.append(local_state.sizeCellsProperty())
144 node.append(local_state.interruptCellsProperty())
145 # PCI address for CPU
146 node.append(FdtPropertyWords("reg",
147 state.addrCells(self.conf_base) +
148 state.sizeCells(self.conf_size) ))
149
150 # Ranges mapping
151 # For now some of this is hard coded, because the PCI module does not
152 # have a proper full understanding of the memory map, but adapting the
153 # PCI module is beyond the scope of what I'm trying to do here.
154 # Values are taken from the VExpress_GEM5_V1 platform.
155 ranges = []
156 # Pio address range
157 ranges += self.pciFdtAddr(space=1, addr=0)
158 ranges += state.addrCells(self.pci_pio_base)
159 ranges += local_state.sizeCells(0x10000) # Fixed size
160
161 # AXI memory address range
162 ranges += self.pciFdtAddr(space=2, addr=0)
163 ranges += state.addrCells(self.pci_mem_base)
164 ranges += local_state.sizeCells(0x40000000) # Fixed size
165 node.append(FdtPropertyWords("ranges", ranges))
166
167 if str(self.int_policy) == 'ARM_PCI_INT_DEV':
168 gic = self._parent.unproxy(self).gic
169 int_phandle = state.phandle(gic)
170 # Interrupt mapping
171 interrupts = []
172
173 # child interrupt specifier
174 child_interrupt = local_state.interruptCells(0x0)
175
176 # parent unit address
177 parent_addr = gic._state.addrCells(0x0)
178
179 for i in range(int(self.int_count)):
180 parent_interrupt = gic.interruptCells(0,
181 int(self.int_base) - 32 + i, 1)
182
183 interrupts += self.pciFdtAddr(device=i, addr=0) + \
184 child_interrupt + [int_phandle] + parent_addr + \
185 parent_interrupt
186
187 node.append(FdtPropertyWords("interrupt-map", interrupts))
188
189 int_count = int(self.int_count)
190 if int_count & (int_count - 1):
191 fatal("PCI interrupt count should be power of 2")
192
193 intmask = self.pciFdtAddr(device=int_count - 1, addr=0) + [0x0]
194 node.append(FdtPropertyWords("interrupt-map-mask", intmask))
195 else:
196 m5.fatal("Unsupported PCI interrupt policy " +
197 "for Device Tree generation")
198
199 if self._dma_coherent:
200 node.append(FdtProperty("dma-coherent"))
201
202 yield node
203
204 class RealViewCtrl(BasicPioDevice):
205 type = 'RealViewCtrl'
206 cxx_header = "dev/arm/rv_ctrl.hh"
207 proc_id0 = Param.UInt32(0x0C000000, "Processor ID, SYS_PROCID")
208 proc_id1 = Param.UInt32(0x0C000222, "Processor ID, SYS_PROCID1")
209 idreg = Param.UInt32(0x00000000, "ID Register, SYS_ID")
210
211 def generateDeviceTree(self, state):
212 node = FdtNode("sysreg@%x" % long(self.pio_addr))
213 node.appendCompatible("arm,vexpress-sysreg")
214 node.append(FdtPropertyWords("reg",
215 state.addrCells(self.pio_addr) +
216 state.sizeCells(0x1000) ))
217 node.append(FdtProperty("gpio-controller"))
218 node.append(FdtPropertyWords("#gpio-cells", [2]))
219 node.appendPhandle(self)
220
221 yield node
222
223 class RealViewOsc(ClockDomain):
224 type = 'RealViewOsc'
225 cxx_header = "dev/arm/rv_ctrl.hh"
226
227 parent = Param.RealViewCtrl(Parent.any, "RealView controller")
228
229 # TODO: We currently don't have the notion of a clock source,
230 # which means we have to associate oscillators with a voltage
231 # source.
232 voltage_domain = Param.VoltageDomain(Parent.voltage_domain,
233 "Voltage domain")
234
235 # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
236 # the individual core/logic tile reference manuals for details
237 # about the site/position/dcc/device allocation.
238 site = Param.UInt8("Board Site")
239 position = Param.UInt8("Position in device stack")
240 dcc = Param.UInt8("Daughterboard Configuration Controller")
241 device = Param.UInt8("Device ID")
242
243 freq = Param.Clock("Default frequency")
244
245 def generateDeviceTree(self, state):
246 phandle = state.phandle(self)
247 node = FdtNode("osc@" + format(long(phandle), 'x'))
248 node.appendCompatible("arm,vexpress-osc")
249 node.append(FdtPropertyWords("arm,vexpress-sysreg,func",
250 [0x1, int(self.device)]))
251 node.append(FdtPropertyWords("#clock-cells", [0]))
252 freq = int(1.0/self.freq.value) # Values are stored as a clock period
253 node.append(FdtPropertyWords("freq-range", [freq, freq]))
254 node.append(FdtPropertyStrings("clock-output-names",
255 ["oscclk" + str(phandle)]))
256 node.appendPhandle(self)
257 yield node
258
259 class RealViewTemperatureSensor(SimObject):
260 type = 'RealViewTemperatureSensor'
261 cxx_header = "dev/arm/rv_ctrl.hh"
262
263 parent = Param.RealViewCtrl(Parent.any, "RealView controller")
264
265 system = Param.System(Parent.any, "system")
266
267 # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
268 # the individual core/logic tile reference manuals for details
269 # about the site/position/dcc/device allocation.
270 site = Param.UInt8("Board Site")
271 position = Param.UInt8("Position in device stack")
272 dcc = Param.UInt8("Daughterboard Configuration Controller")
273 device = Param.UInt8("Device ID")
274
275 class VExpressMCC(SubSystem):
276 """ARM V2M-P1 Motherboard Configuration Controller
277
278 This subsystem describes a subset of the devices that sit behind the
279 motherboard configuration controller on the the ARM Motherboard
280 Express (V2M-P1) motherboard. See ARM DUI 0447J for details.
281 """
282
283 class Osc(RealViewOsc):
284 site, position, dcc = (0, 0, 0)
285
286 class Temperature(RealViewTemperatureSensor):
287 site, position, dcc = (0, 0, 0)
288
289 osc_mcc = Osc(device=0, freq="50MHz")
290 osc_clcd = Osc(device=1, freq="23.75MHz")
291 osc_peripheral = Osc(device=2, freq="24MHz")
292 osc_system_bus = Osc(device=4, freq="24MHz")
293
294 # See Table 4.19 in ARM DUI 0447J (Motherboard Express uATX TRM).
295 temp_crtl = Temperature(device=0)
296
297 def generateDeviceTree(self, state):
298 node = FdtNode("mcc")
299 node.appendCompatible("arm,vexpress,config-bus")
300 node.append(FdtPropertyWords("arm,vexpress,site", [0]))
301
302 for obj in self._children.values():
303 if issubclass(type(obj), SimObject):
304 node.append(obj.generateDeviceTree(state))
305
306 io_phandle = state.phandle(self.osc_mcc.parent.unproxy(self))
307 node.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle))
308
309 yield node
310
311 class CoreTile2A15DCC(SubSystem):
312 """ARM CoreTile Express A15x2 Daughterboard Configuration Controller
313
314 This subsystem describes a subset of the devices that sit behind the
315 daughterboard configuration controller on a CoreTile Express A15x2. See
316 ARM DUI 0604E for details.
317 """
318
319 class Osc(RealViewOsc):
320 site, position, dcc = (1, 0, 0)
321
322 # See Table 2.8 in ARM DUI 0604E (CoreTile Express A15x2 TRM)
323 osc_cpu = Osc(device=0, freq="60MHz")
324 osc_hsbm = Osc(device=4, freq="40MHz")
325 osc_pxl = Osc(device=5, freq="23.75MHz")
326 osc_smb = Osc(device=6, freq="50MHz")
327 osc_sys = Osc(device=7, freq="60MHz")
328 osc_ddr = Osc(device=8, freq="40MHz")
329
330 def generateDeviceTree(self, state):
331 node = FdtNode("dcc")
332 node.appendCompatible("arm,vexpress,config-bus")
333
334 for obj in self._children.values():
335 if isinstance(obj, SimObject):
336 node.append(obj.generateDeviceTree(state))
337
338 io_phandle = state.phandle(self.osc_cpu.parent.unproxy(self))
339 node.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle))
340
341 yield node
342
343 class AmbaFake(AmbaPioDevice):
344 type = 'AmbaFake'
345 cxx_header = "dev/arm/amba_fake.hh"
346 ignore_access = Param.Bool(False, "Ignore reads/writes to this device, (e.g. IsaFake + AMBA)")
347 amba_id = 0;
348
349 # Simple fixed-rate clock source. Intended to be instantiated in Platform
350 # instances for definition of clock bindings on DTB auto-generation
351 class FixedClock(SrcClockDomain):
352 # Keep track of the number of FixedClock instances in the system
353 # to provide unique names
354 _index = 0
355
356 def generateDeviceTree(self, state):
357 if len(self.clock) > 1:
358 fatal('FixedClock configured with multiple frequencies')
359 node = FdtNode('clock{}'.format(FixedClock._index))
360 node.appendCompatible('fixed-clock')
361 node.append(FdtPropertyWords('#clock-cells', 0))
362 node.append(FdtPropertyWords('clock-frequency',
363 self.clock[0].frequency))
364 node.appendPhandle(self)
365 FixedClock._index += 1
366
367 yield node
368
369 class Pl011(Uart):
370 type = 'Pl011'
371 cxx_header = "dev/arm/pl011.hh"
372 interrupt = Param.ArmInterruptPin("Interrupt that connects to GIC")
373 end_on_eot = Param.Bool(False, "End the simulation when a EOT is received on the UART")
374 int_delay = Param.Latency("100ns", "Time between action and interrupt generation by UART")
375
376 def generateDeviceTree(self, state):
377 node = self.generateBasicPioDeviceNode(state, 'uart', self.pio_addr,
378 0x1000, [ self.interrupt ])
379 node.appendCompatible(["arm,pl011", "arm,primecell"])
380
381 # Hardcoded reference to the realview platform clocks, because the
382 # clk_domain can only store one clock (i.e. it is not a VectorParam)
383 realview = self._parent.unproxy(self)
384 node.append(FdtPropertyWords("clocks",
385 [state.phandle(realview.mcc.osc_peripheral),
386 state.phandle(realview.dcc.osc_smb)]))
387 node.append(FdtPropertyStrings("clock-names", ["uartclk", "apb_pclk"]))
388 yield node
389
390 class Sp804(AmbaPioDevice):
391 type = 'Sp804'
392 cxx_header = "dev/arm/timer_sp804.hh"
393 int0 = Param.ArmSPI("Interrupt that connects to GIC")
394 clock0 = Param.Clock('1MHz', "Clock speed of the input")
395 int1 = Param.ArmSPI("Interrupt that connects to GIC")
396 clock1 = Param.Clock('1MHz', "Clock speed of the input")
397 amba_id = 0x00141804
398
399 class Sp805(AmbaIntDevice):
400 """
401 Arm Watchdog Module (SP805)
402 Reference:
403 Arm Watchdog Module (SP805) - Technical Reference Manual - rev. r1p0
404 Doc. ID: ARM DDI 0270B
405 """
406
407 type = 'Sp805'
408 cxx_header = 'dev/arm/watchdog_sp805.hh'
409
410 amba_id = 0x00141805
411
412 def generateDeviceTree(self, state):
413 node = self.generateBasicPioDeviceNode(state, 'watchdog',
414 self.pio_addr, 0x1000, [ self.interrupt ])
415 node.appendCompatible(['arm,sp805', 'arm,primecell'])
416 clocks = [state.phandle(self.clk_domain.unproxy(self))]
417 clock_names = ['wdogclk']
418 platform = self._parent.unproxy(self)
419 if self in platform._off_chip_devices():
420 clocks.append(state.phandle(platform.dcc.osc_smb))
421 clock_names.append('apb_pclk')
422 node.append(FdtPropertyWords('clocks', clocks))
423 node.append(FdtPropertyStrings('clock-names', clock_names))
424
425 yield node
426
427 class A9GlobalTimer(BasicPioDevice):
428 type = 'A9GlobalTimer'
429 cxx_header = "dev/arm/timer_a9global.hh"
430 gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
431 int_num = Param.UInt32("Interrrupt number that connects to GIC")
432
433 class CpuLocalTimer(BasicPioDevice):
434 type = 'CpuLocalTimer'
435 cxx_header = "dev/arm/timer_cpulocal.hh"
436 int_timer = Param.ArmPPI("Interrrupt used per-cpu to GIC")
437 int_watchdog = Param.ArmPPI("Interrupt for per-cpu watchdog to GIC")
438
439 class PL031(AmbaIntDevice):
440 type = 'PL031'
441 cxx_header = "dev/arm/rtc_pl031.hh"
442 time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)")
443 amba_id = 0x00041031
444
445 def generateDeviceTree(self, state):
446 node = self.generateBasicPioDeviceNode(state, 'rtc', self.pio_addr,
447 0x1000, [ self.interrupt ])
448
449 node.appendCompatible(["arm,pl031", "arm,primecell"])
450 clock = state.phandle(self.clk_domain.unproxy(self))
451 node.append(FdtPropertyWords("clocks", clock))
452 node.append(FdtPropertyStrings("clock-names", ["apb_pclk"]))
453
454 yield node
455
456 class Pl050(AmbaIntDevice):
457 type = 'Pl050'
458 cxx_header = "dev/arm/kmi.hh"
459 amba_id = 0x00141050
460
461 ps2 = Param.PS2Device("PS/2 device")
462
463 def generateDeviceTree(self, state):
464 node = self.generateBasicPioDeviceNode(state, 'kmi', self.pio_addr,
465 0x1000, [ self.interrupt ])
466
467 node.appendCompatible(["arm,pl050", "arm,primecell"])
468 clock = state.phandle(self.clk_domain.unproxy(self))
469 node.append(FdtPropertyWords("clocks", clock))
470
471 yield node
472
473 class Pl111(AmbaDmaDevice):
474 type = 'Pl111'
475 cxx_header = "dev/arm/pl111.hh"
476 pixel_clock = Param.Clock('24MHz', "Pixel clock")
477 vnc = Param.VncInput(Parent.any, "Vnc server for remote frame buffer display")
478 amba_id = 0x00141111
479 enable_capture = Param.Bool(True, "capture frame to system.framebuffer.bmp")
480
481 class HDLcd(AmbaDmaDevice):
482 type = 'HDLcd'
483 cxx_header = "dev/arm/hdlcd.hh"
484 vnc = Param.VncInput(Parent.any, "Vnc server for remote frame buffer "
485 "display")
486 amba_id = 0x00141000
487 workaround_swap_rb = Param.Bool(False, "Workaround incorrect color "
488 "selector order in some kernels")
489 workaround_dma_line_count = Param.Bool(True, "Workaround incorrect "
490 "DMA line count (off by 1)")
491 enable_capture = Param.Bool(True, "capture frame to "
492 "system.framebuffer.{extension}")
493 frame_format = Param.ImageFormat("Auto",
494 "image format of the captured frame")
495
496 pixel_buffer_size = Param.MemorySize32("2kB", "Size of address range")
497
498 pxl_clk = Param.ClockDomain("Pixel clock source")
499 pixel_chunk = Param.Unsigned(32, "Number of pixels to handle in one batch")
500 virt_refresh_rate = Param.Frequency("20Hz", "Frame refresh rate "
501 "in KVM mode")
502 _status = "disabled"
503
504 encoder = Param.Display(Display1080p(), "Display encoder")
505
506 def endpointPhandle(self):
507 return "hdlcd_endpoint"
508
509 def generateDeviceTree(self, state):
510 endpoint_node = FdtNode("endpoint")
511 endpoint_node.appendPhandle(self.endpointPhandle())
512
513 for encoder_node in self.encoder.generateDeviceTree(state):
514 encoder_endpoint = self.encoder.endpointNode()
515
516 # Endpoint subnode
517 endpoint_node.append(FdtPropertyWords("remote-endpoint",
518 [ state.phandle(self.encoder.endpointPhandle()) ]))
519 encoder_endpoint.append(FdtPropertyWords("remote-endpoint",
520 [ state.phandle(self.endpointPhandle()) ]))
521
522 yield encoder_node
523
524 port_node = FdtNode("port")
525 port_node.append(endpoint_node)
526
527 node = self.generateBasicPioDeviceNode(state, 'hdlcd',
528 self.pio_addr, 0x1000, [ self.interrupt ])
529
530 node.appendCompatible(["arm,hdlcd"])
531 node.append(FdtPropertyWords("clocks", state.phandle(self.pxl_clk)))
532 node.append(FdtPropertyStrings("clock-names", ["pxlclk"]))
533
534 # This driver is disabled by default since the required DT nodes
535 # haven't been standardized yet. To use it, override this status to
536 # "ok" and add the display configuration nodes required by the driver.
537 # See the driver for more information.
538 node.append(FdtPropertyStrings("status", [ self._status ]))
539
540 self.addIommuProperty(state, node)
541
542 node.append(port_node)
543
544 yield node
545
546 class FVPBasePwrCtrl(BasicPioDevice):
547 """
548 Based on Fast Models Base_PowerController v11.8
549 Reference:
550 Fast Models Reference Manual - Section 7.7.2 - Version 11.8
551 Document ID: 100964_1180_00_en
552 """
553
554 type = 'FVPBasePwrCtrl'
555 cxx_header = 'dev/arm/fvp_base_pwr_ctrl.hh'
556
557 class RealView(Platform):
558 type = 'RealView'
559 cxx_header = "dev/arm/realview.hh"
560 system = Param.System(Parent.any, "system")
561 _mem_regions = [ AddrRange(0, size='256MB') ]
562 _num_pci_dev = 0
563
564 def _on_chip_devices(self):
565 return []
566
567 def _off_chip_devices(self):
568 return []
569
570 def _on_chip_memory(self):
571 return []
572
573 def _off_chip_memory(self):
574 return []
575
576 _off_chip_ranges = []
577
578 def _attach_memory(self, mem, bus, mem_ports=None):
579 if hasattr(mem, "port"):
580 if mem_ports is None:
581 mem.port = bus.mem_side_ports
582 else:
583 mem_ports.append(mem.port)
584
585 def _attach_device(self, device, bus, dma_ports=None):
586 if hasattr(device, "pio"):
587 device.pio = bus.mem_side_ports
588 if hasattr(device, "dma"):
589 if dma_ports is None:
590 device.dma = bus.cpu_side_ports
591 else:
592 dma_ports.append(device.dma)
593
594 def _attach_io(self, devices, *args, **kwargs):
595 for d in devices:
596 self._attach_device(d, *args, **kwargs)
597
598 def _attach_mem(self, memories, *args, **kwargs):
599 for mem in memories:
600 self._attach_memory(mem, *args, **kwargs)
601
602 def _attach_clk(self, devices, clkdomain):
603 for d in devices:
604 if hasattr(d, "clk_domain"):
605 d.clk_domain = clkdomain
606
607 def attachPciDevices(self):
608 pass
609
610 def enableMSIX(self):
611 pass
612
613 def onChipIOClkDomain(self, clkdomain):
614 self._attach_clk(self._on_chip_devices(), clkdomain)
615
616 def offChipIOClkDomain(self, clkdomain):
617 self._attach_clk(self._off_chip_devices(), clkdomain)
618
619 def attachOnChipIO(self, bus, bridge=None, dma_ports=None, mem_ports=None):
620 self._attach_mem(self._on_chip_memory(), bus, mem_ports)
621 self._attach_io(self._on_chip_devices(), bus, dma_ports)
622 if bridge:
623 bridge.ranges = self._off_chip_ranges
624
625 def attachIO(self, bus, dma_ports=None, mem_ports=None):
626 self._attach_mem(self._off_chip_memory(), bus, mem_ports)
627 self._attach_io(self._off_chip_devices(), bus, dma_ports)
628
629 def setupBootLoader(self, cur_sys, boot_loader, atags_addr, load_offset):
630 cur_sys.workload.boot_loader = boot_loader
631 cur_sys.workload.atags_addr = atags_addr
632 cur_sys.workload.load_addr_offset = load_offset
633
634 def generateDeviceTree(self, state):
635 node = FdtNode("/") # Things in this module need to end up in the root
636 node.append(FdtPropertyWords("interrupt-parent",
637 state.phandle(self.gic)))
638
639 for subnode in self.recurseDeviceTree(state):
640 node.append(subnode)
641
642 yield node
643
644 def annotateCpuDeviceNode(self, cpu, state):
645 system = self.system.unproxy(self)
646 if system._have_psci:
647 cpu.append(FdtPropertyStrings('enable-method', 'psci'))
648 else:
649 cpu.append(FdtPropertyStrings("enable-method", "spin-table"))
650 cpu.append(FdtPropertyWords("cpu-release-addr", \
651 state.addrCells(0x8000fff8)))
652
653 class VExpress_EMM(RealView):
654 _mem_regions = [ AddrRange('2GB', size='2GB') ]
655
656 # Ranges based on excluding what is part of on-chip I/O (gic,
657 # a9scu)
658 _off_chip_ranges = [AddrRange(0x2F000000, size='16MB'),
659 AddrRange(0x30000000, size='256MB'),
660 AddrRange(0x40000000, size='512MB'),
661 AddrRange(0x18000000, size='64MB'),
662 AddrRange(0x1C000000, size='64MB')]
663
664 # Platform control device (off-chip)
665 realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000,
666 idreg=0x02250000, pio_addr=0x1C010000)
667
668 mcc = VExpressMCC()
669 dcc = CoreTile2A15DCC()
670
671 ### On-chip devices ###
672 gic = Gic400(dist_addr=0x2C001000, cpu_addr=0x2C002000)
673 vgic = VGic(vcpu_addr=0x2c006000, hv_addr=0x2c004000, maint_int=25)
674
675 local_cpu_timer = CpuLocalTimer(int_timer=ArmPPI(num=29),
676 int_watchdog=ArmPPI(num=30),
677 pio_addr=0x2C080000)
678
679 hdlcd = HDLcd(pxl_clk=dcc.osc_pxl,
680 pio_addr=0x2b000000, interrupt=ArmSPI(num=117),
681 workaround_swap_rb=True)
682
683 def _on_chip_devices(self):
684 devices = [
685 self.gic, self.vgic,
686 self.local_cpu_timer
687 ]
688 if hasattr(self, "gicv2m"):
689 devices.append(self.gicv2m)
690 devices.append(self.hdlcd)
691 return devices
692
693 def _on_chip_memory(self):
694 memories = [
695 self.bootmem,
696 ]
697 return memories
698
699 ### Off-chip devices ###
700 uart = Pl011(pio_addr=0x1c090000, interrupt=ArmSPI(num=37))
701 pci_host = GenericPciHost(
702 conf_base=0x30000000, conf_size='256MB', conf_device_bits=16,
703 pci_pio_base=0)
704
705 sys_counter = SystemCounter()
706 generic_timer = GenericTimer(int_phys_s=ArmPPI(num=29),
707 int_phys_ns=ArmPPI(num=30),
708 int_virt=ArmPPI(num=27),
709 int_hyp=ArmPPI(num=26))
710
711 timer0 = Sp804(int0=ArmSPI(num=34), int1=ArmSPI(num=34),
712 pio_addr=0x1C110000, clock0='1MHz', clock1='1MHz')
713 timer1 = Sp804(int0=ArmSPI(num=35), int1=ArmSPI(num=35),
714 pio_addr=0x1C120000, clock0='1MHz', clock1='1MHz')
715 clcd = Pl111(pio_addr=0x1c1f0000, interrupt=ArmSPI(num=46))
716 kmi0 = Pl050(pio_addr=0x1c060000, interrupt=ArmSPI(num=44),
717 ps2=PS2Keyboard())
718 kmi1 = Pl050(pio_addr=0x1c070000, interrupt=ArmSPI(num=45),
719 ps2=PS2TouchKit())
720 cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=0, pci_bus=2,
721 io_shift = 2, ctrl_offset = 2, Command = 0x1)
722 cf_ctrl.BAR0 = PciLegacyIoBar(addr='0x1C1A0000', size='256B')
723 cf_ctrl.BAR1 = PciLegacyIoBar(addr='0x1C1A0100', size='4096B')
724
725 bootmem = SimpleMemory(range = AddrRange('64MB'),
726 conf_table_reported = False)
727 vram = SimpleMemory(range = AddrRange(0x18000000, size='32MB'),
728 conf_table_reported = False)
729 rtc = PL031(pio_addr=0x1C170000, interrupt=ArmSPI(num=36))
730
731 l2x0_fake = IsaFake(pio_addr=0x2C100000, pio_size=0xfff)
732 uart1_fake = AmbaFake(pio_addr=0x1C0A0000)
733 uart2_fake = AmbaFake(pio_addr=0x1C0B0000)
734 uart3_fake = AmbaFake(pio_addr=0x1C0C0000)
735 sp810_fake = AmbaFake(pio_addr=0x1C020000, ignore_access=True)
736 watchdog_fake = AmbaFake(pio_addr=0x1C0F0000)
737 aaci_fake = AmbaFake(pio_addr=0x1C040000)
738 lan_fake = IsaFake(pio_addr=0x1A000000, pio_size=0xffff)
739 usb_fake = IsaFake(pio_addr=0x1B000000, pio_size=0x1ffff)
740 mmc_fake = AmbaFake(pio_addr=0x1c050000)
741 energy_ctrl = EnergyCtrl(pio_addr=0x1c080000)
742
743 def _off_chip_devices(self):
744 devices = [
745 self.uart,
746 self.realview_io,
747 self.pci_host,
748 self.timer0,
749 self.timer1,
750 self.clcd,
751 self.kmi0,
752 self.kmi1,
753 self.cf_ctrl,
754 self.rtc,
755 self.vram,
756 self.l2x0_fake,
757 self.uart1_fake,
758 self.uart2_fake,
759 self.uart3_fake,
760 self.sp810_fake,
761 self.watchdog_fake,
762 self.aaci_fake,
763 self.lan_fake,
764 self.usb_fake,
765 self.mmc_fake,
766 self.energy_ctrl,
767 ]
768 # Try to attach the I/O if it exists
769 if hasattr(self, "ide"):
770 devices.append(self.ide)
771 if hasattr(self, "ethernet"):
772 devices.append(self.ethernet)
773 return devices
774
775 # Attach any PCI devices that are supported
776 def attachPciDevices(self):
777 self.ethernet = IGbE_e1000(pci_bus=0, pci_dev=0, pci_func=0,
778 InterruptLine=1, InterruptPin=1)
779 self.ide = IdeController(disks = [], pci_bus=0, pci_dev=1, pci_func=0,
780 InterruptLine=2, InterruptPin=2)
781
782 def enableMSIX(self):
783 self.gic = Gic400(dist_addr=0x2C001000, cpu_addr=0x2C002000,
784 it_lines=512)
785 self.gicv2m = Gicv2m()
786 self.gicv2m.frames = [Gicv2mFrame(spi_base=256, spi_len=64, addr=0x2C1C0000)]
787
788 def setupBootLoader(self, cur_sys, loc, boot_loader=None):
789 if boot_loader is None:
790 boot_loader = loc('boot_emm.arm')
791 super(VExpress_EMM, self).setupBootLoader(
792 cur_sys, boot_loader, 0x8000000, 0x80000000)
793
794 class VExpress_EMM64(VExpress_EMM):
795 # Three memory regions are specified totalling 512GB
796 _mem_regions = [ AddrRange('2GB', size='2GB'),
797 AddrRange('34GB', size='30GB'),
798 AddrRange('512GB', size='480GB') ]
799 pci_host = GenericPciHost(
800 conf_base=0x30000000, conf_size='256MB', conf_device_bits=12,
801 pci_pio_base=0x2f000000)
802
803 def setupBootLoader(self, cur_sys, loc, boot_loader=None):
804 if boot_loader is None:
805 boot_loader = loc('boot_emm.arm64')
806 RealView.setupBootLoader(self, cur_sys, boot_loader,
807 0x8000000, 0x80000000)
808
809 class VExpress_GEM5_Base(RealView):
810 """
811 The VExpress gem5 memory map is loosely based on a modified
812 Versatile Express RS1 memory map.
813
814 The gem5 platform has been designed to implement a subset of the
815 original Versatile Express RS1 memory map. Off-chip peripherals should,
816 when possible, adhere to the Versatile Express memory map. Non-PCI
817 off-chip devices that are gem5-specific should live in the CS5 memory
818 space to avoid conflicts with existing devices that we might want to
819 model in the future. Such devices should normally have interrupts in
820 the gem5-specific SPI range.
821
822 On-chip peripherals are loosely modeled after the ARM CoreTile Express
823 A15x2 memory and interrupt map. In particular, the GIC and
824 Generic Timer have the same interrupt lines and base addresses. Other
825 on-chip devices are gem5 specific.
826
827 Unlike the original Versatile Express RS2 extended platform, gem5 implements a
828 large contigious DRAM space, without aliases or holes, starting at the
829 2GiB boundary. This means that PCI memory is limited to 1GiB.
830
831 References:
832
833 Technical Reference Manuals:
834 Arm Motherboard Express uATX (V2M-P1) - ARM DUI 0447J
835 Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
836
837 Official Linux device tree specifications:
838 V2M-P1 - arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
839 V2P-CA15 - arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
840
841 Memory map:
842 Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
843 Daughterboard (global)
844 Section 3.2.1 - Table 3-1 - Daughterboard memory map
845 On-chip
846 Section 3.2.3 - Table 3-2 - Cortex-A15 MPCore on-chip peripheral
847 memory map
848
849 Interrupts:
850 Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
851 Section 2.8.2 - Test chip interrupts
852
853 Memory map:
854 0x00000000-0x03ffffff: Boot memory (CS0)
855 0x04000000-0x07ffffff: Reserved
856 0x08000000-0x0bffffff: NOR FLASH0 (CS0 alias)
857 0x0c000000-0x0fffffff: NOR FLASH1 (Off-chip, CS4)
858 0x10000000-0x13ffffff: gem5-specific peripherals (Off-chip, CS5)
859 0x10000000-0x1000ffff: gem5 energy controller
860 0x10010000-0x1001ffff: gem5 pseudo-ops
861
862 0x14000000-0x17ffffff: Reserved (Off-chip, PSRAM, CS1)
863 0x18000000-0x1bffffff: Reserved (Off-chip, Peripherals, CS2)
864 0x1c000000-0x1fffffff: Peripheral block 1 (Off-chip, CS3):
865 0x1c010000-0x1c01ffff: realview_io (VE system control regs.)
866 0x1c060000-0x1c06ffff: KMI0 (keyboard)
867 0x1c070000-0x1c07ffff: KMI1 (mouse)
868 0x1c090000-0x1c09ffff: UART0
869 0x1c0a0000-0x1c0affff: UART1
870 0x1c0b0000-0x1c0bffff: UART2
871 0x1c0c0000-0x1c0cffff: UART3
872 0x1c0f0000-0x1c0fffff: Watchdog (SP805)
873 0x1c130000-0x1c13ffff: VirtIO (gem5/FM extension)
874 0x1c140000-0x1c14ffff: VirtIO (gem5/FM extension)
875 0x1c170000-0x1c17ffff: RTC
876
877 0x20000000-0x3fffffff: On-chip peripherals:
878 0x2a430000-0x2a43ffff: System Counter (control)
879 0x2a490000-0x2a49ffff: Trusted Watchdog (SP805)
880 0x2a800000-0x2a800fff: System Counter (read)
881 0x2a810000-0x2a810fff: System Timer (control)
882
883 0x2a820000-0x2a820fff: System Timer (frame 0)
884 0x2a830000-0x2a830fff: System Timer (frame 1)
885
886 0x2b000000-0x2b00ffff: HDLCD
887
888 0x2b060000-0x2b060fff: System Watchdog (SP805)
889
890 0x2b400000-0x2b41ffff: SMMUv3
891
892 0x2c001000-0x2c001fff: GIC (distributor)
893 0x2c002000-0x2c003fff: GIC (CPU interface)
894 0x2c004000-0x2c005fff: vGIC (HV)
895 0x2c006000-0x2c007fff: vGIC (VCPU)
896 0x2c1c0000-0x2c1cffff: GICv2m MSI frame 0
897
898 0x2d000000-0x2d00ffff: GPU (reserved)
899
900 0x2f000000-0x2fffffff: PCI IO space
901 0x30000000-0x3fffffff: PCI config space
902
903 0x40000000-0x7fffffff: Ext. AXI: Used as PCI memory
904
905 0x80000000-X: DRAM
906
907 Interrupts:
908 0- 15: Software generated interrupts (SGIs)
909 16- 31: On-chip private peripherals (PPIs)
910 25 : vgic
911 26 : generic_timer (hyp)
912 27 : generic_timer (virt)
913 28 : Reserved (Legacy FIQ)
914 29 : generic_timer (phys, sec)
915 30 : generic_timer (phys, non-sec)
916 31 : Reserved (Legacy IRQ)
917 32- 95: Mother board peripherals (SPIs)
918 32 : Watchdog (SP805)
919 33 : Reserved (IOFPGA SW int)
920 34-35: Reserved (SP804)
921 36 : RTC
922 37-40: uart0-uart3
923 41-42: Reserved (PL180)
924 43 : Reserved (AACI)
925 44-45: kmi0-kmi1
926 46 : Reserved (CLCD)
927 47 : Reserved (Ethernet)
928 48 : Reserved (USB)
929 56 : Trusted Watchdog (SP805)
930 57 : System timer0 (phys)
931 58 : System timer1 (phys)
932 95-255: On-chip interrupt sources (we use these for
933 gem5-specific devices, SPIs)
934 74 : VirtIO (gem5/FM extension)
935 75 : VirtIO (gem5/FM extension)
936 95 : HDLCD
937 96- 98: GPU (reserved)
938 100-103: PCI
939 130 : System Watchdog (SP805)
940 256-319: MSI frame 0 (gem5-specific, SPIs)
941 320-511: Unused
942
943 """
944
945 # Everything above 2GiB is memory
946 _mem_regions = [ AddrRange('2GB', size='510GB') ]
947
948 _off_chip_ranges = [
949 # CS1-CS5
950 AddrRange(0x0c000000, 0x20000000),
951 # External AXI interface (PCI)
952 AddrRange(0x2f000000, 0x80000000),
953 ]
954
955 bootmem = SimpleMemory(range=AddrRange(0, size='64MB'),
956 conf_table_reported=False)
957
958 # NOR flash, flash0
959 flash0 = SimpleMemory(range=AddrRange(0x08000000, size='64MB'),
960 conf_table_reported=False)
961
962 # Trusted SRAM
963 trusted_sram = SimpleMemory(range=AddrRange(0x04000000, size='256kB'),
964 conf_table_reported=False)
965
966 # Platform control device (off-chip)
967 realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000,
968 idreg=0x30101100, pio_addr=0x1c010000)
969 mcc = VExpressMCC()
970 dcc = CoreTile2A15DCC()
971
972 ### On-chip devices ###
973
974 # Trusted Watchdog, SP805
975 trusted_watchdog = Sp805(pio_addr=0x2a490000, interrupt=ArmSPI(num=56))
976
977 sys_counter = SystemCounter()
978 generic_timer = GenericTimer(int_phys_s=ArmPPI(num=29),
979 int_phys_ns=ArmPPI(num=30),
980 int_virt=ArmPPI(num=27),
981 int_hyp=ArmPPI(num=26))
982 generic_timer_mem = GenericTimerMem(cnt_control_base=0x2a430000,
983 cnt_read_base=0x2a800000,
984 cnt_ctl_base=0x2a810000,
985 frames=[
986 GenericTimerFrame(cnt_base=0x2a820000,
987 int_phys=ArmSPI(num=57), int_virt=ArmSPI(num=133)),
988 GenericTimerFrame(cnt_base=0x2a830000,
989 int_phys=ArmSPI(num=58), int_virt=ArmSPI(num=134))
990 ])
991
992 system_watchdog = Sp805(pio_addr=0x2b060000, interrupt=ArmSPI(num=130))
993
994 def _on_chip_devices(self):
995 return [
996 self.generic_timer_mem,
997 self.trusted_watchdog,
998 self.system_watchdog
999 ] + self.generic_timer_mem.frames
1000
1001 def _on_chip_memory(self):
1002 memories = [
1003 self.bootmem,
1004 self.trusted_sram,
1005 self.flash0,
1006 ]
1007 return memories
1008
1009 ### Off-chip devices ###
1010 io_voltage = VoltageDomain(voltage="3.3V")
1011 clock32KHz = SrcClockDomain(clock="32kHz")
1012 clock24MHz = SrcClockDomain(clock="24MHz")
1013
1014 uart = [
1015 Pl011(pio_addr=0x1c090000,
1016 interrupt=ArmSPI(num=37)),
1017 Pl011(pio_addr=0x1c0a0000,
1018 interrupt=ArmSPI(num=38), device=Terminal()),
1019 Pl011(pio_addr=0x1c0b0000,
1020 interrupt=ArmSPI(num=39), device=Terminal()),
1021 Pl011(pio_addr=0x1c0c0000,
1022 interrupt=ArmSPI(num=40), device=Terminal())
1023 ]
1024
1025 kmi0 = Pl050(pio_addr=0x1c060000, interrupt=ArmSPI(num=44),
1026 ps2=PS2Keyboard())
1027 kmi1 = Pl050(pio_addr=0x1c070000, interrupt=ArmSPI(num=45),
1028 ps2=PS2TouchKit())
1029
1030 watchdog = Sp805(pio_addr=0x1c0f0000, interrupt=ArmSPI(num=32))
1031
1032 rtc = PL031(pio_addr=0x1C170000, interrupt=ArmSPI(num=36))
1033
1034 ### gem5-specific off-chip devices ###
1035 pci_host = GenericArmPciHost(
1036 conf_base=0x30000000, conf_size='256MB', conf_device_bits=12,
1037 pci_pio_base=0x2f000000,
1038 pci_mem_base=0x40000000,
1039 int_policy="ARM_PCI_INT_DEV", int_base=100, int_count=4)
1040
1041 energy_ctrl = EnergyCtrl(pio_addr=0x10000000)
1042
1043 pwr_ctrl = FVPBasePwrCtrl(pio_addr=0x1c100000)
1044
1045 vio = [
1046 MmioVirtIO(pio_addr=0x1c130000, pio_size=0x1000,
1047 interrupt=ArmSPI(num=74)),
1048 MmioVirtIO(pio_addr=0x1c140000, pio_size=0x1000,
1049 interrupt=ArmSPI(num=75)),
1050 ]
1051
1052 # NOR flash, flash1
1053 flash1 = SimpleMemory(range=AddrRange(0x0c000000, 0x10000000),
1054 conf_table_reported=False)
1055
1056 def _off_chip_devices(self):
1057 return [
1058 self.realview_io,
1059 self.kmi0,
1060 self.kmi1,
1061 self.watchdog,
1062 self.rtc,
1063 self.pci_host,
1064 self.energy_ctrl,
1065 self.pwr_ctrl,
1066 self.clock32KHz,
1067 self.clock24MHz,
1068 self.vio[0],
1069 self.vio[1],
1070 ] + self.uart
1071
1072 def _off_chip_memory(self):
1073 return [
1074 self.flash1,
1075 ]
1076
1077 def __init__(self, **kwargs):
1078 super(VExpress_GEM5_Base, self).__init__(**kwargs)
1079 self.clock32KHz.voltage_domain = self.io_voltage
1080 self.clock24MHz.voltage_domain = self.io_voltage
1081 self.system_watchdog.clk_domain = self.dcc.osc_sys
1082 self.watchdog.clk_domain = self.clock32KHz
1083
1084 def attachPciDevice(self, device, *args, **kwargs):
1085 device.host = self.pci_host
1086 self._num_pci_dev += 1
1087 device.pci_bus = 0
1088 device.pci_dev = self._num_pci_dev
1089 device.pci_func = 0
1090 self._attach_device(device, *args, **kwargs)
1091
1092 def attachSmmu(self, devices, bus):
1093 """
1094 Instantiate a single SMMU and attach a group of client devices to it.
1095 The devices' dma port is wired to the SMMU and the SMMU's dma port
1096 is attached to the bus. In order to make it work, the list of clients
1097 shouldn't contain any device part of the _off_chip_devices or
1098 _on_chip_devices.
1099 This method should be called only once.
1100
1101 Parameters:
1102 devices (list): List of devices which will be using the SMMU
1103 bus (Bus): The bus downstream of the SMMU. Its response port will
1104 receive memory requests from the SMMU, and its request
1105 port will forward accesses to the memory mapped devices
1106 """
1107 if hasattr(self, 'smmu'):
1108 m5.fatal("A SMMU has already been instantiated\n")
1109
1110 self.smmu = SMMUv3(reg_map=AddrRange(0x2b400000, size=0x00020000))
1111
1112 self.smmu.request = bus.cpu_side_ports
1113 self.smmu.control = bus.mem_side_ports
1114
1115 dma_ports = []
1116 for dev in devices:
1117 self._attach_device(dev, bus, dma_ports)
1118 self.smmu.connect(dev)
1119
1120 def setupBootLoader(self, cur_sys, boot_loader):
1121 super(VExpress_GEM5_Base, self).setupBootLoader(
1122 cur_sys, boot_loader, 0x8000000, 0x80000000)
1123
1124 # Setup m5ops. It's technically not a part of the boot
1125 # loader, but this is the only place we can configure the
1126 # system.
1127 cur_sys.m5ops_base = 0x10010000
1128
1129 def generateDeviceTree(self, state):
1130 # Generate using standard RealView function
1131 dt = list(super(VExpress_GEM5_Base, self).generateDeviceTree(state))
1132 if len(dt) > 1:
1133 raise Exception("System returned too many DT nodes")
1134 node = dt[0]
1135
1136 node.appendCompatible(["arm,vexpress"])
1137 node.append(FdtPropertyStrings("model", ["V2P-CA15"]))
1138 node.append(FdtPropertyWords("arm,hbi", [0x0]))
1139 node.append(FdtPropertyWords("arm,vexpress,site", [0xf]))
1140
1141 system = self.system.unproxy(self)
1142 if system._have_psci:
1143 # PSCI functions exposed to the kernel
1144 if not system.have_security:
1145 raise AssertionError("PSCI requires EL3 (have_security)")
1146
1147 psci_node = FdtNode('psci')
1148 psci_node.appendCompatible(['arm,psci-1.0', 'arm,psci-0.2',
1149 'arm,psci'])
1150 method = 'smc'
1151 psci_node.append(FdtPropertyStrings('method', method))
1152 psci_node.append(FdtPropertyWords('cpu_suspend', 0xc4000001))
1153 psci_node.append(FdtPropertyWords('cpu_off', 0x84000002))
1154 psci_node.append(FdtPropertyWords('cpu_on', 0xc4000003))
1155 psci_node.append(FdtPropertyWords('sys_poweroff', 0x84000008))
1156 psci_node.append(FdtPropertyWords('sys_reset', 0x84000009))
1157 node.append(psci_node)
1158
1159 yield node
1160
1161 class VExpress_GEM5_V1_Base(VExpress_GEM5_Base):
1162 gic = kvm_gicv2_class(dist_addr=0x2c001000, cpu_addr=0x2c002000,
1163 it_lines=512)
1164 vgic = VGic(vcpu_addr=0x2c006000, hv_addr=0x2c004000, maint_int=25)
1165 gicv2m = Gicv2m()
1166 gicv2m.frames = [
1167 Gicv2mFrame(spi_base=256, spi_len=64, addr=0x2c1c0000),
1168 ]
1169
1170 def setupBootLoader(self, cur_sys, loc, boot_loader=None):
1171 if boot_loader is None:
1172 boot_loader = [ loc('boot.arm64'), loc('boot.arm') ]
1173 super(VExpress_GEM5_V1_Base, self).setupBootLoader(
1174 cur_sys, boot_loader)
1175
1176 def _on_chip_devices(self):
1177 return super(VExpress_GEM5_V1_Base,self)._on_chip_devices() + [
1178 self.gic, self.vgic, self.gicv2m,
1179 ]
1180
1181 class VExpress_GEM5_V1(VExpress_GEM5_V1_Base):
1182 hdlcd = HDLcd(pxl_clk=VExpress_GEM5_V1_Base.dcc.osc_pxl,
1183 pio_addr=0x2b000000, interrupt=ArmSPI(num=95))
1184
1185 def _on_chip_devices(self):
1186 return super(VExpress_GEM5_V1,self)._on_chip_devices() + [
1187 self.hdlcd,
1188 ]
1189
1190 class VExpress_GEM5_V2_Base(VExpress_GEM5_Base):
1191 gic = Gicv3(dist_addr=0x2c000000, redist_addr=0x2c010000,
1192 maint_int=ArmPPI(num=25),
1193 its=Gicv3Its(pio_addr=0x2e010000))
1194
1195 # Limiting to 128 since it will otherwise overlap with PCI space
1196 gic.cpu_max = 128
1197
1198 def _on_chip_devices(self):
1199 return super(VExpress_GEM5_V2_Base,self)._on_chip_devices() + [
1200 self.gic, self.gic.its
1201 ]
1202
1203 def setupBootLoader(self, cur_sys, loc, boot_loader=None):
1204 if boot_loader is None:
1205 boot_loader = [ loc('boot_v2.arm64') ]
1206 super(VExpress_GEM5_V2_Base, self).setupBootLoader(
1207 cur_sys, boot_loader)
1208
1209 class VExpress_GEM5_V2(VExpress_GEM5_V2_Base):
1210 hdlcd = HDLcd(pxl_clk=VExpress_GEM5_V2_Base.dcc.osc_pxl,
1211 pio_addr=0x2b000000, interrupt=ArmSPI(num=95))
1212
1213 def _on_chip_devices(self):
1214 return super(VExpress_GEM5_V2,self)._on_chip_devices() + [
1215 self.hdlcd,
1216 ]
1217
1218 class VExpress_GEM5_Foundation(VExpress_GEM5_Base):
1219 """
1220 Based on Armv8-A FVP Foundation platform v11.8
1221 Reference for memory and interrupt map:
1222 Armv8-A Foundation Platform - User Guide - Version 11.8
1223 Document ID: 100961_1180_00_en
1224 """
1225 _off_chip_ranges = [
1226 # CS1-CS5
1227 AddrRange(0x0c000000, 0x20000000),
1228 # External AXI interface (PCI)
1229 AddrRange(0x40000000, 0x80000000),
1230 ]
1231
1232 gic = Gicv3(dist_addr=0x2f000000, redist_addr=0x2f100000,
1233 maint_int=ArmPPI(num=25), gicv4=False,
1234 its=NULL)
1235
1236 pci_host = GenericArmPciHost(
1237 conf_base=0x40000000, conf_size='256MB', conf_device_bits=12,
1238 pci_pio_base=0x50000000,
1239 pci_mem_base=0x400000000,
1240 int_policy="ARM_PCI_INT_DEV", int_base=100, int_count=4)
1241
1242 def _on_chip_devices(self):
1243 return super(VExpress_GEM5_Foundation, self)._on_chip_devices() + [
1244 self.gic
1245 ]
1246
1247 def setupBootLoader(self, cur_sys, loc, boot_loader=None):
1248 if boot_loader is None:
1249 boot_loader = [ loc('boot_v2.arm64') ]
1250 super(VExpress_GEM5_Foundation, self).setupBootLoader(
1251 cur_sys, boot_loader)