timer_sp804.cc revision 7584:28ddf6d9e982
12SN/A/* 21762SN/A * Copyright (c) 2010 ARM Limited 32SN/A * All rights reserved 42SN/A * 52SN/A * The license below extends only to copyright in the software and shall 62SN/A * not be construed as granting a license to any other intellectual 72SN/A * property including but not limited to intellectual property relating 82SN/A * to a hardware implementation of the functionality of the software 92SN/A * licensed hereunder. You may use the software subject to the license 102SN/A * terms below provided that you ensure that this notice is replicated 112SN/A * unmodified and in its entirety in all distributions of the software, 122SN/A * modified or unmodified, in source code or in binary form. 132SN/A * 142SN/A * Redistribution and use in source and binary forms, with or without 152SN/A * modification, are permitted provided that the following conditions are 162SN/A * met: redistributions of source code must retain the above copyright 172SN/A * notice, this list of conditions and the following disclaimer; 182SN/A * redistributions in binary form must reproduce the above copyright 192SN/A * notice, this list of conditions and the following disclaimer in the 202SN/A * documentation and/or other materials provided with the distribution; 212SN/A * neither the name of the copyright holders nor the names of its 222SN/A * contributors may be used to endorse or promote products derived from 232SN/A * this software without specific prior written permission. 242SN/A * 252SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272665Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292665Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 328229Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 338229Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 348229Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 358229Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 368229Snate@binkert.org * 378229Snate@binkert.org * Authors: Ali Saidi 382SN/A */ 392SN/A 402SN/A#include "base/intmath.hh" 418229Snate@binkert.org#include "base/trace.hh" 429538Satgutier@umich.edu#include "dev/arm/gic.hh" 438229Snate@binkert.org#include "dev/arm/timer_sp804.hh" 448229Snate@binkert.org#include "mem/packet.hh" 458229Snate@binkert.org#include "mem/packet_access.hh" 468229Snate@binkert.org 478229Snate@binkert.orgSp804::Sp804(Params *p) 4856SN/A : AmbaDevice(p), gic(p->gic), timer0(name() + ".timer0", this, p->int_num0, p->clock0), 498706Sandreas.hansson@arm.com timer1(name() + ".timer1", this, p->int_num1, p->clock1) 502420SN/A{ 512SN/A pioSize = 0xfff; 522SN/A} 5310880SCurtis.Dunham@arm.com 54360SN/ASp804::Timer::Timer(std::string __name, Sp804 *_parent, int int_num, Tick _clock) 55360SN/A : _name(__name), parent(_parent), intNum(int_num), clock(_clock), control(0x20), 5610880SCurtis.Dunham@arm.com rawInt(false), pendingInt(false), loadValue(0xffffffff), zeroEvent(this) 5710422Sandreas.hansson@arm.com{ 5810422Sandreas.hansson@arm.com} 5912SN/A 6012SN/A 612SN/ATick 622SN/ASp804::read(PacketPtr pkt) 632SN/A{ 642SN/A assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 652SN/A assert(pkt->getSize() == 4); 6612SN/A Addr daddr = pkt->getAddr() - pioAddr; 672SN/A pkt->allocate(); 682SN/A DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr); 692420SN/A 7010037SARM gem5 Developers if (daddr < Timer::Size) 712420SN/A timer0.read(pkt, daddr); 722420SN/A else if ((daddr - Timer::Size) < Timer::Size) 7310037SARM gem5 Developers timer1.read(pkt, daddr - Timer::Size); 742420SN/A else if (!readId(pkt)) 758852Sandreas.hansson@arm.com panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr); 762420SN/A pkt->makeAtomicResponse(); 772420SN/A return pioDelay; 782420SN/A} 798852Sandreas.hansson@arm.com 802420SN/A 812420SN/Avoid 822420SN/ASp804::Timer::read(PacketPtr pkt, Addr daddr) 832420SN/A{ 842420SN/A DPRINTF(Timer, "Reading from Timer at offset: %#x\n", daddr); 852420SN/A 862420SN/A switch(daddr) { 8710037SARM gem5 Developers case LoadReg: 882420SN/A pkt->set<uint32_t>(loadValue); 8910037SARM gem5 Developers break; 9010037SARM gem5 Developers case CurrentReg: 9110037SARM gem5 Developers DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n", 922420SN/A zeroEvent.when(), clock, control.timerPrescale); 932420SN/A Tick time; 942420SN/A time = zeroEvent.when() - curTick; 952SN/A time = time / clock / power(16, control.timerPrescale); 962SN/A DPRINTF(Timer, "-- returning counter at %d\n", time); 972SN/A pkt->set<uint32_t>(time); 9812SN/A break; 993918Ssaidi@eecs.umich.edu case ControlReg: 10012SN/A pkt->set<uint32_t>(control); 10112SN/A break; 1022SN/A case RawISR: 1032SN/A pkt->set<uint32_t>(rawInt); 10412SN/A break; 10512SN/A case MaskedISR: 1063584Ssaidi@eecs.umich.edu pkt->set<uint32_t>(pendingInt); 1072SN/A break; 10812SN/A case BGLoad: 10912SN/A pkt->set<uint32_t>(loadValue); 11012SN/A break; 11112SN/A default: 1122SN/A panic("Tried to read SP804 timer at offset %#x\n", daddr); 1132SN/A break; 11412SN/A } 11510422Sandreas.hansson@arm.com} 11610422Sandreas.hansson@arm.com 11710422Sandreas.hansson@arm.comTick 11812SN/ASp804::write(PacketPtr pkt) 11912SN/A{ 12012SN/A assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 12112SN/A assert(pkt->getSize() == 4); 12210880SCurtis.Dunham@arm.com Addr daddr = pkt->getAddr() - pioAddr; 12312SN/A pkt->allocate(); 12412SN/A DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr); 1252SN/A 1262SN/A if (daddr < Timer::Size) 12712SN/A timer0.write(pkt, daddr); 1282SN/A else if ((daddr - Timer::Size) < Timer::Size) 12912SN/A timer1.write(pkt, daddr - Timer::Size); 13010880SCurtis.Dunham@arm.com else if (!readId(pkt)) 13112SN/A panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr); 1322SN/A pkt->makeAtomicResponse(); 1332SN/A return pioDelay; 13410880SCurtis.Dunham@arm.com} 13512SN/A 1362SN/Avoid 1372SN/ASp804::Timer::write(PacketPtr pkt, Addr daddr) 13810880SCurtis.Dunham@arm.com{ 13912SN/A DPRINTF(Timer, "Writing to Timer at offset: %#x\n", daddr); 1402SN/A switch (daddr) { 1412SN/A case LoadReg: 14210880SCurtis.Dunham@arm.com loadValue = pkt->get<uint32_t>(); 1439538Satgutier@umich.edu restartCounter(loadValue); 1449538Satgutier@umich.edu break; 1459538Satgutier@umich.edu case CurrentReg: 1463584Ssaidi@eecs.umich.edu // Spec says this value can't be written, but linux writes it anyway 14710880SCurtis.Dunham@arm.com break; 1483584Ssaidi@eecs.umich.edu case ControlReg: 14912SN/A bool old_enable; 1503918Ssaidi@eecs.umich.edu old_enable = control.timerEnable; 15112SN/A control = pkt->get<uint32_t>(); 1522SN/A if ((old_enable == 0) && control.timerEnable) 153 restartCounter(loadValue); 154 break; 155 case IntClear: 156 rawInt = false; 157 if (pendingInt) { 158 pendingInt = false; 159 DPRINTF(Timer, "Clearing interrupt\n"); 160 parent->gic->clearInt(intNum); 161 } 162 break; 163 case BGLoad: 164 loadValue = pkt->get<uint32_t>(); 165 break; 166 default: 167 panic("Tried to write SP804 timer at offset %#x\n", daddr); 168 break; 169 } 170} 171 172void 173Sp804::Timer::restartCounter(uint32_t val) 174{ 175 DPRINTF(Timer, "Resetting counter with value %#x\n", val); 176 if (!control.timerEnable) 177 return; 178 179 Tick time = clock << power(16, control.timerPrescale); 180 if (control.timerSize) 181 time *= bits(val,15,0); 182 else 183 time *= val; 184 185 if (zeroEvent.scheduled()) { 186 DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 187 parent->deschedule(zeroEvent); 188 } 189 parent->schedule(zeroEvent, curTick + time); 190 DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick + time); 191} 192 193void 194Sp804::Timer::counterAtZero() 195{ 196 if (!control.timerEnable) 197 return; 198 199 DPRINTF(Timer, "Counter reached zero\n"); 200 201 rawInt = true; 202 bool old_pending = pendingInt; 203 if (control.intEnable) 204 pendingInt = true; 205 if (pendingInt && ~old_pending) { 206 DPRINTF(Timer, "-- Causing interrupt\n"); 207 parent->gic->sendInt(intNum); 208 } 209 210 if (control.oneShot) 211 return; 212 213 // Free-running 214 if (control.timerMode == 0) 215 restartCounter(0xffffffff); 216 else 217 restartCounter(loadValue); 218} 219 220 221void 222Sp804::serialize(std::ostream &os) 223{ 224 panic("Need to implement serialization\n"); 225} 226 227void 228Sp804::unserialize(Checkpoint *cp, const std::string §ion) 229{ 230 panic("Need to implement serialization\n"); 231} 232 233Sp804 * 234Sp804Params::create() 235{ 236 return new Sp804(this); 237} 238