RealView.py revision 13167:258a04d4c20b
1# Copyright (c) 2009-2018 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# Authors: Ali Saidi
40#          Gabe Black
41#          William Wang
42#          Glenn Bergmans
43
44from m5.defines import buildEnv
45from m5.params import *
46from m5.proxy import *
47from m5.util.fdthelper import *
48from ClockDomain import ClockDomain
49from VoltageDomain import VoltageDomain
50from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr, DmaDevice
51from PciHost import *
52from Ethernet import NSGigE, IGbE_igb, IGbE_e1000
53from Ide import *
54from Platform import Platform
55from Terminal import Terminal
56from Uart import Uart
57from SimpleMemory import SimpleMemory
58from Gic import *
59from EnergyCtrl import EnergyCtrl
60from ClockedObject import ClockedObject
61from ClockDomain import SrcClockDomain
62from SubSystem import SubSystem
63from Graphics import ImageFormat
64from ClockedObject import ClockedObject
65from PS2 import *
66from VirtIOMMIO import MmioVirtIO
67
68# Platforms with KVM support should generally use in-kernel GIC
69# emulation. Use a GIC model that automatically switches between
70# gem5's GIC model and KVM's GIC model if KVM is available.
71try:
72    from KvmGic import MuxingKvmGic
73    kvm_gicv2_class = MuxingKvmGic
74except ImportError:
75    # KVM support wasn't compiled into gem5. Fallback to a
76    # software-only GIC.
77    kvm_gicv2_class = GicV2
78    pass
79
80class AmbaPioDevice(BasicPioDevice):
81    type = 'AmbaPioDevice'
82    abstract = True
83    cxx_header = "dev/arm/amba_device.hh"
84    amba_id = Param.UInt32("ID of AMBA device for kernel detection")
85
86class AmbaIntDevice(AmbaPioDevice):
87    type = 'AmbaIntDevice'
88    abstract = True
89    cxx_header = "dev/arm/amba_device.hh"
90    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
91    int_num = Param.UInt32("Interrupt number that connects to GIC")
92    int_delay = Param.Latency("100ns",
93            "Time between action and interrupt generation by device")
94
95class AmbaDmaDevice(DmaDevice):
96    type = 'AmbaDmaDevice'
97    abstract = True
98    cxx_header = "dev/arm/amba_device.hh"
99    pio_addr = Param.Addr("Address for AMBA slave interface")
100    pio_latency = Param.Latency("10ns", "Time between action and write/read result by AMBA DMA Device")
101    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
102    int_num = Param.UInt32("Interrupt number that connects to GIC")
103    amba_id = Param.UInt32("ID of AMBA device for kernel detection")
104
105class A9SCU(BasicPioDevice):
106    type = 'A9SCU'
107    cxx_header = "dev/arm/a9scu.hh"
108
109class ArmPciIntRouting(Enum): vals = [
110    'ARM_PCI_INT_STATIC',
111    'ARM_PCI_INT_DEV',
112    'ARM_PCI_INT_PIN',
113    ]
114
115class GenericArmPciHost(GenericPciHost):
116    type = 'GenericArmPciHost'
117    cxx_header = "dev/arm/pci_host.hh"
118
119    int_policy = Param.ArmPciIntRouting("PCI interrupt routing policy")
120    int_base = Param.Unsigned("PCI interrupt base")
121    int_count = Param.Unsigned("Maximum number of interrupts used by this host")
122
123    def generateDeviceTree(self, state):
124        local_state = FdtState(addr_cells=3, size_cells=2, cpu_cells=1)
125        intterrupt_cells = 1
126
127        node = FdtNode("pci")
128
129        if int(self.conf_device_bits) == 8:
130            node.appendCompatible("pci-host-cam-generic")
131        elif int(self.conf_device_bits) == 12:
132            node.appendCompatible("pci-host-ecam-generic")
133        else:
134            m5.fatal("No compatibility string for the set conf_device_width")
135
136        node.append(FdtPropertyStrings("device_type", ["pci"]))
137
138        # Cell sizes of child nodes/peripherals
139        node.append(local_state.addrCellsProperty())
140        node.append(local_state.sizeCellsProperty())
141        node.append(FdtPropertyWords("#interrupt-cells", intterrupt_cells))
142        # PCI address for CPU
143        node.append(FdtPropertyWords("reg",
144            state.addrCells(self.conf_base) +
145            state.sizeCells(self.conf_size) ))
146
147        # Ranges mapping
148        # For now some of this is hard coded, because the PCI module does not
149        # have a proper full understanding of the memory map, but adapting the
150        # PCI module is beyond the scope of what I'm trying to do here.
151        # Values are taken from the VExpress_GEM5_V1 platform.
152        ranges = []
153        # Pio address range
154        ranges += self.pciFdtAddr(space=1, addr=0)
155        ranges += state.addrCells(self.pci_pio_base)
156        ranges += local_state.sizeCells(0x10000)  # Fixed size
157
158        # AXI memory address range
159        ranges += self.pciFdtAddr(space=2, addr=0)
160        ranges += state.addrCells(0x40000000) # Fixed offset
161        ranges += local_state.sizeCells(0x40000000) # Fixed size
162        node.append(FdtPropertyWords("ranges", ranges))
163
164        if str(self.int_policy) == 'ARM_PCI_INT_DEV':
165            int_phandle = state.phandle(self._parent.unproxy(self).gic)
166            # Interrupt mapping
167            interrupts = []
168            for i in range(int(self.int_count)):
169                interrupts += self.pciFdtAddr(device=i, addr=0) + \
170                    [0x0, int_phandle, 0, int(self.int_base) - 32 + i, 1]
171
172            node.append(FdtPropertyWords("interrupt-map", interrupts))
173
174            int_count = int(self.int_count)
175            if int_count & (int_count - 1):
176                fatal("PCI interrupt count should be power of 2")
177
178            intmask = self.pciFdtAddr(device=int_count - 1, addr=0) + [0x0]
179            node.append(FdtPropertyWords("interrupt-map-mask", intmask))
180        else:
181            m5.fatal("Unsupported PCI interrupt policy " +
182                     "for Device Tree generation")
183
184        node.append(FdtProperty("dma-coherent"))
185
186        yield node
187
188class RealViewCtrl(BasicPioDevice):
189    type = 'RealViewCtrl'
190    cxx_header = "dev/arm/rv_ctrl.hh"
191    proc_id0 = Param.UInt32(0x0C000000, "Processor ID, SYS_PROCID")
192    proc_id1 = Param.UInt32(0x0C000222, "Processor ID, SYS_PROCID1")
193    idreg = Param.UInt32(0x00000000, "ID Register, SYS_ID")
194
195    def generateDeviceTree(self, state):
196        node = FdtNode("sysreg@%x" % long(self.pio_addr))
197        node.appendCompatible("arm,vexpress-sysreg")
198        node.append(FdtPropertyWords("reg",
199            state.addrCells(self.pio_addr) +
200            state.sizeCells(0x1000) ))
201        node.append(FdtProperty("gpio-controller"))
202        node.append(FdtPropertyWords("#gpio-cells", [2]))
203        node.appendPhandle(self)
204
205        yield node
206
207class RealViewOsc(ClockDomain):
208    type = 'RealViewOsc'
209    cxx_header = "dev/arm/rv_ctrl.hh"
210
211    parent = Param.RealViewCtrl(Parent.any, "RealView controller")
212
213    # TODO: We currently don't have the notion of a clock source,
214    # which means we have to associate oscillators with a voltage
215    # source.
216    voltage_domain = Param.VoltageDomain(Parent.voltage_domain,
217                                         "Voltage domain")
218
219    # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
220    # the individual core/logic tile reference manuals for details
221    # about the site/position/dcc/device allocation.
222    site = Param.UInt8("Board Site")
223    position = Param.UInt8("Position in device stack")
224    dcc = Param.UInt8("Daughterboard Configuration Controller")
225    device = Param.UInt8("Device ID")
226
227    freq = Param.Clock("Default frequency")
228
229    def generateDeviceTree(self, state):
230        phandle = state.phandle(self)
231        node = FdtNode("osc@" + format(long(phandle), 'x'))
232        node.appendCompatible("arm,vexpress-osc")
233        node.append(FdtPropertyWords("arm,vexpress-sysreg,func",
234                                     [0x1, int(self.device)]))
235        node.append(FdtPropertyWords("#clock-cells", [0]))
236        freq = int(1.0/self.freq.value) # Values are stored as a clock period
237        node.append(FdtPropertyWords("freq-range", [freq, freq]))
238        node.append(FdtPropertyStrings("clock-output-names",
239                                       ["oscclk" + str(phandle)]))
240        node.appendPhandle(self)
241        yield node
242
243class RealViewTemperatureSensor(SimObject):
244    type = 'RealViewTemperatureSensor'
245    cxx_header = "dev/arm/rv_ctrl.hh"
246
247    parent = Param.RealViewCtrl(Parent.any, "RealView controller")
248
249    system = Param.System(Parent.any, "system")
250
251    # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
252    # the individual core/logic tile reference manuals for details
253    # about the site/position/dcc/device allocation.
254    site = Param.UInt8("Board Site")
255    position = Param.UInt8("Position in device stack")
256    dcc = Param.UInt8("Daughterboard Configuration Controller")
257    device = Param.UInt8("Device ID")
258
259class VExpressMCC(SubSystem):
260    """ARM V2M-P1 Motherboard Configuration Controller
261
262This subsystem describes a subset of the devices that sit behind the
263motherboard configuration controller on the the ARM Motherboard
264Express (V2M-P1) motherboard. See ARM DUI 0447J for details.
265    """
266
267    class Osc(RealViewOsc):
268        site, position, dcc = (0, 0, 0)
269
270    class Temperature(RealViewTemperatureSensor):
271        site, position, dcc = (0, 0, 0)
272
273    osc_mcc = Osc(device=0, freq="50MHz")
274    osc_clcd = Osc(device=1, freq="23.75MHz")
275    osc_peripheral = Osc(device=2, freq="24MHz")
276    osc_system_bus = Osc(device=4, freq="24MHz")
277
278    # See Table 4.19 in ARM DUI 0447J (Motherboard Express uATX TRM).
279    temp_crtl = Temperature(device=0)
280
281    def generateDeviceTree(self, state):
282        node = FdtNode("mcc")
283        node.appendCompatible("arm,vexpress,config-bus")
284        node.append(FdtPropertyWords("arm,vexpress,site", [0]))
285
286        for obj in self._children.values():
287            if issubclass(type(obj), SimObject):
288                node.append(obj.generateDeviceTree(state))
289
290        io_phandle = state.phandle(self.osc_mcc.parent.unproxy(self))
291        node.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle))
292
293        yield node
294
295class CoreTile2A15DCC(SubSystem):
296    """ARM CoreTile Express A15x2 Daughterboard Configuration Controller
297
298This subsystem describes a subset of the devices that sit behind the
299daughterboard configuration controller on a CoreTile Express A15x2. See
300ARM DUI 0604E for details.
301    """
302
303    class Osc(RealViewOsc):
304        site, position, dcc = (1, 0, 0)
305
306    # See Table 2.8 in ARM DUI 0604E (CoreTile Express A15x2 TRM)
307    osc_cpu = Osc(device=0, freq="60MHz")
308    osc_hsbm = Osc(device=4, freq="40MHz")
309    osc_pxl = Osc(device=5, freq="23.75MHz")
310    osc_smb = Osc(device=6, freq="50MHz")
311    osc_sys = Osc(device=7, freq="60MHz")
312    osc_ddr = Osc(device=8, freq="40MHz")
313
314    def generateDeviceTree(self, state):
315        node = FdtNode("dcc")
316        node.appendCompatible("arm,vexpress,config-bus")
317
318        for obj in self._children.values():
319            if isinstance(obj, SimObject):
320                node.append(obj.generateDeviceTree(state))
321
322        io_phandle = state.phandle(self.osc_cpu.parent.unproxy(self))
323        node.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle))
324
325        yield node
326
327class VGic(PioDevice):
328    type = 'VGic'
329    cxx_header = "dev/arm/vgic.hh"
330    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
331    platform = Param.Platform(Parent.any, "Platform this device is part of.")
332    vcpu_addr = Param.Addr(0, "Address for vcpu interfaces")
333    hv_addr = Param.Addr(0, "Address for hv control")
334    pio_delay = Param.Latency('10ns', "Delay for PIO r/w")
335   # The number of list registers is not currently configurable at runtime.
336    ppint = Param.UInt32("HV maintenance interrupt number")
337
338    def generateDeviceTree(self, state):
339        gic = self.gic.unproxy(self)
340
341        node = FdtNode("interrupt-controller")
342        node.appendCompatible(["gem5,gic", "arm,cortex-a15-gic",
343                               "arm,cortex-a9-gic"])
344        node.append(FdtPropertyWords("#interrupt-cells", [3]))
345        node.append(FdtPropertyWords("#address-cells", [0]))
346        node.append(FdtProperty("interrupt-controller"))
347
348        regs = (
349            state.addrCells(gic.dist_addr) +
350            state.sizeCells(0x1000) +
351            state.addrCells(gic.cpu_addr) +
352            state.sizeCells(0x1000) +
353            state.addrCells(self.hv_addr) +
354            state.sizeCells(0x2000) +
355            state.addrCells(self.vcpu_addr) +
356            state.sizeCells(0x2000) )
357
358        node.append(FdtPropertyWords("reg", regs))
359        node.append(FdtPropertyWords("interrupts",
360                                     [1, int(self.ppint)-16, 0xf04]))
361
362        node.appendPhandle(gic)
363
364        yield node
365
366class AmbaFake(AmbaPioDevice):
367    type = 'AmbaFake'
368    cxx_header = "dev/arm/amba_fake.hh"
369    ignore_access = Param.Bool(False, "Ignore reads/writes to this device, (e.g. IsaFake + AMBA)")
370    amba_id = 0;
371
372class Pl011(Uart):
373    type = 'Pl011'
374    cxx_header = "dev/arm/pl011.hh"
375    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
376    int_num = Param.UInt32("Interrupt number that connects to GIC")
377    end_on_eot = Param.Bool(False, "End the simulation when a EOT is received on the UART")
378    int_delay = Param.Latency("100ns", "Time between action and interrupt generation by UART")
379
380    def generateDeviceTree(self, state):
381        node = self.generateBasicPioDeviceNode(state, 'uart', self.pio_addr,
382                                               0x1000, [int(self.int_num)])
383        node.appendCompatible(["arm,pl011", "arm,primecell"])
384
385        # Hardcoded reference to the realview platform clocks, because the
386        # clk_domain can only store one clock (i.e. it is not a VectorParam)
387        realview = self._parent.unproxy(self)
388        node.append(FdtPropertyWords("clocks",
389            [state.phandle(realview.mcc.osc_peripheral),
390            state.phandle(realview.dcc.osc_smb)]))
391        node.append(FdtPropertyStrings("clock-names", ["uartclk", "apb_pclk"]))
392        yield node
393
394class Sp804(AmbaPioDevice):
395    type = 'Sp804'
396    cxx_header = "dev/arm/timer_sp804.hh"
397    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
398    int_num0 = Param.UInt32("Interrupt number that connects to GIC")
399    clock0 = Param.Clock('1MHz', "Clock speed of the input")
400    int_num1 = Param.UInt32("Interrupt number that connects to GIC")
401    clock1 = Param.Clock('1MHz', "Clock speed of the input")
402    amba_id = 0x00141804
403
404class A9GlobalTimer(BasicPioDevice):
405    type = 'A9GlobalTimer'
406    cxx_header = "dev/arm/timer_a9global.hh"
407    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
408    int_num = Param.UInt32("Interrrupt number that connects to GIC")
409
410class CpuLocalTimer(BasicPioDevice):
411    type = 'CpuLocalTimer'
412    cxx_header = "dev/arm/timer_cpulocal.hh"
413    int_timer = Param.ArmPPI("Interrrupt used per-cpu to GIC")
414    int_watchdog = Param.ArmPPI("Interrupt for per-cpu watchdog to GIC")
415
416class GenericTimer(ClockedObject):
417    type = 'GenericTimer'
418    cxx_header = "dev/arm/generic_timer.hh"
419    system = Param.ArmSystem(Parent.any, "system")
420    int_phys_s = Param.ArmPPI("Physical (S) timer interrupt")
421    int_phys_ns = Param.ArmPPI("Physical (NS) timer interrupt")
422    int_virt = Param.ArmPPI("Virtual timer interrupt")
423    int_hyp = Param.ArmPPI("Hypervisor timer interrupt")
424
425    def generateDeviceTree(self, state):
426        node = FdtNode("timer")
427
428        node.appendCompatible(["arm,cortex-a15-timer",
429                               "arm,armv7-timer",
430                               "arm,armv8-timer"])
431        node.append(FdtPropertyWords("interrupts", [
432            1, int(self.int_phys_s.num) - 16, 0xf08,
433            1, int(self.int_phys_ns.num) - 16, 0xf08,
434            1, int(self.int_virt.num) - 16, 0xf08,
435            1, int(self.int_hyp.num) - 16, 0xf08,
436        ]))
437        clock = state.phandle(self.clk_domain.unproxy(self))
438        node.append(FdtPropertyWords("clocks", clock))
439
440        yield node
441
442class GenericTimerMem(PioDevice):
443    type = 'GenericTimerMem'
444    cxx_header = "dev/arm/generic_timer.hh"
445
446    base = Param.Addr(0, "Base address")
447
448    int_phys = Param.ArmSPI("Physical Interrupt")
449    int_virt = Param.ArmSPI("Virtual Interrupt")
450
451class PL031(AmbaIntDevice):
452    type = 'PL031'
453    cxx_header = "dev/arm/rtc_pl031.hh"
454    time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)")
455    amba_id = 0x00341031
456
457    def generateDeviceTree(self, state):
458        node = self.generateBasicPioDeviceNode(state, 'rtc', self.pio_addr,
459                                               0x1000, [int(self.int_num)])
460
461        node.appendCompatible(["arm,pl031", "arm,primecell"])
462        clock = state.phandle(self.clk_domain.unproxy(self))
463        node.append(FdtPropertyWords("clocks", clock))
464
465        yield node
466
467class Pl050(AmbaIntDevice):
468    type = 'Pl050'
469    cxx_header = "dev/arm/kmi.hh"
470    amba_id = 0x00141050
471
472    ps2 = Param.PS2Device("PS/2 device")
473
474    def generateDeviceTree(self, state):
475        node = self.generateBasicPioDeviceNode(state, 'kmi', self.pio_addr,
476                                               0x1000, [int(self.int_num)])
477
478        node.appendCompatible(["arm,pl050", "arm,primecell"])
479        clock = state.phandle(self.clk_domain.unproxy(self))
480        node.append(FdtPropertyWords("clocks", clock))
481
482        yield node
483
484class Pl111(AmbaDmaDevice):
485    type = 'Pl111'
486    cxx_header = "dev/arm/pl111.hh"
487    pixel_clock = Param.Clock('24MHz', "Pixel clock")
488    vnc   = Param.VncInput(Parent.any, "Vnc server for remote frame buffer display")
489    amba_id = 0x00141111
490    enable_capture = Param.Bool(True, "capture frame to system.framebuffer.bmp")
491
492class HDLcd(AmbaDmaDevice):
493    type = 'HDLcd'
494    cxx_header = "dev/arm/hdlcd.hh"
495    vnc = Param.VncInput(Parent.any, "Vnc server for remote frame buffer "
496                                     "display")
497    amba_id = 0x00141000
498    workaround_swap_rb = Param.Bool(False, "Workaround incorrect color "
499                                    "selector order in some kernels")
500    workaround_dma_line_count = Param.Bool(True, "Workaround incorrect "
501                                           "DMA line count (off by 1)")
502    enable_capture = Param.Bool(True, "capture frame to "
503                                      "system.framebuffer.{extension}")
504    frame_format = Param.ImageFormat("Auto",
505                                     "image format of the captured frame")
506
507    pixel_buffer_size = Param.MemorySize32("2kB", "Size of address range")
508
509    pxl_clk = Param.ClockDomain("Pixel clock source")
510    pixel_chunk = Param.Unsigned(32, "Number of pixels to handle in one batch")
511    virt_refresh_rate = Param.Frequency("20Hz", "Frame refresh rate "
512                                        "in KVM mode")
513
514    def generateDeviceTree(self, state):
515        # Interrupt number is hardcoded; it is not a property of this class
516        node = self.generateBasicPioDeviceNode(state, 'hdlcd',
517                                               self.pio_addr, 0x1000, [63])
518
519        node.appendCompatible(["arm,hdlcd"])
520        node.append(FdtPropertyWords("clocks", state.phandle(self.pxl_clk)))
521        node.append(FdtPropertyStrings("clock-names", ["pxlclk"]))
522
523        # This driver is disabled by default since the required DT nodes
524        # haven't been standardized yet. To use it,  override this status to
525        # "ok" and add the display configuration nodes required by the driver.
526        # See the driver for more information.
527        node.append(FdtPropertyStrings("status", ["disabled"]))
528
529        yield node
530
531class RealView(Platform):
532    type = 'RealView'
533    cxx_header = "dev/arm/realview.hh"
534    system = Param.System(Parent.any, "system")
535    _mem_regions = [(Addr(0), Addr('256MB'))]
536
537    def _on_chip_devices(self):
538        return []
539
540    def _off_chip_devices(self):
541        return []
542
543    _off_chip_ranges = []
544
545    def _attach_device(self, device, bus, dma_ports=None):
546        if hasattr(device, "pio"):
547            device.pio = bus.master
548        if hasattr(device, "dma"):
549            if dma_ports is None:
550                device.dma = bus.slave
551            else:
552                dma_ports.append(device.dma)
553
554    def _attach_io(self, devices, *args, **kwargs):
555        for d in devices:
556            self._attach_device(d, *args, **kwargs)
557
558    def _attach_clk(self, devices, clkdomain):
559        for d in devices:
560            if hasattr(d, "clk_domain"):
561                d.clk_domain = clkdomain
562
563    def attachPciDevices(self):
564        pass
565
566    def enableMSIX(self):
567        pass
568
569    def onChipIOClkDomain(self, clkdomain):
570        self._attach_clk(self._on_chip_devices(), clkdomain)
571
572    def offChipIOClkDomain(self, clkdomain):
573        self._attach_clk(self._off_chip_devices(), clkdomain)
574
575    def attachOnChipIO(self, bus, bridge=None, *args, **kwargs):
576        self._attach_io(self._on_chip_devices(), bus, *args, **kwargs)
577        if bridge:
578            bridge.ranges = self._off_chip_ranges
579
580    def attachIO(self, *args, **kwargs):
581        self._attach_io(self._off_chip_devices(), *args, **kwargs)
582
583    def setupBootLoader(self, mem_bus, cur_sys, loc):
584        cur_sys.bootmem = SimpleMemory(
585            range = AddrRange('2GB', size = '64MB'),
586            conf_table_reported = False)
587        if mem_bus is not None:
588            cur_sys.bootmem.port = mem_bus.master
589        cur_sys.boot_loader = loc('boot.arm')
590        cur_sys.atags_addr = 0x100
591        cur_sys.load_offset = 0
592
593    def generateDeviceTree(self, state):
594        node = FdtNode("/") # Things in this module need to end up in the root
595        node.append(FdtPropertyWords("interrupt-parent",
596                                     state.phandle(self.gic)))
597
598        for subnode in self.recurseDeviceTree(state):
599            node.append(subnode)
600
601        yield node
602
603    def annotateCpuDeviceNode(self, cpu, state):
604        cpu.append(FdtPropertyStrings("enable-method", "spin-table"))
605        cpu.append(FdtPropertyWords("cpu-release-addr", \
606                                    state.addrCells(0x8000fff8)))
607
608# Reference for memory map and interrupt number
609# RealView Platform Baseboard Explore for Cortex-A9 User Guide(ARM DUI 0440A)
610# Chapter 4: Programmer's Reference
611class RealViewPBX(RealView):
612    uart = Pl011(pio_addr=0x10009000, int_num=44)
613    realview_io = RealViewCtrl(pio_addr=0x10000000)
614    mcc = VExpressMCC()
615    dcc = CoreTile2A15DCC()
616    gic = GicV2(cpu_addr=0x1f000100, dist_addr=0x1f001000, cpu_size=0x100)
617    pci_host = GenericPciHost(
618        conf_base=0x30000000, conf_size='256MB', conf_device_bits=16,
619        pci_pio_base=0)
620    timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
621    timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
622    global_timer = A9GlobalTimer(int_num=27, pio_addr=0x1f000200)
623    local_cpu_timer = CpuLocalTimer(int_timer=ArmPPI(num=29),
624                                    int_watchdog=ArmPPI(num=30),
625                                    pio_addr=0x1f000600)
626    clcd = Pl111(pio_addr=0x10020000, int_num=55)
627    kmi0   = Pl050(pio_addr=0x10006000, int_num=52, ps2=PS2Keyboard())
628    kmi1   = Pl050(pio_addr=0x10007000, int_num=53, ps2=PS2TouchKit())
629    a9scu  = A9SCU(pio_addr=0x1f000000)
630    cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=7, pci_bus=2,
631                            io_shift = 1, ctrl_offset = 2, Command = 0x1,
632                            BAR0 = 0x18000000, BAR0Size = '16B',
633                            BAR1 = 0x18000100, BAR1Size = '1B',
634                            BAR0LegacyIO = True, BAR1LegacyIO = True)
635
636
637    l2x0_fake     = IsaFake(pio_addr=0x1f002000, pio_size=0xfff)
638    flash_fake    = IsaFake(pio_addr=0x40000000, pio_size=0x20000000,
639                            fake_mem=True)
640    dmac_fake     = AmbaFake(pio_addr=0x10030000)
641    uart1_fake    = AmbaFake(pio_addr=0x1000a000)
642    uart2_fake    = AmbaFake(pio_addr=0x1000b000)
643    uart3_fake    = AmbaFake(pio_addr=0x1000c000)
644    smc_fake      = AmbaFake(pio_addr=0x100e1000)
645    sp810_fake    = AmbaFake(pio_addr=0x10001000, ignore_access=True)
646    watchdog_fake = AmbaFake(pio_addr=0x10010000)
647    gpio0_fake    = AmbaFake(pio_addr=0x10013000)
648    gpio1_fake    = AmbaFake(pio_addr=0x10014000)
649    gpio2_fake    = AmbaFake(pio_addr=0x10015000)
650    ssp_fake      = AmbaFake(pio_addr=0x1000d000)
651    sci_fake      = AmbaFake(pio_addr=0x1000e000)
652    aaci_fake     = AmbaFake(pio_addr=0x10004000)
653    mmc_fake      = AmbaFake(pio_addr=0x10005000)
654    rtc           = PL031(pio_addr=0x10017000, int_num=42)
655    energy_ctrl   = EnergyCtrl(pio_addr=0x1000f000)
656
657
658    # Attach I/O devices that are on chip and also set the appropriate
659    # ranges for the bridge
660    def attachOnChipIO(self, bus, bridge):
661       self.gic.pio = bus.master
662       self.l2x0_fake.pio = bus.master
663       self.a9scu.pio = bus.master
664       self.global_timer.pio = bus.master
665       self.local_cpu_timer.pio = bus.master
666       # Bridge ranges based on excluding what is part of on-chip I/O
667       # (gic, l2x0, a9scu, local_cpu_timer)
668       bridge.ranges = [AddrRange(self.realview_io.pio_addr,
669                                  self.a9scu.pio_addr - 1),
670                        AddrRange(self.flash_fake.pio_addr,
671                                  self.flash_fake.pio_addr + \
672                                  self.flash_fake.pio_size - 1)]
673
674    # Set the clock domain for IO objects that are considered
675    # to be "close" to the cores.
676    def onChipIOClkDomain(self, clkdomain):
677        self.gic.clk_domain             = clkdomain
678        self.l2x0_fake.clk_domain       = clkdomain
679        self.a9scu.clkdomain            = clkdomain
680        self.local_cpu_timer.clk_domain = clkdomain
681
682    # Attach I/O devices to specified bus object.  Can't do this
683    # earlier, since the bus object itself is typically defined at the
684    # System level.
685    def attachIO(self, bus):
686       self.uart.pio          = bus.master
687       self.realview_io.pio   = bus.master
688       self.pci_host.pio      = bus.master
689       self.timer0.pio        = bus.master
690       self.timer1.pio        = bus.master
691       self.clcd.pio          = bus.master
692       self.clcd.dma          = bus.slave
693       self.kmi0.pio          = bus.master
694       self.kmi1.pio          = bus.master
695       self.cf_ctrl.pio       = bus.master
696       self.cf_ctrl.dma       = bus.slave
697       self.dmac_fake.pio     = bus.master
698       self.uart1_fake.pio    = bus.master
699       self.uart2_fake.pio    = bus.master
700       self.uart3_fake.pio    = bus.master
701       self.smc_fake.pio      = bus.master
702       self.sp810_fake.pio    = bus.master
703       self.watchdog_fake.pio = bus.master
704       self.gpio0_fake.pio    = bus.master
705       self.gpio1_fake.pio    = bus.master
706       self.gpio2_fake.pio    = bus.master
707       self.ssp_fake.pio      = bus.master
708       self.sci_fake.pio      = bus.master
709       self.aaci_fake.pio     = bus.master
710       self.mmc_fake.pio      = bus.master
711       self.rtc.pio           = bus.master
712       self.flash_fake.pio    = bus.master
713       self.energy_ctrl.pio   = bus.master
714
715    # Set the clock domain for IO objects that are considered
716    # to be "far" away from the cores.
717    def offChipIOClkDomain(self, clkdomain):
718        self.uart.clk_domain          = clkdomain
719        self.realview_io.clk_domain   = clkdomain
720        self.timer0.clk_domain        = clkdomain
721        self.timer1.clk_domain        = clkdomain
722        self.clcd.clk_domain          = clkdomain
723        self.kmi0.clk_domain          = clkdomain
724        self.kmi1.clk_domain          = clkdomain
725        self.cf_ctrl.clk_domain       = clkdomain
726        self.dmac_fake.clk_domain     = clkdomain
727        self.uart1_fake.clk_domain    = clkdomain
728        self.uart2_fake.clk_domain    = clkdomain
729        self.uart3_fake.clk_domain    = clkdomain
730        self.smc_fake.clk_domain      = clkdomain
731        self.sp810_fake.clk_domain    = clkdomain
732        self.watchdog_fake.clk_domain = clkdomain
733        self.gpio0_fake.clk_domain    = clkdomain
734        self.gpio1_fake.clk_domain    = clkdomain
735        self.gpio2_fake.clk_domain    = clkdomain
736        self.ssp_fake.clk_domain      = clkdomain
737        self.sci_fake.clk_domain      = clkdomain
738        self.aaci_fake.clk_domain     = clkdomain
739        self.mmc_fake.clk_domain      = clkdomain
740        self.rtc.clk_domain           = clkdomain
741        self.flash_fake.clk_domain    = clkdomain
742        self.energy_ctrl.clk_domain   = clkdomain
743
744class VExpress_EMM(RealView):
745    _mem_regions = [(Addr('2GB'), Addr('2GB'))]
746
747    # Ranges based on excluding what is part of on-chip I/O (gic,
748    # a9scu)
749    _off_chip_ranges = [AddrRange(0x2F000000, size='16MB'),
750                        AddrRange(0x30000000, size='256MB'),
751                        AddrRange(0x40000000, size='512MB'),
752                        AddrRange(0x18000000, size='64MB'),
753                        AddrRange(0x1C000000, size='64MB')]
754
755    # Platform control device (off-chip)
756    realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000,
757                               idreg=0x02250000, pio_addr=0x1C010000)
758
759    mcc = VExpressMCC()
760    dcc = CoreTile2A15DCC()
761
762    ### On-chip devices ###
763    gic = GicV2(dist_addr=0x2C001000, cpu_addr=0x2C002000)
764    vgic   = VGic(vcpu_addr=0x2c006000, hv_addr=0x2c004000, ppint=25)
765
766    local_cpu_timer = CpuLocalTimer(int_timer=ArmPPI(num=29),
767                                    int_watchdog=ArmPPI(num=30),
768                                    pio_addr=0x2C080000)
769
770    hdlcd  = HDLcd(pxl_clk=dcc.osc_pxl,
771                   pio_addr=0x2b000000, int_num=117,
772                   workaround_swap_rb=True)
773
774    def _on_chip_devices(self):
775        devices = [
776            self.gic, self.vgic,
777            self.local_cpu_timer
778        ]
779        if hasattr(self, "gicv2m"):
780            devices.append(self.gicv2m)
781        devices.append(self.hdlcd)
782        return devices
783
784    ### Off-chip devices ###
785    uart = Pl011(pio_addr=0x1c090000, int_num=37)
786    pci_host = GenericPciHost(
787        conf_base=0x30000000, conf_size='256MB', conf_device_bits=16,
788        pci_pio_base=0)
789
790    generic_timer = GenericTimer(int_phys_s=ArmPPI(num=29),
791                                 int_phys_ns=ArmPPI(num=30),
792                                 int_virt=ArmPPI(num=27),
793                                 int_hyp=ArmPPI(num=26))
794
795    timer0 = Sp804(int_num0=34, int_num1=34, pio_addr=0x1C110000, clock0='1MHz', clock1='1MHz')
796    timer1 = Sp804(int_num0=35, int_num1=35, pio_addr=0x1C120000, clock0='1MHz', clock1='1MHz')
797    clcd   = Pl111(pio_addr=0x1c1f0000, int_num=46)
798    kmi0   = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
799    kmi1   = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
800    cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=0, pci_bus=2,
801                            io_shift = 2, ctrl_offset = 2, Command = 0x1,
802                            BAR0 = 0x1C1A0000, BAR0Size = '256B',
803                            BAR1 = 0x1C1A0100, BAR1Size = '4096B',
804                            BAR0LegacyIO = True, BAR1LegacyIO = True)
805
806    vram           = SimpleMemory(range = AddrRange(0x18000000, size='32MB'),
807                                  conf_table_reported = False)
808    rtc            = PL031(pio_addr=0x1C170000, int_num=36)
809
810    l2x0_fake      = IsaFake(pio_addr=0x2C100000, pio_size=0xfff)
811    uart1_fake     = AmbaFake(pio_addr=0x1C0A0000)
812    uart2_fake     = AmbaFake(pio_addr=0x1C0B0000)
813    uart3_fake     = AmbaFake(pio_addr=0x1C0C0000)
814    sp810_fake     = AmbaFake(pio_addr=0x1C020000, ignore_access=True)
815    watchdog_fake  = AmbaFake(pio_addr=0x1C0F0000)
816    aaci_fake      = AmbaFake(pio_addr=0x1C040000)
817    lan_fake       = IsaFake(pio_addr=0x1A000000, pio_size=0xffff)
818    usb_fake       = IsaFake(pio_addr=0x1B000000, pio_size=0x1ffff)
819    mmc_fake       = AmbaFake(pio_addr=0x1c050000)
820    energy_ctrl    = EnergyCtrl(pio_addr=0x1c080000)
821
822    def _off_chip_devices(self):
823        devices = [
824            self.uart,
825            self.realview_io,
826            self.pci_host,
827            self.timer0,
828            self.timer1,
829            self.clcd,
830            self.kmi0,
831            self.kmi1,
832            self.cf_ctrl,
833            self.rtc,
834            self.vram,
835            self.l2x0_fake,
836            self.uart1_fake,
837            self.uart2_fake,
838            self.uart3_fake,
839            self.sp810_fake,
840            self.watchdog_fake,
841            self.aaci_fake,
842            self.lan_fake,
843            self.usb_fake,
844            self.mmc_fake,
845            self.energy_ctrl,
846        ]
847        # Try to attach the I/O if it exists
848        if hasattr(self, "ide"):
849            devices.append(self.ide)
850        if hasattr(self, "ethernet"):
851            devices.append(self.ethernet)
852        return devices
853
854    # Attach any PCI devices that are supported
855    def attachPciDevices(self):
856        self.ethernet = IGbE_e1000(pci_bus=0, pci_dev=0, pci_func=0,
857                                   InterruptLine=1, InterruptPin=1)
858        self.ide = IdeController(disks = [], pci_bus=0, pci_dev=1, pci_func=0,
859                                 InterruptLine=2, InterruptPin=2)
860
861    def enableMSIX(self):
862        self.gic = GicV2(dist_addr=0x2C001000, cpu_addr=0x2C002000, it_lines=512)
863        self.gicv2m = Gicv2m()
864        self.gicv2m.frames = [Gicv2mFrame(spi_base=256, spi_len=64, addr=0x2C1C0000)]
865
866    def setupBootLoader(self, mem_bus, cur_sys, loc):
867        cur_sys.bootmem = SimpleMemory(range = AddrRange('64MB'),
868                                       conf_table_reported = False)
869        if mem_bus is not None:
870            cur_sys.bootmem.port = mem_bus.master
871        if not cur_sys.boot_loader:
872            cur_sys.boot_loader = loc('boot_emm.arm')
873        cur_sys.atags_addr = 0x8000000
874        cur_sys.load_offset = 0x80000000
875
876class VExpress_EMM64(VExpress_EMM):
877    # Three memory regions are specified totalling 512GB
878    _mem_regions = [(Addr('2GB'), Addr('2GB')), (Addr('34GB'), Addr('30GB')),
879                    (Addr('512GB'), Addr('480GB'))]
880    pci_host = GenericPciHost(
881        conf_base=0x30000000, conf_size='256MB', conf_device_bits=12,
882        pci_pio_base=0x2f000000)
883
884    def setupBootLoader(self, mem_bus, cur_sys, loc):
885        cur_sys.bootmem = SimpleMemory(range=AddrRange(0, size='64MB'),
886                                       conf_table_reported=False)
887        if mem_bus is not None:
888            cur_sys.bootmem.port = mem_bus.master
889        if not cur_sys.boot_loader:
890            cur_sys.boot_loader = loc('boot_emm.arm64')
891        cur_sys.atags_addr = 0x8000000
892        cur_sys.load_offset = 0x80000000
893
894class VExpress_GEM5_V1_Base(RealView):
895    """
896The VExpress gem5 memory map is loosely based on a modified
897Versatile Express RS1 memory map.
898
899The gem5 platform has been designed to implement a subset of the
900original Versatile Express RS1 memory map. Off-chip peripherals should,
901when possible, adhere to the Versatile Express memory map. Non-PCI
902off-chip devices that are gem5-specific should live in the CS5 memory
903space to avoid conflicts with existing devices that we might want to
904model in the future. Such devices should normally have interrupts in
905the gem5-specific SPI range.
906
907On-chip peripherals are loosely modeled after the ARM CoreTile Express
908A15x2 A7x3 memory and interrupt map. In particular, the GIC and
909Generic Timer have the same interrupt lines and base addresses. Other
910on-chip devices are gem5 specific.
911
912Unlike the original Versatile Express RS2 extended platform, gem5 implements a
913large contigious DRAM space, without aliases or holes, starting at the
9142GiB boundary. This means that PCI memory is limited to 1GiB.
915
916Memory map:
917   0x00000000-0x03ffffff: Boot memory (CS0)
918   0x04000000-0x07ffffff: Reserved
919   0x08000000-0x0bffffff: Reserved (CS0 alias)
920   0x0c000000-0x0fffffff: Reserved (Off-chip, CS4)
921   0x10000000-0x13ffffff: gem5-specific peripherals (Off-chip, CS5)
922       0x10000000-0x1000ffff: gem5 energy controller
923       0x10010000-0x1001ffff: gem5 pseudo-ops
924
925   0x14000000-0x17ffffff: Reserved (Off-chip, PSRAM, CS1)
926   0x18000000-0x1bffffff: Reserved (Off-chip, Peripherals, CS2)
927   0x1c000000-0x1fffffff: Peripheral block 1 (Off-chip, CS3):
928       0x1c010000-0x1c01ffff: realview_io (VE system control regs.)
929       0x1c060000-0x1c06ffff: KMI0 (keyboard)
930       0x1c070000-0x1c07ffff: KMI1 (mouse)
931       0x1c090000-0x1c09ffff: UART0
932       0x1c0a0000-0x1c0affff: UART1 (reserved)
933       0x1c0b0000-0x1c0bffff: UART2 (reserved)
934       0x1c0c0000-0x1c0cffff: UART3 (reserved)
935       0x1c130000-0x1c13ffff: VirtIO (gem5/FM extension)
936       0x1c140000-0x1c14ffff: VirtIO (gem5/FM extension)
937       0x1c170000-0x1c17ffff: RTC
938
939   0x20000000-0x3fffffff: On-chip peripherals:
940       0x2b000000-0x2b00ffff: HDLCD
941
942       0x2c001000-0x2c001fff: GIC (distributor)
943       0x2c002000-0x2c003fff: GIC (CPU interface)
944       0x2c004000-0x2c005fff: vGIC (HV)
945       0x2c006000-0x2c007fff: vGIC (VCPU)
946       0x2c1c0000-0x2c1cffff: GICv2m MSI frame 0
947
948       0x2d000000-0x2d00ffff: GPU (reserved)
949
950       0x2f000000-0x2fffffff: PCI IO space
951       0x30000000-0x3fffffff: PCI config space
952
953   0x40000000-0x7fffffff: Ext. AXI: Used as PCI memory
954
955   0x80000000-X: DRAM
956
957Interrupts:
958      0- 15: Software generated interrupts (SGIs)
959     16- 31: On-chip private peripherals (PPIs)
960        25   : vgic
961        26   : generic_timer (hyp)
962        27   : generic_timer (virt)
963        28   : Reserved (Legacy FIQ)
964        29   : generic_timer (phys, sec)
965        30   : generic_timer (phys, non-sec)
966        31   : Reserved (Legacy IRQ)
967    32- 95: Mother board peripherals (SPIs)
968        32   : Reserved (SP805)
969        33   : Reserved (IOFPGA SW int)
970        34-35: Reserved (SP804)
971        36   : RTC
972        37-40: uart0-uart3
973        41-42: Reserved (PL180)
974        43   : Reserved (AACI)
975        44-45: kmi0-kmi1
976        46   : Reserved (CLCD)
977        47   : Reserved (Ethernet)
978        48   : Reserved (USB)
979    95-255: On-chip interrupt sources (we use these for
980            gem5-specific devices, SPIs)
981         74    : VirtIO (gem5/FM extension)
982         75    : VirtIO (gem5/FM extension)
983         95    : HDLCD
984         96- 98: GPU (reserved)
985        100-103: PCI
986   256-319: MSI frame 0 (gem5-specific, SPIs)
987   320-511: Unused
988
989    """
990
991    # Everything above 2GiB is memory
992    _mem_regions = [(Addr('2GB'), Addr('510GB'))]
993
994    _off_chip_ranges = [
995        # CS1-CS5
996        AddrRange(0x0c000000, 0x1fffffff),
997        # External AXI interface (PCI)
998        AddrRange(0x2f000000, 0x7fffffff),
999    ]
1000
1001    # Platform control device (off-chip)
1002    realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000,
1003                               idreg=0x02250000, pio_addr=0x1c010000)
1004    mcc = VExpressMCC()
1005    dcc = CoreTile2A15DCC()
1006
1007    ### On-chip devices ###
1008    gic = kvm_gicv2_class(dist_addr=0x2c001000, cpu_addr=0x2c002000,
1009                          it_lines=512)
1010    vgic = VGic(vcpu_addr=0x2c006000, hv_addr=0x2c004000, ppint=25)
1011    gicv2m = Gicv2m()
1012    gicv2m.frames = [
1013        Gicv2mFrame(spi_base=256, spi_len=64, addr=0x2c1c0000),
1014    ]
1015
1016    generic_timer = GenericTimer(int_phys_s=ArmPPI(num=29),
1017                                 int_phys_ns=ArmPPI(num=30),
1018                                 int_virt=ArmPPI(num=27),
1019                                 int_hyp=ArmPPI(num=26))
1020
1021    def _on_chip_devices(self):
1022        return [
1023            self.gic, self.vgic, self.gicv2m,
1024            self.generic_timer,
1025        ]
1026
1027    ### Off-chip devices ###
1028    clock24MHz = SrcClockDomain(clock="24MHz",
1029        voltage_domain=VoltageDomain(voltage="3.3V"))
1030
1031    uart = [
1032        Pl011(pio_addr=0x1c090000, int_num=37),
1033    ]
1034
1035    kmi0 = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
1036    kmi1 = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
1037
1038    rtc = PL031(pio_addr=0x1c170000, int_num=36)
1039
1040    ### gem5-specific off-chip devices ###
1041    pci_host = GenericArmPciHost(
1042        conf_base=0x30000000, conf_size='256MB', conf_device_bits=12,
1043        pci_pio_base=0x2f000000,
1044        int_policy="ARM_PCI_INT_DEV", int_base=100, int_count=4)
1045
1046    energy_ctrl = EnergyCtrl(pio_addr=0x10000000)
1047
1048    vio = [
1049        MmioVirtIO(pio_addr=0x1c130000, pio_size=0x1000,
1050                   interrupt=ArmSPI(num=74)),
1051        MmioVirtIO(pio_addr=0x1c140000, pio_size=0x1000,
1052                   interrupt=ArmSPI(num=75)),
1053    ]
1054
1055    def _off_chip_devices(self):
1056        return [
1057            self.realview_io,
1058            self.uart[0],
1059            self.kmi0,
1060            self.kmi1,
1061            self.rtc,
1062            self.pci_host,
1063            self.energy_ctrl,
1064            self.clock24MHz,
1065            self.vio[0],
1066            self.vio[1],
1067        ]
1068
1069    def attachPciDevice(self, device, *args, **kwargs):
1070        device.host = self.pci_host
1071        self._attach_device(device, *args, **kwargs)
1072
1073    def setupBootLoader(self, mem_bus, cur_sys, loc):
1074        cur_sys.bootmem = SimpleMemory(range=AddrRange(0, size='64MB'),
1075                                       conf_table_reported=False)
1076        if mem_bus is not None:
1077            cur_sys.bootmem.port = mem_bus.master
1078        if not cur_sys.boot_loader:
1079            cur_sys.boot_loader = [ loc('boot_emm.arm64'), loc('boot_emm.arm') ]
1080        cur_sys.atags_addr = 0x8000000
1081        cur_sys.load_offset = 0x80000000
1082
1083        #  Setup m5ops. It's technically not a part of the boot
1084        #  loader, but this is the only place we can configure the
1085        #  system.
1086        cur_sys.m5ops_base = 0x10010000
1087
1088    def generateDeviceTree(self, state):
1089        # Generate using standard RealView function
1090        dt = list(super(VExpress_GEM5_V1_Base, self).generateDeviceTree(state))
1091        if len(dt) > 1:
1092            raise Exception("System returned too many DT nodes")
1093        node = dt[0]
1094
1095        node.appendCompatible(["arm,vexpress"])
1096        node.append(FdtPropertyStrings("model", ["V2P-CA15"]))
1097        node.append(FdtPropertyWords("arm,hbi", [0x0]))
1098        node.append(FdtPropertyWords("arm,vexpress,site", [0xf]))
1099
1100        yield node
1101
1102
1103class VExpress_GEM5_V1(VExpress_GEM5_V1_Base):
1104    hdlcd  = HDLcd(pxl_clk=VExpress_GEM5_V1_Base.dcc.osc_pxl,
1105                   pio_addr=0x2b000000, int_num=95)
1106
1107    def _on_chip_devices(self):
1108        return super(VExpress_GEM5_V1,self)._on_chip_devices() + [
1109                self.hdlcd,
1110            ]
1111