changeset 2ca6c68fdd6c in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=2ca6c68fdd6c
description:
        arm: Add support for programmable oscillators

        Add support for oscillators that can be programmed using the RealView
        / Versatile Express configuration interface. These oscillators are
        typically used for things like the pixel clock in the display
        controller.

        The default configurations support the oscillators from a Versatile
        Express motherboard (V2M-P1) with a CoreTile Express A15x2.

diffstat:

 src/dev/arm/RealView.py |   54 ++++++++++++-
 src/dev/arm/rv_ctrl.cc  |  200 +++++++++++++++++++++++++++++------------------
 src/dev/arm/rv_ctrl.hh  |   85 +++++++++++++++++++-
 3 files changed, 253 insertions(+), 86 deletions(-)

diffs (truncated from 456 to 300 lines):

diff -r 034378be28a2 -r 2ca6c68fdd6c src/dev/arm/RealView.py
--- a/src/dev/arm/RealView.py   Fri Aug 07 09:59:23 2015 +0100
+++ b/src/dev/arm/RealView.py   Fri Aug 07 09:59:25 2015 +0100
@@ -42,6 +42,8 @@
 
 from m5.params import *
 from m5.proxy import *
+from ClockDomain import ClockDomain
+from VoltageDomain import VoltageDomain
 from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr, DmaDevice
 from Pci import PciConfigAll
 from Ethernet import NSGigE, IGbE_igb, IGbE_e1000
@@ -89,6 +91,49 @@
     proc_id1 = Param.UInt32(0x0C000222, "Processor ID, SYS_PROCID1")
     idreg = Param.UInt32(0x00000000, "ID Register, SYS_ID")
 
+class RealViewOsc(ClockDomain):
+    type = 'RealViewOsc'
+    cxx_header = "dev/arm/rv_ctrl.hh"
+
+    parent = Param.RealViewCtrl(Parent.any, "RealView controller")
+
+    # TODO: We currently don't have the notion of a clock source,
+    # which means we have to associate oscillators with a voltage
+    # source.
+    voltage_domain = Param.VoltageDomain(Parent.voltage_domain,
+                                         "Voltage domain")
+
+    # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1) and
+    # the individual core/logic tile reference manuals for details
+    # about the site/position/dcc/device allocation.
+    site = Param.UInt8("Board Site")
+    position = Param.UInt8("Position in device stack")
+    dcc = Param.UInt8("Daughterboard Configuration Controller")
+    device = Param.UInt8("Device ID")
+
+    freq = Param.Clock("Default frequency")
+
+class VExpressCoreTileCtrl(RealViewCtrl):
+    class MotherBoardOsc(RealViewOsc):
+        site, position, dcc = (0, 0, 0)
+
+    class CoreTileOsc(RealViewOsc):
+        site, position, dcc = (1, 0, 0)
+
+    # See ARM DUI 0447J (ARM Motherboard Express uATX -- V2M-P1)
+    osc_mcc = MotherBoardOsc(device=0, freq="50MHz")
+    osc_clcd = MotherBoardOsc(device=1, freq="23.75MHz")
+    osc_peripheral = MotherBoardOsc(device=2, freq="24MHz")
+    osc_system_bus = MotherBoardOsc(device=4, freq="24MHz")
+
+    # See Table 2.8 in ARM DUI 0604E (CoreTile Express A15x2 TRM).
+    osc_cpu = CoreTileOsc(device=0, freq="60MHz")
+    osc_hsbm = CoreTileOsc(device=4, freq="40MHz")
+    osc_pxl = CoreTileOsc(device=5, freq="23.75MHz")
+    osc_smb = CoreTileOsc(device=6, freq="50MHz")
+    osc_sys = CoreTileOsc(device=7, freq="60MHz")
+    osc_ddr = CoreTileOsc(device=8, freq="40MHz")
+
 class VGic(PioDevice):
     type = 'VGic'
     cxx_header = "dev/arm/vgic.hh"
@@ -227,7 +272,7 @@
 # Chapter 4: Programmer's Reference
 class RealViewPBX(RealView):
     uart = Pl011(pio_addr=0x10009000, int_num=44)
-    realview_io = RealViewCtrl(pio_addr=0x10000000)
+    realview_io = VExpressCoreTileCtrl(pio_addr=0x10000000)
     gic = Pl390()
     timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
     timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
@@ -354,7 +399,7 @@
 # Chapter 4: Programmer's Reference
 class RealViewEB(RealView):
     uart = Pl011(pio_addr=0x10009000, int_num=44)
-    realview_io = RealViewCtrl(pio_addr=0x10000000, idreg=0x01400500)
+    realview_io = VExpressCoreTileCtrl(pio_addr=0x10000000, idreg=0x01400500)
     gic = Pl390(dist_addr=0x10041000, cpu_addr=0x10040000)
     timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
     timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
@@ -464,8 +509,9 @@
     _mem_regions = [(Addr('2GB'), Addr('2GB'))]
     pci_cfg_base = 0x30000000
     uart = Pl011(pio_addr=0x1c090000, int_num=37)
-    realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000, \
-                               idreg=0x02250000, pio_addr=0x1C010000)
+    realview_io = VExpressCoreTileCtrl(
+        proc_id0=0x14000000, proc_id1=0x14000000,
+        idreg=0x02250000, pio_addr=0x1C010000)
     gic = Pl390(dist_addr=0x2C001000, cpu_addr=0x2C002000)
     local_cpu_timer = CpuLocalTimer(int_num_timer=29, int_num_watchdog=30, 
pio_addr=0x2C080000)
     generic_timer = GenericTimer(int_phys=29, int_virt=27)
diff -r 034378be28a2 -r 2ca6c68fdd6c src/dev/arm/rv_ctrl.cc
--- a/src/dev/arm/rv_ctrl.cc    Fri Aug 07 09:59:23 2015 +0100
+++ b/src/dev/arm/rv_ctrl.cc    Fri Aug 07 09:59:25 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010,2013 ARM Limited
+ * Copyright (c) 2010,2013,2015 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -42,6 +42,7 @@
 #include "dev/arm/rv_ctrl.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
+#include "sim/voltage_domain.hh"
 
 RealViewCtrl::RealViewCtrl(Params *p)
     : BasicPioDevice(p, 0xD4), flags(0), scData(0)
@@ -155,86 +156,33 @@
           // A request is being submitted to read/write the system control
           // registers.  See
           // 
http://infocenter.arm.com/help/topic/com.arm.doc.dui0447h/CACDEFGH.html
-          // 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;
+          }
 
-          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);
+
           } else {
-              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);
           }
       } break;
       case CfgStat:     // Weird to write this
@@ -259,8 +207,102 @@
     UNSERIALIZE_SCALAR(flags);
 }
 
+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
+{
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to