rtc_pl031.cc revision 8904
12221SN/A/* 22221SN/A * Copyright (c) 2010-2012 ARM Limited 32221SN/A * All rights reserved 42221SN/A * 52221SN/A * The license below extends only to copyright in the software and shall 62221SN/A * not be construed as granting a license to any other intellectual 72221SN/A * property including but not limited to intellectual property relating 82221SN/A * to a hardware implementation of the functionality of the software 92221SN/A * licensed hereunder. You may use the software subject to the license 102221SN/A * terms below provided that you ensure that this notice is replicated 112221SN/A * unmodified and in its entirety in all distributions of the software, 122221SN/A * modified or unmodified, in source code or in binary form. 132221SN/A * 142221SN/A * Redistribution and use in source and binary forms, with or without 152221SN/A * modification, are permitted provided that the following conditions are 162221SN/A * met: redistributions of source code must retain the above copyright 172221SN/A * notice, this list of conditions and the following disclaimer; 182221SN/A * redistributions in binary form must reproduce the above copyright 192221SN/A * notice, this list of conditions and the following disclaimer in the 202221SN/A * documentation and/or other materials provided with the distribution; 212221SN/A * neither the name of the copyright holders nor the names of its 222221SN/A * contributors may be used to endorse or promote products derived from 232221SN/A * this software without specific prior written permission. 242221SN/A * 252221SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262221SN/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, 302221SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312221SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 323415Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 333415Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 342223SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 353415Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 363578Sgblack@eecs.umich.edu * 373415Sgblack@eecs.umich.edu * Authors: Ali Saidi 383415Sgblack@eecs.umich.edu */ 393523Sgblack@eecs.umich.edu 403415Sgblack@eecs.umich.edu#include "base/intmath.hh" 412680Sktlim@umich.edu#include "base/time.hh" 422800Ssaidi@eecs.umich.edu#include "base/trace.hh" 433523Sgblack@eecs.umich.edu#include "debug/Checkpoint.hh" 443415Sgblack@eecs.umich.edu#include "debug/Timer.hh" 452800Ssaidi@eecs.umich.edu#include "dev/arm/amba_device.hh" 462800Ssaidi@eecs.umich.edu#include "dev/arm/rtc_pl031.hh" 472221SN/A#include "dev/mc146818.hh" 483415Sgblack@eecs.umich.edu#include "mem/packet.hh" 493415Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 502223SN/A 512221SN/Ausing namespace AmbaDev; 522221SN/A 533573Sgblack@eecs.umich.eduPL031::PL031(Params *p) 543576Sgblack@eecs.umich.edu : AmbaIntDevice(p), timeVal(mkutctime(&p->time)), lastWrittenTick(0), 553576Sgblack@eecs.umich.edu loadVal(0), matchVal(0), rawInt(false), maskInt(false), 562221SN/A pendingInt(false), matchEvent(this) 573573Sgblack@eecs.umich.edu{ 583576Sgblack@eecs.umich.edu pioSize = 0xfff; 593576Sgblack@eecs.umich.edu} 602221SN/A 613573Sgblack@eecs.umich.edu 623576Sgblack@eecs.umich.eduTick 633576Sgblack@eecs.umich.eduPL031::read(PacketPtr pkt) 642221SN/A{ 653573Sgblack@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 663576Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 673576Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() - pioAddr; 682221SN/A pkt->allocate(); 693573Sgblack@eecs.umich.edu uint32_t data; 703576Sgblack@eecs.umich.edu 713576Sgblack@eecs.umich.edu DPRINTF(Timer, "Reading from RTC at offset: %#x\n", daddr); 722221SN/A 733573Sgblack@eecs.umich.edu switch (daddr) { 743576Sgblack@eecs.umich.edu case DataReg: 753576Sgblack@eecs.umich.edu data = timeVal + ((curTick() - lastWrittenTick) / SimClock::Int::s); 762221SN/A break; 773573Sgblack@eecs.umich.edu case MatchReg: 783576Sgblack@eecs.umich.edu data = matchVal; 793576Sgblack@eecs.umich.edu break; 803576Sgblack@eecs.umich.edu case LoadReg: 813576Sgblack@eecs.umich.edu data = loadVal; 823576Sgblack@eecs.umich.edu break; 833576Sgblack@eecs.umich.edu case ControlReg: 843576Sgblack@eecs.umich.edu data = 1; // Always enabled otherwise there is no point 852221SN/A break; 863573Sgblack@eecs.umich.edu case IntMask: 873576Sgblack@eecs.umich.edu data = maskInt; 883576Sgblack@eecs.umich.edu break; 892221SN/A case RawISR: 903573Sgblack@eecs.umich.edu data = rawInt; 913576Sgblack@eecs.umich.edu break; 923576Sgblack@eecs.umich.edu case MaskedISR: 932221SN/A data = pendingInt; 943573Sgblack@eecs.umich.edu break; 953576Sgblack@eecs.umich.edu default: 963576Sgblack@eecs.umich.edu if (AmbaDev::readId(pkt, ambaId, pioAddr)) { 973576Sgblack@eecs.umich.edu // Hack for variable sized access 983576Sgblack@eecs.umich.edu data = pkt->get<uint32_t>(); 993576Sgblack@eecs.umich.edu break; 1003576Sgblack@eecs.umich.edu } 1013576Sgblack@eecs.umich.edu panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr); 1023576Sgblack@eecs.umich.edu break; 1033576Sgblack@eecs.umich.edu } 1043576Sgblack@eecs.umich.edu 1053576Sgblack@eecs.umich.edu switch(pkt->getSize()) { 1063576Sgblack@eecs.umich.edu case 1: 1072221SN/A pkt->set<uint8_t>(data); 1083573Sgblack@eecs.umich.edu break; 1093576Sgblack@eecs.umich.edu case 2: 1103576Sgblack@eecs.umich.edu pkt->set<uint16_t>(data); 1112221SN/A break; 1123573Sgblack@eecs.umich.edu case 4: 1133576Sgblack@eecs.umich.edu pkt->set<uint32_t>(data); 1143576Sgblack@eecs.umich.edu break; 1152221SN/A default: 1163573Sgblack@eecs.umich.edu panic("Uart read size too big?\n"); 1173576Sgblack@eecs.umich.edu break; 1183576Sgblack@eecs.umich.edu } 1192221SN/A 1203573Sgblack@eecs.umich.edu 1213576Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1223576Sgblack@eecs.umich.edu return pioDelay; 1232221SN/A} 1243573Sgblack@eecs.umich.edu 1253576Sgblack@eecs.umich.eduTick 1263576Sgblack@eecs.umich.eduPL031::write(PacketPtr pkt) 1272221SN/A{ 1283573Sgblack@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1293576Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 1303576Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() - pioAddr; 1312223SN/A pkt->allocate(); 1323573Sgblack@eecs.umich.edu DPRINTF(Timer, "Writing to RTC at offset: %#x\n", daddr); 1333576Sgblack@eecs.umich.edu 1343576Sgblack@eecs.umich.edu switch (daddr) { 1352223SN/A case DataReg: 1363573Sgblack@eecs.umich.edu break; 1373576Sgblack@eecs.umich.edu case MatchReg: 1383576Sgblack@eecs.umich.edu matchVal = pkt->get<uint32_t>(); 1392223SN/A resyncMatch(); 1403573Sgblack@eecs.umich.edu break; 1413576Sgblack@eecs.umich.edu case LoadReg: 1423576Sgblack@eecs.umich.edu lastWrittenTick = curTick(); 1432223SN/A timeVal = pkt->get<uint32_t>(); 1443573Sgblack@eecs.umich.edu loadVal = timeVal; 1453576Sgblack@eecs.umich.edu resyncMatch(); 1463576Sgblack@eecs.umich.edu break; 1473576Sgblack@eecs.umich.edu case ControlReg: 1483576Sgblack@eecs.umich.edu break; // Can't stop when started 1493576Sgblack@eecs.umich.edu case IntMask: 1503576Sgblack@eecs.umich.edu maskInt = pkt->get<uint32_t>(); 1513576Sgblack@eecs.umich.edu break; 1522223SN/A case IntClear: 1533573Sgblack@eecs.umich.edu if (pkt->get<uint32_t>()) { 1543576Sgblack@eecs.umich.edu rawInt = false; 1553576Sgblack@eecs.umich.edu pendingInt = false; 1562223SN/A } 1573573Sgblack@eecs.umich.edu break; 1583576Sgblack@eecs.umich.edu default: 1593576Sgblack@eecs.umich.edu if (AmbaDev::readId(pkt, ambaId, pioAddr)) 1602223SN/A break; 1613573Sgblack@eecs.umich.edu panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr); 1623576Sgblack@eecs.umich.edu break; 1633576Sgblack@eecs.umich.edu } 1642223SN/A 1653573Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1663576Sgblack@eecs.umich.edu return pioDelay; 1673576Sgblack@eecs.umich.edu} 1682223SN/A 1693573Sgblack@eecs.umich.eduvoid 1703576Sgblack@eecs.umich.eduPL031::resyncMatch() 1713576Sgblack@eecs.umich.edu{ 1722223SN/A DPRINTF(Timer, "Setting up new match event match=%d time=%d\n", matchVal, 1733573Sgblack@eecs.umich.edu timeVal); 1743576Sgblack@eecs.umich.edu 1753576Sgblack@eecs.umich.edu uint32_t seconds_until = matchVal - timeVal; 1762223SN/A Tick ticks_until = SimClock::Int::s * seconds_until; 1773573Sgblack@eecs.umich.edu 1783576Sgblack@eecs.umich.edu if (matchEvent.scheduled()) { 1793576Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 1802223SN/A deschedule(matchEvent); 1813573Sgblack@eecs.umich.edu } 1823576Sgblack@eecs.umich.edu schedule(matchEvent, curTick() + ticks_until); 1833576Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + ticks_until); 1842223SN/A} 1853573Sgblack@eecs.umich.edu 1863576Sgblack@eecs.umich.eduvoid 1873576Sgblack@eecs.umich.eduPL031::counterMatch() 1882223SN/A{ 1893573Sgblack@eecs.umich.edu DPRINTF(Timer, "Counter reached zero\n"); 1903576Sgblack@eecs.umich.edu 1913576Sgblack@eecs.umich.edu rawInt = true; 1922223SN/A bool old_pending = pendingInt; 1933576Sgblack@eecs.umich.edu pendingInt = maskInt & rawInt; 1943576Sgblack@eecs.umich.edu if (pendingInt && ~old_pending) { 1953576Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Causing interrupt\n"); 1963576Sgblack@eecs.umich.edu gic->sendInt(intNum); 1972527SN/A } 1983573Sgblack@eecs.umich.edu} 1993576Sgblack@eecs.umich.edu 2003890Ssaidi@eecs.umich.eduvoid 2012223SN/APL031::serialize(std::ostream &os) 2023573Sgblack@eecs.umich.edu{ 2033576Sgblack@eecs.umich.edu DPRINTF(Checkpoint, "Serializing Arm PL031\n"); 2043576Sgblack@eecs.umich.edu SERIALIZE_SCALAR(timeVal); 2052223SN/A SERIALIZE_SCALAR(lastWrittenTick); 2063573Sgblack@eecs.umich.edu SERIALIZE_SCALAR(loadVal); 2073576Sgblack@eecs.umich.edu SERIALIZE_SCALAR(matchVal); 2083576Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rawInt); 2092223SN/A SERIALIZE_SCALAR(maskInt); 2103573Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pendingInt); 2114103Ssaidi@eecs.umich.edu 2124103Ssaidi@eecs.umich.edu bool is_in_event = matchEvent.scheduled(); 2134103Ssaidi@eecs.umich.edu SERIALIZE_SCALAR(is_in_event); 2144103Ssaidi@eecs.umich.edu 2153576Sgblack@eecs.umich.edu Tick event_time; 2163576Sgblack@eecs.umich.edu if (is_in_event){ 2172223SN/A event_time = matchEvent.when(); 2183573Sgblack@eecs.umich.edu SERIALIZE_SCALAR(event_time); 2193576Sgblack@eecs.umich.edu } 2203576Sgblack@eecs.umich.edu} 2212223SN/A 2223573Sgblack@eecs.umich.eduvoid 2233576Sgblack@eecs.umich.eduPL031::unserialize(Checkpoint *cp, const std::string §ion) 2243576Sgblack@eecs.umich.edu{ 2253576Sgblack@eecs.umich.edu DPRINTF(Checkpoint, "Unserializing Arm PL031\n"); 2263576Sgblack@eecs.umich.edu 2273576Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(timeVal); 2283576Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(lastWrittenTick); 2293576Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(loadVal); 2303576Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(matchVal); 2313576Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(rawInt); 2323576Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(maskInt); 2333576Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(pendingInt); 2343576Sgblack@eecs.umich.edu 2353576Sgblack@eecs.umich.edu bool is_in_event; 2363576Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(is_in_event); 2373576Sgblack@eecs.umich.edu 2383576Sgblack@eecs.umich.edu Tick event_time; 2393576Sgblack@eecs.umich.edu if (is_in_event){ 2403576Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(event_time); 2413576Sgblack@eecs.umich.edu schedule(matchEvent, event_time); 2423576Sgblack@eecs.umich.edu } 2433576Sgblack@eecs.umich.edu} 2443576Sgblack@eecs.umich.edu 2453576Sgblack@eecs.umich.edu 2463576Sgblack@eecs.umich.edu 2473893Shsul@eecs.umich.eduPL031 * 2483576Sgblack@eecs.umich.eduPL031Params::create() 2493576Sgblack@eecs.umich.edu{ 2503576Sgblack@eecs.umich.edu return new PL031(this); 2513576Sgblack@eecs.umich.edu} 2523576Sgblack@eecs.umich.edu