timer_sp804.cc revision 8524
12817Sksewell@umich.edu/* 22817Sksewell@umich.edu * Copyright (c) 2010 ARM Limited 32817Sksewell@umich.edu * All rights reserved 42817Sksewell@umich.edu * 52817Sksewell@umich.edu * The license below extends only to copyright in the software and shall 62817Sksewell@umich.edu * not be construed as granting a license to any other intellectual 72817Sksewell@umich.edu * property including but not limited to intellectual property relating 82817Sksewell@umich.edu * to a hardware implementation of the functionality of the software 92817Sksewell@umich.edu * licensed hereunder. You may use the software subject to the license 102817Sksewell@umich.edu * terms below provided that you ensure that this notice is replicated 112817Sksewell@umich.edu * unmodified and in its entirety in all distributions of the software, 122817Sksewell@umich.edu * modified or unmodified, in source code or in binary form. 132817Sksewell@umich.edu * 142817Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without 152817Sksewell@umich.edu * modification, are permitted provided that the following conditions are 162817Sksewell@umich.edu * met: redistributions of source code must retain the above copyright 172817Sksewell@umich.edu * notice, this list of conditions and the following disclaimer; 182817Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright 192817Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the 202817Sksewell@umich.edu * documentation and/or other materials provided with the distribution; 212817Sksewell@umich.edu * neither the name of the copyright holders nor the names of its 222817Sksewell@umich.edu * contributors may be used to endorse or promote products derived from 232817Sksewell@umich.edu * this software without specific prior written permission. 242817Sksewell@umich.edu * 252817Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262817Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272817Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282817Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292817Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302817Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312817Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 323776Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332817Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 342834Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352817Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362817Sksewell@umich.edu * 372817Sksewell@umich.edu * Authors: Ali Saidi 382817Sksewell@umich.edu */ 395499Ssaidi@eecs.umich.edu 402817Sksewell@umich.edu#include "base/intmath.hh" 415499Ssaidi@eecs.umich.edu#include "base/trace.hh" 422817Sksewell@umich.edu#include "debug/Checkpoint.hh" 432817Sksewell@umich.edu#include "debug/Timer.hh" 442817Sksewell@umich.edu#include "dev/arm/gic.hh" 452817Sksewell@umich.edu#include "dev/arm/timer_sp804.hh" 462817Sksewell@umich.edu#include "mem/packet.hh" 472817Sksewell@umich.edu#include "mem/packet_access.hh" 483126Sktlim@umich.edu 492817Sksewell@umich.eduusing namespace AmbaDev; 502817Sksewell@umich.edu 512817Sksewell@umich.eduSp804::Sp804(Params *p) 522817Sksewell@umich.edu : AmbaDevice(p), gic(p->gic), timer0(name() + ".timer0", this, p->int_num0, p->clock0), 532817Sksewell@umich.edu timer1(name() + ".timer1", this, p->int_num1, p->clock1) 542817Sksewell@umich.edu{ 552817Sksewell@umich.edu pioSize = 0xfff; 562817Sksewell@umich.edu} 572817Sksewell@umich.edu 585803Snate@binkert.orgSp804::Timer::Timer(std::string __name, Sp804 *_parent, int int_num, Tick _clock) 592817Sksewell@umich.edu : _name(__name), parent(_parent), intNum(int_num), clock(_clock), control(0x20), 602817Sksewell@umich.edu rawInt(false), pendingInt(false), loadValue(0xffffffff), zeroEvent(this) 612817Sksewell@umich.edu{ 622817Sksewell@umich.edu} 632817Sksewell@umich.edu 642817Sksewell@umich.edu 655714Shsul@eecs.umich.eduTick 665715Shsul@eecs.umich.eduSp804::read(PacketPtr pkt) 672817Sksewell@umich.edu{ 682817Sksewell@umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 692817Sksewell@umich.edu assert(pkt->getSize() == 4); 702817Sksewell@umich.edu Addr daddr = pkt->getAddr() - pioAddr; 712817Sksewell@umich.edu pkt->allocate(); 722817Sksewell@umich.edu DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr); 732817Sksewell@umich.edu 742817Sksewell@umich.edu if (daddr < Timer::Size) 752817Sksewell@umich.edu timer0.read(pkt, daddr); 762817Sksewell@umich.edu else if ((daddr - Timer::Size) < Timer::Size) 772817Sksewell@umich.edu timer1.read(pkt, daddr - Timer::Size); 782817Sksewell@umich.edu else if (!readId(pkt, ambaId, pioAddr)) 792817Sksewell@umich.edu panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr); 802817Sksewell@umich.edu pkt->makeAtomicResponse(); 812817Sksewell@umich.edu return pioDelay; 822817Sksewell@umich.edu} 832817Sksewell@umich.edu 842817Sksewell@umich.edu 852817Sksewell@umich.eduvoid 862817Sksewell@umich.eduSp804::Timer::read(PacketPtr pkt, Addr daddr) 872817Sksewell@umich.edu{ 882817Sksewell@umich.edu switch(daddr) { 892817Sksewell@umich.edu case LoadReg: 902817Sksewell@umich.edu pkt->set<uint32_t>(loadValue); 912817Sksewell@umich.edu break; 922817Sksewell@umich.edu case CurrentReg: 932817Sksewell@umich.edu DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n", 942817Sksewell@umich.edu zeroEvent.when(), clock, control.timerPrescale); 952817Sksewell@umich.edu Tick time; 962817Sksewell@umich.edu time = zeroEvent.when() - curTick(); 972875Sksewell@umich.edu time = time / clock / power(16, control.timerPrescale); 985715Shsul@eecs.umich.edu DPRINTF(Timer, "-- returning counter at %d\n", time); 992817Sksewell@umich.edu pkt->set<uint32_t>(time); 1002817Sksewell@umich.edu break; 1012817Sksewell@umich.edu case ControlReg: 1022817Sksewell@umich.edu pkt->set<uint32_t>(control); 1032817Sksewell@umich.edu break; 1042817Sksewell@umich.edu case RawISR: 1052817Sksewell@umich.edu pkt->set<uint32_t>(rawInt); 1062817Sksewell@umich.edu break; 1072817Sksewell@umich.edu case MaskedISR: 1085715Shsul@eecs.umich.edu pkt->set<uint32_t>(pendingInt); 1092817Sksewell@umich.edu break; 1102817Sksewell@umich.edu case BGLoad: 1112817Sksewell@umich.edu pkt->set<uint32_t>(loadValue); 1122817Sksewell@umich.edu break; 1132817Sksewell@umich.edu default: 1142817Sksewell@umich.edu panic("Tried to read SP804 timer at offset %#x\n", daddr); 1155715Shsul@eecs.umich.edu break; 1162817Sksewell@umich.edu } 1172817Sksewell@umich.edu DPRINTF(Timer, "Reading %#x from Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr); 1182817Sksewell@umich.edu} 1192817Sksewell@umich.edu 1205250Sksewell@umich.eduTick 1212817Sksewell@umich.eduSp804::write(PacketPtr pkt) 1222875Sksewell@umich.edu{ 1235715Shsul@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1242817Sksewell@umich.edu assert(pkt->getSize() == 4); 1252817Sksewell@umich.edu Addr daddr = pkt->getAddr() - pioAddr; 1262817Sksewell@umich.edu pkt->allocate(); 1272817Sksewell@umich.edu DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr); 1282817Sksewell@umich.edu 1292817Sksewell@umich.edu if (daddr < Timer::Size) 1302817Sksewell@umich.edu timer0.write(pkt, daddr); 1312817Sksewell@umich.edu else if ((daddr - Timer::Size) < Timer::Size) 1322817Sksewell@umich.edu timer1.write(pkt, daddr - Timer::Size); 1332817Sksewell@umich.edu else if (!readId(pkt, ambaId, pioAddr)) 1342817Sksewell@umich.edu panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr); 1355704Snate@binkert.org pkt->makeAtomicResponse(); 1362817Sksewell@umich.edu return pioDelay; 1372817Sksewell@umich.edu} 1382817Sksewell@umich.edu 1392817Sksewell@umich.eduvoid 1402817Sksewell@umich.eduSp804::Timer::write(PacketPtr pkt, Addr daddr) 1412817Sksewell@umich.edu{ 1425715Shsul@eecs.umich.edu DPRINTF(Timer, "Writing %#x to Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr); 1432817Sksewell@umich.edu switch (daddr) { 1442817Sksewell@umich.edu case LoadReg: 1452817Sksewell@umich.edu loadValue = pkt->get<uint32_t>(); 1462817Sksewell@umich.edu restartCounter(loadValue); 1472875Sksewell@umich.edu break; 1482817Sksewell@umich.edu case CurrentReg: 1493221Sktlim@umich.edu // Spec says this value can't be written, but linux writes it anyway 1505715Shsul@eecs.umich.edu break; 1512817Sksewell@umich.edu case ControlReg: 1522817Sksewell@umich.edu bool old_enable; 1532817Sksewell@umich.edu old_enable = control.timerEnable; 1542817Sksewell@umich.edu control = pkt->get<uint32_t>(); 1552817Sksewell@umich.edu if ((old_enable == 0) && control.timerEnable) 1565715Shsul@eecs.umich.edu restartCounter(loadValue); 1572817Sksewell@umich.edu break; 1582817Sksewell@umich.edu case IntClear: 1592817Sksewell@umich.edu rawInt = false; 1602817Sksewell@umich.edu if (pendingInt) { 1615250Sksewell@umich.edu pendingInt = false; 1622817Sksewell@umich.edu DPRINTF(Timer, "Clearing interrupt\n"); 1632875Sksewell@umich.edu parent->gic->clearInt(intNum); 1645715Shsul@eecs.umich.edu } 1652817Sksewell@umich.edu break; 1662817Sksewell@umich.edu case BGLoad: 1672817Sksewell@umich.edu loadValue = pkt->get<uint32_t>(); 1682817Sksewell@umich.edu break; 1692817Sksewell@umich.edu default: 1705715Shsul@eecs.umich.edu panic("Tried to write SP804 timer at offset %#x\n", daddr); 1712817Sksewell@umich.edu break; 1722817Sksewell@umich.edu } 1732817Sksewell@umich.edu} 1742817Sksewell@umich.edu 1752817Sksewell@umich.eduvoid 1762817Sksewell@umich.eduSp804::Timer::restartCounter(uint32_t val) 1772817Sksewell@umich.edu{ 1783548Sgblack@eecs.umich.edu DPRINTF(Timer, "Resetting counter with value %#x\n", val); 1792817Sksewell@umich.edu if (!control.timerEnable) 1802817Sksewell@umich.edu return; 1812817Sksewell@umich.edu 1822817Sksewell@umich.edu Tick time = clock * power(16, control.timerPrescale); 1832817Sksewell@umich.edu if (control.timerSize) 1842817Sksewell@umich.edu time *= val; 1852817Sksewell@umich.edu else 1862817Sksewell@umich.edu time *= bits(val,15,0); 1872817Sksewell@umich.edu 1882817Sksewell@umich.edu if (zeroEvent.scheduled()) { 1892817Sksewell@umich.edu DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 1902817Sksewell@umich.edu parent->deschedule(zeroEvent); 1912817Sksewell@umich.edu } 1922817Sksewell@umich.edu parent->schedule(zeroEvent, curTick() + time); 1932817Sksewell@umich.edu DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time); 1942817Sksewell@umich.edu} 1952817Sksewell@umich.edu 1962817Sksewell@umich.eduvoid 1972817Sksewell@umich.eduSp804::Timer::counterAtZero() 1982817Sksewell@umich.edu{ 1992817Sksewell@umich.edu if (!control.timerEnable) 2002817Sksewell@umich.edu return; 2012817Sksewell@umich.edu 2022817Sksewell@umich.edu DPRINTF(Timer, "Counter reached zero\n"); 2032817Sksewell@umich.edu 2042817Sksewell@umich.edu rawInt = true; 2052817Sksewell@umich.edu bool old_pending = pendingInt; 2062817Sksewell@umich.edu if (control.intEnable) 2072817Sksewell@umich.edu pendingInt = true; 2082817Sksewell@umich.edu if (pendingInt && ~old_pending) { 2092817Sksewell@umich.edu DPRINTF(Timer, "-- Causing interrupt\n"); 2102817Sksewell@umich.edu parent->gic->sendInt(intNum); 2112817Sksewell@umich.edu } 2122817Sksewell@umich.edu 2132817Sksewell@umich.edu if (control.oneShot) 2142817Sksewell@umich.edu return; 2152817Sksewell@umich.edu 2162817Sksewell@umich.edu // Free-running 2172817Sksewell@umich.edu if (control.timerMode == 0) 2182817Sksewell@umich.edu restartCounter(0xffffffff); 2192817Sksewell@umich.edu else 2202817Sksewell@umich.edu restartCounter(loadValue); 2212817Sksewell@umich.edu} 2222817Sksewell@umich.edu 2233126Sktlim@umich.eduvoid 2243126Sktlim@umich.eduSp804::Timer::serialize(std::ostream &os) 2253126Sktlim@umich.edu{ 2262817Sksewell@umich.edu DPRINTF(Checkpoint, "Serializing Arm Sp804\n"); 2272817Sksewell@umich.edu SERIALIZE_SCALAR(intNum); 2282817Sksewell@umich.edu SERIALIZE_SCALAR(clock); 2292817Sksewell@umich.edu 2303126Sktlim@umich.edu uint32_t control_serial = control; 2313126Sktlim@umich.edu SERIALIZE_SCALAR(control_serial); 2323126Sktlim@umich.edu 2332817Sksewell@umich.edu SERIALIZE_SCALAR(rawInt); 2342817Sksewell@umich.edu SERIALIZE_SCALAR(pendingInt); 2352817Sksewell@umich.edu SERIALIZE_SCALAR(loadValue); 2362817Sksewell@umich.edu 2372817Sksewell@umich.edu bool is_in_event = zeroEvent.scheduled(); 2382817Sksewell@umich.edu SERIALIZE_SCALAR(is_in_event); 2392817Sksewell@umich.edu 2402817Sksewell@umich.edu Tick event_time; 2412817Sksewell@umich.edu if (is_in_event){ 2422817Sksewell@umich.edu event_time = zeroEvent.when(); 2432817Sksewell@umich.edu SERIALIZE_SCALAR(event_time); 2442817Sksewell@umich.edu } 2452817Sksewell@umich.edu} 2462817Sksewell@umich.edu 2472817Sksewell@umich.eduvoid 2485715Shsul@eecs.umich.eduSp804::Timer::unserialize(Checkpoint *cp, const std::string §ion) 2492817Sksewell@umich.edu{ 2502817Sksewell@umich.edu DPRINTF(Checkpoint, "Unserializing Arm Sp804\n"); 2512817Sksewell@umich.edu 2522817Sksewell@umich.edu UNSERIALIZE_SCALAR(intNum); 2532817Sksewell@umich.edu UNSERIALIZE_SCALAR(clock); 2542817Sksewell@umich.edu 2552817Sksewell@umich.edu uint32_t control_serial; 2562817Sksewell@umich.edu UNSERIALIZE_SCALAR(control_serial); 2572817Sksewell@umich.edu control = control_serial; 2582817Sksewell@umich.edu 2592817Sksewell@umich.edu UNSERIALIZE_SCALAR(rawInt); 2602817Sksewell@umich.edu UNSERIALIZE_SCALAR(pendingInt); 2612817Sksewell@umich.edu UNSERIALIZE_SCALAR(loadValue); 2622817Sksewell@umich.edu 2632817Sksewell@umich.edu bool is_in_event; 2642817Sksewell@umich.edu UNSERIALIZE_SCALAR(is_in_event); 2652817Sksewell@umich.edu 2662817Sksewell@umich.edu Tick event_time; 2672817Sksewell@umich.edu if (is_in_event){ 2682817Sksewell@umich.edu UNSERIALIZE_SCALAR(event_time); 2692817Sksewell@umich.edu parent->schedule(zeroEvent, event_time); 2702817Sksewell@umich.edu } 2712986Sgblack@eecs.umich.edu} 2722817Sksewell@umich.edu 2735258Sksewell@umich.edu 2745258Sksewell@umich.edu 2752817Sksewell@umich.eduvoid 2762817Sksewell@umich.eduSp804::serialize(std::ostream &os) 2775258Sksewell@umich.edu{ 2785258Sksewell@umich.edu nameOut(os, csprintf("%s.timer0", name())); 2795258Sksewell@umich.edu timer0.serialize(os); 2802817Sksewell@umich.edu nameOut(os, csprintf("%s.timer1", name())); 2812817Sksewell@umich.edu timer1.serialize(os); 2822817Sksewell@umich.edu} 2832817Sksewell@umich.edu 2842817Sksewell@umich.eduvoid 2852817Sksewell@umich.eduSp804::unserialize(Checkpoint *cp, const std::string §ion) 2862817Sksewell@umich.edu{ 2872817Sksewell@umich.edu timer0.unserialize(cp, csprintf("%s.timer0", section)); 2882817Sksewell@umich.edu timer1.unserialize(cp, csprintf("%s.timer1", section)); 2892817Sksewell@umich.edu} 2902817Sksewell@umich.edu 2912817Sksewell@umich.eduSp804 * 2922817Sksewell@umich.eduSp804Params::create() 2932817Sksewell@umich.edu{ 2943776Sgblack@eecs.umich.edu return new Sp804(this); 2955715Shsul@eecs.umich.edu} 2962817Sksewell@umich.edu