arch-arm, dev-arm: Remove Python 2 compatibility code
[gem5.git] / src / dev / arm / RealView.py
index 25bad06ad7e169b0264a51823660df401d646bef..81d1f0755db4044feb05dfc542e2dfd395625533 100644 (file)
@@ -51,7 +51,9 @@ from m5.objects.Platform import Platform
 from m5.objects.Terminal import Terminal
 from m5.objects.Uart import Uart
 from m5.objects.SimpleMemory import SimpleMemory
+from m5.objects.GenericTimer import *
 from m5.objects.Gic import *
+from m5.objects.MHU import MHU, Scp2ApDoorbell, Ap2ScpDoorbell
 from m5.objects.EnergyCtrl import EnergyCtrl
 from m5.objects.ClockedObject import ClockedObject
 from m5.objects.SubSystem import SubSystem
@@ -60,7 +62,9 @@ from m5.objects.ClockedObject import ClockedObject
 from m5.objects.PS2 import *
 from m5.objects.VirtIOMMIO import MmioVirtIO
 from m5.objects.Display import Display, Display1080p
+from m5.objects.Scmi import *
 from m5.objects.SMMUv3 import SMMUv3
+from m5.objects.PciDevice import PciLegacyIoBar, PciIoBar
 
 # Platforms with KVM support should generally use in-kernel GIC
 # emulation. Use a GIC model that automatically switches between
@@ -84,8 +88,7 @@ class AmbaIntDevice(AmbaPioDevice):
     type = 'AmbaIntDevice'
     abstract = True
     cxx_header = "dev/arm/amba_device.hh"
-    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
-    int_num = Param.UInt32("Interrupt number that connects to GIC")
+    interrupt = Param.ArmInterruptPin("Interrupt that connects to GIC")
     int_delay = Param.Latency("100ns",
             "Time between action and interrupt generation by device")
 
@@ -93,10 +96,10 @@ class AmbaDmaDevice(DmaDevice):
     type = 'AmbaDmaDevice'
     abstract = True
     cxx_header = "dev/arm/amba_device.hh"
-    pio_addr = Param.Addr("Address for AMBA slave interface")
-    pio_latency = Param.Latency("10ns", "Time between action and write/read result by AMBA DMA Device")
-    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
-    int_num = Param.UInt32("Interrupt number that connects to GIC")
+    pio_addr = Param.Addr("Address for AMBA responder interface")
+    pio_latency = Param.Latency("10ns", "Time between action and write/read"
+                                        "result by AMBA DMA Device")
+    interrupt = Param.ArmInterruptPin("Interrupt that connects to GIC")
     amba_id = Param.UInt32("ID of AMBA device for kernel detection")
 
 class A9SCU(BasicPioDevice):
@@ -159,7 +162,7 @@ class GenericArmPciHost(GenericPciHost):
 
         # AXI memory address range
         ranges += self.pciFdtAddr(space=2, addr=0)
-        ranges += state.addrCells(0x40000000) # Fixed offset
+        ranges += state.addrCells(self.pci_mem_base)
         ranges += local_state.sizeCells(0x40000000) # Fixed size
         node.append(FdtPropertyWords("ranges", ranges))
 
@@ -208,7 +211,7 @@ class RealViewCtrl(BasicPioDevice):
     idreg = Param.UInt32(0x00000000, "ID Register, SYS_ID")
 
     def generateDeviceTree(self, state):
