timer_sp804.cc revision 10565:23593fdaadcd
110152Satgutier@umich.edu/* 210152Satgutier@umich.edu * Copyright (c) 2010 ARM Limited 310152Satgutier@umich.edu * All rights reserved 410152Satgutier@umich.edu * 510152Satgutier@umich.edu * The license below extends only to copyright in the software and shall 610152Satgutier@umich.edu * not be construed as granting a license to any other intellectual 710152Satgutier@umich.edu * property including but not limited to intellectual property relating 810152Satgutier@umich.edu * to a hardware implementation of the functionality of the software 910152Satgutier@umich.edu * licensed hereunder. You may use the software subject to the license 1010152Satgutier@umich.edu * terms below provided that you ensure that this notice is replicated 1110152Satgutier@umich.edu * unmodified and in its entirety in all distributions of the software, 1210152Satgutier@umich.edu * modified or unmodified, in source code or in binary form. 1310152Satgutier@umich.edu * 1410152Satgutier@umich.edu * Redistribution and use in source and binary forms, with or without 1510152Satgutier@umich.edu * modification, are permitted provided that the following conditions are 1610152Satgutier@umich.edu * met: redistributions of source code must retain the above copyright 1710152Satgutier@umich.edu * notice, this list of conditions and the following disclaimer; 1810152Satgutier@umich.edu * redistributions in binary form must reproduce the above copyright 1910152Satgutier@umich.edu * notice, this list of conditions and the following disclaimer in the 2010152Satgutier@umich.edu * documentation and/or other materials provided with the distribution; 2110152Satgutier@umich.edu * neither the name of the copyright holders nor the names of its 2210152Satgutier@umich.edu * contributors may be used to endorse or promote products derived from 2310152Satgutier@umich.edu * this software without specific prior written permission. 2410152Satgutier@umich.edu * 2510152Satgutier@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610152Satgutier@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710152Satgutier@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810152Satgutier@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910152Satgutier@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010152Satgutier@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110152Satgutier@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210152Satgutier@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310152Satgutier@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410152Satgutier@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510152Satgutier@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610152Satgutier@umich.edu * 3710152Satgutier@umich.edu * Authors: Ali Saidi 3810152Satgutier@umich.edu */ 3910152Satgutier@umich.edu 4010152Satgutier@umich.edu#include "base/intmath.hh" 4110152Satgutier@umich.edu#include "base/trace.hh" 4210152Satgutier@umich.edu#include "debug/Checkpoint.hh" 4310152Satgutier@umich.edu#include "debug/Timer.hh" 4410152Satgutier@umich.edu#include "dev/arm/base_gic.hh" 4510152Satgutier@umich.edu#include "dev/arm/timer_sp804.hh" 4610152Satgutier@umich.edu#include "mem/packet.hh" 4710152Satgutier@umich.edu#include "mem/packet_access.hh" 4810152Satgutier@umich.edu 4910152Satgutier@umich.eduSp804::Sp804(Params *p) 5010152Satgutier@umich.edu : AmbaPioDevice(p, 0xfff), gic(p->gic), 5110152Satgutier@umich.edu timer0(name() + ".timer0", this, p->int_num0, p->clock0), 5210152Satgutier@umich.edu timer1(name() + ".timer1", this, p->int_num1, p->clock1) 5310152Satgutier@umich.edu{ 5410152Satgutier@umich.edu} 5510152Satgutier@umich.edu 5610152Satgutier@umich.eduSp804::Timer::Timer(std::string __name, Sp804 *_parent, int int_num, Tick _clock) 5710152Satgutier@umich.edu : _name(__name), parent(_parent), intNum(int_num), clock(_clock), control(0x20), 5810152Satgutier@umich.edu rawInt(false), pendingInt(false), loadValue(0xffffffff), zeroEvent(this) 5910152Satgutier@umich.edu{ 6010152Satgutier@umich.edu} 6110152Satgutier@umich.edu 6210152Satgutier@umich.edu 6310152Satgutier@umich.eduTick 6410152Satgutier@umich.eduSp804::read(PacketPtr pkt) 6510152Satgutier@umich.edu{ 6610152Satgutier@umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 6710152Satgutier@umich.edu assert(pkt->getSize() == 4); 6810152Satgutier@umich.edu Addr daddr = pkt->getAddr() - pioAddr; 6910152Satgutier@umich.edu DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr); 7010152Satgutier@umich.edu 7110152Satgutier@umich.edu if (daddr < Timer::Size) 7210152Satgutier@umich.edu timer0.read(pkt, daddr); 7310152Satgutier@umich.edu else if ((daddr - Timer::Size) < Timer::Size) 7410152Satgutier@umich.edu timer1.read(pkt, daddr - Timer::Size); 7510152Satgutier@umich.edu else if (!readId(pkt, ambaId, pioAddr)) 7610152Satgutier@umich.edu panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr); 7710152Satgutier@umich.edu pkt->makeAtomicResponse(); 7810152Satgutier@umich.edu return pioDelay; 7910152Satgutier@umich.edu} 8010152Satgutier@umich.edu 8110152Satgutier@umich.edu 8210152Satgutier@umich.eduvoid 8310152Satgutier@umich.eduSp804::Timer::read(PacketPtr pkt, Addr daddr) 8410152Satgutier@umich.edu{ 8510152Satgutier@umich.edu switch(daddr) { 8610152Satgutier@umich.edu case LoadReg: 8710152Satgutier@umich.edu pkt->set<uint32_t>(loadValue); 8810152Satgutier@umich.edu break; 8910152Satgutier@umich.edu case CurrentReg: 9010152Satgutier@umich.edu DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n", 9110152Satgutier@umich.edu zeroEvent.when(), clock, control.timerPrescale); 9210152Satgutier@umich.edu Tick time; 9310152Satgutier@umich.edu time = zeroEvent.when() - curTick(); 9410152Satgutier@umich.edu time = time / clock / power(16, control.timerPrescale); 9510152Satgutier@umich.edu DPRINTF(Timer, "-- returning counter at %d\n", time); 9610152Satgutier@umich.edu pkt->set<uint32_t>(time); 9710152Satgutier@umich.edu break; 9810152Satgutier@umich.edu case ControlReg: 9910152Satgutier@umich.edu pkt->set<uint32_t>(control); 10010152Satgutier@umich.edu break; 10110152Satgutier@umich.edu case RawISR: 10210152Satgutier@umich.edu pkt->set<uint32_t>(rawInt); 10310152Satgutier@umich.edu break; 10410152Satgutier@umich.edu case MaskedISR: 10510152Satgutier@umich.edu pkt->set<uint32_t>(pendingInt); 10610152Satgutier@umich.edu break; 10710152Satgutier@umich.edu case BGLoad: 10810152Satgutier@umich.edu pkt->set<uint32_t>(loadValue); 10910152Satgutier@umich.edu break; 11010152Satgutier@umich.edu default: 11110152Satgutier@umich.edu panic("Tried to read SP804 timer at offset %#x\n", daddr); 11210152Satgutier@umich.edu break; 11310152Satgutier@umich.edu } 11410152Satgutier@umich.edu DPRINTF(Timer, "Reading %#x from Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr); 11510152Satgutier@umich.edu} 11610152Satgutier@umich.edu 11710152Satgutier@umich.eduTick 11810152Satgutier@umich.eduSp804::write(PacketPtr pkt) 11910152Satgutier@umich.edu{ 12010152Satgutier@umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 12110152Satgutier@umich.edu assert(pkt->getSize() == 4); 12210152Satgutier@umich.edu Addr daddr = pkt->getAddr() - pioAddr; 12310152Satgutier@umich.edu DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr); 12410152Satgutier@umich.edu 12510152Satgutier@umich.edu if (daddr < Timer::Size) 12610152Satgutier@umich.edu timer0.write(pkt, daddr); 12710152Satgutier@umich.edu else if ((daddr - Timer::Size) < Timer::Size) 12810152Satgutier@umich.edu timer1.write(pkt, daddr - Timer::Size); 12910152Satgutier@umich.edu else if (!readId(pkt, ambaId, pioAddr)) 13010152Satgutier@umich.edu panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr); 13110152Satgutier@umich.edu pkt->makeAtomicResponse(); 13210152Satgutier@umich.edu return pioDelay; 13310152Satgutier@umich.edu} 13410152Satgutier@umich.edu 13510152Satgutier@umich.eduvoid 13610152Satgutier@umich.eduSp804::Timer::write(PacketPtr pkt, Addr daddr) 13710152Satgutier@umich.edu{ 13810152Satgutier@umich.edu DPRINTF(Timer, "Writing %#x to Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr); 13910152Satgutier@umich.edu switch (daddr) { 14010152Satgutier@umich.edu case LoadReg: 14110152Satgutier@umich.edu loadValue = pkt->get<uint32_t>(); 14210152Satgutier@umich.edu restartCounter(loadValue); 14310152Satgutier@umich.edu break; 14410152Satgutier@umich.edu case CurrentReg: 14510152Satgutier@umich.edu // Spec says this value can't be written, but linux writes it anyway 14610152Satgutier@umich.edu break; 14710152Satgutier@umich.edu case ControlReg: 14810152Satgutier@umich.edu bool old_enable; 14910152Satgutier@umich.edu old_enable = control.timerEnable; 15010152Satgutier@umich.edu control = pkt->get<uint32_t>(); 15110152Satgutier@umich.edu if ((old_enable == 0) && control.timerEnable) 15210152Satgutier@umich.edu restartCounter(loadValue); 15310152Satgutier@umich.edu break; 15410152Satgutier@umich.edu case IntClear: 15510152Satgutier@umich.edu rawInt = false; 15610152Satgutier@umich.edu if (pendingInt) { 15710152Satgutier@umich.edu pendingInt = false; 15810152Satgutier@umich.edu DPRINTF(Timer, "Clearing interrupt\n"); 15910152Satgutier@umich.edu parent->gic->clearInt(intNum); 16010152Satgutier@umich.edu } 16110152Satgutier@umich.edu break; 16210152Satgutier@umich.edu case BGLoad: 16310152Satgutier@umich.edu loadValue = pkt->get<uint32_t>(); 16410152Satgutier@umich.edu break; 16510152Satgutier@umich.edu default: 16610152Satgutier@umich.edu panic("Tried to write SP804 timer at offset %#x\n", daddr); 16710152Satgutier@umich.edu break; 16810152Satgutier@umich.edu } 16910152Satgutier@umich.edu} 17010152Satgutier@umich.edu 17110152Satgutier@umich.eduvoid 17210152Satgutier@umich.eduSp804::Timer::restartCounter(uint32_t val) 17310152Satgutier@umich.edu{ 17410152Satgutier@umich.edu DPRINTF(Timer, "Resetting counter with value %#x\n", val); 17510152Satgutier@umich.edu if (!control.timerEnable) 17610152Satgutier@umich.edu return; 17710152Satgutier@umich.edu 17810152Satgutier@umich.edu Tick time = clock * power(16, control.timerPrescale); 17910152Satgutier@umich.edu if (control.timerSize) 18010152Satgutier@umich.edu time *= val; 18110152Satgutier@umich.edu else 18210152Satgutier@umich.edu time *= bits(val,15,0); 18310152Satgutier@umich.edu 18410152Satgutier@umich.edu if (zeroEvent.scheduled()) { 18510152Satgutier@umich.edu DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 18610152Satgutier@umich.edu parent->deschedule(zeroEvent); 18710152Satgutier@umich.edu } 18810152Satgutier@umich.edu parent->schedule(zeroEvent, curTick() + time); 18910152Satgutier@umich.edu DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time); 19010152Satgutier@umich.edu} 19110152Satgutier@umich.edu 19210152Satgutier@umich.eduvoid 19310152Satgutier@umich.eduSp804::Timer::counterAtZero() 19410152Satgutier@umich.edu{ 19510152Satgutier@umich.edu if (!control.timerEnable) 19610152Satgutier@umich.edu return; 19710152Satgutier@umich.edu 19810152Satgutier@umich.edu DPRINTF(Timer, "Counter reached zero\n"); 19910152Satgutier@umich.edu 20010152Satgutier@umich.edu rawInt = true; 20110152Satgutier@umich.edu bool old_pending = pendingInt; 20210152Satgutier@umich.edu if (control.intEnable) 20310152Satgutier@umich.edu pendingInt = true; 20410152Satgutier@umich.edu if (pendingInt && !old_pending) { 20510152Satgutier@umich.edu DPRINTF(Timer, "-- Causing interrupt\n"); 20610152Satgutier@umich.edu parent->gic->sendInt(intNum); 20710152Satgutier@umich.edu } 20810152Satgutier@umich.edu 20910152Satgutier@umich.edu if (control.oneShot) 21010152Satgutier@umich.edu return; 21110152Satgutier@umich.edu 21210152Satgutier@umich.edu // Free-running 21310152Satgutier@umich.edu if (control.timerMode == 0) 21410152Satgutier@umich.edu restartCounter(0xffffffff); 21510152Satgutier@umich.edu else 21610152Satgutier@umich.edu restartCounter(loadValue); 21710152Satgutier@umich.edu} 21810152Satgutier@umich.edu 21910152Satgutier@umich.eduvoid 22010152Satgutier@umich.eduSp804::Timer::serialize(std::ostream &os) 22110152Satgutier@umich.edu{ 22210152Satgutier@umich.edu DPRINTF(Checkpoint, "Serializing Arm Sp804\n"); 22310152Satgutier@umich.edu 22410152Satgutier@umich.edu uint32_t control_serial = control; 22510152Satgutier@umich.edu SERIALIZE_SCALAR(control_serial); 22610152Satgutier@umich.edu 22710152Satgutier@umich.edu SERIALIZE_SCALAR(rawInt); 22810152Satgutier@umich.edu SERIALIZE_SCALAR(pendingInt); 22910152Satgutier@umich.edu SERIALIZE_SCALAR(loadValue); 23010152Satgutier@umich.edu 23110152Satgutier@umich.edu bool is_in_event = zeroEvent.scheduled(); 23210152Satgutier@umich.edu SERIALIZE_SCALAR(is_in_event); 23310152Satgutier@umich.edu 23410152Satgutier@umich.edu Tick event_time; 23510152Satgutier@umich.edu if (is_in_event){ 23610152Satgutier@umich.edu event_time = zeroEvent.when(); 23710152Satgutier@umich.edu SERIALIZE_SCALAR(event_time); 23810152Satgutier@umich.edu } 23910152Satgutier@umich.edu} 24010152Satgutier@umich.edu 24110152Satgutier@umich.eduvoid 24210152Satgutier@umich.eduSp804::Timer::unserialize(Checkpoint *cp, const std::string §ion) 24310152Satgutier@umich.edu{ 24410152Satgutier@umich.edu DPRINTF(Checkpoint, "Unserializing Arm Sp804\n"); 24510152Satgutier@umich.edu 24610152Satgutier@umich.edu uint32_t control_serial; 24710152Satgutier@umich.edu UNSERIALIZE_SCALAR(control_serial); 24810152Satgutier@umich.edu control = control_serial; 24910152Satgutier@umich.edu 25010152Satgutier@umich.edu UNSERIALIZE_SCALAR(rawInt); 25110152Satgutier@umich.edu UNSERIALIZE_SCALAR(pendingInt); 25210152Satgutier@umich.edu UNSERIALIZE_SCALAR(loadValue); 25310152Satgutier@umich.edu 25410152Satgutier@umich.edu bool is_in_event; 25510152Satgutier@umich.edu UNSERIALIZE_SCALAR(is_in_event); 25610152Satgutier@umich.edu 25710152Satgutier@umich.edu Tick event_time; 25810152Satgutier@umich.edu if (is_in_event){ 25910152Satgutier@umich.edu UNSERIALIZE_SCALAR(event_time); 26010152Satgutier@umich.edu parent->schedule(zeroEvent, event_time); 26110152Satgutier@umich.edu } 26210152Satgutier@umich.edu} 26310152Satgutier@umich.edu 26410152Satgutier@umich.edu 26510152Satgutier@umich.edu 26610152Satgutier@umich.eduvoid 26710152Satgutier@umich.eduSp804::serialize(std::ostream &os) 26810152Satgutier@umich.edu{ 26910152Satgutier@umich.edu nameOut(os, csprintf("%s.timer0", name())); 27010152Satgutier@umich.edu timer0.serialize(os); 27110152Satgutier@umich.edu nameOut(os, csprintf("%s.timer1", name())); 27210152Satgutier@umich.edu timer1.serialize(os); 27310152Satgutier@umich.edu} 27410152Satgutier@umich.edu 27510152Satgutier@umich.eduvoid 27610152Satgutier@umich.eduSp804::unserialize(Checkpoint *cp, const std::string §ion) 27710152Satgutier@umich.edu{ 27810152Satgutier@umich.edu timer0.unserialize(cp, csprintf("%s.timer0", section)); 27910152Satgutier@umich.edu timer1.unserialize(cp, csprintf("%s.timer1", section)); 28010152Satgutier@umich.edu} 28110152Satgutier@umich.edu 28210152Satgutier@umich.eduSp804 * 28310152Satgutier@umich.eduSp804Params::create() 28410152Satgutier@umich.edu{ 28510152Satgutier@umich.edu return new Sp804(this); 28610152Satgutier@umich.edu} 28710152Satgutier@umich.edu