From 8ed4f0a02cd936f717f5af0c15b64fedddd5af54 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 23 Aug 2010 11:18:40 -0500 Subject: [PATCH] ARM: Add I/O devices for booting linux --HG-- rename : src/dev/arm/Versatile.py => src/dev/arm/RealView.py rename : src/dev/arm/versatile.cc => src/dev/arm/realview.cc rename : src/dev/arm/versatile.hh => src/dev/arm/realview.hh --- src/base/intmath.hh | 22 ++ src/dev/arm/RealView.py | 212 ++++++++++ src/dev/arm/SConscript | 12 +- src/dev/arm/Versatile.py | 62 --- src/dev/arm/amba_device.cc | 71 ++++ src/dev/arm/amba_device.hh | 82 ++++ src/dev/arm/amba_fake.cc | 91 +++++ src/dev/arm/amba_fake.hh | 74 ++++ src/dev/arm/gic.cc | 459 ++++++++++++++++++++++ src/dev/arm/gic.hh | 241 ++++++++++++ src/dev/arm/pl011.cc | 292 ++++++++++++++ src/dev/arm/pl011.hh | 174 ++++++++ src/dev/arm/{versatile.cc => realview.cc} | 30 +- src/dev/arm/{versatile.hh => realview.hh} | 16 +- src/dev/arm/rv_ctrl.cc | 113 ++++++ src/dev/arm/rv_ctrl.hh | 123 ++++++ src/dev/arm/timer_sp804.cc | 237 +++++++++++ src/dev/arm/timer_sp804.hh | 167 ++++++++ 18 files changed, 2391 insertions(+), 87 deletions(-) create mode 100644 src/dev/arm/RealView.py delete mode 100644 src/dev/arm/Versatile.py create mode 100644 src/dev/arm/amba_device.cc create mode 100644 src/dev/arm/amba_device.hh create mode 100644 src/dev/arm/amba_fake.cc create mode 100644 src/dev/arm/amba_fake.hh create mode 100644 src/dev/arm/gic.cc create mode 100644 src/dev/arm/gic.hh create mode 100644 src/dev/arm/pl011.cc create mode 100644 src/dev/arm/pl011.hh rename src/dev/arm/{versatile.cc => realview.cc} (86%) rename src/dev/arm/{versatile.hh => realview.hh} (92%) create mode 100644 src/dev/arm/rv_ctrl.cc create mode 100644 src/dev/arm/rv_ctrl.hh create mode 100644 src/dev/arm/timer_sp804.cc create mode 100644 src/dev/arm/timer_sp804.hh diff --git a/src/base/intmath.hh b/src/base/intmath.hh index a2960e750..b8c83f05a 100644 --- a/src/base/intmath.hh +++ b/src/base/intmath.hh @@ -33,6 +33,7 @@ #include +#include "base/misc.hh" #include "base/types.hh" // Returns the prime number one less than n. @@ -74,6 +75,27 @@ isPowerOf2(T n) return n != 0 && leastSigBit(n) == n; } +inline uint64_t +power(uint32_t n, uint32_t e) +{ + if (e > 20) + warn("Warning, power() function is quite slow for large exponents\n"); + + if (e == 0) + return 1; + + uint64_t result = n; + uint64_t old_result = 0; + for (int x = 1; x < e; x++) { + old_result = result; + result *= n; + if (old_result > result) + warn("power() overflowed!\n"); + } + return result; +} + + inline int floorLog2(unsigned x) { diff --git a/src/dev/arm/RealView.py b/src/dev/arm/RealView.py new file mode 100644 index 000000000..27d1e6b45 --- /dev/null +++ b/src/dev/arm/RealView.py @@ -0,0 +1,212 @@ +# Copyright (c) 2009 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi +# Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr +from Platform import Platform +from Terminal import Terminal +from Uart import Uart + +class AmbaDevice(BasicPioDevice): + type = 'AmbaDevice' + abstract = True + amba_id = Param.UInt32("ID of AMBA device for kernel detection") + +class RealViewCtrl(BasicPioDevice): + type = 'RealViewCtrl' + proc_id = Param.UInt32(0x0C000000, "Platform ID") + +class Gic(PioDevice): + type = 'Gic' + dist_addr = Param.Addr(0x1f001000, "Address for distributor") + cpu_addr = Param.Addr(0x1f000100, "Address for cpu") + dist_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to distributor") + cpu_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to cpu") + it_lines = Param.UInt32(128, "Number of interrupt lines supported (max = 1020)") + +class AmbaFake(AmbaDevice): + type = 'AmbaFake' + ignore_access = Param.Bool(False, "Ignore reads/writes to this device, (e.g. IsaFake + AMBA)") + amba_id = 0; + +class Pl011(Uart): + type = 'Pl011' + gic = Param.Gic(Parent.any, "Gic to use for interrupting") + int_num = Param.UInt32("Interrupt number 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") + +class Sp804(AmbaDevice): + type = 'Sp804' + gic = Param.Gic(Parent.any, "Gic to use for interrupting") + int_num0 = Param.UInt32("Interrupt number that connects to GIC") + clock0 = Param.Clock('1MHz', "Clock speed of the input") + int_num1 = Param.UInt32("Interrupt number that connects to GIC") + clock1 = Param.Clock('1MHz', "Clock speed of the input") + amba_id = 0x00141804 + +class RealView(Platform): + type = 'RealView' + system = Param.System(Parent.any, "system") + +class RealViewPBX(RealView): + uart = Pl011(pio_addr=0x10009000, int_num=44) + realview_io = RealViewCtrl(pio_addr=0x10000000) + gic = Gic() + timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000) + timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000) + + l2x0_fake = IsaFake(pio_addr=0x1f002000, pio_size=0xfff, warn_access="1") + dmac_fake = AmbaFake(pio_addr=0x10030000) + uart1_fake = AmbaFake(pio_addr=0x1000a000) + uart2_fake = AmbaFake(pio_addr=0x1000b000) + uart3_fake = AmbaFake(pio_addr=0x1000c000) + smc_fake = AmbaFake(pio_addr=0x100e1000) + clcd_fake = AmbaFake(pio_addr=0x10020000) + sp810_fake = AmbaFake(pio_addr=0x10001000, ignore_access=True) + watchdog_fake = AmbaFake(pio_addr=0x10010000) + gpio0_fake = AmbaFake(pio_addr=0x10013000) + gpio1_fake = AmbaFake(pio_addr=0x10014000) + gpio2_fake = AmbaFake(pio_addr=0x10015000) + ssp_fake = AmbaFake(pio_addr=0x1000d000) + sci_fake = AmbaFake(pio_addr=0x1000e000) + aaci_fake = AmbaFake(pio_addr=0x10004000) + mmc_fake = AmbaFake(pio_addr=0x10005000) + kmi0_fake = AmbaFake(pio_addr=0x10006000) + kmi1_fake = AmbaFake(pio_addr=0x10007000) + rtc_fake = AmbaFake(pio_addr=0x10017000, amba_id=0x41031) + + + + # Attach I/O devices that are on chip + def attachOnChipIO(self, bus): + self.gic.pio = bus.port + self.l2x0_fake.pio = bus.port + + # Attach I/O devices to specified bus object. Can't do this + # earlier, since the bus object itself is typically defined at the + # System level. + def attachIO(self, bus): + self.uart.pio = bus.port + self.realview_io.pio = bus.port + self.timer0.pio = bus.port + self.timer1.pio = bus.port + self.dmac_fake.pio = bus.port + self.uart1_fake.pio = bus.port + self.uart2_fake.pio = bus.port + self.uart3_fake.pio = bus.port + self.smc_fake.pio = bus.port + self.clcd_fake.pio = bus.port + self.sp810_fake.pio = bus.port + self.watchdog_fake.pio = bus.port + self.gpio0_fake.pio = bus.port + self.gpio1_fake.pio = bus.port + self.gpio2_fake.pio = bus.port + self.ssp_fake.pio = bus.port + self.sci_fake.pio = bus.port + self.aaci_fake.pio = bus.port + self.mmc_fake.pio = bus.port + self.kmi0_fake.pio = bus.port + self.kmi1_fake.pio = bus.port + self.rtc_fake.pio = bus.port + +class RealViewEB(RealView): + uart = Pl011(pio_addr=0x10009000, int_num=44) + realview_io = RealViewCtrl(pio_addr=0x10000000) + gic = Gic(dist_addr=0x10041000, cpu_addr=0x10040000) + timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000) + timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000) + + l2x0_fake = IsaFake(pio_addr=0x1f002000, pio_size=0xfff, warn_access="1") + dmac_fake = AmbaFake(pio_addr=0x10030000) + uart1_fake = AmbaFake(pio_addr=0x1000a000) + uart2_fake = AmbaFake(pio_addr=0x1000b000) + uart3_fake = AmbaFake(pio_addr=0x1000c000) + smc_fake = AmbaFake(pio_addr=0x100e1000) + clcd_fake = AmbaFake(pio_addr=0x10020000) + sp810_fake = AmbaFake(pio_addr=0x10001000, ignore_access=True) + watchdog_fake = AmbaFake(pio_addr=0x10010000) + gpio0_fake = AmbaFake(pio_addr=0x10013000) + gpio1_fake = AmbaFake(pio_addr=0x10014000) + gpio2_fake = AmbaFake(pio_addr=0x10015000) + ssp_fake = AmbaFake(pio_addr=0x1000d000) + sci_fake = AmbaFake(pio_addr=0x1000e000) + aaci_fake = AmbaFake(pio_addr=0x10004000) + mmc_fake = AmbaFake(pio_addr=0x10005000) + kmi0_fake = AmbaFake(pio_addr=0x10006000) + kmi1_fake = AmbaFake(pio_addr=0x10007000) + rtc_fake = AmbaFake(pio_addr=0x10017000, amba_id=0x41031) + + + + # Attach I/O devices that are on chip + def attachOnChipIO(self, bus): + self.gic.pio = bus.port + self.l2x0_fake.pio = bus.port + + # Attach I/O devices to specified bus object. Can't do this + # earlier, since the bus object itself is typically defined at the + # System level. + def attachIO(self, bus): + self.uart.pio = bus.port + self.realview_io.pio = bus.port + self.timer0.pio = bus.port + self.timer1.pio = bus.port + self.dmac_fake.pio = bus.port + self.uart1_fake.pio = bus.port + self.uart2_fake.pio = bus.port + self.uart3_fake.pio = bus.port + self.smc_fake.pio = bus.port + self.clcd_fake.pio = bus.port + self.sp810_fake.pio = bus.port + self.watchdog_fake.pio = bus.port + self.gpio0_fake.pio = bus.port + self.gpio1_fake.pio = bus.port + self.gpio2_fake.pio = bus.port + self.ssp_fake.pio = bus.port + self.sci_fake.pio = bus.port + self.aaci_fake.pio = bus.port + self.mmc_fake.pio = bus.port + self.kmi0_fake.pio = bus.port + self.kmi1_fake.pio = bus.port + self.rtc_fake.pio = bus.port + diff --git a/src/dev/arm/SConscript b/src/dev/arm/SConscript index 7b7628fbf..423bf1726 100644 --- a/src/dev/arm/SConscript +++ b/src/dev/arm/SConscript @@ -40,6 +40,14 @@ Import('*') if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'arm': - SimObject('Versatile.py') + SimObject('RealView.py') - Source('versatile.cc') + Source('amba_device.cc') + Source('amba_fake.cc') + Source('gic.cc') + Source('pl011.cc') + Source('timer_sp804.cc') + Source('rv_ctrl.cc') + Source('realview.cc') + + TraceFlag('AMBA') diff --git a/src/dev/arm/Versatile.py b/src/dev/arm/Versatile.py deleted file mode 100644 index bc7063076..000000000 --- a/src/dev/arm/Versatile.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright (c) 2009 ARM Limited -# All rights reserved. -# -# The license below extends only to copyright in the software and shall -# not be construed as granting a license to any other intellectual -# property including but not limited to intellectual property relating -# to a hardware implementation of the functionality of the software -# licensed hereunder. You may use the software subject to the license -# terms below provided that you ensure that this notice is replicated -# unmodified and in its entirety in all distributions of the software, -# modified or unmodified, in source code or in binary form. -# -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Gabe Black - -from m5.params import * -from m5.proxy import * -from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr -from Platform import Platform -from Terminal import Terminal -from Uart import Uart8250 - - -class Versatile(Platform): - type = 'Versatile' - system = Param.System(Parent.any, "system") - - # Attach I/O devices that are on chip - def attachOnChipIO(self, bus): - pass - - - # Attach I/O devices to specified bus object. Can't do this - # earlier, since the bus object itself is typically defined at the - # System level. - def attachIO(self, bus): - pass diff --git a/src/dev/arm/amba_device.cc b/src/dev/arm/amba_device.cc new file mode 100644 index 000000000..81c740aec --- /dev/null +++ b/src/dev/arm/amba_device.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "base/trace.hh" +#include "dev/arm/amba_fake.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +AmbaDevice::AmbaDevice(const Params *p) + : BasicPioDevice(p), ambaId(ULL(0xb105f00d00000000) | p->amba_id) +{ +} + +bool +AmbaDevice::readId(PacketPtr pkt) +{ + Addr daddr = pkt->getAddr() - pioAddr; + if (daddr < AMBA_PER_ID0 || daddr > AMBA_CEL_ID3) + return false; + + pkt->allocate(); + + daddr -= AMBA_PER_ID0; + daddr <<= 1; + // Too noisy right now + //DPRINTF(AMBA, "Returning %#x for offset %#x(%d)\n", (ambaId >> daddr) & 0xFF, + // pkt->getAddr() - pioAddr, daddr); + assert(pkt->getSize() == 4); + pkt->set((ambaId >> daddr) & 0xFF); + return true; +} + diff --git a/src/dev/arm/amba_device.hh b/src/dev/arm/amba_device.hh new file mode 100644 index 000000000..b2d7af043 --- /dev/null +++ b/src/dev/arm/amba_device.hh @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + + +/** @file + * This is a base class for AMBA devices that have to respond to Device and + * Implementer ID calls. + */ + +#ifndef __DEV_ARM_AMBA_DEVICE_H__ +#define __DEV_ARM_AMBA_DEVICE_H__ + +#include "base/range.hh" +#include "dev/io_device.hh" +#include "params/AmbaDevice.hh" + +class AmbaDevice : public BasicPioDevice +{ + protected: + static const int AMBA_PER_ID0 = 0xFE0; + static const int AMBA_PER_ID1 = 0xFE4; + static const int AMBA_PER_ID2 = 0xFE8; + static const int AMBA_PER_ID3 = 0xFEC; + static const int AMBA_CEL_ID0 = 0xFF0; + static const int AMBA_CEL_ID1 = 0xFF4; + static const int AMBA_CEL_ID2 = 0xFF8; + static const int AMBA_CEL_ID3 = 0xFFC; + + uint64_t ambaId; + + public: + typedef AmbaDeviceParams Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + AmbaDevice(const Params *p); + + bool readId(PacketPtr pkt); +}; + +#endif //__DEV_ARM_AMBA_FAKE_H__ diff --git a/src/dev/arm/amba_fake.cc b/src/dev/arm/amba_fake.cc new file mode 100644 index 000000000..25206c674 --- /dev/null +++ b/src/dev/arm/amba_fake.cc @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "base/trace.hh" +#include "dev/arm/amba_fake.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +AmbaFake::AmbaFake(const Params *p) + : AmbaDevice(p) +{ + pioSize = 0xfff; +} + +Tick +AmbaFake::read(PacketPtr pkt) +{ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + + Addr daddr = pkt->getAddr() - pioAddr; + pkt->allocate(); + + DPRINTF(AMBA, " read register %#x\n", daddr); + + pkt->set(0); + if (!readId(pkt) && !params()->ignore_access) + panic("Tried to read AmbaFake at offset %#x that doesn't exist\n", daddr); + + pkt->makeAtomicResponse(); + return pioDelay; +} + +Tick +AmbaFake::write(PacketPtr pkt) +{ + + Addr daddr = pkt->getAddr() - pioAddr; + pkt->allocate(); + + if (!params()->ignore_access) + panic("Tried to write AmbaFake at offset %#x that doesn't exist\n", daddr); + + pkt->makeAtomicResponse(); + return pioDelay; +} + + +AmbaFake * +AmbaFakeParams::create() +{ + return new AmbaFake(this); +} diff --git a/src/dev/arm/amba_fake.hh b/src/dev/arm/amba_fake.hh new file mode 100644 index 000000000..4a67ab9d5 --- /dev/null +++ b/src/dev/arm/amba_fake.hh @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + + +/** @file + * This device sits in memory and reponds appropriately so the linux kernel + * ignores the device it is trying to talk to. It is used so the kernel doesn't + * need to be modified and devices that we are not interested in will simply be + * skipped. + */ + +#ifndef __DEV_ARM_AMBA_FAKE_H__ +#define __DEV_ARM_AMBA_FAKE_H__ + +#include "base/range.hh" +#include "dev/arm/amba_device.hh" +#include "params/AmbaFake.hh" + +class AmbaFake : public AmbaDevice +{ + public: + typedef AmbaFakeParams Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + AmbaFake(const Params *p); + + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); + +}; + +#endif //__DEV_ARM_AMBA_FAKE_H__ diff --git a/src/dev/arm/gic.cc b/src/dev/arm/gic.cc new file mode 100644 index 000000000..87d0d17b7 --- /dev/null +++ b/src/dev/arm/gic.cc @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "base/trace.hh" +#include "cpu/intr_control.hh" +#include "dev/arm/gic.hh" +#include "dev/platform.hh" +#include "dev/terminal.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +Gic::Gic(const Params *p) + : PioDevice(p),distAddr(p->dist_addr), cpuAddr(p->cpu_addr), + distPioDelay(p->dist_pio_delay), cpuPioDelay(p->cpu_pio_delay), + enabled(false), itLines(p->it_lines) +{ + itLinesLog2 = ceilLog2(itLines); + + for (int x = 0; x < 8; x++) { + cpuEnabled[x] = false; + cpuPriority[x] = 0; + cpuBpr[x] = 0; + } + + for (int x = 0; x < 32; x++) { + intEnabled[x] = 0; + pendingInt[x] = 0; + activeInt[x] = 0; + } + + for (int x = 0; x < 1020; x++) { + intPriority[x] = 0; + cpuTarget[x] = 0; + } + + for (int x = 0; x < 64; x++) { + intConfig[x] = 0; + } +} + +Tick +Gic::read(PacketPtr pkt) +{ + + Addr addr = pkt->getAddr(); + + if (addr >= distAddr && addr < distAddr + DIST_SIZE) + return readDistributor(pkt); + else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE) + return readCpu(pkt); + else + panic("Read to unknown address %#x\n", pkt->getAddr()); +} + + +Tick +Gic::write(PacketPtr pkt) +{ + + Addr addr = pkt->getAddr(); + + if (addr >= distAddr && addr < distAddr + DIST_SIZE) + return writeDistributor(pkt); + else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE) + return writeCpu(pkt); + else + panic("Write to unknown address %#x\n", pkt->getAddr()); +} + +Tick +Gic::readDistributor(PacketPtr pkt) +{ + Addr daddr = pkt->getAddr() - distAddr; + pkt->allocate(); + + DPRINTF(Interrupt, "gic distributor read register %#x\n", daddr); + + if (daddr >= ICDISER_ST && daddr < ICDISER_ED + 4) { + assert((daddr-ICDISER_ST) >> 2 < 32); + pkt->set(intEnabled[(daddr-ICDISER_ST)>>2]); + goto done; + } + + if (daddr >= ICDICER_ST && daddr < ICDICER_ED + 4) { + assert((daddr-ICDICER_ST) >> 2 < 32); + pkt->set(intEnabled[(daddr-ICDICER_ST)>>2]); + goto done; + } + + if (daddr >= ICDISPR_ST && daddr < ICDISPR_ED + 4) { + assert((daddr-ICDISPR_ST) >> 2 < 32); + pkt->set(pendingInt[(daddr-ICDISPR_ST)>>2]); + goto done; + } + + if (daddr >= ICDICPR_ST && daddr < ICDICPR_ED + 4) { + assert((daddr-ICDICPR_ST) >> 2 < 32); + pkt->set(pendingInt[(daddr-ICDICPR_ST)>>2]); + goto done; + } + + if (daddr >= ICDABR_ST && daddr < ICDABR_ED + 4) { + assert((daddr-ICDABR_ST) >> 2 < 32); + pkt->set(activeInt[(daddr-ICDABR_ST)>>2]); + goto done; + } + + if (daddr >= ICDIPR_ST && daddr < ICDIPR_ED + 4) { + Addr int_num; + int_num = (daddr-ICDIPR_ST) << 2; + assert(int_num < 1020); + + pkt->set(intPriority[int_num] | + intPriority[int_num+1] << 8 | + intPriority[int_num+2] << 16 | + intPriority[int_num+3] << 24) ; + goto done; + } + + if (daddr >= ICDIPTR_ST && daddr < ICDIPTR_ED + 4) { + Addr int_num; + int_num = (daddr-ICDIPTR_ST) << 2; + assert(int_num < 1020); + + // First 31 interrupts only target single processor + if (int_num > 31) { + pkt->set(cpuTarget[int_num] | + cpuTarget[int_num+1] << 8 | + cpuTarget[int_num+2] << 16 | + cpuTarget[int_num+3] << 24) ; + } else { + /** @todo should be processor id */ + pkt->set(0); + } + goto done; + } + + if (daddr >= ICDICFR_ST && daddr < ICDICFR_ED + 4) { + assert((daddr-ICDICFR_ST) >> 2 < 64); + /** @todo software generated interrutps and PPIs + * can't be configured in some ways + */ + pkt->set(intConfig[(daddr-ICDICFR_ST)>>2]); + goto done; + } + + switch(daddr) { + case ICDDCR: + pkt->set(enabled); + break; + case ICDICTR: + /* @todo this needs to refelct the number of CPUs in the system */ + uint32_t tmp; + tmp = 0 << 5 | // cpu number + (itLines/32 -1); + pkt->set(tmp); + break; + default: + panic("Tried to read Gic distributor at offset %#x\n", daddr); + break; + } +done: + pkt->makeAtomicResponse(); + return distPioDelay; +} + +Tick +Gic::readCpu(PacketPtr pkt) +{ + Addr daddr = pkt->getAddr() - cpuAddr; + pkt->allocate(); + + DPRINTF(Interrupt, "gic cpu read register %#x\n", daddr); + + switch(daddr) { + case ICCICR: + pkt->set(cpuEnabled[0]); + break; + case ICCPMR: + pkt->set(cpuPriority[0]); + break; + case ICCBPR: + pkt->set(cpuBpr[0]); + break; + case ICCIAR: + DPRINTF(Interrupt, "CPU reading IAR = %d\n", cpuHighestInt[0]); + pkt->set(cpuHighestInt[0]); + activeInt[intNumToWord(cpuHighestInt[0])] |= + 1 << intNumToBit(cpuHighestInt[0]); + pendingInt[intNumToWord(cpuHighestInt[0])] &= + ~(1 << intNumToBit(cpuHighestInt[0])); + cpuHighestInt[0] = SPURIOUS_INT; + updateIntState(-1); + platform->intrctrl->clear(0, ArmISA::INT_IRQ, 0); + break; + case ICCRPR: + pkt->set(0); + panic("Need to implement RPR"); + break; + case ICCHPIR: + pkt->set(0); + panic("Need to implement HPIR"); + break; + default: + panic("Tried to read Gic cpu at offset %#x\n", daddr); + break; + } + pkt->makeAtomicResponse(); + return cpuPioDelay; +} + + +Tick +Gic::writeDistributor(PacketPtr pkt) +{ + Addr daddr = pkt->getAddr() - distAddr; + pkt->allocate(); + + DPRINTF(Interrupt, "gic distributor write register %#x val: %#x\n", + daddr, pkt->get()); + + if (daddr >= ICDISER_ST && daddr < ICDISER_ED + 4) { + assert((daddr-ICDISER_ST) >> 2 < 32); + intEnabled[(daddr-ICDISER_ST)>>2] |= pkt->get(); + goto done; + } + + if (daddr >= ICDICER_ST && daddr < ICDICER_ED + 4) { + assert((daddr-ICDICER_ST) >> 2 < 32); + intEnabled[(daddr-ICDICER_ST)>>2] &= ~pkt->get(); + goto done; + } + + if (daddr >= ICDISPR_ST && daddr < ICDISPR_ED + 4) { + assert((daddr-ICDISPR_ST) >> 2 < 32); + pendingInt[(daddr-ICDISPR_ST)>>2] |= pkt->get(); + updateIntState((daddr-ICDISPR_ST)>>2); + goto done; + } + + if (daddr >= ICDICPR_ST && daddr < ICDICPR_ED + 4) { + assert((daddr-ICDICPR_ST) >> 2 < 32); + pendingInt[(daddr-ICDICPR_ST)>>2] &= ~pkt->get(); + updateIntState((daddr-ICDICPR_ST)>>2); + goto done; + } + + if (daddr >= ICDIPR_ST && daddr < ICDIPR_ED + 4) { + Addr int_num = (daddr-ICDIPR_ST) << 2; + assert(int_num < 1020); + uint32_t tmp = pkt->get(); + intPriority[int_num] = tmp & 0xff; + intPriority[int_num+1] = (tmp >> 8) & 0xff; + intPriority[int_num+2] = (tmp >> 16) & 0xff; + intPriority[int_num+3] = (tmp >> 24) & 0xff; + updateIntState((daddr-ICDIPR_ST)>>2); + goto done; + } + + if (daddr >= ICDIPTR_ST && daddr < ICDIPTR_ED + 4) { + Addr int_num = (daddr-ICDIPTR_ST) << 2; + assert(int_num < 1020); + + // First 31 interrupts only target single processor + if (int_num > 31) { + uint32_t tmp = pkt->get(); + cpuTarget[int_num] = tmp & 0xff; + cpuTarget[int_num+1] = (tmp >> 8) & 0xff; + cpuTarget[int_num+2] = (tmp >> 16) & 0xff; + cpuTarget[int_num+3] = (tmp >> 24) & 0xff; + updateIntState((daddr-ICDIPTR_ST)>>2); + } + goto done; + } + + if (daddr >= ICDICFR_ST && daddr < ICDICFR_ED + 4) { + assert((daddr-ICDICFR_ST) >> 2 < 64); + intConfig[(daddr-ICDICFR_ST)>>2] = pkt->get(); + goto done; + } + + switch(daddr) { + case ICDDCR: + enabled = pkt->get(); + break; + case ICDSGIR: + softInt(pkt->get()); + break; + default: + panic("Tried to write Gic distributor at offset %#x\n", daddr); + break; + } + +done: + pkt->makeAtomicResponse(); + return distPioDelay; +} + +Tick +Gic::writeCpu(PacketPtr pkt) +{ + Addr daddr = pkt->getAddr() - cpuAddr; + pkt->allocate(); + + DPRINTF(Interrupt, "gic cpu write register %#x val: %#x\n", + daddr, pkt->get()); + + switch(daddr) { + case ICCICR: + cpuEnabled[0] = pkt->get(); + updateIntState(-1); + break; + case ICCPMR: + cpuPriority[0] = pkt->get(); + updateIntState(-1); + break; + case ICCBPR: + cpuBpr[0] = pkt->get(); + updateIntState(-1); + break; + case ICCEOIR: + uint32_t tmp; + tmp = pkt->get(); + if (!(activeInt[intNumToWord(tmp)] & (1 << intNumToBit(tmp)))) + panic("Done handling interrupt that isn't active?\n"); + activeInt[intNumToWord(tmp)] &= ~(1 << intNumToBit(tmp)); + DPRINTF(Interrupt, "CPU done handling interrupt IAR = %d\n", tmp); + break; + default: + panic("Tried to write Gic cpu at offset %#x\n", daddr); + break; + } + pkt->makeAtomicResponse(); + return cpuPioDelay; +} + +void +Gic::softInt(SWI swi) +{ + warn("Should be causing software interrupt"); +} + +void +Gic::updateIntState(int hint) +{ + /*@todo use hint to do less work. */ + int highest_int = -1; + uint8_t highest_pri = 0xff; + + for (int x = 0; x < itLinesLog2; x++) { + if (intEnabled[x] & pendingInt[x]) { + for (int y = 0; y < 32; y++) { + if (bits(intEnabled[x], y) & bits(pendingInt[x], y)) + if (intPriority[x*32+y] < highest_pri) { + highest_pri = intPriority[x*32+y]; + highest_int = x*32 + y; + } + } + } + } + + if (highest_int == -1) + return; + + cpuHighestInt[0] = highest_int; + + + /* @todo make this work for more than one cpu, need to handle 1:N, N:N + * models */ + if (cpuEnabled[0] && highest_pri < cpuPriority[0]) { + /* @todo delay interrupt by some time to deal with calculation delay */ + /* @todo only interrupt if we've haven't already interrupted for this + * int !!!!!!!!!! */ + DPRINTF(Interrupt, "Posting interrupt %d to cpu0\n", highest_int); + platform->intrctrl->post(0, ArmISA::INT_IRQ, 0); + } +} + + +void +Gic::sendInt(uint32_t num) +{ + DPRINTF(Interrupt, "Received Interupt number %d\n", num); + pendingInt[intNumToWord(num)] |= 1 << intNumToBit(num); + updateIntState(intNumToWord(num)); + +} + +void +Gic::clearInt(uint32_t number) +{ + /* @todo assume edge triggered only at the moment. Nothing to do. */ +} + +void +Gic::addressRanges(AddrRangeList &range_list) +{ + range_list.clear(); + range_list.push_back(RangeSize(distAddr, DIST_SIZE)); + range_list.push_back(RangeSize(cpuAddr, CPU_SIZE)); +} + + +void +Gic::serialize(std::ostream &os) +{ + panic("Need to implement serialization\n"); +} + +void +Gic::unserialize(Checkpoint *cp, const std::string §ion) +{ + panic("Need to implement serialization\n"); +} + +Gic * +GicParams::create() +{ + return new Gic(this); +} diff --git a/src/dev/arm/gic.hh b/src/dev/arm/gic.hh new file mode 100644 index 000000000..6ec83a58c --- /dev/null +++ b/src/dev/arm/gic.hh @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + + +/** @file + * Implementiation of a PL390 GIC + */ + +#ifndef __DEV_ARM_GIC_H__ +#define __DEV_ARM_GIC_H__ + +#include "base/bitunion.hh" +#include "base/range.hh" +#include "dev/io_device.hh" +#include "params/Gic.hh" + +/** @todo this code only assumes one processor for now. Low word + * of intEnabled and pendingInt need to be replicated per CPU. + * bottom 31 interrupts (7 words) need to be replicated for + * for interrupt priority register, processor target registers + * interrupt config registers */ + +class Gic : public PioDevice +{ + protected: + // distributor memory addresses + static const int ICDDCR = 0x000; // control register + static const int ICDICTR = 0x004; // controller type + static const int ICDIIDR = 0x008; // implementer id + static const int ICDISER_ST = 0x100; // interrupt set enable + static const int ICDISER_ED = 0x17c; + static const int ICDICER_ST = 0x180; // interrupt clear enable + static const int ICDICER_ED = 0x1fc; + static const int ICDISPR_ST = 0x200; // set pending interrupt + static const int ICDISPR_ED = 0x27c; + static const int ICDICPR_ST = 0x280; // clear pending interrupt + static const int ICDICPR_ED = 0x2fc; + static const int ICDABR_ST = 0x300; // active bit registers + static const int ICDABR_ED = 0x37c; + static const int ICDIPR_ST = 0x400; // interrupt priority registers + static const int ICDIPR_ED = 0x7f8; + static const int ICDIPTR_ST = 0x800; // processor target registers + static const int ICDIPTR_ED = 0xbf8; + static const int ICDICFR_ST = 0xc00; // interrupt config registers + static const int ICDICFR_ED = 0xcfc; + static const int ICDSGIR = 0xf00; // software generated interrupt + static const int DIST_SIZE = 0xfff; + + // cpu memory addressesa + static const int ICCICR = 0x00; // CPU control register + static const int ICCPMR = 0x04; // Interrupt priority mask + static const int ICCBPR = 0x08; // binary point register + static const int ICCIAR = 0x0C; // interrupt ack register + static const int ICCEOIR = 0x10; // end of interrupt + static const int ICCRPR = 0x14; // runing priority + static const int ICCHPIR = 0x18; // highest pending interrupt + static const int ICCABPR = 0x1c; // aliased binary point + static const int ICCIIDR = 0xfc; // cpu interface id register + static const int CPU_SIZE = 0xff; + + static const int SPURIOUS_INT = 1023; + + BitUnion32(SWI) + Bitfield<3,0> sgi_id; + Bitfield<23,16> cpu_list; + Bitfield<25,24> list_type; + EndBitUnion(SWI) + + /** Distributor address GIC listens at */ + Addr distAddr; + + /** CPU address GIC listens at */ + /** @todo is this one per cpu? */ + Addr cpuAddr; + + /** Latency for a distributor operation */ + Tick distPioDelay; + + /** Latency for a cpu operation */ + Tick cpuPioDelay; + + /** Gic enabled */ + bool enabled; + + /** Number of itLines enabled */ + uint32_t itLines; + + uint32_t itLinesLog2; + + /** interrupt enable bits for all possible 1020 interupts. + * one bit per interrupt, 32 bit per word = 32 words */ + uint32_t intEnabled[32]; + + /** interrupt pending bits for all possible 1020 interupts. + * one bit per interrupt, 32 bit per word = 32 words */ + uint32_t pendingInt[32]; + + /** interrupt active bits for all possible 1020 interupts. + * one bit per interrupt, 32 bit per word = 32 words */ + uint32_t activeInt[32]; + + /** an 8 bit priority (lower is higher priority) for each + * of the 1020 possible supported interrupts. + */ + uint8_t intPriority[1020]; + + /** an 8 bit cpu target id for each shared peripheral interrupt + * of the 1020 possible supported interrupts. + */ + uint8_t cpuTarget[1020]; + + /** 2 bit per interrupt signaling if it's level or edge sensitive + * and if it is 1:N or N:N */ + uint32_t intConfig[64]; + + /** CPU enabled */ + bool cpuEnabled[8]; + + /** CPU priority */ + uint8_t cpuPriority[8]; + + /** Binary point registers */ + uint8_t cpuBpr[8]; + + /** highest interrupt that is interrupting CPU */ + uint32_t cpuHighestInt[8]; + + /** software generated interrupt + * @param data data to decode that indicates which cpus to interrupt + */ + void softInt(SWI swi); + + /** See if some processor interrupt flags need to be enabled/disabled + * @param hint which set of interrupts needs to be checked + */ + void updateIntState(int hint); + + int intNumToWord(int num) const { return num >> 5; } + int intNumToBit(int num) const { return num % 32; } + + public: + typedef GicParams Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + Gic(const Params *p); + + /** Return the address ranges used by the Gic + * This is the distributor address + all cpu addresses + */ + virtual void addressRanges(AddrRangeList &range_list); + + /** A PIO read to the device, immediately split up into + * readDistributor() or readCpu() + */ + virtual Tick read(PacketPtr pkt); + + /** A PIO read to the device, immediately split up into + * writeDistributor() or writeCpu() + */ + virtual Tick write(PacketPtr pkt); + + /** Handle a read to the distributor poriton of the GIC + * @param pkt packet to respond to + */ + Tick readDistributor(PacketPtr pkt); + + /** Handle a read to the cpu poriton of the GIC + * @param pkt packet to respond to + */ + Tick readCpu(PacketPtr pkt); + + /** Handle a write to the distributor poriton of the GIC + * @param pkt packet to respond to + */ + Tick writeDistributor(PacketPtr pkt); + + /** Handle a write to the cpu poriton of the GIC + * @param pkt packet to respond to + */ + Tick writeCpu(PacketPtr pkt); + + /** Post an interrupt from a device that is connected to the Gic. + * Depending on the configuration, the gic will pass this interrupt + * on through to a CPU. + * @param number number of interrupt to send */ + void sendInt(uint32_t number); + + /** Clear an interrupt from a device that is connected to the Gic + * Depending on the configuration, the gic may de-assert it's cpu line + * @param number number of interrupt to send */ + void clearInt(uint32_t number); + + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + +}; + +#endif //__DEV_ARM_GIC_H__ diff --git a/src/dev/arm/pl011.cc b/src/dev/arm/pl011.cc new file mode 100644 index 000000000..2afc9977d --- /dev/null +++ b/src/dev/arm/pl011.cc @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "base/trace.hh" +#include "dev/arm/gic.hh" +#include "dev/arm/pl011.hh" +#include "dev/terminal.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "sim/sim_exit.hh" + +Pl011::Pl011(const Params *p) + : Uart(p), control(0x300), fbrd(0), ibrd(0), lcrh(0), ifls(0x12), imsc(0), + rawInt(0), maskInt(0), intNum(p->int_num), gic(p->gic), + endOnEOT(p->end_on_eot), intDelay(p->int_delay), intEvent(this) +{ + pioSize = 0xfff; +} + +Tick +Pl011::read(PacketPtr pkt) +{ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + + Addr daddr = pkt->getAddr() - pioAddr; + pkt->allocate(); + + DPRINTF(Uart, " read register %#x size=%d\n", daddr, pkt->getSize()); + + // use a temporary data since the uart registers are read/written with + // different size operations + // + uint32_t data = 0; + + switch(daddr) { + case UART_DR: + data = 0; + if (term->dataAvailable()) + data = term->in(); + break; + case UART_FR: + // For now we're infintely fast, so TX is never full, always empty, + // always clear to send + data = UART_FR_TXFE | UART_FR_CTS; + if (!term->dataAvailable()) + data |= UART_FR_RXFE; + DPRINTF(Uart, "Reading FR register as %#x rawInt=0x%x imsc=0x%x maskInt=0x%x\n", + data, rawInt, imsc, maskInt); + break; + case UART_CR: + data = control; + break; + case UART_IBRD: + data = ibrd; + break; + case UART_FBRD: + data = fbrd; + break; + case UART_LCRH: + data = lcrh; + break; + case UART_IFLS: + data = ifls; + break; + case UART_IMSC: + data = imsc; + break; + case UART_RIS: + data = rawInt; + DPRINTF(Uart, "Reading Raw Int status as 0x%x\n", rawInt); + break; + case UART_MIS: + DPRINTF(Uart, "Reading Masked Int status as 0x%x\n", rawInt); + data = maskInt; + break; + default: + if (daddr >= UART_PER_ID0 && daddr <= UART_CEL_ID3) { + // AMBA ID information + int byte; + byte = (daddr - UART_PER_ID0) << 1; + DPRINTF(AMBA, "--daddr=%#x shift=%d val=%#x\n", daddr, byte, + (ULL(0xb105f00d00341011) >> byte) & 0xFF); + data = (ULL(0xb105f00d00341011) >> byte) & 0xFF; + break; + } + panic("Tried to read PL011 at offset %#x that doesn't exist\n", daddr); + break; + } + + switch(pkt->getSize()) { + case 1: + pkt->set(data); + break; + case 2: + pkt->set(data); + break; + case 4: + pkt->set(data); + break; + default: + panic("Uart read size too big?\n"); + break; + } + + + pkt->makeAtomicResponse(); + return pioDelay; +} + +Tick +Pl011::write(PacketPtr pkt) +{ + + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + + Addr daddr = pkt->getAddr() - pioAddr; + + DPRINTF(Uart, " write register %#x value %#x size=%d\n", daddr, + pkt->get(), pkt->getSize()); + + // use a temporary data since the uart registers are read/written with + // different size operations + // + uint32_t data = 0; + + switch(pkt->getSize()) { + case 1: + data = pkt->get(); + break; + case 2: + data = pkt->get(); + break; + case 4: + data = pkt->get(); + break; + default: + panic("Uart write size too big?\n"); + break; + } + + + switch (daddr) { + case UART_DR: + if ((data & 0xFF) == 0x04 && endOnEOT) + exitSimLoop("UART received EOT", 0); + + term->out(data & 0xFF); + + if (imsc.txim) { + DPRINTF(Uart, "TX int enabled, scheduling interruptt\n"); + rawInt.txim = 1; + if (!intEvent.scheduled()) + schedule(intEvent, curTick + intDelay); + } + + break; + case UART_CR: + control = data; + break; + case UART_IBRD: + ibrd = data; + break; + case UART_FBRD: + fbrd = data; + break; + case UART_LCRH: + lcrh = data; + break; + case UART_IFLS: + ifls = data; + break; + case UART_IMSC: + imsc = data; + + if (imsc.rimim || imsc.ctsmim || imsc.dcdmim || imsc.dsrmim + || imsc.feim || imsc.peim || imsc.beim || imsc.oeim || imsc.rsvd) + panic("Unknown interrupt enabled\n"); + + if (imsc.txim) { + DPRINTF(Uart, "Writing to IMSC: TX int enabled, scheduling interruptt\n"); + rawInt.txim = 1; + if (!intEvent.scheduled()) + schedule(intEvent, curTick + intDelay); + } + + break; + + case UART_ICR: + DPRINTF(Uart, "Clearing interrupts 0x%x\n", data); + rawInt = rawInt & ~data; + maskInt = rawInt & imsc; + + DPRINTF(Uart, " -- Masked interrupts 0x%x\n", maskInt); + + if (!maskInt) + gic->clearInt(intNum); + + break; + default: + panic("Tried to write PL011 at offset %#x that doesn't exist\n", daddr); + break; + } + pkt->makeAtomicResponse(); + return pioDelay; +} + +void +Pl011::dataAvailable() +{ + /*@todo ignore the fifo, just say we have data now + * We might want to fix this, or we might not care */ + rawInt.rxim = 1; + rawInt.rtim = 1; + + DPRINTF(Uart, "Data available, scheduling interrupt\n"); + + if (!intEvent.scheduled()) + schedule(intEvent, curTick + intDelay); +} + +void +Pl011::generateInterrupt() +{ + DPRINTF(Uart, "Generate Interrupt: imsc=0x%x rawInt=0x%x maskInt=0x%x\n", + imsc, rawInt, maskInt); + maskInt = imsc & rawInt; + + if (maskInt.rxim || maskInt.rtim || maskInt.txim) { + gic->sendInt(intNum); + DPRINTF(Uart, " -- Generated\n"); + } + +} + + + +void +Pl011::serialize(std::ostream &os) +{ + panic("Need to implement serialization\n"); +} + +void +Pl011::unserialize(Checkpoint *cp, const std::string §ion) +{ + panic("Need to implement serialization\n"); +} + +Pl011 * +Pl011Params::create() +{ + return new Pl011(this); +} diff --git a/src/dev/arm/pl011.hh b/src/dev/arm/pl011.hh new file mode 100644 index 000000000..63289fc38 --- /dev/null +++ b/src/dev/arm/pl011.hh @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + + +/** @file + * Implementiation of a PL011 UART + */ + +#ifndef __DEV_ARM_PL011_H__ +#define __DEV_ARM_PL011_H__ + +#include "base/range.hh" +#include "dev/io_device.hh" +#include "dev/uart.hh" +#include "params/Pl011.hh" + +class Gic; + +class Pl011 : public Uart +{ + protected: + static const int UART_DR = 0x000; + static const int UART_FR = 0x018; + static const int UART_FR_CTS = 0x001; + static const int UART_FR_TXFE = 0x080; + static const int UART_FR_RXFE = 0x010; + static const int UART_IBRD = 0x024; + static const int UART_FBRD = 0x028; + static const int UART_LCRH = 0x02C; + static const int UART_CR = 0x030; + static const int UART_IFLS = 0x034; + static const int UART_IMSC = 0x038; + static const int UART_RIS = 0x03C; + static const int UART_MIS = 0x040; + static const int UART_ICR = 0x044; + static const int UART_PER_ID0 = 0xFE0; + static const int UART_PER_ID1 = 0xFE4; + static const int UART_PER_ID2 = 0xFE8; + static const int UART_PER_ID3 = 0xFEC; + static const int UART_CEL_ID0 = 0xFF0; + static const int UART_CEL_ID1 = 0xFF4; + static const int UART_CEL_ID2 = 0xFF8; + static const int UART_CEL_ID3 = 0xFFC; + + uint16_t control; + + /** fractional baud rate divisor. Not used for anything but reporting + * written value */ + uint16_t fbrd; + + /** integer baud rate divisor. Not used for anything but reporting + * written value */ + uint16_t ibrd; + + /** Line control register. Not used for anything but reporting + * written value */ + uint16_t lcrh; + + /** interrupt fifo level register. Not used for anything but reporting + * written value */ + uint16_t ifls; + + BitUnion16(INTREG) + Bitfield<0> rimim; + Bitfield<1> ctsmim; + Bitfield<2> dcdmim; + Bitfield<3> dsrmim; + Bitfield<4> rxim; + Bitfield<5> txim; + Bitfield<6> rtim; + Bitfield<7> feim; + Bitfield<8> peim; + Bitfield<9> beim; + Bitfield<10> oeim; + Bitfield<15,11> rsvd; + EndBitUnion(INTREG) + + /** interrupt mask register. */ + INTREG imsc; + + /** raw interrupt status register */ + INTREG rawInt; + + /** Masked interrupt status register */ + INTREG maskInt; + + /** Interrupt number to generate */ + int intNum; + + /** Gic to use for interrupting */ + Gic *gic; + + /** Should the simulation end on an EOT */ + bool endOnEOT; + + /** Delay before interrupting */ + Tick intDelay; + + /** Function to generate interrupt */ + void generateInterrupt(); + + /** Wrapper to create an event out of the thing */ + EventWrapper intEvent; + + public: + typedef Pl011Params Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + Pl011(const Params *p); + + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); + + /** + * Inform the uart that there is data available. + */ + virtual void dataAvailable(); + + + /** + * Return if we have an interrupt pending + * @return interrupt status + * @todo fix me when implementation improves + */ + virtual bool intStatus() { return false; } + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + +}; + +#endif //__DEV_ARM_PL011_H__ diff --git a/src/dev/arm/versatile.cc b/src/dev/arm/realview.cc similarity index 86% rename from src/dev/arm/versatile.cc rename to src/dev/arm/realview.cc index d003c29aa..303c40912 100644 --- a/src/dev/arm/versatile.cc +++ b/src/dev/arm/realview.cc @@ -41,7 +41,7 @@ */ /** @file - * Implementation of Versatile platform. + * Implementation of RealView platform. */ #include @@ -50,14 +50,14 @@ #include "config/the_isa.hh" #include "cpu/intr_control.hh" -#include "dev/arm/versatile.hh" +#include "dev/arm/realview.hh" #include "dev/terminal.hh" #include "sim/system.hh" using namespace std; using namespace TheISA; -Versatile::Versatile(const Params *p) +RealView::RealView(const Params *p) : Platform(p), system(p->system) { // set the back pointer from the system to myself @@ -65,40 +65,40 @@ Versatile::Versatile(const Params *p) } Tick -Versatile::intrFrequency() +RealView::intrFrequency() { panic("Need implementation\n"); M5_DUMMY_RETURN } void -Versatile::postConsoleInt() +RealView::postConsoleInt() { warn_once("Don't know what interrupt to post for console.\n"); //panic("Need implementation\n"); } void -Versatile::clearConsoleInt() +RealView::clearConsoleInt() { warn_once("Don't know what interrupt to clear for console.\n"); //panic("Need implementation\n"); } void -Versatile::postPciInt(int line) +RealView::postPciInt(int line) { panic("Need implementation\n"); } void -Versatile::clearPciInt(int line) +RealView::clearPciInt(int line) { panic("Need implementation\n"); } Addr -Versatile::pciToDma(Addr pciAddr) const +RealView::pciToDma(Addr pciAddr) const { panic("Need implementation\n"); M5_DUMMY_RETURN @@ -106,28 +106,28 @@ Versatile::pciToDma(Addr pciAddr) const Addr -Versatile::calcPciConfigAddr(int bus, int dev, int func) +RealView::calcPciConfigAddr(int bus, int dev, int func) { panic("Need implementation\n"); M5_DUMMY_RETURN } Addr -Versatile::calcPciIOAddr(Addr addr) +RealView::calcPciIOAddr(Addr addr) { panic("Need implementation\n"); M5_DUMMY_RETURN } Addr -Versatile::calcPciMemAddr(Addr addr) +RealView::calcPciMemAddr(Addr addr) { panic("Need implementation\n"); M5_DUMMY_RETURN } -Versatile * -VersatileParams::create() +RealView * +RealViewParams::create() { - return new Versatile(this); + return new RealView(this); } diff --git a/src/dev/arm/versatile.hh b/src/dev/arm/realview.hh similarity index 92% rename from src/dev/arm/versatile.hh rename to src/dev/arm/realview.hh index 791c5ed5b..c15f97a71 100644 --- a/src/dev/arm/versatile.hh +++ b/src/dev/arm/realview.hh @@ -42,34 +42,34 @@ /** * @file - * Declaration of top level class for the Versatile platform chips. This class just + * Declaration of top level class for the RealView platform chips. This class just * retains pointers to all its children so the children can communicate. */ -#ifndef __DEV_ARM_VERSATILE_HH__ -#define __DEV_ARM_VERSATILE_HH__ +#ifndef __DEV_ARM_RealView_HH__ +#define __DEV_ARM_RealView_HH__ #include "dev/platform.hh" -#include "params/Versatile.hh" +#include "params/RealView.hh" class IdeController; class System; -class Versatile : public Platform +class RealView : public Platform { public: /** Pointer to the system */ System *system; public: - typedef VersatileParams Params; + typedef RealViewParams Params; /** * Constructor for the Tsunami Class. * @param name name of the object * @param s system the object belongs to * @param intctrl pointer to the interrupt controller */ - Versatile(const Params *p); + RealView(const Params *p); /** * Return the interrupting frequency to AlphaAccess @@ -116,4 +116,4 @@ class Versatile : public Platform virtual Addr calcPciMemAddr(Addr addr); }; -#endif // __DEV_ARM_VERSATILE_HH__ +#endif // __DEV_ARM_RealView_HH__ diff --git a/src/dev/arm/rv_ctrl.cc b/src/dev/arm/rv_ctrl.cc new file mode 100644 index 000000000..e2543426b --- /dev/null +++ b/src/dev/arm/rv_ctrl.cc @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "base/trace.hh" +#include "dev/arm/rv_ctrl.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +RealViewCtrl::RealViewCtrl(Params *p) + : BasicPioDevice(p) +{ + pioSize = 0xD4; +} + +Tick +RealViewCtrl::read(PacketPtr pkt) +{ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + assert(pkt->getSize() == 4); + Addr daddr = pkt->getAddr() - pioAddr; + pkt->allocate(); + + switch(daddr) { + case ProcId: + pkt->set(params()->proc_id); + break; + case Clock24: + Tick clk; + clk = (Tick)(curTick / (24 * SimClock::Float::MHz)); + pkt->set((uint32_t)(clk)); + break; + case Flash: + pkt->set(0); + break; + default: + panic("Tried to read RealView I/O at offset %#x that doesn't exist\n", daddr); + break; + } + pkt->makeAtomicResponse(); + return pioDelay; + +} + +Tick +RealViewCtrl::write(PacketPtr pkt) +{ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + + Addr daddr = pkt->getAddr() - pioAddr; + switch (daddr) { + case Flash: + break; + default: + panic("Tried to write RVIO at offset %#x that doesn't exist\n", daddr); + break; + } + pkt->makeAtomicResponse(); + return pioDelay; +} + +void +RealViewCtrl::serialize(std::ostream &os) +{ + panic("Need to implement serialization\n"); +} + +void +RealViewCtrl::unserialize(Checkpoint *cp, const std::string §ion) +{ + panic("Need to implement serialization\n"); +} + +RealViewCtrl * +RealViewCtrlParams::create() +{ + return new RealViewCtrl(this); +} diff --git a/src/dev/arm/rv_ctrl.hh b/src/dev/arm/rv_ctrl.hh new file mode 100644 index 000000000..00a19d715 --- /dev/null +++ b/src/dev/arm/rv_ctrl.hh @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#ifndef __DEV_ARM_RV_HH__ +#define __DEV_ARM_RV_HH__ + +#include "base/range.hh" +#include "dev/io_device.hh" +#include "params/RealViewCtrl.hh" + +/** @file + * This implements the simple real view registers on a PBXA9 + */ + +class RealViewCtrl : public BasicPioDevice +{ + protected: + enum { + IdReg = 0x00, + SwReg = 0x04, + Led = 0x08, + Osc0 = 0x0C, + Osc1 = 0x10, + Osc2 = 0x14, + Osc3 = 0x18, + Osc4 = 0x1C, + Lock = 0x20, + Clock100 = 0x24, + CfgData1 = 0x28, + CfgData2 = 0x2C, + Flags = 0x30, + FlagsClr = 0x34, + NvFlags = 0x38, + NvFlagsClr = 0x3C, + ResetCtl = 0x40, + PciCtl = 0x44, + MciCtl = 0x48, + Flash = 0x4C, + Clcd = 0x50, + ClcdSer = 0x54, + Bootcs = 0x58, + Clock24 = 0x5C, + Misc = 0x60, + IoSel = 0x70, + ProcId = 0x84, + TestOsc0 = 0xC0, + TestOsc1 = 0xC4, + TestOsc2 = 0xC8, + TestOsc3 = 0xCC, + TestOsc4 = 0xD0 + }; + + public: + typedef RealViewCtrlParams Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + /** + * The constructor for RealView just registers itself with the MMU. + * @param p params structure + */ + RealViewCtrl(Params *p); + + /** + * Handle a read to the device + * @param pkt The memory request. + * @param data Where to put the data. + */ + virtual Tick read(PacketPtr pkt); + + /** + * All writes are simply ignored. + * @param pkt The memory request. + * @param data the data + */ + virtual Tick write(PacketPtr pkt); + + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + + +#endif // __DEV_ARM_RV_HH__ + diff --git a/src/dev/arm/timer_sp804.cc b/src/dev/arm/timer_sp804.cc new file mode 100644 index 000000000..6a6792f60 --- /dev/null +++ b/src/dev/arm/timer_sp804.cc @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "base/intmath.hh" +#include "base/trace.hh" +#include "dev/arm/gic.hh" +#include "dev/arm/timer_sp804.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +Sp804::Sp804(Params *p) + : AmbaDevice(p), gic(p->gic), timer0(name() + ".timer0", this, p->int_num0, p->clock0), + timer1(name() + ".timer1", this, p->int_num1, p->clock1) +{ + pioSize = 0xfff; +} + +Sp804::Timer::Timer(std::string __name, Sp804 *_parent, int int_num, Tick _clock) + : _name(__name), parent(_parent), intNum(int_num), clock(_clock), control(0x20), + rawInt(false), pendingInt(false), loadValue(0xffffffff), zeroEvent(this) +{ +} + + +Tick +Sp804::read(PacketPtr pkt) +{ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + assert(pkt->getSize() == 4); + Addr daddr = pkt->getAddr() - pioAddr; + pkt->allocate(); + DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr); + + if (daddr < Timer::Size) + timer0.read(pkt, daddr); + else if ((daddr - Timer::Size) < Timer::Size) + timer1.read(pkt, daddr - Timer::Size); + else if (!readId(pkt)) + panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr); + pkt->makeAtomicResponse(); + return pioDelay; +} + + +void +Sp804::Timer::read(PacketPtr pkt, Addr daddr) +{ + DPRINTF(Timer, "Reading from Timer at offset: %#x\n", daddr); + + switch(daddr) { + case LoadReg: + pkt->set(loadValue); + break; + case CurrentReg: + DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n", + zeroEvent.when(), clock, control.timerPrescale); + Tick time; + time = zeroEvent.when() - curTick; + time = time / clock / power(16, control.timerPrescale); + DPRINTF(Timer, "-- returning counter at %d\n", time); + pkt->set(time); + break; + case ControlReg: + pkt->set(control); + break; + case RawISR: + pkt->set(rawInt); + break; + case MaskedISR: + pkt->set(pendingInt); + break; + case BGLoad: + pkt->set(loadValue); + break; + default: + panic("Tried to read SP804 timer at offset %#x\n", daddr); + break; + } +} + +Tick +Sp804::write(PacketPtr pkt) +{ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + assert(pkt->getSize() == 4); + Addr daddr = pkt->getAddr() - pioAddr; + pkt->allocate(); + DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr); + + if (daddr < Timer::Size) + timer0.write(pkt, daddr); + else if ((daddr - Timer::Size) < Timer::Size) + timer1.write(pkt, daddr - Timer::Size); + else if (!readId(pkt)) + panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr); + pkt->makeAtomicResponse(); + return pioDelay; +} + +void +Sp804::Timer::write(PacketPtr pkt, Addr daddr) +{ + DPRINTF(Timer, "Writing to Timer at offset: %#x\n", daddr); + switch (daddr) { + case LoadReg: + loadValue = pkt->get(); + restartCounter(loadValue); + break; + case CurrentReg: + // Spec says this value can't be written, but linux writes it anyway + break; + case ControlReg: + bool old_enable; + old_enable = control.timerEnable; + control = pkt->get(); + if ((old_enable == 0) && control.timerEnable) + restartCounter(loadValue); + break; + case IntClear: + rawInt = false; + if (pendingInt) { + pendingInt = false; + DPRINTF(Timer, "Clearing interrupt\n"); + parent->gic->clearInt(intNum); + } + break; + case BGLoad: + loadValue = pkt->get(); + break; + default: + panic("Tried to write SP804 timer at offset %#x\n", daddr); + break; + } +} + +void +Sp804::Timer::restartCounter(uint32_t val) +{ + DPRINTF(Timer, "Resetting counter with value %#x\n", val); + if (!control.timerEnable) + return; + + Tick time = clock << power(16, control.timerPrescale); + if (control.timerSize) + time *= bits(val,15,0); + else + time *= val; + + if (zeroEvent.scheduled()) { + DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); + parent->deschedule(zeroEvent); + } + parent->schedule(zeroEvent, curTick + time); + DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick + time); +} + +void +Sp804::Timer::counterAtZero() +{ + if (!control.timerEnable) + return; + + DPRINTF(Timer, "Counter reached zero\n"); + + rawInt = true; + bool old_pending = pendingInt; + if (control.intEnable) + pendingInt = true; + if (pendingInt && ~old_pending) { + DPRINTF(Timer, "-- Causing interrupt\n"); + parent->gic->sendInt(intNum); + } + + if (control.oneShot) + return; + + // Free-running + if (control.timerMode == 0) + restartCounter(0xffffffff); + else + restartCounter(loadValue); +} + + +void +Sp804::serialize(std::ostream &os) +{ + panic("Need to implement serialization\n"); +} + +void +Sp804::unserialize(Checkpoint *cp, const std::string §ion) +{ + panic("Need to implement serialization\n"); +} + +Sp804 * +Sp804Params::create() +{ + return new Sp804(this); +} diff --git a/src/dev/arm/timer_sp804.hh b/src/dev/arm/timer_sp804.hh new file mode 100644 index 000000000..1039456ab --- /dev/null +++ b/src/dev/arm/timer_sp804.hh @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#ifndef __DEV_ARM_SP804_HH__ +#define __DEV_ARM_SP804_HH__ + +#include "base/range.hh" +#include "dev/arm/amba_device.hh" +#include "params/Sp804.hh" + +/** @file + * This implements the dual Sp804 timer block + */ + +class Gic; + +class Sp804 : public AmbaDevice +{ + protected: + class Timer + { + + public: + enum { + LoadReg = 0x00, + CurrentReg = 0x04, + ControlReg = 0x08, + IntClear = 0x0C, + RawISR = 0x10, + MaskedISR = 0x14, + BGLoad = 0x18, + Size = 0x20 + }; + + BitUnion32(CTRL) + Bitfield<0> oneShot; + Bitfield<1> timerSize; + Bitfield<3,2> timerPrescale; + Bitfield<5> intEnable; + Bitfield<6> timerMode; + Bitfield<7> timerEnable; + EndBitUnion(CTRL) + + protected: + std::string _name; + + /** Pointer to parent class */ + Sp804 *parent; + + /** Number of interrupt to cause/clear */ + uint32_t intNum; + + /** Number of ticks in a clock input */ + Tick clock; + + /** Control register as specified above */ + CTRL control; + + /** If timer has caused an interrupt. This is irrespective of + * interrupt enable */ + bool rawInt; + + /** If an interrupt is currently pending. Logical and of CTRL.intEnable + * and rawInt */ + bool pendingInt; + + /** Value to load into counter when periodic mode reaches 0 */ + uint32_t loadValue; + + /** Called when the counter reaches 0 */ + void counterAtZero(); + EventWrapper zeroEvent; + + public: + /** Restart the counter ticking at val + * @param val the value to start at (pre-16 bit masking if en) */ + void restartCounter(uint32_t val); + + Timer(std::string __name, Sp804 *parent, int int_num, Tick clock); + + std::string name() const { return _name; } + + /** Handle read for a single timer */ + void read(PacketPtr pkt, Addr daddr); + + /** Handle write for a single timer */ + void write(PacketPtr pkt, Addr daddr); + }; + + /** Pointer to the GIC for causing an interrupt */ + Gic *gic; + + /** Timers that do the actual work */ + Timer timer0; + Timer timer1; + + public: + typedef Sp804Params Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + /** + * The constructor for RealView just registers itself with the MMU. + * @param p params structure + */ + Sp804(Params *p); + + /** + * Handle a read to the device + * @param pkt The memory request. + * @param data Where to put the data. + */ + virtual Tick read(PacketPtr pkt); + + /** + * All writes are simply ignored. + * @param pkt The memory request. + * @param data the data + */ + virtual Tick write(PacketPtr pkt); + + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + + +#endif // __DEV_ARM_SP804_HH__ +