- 
                Notifications
    
You must be signed in to change notification settings  - Fork 8.2k
 
The emulation system for eSPI #31139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
          
     Merged
      
      
            nashif
  merged 2 commits into
  zephyrproject-rtos:master
from
niedzwiecki-dawid:emul_espi
  
      
      
   
  Jan 20, 2021 
      
    
  
     Merged
                    Changes from all commits
      Commits
    
    
            Show all changes
          
          
            2 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      
    File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # Copyright 2020 Google LLC | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| 
     | 
||
| config ESPI_EMUL | ||
| bool "eSPI emulator" | ||
| help | ||
| Enable the eSPI emulator driver. This is a fake driver, | ||
| it does not talk to real hardware. Instead it talks to emulation | ||
| drivers that pretend to be devices on the emulated eSPI bus. It is | ||
| used for testing drivers for eSPI devices. | ||
| 
     | 
||
| eSPI is an interface using SPI wires, whose main goal is to reduce the | ||
| number of required pins. It includes the functionality of LPC, SMB, SPI | ||
| itself (flash access) and GPIO (virtual wires). Please refer to the | ||
| specification for more details (it is good for the introduction as well) | ||
| https://www.intel.com/content/dam/support/us/en/documents/software/chipset-software/327432-004_espi_base_specification_rev1.0_cb.pdf | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,207 @@ | ||
| /* | ||
| * Copyright 2020 Google LLC | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| * This driver creates fake eSPI buses which can contain emulated devices | ||
| * (mainly host), implemented by a separate emulation driver. | ||
| * The API between this driver/controller and device emulators attached | ||
| * to its bus is defined by struct emul_espi_device_api. | ||
                
      
                  sjg20 marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| */ | ||
| 
     | 
||
| #define DT_DRV_COMPAT zephyr_espi_emul_controller | ||
| 
     | 
||
| #define LOG_LEVEL CONFIG_ESPI_LOG_LEVEL | ||
| #include <logging/log.h> | ||
| LOG_MODULE_REGISTER(espi_emul_ctlr); | ||
| 
     | 
||
| #include <device.h> | ||
| #include <emul.h> | ||
| #include <drivers/espi.h> | ||
| #include <drivers/espi_emul.h> | ||
| #include "espi_utils.h" | ||
| 
     | 
||
| /** Working data for the controller */ | ||
| struct espi_emul_data { | ||
| /* List of struct espi_emul associated with the device */ | ||
| sys_slist_t emuls; | ||
| /* eSPI host configuration */ | ||
| struct espi_cfg cfg; | ||
| /** List of eSPI callbacks */ | ||
| sys_slist_t callbacks; | ||
| }; | ||
| 
     | 
||
| static struct espi_emul *espi_emul_find(const struct device *dev, | ||
| unsigned int chipsel) | ||
| { | ||
| struct espi_emul_data *data = dev->data; | ||
| sys_snode_t *node; | ||
| 
     | 
||
| SYS_SLIST_FOR_EACH_NODE(&data->emuls, node) { | ||
| struct espi_emul *emul; | ||
| 
     | 
||
| emul = CONTAINER_OF(node, struct espi_emul, node); | ||
| if (emul->chipsel == chipsel) { | ||
| return emul; | ||
| } | ||
| } | ||
| 
     | 
||
| return NULL; | ||
| } | ||
| 
     | 
||
| static int espi_emul_config(const struct device *dev, struct espi_cfg *cfg) | ||
| { | ||
| struct espi_emul_data *data = dev->data; | ||
| 
     | 
||
| __ASSERT_NO_MSG(cfg); | ||
| 
     | 
||
| data->cfg = *cfg; | ||
| 
     | 
||
| return 0; | ||
| } | ||
| 
     | 
||
| 
     | 
||
| static int emul_espi_trigger_event(const struct device *dev, | ||
| struct espi_event *evt) | ||
| { | ||
| struct espi_emul_data *data = dev->data; | ||
| 
     | 
||
| if (((evt->evt_type & ESPI_BUS_EVENT_VWIRE_RECEIVED) && | ||
| !(data->cfg.channel_caps & ESPI_CHANNEL_VWIRE)) || | ||
| ((evt->evt_type & ESPI_BUS_EVENT_OOB_RECEIVED) && | ||
| !(data->cfg.channel_caps & ESPI_CHANNEL_OOB)) || | ||
| ((evt->evt_type & ESPI_BUS_PERIPHERAL_NOTIFICATION) | ||
| && !(data->cfg.channel_caps & ESPI_CHANNEL_PERIPHERAL))) { | ||
| return -EIO; | ||
| } | ||
| 
     | 
||
| espi_send_callbacks(&data->callbacks, dev, *evt); | ||
| 
     | 
||
| return 0; | ||
| } | ||
| 
     | 
||
| static bool espi_emul_get_channel_status(const struct device *dev, enum espi_channel ch) | ||
| { | ||
| struct espi_emul_data *data = dev->data; | ||
| 
     | 
||
| return (data->cfg.channel_caps & ch); | ||
| } | ||
| 
     | 