-        node = FdtNode("sysreg@%x" % long(self.pio_addr))
+        node = FdtNode("sysreg@%x" % int(self.pio_addr))
         node.appendCompatible("arm,vexpress-sysreg")
         node.append(FdtPropertyWords("reg",
             state.addrCells(self.pio_addr) +
@@ -241,15 +244,27 @@ class RealViewOsc(ClockDomain):
 
     freq = Param.Clock("Default frequency")
 
+    # These are currently only used for the device tree.
+    min_freq = Param.Clock("0t", "Minimum frequency")
+    max_freq = Param.Clock("0t", "Maximum frequency")
+
     def generateDeviceTree(self, state):
         phandle = state.phandle(self)
-        node = FdtNode("osc@" + format(long(phandle), 'x'))
+        node = FdtNode("osc@" + format(int(phandle), 'x'))
         node.appendCompatible("arm,vexpress-osc")
         node.append(FdtPropertyWords("arm,vexpress-sysreg,func",
                                      [0x1, int(self.device)]))
         node.append(FdtPropertyWords("#clock-cells", [0]))
-        freq = int(1.0/self.freq.value) # Values are stored as a clock period
-        node.append(FdtPropertyWords("freq-range", [freq, freq]))
+
+        minf = self.min_freq if self.min_freq.value else self.freq
+        maxf = self.max_freq if self.max_freq.value else self.freq
+
+        # Values are stored as a clock period.
+        def to_freq(prop):
+            return int(1.0 / prop.value)
+
+        node.append(FdtPropertyWords("freq-range",
+                                     [to_freq(minf), to_freq(maxf)]))
         node.append(FdtPropertyStrings("clock-output-names",
                                        ["oscclk" + str(phandle)]))
         node.appendPhandle(self)
@@ -285,10 +300,12 @@ Express (V2M-P1) motherboard. See ARM DUI 0447J for details.
     class Temperature(RealViewTemperatureSensor):
         site, position, dcc = (0, 0, 0)
 
-    osc_mcc = Osc(device=0, freq="50MHz")
-    osc_clcd = Osc(device=1, freq="23.75MHz")
+    osc_mcc = Osc(device=0, min_freq="25MHz", max_freq="60MHz", freq="50MHz")
+    osc_clcd = Osc(device=1, min_freq="23.75MHz", max_freq="63.5MHz",
+                   freq="23.75MHz")
     osc_peripheral = Osc(device=2, freq="24MHz")
-    osc_system_bus = Osc(device=4, freq="24MHz")
+    osc_system_bus = Osc(device=4, min_freq="2MHz", max_freq="230MHz",
+                         freq="24MHz")
 
     # See Table 4.19 in ARM DUI 0447J (Motherboard Express uATX TRM).
     temp_crtl = Temperature(device=0)
@@ -319,11 +336,12 @@ ARM DUI 0604E for details.
         site, position, dcc = (1, 0, 0)
 
     # See Table 2.8 in ARM DUI 0604E (CoreTile Express A15x2 TRM)
-    osc_cpu = Osc(device=0, freq="60MHz")
-    osc_hsbm = Osc(device=4, freq="40MHz")
-    osc_pxl = Osc(device=5, freq="23.75MHz")
-    osc_smb = Osc(device=6, freq="50MHz")
-    osc_sys = Osc(device=7, freq="60MHz")
+    osc_cpu = Osc(device=0, min_freq="20MHz", max_freq="60MHz", freq="60MHz")
+    osc_hsbm = Osc(device=4, min_freq="20MHz", max_freq="40MHz", freq="40MHz")
+    osc_pxl = Osc(device=5, min_freq="23.76MHz", max_freq="165MHz",
+                  freq="23.75MHz")
+    osc_smb = Osc(device=6, min_freq="20MHz", max_freq="50MHz", freq="50MHz")
+    osc_sys = Osc(device=7, min_freq="20MHz", max_freq="60MHz", freq="60MHz")
     osc_ddr = Osc(device=8, freq="40MHz")
 
     def generateDeviceTree(self, state):
@@ -368,14 +386,13 @@ class FixedClock(SrcClockDomain):
 class Pl011(Uart):
     type = 'Pl011'
     cxx_header = "dev/arm/pl011.hh"
-    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
-    int_num = Param.UInt32("Interrupt number that connects to GIC")
+    interrupt = Param.ArmInterruptPin("Interrupt that connects to GIC")
     end_on_eot = Param.Bool(False, "End the simulation when a EOT is received on the UART")
     int_delay = Param.Latency("100ns", "Time between action and interrupt generation by UART")
 
     def generateDeviceTree(self, state):
         node = self.generateBasicPioDeviceNode(state, 'uart', self.pio_addr,
-                                               0x1000, [int(self.int_num)])
+            0x1000, [ self.interrupt ])
         node.appendCompatible(["arm,pl011", "arm,primecell"])
 
         # Hardcoded reference to the realview platform clocks, because the
@@ -390,10 +407,9 @@ class Pl011(Uart):
 class Sp804(AmbaPioDevice):
     type = 'Sp804'
     cxx_header = "dev/arm/timer_sp804.hh"
-    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
-    int_num0 = Param.UInt32("Interrupt number that connects to GIC")
+    int0 = Param.ArmSPI("Interrupt that connects to GIC")
     clock0 = Param.Clock('1MHz', "Clock speed of the input")
-    int_num1 = Param.UInt32("Interrupt number that connects to GIC")
+    int1 = Param.ArmSPI("Interrupt that connects to GIC")
     clock1 = Param.Clock('1MHz', "Clock speed of the input")
     amba_id = 0x00141804
 
@@ -412,7 +428,7 @@ Reference:
 
     def generateDeviceTree(self, state):
         node = self.generateBasicPioDeviceNode(state, 'watchdog',
-            self.pio_addr, 0x1000, [int(self.int_num)])
+            self.pio_addr, 0x1000, [ self.interrupt ])
         node.appendCompatible(['arm,sp805', 'arm,primecell'])
         clocks = [state.phandle(self.clk_domain.unproxy(self))]
         clock_names = ['wdogclk']
@@ -437,62 +453,20 @@ class CpuLocalTimer(BasicPioDevice):
     int_timer = Param.ArmPPI("Interrrupt used per-cpu to GIC")
     int_watchdog = Param.ArmPPI("Interrupt for per-cpu watchdog to GIC")
 
