LCOV - code coverage report
Current view: top level - zephyr/pmci/mctp - mctp_i2c_gpio_controller.h Coverage Total Hit
Test: new.info Lines: 66.7 % 3 2
Test Date: 2025-09-05 20:47:19

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2025 Intel Corporation
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  *
       6              :  */
       7              : 
       8              : #ifndef ZEPHYR_MCTP_I2C_GPIO_CONTROLLER_H_
       9              : #define ZEPHYR_MCTP_I2C_GPIO_CONTROLLER_H_
      10              : 
      11              : #include <stdint.h>
      12              : #include <zephyr/kernel.h>
      13              : #include <zephyr/device.h>
      14              : #include <zephyr/drivers/i2c.h>
      15              : #include <zephyr/drivers/gpio.h>
      16              : #include <zephyr/sys/mpsc_lockfree.h>
      17              : #include <zephyr/rtio/rtio.h>
      18              : #include <zephyr/pmci/mctp/mctp_i2c_gpio_common.h>
      19              : 
      20              : #include <libmctp.h>
      21              : #include <stdatomic.h>
      22              : 
      23              : /** @cond INTERNAL_HIDDEN */
      24              : 
      25              : struct mctp_binding_i2c_gpio_controller;
      26              : 
      27              : struct mctp_i2c_gpio_controller_cb {
      28              :         struct mpsc_node q;
      29              :         struct gpio_callback callback;
      30              :         struct mctp_binding_i2c_gpio_controller *binding;
      31              :         uint8_t index;
      32              : };
      33              : 
      34              : /** @endcond INTERNAL_HIDDEN */
      35              : 
      36              : 
      37              : /**
      38              :  * @brief An MCTP binding for Zephyr's I2C interface using GPIO
      39              :  */
      40            1 : struct mctp_binding_i2c_gpio_controller {
      41              :         /** @cond INTERNAL_HIDDEN */
      42              :         struct mctp_binding binding;
      43              :         const struct device *i2c;
      44              : 
      45              :         uint8_t rx_buf_len;
      46              :         uint8_t rx_buf[MCTP_I2C_GPIO_MAX_PKT_SIZE];
      47              :         uint8_t tx_buf[MCTP_I2C_GPIO_MAX_PKT_SIZE];
      48              : 
      49              :         struct mctp_pktbuf *rx_pkt;
      50              : 
      51              :         /* Avoid needing a thread or work queue task by using RTIO */
      52              :         struct k_sem *tx_lock;
      53              :         struct rtio *r_tx;
      54              : 
      55              :         /* Mapping of endpoints to i2c targets with gpios */
      56              :         size_t num_endpoints;
      57              :         const uint8_t *endpoint_ids;
      58              :         const struct rtio_iodev **endpoint_iodevs;
      59              :         const struct gpio_dt_spec *endpoint_gpios;
      60              :         struct mctp_i2c_gpio_controller_cb *endpoint_gpio_cbs;
      61              : 
      62              :         /* Ongoing request from a particular gpio */
      63              :         struct k_spinlock rx_lock;
      64              :         struct rtio *r_rx;
      65              :         struct mpsc rx_q;
      66              :         struct mctp_i2c_gpio_controller_cb *inflight_rx;
      67              : 
      68              :         /** @endcond INTERNAL_HIDDEN */
      69              : };
      70              : 
      71              : /** @cond INTERNAL_HIDDEN */
      72              : int mctp_i2c_gpio_controller_start(struct mctp_binding *binding);
      73              : int mctp_i2c_gpio_controller_tx(struct mctp_binding *binding, struct mctp_pktbuf *pkt);
      74              : 
      75              : #define MCTP_I2C_GPIO_CONTROLLER_IODEV_NAME(_idx, _name) _name##_idx
      76              : 
      77              : #define MCTP_I2C_GPIO_CONTROLLER_IODEV_DEFINE(_node_id, addrs, _idx, _name)                        \
      78              :         I2C_IODEV_DEFINE(MCTP_I2C_GPIO_CONTROLLER_IODEV_NAME(_idx, _name),                         \
      79              :                 DT_PHANDLE(_node_id, i2c),                                                         \
      80              :                 DT_PROP_BY_IDX(_node_id, addrs, _idx));
      81              : 
      82              : 
      83              : #define MCTP_I2C_GPIO_CONTROLLER_DEFINE_GPIOS(_node_id, _name)                                     \
      84              :         const struct gpio_dt_spec _name##_endpoint_gpios[] = {                                     \
      85              :                 DT_FOREACH_PROP_ELEM_SEP(_node_id, endpoint_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,))   \
      86              :         }
      87              : 
      88              : #define MCTP_I2C_GPIO_CONTROLLER_DEFINE_IDS(_node_id, _name)                                       \
      89              :         const uint8_t _name##_endpoint_ids[] = DT_PROP(_node_id, endpoint_ids);
      90              : 
      91              : #define MCTP_I2C_GPIO_CONTROLLER_DEFINE_GPIO_CBS(_node_id, _name)                                  \
      92              :         struct mctp_i2c_gpio_controller_cb \
      93              :                 _name##_endpoint_gpio_cbs[DT_PROP_LEN(_node_id, endpoint_ids)]
      94              : 
      95              : 
      96              : #define MCTP_I2C_GPIO_CONTROLLER_DEFINE_IODEVS(_node_id, _name)                                    \
      97              :         DT_FOREACH_PROP_ELEM_VARGS(_node_id, endpoint_addrs,                                       \
      98              :                         MCTP_I2C_GPIO_CONTROLLER_IODEV_DEFINE, _name)                              \
      99              :                 const struct rtio_iodev *_name##_endpoint_iodevs[] = {                             \
     100              :                 LISTIFY(DT_PROP_LEN(_node_id, endpoint_ids), &MCTP_I2C_GPIO_CONTROLLER_IODEV_NAME, \
     101              :                                 (,), _name)                                                        \
     102              :         }
     103              : 
     104              : /** @endcond INTERNAL_HIDDEN */
     105              : 
     106              : /**
     107              :  * @brief Define a MCTP bus binding for I2C controller with GPIO
     108              :  *
     109              :  * Rather than mode switching as the MCTP standard wishes, this is a custom
     110              :  * binding. On the controller side each neighbor has an associated i2c address
     111              :  * and gpio it will listen for a trigger on. When triggered the controller will
     112              :  * read the target device. The target device will be expected to have what amounts
     113              :  * to two registers, one containing a message length and another containing a FIFO
     114              :  * like register producing the message bytes.
     115              :  *
     116              :  * Thus the sequence for a I2C target to send a message would be...
     117              :  *
     118              :  * 1. Setup a length and message value (pseudo registers).
     119              :  * 2. Signal the controller with a GPIO level set
     120              :  * 3. The controller then is expected to read the length (write of addr 0 + read 1 byte)
     121              :  * 4. The controller then is expected to read the message (write of addr 1 + read N bytes)
     122              :  * 5. The target clears the pin set
     123              :  * 6. The controller reports a message receive to MCTP
     124              :  *
     125              :  * @param _name Symbolic name of the bus binding variable
     126              :  * @param _node_id DeviceTree Node containing the configuration of this MCTP binding
     127              :  */
     128            1 : #define MCTP_I2C_GPIO_CONTROLLER_DT_DEFINE(_name, _node_id)                                        \
     129              :         RTIO_DEFINE(_name##_rtio_tx, 5, 5);                                                        \
     130              :         RTIO_DEFINE(_name##_rtio_rx, 5, 5);                                                        \
     131              :         MCTP_I2C_GPIO_CONTROLLER_DEFINE_IODEVS(_node_id, _name);                                   \
     132              :         MCTP_I2C_GPIO_CONTROLLER_DEFINE_GPIOS(_node_id, _name);                                    \
     133              :         MCTP_I2C_GPIO_CONTROLLER_DEFINE_IDS(_node_id, _name);                                      \
     134              :         MCTP_I2C_GPIO_CONTROLLER_DEFINE_GPIO_CBS(_node_id, _name);                                 \
     135              :         K_SEM_DEFINE(_name##_tx_lock, 1, 1);                                                       \
     136              :         struct mctp_binding_i2c_gpio_controller _name = {                                          \
     137              :                 .binding = {                                                                       \
     138              :                         .name = STRINGIFY(_name), .version = 1,                                    \
     139              :                         .start = mctp_i2c_gpio_controller_start,                                   \
     140              :                         .tx = mctp_i2c_gpio_controller_tx,                                         \
     141              :                         .pkt_size = MCTP_I2C_GPIO_MAX_PKT_SIZE,                                    \
     142              :                 },                                                                                 \
     143              :                 .i2c = DEVICE_DT_GET(DT_PHANDLE(_node_id, i2c)),                                   \
     144              :                 .num_endpoints = DT_PROP_LEN(_node_id, endpoint_ids),                              \
     145              :                 .endpoint_ids = _name##_endpoint_ids,                                              \
     146              :                 .endpoint_gpios = _name##_endpoint_gpios,                                          \
     147              :                 .endpoint_gpio_cbs = _name##_endpoint_gpio_cbs,                                    \
     148              :                 .endpoint_iodevs = _name##_endpoint_iodevs,                                        \
     149              :                 .r_tx = &_name##_rtio_tx,                                                          \
     150              :                 .r_rx = &_name##_rtio_rx,                                                          \
     151              :                 .tx_lock = &_name##_tx_lock,                                                       \
     152              :         };
     153              : 
     154              : #endif /* ZEPHYR_MCTP_I2C_GPIO_CONTROLLER_H_ */
        

Generated by: LCOV version 2.0-1