c662d35bb008216c429a9be4a61e213eb65fea80
2 * Copyright (c) 2010 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include "base/intmath.hh"
41 #include "base/trace.hh"
42 #include "dev/arm/gic.hh"
43 #include "dev/arm/timer_sp804.hh"
44 #include "mem/packet.hh"
45 #include "mem/packet_access.hh"
47 using namespace AmbaDev
;
49 Sp804::Sp804(Params
*p
)
50 : AmbaDevice(p
), gic(p
->gic
), timer0(name() + ".timer0", this, p
->int_num0
, p
->clock0
),
51 timer1(name() + ".timer1", this, p
->int_num1
, p
->clock1
)
56 Sp804::Timer::Timer(std::string __name
, Sp804
*_parent
, int int_num
, Tick _clock
)
57 : _name(__name
), parent(_parent
), intNum(int_num
), clock(_clock
), control(0x20),
58 rawInt(false), pendingInt(false), loadValue(0xffffffff), zeroEvent(this)
64 Sp804::read(PacketPtr pkt
)
66 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
67 assert(pkt
->getSize() == 4);
68 Addr daddr
= pkt
->getAddr() - pioAddr
;
70 DPRINTF(Timer
, "Reading from DualTimer at offset: %#x\n", daddr
);
72 if (daddr
< Timer::Size
)
73 timer0
.read(pkt
, daddr
);
74 else if ((daddr
- Timer::Size
) < Timer::Size
)
75 timer1
.read(pkt
, daddr
- Timer::Size
);
76 else if (!readId(pkt
, ambaId
, pioAddr
))
77 panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr
);
78 pkt
->makeAtomicResponse();
84 Sp804::Timer::read(PacketPtr pkt
, Addr daddr
)
86 DPRINTF(Timer
, "Reading from Timer at offset: %#x\n", daddr
);
90 pkt
->set
<uint32_t>(loadValue
);
93 DPRINTF(Timer
, "Event schedule for %d, clock=%d, prescale=%d\n",
94 zeroEvent
.when(), clock
, control
.timerPrescale
);
96 time
= zeroEvent
.when() - curTick
;
97 time
= time
/ clock
/ power(16, control
.timerPrescale
);
98 DPRINTF(Timer
, "-- returning counter at %d\n", time
);
99 pkt
->set
<uint32_t>(time
);
102 pkt
->set
<uint32_t>(control
);
105 pkt
->set
<uint32_t>(rawInt
);
108 pkt
->set
<uint32_t>(pendingInt
);
111 pkt
->set
<uint32_t>(loadValue
);
114 panic("Tried to read SP804 timer at offset %#x\n", daddr
);
120 Sp804::write(PacketPtr pkt
)
122 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
123 assert(pkt
->getSize() == 4);
124 Addr daddr
= pkt
->getAddr() - pioAddr
;
126 DPRINTF(Timer
, "Writing to DualTimer at offset: %#x\n", daddr
);
128 if (daddr
< Timer::Size
)
129 timer0
.write(pkt
, daddr
);
130 else if ((daddr
- Timer::Size
) < Timer::Size
)
131 timer1
.write(pkt
, daddr
- Timer::Size
);
132 else if (!readId(pkt
, ambaId
, pioAddr
))
133 panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr
);
134 pkt
->makeAtomicResponse();
139 Sp804::Timer::write(PacketPtr pkt
, Addr daddr
)
141 DPRINTF(Timer
, "Writing to Timer at offset: %#x\n", daddr
);
144 loadValue
= pkt
->get
<uint32_t>();
145 restartCounter(loadValue
);
148 // Spec says this value can't be written, but linux writes it anyway
152 old_enable
= control
.timerEnable
;
153 control
= pkt
->get
<uint32_t>();
154 if ((old_enable
== 0) && control
.timerEnable
)
155 restartCounter(loadValue
);
161 DPRINTF(Timer
, "Clearing interrupt\n");
162 parent
->gic
->clearInt(intNum
);
166 loadValue
= pkt
->get
<uint32_t>();
169 panic("Tried to write SP804 timer at offset %#x\n", daddr
);
175 Sp804::Timer::restartCounter(uint32_t val
)
177 DPRINTF(Timer
, "Resetting counter with value %#x\n", val
);
178 if (!control
.timerEnable
)
181 Tick time
= clock
<< power(16, control
.timerPrescale
);
182 if (control
.timerSize
)
183 time
*= bits(val
,15,0);
187 if (zeroEvent
.scheduled()) {
188 DPRINTF(Timer
, "-- Event was already schedule, de-scheduling\n");
189 parent
->deschedule(zeroEvent
);
191 parent
->schedule(zeroEvent
, curTick
+ time
);
192 DPRINTF(Timer
, "-- Scheduling new event for: %d\n", curTick
+ time
);
196 Sp804::Timer::counterAtZero()
198 if (!control
.timerEnable
)
201 DPRINTF(Timer
, "Counter reached zero\n");
204 bool old_pending
= pendingInt
;
205 if (control
.intEnable
)
207 if (pendingInt
&& ~old_pending
) {
208 DPRINTF(Timer
, "-- Causing interrupt\n");
209 parent
->gic
->sendInt(intNum
);
216 if (control
.timerMode
== 0)
217 restartCounter(0xffffffff);
219 restartCounter(loadValue
);
224 Sp804::serialize(std::ostream
&os
)
226 panic("Need to implement serialization\n");
230 Sp804::unserialize(Checkpoint
*cp
, const std::string
§ion
)
232 panic("Need to implement serialization\n");
236 Sp804Params::create()
238 return new Sp804(this);