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