17584SAli.Saidi@arm.com/* 211011SAndreas.Sandberg@ARM.com * Copyright (c) 2010,2013,2015 ARM Limited 37584SAli.Saidi@arm.com * All rights reserved 47584SAli.Saidi@arm.com * 57584SAli.Saidi@arm.com * The license below extends only to copyright in the software and shall 67584SAli.Saidi@arm.com * not be construed as granting a license to any other intellectual 77584SAli.Saidi@arm.com * property including but not limited to intellectual property relating 87584SAli.Saidi@arm.com * to a hardware implementation of the functionality of the software 97584SAli.Saidi@arm.com * licensed hereunder. You may use the software subject to the license 107584SAli.Saidi@arm.com * terms below provided that you ensure that this notice is replicated 117584SAli.Saidi@arm.com * unmodified and in its entirety in all distributions of the software, 127584SAli.Saidi@arm.com * modified or unmodified, in source code or in binary form. 137584SAli.Saidi@arm.com * 147584SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without 157584SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are 167584SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright 177584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer; 187584SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright 197584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the 207584SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution; 217584SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its 227584SAli.Saidi@arm.com * contributors may be used to endorse or promote products derived from 237584SAli.Saidi@arm.com * this software without specific prior written permission. 247584SAli.Saidi@arm.com * 257584SAli.Saidi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 267584SAli.Saidi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 277584SAli.Saidi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 287584SAli.Saidi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 297584SAli.Saidi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307584SAli.Saidi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 317584SAli.Saidi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 327584SAli.Saidi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337584SAli.Saidi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347584SAli.Saidi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 357584SAli.Saidi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 367584SAli.Saidi@arm.com * 377584SAli.Saidi@arm.com * Authors: Ali Saidi 387584SAli.Saidi@arm.com */ 397584SAli.Saidi@arm.com 4011421Sdavid.guillen@arm.com#include "dev/arm/rv_ctrl.hh" 4111421Sdavid.guillen@arm.com 427584SAli.Saidi@arm.com#include "base/trace.hh" 439958Smatt.evans@arm.com#include "debug/RVCTRL.hh" 447584SAli.Saidi@arm.com#include "mem/packet.hh" 457584SAli.Saidi@arm.com#include "mem/packet_access.hh" 4611421Sdavid.guillen@arm.com#include "sim/power/thermal_model.hh" 4711421Sdavid.guillen@arm.com#include "sim/system.hh" 4811011SAndreas.Sandberg@ARM.com#include "sim/voltage_domain.hh" 497584SAli.Saidi@arm.com 507584SAli.Saidi@arm.comRealViewCtrl::RealViewCtrl(Params *p) 519958Smatt.evans@arm.com : BasicPioDevice(p, 0xD4), flags(0), scData(0) 527584SAli.Saidi@arm.com{ 537584SAli.Saidi@arm.com} 547584SAli.Saidi@arm.com 557584SAli.Saidi@arm.comTick 567584SAli.Saidi@arm.comRealViewCtrl::read(PacketPtr pkt) 577584SAli.Saidi@arm.com{ 587584SAli.Saidi@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 597584SAli.Saidi@arm.com assert(pkt->getSize() == 4); 607584SAli.Saidi@arm.com Addr daddr = pkt->getAddr() - pioAddr; 617584SAli.Saidi@arm.com 627584SAli.Saidi@arm.com switch(daddr) { 638524SAli.Saidi@ARM.com case ProcId0: 6413230Sgabeblack@google.com pkt->setLE(params()->proc_id0); 658524SAli.Saidi@ARM.com break; 668524SAli.Saidi@ARM.com case ProcId1: 6713230Sgabeblack@google.com pkt->setLE(params()->proc_id1); 687584SAli.Saidi@arm.com break; 697584SAli.Saidi@arm.com case Clock24: 707584SAli.Saidi@arm.com Tick clk; 719004Skoansin.tan@gmail.com clk = SimClock::Float::MHz * curTick() * 24; 7213230Sgabeblack@google.com pkt->setLE((uint32_t)(clk)); 737584SAli.Saidi@arm.com break; 748060SAli.Saidi@ARM.com case Clock100: 758060SAli.Saidi@ARM.com Tick clk100; 769004Skoansin.tan@gmail.com clk100 = SimClock::Float::MHz * curTick() * 100; 7713230Sgabeblack@google.com pkt->setLE((uint32_t)(clk100)); 788060SAli.Saidi@ARM.com break; 797584SAli.Saidi@arm.com case Flash: 8013230Sgabeblack@google.com pkt->setLE<uint32_t>(0); 817584SAli.Saidi@arm.com break; 827950SAli.Saidi@ARM.com case Clcd: 8313230Sgabeblack@google.com pkt->setLE<uint32_t>(0x00001F00); 847950SAli.Saidi@ARM.com break; 857950SAli.Saidi@ARM.com case Osc0: 8613230Sgabeblack@google.com pkt->setLE<uint32_t>(0x00012C5C); 877950SAli.Saidi@ARM.com break; 887950SAli.Saidi@ARM.com case Osc1: 8913230Sgabeblack@google.com pkt->setLE<uint32_t>(0x00002CC0); 907950SAli.Saidi@ARM.com break; 917950SAli.Saidi@ARM.com case Osc2: 9213230Sgabeblack@google.com pkt->setLE<uint32_t>(0x00002C75); 937950SAli.Saidi@ARM.com break; 947950SAli.Saidi@ARM.com case Osc3: 9513230Sgabeblack@google.com pkt->setLE<uint32_t>(0x00020211); 967950SAli.Saidi@ARM.com break; 977950SAli.Saidi@ARM.com case Osc4: 9813230Sgabeblack@google.com pkt->setLE<uint32_t>(0x00002C75); 997950SAli.Saidi@ARM.com break; 1007950SAli.Saidi@ARM.com case Lock: 10113230Sgabeblack@google.com pkt->setLE<uint32_t>(sysLock); 1027950SAli.Saidi@ARM.com break; 1038281SAli.Saidi@ARM.com case Flags: 10413230Sgabeblack@google.com pkt->setLE<uint32_t>(flags); 1058281SAli.Saidi@ARM.com break; 1068299Schander.sudanthi@arm.com case IdReg: 10713230Sgabeblack@google.com pkt->setLE<uint32_t>(params()->idreg); 1088299Schander.sudanthi@arm.com break; 1098870SAli.Saidi@ARM.com case CfgStat: 11013230Sgabeblack@google.com pkt->setLE<uint32_t>(1); 1118988SAli.Saidi@ARM.com break; 1129958Smatt.evans@arm.com case CfgData: 11313230Sgabeblack@google.com pkt->setLE<uint32_t>(scData); 1149958Smatt.evans@arm.com DPRINTF(RVCTRL, "Read %#x from SCReg\n", scData); 1159958Smatt.evans@arm.com break; 1169958Smatt.evans@arm.com case CfgCtrl: 11713230Sgabeblack@google.com pkt->setLE<uint32_t>(0); // not busy 1189958Smatt.evans@arm.com DPRINTF(RVCTRL, "Read 0 from CfgCtrl\n"); 1199958Smatt.evans@arm.com break; 1207584SAli.Saidi@arm.com default: 1218299Schander.sudanthi@arm.com warn("Tried to read RealView I/O at offset %#x that doesn't exist\n", 1228299Schander.sudanthi@arm.com daddr); 12313230Sgabeblack@google.com pkt->setLE<uint32_t>(0); 1247584SAli.Saidi@arm.com break; 1257584SAli.Saidi@arm.com } 1267584SAli.Saidi@arm.com pkt->makeAtomicResponse(); 1277584SAli.Saidi@arm.com return pioDelay; 1287584SAli.Saidi@arm.com 1297584SAli.Saidi@arm.com} 1307584SAli.Saidi@arm.com 1317584SAli.Saidi@arm.comTick 1327584SAli.Saidi@arm.comRealViewCtrl::write(PacketPtr pkt) 1337584SAli.Saidi@arm.com{ 1347584SAli.Saidi@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1357584SAli.Saidi@arm.com 1367584SAli.Saidi@arm.com Addr daddr = pkt->getAddr() - pioAddr; 1377584SAli.Saidi@arm.com switch (daddr) { 1387584SAli.Saidi@arm.com case Flash: 1397950SAli.Saidi@ARM.com case Clcd: 1407950SAli.Saidi@ARM.com case Osc0: 1417950SAli.Saidi@ARM.com case Osc1: 1427950SAli.Saidi@ARM.com case Osc2: 1437950SAli.Saidi@ARM.com case Osc3: 1447950SAli.Saidi@ARM.com case Osc4: 1457950SAli.Saidi@ARM.com break; 1467950SAli.Saidi@ARM.com case Lock: 14713230Sgabeblack@google.com sysLock.lockVal = pkt->getLE<uint16_t>(); 1487584SAli.Saidi@arm.com break; 14912078Sgedare@rtems.org case ResetCtl: 15012078Sgedare@rtems.org // Ignore writes to reset control 15112078Sgedare@rtems.org warn_once("Ignoring write to reset control\n"); 15212078Sgedare@rtems.org break; 1538281SAli.Saidi@ARM.com case Flags: 15413230Sgabeblack@google.com flags = pkt->getLE<uint32_t>(); 1558281SAli.Saidi@ARM.com break; 1568524SAli.Saidi@ARM.com case FlagsClr: 1578524SAli.Saidi@ARM.com flags = 0; 1588524SAli.Saidi@ARM.com break; 1599958Smatt.evans@arm.com case CfgData: 16013230Sgabeblack@google.com scData = pkt->getLE<uint32_t>(); 1619958Smatt.evans@arm.com break; 1629958Smatt.evans@arm.com case CfgCtrl: { 1639958Smatt.evans@arm.com // A request is being submitted to read/write the system control 1649958Smatt.evans@arm.com // registers. See 1659958Smatt.evans@arm.com // http://infocenter.arm.com/help/topic/com.arm.doc.dui0447h/CACDEFGH.html 16613230Sgabeblack@google.com CfgCtrlReg req = pkt->getLE<uint32_t>(); 16711011SAndreas.Sandberg@ARM.com if (!req.start) { 16811011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "SCReg: write %#x to ctrl but not starting\n", 16911011SAndreas.Sandberg@ARM.com req); 17011011SAndreas.Sandberg@ARM.com break; 17111011SAndreas.Sandberg@ARM.com } 1729958Smatt.evans@arm.com 17311011SAndreas.Sandberg@ARM.com auto it_dev(devices.find(req & CFG_CTRL_ADDR_MASK)); 17411011SAndreas.Sandberg@ARM.com if (it_dev == devices.end()) { 17511011SAndreas.Sandberg@ARM.com warn_once("SCReg: Access to unknown device " 17611011SAndreas.Sandberg@ARM.com "dcc%d:site%d:pos%d:fn%d:dev%d\n", 17711011SAndreas.Sandberg@ARM.com req.dcc, req.site, req.pos, req.func, req.dev); 17811011SAndreas.Sandberg@ARM.com break; 17911011SAndreas.Sandberg@ARM.com } 18011011SAndreas.Sandberg@ARM.com 18111011SAndreas.Sandberg@ARM.com // Service the request as a read or write depending on the 18211011SAndreas.Sandberg@ARM.com // wr bit in the control register. 18311011SAndreas.Sandberg@ARM.com Device &dev(*it_dev->second); 18411011SAndreas.Sandberg@ARM.com if (req.wr) { 18511011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "SCReg: Writing %#x (ctrlWr %#x)\n", 18611011SAndreas.Sandberg@ARM.com scData, req); 18711011SAndreas.Sandberg@ARM.com dev.write(scData); 18811011SAndreas.Sandberg@ARM.com 1899958Smatt.evans@arm.com } else { 19011011SAndreas.Sandberg@ARM.com scData = dev.read(); 19111011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "SCReg: Reading %#x (ctrlRd %#x)\n", 19211011SAndreas.Sandberg@ARM.com scData, req); 1939958Smatt.evans@arm.com } 1949958Smatt.evans@arm.com } break; 1959958Smatt.evans@arm.com case CfgStat: // Weird to write this 1967584SAli.Saidi@arm.com default: 1979958Smatt.evans@arm.com warn("Tried to write RVIO at offset %#x (data %#x) that doesn't exist\n", 19813230Sgabeblack@google.com daddr, pkt->getLE<uint32_t>()); 1997584SAli.Saidi@arm.com break; 2007584SAli.Saidi@arm.com } 2017584SAli.Saidi@arm.com pkt->makeAtomicResponse(); 2027584SAli.Saidi@arm.com return pioDelay; 2037584SAli.Saidi@arm.com} 2047584SAli.Saidi@arm.com 2057584SAli.Saidi@arm.comvoid 20610905Sandreas.sandberg@arm.comRealViewCtrl::serialize(CheckpointOut &cp) const 2077584SAli.Saidi@arm.com{ 2088281SAli.Saidi@ARM.com SERIALIZE_SCALAR(flags); 2097584SAli.Saidi@arm.com} 2107584SAli.Saidi@arm.com 2117584SAli.Saidi@arm.comvoid 21210905Sandreas.sandberg@arm.comRealViewCtrl::unserialize(CheckpointIn &cp) 2137584SAli.Saidi@arm.com{ 2148281SAli.Saidi@ARM.com UNSERIALIZE_SCALAR(flags); 2157584SAli.Saidi@arm.com} 2167584SAli.Saidi@arm.com 21711011SAndreas.Sandberg@ARM.comvoid 21811011SAndreas.Sandberg@ARM.comRealViewCtrl::registerDevice(DeviceFunc func, uint8_t site, uint8_t pos, 21911011SAndreas.Sandberg@ARM.com uint8_t dcc, uint16_t dev, 22011011SAndreas.Sandberg@ARM.com Device *handler) 22111011SAndreas.Sandberg@ARM.com{ 22211011SAndreas.Sandberg@ARM.com CfgCtrlReg addr = 0; 22311011SAndreas.Sandberg@ARM.com addr.func = func; 22411011SAndreas.Sandberg@ARM.com addr.site = site; 22511011SAndreas.Sandberg@ARM.com addr.pos = pos; 22611011SAndreas.Sandberg@ARM.com addr.dcc = dcc; 22711011SAndreas.Sandberg@ARM.com addr.dev = dev; 22811011SAndreas.Sandberg@ARM.com 22911011SAndreas.Sandberg@ARM.com if (devices.find(addr) != devices.end()) { 23011011SAndreas.Sandberg@ARM.com fatal("Platform device dcc%d:site%d:pos%d:fn%d:dev%d " 23111011SAndreas.Sandberg@ARM.com "already registered.", 23211011SAndreas.Sandberg@ARM.com addr.dcc, addr.site, addr.pos, addr.func, addr.dev); 23311011SAndreas.Sandberg@ARM.com } 23411011SAndreas.Sandberg@ARM.com 23511011SAndreas.Sandberg@ARM.com devices[addr] = handler; 23611011SAndreas.Sandberg@ARM.com} 23711011SAndreas.Sandberg@ARM.com 23811011SAndreas.Sandberg@ARM.com 23911011SAndreas.Sandberg@ARM.comRealViewOsc::RealViewOsc(RealViewOscParams *p) 24011011SAndreas.Sandberg@ARM.com : ClockDomain(p, p->voltage_domain), 24111011SAndreas.Sandberg@ARM.com RealViewCtrl::Device(*p->parent, RealViewCtrl::FUNC_OSC, 24211011SAndreas.Sandberg@ARM.com p->site, p->position, p->dcc, p->device) 24311011SAndreas.Sandberg@ARM.com{ 24411011SAndreas.Sandberg@ARM.com if (SimClock::Float::s / p->freq > UINT32_MAX) { 24511011SAndreas.Sandberg@ARM.com fatal("Oscillator frequency out of range: %f\n", 24611011SAndreas.Sandberg@ARM.com SimClock::Float::s / p->freq / 1E6); 24711011SAndreas.Sandberg@ARM.com } 24811011SAndreas.Sandberg@ARM.com 24911011SAndreas.Sandberg@ARM.com _clockPeriod = p->freq; 25011011SAndreas.Sandberg@ARM.com} 25111011SAndreas.Sandberg@ARM.com 25211011SAndreas.Sandberg@ARM.comvoid 25311011SAndreas.Sandberg@ARM.comRealViewOsc::startup() 25411011SAndreas.Sandberg@ARM.com{ 25511011SAndreas.Sandberg@ARM.com // Tell dependent object to set their clock frequency 25611011SAndreas.Sandberg@ARM.com for (auto m : members) 25711011SAndreas.Sandberg@ARM.com m->updateClockPeriod(); 25811011SAndreas.Sandberg@ARM.com} 25911011SAndreas.Sandberg@ARM.com 26011011SAndreas.Sandberg@ARM.comvoid 26111011SAndreas.Sandberg@ARM.comRealViewOsc::serialize(CheckpointOut &cp) const 26211011SAndreas.Sandberg@ARM.com{ 26311011SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(_clockPeriod); 26411011SAndreas.Sandberg@ARM.com} 26511011SAndreas.Sandberg@ARM.com 26611011SAndreas.Sandberg@ARM.comvoid 26711011SAndreas.Sandberg@ARM.comRealViewOsc::unserialize(CheckpointIn &cp) 26811011SAndreas.Sandberg@ARM.com{ 26911011SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(_clockPeriod); 27011011SAndreas.Sandberg@ARM.com} 27111011SAndreas.Sandberg@ARM.com 27211011SAndreas.Sandberg@ARM.comvoid 27311011SAndreas.Sandberg@ARM.comRealViewOsc::clockPeriod(Tick clock_period) 27411011SAndreas.Sandberg@ARM.com{ 27511011SAndreas.Sandberg@ARM.com panic_if(clock_period == 0, "%s has a clock period of zero\n", name()); 27611011SAndreas.Sandberg@ARM.com 27711011SAndreas.Sandberg@ARM.com // Align all members to the current tick 27811011SAndreas.Sandberg@ARM.com for (auto m : members) 27911011SAndreas.Sandberg@ARM.com m->updateClockPeriod(); 28011011SAndreas.Sandberg@ARM.com 28111011SAndreas.Sandberg@ARM.com _clockPeriod = clock_period; 28211011SAndreas.Sandberg@ARM.com 28311011SAndreas.Sandberg@ARM.com // inform any derived clocks they need to updated their period 28411011SAndreas.Sandberg@ARM.com for (auto m : children) 28511011SAndreas.Sandberg@ARM.com m->updateClockPeriod(); 28611011SAndreas.Sandberg@ARM.com} 28711011SAndreas.Sandberg@ARM.com 28811011SAndreas.Sandberg@ARM.comuint32_t 28911011SAndreas.Sandberg@ARM.comRealViewOsc::read() const 29011011SAndreas.Sandberg@ARM.com{ 29111011SAndreas.Sandberg@ARM.com const uint32_t freq(SimClock::Float::s / _clockPeriod); 29211011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "Reading OSC frequency: %f MHz\n", freq / 1E6); 29311011SAndreas.Sandberg@ARM.com return freq; 29411011SAndreas.Sandberg@ARM.com} 29511011SAndreas.Sandberg@ARM.com 29611011SAndreas.Sandberg@ARM.comvoid 29711011SAndreas.Sandberg@ARM.comRealViewOsc::write(uint32_t freq) 29811011SAndreas.Sandberg@ARM.com{ 29911011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "Setting new OSC frequency: %f MHz\n", freq / 1E6); 30011011SAndreas.Sandberg@ARM.com clockPeriod(SimClock::Float::s / freq); 30111011SAndreas.Sandberg@ARM.com} 30211011SAndreas.Sandberg@ARM.com 30311421Sdavid.guillen@arm.comuint32_t 30411421Sdavid.guillen@arm.comRealViewTemperatureSensor::read() const 30511421Sdavid.guillen@arm.com{ 30611421Sdavid.guillen@arm.com // Temperature reported in uC 30711421Sdavid.guillen@arm.com ThermalModel * tm = system->getThermalModel(); 30811421Sdavid.guillen@arm.com if (tm) { 30911421Sdavid.guillen@arm.com double t = tm->getTemp(); 31011421Sdavid.guillen@arm.com if (t < 0) 31111421Sdavid.guillen@arm.com warn("Temperature below zero!\n"); 31211421Sdavid.guillen@arm.com return fmax(0, t) * 1000000; 31311421Sdavid.guillen@arm.com } 31411011SAndreas.Sandberg@ARM.com 31511421Sdavid.guillen@arm.com // Report a dummy 25 degrees temperature 31611421Sdavid.guillen@arm.com return 25000000; 31711421Sdavid.guillen@arm.com} 31811011SAndreas.Sandberg@ARM.com 3197584SAli.Saidi@arm.comRealViewCtrl * 3207584SAli.Saidi@arm.comRealViewCtrlParams::create() 3217584SAli.Saidi@arm.com{ 3227584SAli.Saidi@arm.com return new RealViewCtrl(this); 3237584SAli.Saidi@arm.com} 32411011SAndreas.Sandberg@ARM.com 32511011SAndreas.Sandberg@ARM.comRealViewOsc * 32611011SAndreas.Sandberg@ARM.comRealViewOscParams::create() 32711011SAndreas.Sandberg@ARM.com{ 32811011SAndreas.Sandberg@ARM.com return new RealViewOsc(this); 32911011SAndreas.Sandberg@ARM.com} 33011421Sdavid.guillen@arm.com 33111421Sdavid.guillen@arm.comRealViewTemperatureSensor * 33211421Sdavid.guillen@arm.comRealViewTemperatureSensorParams::create() 33311421Sdavid.guillen@arm.com{ 33411421Sdavid.guillen@arm.com return new RealViewTemperatureSensor(this); 33511421Sdavid.guillen@arm.com} 336