2c2
< * Copyright (c) 2010,2013 ARM Limited
---
> * Copyright (c) 2010,2013,2015 ARM Limited
44a45
> #include "sim/voltage_domain.hh"
158,169c159,164
< // For now, model as much of the OSC regs (can't find docs) as Linux
< // seems to require (can't find docs); some clocks are deemed to be 0,
< // giving all kinds of /0 problems booting Linux 3.9. Return a
< // vaguely plausible number within the range the device trees state:
< uint32_t data = pkt->get<uint32_t>();
< uint16_t dev = bits(data, 11, 0);
< uint8_t pos = bits(data, 15, 12);
< uint8_t site = bits(data, 17, 16);
< uint8_t func = bits(data, 25, 20);
< uint8_t dcc = bits(data, 29, 26);
< bool wr = bits(data, 30);
< bool start = bits(data, 31);
---
> CfgCtrlReg req = pkt->get<uint32_t>();
> if (!req.start) {
> DPRINTF(RVCTRL, "SCReg: write %#x to ctrl but not starting\n",
> req);
> break;
> }
171,235c166,181
< if (start) {
< if (wr) {
< warn_once("SCReg: Writing %#x to dcc%d:site%d:pos%d:fn%d:dev%d\n",
< scData, dcc, site, pos, func, dev);
< // Only really support reading, for now!
< } else {
< // Only deal with function 1 (oscillators) so far!
< if (dcc != 0 || pos != 0 || func != 1) {
< warn("SCReg: read from unknown area "
< "(dcc %d:site%d:pos%d:fn%d:dev%d)\n",
< dcc, site, pos, func, dev);
< } else {
< switch (site) {
< case 0: { // Motherboard regs
< switch(dev) {
< case 0: // MCC clk
< scData = 25000000;
< break;
< case 1: // CLCD clk
< scData = 25000000;
< break;
< case 2: // PeriphClk 24MHz
< scData = 24000000;
< break;
< default:
< scData = 0;
< warn("SCReg: read from unknown dev %d "
< "(site%d:pos%d:fn%d)\n",
< dev, site, pos, func);
< }
< } break;
< case 1: { // Coretile 1 regs
< switch(dev) {
< case 0: // CPU PLL ref
< scData = 50000000;
< break;
< case 4: // Muxed AXI master clock
< scData = 40000000;
< break;
< case 5: // HDLCD clk
< scData = 50000000;
< break;
< case 6: // SMB clock
< scData = 35000000;
< break;
< case 7: // SYS PLL (also used for pl011 UART!)
< scData = 40000000;
< break;
< case 8: // DDR PLL 40MHz fixed
< scData = 40000000;
< break;
< default:
< scData = 0;
< warn("SCReg: read from unknown dev %d "
< "(site%d:pos%d:fn%d)\n",
< dev, site, pos, func);
< }
< } break;
< default:
< warn("SCReg: Read from unknown site %d (pos%d:fn%d:dev%d)\n",
< site, pos, func, dev);
< }
< DPRINTF(RVCTRL, "SCReg: Will read %#x (ctrlWr %#x)\n", scData, data);
< }
< }
---
> auto it_dev(devices.find(req & CFG_CTRL_ADDR_MASK));
> if (it_dev == devices.end()) {
> warn_once("SCReg: Access to unknown device "
> "dcc%d:site%d:pos%d:fn%d:dev%d\n",
> req.dcc, req.site, req.pos, req.func, req.dev);
> break;
> }
>
> // Service the request as a read or write depending on the
> // wr bit in the control register.
> Device &dev(*it_dev->second);
> if (req.wr) {
> DPRINTF(RVCTRL, "SCReg: Writing %#x (ctrlWr %#x)\n",
> scData, req);
> dev.write(scData);
>
237c183,185
< DPRINTF(RVCTRL, "SCReg: write %#x to ctrl but not starting\n", data);
---
> scData = dev.read();
> DPRINTF(RVCTRL, "SCReg: Reading %#x (ctrlRd %#x)\n",
> scData, req);
261a210,297
> void
> RealViewCtrl::registerDevice(DeviceFunc func, uint8_t site, uint8_t pos,
> uint8_t dcc, uint16_t dev,
> Device *handler)
> {
> CfgCtrlReg addr = 0;
> addr.func = func;
> addr.site = site;
> addr.pos = pos;
> addr.dcc = dcc;
> addr.dev = dev;
>
> if (devices.find(addr) != devices.end()) {
> fatal("Platform device dcc%d:site%d:pos%d:fn%d:dev%d "
> "already registered.",
> addr.dcc, addr.site, addr.pos, addr.func, addr.dev);
> }
>
> devices[addr] = handler;
> }
>
>
> RealViewOsc::RealViewOsc(RealViewOscParams *p)
> : ClockDomain(p, p->voltage_domain),
> RealViewCtrl::Device(*p->parent, RealViewCtrl::FUNC_OSC,
> p->site, p->position, p->dcc, p->device)
> {
> if (SimClock::Float::s / p->freq > UINT32_MAX) {
> fatal("Oscillator frequency out of range: %f\n",
> SimClock::Float::s / p->freq / 1E6);
> }
>
> _clockPeriod = p->freq;
> }
>
> void
> RealViewOsc::startup()
> {
> // Tell dependent object to set their clock frequency
> for (auto m : members)
> m->updateClockPeriod();
> }
>
> void
> RealViewOsc::serialize(CheckpointOut &cp) const
> {
> SERIALIZE_SCALAR(_clockPeriod);
> }
>
> void
> RealViewOsc::unserialize(CheckpointIn &cp)
> {
> UNSERIALIZE_SCALAR(_clockPeriod);
> }
>
> void
> RealViewOsc::clockPeriod(Tick clock_period)
> {
> panic_if(clock_period == 0, "%s has a clock period of zero\n", name());
>
> // Align all members to the current tick
> for (auto m : members)
> m->updateClockPeriod();
>
> _clockPeriod = clock_period;
>
> // inform any derived clocks they need to updated their period
> for (auto m : children)
> m->updateClockPeriod();
> }
>
> uint32_t
> RealViewOsc::read() const
> {
> const uint32_t freq(SimClock::Float::s / _clockPeriod);
> DPRINTF(RVCTRL, "Reading OSC frequency: %f MHz\n", freq / 1E6);
> return freq;
> }
>
> void
> RealViewOsc::write(uint32_t freq)
> {
> DPRINTF(RVCTRL, "Setting new OSC frequency: %f MHz\n", freq / 1E6);
> clockPeriod(SimClock::Float::s / freq);
> }
>
>
>
266a303,308
>
> RealViewOsc *
> RealViewOscParams::create()
> {
> return new RealViewOsc(this);
> }