| /* |
| * 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(); |
| } |