115527a43SZane Shelley 
215527a43SZane Shelley #include <analyzer/plugins/plugin.hpp>
32c228cdcSZane Shelley #include <hei_util.hpp>
42c228cdcSZane Shelley #include <util/pdbg.hpp>
515527a43SZane Shelley #include <util/trace.hpp>
615527a43SZane Shelley 
715527a43SZane Shelley namespace analyzer
815527a43SZane Shelley {
915527a43SZane Shelley 
1015527a43SZane Shelley namespace P10
1115527a43SZane Shelley {
1215527a43SZane Shelley 
1315527a43SZane Shelley /**
1415527a43SZane Shelley  * @brief Adds all clocks/chips reporting PLL unlock attentions to the callout
1515527a43SZane Shelley  *        list.
1615527a43SZane Shelley  *
1715527a43SZane Shelley  *  Processors are always called out at medium priority and never guarded. If
1815527a43SZane Shelley  *  more than one processor is reporting a PLL unlock attention on the same
1915527a43SZane Shelley  *  clock, the clock is called out with high priority. Otherwise, the clock
2015527a43SZane Shelley  *  callout priority is medium.
2115527a43SZane Shelley  */
pll_unlock(unsigned int i_instance,const libhei::Chip &,ServiceData & io_servData)222c228cdcSZane Shelley void pll_unlock(unsigned int i_instance, const libhei::Chip&,
232c228cdcSZane Shelley                 ServiceData& io_servData)
2415527a43SZane Shelley {
252c228cdcSZane Shelley     auto nodeId = libhei::hash<libhei::NodeId_t>("PLL_UNLOCK");
262c228cdcSZane Shelley 
272c228cdcSZane Shelley     auto sigList = io_servData.getIsolationData().getSignatureList();
282c228cdcSZane Shelley 
292c228cdcSZane Shelley     // The PLL list is initially the same size of the signature list.
302c228cdcSZane Shelley     std::vector<libhei::Signature> pllList{sigList.size()};
312c228cdcSZane Shelley 
322c228cdcSZane Shelley     // Copy all signatures that match the node ID and bit position. Note that
332c228cdcSZane Shelley     // in this case the bit position is the same as the plugin instance.
342c228cdcSZane Shelley     auto itr = std::copy_if(sigList.begin(), sigList.end(), pllList.begin(),
352c228cdcSZane Shelley                             [&nodeId, &i_instance](const auto& s) {
36*27dd6368SPatrick Williams         return (nodeId == s.getId() && i_instance == s.getBit());
372c228cdcSZane Shelley     });
382c228cdcSZane Shelley 
392c228cdcSZane Shelley     // Shrink the size of the PLL list if necessary.
402c228cdcSZane Shelley     pllList.resize(std::distance(pllList.begin(), itr));
412c228cdcSZane Shelley 
422c228cdcSZane Shelley     // The clock callout priority is dependent on the number of chips with PLL
432c228cdcSZane Shelley     // unlock attentions.
44*27dd6368SPatrick Williams     auto clockPriority = (1 < pllList.size()) ? callout::Priority::HIGH
45*27dd6368SPatrick Williams                                               : callout::Priority::MED;
462c228cdcSZane Shelley 
472c228cdcSZane Shelley     // Callout the clock.
482c228cdcSZane Shelley     auto clockCallout = (0 == i_instance) ? callout::ClockType::OSC_REF_CLOCK_0
492c228cdcSZane Shelley                                           : callout::ClockType::OSC_REF_CLOCK_1;
502c228cdcSZane Shelley     io_servData.calloutClock(clockCallout, clockPriority, true);
512c228cdcSZane Shelley 
522c228cdcSZane Shelley     // Callout the processors connected to this clock that are reporting PLL
532c228cdcSZane Shelley     // unlock attentions. Always a medium callout and no guarding.
542c228cdcSZane Shelley     for (const auto& sig : pllList)
552c228cdcSZane Shelley     {
562c228cdcSZane Shelley         io_servData.calloutTarget(util::pdbg::getTrgt(sig.getChip()),
572c228cdcSZane Shelley                                   callout::Priority::MED, false);
582c228cdcSZane Shelley     }
5915527a43SZane Shelley }
6015527a43SZane Shelley 
lpc_timeout_callout(const libhei::Chip & i_chip,ServiceData & io_servData)61513f64aaSZane Shelley void lpc_timeout_callout(const libhei::Chip& i_chip, ServiceData& io_servData)
62e90b85dcSZane Shelley {
63e90b85dcSZane Shelley     auto target = util::pdbg::getTrgt(i_chip);
64e90b85dcSZane Shelley     auto path = util::pdbg::getPath(target);
65e90b85dcSZane Shelley 
66e90b85dcSZane Shelley     // Callout the PNOR.
67513f64aaSZane Shelley     io_servData.calloutPart(callout::PartType::PNOR, callout::Priority::MED);
68e90b85dcSZane Shelley 
69e90b85dcSZane Shelley     // Callout the associated clock, no guard.
70e90b85dcSZane Shelley     auto chipPos = util::pdbg::getChipPos(target);
71e90b85dcSZane Shelley     if (0 == chipPos)
72e90b85dcSZane Shelley     {
73e90b85dcSZane Shelley         // Clock 0 is hardwired to proc 0.
74e90b85dcSZane Shelley         io_servData.calloutClock(callout::ClockType::OSC_REF_CLOCK_0,
75e90b85dcSZane Shelley                                  callout::Priority::MED, false);
76e90b85dcSZane Shelley     }
77e90b85dcSZane Shelley     else if (1 == chipPos)
78e90b85dcSZane Shelley     {
79e90b85dcSZane Shelley         // Clock 1 is hardwired to proc 1.
80e90b85dcSZane Shelley         io_servData.calloutClock(callout::ClockType::OSC_REF_CLOCK_1,
81e90b85dcSZane Shelley                                  callout::Priority::MED, false);
82e90b85dcSZane Shelley     }
83e90b85dcSZane Shelley     else
84e90b85dcSZane Shelley     {
85e90b85dcSZane Shelley         trace::err("LPC timeout on unexpected processor: %s", path);
86e90b85dcSZane Shelley     }
87e90b85dcSZane Shelley 
88e90b85dcSZane Shelley     // Callout the processor, no guard.
89e90b85dcSZane Shelley     io_servData.calloutTarget(target, callout::Priority::MED, false);
90e90b85dcSZane Shelley }
91513f64aaSZane Shelley 
92513f64aaSZane Shelley /**
93513f64aaSZane Shelley  * @brief Queries for an LPC timeout. If present, will callout all appropriate
94513f64aaSZane Shelley  *        hardware.
95513f64aaSZane Shelley  */
lpc_timeout(unsigned int,const libhei::Chip & i_chip,ServiceData & io_servData)96513f64aaSZane Shelley void lpc_timeout(unsigned int, const libhei::Chip& i_chip,
97513f64aaSZane Shelley                  ServiceData& io_servData)
98513f64aaSZane Shelley {
99513f64aaSZane Shelley     auto target = util::pdbg::getTrgt(i_chip);
100513f64aaSZane Shelley     auto path = util::pdbg::getPath(target);
101513f64aaSZane Shelley 
102513f64aaSZane Shelley     if (util::pdbg::queryLpcTimeout(target))
103513f64aaSZane Shelley     {
104513f64aaSZane Shelley         trace::inf("LPC timeout detected on %s", path);
105513f64aaSZane Shelley 
106513f64aaSZane Shelley         lpc_timeout_callout(i_chip, io_servData);
107513f64aaSZane Shelley     }
108e90b85dcSZane Shelley     else
109e90b85dcSZane Shelley     {
110e90b85dcSZane Shelley         trace::inf("No LPC timeout detected on %s", path);
111e90b85dcSZane Shelley 
112e90b85dcSZane Shelley         io_servData.calloutProcedure(callout::Procedure::NEXTLVL,
113e90b85dcSZane Shelley                                      callout::Priority::HIGH);
114e90b85dcSZane Shelley     }
115e90b85dcSZane Shelley }
116e90b85dcSZane Shelley 
117513f64aaSZane Shelley /**
118513f64aaSZane Shelley  * @brief If Hostboot detects an LPC timeout, it will manually trigger a
119513f64aaSZane Shelley  *        checkstop attention. We will have to bypass checking for an LPC
120513f64aaSZane Shelley  *        timeout via the HWP because it will not find the timeout. Instead,
121513f64aaSZane Shelley  *        simply make the callout when Hostboot triggers the attention.
122513f64aaSZane Shelley  */
lpc_timeout_workaround(unsigned int,const libhei::Chip & i_chip,ServiceData & io_servData)123513f64aaSZane Shelley void lpc_timeout_workaround(unsigned int, const libhei::Chip& i_chip,
124513f64aaSZane Shelley                             ServiceData& io_servData)
125513f64aaSZane Shelley {
126513f64aaSZane Shelley     trace::inf("Host detected LPC timeout %s", util::pdbg::getPath(i_chip));
127513f64aaSZane Shelley 
128513f64aaSZane Shelley     lpc_timeout_callout(i_chip, io_servData);
129513f64aaSZane Shelley }
130513f64aaSZane Shelley 
13151f8202cSCaleb Palmer /**
13251f8202cSCaleb Palmer  * @brief Calls out all DIMMs attached to an OCMB.
13351f8202cSCaleb Palmer  */
callout_attached_dimms(unsigned int i_instance,const libhei::Chip & i_chip,ServiceData & io_servData)13451f8202cSCaleb Palmer void callout_attached_dimms(unsigned int i_instance, const libhei::Chip& i_chip,
13551f8202cSCaleb Palmer                             ServiceData& io_servData)
13651f8202cSCaleb Palmer {
13751f8202cSCaleb Palmer     // Get the OMI target for this instance
13851f8202cSCaleb Palmer     auto procTarget = util::pdbg::getTrgt(i_chip);
139*27dd6368SPatrick Williams     auto omiTarget = util::pdbg::getChipUnit(procTarget, util::pdbg::TYPE_OMI,
140*27dd6368SPatrick Williams                                              i_instance);
14151f8202cSCaleb Palmer 
14251f8202cSCaleb Palmer     if (nullptr != omiTarget)
14351f8202cSCaleb Palmer     {
14451f8202cSCaleb Palmer         // Get the connected OCMB from the OMI
14551f8202cSCaleb Palmer         auto ocmbTarget = util::pdbg::getConnectedTarget(
14651f8202cSCaleb Palmer             omiTarget, callout::BusType::OMI_BUS);
14751f8202cSCaleb Palmer 
14851f8202cSCaleb Palmer         // Loop through all DIMMs connected to the OCMB
14951f8202cSCaleb Palmer         pdbg_target* dimmTarget = nullptr;
15051f8202cSCaleb Palmer         pdbg_for_each_target("dimm", ocmbTarget, dimmTarget)
15151f8202cSCaleb Palmer         {
15251f8202cSCaleb Palmer             if (nullptr != dimmTarget)
15351f8202cSCaleb Palmer             {
15451f8202cSCaleb Palmer                 // Call out the DIMM, medium priority and guard
15551f8202cSCaleb Palmer                 io_servData.calloutTarget(dimmTarget, callout::Priority::MED,
15651f8202cSCaleb Palmer                                           true);
15751f8202cSCaleb Palmer             }
15851f8202cSCaleb Palmer         }
15951f8202cSCaleb Palmer     }
16051f8202cSCaleb Palmer }
16151f8202cSCaleb Palmer 
16215527a43SZane Shelley } // namespace P10
16315527a43SZane Shelley 
16415527a43SZane Shelley PLUGIN_DEFINE_NS(P10_10, P10, pll_unlock);
16515527a43SZane Shelley PLUGIN_DEFINE_NS(P10_20, P10, pll_unlock);
16615527a43SZane Shelley 
167e90b85dcSZane Shelley PLUGIN_DEFINE_NS(P10_10, P10, lpc_timeout);
168e90b85dcSZane Shelley PLUGIN_DEFINE_NS(P10_20, P10, lpc_timeout);
169e90b85dcSZane Shelley 
170513f64aaSZane Shelley PLUGIN_DEFINE_NS(P10_10, P10, lpc_timeout_workaround);
171513f64aaSZane Shelley PLUGIN_DEFINE_NS(P10_20, P10, lpc_timeout_workaround);
172513f64aaSZane Shelley 
17351f8202cSCaleb Palmer PLUGIN_DEFINE_NS(P10_10, P10, callout_attached_dimms);
17451f8202cSCaleb Palmer PLUGIN_DEFINE_NS(P10_20, P10, callout_attached_dimms);
17551f8202cSCaleb Palmer 
17615527a43SZane Shelley } // namespace analyzer
177