timer_sp804.cc revision 10565:23593fdaadcd
110152Satgutier@umich.edu/*
210152Satgutier@umich.edu * Copyright (c) 2010 ARM Limited
310152Satgutier@umich.edu * All rights reserved
410152Satgutier@umich.edu *
510152Satgutier@umich.edu * The license below extends only to copyright in the software and shall
610152Satgutier@umich.edu * not be construed as granting a license to any other intellectual
710152Satgutier@umich.edu * property including but not limited to intellectual property relating
810152Satgutier@umich.edu * to a hardware implementation of the functionality of the software
910152Satgutier@umich.edu * licensed hereunder.  You may use the software subject to the license
1010152Satgutier@umich.edu * terms below provided that you ensure that this notice is replicated
1110152Satgutier@umich.edu * unmodified and in its entirety in all distributions of the software,
1210152Satgutier@umich.edu * modified or unmodified, in source code or in binary form.
1310152Satgutier@umich.edu *
1410152Satgutier@umich.edu * Redistribution and use in source and binary forms, with or without
1510152Satgutier@umich.edu * modification, are permitted provided that the following conditions are
1610152Satgutier@umich.edu * met: redistributions of source code must retain the above copyright
1710152Satgutier@umich.edu * notice, this list of conditions and the following disclaimer;
1810152Satgutier@umich.edu * redistributions in binary form must reproduce the above copyright
1910152Satgutier@umich.edu * notice, this list of conditions and the following disclaimer in the
2010152Satgutier@umich.edu * documentation and/or other materials provided with the distribution;
2110152Satgutier@umich.edu * neither the name of the copyright holders nor the names of its
2210152Satgutier@umich.edu * contributors may be used to endorse or promote products derived from
2310152Satgutier@umich.edu * this software without specific prior written permission.
2410152Satgutier@umich.edu *
2510152Satgutier@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610152Satgutier@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710152Satgutier@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810152Satgutier@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910152Satgutier@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010152Satgutier@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110152Satgutier@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210152Satgutier@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310152Satgutier@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410152Satgutier@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510152Satgutier@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610152Satgutier@umich.edu *
3710152Satgutier@umich.edu * Authors: Ali Saidi
3810152Satgutier@umich.edu */
3910152Satgutier@umich.edu
4010152Satgutier@umich.edu#include "base/intmath.hh"
4110152Satgutier@umich.edu#include "base/trace.hh"
4210152Satgutier@umich.edu#include "debug/Checkpoint.hh"
4310152Satgutier@umich.edu#include "debug/Timer.hh"
4410152Satgutier@umich.edu#include "dev/arm/base_gic.hh"
4510152Satgutier@umich.edu#include "dev/arm/timer_sp804.hh"
4610152Satgutier@umich.edu#include "mem/packet.hh"
4710152Satgutier@umich.edu#include "mem/packet_access.hh"
4810152Satgutier@umich.edu
4910152Satgutier@umich.eduSp804::Sp804(Params *p)
5010152Satgutier@umich.edu    : AmbaPioDevice(p, 0xfff), gic(p->gic),
5110152Satgutier@umich.edu      timer0(name() + ".timer0", this, p->int_num0, p->clock0),
5210152Satgutier@umich.edu      timer1(name() + ".timer1", this, p->int_num1, p->clock1)
5310152Satgutier@umich.edu{
5410152Satgutier@umich.edu}
5510152Satgutier@umich.edu
5610152Satgutier@umich.eduSp804::Timer::Timer(std::string __name, Sp804 *_parent, int int_num, Tick _clock)
5710152Satgutier@umich.edu    : _name(__name), parent(_parent), intNum(int_num), clock(_clock), control(0x20),
5810152Satgutier@umich.edu      rawInt(false), pendingInt(false), loadValue(0xffffffff), zeroEvent(this)
5910152Satgutier@umich.edu{
6010152Satgutier@umich.edu}
6110152Satgutier@umich.edu
6210152Satgutier@umich.edu
6310152Satgutier@umich.eduTick
6410152Satgutier@umich.eduSp804::read(PacketPtr pkt)
6510152Satgutier@umich.edu{
6610152Satgutier@umich.edu    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
6710152Satgutier@umich.edu    assert(pkt->getSize() == 4);
6810152Satgutier@umich.edu    Addr daddr = pkt->getAddr() - pioAddr;
6910152Satgutier@umich.edu    DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr);
7010152Satgutier@umich.edu
7110152Satgutier@umich.edu    if (daddr < Timer::Size)
7210152Satgutier@umich.edu        timer0.read(pkt, daddr);
7310152Satgutier@umich.edu    else if ((daddr - Timer::Size) < Timer::Size)
7410152Satgutier@umich.edu        timer1.read(pkt, daddr - Timer::Size);
7510152Satgutier@umich.edu    else if (!readId(pkt, ambaId, pioAddr))
7610152Satgutier@umich.edu        panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr);
7710152Satgutier@umich.edu    pkt->makeAtomicResponse();
7810152Satgutier@umich.edu    return pioDelay;
7910152Satgutier@umich.edu}
8010152Satgutier@umich.edu
8110152Satgutier@umich.edu
8210152Satgutier@umich.eduvoid
8310152Satgutier@umich.eduSp804::Timer::read(PacketPtr pkt, Addr daddr)
8410152Satgutier@umich.edu{
8510152Satgutier@umich.edu    switch(daddr) {
8610152Satgutier@umich.edu      case LoadReg:
8710152Satgutier@umich.edu        pkt->set<uint32_t>(loadValue);
8810152Satgutier@umich.edu        break;
8910152Satgutier@umich.edu      case CurrentReg:
9010152Satgutier@umich.edu        DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n",
9110152Satgutier@umich.edu                zeroEvent.when(), clock, control.timerPrescale);
9210152Satgutier@umich.edu        Tick time;
9310152Satgutier@umich.edu        time = zeroEvent.when() - curTick();
9410152Satgutier@umich.edu        time = time / clock / power(16, control.timerPrescale);
9510152Satgutier@umich.edu        DPRINTF(Timer, "-- returning counter at %d\n", time);
9610152Satgutier@umich.edu        pkt->set<uint32_t>(time);
9710152Satgutier@umich.edu        break;
9810152Satgutier@umich.edu      case ControlReg:
9910152Satgutier@umich.edu        pkt->set<uint32_t>(control);
10010152Satgutier@umich.edu        break;
10110152Satgutier@umich.edu      case RawISR:
10210152Satgutier@umich.edu        pkt->set<uint32_t>(rawInt);
10310152Satgutier@umich.edu        break;
10410152Satgutier@umich.edu      case MaskedISR:
10510152Satgutier@umich.edu        pkt->set<uint32_t>(pendingInt);
10610152Satgutier@umich.edu        break;
10710152Satgutier@umich.edu      case BGLoad:
10810152Satgutier@umich.edu        pkt->set<uint32_t>(loadValue);
10910152Satgutier@umich.edu        break;
11010152Satgutier@umich.edu      default:
11110152Satgutier@umich.edu        panic("Tried to read SP804 timer at offset %#x\n", daddr);
11210152Satgutier@umich.edu        break;
11310152Satgutier@umich.edu    }
11410152Satgutier@umich.edu    DPRINTF(Timer, "Reading %#x from Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr);
11510152Satgutier@umich.edu}
11610152Satgutier@umich.edu
11710152Satgutier@umich.eduTick
11810152Satgutier@umich.eduSp804::write(PacketPtr pkt)
11910152Satgutier@umich.edu{
12010152Satgutier@umich.edu    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
12110152Satgutier@umich.edu    assert(pkt->getSize() == 4);
12210152Satgutier@umich.edu    Addr daddr = pkt->getAddr() - pioAddr;
12310152Satgutier@umich.edu    DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr);
12410152Satgutier@umich.edu
12510152Satgutier@umich.edu    if (daddr < Timer::Size)
12610152Satgutier@umich.edu        timer0.write(pkt, daddr);
12710152Satgutier@umich.edu    else if ((daddr - Timer::Size) < Timer::Size)
12810152Satgutier@umich.edu        timer1.write(pkt, daddr - Timer::Size);
12910152Satgutier@umich.edu    else if (!readId(pkt, ambaId, pioAddr))
13010152Satgutier@umich.edu        panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr);
13110152Satgutier@umich.edu    pkt->makeAtomicResponse();
13210152Satgutier@umich.edu    return pioDelay;
13310152Satgutier@umich.edu}
13410152Satgutier@umich.edu
13510152Satgutier@umich.eduvoid
13610152Satgutier@umich.eduSp804::Timer::write(PacketPtr pkt, Addr daddr)
13710152Satgutier@umich.edu{
13810152Satgutier@umich.edu    DPRINTF(Timer, "Writing %#x to Timer at offset: %#x\n", pkt->get<uint32_t>(), daddr);
13910152Satgutier@umich.edu    switch (daddr) {
14010152Satgutier@umich.edu      case LoadReg:
14110152Satgutier@umich.edu        loadValue = pkt->get<uint32_t>();
14210152Satgutier@umich.edu        restartCounter(loadValue);
14310152Satgutier@umich.edu        break;
14410152Satgutier@umich.edu      case CurrentReg:
14510152Satgutier@umich.edu        // Spec says this value can't be written, but linux writes it anyway
14610152Satgutier@umich.edu        break;
14710152Satgutier@umich.edu      case ControlReg:
14810152Satgutier@umich.edu        bool old_enable;
14910152Satgutier@umich.edu        old_enable = control.timerEnable;
15010152Satgutier@umich.edu        control = pkt->get<uint32_t>();
15110152Satgutier@umich.edu        if ((old_enable == 0) && control.timerEnable)
15210152Satgutier@umich.edu            restartCounter(loadValue);
15310152Satgutier@umich.edu        break;
15410152Satgutier@umich.edu      case IntClear:
15510152Satgutier@umich.edu        rawInt = false;
15610152Satgutier@umich.edu        if (pendingInt) {
15710152Satgutier@umich.edu            pendingInt = false;
15810152Satgutier@umich.edu            DPRINTF(Timer, "Clearing interrupt\n");
15910152Satgutier@umich.edu            parent->gic->clearInt(intNum);
16010152Satgutier@umich.edu        }
16110152Satgutier@umich.edu        break;
16210152Satgutier@umich.edu      case BGLoad:
16310152Satgutier@umich.edu        loadValue = pkt->get<uint32_t>();
16410152Satgutier@umich.edu        break;
16510152Satgutier@umich.edu      default:
16610152Satgutier@umich.edu        panic("Tried to write SP804 timer at offset %#x\n", daddr);
16710152Satgutier@umich.edu        break;
16810152Satgutier@umich.edu    }
16910152Satgutier@umich.edu}
17010152Satgutier@umich.edu
17110152Satgutier@umich.eduvoid
17210152Satgutier@umich.eduSp804::Timer::restartCounter(uint32_t val)
17310152Satgutier@umich.edu{
17410152Satgutier@umich.edu    DPRINTF(Timer, "Resetting counter with value %#x\n", val);
17510152Satgutier@umich.edu    if (!control.timerEnable)
17610152Satgutier@umich.edu        return;
17710152Satgutier@umich.edu
17810152Satgutier@umich.edu    Tick time = clock * power(16, control.timerPrescale);
17910152Satgutier@umich.edu    if (control.timerSize)
18010152Satgutier@umich.edu        time *= val;
18110152Satgutier@umich.edu    else
18210152Satgutier@umich.edu        time *= bits(val,15,0);
18310152Satgutier@umich.edu
18410152Satgutier@umich.edu    if (zeroEvent.scheduled()) {
18510152Satgutier@umich.edu        DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
18610152Satgutier@umich.edu        parent->deschedule(zeroEvent);
18710152Satgutier@umich.edu    }
18810152Satgutier@umich.edu    parent->schedule(zeroEvent, curTick() + time);
18910152Satgutier@umich.edu    DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time);
19010152Satgutier@umich.edu}
19110152Satgutier@umich.edu
19210152Satgutier@umich.eduvoid
19310152Satgutier@umich.eduSp804::Timer::counterAtZero()
19410152Satgutier@umich.edu{
19510152Satgutier@umich.edu    if (!control.timerEnable)
19610152Satgutier@umich.edu        return;
19710152Satgutier@umich.edu
19810152Satgutier@umich.edu    DPRINTF(Timer, "Counter reached zero\n");
19910152Satgutier@umich.edu
20010152Satgutier@umich.edu    rawInt = true;
20110152Satgutier@umich.edu    bool old_pending = pendingInt;
20210152Satgutier@umich.edu    if (control.intEnable)
20310152Satgutier@umich.edu        pendingInt = true;
20410152Satgutier@umich.edu    if (pendingInt && !old_pending) {
20510152Satgutier@umich.edu        DPRINTF(Timer, "-- Causing interrupt\n");
20610152Satgutier@umich.edu        parent->gic->sendInt(intNum);
20710152Satgutier@umich.edu    }
20810152Satgutier@umich.edu
20910152Satgutier@umich.edu    if (control.oneShot)
21010152Satgutier@umich.edu        return;
21110152Satgutier@umich.edu
21210152Satgutier@umich.edu    // Free-running
21310152Satgutier@umich.edu    if (control.timerMode == 0)
21410152Satgutier@umich.edu        restartCounter(0xffffffff);
21510152Satgutier@umich.edu    else
21610152Satgutier@umich.edu        restartCounter(loadValue);
21710152Satgutier@umich.edu}
21810152Satgutier@umich.edu
21910152Satgutier@umich.eduvoid
22010152Satgutier@umich.eduSp804::Timer::serialize(std::ostream &os)
22110152Satgutier@umich.edu{
22210152Satgutier@umich.edu    DPRINTF(Checkpoint, "Serializing Arm Sp804\n");
22310152Satgutier@umich.edu
22410152Satgutier@umich.edu    uint32_t control_serial = control;
22510152Satgutier@umich.edu    SERIALIZE_SCALAR(control_serial);
22610152Satgutier@umich.edu
22710152Satgutier@umich.edu    SERIALIZE_SCALAR(rawInt);
22810152Satgutier@umich.edu    SERIALIZE_SCALAR(pendingInt);
22910152Satgutier@umich.edu    SERIALIZE_SCALAR(loadValue);
23010152Satgutier@umich.edu
23110152Satgutier@umich.edu    bool is_in_event = zeroEvent.scheduled();
23210152Satgutier@umich.edu    SERIALIZE_SCALAR(is_in_event);
23310152Satgutier@umich.edu
23410152Satgutier@umich.edu    Tick event_time;
23510152Satgutier@umich.edu    if (is_in_event){
23610152Satgutier@umich.edu        event_time = zeroEvent.when();
23710152Satgutier@umich.edu        SERIALIZE_SCALAR(event_time);
23810152Satgutier@umich.edu    }
23910152Satgutier@umich.edu}
24010152Satgutier@umich.edu
24110152Satgutier@umich.eduvoid
24210152Satgutier@umich.eduSp804::Timer::unserialize(Checkpoint *cp, const std::string &section)
24310152Satgutier@umich.edu{
24410152Satgutier@umich.edu    DPRINTF(Checkpoint, "Unserializing Arm Sp804\n");
24510152Satgutier@umich.edu
24610152Satgutier@umich.edu    uint32_t control_serial;
24710152Satgutier@umich.edu    UNSERIALIZE_SCALAR(control_serial);
24810152Satgutier@umich.edu    control = control_serial;
24910152Satgutier@umich.edu
25010152Satgutier@umich.edu    UNSERIALIZE_SCALAR(rawInt);
25110152Satgutier@umich.edu    UNSERIALIZE_SCALAR(pendingInt);
25210152Satgutier@umich.edu    UNSERIALIZE_SCALAR(loadValue);
25310152Satgutier@umich.edu
25410152Satgutier@umich.edu    bool is_in_event;
25510152Satgutier@umich.edu    UNSERIALIZE_SCALAR(is_in_event);
25610152Satgutier@umich.edu
25710152Satgutier@umich.edu    Tick event_time;
25810152Satgutier@umich.edu    if (is_in_event){
25910152Satgutier@umich.edu        UNSERIALIZE_SCALAR(event_time);
26010152Satgutier@umich.edu        parent->schedule(zeroEvent, event_time);
26110152Satgutier@umich.edu    }
26210152Satgutier@umich.edu}
26310152Satgutier@umich.edu
26410152Satgutier@umich.edu
26510152Satgutier@umich.edu
26610152Satgutier@umich.eduvoid
26710152Satgutier@umich.eduSp804::serialize(std::ostream &os)
26810152Satgutier@umich.edu{
26910152Satgutier@umich.edu    nameOut(os, csprintf("%s.timer0", name()));
27010152Satgutier@umich.edu    timer0.serialize(os);
27110152Satgutier@umich.edu    nameOut(os, csprintf("%s.timer1", name()));
27210152Satgutier@umich.edu    timer1.serialize(os);
27310152Satgutier@umich.edu}
27410152Satgutier@umich.edu
27510152Satgutier@umich.eduvoid
27610152Satgutier@umich.eduSp804::unserialize(Checkpoint *cp, const std::string &section)
27710152Satgutier@umich.edu{
27810152Satgutier@umich.edu    timer0.unserialize(cp, csprintf("%s.timer0", section));
27910152Satgutier@umich.edu    timer1.unserialize(cp, csprintf("%s.timer1", section));
28010152Satgutier@umich.edu}
28110152Satgutier@umich.edu
28210152Satgutier@umich.eduSp804 *
28310152Satgutier@umich.eduSp804Params::create()
28410152Satgutier@umich.edu{
28510152Satgutier@umich.edu    return new Sp804(this);
28610152Satgutier@umich.edu}
28710152Satgutier@umich.edu