rtc_pl031.cc revision 9806
17199Sgblack@eecs.umich.edu/* 27199Sgblack@eecs.umich.edu * Copyright (c) 2010-2012 ARM Limited 37199Sgblack@eecs.umich.edu * All rights reserved 47199Sgblack@eecs.umich.edu * 57199Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 67199Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 77199Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 87199Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 97199Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 107199Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 117199Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 127199Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137199Sgblack@eecs.umich.edu * 147199Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 157199Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 167199Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 177199Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 187199Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 197199Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 207199Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 217199Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 227199Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 237199Sgblack@eecs.umich.edu * this software without specific prior written permission. 247199Sgblack@eecs.umich.edu * 257199Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 267199Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 277199Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 287199Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 297199Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307199Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 317199Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 327199Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337199Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347199Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 357199Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 367199Sgblack@eecs.umich.edu * 377199Sgblack@eecs.umich.edu * Authors: Ali Saidi 387199Sgblack@eecs.umich.edu */ 397199Sgblack@eecs.umich.edu 407199Sgblack@eecs.umich.edu#include "base/intmath.hh" 417199Sgblack@eecs.umich.edu#include "base/time.hh" 427199Sgblack@eecs.umich.edu#include "base/trace.hh" 437199Sgblack@eecs.umich.edu#include "debug/Checkpoint.hh" 447199Sgblack@eecs.umich.edu#include "debug/Timer.hh" 457199Sgblack@eecs.umich.edu#include "dev/arm/amba_device.hh" 467199Sgblack@eecs.umich.edu#include "dev/arm/rtc_pl031.hh" 477199Sgblack@eecs.umich.edu#include "dev/mc146818.hh" 487199Sgblack@eecs.umich.edu#include "mem/packet.hh" 497199Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 507199Sgblack@eecs.umich.edu 517199Sgblack@eecs.umich.eduPL031::PL031(Params *p) 527199Sgblack@eecs.umich.edu : AmbaIntDevice(p), timeVal(mkutctime(&p->time)), lastWrittenTick(0), 537199Sgblack@eecs.umich.edu loadVal(0), matchVal(0), rawInt(false), maskInt(false), 547199Sgblack@eecs.umich.edu pendingInt(false), matchEvent(this) 557199Sgblack@eecs.umich.edu{ 567199Sgblack@eecs.umich.edu pioSize = 0xfff; 577199Sgblack@eecs.umich.edu} 587202Sgblack@eecs.umich.edu 597202Sgblack@eecs.umich.edu 607202Sgblack@eecs.umich.eduTick 617202Sgblack@eecs.umich.eduPL031::read(PacketPtr pkt) 627202Sgblack@eecs.umich.edu{ 637202Sgblack@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 647202Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 657202Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() - pioAddr; 667599Sminkyu.jeong@arm.com pkt->allocate(); 677599Sminkyu.jeong@arm.com uint32_t data; 687202Sgblack@eecs.umich.edu 697202Sgblack@eecs.umich.edu DPRINTF(Timer, "Reading from RTC at offset: %#x\n", daddr); 707202Sgblack@eecs.umich.edu 717202Sgblack@eecs.umich.edu switch (daddr) { 727202Sgblack@eecs.umich.edu case DataReg: 737202Sgblack@eecs.umich.edu data = timeVal + ((curTick() - lastWrittenTick) / SimClock::Int::s); 747202Sgblack@eecs.umich.edu break; 757599Sminkyu.jeong@arm.com case MatchReg: 767599Sminkyu.jeong@arm.com data = matchVal; 777202Sgblack@eecs.umich.edu break; 787202Sgblack@eecs.umich.edu case LoadReg: 797202Sgblack@eecs.umich.edu data = loadVal; 807202Sgblack@eecs.umich.edu break; 817202Sgblack@eecs.umich.edu case ControlReg: 827400SAli.Saidi@ARM.com data = 1; // Always enabled otherwise there is no point 837202Sgblack@eecs.umich.edu break; 847400SAli.Saidi@ARM.com case IntMask: 857202Sgblack@eecs.umich.edu data = maskInt; 867202Sgblack@eecs.umich.edu break; 877202Sgblack@eecs.umich.edu case RawISR: 887202Sgblack@eecs.umich.edu data = rawInt; 897202Sgblack@eecs.umich.edu break; 907599Sminkyu.jeong@arm.com case MaskedISR: 917599Sminkyu.jeong@arm.com data = pendingInt; 927202Sgblack@eecs.umich.edu break; 937202Sgblack@eecs.umich.edu default: 947202Sgblack@eecs.umich.edu if (readId(pkt, ambaId, pioAddr)) { 957202Sgblack@eecs.umich.edu // Hack for variable sized access 967202Sgblack@eecs.umich.edu data = pkt->get<uint32_t>(); 977202Sgblack@eecs.umich.edu break; 987202Sgblack@eecs.umich.edu } 997599Sminkyu.jeong@arm.com panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr); 1007599Sminkyu.jeong@arm.com break; 1017202Sgblack@eecs.umich.edu } 1027202Sgblack@eecs.umich.edu 1037202Sgblack@eecs.umich.edu switch(pkt->getSize()) { 1047202Sgblack@eecs.umich.edu case 1: 1057202Sgblack@eecs.umich.edu pkt->set<uint8_t>(data); 1067400SAli.Saidi@ARM.com break; 1077202Sgblack@eecs.umich.edu case 2: 1087400SAli.Saidi@ARM.com pkt->set<uint16_t>(data); 1097202Sgblack@eecs.umich.edu break; 1107202Sgblack@eecs.umich.edu case 4: 1117202Sgblack@eecs.umich.edu pkt->set<uint32_t>(data); 1127202Sgblack@eecs.umich.edu break; 1137202Sgblack@eecs.umich.edu default: 1147599Sminkyu.jeong@arm.com panic("Uart read size too big?\n"); 1157599Sminkyu.jeong@arm.com break; 1167202Sgblack@eecs.umich.edu } 1177202Sgblack@eecs.umich.edu 1187202Sgblack@eecs.umich.edu 1197202Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1207202Sgblack@eecs.umich.edu return pioDelay; 1217202Sgblack@eecs.umich.edu} 1227202Sgblack@eecs.umich.edu 1237599Sminkyu.jeong@arm.comTick 1247599Sminkyu.jeong@arm.comPL031::write(PacketPtr pkt) 1257202Sgblack@eecs.umich.edu{ 1267202Sgblack@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1277202Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 1287209Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() - pioAddr; 1297209Sgblack@eecs.umich.edu pkt->allocate(); 1307209Sgblack@eecs.umich.edu DPRINTF(Timer, "Writing to RTC at offset: %#x\n", daddr); 1317209Sgblack@eecs.umich.edu 1327209Sgblack@eecs.umich.edu switch (daddr) { 1337261Sgblack@eecs.umich.edu case DataReg: 1347209Sgblack@eecs.umich.edu break; 1357209Sgblack@eecs.umich.edu case MatchReg: 1367261Sgblack@eecs.umich.edu matchVal = pkt->get<uint32_t>(); 1377261Sgblack@eecs.umich.edu resyncMatch(); 1387209Sgblack@eecs.umich.edu break; 1397209Sgblack@eecs.umich.edu case LoadReg: 1407209Sgblack@eecs.umich.edu lastWrittenTick = curTick(); 1417209Sgblack@eecs.umich.edu timeVal = pkt->get<uint32_t>(); 1427209Sgblack@eecs.umich.edu loadVal = timeVal; 1437209Sgblack@eecs.umich.edu resyncMatch(); 1447209Sgblack@eecs.umich.edu break; 1457209Sgblack@eecs.umich.edu case ControlReg: 1467209Sgblack@eecs.umich.edu break; // Can't stop when started 1477261Sgblack@eecs.umich.edu case IntMask: 1487209Sgblack@eecs.umich.edu maskInt = pkt->get<uint32_t>(); 1497209Sgblack@eecs.umich.edu break; 1507261Sgblack@eecs.umich.edu case IntClear: 1517261Sgblack@eecs.umich.edu if (pkt->get<uint32_t>()) { 1527209Sgblack@eecs.umich.edu rawInt = false; 1537209Sgblack@eecs.umich.edu pendingInt = false; 1547209Sgblack@eecs.umich.edu } 1557209Sgblack@eecs.umich.edu break; 1567209Sgblack@eecs.umich.edu default: 1577209Sgblack@eecs.umich.edu if (readId(pkt, ambaId, pioAddr)) 1587261Sgblack@eecs.umich.edu break; 1597209Sgblack@eecs.umich.edu panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr); 1607209Sgblack@eecs.umich.edu break; 1617261Sgblack@eecs.umich.edu } 1627261Sgblack@eecs.umich.edu 1637209Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1647226Sgblack@eecs.umich.edu return pioDelay; 1657249Sgblack@eecs.umich.edu} 1667249Sgblack@eecs.umich.edu 1677249Sgblack@eecs.umich.eduvoid 1687249Sgblack@eecs.umich.eduPL031::resyncMatch() 1697249Sgblack@eecs.umich.edu{ 1707249Sgblack@eecs.umich.edu DPRINTF(Timer, "Setting up new match event match=%d time=%d\n", matchVal, 1717249Sgblack@eecs.umich.edu timeVal); 1727249Sgblack@eecs.umich.edu 1737249Sgblack@eecs.umich.edu uint32_t seconds_until = matchVal - timeVal; 1747249Sgblack@eecs.umich.edu Tick ticks_until = SimClock::Int::s * seconds_until; 1757249Sgblack@eecs.umich.edu 1767249Sgblack@eecs.umich.edu if (matchEvent.scheduled()) { 1777249Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 1787261Sgblack@eecs.umich.edu deschedule(matchEvent); 1797249Sgblack@eecs.umich.edu } 1807249Sgblack@eecs.umich.edu schedule(matchEvent, curTick() + ticks_until); 1817261Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + ticks_until); 1827261Sgblack@eecs.umich.edu} 1837249Sgblack@eecs.umich.edu 1847249Sgblack@eecs.umich.eduvoid 1857251Sgblack@eecs.umich.eduPL031::counterMatch() 1867251Sgblack@eecs.umich.edu{ 1877251Sgblack@eecs.umich.edu DPRINTF(Timer, "Counter reached zero\n"); 1887261Sgblack@eecs.umich.edu 1897251Sgblack@eecs.umich.edu rawInt = true; 1907251Sgblack@eecs.umich.edu bool old_pending = pendingInt; 1917261Sgblack@eecs.umich.edu pendingInt = maskInt & rawInt; 1927261Sgblack@eecs.umich.edu if (pendingInt && !old_pending) { 1937251Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Causing interrupt\n"); 1947251Sgblack@eecs.umich.edu gic->sendInt(intNum); 1957226Sgblack@eecs.umich.edu } 1967226Sgblack@eecs.umich.edu} 1977226Sgblack@eecs.umich.edu 1987232Sgblack@eecs.umich.eduvoid 1997226Sgblack@eecs.umich.eduPL031::serialize(std::ostream &os) 2007226Sgblack@eecs.umich.edu{ 2017226Sgblack@eecs.umich.edu DPRINTF(Checkpoint, "Serializing Arm PL031\n"); 2027226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(timeVal); 2037226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(lastWrittenTick); 2047232Sgblack@eecs.umich.edu SERIALIZE_SCALAR(loadVal); 2057226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(matchVal); 2067422Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rawInt); 2077232Sgblack@eecs.umich.edu SERIALIZE_SCALAR(maskInt); 2087232Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pendingInt); 2097226Sgblack@eecs.umich.edu 2107226Sgblack@eecs.umich.edu bool is_in_event = matchEvent.scheduled(); 2117226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(is_in_event); 2127226Sgblack@eecs.umich.edu 2137226Sgblack@eecs.umich.edu Tick event_time; 2147232Sgblack@eecs.umich.edu if (is_in_event){ 2157226Sgblack@eecs.umich.edu event_time = matchEvent.when(); 2167226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(event_time); 2177226Sgblack@eecs.umich.edu } 2187226Sgblack@eecs.umich.edu} 2197226Sgblack@eecs.umich.edu 2207232Sgblack@eecs.umich.eduvoid 2217226Sgblack@eecs.umich.eduPL031::unserialize(Checkpoint *cp, const std::string §ion) 2227422Sgblack@eecs.umich.edu{ 2237232Sgblack@eecs.umich.edu DPRINTF(Checkpoint, "Unserializing Arm PL031\n"); 2247232Sgblack@eecs.umich.edu 2257226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(timeVal); 2267226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(lastWrittenTick); 2277226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(loadVal); 2287226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(matchVal); 2297226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(rawInt); 2307226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(maskInt); 2317226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(pendingInt); 2327226Sgblack@eecs.umich.edu 2337232Sgblack@eecs.umich.edu bool is_in_event; 2347226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(is_in_event); 2357226Sgblack@eecs.umich.edu 2367232Sgblack@eecs.umich.edu Tick event_time; 2377226Sgblack@eecs.umich.edu if (is_in_event){ 2387226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(event_time); 2397226Sgblack@eecs.umich.edu schedule(matchEvent, event_time); 2407226Sgblack@eecs.umich.edu } 2417232Sgblack@eecs.umich.edu} 2427226Sgblack@eecs.umich.edu 2437422Sgblack@eecs.umich.edu 2447232Sgblack@eecs.umich.edu 2457232Sgblack@eecs.umich.eduPL031 * 2467226Sgblack@eecs.umich.eduPL031Params::create() 2477226Sgblack@eecs.umich.edu{ 2487226Sgblack@eecs.umich.edu return new PL031(this); 2497226Sgblack@eecs.umich.edu} 2507226Sgblack@eecs.umich.edu