1# Copyright (c) 2012-2013, 2017-2019 ARM Limited 2# All rights reserved. 3# 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. 12# 13# Redistribution and use in source and binary forms, with or without 14# modification, are permitted provided that the following conditions are 15# met: redistributions of source code must retain the above copyright 16# notice, this list of conditions and the following disclaimer; 17# redistributions in binary form must reproduce the above copyright 18# notice, this list of conditions and the following disclaimer in the 19# documentation and/or other materials provided with the distribution; 20# neither the name of the copyright holders nor the names of its 21# contributors may be used to endorse or promote products derived from 22# this software without specific prior written permission. 23# 24# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35# 36# Authors: Andreas Sandberg 37 38from m5.params import * 39from m5.proxy import * 40from m5.util.fdthelper import * 41from m5.SimObject import SimObject 42 43from m5.objects.Device import PioDevice, BasicPioDevice 44from m5.objects.Platform import Platform 45 46class BaseGic(PioDevice): 47 type = 'BaseGic' 48 abstract = True 49 cxx_header = "dev/arm/base_gic.hh" 50 51 # Used for DTB autogeneration 52 _state = FdtState(addr_cells=0, interrupt_cells=3) 53 54 platform = Param.Platform(Parent.any, "Platform this device is part of.") 55 56 gicd_iidr = Param.UInt32(0, 57 "Distributor Implementer Identification Register") 58 gicd_pidr = Param.UInt32(0, 59 "Peripheral Identification Register") 60 gicc_iidr = Param.UInt32(0, 61 "CPU Interface Identification Register") 62 gicv_iidr = Param.UInt32(0, 63 "VM CPU Interface Identification Register") 64 65 def interruptCells(self, int_type, int_num, int_flag): 66 """ 67 Interupt cells generation helper: 68 Following specifications described in 69 70 Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt 71 """ 72 assert self._state.interrupt_cells == 3 73 return [ int_type, int_num, int_flag ] 74 75class ArmInterruptPin(SimObject): 76 type = 'ArmInterruptPin' 77 cxx_header = "dev/arm/base_gic.hh" 78 cxx_class = "ArmInterruptPinGen" 79 abstract = True 80 81 platform = Param.Platform(Parent.any, "Platform with interrupt controller") 82 num = Param.UInt32("Interrupt number in GIC") 83 84class ArmSPI(ArmInterruptPin): 85 type = 'ArmSPI' 86 cxx_header = "dev/arm/base_gic.hh" 87 cxx_class = "ArmSPIGen" 88 89class ArmPPI(ArmInterruptPin): 90 type = 'ArmPPI' 91 cxx_header = "dev/arm/base_gic.hh" 92 cxx_class = "ArmPPIGen" 93 94class GicV2(BaseGic): 95 type = 'GicV2' 96 cxx_header = "dev/arm/gic_v2.hh" 97 98 dist_addr = Param.Addr("Address for distributor") 99 cpu_addr = Param.Addr("Address for cpu") 100 cpu_size = Param.Addr(0x2000, "Size of cpu register bank") 101 dist_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to distributor") 102 cpu_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to cpu interface") 103 int_latency = Param.Latency('10ns', "Delay for interrupt to get to CPU") 104 it_lines = Param.UInt32(128, "Number of interrupt lines supported (max = 1020)") 105 gem5_extensions = Param.Bool(False, "Enable gem5 extensions") 106 107class Gic400(GicV2): 108 """ 109 As defined in: 110 "ARM Generic Interrupt Controller Architecture" version 2.0 111 "CoreLink GIC-400 Generic Interrupt Controller" revision r0p1 112 """ 113 gicd_pidr = 0x002bb490 114 gicd_iidr = 0x0200143B 115 gicc_iidr = 0x0202143B 116 117 # gicv_iidr same as gicc_idr 118 gicv_iidr = gicc_iidr 119 120class Gicv2mFrame(SimObject): 121 type = 'Gicv2mFrame' 122 cxx_header = "dev/arm/gic_v2m.hh" 123 spi_base = Param.UInt32(0x0, "Frame SPI base number"); 124 spi_len = Param.UInt32(0x0, "Frame SPI total number"); 125 addr = Param.Addr("Address for frame PIO") 126 127class Gicv2m(PioDevice): 128 type = 'Gicv2m' 129 cxx_header = "dev/arm/gic_v2m.hh" 130 131 pio_delay = Param.Latency('10ns', "Delay for PIO r/w") 132 gic = Param.BaseGic(Parent.any, "Gic on which to trigger interrupts") 133 frames = VectorParam.Gicv2mFrame([], "Power of two number of frames") 134 135class VGic(PioDevice): 136 type = 'VGic' 137 cxx_header = "dev/arm/vgic.hh" 138 gic = Param.BaseGic(Parent.any, "Gic to use for interrupting") 139 platform = Param.Platform(Parent.any, "Platform this device is part of.") 140 vcpu_addr = Param.Addr(0, "Address for vcpu interfaces") 141 hv_addr = Param.Addr(0, "Address for hv control") 142 pio_delay = Param.Latency('10ns', "Delay for PIO r/w") 143 # The number of list registers is not currently configurable at runtime. 144 maint_int = Param.UInt32("HV maintenance interrupt number") 145 146 # gicv_iidr same as gicc_idr 147 gicv_iidr = Param.UInt32(Self.gic.gicc_iidr, 148 "VM CPU Interface Identification Register") 149 150 def generateDeviceTree(self, state): 151 gic = self.gic.unproxy(self) 152 153 node = FdtNode("interrupt-controller") 154 node.appendCompatible(["gem5,gic", "arm,cortex-a15-gic", 155 "arm,cortex-a9-gic"]) 156 node.append(gic._state.interruptCellsProperty()) 157 node.append(gic._state.addrCellsProperty()) 158 node.append(FdtProperty("interrupt-controller")) 159 160 regs = ( 161 state.addrCells(gic.dist_addr) + 162 state.sizeCells(0x1000) + 163 state.addrCells(gic.cpu_addr) + 164 state.sizeCells(0x1000) + 165 state.addrCells(self.hv_addr) + 166 state.sizeCells(0x2000) + 167 state.addrCells(self.vcpu_addr) + 168 state.sizeCells(0x2000) ) 169 170 node.append(FdtPropertyWords("reg", regs)) 171 node.append(FdtPropertyWords("interrupts", 172 [1, int(self.maint_int)-16, 0xf04])) 173 174 node.appendPhandle(gic) 175 176 yield node 177 178class Gicv3Its(BasicPioDevice): 179 type = 'Gicv3Its' 180 cxx_header = "dev/arm/gic_v3_its.hh" 181 182 dma = MasterPort("DMA port") 183 pio_size = Param.Unsigned(0x20000, "Gicv3Its pio size") 184 185 # CIL [36] = 0: ITS supports 16-bit CollectionID 186 # Devbits [17:13] = 0b100011: ITS supports 23 DeviceID bits 187 # ID_bits [12:8] = 0b11111: ITS supports 31 EventID bits 188 gits_typer = Param.UInt64(0x30023F01, "GITS_TYPER RO value") 189 190 def generateDeviceTree(self, state): 191 node = self.generateBasicPioDeviceNode(state, "gic-its", self.pio_addr, 192 self.pio_size) 193 node.appendCompatible(["arm,gic-v3-its"]) 194 node.append(FdtProperty("msi-controller")) 195 node.append(FdtPropertyWords("#msi-cells", [1])) 196 197 return node 198 199class Gicv3(BaseGic): 200 type = 'Gicv3' 201 cxx_header = "dev/arm/gic_v3.hh" 202 203 # Used for DTB autogeneration 204 _state = FdtState(addr_cells=2, size_cells=2, interrupt_cells=3) 205 206 its = Param.Gicv3Its(Gicv3Its(), "GICv3 Interrupt Translation Service") 207 208 dist_addr = Param.Addr("Address for distributor") 209 dist_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to distributor") 210 redist_addr = Param.Addr("Address for redistributors") 211 redist_pio_delay = Param.Latency('10ns', 212 "Delay for PIO r/w to redistributors") 213 it_lines = Param.UInt32(1020, 214 "Number of interrupt lines supported (max = 1020)") 215 216 maint_int = Param.ArmInterruptPin( 217 "HV maintenance interrupt." 218 "ARM strongly recommends that maintenance interrupts " 219 "are configured to use INTID 25 (PPI Interrupt).") 220 221 cpu_max = Param.Unsigned(256, 222 "Maximum number of PE. This is affecting the maximum number of " 223 "redistributors") 224 225 gicv4 = Param.Bool(True, "GICv4 extension available") 226 227 def interruptCells(self, int_type, int_num, int_flag): 228 """ 229 Interupt cells generation helper: 230 Following specifications described in 231 232 Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt 233 """ 234 prop = self._state.interruptCells(0) 235 assert len(prop) >= 3 236 prop[0] = int_type 237 prop[1] = int_num 238 prop[2] = int_flag 239 return prop 240 241 def generateDeviceTree(self, state): 242 node = FdtNode("interrupt-controller") 243 node.appendCompatible(["arm,gic-v3"]) 244 node.append(self._state.interruptCellsProperty()) 245 node.append(self._state.addrCellsProperty()) 246 node.append(self._state.sizeCellsProperty()) 247 node.append(FdtProperty("ranges")) 248 node.append(FdtProperty("interrupt-controller")) 249 250 redist_stride = 0x40000 if self.gicv4 else 0x20000 251 node.append(FdtPropertyWords("redistributor-stride", 252 state.sizeCells(redist_stride))) 253 254 regs = ( 255 state.addrCells(self.dist_addr) + 256 state.sizeCells(0x10000) + 257 state.addrCells(self.redist_addr) + 258 state.sizeCells(0x2000000) ) 259 260 node.append(FdtPropertyWords("reg", regs)) 261 node.append(FdtPropertyWords("interrupts", 262 self.interruptCells(1, int(self.maint_int.num)-16, 0xf04))) 263 264 node.appendPhandle(self) 265 266 # Generate the ITS device tree 267 node.append(self.its.generateDeviceTree(self._state)) 268 269 yield node 270