blob: 1afdcf55b97494669aacc38313483fcdba9f2321 [file] [log] [blame]
Jayanth Othayothed7fb7a2022-09-09 00:07:41 -05001/**
2 * Copyright © 2022 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "extensions/phal/clock_logger.hpp"
18
19#include "util.hpp"
20
21#include <attributes_info.H>
22#include <libphal.H>
23
24#include <phosphor-logging/lg2.hpp>
25#include <sdeventplus/event.hpp>
26#include <sdeventplus/utility/timer.hpp>
27
28#include <chrono>
29
30using namespace openpower::pel;
31
32PHOSPHOR_LOG2_USING;
33
34namespace openpower::phal::clock
35{
36constexpr auto CLOCK_DAILY_LOGGER_TIMEOUT_IN_HOUR = 24;
37
38Manager::Manager(const sdeventplus::Event& event) :
39 _event(event), timer(event, std::bind(&Manager::timerExpired, this))
40
41{
42 try
43 {
44 // pdbg initialisation
45 openpower::phal::pdbg::init();
46
47 // Create clock data log.
48 createClockDataLog();
49 }
50 catch (const std::exception& e)
51 {
52 error("Clock Data Log exception ({ERROR})", "ERROR", e);
53 }
54
55 addTimer();
56}
57
58void Manager::addTimer()
59{
60 // Set timer for 24 hours.
61 timer.restart(std::chrono::hours(CLOCK_DAILY_LOGGER_TIMEOUT_IN_HOUR));
62}
63
64void Manager::timerExpired()
65{
66 info("Clock daily logging started");
67
68 try
69 {
70 // Create clock data log.
71 createClockDataLog();
72 }
73 catch (const std::exception& e)
74 {
75 error("createClockDataLog exception ({ERROR})", "ERROR", e);
76 }
77}
78
79void Manager::createClockDataLog()
80{
81 // check chassis power state.
82 auto powerState = openpower::util::getChassisPowerState();
83
84 if (powerState != "xyz.openbmc_project.State.Chassis.PowerState.On")
85 {
86 warning("The chassis power state({POWERSTATE}) is not ON, Skipping "
87 "clock data "
88 "logging",
89 "POWERSTATE", powerState);
90 return;
91 }
92
93 // Data logger storage
94 FFDCData clockDataLog;
95
96 struct pdbg_target* procTarget;
97 ATTR_HWAS_STATE_Type hwasState;
98 pdbg_for_each_class_target("proc", procTarget)
99 {
100 if (DT_GET_PROP(ATTR_HWAS_STATE, procTarget, hwasState))
101 {
102 error("{TARGET} Could not read HWAS_STATE attribute", "TARGET",
103 pdbg_target_path(procTarget));
104 continue;
105 }
106 if (!hwasState.present)
107 {
108 continue;
109 }
110
111 auto index = std::to_string(pdbg_target_index(procTarget));
112
113 // update functional State
114 std::string funState = "Non Functional";
115
116 if (hwasState.functional)
117 {
118 funState = "Functional";
119 }
120 std::stringstream ssState;
121 ssState << "Proc" << index;
122 clockDataLog.push_back(std::make_pair(ssState.str(), funState));
123
124 // update location code information
125 ATTR_LOCATION_CODE_Type locationCode;
126 memset(&locationCode, '\0', sizeof(locationCode));
127 try
128 {
129 openpower::phal::pdbg::getLocationCode(procTarget, locationCode);
130 }
131 catch (const std::exception& e)
132 {
133 error("getLocationCode on {TARGET} thrown exception ({ERROR})",
134 "TARGET", pdbg_target_path(procTarget), "ERROR", e);
135 }
136 std::stringstream ssLoc;
137 ssLoc << "Proc" << index << " Location Code";
138 clockDataLog.push_back(std::make_pair(ssLoc.str(), locationCode));
139
140 // Update Processor EC level
141 ATTR_EC_Type ecVal = 0;
142 if (DT_GET_PROP(ATTR_EC, procTarget, ecVal))
143 {
144 error("Could not read ATTR_EC attribute");
145 }
146 std::stringstream ssEC;
147 ssEC << "Proc" << index << " EC";
148
149 std::stringstream ssECVal;
150 ssECVal << "0x" << std::setfill('0') << std::setw(10) << std::hex
151 << (uint16_t)ecVal;
152 clockDataLog.push_back(std::make_pair(ssEC.str(), ssECVal.str()));
Jayanth Othayoth91bf93e2022-09-09 04:30:17 -0500153
154 // Add CFAM register information.
155 addCFAMData(procTarget, clockDataLog);
Jayanth Othayothed7fb7a2022-09-09 00:07:41 -0500156 }
157
Jayanth Othayoth5ffe7fb2022-09-09 06:39:58 -0500158 // Add clock register information
159 addClockRegData(clockDataLog);
160
Jayanth Othayothed7fb7a2022-09-09 00:07:41 -0500161 openpower::pel::createPEL("org.open_power.PHAL.Info.ClockDailyLog",
Matt Spinlerbe14ec22023-03-24 15:59:48 -0500162 clockDataLog, Severity::Informational);
Jayanth Othayothed7fb7a2022-09-09 00:07:41 -0500163}
164
Jayanth Othayoth91bf93e2022-09-09 04:30:17 -0500165void Manager::addCFAMData(struct pdbg_target* proc,
166 openpower::pel::FFDCData& clockDataLog)
167{
Jayanth Othayoth91bf93e2022-09-09 04:30:17 -0500168 // collect Processor CFAM register data
169 const std::vector<int> procCFAMAddr = {
170 0x1007, 0x2804, 0x2810, 0x2813, 0x2814, 0x2815, 0x2816, 0x281D, 0x281E};
171
172 auto index = std::to_string(pdbg_target_index(proc));
173
174 for (int addr : procCFAMAddr)
175 {
176 auto val = 0xDEADBEEF;
177 try
178 {
179 val = openpower::phal::pdbg::getCFAM(proc, addr);
180 }
181 catch (const std::exception& e)
182 {
183 error("getCFAM on {TARGET} thrown exception({ERROR}): Addr ({REG})",
184 "TARGET", pdbg_target_path(proc), "ERROR", e, "REG", addr);
185 }
186 std::stringstream ssData;
187 ssData << "0x" << std::setfill('0') << std::setw(8) << std::hex << val;
188 std::stringstream ssAddr;
189 ssAddr << "Proc" << index << " REG 0x" << std::hex << addr;
190 // update the data
191 clockDataLog.push_back(make_pair(ssAddr.str(), ssData.str()));
192 }
193}
194
Jayanth Othayoth5ffe7fb2022-09-09 06:39:58 -0500195void Manager::addClockRegData(openpower::pel::FFDCData& clockDataLog)
196{
197 info("Adding clock register information to daily logger");
198
199 struct pdbg_target* clockTarget;
200 pdbg_for_each_class_target("oscrefclk", clockTarget)
201 {
202 ATTR_HWAS_STATE_Type hwasState;
203 if (DT_GET_PROP(ATTR_HWAS_STATE, clockTarget, hwasState))
204 {
205 error("({TARGET}) Could not read HWAS_STATE attribute", "TARGET",
206 pdbg_target_path(clockTarget));
207 continue;
208 }
209
210 if (!hwasState.present)
211 {
212 continue;
213 }
214
215 std::string funState = "Non Functional";
216
217 if (hwasState.functional)
218 {
219 funState = "Functional";
220 }
221
222 auto index = std::to_string(pdbg_target_index(clockTarget));
223
224 std::stringstream ssState;
225 ssState << "Clock" << index;
226 clockDataLog.push_back(std::make_pair(ssState.str(), funState));
227
228 // Add clcok device path information
229 std::stringstream ssName;
230 ssName << "Clock" << index << " path";
231 clockDataLog.push_back(
232 std::make_pair(ssName.str(), pdbg_target_path(clockTarget)));
233
234 auto status = pdbg_target_probe(clockTarget);
235 if (status != PDBG_TARGET_ENABLED)
236 {
237 continue;
238 }
239
240 // Update Buffer with clock I2C register data.
241 auto constexpr I2C_READ_SIZE = 0x08;
242 auto constexpr I2C_ADDR_MAX = 0xFF;
243
244 for (auto addr = 0; addr <= I2C_ADDR_MAX; addr += I2C_READ_SIZE)
245 {
246 std::stringstream ssData;
247
248 uint8_t data[0x8];
249 auto i2cRc = i2c_read(clockTarget, 0, addr, I2C_READ_SIZE, data);
250 if (i2cRc)
251 {
252 error("({TARGET}) I2C read error({ERROR}) reported {ADDRESS} ",
253 "TARGET", pdbg_target_path(clockTarget), "ERROR", i2cRc,
254 "ADDRESS", addr);
255 continue;
256 }
257
258 for (auto i = 0; i < I2C_READ_SIZE; i++)
259 {
260 ssData << " " << std::hex << std::setfill('0') << std::setw(2)
261 << (uint16_t)data[i];
262 }
263 std::stringstream ssAddr;
264 ssAddr << "Clock" << index << "_0x" << std::hex << std::setfill('0')
265 << std::setw(2) << addr;
266 clockDataLog.push_back(make_pair(ssAddr.str(), ssData.str()));
267 }
268 }
269}
270
Jayanth Othayothed7fb7a2022-09-09 00:07:41 -0500271} // namespace openpower::phal::clock