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