1 /*
2  * Copyright (c) 2024 Texas Instruments Incorporated
3  *	Andrew Davis <afd@ti.com>
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT zephyr_mbox_ipm
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/ipm.h>
13 #include <zephyr/drivers/mbox.h>
14 
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(ipm_mbox, CONFIG_IPM_LOG_LEVEL);
17 
18 struct ipm_mbox_data {
19 	ipm_callback_t callback;
20 	void *user_data;
21 };
22 
23 struct ipm_mbox_config {
24 	struct mbox_dt_spec mbox_tx;
25 	struct mbox_dt_spec mbox_rx;
26 };
27 
ipm_mbox_callback(const struct device * mboxdev,mbox_channel_id_t channel_id,void * user_data,struct mbox_msg * data)28 static void ipm_mbox_callback(const struct device *mboxdev, mbox_channel_id_t channel_id,
29 			      void *user_data, struct mbox_msg *data)
30 {
31 	const struct device *ipmdev = user_data;
32 	struct ipm_mbox_data *ipm_mbox_data = ipmdev->data;
33 
34 	ipm_mbox_data->callback(ipmdev, ipm_mbox_data->user_data, channel_id, (void *)data->data);
35 }
36 
ipm_mbox_send(const struct device * ipmdev,int wait,uint32_t id,const void * data,int size)37 static int ipm_mbox_send(const struct device *ipmdev, int wait, uint32_t id,
38 			 const void *data, int size)
39 {
40 	const struct ipm_mbox_config *config = ipmdev->config;
41 
42 	struct mbox_msg message = {
43 		.data = data,
44 		.size = size,
45 	};
46 
47 	return mbox_send_dt(&config->mbox_tx, &message);
48 }
49 
ipm_mbox_register_callback(const struct device * ipmdev,ipm_callback_t cb,void * user_data)50 static void ipm_mbox_register_callback(const struct device *ipmdev,
51 				       ipm_callback_t cb,
52 				       void *user_data)
53 {
54 	struct ipm_mbox_data *data = ipmdev->data;
55 
56 	data->callback = cb;
57 	data->user_data = user_data;
58 }
59 
ipm_mbox_get_max_data_size(const struct device * ipmdev)60 static int ipm_mbox_get_max_data_size(const struct device *ipmdev)
61 {
62 	const struct ipm_mbox_config *config = ipmdev->config;
63 
64 	return mbox_mtu_get_dt(&config->mbox_tx);
65 }
66 
ipm_mbox_get_max_id(const struct device * ipmdev)67 static uint32_t ipm_mbox_get_max_id(const struct device *ipmdev)
68 {
69 	const struct ipm_mbox_config *config = ipmdev->config;
70 
71 	return mbox_max_channels_get_dt(&config->mbox_tx);
72 }
73 
ipm_mbox_set_enable(const struct device * ipmdev,int enable)74 static int ipm_mbox_set_enable(const struct device *ipmdev, int enable)
75 {
76 	const struct ipm_mbox_config *config = ipmdev->config;
77 
78 	mbox_set_enabled_dt(&config->mbox_rx, enable);
79 
80 	return 0;
81 }
82 
ipm_mbox_init(const struct device * ipmdev)83 static int ipm_mbox_init(const struct device *ipmdev)
84 {
85 	const struct ipm_mbox_config *config = ipmdev->config;
86 
87 	mbox_register_callback_dt(&config->mbox_rx, ipm_mbox_callback, (void *)ipmdev);
88 
89 	return 0;
90 }
91 
92 static DEVICE_API(ipm, ipm_mbox_funcs) = {
93 	.send = ipm_mbox_send,
94 	.register_callback = ipm_mbox_register_callback,
95 	.max_data_size_get = ipm_mbox_get_max_data_size,
96 	.max_id_val_get = ipm_mbox_get_max_id,
97 	.set_enabled = ipm_mbox_set_enable,
98 };
99 
100 #define IPM_MBOX_DEV_DEFINE(n)						\
101 	static struct ipm_mbox_data ipm_mbox_data_##n;			\
102 	static const struct ipm_mbox_config ipm_mbox_config_##n = {	\
103 		.mbox_tx = MBOX_DT_SPEC_INST_GET(n, tx),		\
104 		.mbox_rx = MBOX_DT_SPEC_INST_GET(n, rx),		\
105 	};								\
106 	DEVICE_DT_INST_DEFINE(n,					\
107 			      &ipm_mbox_init,				\
108 			      NULL,					\
109 			      &ipm_mbox_data_##n,			\
110 			      &ipm_mbox_config_##n,			\
111 			      POST_KERNEL,				\
112 			      CONFIG_KERNEL_INIT_PRIORITY_DEVICE,	\
113 			      &ipm_mbox_funcs);
114 
115 DT_INST_FOREACH_STATUS_OKAY(IPM_MBOX_DEV_DEFINE)
116