X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Farm%2FRealView.py;h=81d1f0755db4044feb05dfc542e2dfd395625533;hb=75e7f18e80351e12e1b828b6e077f3ec1d5ace1b;hp=68a69d3ff6577d7425cabd8e4c862899dc3fa5c4;hpb=73fdc2eb57dded37c2e0d93c1cdb179d1faa6679;p=gem5.git diff --git a/src/dev/arm/RealView.py b/src/dev/arm/RealView.py index 68a69d3ff..81d1f0755 100644 --- a/src/dev/arm/RealView.py +++ b/src/dev/arm/RealView.py @@ -53,6 +53,7 @@ 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 @@ -61,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 @@ -85,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") @@ -94,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): @@ -160,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)) @@ -209,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) + @@ -242,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) @@ -286,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) @@ -320,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): @@ -369,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 @@ -391,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 @@ -413,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'] @@ -446,7 +461,7 @@ class PL031(AmbaIntDevice): 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)) @@ -464,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)) @@ -526,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))) @@ -546,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" @@ -570,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) @@ -614,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): + def setupBootLoader(self, cur_sys, boot_loader, dtb_addr, load_offset): cur_sys.workload.boot_loader = boot_loader - cur_sys.workload.atags_addr = atags_addr 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 @@ -634,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') ] @@ -665,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): @@ -685,33 +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) sys_counter = SystemCounter() - 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()) + 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) @@ -839,10 +946,11 @@ Memory map: 0x00000000-0x03ffffff: Boot memory (CS0) 0x04000000-0x07ffffff: Reserved 0x08000000-0x0bffffff: NOR FLASH0 (CS0 alias) - 0x0c000000-0x0fffffff: Reserved (Off-chip, CS4) + 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) @@ -882,6 +990,8 @@ Memory map: 0x2d000000-0x2d00ffff: GPU (reserved) + 0x2e000000-0x2e007fff: Non-trusted SRAM + 0x2f000000-0x2fffffff: PCI IO space 0x30000000-0x3fffffff: PCI config space @@ -948,22 +1058,27 @@ Interrupts: 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 ### # Trusted Watchdog, SP805 - trusted_watchdog = Sp805(pio_addr=0x2a490000, int_num=56) + trusted_watchdog = Sp805(pio_addr=0x2a490000, interrupt=ArmSPI(num=56)) sys_counter = SystemCounter() - 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)) + 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, @@ -974,7 +1089,7 @@ Interrupts: int_phys=ArmSPI(num=58), int_virt=ArmSPI(num=134)) ]) - system_watchdog = Sp805(pio_addr=0x2b060000, int_num=130) + system_watchdog = Sp805(pio_addr=0x2b060000, interrupt=ArmSPI(num=130)) def _on_chip_devices(self): return [ @@ -987,6 +1102,7 @@ Interrupts: memories = [ self.bootmem, self.trusted_sram, + self.non_trusted_sram, self.flash0, ] return memories @@ -997,27 +1113,36 @@ Interrupts: clock24MHz = SrcClockDomain(clock="24MHz") uart = [ - Pl011(pio_addr=0x1c090000, int_num=37), - Pl011(pio_addr=0x1c0a0000, int_num=38, device=Terminal()), - Pl011(pio_addr=0x1c0b0000, int_num=39, device=Terminal()), - Pl011(pio_addr=0x1c0c0000, int_num=40, device=Terminal()) + 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)), @@ -1025,6 +1150,10 @@ 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, @@ -1034,12 +1163,18 @@ Interrupts: 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): super(VExpress_GEM5_Base, self).__init__(**kwargs) self.clock32KHz.voltage_domain = self.io_voltage @@ -1059,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'): @@ -1075,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( @@ -1089,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)) @@ -1101,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): @@ -1125,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() + [ @@ -1153,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)