Line data Source code
1 : /**
2 : * @file GIBIONode.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/GIBIONode.hpp"
10 : #include "timing/LM75Node.hpp"
11 :
12 : #include <string>
13 : #include <math.h>
14 :
15 : namespace dunedaq {
16 : namespace timing {
17 :
18 0 : UHAL_REGISTER_DERIVED_NODE(GIBIONode)
19 :
20 : //-----------------------------------------------------------------------------
21 0 : GIBIONode::GIBIONode(const uhal::Node& node)
22 0 : : IONode(node, "i2c", "i2c", { "PLL" }, { "PLL", "SFP CDR 0", "SFP CDR 1", "SFP CDR 2", "SFP CDR 3", "SFP CDR 4", "SFP CDR 5", "10 MHz" }, { "i2c", "i2c", "i2c", "i2c", "i2c", "i2c" })
23 : {
24 0 : }
25 : //-----------------------------------------------------------------------------
26 :
27 : //-----------------------------------------------------------------------------
28 0 : GIBIONode::GIBIONode(const uhal::Node& node,
29 : std::string uid_i2c_bus,
30 : std::string pll_i2c_bus,
31 : std::string pll_i2c_device,
32 : std::vector<std::string> clock_names,
33 0 : std::vector<std::string> sfp_i2c_buses)
34 0 : : IONode(node, uid_i2c_bus, pll_i2c_bus, pll_i2c_device, clock_names, sfp_i2c_buses)
35 : {
36 0 : }
37 : //-----------------------------------------------------------------------------
38 :
39 : //-----------------------------------------------------------------------------
40 0 : GIBIONode::~GIBIONode() {}
41 : //-----------------------------------------------------------------------------
42 :
43 : //-----------------------------------------------------------------------------
44 : std::string
45 0 : GIBIONode::get_uid_address_parameter_name() const
46 : {
47 0 : return "UID_PROM";
48 : }
49 : //-----------------------------------------------------------------------------
50 :
51 : //-----------------------------------------------------------------------------
52 : std::string
53 0 : GIBIONode::get_status(bool print_out) const
54 : {
55 0 : std::stringstream status;
56 :
57 0 : auto subnodes = read_sub_nodes(getNode("csr.stat"));
58 0 : status << format_reg_table(subnodes, "GIB IO state");
59 :
60 0 : auto subnodes_2 = read_sub_nodes(getNode("csr.ctrl"));
61 0 : status << format_reg_table(subnodes_2, "GIB IO control");
62 :
63 0 : uint8_t sfp_los = read_sfps_los();
64 0 : uint8_t sfp_fault = read_sfps_fault();
65 :
66 0 : std::vector<std::string> sfp_vec;
67 0 : std::vector<uint8_t> los_vec;
68 0 : std::vector<uint8_t> fault_vec;
69 :
70 0 : for (int i=0; i<get_num_sfps(); i++) {
71 0 : sfp_vec.push_back(to_string(i));
72 : // L is 0x4C, H is L - 4
73 0 : los_vec.push_back(0x4C - 4*((sfp_los >> i) & 1));
74 0 : fault_vec.push_back(0x4C - 4*((sfp_fault >> i) & 1));
75 : }
76 :
77 0 : status << "------IO expander----" << std::endl;
78 0 : status << "SFP: " << vec_fmt(sfp_vec) << std::endl;
79 0 : status << "LOS: " << vec_fmt(los_vec) << std::endl;
80 0 : status << "Fault: " << vec_fmt(fault_vec) << std::endl;
81 :
82 0 : status << "Board temperature: " << read_board_temperature() << " [C]" << std::endl;
83 :
84 0 : if (print_out)
85 0 : TLOG() << std::endl << status.str();
86 0 : return status.str();
87 0 : }
88 : //-----------------------------------------------------------------------------
89 :
90 : //-----------------------------------------------------------------------------
91 : std::unique_ptr<const SI534xSlave>
92 0 : GIBIONode::get_pll() const
93 : {
94 : // enable pll channel 0 only
95 0 : set_i2c_mux_channels(0x1);
96 0 : return get_i2c_device<SI534xSlave>(m_pll_i2c_bus, m_pll_i2c_device);
97 : }
98 : //-----------------------------------------------------------------------------
99 :
100 : //-----------------------------------------------------------------------------
101 : std::string
102 0 : GIBIONode::get_hardware_info(bool print_out) const
103 : {
104 : // enable pll/uid channel 0 only
105 0 : set_i2c_mux_channels(0x1);
106 0 : return IONode::get_hardware_info(print_out);
107 : }
108 : //-----------------------------------------------------------------------------
109 :
110 : //-----------------------------------------------------------------------------
111 : void
112 0 : GIBIONode::set_up_io_infrastructure() const
113 : {
114 : // enclustra i2c switch stuff
115 0 : CarrierType carrier_type = convert_value_to_carrier_type(read_carrier_type());
116 0 : if (carrier_type == kCarrierEnclustraA35) {
117 0 : try {
118 0 : getNode<I2CMasterNode>(m_uid_i2c_bus).get_slave("AX3_Switch").write_i2c(0x01, 0x7f);
119 0 : } catch (const std::exception& e) {
120 0 : ers::warning(EnclustraSwitchFailure(ERS_HERE, e));
121 0 : }
122 : }
123 :
124 : // Disable ICs
125 : //getNode("csr.ctrl.i2c_sw_rst").write(0x1);
126 : //getNode("csr.ctrl.i2c_exten_rst").write(0x1);
127 : //getNode("csr.ctrl.clk_gen_rst").write(0x1);
128 : //getClient().dispatch();
129 :
130 : // Enable ICs
131 0 : getNode("csr.ctrl.i2c_sw_rst").write(0x0);
132 0 : getNode("csr.ctrl.i2c_exten_rst").write(0x0);
133 0 : getNode("csr.ctrl.clk_gen_rst").write(0x0);
134 0 : getClient().dispatch();
135 :
136 0 : set_i2c_mux_channels(0x1);
137 0 : }
138 : //-----------------------------------------------------------------------------
139 :
140 : //-----------------------------------------------------------------------------
141 : void
142 0 : GIBIONode::reset(const std::string& clock_config_file) const
143 : {
144 : // Clear IPBus regs
145 0 : soft_reset();
146 :
147 : // In case this method is called directly, TODO refactor
148 0 : set_up_io_infrastructure();
149 :
150 0 : getNode("csr.ctrl.gps_clk_en").write(0x0);
151 :
152 : // Set filter to full bandwidth mode A = B = 0x0
153 0 : getNode("csr.ctrl.gps_clk_fltr_a").write(0x0);
154 0 : getNode("csr.ctrl.gps_clk_fltr_b").write(0x0);
155 0 : getClient().dispatch();
156 :
157 : // Upload config file to PLL
158 0 : configure_pll(clock_config_file);
159 :
160 0 : configure_expander();
161 :
162 : // reset dts logic
163 0 : getNode("csr.ctrl.rst").write(0x1);
164 0 : getClient().dispatch();
165 0 : getNode("csr.ctrl.rst").write(0x0);
166 0 : getClient().dispatch();
167 :
168 0 : TLOG() << "Reset done";
169 0 : }
170 : //-----------------------------------------------------------------------------
171 :
172 : //-----------------------------------------------------------------------------
173 : void
174 0 : GIBIONode::configure_expander() const
175 : {
176 0 : auto sfp_expander_0 = get_i2c_device<I2CExpanderSlave>(m_uid_i2c_bus, "SFPExpander0");
177 0 : auto sfp_expander_1 = get_i2c_device<I2CExpanderSlave>(m_uid_i2c_bus, "SFPExpander1");
178 :
179 : // Set invert registers to default for both (0,1) banks
180 0 : sfp_expander_0->set_inversion(0, 0x00);
181 0 : sfp_expander_0->set_inversion(1, 0x00);
182 0 : sfp_expander_1->set_inversion(0, 0x00);
183 0 : sfp_expander_1->set_inversion(1, 0x00);
184 :
185 : // 0: pin set as output, 1: pin set as input
186 0 : sfp_expander_0->set_io(0, 0xff); // set all pins of bank 0 as inputs
187 0 : sfp_expander_0->set_io(1, 0xff); // set all pins of bank 1 as inputs
188 :
189 0 : sfp_expander_1->set_io(0, 0xff); // set all pins of bank 0 as inputs
190 0 : sfp_expander_1->set_io(1, 0x00); // set all pins of bank 1 as outputs
191 :
192 : // Set SFP disable
193 : // Set tx disable pins low, i.e. enable the pins given in the bitmap
194 : // (different between v1 and v2/3)
195 0 : sfp_expander_1->set_outputs(1, get_sfp_tx_disable_bitmap());
196 0 : }
197 : //-----------------------------------------------------------------------------
198 :
199 : //-----------------------------------------------------------------------------
200 : void
201 0 : GIBIONode::reset_pll() const
202 : {
203 0 : getNode("csr.ctrl.clk_gen_rst").write(0x1);
204 0 : getNode("csr.ctrl.clk_gen_rst").write(0x0);
205 0 : }
206 : //-----------------------------------------------------------------------------
207 :
208 : //-----------------------------------------------------------------------------
209 : std::string
210 0 : GIBIONode::get_sfp_status(uint32_t sfp_id, bool print_out) const { // NOLINT(build/unsigned)
211 0 : std::stringstream status;
212 :
213 0 : validate_sfp_id(sfp_id);
214 :
215 0 : uint8_t i2c_mux_bitmask = 1UL << (sfp_id+1);
216 :
217 0 : set_i2c_mux_channels(i2c_mux_bitmask);
218 :
219 0 : auto sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(sfp_id), "SFP_EEProm");
220 :
221 0 : status << "SFP " << sfp_id << ":" << std::endl;
222 0 : status << sfp->get_status();
223 :
224 0 : if (print_out)
225 0 : TLOG() << status.str();
226 :
227 0 : return status.str();
228 0 : }
229 : //-----------------------------------------------------------------------------
230 :
231 : //-----------------------------------------------------------------------------
232 : uint32_t
233 0 : GIBIONode::read_io_expanders() const { // NOLINT(build/unsigned)
234 0 : auto sfp_expander_0 = get_i2c_device<I2CExpanderSlave>(m_uid_i2c_bus, "SFPExpander0");
235 0 : auto sfp_expander_1 = get_i2c_device<I2CExpanderSlave>(m_uid_i2c_bus, "SFPExpander1");
236 :
237 0 : uint32_t expander_bits = sfp_expander_1->read_inputs(0);
238 0 : expander_bits = (expander_bits << 8) + sfp_expander_0->read_inputs(1);
239 0 : expander_bits = (expander_bits << 8) + sfp_expander_0->read_inputs(0);
240 :
241 0 : return expander_bits;
242 0 : }
243 : //-----------------------------------------------------------------------------
244 :
245 : //-----------------------------------------------------------------------------
246 : uint8_t
247 0 : GIBIONode::read_sfps_los() const { // NOLINT(build/unsigned)
248 0 : uint32_t expander_bits = read_io_expanders();
249 :
250 0 : uint8_t los_bits = 0x00;
251 :
252 0 : for (uint8_t sfp = 0; sfp<6; sfp++) {
253 : // Each SFP has 4 bits, the 3rd bit is the LOS
254 : // Adds the SFPs in inverse order
255 0 : los_bits = (los_bits << 1) + ((expander_bits >> (2 + 20 - 4*sfp)) & 1);
256 : }
257 :
258 0 : return los_bits;
259 : }
260 : //-----------------------------------------------------------------------------
261 :
262 : //-----------------------------------------------------------------------------
263 : uint8_t
264 0 : GIBIONode::read_sfps_fault() const { // NOLINT(build/unsigned)
265 0 : uint32_t expander_bits = read_io_expanders();
266 :
267 0 : uint8_t fault_bits = 0x00;
268 :
269 0 : for (uint8_t sfp = 0; sfp<6; sfp++) {
270 : // Each SFP has 4 bits, the 4th bit is the fault
271 : // Adds the SFPs in inverse order
272 0 : fault_bits = (fault_bits << 1) + ((expander_bits >> (3 + 20 - 4*sfp)) & 1);
273 : }
274 :
275 0 : return fault_bits;
276 : }
277 : //-----------------------------------------------------------------------------
278 :
279 : //-----------------------------------------------------------------------------
280 : bool
281 0 : GIBIONode::clocks_ok() const
282 : {
283 0 : std::stringstream status;
284 :
285 0 : auto states = read_sub_nodes(getNode("csr.stat"));
286 0 : bool pll_lol = states.find("clk_gen_lol")->second.value();
287 0 : bool pll_interrupt = states.find("clk_gen_intr")->second.value();
288 0 : bool mmcm_ok = states.find("mmcm_ok")->second.value();
289 0 : bool mmcm_10_ok = states.find("mmcm_ok")->second.value();
290 :
291 0 : TLOG_DEBUG(5) << "pll lol: " << pll_lol << ", pll intr: " << pll_interrupt
292 0 : << ", mmcm ok: " << mmcm_ok << ", mmcm 10MHz ok: " << mmcm_10_ok;
293 :
294 0 : return !pll_lol && mmcm_ok && mmcm_10_ok;
295 0 : }
296 : //-----------------------------------------------------------------------------
297 :
298 : //-----------------------------------------------------------------------------
299 : void
300 0 : GIBIONode::switch_sfp_soft_tx_control_bit(uint32_t sfp_id, bool turn_on) const { // NOLINT(build/unsigned)
301 0 : validate_sfp_id(sfp_id);
302 :
303 0 : auto sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(sfp_id), "SFP_EEProm");
304 0 : sfp->switch_soft_tx_control_bit(turn_on);
305 0 : }
306 : //-----------------------------------------------------------------------------
307 :
308 : //-----------------------------------------------------------------------------
309 : void
310 0 : GIBIONode::switch_sfp_tx(uint32_t sfp_id, bool turn_on) const { // NOLINT(build/unsigned)
311 0 : validate_sfp_id(sfp_id);
312 :
313 0 : auto sfp_expander_1 = get_i2c_device<I2CExpanderSlave>(m_uid_i2c_bus, "SFPExpander1");
314 0 : uint8_t current_sfp_tx_control_flags = sfp_expander_1->read_outputs_config(1); // NOLINT(build/unsigned)
315 :
316 0 : uint8_t new_sfp_tx_control_flags; // NOLINT(build/unsigned)
317 0 : if (turn_on)
318 : {
319 0 : new_sfp_tx_control_flags = current_sfp_tx_control_flags & ~(1UL << sfp_id);
320 : }
321 : else
322 : {
323 0 : new_sfp_tx_control_flags = current_sfp_tx_control_flags | (1UL << sfp_id);
324 : }
325 :
326 0 : sfp_expander_1->set_outputs(1, new_sfp_tx_control_flags);
327 0 : }
328 : //-----------------------------------------------------------------------------
329 :
330 : //-----------------------------------------------------------------------------
331 : //void
332 : //GIBIONode::get_info(timinghardwareinfo::TimingGIBMonitorData& mon_data) const
333 : //{
334 : // TODO
335 : //}
336 : //-----------------------------------------------------------------------------
337 :
338 : //-----------------------------------------------------------------------------
339 : // void
340 : // GIBIONode::get_info(opmonlib::InfoCollector& /*ci*/, int /*level*/) const
341 : // {
342 : // // TO DO
343 : // }
344 : //-----------------------------------------------------------------------------
345 :
346 : //-----------------------------------------------------------------------------
347 : uint8_t
348 0 : GIBIONode::get_sfp_tx_disable_bitmap() const { // NOLINT(build/unsigned)
349 : // First 6 bits are tx disable on GIBv1
350 0 : return 0xC0;
351 : }
352 : //-----------------------------------------------------------------------------
353 :
354 : //-----------------------------------------------------------------------------
355 : uint8_t
356 0 : GIBIONode::get_num_sfps() const { // NOLINT(build/unsigned)
357 : // 6 SFPs on GIBv1
358 0 : return 6;
359 : }
360 : //-----------------------------------------------------------------------------
361 :
362 : //-----------------------------------------------------------------------------
363 : void
364 0 : GIBIONode::validate_sfp_id(uint32_t sfp_id) const { // NOLINT(build/unsigned)
365 : // number of sfps on board defined by get_num_sfps
366 0 : if (sfp_id >= get_num_sfps()) {
367 0 : throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
368 : }
369 0 : }
370 : //-----------------------------------------------------------------------------
371 :
372 : //-----------------------------------------------------------------------------
373 : void
374 0 : GIBIONode::set_i2c_mux_channels(uint8_t mux_channel_bitmask) const { // NOLINT(build/unsigned)
375 :
376 0 : uint8_t mux_channel_config = mux_channel_bitmask & 0x7f;
377 :
378 0 : auto i2c_bus = getNode<I2CMasterNode>("i2c");
379 0 : i2c_bus.write_i2cPrimitive(0x70, {mux_channel_config});
380 0 : }
381 : //-----------------------------------------------------------------------------
382 :
383 : //-----------------------------------------------------------------------------
384 : float
385 0 : GIBIONode::read_board_temperature() const
386 : {
387 0 : auto temp_mon = get_i2c_device<LM75Node>(m_pll_i2c_bus, "TEMP_MON");
388 0 : return temp_mon->read_temperature();
389 0 : }
390 : //-----------------------------------------------------------------------------
391 : } // namespace timing
392 : } // namespace dunedaq
|