-class GenericTimer(ClockedObject):
-    type = 'GenericTimer'
-    cxx_header = "dev/arm/generic_timer.hh"
-    system = Param.ArmSystem(Parent.any, "system")
-    int_phys_s = Param.ArmPPI("Physical (S) timer interrupt")
-    int_phys_ns = Param.ArmPPI("Physical (NS) timer interrupt")
-    int_virt = Param.ArmPPI("Virtual timer interrupt")
-    int_hyp = Param.ArmPPI("Hypervisor timer interrupt")
-
-    freqs = VectorParam.UInt32([0x01800000], "Frequencies available for the "
-        "system counter (in Hz). First element is the base frequency, "
-        "following are alternative lower ones which must be exact divisors")
-
-    def generateDeviceTree(self, state):
-        node = FdtNode("timer")
-
-        node.appendCompatible(["arm,cortex-a15-timer",
-                               "arm,armv7-timer",
-                               "arm,armv8-timer"])
-        node.append(FdtPropertyWords("interrupts", [
-            1, int(self.int_phys_s.num) - 16, 0xf08,
-            1, int(self.int_phys_ns.num) - 16, 0xf08,
-            1, int(self.int_virt.num) - 16, 0xf08,
-            1, int(self.int_hyp.num) - 16, 0xf08,
-        ]))
-        clock = state.phandle(self.clk_domain.unproxy(self))
-        node.append(FdtPropertyWords("clocks", clock))
-
-        yield node
-
-class GenericTimerMem(PioDevice):
-    type = 'GenericTimerMem'
-    cxx_header = "dev/arm/generic_timer.hh"
-
-    base = Param.Addr(0, "Base address")
-
-    int_phys = Param.ArmSPI("Physical Interrupt")
-    int_virt = Param.ArmSPI("Virtual Interrupt")
-
-    freqs = VectorParam.UInt32([0x01800000], "Frequencies available for the "
-        "system counter (in Hz). First element is the base frequency, "
-        "following are alternative lower ones which must be exact divisors")
-
 class PL031(AmbaIntDevice):
     type = 'PL031'
     cxx_header = "dev/arm/rtc_pl031.hh"
     time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)")
-    amba_id = 0x00341031
+    amba_id = 0x00041031
 
     def generateDeviceTree(self, state):
         node = self.generateBasicPioDeviceNode(state, 'rtc', self.pio_addr,
-                                               0x1000, [int(self.int_num)])
+            0x1000, [ self.interrupt ])
 
         node.appendCompatible(["arm,pl031", "arm,primecell"])
         clock = state.phandle(self.clk_domain.unproxy(self))
         node.append(FdtPropertyWords("clocks", clock))
+        node.append(FdtPropertyStrings("clock-names", ["apb_pclk"]))
 
         yield node
 
@@ -505,7 +479,7 @@ class Pl050(AmbaIntDevice):
 
     def generateDeviceTree(self, state):
         node = self.generateBasicPioDeviceNode(state, 'kmi', self.pio_addr,
-                                               0x1000, [int(self.int_num)])
+            0x1000, [ self.interrupt ])
 
         node.appendCompatible(["arm,pl050", "arm,primecell"])
         clock = state.phandle(self.clk_domain.unproxy(self))
@@ -567,9 +541,8 @@ class HDLcd(AmbaDmaDevice):
         port_node = FdtNode("port")
         port_node.append(endpoint_node)
 
-        # Interrupt number is hardcoded; it is not a property of this class
         node = self.generateBasicPioDeviceNode(state, 'hdlcd',
-                                               self.pio_addr, 0x1000, [63])
+            self.pio_addr, 0x1000, [ self.interrupt ])
 
         node.appendCompatible(["arm,hdlcd"])
         node.append(FdtPropertyWords("clocks", state.phandle(self.pxl_clk)))
@@ -587,6 +560,87 @@ class HDLcd(AmbaDmaDevice):
 
         yield node
 
