timer_sp804.cc revision 9525:0587c8983d47
12SN/A/*
29428SAndreas.Sandberg@ARM.com * Copyright (c) 2010 ARM Limited
39920Syasuko.eckert@amd.com * All rights reserved
48733Sgeoffrey.blake@arm.com *
58733Sgeoffrey.blake@arm.com * The license below extends only to copyright in the software and shall
68733Sgeoffrey.blake@arm.com * not be construed as granting a license to any other intellectual
78733Sgeoffrey.blake@arm.com * property including but not limited to intellectual property relating
88733Sgeoffrey.blake@arm.com * to a hardware implementation of the functionality of the software
98733Sgeoffrey.blake@arm.com * licensed hereunder.  You may use the software subject to the license
108733Sgeoffrey.blake@arm.com * terms below provided that you ensure that this notice is replicated
118733Sgeoffrey.blake@arm.com * unmodified and in its entirety in all distributions of the software,
128733Sgeoffrey.blake@arm.com * modified or unmodified, in source code or in binary form.
138733Sgeoffrey.blake@arm.com *
148733Sgeoffrey.blake@arm.com * Redistribution and use in source and binary forms, with or without
152190SN/A * modification, are permitted provided that the following conditions are
162SN/A * met: redistributions of source code must retain the above copyright
172SN/A * notice, this list of conditions and the following disclaimer;
182SN/A * redistributions in binary form must reproduce the above copyright
192SN/A * notice, this list of conditions and the following disclaimer in the
202SN/A * documentation and/or other materials provided with the distribution;
212SN/A * neither the name of the copyright holders nor the names of its
222SN/A * contributors may be used to endorse or promote products derived from
232SN/A * this software without specific prior written permission.
242SN/A *
252SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
262SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
272SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
312SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
322SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
332SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
342SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
352SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
362SN/A *
372SN/A * Authors: Ali Saidi
382SN/A */
392SN/A
402665SN/A#include "base/intmath.hh"
412665SN/A#include "base/trace.hh"
422SN/A#include "debug/Checkpoint.hh"
432SN/A#include "debug/Timer.hh"
442680Sktlim@umich.edu#include "dev/arm/base_gic.hh"
452680Sktlim@umich.edu#include "dev/arm/timer_sp804.hh"
462SN/A#include "mem/packet.hh"
478229Snate@binkert.org#include "mem/packet_access.hh"
487680Sgblack@eecs.umich.edu
497680Sgblack@eecs.umich.eduusing namespace AmbaDev;
506329Sgblack@eecs.umich.edu
513453Sgblack@eecs.umich.eduSp804::Sp804(Params *p)
526216Snate@binkert.org    : AmbaDevice(p), gic(p->gic), timer0(name() + ".timer0", this, p->int_num0, p->clock0),
536658Snate@binkert.org      timer1(name() + ".timer1", this, p->int_num1, p->clock1)
5412104Snathanael.premillieu@arm.com{
552SN/A    pioSize = 0xfff;
562190SN/A}
572190SN/A
583453Sgblack@eecs.umich.eduSp804::Timer::Timer(std::string __name, Sp804 *_parent, int int_num, Tick _clock)
593453Sgblack@eecs.umich.edu    : _name(__name), parent(_parent), intNum(int_num), clock(_clock), control(0x20),
609020Sgblack@eecs.umich.edu      rawInt(false), pendingInt(false), loadValue(0xffffffff), zeroEvent(this)
616022Sgblack@eecs.umich.edu{
623453Sgblack@eecs.umich.edu}
632190SN/A
648887Sgeoffrey.blake@arm.com
657680Sgblack@eecs.umich.eduTick
662313SN/ASp804::read(PacketPtr pkt)
678706Sandreas.hansson@arm.com{
688706Sandreas.hansson@arm.com    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
698706Sandreas.hansson@arm.com    assert(pkt->getSize() == 4);
702190SN/A    Addr daddr = pkt->getAddr() - pioAddr;
712190SN/A    pkt->allocate();
723548Sgblack@eecs.umich.edu    DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr);
733548Sgblack@eecs.umich.edu
743548Sgblack@eecs.umich.edu    if (daddr < Timer::Size)
758902Sandreas.hansson@arm.com        timer0.read(pkt, daddr);
768902Sandreas.hansson@arm.com    else if ((daddr - Timer::Size) < Timer::Size)
772SN/A        timer1.read(pkt, daddr - Timer::Size);
782680Sktlim@umich.edu    else if (!readId(pkt, ambaId, pioAddr))
792680Sktlim@umich.edu        panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr);
802680Sktlim@umich.edu    pkt->makeAtomicResponse();
812680Sktlim@umich.edu    return pioDelay;
822680Sktlim@umich.edu}
832680Sktlim@umich.edu
842680Sktlim@umich.edu
852680Sktlim@umich.eduvoid
862680Sktlim@umich.eduSp804::Timer::read(PacketPtr pkt, Addr daddr)
872680Sktlim@umich.edu{
882680Sktlim@umich.edu    switch(daddr) {
892682Sktlim@umich.edu      case LoadReg:
902680Sktlim@umich.edu        pkt->set<uint32_t>(loadValue);
912680Sktlim@umich.edu        break;
922680Sktlim@umich.edu      case CurrentReg:
932680Sktlim@umich.edu        DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n",
942680Sktlim@umich.edu                zeroEvent.when(), clock, control.timerPrescale);
952SN/A        Tick time;
962107SN/A        time = zeroEvent.when() - curTick();
972107SN/A        time = time / clock / power(16, control.timerPrescale);
982190SN/A        DPRINTF(Timer, "-- returning counter at %d\n", time);
992455SN/A        pkt->set<uint32_t>(time);
1002455SN/A        break;
1019920Syasuko.eckert@amd.com      case ControlReg:
1022159SN/A        pkt->set<uint32_t>(control);
1032SN/A        break;
1046029Ssteve.reinhardt@amd.com      case RawISR:
105246SN/A        pkt->set<uint32_t>(rawInt);
106246SN/A        break;
107246SN/A      case MaskedISR:
108246SN/A        pkt->set<uint32_t>(pendingInt);
109246SN/A        break;
110246SN/A      case BGLoad:
111246SN/A        pkt->set<uint32_t>(loadValue);
1122190SN/A        break;
113246SN/A      default:
114246SN/A        panic("Tried to read SP804 timer at offset %#x\n", daddr);
115246SN/A        break;
116246SN/A    }
117246SN/A    DPRINTF(Timer, "Reading %#x from Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr);
118246SN/A}
119246SN/A
1202SN/ATick
1212680Sktlim@umich.eduSp804::write(PacketPtr pkt)
1222423SN/A{
1232190SN/A    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
124180SN/A    assert(pkt->getSize() == 4);
12510110Sandreas.hansson@arm.com    Addr daddr = pkt->getAddr() - pioAddr;
1262190SN/A    pkt->allocate();
12710190Sakash.bagdia@arm.com    DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr);
12810190Sakash.bagdia@arm.com
12910110Sandreas.hansson@arm.com    if (daddr < Timer::Size)
1305715Shsul@eecs.umich.edu        timer0.write(pkt, daddr);
1315715Shsul@eecs.umich.edu    else if ((daddr - Timer::Size) < Timer::Size)
1325714Shsul@eecs.umich.edu        timer1.write(pkt, daddr - Timer::Size);
13310110Sandreas.hansson@arm.com    else if (!readId(pkt, ambaId, pioAddr))
1345714Shsul@eecs.umich.edu        panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr);
1355714Shsul@eecs.umich.edu    pkt->makeAtomicResponse();
1365714Shsul@eecs.umich.edu    return pioDelay;
1376022Sgblack@eecs.umich.edu}
1382190SN/A
1396022Sgblack@eecs.umich.eduvoid
1402521SN/ASp804::Timer::write(PacketPtr pkt, Addr daddr)
1418887Sgeoffrey.blake@arm.com{
1428733Sgeoffrey.blake@arm.com    DPRINTF(Timer, "Writing %#x to Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr);
1439020Sgblack@eecs.umich.edu    switch (daddr) {
1448541Sgblack@eecs.umich.edu      case LoadReg:
1454997Sgblack@eecs.umich.edu        loadValue = pkt->get<uint32_t>();
1464997Sgblack@eecs.umich.edu        restartCounter(loadValue);
1473548Sgblack@eecs.umich.edu        break;
1482654SN/A      case CurrentReg:
1498852Sandreas.hansson@arm.com        // Spec says this value can't be written, but linux writes it anyway
1502521SN/A        break;
1518852Sandreas.hansson@arm.com      case ControlReg:
1523673Srdreslin@umich.edu        bool old_enable;
1538706Sandreas.hansson@arm.com        old_enable = control.timerEnable;
1548706Sandreas.hansson@arm.com        control = pkt->get<uint32_t>();
1558706Sandreas.hansson@arm.com        if ((old_enable == 0) && control.timerEnable)
1568706Sandreas.hansson@arm.com            restartCounter(loadValue);
1578706Sandreas.hansson@arm.com        break;
1588706Sandreas.hansson@arm.com      case IntClear:
1598706Sandreas.hansson@arm.com        rawInt = false;
1608799Sgblack@eecs.umich.edu        if (pendingInt) {
1618852Sandreas.hansson@arm.com            pendingInt = false;
1622518SN/A            DPRINTF(Timer, "Clearing interrupt\n");
1632190SN/A            parent->gic->clearInt(intNum);
1642190SN/A        }
16511886Sbrandon.potter@amd.com        break;
16611886Sbrandon.potter@amd.com      case BGLoad:
1672190SN/A        loadValue = pkt->get<uint32_t>();
1682159SN/A        break;
1692235SN/A      default:
1702103SN/A        panic("Tried to write SP804 timer at offset %#x\n", daddr);
17110407Smitch.hayenga@arm.com        break;
17210407Smitch.hayenga@arm.com    }
173393SN/A}
174393SN/A
17510407Smitch.hayenga@arm.comvoid
176393SN/ASp804::Timer::restartCounter(uint32_t val)
177393SN/A{
17810407Smitch.hayenga@arm.com    DPRINTF(Timer, "Resetting counter with value %#x\n", val);
1792159SN/A    if (!control.timerEnable)
18011627Smichael.lebeane@amd.com        return;
18111627Smichael.lebeane@amd.com
18211627Smichael.lebeane@amd.com    Tick time = clock * power(16, control.timerPrescale);
18311627Smichael.lebeane@amd.com    if (control.timerSize)
18411627Smichael.lebeane@amd.com        time *= val;
18511627Smichael.lebeane@amd.com    else
1862190SN/A        time *= bits(val,15,0);
1872159SN/A
1882680Sktlim@umich.edu    if (zeroEvent.scheduled()) {
1892159SN/A        DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
1902190SN/A        parent->deschedule(zeroEvent);
1912159SN/A    }
1922313SN/A    parent->schedule(zeroEvent, curTick() + time);
1932235SN/A    DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time);
1942235SN/A}
1952235SN/A
1962235SN/Avoid
1972235SN/ASp804::Timer::counterAtZero()
1982254SN/A{
1992254SN/A    if (!control.timerEnable)
2002254SN/A        return;
2012235SN/A
2022680Sktlim@umich.edu    DPRINTF(Timer, "Counter reached zero\n");
2032159SN/A
2042190SN/A    rawInt = true;
2052159SN/A    bool old_pending = pendingInt;
2062159SN/A    if (control.intEnable)
2072159SN/A        pendingInt = true;
2082159SN/A    if (pendingInt && !old_pending) {
2092190SN/A        DPRINTF(Timer, "-- Causing interrupt\n");
2102159SN/A        parent->gic->sendInt(intNum);
2112455SN/A    }
2122159SN/A
2132455SN/A    if (control.oneShot)
2142159SN/A        return;
2159920Syasuko.eckert@amd.com
2169920Syasuko.eckert@amd.com    // Free-running
2172190SN/A    if (control.timerMode == 0)
2182159SN/A        restartCounter(0xffffffff);
2192455SN/A    else
2202159SN/A        restartCounter(loadValue);
2212455SN/A}
2222455SN/A
2239920Syasuko.eckert@amd.comvoid
2249920Syasuko.eckert@amd.comSp804::Timer::serialize(std::ostream &os)
2257720Sgblack@eecs.umich.edu{
2262159SN/A    DPRINTF(Checkpoint, "Serializing Arm Sp804\n");
2277720Sgblack@eecs.umich.edu
2282159SN/A    uint32_t control_serial = control;
22911886Sbrandon.potter@amd.com    SERIALIZE_SCALAR(control_serial);
23011886Sbrandon.potter@amd.com
23111886Sbrandon.potter@amd.com    SERIALIZE_SCALAR(rawInt);
23211886Sbrandon.potter@amd.com    SERIALIZE_SCALAR(pendingInt);
23311886Sbrandon.potter@amd.com    SERIALIZE_SCALAR(loadValue);
23411886Sbrandon.potter@amd.com
23511886Sbrandon.potter@amd.com    bool is_in_event = zeroEvent.scheduled();
23611886Sbrandon.potter@amd.com    SERIALIZE_SCALAR(is_in_event);
2378733Sgeoffrey.blake@arm.com
2388733Sgeoffrey.blake@arm.com    Tick event_time;
2397720Sgblack@eecs.umich.edu    if (is_in_event){
2402159SN/A        event_time = zeroEvent.when();
2417720Sgblack@eecs.umich.edu        SERIALIZE_SCALAR(event_time);
2422159SN/A    }
2437720Sgblack@eecs.umich.edu}
2445260Sksewell@umich.edu
24510698Sandreas.hansson@arm.comvoid
2464172Ssaidi@eecs.umich.eduSp804::Timer::unserialize(Checkpoint *cp, const std::string &section)
2472190SN/A{
2482159SN/A    DPRINTF(Checkpoint, "Unserializing Arm Sp804\n");
2494172Ssaidi@eecs.umich.edu
2502190SN/A    uint32_t control_serial;
2513468Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(control_serial);
2522190SN/A    control = control_serial;
25312106SRekai.GonzalezAlberquilla@arm.com
2546313Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(rawInt);
2556221Snate@binkert.org    UNSERIALIZE_SCALAR(pendingInt);
25612106SRekai.GonzalezAlberquilla@arm.com    UNSERIALIZE_SCALAR(loadValue);
2576221Snate@binkert.org
2586221Snate@binkert.org    bool is_in_event;
2596221Snate@binkert.org    UNSERIALIZE_SCALAR(is_in_event);
2604661Sksewell@umich.edu
2616221Snate@binkert.org    Tick event_time;
26212106SRekai.GonzalezAlberquilla@arm.com    if (is_in_event){
2636221Snate@binkert.org        UNSERIALIZE_SCALAR(event_time);
2646221Snate@binkert.org        parent->schedule(zeroEvent, event_time);
2654661Sksewell@umich.edu    }
2662235SN/A}
2672235SN/A
2682190SN/A
2692190SN/A
2702190SN/Avoid
2712159SN/ASp804::serialize(std::ostream &os)
2722235SN/A{
2732190SN/A    nameOut(os, csprintf("%s.timer0", name()));
2742834Sksewell@umich.edu    timer0.serialize(os);
27511877Sbrandon.potter@amd.com    nameOut(os, csprintf("%s.timer1", name()));
2764111Sgblack@eecs.umich.edu    timer1.serialize(os);
2772834Sksewell@umich.edu}
2782834Sksewell@umich.edu
2792834Sksewell@umich.eduvoid
2802834Sksewell@umich.eduSp804::unserialize(Checkpoint *cp, const std::string &section)
2812525SN/A{
2825217Ssaidi@eecs.umich.edu    timer0.unserialize(cp, csprintf("%s.timer0", section));
2835217Ssaidi@eecs.umich.edu    timer1.unserialize(cp, csprintf("%s.timer1", section));
2849426SAndreas.Sandberg@ARM.com}
2859426SAndreas.Sandberg@ARM.com
2869426SAndreas.Sandberg@ARM.comSp804 *
2879426SAndreas.Sandberg@ARM.comSp804Params::create()
2889426SAndreas.Sandberg@ARM.com{
2899426SAndreas.Sandberg@ARM.com    return new Sp804(this);
2909426SAndreas.Sandberg@ARM.com}
29112106SRekai.GonzalezAlberquilla@arm.com