samples: drivers: peci: Add PECI driver sample app
Sample code that showcase PECI API get device CPU information then monitors temperature. Verified in Modular MEC1501 connected to computer (PECI host). Signed-off-by: Jose Alberto Meza <jose.a.meza.arellano@intel.com>
This commit is contained in:
parent
55e6b294f2
commit
fc3293ed1f
5 changed files with 262 additions and 0 deletions
8
samples/drivers/peci/CMakeLists.txt
Normal file
8
samples/drivers/peci/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(peci)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
27
samples/drivers/peci/README.rst
Normal file
27
samples/drivers/peci/README.rst
Normal file
|
@ -0,0 +1,27 @@
|
|||
.. peci-sample:
|
||||
|
||||
PECI Interface
|
||||
####################################
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
This sample demonstrates how to use the :ref:`PECI API <peci>`.
|
||||
Callbacks are registered that will write to the console indicating PECI events.
|
||||
These events indicate PECI host interaction.
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
|
||||
The sample can be built and executed on boards supporting PECI.
|
||||
Please connect ensure the microcontroller used is connected to a PECI Host
|
||||
in order to execute.
|
||||
|
||||
Sample output
|
||||
=============
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
PECI test
|
||||
Note: You are expected to see several interactions including ID and
|
||||
temperature retrieval.
|
3
samples/drivers/peci/prj.conf
Normal file
3
samples/drivers/peci/prj.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_PECI=y
|
12
samples/drivers/peci/sample.yaml
Normal file
12
samples/drivers/peci/sample.yaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
sample:
|
||||
name: PECI driver sample
|
||||
tests:
|
||||
sample.drivers.peci:
|
||||
tags: drivers
|
||||
harness: console
|
||||
harness_config:
|
||||
type: multi_line
|
||||
ordered: true
|
||||
regex:
|
||||
- "mb data(.*)"
|
||||
depends_on: peci
|
212
samples/drivers/peci/src/main.c
Normal file
212
samples/drivers/peci/src/main.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <sys/printk.h>
|
||||
#include <drivers/peci.h>
|
||||
#include <soc.h>
|
||||
|
||||
#define TASK_STACK_SIZE 1024
|
||||
#define PRIORITY 7
|
||||
|
||||
/* PECI Host address */
|
||||
#define PECI_HOST_ADDR 0x30u
|
||||
/* PECI Host bitrate 1Mbps */
|
||||
#define PECI_HOST_BITRATE 1000u
|
||||
|
||||
#define PECI_CONFIGINDEX_TJMAX 16u
|
||||
#define PECI_CONFIGHOSTID 0u
|
||||
#define PECI_CONFIGPARAM 0u
|
||||
|
||||
#define PECI_SAFE_TEMP 72
|
||||
|
||||
static struct device *peci_dev;
|
||||
static bool peci_initialized;
|
||||
static u8_t tjmax;
|
||||
static u8_t rx_fcs;
|
||||
static void monitor_temperature_func(void *dummy1, void *dummy2, void *dummy3);
|
||||
|
||||
static struct k_thread temp_id;
|
||||
K_THREAD_STACK_DEFINE(temp_stack, TASK_STACK_SIZE);
|
||||
|
||||
int peci_ping(void)
|
||||
{
|
||||
int ret;
|
||||
struct peci_msg packet;
|
||||
|
||||
printk("%s\n", __func__);
|
||||
|
||||
packet.addr = PECI_HOST_ADDR;
|
||||
packet.cmd_code = PECI_CMD_PING;
|
||||
packet.tx_buffer.buf = NULL;
|
||||
packet.tx_buffer.len = PECI_PING_WR_LEN;
|
||||
packet.rx_buffer.buf = NULL;
|
||||
packet.rx_buffer.len = PECI_PING_RD_LEN;
|
||||
|
||||
ret = peci_transfer(peci_dev, &packet);
|
||||
if (ret) {
|
||||
printk("ping failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int peci_get_tjmax(u8_t *tjmax)
|
||||
{
|
||||
int ret;
|
||||
int retries = 3;
|
||||
u8_t peci_resp;
|
||||
struct peci_msg packet;
|
||||
|
||||
u8_t peci_resp_buf[PECI_RD_PKG_LEN_DWORD+1];
|
||||
u8_t peci_req_buf[] = { PECI_CONFIGHOSTID,
|
||||
PECI_CONFIGINDEX_TJMAX,
|
||||
PECI_CONFIGPARAM & 0x00FF,
|
||||
(PECI_CONFIGPARAM & 0xFF00) >> 8,
|
||||
};
|
||||
|
||||
packet.tx_buffer.buf = peci_req_buf;
|
||||
packet.tx_buffer.len = PECI_RD_PKG_WR_LEN;
|
||||
packet.rx_buffer.buf = peci_resp_buf;
|
||||
packet.rx_buffer.len = PECI_RD_PKG_LEN_DWORD;
|
||||
|
||||
do {
|
||||
rx_fcs = 0;
|
||||
packet.addr = PECI_HOST_ADDR;
|
||||
packet.cmd_code = PECI_CMD_RD_PKG_CFG0;
|
||||
|
||||
ret = peci_transfer(peci_dev, &packet);
|
||||
|
||||
for (int i = 0; i < PECI_RD_PKG_LEN_DWORD; i++) {
|
||||
printk("%02x\n", packet.rx_buffer.buf[i]);
|
||||
}
|
||||
|
||||
peci_resp = packet.rx_buffer.buf[0];
|
||||
rx_fcs = packet.rx_buffer.buf[PECI_RD_PKG_LEN_DWORD];
|
||||
k_sleep(1);
|
||||
printk("\npeci_resp %x\n", peci_resp);
|
||||
retries--;
|
||||
} while ((peci_resp != PECI_RW_PKG_CFG_RSP_PASS) && (retries > 0));
|
||||
|
||||
*tjmax = packet.rx_buffer.buf[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int peci_get_temp(int *temperature)
|
||||
{
|
||||
s16_t raw_cpu_temp;
|
||||
int ret;
|
||||
struct peci_msg packet = {0};
|
||||
|
||||
u8_t peci_resp_buf[PECI_GET_TEMP_RD_LEN+1];
|
||||
|
||||
rx_fcs = 0;
|
||||
packet.tx_buffer.buf = NULL;
|
||||
packet.tx_buffer.len = PECI_GET_TEMP_WR_LEN;
|
||||
packet.rx_buffer.buf = peci_resp_buf;
|
||||
packet.rx_buffer.len = PECI_GET_TEMP_RD_LEN;
|
||||
|
||||
packet.addr = PECI_HOST_ADDR;
|
||||
packet.cmd_code = PECI_CMD_GET_TEMP0;
|
||||
|
||||
ret = peci_transfer(peci_dev, &packet);
|
||||
if (ret) {
|
||||
printk("Get temp failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rx_fcs = packet.rx_buffer.buf[PECI_GET_TEMP_RD_LEN];
|
||||
printk("R FCS %x\n", rx_fcs);
|
||||
printk("Temp bytes: %02x", packet.rx_buffer.buf[0]);
|
||||
printk("%02x\n", packet.rx_buffer.buf[1]);
|
||||
|
||||
raw_cpu_temp = (s16_t)(packet.rx_buffer.buf[0] |
|
||||
(s16_t)((packet.rx_buffer.buf[1] << 8) & 0xFF00));
|
||||
|
||||
if (raw_cpu_temp == 0x8000) {
|
||||
printk("Invalid temp %x\n", raw_cpu_temp);
|
||||
*temperature = PECI_SAFE_TEMP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
raw_cpu_temp = (raw_cpu_temp >> 6) | 0x7E00;
|
||||
*temperature = raw_cpu_temp + tjmax;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void read_temp(void)
|
||||
{
|
||||
int ret;
|
||||
int temp;
|
||||
|
||||
ret = peci_get_temp(&temp);
|
||||
|
||||
if (!ret) {
|
||||
printk("Temperature %d C\n", temp);
|
||||
}
|
||||
}
|
||||
|
||||
void get_max_temp(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = peci_get_tjmax(&tjmax);
|
||||
if (ret) {
|
||||
printk("Fail to obtain maximum temperature: %d\n", ret);
|
||||
} else {
|
||||
printk("Maximum temperature: %u\n", tjmax);
|
||||
}
|
||||
}
|
||||
|
||||
static void monitor_temperature_func(void *dummy1, void *dummy2, void *dummy3)
|
||||
{
|
||||
while (true) {
|
||||
k_sleep(1000);
|
||||
if (peci_initialized) {
|
||||
read_temp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
#ifdef DT_ALIAS_PECI_0_LABEL
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
printk("PECI sample test\n");
|
||||
|
||||
k_thread_create(&temp_id, temp_stack, TASK_STACK_SIZE,
|
||||
monitor_temperature_func, NULL, NULL, NULL, PRIORITY,
|
||||
K_INHERIT_PERMS, K_FOREVER);
|
||||
|
||||
#ifdef DT_ALIAS_PECI_0_LABEL
|
||||
peci_dev = device_get_binding(DT_ALIAS_PECI_0_LABEL);
|
||||
if (!peci_dev) {
|
||||
printk("Err: PECI device not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = peci_config(peci_dev, 1000u);
|
||||
if (ret) {
|
||||
printk("Err: Fail to configure bitrate\n");
|
||||
return;
|
||||
}
|
||||
|
||||
peci_enable(peci_dev);
|
||||
|
||||
tjmax = 100;
|
||||
|
||||
get_max_temp();
|
||||
printk("Start thread...\n");
|
||||
k_thread_start(&temp_id);
|
||||
|
||||
peci_initialized = true;
|
||||
#endif
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue