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.
44 from m5
.defines
import buildEnv
45 from m5
.params
import *
46 from m5
.proxy
import *
47 from m5
.util
.fdthelper
import *
48 from m5
.objects
.ClockDomain
import ClockDomain
, SrcClockDomain
49 from m5
.objects
.VoltageDomain
import VoltageDomain
50 from m5
.objects
.Device
import \
51 BasicPioDevice
, PioDevice
, IsaFake
, BadAddr
, DmaDevice
52 from m5
.objects
.PciHost
import *
53 from m5
.objects
.Ethernet
import NSGigE
, IGbE_igb
, IGbE_e1000
54 from m5
.objects
.Ide
import *
55 from m5
.objects
.Platform
import Platform
56 from m5
.objects
.Terminal
import Terminal
57 from m5
.objects
.Uart
import Uart
58 from m5
.objects
.SimpleMemory
import SimpleMemory
59 from m5
.objects
.Gic
import *
60 from m5
.objects
.EnergyCtrl
import EnergyCtrl
61 from m5
.objects
.ClockedObject
import ClockedObject
62 from m5
.objects
.SubSystem
import SubSystem
63 from m5
.objects
.Graphics
import ImageFormat
64 from m5
.objects
.ClockedObject
import ClockedObject
65 from m5
.objects
.PS2
import *
66 from m5
.objects
.VirtIOMMIO
import MmioVirtIO
67 from m5
.objects
.Display
import Display
, Display1080p
68 from m5
.objects
.SMMUv3
import SMMUv3
70 # Platforms with KVM support should generally use in-kernel GIC
71 # emulation. Use a GIC model that automatically switches between
72 # gem5's GIC model and KVM's GIC model if KVM is available.
74 from m5
.objects
.KvmGic
import MuxingKvmGic
75 kvm_gicv2_class
= MuxingKvmGic
77 # KVM support wasn't compiled into gem5. Fallback to a
79 kvm_gicv2_class
= Gic400
82 class AmbaPioDevice(BasicPioDevice
):
83 type = 'AmbaPioDevice'
85 cxx_header
= "dev/arm/amba_device.hh"
86 amba_id
= Param
.UInt32("ID of AMBA device for kernel detection")
88 class AmbaIntDevice(AmbaPioDevice
):
89 type = 'AmbaIntDevice'
91 cxx_header
= "dev/arm/amba_device.hh"
92 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
93 int_num
= Param
.UInt32("Interrupt number that connects to GIC")
94 int_delay
= Param
.Latency("100ns",
95 "Time between action and interrupt generation by device")
97 class AmbaDmaDevice(DmaDevice
):
98 type = 'AmbaDmaDevice'
100 cxx_header
= "dev/arm/amba_device.hh"
101 pio_addr
= Param
.Addr("Address for AMBA slave interface")
102 pio_latency
= Param
.Latency("10ns", "Time between action and write/read result by AMBA DMA Device")
103 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
104 int_num
= Param
.UInt32("Interrupt number that connects to GIC")
105 amba_id
= Param
.UInt32("ID of AMBA device for kernel detection")
107 class A9SCU(BasicPioDevice
):
109 cxx_header
= "dev/arm/a9scu.hh"
111 class ArmPciIntRouting(Enum
): vals
= [
112 'ARM_PCI_INT_STATIC',
117 class GenericArmPciHost(GenericPciHost
):
118 type = 'GenericArmPciHost'
119 cxx_header
= "dev/arm/pci_host.hh"
121 int_policy
= Param
.ArmPciIntRouting("PCI interrupt routing policy")
122 int_base
= Param
.Unsigned("PCI interrupt base")
123 int_count
= Param
.Unsigned("Maximum number of interrupts used by this host")
125 # This python parameter can be used in configuration scripts to turn
126 # on/off the fdt dma-coherent flag when doing dtb autogeneration
129 def generateDeviceTree(self
, state
):
130 local_state
= FdtState(
131 addr_cells
=3, size_cells
=2,
132 cpu_cells
=1, interrupt_cells
=1)
134 node
= FdtNode("pci")
136 if int(self
.conf_device_bits
) == 8:
137 node
.appendCompatible("pci-host-cam-generic")
138 elif int(self
.conf_device_bits
) == 12:
139 node
.appendCompatible("pci-host-ecam-generic")
141 m5
.fatal("No compatibility string for the set conf_device_width")
143 node
.append(FdtPropertyStrings("device_type", ["pci"]))
145 # Cell sizes of child nodes/peripherals
146 node
.append(local_state
.addrCellsProperty())
147 node
.append(local_state
.sizeCellsProperty())
148 node
.append(local_state
.interruptCellsProperty())
149 # PCI address for CPU
150 node
.append(FdtPropertyWords("reg",
151 state
.addrCells(self
.conf_base
) +
152 state
.sizeCells(self
.conf_size
) ))
155 # For now some of this is hard coded, because the PCI module does not
156 # have a proper full understanding of the memory map, but adapting the
157 # PCI module is beyond the scope of what I'm trying to do here.
158 # Values are taken from the VExpress_GEM5_V1 platform.
161 ranges
+= self
.pciFdtAddr(space
=1, addr
=0)
162 ranges
+= state
.addrCells(self
.pci_pio_base
)
163 ranges
+= local_state
.sizeCells(0x10000) # Fixed size
165 # AXI memory address range
166 ranges
+= self
.pciFdtAddr(space
=2, addr
=0)
167 ranges
+= state
.addrCells(0x40000000) # Fixed offset
168 ranges
+= local_state
.sizeCells(0x40000000) # Fixed size
169 node
.append(FdtPropertyWords("ranges", ranges
))
171 if str(self
.int_policy
) == 'ARM_PCI_INT_DEV':
172 gic
= self
._parent
.unproxy(self
).gic
173 int_phandle
= state
.phandle(gic
)
177 # child interrupt specifier
178 child_interrupt
= local_state
.interruptCells(0x0)
180 # parent unit address
181 parent_addr
= gic
._state
.addrCells(0x0)
183 for i
in range(int(self
.int_count
)):
184 parent_interrupt
= gic
.interruptCells(0,
185 int(self
.int_base
) - 32 + i
, 1)
187 interrupts
+= self
.pciFdtAddr(device
=i
, addr
=0) + \
188 child_interrupt
+ [int_phandle
] + parent_addr
+ \
191 node
.append(FdtPropertyWords("interrupt-map", interrupts
))
193 int_count
= int(self
.int_count
)
194 if int_count
& (int_count
- 1):
195 fatal("PCI interrupt count should be power of 2")
197 intmask
= self
.pciFdtAddr(device
=int_count
- 1, addr
=0) + [0x0]
198 node
.append(FdtPropertyWords("interrupt-map-mask", intmask
))
200 m5
.fatal("Unsupported PCI interrupt policy " +
201 "for Device Tree generation")
203 if self
._dma
_coherent
:
204 node
.append(FdtProperty("dma-coherent"))
208 class RealViewCtrl(BasicPioDevice
):
209 type = 'RealViewCtrl'
210 cxx_header
= "dev/arm/rv_ctrl.hh"
211 proc_id0
= Param
.UInt32(0x0C000000, "Processor ID, SYS_PROCID")
212 proc_id1
= Param
.UInt32(0x0C000222, "Processor ID, SYS_PROCID1")
213 idreg
= Param
.UInt32(0x00000000, "ID Register, SYS_ID")
215 def generateDeviceTree(self
, state
):
216 node
= FdtNode("sysreg@%x" % long(self
.pio_addr
))
217 node
.appendCompatible("arm,vexpress-sysreg")
218 node
.append(FdtPropertyWords("reg",
219 state
.addrCells(self
.pio_addr
) +
220 state
.sizeCells(0x1000) ))
221 node
.append(FdtProperty("gpio-controller"))
222 node
.append(FdtPropertyWords("#gpio-cells", [2]))
223 node
.appendPhandle(self
)
227 class RealViewOsc(ClockDomain
):
229 cxx_header
= "dev/arm/rv_ctrl.hh"
231 parent
= Param
.RealViewCtrl(Parent
.any
, "RealView controller")
233 # TODO: We currently don't have the notion of a clock source,
234 # which means we have to associate oscillators with a voltage
236 voltage_domain
= Param
.VoltageDomain(Parent
.voltage_domain
,
239 # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
240 # the individual core/logic tile reference manuals for details
241 # about the site/position/dcc/device allocation.
242 site
= Param
.UInt8("Board Site")
243 position
= Param
.UInt8("Position in device stack")
244 dcc
= Param
.UInt8("Daughterboard Configuration Controller")
245 device
= Param
.UInt8("Device ID")
247 freq
= Param
.Clock("Default frequency")
249 def generateDeviceTree(self
, state
):
250 phandle
= state
.phandle(self
)
251 node
= FdtNode("osc@" + format(long(phandle
), 'x'))
252 node
.appendCompatible("arm,vexpress-osc")
253 node
.append(FdtPropertyWords("arm,vexpress-sysreg,func",
254 [0x1, int(self
.device
)]))
255 node
.append(FdtPropertyWords("#clock-cells", [0]))
256 freq
= int(1.0/self
.freq
.value
) # Values are stored as a clock period
257 node
.append(FdtPropertyWords("freq-range", [freq
, freq
]))
258 node
.append(FdtPropertyStrings("clock-output-names",
259 ["oscclk" + str(phandle
)]))
260 node
.appendPhandle(self
)
263 class RealViewTemperatureSensor(SimObject
):
264 type = 'RealViewTemperatureSensor'
265 cxx_header
= "dev/arm/rv_ctrl.hh"
267 parent
= Param
.RealViewCtrl(Parent
.any
, "RealView controller")
269 system
= Param
.System(Parent
.any
, "system")
271 # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
272 # the individual core/logic tile reference manuals for details
273 # about the site/position/dcc/device allocation.
274 site
= Param
.UInt8("Board Site")
275 position
= Param
.UInt8("Position in device stack")
276 dcc
= Param
.UInt8("Daughterboard Configuration Controller")
277 device
= Param
.UInt8("Device ID")
279 class VExpressMCC(SubSystem
):
280 """ARM V2M-P1 Motherboard Configuration Controller
282 This subsystem describes a subset of the devices that sit behind the
283 motherboard configuration controller on the the ARM Motherboard
284 Express (V2M-P1) motherboard. See ARM DUI 0447J for details.
287 class Osc(RealViewOsc
):
288 site
, position
, dcc
= (0, 0, 0)
290 class Temperature(RealViewTemperatureSensor
):
291 site
, position
, dcc
= (0, 0, 0)
293 osc_mcc
= Osc(device
=0, freq
="50MHz")
294 osc_clcd
= Osc(device
=1, freq
="23.75MHz")
295 osc_peripheral
= Osc(device
=2, freq
="24MHz")
296 osc_system_bus
= Osc(device
=4, freq
="24MHz")
298 # See Table 4.19 in ARM DUI 0447J (Motherboard Express uATX TRM).
299 temp_crtl
= Temperature(device
=0)
301 def generateDeviceTree(self
, state
):
302 node
= FdtNode("mcc")
303 node
.appendCompatible("arm,vexpress,config-bus")
304 node
.append(FdtPropertyWords("arm,vexpress,site", [0]))
306 for obj
in self
._children
.values():
307 if issubclass(type(obj
), SimObject
):
308 node
.append(obj
.generateDeviceTree(state
))
310 io_phandle
= state
.phandle(self
.osc_mcc
.parent
.unproxy(self
))
311 node
.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle
))
315 class CoreTile2A15DCC(SubSystem
):
316 """ARM CoreTile Express A15x2 Daughterboard Configuration Controller
318 This subsystem describes a subset of the devices that sit behind the
319 daughterboard configuration controller on a CoreTile Express A15x2. See
320 ARM DUI 0604E for details.
323 class Osc(RealViewOsc
):
324 site
, position
, dcc
= (1, 0, 0)
326 # See Table 2.8 in ARM DUI 0604E (CoreTile Express A15x2 TRM)
327 osc_cpu
= Osc(device
=0, freq
="60MHz")
328 osc_hsbm
= Osc(device
=4, freq
="40MHz")
329 osc_pxl
= Osc(device
=5, freq
="23.75MHz")
330 osc_smb
= Osc(device
=6, freq
="50MHz")
331 osc_sys
= Osc(device
=7, freq
="60MHz")
332 osc_ddr
= Osc(device
=8, freq
="40MHz")
334 def generateDeviceTree(self
, state
):
335 node
= FdtNode("dcc")
336 node
.appendCompatible("arm,vexpress,config-bus")
338 for obj
in self
._children
.values():
339 if isinstance(obj
, SimObject
):
340 node
.append(obj
.generateDeviceTree(state
))
342 io_phandle
= state
.phandle(self
.osc_cpu
.parent
.unproxy(self
))
343 node
.append(FdtPropertyWords("arm,vexpress,config-bridge", io_phandle
))
347 class AmbaFake(AmbaPioDevice
):
349 cxx_header
= "dev/arm/amba_fake.hh"
350 ignore_access
= Param
.Bool(False, "Ignore reads/writes to this device, (e.g. IsaFake + AMBA)")
353 # Simple fixed-rate clock source. Intended to be instantiated in Platform
354 # instances for definition of clock bindings on DTB auto-generation
355 class FixedClock(SrcClockDomain
):
356 # Keep track of the number of FixedClock instances in the system
357 # to provide unique names
360 def generateDeviceTree(self
, state
):
361 if len(self
.clock
) > 1:
362 fatal('FixedClock configured with multiple frequencies')
363 node
= FdtNode('clock{}'.format(FixedClock
._index
))
364 node
.appendCompatible('fixed-clock')
365 node
.append(FdtPropertyWords('#clock-cells', 0))
366 node
.append(FdtPropertyWords('clock-frequency',
367 self
.clock
[0].frequency
))
368 node
.appendPhandle(self
)
369 FixedClock
._index
+= 1
375 cxx_header
= "dev/arm/pl011.hh"
376 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
377 int_num
= Param
.UInt32("Interrupt number that connects to GIC")
378 end_on_eot
= Param
.Bool(False, "End the simulation when a EOT is received on the UART")
379 int_delay
= Param
.Latency("100ns", "Time between action and interrupt generation by UART")
381 def generateDeviceTree(self
, state
):
382 node
= self
.generateBasicPioDeviceNode(state
, 'uart', self
.pio_addr
,
383 0x1000, [int(self
.int_num
)])
384 node
.appendCompatible(["arm,pl011", "arm,primecell"])
386 # Hardcoded reference to the realview platform clocks, because the
387 # clk_domain can only store one clock (i.e. it is not a VectorParam)
388 realview
= self
._parent
.unproxy(self
)
389 node
.append(FdtPropertyWords("clocks",
390 [state
.phandle(realview
.mcc
.osc_peripheral
),
391 state
.phandle(realview
.dcc
.osc_smb
)]))
392 node
.append(FdtPropertyStrings("clock-names", ["uartclk", "apb_pclk"]))
395 class Sp804(AmbaPioDevice
):
397 cxx_header
= "dev/arm/timer_sp804.hh"
398 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
399 int_num0
= Param
.UInt32("Interrupt number that connects to GIC")
400 clock0
= Param
.Clock('1MHz', "Clock speed of the input")
401 int_num1
= Param
.UInt32("Interrupt number that connects to GIC")
402 clock1
= Param
.Clock('1MHz', "Clock speed of the input")
405 class Sp805(AmbaIntDevice
):
407 Arm Watchdog Module (SP805)
409 Arm Watchdog Module (SP805) - Technical Reference Manual - rev. r1p0
410 Doc. ID: ARM DDI 0270B
414 cxx_header
= 'dev/arm/watchdog_sp805.hh'
418 def generateDeviceTree(self
, state
):
419 node
= self
.generateBasicPioDeviceNode(state
, 'watchdog',
420 self
.pio_addr
, 0x1000, [int(self
.int_num
)])
421 node
.appendCompatible(['arm,sp805', 'arm,primecell'])
422 clocks
= [state
.phandle(self
.clk_domain
.unproxy(self
))]
423 clock_names
= ['wdogclk']
424 platform
= self
._parent
.unproxy(self
)
425 if self
in platform
._off
_chip
_devices
():
426 clocks
.append(state
.phandle(platform
.dcc
.osc_smb
))
427 clock_names
.append('apb_pclk')
428 node
.append(FdtPropertyWords('clocks', clocks
))
429 node
.append(FdtPropertyStrings('clock-names', clock_names
))
433 class A9GlobalTimer(BasicPioDevice
):
434 type = 'A9GlobalTimer'
435 cxx_header
= "dev/arm/timer_a9global.hh"
436 gic
= Param
.BaseGic(Parent
.any
, "Gic to use for interrupting")
437 int_num
= Param
.UInt32("Interrrupt number that connects to GIC")
439 class CpuLocalTimer(BasicPioDevice
):
440 type = 'CpuLocalTimer'
441 cxx_header
= "dev/arm/timer_cpulocal.hh"
442 int_timer
= Param
.ArmPPI("Interrrupt used per-cpu to GIC")
443 int_watchdog
= Param
.ArmPPI("Interrupt for per-cpu watchdog to GIC")
445 class GenericTimer(ClockedObject
):
446 type = 'GenericTimer'
447 cxx_header
= "dev/arm/generic_timer.hh"
448 system
= Param
.ArmSystem(Parent
.any
, "system")
449 int_phys_s
= Param
.ArmPPI("Physical (S) timer interrupt")
450 int_phys_ns
= Param
.ArmPPI("Physical (NS) timer interrupt")
451 int_virt
= Param
.ArmPPI("Virtual timer interrupt")
452 int_hyp
= Param
.ArmPPI("Hypervisor timer interrupt")
454 freqs
= VectorParam
.UInt32([0x01800000], "Frequencies available for the "
455 "system counter (in Hz). First element is the base frequency, "
456 "following are alternative lower ones which must be exact divisors")
458 def generateDeviceTree(self
, state
):
459 node
= FdtNode("timer")
461 node
.appendCompatible(["arm,cortex-a15-timer",
464 node
.append(FdtPropertyWords("interrupts", [
465 1, int(self
.int_phys_s
.num
) - 16, 0xf08,
466 1, int(self
.int_phys_ns
.num
) - 16, 0xf08,
467 1, int(self
.int_virt
.num
) - 16, 0xf08,
468 1, int(self
.int_hyp
.num
) - 16, 0xf08,
470 clock
= state
.phandle(self
.clk_domain
.unproxy(self
))
471 node
.append(FdtPropertyWords("clocks", clock
))
475 class GenericTimerMem(PioDevice
):
476 type = 'GenericTimerMem'
477 cxx_header
= "dev/arm/generic_timer.hh"
479 base
= Param
.Addr(0, "Base address")
481 int_phys
= Param
.ArmSPI("Physical Interrupt")
482 int_virt
= Param
.ArmSPI("Virtual Interrupt")
484 freqs
= VectorParam
.UInt32([0x01800000], "Frequencies available for the "
485 "system counter (in Hz). First element is the base frequency, "
486 "following are alternative lower ones which must be exact divisors")
488 class PL031(AmbaIntDevice
):
490 cxx_header
= "dev/arm/rtc_pl031.hh"
491 time
= Param
.Time('01/01/2009', "System time to use ('Now' for actual time)")
494 def generateDeviceTree(self
, state
):
495 node
= self
.generateBasicPioDeviceNode(state
, 'rtc', self
.pio_addr
,
496 0x1000, [int(self
.int_num
)])
498 node
.appendCompatible(["arm,pl031", "arm,primecell"])
499 clock
= state
.phandle(self
.clk_domain
.unproxy(self
))
500 node
.append(FdtPropertyWords("clocks", clock
))
504 class Pl050(AmbaIntDevice
):
506 cxx_header
= "dev/arm/kmi.hh"
509 ps2
= Param
.PS2Device("PS/2 device")
511 def generateDeviceTree(self
, state
):
512 node
= self
.generateBasicPioDeviceNode(state
, 'kmi', self
.pio_addr
,
513 0x1000, [int(self
.int_num
)])
515 node
.appendCompatible(["arm,pl050", "arm,primecell"])
516 clock
= state
.phandle(self
.clk_domain
.unproxy(self
))
517 node
.append(FdtPropertyWords("clocks", clock
))
521 class Pl111(AmbaDmaDevice
):
523 cxx_header
= "dev/arm/pl111.hh"
524 pixel_clock
= Param
.Clock('24MHz', "Pixel clock")
525 vnc
= Param
.VncInput(Parent
.any
, "Vnc server for remote frame buffer display")
527 enable_capture
= Param
.Bool(True, "capture frame to system.framebuffer.bmp")
529 class HDLcd(AmbaDmaDevice
):
531 cxx_header
= "dev/arm/hdlcd.hh"
532 vnc
= Param
.VncInput(Parent
.any
, "Vnc server for remote frame buffer "
535 workaround_swap_rb
= Param
.Bool(False, "Workaround incorrect color "
536 "selector order in some kernels")
537 workaround_dma_line_count
= Param
.Bool(True, "Workaround incorrect "
538 "DMA line count (off by 1)")
539 enable_capture
= Param
.Bool(True, "capture frame to "
540 "system.framebuffer.{extension}")
541 frame_format
= Param
.ImageFormat("Auto",
542 "image format of the captured frame")
544 pixel_buffer_size
= Param
.MemorySize32("2kB", "Size of address range")
546 pxl_clk
= Param
.ClockDomain("Pixel clock source")
547 pixel_chunk
= Param
.Unsigned(32, "Number of pixels to handle in one batch")
548 virt_refresh_rate
= Param
.Frequency("20Hz", "Frame refresh rate "
552 encoder
= Param
.Display(Display1080p(), "Display encoder")
554 def endpointPhandle(self
):
555 return "hdlcd_endpoint"
557 def generateDeviceTree(self
, state
):
558 endpoint_node
= FdtNode("endpoint")
559 endpoint_node
.appendPhandle(self
.endpointPhandle())
561 for encoder_node
in self
.encoder
.generateDeviceTree(state
):
562 encoder_endpoint
= self
.encoder
.endpointNode()
565 endpoint_node
.append(FdtPropertyWords("remote-endpoint",
566 [ state
.phandle(self
.encoder
.endpointPhandle()) ]))
567 encoder_endpoint
.append(FdtPropertyWords("remote-endpoint",
568 [ state
.phandle(self
.endpointPhandle()) ]))
572 port_node
= FdtNode("port")
573 port_node
.append(endpoint_node
)
575 # Interrupt number is hardcoded; it is not a property of this class
576 node
= self
.generateBasicPioDeviceNode(state
, 'hdlcd',
577 self
.pio_addr
, 0x1000, [63])
579 node
.appendCompatible(["arm,hdlcd"])
580 node
.append(FdtPropertyWords("clocks", state
.phandle(self
.pxl_clk
)))
581 node
.append(FdtPropertyStrings("clock-names", ["pxlclk"]))
583 # This driver is disabled by default since the required DT nodes
584 # haven't been standardized yet. To use it, override this status to
585 # "ok" and add the display configuration nodes required by the driver.
586 # See the driver for more information.
587 node
.append(FdtPropertyStrings("status", [ self
._status
]))
589 self
.addIommuProperty(state
, node
)
591 node
.append(port_node
)
595 class RealView(Platform
):
597 cxx_header
= "dev/arm/realview.hh"
598 system
= Param
.System(Parent
.any
, "system")
599 _mem_regions
= [ AddrRange(0, size
='256MB') ]
602 def _on_chip_devices(self
):
605 def _off_chip_devices(self
):
608 _off_chip_ranges
= []
610 def _attach_memory(self
, mem
, bus
, mem_ports
=None):
611 if hasattr(mem
, "port"):
612 if mem_ports
is None:
613 mem
.port
= bus
.master
615 mem_ports
.append(mem
.port
)
617 def _attach_device(self
, device
, bus
, dma_ports
=None):
618 if hasattr(device
, "pio"):
619 device
.pio
= bus
.master
620 if hasattr(device
, "dma"):
621 if dma_ports
is None:
622 device
.dma
= bus
.slave
624 dma_ports
.append(device
.dma
)
626 def _attach_io(self
, devices
, *args
, **kwargs
):
628 self
._attach
_device
(d
, *args
, **kwargs
)
630 def _attach_mem(self
, memories
, *args
, **kwargs
):
632 self
._attach
_memory
(mem
, *args
, **kwargs
)
634 def _attach_clk(self
, devices
, clkdomain
):
636 if hasattr(d
, "clk_domain"):
637 d
.clk_domain
= clkdomain
639 def attachPciDevices(self
):
642 def enableMSIX(self
):
645 def onChipIOClkDomain(self
, clkdomain
):
646 self
._attach
_clk
(self
._on
_chip
_devices
(), clkdomain
)
648 def offChipIOClkDomain(self
, clkdomain
):
649 self
._attach
_clk
(self
._off
_chip
_devices
(), clkdomain
)
651 def attachOnChipIO(self
, bus
, bridge
=None, dma_ports
=None, mem_ports
=None):
652 self
._attach
_mem
(self
._on
_chip
_memory
(), bus
, mem_ports
)
653 self
._attach
_io
(self
._on
_chip
_devices
(), bus
, dma_ports
)
655 bridge
.ranges
= self
._off
_chip
_ranges
657 def attachIO(self
, *args
, **kwargs
):
658 self
._attach
_io
(self
._off
_chip
_devices
(), *args
, **kwargs
)
660 def setupBootLoader(self
, cur_sys
, boot_loader
, atags_addr
, load_offset
):
661 cur_sys
.boot_loader
= boot_loader
662 cur_sys
.atags_addr
= atags_addr
663 cur_sys
.load_offset
= load_offset
665 def generateDeviceTree(self
, state
):
666 node
= FdtNode("/") # Things in this module need to end up in the root
667 node
.append(FdtPropertyWords("interrupt-parent",
668 state
.phandle(self
.gic
)))
670 for subnode
in self
.recurseDeviceTree(state
):
675 def annotateCpuDeviceNode(self
, cpu
, state
):
676 cpu
.append(FdtPropertyStrings("enable-method", "spin-table"))
677 cpu
.append(FdtPropertyWords("cpu-release-addr", \
678 state
.addrCells(0x8000fff8)))
680 class VExpress_EMM(RealView
):
681 _mem_regions
= [ AddrRange('2GB', size
='2GB') ]
683 # Ranges based on excluding what is part of on-chip I/O (gic,
685 _off_chip_ranges
= [AddrRange(0x2F000000, size
='16MB'),
686 AddrRange(0x30000000, size
='256MB'),
687 AddrRange(0x40000000, size
='512MB'),
688 AddrRange(0x18000000, size
='64MB'),
689 AddrRange(0x1C000000, size
='64MB')]
691 # Platform control device (off-chip)
692 realview_io
= RealViewCtrl(proc_id0
=0x14000000, proc_id1
=0x14000000,
693 idreg
=0x02250000, pio_addr
=0x1C010000)
696 dcc
= CoreTile2A15DCC()
698 ### On-chip devices ###
699 gic
= Gic400(dist_addr
=0x2C001000, cpu_addr
=0x2C002000)
700 vgic
= VGic(vcpu_addr
=0x2c006000, hv_addr
=0x2c004000, maint_int
=25)
702 local_cpu_timer
= CpuLocalTimer(int_timer
=ArmPPI(num
=29),
703 int_watchdog
=ArmPPI(num
=30),
706 hdlcd
= HDLcd(pxl_clk
=dcc
.osc_pxl
,
707 pio_addr
=0x2b000000, int_num
=117,
708 workaround_swap_rb
=True)
710 def _on_chip_devices(self
):
715 if hasattr(self
, "gicv2m"):
716 devices
.append(self
.gicv2m
)
717 devices
.append(self
.hdlcd
)
720 def _on_chip_memory(self
):
726 ### Off-chip devices ###
727 uart
= Pl011(pio_addr
=0x1c090000, int_num
=37)
728 pci_host
= GenericPciHost(
729 conf_base
=0x30000000, conf_size
='256MB', conf_device_bits
=16,
732 generic_timer
= GenericTimer(int_phys_s
=ArmPPI(num
=29),
733 int_phys_ns
=ArmPPI(num
=30),
734 int_virt
=ArmPPI(num
=27),
735 int_hyp
=ArmPPI(num
=26))
737 timer0
= Sp804(int_num0
=34, int_num1
=34, pio_addr
=0x1C110000, clock0
='1MHz', clock1
='1MHz')
738 timer1
= Sp804(int_num0
=35, int_num1
=35, pio_addr
=0x1C120000, clock0
='1MHz', clock1
='1MHz')
739 clcd
= Pl111(pio_addr
=0x1c1f0000, int_num
=46)
740 kmi0
= Pl050(pio_addr
=0x1c060000, int_num
=44, ps2
=PS2Keyboard())
741 kmi1
= Pl050(pio_addr
=0x1c070000, int_num
=45, ps2
=PS2TouchKit())
742 cf_ctrl
= IdeController(disks
=[], pci_func
=0, pci_dev
=0, pci_bus
=2,
743 io_shift
= 2, ctrl_offset
= 2, Command
= 0x1,
744 BAR0
= 0x1C1A0000, BAR0Size
= '256B',
745 BAR1
= 0x1C1A0100, BAR1Size
= '4096B',
746 BAR0LegacyIO
= True, BAR1LegacyIO
= True)
748 bootmem
= SimpleMemory(range = AddrRange('64MB'),
749 conf_table_reported
= False)
750 vram
= SimpleMemory(range = AddrRange(0x18000000, size
='32MB'),
751 conf_table_reported
= False)
752 rtc
= PL031(pio_addr
=0x1C170000, int_num
=36)
754 l2x0_fake
= IsaFake(pio_addr
=0x2C100000, pio_size
=0xfff)
755 uart1_fake
= AmbaFake(pio_addr
=0x1C0A0000)
756 uart2_fake
= AmbaFake(pio_addr
=0x1C0B0000)
757 uart3_fake
= AmbaFake(pio_addr
=0x1C0C0000)
758 sp810_fake
= AmbaFake(pio_addr
=0x1C020000, ignore_access
=True)
759 watchdog_fake
= AmbaFake(pio_addr
=0x1C0F0000)
760 aaci_fake
= AmbaFake(pio_addr
=0x1C040000)
761 lan_fake
= IsaFake(pio_addr
=0x1A000000, pio_size
=0xffff)
762 usb_fake
= IsaFake(pio_addr
=0x1B000000, pio_size
=0x1ffff)
763 mmc_fake
= AmbaFake(pio_addr
=0x1c050000)
764 energy_ctrl
= EnergyCtrl(pio_addr
=0x1c080000)
766 def _off_chip_devices(self
):
791 # Try to attach the I/O if it exists
792 if hasattr(self
, "ide"):
793 devices
.append(self
.ide
)
794 if hasattr(self
, "ethernet"):
795 devices
.append(self
.ethernet
)
798 # Attach any PCI devices that are supported
799 def attachPciDevices(self
):
800 self
.ethernet
= IGbE_e1000(pci_bus
=0, pci_dev
=0, pci_func
=0,
801 InterruptLine
=1, InterruptPin
=1)
802 self
.ide
= IdeController(disks
= [], pci_bus
=0, pci_dev
=1, pci_func
=0,
803 InterruptLine
=2, InterruptPin
=2)
805 def enableMSIX(self
):
806 self
.gic
= Gic400(dist_addr
=0x2C001000, cpu_addr
=0x2C002000,
808 self
.gicv2m
= Gicv2m()
809 self
.gicv2m
.frames
= [Gicv2mFrame(spi_base
=256, spi_len
=64, addr
=0x2C1C0000)]
811 def setupBootLoader(self
, cur_sys
, loc
, boot_loader
=None):
812 if boot_loader
is None:
813 boot_loader
= loc('boot_emm.arm')
814 super(VExpress_EMM
, self
).setupBootLoader(
815 cur_sys
, boot_loader
, 0x8000000, 0x80000000)
817 class VExpress_EMM64(VExpress_EMM
):
818 # Three memory regions are specified totalling 512GB
819 _mem_regions
= [ AddrRange('2GB', size
='2GB'),
820 AddrRange('34GB', size
='30GB'),
821 AddrRange('512GB', size
='480GB') ]
822 pci_host
= GenericPciHost(
823 conf_base
=0x30000000, conf_size
='256MB', conf_device_bits
=12,
824 pci_pio_base
=0x2f000000)
826 def setupBootLoader(self
, cur_sys
, loc
, boot_loader
=None):
827 if boot_loader
is None:
828 boot_loader
= loc('boot_emm.arm64')
829 RealView
.setupBootLoader(self
, cur_sys
, boot_loader
,
830 0x8000000, 0x80000000)
832 class VExpress_GEM5_Base(RealView
):
834 The VExpress gem5 memory map is loosely based on a modified
835 Versatile Express RS1 memory map.
837 The gem5 platform has been designed to implement a subset of the
838 original Versatile Express RS1 memory map. Off-chip peripherals should,
839 when possible, adhere to the Versatile Express memory map. Non-PCI
840 off-chip devices that are gem5-specific should live in the CS5 memory
841 space to avoid conflicts with existing devices that we might want to
842 model in the future. Such devices should normally have interrupts in
843 the gem5-specific SPI range.
845 On-chip peripherals are loosely modeled after the ARM CoreTile Express
846 A15x2 memory and interrupt map. In particular, the GIC and
847 Generic Timer have the same interrupt lines and base addresses. Other
848 on-chip devices are gem5 specific.
850 Unlike the original Versatile Express RS2 extended platform, gem5 implements a
851 large contigious DRAM space, without aliases or holes, starting at the
852 2GiB boundary. This means that PCI memory is limited to 1GiB.
856 Technical Reference Manuals:
857 Arm Motherboard Express uATX (V2M-P1) - ARM DUI 0447J
858 Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
860 Official Linux device tree specifications:
861 V2M-P1 - arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
862 V2P-CA15 - arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
865 Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
866 Daughterboard (global)
867 Section 3.2.1 - Table 3-1 - Daughterboard memory map
869 Section 3.2.3 - Table 3-2 - Cortex-A15 MPCore on-chip peripheral
873 Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
874 Section 2.8.2 - Test chip interrupts
877 0x00000000-0x03ffffff: Boot memory (CS0)
878 0x04000000-0x07ffffff: Reserved
879 0x08000000-0x0bffffff: Reserved (CS0 alias)
880 0x0c000000-0x0fffffff: Reserved (Off-chip, CS4)
881 0x10000000-0x13ffffff: gem5-specific peripherals (Off-chip, CS5)
882 0x10000000-0x1000ffff: gem5 energy controller
883 0x10010000-0x1001ffff: gem5 pseudo-ops
885 0x14000000-0x17ffffff: Reserved (Off-chip, PSRAM, CS1)
886 0x18000000-0x1bffffff: Reserved (Off-chip, Peripherals, CS2)
887 0x1c000000-0x1fffffff: Peripheral block 1 (Off-chip, CS3):
888 0x1c010000-0x1c01ffff: realview_io (VE system control regs.)
889 0x1c060000-0x1c06ffff: KMI0 (keyboard)
890 0x1c070000-0x1c07ffff: KMI1 (mouse)
891 0x1c090000-0x1c09ffff: UART0
892 0x1c0a0000-0x1c0affff: UART1 (reserved)
893 0x1c0b0000-0x1c0bffff: UART2 (reserved)
894 0x1c0c0000-0x1c0cffff: UART3 (reserved)
895 0x1c0f0000-0x1c0fffff: Watchdog (SP805)
896 0x1c130000-0x1c13ffff: VirtIO (gem5/FM extension)
897 0x1c140000-0x1c14ffff: VirtIO (gem5/FM extension)
898 0x1c170000-0x1c17ffff: RTC
900 0x20000000-0x3fffffff: On-chip peripherals:
901 0x2b000000-0x2b00ffff: HDLCD
903 0x2b060000-0x2b060fff: System Watchdog (SP805)
905 0x2b400000-0x2b41ffff: SMMUv3
907 0x2c001000-0x2c001fff: GIC (distributor)
908 0x2c002000-0x2c003fff: GIC (CPU interface)
909 0x2c004000-0x2c005fff: vGIC (HV)
910 0x2c006000-0x2c007fff: vGIC (VCPU)
911 0x2c1c0000-0x2c1cffff: GICv2m MSI frame 0
913 0x2d000000-0x2d00ffff: GPU (reserved)
915 0x2f000000-0x2fffffff: PCI IO space
916 0x30000000-0x3fffffff: PCI config space
918 0x40000000-0x7fffffff: Ext. AXI: Used as PCI memory
923 0- 15: Software generated interrupts (SGIs)
924 16- 31: On-chip private peripherals (PPIs)
926 26 : generic_timer (hyp)
927 27 : generic_timer (virt)
928 28 : Reserved (Legacy FIQ)
929 29 : generic_timer (phys, sec)
930 30 : generic_timer (phys, non-sec)
931 31 : Reserved (Legacy IRQ)
932 32- 95: Mother board peripherals (SPIs)
933 32 : Watchdog (SP805)
934 33 : Reserved (IOFPGA SW int)
935 34-35: Reserved (SP804)
938 41-42: Reserved (PL180)
942 47 : Reserved (Ethernet)
944 95-255: On-chip interrupt sources (we use these for
945 gem5-specific devices, SPIs)
946 74 : VirtIO (gem5/FM extension)
947 75 : VirtIO (gem5/FM extension)
949 96- 98: GPU (reserved)
951 130 : System Watchdog (SP805)
952 256-319: MSI frame 0 (gem5-specific, SPIs)
957 # Everything above 2GiB is memory
958 _mem_regions
= [ AddrRange('2GB', size
='510GB') ]
962 AddrRange(0x0c000000, 0x20000000),
963 # External AXI interface (PCI)
964 AddrRange(0x2f000000, 0x80000000),
967 bootmem
= SimpleMemory(range=AddrRange(0, size
='64MB'),
968 conf_table_reported
=False)
970 # Platform control device (off-chip)
971 realview_io
= RealViewCtrl(proc_id0
=0x14000000, proc_id1
=0x14000000,
972 idreg
=0x02250000, pio_addr
=0x1c010000)
974 dcc
= CoreTile2A15DCC()
976 ### On-chip devices ###
977 generic_timer
= GenericTimer(int_phys_s
=ArmPPI(num
=29),
978 int_phys_ns
=ArmPPI(num
=30),
979 int_virt
=ArmPPI(num
=27),
980 int_hyp
=ArmPPI(num
=26))
982 system_watchdog
= Sp805(pio_addr
=0x2b060000, int_num
=130)
984 def _on_chip_devices(self
):
990 def _on_chip_memory(self
):
996 ### Off-chip devices ###
997 io_voltage
= VoltageDomain(voltage
="3.3V")
998 clock32KHz
= SrcClockDomain(clock
="32kHz")
999 clock24MHz
= SrcClockDomain(clock
="24MHz")
1002 Pl011(pio_addr
=0x1c090000, int_num
=37),
1005 kmi0
= Pl050(pio_addr
=0x1c060000, int_num
=44, ps2
=PS2Keyboard())
1006 kmi1
= Pl050(pio_addr
=0x1c070000, int_num
=45, ps2
=PS2TouchKit())
1008 watchdog
= Sp805(pio_addr
=0x1c0f0000, int_num
=32)
1010 rtc
= PL031(pio_addr
=0x1c170000, int_num
=36)
1012 ### gem5-specific off-chip devices ###
1013 pci_host
= GenericArmPciHost(
1014 conf_base
=0x30000000, conf_size
='256MB', conf_device_bits
=12,
1015 pci_pio_base
=0x2f000000,
1016 int_policy
="ARM_PCI_INT_DEV", int_base
=100, int_count
=4)
1018 energy_ctrl
= EnergyCtrl(pio_addr
=0x10000000)
1021 MmioVirtIO(pio_addr
=0x1c130000, pio_size
=0x1000,
1022 interrupt
=ArmSPI(num
=74)),
1023 MmioVirtIO(pio_addr
=0x1c140000, pio_size
=0x1000,
1024 interrupt
=ArmSPI(num
=75)),
1027 def _off_chip_devices(self
):
1043 def __init__(self
, **kwargs
):
1044 super(VExpress_GEM5_Base
, self
).__init
__(**kwargs
)
1045 self
.clock32KHz
.voltage_domain
= self
.io_voltage
1046 self
.clock24MHz
.voltage_domain
= self
.io_voltage
1047 self
.system_watchdog
.clk_domain
= self
.dcc
.osc_sys
1048 self
.watchdog
.clk_domain
= self
.clock32KHz
1050 def attachPciDevice(self
, device
, *args
, **kwargs
):
1051 device
.host
= self
.pci_host
1052 self
._num
_pci
_dev
+= 1
1054 device
.pci_dev
= self
._num
_pci
_dev
1056 self
._attach
_device
(device
, *args
, **kwargs
)
1058 def attachSmmu(self
, devices
, bus
):
1060 Instantiate a single SMMU and attach a group of client devices to it.
1061 The devices' dma port is wired to the SMMU and the SMMU's dma port
1062 (master) is attached to the bus. In order to make it work, the list
1063 of clients shouldn't contain any device part of the _off_chip_devices
1064 or _on_chip_devices.
1065 This method should be called only once.
1068 devices (list): List of devices which will be using the SMMU
1069 bus (Bus): The bus downstream of the SMMU. Its slave port will
1070 receive memory requests from the SMMU, and its master
1071 port will forward accesses to the memory mapped devices
1073 if hasattr(self
, 'smmu'):
1074 m5
.fatal("A SMMU has already been instantiated\n")
1076 self
.smmu
= SMMUv3(reg_map
=AddrRange(0x2b400000, size
=0x00020000))
1080 self
._attach
_device
(dev
, bus
, dma_ports
)
1081 self
.smmu
.connect(dev
, bus
)
1083 def setupBootLoader(self
, cur_sys
, loc
, boot_loader
=None):
1084 if boot_loader
is None:
1085 boot_loader
= [ loc('boot.arm64'), loc('boot.arm') ]
1086 super(VExpress_GEM5_Base
, self
).setupBootLoader(
1087 cur_sys
, boot_loader
, 0x8000000, 0x80000000)
1089 # Setup m5ops. It's technically not a part of the boot
1090 # loader, but this is the only place we can configure the
1092 cur_sys
.m5ops_base
= 0x10010000
1094 def generateDeviceTree(self
, state
):
1095 # Generate using standard RealView function
1096 dt
= list(super(VExpress_GEM5_Base
, self
).generateDeviceTree(state
))
1098 raise Exception("System returned too many DT nodes")
1101 node
.appendCompatible(["arm,vexpress"])
1102 node
.append(FdtPropertyStrings("model", ["V2P-CA15"]))
1103 node
.append(FdtPropertyWords("arm,hbi", [0x0]))
1104 node
.append(FdtPropertyWords("arm,vexpress,site", [0xf]))
1108 class VExpress_GEM5_V1_Base(VExpress_GEM5_Base
):
1109 gic
= kvm_gicv2_class(dist_addr
=0x2c001000, cpu_addr
=0x2c002000,
1111 vgic
= VGic(vcpu_addr
=0x2c006000, hv_addr
=0x2c004000, maint_int
=25)
1114 Gicv2mFrame(spi_base
=256, spi_len
=64, addr
=0x2c1c0000),
1117 def _on_chip_devices(self
):
1118 return super(VExpress_GEM5_V1_Base
,self
)._on
_chip
_devices
() + [
1119 self
.gic
, self
.vgic
, self
.gicv2m
,
1122 class VExpress_GEM5_V1(VExpress_GEM5_V1_Base
):
1123 hdlcd
= HDLcd(pxl_clk
=VExpress_GEM5_V1_Base
.dcc
.osc_pxl
,
1124 pio_addr
=0x2b000000, int_num
=95)
1126 def _on_chip_devices(self
):
1127 return super(VExpress_GEM5_V1
,self
)._on
_chip
_devices
() + [
1131 class VExpress_GEM5_V2_Base(VExpress_GEM5_Base
):
1132 gic
= Gicv3(dist_addr
=0x2c000000, redist_addr
=0x2c010000,
1133 maint_int
=ArmPPI(num
=25),
1134 its
=Gicv3Its(pio_addr
=0x2e010000))
1136 # Limiting to 128 since it will otherwise overlap with PCI space
1139 def _on_chip_devices(self
):
1140 return super(VExpress_GEM5_V2_Base
,self
)._on
_chip
_devices
() + [
1141 self
.gic
, self
.gic
.its
1144 def setupBootLoader(self
, cur_sys
, loc
, boot_loader
=None):
1145 if boot_loader
is None:
1146 boot_loader
= [ loc('boot_v2.arm64') ]
1147 super(VExpress_GEM5_V2_Base
, self
).setupBootLoader(
1148 cur_sys
, boot_loader
)
1150 class VExpress_GEM5_V2(VExpress_GEM5_V2_Base
):
1151 hdlcd
= HDLcd(pxl_clk
=VExpress_GEM5_V2_Base
.dcc
.osc_pxl
,
1152 pio_addr
=0x2b000000, int_num
=95)
1154 def _on_chip_devices(self
):
1155 return super(VExpress_GEM5_V2
,self
)._on
_chip
_devices
() + [