+class ParentMem(SimpleMemory):
+    """
+    This is a base abstract class for child node generation
+    A memory willing to autogenerate child nodes can do that
+    directly in the generateDeviceTree method.
+    However sometimes portions of memory (child nodes) are tagged
+    for specific applications. Hardcoding the child node in the
+    parent memory class is not flexible, so we delegate this
+    to the application model, which is registering the generator
+    helper via the ParentMem interface.
+    """
+    def __init__(self, *args, **kwargs):
+        super(ParentMem, self).__init__(*args, **kwargs)
+        self._generators = []
+
+    def addSubnodeGenerator(self, gen):
+        """
+        This is the method a client application would use to
+        register a child generator in the memory object.
+        """
+        self._generators.append(gen)
+
+    def generateSubnodes(self, node, state):
+        """
+        This is the method the memory would use to instantiate
+        the child nodes via the previously registered generators.
+        """
+        for subnode_gen in self._generators:
+            node.append(subnode_gen(state))
+
+class MmioSRAM(ParentMem):
+    def __init__(self, *args, **kwargs):
+        super(MmioSRAM, self).__init__(**kwargs)
+
+    def generateDeviceTree(self, state):
+        node = FdtNode("sram@%x" % int(self.range.start))
+        node.appendCompatible(["mmio-sram"])
+        node.append(FdtPropertyWords("reg",
+            state.addrCells(self.range.start) +
+            state.sizeCells(self.range.size()) ))
+
+        local_state = FdtState(addr_cells=2, size_cells=2, cpu_cells=1)
+        node.append(local_state.addrCellsProperty())
+        node.append(local_state.sizeCellsProperty())
+        node.append(FdtPropertyWords("ranges",
+            local_state.addrCells(0) +
+            state.addrCells(self.range.start) +
+            state.sizeCells(self.range.size()) ))
+
+        self.generateSubnodes(node, state)
+
+        yield node
+
+class FVPBasePwrCtrl(BasicPioDevice):
+    """
+Based on Fast Models Base_PowerController v11.8
+Reference:
+    Fast Models Reference Manual - Section 7.7.2 - Version 11.8
+    Document ID: 100964_1180_00_en
+    """
+
+    type = 'FVPBasePwrCtrl'
+    cxx_header = 'dev/arm/fvp_base_pwr_ctrl.hh'
+
+class GenericMHU(MHU):
+    lowp_scp2ap = Scp2ApDoorbell(
+        set_address=0x10020008, clear_address=0x10020010,
+        interrupt=ArmSPI(num=68))
+    highp_scp2ap = Scp2ApDoorbell(
+        set_address=0x10020028, clear_address=0x10020030,
+        interrupt=ArmSPI(num=67))
+    sec_scp2ap = Scp2ApDoorbell(
+        set_address=0x10020208, clear_address=0x10020210,
+        interrupt=ArmSPI(num=69))
+    lowp_ap2scp = Ap2ScpDoorbell(
+        set_address=0x10020108, clear_address=0x10020110)
+    highp_ap2scp = Ap2ScpDoorbell(
+        set_address=0x10020128, clear_address=0x10020130)
+    sec_ap2scp = Ap2ScpDoorbell(
+        set_address=0x10020308, clear_address=0x10020310)
+
 class RealView(Platform):
     type = 'RealView'
     cxx_header = "dev/arm/realview.hh"
@@ -611,16 +665,16 @@ class RealView(Platform):
     def _attach_memory(self, mem, bus, mem_ports=None):
         if hasattr(mem, "port"):
             if mem_ports is None:
-                mem.port = bus.master
+                mem.port = bus.mem_side_ports
             else:
                 mem_ports.append(mem.port)
 
     def _attach_device(self, device, bus, dma_ports=None):
         if hasattr(device, "pio"):
-            device.pio = bus.master
+            device.pio = bus.mem_side_ports
         if hasattr(device, "dma"):
             if dma_ports is None:
-                device.dma = bus.slave
+                device.dma = bus.cpu_side_ports
             else:
                 dma_ports.append(device.dma)
 
@@ -655,14 +709,15 @@ class RealView(Platform):
         if bridge:
             bridge.ranges = self._off_chip_ranges
 
-    def attachIO(self, *args, **kwargs):
-        self._attach_mem(self._off_chip_memory(), *args, **kwargs)
-        self._attach_io(self._off_chip_devices(), *args, **kwargs)
+    def attachIO(self, bus, dma_ports=None, mem_ports=None):
+        self._attach_mem(self._off_chip_memory(), bus, mem_ports)
+        self._attach_io(self._off_chip_devices(), bus, dma_ports)
 
-    def setupBootLoader(self, cur_sys, boot_loader, atags_addr, load_offset):
-        cur_sys.boot_loader = boot_loader
-        cur_sys.atags_addr = atags_addr
-        cur_sys.load_offset = load_offset
+    def setupBootLoader(self, cur_sys, boot_loader, dtb_addr, load_offset):
+        cur_sys.workload.boot_loader = boot_loader
+        cur_sys.workload.load_addr_offset = load_offset
+        cur_sys.workload.dtb_addr = load_offset + dtb_addr
+        cur_sys.workload.cpu_release_addr = cur_sys.workload.dtb_addr - 8
 
     def generateDeviceTree(self, state):
         node = FdtNode("/") # Things in this module need to end up in the root
@@ -675,9 +730,16 @@ class RealView(Platform):
         yield node
 
     def annotateCpuDeviceNode(self, cpu, state):
-        cpu.append(FdtPropertyStrings("enable-method", "spin-table"))
-        cpu.append(FdtPropertyWords("cpu-release-addr", \
-                                    state.addrCells(0x8000fff8)))
+        system = self.system.unproxy(self)
+        if system._have_psci:
+            cpu.append(FdtPropertyStrings('enable-method', 'psci'))
+        else:
+            cpu.append(FdtPropertyStrings("enable-method", "spin-table"))
+            # The kernel writes the entry addres of secondary CPUs to this
+            # address before waking up secondary CPUs.
+            # The gem5 bootloader then makes secondary CPUs jump to it.
+            cpu.append(FdtPropertyWords("cpu-release-addr", \
+                        state.addrCells(system.workload.cpu_release_addr)))
 
 class VExpress_EMM(RealView):
     _mem_regions = [ AddrRange('2GB', size='2GB') ]
