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_TARGET_H_
9 : #define ZEPHYR_MCTP_I2C_GPIO_TARGET_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/pmci/mctp/mctp_i2c_gpio_common.h>
17 : #include <libmctp.h>
18 :
19 : /**
20 : * @brief An MCTP binding for Zephyr's I2C target interface using GPIO
21 : */
22 1 : struct mctp_binding_i2c_gpio_target {
23 : /** @cond INTERNAL_HIDDEN */
24 : struct mctp_binding binding;
25 : const struct device *i2c;
26 : struct i2c_target_config i2c_target_cfg;
27 : uint8_t endpoint_id;
28 : const struct gpio_dt_spec endpoint_gpio;
29 : uint8_t reg_addr;
30 : bool rxtx;
31 : uint8_t rx_idx;
32 : struct mctp_pktbuf *rx_pkt;
33 : struct k_sem *tx_lock;
34 : struct k_sem *tx_complete;
35 : uint8_t tx_idx;
36 : struct mctp_pktbuf *tx_pkt;
37 : /** @endcond INTERNAL_HIDDEN */
38 : };
39 :
40 : /** @cond INTERNAL_HIDDEN */
41 : extern const struct i2c_target_callbacks mctp_i2c_gpio_target_callbacks;
42 : int mctp_i2c_gpio_target_start(struct mctp_binding *binding);
43 : int mctp_i2c_gpio_target_tx(struct mctp_binding *binding, struct mctp_pktbuf *pkt);
44 : /** @endcond INTERNAL_HIDDEN */
45 :
46 : /**
47 : * @brief Define a MCTP bus binding for I2C target with GPIO
48 : *
49 : * Rather than mode switching as the MCTP standard wishes, this is a custom
50 : * binding. On the target side a gpio pin is set active (could be active low or
51 : * active high) when writes are pending. It's expected the controller then
52 : * reads from the I2C target device at some point in the future. Reads are
53 : * accepted at any time and are expected to contain full mctp packets.
54 : *
55 : * In effect each device has a pair of pseudo registers for reading or writing
56 : * as a packet FIFO.
57 : *
58 : * Thus the sequence for a I2C target to send a message would be...
59 : *
60 : * 1. Setup a length and message value (pseudo registers).
61 : * 2. Signal the controller with a GPIO level set
62 : * 3. The controller then is expected to read the length (write of addr 0 + read 1 byte)
63 : * 4. The controller then is expected to read the message (write of addr 1 + read N bytes)
64 : * 5. The target clears the pin set
65 : * 6. The controller reports a message receive to MCTP
66 : *
67 : * @param _name Symbolic name of the bus binding variable
68 : * @param _node_id DeviceTree Node containing the configuration of this MCTP binding
69 : */
70 1 : #define MCTP_I2C_GPIO_TARGET_DT_DEFINE(_name, _node_id) \
71 : K_SEM_DEFINE(_name ##_tx_lock, 1, 1); \
72 : K_SEM_DEFINE(_name ##_tx_complete, 0, 1); \
73 : struct mctp_binding_i2c_gpio_target _name = { \
74 : .binding = { \
75 : .name = STRINGIFY(_name), .version = 1, \
76 : .start = mctp_i2c_gpio_target_start, \
77 : .tx = mctp_i2c_gpio_target_tx, \
78 : .pkt_size = MCTP_I2C_GPIO_MAX_PKT_SIZE, \
79 : }, \
80 : .i2c = DEVICE_DT_GET(DT_PHANDLE(_node_id, i2c)), \
81 : .i2c_target_cfg = { \
82 : .address = DT_PROP(_node_id, i2c_addr), \
83 : .callbacks = &mctp_i2c_gpio_target_callbacks, \
84 : }, \
85 : .endpoint_id = DT_PROP(_node_id, endpoint_id), \
86 : .endpoint_gpio = GPIO_DT_SPEC_GET(_node_id, endpoint_gpios), \
87 : .tx_lock = &_name##_tx_lock, \
88 : .tx_complete = &_name##_tx_complete, \
89 : };
90 :
91 : #endif /* ZEPHYR_MCTP_I2C_GPIO_TARGET_H_ */
|