dev: Add 'OSC' oscillator sys control reg support to VersatileExpress
authorMatt Evans <matt.evans@arm.com>
Thu, 31 Oct 2013 18:41:13 +0000 (13:41 -0500)
committerMatt Evans <matt.evans@arm.com>
Thu, 31 Oct 2013 18:41:13 +0000 (13:41 -0500)
The VE motherboard provides a set of system control registers through which
various motherboard and coretile registers are accessed.  Voltage regulators and
oscillator (DLL/PLL) config are examples. These registers must be impleted to
boot Linux 3.9+ kernels.

src/dev/arm/SConscript
src/dev/arm/rv_ctrl.cc
src/dev/arm/rv_ctrl.hh

index 60a85220edd12762220bca18527eeb027d2be80d..68779ec6405c540dcd685286a52b632b01a3301a 100644 (file)
@@ -63,3 +63,4 @@ if env['TARGET_ISA'] == 'arm':
     DebugFlag('PL111')
     DebugFlag('Pl050')
     DebugFlag('GIC')
+    DebugFlag('RVCTRL')
index 61111d22ee25861dcfe389ce288876b486f5119c..af121861c9852be07bf6c923a444d81f734fc3b3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010,2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
  */
 
 #include "base/trace.hh"
+#include "debug/RVCTRL.hh"
 #include "dev/arm/rv_ctrl.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
 
 RealViewCtrl::RealViewCtrl(Params *p)
-    : BasicPioDevice(p, 0xD4), flags(0)
+    : BasicPioDevice(p, 0xD4), flags(0), scData(0)
 {
 }
 
@@ -105,9 +106,18 @@ RealViewCtrl::read(PacketPtr pkt)
       case CfgStat:
         pkt->set<uint32_t>(1);
         break;
+      case CfgData:
+        pkt->set<uint32_t>(scData);
+        DPRINTF(RVCTRL, "Read %#x from SCReg\n", scData);
+        break;
+      case CfgCtrl:
+        pkt->set<uint32_t>(0); // not busy
+        DPRINTF(RVCTRL, "Read 0 from CfgCtrl\n");
+        break;
       default:
         warn("Tried to read RealView I/O at offset %#x that doesn't exist\n",
              daddr);
+        pkt->set<uint32_t>(0);
         break;
     }
     pkt->makeAtomicResponse();
@@ -139,9 +149,99 @@ RealViewCtrl::write(PacketPtr pkt)
       case FlagsClr:
         flags = 0;
         break;
+      case CfgData:
+        scData = pkt->get<uint32_t>();
+        break;
+      case CfgCtrl: {
+          // 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);
+
+          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);
+                  }
+              }
+          } else {
+              DPRINTF(RVCTRL, "SCReg: write %#x to ctrl but not starting\n", data);
+          }
+      } break;
+      case CfgStat:     // Weird to write this
       default:
-        warn("Tried to write RVIO at offset %#x that doesn't exist\n",
-             daddr);
+        warn("Tried to write RVIO at offset %#x (data %#x) that doesn't exist\n",
+             daddr, pkt->get<uint32_t>());
         break;
     }
     pkt->makeAtomicResponse();
index c6cf40f96ca213103e8c41895c7615227e80ff5f..adf06563178e60474bbd869b66a2852e457aa797 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010,2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -80,8 +80,8 @@ class RealViewCtrl : public BasicPioDevice
         IoSel      = 0x70,
         ProcId0    = 0x84,
         ProcId1    = 0x88,
-        CfgCtrl    = 0xA0,
-        CfgData    = 0xA4,
+        CfgData    = 0xA0,
+        CfgCtrl    = 0xA4,
         CfgStat    = 0xA8,
         TestOsc0   = 0xC0,
         TestOsc1   = 0xC4,
@@ -105,6 +105,10 @@ class RealViewCtrl : public BasicPioDevice
      */
     uint32_t flags;
 
+    /** This register contains the result from a system control reg access
+     */
+    uint32_t scData;
+
   public:
     typedef RealViewCtrlParams Params;
     const Params *