1 # Copyright (c) 2009-2020 ARM Limited
4 # The license below extends only to copyright in the software and shall
5 # not be construed as granting a license to any other intellectual
6 # property including but not limited to intellectual property relating
7 # to a hardware implementation of the functionality of the software
8 # licensed hereunder. You may use the software subject to the license
9 # terms below provided that you ensure that this notice is replicated
10 # unmodified and in its entirety in all distributions of the software,
11 # modified or unmodified, in source code or in binary form.
13 # Copyright (c) 2006-2007 The Regents of The University of Michigan
14 # All rights reserved.
16 # Redistribution and use in source and binary forms, with or without
17 # modification, are permitted provided that the following conditions are
18 # met: redistributions of source code must retain the above copyright
19 # notice, this list of conditions and the following disclaimer;
20 # redistributions in binary form must reproduce the above copyright
21 # notice, this list of conditions and the following disclaimer in the
22 # documentation and/or other materials provided with the distribution;
23 # neither the name of the copyright holders nor the names of its
24 # contributors may be used to endorse or promote products derived from
25 # this software without specific prior written permission.
27 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 from m5
.defines
import buildEnv
40 from m5
.params
import *
41 from m5
.proxy
import *
42 from m5
.util
.fdthelper
import *
43 from m5
.objects
.ClockDomain
import ClockDomain
, SrcClockDomain
44 from m5
.objects
.VoltageDomain
import VoltageDomain
45 from m5
.objects
.Device
import \
46 BasicPioDevice
, PioDevice
, IsaFake
, BadAddr
, DmaDevice
47 from m5
.objects
.PciHost
import *
48 from m5
.objects
.Ethernet
import NSGigE
, IGbE_igb
, IGbE_e1000
49 from m5
.objects
.Ide
import *
50 from m5
.objects
.Platform
import Platform
51 from m5
.objects
.Terminal
import Terminal
52 from m5
.objects
.Uart
import Uart
53 from m5
.objects
.SimpleMemory
import SimpleMemory
54 from m5
.objects
.Gic
import *
55 from m5
.objects
.EnergyCtrl
import EnergyCtrl
56 from m5
.objects
.ClockedObject
import ClockedObject
57 from m5
.objects
.SubSystem
import SubSystem
58 from m5
.objects
.Graphics
import ImageFormat
59 from m5
.objects
.ClockedObject
import ClockedObject
60 from m5
.objects
.PS2
import *
61 from m5
.objects
.VirtIOMMIO
import MmioVirtIO
62 from m5
.objects
.Display
import Display
, Display1080p
63 from m5
.objects
.SMMUv3
import SMMUv3
65 # Platforms with KVM support should generally use in-kernel GIC
66 # emulation. Use a GIC model that automatically switches between
67 # gem5's GIC model and KVM's GIC model if KVM is available.
69 from m5
.objects
.KvmGic
import MuxingKvmGic
70 kvm_gicv2_class
= MuxingKvmGic
72 # KVM support wasn't compiled into gem5. Fallback to a
74 kvm_gicv2_class
= Gic400
77 class AmbaPioDevice(BasicPioDevice
):
78 type = 'AmbaPioDevice'
80 cxx_header
= "dev/arm/amba_device.hh"
81 amba_id
= Param
.UInt32("ID of AMBA device for kernel detection")
83 class AmbaIntDevice(AmbaPioDevice
):
84 type = 'AmbaIntDevice'
86 cxx_header
= "dev/arm/amba_device.hh"
87 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
88 int_num
= Param
.UInt32("Interrupt number that connects to GIC")
89 int_delay
= Param
.Latency("100ns",
90 "Time between action and interrupt generation by device")
92 class AmbaDmaDevice(DmaDevice
):
93 type = 'AmbaDmaDevice'
95 cxx_header
= "dev/arm/amba_device.hh"
96 pio_addr
= Param
.Addr("Address for AMBA slave interface")
97 pio_latency
= Param
.Latency("10ns", "Time between action and write/read result by AMBA DMA Device")
98 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
99 int_num
= Param
.UInt32("Interrupt number that connects to GIC")
100 amba_id
= Param
.UInt32("ID of AMBA device for kernel detection")
102 class A9SCU(BasicPioDevice
):
104 cxx_header
= "dev/arm/a9scu.hh"
106 class ArmPciIntRouting(Enum
): vals
= [
107 'ARM_PCI_INT_STATIC',
112 class GenericArmPciHost(GenericPciHost
):
113 type = 'GenericArmPciHost'
114 cxx_header
= "dev/arm/pci_host.hh"
116 int_policy
= Param
.ArmPciIntRouting("PCI interrupt routing policy")
117 int_base
= Param
.Unsigned("PCI interrupt base")
118 int_count
= Param
.Unsigned("Maximum number of interrupts used by this host")
120 # This python parameter can be used in configuration scripts to turn
121 # on/off the fdt dma-coherent flag when doing dtb autogeneration
124 def generateDeviceTree(self
, state
):
125 local_state
= FdtState(
126 addr_cells
=3, size_cells
=2,
127 cpu_cells
=1, interrupt_cells
=1)
129 node
= FdtNode("pci")
131 if int(self
.conf_device_bits
) == 8:
132 node
.appendCompatible("pci-host-cam-generic")
133 elif int(self
.conf_device_bits
) == 12:
134 node
.appendCompatible("pci-host-ecam-generic")
136 m5
.fatal("No compatibility string for the set conf_device_width")
138 node
.append(FdtPropertyStrings("device_type", ["pci"]))
140 # Cell sizes of child nodes/peripherals
141 node
.append(local_state
.addrCellsProperty())
142 node
.append(local_state
.sizeCellsProperty())
143 node
.append(local_state
.interruptCellsProperty())
144 # PCI address for CPU
145 node
.append(FdtPropertyWords("reg",
146 state
.addrCells(self
.conf_base
) +
147 state
.sizeCells(self
.conf_size
) ))
150 # For now some of this is hard coded, because the PCI module does not
151 # have a proper full understanding of the memory map, but adapting the
152 # PCI module is beyond the scope of what I'm trying to do here.
153 # Values are taken from the VExpress_GEM5_V1 platform.
156 ranges
+= self
.pciFdtAddr(space
=1, addr
=0)
157 ranges
+= state
.addrCells(self
.pci_pio_base
)
158 ranges
+= local_state
.sizeCells(0x10000) # Fixed size
160 # AXI memory address range
161 ranges
+= self
.pciFdtAddr(space
=2, addr
=0)
162 ranges
+= state
.addrCells(0x40000000) # Fixed offset
163 ranges
+= local_state
.sizeCells(0x40000000) # Fixed size
164 node
.append(FdtPropertyWords("ranges", ranges
))
166 if str(self
.int_policy
) == 'ARM_PCI_INT_DEV':
167 gic
= self
._parent
.unproxy(self
).gic
168 int_phandle
= state
.phandle(gic
)
172 # child interrupt specifier
173 child_interrupt
= local_state
.interruptCells(0x0)
175 # parent unit address
176 parent_addr
= gic
._state
.addrCells(0x0)
178 for i
in range(int(self
.int_count
)):
179 parent_interrupt
= gic
.interruptCells(0,
180 int(self
.int_base
) - 32 + i
, 1)
182 interrupts
+= self
.pciFdtAddr(device
=i
, addr
=0) + \
183 child_interrupt
+ [int_phandle
] + parent_addr
+ \
186 node
.append(FdtPropertyWords("interrupt-map", interrupts
))
188 int_count
= int(self
.int_count
)
189 if int_count
& (int_count
- 1):
190 fatal("PCI interrupt count should be power of 2")
192 intmask
= self
.pciFdtAddr(device
=int_count
- 1, addr
=0) + [0x0]
193 node
.append(FdtPropertyWords("interrupt-map-mask", intmask
))
195 m5
.fatal("Unsupported PCI interrupt policy " +
196 "for Device Tree generation")
198 if self
._dma
_coherent
:
199 node
.append(FdtProperty("dma-coherent"))
203 class RealViewCtrl(BasicPioDevice
):
204 type = 'RealViewCtrl'
205 cxx_header
= "dev/arm/rv_ctrl.hh"
206 proc_id0
= Param
.UInt32(0x0C000000, "Processor ID, SYS_PROCID")
207 proc_id1
= Param
.UInt32(0x0C000222, "Processor ID, SYS_PROCID1")
208 idreg
= Param
.UInt32(0x00000000, "ID Register, SYS_ID")
210 def generateDeviceTree(self
, state
):
211 node
= FdtNode("sysreg@%x" % long(self
.pio_addr
))
212 node
.appendCompatible("arm,vexpress-sysreg")
213 node
.append(FdtPropertyWords("reg",
214 state
.addrCells(self
.pio_addr
) +
215 state
.sizeCells(0x1000) ))
216 node
.append(FdtProperty("gpio-controller"))
217 node
.append(FdtPropertyWords("#gpio-cells", [2]))
218 node
.appendPhandle(self
)
222 class RealViewOsc(ClockDomain
):
224 cxx_header
= "dev/arm/rv_ctrl.hh"
226 parent
= Param
.RealViewCtrl(Parent
.any
, "RealView controller")
228 # TODO: We currently don't have the notion of a clock source,
229 # which means we have to associate oscillators with a voltage
231 voltage_domain
= Param
.VoltageDomain(Parent
.voltage_domain
,
234 # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
235 # the individual core/logic tile reference manuals for details
236 # about the site/position/dcc/device allocation.
237 site
= Param
.UInt8("Board Site")
238 position
= Param
.UInt8("Position in device stack")
239 dcc
= Param
.UInt8("Daughterboard Configuration Controller")
240 device
= Param
.UInt8("Device ID")
242 freq
= Param
.Clock("Default frequency")
244 def generateDeviceTree(self
, state
):
245 phandle
= state
.phandle(self
)
246 node
= FdtNode("osc@" + format(long(phandle
), 'x'))
247 node
.appendCompatible("arm,vexpress-osc")
248 node
.append(FdtPropertyWords("arm,vexpress-sysreg,func",
249 [0x1, int(self
.device
)]))
250 node
.append(FdtPropertyWords("#clock-cells", [0]))
251 freq
= int(1.0/self
.freq
.value
) # Values are stored as a clock period
252 node
.append(FdtPropertyWords("freq-range", [freq
, freq
]))
253 node
.append(FdtPropertyStrings("clock-output-names",
254 ["oscclk" + str(phandle
)]))
255 node
.appendPhandle(self
)
258 class RealViewTemperatureSensor(SimObject
):
259 type = 'RealViewTemperatureSensor'
260 cxx_header
= "dev/arm/rv_ctrl.hh"
262 parent
= Param
.RealViewCtrl(Parent
.any
, "RealView controller")
264 system
= Param
.System(Parent
.any
, "system")
266 # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
267 # the individual core/logic tile reference manuals for details
268 # about the site/position/dcc/device allocation.
269 site
= Param
.UInt8("Board Site")
270 position
= Param
.UInt8("Position in device stack")
271 dcc
= Param
.UInt8("Daughterboard Configuration Controller")
272 device
= Param
.UInt8("Device ID")
274 class VExpressMCC(SubSystem
):
275 """ARM V2M-P1 Motherboard Configuration Controller
277 This subsystem describes a subset of the devices that sit behind the
278 motherboard configuration controller on the the ARM Motherboard
279 Express (V2M-P1) motherboard. See ARM DUI 0447J for details.
282 class Osc(RealViewOsc
):
283 site
, position
, dcc
= (0, 0, 0)
285 class Temperature(RealViewTemperatureSensor
):
286 site
, position
, dcc
= (0, 0, 0)
288 osc_mcc
= Osc(device
=0, freq
="50MHz")
289 osc_clcd
= Osc(device
=1, freq
="23.75MHz")
290 osc_peripheral
= Osc(device
=2, freq
="24MHz")
291 osc_system_bus
= Osc(device
=4, freq
="24MHz")
293 # See Table 4.19 in ARM DUI 0447J (Motherboard Express uATX TRM).
294 temp_crtl
= Temperature(device
=0)
296 def generateDeviceTree(self
, state
):
297 node
= FdtNode("mcc")
298 node
.appendCompatible("arm,vexpress,config-bus")
299 node
.append(FdtPropertyWords("arm,vexpress,site", [0]))
301 for obj
in self
._children
.values():
302 if issubclass(type(obj
), SimObject
):
303 node
.append(obj
.generateDeviceTree(state
))
305 io_phandle
= state
.phandle(self
.osc_mcc
.parent
.unproxy(self
))
306 node
.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle
))
310 class CoreTile2A15DCC(SubSystem
):
311 """ARM CoreTile Express A15x2 Daughterboard Configuration Controller
313 This subsystem describes a subset of the devices that sit behind the
314 daughterboard configuration controller on a CoreTile Express A15x2. See
315 ARM DUI 0604E for details.
318 class Osc(RealViewOsc
):
319 site
, position
, dcc
= (1, 0, 0)
321 # See Table 2.8 in ARM DUI 0604E (CoreTile Express A15x2 TRM)
322 osc_cpu
= Osc(device
=0, freq
="60MHz")
323 osc_hsbm
= Osc(device
=4, freq
="40MHz")
324 osc_pxl
= Osc(device
=5, freq
="23.75MHz")
325 osc_smb
= Osc(device
=6, freq
="50MHz")
326 osc_sys
= Osc(device
=7, freq
="60MHz")
327 osc_ddr
= Osc(device
=8, freq
="40MHz")
329 def generateDeviceTree(self
, state
):
330 node
= FdtNode("dcc")
331 node
.appendCompatible("arm,vexpress,config-bus")
333 for obj
in self
._children
.values():
334 if isinstance(obj
, SimObject
):
335 node
.append(obj
.generateDeviceTree(state
))
337 io_phandle
= state
.phandle(self
.osc_cpu
.parent
.unproxy(self
))
338 node
.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle
))
342 class AmbaFake(AmbaPioDevice
):
344 cxx_header
= "dev/arm/amba_fake.hh"
345 ignore_access
= Param
.Bool(False, "Ignore reads/writes to this device, (e.g. IsaFake + AMBA)")
348 # Simple fixed-rate clock source. Intended to be instantiated in Platform
349 # instances for definition of clock bindings on DTB auto-generation
350 class FixedClock(SrcClockDomain
):
351 # Keep track of the number of FixedClock instances in the system
352 # to provide unique names
355 def generateDeviceTree(self
, state
):
356 if len(self
.clock
) > 1:
357 fatal('FixedClock configured with multiple frequencies')
358 node
= FdtNode('clock{}'.format(FixedClock
._index
))
359 node
.appendCompatible('fixed-clock')
360 node
.append(FdtPropertyWords('#clock-cells', 0))
361 node
.append(FdtPropertyWords('clock-frequency',
362 self
.clock
[0].frequency
))
363 node
.appendPhandle(self
)
364 FixedClock
._index
+= 1
370 cxx_header
= "dev/arm/pl011.hh"
371 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
372 int_num
= Param
.UInt32("Interrupt number that connects to GIC")
373 end_on_eot
= Param
.Bool(False, "End the simulation when a EOT is received on the UART")
374 int_delay
= Param
.Latency("100ns", "Time between action and interrupt generation by UART")
376 def generateDeviceTree(self
, state
):
377 node
= self
.generateBasicPioDeviceNode(state
, 'uart', self
.pio_addr
,
378 0x1000, [int(self
.int_num
)])
379 node
.appendCompatible(["arm,pl011", "arm,primecell"])
381 # Hardcoded reference to the realview platform clocks, because the
382 # clk_domain can only store one clock (i.e. it is not a VectorParam)
383 realview
= self
._parent
.unproxy(self
)
384 node
.append(FdtPropertyWords("clocks",
385 [state
.phandle(realview
.mcc
.osc_peripheral
),
386 state
.phandle(realview
.dcc
.osc_smb
)]))
387 node
.append(FdtPropertyStrings("clock-names", ["uartclk", "apb_pclk"]))
390 class Sp804(AmbaPioDevice
):
392 cxx_header
= "dev/arm/timer_sp804.hh"
393 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
394 int_num0
= Param
.UInt32("Interrupt number that connects to GIC")
395 clock0
= Param
.Clock('1MHz', "Clock speed of the input")
396 int_num1
= Param
.UInt32("Interrupt number that connects to GIC")
397 clock1
= Param
.Clock('1MHz', "Clock speed of the input")
400 class Sp805(AmbaIntDevice
):
402 Arm Watchdog Module (SP805)
404 Arm Watchdog Module (SP805) - Technical Reference Manual - rev. r1p0
405 Doc. ID: ARM DDI 0270B
409 cxx_header
= 'dev/arm/watchdog_sp805.hh'
413 def generateDeviceTree(self
, state
):
414 node
= self
.generateBasicPioDeviceNode(state
, 'watchdog',
415 self
.pio_addr
, 0x1000, [int(self
.int_num
)])
416 node
.appendCompatible(['arm,sp805', 'arm,primecell'])
417 clocks
= [state
.phandle(self
.clk_domain
.unproxy(self
))]
418 clock_names
= ['wdogclk']
419 platform
= self
._parent
.unproxy(self
)
420 if self
in platform
._off
_chip
_devices
():
421 clocks
.append(state
.phandle(platform
.dcc
.osc_smb
))
422 clock_names
.append('apb_pclk')
423 node
.append(FdtPropertyWords('clocks', clocks
))
424 node
.append(FdtPropertyStrings('clock-names', clock_names
))
428 class A9GlobalTimer(BasicPioDevice
):
429 type = 'A9GlobalTimer'
430 cxx_header
= "dev/arm/timer_a9global.hh"
431 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
432 int_num
= Param
.UInt32("Interrrupt number that connects to GIC")
434 class CpuLocalTimer(BasicPioDevice
):
435 type = 'CpuLocalTimer'
436 cxx_header
= "dev/arm/timer_cpulocal.hh"
437 int_timer
= Param
.ArmPPI("Interrrupt used per-cpu to GIC")
438 int_watchdog
= Param
.ArmPPI("Interrupt for per-cpu watchdog to GIC")
440 class GenericTimer(ClockedObject
):
441 type = 'GenericTimer'
442 cxx_header
= "dev/arm/generic_timer.hh"
443 system
= Param
.ArmSystem(Parent
.any
, "system")
444 int_phys_s
= Param
.ArmPPI("Physical (S) timer interrupt")
445 int_phys_ns
= Param
.ArmPPI("Physical (NS) timer interrupt")
446 int_virt
= Param
.ArmPPI("Virtual timer interrupt")
447 int_hyp
= Param
.ArmPPI("Hypervisor timer interrupt")
449 freqs
= VectorParam
.UInt32([0x01800000], "Frequencies available for the "
450 "system counter (in Hz). First element is the base frequency, "
451 "following are alternative lower ones which must be exact divisors")
453 def generateDeviceTree(self
, state
):
454 node
= FdtNode("timer")
456 node
.appendCompatible(["arm,cortex-a15-timer",
459 node
.append(FdtPropertyWords("interrupts", [
460 1, int(self
.int_phys_s
.num
) - 16, 0xf08,
461 1, int(self
.int_phys_ns
.num
) - 16, 0xf08,
462 1, int(self
.int_virt
.num
) - 16, 0xf08,
463 1, int(self
.int_hyp
.num
) - 16, 0xf08,
465 clock
= state
.phandle(self
.clk_domain
.unproxy(self
))
466 node
.append(FdtPropertyWords("clocks", clock
))
470 class GenericTimerMem(PioDevice
):
471 type = 'GenericTimerMem'
472 cxx_header
= "dev/arm/generic_timer.hh"
474 base
= Param
.Addr(0, "Base address")
476 int_phys
= Param
.ArmSPI("Physical Interrupt")
477 int_virt
= Param
.ArmSPI("Virtual Interrupt")
479 freqs
= VectorParam
.UInt32([0x01800000], "Frequencies available for the "
480 "system counter (in Hz). First element is the base frequency, "
481 "following are alternative lower ones which must be exact divisors")
483 class PL031(AmbaIntDevice
):
485 cxx_header
= "dev/arm/rtc_pl031.hh"
486 time
= Param
.Time('01/01/2009', "System time to use ('Now' for actual time)")
489 def generateDeviceTree(self
, state
):
490 node
= self
.generateBasicPioDeviceNode(state
, 'rtc', self
.pio_addr
,
491 0x1000, [int(self
.int_num
)])
493 node
.appendCompatible(["arm,pl031", "arm,primecell"])
494 clock
= state
.phandle(self
.clk_domain
.unproxy(self
))
495 node
.append(FdtPropertyWords("clocks", clock
))
496 node
.append(FdtPropertyStrings("clock-names", ["apb_pclk"]))
500 class Pl050(AmbaIntDevice
):
502 cxx_header
= "dev/arm/kmi.hh"
505 ps2
= Param
.PS2Device("PS/2 device")
507 def generateDeviceTree(self
, state
):
508 node
= self
.generateBasicPioDeviceNode(state
, 'kmi', self
.pio_addr
,
509 0x1000, [int(self
.int_num
)])
511 node
.appendCompatible(["arm,pl050", "arm,primecell"])
512 clock
= state
.phandle(self
.clk_domain
.unproxy(self
))
513 node
.append(FdtPropertyWords("clocks", clock
))
517 class Pl111(AmbaDmaDevice
):
519 cxx_header
= "dev/arm/pl111.hh"
520 pixel_clock
= Param
.Clock('24MHz', "Pixel clock")
521 vnc
= Param
.VncInput(Parent
.any
, "Vnc server for remote frame buffer display")
523 enable_capture
= Param
.Bool(True, "capture frame to system.framebuffer.bmp")
525 class HDLcd(AmbaDmaDevice
):
527 cxx_header
= "dev/arm/hdlcd.hh"
528 vnc
= Param
.VncInput(Parent
.any
, "Vnc server for remote frame buffer "
531 workaround_swap_rb
= Param
.Bool(False, "Workaround incorrect color "
532 "selector order in some kernels")
533 workaround_dma_line_count
= Param
.Bool(True, "Workaround incorrect "
534 "DMA line count (off by 1)")
535 enable_capture
= Param
.Bool(True, "capture frame to "
536 "system.framebuffer.{extension}")
537 frame_format
= Param
.ImageFormat("Auto",
538 "image format of the captured frame")
540 pixel_buffer_size
= Param
.MemorySize32("2kB", "Size of address range")
542 pxl_clk
= Param
.ClockDomain("Pixel clock source")
543 pixel_chunk
= Param
.Unsigned(32, "Number of pixels to handle in one batch")
544 virt_refresh_rate
= Param
.Frequency("20Hz", "Frame refresh rate "
548 encoder
= Param
.Display(Display1080p(), "Display encoder")
550 def endpointPhandle(self
):
551 return "hdlcd_endpoint"
553 def generateDeviceTree(self
, state
):
554 endpoint_node
= FdtNode("endpoint")
555 endpoint_node
.appendPhandle(self
.endpointPhandle())
557 for encoder_node
in self
.encoder
.generateDeviceTree(state
):
558 encoder_endpoint
= self
.encoder
.endpointNode()
561 endpoint_node
.append(FdtPropertyWords("remote-endpoint",
562 [ state
.phandle(self
.encoder
.endpointPhandle()) ]))
563 encoder_endpoint
.append(FdtPropertyWords("remote-endpoint",
564 [ state
.phandle(self
.endpointPhandle()) ]))
568 port_node
= FdtNode("port")
569 port_node
.append(endpoint_node
)
571 # Interrupt number is hardcoded; it is not a property of this class
572 node
= self
.generateBasicPioDeviceNode(state
, 'hdlcd',
573 self
.pio_addr
, 0x1000, [63])
575 node
.appendCompatible(["arm,hdlcd"])
576 node
.append(FdtPropertyWords("clocks", state
.phandle(self
.pxl_clk
)))
577 node
.append(FdtPropertyStrings("clock-names", ["pxlclk"]))
579 # This driver is disabled by default since the required DT nodes
580 # haven't been standardized yet. To use it, override this status to
581 # "ok" and add the display configuration nodes required by the driver.
582 # See the driver for more information.
583 node
.append(FdtPropertyStrings("status", [ self
._status
]))
585 self
.addIommuProperty(state
, node
)
587 node
.append(port_node
)
591 class RealView(Platform
):
593 cxx_header
= "dev/arm/realview.hh"
594 system
= Param
.System(Parent
.any
, "system")
595 _mem_regions
= [ AddrRange(0, size
='256MB') ]
598 def _on_chip_devices(self
):
601 def _off_chip_devices(self
):
604 def _on_chip_memory(self
):
607 def _off_chip_memory(self
):
610 _off_chip_ranges
= []
612 def _attach_memory(self
, mem
, bus
, mem_ports
=None):
613 if hasattr(mem
, "port"):
614 if mem_ports
is None:
615 mem
.port
= bus
.master
617 mem_ports
.append(mem
.port
)
619 def _attach_device(self
, device
, bus
, dma_ports
=None):
620 if hasattr(device
, "pio"):
621 device
.pio
= bus
.master
622 if hasattr(device
, "dma"):
623 if dma_ports
is None:
624 device
.dma
= bus
.slave
626 dma_ports
.append(device
.dma
)
628 def _attach_io(self
, devices
, *args
, **kwargs
):
630 self
._attach
_device
(d
, *args
, **kwargs
)
632 def _attach_mem(self
, memories
, *args
, **kwargs
):
634 self
._attach
_memory
(mem
, *args
, **kwargs
)
636 def _attach_clk(self
, devices
, clkdomain
):
638 if hasattr(d
, "clk_domain"):
639 d
.clk_domain
= clkdomain
641 def attachPciDevices(self
):
644 def enableMSIX(self
):
647 def onChipIOClkDomain(self
, clkdomain
):
648 self
._attach
_clk
(self
._on
_chip
_devices
(), clkdomain
)
650 def offChipIOClkDomain(self
, clkdomain
):
651 self
._attach
_clk
(self
._off
_chip
_devices
(), clkdomain
)
653 def attachOnChipIO(self
, bus
, bridge
=None, dma_ports
=None, mem_ports
=None):
654 self
._attach
_mem
(self
._on
_chip
_memory
(), bus
, mem_ports
)
655 self
._attach
_io
(self
._on
_chip
_devices
(), bus
, dma_ports
)
657 bridge
.ranges
= self
._off
_chip
_ranges
659 def attachIO(self
, *args
, **kwargs
):
660 self
._attach
_mem
(self
._off
_chip
_memory
(), *args
, **kwargs
)
661 self
._attach
_io
(self
._off
_chip
_devices
(), *args
, **kwargs
)
663 def setupBootLoader(self
, cur_sys
, boot_loader
, atags_addr
, load_offset
):
664 cur_sys
.boot_loader
= boot_loader
665 cur_sys
.atags_addr
= atags_addr
666 cur_sys
.load_offset
= load_offset
668 def generateDeviceTree(self
, state
):
669 node
= FdtNode("/") # Things in this module need to end up in the root
670 node
.append(FdtPropertyWords("interrupt-parent",
671 state
.phandle(self
.gic
)))
673 for subnode
in self
.recurseDeviceTree(state
):
678 def annotateCpuDeviceNode(self
, cpu
, state
):
679 cpu
.append(FdtPropertyStrings("enable-method", "spin-table"))
680 cpu
.append(FdtPropertyWords("cpu-release-addr", \
681 state
.addrCells(0x8000fff8)))
683 class VExpress_EMM(RealView
):
684 _mem_regions
= [ AddrRange('2GB', size
='2GB') ]
686 # Ranges based on excluding what is part of on-chip I/O (gic,
688 _off_chip_ranges
= [AddrRange(0x2F000000, size
='16MB'),
689 AddrRange(0x30000000, size
='256MB'),
690 AddrRange(0x40000000, size
='512MB'),
691 AddrRange(0x18000000, size
='64MB'),
692 AddrRange(0x1C000000, size
='64MB')]
694 # Platform control device (off-chip)
695 realview_io
= RealViewCtrl(proc_id0
=0x14000000, proc_id1
=0x14000000,
696 idreg
=0x02250000, pio_addr
=0x1C010000)
699 dcc
= CoreTile2A15DCC()
701 ### On-chip devices ###
702 gic
= Gic400(dist_addr
=0x2C001000, cpu_addr
=0x2C002000)
703 vgic
= VGic(vcpu_addr
=0x2c006000, hv_addr
=0x2c004000, maint_int
=25)
705 local_cpu_timer
= CpuLocalTimer(int_timer
=ArmPPI(num
=29),
706 int_watchdog
=ArmPPI(num
=30),
709 hdlcd
= HDLcd(pxl_clk
=dcc
.osc_pxl
,
710 pio_addr
=0x2b000000, int_num
=117,
711 workaround_swap_rb
=True)
713 def _on_chip_devices(self
):
718 if hasattr(self
, "gicv2m"):
719 devices
.append(self
.gicv2m
)
720 devices
.append(self
.hdlcd
)
723 def _on_chip_memory(self
):
729 ### Off-chip devices ###
730 uart
= Pl011(pio_addr
=0x1c090000, int_num
=37)
731 pci_host
= GenericPciHost(
732 conf_base
=0x30000000, conf_size
='256MB', conf_device_bits
=16,
735 generic_timer
= GenericTimer(int_phys_s
=ArmPPI(num
=29),
736 int_phys_ns
=ArmPPI(num
=30),
737 int_virt
=ArmPPI(num
=27),
738 int_hyp
=ArmPPI(num
=26))
740 timer0
= Sp804(int_num0
=34, int_num1
=34, pio_addr
=0x1C110000, clock0
='1MHz', clock1
='1MHz')
741 timer1
= Sp804(int_num0
=35, int_num1
=35, pio_addr
=0x1C120000, clock0
='1MHz', clock1
='1MHz')
742 clcd
= Pl111(pio_addr
=0x1c1f0000, int_num
=46)
743 kmi0
= Pl050(pio_addr
=0x1c060000, int_num
=44, ps2
=PS2Keyboard())
744 kmi1
= Pl050(pio_addr
=0x1c070000, int_num
=45, ps2
=PS2TouchKit())
745 cf_ctrl
= IdeController(disks
=[], pci_func
=0, pci_dev
=0, pci_bus
=2,
746 io_shift
= 2, ctrl_offset
= 2, Command
= 0x1,
747 BAR0
= 0x1C1A0000, BAR0Size
= '256B',
748 BAR1
= 0x1C1A0100, BAR1Size
= '4096B',
749 BAR0LegacyIO
= True, BAR1LegacyIO
= True)
751 bootmem
= SimpleMemory(range = AddrRange('64MB'),
752 conf_table_reported
= False)
753 vram
= SimpleMemory(range = AddrRange(0x18000000, size
='32MB'),
754 conf_table_reported
= False)
755 rtc
= PL031(pio_addr
=0x1C170000, int_num
=36)
757 l2x0_fake
= IsaFake(pio_addr
=0x2C100000, pio_size
=0xfff)
758 uart1_fake
= AmbaFake(pio_addr
=0x1C0A0000)
759 uart2_fake
= AmbaFake(pio_addr
=0x1C0B0000)
760 uart3_fake
= AmbaFake(pio_addr
=0x1C0C0000)
761 sp810_fake
= AmbaFake(pio_addr
=0x1C020000, ignore_access
=True)
762 watchdog_fake
= AmbaFake(pio_addr
=0x1C0F0000)
763 aaci_fake
= AmbaFake(pio_addr
=0x1C040000)
764 lan_fake
= IsaFake(pio_addr
=0x1A000000, pio_size
=0xffff)
765 usb_fake
= IsaFake(pio_addr
=0x1B000000, pio_size
=0x1ffff)
766 mmc_fake
= AmbaFake(pio_addr
=0x1c050000)
767 energy_ctrl
= EnergyCtrl(pio_addr
=0x1c080000)
769 def _off_chip_devices(self
):
794 # Try to attach the I/O if it exists
795 if hasattr(self
, "ide"):
796 devices
.append(self
.ide
)
797 if hasattr(self
, "ethernet"):
798 devices
.append(self
.ethernet
)
801 # Attach any PCI devices that are supported
802 def attachPciDevices(self
):
803 self
.ethernet
= IGbE_e1000(pci_bus
=0, pci_dev
=0, pci_func
=0,
804 InterruptLine
=1, InterruptPin
=1)
805 self
.ide
= IdeController(disks
= [], pci_bus
=0, pci_dev
=1, pci_func
=0,
806 InterruptLine
=2, InterruptPin
=2)
808 def enableMSIX(self
):
809 self
.gic
= Gic400(dist_addr
=0x2C001000, cpu_addr
=0x2C002000,
811 self
.gicv2m
= Gicv2m()
812 self
.gicv2m
.frames
= [Gicv2mFrame(spi_base
=256, spi_len
=64, addr
=0x2C1C0000)]
814 def setupBootLoader(self
, cur_sys
, loc
, boot_loader
=None):
815 if boot_loader
is None:
816 boot_loader
= loc('boot_emm.arm')
817 super(VExpress_EMM
, self
).setupBootLoader(
818 cur_sys
, boot_loader
, 0x8000000, 0x80000000)
820 class VExpress_EMM64(VExpress_EMM
):
821 # Three memory regions are specified totalling 512GB
822 _mem_regions
= [ AddrRange('2GB', size
='2GB'),
823 AddrRange('34GB', size
='30GB'),
824 AddrRange('512GB', size
='480GB') ]
825 pci_host
= GenericPciHost(
826 conf_base
=0x30000000, conf_size
='256MB', conf_device_bits
=12,
827 pci_pio_base
=0x2f000000)
829 def setupBootLoader(self
, cur_sys
, loc
, boot_loader
=None):
830 if boot_loader
is None:
831 boot_loader
= loc('boot_emm.arm64')
832 RealView
.setupBootLoader(self
, cur_sys
, boot_loader
,
833 0x8000000, 0x80000000)
835 class VExpress_GEM5_Base(RealView
):
837 The VExpress gem5 memory map is loosely based on a modified
838 Versatile Express RS1 memory map.
840 The gem5 platform has been designed to implement a subset of the
841 original Versatile Express RS1 memory map. Off-chip peripherals should,
842 when possible, adhere to the Versatile Express memory map. Non-PCI
843 off-chip devices that are gem5-specific should live in the CS5 memory
844 space to avoid conflicts with existing devices that we might want to
845 model in the future. Such devices should normally have interrupts in
846 the gem5-specific SPI range.
848 On-chip peripherals are loosely modeled after the ARM CoreTile Express
849 A15x2 memory and interrupt map. In particular, the GIC and
850 Generic Timer have the same interrupt lines and base addresses. Other
851 on-chip devices are gem5 specific.
853 Unlike the original Versatile Express RS2 extended platform, gem5 implements a
854 large contigious DRAM space, without aliases or holes, starting at the
855 2GiB boundary. This means that PCI memory is limited to 1GiB.
859 Technical Reference Manuals:
860 Arm Motherboard Express uATX (V2M-P1) - ARM DUI 0447J
861 Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
863 Official Linux device tree specifications:
864 V2M-P1 - arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
865 V2P-CA15 - arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
868 Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
869 Daughterboard (global)
870 Section 3.2.1 - Table 3-1 - Daughterboard memory map
872 Section 3.2.3 - Table 3-2 - Cortex-A15 MPCore on-chip peripheral
876 Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
877 Section 2.8.2 - Test chip interrupts
880 0x00000000-0x03ffffff: Boot memory (CS0)
881 0x04000000-0x07ffffff: Reserved
882 0x08000000-0x0bffffff: NOR FLASH0 (CS0 alias)
883 0x0c000000-0x0fffffff: Reserved (Off-chip, CS4)
884 0x10000000-0x13ffffff: gem5-specific peripherals (Off-chip, CS5)
885 0x10000000-0x1000ffff: gem5 energy controller
886 0x10010000-0x1001ffff: gem5 pseudo-ops
888 0x14000000-0x17ffffff: Reserved (Off-chip, PSRAM, CS1)
889 0x18000000-0x1bffffff: Reserved (Off-chip, Peripherals, CS2)
890 0x1c000000-0x1fffffff: Peripheral block 1 (Off-chip, CS3):
891 0x1c010000-0x1c01ffff: realview_io (VE system control regs.)
892 0x1c060000-0x1c06ffff: KMI0 (keyboard)
893 0x1c070000-0x1c07ffff: KMI1 (mouse)
894 0x1c090000-0x1c09ffff: UART0
895 0x1c0a0000-0x1c0affff: UART1 (reserved)
896 0x1c0b0000-0x1c0bffff: UART2 (reserved)
897 0x1c0c0000-0x1c0cffff: UART3 (reserved)
898 0x1c0f0000-0x1c0fffff: Watchdog (SP805)
899 0x1c130000-0x1c13ffff: VirtIO (gem5/FM extension)
900 0x1c140000-0x1c14ffff: VirtIO (gem5/FM extension)
901 0x1c170000-0x1c17ffff: RTC
903 0x20000000-0x3fffffff: On-chip peripherals:
904 0x2a490000-0x2a49ffff: Trusted Watchdog (SP805)
905 0x2b000000-0x2b00ffff: HDLCD
907 0x2b060000-0x2b060fff: System Watchdog (SP805)
909 0x2b400000-0x2b41ffff: SMMUv3
911 0x2c001000-0x2c001fff: GIC (distributor)
912 0x2c002000-0x2c003fff: GIC (CPU interface)
913 0x2c004000-0x2c005fff: vGIC (HV)
914 0x2c006000-0x2c007fff: vGIC (VCPU)
915 0x2c1c0000-0x2c1cffff: GICv2m MSI frame 0
917 0x2d000000-0x2d00ffff: GPU (reserved)
919 0x2f000000-0x2fffffff: PCI IO space
920 0x30000000-0x3fffffff: PCI config space
922 0x40000000-0x7fffffff: Ext. AXI: Used as PCI memory
927 0- 15: Software generated interrupts (SGIs)
928 16- 31: On-chip private peripherals (PPIs)
930 26 : generic_timer (hyp)
931 27 : generic_timer (virt)
932 28 : Reserved (Legacy FIQ)
933 29 : generic_timer (phys, sec)
934 30 : generic_timer (phys, non-sec)
935 31 : Reserved (Legacy IRQ)
936 32- 95: Mother board peripherals (SPIs)
937 32 : Watchdog (SP805)
938 33 : Reserved (IOFPGA SW int)
939 34-35: Reserved (SP804)
942 41-42: Reserved (PL180)
946 47 : Reserved (Ethernet)
948 56 : Trusted Watchdog (SP805)
949 95-255: On-chip interrupt sources (we use these for
950 gem5-specific devices, SPIs)
951 74 : VirtIO (gem5/FM extension)
952 75 : VirtIO (gem5/FM extension)
954 96- 98: GPU (reserved)
956 130 : System Watchdog (SP805)
957 256-319: MSI frame 0 (gem5-specific, SPIs)
962 # Everything above 2GiB is memory
963 _mem_regions
= [ AddrRange('2GB', size
='510GB') ]
967 AddrRange(0x0c000000, 0x20000000),
968 # External AXI interface (PCI)
969 AddrRange(0x2f000000, 0x80000000),
972 bootmem
= SimpleMemory(range=AddrRange(0, size
='64MB'),
973 conf_table_reported
=False)
976 flash0
= SimpleMemory(range=AddrRange(0x08000000, size
='64MB'),
977 conf_table_reported
=False)
980 trusted_sram
= SimpleMemory(range=AddrRange(0x04000000, size
='256kB'),
981 conf_table_reported
=False)
983 # Platform control device (off-chip)
984 realview_io
= RealViewCtrl(proc_id0
=0x14000000, proc_id1
=0x14000000,
985 idreg
=0x02250000, pio_addr
=0x1c010000)
987 dcc
= CoreTile2A15DCC()
989 ### On-chip devices ###
991 # Trusted Watchdog, SP805
992 trusted_watchdog
= Sp805(pio_addr
=0x2a490000, int_num
=56)
994 generic_timer
= GenericTimer(int_phys_s
=ArmPPI(num
=29),
995 int_phys_ns
=ArmPPI(num
=30),
996 int_virt
=ArmPPI(num
=27),
997 int_hyp
=ArmPPI(num
=26))
999 system_watchdog
= Sp805(pio_addr
=0x2b060000, int_num
=130)
1001 def _on_chip_devices(self
):
1004 self
.trusted_watchdog
,
1005 self
.system_watchdog
1008 def _on_chip_memory(self
):
1016 ### Off-chip devices ###
1017 io_voltage
= VoltageDomain(voltage
="3.3V")
1018 clock32KHz
= SrcClockDomain(clock
="32kHz")
1019 clock24MHz
= SrcClockDomain(clock
="24MHz")
1022 Pl011(pio_addr
=0x1c090000, int_num
=37),
1025 kmi0
= Pl050(pio_addr
=0x1c060000, int_num
=44, ps2
=PS2Keyboard())
1026 kmi1
= Pl050(pio_addr
=0x1c070000, int_num
=45, ps2
=PS2TouchKit())
1028 watchdog
= Sp805(pio_addr
=0x1c0f0000, int_num
=32)
1030 rtc
= PL031(pio_addr
=0x1c170000, int_num
=36)
1032 ### gem5-specific off-chip devices ###
1033 pci_host
= GenericArmPciHost(
1034 conf_base
=0x30000000, conf_size
='256MB', conf_device_bits
=12,
1035 pci_pio_base
=0x2f000000,
1036 int_policy
="ARM_PCI_INT_DEV", int_base
=100, int_count
=4)
1038 energy_ctrl
= EnergyCtrl(pio_addr
=0x10000000)
1041 MmioVirtIO(pio_addr
=0x1c130000, pio_size
=0x1000,
1042 interrupt
=ArmSPI(num
=74)),
1043 MmioVirtIO(pio_addr
=0x1c140000, pio_size
=0x1000,
1044 interrupt
=ArmSPI(num
=75)),
1047 def _off_chip_devices(self
):
1063 def __init__(self
, **kwargs
):
1064 super(VExpress_GEM5_Base
, self
).__init
__(**kwargs
)
1065 self
.clock32KHz
.voltage_domain
= self
.io_voltage
1066 self
.clock24MHz
.voltage_domain
= self
.io_voltage
1067 self
.system_watchdog
.clk_domain
= self
.dcc
.osc_sys
1068 self
.watchdog
.clk_domain
= self
.clock32KHz
1070 def attachPciDevice(self
, device
, *args
, **kwargs
):
1071 device
.host
= self
.pci_host
1072 self
._num
_pci
_dev
+= 1
1074 device
.pci_dev
= self
._num
_pci
_dev
1076 self
._attach
_device
(device
, *args
, **kwargs
)
1078 def attachSmmu(self
, devices
, bus
):
1080 Instantiate a single SMMU and attach a group of client devices to it.
1081 The devices' dma port is wired to the SMMU and the SMMU's dma port
1082 (master) is attached to the bus. In order to make it work, the list
1083 of clients shouldn't contain any device part of the _off_chip_devices
1084 or _on_chip_devices.
1085 This method should be called only once.
1088 devices (list): List of devices which will be using the SMMU
1089 bus (Bus): The bus downstream of the SMMU. Its slave port will
1090 receive memory requests from the SMMU, and its master
1091 port will forward accesses to the memory mapped devices
1093 if hasattr(self
, 'smmu'):
1094 m5
.fatal("A SMMU has already been instantiated\n")
1096 self
.smmu
= SMMUv3(reg_map
=AddrRange(0x2b400000, size
=0x00020000))
1100 self
._attach
_device
(dev
, bus
, dma_ports
)
1101 self
.smmu
.connect(dev
, bus
)
1103 def setupBootLoader(self
, cur_sys
, boot_loader
):
1104 super(VExpress_GEM5_Base
, self
).setupBootLoader(
1105 cur_sys
, boot_loader
, 0x8000000, 0x80000000)
1107 # Setup m5ops. It's technically not a part of the boot
1108 # loader, but this is the only place we can configure the
1110 cur_sys
.m5ops_base
= 0x10010000
1112 def generateDeviceTree(self
, state
):
1113 # Generate using standard RealView function
1114 dt
= list(super(VExpress_GEM5_Base
, self
).generateDeviceTree(state
))
1116 raise Exception("System returned too many DT nodes")
1119 node
.appendCompatible(["arm,vexpress"])
1120 node
.append(FdtPropertyStrings("model", ["V2P-CA15"]))
1121 node
.append(FdtPropertyWords("arm,hbi", [0x0]))
1122 node
.append(FdtPropertyWords("arm,vexpress,site", [0xf]))
1126 class VExpress_GEM5_V1_Base(VExpress_GEM5_Base
):
1127 gic
= kvm_gicv2_class(dist_addr
=0x2c001000, cpu_addr
=0x2c002000,
1129 vgic
= VGic(vcpu_addr
=0x2c006000, hv_addr
=0x2c004000, maint_int
=25)
1132 Gicv2mFrame(spi_base
=256, spi_len
=64, addr
=0x2c1c0000),
1135 def setupBootLoader(self
, cur_sys
, loc
, boot_loader
=None):
1136 if boot_loader
is None:
1137 boot_loader
= [ loc('boot.arm64'), loc('boot.arm') ]
1138 super(VExpress_GEM5_V1_Base
, self
).setupBootLoader(
1139 cur_sys
, boot_loader
)
1141 def _on_chip_devices(self
):
1142 return super(VExpress_GEM5_V1_Base
,self
)._on
_chip
_devices
() + [
1143 self
.gic
, self
.vgic
, self
.gicv2m
,
1146 class VExpress_GEM5_V1(VExpress_GEM5_V1_Base
):
1147 hdlcd
= HDLcd(pxl_clk
=VExpress_GEM5_V1_Base
.dcc
.osc_pxl
,
1148 pio_addr
=0x2b000000, int_num
=95)
1150 def _on_chip_devices(self
):
1151 return super(VExpress_GEM5_V1
,self
)._on
_chip
_devices
() + [
1155 class VExpress_GEM5_V2_Base(VExpress_GEM5_Base
):
1156 gic
= Gicv3(dist_addr
=0x2c000000, redist_addr
=0x2c010000,
1157 maint_int
=ArmPPI(num
=25),
1158 its
=Gicv3Its(pio_addr
=0x2e010000))
1160 # Limiting to 128 since it will otherwise overlap with PCI space
1163 def _on_chip_devices(self
):
1164 return super(VExpress_GEM5_V2_Base
,self
)._on
_chip
_devices
() + [
1165 self
.gic
, self
.gic
.its
1168 def setupBootLoader(self
, cur_sys
, loc
, boot_loader
=None):
1169 if boot_loader
is None:
1170 boot_loader
= [ loc('boot_v2.arm64') ]
1171 super(VExpress_GEM5_V2_Base
, self
).setupBootLoader(
1172 cur_sys
, boot_loader
)
1174 class VExpress_GEM5_V2(VExpress_GEM5_V2_Base
):
1175 hdlcd
= HDLcd(pxl_clk
=VExpress_GEM5_V2_Base
.dcc
.osc_pxl
,
1176 pio_addr
=0x2b000000, int_num
=95)
1178 def _on_chip_devices(self
):
1179 return super(VExpress_GEM5_V2
,self
)._on
_chip
_devices
() + [