@@ -706,7 +768,7 @@ class VExpress_EMM(RealView):
                                     pio_addr=0x2C080000)
 
     hdlcd  = HDLcd(pxl_clk=dcc.osc_pxl,
-                   pio_addr=0x2b000000, int_num=117,
+                   pio_addr=0x2b000000, interrupt=ArmSPI(num=117),
                    workaround_swap_rb=True)
 
     def _on_chip_devices(self):
@@ -726,32 +788,37 @@ class VExpress_EMM(RealView):
         return memories
 
     ### Off-chip devices ###
-    uart = Pl011(pio_addr=0x1c090000, int_num=37)
+    uart = Pl011(pio_addr=0x1c090000, interrupt=ArmSPI(num=37))
     pci_host = GenericPciHost(
         conf_base=0x30000000, conf_size='256MB', conf_device_bits=16,
         pci_pio_base=0)
 
-    generic_timer = GenericTimer(int_phys_s=ArmPPI(num=29),
-                                 int_phys_ns=ArmPPI(num=30),
-                                 int_virt=ArmPPI(num=27),
-                                 int_hyp=ArmPPI(num=26))
-
-    timer0 = Sp804(int_num0=34, int_num1=34, pio_addr=0x1C110000, clock0='1MHz', clock1='1MHz')
-    timer1 = Sp804(int_num0=35, int_num1=35, pio_addr=0x1C120000, clock0='1MHz', clock1='1MHz')
-    clcd   = Pl111(pio_addr=0x1c1f0000, int_num=46)
-    kmi0   = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
-    kmi1   = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
+    sys_counter = SystemCounter()
+    generic_timer = GenericTimer(
+        int_phys_s=ArmPPI(num=29, int_type='IRQ_TYPE_LEVEL_LOW'),
+        int_phys_ns=ArmPPI(num=30, int_type='IRQ_TYPE_LEVEL_LOW'),
+        int_virt=ArmPPI(num=27, int_type='IRQ_TYPE_LEVEL_LOW'),
+        int_hyp=ArmPPI(num=26, int_type='IRQ_TYPE_LEVEL_LOW'))
+
+    timer0 = Sp804(int0=ArmSPI(num=34), int1=ArmSPI(num=34),
+                   pio_addr=0x1C110000, clock0='1MHz', clock1='1MHz')
+    timer1 = Sp804(int0=ArmSPI(num=35), int1=ArmSPI(num=35),
+                   pio_addr=0x1C120000, clock0='1MHz', clock1='1MHz')
+    clcd   = Pl111(pio_addr=0x1c1f0000, interrupt=ArmSPI(num=46))
+    kmi0   = Pl050(pio_addr=0x1c060000, interrupt=ArmSPI(num=44),
+                   ps2=PS2Keyboard())
+    kmi1   = Pl050(pio_addr=0x1c070000, interrupt=ArmSPI(num=45),
+                   ps2=PS2TouchKit())
     cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=0, pci_bus=2,
-                            io_shift = 2, ctrl_offset = 2, Command = 0x1,
-                            BAR0 = 0x1C1A0000, BAR0Size = '256B',
-                            BAR1 = 0x1C1A0100, BAR1Size = '4096B',
-                            BAR0LegacyIO = True, BAR1LegacyIO = True)
+                            io_shift = 2, ctrl_offset = 2, Command = 0x1)
+    cf_ctrl.BAR0 = PciLegacyIoBar(addr='0x1C1A0000', size='256B')
+    cf_ctrl.BAR1 = PciLegacyIoBar(addr='0x1C1A0100', size='4096B')
 
     bootmem        = SimpleMemory(range = AddrRange('64MB'),
                                   conf_table_reported = False)
     vram           = SimpleMemory(range = AddrRange(0x18000000, size='32MB'),
                                   conf_table_reported = False)
-    rtc            = PL031(pio_addr=0x1C170000, int_num=36)
+    rtc            = PL031(pio_addr=0x1C170000, interrupt=ArmSPI(num=36))
 
     l2x0_fake      = IsaFake(pio_addr=0x2C100000, pio_size=0xfff)
     uart1_fake     = AmbaFake(pio_addr=0x1C0A0000)
@@ -878,11 +945,12 @@ References:
 Memory map:
    0x00000000-0x03ffffff: Boot memory (CS0)
    0x04000000-0x07ffffff: Reserved
-   0x08000000-0x0bffffff: Reserved (CS0 alias)
-   0x0c000000-0x0fffffff: Reserved (Off-chip, CS4)
+   0x08000000-0x0bffffff: NOR FLASH0 (CS0 alias)
+   0x0c000000-0x0fffffff: NOR FLASH1 (Off-chip, CS4)
    0x10000000-0x13ffffff: gem5-specific peripherals (Off-chip, CS5)
        0x10000000-0x1000ffff: gem5 energy controller
        0x10010000-0x1001ffff: gem5 pseudo-ops
+       0x10020000-0x1002ffff: gem5 MHU
 
    0x14000000-0x17ffffff: Reserved (Off-chip, PSRAM, CS1)
    0x18000000-0x1bffffff: Reserved (Off-chip, Peripherals, CS2)
