rtc_pl031.cc revision 9808
17160Sgblack@eecs.umich.edu/* 27160Sgblack@eecs.umich.edu * Copyright (c) 2010-2012 ARM Limited 37160Sgblack@eecs.umich.edu * All rights reserved 47160Sgblack@eecs.umich.edu * 57160Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 67160Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 77160Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 87160Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 97160Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 107160Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 117160Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 127160Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137160Sgblack@eecs.umich.edu * 147160Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 157160Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 167160Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 177160Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 187160Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 197160Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 207160Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 217160Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 227160Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 237160Sgblack@eecs.umich.edu * this software without specific prior written permission. 247160Sgblack@eecs.umich.edu * 257160Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 267160Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 277160Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 287160Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 297160Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307160Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 317160Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 327160Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337160Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347160Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 357160Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 367160Sgblack@eecs.umich.edu * 377160Sgblack@eecs.umich.edu * Authors: Ali Saidi 387160Sgblack@eecs.umich.edu */ 397160Sgblack@eecs.umich.edu 407160Sgblack@eecs.umich.edu#include "base/intmath.hh" 417160Sgblack@eecs.umich.edu#include "base/time.hh" 427160Sgblack@eecs.umich.edu#include "base/trace.hh" 437160Sgblack@eecs.umich.edu#include "debug/Checkpoint.hh" 447160Sgblack@eecs.umich.edu#include "debug/Timer.hh" 457160Sgblack@eecs.umich.edu#include "dev/arm/amba_device.hh" 467160Sgblack@eecs.umich.edu#include "dev/arm/rtc_pl031.hh" 478302SAli.Saidi@ARM.com#include "dev/mc146818.hh" 487160Sgblack@eecs.umich.edu#include "mem/packet.hh" 497160Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 507160Sgblack@eecs.umich.edu 517160Sgblack@eecs.umich.eduPL031::PL031(Params *p) 527160Sgblack@eecs.umich.edu : AmbaIntDevice(p, 0xfff), timeVal(mkutctime(&p->time)), 537160Sgblack@eecs.umich.edu lastWrittenTick(0), loadVal(0), matchVal(0), 547160Sgblack@eecs.umich.edu rawInt(false), maskInt(false), pendingInt(false), matchEvent(this) 558301SAli.Saidi@ARM.com{ 567160Sgblack@eecs.umich.edu} 577160Sgblack@eecs.umich.edu 587160Sgblack@eecs.umich.edu 597160Sgblack@eecs.umich.eduTick 607160Sgblack@eecs.umich.eduPL031::read(PacketPtr pkt) 617160Sgblack@eecs.umich.edu{ 627160Sgblack@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 637160Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 647160Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() - pioAddr; 657160Sgblack@eecs.umich.edu pkt->allocate(); 667160Sgblack@eecs.umich.edu uint32_t data; 677160Sgblack@eecs.umich.edu 687160Sgblack@eecs.umich.edu DPRINTF(Timer, "Reading from RTC at offset: %#x\n", daddr); 697160Sgblack@eecs.umich.edu 707160Sgblack@eecs.umich.edu switch (daddr) { 717160Sgblack@eecs.umich.edu case DataReg: 727160Sgblack@eecs.umich.edu data = timeVal + ((curTick() - lastWrittenTick) / SimClock::Int::s); 737160Sgblack@eecs.umich.edu break; 747160Sgblack@eecs.umich.edu case MatchReg: 757160Sgblack@eecs.umich.edu data = matchVal; 767160Sgblack@eecs.umich.edu break; 777160Sgblack@eecs.umich.edu case LoadReg: 787160Sgblack@eecs.umich.edu data = loadVal; 797160Sgblack@eecs.umich.edu break; 807160Sgblack@eecs.umich.edu case ControlReg: 817160Sgblack@eecs.umich.edu data = 1; // Always enabled otherwise there is no point 827160Sgblack@eecs.umich.edu break; 837160Sgblack@eecs.umich.edu case IntMask: 847160Sgblack@eecs.umich.edu data = maskInt; 857160Sgblack@eecs.umich.edu break; 867162Sgblack@eecs.umich.edu case RawISR: 877160Sgblack@eecs.umich.edu data = rawInt; 887160Sgblack@eecs.umich.edu break; 897160Sgblack@eecs.umich.edu case MaskedISR: 907160Sgblack@eecs.umich.edu data = pendingInt; 917760SGiacomo.Gabrielli@arm.com break; 927760SGiacomo.Gabrielli@arm.com default: 937160Sgblack@eecs.umich.edu if (readId(pkt, ambaId, pioAddr)) { 947160Sgblack@eecs.umich.edu // Hack for variable sized access 957160Sgblack@eecs.umich.edu data = pkt->get<uint32_t>(); 967760SGiacomo.Gabrielli@arm.com break; 977760SGiacomo.Gabrielli@arm.com } 987160Sgblack@eecs.umich.edu panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr); 997160Sgblack@eecs.umich.edu break; 1007160Sgblack@eecs.umich.edu } 1017160Sgblack@eecs.umich.edu 1027160Sgblack@eecs.umich.edu switch(pkt->getSize()) { 1037160Sgblack@eecs.umich.edu case 1: 1047160Sgblack@eecs.umich.edu pkt->set<uint8_t>(data); 1057160Sgblack@eecs.umich.edu break; 1067160Sgblack@eecs.umich.edu case 2: 1077160Sgblack@eecs.umich.edu pkt->set<uint16_t>(data); 1087160Sgblack@eecs.umich.edu break; 1097160Sgblack@eecs.umich.edu case 4: 1107160Sgblack@eecs.umich.edu pkt->set<uint32_t>(data); 1117160Sgblack@eecs.umich.edu break; 1127160Sgblack@eecs.umich.edu default: 1137160Sgblack@eecs.umich.edu panic("Uart read size too big?\n"); 1147160Sgblack@eecs.umich.edu break; 1157160Sgblack@eecs.umich.edu } 1167160Sgblack@eecs.umich.edu 1177160Sgblack@eecs.umich.edu 1187160Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1197160Sgblack@eecs.umich.edu return pioDelay; 1207160Sgblack@eecs.umich.edu} 1217160Sgblack@eecs.umich.edu 1227160Sgblack@eecs.umich.eduTick 1237160Sgblack@eecs.umich.eduPL031::write(PacketPtr pkt) 1247160Sgblack@eecs.umich.edu{ 1257160Sgblack@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1267160Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 1277160Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() - pioAddr; 1287160Sgblack@eecs.umich.edu pkt->allocate(); 1297160Sgblack@eecs.umich.edu DPRINTF(Timer, "Writing to RTC at offset: %#x\n", daddr); 1307160Sgblack@eecs.umich.edu 1317160Sgblack@eecs.umich.edu switch (daddr) { 1327160Sgblack@eecs.umich.edu case DataReg: 1337160Sgblack@eecs.umich.edu break; 1347160Sgblack@eecs.umich.edu case MatchReg: 1357160Sgblack@eecs.umich.edu matchVal = pkt->get<uint32_t>(); 1367160Sgblack@eecs.umich.edu resyncMatch(); 1377160Sgblack@eecs.umich.edu break; 1387196Sgblack@eecs.umich.edu case LoadReg: 1397160Sgblack@eecs.umich.edu lastWrittenTick = curTick(); 1407196Sgblack@eecs.umich.edu timeVal = pkt->get<uint32_t>(); 1417196Sgblack@eecs.umich.edu loadVal = timeVal; 1427160Sgblack@eecs.umich.edu resyncMatch(); 1437160Sgblack@eecs.umich.edu break; 1447160Sgblack@eecs.umich.edu case ControlReg: 1457196Sgblack@eecs.umich.edu break; // Can't stop when started 1467160Sgblack@eecs.umich.edu case IntMask: 1477196Sgblack@eecs.umich.edu maskInt = pkt->get<uint32_t>(); 1487196Sgblack@eecs.umich.edu break; 1497160Sgblack@eecs.umich.edu case IntClear: 1507160Sgblack@eecs.umich.edu if (pkt->get<uint32_t>()) { 1517160Sgblack@eecs.umich.edu rawInt = false; 1527196Sgblack@eecs.umich.edu pendingInt = false; 1537160Sgblack@eecs.umich.edu } 1547196Sgblack@eecs.umich.edu break; 1557196Sgblack@eecs.umich.edu default: 1567160Sgblack@eecs.umich.edu if (readId(pkt, ambaId, pioAddr)) 1577160Sgblack@eecs.umich.edu break; 1587160Sgblack@eecs.umich.edu panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr); 1597196Sgblack@eecs.umich.edu break; 1607160Sgblack@eecs.umich.edu } 1617196Sgblack@eecs.umich.edu 1627196Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1637160Sgblack@eecs.umich.edu return pioDelay; 1647160Sgblack@eecs.umich.edu} 1657160Sgblack@eecs.umich.edu 1667160Sgblack@eecs.umich.eduvoid 1677160Sgblack@eecs.umich.eduPL031::resyncMatch() 1687160Sgblack@eecs.umich.edu{ 1697160Sgblack@eecs.umich.edu DPRINTF(Timer, "Setting up new match event match=%d time=%d\n", matchVal, 1707228Sgblack@eecs.umich.edu timeVal); 1717228Sgblack@eecs.umich.edu 1727160Sgblack@eecs.umich.edu uint32_t seconds_until = matchVal - timeVal; 1737160Sgblack@eecs.umich.edu Tick ticks_until = SimClock::Int::s * seconds_until; 1747160Sgblack@eecs.umich.edu 1757160Sgblack@eecs.umich.edu if (matchEvent.scheduled()) { 1767160Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 1777160Sgblack@eecs.umich.edu deschedule(matchEvent); 1787160Sgblack@eecs.umich.edu } 1797228Sgblack@eecs.umich.edu schedule(matchEvent, curTick() + ticks_until); 1807228Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + ticks_until); 1817160Sgblack@eecs.umich.edu} 1827160Sgblack@eecs.umich.edu 1837160Sgblack@eecs.umich.eduvoid 1847160Sgblack@eecs.umich.eduPL031::counterMatch() 1857160Sgblack@eecs.umich.edu{ 1867160Sgblack@eecs.umich.edu DPRINTF(Timer, "Counter reached zero\n"); 1877160Sgblack@eecs.umich.edu 1887160Sgblack@eecs.umich.edu rawInt = true; 1897160Sgblack@eecs.umich.edu bool old_pending = pendingInt; 1907160Sgblack@eecs.umich.edu pendingInt = maskInt & rawInt; 1917160Sgblack@eecs.umich.edu if (pendingInt && !old_pending) { 1927160Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Causing interrupt\n"); 1937160Sgblack@eecs.umich.edu gic->sendInt(intNum); 1947160Sgblack@eecs.umich.edu } 1957160Sgblack@eecs.umich.edu} 1967160Sgblack@eecs.umich.edu 1977160Sgblack@eecs.umich.eduvoid 1987160Sgblack@eecs.umich.eduPL031::serialize(std::ostream &os) 1997160Sgblack@eecs.umich.edu{ 2007160Sgblack@eecs.umich.edu DPRINTF(Checkpoint, "Serializing Arm PL031\n"); 2017160Sgblack@eecs.umich.edu SERIALIZE_SCALAR(timeVal); 2027160Sgblack@eecs.umich.edu SERIALIZE_SCALAR(lastWrittenTick); 2037160Sgblack@eecs.umich.edu SERIALIZE_SCALAR(loadVal); 2047160Sgblack@eecs.umich.edu SERIALIZE_SCALAR(matchVal); 2057160Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rawInt); 2067160Sgblack@eecs.umich.edu SERIALIZE_SCALAR(maskInt); 2077160Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pendingInt); 2087160Sgblack@eecs.umich.edu 2097160Sgblack@eecs.umich.edu bool is_in_event = matchEvent.scheduled(); 2107160Sgblack@eecs.umich.edu SERIALIZE_SCALAR(is_in_event); 2117160Sgblack@eecs.umich.edu 2127160Sgblack@eecs.umich.edu Tick event_time; 2137160Sgblack@eecs.umich.edu if (is_in_event){ 2147160Sgblack@eecs.umich.edu event_time = matchEvent.when(); 2157160Sgblack@eecs.umich.edu SERIALIZE_SCALAR(event_time); 2167160Sgblack@eecs.umich.edu } 2177160Sgblack@eecs.umich.edu} 2187160Sgblack@eecs.umich.edu 2197160Sgblack@eecs.umich.eduvoid 2207160Sgblack@eecs.umich.eduPL031::unserialize(Checkpoint *cp, const std::string §ion) 2217160Sgblack@eecs.umich.edu{ 2227160Sgblack@eecs.umich.edu DPRINTF(Checkpoint, "Unserializing Arm PL031\n"); 2237160Sgblack@eecs.umich.edu 2247160Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(timeVal); 2257160Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(lastWrittenTick); 2267160Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(loadVal); 2277160Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(matchVal); 2287160Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(rawInt); 2297160Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(maskInt); 2307160Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(pendingInt); 2317160Sgblack@eecs.umich.edu 2327160Sgblack@eecs.umich.edu bool is_in_event; 2337160Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(is_in_event); 2347160Sgblack@eecs.umich.edu 2357160Sgblack@eecs.umich.edu Tick event_time; 2367160Sgblack@eecs.umich.edu if (is_in_event){ 2377160Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(event_time); 2387196Sgblack@eecs.umich.edu schedule(matchEvent, event_time); 2397196Sgblack@eecs.umich.edu } 2407196Sgblack@eecs.umich.edu} 2417160Sgblack@eecs.umich.edu 2427160Sgblack@eecs.umich.edu 2437160Sgblack@eecs.umich.edu 2447160Sgblack@eecs.umich.eduPL031 * 2457196Sgblack@eecs.umich.eduPL031Params::create() 2467196Sgblack@eecs.umich.edu{ 2477196Sgblack@eecs.umich.edu return new PL031(this); 2487160Sgblack@eecs.umich.edu} 2497160Sgblack@eecs.umich.edu