Skip to content
Permalink
Browse files

samples: drivers: espi: Add eSPI driver sample app

Show eSPI API driver usage, including early configuration,
send of virtual wire packets and callback mechanism

Signed-off-by: Jose Alberto Meza <jose.a.meza.arellano@intel.com>
  • Loading branch information...
Jose Alberto Meza authored and andrewboie committed May 22, 2019
1 parent 64c334f commit 11d07254894120613083671fee1d1508d8fcc218
@@ -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(espi)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
@@ -0,0 +1,43 @@
# Kconfig - Private config options for eSPI sample app

#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#

mainmenu "Enhanced Serial Peripheral Interface application"

config ESPI_DEV
string "Name of the eSPI device"
default "ESPI_0"
help
Name of the eSPI device used for send an receive.

config ESPI_VIRTUAL_WIRE_TIMEOUT
int "Timeout for virtual wires"
default 5000
help
Timeout for virtual wires

config ESPI_GPIO_DEV_NEEDED
bool "GPIO required for minimum eSPI handshake"
default n

if ESPI_GPIO_DEV_NEEDED

config ESPI_GPIO_DEV
string "Name of the GPIO port"
default "GPIO_0"
help
Name of the port used in mimimal handshake

config ESPI_INIT_PIN
int "eSPI master enable pin"
default 0
help
Pin number of eSPI master init pin

endif # ESPI_GPIO_DEV_NEEDED

source "Kconfig.zephyr"
@@ -0,0 +1,44 @@
.. espi-sample:
Enhanced Serial Peripheral Interface
####################################

Overview
********

This sample demonstrates how to use the Enhanced Serial Peripheral Interface
(eSPI) API.
It shows how to configure and select eSPI controller capabilities as part of
a simple eSPI handshake that includes exchanging virtual wire packets.

Standard platform signals are sent virtual wire packets over the bus.
Callbacks are registered that will write to the console indicating main
eSPI events and when a virtual wire is received.

Building and Running
********************

The sample can be built and executed on boards supporting eSPI.
Any pins required for minimum eSPI handshake should be configured.

Sample output
=============

.. code-block:: console

Hello eSPI test!
eSPI test - I/O initialization...complete
eSPI slave configured successfully!
eSPI test - callbacks initialization... complete
eSPI test - callbacks registration... complete
eSPI test - Power initialization...complete
eSPI test - Handshake
eSPI BUS reset 0
VW channel is ready

PLT_RST changed 1
1st phase completed
2nd phase completed
3rd phase completed

note:: The values shown above might differ.
@@ -0,0 +1,4 @@
CONFIG_ESPI=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_PRINTK=y

@@ -0,0 +1,7 @@
# eSPI + mec15xxevb_assy6853
CONFIG_ESPI=y
CONFIG_ESPI_DEV="ESPI_0"
CONFIG_ESPI_GPIO_DEV_NEEDED=y
CONFIG_ESPI_GPIO_DEV="GPIO040_076"
CONFIG_ESPI_INIT_PIN=12
CONFIG_LOG=y
@@ -0,0 +1,17 @@
sample:
name: eSPI driver sample
tests:
sample.driver.espi:
tags: drivers
harness: console
harness_config:
type: multi_line
ordered: true
regex:
- "Hello eSPI test (.*)"
- "eSPI test - I/O initialization...complete"
- "eSPI slave configured successfully!"
- "eSPI test - callbacks initialization... complete"
- "eSPI test - Power initialization...complete"
- "eSPI BUS reset (.*)"
depends_on: espi
@@ -0,0 +1,230 @@
/*
* Copyright (c) 2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <errno.h>
#include <zephyr.h>
#include <misc/printk.h>
#include <device.h>
#include <soc.h>
#include <gpio.h>
#include <espi.h>

#ifdef CONFIG_ESPI_GPIO_DEV_NEEDED
static struct device *gpio_dev;
#endif

static struct device *espi_dev;

static struct espi_callback espi_bus_cb;
static struct espi_callback vw_rdy_cb;
static struct espi_callback vw_cb;
static struct espi_callback p80_cb;

/* eSPI bus event handler */
static void espi_reset_handler(struct device *dev,
struct espi_callback *cb,
struct espi_event event)
{
if (event.evt_type == ESPI_BUS_RESET) {
printk("\neSPI BUS reset %d", event.evt_data);
}
}

/* eSPI logical channels enable/disable event handler */
static void espi_ch_handler(struct device *dev, struct espi_callback *cb,
struct espi_event event)
{
if (event.evt_type == ESPI_BUS_EVENT_CHANNEL_READY) {
if (event.evt_details == ESPI_CHANNEL_VWIRE) {
printk("\nVW channel is ready\n");
}
}
}

/* eSPI vwire received event handler */
static void vwire_handler(struct device *dev, struct espi_callback *cb,
struct espi_event event)
{
if (event.evt_type == ESPI_BUS_EVENT_VWIRE_RECEIVED) {
if (event.evt_details == ESPI_VWIRE_SIGNAL_PLTRST) {
printk("\nPLT_RST changed %d\n", event.evt_data);
}
}
}

