blob: ce6661ab781bec5e79c74f1b4102892416daf539 [file] [log] [blame]
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001/*
2// Copyright (c) 2019 Intel 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#include <errno.h>
17#include <fcntl.h>
18#include <peci.h>
Anna Platash03d7dae2021-02-05 13:52:05 +010019#include <stdlib.h>
Jason M. Bills7ef5a552020-04-06 14:58:44 -070020#include <string.h>
21#include <sys/ioctl.h>
22#include <syslog.h>
23#include <time.h>
24#include <unistd.h>
Jason M. Billsa2ceec22020-05-05 13:16:00 -070025#pragma GCC diagnostic push
26#pragma GCC diagnostic ignored "-Wcpp"
27#pragma GCC diagnostic ignored "-Wvariadic-macros"
28#include <linux/peci-ioctl.h>
29#pragma GCC diagnostic pop
Jason M. Bills7ef5a552020-04-06 14:58:44 -070030
31EPECIStatus peci_GetDIB_seq(uint8_t target, uint64_t* dib, int peci_fd);
32
Anna Platash03d7dae2021-02-05 13:52:05 +010033char* peci_device_list[2];
34#define DEV_NAME_SIZE 64
35/*-------------------------------------------------------------------------
Manojkiran Eda5302b932024-06-17 11:03:46 +053036 * This function sets the name of the PECI device file to use.
Anna Platash03d7dae2021-02-05 13:52:05 +010037 * If the PECI device name is null try "/dev/peci-default",
38 * if "/dev/peci-default" does not exist, fall back to "/dev/peci-0"
39 *------------------------------------------------------------------------*/
40void peci_SetDevName(char* peci_dev)
41{
Nirav Shahfd5dfd52022-03-09 12:29:41 -080042 static char peci_name_new[DEV_NAME_SIZE] = {0};
Anna Platash03d7dae2021-02-05 13:52:05 +010043
44 if (peci_dev)
45 {
46 strncpy(peci_name_new, peci_dev, sizeof(peci_name_new));
47 peci_name_new[DEV_NAME_SIZE - 1] = '\0';
48 peci_device_list[0] = peci_name_new;
49 peci_device_list[1] = NULL;
50 syslog(LOG_INFO, "PECI set dev name to %s\n", peci_device_list[0]);
51 }
52 else
53 {
54 peci_device_list[0] = "/dev/peci-default";
55 peci_device_list[1] = "/dev/peci-0";
56 syslog(LOG_INFO, "PECI set dev names to %s, %s\n", peci_device_list[0],
57 peci_device_list[1]);
58 }
59}
60
61/*-------------------------------------------------------------------------
62 * This function initializes PECI device name when a shared library
63 * is loaded, typically during program startup.
64 *------------------------------------------------------------------------*/
65static void init() __attribute__((constructor));
66static void init()
67{
68 // By default PECI_DEV is not defined in the environment,
69 // so this will call peci_SetDevName(NULL) and initialize
70 // PECI device name to defaults.
71 peci_SetDevName(getenv("PECI_DEV"));
72}
73
Jason M. Bills7ef5a552020-04-06 14:58:44 -070074/*-------------------------------------------------------------------------
75 * This function unlocks the peci interface
76 *------------------------------------------------------------------------*/
77void peci_Unlock(int peci_fd)
78{
79 if (close(peci_fd) != 0)
80 {
81 syslog(LOG_ERR, "PECI device failed to unlock.\n");
82 }
83}
84
Jason M. Bills7ef5a552020-04-06 14:58:44 -070085/*-------------------------------------------------------------------------
86 * This function attempts to lock the peci interface with the specified
87 * timeout and returns a file descriptor if successful.
88 *------------------------------------------------------------------------*/
89EPECIStatus peci_Lock(int* peci_fd, int timeout_ms)
90{
Nirav Shahfd5dfd52022-03-09 12:29:41 -080091 struct timespec sRequest = {0};
Jason M. Bills7ef5a552020-04-06 14:58:44 -070092 sRequest.tv_sec = 0;
93 sRequest.tv_nsec = PECI_TIMEOUT_RESOLUTION_MS * 1000 * 1000;
94 int timeout_count = 0;
Anna Platash03d7dae2021-02-05 13:52:05 +010095 char* peci_device = peci_device_list[0];
Jason M. Bills7ef5a552020-04-06 14:58:44 -070096
97 if (NULL == peci_fd)
98 {
99 return PECI_CC_INVALID_REQ;
100 }
101
102 // Open the PECI driver with the specified timeout
Anna Platash03d7dae2021-02-05 13:52:05 +0100103 *peci_fd = open(peci_device, O_RDWR | O_CLOEXEC);
104 if (*peci_fd == -1 && errno == ENOENT && peci_device_list[1])
105 {
106 peci_device = peci_device_list[1];
107 *peci_fd = open(peci_device, O_RDWR | O_CLOEXEC);
108 }
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700109 switch (timeout_ms)
110 {
111 case PECI_NO_WAIT:
112 break;
113 case PECI_WAIT_FOREVER:
114 while (-1 == *peci_fd)
115 {
116 nanosleep(&sRequest, NULL);
Anna Platash03d7dae2021-02-05 13:52:05 +0100117 *peci_fd = open(peci_device, O_RDWR | O_CLOEXEC);
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700118 }
V-Sanjana258161b2023-01-18 20:56:30 +0530119 break;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700120 default:
121 while (-1 == *peci_fd && timeout_count < timeout_ms)
122 {
123 nanosleep(&sRequest, NULL);
124 timeout_count += PECI_TIMEOUT_RESOLUTION_MS;
Anna Platash03d7dae2021-02-05 13:52:05 +0100125 *peci_fd = open(peci_device, O_RDWR | O_CLOEXEC);
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700126 }
127 }
128 if (-1 == *peci_fd)
129 {
130 syslog(LOG_ERR, " >>> PECI Device Busy <<< \n");
131 return PECI_CC_DRIVER_ERR;
132 }
133 return PECI_CC_SUCCESS;
134}
135
136/*-------------------------------------------------------------------------
137 * This function closes the peci interface
138 *------------------------------------------------------------------------*/
139static void peci_Close(int peci_fd)
140{
141 peci_Unlock(peci_fd);
142}
143
144/*-------------------------------------------------------------------------
145 * This function opens the peci interface and returns a file descriptor
146 *------------------------------------------------------------------------*/
147static EPECIStatus peci_Open(int* peci_fd)
148{
149 if (NULL == peci_fd)
150 {
151 return PECI_CC_INVALID_REQ;
152 }
153
154 // Lock the PECI driver with a default timeout
155 return peci_Lock(peci_fd, PECI_TIMEOUT_MS);
156}
157
158/*-------------------------------------------------------------------------
159 * This function issues peci commands to peci driver
160 *------------------------------------------------------------------------*/
161static EPECIStatus HW_peci_issue_cmd(unsigned int cmd, char* cmdPtr,
162 int peci_fd)
163{
164 if (cmdPtr == NULL)
165 {
166 return PECI_CC_INVALID_REQ;
167 }
168
169 if (ioctl(peci_fd, cmd, cmdPtr) != 0)
170 {
171 if (errno == ETIMEDOUT)
172 {
173 return PECI_CC_TIMEOUT;
174 }
175 return PECI_CC_DRIVER_ERR;
176 }
177
178 return PECI_CC_SUCCESS;
179}
180
181/*-------------------------------------------------------------------------
182 * Find the specified PCI bus number value
183 *------------------------------------------------------------------------*/
184EPECIStatus FindBusNumber(uint8_t u8Bus, uint8_t u8Cpu, uint8_t* pu8BusValue)
185{
186 uint8_t u8CpuBus0[] = {
187 PECI_PCI_BUS0_CPU0,
188 PECI_PCI_BUS0_CPU1,
189 };
190 uint8_t u8Bus0 = 0;
191 uint8_t u8Offset = 0;
Jason M. Billsbc641112020-08-19 16:31:53 -0700192 EPECIStatus ret = PECI_CC_SUCCESS;
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800193 uint8_t u8Reg[4] = {0};
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700194 uint8_t cc = 0;
195
196 // First check for valid inputs
197 // Check cpu and bus numbers, only support buses [5:0]
198 if ((u8Bus > 5) || (u8Cpu >= (sizeof(u8CpuBus0) / sizeof(uint8_t))) ||
199 (pu8BusValue == NULL))
200 {
201 return PECI_CC_INVALID_REQ;
202 }
203
204 // Get the Bus 0 value for the requested CPU
205 u8Bus0 = u8CpuBus0[u8Cpu];
206
207 // Next check that the bus numbers are valid
208 // CPUBUSNO_VALID register - Above registers valid? - B(0) D5 F0 offset
209 // D4h
210 ret = peci_RdPCIConfig(u8Cpu, u8Bus0, PECI_PCI_CPUBUSNO_DEV,
211 PECI_PCI_CPUBUSNO_FUNC, PECI_PCI_CPUBUSNO_VALID,
212 u8Reg, &cc);
213 if (ret != PECI_CC_SUCCESS)
214 {
215 return ret;
216 }
217 // BIOS will set bit 31 of CPUBUSNO_VALID when the bus numbers are valid
218 if ((u8Reg[3] & 0x80) == 0)
219 {
220 return PECI_CC_HW_ERR;
221 }
222
223 // Bus numbers are valid so read the correct offset for the requested
224 // bus CPUBUSNO register - CPU Internal Bus Numbers [3:0] - B(0) D5 F0
225 // offset CCh CPUBUSNO_1 register - CPU Internal Bus Numbers [5:4] -
226 // B(0) D5 F0 offset D0h
227 u8Offset = u8Bus <= 3 ? PECI_PCI_CPUBUSNO : PECI_PCI_CPUBUSNO_1;
228 ret = peci_RdPCIConfig(u8Cpu, u8Bus0, PECI_PCI_CPUBUSNO_DEV,
229 PECI_PCI_CPUBUSNO_FUNC, u8Offset, u8Reg, &cc);
230 if (ret != PECI_CC_SUCCESS)
231 {
232 return ret;
233 }
234
235 // Now return the bus value for the requested bus
236 *pu8BusValue = u8Reg[u8Bus % 4];
237
238 // Unused bus numbers are set to zero which is only valid for bus 0
239 // so, return an error for any other bus set to zero
240 if (*pu8BusValue == 0 && u8Bus != 0)
241 {
242 return PECI_CC_CPU_NOT_PRESENT;
243 }
244
245 return PECI_CC_SUCCESS;
246}
247
248/*-------------------------------------------------------------------------
249 * This function checks the CPU PECI interface
250 *------------------------------------------------------------------------*/
251EPECIStatus peci_Ping(uint8_t target)
252{
253 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -0700254 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700255
Jason M. Bills6ca31642020-08-06 10:26:19 -0700256 // The target address must be in the valid range
257 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
258 {
259 return PECI_CC_INVALID_REQ;
260 }
261
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700262 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
263 {
264 return PECI_CC_DRIVER_ERR;
265 }
266 ret = peci_Ping_seq(target, peci_fd);
267
268 peci_Close(peci_fd);
269 return ret;
270}
271
272/*-------------------------------------------------------------------------
273 * This function allows sequential Ping with the provided
274 * peci file descriptor.
275 *------------------------------------------------------------------------*/
276EPECIStatus peci_Ping_seq(uint8_t target, int peci_fd)
277{
Jason M. Billsbc641112020-08-19 16:31:53 -0700278 EPECIStatus ret = PECI_CC_SUCCESS;
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800279 struct peci_ping_msg cmd = {0};
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700280
Jason M. Bills6ca31642020-08-06 10:26:19 -0700281 // The target address must be in the valid range
282 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
283 {
284 return PECI_CC_INVALID_REQ;
285 }
286
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700287 cmd.addr = target;
288 ret = HW_peci_issue_cmd(PECI_IOC_PING, (char*)&cmd, peci_fd);
289
290 return ret;
291}
292
293/*-------------------------------------------------------------------------
294 * This function gets PECI device information
295 *------------------------------------------------------------------------*/
296EPECIStatus peci_GetDIB(uint8_t target, uint64_t* dib)
297{
298 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -0700299 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700300
301 if (dib == NULL)
302 {
303 return PECI_CC_INVALID_REQ;
304 }
305
Jason M. Bills6ca31642020-08-06 10:26:19 -0700306 // The target address must be in the valid range
307 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
308 {
309 return PECI_CC_INVALID_REQ;
310 }
311
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700312 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
313 {
314 return PECI_CC_DRIVER_ERR;
315 }
316 ret = peci_GetDIB_seq(target, dib, peci_fd);
317
318 peci_Close(peci_fd);
319 return ret;
320}
321
322/*-------------------------------------------------------------------------
323 * This function allows sequential GetDIB with the provided
324 * peci file descriptor.
325 *------------------------------------------------------------------------*/
326EPECIStatus peci_GetDIB_seq(uint8_t target, uint64_t* dib, int peci_fd)
327{
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800328 struct peci_get_dib_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -0700329 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700330 cmd.addr = target;
331
332 if (dib == NULL)
333 {
334 return PECI_CC_INVALID_REQ;
335 }
336
Jason M. Bills6ca31642020-08-06 10:26:19 -0700337 // The target address must be in the valid range
338 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
339 {
340 return PECI_CC_INVALID_REQ;
341 }
342
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700343 ret = HW_peci_issue_cmd(PECI_IOC_GET_DIB, (char*)&cmd, peci_fd);
344
345 if (ret == PECI_CC_SUCCESS)
346 {
347 *dib = cmd.dib;
348 }
349
350 return ret;
351}
352
353/*-------------------------------------------------------------------------
354 * This function get PECI Thermal temperature
355 * Expressed in signed fixed point value of 1/64 degrees celsius
356 *------------------------------------------------------------------------*/
357EPECIStatus peci_GetTemp(uint8_t target, int16_t* temperature)
358{
359 int peci_fd = -1;
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800360 struct peci_get_temp_msg cmd = {0};
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700361
362 if (temperature == NULL)
363 {
364 return PECI_CC_INVALID_REQ;
365 }
366
Jason M. Bills6ca31642020-08-06 10:26:19 -0700367 // The target address must be in the valid range
368 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
369 {
370 return PECI_CC_INVALID_REQ;
371 }
372
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700373 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
374 {
375 return PECI_CC_DRIVER_ERR;
376 }
377
378 cmd.addr = target;
379
Patrick Williamsc96261e2024-08-16 15:22:05 -0400380 EPECIStatus ret =
381 HW_peci_issue_cmd(PECI_IOC_GET_TEMP, (char*)&cmd, peci_fd);
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700382
383 if (ret == PECI_CC_SUCCESS)
384 {
385 *temperature = cmd.temp_raw;
386 }
387
388 peci_Close(peci_fd);
389
390 return ret;
391}
392
393/*-------------------------------------------------------------------------
394 * This function provides read access to the package configuration
395 * space within the processor.
396 *------------------------------------------------------------------------*/
397EPECIStatus peci_RdPkgConfig(uint8_t target, uint8_t u8Index, uint16_t u16Value,
398 uint8_t u8ReadLen, uint8_t* pPkgConfig,
399 uint8_t* cc)
400{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800401 // Default to domain ID 0
402 return peci_RdPkgConfig_dom(target, 0, u8Index, u16Value, u8ReadLen,
403 pPkgConfig, cc);
404}
405
406/*-------------------------------------------------------------------------
407 * This function provides read access to the package configuration
408 * space within the processor in the specified domain.
409 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400410EPECIStatus peci_RdPkgConfig_dom(
411 uint8_t target, uint8_t domainId, uint8_t u8Index, uint16_t u16Value,
412 uint8_t u8ReadLen, uint8_t* pPkgConfig, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800413{
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700414 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -0700415 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700416
417 if (pPkgConfig == NULL || cc == NULL)
418 {
419 return PECI_CC_INVALID_REQ;
420 }
421
Jason M. Bills6ca31642020-08-06 10:26:19 -0700422 // The target address must be in the valid range
423 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
424 {
425 return PECI_CC_INVALID_REQ;
426 }
427
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700428 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
429 {
430 return PECI_CC_DRIVER_ERR;
431 }
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800432 ret = peci_RdPkgConfig_seq_dom(target, domainId, u8Index, u16Value,
433 u8ReadLen, pPkgConfig, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700434
435 peci_Close(peci_fd);
436 return ret;
437}
438
439/*-------------------------------------------------------------------------
440 * This function allows sequential RdPkgConfig with the provided
441 * peci file descriptor.
442 *------------------------------------------------------------------------*/
443EPECIStatus peci_RdPkgConfig_seq(uint8_t target, uint8_t u8Index,
444 uint16_t u16Value, uint8_t u8ReadLen,
445 uint8_t* pPkgConfig, int peci_fd, uint8_t* cc)
446{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800447 // Default to domain ID 0
448 return peci_RdPkgConfig_seq_dom(target, 0, u8Index, u16Value, u8ReadLen,
449 pPkgConfig, peci_fd, cc);
450}
451
452/*-------------------------------------------------------------------------
453 * This function allows sequential RdPkgConfig with the provided
454 * peci file descriptor in the specified domain.
455 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400456EPECIStatus peci_RdPkgConfig_seq_dom(
457 uint8_t target, uint8_t domainId, uint8_t u8Index, uint16_t u16Value,
458 uint8_t u8ReadLen, uint8_t* pPkgConfig, int peci_fd, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800459{
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800460 struct peci_rd_pkg_cfg_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -0700461 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700462
463 if (pPkgConfig == NULL || cc == NULL)
464 {
465 return PECI_CC_INVALID_REQ;
466 }
467
Jason M. Bills6ca31642020-08-06 10:26:19 -0700468 // The target address must be in the valid range
469 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
470 {
471 return PECI_CC_INVALID_REQ;
472 }
473
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700474 // Per the PECI spec, the write length must be a byte, word, or dword
475 if (u8ReadLen != 1 && u8ReadLen != 2 && u8ReadLen != 4)
476 {
477 return PECI_CC_INVALID_REQ;
478 }
479
480 // The PECI buffer must be large enough to hold the requested data
481 if (sizeof(cmd.pkg_config) < u8ReadLen)
482 {
483 return PECI_CC_INVALID_REQ;
484 }
485
486 cmd.addr = target;
487 cmd.index = u8Index; // RdPkgConfig index
488 cmd.param = u16Value; // Config parameter value
489 cmd.rx_len = u8ReadLen;
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800490 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700491
492 ret = HW_peci_issue_cmd(PECI_IOC_RD_PKG_CFG, (char*)&cmd, peci_fd);
493 *cc = cmd.cc;
494 if (ret == PECI_CC_SUCCESS)
495 {
496 memcpy(pPkgConfig, cmd.pkg_config, u8ReadLen);
497 }
498
499 return ret;
500}
501
502/*-------------------------------------------------------------------------
503 * This function provides write access to the package configuration
504 * space within the processor
505 *------------------------------------------------------------------------*/
506EPECIStatus peci_WrPkgConfig(uint8_t target, uint8_t u8Index, uint16_t u16Param,
507 uint32_t u32Value, uint8_t u8WriteLen, uint8_t* cc)
508{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800509 // Default to domain ID 0
510 return peci_WrPkgConfig_dom(target, 0, u8Index, u16Param, u32Value,
511 u8WriteLen, cc);
512}
513
514/*-------------------------------------------------------------------------
515 * This function provides write access to the package configuration
516 * space within the processor in the specified domain
517 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400518EPECIStatus peci_WrPkgConfig_dom(
519 uint8_t target, uint8_t domainId, uint8_t u8Index, uint16_t u16Param,
520 uint32_t u32Value, uint8_t u8WriteLen, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800521{
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700522 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -0700523 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700524
525 if (cc == NULL)
526 {
527 return PECI_CC_INVALID_REQ;
528 }
529
Jason M. Bills6ca31642020-08-06 10:26:19 -0700530 // The target address must be in the valid range
531 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
532 {
533 return PECI_CC_INVALID_REQ;
534 }
535
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700536 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
537 {
538 return PECI_CC_DRIVER_ERR;
539 }
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800540 ret = peci_WrPkgConfig_seq_dom(target, domainId, u8Index, u16Param,
541 u32Value, u8WriteLen, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700542
543 peci_Close(peci_fd);
544 return ret;
545}
546
547/*-------------------------------------------------------------------------
548 * This function allows sequential WrPkgConfig with the provided
549 * peci file descriptor.
550 *------------------------------------------------------------------------*/
551EPECIStatus peci_WrPkgConfig_seq(uint8_t target, uint8_t u8Index,
552 uint16_t u16Param, uint32_t u32Value,
553 uint8_t u8WriteLen, int peci_fd, uint8_t* cc)
554{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800555 // Default to domain ID 0
556 return peci_WrPkgConfig_seq_dom(target, 0, u8Index, u16Param, u32Value,
557 u8WriteLen, peci_fd, cc);
558}
559
560/*-------------------------------------------------------------------------
561 * This function allows sequential WrPkgConfig with the provided
562 * peci file descriptor in the specified domain.
563 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400564EPECIStatus peci_WrPkgConfig_seq_dom(
565 uint8_t target, uint8_t domainId, uint8_t u8Index, uint16_t u16Param,
566 uint32_t u32Value, uint8_t u8WriteLen, int peci_fd, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800567{
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800568 struct peci_wr_pkg_cfg_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -0700569 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700570
571 if (cc == NULL)
572 {
573 return PECI_CC_INVALID_REQ;
574 }
575
Jason M. Bills6ca31642020-08-06 10:26:19 -0700576 // The target address must be in the valid range
577 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
578 {
579 return PECI_CC_INVALID_REQ;
580 }
581
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700582 // Per the PECI spec, the write length must be a byte, word, or dword
583 if ((u8WriteLen != 1) && (u8WriteLen != 2) && (u8WriteLen != 4))
584 {
585 return PECI_CC_INVALID_REQ;
586 }
587
588 cmd.addr = target;
589 cmd.index = u8Index; // RdPkgConfig index
590 cmd.param = u16Param; // parameter value
591 cmd.tx_len = u8WriteLen;
592 cmd.value = u32Value;
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800593 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700594
595 ret = HW_peci_issue_cmd(PECI_IOC_WR_PKG_CFG, (char*)&cmd, peci_fd);
596 *cc = cmd.cc;
597
598 return ret;
599}
600
601/*-------------------------------------------------------------------------
602 * This function provides read access to Model Specific Registers
603 * defined in the processor doc.
604 *------------------------------------------------------------------------*/
605EPECIStatus peci_RdIAMSR(uint8_t target, uint8_t threadID, uint16_t MSRAddress,
606 uint64_t* u64MsrVal, uint8_t* cc)
607{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800608 // Default to domain ID 0
609 return peci_RdIAMSR_dom(target, 0, threadID, MSRAddress, u64MsrVal, cc);
610}
611
612/*-------------------------------------------------------------------------
613 * This function provides read access to Model Specific Registers
614 * defined in the processor doc in the specified domain.
615 *------------------------------------------------------------------------*/
616EPECIStatus peci_RdIAMSR_dom(uint8_t target, uint8_t domainId, uint8_t threadID,
617 uint16_t MSRAddress, uint64_t* u64MsrVal,
618 uint8_t* cc)
619{
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700620 int peci_fd = -1;
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800621 struct peci_rd_ia_msr_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -0700622 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700623
624 if (u64MsrVal == NULL || cc == NULL)
625 {
626 return PECI_CC_INVALID_REQ;
627 }
628
Jason M. Bills6ca31642020-08-06 10:26:19 -0700629 // The target address must be in the valid range
630 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
631 {
632 return PECI_CC_INVALID_REQ;
633 }
634
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700635 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
636 {
637 return PECI_CC_DRIVER_ERR;
638 }
639
640 cmd.addr = target;
641 cmd.thread_id = threadID; // request byte for thread ID
642 cmd.address = MSRAddress; // MSR Address
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800643 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700644
645 ret = HW_peci_issue_cmd(PECI_IOC_RD_IA_MSR, (char*)&cmd, peci_fd);
646 *cc = cmd.cc;
647 if (ret == PECI_CC_SUCCESS)
648 {
649 *u64MsrVal = cmd.value;
650 }
651
652 peci_Close(peci_fd);
653 return ret;
654}
655
656/*-------------------------------------------------------------------------
657 * This function provides read access to the PCI configuration space at
658 * the requested PCI configuration address.
659 *------------------------------------------------------------------------*/
660EPECIStatus peci_RdPCIConfig(uint8_t target, uint8_t u8Bus, uint8_t u8Device,
661 uint8_t u8Fcn, uint16_t u16Reg, uint8_t* pPCIData,
662 uint8_t* cc)
663{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800664 // Default to domain ID 0
665 return peci_RdPCIConfig_dom(target, 0, u8Bus, u8Device, u8Fcn, u16Reg,
666 pPCIData, cc);
667}
668
669/*-------------------------------------------------------------------------
670 * This function provides read access to the PCI configuration space at
671 * the requested PCI configuration address in the specified domain.
672 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400673EPECIStatus peci_RdPCIConfig_dom(
674 uint8_t target, uint8_t domainId, uint8_t u8Bus, uint8_t u8Device,
675 uint8_t u8Fcn, uint16_t u16Reg, uint8_t* pPCIData, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800676{
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700677 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -0700678 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700679
680 if (pPCIData == NULL || cc == NULL)
681 {
682 return PECI_CC_INVALID_REQ;
683 }
684
Jason M. Bills6ca31642020-08-06 10:26:19 -0700685 // The target address must be in the valid range
686 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
687 {
688 return PECI_CC_INVALID_REQ;
689 }
690
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700691 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
692 {
693 return PECI_CC_DRIVER_ERR;
694 }
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800695 ret = peci_RdPCIConfig_seq_dom(target, domainId, u8Bus, u8Device, u8Fcn,
696 u16Reg, pPCIData, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700697
698 peci_Close(peci_fd);
699 return ret;
700}
701
702/*-------------------------------------------------------------------------
703 * This function allows sequential RdPCIConfig with the provided
704 * peci file descriptor.
705 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400706EPECIStatus peci_RdPCIConfig_seq(
707 uint8_t target, uint8_t u8Bus, uint8_t u8Device, uint8_t u8Fcn,
708 uint16_t u16Reg, uint8_t* pPCIData, int peci_fd, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700709{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800710 // Default to domain ID 0
711 return peci_RdPCIConfig_seq_dom(target, 0, u8Bus, u8Device, u8Fcn, u16Reg,
712 pPCIData, peci_fd, cc);
713}
714
715/*-------------------------------------------------------------------------
716 * This function allows sequential RdPCIConfig with the provided
717 * peci file descriptor in the specified domain.
718 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400719EPECIStatus peci_RdPCIConfig_seq_dom(
720 uint8_t target, uint8_t domainId, uint8_t u8Bus, uint8_t u8Device,
721 uint8_t u8Fcn, uint16_t u16Reg, uint8_t* pPCIData, int peci_fd, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800722{
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800723 struct peci_rd_pci_cfg_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -0700724 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700725
726 if (pPCIData == NULL || cc == NULL)
727 {
728 return PECI_CC_INVALID_REQ;
729 }
730
Jason M. Bills6ca31642020-08-06 10:26:19 -0700731 // The target address must be in the valid range
732 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
733 {
734 return PECI_CC_INVALID_REQ;
735 }
736
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700737 // The PECI buffer must be large enough to hold the PCI data
738 if (sizeof(cmd.pci_config) < 4)
739 {
740 return PECI_CC_INVALID_REQ;
741 }
742
743 cmd.addr = target;
744 cmd.bus = u8Bus;
745 cmd.device = u8Device;
746 cmd.function = u8Fcn;
747 cmd.reg = u16Reg;
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800748 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700749
750 ret = HW_peci_issue_cmd(PECI_IOC_RD_PCI_CFG, (char*)&cmd, peci_fd);
751 *cc = cmd.cc;
752
753 if (ret == PECI_CC_SUCCESS)
754 {
755 memcpy(pPCIData, cmd.pci_config, 4);
756 }
757
758 return ret;
759}
760
761/*-------------------------------------------------------------------------
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800762 * This function provides read access to the local PCI configuration space
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700763 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400764EPECIStatus peci_RdPCIConfigLocal(
765 uint8_t target, uint8_t u8Bus, uint8_t u8Device, uint8_t u8Fcn,
766 uint16_t u16Reg, uint8_t u8ReadLen, uint8_t* pPCIReg, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700767{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800768 // Default to domain ID 0
769 return peci_RdPCIConfigLocal_dom(target, 0, u8Bus, u8Device, u8Fcn, u16Reg,
770 u8ReadLen, pPCIReg, cc);
771}
772
773/*-------------------------------------------------------------------------
774 * This function provides read access to the local PCI configuration space in
775 * the specified domain
776 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400777EPECIStatus
778 peci_RdPCIConfigLocal_dom(uint8_t target, uint8_t domainId, uint8_t u8Bus,
779 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg,
780 uint8_t u8ReadLen, uint8_t* pPCIReg, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800781{
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700782 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -0700783 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700784
785 if (pPCIReg == NULL || cc == NULL)
786 {
787 return PECI_CC_INVALID_REQ;
788 }
789
Jason M. Bills6ca31642020-08-06 10:26:19 -0700790 // The target address must be in the valid range
791 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
792 {
793 return PECI_CC_INVALID_REQ;
794 }
795
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700796 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
797 {
798 return PECI_CC_DRIVER_ERR;
799 }
Patrick Williamsc96261e2024-08-16 15:22:05 -0400800 ret =
801 peci_RdPCIConfigLocal_seq_dom(target, domainId, u8Bus, u8Device, u8Fcn,
802 u16Reg, u8ReadLen, pPCIReg, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700803
804 peci_Close(peci_fd);
805 return ret;
806}
807
808/*-------------------------------------------------------------------------
809 * This function allows sequential RdPCIConfigLocal with the provided
810 * peci file descriptor.
811 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400812EPECIStatus
813 peci_RdPCIConfigLocal_seq(uint8_t target, uint8_t u8Bus, uint8_t u8Device,
814 uint8_t u8Fcn, uint16_t u16Reg, uint8_t u8ReadLen,
815 uint8_t* pPCIReg, int peci_fd, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700816{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800817 // Default to domain ID 0
Patrick Williamsc96261e2024-08-16 15:22:05 -0400818 return peci_RdPCIConfigLocal_seq_dom(
819 target, 0, u8Bus, u8Device, u8Fcn, u16Reg, u8ReadLen, pPCIReg, peci_fd,
820 cc);
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800821}
822
823/*-------------------------------------------------------------------------
824 * This function allows sequential RdPCIConfigLocal with the provided
825 * peci file descriptor in the specified domain.
826 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400827EPECIStatus peci_RdPCIConfigLocal_seq_dom(
828 uint8_t target, uint8_t domainId, uint8_t u8Bus, uint8_t u8Device,
829 uint8_t u8Fcn, uint16_t u16Reg, uint8_t u8ReadLen, uint8_t* pPCIReg,
830 int peci_fd, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800831{
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800832 struct peci_rd_pci_cfg_local_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -0700833 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700834
835 if (pPCIReg == NULL || cc == NULL)
836 {
837 return PECI_CC_INVALID_REQ;
838 }
839
Jason M. Bills6ca31642020-08-06 10:26:19 -0700840 // The target address must be in the valid range
841 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
842 {
843 return PECI_CC_INVALID_REQ;
844 }
845
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700846 // Per the PECI spec, the read length must be a byte, word, or dword
847 if (u8ReadLen != 1 && u8ReadLen != 2 && u8ReadLen != 4)
848 {
849 return PECI_CC_INVALID_REQ;
850 }
851
852 // The PECI buffer must be large enough to hold the requested data
853 if (sizeof(cmd.pci_config) < u8ReadLen)
854 {
855 return PECI_CC_INVALID_REQ;
856 }
857
858 cmd.addr = target;
859 cmd.bus = u8Bus;
860 cmd.device = u8Device;
861 cmd.function = u8Fcn;
862 cmd.reg = u16Reg;
863 cmd.rx_len = u8ReadLen;
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800864 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700865
866 ret = HW_peci_issue_cmd(PECI_IOC_RD_PCI_CFG_LOCAL, (char*)&cmd, peci_fd);
867 *cc = cmd.cc;
868
869 if (ret == PECI_CC_SUCCESS)
870 {
871 memcpy(pPCIReg, cmd.pci_config, u8ReadLen);
872 }
873
874 return ret;
875}
876
877/*-------------------------------------------------------------------------
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800878 * This function provides write access to the local PCI configuration space
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700879 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400880EPECIStatus peci_WrPCIConfigLocal(
881 uint8_t target, uint8_t u8Bus, uint8_t u8Device, uint8_t u8Fcn,
882 uint16_t u16Reg, uint8_t DataLen, uint32_t DataVal, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700883{
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800884 // Default to domain ID 0
885 return peci_WrPCIConfigLocal_dom(target, 0, u8Bus, u8Device, u8Fcn, u16Reg,
886 DataLen, DataVal, cc);
887}
888
889/*-------------------------------------------------------------------------
890 * This function provides write access to the local PCI configuration space in
891 * the specified domain
892 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400893EPECIStatus
894 peci_WrPCIConfigLocal_dom(uint8_t target, uint8_t domainId, uint8_t u8Bus,
895 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg,
896 uint8_t DataLen, uint32_t DataVal, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800897{
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700898 int peci_fd = -1;
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800899 struct peci_wr_pci_cfg_local_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -0700900 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700901
902 if (cc == NULL)
903 {
904 return PECI_CC_INVALID_REQ;
905 }
906
Jason M. Bills6ca31642020-08-06 10:26:19 -0700907 // The target address must be in the valid range
908 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
909 {
910 return PECI_CC_INVALID_REQ;
911 }
912
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700913 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
914 {
915 return PECI_CC_DRIVER_ERR;
916 }
917
918 // Per the PECI spec, the write length must be a byte, word, or dword
919 if (DataLen != 1 && DataLen != 2 && DataLen != 4)
920 {
921 peci_Close(peci_fd);
922 return PECI_CC_INVALID_REQ;
923 }
924
925 cmd.addr = target;
926 cmd.bus = u8Bus;
927 cmd.device = u8Device;
928 cmd.function = u8Fcn;
929 cmd.reg = u16Reg;
930 cmd.tx_len = DataLen;
931 cmd.value = DataVal;
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800932 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700933
934 ret = HW_peci_issue_cmd(PECI_IOC_WR_PCI_CFG_LOCAL, (char*)&cmd, peci_fd);
935 *cc = cmd.cc;
936
937 peci_Close(peci_fd);
938 return ret;
939}
940
941/*-------------------------------------------------------------------------
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800942 * This internal function is the common interface for RdEndPointConfig to PCI in
943 * the specified domain
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700944 *------------------------------------------------------------------------*/
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800945static EPECIStatus peci_RdEndPointConfigPciCommon_dom(
946 uint8_t target, uint8_t domainId, uint8_t u8MsgType, uint8_t u8Seg,
947 uint8_t u8Bus, uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg,
948 uint8_t u8ReadLen, uint8_t* pPCIData, int peci_fd, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700949{
Nirav Shahfd5dfd52022-03-09 12:29:41 -0800950 struct peci_rd_end_pt_cfg_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -0700951 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700952
953 if (pPCIData == NULL || cc == NULL)
954 {
955 return PECI_CC_INVALID_REQ;
956 }
957
Jason M. Bills6ca31642020-08-06 10:26:19 -0700958 // The target address must be in the valid range
959 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
960 {
961 return PECI_CC_INVALID_REQ;
962 }
963
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700964 // The PECI buffer must be large enough to hold the requested data
965 if (sizeof(cmd.data) < u8ReadLen)
966 {
967 return PECI_CC_INVALID_REQ;
968 }
969
970 cmd.addr = target;
971 cmd.msg_type = u8MsgType;
972 cmd.params.pci_cfg.seg = u8Seg;
973 cmd.params.pci_cfg.bus = u8Bus;
974 cmd.params.pci_cfg.device = u8Device;
975 cmd.params.pci_cfg.function = u8Fcn;
976 cmd.params.pci_cfg.reg = u16Reg;
977 cmd.rx_len = u8ReadLen;
Jason M. Bills8bb8f372022-03-01 16:04:44 -0800978 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -0700979
980 ret = HW_peci_issue_cmd(PECI_IOC_RD_END_PT_CFG, (char*)&cmd, peci_fd);
981 *cc = cmd.cc;
982
983 if (ret == PECI_CC_SUCCESS)
984 {
985 memcpy(pPCIData, cmd.data, u8ReadLen);
986 }
987 else
988 {
989 ret = PECI_CC_DRIVER_ERR;
990 }
991
992 return ret;
993}
994
995/*-------------------------------------------------------------------------
996 * This function provides read access to the PCI configuration space at
997 * the requested PCI configuration address.
998 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -0400999EPECIStatus
1000 peci_RdEndPointConfigPci(uint8_t target, uint8_t u8Seg, uint8_t u8Bus,
1001 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg,
1002 uint8_t u8ReadLen, uint8_t* pPCIData, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001003{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001004 // Default to domain ID 0
1005 return peci_RdEndPointConfigPci_dom(target, 0, u8Seg, u8Bus, u8Device,
1006 u8Fcn, u16Reg, u8ReadLen, pPCIData, cc);
1007}
1008
1009/*-------------------------------------------------------------------------
1010 * This function provides read access to the PCI configuration space at
1011 * the requested PCI configuration address in the specified domain.
1012 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001013EPECIStatus peci_RdEndPointConfigPci_dom(
1014 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1015 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg, uint8_t u8ReadLen,
1016 uint8_t* pPCIData, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001017{
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001018 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -07001019 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001020
1021 if (pPCIData == NULL || cc == NULL)
1022 {
1023 return PECI_CC_INVALID_REQ;
1024 }
1025
Jason M. Bills6ca31642020-08-06 10:26:19 -07001026 // The target address must be in the valid range
1027 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1028 {
1029 return PECI_CC_INVALID_REQ;
1030 }
1031
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001032 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
1033 {
1034 return PECI_CC_DRIVER_ERR;
1035 }
Patrick Williamsc96261e2024-08-16 15:22:05 -04001036 ret = peci_RdEndPointConfigPci_seq_dom(
1037 target, domainId, u8Seg, u8Bus, u8Device, u8Fcn, u16Reg, u8ReadLen,
1038 pPCIData, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001039 peci_Close(peci_fd);
1040 return ret;
1041}
1042
1043/*-------------------------------------------------------------------------
1044 * This function allows sequential RdEndPointConfig to PCI with the provided
1045 * peci file descriptor.
1046 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001047EPECIStatus peci_RdEndPointConfigPci_seq(
1048 uint8_t target, uint8_t u8Seg, uint8_t u8Bus, uint8_t u8Device,
1049 uint8_t u8Fcn, uint16_t u16Reg, uint8_t u8ReadLen, uint8_t* pPCIData,
1050 int peci_fd, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001051{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001052 // Default to domain ID 0
Patrick Williamsc96261e2024-08-16 15:22:05 -04001053 return peci_RdEndPointConfigPci_seq_dom(
1054 target, 0, u8Seg, u8Bus, u8Device, u8Fcn, u16Reg, u8ReadLen, pPCIData,
1055 peci_fd, cc);
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001056}
1057
1058/*-------------------------------------------------------------------------
1059 * This function allows sequential RdEndPointConfig to PCI with the provided
1060 * peci file descriptor in the specified domain.
1061 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001062EPECIStatus peci_RdEndPointConfigPci_seq_dom(
1063 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1064 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg, uint8_t u8ReadLen,
1065 uint8_t* pPCIData, int peci_fd, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001066{
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001067 if (pPCIData == NULL || cc == NULL)
1068 {
1069 return PECI_CC_INVALID_REQ;
1070 }
1071
Jason M. Bills6ca31642020-08-06 10:26:19 -07001072 // The target address must be in the valid range
1073 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1074 {
1075 return PECI_CC_INVALID_REQ;
1076 }
1077
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001078 // Per the PECI spec, the read length must be a byte, word, or dword
1079 if (u8ReadLen != 1 && u8ReadLen != 2 && u8ReadLen != 4)
1080 {
1081 return PECI_CC_INVALID_REQ;
1082 }
1083
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001084 return peci_RdEndPointConfigPciCommon_dom(
1085 target, domainId, PECI_ENDPTCFG_TYPE_PCI, u8Seg, u8Bus, u8Device, u8Fcn,
1086 u16Reg, u8ReadLen, pPCIData, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001087}
1088
1089/*-------------------------------------------------------------------------
1090 * This function provides read access to the Local PCI configuration space at
1091 * the requested PCI configuration address.
1092 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001093EPECIStatus peci_RdEndPointConfigPciLocal(
1094 uint8_t target, uint8_t u8Seg, uint8_t u8Bus, uint8_t u8Device,
1095 uint8_t u8Fcn, uint16_t u16Reg, uint8_t u8ReadLen, uint8_t* pPCIData,
1096 uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001097{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001098 // Default to domain ID 0
Patrick Williamsc96261e2024-08-16 15:22:05 -04001099 return peci_RdEndPointConfigPciLocal_dom(
1100 target, 0, u8Seg, u8Bus, u8Device, u8Fcn, u16Reg, u8ReadLen, pPCIData,
1101 cc);
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001102}
1103
1104/*-------------------------------------------------------------------------
1105 * This function provides read access to the Local PCI configuration space at
1106 * the requested PCI configuration address in the specified domain.
1107 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001108EPECIStatus peci_RdEndPointConfigPciLocal_dom(
1109 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1110 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg, uint8_t u8ReadLen,
1111 uint8_t* pPCIData, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001112{
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001113 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -07001114 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001115
1116 if (pPCIData == NULL || cc == NULL)
1117 {
1118 return PECI_CC_INVALID_REQ;
1119 }
1120
Jason M. Bills6ca31642020-08-06 10:26:19 -07001121 // The target address must be in the valid range
1122 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1123 {
1124 return PECI_CC_INVALID_REQ;
1125 }
1126
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001127 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
1128 {
1129 return PECI_CC_DRIVER_ERR;
1130 }
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001131 ret = peci_RdEndPointConfigPciLocal_seq_dom(
1132 target, domainId, u8Seg, u8Bus, u8Device, u8Fcn, u16Reg, u8ReadLen,
1133 pPCIData, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001134 peci_Close(peci_fd);
1135 return ret;
1136}
1137
1138/*-------------------------------------------------------------------------
1139 * This function allows sequential RdEndPointConfig to PCI Local with the
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001140 * provided peci file descriptor.
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001141 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001142EPECIStatus peci_RdEndPointConfigPciLocal_seq(
1143 uint8_t target, uint8_t u8Seg, uint8_t u8Bus, uint8_t u8Device,
1144 uint8_t u8Fcn, uint16_t u16Reg, uint8_t u8ReadLen, uint8_t* pPCIData,
1145 int peci_fd, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001146{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001147 // Default to domain ID 0
1148 return peci_RdEndPointConfigPciLocal_seq_dom(
1149 target, 0, u8Seg, u8Bus, u8Device, u8Fcn, u16Reg, u8ReadLen, pPCIData,
1150 peci_fd, cc);
1151}
1152
1153/*-------------------------------------------------------------------------
1154 * This function allows sequential RdEndPointConfig to PCI Local with the
1155 * provided peci file descriptor in the specified domain.
1156 *------------------------------------------------------------------------*/
1157EPECIStatus peci_RdEndPointConfigPciLocal_seq_dom(
1158 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1159 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg, uint8_t u8ReadLen,
1160 uint8_t* pPCIData, int peci_fd, uint8_t* cc)
1161{
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001162 if (pPCIData == NULL || cc == NULL)
1163 {
1164 return PECI_CC_INVALID_REQ;
1165 }
1166
Jason M. Bills6ca31642020-08-06 10:26:19 -07001167 // The target address must be in the valid range
1168 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1169 {
1170 return PECI_CC_INVALID_REQ;
1171 }
1172
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001173 // Per the PECI spec, the read length must be a byte, word, or dword
1174 if (u8ReadLen != 1 && u8ReadLen != 2 && u8ReadLen != 4)
1175 {
1176 return PECI_CC_INVALID_REQ;
1177 }
1178
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001179 return peci_RdEndPointConfigPciCommon_dom(
1180 target, domainId, PECI_ENDPTCFG_TYPE_LOCAL_PCI, u8Seg, u8Bus, u8Device,
1181 u8Fcn, u16Reg, u8ReadLen, pPCIData, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001182}
1183
1184/*-------------------------------------------------------------------------
1185 * This function provides read access to PCI MMIO space at
1186 * the requested PCI configuration address.
1187 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001188EPECIStatus peci_RdEndPointConfigMmio(
1189 uint8_t target, uint8_t u8Seg, uint8_t u8Bus, uint8_t u8Device,
1190 uint8_t u8Fcn, uint8_t u8Bar, uint8_t u8AddrType, uint64_t u64Offset,
1191 uint8_t u8ReadLen, uint8_t* pMmioData, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001192{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001193 // Default to domain ID 0
Patrick Williamsc96261e2024-08-16 15:22:05 -04001194 return peci_RdEndPointConfigMmio_dom(
1195 target, 0, u8Seg, u8Bus, u8Device, u8Fcn, u8Bar, u8AddrType, u64Offset,
1196 u8ReadLen, pMmioData, cc);
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001197}
1198
1199/*-------------------------------------------------------------------------
1200 * This function provides read access to PCI MMIO space at
1201 * the requested PCI configuration address in the specified domain.
1202 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001203EPECIStatus peci_RdEndPointConfigMmio_dom(
1204 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1205 uint8_t u8Device, uint8_t u8Fcn, uint8_t u8Bar, uint8_t u8AddrType,
1206 uint64_t u64Offset, uint8_t u8ReadLen, uint8_t* pMmioData, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001207{
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001208 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -07001209 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001210
1211 if (pMmioData == NULL || cc == NULL)
1212 {
1213 return PECI_CC_INVALID_REQ;
1214 }
1215
Jason M. Bills6ca31642020-08-06 10:26:19 -07001216 // The target address must be in the valid range
1217 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1218 {
1219 return PECI_CC_INVALID_REQ;
1220 }
1221
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001222 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
1223 {
1224 return PECI_CC_DRIVER_ERR;
1225 }
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001226 ret = peci_RdEndPointConfigMmio_seq_dom(
1227 target, domainId, u8Seg, u8Bus, u8Device, u8Fcn, u8Bar, u8AddrType,
1228 u64Offset, u8ReadLen, pMmioData, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001229 peci_Close(peci_fd);
1230 return ret;
1231}
1232
1233/*-------------------------------------------------------------------------
1234 * This function allows sequential RdEndPointConfig to PCI MMIO with the
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001235 * provided peci file descriptor.
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001236 *------------------------------------------------------------------------*/
1237EPECIStatus peci_RdEndPointConfigMmio_seq(
1238 uint8_t target, uint8_t u8Seg, uint8_t u8Bus, uint8_t u8Device,
1239 uint8_t u8Fcn, uint8_t u8Bar, uint8_t u8AddrType, uint64_t u64Offset,
1240 uint8_t u8ReadLen, uint8_t* pMmioData, int peci_fd, uint8_t* cc)
1241{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001242 // Default to domain ID 0
1243 return peci_RdEndPointConfigMmio_seq_dom(
1244 target, 0, u8Seg, u8Bus, u8Device, u8Fcn, u8Bar, u8AddrType, u64Offset,
1245 u8ReadLen, pMmioData, peci_fd, cc);
1246}
1247
1248/*-------------------------------------------------------------------------
1249 * This function allows sequential RdEndPointConfig to PCI MMIO with the
1250 * provided peci file descriptor in the specified domain.
1251 *------------------------------------------------------------------------*/
1252EPECIStatus peci_RdEndPointConfigMmio_seq_dom(
1253 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1254 uint8_t u8Device, uint8_t u8Fcn, uint8_t u8Bar, uint8_t u8AddrType,
1255 uint64_t u64Offset, uint8_t u8ReadLen, uint8_t* pMmioData, int peci_fd,
1256 uint8_t* cc)
1257{
Nirav Shahfd5dfd52022-03-09 12:29:41 -08001258 struct peci_rd_end_pt_cfg_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -07001259 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001260
1261 if (pMmioData == NULL || cc == NULL)
1262 {
1263 return PECI_CC_INVALID_REQ;
1264 }
1265
Jason M. Bills6ca31642020-08-06 10:26:19 -07001266 // The target address must be in the valid range
1267 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1268 {
1269 return PECI_CC_INVALID_REQ;
1270 }
1271
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001272 // Per the PECI spec, the read length must be a byte, word, dword, or qword
1273 if (u8ReadLen != 1 && u8ReadLen != 2 && u8ReadLen != 4 && u8ReadLen != 8)
1274 {
1275 return PECI_CC_INVALID_REQ;
1276 }
1277
1278 // The PECI buffer must be large enough to hold the requested data
1279 if (sizeof(cmd.data) < u8ReadLen)
1280 {
1281 return PECI_CC_INVALID_REQ;
1282 }
1283
1284 cmd.addr = target;
1285 cmd.msg_type = PECI_ENDPTCFG_TYPE_MMIO;
1286 cmd.params.mmio.seg = u8Seg;
1287 cmd.params.mmio.bus = u8Bus;
1288 cmd.params.mmio.device = u8Device;
1289 cmd.params.mmio.function = u8Fcn;
1290 cmd.params.mmio.bar = u8Bar;
1291 cmd.params.mmio.addr_type = u8AddrType;
1292 cmd.params.mmio.offset = u64Offset;
1293 cmd.rx_len = u8ReadLen;
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001294 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001295
1296 ret = HW_peci_issue_cmd(PECI_IOC_RD_END_PT_CFG, (char*)&cmd, peci_fd);
1297 *cc = cmd.cc;
1298
1299 if (ret == PECI_CC_SUCCESS)
1300 {
1301 memcpy(pMmioData, cmd.data, u8ReadLen);
1302 }
1303 else
1304 {
1305 ret = PECI_CC_DRIVER_ERR;
1306 }
1307
1308 return ret;
1309}
1310
1311/*-------------------------------------------------------------------------
1312 * This function allows sequential peci_WrEndPointConfig to PCI EndPoint with
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001313 * the provided peci file descriptor.
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001314 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001315EPECIStatus peci_WrEndPointConfig_seq(
1316 uint8_t target, uint8_t u8MsgType, uint8_t u8Seg, uint8_t u8Bus,
1317 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg, uint8_t DataLen,
1318 uint32_t DataVal, int peci_fd, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001319{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001320 // Default to domain ID 0
Patrick Williamsc96261e2024-08-16 15:22:05 -04001321 return peci_WrEndPointConfig_seq_dom(
1322 target, 0, u8MsgType, u8Seg, u8Bus, u8Device, u8Fcn, u16Reg, DataLen,
1323 DataVal, peci_fd, cc);
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001324}
1325
1326/*-------------------------------------------------------------------------
1327 * This function allows sequential peci_WrEndPointConfig to PCI EndPoint with
1328 * the provided peci file descriptor in the specified domain.
1329 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001330EPECIStatus peci_WrEndPointConfig_seq_dom(
1331 uint8_t target, uint8_t domainId, uint8_t u8MsgType, uint8_t u8Seg,
1332 uint8_t u8Bus, uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg,
1333 uint8_t DataLen, uint32_t DataVal, int peci_fd, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001334{
Nirav Shahfd5dfd52022-03-09 12:29:41 -08001335 struct peci_wr_end_pt_cfg_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -07001336 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001337
1338 if (cc == NULL)
1339 {
1340 return PECI_CC_INVALID_REQ;
1341 }
1342
Jason M. Bills6ca31642020-08-06 10:26:19 -07001343 // The target address must be in the valid range
1344 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1345 {
1346 return PECI_CC_INVALID_REQ;
1347 }
1348
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001349 // Per the PECI spec, the write length must be a byte, word, or dword
1350 if (DataLen != 1 && DataLen != 2 && DataLen != 4)
1351 {
1352 return PECI_CC_INVALID_REQ;
1353 }
1354
1355 cmd.addr = target;
1356 cmd.msg_type = u8MsgType;
1357 cmd.params.pci_cfg.seg = u8Seg;
1358 cmd.params.pci_cfg.bus = u8Bus;
1359 cmd.params.pci_cfg.device = u8Device;
1360 cmd.params.pci_cfg.function = u8Fcn;
1361 cmd.params.pci_cfg.reg = u16Reg;
1362 cmd.tx_len = DataLen;
1363 cmd.value = DataVal;
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001364 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001365
1366 ret = HW_peci_issue_cmd(PECI_IOC_WR_END_PT_CFG, (char*)&cmd, peci_fd);
1367 *cc = cmd.cc;
1368
1369 return ret;
1370}
1371
1372/*-------------------------------------------------------------------------
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001373 * This function provides write access to the EP local PCI configuration space
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001374 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001375EPECIStatus peci_WrEndPointPCIConfigLocal(
1376 uint8_t target, uint8_t u8Seg, uint8_t u8Bus, uint8_t u8Device,
1377 uint8_t u8Fcn, uint16_t u16Reg, uint8_t DataLen, uint32_t DataVal,
1378 uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001379{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001380 // Default to domain ID 0
1381 return peci_WrEndPointPCIConfigLocal_dom(
1382 target, 0, u8Seg, u8Bus, u8Device, u8Fcn, u16Reg, DataLen, DataVal, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001383}
1384
1385/*-------------------------------------------------------------------------
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001386 * This function provides write access to the EP local PCI configuration space
1387 * in the specified domain
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001388 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001389EPECIStatus peci_WrEndPointPCIConfigLocal_dom(
1390 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1391 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg, uint8_t DataLen,
1392 uint32_t DataVal, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001393{
1394 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -07001395 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001396
1397 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
1398 {
1399 return PECI_CC_DRIVER_ERR;
1400 }
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001401
1402 ret = peci_WrEndPointConfig_seq_dom(
1403 target, domainId, PECI_ENDPTCFG_TYPE_LOCAL_PCI, u8Seg, u8Bus, u8Device,
1404 u8Fcn, u16Reg, DataLen, DataVal, peci_fd, cc);
1405 peci_Close(peci_fd);
1406 return ret;
1407}
1408
1409/*-------------------------------------------------------------------------
1410 * This function provides write access to the EP local PCI configuration space
1411 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001412EPECIStatus
1413 peci_WrEndPointPCIConfig(uint8_t target, uint8_t u8Seg, uint8_t u8Bus,
1414 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg,
1415 uint8_t DataLen, uint32_t DataVal, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001416{
1417 // Default to domain ID 0
1418 return peci_WrEndPointPCIConfig_dom(target, 0, u8Seg, u8Bus, u8Device,
1419 u8Fcn, u16Reg, DataLen, DataVal, cc);
1420}
1421
1422/*-------------------------------------------------------------------------
1423 * This function provides write access to the EP local PCI configuration space
1424 * in the specified domain
1425 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001426EPECIStatus peci_WrEndPointPCIConfig_dom(
1427 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1428 uint8_t u8Device, uint8_t u8Fcn, uint16_t u16Reg, uint8_t DataLen,
1429 uint32_t DataVal, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001430{
1431 int peci_fd = -1;
1432 EPECIStatus ret = PECI_CC_SUCCESS;
1433
1434 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
1435 {
1436 return PECI_CC_DRIVER_ERR;
1437 }
1438 ret = peci_WrEndPointConfig_seq_dom(
1439 target, domainId, PECI_ENDPTCFG_TYPE_PCI, u8Seg, u8Bus, u8Device, u8Fcn,
1440 u16Reg, DataLen, DataVal, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001441 peci_Close(peci_fd);
1442 return ret;
1443}
1444
1445/*-------------------------------------------------------------------------
1446 * This function provides write access to PCI MMIO space at
1447 * the requested PCI configuration address.
1448 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001449EPECIStatus peci_WrEndPointConfigMmio(
1450 uint8_t target, uint8_t u8Seg, uint8_t u8Bus, uint8_t u8Device,
1451 uint8_t u8Fcn, uint8_t u8Bar, uint8_t u8AddrType, uint64_t u64Offset,
1452 uint8_t u8DataLen, uint64_t u64DataVal, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001453{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001454 // Default to domain ID 0
Patrick Williamsc96261e2024-08-16 15:22:05 -04001455 return peci_WrEndPointConfigMmio_dom(
1456 target, 0, u8Seg, u8Bus, u8Device, u8Fcn, u8Bar, u8AddrType, u64Offset,
1457 u8DataLen, u64DataVal, cc);
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001458}
1459
1460/*-------------------------------------------------------------------------
1461 * This function provides write access to PCI MMIO space at
1462 * the requested PCI configuration address in the specified domain.
1463 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001464EPECIStatus peci_WrEndPointConfigMmio_dom(
1465 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1466 uint8_t u8Device, uint8_t u8Fcn, uint8_t u8Bar, uint8_t u8AddrType,
1467 uint64_t u64Offset, uint8_t u8DataLen, uint64_t u64DataVal, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001468{
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001469 int peci_fd = -1;
Jason M. Billsbc641112020-08-19 16:31:53 -07001470 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001471
1472 if (cc == NULL)
1473 {
1474 return PECI_CC_INVALID_REQ;
1475 }
1476
Jason M. Bills6ca31642020-08-06 10:26:19 -07001477 // The target address must be in the valid range
1478 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1479 {
1480 return PECI_CC_INVALID_REQ;
1481 }
1482
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001483 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
1484 {
1485 return PECI_CC_DRIVER_ERR;
1486 }
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001487 ret = peci_WrEndPointConfigMmio_seq_dom(
1488 target, domainId, u8Seg, u8Bus, u8Device, u8Fcn, u8Bar, u8AddrType,
1489 u64Offset, u8DataLen, u64DataVal, peci_fd, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001490 peci_Close(peci_fd);
1491 return ret;
1492}
1493
1494/*-------------------------------------------------------------------------
1495 * This function allows sequential WrEndPointConfig to PCI MMIO with the
1496 * provided peci file descriptor.
1497 *------------------------------------------------------------------------*/
1498EPECIStatus peci_WrEndPointConfigMmio_seq(
1499 uint8_t target, uint8_t u8Seg, uint8_t u8Bus, uint8_t u8Device,
1500 uint8_t u8Fcn, uint8_t u8Bar, uint8_t u8AddrType, uint64_t u64Offset,
1501 uint8_t u8DataLen, uint64_t u64DataVal, int peci_fd, uint8_t* cc)
1502{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001503 // Default to domain ID 0
1504 return peci_WrEndPointConfigMmio_seq_dom(
1505 target, 0, u8Seg, u8Bus, u8Device, u8Fcn, u8Bar, u8AddrType, u64Offset,
1506 u8DataLen, u64DataVal, peci_fd, cc);
1507}
1508
1509/*-------------------------------------------------------------------------
1510 * This function allows sequential WrEndPointConfig to PCI MMIO with the
1511 * provided peci file descriptor in the specified domain.
1512 *------------------------------------------------------------------------*/
1513EPECIStatus peci_WrEndPointConfigMmio_seq_dom(
1514 uint8_t target, uint8_t domainId, uint8_t u8Seg, uint8_t u8Bus,
1515 uint8_t u8Device, uint8_t u8Fcn, uint8_t u8Bar, uint8_t u8AddrType,
1516 uint64_t u64Offset, uint8_t u8DataLen, uint64_t u64DataVal, int peci_fd,
1517 uint8_t* cc)
1518{
Nirav Shahfd5dfd52022-03-09 12:29:41 -08001519 struct peci_wr_end_pt_cfg_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -07001520 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001521
1522 if (cc == NULL)
1523 {
1524 return PECI_CC_INVALID_REQ;
1525 }
1526
Jason M. Bills6ca31642020-08-06 10:26:19 -07001527 // The target address must be in the valid range
1528 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1529 {
1530 return PECI_CC_INVALID_REQ;
1531 }
1532
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001533 // Per the PECI spec, the read length must be a byte, word, dword, or qword
1534 if (u8DataLen != 1 && u8DataLen != 2 && u8DataLen != 4 && u8DataLen != 8)
1535 {
1536 return PECI_CC_INVALID_REQ;
1537 }
1538
1539 cmd.addr = target;
1540 cmd.msg_type = PECI_ENDPTCFG_TYPE_MMIO;
1541 cmd.params.mmio.seg = u8Seg;
1542 cmd.params.mmio.bus = u8Bus;
1543 cmd.params.mmio.device = u8Device;
1544 cmd.params.mmio.function = u8Fcn;
1545 cmd.params.mmio.bar = u8Bar;
1546 cmd.params.mmio.addr_type = u8AddrType;
1547 cmd.params.mmio.offset = u64Offset;
1548 cmd.tx_len = u8DataLen;
1549 cmd.value = u64DataVal;
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001550 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001551
1552 ret = HW_peci_issue_cmd(PECI_IOC_WR_END_PT_CFG, (char*)&cmd, peci_fd);
1553 *cc = cmd.cc;
1554
1555 return ret;
1556}
1557
1558/*-------------------------------------------------------------------------
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001559 * This function provides crashdump discovery data over PECI
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001560 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001561EPECIStatus peci_CrashDump_Discovery(
1562 uint8_t target, uint8_t subopcode, uint8_t param0, uint16_t param1,
1563 uint8_t param2, uint8_t u8ReadLen, uint8_t* pData, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001564{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001565 // Default to domain ID 0
1566 return peci_CrashDump_Discovery_dom(target, 0, subopcode, param0, param1,
1567 param2, u8ReadLen, pData, cc);
1568}
1569
1570/*-------------------------------------------------------------------------
1571 * This function provides crashdump discovery data over PECI in the specified
1572 * domain
1573 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001574EPECIStatus peci_CrashDump_Discovery_dom(
1575 uint8_t target, uint8_t domainId, uint8_t subopcode, uint8_t param0,
1576 uint16_t param1, uint8_t param2, uint8_t u8ReadLen, uint8_t* pData,
1577 uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001578{
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001579 int peci_fd = -1;
Nirav Shahfd5dfd52022-03-09 12:29:41 -08001580 struct peci_crashdump_disc_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -07001581 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001582
1583 if (pData == NULL || cc == NULL)
1584 {
1585 return PECI_CC_INVALID_REQ;
1586 }
1587
Jason M. Bills6ca31642020-08-06 10:26:19 -07001588 // The target address must be in the valid range
1589 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1590 {
1591 return PECI_CC_INVALID_REQ;
1592 }
1593
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001594 // Per the PECI spec, the read length must be a byte, word, or qword
1595 if (u8ReadLen != 1 && u8ReadLen != 2 && u8ReadLen != 8)
1596 {
1597 return PECI_CC_INVALID_REQ;
1598 }
1599
1600 // The PECI buffer must be large enough to hold the requested data
1601 if (sizeof(cmd.data) < u8ReadLen)
1602 {
1603 return PECI_CC_INVALID_REQ;
1604 }
1605
1606 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
1607 {
1608 return PECI_CC_DRIVER_ERR;
1609 }
1610
1611 cmd.addr = target;
1612 cmd.subopcode = subopcode;
1613 cmd.param0 = param0;
1614 cmd.param1 = param1;
1615 cmd.param2 = param2;
1616 cmd.rx_len = u8ReadLen;
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001617 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001618
1619 ret = HW_peci_issue_cmd(PECI_IOC_CRASHDUMP_DISC, (char*)&cmd, peci_fd);
1620 *cc = cmd.cc;
1621 if (ret == PECI_CC_SUCCESS)
1622 {
1623 memcpy(pData, cmd.data, u8ReadLen);
1624 }
1625 else
1626 {
1627 ret = PECI_CC_DRIVER_ERR;
1628 }
1629
1630 peci_Close(peci_fd);
1631 return ret;
1632}
1633
1634/*-------------------------------------------------------------------------
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001635 * This function provides crashdump GetFrame data over PECI
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001636 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001637EPECIStatus peci_CrashDump_GetFrame(
1638 uint8_t target, uint16_t param0, uint16_t param1, uint16_t param2,
1639 uint8_t u8ReadLen, uint8_t* pData, uint8_t* cc)
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001640{
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001641 // Default to domain ID 0
1642 return peci_CrashDump_GetFrame_dom(target, 0, param0, param1, param2,
1643 u8ReadLen, pData, cc);
1644}
1645
1646/*-------------------------------------------------------------------------
1647 * This function provides crashdump GetFrame data over PECI in the specified
1648 * domain
1649 *------------------------------------------------------------------------*/
Patrick Williamsc96261e2024-08-16 15:22:05 -04001650EPECIStatus peci_CrashDump_GetFrame_dom(
1651 uint8_t target, uint8_t domainId, uint16_t param0, uint16_t param1,
1652 uint16_t param2, uint8_t u8ReadLen, uint8_t* pData, uint8_t* cc)
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001653{
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001654 int peci_fd = -1;
Nirav Shahfd5dfd52022-03-09 12:29:41 -08001655 struct peci_crashdump_get_frame_msg cmd = {0};
Jason M. Billsbc641112020-08-19 16:31:53 -07001656 EPECIStatus ret = PECI_CC_SUCCESS;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001657
1658 if (pData == NULL || cc == NULL)
1659 {
1660 return PECI_CC_INVALID_REQ;
1661 }
1662
Jason M. Bills6ca31642020-08-06 10:26:19 -07001663 // The target address must be in the valid range
1664 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1665 {
1666 return PECI_CC_INVALID_REQ;
1667 }
1668
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001669 // Per the PECI spec, the read length must be a qword or dqword
1670 if (u8ReadLen != 8 && u8ReadLen != 16)
1671 {
1672 return PECI_CC_INVALID_REQ;
1673 }
1674
1675 // The PECI buffer must be large enough to hold the requested data
1676 if (sizeof(cmd.data) < u8ReadLen)
1677 {
1678 return PECI_CC_INVALID_REQ;
1679 }
1680
1681 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
1682 {
1683 return PECI_CC_DRIVER_ERR;
1684 }
1685
1686 cmd.addr = target;
1687 cmd.param0 = param0;
1688 cmd.param1 = param1;
1689 cmd.param2 = param2;
1690 cmd.rx_len = u8ReadLen;
Jason M. Bills8bb8f372022-03-01 16:04:44 -08001691 cmd.domain_id = domainId;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001692
1693 ret = HW_peci_issue_cmd(PECI_IOC_CRASHDUMP_GET_FRAME, (char*)&cmd, peci_fd);
1694 *cc = cmd.cc;
1695 if (ret == PECI_CC_SUCCESS)
1696 {
1697 memcpy(pData, cmd.data, u8ReadLen);
1698 }
1699 else
1700 {
1701 ret = PECI_CC_DRIVER_ERR;
1702 }
1703
1704 peci_Close(peci_fd);
1705 return ret;
1706}
1707
1708/*-------------------------------------------------------------------------
1709 * This function provides raw PECI command access
1710 *------------------------------------------------------------------------*/
1711EPECIStatus peci_raw(uint8_t target, uint8_t u8ReadLen, const uint8_t* pRawCmd,
1712 const uint32_t cmdSize, uint8_t* pRawResp,
1713 uint32_t respSize)
1714{
1715 int peci_fd = -1;
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001716 if (u8ReadLen && pRawResp == NULL)
1717 {
1718 return PECI_CC_INVALID_REQ;
1719 }
1720
Jason M. Bills6ca31642020-08-06 10:26:19 -07001721 // The target address must be in the valid range
1722 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1723 {
1724 return PECI_CC_INVALID_REQ;
1725 }
1726
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001727 if (peci_Open(&peci_fd) != PECI_CC_SUCCESS)
1728 {
1729 return PECI_CC_DRIVER_ERR;
1730 }
1731
Zbigniew Kurzynskif2a5fa22023-11-06 13:48:11 +01001732 EPECIStatus ret = peci_raw_seq(target, u8ReadLen, pRawCmd, cmdSize,
1733 pRawResp, respSize, peci_fd);
1734 peci_Close(peci_fd);
1735 return ret;
1736}
1737
1738/*-------------------------------------------------------------------------
1739 * This function provides sequential raw PECI command access
1740 *------------------------------------------------------------------------*/
1741EPECIStatus peci_raw_seq(uint8_t target, uint8_t u8ReadLen,
1742 const uint8_t* pRawCmd, const uint32_t cmdSize,
1743 uint8_t* pRawResp, uint32_t respSize, int peci_fd)
1744{
1745 struct peci_xfer_msg cmd = {0};
1746 uint8_t u8TxBuf[PECI_BUFFER_SIZE] = {0};
1747 uint8_t u8RxBuf[PECI_BUFFER_SIZE] = {0};
1748 EPECIStatus ret = PECI_CC_SUCCESS;
1749
1750 if (u8ReadLen && pRawResp == NULL)
1751 {
1752 return PECI_CC_INVALID_REQ;
1753 }
1754
1755 // The target address must be in the valid range
1756 if (target < MIN_CLIENT_ADDR || target > MAX_CLIENT_ADDR)
1757 {
1758 return PECI_CC_INVALID_REQ;
1759 }
1760
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001761 // Check for valid buffer sizes
1762 if (cmdSize > PECI_BUFFER_SIZE || respSize < u8ReadLen ||
1763 u8ReadLen >
1764 (PECI_BUFFER_SIZE - 1)) // response buffer is data + 1 status byte
1765 {
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001766 return PECI_CC_INVALID_REQ;
1767 }
1768
1769 cmd.addr = target;
1770 cmd.tx_len = (uint8_t)cmdSize;
1771 cmd.rx_len = u8ReadLen;
1772
1773 memcpy(u8TxBuf, pRawCmd, cmdSize);
1774
1775 cmd.tx_buf = u8TxBuf;
1776 cmd.rx_buf = u8RxBuf;
1777 ret = HW_peci_issue_cmd(PECI_IOC_XFER, (char*)&cmd, peci_fd);
1778
1779 if (ret == PECI_CC_SUCCESS || ret == PECI_CC_TIMEOUT)
1780 {
1781 memcpy(pRawResp, u8RxBuf, u8ReadLen);
1782 }
1783
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001784 return ret;
1785}
1786
1787/*-------------------------------------------------------------------------
1788 * This function returns the CPUID (Model and stepping) for the given PECI
1789 * client address
1790 *------------------------------------------------------------------------*/
1791EPECIStatus peci_GetCPUID(const uint8_t clientAddr, CPUModel* cpuModel,
1792 uint8_t* stepping, uint8_t* cc)
1793{
1794 EPECIStatus ret = PECI_CC_SUCCESS;
1795 uint32_t cpuid = 0;
1796
1797 if (cpuModel == NULL || stepping == NULL || cc == NULL)
1798 {
1799 return PECI_CC_INVALID_REQ;
1800 }
1801
Jason M. Bills6ca31642020-08-06 10:26:19 -07001802 // The client address must be in the valid range
1803 if (clientAddr < MIN_CLIENT_ADDR || clientAddr > MAX_CLIENT_ADDR)
1804 {
1805 return PECI_CC_INVALID_REQ;
1806 }
1807
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001808 if (peci_Ping(clientAddr) != PECI_CC_SUCCESS)
1809 {
1810 return PECI_CC_CPU_NOT_PRESENT;
1811 }
1812
Patrick Williamsc96261e2024-08-16 15:22:05 -04001813 ret =
1814 peci_RdPkgConfig(clientAddr, PECI_MBX_INDEX_CPU_ID, PECI_PKG_ID_CPU_ID,
1815 sizeof(uint32_t), (uint8_t*)&cpuid, cc);
Jason M. Bills7ef5a552020-04-06 14:58:44 -07001816
1817 // Separate out the model and stepping (bits 3:0) from the CPUID
1818 *cpuModel = cpuid & 0xFFFFFFF0;
1819 *stepping = (uint8_t)(cpuid & 0x0000000F);
1820 return ret;
1821}