@@ -891,15 +959,23 @@ Memory map:
        0x1c060000-0x1c06ffff: KMI0 (keyboard)
        0x1c070000-0x1c07ffff: KMI1 (mouse)
        0x1c090000-0x1c09ffff: UART0
-       0x1c0a0000-0x1c0affff: UART1 (reserved)
-       0x1c0b0000-0x1c0bffff: UART2 (reserved)
-       0x1c0c0000-0x1c0cffff: UART3 (reserved)
+       0x1c0a0000-0x1c0affff: UART1
+       0x1c0b0000-0x1c0bffff: UART2
+       0x1c0c0000-0x1c0cffff: UART3
        0x1c0f0000-0x1c0fffff: Watchdog (SP805)
        0x1c130000-0x1c13ffff: VirtIO (gem5/FM extension)
        0x1c140000-0x1c14ffff: VirtIO (gem5/FM extension)
        0x1c170000-0x1c17ffff: RTC
 
    0x20000000-0x3fffffff: On-chip peripherals:
+       0x2a430000-0x2a43ffff: System Counter (control)
+       0x2a490000-0x2a49ffff: Trusted Watchdog (SP805)
+       0x2a800000-0x2a800fff: System Counter (read)
+       0x2a810000-0x2a810fff: System Timer (control)
+
+       0x2a820000-0x2a820fff: System Timer (frame 0)
+       0x2a830000-0x2a830fff: System Timer (frame 1)
+
        0x2b000000-0x2b00ffff: HDLCD
 
        0x2b060000-0x2b060fff: System Watchdog (SP805)
@@ -914,6 +990,8 @@ Memory map:
 
        0x2d000000-0x2d00ffff: GPU (reserved)
 
+       0x2e000000-0x2e007fff: Non-trusted SRAM
+
        0x2f000000-0x2fffffff: PCI IO space
        0x30000000-0x3fffffff: PCI config space
 
@@ -943,6 +1021,9 @@ Interrupts:
         46   : Reserved (CLCD)
         47   : Reserved (Ethernet)
         48   : Reserved (USB)
+        56   : Trusted Watchdog (SP805)
+        57   : System timer0 (phys)
+        58   : System timer1 (phys)
     95-255: On-chip interrupt sources (we use these for
             gem5-specific devices, SPIs)
          74    : VirtIO (gem5/FM extension)
@@ -969,29 +1050,60 @@ Interrupts:
     bootmem = SimpleMemory(range=AddrRange(0, size='64MB'),
                            conf_table_reported=False)
 
+    # NOR flash, flash0
+    flash0 = SimpleMemory(range=AddrRange(0x08000000, size='64MB'),
+                          conf_table_reported=False)
+
+    # Trusted SRAM
+    trusted_sram = SimpleMemory(range=AddrRange(0x04000000, size='256kB'),
+                                conf_table_reported=False)
+
+    # Non-Trusted SRAM
+    non_trusted_sram = MmioSRAM(range=AddrRange(0x2e000000, size=0x8000),
+                                conf_table_reported=False)
+
     # Platform control device (off-chip)
     realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000,
-                               idreg=0x02250000, pio_addr=0x1c010000)
+                               idreg=0x30101100, pio_addr=0x1c010000)
     mcc = VExpressMCC()
     dcc = CoreTile2A15DCC()
 
     ### On-chip devices ###
-    generic_timer = GenericTimer(int_phys_s=ArmPPI(num=29),
-                                 int_phys_ns=ArmPPI(num=30),
-                                 int_virt=ArmPPI(num=27),
-                                 int_hyp=ArmPPI(num=26))
 
-    system_watchdog = Sp805(pio_addr=0x2b060000, int_num=130)
+    # Trusted Watchdog, SP805
+    trusted_watchdog = Sp805(pio_addr=0x2a490000, interrupt=ArmSPI(num=56))
+
+    sys_counter = SystemCounter()
+    generic_timer = GenericTimer(
+        int_phys_s=ArmPPI(num=29, int_type='IRQ_TYPE_LEVEL_LOW'),
+        int_phys_ns=ArmPPI(num=30, int_type='IRQ_TYPE_LEVEL_LOW'),
+        int_virt=ArmPPI(num=27, int_type='IRQ_TYPE_LEVEL_LOW'),
+        int_hyp=ArmPPI(num=26, int_type='IRQ_TYPE_LEVEL_LOW'))
+    generic_timer_mem = GenericTimerMem(cnt_control_base=0x2a430000,
+                                        cnt_read_base=0x2a800000,
+                                        cnt_ctl_base=0x2a810000,
+                                        frames=[
+            GenericTimerFrame(cnt_base=0x2a820000,
+                int_phys=ArmSPI(num=57), int_virt=ArmSPI(num=133)),
+            GenericTimerFrame(cnt_base=0x2a830000,
+                int_phys=ArmSPI(num=58), int_virt=ArmSPI(num=134))
+    ])
+
+    system_watchdog = Sp805(pio_addr=0x2b060000, interrupt=ArmSPI(num=130))
 
     def _on_chip_devices(self):
         return [
-            self.generic_timer,
+            self.generic_timer_mem,
+            self.trusted_watchdog,
             self.system_watchdog
-        ]
+        ] + self.generic_timer_mem.frames
 
     def _on_chip_memory(self):
         memories = [
             self.bootmem,
+            self.trusted_sram,
+            self.non_trusted_sram,
+            self.flash0,
         ]
         return memories
 
