RealView.py revision 13504:5a01198080fa
17584SAli.Saidi@arm.com# Copyright (c) 2009-2018 ARM Limited
27584SAli.Saidi@arm.com# All rights reserved.
37584SAli.Saidi@arm.com#
47584SAli.Saidi@arm.com# The license below extends only to copyright in the software and shall
57584SAli.Saidi@arm.com# not be construed as granting a license to any other intellectual
67584SAli.Saidi@arm.com# property including but not limited to intellectual property relating
77584SAli.Saidi@arm.com# to a hardware implementation of the functionality of the software
87584SAli.Saidi@arm.com# licensed hereunder.  You may use the software subject to the license
97584SAli.Saidi@arm.com# terms below provided that you ensure that this notice is replicated
107584SAli.Saidi@arm.com# unmodified and in its entirety in all distributions of the software,
117584SAli.Saidi@arm.com# modified or unmodified, in source code or in binary form.
127584SAli.Saidi@arm.com#
137584SAli.Saidi@arm.com# Copyright (c) 2006-2007 The Regents of The University of Michigan
147584SAli.Saidi@arm.com# All rights reserved.
157584SAli.Saidi@arm.com#
167584SAli.Saidi@arm.com# Redistribution and use in source and binary forms, with or without
177584SAli.Saidi@arm.com# modification, are permitted provided that the following conditions are
187584SAli.Saidi@arm.com# met: redistributions of source code must retain the above copyright
197584SAli.Saidi@arm.com# notice, this list of conditions and the following disclaimer;
207584SAli.Saidi@arm.com# redistributions in binary form must reproduce the above copyright
217584SAli.Saidi@arm.com# notice, this list of conditions and the following disclaimer in the
227584SAli.Saidi@arm.com# documentation and/or other materials provided with the distribution;
237584SAli.Saidi@arm.com# neither the name of the copyright holders nor the names of its
247584SAli.Saidi@arm.com# contributors may be used to endorse or promote products derived from
257584SAli.Saidi@arm.com# this software without specific prior written permission.
267584SAli.Saidi@arm.com#
277584SAli.Saidi@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
287584SAli.Saidi@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
297584SAli.Saidi@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
307584SAli.Saidi@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
317584SAli.Saidi@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
327584SAli.Saidi@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
337584SAli.Saidi@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
347584SAli.Saidi@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
357584SAli.Saidi@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
367584SAli.Saidi@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
377584SAli.Saidi@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
387584SAli.Saidi@arm.com#
397584SAli.Saidi@arm.com# Authors: Ali Saidi
407584SAli.Saidi@arm.com#          Gabe Black
417584SAli.Saidi@arm.com#          William Wang
428245Snate@binkert.org#          Glenn Bergmans
438245Snate@binkert.org
449525SAndreas.Sandberg@ARM.comfrom m5.defines import buildEnv
457584SAli.Saidi@arm.comfrom m5.params import *
467584SAli.Saidi@arm.comfrom m5.proxy import *
477584SAli.Saidi@arm.comfrom m5.util.fdthelper import *
487584SAli.Saidi@arm.comfrom ClockDomain import ClockDomain
497584SAli.Saidi@arm.comfrom VoltageDomain import VoltageDomain
509808Sstever@gmail.comfrom Device import BasicPioDevice, PioDevice, IsaFake, BadAddr, DmaDevice
519808Sstever@gmail.comfrom PciHost import *
527584SAli.Saidi@arm.comfrom Ethernet import NSGigE, IGbE_igb, IGbE_e1000
537584SAli.Saidi@arm.comfrom Ide import *
547584SAli.Saidi@arm.comfrom Platform import Platform
557584SAli.Saidi@arm.comfrom Terminal import Terminal
567584SAli.Saidi@arm.comfrom Uart import Uart
577584SAli.Saidi@arm.comfrom SimpleMemory import SimpleMemory
587584SAli.Saidi@arm.comfrom Gic import *
597584SAli.Saidi@arm.comfrom EnergyCtrl import EnergyCtrl
607584SAli.Saidi@arm.comfrom ClockedObject import ClockedObject
617584SAli.Saidi@arm.comfrom ClockDomain import SrcClockDomain
627584SAli.Saidi@arm.comfrom SubSystem import SubSystem
637584SAli.Saidi@arm.comfrom Graphics import ImageFormat
647584SAli.Saidi@arm.comfrom ClockedObject import ClockedObject
657584SAli.Saidi@arm.comfrom PS2 import *
667584SAli.Saidi@arm.comfrom VirtIOMMIO import MmioVirtIO
677584SAli.Saidi@arm.com
687584SAli.Saidi@arm.com# Platforms with KVM support should generally use in-kernel GIC
697584SAli.Saidi@arm.com# emulation. Use a GIC model that automatically switches between
707584SAli.Saidi@arm.com# gem5's GIC model and KVM's GIC model if KVM is available.
717584SAli.Saidi@arm.comtry:
727584SAli.Saidi@arm.com    from KvmGic import MuxingKvmGic
737584SAli.Saidi@arm.com    kvm_gicv2_class = MuxingKvmGic
747584SAli.Saidi@arm.comexcept ImportError:
757587SAli.Saidi@arm.com    # KVM support wasn't compiled into gem5. Fallback to a
767584SAli.Saidi@arm.com    # software-only GIC.
777584SAli.Saidi@arm.com    kvm_gicv2_class = GicV2
787584SAli.Saidi@arm.com    pass
797584SAli.Saidi@arm.com
807584SAli.Saidi@arm.comclass AmbaPioDevice(BasicPioDevice):
817584SAli.Saidi@arm.com    type = 'AmbaPioDevice'
827584SAli.Saidi@arm.com    abstract = True
837584SAli.Saidi@arm.com    cxx_header = "dev/arm/amba_device.hh"
847584SAli.Saidi@arm.com    amba_id = Param.UInt32("ID of AMBA device for kernel detection")
857584SAli.Saidi@arm.com
867584SAli.Saidi@arm.comclass AmbaIntDevice(AmbaPioDevice):
877584SAli.Saidi@arm.com    type = 'AmbaIntDevice'
887584SAli.Saidi@arm.com    abstract = True
897584SAli.Saidi@arm.com    cxx_header = "dev/arm/amba_device.hh"
907584SAli.Saidi@arm.com    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
917584SAli.Saidi@arm.com    int_num = Param.UInt32("Interrupt number that connects to GIC")
927584SAli.Saidi@arm.com    int_delay = Param.Latency("100ns",
937823Ssteve.reinhardt@amd.com            "Time between action and interrupt generation by device")
947584SAli.Saidi@arm.com
957584SAli.Saidi@arm.comclass AmbaDmaDevice(DmaDevice):
967584SAli.Saidi@arm.com    type = 'AmbaDmaDevice'
977584SAli.Saidi@arm.com    abstract = True
987584SAli.Saidi@arm.com    cxx_header = "dev/arm/amba_device.hh"
997584SAli.Saidi@arm.com    pio_addr = Param.Addr("Address for AMBA slave interface")
1007584SAli.Saidi@arm.com    pio_latency = Param.Latency("10ns", "Time between action and write/read result by AMBA DMA Device")
1017584SAli.Saidi@arm.com    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
1027584SAli.Saidi@arm.com    int_num = Param.UInt32("Interrupt number that connects to GIC")
1037584SAli.Saidi@arm.com    amba_id = Param.UInt32("ID of AMBA device for kernel detection")
1047584SAli.Saidi@arm.com
1057584SAli.Saidi@arm.comclass A9SCU(BasicPioDevice):
1067584SAli.Saidi@arm.com    type = 'A9SCU'
1077584SAli.Saidi@arm.com    cxx_header = "dev/arm/a9scu.hh"
1087584SAli.Saidi@arm.com
1097584SAli.Saidi@arm.comclass ArmPciIntRouting(Enum): vals = [
1107584SAli.Saidi@arm.com    'ARM_PCI_INT_STATIC',
1117584SAli.Saidi@arm.com    'ARM_PCI_INT_DEV',
1127584SAli.Saidi@arm.com    'ARM_PCI_INT_PIN',
1137584SAli.Saidi@arm.com    ]
1148524SAli.Saidi@ARM.com
1157584SAli.Saidi@arm.comclass GenericArmPciHost(GenericPciHost):
1167584SAli.Saidi@arm.com    type = 'GenericArmPciHost'
1177584SAli.Saidi@arm.com    cxx_header = "dev/arm/pci_host.hh"
1187584SAli.Saidi@arm.com
1197584SAli.Saidi@arm.com    int_policy = Param.ArmPciIntRouting("PCI interrupt routing policy")
1207584SAli.Saidi@arm.com    int_base = Param.Unsigned("PCI interrupt base")
1217584SAli.Saidi@arm.com    int_count = Param.Unsigned("Maximum number of interrupts used by this host")
1227584SAli.Saidi@arm.com
1237584SAli.Saidi@arm.com    def generateDeviceTree(self, state):
1247584SAli.Saidi@arm.com        local_state = FdtState(addr_cells=3, size_cells=2, cpu_cells=1)
1257584SAli.Saidi@arm.com        intterrupt_cells = 1
1267584SAli.Saidi@arm.com
1277584SAli.Saidi@arm.com        node = FdtNode("pci")
1287584SAli.Saidi@arm.com
1297587SAli.Saidi@arm.com        if int(self.conf_device_bits) == 8:
1307584SAli.Saidi@arm.com            node.appendCompatible("pci-host-cam-generic")
1317584SAli.Saidi@arm.com        elif int(self.conf_device_bits) == 12:
1327584SAli.Saidi@arm.com            node.appendCompatible("pci-host-ecam-generic")
1337584SAli.Saidi@arm.com        else:
1347584SAli.Saidi@arm.com            m5.fatal("No compatibility string for the set conf_device_width")
1357584SAli.Saidi@arm.com
1367584SAli.Saidi@arm.com        node.append(FdtPropertyStrings("device_type", ["pci"]))
1377584SAli.Saidi@arm.com
1388524SAli.Saidi@ARM.com        # Cell sizes of child nodes/peripherals
1397584SAli.Saidi@arm.com        node.append(local_state.addrCellsProperty())
1407584SAli.Saidi@arm.com        node.append(local_state.sizeCellsProperty())
1417584SAli.Saidi@arm.com        node.append(FdtPropertyWords("#interrupt-cells", intterrupt_cells))
1427584SAli.Saidi@arm.com        # PCI address for CPU
1437584SAli.Saidi@arm.com        node.append(FdtPropertyWords("reg",
1447584SAli.Saidi@arm.com            state.addrCells(self.conf_base) +
1457584SAli.Saidi@arm.com            state.sizeCells(self.conf_size) ))
1467584SAli.Saidi@arm.com
1477584SAli.Saidi@arm.com        # Ranges mapping
1487584SAli.Saidi@arm.com        # For now some of this is hard coded, because the PCI module does not
1497584SAli.Saidi@arm.com        # have a proper full understanding of the memory map, but adapting the
1507584SAli.Saidi@arm.com        # PCI module is beyond the scope of what I'm trying to do here.
1517584SAli.Saidi@arm.com        # Values are taken from the VExpress_GEM5_V1 platform.
1527584SAli.Saidi@arm.com        ranges = []
1537584SAli.Saidi@arm.com        # Pio address range
1547584SAli.Saidi@arm.com        ranges += self.pciFdtAddr(space=1, addr=0)
1557584SAli.Saidi@arm.com        ranges += state.addrCells(self.pci_pio_base)
1567584SAli.Saidi@arm.com        ranges += local_state.sizeCells(0x10000)  # Fixed size
1577584SAli.Saidi@arm.com
1587584SAli.Saidi@arm.com        # AXI memory address range
1597584SAli.Saidi@arm.com        ranges += self.pciFdtAddr(space=2, addr=0)
1607584SAli.Saidi@arm.com        ranges += state.addrCells(0x40000000) # Fixed offset
1617584SAli.Saidi@arm.com        ranges += local_state.sizeCells(0x40000000) # Fixed size
1627584SAli.Saidi@arm.com        node.append(FdtPropertyWords("ranges", ranges))
1637584SAli.Saidi@arm.com
1647584SAli.Saidi@arm.com        if str(self.int_policy) == 'ARM_PCI_INT_DEV':
1657584SAli.Saidi@arm.com            int_phandle = state.phandle(self._parent.unproxy(self).gic)
1667584SAli.Saidi@arm.com            # Interrupt mapping
1677584SAli.Saidi@arm.com            interrupts = []
1687584SAli.Saidi@arm.com            for i in range(int(self.int_count)):
1697584SAli.Saidi@arm.com                interrupts += self.pciFdtAddr(device=i, addr=0) + \
1707584SAli.Saidi@arm.com                    [0x0, int_phandle, 0, int(self.int_base) - 32 + i, 1]
1717584SAli.Saidi@arm.com
1727584SAli.Saidi@arm.com            node.append(FdtPropertyWords("interrupt-map", interrupts))
1737584SAli.Saidi@arm.com
1747584SAli.Saidi@arm.com            int_count = int(self.int_count)
1757584SAli.Saidi@arm.com            if int_count & (int_count - 1):
1767584SAli.Saidi@arm.com                fatal("PCI interrupt count should be power of 2")
1777584SAli.Saidi@arm.com
1787943SAli.Saidi@ARM.com            intmask = self.pciFdtAddr(device=int_count - 1, addr=0) + [0x0]
1797584SAli.Saidi@arm.com            node.append(FdtPropertyWords("interrupt-map-mask", intmask))
1807943SAli.Saidi@ARM.com        else:
1817943SAli.Saidi@ARM.com            m5.fatal("Unsupported PCI interrupt policy " +
1827584SAli.Saidi@arm.com                     "for Device Tree generation")
1837584SAli.Saidi@arm.com
1847584SAli.Saidi@arm.com        node.append(FdtProperty("dma-coherent"))
1857584SAli.Saidi@arm.com
1867584SAli.Saidi@arm.com        yield node
1877584SAli.Saidi@arm.com
1887823Ssteve.reinhardt@amd.comclass RealViewCtrl(BasicPioDevice):
1897823Ssteve.reinhardt@amd.com    type = 'RealViewCtrl'
1907584SAli.Saidi@arm.com    cxx_header = "dev/arm/rv_ctrl.hh"
1917584SAli.Saidi@arm.com    proc_id0 = Param.UInt32(0x0C000000, "Processor ID, SYS_PROCID")
1927584SAli.Saidi@arm.com    proc_id1 = Param.UInt32(0x0C000222, "Processor ID, SYS_PROCID1")
1937584SAli.Saidi@arm.com    idreg = Param.UInt32(0x00000000, "ID Register, SYS_ID")
1947584SAli.Saidi@arm.com
1957584SAli.Saidi@arm.com    def generateDeviceTree(self, state):
1967584SAli.Saidi@arm.com        node = FdtNode("sysreg@%x" % long(self.pio_addr))
1977584SAli.Saidi@arm.com        node.appendCompatible("arm,vexpress-sysreg")
1987584SAli.Saidi@arm.com        node.append(FdtPropertyWords("reg",
1997584SAli.Saidi@arm.com            state.addrCells(self.pio_addr) +
2007584SAli.Saidi@arm.com            state.sizeCells(0x1000) ))
2017584SAli.Saidi@arm.com        node.append(FdtProperty("gpio-controller"))
2027584SAli.Saidi@arm.com        node.append(FdtPropertyWords("#gpio-cells", [2]))
2037584SAli.Saidi@arm.com        node.appendPhandle(self)
2048993SAli.Saidi@ARM.com
2057584SAli.Saidi@arm.com        yield node
2067584SAli.Saidi@arm.com
2077584SAli.Saidi@arm.comclass RealViewOsc(ClockDomain):
2087584SAli.Saidi@arm.com    type = 'RealViewOsc'
2097584SAli.Saidi@arm.com    cxx_header = "dev/arm/rv_ctrl.hh"
2107584SAli.Saidi@arm.com
2117584SAli.Saidi@arm.com    parent = Param.RealViewCtrl(Parent.any, "RealView controller")
2127584SAli.Saidi@arm.com
2137584SAli.Saidi@arm.com    # TODO: We currently don't have the notion of a clock source,
2147584SAli.Saidi@arm.com    # which means we have to associate oscillators with a voltage
2157584SAli.Saidi@arm.com    # source.
2167584SAli.Saidi@arm.com    voltage_domain = Param.VoltageDomain(Parent.voltage_domain,
2177584SAli.Saidi@arm.com                                         "Voltage domain")
2187584SAli.Saidi@arm.com
2197733SAli.Saidi@ARM.com    # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
22010905Sandreas.sandberg@arm.com    # the individual core/logic tile reference manuals for details
2217733SAli.Saidi@ARM.com    # about the site/position/dcc/device allocation.
2227733SAli.Saidi@ARM.com    site = Param.UInt8("Board Site")
2237733SAli.Saidi@ARM.com    position = Param.UInt8("Position in device stack")
2247733SAli.Saidi@ARM.com    dcc = Param.UInt8("Daughterboard Configuration Controller")
2257733SAli.Saidi@ARM.com    device = Param.UInt8("Device ID")
2267733SAli.Saidi@ARM.com
2277733SAli.Saidi@ARM.com    freq = Param.Clock("Default frequency")
2287733SAli.Saidi@ARM.com
2297733SAli.Saidi@ARM.com    def generateDeviceTree(self, state):
2307733SAli.Saidi@ARM.com        phandle = state.phandle(self)
2317733SAli.Saidi@ARM.com        node = FdtNode("osc@" + format(long(phandle), 'x'))
2327733SAli.Saidi@ARM.com        node.appendCompatible("arm,vexpress-osc")
2337733SAli.Saidi@ARM.com        node.append(FdtPropertyWords("arm,vexpress-sysreg,func",
2347733SAli.Saidi@ARM.com                                     [0x1, int(self.device)]))
2357733SAli.Saidi@ARM.com        node.append(FdtPropertyWords("#clock-cells", [0]))
2367733SAli.Saidi@ARM.com        freq = int(1.0/self.freq.value) # Values are stored as a clock period
2377733SAli.Saidi@ARM.com        node.append(FdtPropertyWords("freq-range", [freq, freq]))
2387733SAli.Saidi@ARM.com        node.append(FdtPropertyStrings("clock-output-names",
2397733SAli.Saidi@ARM.com                                       ["oscclk" + str(phandle)]))
2407733SAli.Saidi@ARM.com        node.appendPhandle(self)
2417733SAli.Saidi@ARM.com        yield node
24210905Sandreas.sandberg@arm.com
2437733SAli.Saidi@ARM.comclass RealViewTemperatureSensor(SimObject):
2447733SAli.Saidi@ARM.com    type = 'RealViewTemperatureSensor'
2457733SAli.Saidi@ARM.com    cxx_header = "dev/arm/rv_ctrl.hh"
2467733SAli.Saidi@ARM.com
2477733SAli.Saidi@ARM.com    parent = Param.RealViewCtrl(Parent.any, "RealView controller")
2487733SAli.Saidi@ARM.com
2497733SAli.Saidi@ARM.com    system = Param.System(Parent.any, "system")
2507733SAli.Saidi@ARM.com
2517733SAli.Saidi@ARM.com    # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
2527733SAli.Saidi@ARM.com    # the individual core/logic tile reference manuals for details
2537733SAli.Saidi@ARM.com    # about the site/position/dcc/device allocation.
2547733SAli.Saidi@ARM.com    site = Param.UInt8("Board Site")
2557733SAli.Saidi@ARM.com    position = Param.UInt8("Position in device stack")
2567733SAli.Saidi@ARM.com    dcc = Param.UInt8("Daughterboard Configuration Controller")
2577733SAli.Saidi@ARM.com    device = Param.UInt8("Device ID")
2587733SAli.Saidi@ARM.com
2597733SAli.Saidi@ARM.comclass VExpressMCC(SubSystem):
2607733SAli.Saidi@ARM.com    """ARM V2M-P1 Motherboard Configuration Controller
2617733SAli.Saidi@ARM.com
2627733SAli.Saidi@ARM.comThis subsystem describes a subset of the devices that sit behind the
2637733SAli.Saidi@ARM.commotherboard configuration controller on the the ARM Motherboard
2647733SAli.Saidi@ARM.comExpress (V2M-P1) motherboard. See ARM DUI 0447J for details.
2657584SAli.Saidi@arm.com    """
2667584SAli.Saidi@arm.com
26710905Sandreas.sandberg@arm.com    class Osc(RealViewOsc):
2687584SAli.Saidi@arm.com        site, position, dcc = (0, 0, 0)
26910905Sandreas.sandberg@arm.com
27010905Sandreas.sandberg@arm.com    class Temperature(RealViewTemperatureSensor):
2717584SAli.Saidi@arm.com        site, position, dcc = (0, 0, 0)
2727584SAli.Saidi@arm.com
2737584SAli.Saidi@arm.com    osc_mcc = Osc(device=0, freq="50MHz")
27410905Sandreas.sandberg@arm.com    osc_clcd = Osc(device=1, freq="23.75MHz")
2757584SAli.Saidi@arm.com    osc_peripheral = Osc(device=2, freq="24MHz")
27610905Sandreas.sandberg@arm.com    osc_system_bus = Osc(device=4, freq="24MHz")
27710905Sandreas.sandberg@arm.com
2787584SAli.Saidi@arm.com    # See Table 4.19 in ARM DUI 0447J (Motherboard Express uATX TRM).
2797584SAli.Saidi@arm.com    temp_crtl = Temperature(device=0)
2807584SAli.Saidi@arm.com
2817584SAli.Saidi@arm.com    def generateDeviceTree(self, state):
2827584SAli.Saidi@arm.com        node = FdtNode("mcc")
2837584SAli.Saidi@arm.com        node.appendCompatible("arm,vexpress,config-bus")
2847584SAli.Saidi@arm.com        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 AmbaFake(AmbaPioDevice):
328    type = 'AmbaFake'
329    cxx_header = "dev/arm/amba_fake.hh"
330    ignore_access = Param.Bool(False, "Ignore reads/writes to this device, (e.g. IsaFake + AMBA)")
331    amba_id = 0;
332
333class Pl011(Uart):
334    type = 'Pl011'
335    cxx_header = "dev/arm/pl011.hh"
336    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
337    int_num = Param.UInt32("Interrupt number that connects to GIC")
338    end_on_eot = Param.Bool(False, "End the simulation when a EOT is received on the UART")
339    int_delay = Param.Latency("100ns", "Time between action and interrupt generation by UART")
340
341    def generateDeviceTree(self, state):
342        node = self.generateBasicPioDeviceNode(state, 'uart', self.pio_addr,
343                                               0x1000, [int(self.int_num)])
344        node.appendCompatible(["arm,pl011", "arm,primecell"])
345
346        # Hardcoded reference to the realview platform clocks, because the
347        # clk_domain can only store one clock (i.e. it is not a VectorParam)
348        realview = self._parent.unproxy(self)
349        node.append(FdtPropertyWords("clocks",
350            [state.phandle(realview.mcc.osc_peripheral),
351            state.phandle(realview.dcc.osc_smb)]))
352        node.append(FdtPropertyStrings("clock-names", ["uartclk", "apb_pclk"]))
353        yield node
354
355class Sp804(AmbaPioDevice):
356    type = 'Sp804'
357    cxx_header = "dev/arm/timer_sp804.hh"
358    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
359    int_num0 = Param.UInt32("Interrupt number that connects to GIC")
360    clock0 = Param.Clock('1MHz', "Clock speed of the input")
361    int_num1 = Param.UInt32("Interrupt number that connects to GIC")
362    clock1 = Param.Clock('1MHz', "Clock speed of the input")
363    amba_id = 0x00141804
364
365class A9GlobalTimer(BasicPioDevice):
366    type = 'A9GlobalTimer'
367    cxx_header = "dev/arm/timer_a9global.hh"
368    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
369    int_num = Param.UInt32("Interrrupt number that connects to GIC")
370
371class CpuLocalTimer(BasicPioDevice):
372    type = 'CpuLocalTimer'
373    cxx_header = "dev/arm/timer_cpulocal.hh"
374    int_timer = Param.ArmPPI("Interrrupt used per-cpu to GIC")
375    int_watchdog = Param.ArmPPI("Interrupt for per-cpu watchdog to GIC")
376
377class GenericTimer(ClockedObject):
378    type = 'GenericTimer'
379    cxx_header = "dev/arm/generic_timer.hh"
380    system = Param.ArmSystem(Parent.any, "system")
381    int_phys_s = Param.ArmPPI("Physical (S) timer interrupt")
382    int_phys_ns = Param.ArmPPI("Physical (NS) timer interrupt")
383    int_virt = Param.ArmPPI("Virtual timer interrupt")
384    int_hyp = Param.ArmPPI("Hypervisor timer interrupt")
385
386    def generateDeviceTree(self, state):
387        node = FdtNode("timer")
388
389        node.appendCompatible(["arm,cortex-a15-timer",
390                               "arm,armv7-timer",
391                               "arm,armv8-timer"])
392        node.append(FdtPropertyWords("interrupts", [
393            1, int(self.int_phys_s.num) - 16, 0xf08,
394            1, int(self.int_phys_ns.num) - 16, 0xf08,
395            1, int(self.int_virt.num) - 16, 0xf08,
396            1, int(self.int_hyp.num) - 16, 0xf08,
397        ]))
398        clock = state.phandle(self.clk_domain.unproxy(self))
399        node.append(FdtPropertyWords("clocks", clock))
400
401        yield node
402
403class GenericTimerMem(PioDevice):
404    type = 'GenericTimerMem'
405    cxx_header = "dev/arm/generic_timer.hh"
406
407    base = Param.Addr(0, "Base address")
408
409    int_phys = Param.ArmSPI("Physical Interrupt")
410    int_virt = Param.ArmSPI("Virtual Interrupt")
411
412class PL031(AmbaIntDevice):
413    type = 'PL031'
414    cxx_header = "dev/arm/rtc_pl031.hh"
415    time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)")
416    amba_id = 0x00341031
417
418    def generateDeviceTree(self, state):
419        node = self.generateBasicPioDeviceNode(state, 'rtc', self.pio_addr,
420                                               0x1000, [int(self.int_num)])
421
422        node.appendCompatible(["arm,pl031", "arm,primecell"])
423        clock = state.phandle(self.clk_domain.unproxy(self))
424        node.append(FdtPropertyWords("clocks", clock))
425
426        yield node
427
428class Pl050(AmbaIntDevice):
429    type = 'Pl050'
430    cxx_header = "dev/arm/kmi.hh"
431    amba_id = 0x00141050
432
433    ps2 = Param.PS2Device("PS/2 device")
434
435    def generateDeviceTree(self, state):
436        node = self.generateBasicPioDeviceNode(state, 'kmi', self.pio_addr,
437                                               0x1000, [int(self.int_num)])
438
439        node.appendCompatible(["arm,pl050", "arm,primecell"])
440        clock = state.phandle(self.clk_domain.unproxy(self))
441        node.append(FdtPropertyWords("clocks", clock))
442
443        yield node
444
445class Pl111(AmbaDmaDevice):
446    type = 'Pl111'
447    cxx_header = "dev/arm/pl111.hh"
448    pixel_clock = Param.Clock('24MHz', "Pixel clock")
449    vnc   = Param.VncInput(Parent.any, "Vnc server for remote frame buffer display")
450    amba_id = 0x00141111
451    enable_capture = Param.Bool(True, "capture frame to system.framebuffer.bmp")
452
453class HDLcd(AmbaDmaDevice):
454    type = 'HDLcd'
455    cxx_header = "dev/arm/hdlcd.hh"
456    vnc = Param.VncInput(Parent.any, "Vnc server for remote frame buffer "
457                                     "display")
458    amba_id = 0x00141000
459    workaround_swap_rb = Param.Bool(False, "Workaround incorrect color "
460                                    "selector order in some kernels")
461    workaround_dma_line_count = Param.Bool(True, "Workaround incorrect "
462                                           "DMA line count (off by 1)")
463    enable_capture = Param.Bool(True, "capture frame to "
464                                      "system.framebuffer.{extension}")
465    frame_format = Param.ImageFormat("Auto",
466                                     "image format of the captured frame")
467
468    pixel_buffer_size = Param.MemorySize32("2kB", "Size of address range")
469
470    pxl_clk = Param.ClockDomain("Pixel clock source")
471    pixel_chunk = Param.Unsigned(32, "Number of pixels to handle in one batch")
472    virt_refresh_rate = Param.Frequency("20Hz", "Frame refresh rate "
473                                        "in KVM mode")
474
475    def generateDeviceTree(self, state):
476        # Interrupt number is hardcoded; it is not a property of this class
477        node = self.generateBasicPioDeviceNode(state, 'hdlcd',
478                                               self.pio_addr, 0x1000, [63])
479
480        node.appendCompatible(["arm,hdlcd"])
481        node.append(FdtPropertyWords("clocks", state.phandle(self.pxl_clk)))
482        node.append(FdtPropertyStrings("clock-names", ["pxlclk"]))
483
484        # This driver is disabled by default since the required DT nodes
485        # haven't been standardized yet. To use it,  override this status to
486        # "ok" and add the display configuration nodes required by the driver.
487        # See the driver for more information.
488        node.append(FdtPropertyStrings("status", ["disabled"]))
489
490        yield node
491
492class RealView(Platform):
493    type = 'RealView'
494    cxx_header = "dev/arm/realview.hh"
495    system = Param.System(Parent.any, "system")
496    _mem_regions = [(Addr(0), Addr('256MB'))]
497
498    def _on_chip_devices(self):
499        return []
500
501    def _off_chip_devices(self):
502        return []
503
504    _off_chip_ranges = []
505
506    def _attach_device(self, device, bus, dma_ports=None):
507        if hasattr(device, "pio"):
508            device.pio = bus.master
509        if hasattr(device, "dma"):
510            if dma_ports is None:
511                device.dma = bus.slave
512            else:
513                dma_ports.append(device.dma)
514
515    def _attach_io(self, devices, *args, **kwargs):
516        for d in devices:
517            self._attach_device(d, *args, **kwargs)
518
519    def _attach_clk(self, devices, clkdomain):
520        for d in devices:
521            if hasattr(d, "clk_domain"):
522                d.clk_domain = clkdomain
523
524    def attachPciDevices(self):
525        pass
526
527    def enableMSIX(self):
528        pass
529
530    def onChipIOClkDomain(self, clkdomain):
531        self._attach_clk(self._on_chip_devices(), clkdomain)
532
533    def offChipIOClkDomain(self, clkdomain):
534        self._attach_clk(self._off_chip_devices(), clkdomain)
535
536    def attachOnChipIO(self, bus, bridge=None, *args, **kwargs):
537        self._attach_io(self._on_chip_devices(), bus, *args, **kwargs)
538        if bridge:
539            bridge.ranges = self._off_chip_ranges
540
541    def attachIO(self, *args, **kwargs):
542        self._attach_io(self._off_chip_devices(), *args, **kwargs)
543
544    def setupBootLoader(self, mem_bus, cur_sys, loc):
545        cur_sys.bootmem = SimpleMemory(
546            range = AddrRange('2GB', size = '64MB'),
547            conf_table_reported = False)
548        if mem_bus is not None:
549            cur_sys.bootmem.port = mem_bus.master
550        cur_sys.boot_loader = loc('boot.arm')
551        cur_sys.atags_addr = 0x100
552        cur_sys.load_offset = 0
553
554    def generateDeviceTree(self, state):
555        node = FdtNode("/") # Things in this module need to end up in the root
556        node.append(FdtPropertyWords("interrupt-parent",
557                                     state.phandle(self.gic)))
558
559        for subnode in self.recurseDeviceTree(state):
560            node.append(subnode)
561
562        yield node
563
564    def annotateCpuDeviceNode(self, cpu, state):
565        cpu.append(FdtPropertyStrings("enable-method", "spin-table"))
566        cpu.append(FdtPropertyWords("cpu-release-addr", \
567                                    state.addrCells(0x8000fff8)))
568
569# Reference for memory map and interrupt number
570# RealView Platform Baseboard Explore for Cortex-A9 User Guide(ARM DUI 0440A)
571# Chapter 4: Programmer's Reference
572class RealViewPBX(RealView):
573    uart = Pl011(pio_addr=0x10009000, int_num=44)
574    realview_io = RealViewCtrl(pio_addr=0x10000000)
575    mcc = VExpressMCC()
576    dcc = CoreTile2A15DCC()
577    gic = GicV2(cpu_addr=0x1f000100, dist_addr=0x1f001000, cpu_size=0x100)
578    pci_host = GenericPciHost(
579        conf_base=0x30000000, conf_size='256MB', conf_device_bits=16,
580        pci_pio_base=0)
581    timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
582    timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
583    global_timer = A9GlobalTimer(int_num=27, pio_addr=0x1f000200)
584    local_cpu_timer = CpuLocalTimer(int_timer=ArmPPI(num=29),
585                                    int_watchdog=ArmPPI(num=30),
586                                    pio_addr=0x1f000600)
587    clcd = Pl111(pio_addr=0x10020000, int_num=55)
588    kmi0   = Pl050(pio_addr=0x10006000, int_num=52, ps2=PS2Keyboard())
589    kmi1   = Pl050(pio_addr=0x10007000, int_num=53, ps2=PS2TouchKit())
590    a9scu  = A9SCU(pio_addr=0x1f000000)
591    cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=7, pci_bus=2,
592                            io_shift = 1, ctrl_offset = 2, Command = 0x1,
593                            BAR0 = 0x18000000, BAR0Size = '16B',
594                            BAR1 = 0x18000100, BAR1Size = '1B',
595                            BAR0LegacyIO = True, BAR1LegacyIO = True)
596
597
598    l2x0_fake     = IsaFake(pio_addr=0x1f002000, pio_size=0xfff)
599    flash_fake    = IsaFake(pio_addr=0x40000000, pio_size=0x20000000,
600                            fake_mem=True)
601    dmac_fake     = AmbaFake(pio_addr=0x10030000)
602    uart1_fake    = AmbaFake(pio_addr=0x1000a000)
603    uart2_fake    = AmbaFake(pio_addr=0x1000b000)
604    uart3_fake    = AmbaFake(pio_addr=0x1000c000)
605    smc_fake      = AmbaFake(pio_addr=0x100e1000)
606    sp810_fake    = AmbaFake(pio_addr=0x10001000, ignore_access=True)
607    watchdog_fake = AmbaFake(pio_addr=0x10010000)
608    gpio0_fake    = AmbaFake(pio_addr=0x10013000)
609    gpio1_fake    = AmbaFake(pio_addr=0x10014000)
610    gpio2_fake    = AmbaFake(pio_addr=0x10015000)
611    ssp_fake      = AmbaFake(pio_addr=0x1000d000)
612    sci_fake      = AmbaFake(pio_addr=0x1000e000)
613    aaci_fake     = AmbaFake(pio_addr=0x10004000)
614    mmc_fake      = AmbaFake(pio_addr=0x10005000)
615    rtc           = PL031(pio_addr=0x10017000, int_num=42)
616    energy_ctrl   = EnergyCtrl(pio_addr=0x1000f000)
617
618
619    # Attach I/O devices that are on chip and also set the appropriate
620    # ranges for the bridge
621    def attachOnChipIO(self, bus, bridge):
622       self.gic.pio = bus.master
623       self.l2x0_fake.pio = bus.master
624       self.a9scu.pio = bus.master
625       self.global_timer.pio = bus.master
626       self.local_cpu_timer.pio = bus.master
627       # Bridge ranges based on excluding what is part of on-chip I/O
628       # (gic, l2x0, a9scu, local_cpu_timer)
629       bridge.ranges = [AddrRange(self.realview_io.pio_addr,
630                                  self.a9scu.pio_addr - 1),
631                        AddrRange(self.flash_fake.pio_addr,
632                                  self.flash_fake.pio_addr + \
633                                  self.flash_fake.pio_size - 1)]
634
635    # Set the clock domain for IO objects that are considered
636    # to be "close" to the cores.
637    def onChipIOClkDomain(self, clkdomain):
638        self.gic.clk_domain             = clkdomain
639        self.l2x0_fake.clk_domain       = clkdomain
640        self.a9scu.clkdomain            = clkdomain
641        self.local_cpu_timer.clk_domain = clkdomain
642
643    # Attach I/O devices to specified bus object.  Can't do this
644    # earlier, since the bus object itself is typically defined at the
645    # System level.
646    def attachIO(self, bus):
647       self.uart.pio          = bus.master
648       self.realview_io.pio   = bus.master
649       self.pci_host.pio      = bus.master
650       self.timer0.pio        = bus.master
651       self.timer1.pio        = bus.master
652       self.clcd.pio          = bus.master
653       self.clcd.dma          = bus.slave
654       self.kmi0.pio          = bus.master
655       self.kmi1.pio          = bus.master
656       self.cf_ctrl.pio       = bus.master
657       self.cf_ctrl.dma       = bus.slave
658       self.dmac_fake.pio     = bus.master
659       self.uart1_fake.pio    = bus.master
660       self.uart2_fake.pio    = bus.master
661       self.uart3_fake.pio    = bus.master
662       self.smc_fake.pio      = bus.master
663       self.sp810_fake.pio    = bus.master
664       self.watchdog_fake.pio = bus.master
665       self.gpio0_fake.pio    = bus.master
666       self.gpio1_fake.pio    = bus.master
667       self.gpio2_fake.pio    = bus.master
668       self.ssp_fake.pio      = bus.master
669       self.sci_fake.pio      = bus.master
670       self.aaci_fake.pio     = bus.master
671       self.mmc_fake.pio      = bus.master
672       self.rtc.pio           = bus.master
673       self.flash_fake.pio    = bus.master
674       self.energy_ctrl.pio   = bus.master
675
676    # Set the clock domain for IO objects that are considered
677    # to be "far" away from the cores.
678    def offChipIOClkDomain(self, clkdomain):
679        self.uart.clk_domain          = clkdomain
680        self.realview_io.clk_domain   = clkdomain
681        self.timer0.clk_domain        = clkdomain
682        self.timer1.clk_domain        = clkdomain
683        self.clcd.clk_domain          = clkdomain
684        self.kmi0.clk_domain          = clkdomain
685        self.kmi1.clk_domain          = clkdomain
686        self.cf_ctrl.clk_domain       = clkdomain
687        self.dmac_fake.clk_domain     = clkdomain
688        self.uart1_fake.clk_domain    = clkdomain
689        self.uart2_fake.clk_domain    = clkdomain
690        self.uart3_fake.clk_domain    = clkdomain
691        self.smc_fake.clk_domain      = clkdomain
692        self.sp810_fake.clk_domain    = clkdomain
693        self.watchdog_fake.clk_domain = clkdomain
694        self.gpio0_fake.clk_domain    = clkdomain
695        self.gpio1_fake.clk_domain    = clkdomain
696        self.gpio2_fake.clk_domain    = clkdomain
697        self.ssp_fake.clk_domain      = clkdomain
698        self.sci_fake.clk_domain      = clkdomain
699        self.aaci_fake.clk_domain     = clkdomain
700        self.mmc_fake.clk_domain      = clkdomain
701        self.rtc.clk_domain           = clkdomain
702        self.flash_fake.clk_domain    = clkdomain
703        self.energy_ctrl.clk_domain   = clkdomain
704
705class VExpress_EMM(RealView):
706    _mem_regions = [(Addr('2GB'), Addr('2GB'))]
707
708    # Ranges based on excluding what is part of on-chip I/O (gic,
709    # a9scu)
710    _off_chip_ranges = [AddrRange(0x2F000000, size='16MB'),
711                        AddrRange(0x30000000, size='256MB'),
712                        AddrRange(0x40000000, size='512MB'),
713                        AddrRange(0x18000000, size='64MB'),
714                        AddrRange(0x1C000000, size='64MB')]
715
716    # Platform control device (off-chip)
717    realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000,
718                               idreg=0x02250000, pio_addr=0x1C010000)
719
720    mcc = VExpressMCC()
721    dcc = CoreTile2A15DCC()
722
723    ### On-chip devices ###
724    gic = GicV2(dist_addr=0x2C001000, cpu_addr=0x2C002000)
725    vgic   = VGic(vcpu_addr=0x2c006000, hv_addr=0x2c004000, ppint=25)
726
727    local_cpu_timer = CpuLocalTimer(int_timer=ArmPPI(num=29),
728                                    int_watchdog=ArmPPI(num=30),
729                                    pio_addr=0x2C080000)
730
731    hdlcd  = HDLcd(pxl_clk=dcc.osc_pxl,
732                   pio_addr=0x2b000000, int_num=117,
733                   workaround_swap_rb=True)
734
735    def _on_chip_devices(self):
736        devices = [
737            self.gic, self.vgic,
738            self.local_cpu_timer
739        ]
740        if hasattr(self, "gicv2m"):
741            devices.append(self.gicv2m)
742        devices.append(self.hdlcd)
743        return devices
744
745    ### Off-chip devices ###
746    uart = Pl011(pio_addr=0x1c090000, int_num=37)
747    pci_host = GenericPciHost(
748        conf_base=0x30000000, conf_size='256MB', conf_device_bits=16,
749        pci_pio_base=0)
750
751    generic_timer = GenericTimer(int_phys_s=ArmPPI(num=29),
752                                 int_phys_ns=ArmPPI(num=30),
753                                 int_virt=ArmPPI(num=27),
754                                 int_hyp=ArmPPI(num=26))
755
756    timer0 = Sp804(int_num0=34, int_num1=34, pio_addr=0x1C110000, clock0='1MHz', clock1='1MHz')
757    timer1 = Sp804(int_num0=35, int_num1=35, pio_addr=0x1C120000, clock0='1MHz', clock1='1MHz')
758    clcd   = Pl111(pio_addr=0x1c1f0000, int_num=46)
759    kmi0   = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
760    kmi1   = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
761    cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=0, pci_bus=2,
762                            io_shift = 2, ctrl_offset = 2, Command = 0x1,
763                            BAR0 = 0x1C1A0000, BAR0Size = '256B',
764                            BAR1 = 0x1C1A0100, BAR1Size = '4096B',
765                            BAR0LegacyIO = True, BAR1LegacyIO = True)
766
767    vram           = SimpleMemory(range = AddrRange(0x18000000, size='32MB'),
768                                  conf_table_reported = False)
769    rtc            = PL031(pio_addr=0x1C170000, int_num=36)
770
771    l2x0_fake      = IsaFake(pio_addr=0x2C100000, pio_size=0xfff)
772    uart1_fake     = AmbaFake(pio_addr=0x1C0A0000)
773    uart2_fake     = AmbaFake(pio_addr=0x1C0B0000)
774    uart3_fake     = AmbaFake(pio_addr=0x1C0C0000)
775    sp810_fake     = AmbaFake(pio_addr=0x1C020000, ignore_access=True)
776    watchdog_fake  = AmbaFake(pio_addr=0x1C0F0000)
777    aaci_fake      = AmbaFake(pio_addr=0x1C040000)
778    lan_fake       = IsaFake(pio_addr=0x1A000000, pio_size=0xffff)
779    usb_fake       = IsaFake(pio_addr=0x1B000000, pio_size=0x1ffff)
780    mmc_fake       = AmbaFake(pio_addr=0x1c050000)
781    energy_ctrl    = EnergyCtrl(pio_addr=0x1c080000)
782
783    def _off_chip_devices(self):
784        devices = [
785            self.uart,
786            self.realview_io,
787            self.pci_host,
788            self.timer0,
789            self.timer1,
790            self.clcd,
791            self.kmi0,
792            self.kmi1,
793            self.cf_ctrl,
794            self.rtc,
795            self.vram,
796            self.l2x0_fake,
797            self.uart1_fake,
798            self.uart2_fake,
799            self.uart3_fake,
800            self.sp810_fake,
801            self.watchdog_fake,
802            self.aaci_fake,
803            self.lan_fake,
804            self.usb_fake,
805            self.mmc_fake,
806            self.energy_ctrl,
807        ]
808        # Try to attach the I/O if it exists
809        if hasattr(self, "ide"):
810            devices.append(self.ide)
811        if hasattr(self, "ethernet"):
812            devices.append(self.ethernet)
813        return devices
814
815    # Attach any PCI devices that are supported
816    def attachPciDevices(self):
817        self.ethernet = IGbE_e1000(pci_bus=0, pci_dev=0, pci_func=0,
818                                   InterruptLine=1, InterruptPin=1)
819        self.ide = IdeController(disks = [], pci_bus=0, pci_dev=1, pci_func=0,
820                                 InterruptLine=2, InterruptPin=2)
821
822    def enableMSIX(self):
823        self.gic = GicV2(dist_addr=0x2C001000, cpu_addr=0x2C002000, it_lines=512)
824        self.gicv2m = Gicv2m()
825        self.gicv2m.frames = [Gicv2mFrame(spi_base=256, spi_len=64, addr=0x2C1C0000)]
826
827    def setupBootLoader(self, mem_bus, cur_sys, loc):
828        cur_sys.bootmem = SimpleMemory(range = AddrRange('64MB'),
829                                       conf_table_reported = False)
830        if mem_bus is not None:
831            cur_sys.bootmem.port = mem_bus.master
832        if not cur_sys.boot_loader:
833            cur_sys.boot_loader = loc('boot_emm.arm')
834        cur_sys.atags_addr = 0x8000000
835        cur_sys.load_offset = 0x80000000
836
837class VExpress_EMM64(VExpress_EMM):
838    # Three memory regions are specified totalling 512GB
839    _mem_regions = [(Addr('2GB'), Addr('2GB')), (Addr('34GB'), Addr('30GB')),
840                    (Addr('512GB'), Addr('480GB'))]
841    pci_host = GenericPciHost(
842        conf_base=0x30000000, conf_size='256MB', conf_device_bits=12,
843        pci_pio_base=0x2f000000)
844
845    def setupBootLoader(self, mem_bus, cur_sys, loc):
846        cur_sys.bootmem = SimpleMemory(range=AddrRange(0, size='64MB'),
847                                       conf_table_reported=False)
848        if mem_bus is not None:
849            cur_sys.bootmem.port = mem_bus.master
850        if not cur_sys.boot_loader:
851            cur_sys.boot_loader = loc('boot_emm.arm64')
852        cur_sys.atags_addr = 0x8000000
853        cur_sys.load_offset = 0x80000000
854
855class VExpress_GEM5_V1_Base(RealView):
856    """
857The VExpress gem5 memory map is loosely based on a modified
858Versatile Express RS1 memory map.
859
860The gem5 platform has been designed to implement a subset of the
861original Versatile Express RS1 memory map. Off-chip peripherals should,
862when possible, adhere to the Versatile Express memory map. Non-PCI
863off-chip devices that are gem5-specific should live in the CS5 memory
864space to avoid conflicts with existing devices that we might want to
865model in the future. Such devices should normally have interrupts in
866the gem5-specific SPI range.
867
868On-chip peripherals are loosely modeled after the ARM CoreTile Express
869A15x2 A7x3 memory and interrupt map. In particular, the GIC and
870Generic Timer have the same interrupt lines and base addresses. Other
871on-chip devices are gem5 specific.
872
873Unlike the original Versatile Express RS2 extended platform, gem5 implements a
874large contigious DRAM space, without aliases or holes, starting at the
8752GiB boundary. This means that PCI memory is limited to 1GiB.
876
877Memory map:
878   0x00000000-0x03ffffff: Boot memory (CS0)
879   0x04000000-0x07ffffff: Reserved
880   0x08000000-0x0bffffff: Reserved (CS0 alias)
881   0x0c000000-0x0fffffff: Reserved (Off-chip, CS4)
882   0x10000000-0x13ffffff: gem5-specific peripherals (Off-chip, CS5)
883       0x10000000-0x1000ffff: gem5 energy controller
884       0x10010000-0x1001ffff: gem5 pseudo-ops
885
886   0x14000000-0x17ffffff: Reserved (Off-chip, PSRAM, CS1)
887   0x18000000-0x1bffffff: Reserved (Off-chip, Peripherals, CS2)
888   0x1c000000-0x1fffffff: Peripheral block 1 (Off-chip, CS3):
889       0x1c010000-0x1c01ffff: realview_io (VE system control regs.)
890       0x1c060000-0x1c06ffff: KMI0 (keyboard)
891       0x1c070000-0x1c07ffff: KMI1 (mouse)
892       0x1c090000-0x1c09ffff: UART0
893       0x1c0a0000-0x1c0affff: UART1 (reserved)
894       0x1c0b0000-0x1c0bffff: UART2 (reserved)
895       0x1c0c0000-0x1c0cffff: UART3 (reserved)
896       0x1c130000-0x1c13ffff: VirtIO (gem5/FM extension)
897       0x1c140000-0x1c14ffff: VirtIO (gem5/FM extension)
898       0x1c170000-0x1c17ffff: RTC
899
900   0x20000000-0x3fffffff: On-chip peripherals:
901       0x2b000000-0x2b00ffff: HDLCD
902
903       0x2c001000-0x2c001fff: GIC (distributor)
904       0x2c002000-0x2c003fff: GIC (CPU interface)
905       0x2c004000-0x2c005fff: vGIC (HV)
906       0x2c006000-0x2c007fff: vGIC (VCPU)
907       0x2c1c0000-0x2c1cffff: GICv2m MSI frame 0
908
909       0x2d000000-0x2d00ffff: GPU (reserved)
910
911       0x2f000000-0x2fffffff: PCI IO space
912       0x30000000-0x3fffffff: PCI config space
913
914   0x40000000-0x7fffffff: Ext. AXI: Used as PCI memory
915
916   0x80000000-X: DRAM
917
918Interrupts:
919      0- 15: Software generated interrupts (SGIs)
920     16- 31: On-chip private peripherals (PPIs)
921        25   : vgic
922        26   : generic_timer (hyp)
923        27   : generic_timer (virt)
924        28   : Reserved (Legacy FIQ)
925        29   : generic_timer (phys, sec)
926        30   : generic_timer (phys, non-sec)
927        31   : Reserved (Legacy IRQ)
928    32- 95: Mother board peripherals (SPIs)
929        32   : Reserved (SP805)
930        33   : Reserved (IOFPGA SW int)
931        34-35: Reserved (SP804)
932        36   : RTC
933        37-40: uart0-uart3
934        41-42: Reserved (PL180)
935        43   : Reserved (AACI)
936        44-45: kmi0-kmi1
937        46   : Reserved (CLCD)
938        47   : Reserved (Ethernet)
939        48   : Reserved (USB)
940    95-255: On-chip interrupt sources (we use these for
941            gem5-specific devices, SPIs)
942         74    : VirtIO (gem5/FM extension)
943         75    : VirtIO (gem5/FM extension)
944         95    : HDLCD
945         96- 98: GPU (reserved)
946        100-103: PCI
947   256-319: MSI frame 0 (gem5-specific, SPIs)
948   320-511: Unused
949
950    """
951
952    # Everything above 2GiB is memory
953    _mem_regions = [(Addr('2GB'), Addr('510GB'))]
954
955    _off_chip_ranges = [
956        # CS1-CS5
957        AddrRange(0x0c000000, 0x1fffffff),
958        # External AXI interface (PCI)
959        AddrRange(0x2f000000, 0x7fffffff),
960    ]
961
962    # Platform control device (off-chip)
963    realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000,
964                               idreg=0x02250000, pio_addr=0x1c010000)
965    mcc = VExpressMCC()
966    dcc = CoreTile2A15DCC()
967
968    ### On-chip devices ###
969    gic = kvm_gicv2_class(dist_addr=0x2c001000, cpu_addr=0x2c002000,
970                          it_lines=512)
971    vgic = VGic(vcpu_addr=0x2c006000, hv_addr=0x2c004000, ppint=25)
972    gicv2m = Gicv2m()
973    gicv2m.frames = [
974        Gicv2mFrame(spi_base=256, spi_len=64, addr=0x2c1c0000),
975    ]
976
977    generic_timer = GenericTimer(int_phys_s=ArmPPI(num=29),
978                                 int_phys_ns=ArmPPI(num=30),
979                                 int_virt=ArmPPI(num=27),
980                                 int_hyp=ArmPPI(num=26))
981
982    def _on_chip_devices(self):
983        return [
984            self.gic, self.vgic, self.gicv2m,
985            self.generic_timer,
986        ]
987
988    ### Off-chip devices ###
989    clock24MHz = SrcClockDomain(clock="24MHz",
990        voltage_domain=VoltageDomain(voltage="3.3V"))
991
992    uart = [
993        Pl011(pio_addr=0x1c090000, int_num=37),
994    ]
995
996    kmi0 = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
997    kmi1 = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
998
999    rtc = PL031(pio_addr=0x1c170000, int_num=36)
1000
1001    ### gem5-specific off-chip devices ###
1002    pci_host = GenericArmPciHost(
1003        conf_base=0x30000000, conf_size='256MB', conf_device_bits=12,
1004        pci_pio_base=0x2f000000,
1005        int_policy="ARM_PCI_INT_DEV", int_base=100, int_count=4)
1006
1007    energy_ctrl = EnergyCtrl(pio_addr=0x10000000)
1008
1009    vio = [
1010        MmioVirtIO(pio_addr=0x1c130000, pio_size=0x1000,
1011                   interrupt=ArmSPI(num=74)),
1012        MmioVirtIO(pio_addr=0x1c140000, pio_size=0x1000,
1013                   interrupt=ArmSPI(num=75)),
1014    ]
1015
1016    def _off_chip_devices(self):
1017        return [
1018            self.realview_io,
1019            self.uart[0],
1020            self.kmi0,
1021            self.kmi1,
1022            self.rtc,
1023            self.pci_host,
1024            self.energy_ctrl,
1025            self.clock24MHz,
1026            self.vio[0],
1027            self.vio[1],
1028        ]
1029
1030    def attachPciDevice(self, device, *args, **kwargs):
1031        device.host = self.pci_host
1032        self._attach_device(device, *args, **kwargs)
1033
1034    def setupBootLoader(self, mem_bus, cur_sys, loc):
1035        cur_sys.bootmem = SimpleMemory(range=AddrRange(0, size='64MB'),
1036                                       conf_table_reported=False)
1037        if mem_bus is not None:
1038            cur_sys.bootmem.port = mem_bus.master
1039        if not cur_sys.boot_loader:
1040            cur_sys.boot_loader = [ loc('boot_emm.arm64'), loc('boot_emm.arm') ]
1041        cur_sys.atags_addr = 0x8000000
1042        cur_sys.load_offset = 0x80000000
1043
1044        #  Setup m5ops. It's technically not a part of the boot
1045        #  loader, but this is the only place we can configure the
1046        #  system.
1047        cur_sys.m5ops_base = 0x10010000
1048
1049    def generateDeviceTree(self, state):
1050        # Generate using standard RealView function
1051        dt = list(super(VExpress_GEM5_V1_Base, self).generateDeviceTree(state))
1052        if len(dt) > 1:
1053            raise Exception("System returned too many DT nodes")
1054        node = dt[0]
1055
1056        node.appendCompatible(["arm,vexpress"])
1057        node.append(FdtPropertyStrings("model", ["V2P-CA15"]))
1058        node.append(FdtPropertyWords("arm,hbi", [0x0]))
1059        node.append(FdtPropertyWords("arm,vexpress,site", [0xf]))
1060
1061        yield node
1062
1063
1064class VExpress_GEM5_V1(VExpress_GEM5_V1_Base):
1065    hdlcd  = HDLcd(pxl_clk=VExpress_GEM5_V1_Base.dcc.osc_pxl,
1066                   pio_addr=0x2b000000, int_num=95)
1067
1068    def _on_chip_devices(self):
1069        return super(VExpress_GEM5_V1,self)._on_chip_devices() + [
1070                self.hdlcd,
1071            ]
1072