hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Rockchip MBOX Demo.
 *
 * Copyright (c) 2023 Rockchip Electronics Co. Ltd.
 * Author: Jiahang Zheng <jiahang.zheng@rock-chips.com>
 */
 
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mailbox_client.h>
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <soc/rockchip/rockchip-mailbox.h>
#include <linux/delay.h>
 
/*
 * The Linux kernel uses the mailbox framework TXDONE_BY_POLL mechanism.
 * The minimum unit of the txpoll period interface is ms.
 * Configure rockchip,txpoll-period-ms = <1> in dts.
 * If data that is longer than MBOX_TX_QUEUE_LEN may be lost,
 * each send should be at least interval txpoll-period-ms
 */
#define MSG_LIMIT (100)
#define LINUX_TEST_COMPENSATION    (1)
 
struct rk_mbox_dev {
   struct platform_device *pdev;
   struct mbox_client mbox_cl;
   struct mbox_chan *mbox_rx_chan;
   struct mbox_chan *mbox_tx_chan;
   struct rockchip_mbox_msg tx_msg;
   int rx_count;
};
 
static void rk_mbox_rx_callback(struct mbox_client *client, void *message)
{
   struct rk_mbox_dev *test_dev = container_of(client, struct rk_mbox_dev, mbox_cl);
   struct platform_device *pdev = test_dev->pdev;
   struct device *dev = &pdev->dev;
   struct rockchip_mbox_msg *tx_msg;
   struct rockchip_mbox_msg *rx_msg;
 
   rx_msg = message;
   dev_info(dev, "mbox master: rx_count:%d cmd=0x%x data=0x%x\n",
           ++test_dev->rx_count, rx_msg->cmd, rx_msg->data);
 
   /* test should not live forever */
   if (test_dev->rx_count >= MSG_LIMIT) {
       dev_info(dev, "Rockchip mbox test exit!\n");
       return;
   }
 
   mdelay(LINUX_TEST_COMPENSATION);
   tx_msg = &test_dev->tx_msg;
   mbox_send_message(test_dev->mbox_tx_chan, tx_msg);
}
 
static int mbox_demo_probe(struct platform_device *pdev)
{
   struct device *dev = &pdev->dev;
   struct rk_mbox_dev *test_dev = NULL;
   struct mbox_client *cl;
   struct rockchip_mbox_msg *tx_msg;
   int ret = 0;
 
   test_dev = devm_kzalloc(dev, sizeof(*test_dev), GFP_KERNEL);
   if (!test_dev)
       return -ENOMEM;
 
   /* link_id: master core 0 and remote core 3 */
   tx_msg = &test_dev->tx_msg;
   tx_msg->cmd = 0x03U;
   tx_msg->data = 0x524D5347U;
 
   dev_info(dev, "rockchip mbox demo probe.\n");
   test_dev->pdev = pdev;
   test_dev->rx_count = 0;
 
   cl = &test_dev->mbox_cl;
   cl->dev = dev;
   cl->rx_callback = rk_mbox_rx_callback;
 
   platform_set_drvdata(pdev, test_dev);
   test_dev->mbox_rx_chan = mbox_request_channel_byname(cl, "test-rx");
   if (IS_ERR(test_dev->mbox_rx_chan)) {
       ret = PTR_ERR(test_dev->mbox_rx_chan);
       dev_err(dev, "failed to request mbox rx chan, ret %d\n", ret);
       return ret;
   }
   test_dev->mbox_tx_chan = mbox_request_channel_byname(cl, "test-tx");
   if (IS_ERR(test_dev->mbox_tx_chan)) {
       ret = PTR_ERR(test_dev->mbox_tx_chan);
       dev_err(dev, "failed to request mbox tx chan, ret %d\n", ret);
       return ret;
   }
 
   dev_info(dev, "mbox master: send cmd=0x%x data=0x%x\n", tx_msg->cmd, tx_msg->data);
   mbox_send_message(test_dev->mbox_tx_chan, tx_msg);
 
   return ret;
}
 
static int mbox_demo_remove(struct platform_device *pdev)
{
   struct rk_mbox_dev *test_dev = platform_get_drvdata(pdev);
 
   mbox_free_channel(test_dev->mbox_rx_chan);
   mbox_free_channel(test_dev->mbox_tx_chan);
 
   return 0;
}
 
static const struct of_device_id mbox_demo_match[] = {
   { .compatible = "rockchip,mbox-demo", },
   { /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, mbox_demo_match);
 
static struct platform_driver mbox_demo_driver = {
   .probe = mbox_demo_probe,
   .remove = mbox_demo_remove,
   .driver = {
       .name = "mbox-demo",
       .of_match_table = mbox_demo_match,
   },
};
module_platform_driver(mbox_demo_driver);
 
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Rockchip MBOX Demo");
MODULE_AUTHOR("Jiahang Zheng <jiahang.zheng@rock-chips.com>");