@@ -1001,24 +1113,36 @@ Interrupts:
     clock24MHz = SrcClockDomain(clock="24MHz")
 
     uart = [
-        Pl011(pio_addr=0x1c090000, int_num=37),
+        Pl011(pio_addr=0x1c090000,
+            interrupt=ArmSPI(num=37)),
+        Pl011(pio_addr=0x1c0a0000,
+            interrupt=ArmSPI(num=38), device=Terminal()),
+        Pl011(pio_addr=0x1c0b0000,
+            interrupt=ArmSPI(num=39), device=Terminal()),
+        Pl011(pio_addr=0x1c0c0000,
+            interrupt=ArmSPI(num=40), device=Terminal())
     ]
 
-    kmi0 = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
-    kmi1 = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
+    kmi0 = Pl050(pio_addr=0x1c060000, interrupt=ArmSPI(num=44),
+                 ps2=PS2Keyboard())
+    kmi1 = Pl050(pio_addr=0x1c070000, interrupt=ArmSPI(num=45),
+                 ps2=PS2TouchKit())
 
-    watchdog = Sp805(pio_addr=0x1c0f0000, int_num=32)
+    watchdog = Sp805(pio_addr=0x1c0f0000, interrupt=ArmSPI(num=32))
 
-    rtc = PL031(pio_addr=0x1c170000, int_num=36)
+    rtc = PL031(pio_addr=0x1C170000, interrupt=ArmSPI(num=36))
 
     ### gem5-specific off-chip devices ###
     pci_host = GenericArmPciHost(
         conf_base=0x30000000, conf_size='256MB', conf_device_bits=12,
         pci_pio_base=0x2f000000,
+        pci_mem_base=0x40000000,
         int_policy="ARM_PCI_INT_DEV", int_base=100, int_count=4)
 
     energy_ctrl = EnergyCtrl(pio_addr=0x10000000)
 
+    pwr_ctrl = FVPBasePwrCtrl(pio_addr=0x1c100000)
+
     vio = [
         MmioVirtIO(pio_addr=0x1c130000, pio_size=0x1000,
                    interrupt=ArmSPI(num=74)),
@@ -1026,20 +1150,29 @@ Interrupts:
                    interrupt=ArmSPI(num=75)),
     ]
 
+    # NOR flash, flash1
+    flash1 = SimpleMemory(range=AddrRange(0x0c000000, 0x10000000),
+                          conf_table_reported=False)
+
     def _off_chip_devices(self):
         return [
             self.realview_io,
-            self.uart[0],
             self.kmi0,
             self.kmi1,
             self.watchdog,
             self.rtc,
             self.pci_host,
             self.energy_ctrl,
+            self.pwr_ctrl,
             self.clock32KHz,
             self.clock24MHz,
             self.vio[0],
             self.vio[1],
+        ] + self.uart
+
+    def _off_chip_memory(self):
+        return [
+            self.flash1,
         ]
 
     def __init__(self, **kwargs):
@@ -1061,15 +1194,15 @@ Interrupts:
         """
         Instantiate a single SMMU and attach a group of client devices to it.
         The devices' dma port is wired to the SMMU and the SMMU's dma port
-        (master) is attached to the bus. In order to make it work, the list
-        of clients shouldn't contain any device part of the _off_chip_devices
-        or _on_chip_devices.
+        is attached to the bus. In order to make it work, the list of clients
+        shouldn't contain any device part of the _off_chip_devices or
+        _on_chip_devices.
         This method should be called only once.
 
         Parameters:
             devices (list): List of devices which will be using the SMMU
-            bus (Bus): The bus downstream of the SMMU. Its slave port will
-                       receive memory requests from the SMMU, and its master
+            bus (Bus): The bus downstream of the SMMU. Its response port will
+                       receive memory requests from the SMMU, and its request
                        port will forward accesses to the memory mapped devices
         """
         if hasattr(self, 'smmu'):
@@ -1077,10 +1210,13 @@ Interrupts:
 
         self.smmu = SMMUv3(reg_map=AddrRange(0x2b400000, size=0x00020000))
 
+        self.smmu.request = bus.cpu_side_ports
+        self.smmu.control = bus.mem_side_ports
+
         dma_ports = []
         for dev in devices:
             self._attach_device(dev, bus, dma_ports)
