LCOV - code coverage report
Current view: top level - timing/src - PC059IONode.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 114 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 22 0

            Line data    Source code
       1              : /**
       2              :  * @file PC059IONode.cpp
       3              :  *
       4              :  * This is part of the DUNE DAQ Software Suite, copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : 
       9              : #include "timing/PC059IONode.hpp"
      10              : 
      11              : #include "logging/Logging.hpp"
      12              : 
      13              : #include <string>
      14              : 
      15              : namespace dunedaq {
      16              : namespace timing {
      17              : 
      18            0 : UHAL_REGISTER_DERIVED_NODE(PC059IONode)
      19              : 
      20              : //-----------------------------------------------------------------------------
      21            0 : PC059IONode::PC059IONode(const uhal::Node& node)
      22            0 :   : SFPMuxIONode(node, "i2c", "i2c", "SI5345", { "PLL", "CDR" }, { "usfp_i2c", "i2c" })
      23            0 : {}
      24              : //-----------------------------------------------------------------------------
      25              : 
      26              : //-----------------------------------------------------------------------------
      27            0 : PC059IONode::~PC059IONode() {}
      28              : //-----------------------------------------------------------------------------
      29              : 
      30              : //-----------------------------------------------------------------------------
      31              : std::string
      32            0 : PC059IONode::get_uid_address_parameter_name() const
      33              : {
      34            0 :   return "FMC_UID_PROM";
      35              : }
      36              : //-----------------------------------------------------------------------------
      37              : 
      38              : //-----------------------------------------------------------------------------
      39              : std::string
      40            0 : PC059IONode::get_status(bool print_out) const
      41              : {
      42            0 :   std::stringstream status;
      43            0 :   auto subnodes = read_sub_nodes(getNode("csr.stat"));
      44            0 :   status << format_reg_table(subnodes, "PC059 IO state");
      45              : 
      46            0 :   if (print_out)
      47            0 :     TLOG() << std::endl << status.str();
      48            0 :   return status.str();
      49            0 : }
      50              : //-----------------------------------------------------------------------------
      51              : 
      52              : //-----------------------------------------------------------------------------
      53              : void
      54            0 : PC059IONode::reset(const std::string& clock_config_file) const
      55              : {
      56              :   // Soft reset
      57            0 :   write_soft_reset_register();
      58              : 
      59            0 :   millisleep(1000);
      60              : 
      61              :   // Reset PLL and I2C
      62            0 :   getNode("csr.ctrl.pll_rst").write(0x1);
      63            0 :   getNode("csr.ctrl.pll_rst").write(0x0);
      64              : 
      65            0 :   getNode("csr.ctrl.rst_i2c").write(0x1);
      66            0 :   getNode("csr.ctrl.rst_i2c").write(0x0);
      67              : 
      68            0 :   getNode("csr.ctrl.rst_i2cmux").write(0x1);
      69            0 :   getNode("csr.ctrl.rst_i2cmux").write(0x0);
      70              : 
      71            0 :   getClient().dispatch();
      72              : 
      73              :   // enclustra i2c switch stuff
      74            0 :   try {
      75            0 :     getNode<I2CMasterNode>(m_uid_i2c_bus).get_slave("AX3_Switch").write_i2c(0x01, 0x7f);
      76            0 :   } catch (const std::exception& e) {
      77            0 :       ers::warning(EnclustraSwitchFailure(ERS_HERE, e));
      78            0 :   }
      79              : 
      80              :   // Upload config file to PLL
      81            0 :   configure_pll(clock_config_file);
      82              : 
      83              :   // Reset mmcm
      84            0 :   getNode("csr.ctrl.rst").write(0x1);
      85            0 :   getNode("csr.ctrl.rst").write(0x0);
      86            0 :   getClient().dispatch();
      87              : 
      88            0 :   getNode("csr.ctrl.mux").write(0);
      89            0 :   getClient().dispatch();
      90              : 
      91            0 :   auto sfp_expander = get_i2c_device<I2CExpanderSlave>(m_uid_i2c_bus, "SFPExpander");
      92              : 
      93              :   // Set invert registers to default for both banks
      94            0 :   sfp_expander->set_inversion(0, 0x00);
      95            0 :   sfp_expander->set_inversion(1, 0x00);
      96              : 
      97              :   // Bank 0 output, bank 1 input
      98            0 :   sfp_expander->set_io(0, 0x00);
      99            0 :   sfp_expander->set_io(1, 0xff);
     100              : 
     101              :   // Bank 0 - enable all SFPGs (enable low)
     102            0 :   sfp_expander->set_outputs(0, 0x00);
     103            0 :   TLOG_DEBUG(0) << "SFPs 0-7 enabled";
     104              : 
     105              :   // To be removed from firmware address maps also
     106              :   //getNode("csr.ctrl.rst_lock_mon").write(0x1);
     107              :   //getNode("csr.ctrl.rst_lock_mon").write(0x0);
     108              :   //getClient().dispatch();
     109              : 
     110            0 :   TLOG() << "Reset done";
     111            0 : }
     112              : //-----------------------------------------------------------------------------
     113              : 
     114              : //-----------------------------------------------------------------------------
     115              : void
     116            0 : PC059IONode::reset_pll() const
     117              : {
     118            0 : }
     119              : //-----------------------------------------------------------------------------
     120              : 
     121              : //-----------------------------------------------------------------------------
     122              : void
     123            0 : PC059IONode::switch_sfp_mux_channel(uint32_t mux_channel) const // NOLINT(build/unsigned)
     124              : {
     125            0 :   getNode("csr.ctrl.mux").write(mux_channel);
     126            0 :   getClient().dispatch();
     127              : 
     128            0 :   TLOG_DEBUG(3) << "SFP input mux set to " << format_reg_value(read_active_sfp_mux_channel());
     129            0 : }
     130              : //-----------------------------------------------------------------------------
     131              : 
     132              : //-----------------------------------------------------------------------------
     133              : uint32_t // NOLINT(build/unsigned)
     134            0 : PC059IONode::read_active_sfp_mux_channel() const
     135              : {
     136            0 :   auto active_sfp_mux_channel = getNode("csr.ctrl.mux").read();
     137            0 :   getClient().dispatch();
     138            0 :   return active_sfp_mux_channel.value();
     139            0 : }
     140              : //-----------------------------------------------------------------------------
     141              : 
     142              : //-----------------------------------------------------------------------------
     143              : void
     144            0 : PC059IONode::switch_sfp_i2c_mux_channel(uint32_t sfp_id) const // NOLINT(build/unsigned)
     145              : {
     146              : 
     147            0 :   getNode("csr.ctrl.rst_i2cmux").write(0x1);
     148            0 :   getClient().dispatch();
     149            0 :   getNode("csr.ctrl.rst_i2cmux").write(0x0);
     150            0 :   getClient().dispatch();
     151            0 :   millisleep(100);
     152              : 
     153            0 :   uint8_t channel_select_byte = 1UL << sfp_id; // NOLINT(build/unsigned)
     154            0 :   getNode<I2CMasterNode>(m_pll_i2c_bus).get_slave("SFP_Switch").write_i2cPrimitive({ channel_select_byte });
     155            0 :   TLOG_DEBUG(3) << "PC059 SFP I2C mux set to " << format_reg_value(sfp_id);
     156            0 : }
     157              : //-----------------------------------------------------------------------------
     158              : 
     159              : //-----------------------------------------------------------------------------
     160              : std::string
     161            0 : PC059IONode::get_sfp_status(uint32_t sfp_id, bool print_out) const // NOLINT(build/unsigned)
     162              : {
     163              :   // on this board the upstream sfp has its own i2c bus, and the 8 downstream sfps are muxed onto the main i2c bus
     164            0 :   std::stringstream status;
     165            0 :   uint32_t sfp_bus_index; // NOLINT(build/unsigned)
     166            0 :   if (sfp_id == 0) {
     167            0 :     sfp_bus_index = 0;
     168            0 :     status << "Upstream SFP:" << std::endl;
     169            0 :   } else if (sfp_id > 0 && sfp_id < 9) {
     170            0 :     switch_sfp_i2c_mux_channel(sfp_id - 1);
     171            0 :     status << "Fanout SFP " << sfp_id - 1 << ":" << std::endl;
     172              :     sfp_bus_index = 1;
     173              :   } else {
     174            0 :     throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
     175              :   }
     176            0 :   auto sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(sfp_bus_index), "SFP_EEProm");
     177              : 
     178            0 :   status << sfp->get_status();
     179              : 
     180            0 :   if (print_out)
     181            0 :     TLOG() << status.str();
     182            0 :   return status.str();
     183            0 : }
     184              : //-----------------------------------------------------------------------------
     185              : 
     186              : //-----------------------------------------------------------------------------
     187              : bool
     188            0 : PC059IONode::clocks_ok() const
     189              : {
     190            0 :   std::stringstream status;
     191              : 
     192            0 :   auto states = read_sub_nodes(getNode("csr.stat"));
     193            0 :   bool pll_ok = states.find("pll_ok")->second.value();
     194            0 :   bool mmcm_ok = states.find("mmcm_ok")->second.value();
     195              : 
     196            0 :   TLOG_DEBUG(5) << "pll ok: " << pll_ok << ", mmcm ok: " << mmcm_ok;
     197              : 
     198            0 :   return pll_ok && mmcm_ok;
     199            0 : }
     200              : //-----------------------------------------------------------------------------
     201              : 
     202              : //-----------------------------------------------------------------------------
     203              : void
     204            0 : PC059IONode::switch_sfp_soft_tx_control_bit(uint32_t sfp_id, bool turn_on) const // NOLINT(build/unsigned)
     205              : {
     206              :   // on this board the upstream sfp has its own i2c bus, and the 8 downstream sfps are muxed onto the main i2c bus
     207            0 :   uint32_t sfp_bus_index; // NOLINT(build/unsigned)
     208            0 :   if (sfp_id == 0) {
     209              :     sfp_bus_index = 0;
     210            0 :   } else if (sfp_id > 0 && sfp_id < 9) {
     211            0 :     switch_sfp_i2c_mux_channel(sfp_id - 1);
     212              :     sfp_bus_index = 1;
     213              :   } else {
     214            0 :     throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
     215              :   }
     216            0 :   auto sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(sfp_bus_index), "SFP_EEProm");
     217            0 :   sfp->switch_soft_tx_control_bit(turn_on);
     218            0 : }
     219              : //-----------------------------------------------------------------------------
     220              : 
     221              : //-----------------------------------------------------------------------------
     222              : void
     223            0 : PC059IONode::switch_sfp_tx(uint32_t sfp_id, bool turn_on) const { // NOLINT(build/unsigned)
     224              : 
     225            0 :   validate_sfp_id(sfp_id);
     226              : 
     227            0 :   auto sfp_expander = get_i2c_device<I2CExpanderSlave>(m_uid_i2c_bus, "SFPExpander");
     228            0 :         uint8_t current_sfp_tx_control_flags = sfp_expander->read_outputs_config(0); // NOLINT(build/unsigned)
     229              : 
     230            0 :         uint8_t new_sfp_tx_control_flags; // NOLINT(build/unsigned)
     231            0 :         if (turn_on)
     232              :         {
     233            0 :                 new_sfp_tx_control_flags = current_sfp_tx_control_flags & ~(1UL << sfp_id);
     234              :         }
     235              :   else
     236              :   {
     237            0 :     new_sfp_tx_control_flags = current_sfp_tx_control_flags | (1UL << sfp_id);
     238              :   }
     239              : 
     240            0 :   sfp_expander->set_outputs(0, new_sfp_tx_control_flags);
     241            0 : }
     242              : //-----------------------------------------------------------------------------
     243              : 
     244              : //-----------------------------------------------------------------------------
     245              : void
     246            0 : PC059IONode::validate_sfp_id(uint32_t sfp_id) const // NOLINT(build/unsigned)
     247              : {
     248              :   // on this board we have 8 downstream SFPs
     249            0 :         if (sfp_id > 7)
     250              :   {
     251            0 :     throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
     252              :         }
     253            0 : }
     254              : //-----------------------------------------------------------------------------
     255              : 
     256              : //-----------------------------------------------------------------------------
     257              : // void
     258              : // PC059IONode::get_info(timinghardwareinfo::TimingPC059MonitorData& mon_data) const
     259              : // {
     260              : //   auto subnodes = read_sub_nodes(getNode("csr.stat"));
     261              : 
     262              : //   mon_data.cdr_lol = subnodes.at("cdr_lol").value();
     263              : //   mon_data.cdr_los = subnodes.at("cdr_los").value();
     264              :   
     265              : //   mon_data.mmcm_ok = subnodes.at("mmcm_ok").value();
     266              : //   mon_data.mmcm_sticky = subnodes.at("mmcm_sticky").value();
     267              :   
     268              : //   mon_data.pll_lol = subnodes.at("pll_lol").value();
     269              : //   mon_data.pll_ok = subnodes.at("pll_ok").value();
     270              : //   mon_data.pll_sticky = subnodes.at("pll_sticky").value();
     271              :   
     272              : //   mon_data.sfp_los = subnodes.at("sfp_los").value();
     273              : 
     274              : //   mon_data.ucdr_lol = subnodes.at("ucdr_lol").value();
     275              : //   mon_data.ucdr_los = subnodes.at("ucdr_los").value();
     276              : 
     277              : //   mon_data.usfp_flt = subnodes.at("usfp_flt").value();
     278              : //   mon_data.usfp_los = subnodes.at("usfp_los").value();
     279              : // }
     280              : //-----------------------------------------------------------------------------
     281              : 
     282              : //-----------------------------------------------------------------------------
     283              : // void
     284              : // PC059IONode::get_info(opmonlib::InfoCollector& ci, int level) const
     285              : // {
     286              : //   if (level >= 2)
     287              : //   {
     288              : //     timinghardwareinfo::TimingPLLMonitorData pll_mon_data;
     289              : //     this->get_pll()->get_info(pll_mon_data);
     290              : //     ci.add(pll_mon_data);
     291              : 
     292              : //     timinghardwareinfo::TimingSFPMonitorData upstream_sfp_mon_data;
     293              : //     auto upstream_sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(0), "SFP_EEProm");
     294              : //     try {
     295              : //       upstream_sfp->get_info(upstream_sfp_mon_data);
     296              : //       opmonlib::InfoCollector upstream_sfp_ic;
     297              : //       upstream_sfp_ic.add(upstream_sfp_mon_data);
     298              : //       ci.add("upstream_sfp", upstream_sfp_ic);
     299              : //     }
     300              : //     catch (timing::SFPUnreachable& e) {
     301              : //       // It is valid that an SFP may not be installed, currently no good way of knowing whether they it should be
     302              : //       TLOG_DEBUG(2) << "Failed to communicate with upstream SFP on i2c bus" << m_sfp_i2c_buses.at(0);
     303              : //     }
     304              : 
     305              : 
     306              : //     for (uint sfp_id=0; sfp_id < 8; ++sfp_id) {
     307              : //       TLOG_DEBUG(5) << "checking sfp: " << sfp_id;
     308              : //       switch_sfp_i2c_mux_channel(sfp_id);
     309              :       
     310              : //       auto sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(1), "SFP_EEProm");
     311              : //       timinghardwareinfo::TimingSFPMonitorData sfp_data;
     312              : 
     313              : //       try {
     314              : //         sfp->get_info(sfp_data);
     315              : //       } catch (timing::SFPUnreachable& e) {
     316              : //         // It is valid that an SFP may not be installed, currently no good way of knowing whether they it should be
     317              : //         TLOG_DEBUG(2) << "Failed to communicate with downstream SFP: " << sfp_id << " on i2c bus" << m_sfp_i2c_buses.at(1);
     318              : //         continue;
     319              : //       }
     320              : 
     321              : //       opmonlib::InfoCollector sfp_ic;
     322              : //       sfp_ic.add(sfp_data);
     323              : //       ci.add("sfp_"+std::to_string(sfp_id), sfp_ic);
     324              : //     }
     325              : //   }
     326              : 
     327              : //   if (level >= 1) {
     328              : //     timinghardwareinfo::TimingPC059MonitorData mon_data;
     329              : //     this->get_info(mon_data);
     330              : //     ci.add(mon_data);
     331              : //   }  
     332              : // }
     333              : //-----------------------------------------------------------------------------
     334              : 
     335              : } // namespace timing
     336              : } // namespace dunedaq
        

Generated by: LCOV version 2.0-1