rtc_pl031.cc revision 10905
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 "mem/packet.hh" 487199Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 497199Sgblack@eecs.umich.edu 507199Sgblack@eecs.umich.eduPL031::PL031(Params *p) 517199Sgblack@eecs.umich.edu : AmbaIntDevice(p, 0xfff), timeVal(mkutctime(&p->time)), 527199Sgblack@eecs.umich.edu lastWrittenTick(0), loadVal(0), matchVal(0), 537199Sgblack@eecs.umich.edu rawInt(false), maskInt(false), pendingInt(false), matchEvent(this) 547199Sgblack@eecs.umich.edu{ 557199Sgblack@eecs.umich.edu} 567199Sgblack@eecs.umich.edu 577199Sgblack@eecs.umich.edu 587202Sgblack@eecs.umich.eduTick 597202Sgblack@eecs.umich.eduPL031::read(PacketPtr pkt) 607202Sgblack@eecs.umich.edu{ 617202Sgblack@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 627202Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 637202Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() - pioAddr; 647202Sgblack@eecs.umich.edu uint32_t data; 657202Sgblack@eecs.umich.edu 667599Sminkyu.jeong@arm.com DPRINTF(Timer, "Reading from RTC at offset: %#x\n", daddr); 677783SGiacomo.Gabrielli@arm.com 687202Sgblack@eecs.umich.edu switch (daddr) { 697202Sgblack@eecs.umich.edu case DataReg: 707202Sgblack@eecs.umich.edu data = timeVal + ((curTick() - lastWrittenTick) / SimClock::Int::s); 717202Sgblack@eecs.umich.edu break; 727202Sgblack@eecs.umich.edu case MatchReg: 737202Sgblack@eecs.umich.edu data = matchVal; 747202Sgblack@eecs.umich.edu break; 757599Sminkyu.jeong@arm.com case LoadReg: 767783SGiacomo.Gabrielli@arm.com data = loadVal; 777202Sgblack@eecs.umich.edu break; 787202Sgblack@eecs.umich.edu case ControlReg: 797202Sgblack@eecs.umich.edu data = 1; // Always enabled otherwise there is no point 807202Sgblack@eecs.umich.edu break; 817202Sgblack@eecs.umich.edu case IntMask: 827400SAli.Saidi@ARM.com data = maskInt; 837202Sgblack@eecs.umich.edu break; 847400SAli.Saidi@ARM.com case RawISR: 857202Sgblack@eecs.umich.edu data = rawInt; 867202Sgblack@eecs.umich.edu break; 877202Sgblack@eecs.umich.edu case MaskedISR: 887202Sgblack@eecs.umich.edu data = pendingInt; 897202Sgblack@eecs.umich.edu break; 907599Sminkyu.jeong@arm.com default: 917599Sminkyu.jeong@arm.com if (readId(pkt, ambaId, pioAddr)) { 927202Sgblack@eecs.umich.edu // Hack for variable sized access 937202Sgblack@eecs.umich.edu data = pkt->get<uint32_t>(); 947202Sgblack@eecs.umich.edu break; 957202Sgblack@eecs.umich.edu } 967202Sgblack@eecs.umich.edu panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr); 977202Sgblack@eecs.umich.edu break; 987202Sgblack@eecs.umich.edu } 997599Sminkyu.jeong@arm.com 1007599Sminkyu.jeong@arm.com switch(pkt->getSize()) { 1017202Sgblack@eecs.umich.edu case 1: 1027202Sgblack@eecs.umich.edu pkt->set<uint8_t>(data); 1037202Sgblack@eecs.umich.edu break; 1047202Sgblack@eecs.umich.edu case 2: 1057202Sgblack@eecs.umich.edu pkt->set<uint16_t>(data); 1067400SAli.Saidi@ARM.com break; 1077202Sgblack@eecs.umich.edu case 4: 1087400SAli.Saidi@ARM.com pkt->set<uint32_t>(data); 1097202Sgblack@eecs.umich.edu break; 1107202Sgblack@eecs.umich.edu default: 1117202Sgblack@eecs.umich.edu panic("Uart read size too big?\n"); 1127202Sgblack@eecs.umich.edu break; 1137202Sgblack@eecs.umich.edu } 1147599Sminkyu.jeong@arm.com 1157599Sminkyu.jeong@arm.com 1167202Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1177202Sgblack@eecs.umich.edu return pioDelay; 1187202Sgblack@eecs.umich.edu} 1197202Sgblack@eecs.umich.edu 1207202Sgblack@eecs.umich.eduTick 1217202Sgblack@eecs.umich.eduPL031::write(PacketPtr pkt) 1227202Sgblack@eecs.umich.edu{ 1237599Sminkyu.jeong@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1247599Sminkyu.jeong@arm.com assert(pkt->getSize() == 4); 1257202Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() - pioAddr; 1267202Sgblack@eecs.umich.edu DPRINTF(Timer, "Writing to RTC at offset: %#x\n", daddr); 1277202Sgblack@eecs.umich.edu 1287209Sgblack@eecs.umich.edu switch (daddr) { 1297209Sgblack@eecs.umich.edu case DataReg: 1307209Sgblack@eecs.umich.edu break; 1317209Sgblack@eecs.umich.edu case MatchReg: 1327209Sgblack@eecs.umich.edu matchVal = pkt->get<uint32_t>(); 1337261Sgblack@eecs.umich.edu resyncMatch(); 1347209Sgblack@eecs.umich.edu break; 1357209Sgblack@eecs.umich.edu case LoadReg: 1367261Sgblack@eecs.umich.edu lastWrittenTick = curTick(); 1377261Sgblack@eecs.umich.edu timeVal = pkt->get<uint32_t>(); 1387209Sgblack@eecs.umich.edu loadVal = timeVal; 1397209Sgblack@eecs.umich.edu resyncMatch(); 1407209Sgblack@eecs.umich.edu break; 1417209Sgblack@eecs.umich.edu case ControlReg: 1427209Sgblack@eecs.umich.edu break; // Can't stop when started 1437209Sgblack@eecs.umich.edu case IntMask: 1447209Sgblack@eecs.umich.edu maskInt = pkt->get<uint32_t>(); 1457209Sgblack@eecs.umich.edu break; 1467209Sgblack@eecs.umich.edu case IntClear: 1477261Sgblack@eecs.umich.edu if (pkt->get<uint32_t>()) { 1487209Sgblack@eecs.umich.edu rawInt = false; 1497209Sgblack@eecs.umich.edu pendingInt = false; 1507261Sgblack@eecs.umich.edu } 1517261Sgblack@eecs.umich.edu break; 1527209Sgblack@eecs.umich.edu default: 1537209Sgblack@eecs.umich.edu if (readId(pkt, ambaId, pioAddr)) 1547209Sgblack@eecs.umich.edu break; 1557209Sgblack@eecs.umich.edu panic("Tried to read PL031 at offset %#x that doesn't exist\n", daddr); 1567209Sgblack@eecs.umich.edu break; 1577209Sgblack@eecs.umich.edu } 1587261Sgblack@eecs.umich.edu 1597209Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1607209Sgblack@eecs.umich.edu return pioDelay; 1617261Sgblack@eecs.umich.edu} 1627261Sgblack@eecs.umich.edu 1637209Sgblack@eecs.umich.eduvoid 1647226Sgblack@eecs.umich.eduPL031::resyncMatch() 1657249Sgblack@eecs.umich.edu{ 1667249Sgblack@eecs.umich.edu DPRINTF(Timer, "Setting up new match event match=%d time=%d\n", matchVal, 1677249Sgblack@eecs.umich.edu timeVal); 1687249Sgblack@eecs.umich.edu 1697249Sgblack@eecs.umich.edu uint32_t seconds_until = matchVal - timeVal; 1707249Sgblack@eecs.umich.edu Tick ticks_until = SimClock::Int::s * seconds_until; 1717249Sgblack@eecs.umich.edu 1727249Sgblack@eecs.umich.edu if (matchEvent.scheduled()) { 1737249Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 1747249Sgblack@eecs.umich.edu deschedule(matchEvent); 1757249Sgblack@eecs.umich.edu } 1767249Sgblack@eecs.umich.edu schedule(matchEvent, curTick() + ticks_until); 1777249Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + ticks_until); 1787261Sgblack@eecs.umich.edu} 1797249Sgblack@eecs.umich.edu 1807249Sgblack@eecs.umich.eduvoid 1817261Sgblack@eecs.umich.eduPL031::counterMatch() 1827261Sgblack@eecs.umich.edu{ 1837249Sgblack@eecs.umich.edu DPRINTF(Timer, "Counter reached zero\n"); 1847249Sgblack@eecs.umich.edu 1857251Sgblack@eecs.umich.edu rawInt = true; 1867251Sgblack@eecs.umich.edu bool old_pending = pendingInt; 1877251Sgblack@eecs.umich.edu pendingInt = maskInt & rawInt; 1887261Sgblack@eecs.umich.edu if (pendingInt && !old_pending) { 1897251Sgblack@eecs.umich.edu DPRINTF(Timer, "-- Causing interrupt\n"); 1907251Sgblack@eecs.umich.edu gic->sendInt(intNum); 1917261Sgblack@eecs.umich.edu } 1927261Sgblack@eecs.umich.edu} 1937251Sgblack@eecs.umich.edu 1947251Sgblack@eecs.umich.eduvoid 1957226Sgblack@eecs.umich.eduPL031::serialize(CheckpointOut &cp) const 1967226Sgblack@eecs.umich.edu{ 1977226Sgblack@eecs.umich.edu DPRINTF(Checkpoint, "Serializing Arm PL031\n"); 1987232Sgblack@eecs.umich.edu SERIALIZE_SCALAR(timeVal); 1997226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(lastWrittenTick); 2007226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(loadVal); 2017226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(matchVal); 2027226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rawInt); 2037226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(maskInt); 2047232Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pendingInt); 2057226Sgblack@eecs.umich.edu 2067422Sgblack@eecs.umich.edu bool is_in_event = matchEvent.scheduled(); 2077232Sgblack@eecs.umich.edu SERIALIZE_SCALAR(is_in_event); 2087232Sgblack@eecs.umich.edu 2097226Sgblack@eecs.umich.edu Tick event_time; 2107226Sgblack@eecs.umich.edu if (is_in_event){ 2117226Sgblack@eecs.umich.edu event_time = matchEvent.when(); 2127226Sgblack@eecs.umich.edu SERIALIZE_SCALAR(event_time); 2137226Sgblack@eecs.umich.edu } 2147232Sgblack@eecs.umich.edu} 2157226Sgblack@eecs.umich.edu 2167226Sgblack@eecs.umich.eduvoid 2177226Sgblack@eecs.umich.eduPL031::unserialize(CheckpointIn &cp) 2187226Sgblack@eecs.umich.edu{ 2197226Sgblack@eecs.umich.edu DPRINTF(Checkpoint, "Unserializing Arm PL031\n"); 2207232Sgblack@eecs.umich.edu 2217226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(timeVal); 2227422Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(lastWrittenTick); 2237232Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(loadVal); 2247232Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(matchVal); 2257226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(rawInt); 2267226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(maskInt); 2277226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(pendingInt); 2287226Sgblack@eecs.umich.edu 2297226Sgblack@eecs.umich.edu bool is_in_event; 2307226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(is_in_event); 2317226Sgblack@eecs.umich.edu 2327226Sgblack@eecs.umich.edu Tick event_time; 2337232Sgblack@eecs.umich.edu if (is_in_event){ 2347226Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(event_time); 2357226Sgblack@eecs.umich.edu schedule(matchEvent, event_time); 2367232Sgblack@eecs.umich.edu } 2377226Sgblack@eecs.umich.edu} 2387226Sgblack@eecs.umich.edu 2397226Sgblack@eecs.umich.edu 2407226Sgblack@eecs.umich.edu 2417232Sgblack@eecs.umich.eduPL031 * 2427226Sgblack@eecs.umich.eduPL031Params::create() 2437422Sgblack@eecs.umich.edu{ 2447232Sgblack@eecs.umich.edu return new PL031(this); 2457232Sgblack@eecs.umich.edu} 2467226Sgblack@eecs.umich.edu