-            self.smmu.connect(dev, bus)
+            self.smmu.connect(dev)
 
     def setupBootLoader(self, cur_sys, boot_loader):
         super(VExpress_GEM5_Base, self).setupBootLoader(
@@ -1091,6 +1227,25 @@ Interrupts:
         #  system.
         cur_sys.m5ops_base = 0x10010000
 
+    def attachScmi(self, bus):
+        # Generate and attach the mailbox
+        self.mailbox = GenericMHU(pio_addr=0x10020000)
+        self._attach_device(self.mailbox, bus)
+
+        # Generate and attach the SCMI platform
+        _scmi_comm = ScmiCommunication(
+            agent_channel = ScmiAgentChannel(
+                shmem=self.non_trusted_sram,
+                shmem_range=AddrRange(0x2e000000, size=0x200),
+                doorbell=self.mailbox.highp_ap2scp),
+            platform_channel = ScmiPlatformChannel(
+                shmem=self.non_trusted_sram,
+                shmem_range=AddrRange(0x2e000000, size=0x200),
+                doorbell=self.mailbox.highp_scp2ap))
+
+        self.scmi = ScmiPlatform(comms=[ _scmi_comm ])
+        self._attach_device(self.scmi, bus)
+
     def generateDeviceTree(self, state):
         # Generate using standard RealView function
         dt = list(super(VExpress_GEM5_Base, self).generateDeviceTree(state))
@@ -1103,6 +1258,24 @@ Interrupts:
         node.append(FdtPropertyWords("arm,hbi", [0x0]))
         node.append(FdtPropertyWords("arm,vexpress,site", [0xf]))
 
+        system = self.system.unproxy(self)
+        if system._have_psci:
+            # PSCI functions exposed to the kernel
+            if not system.have_security:
+                raise AssertionError("PSCI requires EL3 (have_security)")
+
+            psci_node = FdtNode('psci')
+            psci_node.appendCompatible(['arm,psci-1.0', 'arm,psci-0.2',
+                                        'arm,psci'])
+            method = 'smc'
+            psci_node.append(FdtPropertyStrings('method', method))
+            psci_node.append(FdtPropertyWords('cpu_suspend', 0xc4000001))
+            psci_node.append(FdtPropertyWords('cpu_off', 0x84000002))
+            psci_node.append(FdtPropertyWords('cpu_on', 0xc4000003))
+            psci_node.append(FdtPropertyWords('sys_poweroff', 0x84000008))
+            psci_node.append(FdtPropertyWords('sys_reset', 0x84000009))
+            node.append(psci_node)
+
         yield node
 
 class VExpress_GEM5_V1_Base(VExpress_GEM5_Base):
@@ -1127,7 +1300,7 @@ class VExpress_GEM5_V1_Base(VExpress_GEM5_Base):
 
 class VExpress_GEM5_V1(VExpress_GEM5_V1_Base):
     hdlcd  = HDLcd(pxl_clk=VExpress_GEM5_V1_Base.dcc.osc_pxl,
-                   pio_addr=0x2b000000, int_num=95)
+                   pio_addr=0x2b000000, interrupt=ArmSPI(num=95))
 
     def _on_chip_devices(self):
         return super(VExpress_GEM5_V1,self)._on_chip_devices() + [
@@ -1155,9 +1328,44 @@ class VExpress_GEM5_V2_Base(VExpress_GEM5_Base):
 
 class VExpress_GEM5_V2(VExpress_GEM5_V2_Base):
     hdlcd  = HDLcd(pxl_clk=VExpress_GEM5_V2_Base.dcc.osc_pxl,
-                   pio_addr=0x2b000000, int_num=95)
+                   pio_addr=0x2b000000, interrupt=ArmSPI(num=95))
 
     def _on_chip_devices(self):
         return super(VExpress_GEM5_V2,self)._on_chip_devices() + [
                 self.hdlcd,
             ]
+
+class VExpress_GEM5_Foundation(VExpress_GEM5_Base):
+    """
+    Based on Armv8-A FVP Foundation platform v11.8
+    Reference for memory and interrupt map:
+        Armv8-A Foundation Platform - User Guide - Version 11.8
+        Document ID: 100961_1180_00_en
+    """
+    _off_chip_ranges = [
+        # CS1-CS5
+        AddrRange(0x0c000000, 0x20000000),
+        # External AXI interface (PCI)
+        AddrRange(0x40000000, 0x80000000),
+    ]
+
+    gic = Gicv3(dist_addr=0x2f000000, redist_addr=0x2f100000,
+                maint_int=ArmPPI(num=25), gicv4=False,
+                its=NULL)
+
+    pci_host = GenericArmPciHost(
+        conf_base=0x40000000, conf_size='256MB', conf_device_bits=12,
+        pci_pio_base=0x50000000,
+        pci_mem_base=0x400000000,
+        int_policy="ARM_PCI_INT_DEV", int_base=100, int_count=4)
+
+    def _on_chip_devices(self):
+        return super(VExpress_GEM5_Foundation, self)._on_chip_devices() + [
+                self.gic
+            ]
+
+    def setupBootLoader(self, cur_sys, loc, boot_loader=None):
+        if boot_loader is None:
+            boot_loader = [ loc('boot_v2.arm64') ]
+        super(VExpress_GEM5_Foundation, self).setupBootLoader(
+                cur_sys, boot_loader)