/* eSPI peripheral channel notifications handler */
static void periph_handler(struct device *dev, struct espi_callback *cb,
struct espi_event event)
{
u8_t peripheral;

if (event.evt_type == ESPI_BUS_PERIPHERAL_NOTIFICATION) {
peripheral = event.evt_details & 0x00FF;

switch (peripheral) {
case ESPI_PERIPHERAL_DEBUG_PORT80:
printk("Postcode %x\n", event.evt_data);
break;
case ESPI_PERIPHERAL_HOST_IO:
printk("ACPI %x\n", event.evt_data);
break;
default:
printk("\n%s periph 0x%x [%x]\n", __func__, peripheral,
event.evt_data);
}
}
}

int espi_init(void)
{
int ret;
/* Indicate to eSPI master simplest configuration: Single line,
* 20MHz frequency and only logical channel 0 and 1 are supported
*/
struct espi_cfg cfg = {
ESPI_IO_MODE_SINGLE_LINE,
ESPI_CHANNEL_VWIRE | ESPI_CHANNEL_PERIPHERAL,
20,
};

ret = espi_config(espi_dev, &cfg);
if (ret) {
printk("Failed to configure eSPI slave! error (%d)\n", ret);
} else {
printk("eSPI slave configured successfully!\n");
}

printk("eSPI test - callbacks initialization... ");
espi_init_callback(&espi_bus_cb, espi_reset_handler, ESPI_BUS_RESET);
espi_init_callback(&vw_rdy_cb, espi_ch_handler,
ESPI_BUS_EVENT_CHANNEL_READY);
espi_init_callback(&vw_cb, vwire_handler,
ESPI_BUS_EVENT_VWIRE_RECEIVED);
espi_init_callback(&p80_cb, periph_handler,
ESPI_BUS_PERIPHERAL_NOTIFICATION);
printk("complete\n");

printk("eSPI test - callbacks registration... ");
espi_add_callback(espi_dev, &espi_bus_cb);
espi_add_callback(espi_dev, &vw_rdy_cb);
espi_add_callback(espi_dev, &vw_cb);
espi_add_callback(espi_dev, &p80_cb);
printk("complete\n");

return ret;
}

int wait_for_vwire(struct device *espi_dev, enum espi_vwire_signal signal,
u16_t timeout, u8_t exp_level)
{
int ret;
u8_t level;
u16_t loop_cnt = timeout;

do {
ret = espi_receive_vwire(espi_dev, signal, &level);
if (ret) {
printk("Failed to read %x %d", signal, ret);
return -EIO;
}

if (exp_level == level) {
break;
}

k_busy_wait(50);
loop_cnt--;
} while (loop_cnt > 0);

if (loop_cnt == 0) {
printk("VWIRE %d! is %x\n", signal, level);
return -ETIMEDOUT;
}

return 0;
}

int espi_handshake(void)
{
int ret;

printk("eSPI test - Handshake with eSPI master...\n");
ret = wait_for_vwire(espi_dev, ESPI_VWIRE_SIGNAL_SUS_WARN,
CONFIG_ESPI_VIRTUAL_WIRE_TIMEOUT, 1);
if (ret) {
printk("SUS_WARN Timeout!");
return ret;
}

printk("\t1st phase completed\n");
ret = wait_for_vwire(espi_dev, ESPI_VWIRE_SIGNAL_SLP_S5,
CONFIG_ESPI_VIRTUAL_WIRE_TIMEOUT, 1);
if (ret) {
printk("SLP_S5 Timeout!");
return ret;
}

ret = wait_for_vwire(espi_dev, ESPI_VWIRE_SIGNAL_SLP_S4,
CONFIG_ESPI_VIRTUAL_WIRE_TIMEOUT, 1);
if (ret) {
printk("SLP_S4 Timeout!");
return ret;
}

ret = wait_for_vwire(espi_dev, ESPI_VWIRE_SIGNAL_SLP_S3,
CONFIG_ESPI_VIRTUAL_WIRE_TIMEOUT, 1);
if (ret) {
printk("SLP_S3 Timeout!");
return ret;
}

printk("\t2nd phase completed\n");
return 0;
}

void main(void)
{
int ret;

k_sleep(500);

#ifdef CONFIG_ESPI_GPIO_DEV_NEEDED
gpio_dev = device_get_binding(CONFIG_ESPI_GPIO_DEV);
if (gpio_dev) {
printk("%s FOUND!\n", CONFIG_ESPI_GPIO_DEV);
}
#endif
espi_dev = device_get_binding(CONFIG_ESPI_DEV);
if (espi_dev) {
printk("%s FOUND!\n", CONFIG_ESPI_DEV);
}

printk("Hello eSPI test! %s\n", CONFIG_BOARD);

#ifdef CONFIG_ESPI_GPIO_DEV_NEEDED
ret = gpio_pin_configure(gpio_dev, CONFIG_ESPI_INIT_PIN, GPIO_DIR_OUT);
if (ret) {
printk("Unable to configure %d ", CONFIG_ESPI_INIT_PIN);
}

ret = gpio_pin_write(gpio_dev, CONFIG_ESPI_INIT_PIN, 0);
if (ret) {
printk("Unable to initialize %d ", CONFIG_ESPI_INIT_PIN);
}
#endif

espi_init();

#ifdef CONFIG_ESPI_GPIO_DEV_NEEDED
k_sleep(1000);
ret = gpio_pin_write(gpio_dev, CONFIG_ESPI_INIT_PIN, 1);
if (ret) {
printk("Failed to write %x %d", CONFIG_ESPI_INIT_PIN, ret);
}
#endif

espi_handshake();
}

0 comments on commit 11d0725

Please sign in to comment.
You can’t perform that action at this time.