From fc3293ed1fa4b60a5d611f8c76b05561495f5c35 Mon Sep 17 00:00:00 2001 From: Jose Alberto Meza Date: Tue, 4 Feb 2020 17:45:16 -0800 Subject: [PATCH] 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 --- samples/drivers/peci/CMakeLists.txt | 8 ++ samples/drivers/peci/README.rst | 27 ++++ samples/drivers/peci/prj.conf | 3 + samples/drivers/peci/sample.yaml | 12 ++ samples/drivers/peci/src/main.c | 212 ++++++++++++++++++++++++++++ 5 files changed, 262 insertions(+) create mode 100644 samples/drivers/peci/CMakeLists.txt create mode 100644 samples/drivers/peci/README.rst create mode 100644 samples/drivers/peci/prj.conf create mode 100644 samples/drivers/peci/sample.yaml create mode 100644 samples/drivers/peci/src/main.c diff --git a/samples/drivers/peci/CMakeLists.txt b/samples/drivers/peci/CMakeLists.txt new file mode 100644 index 00000000000..0832823533c --- /dev/null +++ b/samples/drivers/peci/CMakeLists.txt @@ -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}) diff --git a/samples/drivers/peci/README.rst b/samples/drivers/peci/README.rst new file mode 100644 index 00000000000..10ef4ed5eef --- /dev/null +++ b/samples/drivers/peci/README.rst @@ -0,0 +1,27 @@ +.. peci-sample: + +PECI Interface +#################################### + +Overview +******** + +This sample demonstrates how to use the :ref:`PECI API `. +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. diff --git a/samples/drivers/peci/prj.conf b/samples/drivers/peci/prj.conf new file mode 100644 index 00000000000..5b7a3806058 --- /dev/null +++ b/samples/drivers/peci/prj.conf @@ -0,0 +1,3 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_PRINTK=y +CONFIG_PECI=y diff --git a/samples/drivers/peci/sample.yaml b/samples/drivers/peci/sample.yaml new file mode 100644 index 00000000000..c6aa244f47d --- /dev/null +++ b/samples/drivers/peci/sample.yaml @@ -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 diff --git a/samples/drivers/peci/src/main.c b/samples/drivers/peci/src/main.c new file mode 100644 index 00000000000..7315074803f --- /dev/null +++ b/samples/drivers/peci/src/main.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#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 +}