1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * IEEE 802.15.4 HDLC RCP interface. This is meant for network connectivity
10  * between a host and a RCP radio device.
11  */
12 
13 /* -------------------------------------------------------------------------- */
14 /*                                  Includes                                  */
15 /* -------------------------------------------------------------------------- */
16 #include <fwk_platform_hdlc.h>
17 #include <fwk_platform_ot.h>
18 #include <openthread/platform/radio.h>
19 #include <stdbool.h>
20 #include <stddef.h>
21 #include <zephyr/init.h>
22 #include <zephyr/logging/log.h>
23 #include <zephyr/net/hdlc_rcp_if/hdlc_rcp_if.h>
24 #include <zephyr/net/ieee802154_radio.h>
25 #include <zephyr/net/openthread.h>
26 
27 /* -------------------------------------------------------------------------- */
28 /*                                  Definitions                               */
29 /* -------------------------------------------------------------------------- */
30 
31 #define DT_DRV_COMPAT nxp_hdlc_rcp_if
32 
33 #define LOG_MODULE_NAME hdlc_rcp_if_nxp
34 #define LOG_LEVEL       CONFIG_HDLC_RCP_IF_DRIVER_LOG_LEVEL
35 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
36 
37 struct ot_hdlc_rcp_context {
38 	struct net_if *iface;
39 	struct openthread_context *ot_context;
40 };
41 
42 /* -------------------------------------------------------------------------- */
43 /*                             Private prototypes                             */
44 /* -------------------------------------------------------------------------- */
45 
46 /* -------------------------------------------------------------------------- */
47 /*                             Private functions                              */
48 /* -------------------------------------------------------------------------- */
49 
hdlc_iface_init(struct net_if * iface)50 static void hdlc_iface_init(struct net_if *iface)
51 {
52 	struct ot_hdlc_rcp_context *ctx = net_if_get_device(iface)->data;
53 	otExtAddress eui64;
54 
55 	ctx->iface = iface;
56 
57 	ieee802154_init(iface);
58 
59 	ctx->ot_context = net_if_l2_data(iface);
60 
61 	otPlatRadioGetIeeeEui64(ctx->ot_context->instance, eui64.m8);
62 	net_if_set_link_addr(iface, eui64.m8, OT_EXT_ADDRESS_SIZE, NET_LINK_IEEE802154);
63 }
64 
hdlc_register_rx_cb(hdlc_rx_callback_t hdlc_rx_callback,void * param)65 static int hdlc_register_rx_cb(hdlc_rx_callback_t hdlc_rx_callback, void *param)
66 {
67 	int ret = 0;
68 
69 	ret = PLATFORM_InitHdlcInterface(hdlc_rx_callback, param);
70 	if (ret < 0) {
71 		LOG_ERR("HDLC RX callback registration failed");
72 	}
73 
74 	return ret;
75 }
76 
hdlc_send(const uint8_t * frame,uint16_t length)77 static int hdlc_send(const uint8_t *frame, uint16_t length)
78 {
79 	int ret = 0;
80 
81 	ret = PLATFORM_SendHdlcMessage((uint8_t *)frame, length);
82 	if (ret < 0) {
83 		LOG_ERR("HDLC send frame failed");
84 	}
85 
86 	return ret;
87 }
88 
hdlc_deinit(void)89 static int hdlc_deinit(void)
90 {
91 	int ret = 0;
92 
93 	ret = PLATFORM_TerminateHdlcInterface();
94 	if (ret < 0) {
95 		LOG_ERR("Failed to shutdown OpenThread controller");
96 	}
97 
98 	return ret;
99 }
100 
101 static const struct hdlc_api nxp_hdlc_api = {
102 	.iface_api.init = hdlc_iface_init,
103 	.register_rx_cb = hdlc_register_rx_cb,
104 	.send = hdlc_send,
105 	.deinit = hdlc_deinit,
106 };
107 
108 #define L2_CTX_TYPE NET_L2_GET_CTX_TYPE(OPENTHREAD_L2)
109 
110 #define MTU 1280
111 
112 NET_DEVICE_DT_INST_DEFINE(0, NULL,                             /* Initialization Function */
113 			  NULL,                                /* No PM API support */
114 			  NULL,                                /* No context data */
115 			  NULL,                                /* Configuration info */
116 			  CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, /* Initial priority */
117 			  &nxp_hdlc_api,                       /* API interface functions */
118 			  OPENTHREAD_L2,                       /* Openthread L2 */
119 			  NET_L2_GET_CTX_TYPE(OPENTHREAD_L2),  /* Openthread L2 context type */
120 			  MTU);                                /* MTU size */
121