||
| static int espi_emul_send_vwire(const struct device *dev, enum espi_vwire_signal vw, uint8_t level) | ||
| { | ||
| const struct emul_espi_device_api *api; | ||
| struct espi_emul *emul; | ||
| struct espi_emul_data *data = dev->data; | ||
| 
     | 
||
| if (!(data->cfg.channel_caps & ESPI_CHANNEL_VWIRE)) { | ||
| return -EIO; | ||
| } | ||
| 
     | 
||
| emul = espi_emul_find(dev, EMUL_ESPI_HOST_CHIPSEL); | ||
| if (!emul) { | ||
| LOG_DBG("espi_emul not found"); | ||
| return -EIO; | ||
| } | ||
| 
     | 
||
| __ASSERT_NO_MSG(emul->api); | ||
| __ASSERT_NO_MSG(emul->api->set_vw); | ||
| api = emul->api; | ||
| 
     | 
||
| return api->set_vw(emul, vw, level); | ||
| } | ||
| 
     | 
||
| static int espi_emul_receive_vwire(const struct device *dev, enum espi_vwire_signal vw, uint8_t *level) | ||
| { | ||
| const struct emul_espi_device_api *api; | ||
| struct espi_emul *emul; | ||
| struct espi_emul_data *data = dev->data; | ||
| 
     | 
||
| if (!(data->cfg.channel_caps & ESPI_CHANNEL_VWIRE)) { | ||
| return -EIO; | ||
| } | ||
| 
     | 
||
| emul = espi_emul_find(dev, EMUL_ESPI_HOST_CHIPSEL); | ||
| if (!emul) { | ||
| LOG_INF("espi_emul not found"); | ||
| return -EIO; | ||
| } | ||
| 
     | 
||
| __ASSERT_NO_MSG(emul->api); | ||
| __ASSERT_NO_MSG(emul->api->get_vw); | ||
| api = emul->api; | ||
| 
     | 
||
| return api->get_vw(emul, vw, level); | ||
| } | ||
| 
     | 
||
| static int espi_emul_manage_callback(const struct device *dev, struct espi_callback *callback, bool set) | ||
| { | ||
| struct espi_emul_data *data = dev->data; | ||
| 
     | 
||
| return espi_manage_callback(&data->callbacks, callback, set); | ||
| } | ||
| 
     | 
||
| /** | ||
| * Set up a new emulator and add it to the list | ||
| * | ||
| * @param dev eSPI emulation controller device | ||
| */ | ||
| static int espi_emul_init(const struct device *dev) | ||
| { | ||
| struct espi_emul_data *data = dev->data; | ||
| const struct emul_list_for_bus *list = dev->config; | ||
| 
     | 
||
| sys_slist_init(&data->emuls); | ||
| 
     | 
||
| return emul_init_for_bus_from_list(dev, list); | ||
| } | ||
| 
     | 
||
| int espi_emul_register(const struct device *dev, const char *name, | ||
| struct espi_emul *emul) | ||
| { | ||
| struct espi_emul_data *data = dev->data; | ||
| 
     | 
||
| sys_slist_append(&data->emuls, &emul->node); | ||
| 
     | 
||
| LOG_INF("Register emulator '%s' at cs %u\n", name, emul->chipsel); | ||
| 
     | 
||
| return 0; | ||
| } | ||
| 
     | 
||
| /* Device instantiation */ | ||
| static struct emul_espi_driver_api emul_espi_driver_api = { | ||
| .espi_api = { | ||
| .config = espi_emul_config, | ||
| .get_channel_status = espi_emul_get_channel_status, | ||
| .send_vwire = espi_emul_send_vwire, | ||
| .receive_vwire = espi_emul_receive_vwire, | ||
| .manage_callback = espi_emul_manage_callback | ||
| }, | ||
| .trigger_event = emul_espi_trigger_event, | ||
| .find_emul = espi_emul_find, | ||
| }; | ||
| 
     | 
||
| 
     | 
||
| #define EMUL_LINK_AND_COMMA(node_id) { \ | ||
| .label = DT_LABEL(node_id), \ | ||
| }, | ||
| 
     | 
||
| #define ESPI_EMUL_INIT(n) \ | ||
| static const struct emul_link_for_bus emuls_##n[] = { \ | ||
| DT_FOREACH_CHILD(DT_DRV_INST(n), EMUL_LINK_AND_COMMA) \ | ||
| }; \ | ||
| static struct emul_list_for_bus espi_emul_cfg_##n = { \ | ||
| .children = emuls_##n, \ | ||
| .num_children = ARRAY_SIZE(emuls_##n), \ | ||
| }; \ | ||
| static struct espi_emul_data espi_emul_data_##n; \ | ||
| DEVICE_DT_INST_DEFINE(n, \ | ||
| &espi_emul_init, \ | ||
| device_pm_control_nop, \ | ||
| &espi_emul_data_##n, \ | ||
| &espi_emul_cfg_##n, \ | ||
| POST_KERNEL, \ | ||
| CONFIG_ESPI_INIT_PRIORITY, \ | ||
| &emul_espi_driver_api); | ||
| 
     | 
||
| 
     | 
||
| DT_INST_FOREACH_STATUS_OKAY(ESPI_EMUL_INIT) | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # Copyright 2020 Google LLC | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| 
     | 
||
| description: Zephyr eSPI Emulation controller | ||
| 
     | 
||
| compatible: "zephyr,espi-emul-controller" | ||
| 
     | 
||
| include: espi-controller.yaml | ||
| 
     | 
||
| properties: | ||
| reg: | ||
| required: true | 
      
      Oops, something went wrong.
        
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.