Line data Source code
1 : /**
2 : * @file MIBIONode.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/MIBIONode.hpp"
10 :
11 : #include <string>
12 : #include <math.h>
13 :
14 : namespace dunedaq {
15 : namespace timing {
16 :
17 0 : UHAL_REGISTER_DERIVED_NODE(MIBIONode)
18 :
19 : //-----------------------------------------------------------------------------
20 0 : MIBIONode::MIBIONode(const uhal::Node& node)
21 0 : : IONode(node, "i2c", "i2c", { "PLL" }, { "PLL", "CDR 0", "CDR 1" }, { "i2c" })
22 : {
23 0 : }
24 : //-----------------------------------------------------------------------------
25 :
26 : //-----------------------------------------------------------------------------
27 0 : MIBIONode::~MIBIONode() {}
28 : //-----------------------------------------------------------------------------
29 :
30 : //-----------------------------------------------------------------------------
31 : std::string
32 0 : MIBIONode::get_uid_address_parameter_name() const
33 : {
34 0 : return "UID_PROM";
35 : }
36 : //-----------------------------------------------------------------------------
37 :
38 : //-----------------------------------------------------------------------------
39 : std::string
40 0 : MIBIONode::get_status(bool print_out) const
41 : {
42 0 : std::stringstream status;
43 :
44 0 : auto subnodes = read_sub_nodes(getNode("csr.stat"));
45 0 : status << format_reg_table(subnodes, "MIB IO state");
46 :
47 0 : if (print_out)
48 0 : TLOG() << std::endl << status.str();
49 0 : return status.str();
50 0 : }
51 : //-----------------------------------------------------------------------------
52 :
53 : //-----------------------------------------------------------------------------
54 : void
55 0 : MIBIONode::configure_pll(const std::string& clock_config_file) const
56 : {
57 : // enable pll channel (#3) only
58 0 : auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
59 0 : i2c_switch->set_channels_states(8);
60 0 : IONode::configure_pll(clock_config_file);
61 0 : }
62 : //-----------------------------------------------------------------------------
63 :
64 : //-----------------------------------------------------------------------------
65 : std::string
66 0 : MIBIONode::get_pll_status(bool print_out) const
67 : {
68 : // enable pll channel (#3) only
69 0 : auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
70 0 : i2c_switch->set_channels_states(8);
71 0 : return IONode::get_pll_status(print_out);
72 0 : }
73 : //-----------------------------------------------------------------------------
74 :
75 : //-----------------------------------------------------------------------------
76 : void
77 0 : MIBIONode::reset(const std::string& clock_config_file) const
78 : {
79 0 : write_soft_reset_register();
80 :
81 0 : millisleep(1000);
82 :
83 : // Upload config file to PLL
84 0 : configure_pll(clock_config_file);
85 :
86 : // Reset mmcm
87 0 : getNode("csr.ctrl.rst").write(0x1);
88 0 : getNode("csr.ctrl.rst").write(0x0);
89 :
90 0 : getNode("io_select.csr.ctrl.amc_out").write(0xfff);
91 0 : getNode("io_select.csr.ctrl.amc_in").write(0x0);
92 0 : getNode("io_select.csr.ctrl.usfp_src").write(0x0);
93 :
94 0 : getClient().dispatch();
95 :
96 0 : TLOG() << "Reset done";
97 0 : }
98 : //-----------------------------------------------------------------------------
99 :
100 : //-----------------------------------------------------------------------------
101 0 : void MIBIONode::reset_pll() const
102 : {
103 0 : }
104 : //-----------------------------------------------------------------------------
105 :
106 : //-----------------------------------------------------------------------------
107 : bool
108 0 : MIBIONode::clocks_ok() const
109 : {
110 0 : TLOG() << "clock check needs to be implemented";
111 0 : return false;
112 : }
113 : //-----------------------------------------------------------------------------
114 :
115 : //-----------------------------------------------------------------------------
116 : //void
117 : //MIBIONode::switch_downstream_mux_channel(uint32_t mux_channel) const // NOLINT(build/unsigned)
118 : //{
119 : // validate_amc_slot(mux_channel);
120 : // uint16_t amc_in_bit = 0x1 << (mux_channel-1);
121 : // getNode("io_select.csr.ctrl.amc_in").write(amc_in_bit);
122 : //
123 : // TLOG_DEBUG(3) << " MIB downstream AMC (in) " << mux_channel << " enabled";
124 : // getClient().dispatch();
125 : //}
126 : //-----------------------------------------------------------------------------
127 :
128 : //-----------------------------------------------------------------------------
129 : //uint32_t // NOLINT(build/unsigned)
130 : //MIBIONode::read_active_downstream_mux_channel() const
131 : //{
132 : // auto active_mux_channel_bits = getNode("io_select.csr.ctrl.amc_in").read();
133 : // getClient().dispatch();
134 : // double mux = log2(active_mux_channel_bits.value());
135 : // return mux+1;
136 : //}
137 : //-----------------------------------------------------------------------------
138 :
139 : //-----------------------------------------------------------------------------
140 : //void
141 : //MIBIONode::switch_upstream_mux_channel(uint32_t mux_channel) const // NOLINT(build/unsigned)
142 : //{
143 : // getNode("io_select.csr.ctrl.usfp_src").write(mux_channel);
144 : // TLOG_DEBUG(3) << " MIB upstream SFP (in) " << mux_channel << " enabled";
145 : // // TODO what about clock config?
146 : // getClient().dispatch();
147 : //}
148 : //-----------------------------------------------------------------------------
149 :
150 : //-----------------------------------------------------------------------------
151 : //uint32_t // NOLINT(build/unsigned)
152 : //MIBIONode::read_active_upstream_mux_channel() const
153 : //{
154 : // auto active_sfp_mux_channel = getNode("io_select.csr.ctrl.usfp_src").read();
155 : // getClient().dispatch();
156 : // return active_sfp_mux_channel.value();
157 : //}
158 : //-----------------------------------------------------------------------------
159 :
160 : //-----------------------------------------------------------------------------
161 : std::string
162 0 : MIBIONode::get_sfp_status(uint32_t sfp_id, bool print_out) const { // NOLINT(build/unsigned)
163 0 : std::stringstream status;
164 :
165 0 : validate_sfp_id(sfp_id);
166 :
167 : // enable i2c path for sfp
168 0 : auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
169 0 : i2c_switch->set_channels_states(1UL << sfp_id);
170 :
171 0 : auto sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(0), "SFP_EEProm");
172 :
173 0 : status << "SFP " << sfp_id << ":" << std::endl;
174 :
175 0 : try
176 : {
177 0 : status << sfp->get_status();
178 : }
179 0 : catch(...)
180 : {
181 0 : i2c_switch->set_channels_states(8);
182 0 : throw;
183 0 : }
184 :
185 0 : i2c_switch->set_channels_states(8);
186 :
187 0 : if (print_out)
188 0 : TLOG() << status.str();
189 :
190 0 : return status.str();
191 0 : }
192 : //-----------------------------------------------------------------------------
193 :
194 : //-----------------------------------------------------------------------------
195 : void
196 0 : MIBIONode::switch_sfp_soft_tx_control_bit(uint32_t sfp_id, bool turn_on) const { // NOLINT(build/unsigned)
197 0 : validate_sfp_id(sfp_id);
198 :
199 0 : auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
200 0 : i2c_switch->set_channels_states(1UL << sfp_id);
201 0 : auto sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(0), "SFP_EEProm");
202 0 : sfp->switch_soft_tx_control_bit(turn_on);
203 0 : i2c_switch->set_channels_states(8);
204 0 : }
205 : //-----------------------------------------------------------------------------
206 :
207 : //-----------------------------------------------------------------------------
208 : // void
209 : // MIBIONode::get_info(timinghardwareinfo::TimingMIBMonitorData& mon_data) const
210 : // {
211 :
212 : // auto subnodes = read_sub_nodes(getNode("csr.stat"));
213 :
214 : // mon_data.cdr_0_lol = subnodes.at("cdr_lol").value() & 0x1;
215 : // mon_data.cdr_1_lol = subnodes.at("cdr_lol").value() & 0x2;
216 :
217 : // mon_data.cdr_0_los = subnodes.at("cdr_los").value() & 0x1;
218 : // mon_data.cdr_1_los = subnodes.at("cdr_los").value() & 0x2;
219 :
220 : // mon_data.mmcm_ok = subnodes.at("mmcm_ok").value();
221 : // mon_data.mmcm_sticky = subnodes.at("mmcm_sticky").value();
222 :
223 : // mon_data.sfp_0_flt = subnodes.at("sfp_flt").value() & 0x1;
224 : // mon_data.sfp_1_flt = subnodes.at("sfp_flt").value() & 0x2;
225 :
226 : // mon_data.sfp_0_los = subnodes.at("sfp_los").value() & 0x1;
227 : // mon_data.sfp_1_los = subnodes.at("sfp_los").value() & 0x2;
228 :
229 : // // TODO 3rd SFP?
230 : // }
231 : // //-----------------------------------------------------------------------------
232 :
233 : // //-----------------------------------------------------------------------------
234 : // void
235 : // MIBIONode::get_info(opmonlib::InfoCollector& ci, int level) const
236 : // {
237 : // auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
238 :
239 : // if (level >= 2) {
240 : // i2c_switch->set_channels_states(8);
241 :
242 : // timinghardwareinfo::TimingPLLMonitorData pll_mon_data;
243 : // get_pll()->get_info(pll_mon_data);
244 : // ci.add(pll_mon_data);
245 :
246 : // for (uint i=0; i < 3; ++i)
247 : // {
248 : // opmonlib::InfoCollector sfp_ic;
249 :
250 : // // enable i2c path for sfp
251 : // i2c_switch->set_channels_states(1UL << i);
252 :
253 : // auto sfp = this->get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(0), "SFP_EEProm");
254 :
255 : // try
256 : // {
257 : // sfp->get_info(sfp_ic, level);
258 : // }
259 : // catch (timing::SFPUnreachable& e)
260 : // {
261 : // // It is valid that an SFP may not be installed, currently no good way of knowing whether they it should be
262 : // TLOG_DEBUG(2) << "Failed to communicate with SFP " << i << " on I2C switch channel " << (1UL << i) << " on i2c bus" << m_sfp_i2c_buses.at(0);
263 : // continue;
264 : // }
265 : // ci.add("sfp_"+std::to_string(i),sfp_ic);
266 : // }
267 : // i2c_switch->set_channels_states(8);
268 : // }
269 : // if (level >= 1) {
270 : // timinghardwareinfo::TimingMIBMonitorData mon_data;
271 : // this->get_info(mon_data);
272 : // ci.add(mon_data);
273 : // }
274 : // }
275 : //-----------------------------------------------------------------------------
276 :
277 : //-----------------------------------------------------------------------------
278 : void
279 0 : MIBIONode::validate_sfp_id(uint32_t sfp_id) const { // NOLINT(build/unsigned)
280 : // on this board we have 3 upstream SFPs
281 0 : if (sfp_id > 2) {
282 0 : throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
283 : }
284 0 : }
285 : //-----------------------------------------------------------------------------
286 :
287 : //-----------------------------------------------------------------------------
288 : void
289 0 : MIBIONode::validate_amc_slot(uint32_t amc_slot) const { // NOLINT(build/unsigned)
290 0 : if (amc_slot < 1 || amc_slot > 12) {
291 0 : throw InvalidAMCSlot(ERS_HERE, format_reg_value(amc_slot, 10));
292 : }
293 0 : }
294 : //-----------------------------------------------------------------------------
295 : } // namespace timing
296 : } // namespace dunedaq
|