1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2015 ST Microelectronics
5 * Author: Lee Jones <lee.jones@linaro.org>
8 #include <linux/debugfs.h>
12 #include <linux/kernel.h>
13 #include <linux/mailbox_client.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
17 #include <linux/platform_device.h>
18 #include <linux/poll.h>
19 #include <linux/slab.h>
20 #include <linux/spinlock.h>
21 #include <linux/uaccess.h>
22 #include <linux/sched/signal.h>
24 #define MBOX_MAX_SIG_LEN 8
25 #define MBOX_MAX_MSG_LEN 128
26 #define MBOX_BYTES_PER_LINE 16
27 #define MBOX_HEXDUMP_LINE_LEN ((MBOX_BYTES_PER_LINE * 4) + 2)
28 #define MBOX_HEXDUMP_MAX_LEN (MBOX_HEXDUMP_LINE_LEN * \
29 (MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
31 static bool mbox_data_ready
;
33 struct mbox_test_device
{
35 void __iomem
*tx_mmio
;
36 void __iomem
*rx_mmio
;
37 struct mbox_chan
*tx_channel
;
38 struct mbox_chan
*rx_channel
;
44 wait_queue_head_t waitq
;
45 struct fasync_struct
*async_queue
;
46 struct dentry
*root_debugfs_dir
;
49 static ssize_t
mbox_test_signal_write(struct file
*filp
,
50 const char __user
*userbuf
,
51 size_t count
, loff_t
*ppos
)
53 struct mbox_test_device
*tdev
= filp
->private_data
;
55 if (!tdev
->tx_channel
) {
56 dev_err(tdev
->dev
, "Channel cannot do Tx\n");
60 if (count
> MBOX_MAX_SIG_LEN
) {
62 "Signal length %zd greater than max allowed %d\n",
63 count
, MBOX_MAX_SIG_LEN
);
67 /* Only allocate memory if we need to */
69 tdev
->signal
= kzalloc(MBOX_MAX_SIG_LEN
, GFP_KERNEL
);
74 if (copy_from_user(tdev
->signal
, userbuf
, count
)) {
83 static const struct file_operations mbox_test_signal_ops
= {
84 .write
= mbox_test_signal_write
,
86 .llseek
= generic_file_llseek
,
89 static int mbox_test_message_fasync(int fd
, struct file
*filp
, int on
)
91 struct mbox_test_device
*tdev
= filp
->private_data
;
93 return fasync_helper(fd
, filp
, on
, &tdev
->async_queue
);
96 static ssize_t
mbox_test_message_write(struct file
*filp
,
97 const char __user
*userbuf
,
98 size_t count
, loff_t
*ppos
)
100 struct mbox_test_device
*tdev
= filp
->private_data
;
105 if (!tdev
->tx_channel
) {
106 dev_err(tdev
->dev
, "Channel cannot do Tx\n");
110 if (count
> MBOX_MAX_MSG_LEN
) {
112 "Message length %zd greater than max allowed %d\n",
113 count
, MBOX_MAX_MSG_LEN
);
117 message
= kzalloc(MBOX_MAX_MSG_LEN
, GFP_KERNEL
);
121 mutex_lock(&tdev
->mutex
);
123 tdev
->message
= message
;
124 ret
= copy_from_user(tdev
->message
, userbuf
, count
);
131 * A separate signal is only of use if there is
132 * MMIO to subsequently pass the message through
134 if (tdev
->tx_mmio
&& tdev
->signal
) {
135 print_hex_dump_bytes("Client: Sending: Signal: ", DUMP_PREFIX_ADDRESS
,
136 tdev
->signal
, MBOX_MAX_SIG_LEN
);
140 data
= tdev
->message
;
142 print_hex_dump_bytes("Client: Sending: Message: ", DUMP_PREFIX_ADDRESS
,
143 tdev
->message
, MBOX_MAX_MSG_LEN
);
145 ret
= mbox_send_message(tdev
->tx_channel
, data
);
147 dev_err(tdev
->dev
, "Failed to send message via mailbox\n");
151 kfree(tdev
->message
);
154 mutex_unlock(&tdev
->mutex
);
156 return ret
< 0 ? ret
: count
;
159 static bool mbox_test_message_data_ready(struct mbox_test_device
*tdev
)
164 spin_lock_irqsave(&tdev
->lock
, flags
);
165 data_ready
= mbox_data_ready
;
166 spin_unlock_irqrestore(&tdev
->lock
, flags
);
171 static ssize_t
mbox_test_message_read(struct file
*filp
, char __user
*userbuf
,
172 size_t count
, loff_t
*ppos
)
174 struct mbox_test_device
*tdev
= filp
->private_data
;
180 DECLARE_WAITQUEUE(wait
, current
);
182 touser
= kzalloc(MBOX_HEXDUMP_MAX_LEN
+ 1, GFP_KERNEL
);
186 if (!tdev
->rx_channel
) {
187 ret
= snprintf(touser
, 20, "<NO RX CAPABILITY>\n");
188 ret
= simple_read_from_buffer(userbuf
, count
, ppos
,
193 add_wait_queue(&tdev
->waitq
, &wait
);
196 __set_current_state(TASK_INTERRUPTIBLE
);
198 if (mbox_test_message_data_ready(tdev
))
201 if (filp
->f_flags
& O_NONBLOCK
) {
206 if (signal_pending(current
)) {
214 spin_lock_irqsave(&tdev
->lock
, flags
);
216 ptr
= tdev
->rx_buffer
;
217 while (l
< MBOX_HEXDUMP_MAX_LEN
) {
218 hex_dump_to_buffer(ptr
,
220 MBOX_BYTES_PER_LINE
, 1, touser
+ l
,
221 MBOX_HEXDUMP_LINE_LEN
, true);
223 ptr
+= MBOX_BYTES_PER_LINE
;
224 l
+= MBOX_HEXDUMP_LINE_LEN
;
225 *(touser
+ (l
- 1)) = '\n';
227 *(touser
+ l
) = '\0';
229 memset(tdev
->rx_buffer
, 0, MBOX_MAX_MSG_LEN
);
230 mbox_data_ready
= false;
232 spin_unlock_irqrestore(&tdev
->lock
, flags
);
234 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, touser
, MBOX_HEXDUMP_MAX_LEN
);
236 __set_current_state(TASK_RUNNING
);
237 remove_wait_queue(&tdev
->waitq
, &wait
);
244 mbox_test_message_poll(struct file
*filp
, struct poll_table_struct
*wait
)
246 struct mbox_test_device
*tdev
= filp
->private_data
;
248 poll_wait(filp
, &tdev
->waitq
, wait
);
250 if (mbox_test_message_data_ready(tdev
))
251 return EPOLLIN
| EPOLLRDNORM
;
255 static const struct file_operations mbox_test_message_ops
= {
256 .write
= mbox_test_message_write
,
257 .read
= mbox_test_message_read
,
258 .fasync
= mbox_test_message_fasync
,
259 .poll
= mbox_test_message_poll
,
261 .llseek
= generic_file_llseek
,
264 static int mbox_test_add_debugfs(struct platform_device
*pdev
,
265 struct mbox_test_device
*tdev
)
267 if (!debugfs_initialized())
270 tdev
->root_debugfs_dir
= debugfs_create_dir(dev_name(&pdev
->dev
), NULL
);
271 if (!tdev
->root_debugfs_dir
) {
272 dev_err(&pdev
->dev
, "Failed to create Mailbox debugfs\n");
276 debugfs_create_file("message", 0600, tdev
->root_debugfs_dir
,
277 tdev
, &mbox_test_message_ops
);
279 debugfs_create_file("signal", 0200, tdev
->root_debugfs_dir
,
280 tdev
, &mbox_test_signal_ops
);
285 static void mbox_test_receive_message(struct mbox_client
*client
, void *message
)
287 struct mbox_test_device
*tdev
= dev_get_drvdata(client
->dev
);
290 spin_lock_irqsave(&tdev
->lock
, flags
);
292 memcpy_fromio(tdev
->rx_buffer
, tdev
->rx_mmio
, MBOX_MAX_MSG_LEN
);
293 print_hex_dump_bytes("Client: Received [MMIO]: ", DUMP_PREFIX_ADDRESS
,
294 tdev
->rx_buffer
, MBOX_MAX_MSG_LEN
);
295 } else if (message
) {
296 print_hex_dump_bytes("Client: Received [API]: ", DUMP_PREFIX_ADDRESS
,
297 message
, MBOX_MAX_MSG_LEN
);
298 memcpy(tdev
->rx_buffer
, message
, MBOX_MAX_MSG_LEN
);
300 mbox_data_ready
= true;
301 spin_unlock_irqrestore(&tdev
->lock
, flags
);
303 wake_up_interruptible(&tdev
->waitq
);
305 kill_fasync(&tdev
->async_queue
, SIGIO
, POLL_IN
);
308 static void mbox_test_prepare_message(struct mbox_client
*client
, void *message
)
310 struct mbox_test_device
*tdev
= dev_get_drvdata(client
->dev
);
314 memcpy_toio(tdev
->tx_mmio
, tdev
->message
, MBOX_MAX_MSG_LEN
);
316 memcpy_toio(tdev
->tx_mmio
, message
, MBOX_MAX_MSG_LEN
);
320 static void mbox_test_message_sent(struct mbox_client
*client
,
321 void *message
, int r
)
324 dev_warn(client
->dev
,
325 "Client: Message could not be sent: %d\n", r
);
327 dev_info(client
->dev
,
328 "Client: Message sent\n");
331 static struct mbox_chan
*
332 mbox_test_request_channel(struct platform_device
*pdev
, const char *name
)
334 struct mbox_client
*client
;
335 struct mbox_chan
*channel
;
337 client
= devm_kzalloc(&pdev
->dev
, sizeof(*client
), GFP_KERNEL
);
339 return ERR_PTR(-ENOMEM
);
341 client
->dev
= &pdev
->dev
;
342 client
->rx_callback
= mbox_test_receive_message
;
343 client
->tx_prepare
= mbox_test_prepare_message
;
344 client
->tx_done
= mbox_test_message_sent
;
345 client
->tx_block
= true;
346 client
->knows_txdone
= false;
347 client
->tx_tout
= 500;
349 channel
= mbox_request_channel_byname(client
, name
);
350 if (IS_ERR(channel
)) {
351 dev_warn(&pdev
->dev
, "Failed to request %s channel\n", name
);
358 static int mbox_test_probe(struct platform_device
*pdev
)
360 struct mbox_test_device
*tdev
;
361 struct resource
*res
;
362 resource_size_t size
;
365 tdev
= devm_kzalloc(&pdev
->dev
, sizeof(*tdev
), GFP_KERNEL
);
369 /* It's okay for MMIO to be NULL */
370 tdev
->tx_mmio
= devm_platform_get_and_ioremap_resource(pdev
, 0, &res
);
371 if (PTR_ERR(tdev
->tx_mmio
) == -EBUSY
) {
372 /* if reserved area in SRAM, try just ioremap */
373 size
= resource_size(res
);
374 tdev
->tx_mmio
= devm_ioremap(&pdev
->dev
, res
->start
, size
);
375 } else if (IS_ERR(tdev
->tx_mmio
)) {
376 tdev
->tx_mmio
= NULL
;
379 /* If specified, second reg entry is Rx MMIO */
380 tdev
->rx_mmio
= devm_platform_get_and_ioremap_resource(pdev
, 1, &res
);
381 if (PTR_ERR(tdev
->rx_mmio
) == -EBUSY
) {
382 size
= resource_size(res
);
383 tdev
->rx_mmio
= devm_ioremap(&pdev
->dev
, res
->start
, size
);
384 } else if (IS_ERR(tdev
->rx_mmio
)) {
385 tdev
->rx_mmio
= tdev
->tx_mmio
;
388 tdev
->tx_channel
= mbox_test_request_channel(pdev
, "tx");
389 tdev
->rx_channel
= mbox_test_request_channel(pdev
, "rx");
391 if (IS_ERR_OR_NULL(tdev
->tx_channel
) && IS_ERR_OR_NULL(tdev
->rx_channel
))
392 return -EPROBE_DEFER
;
394 /* If Rx is not specified but has Rx MMIO, then Rx = Tx */
395 if (!tdev
->rx_channel
&& (tdev
->rx_mmio
!= tdev
->tx_mmio
))
396 tdev
->rx_channel
= tdev
->tx_channel
;
398 tdev
->dev
= &pdev
->dev
;
399 platform_set_drvdata(pdev
, tdev
);
401 spin_lock_init(&tdev
->lock
);
402 mutex_init(&tdev
->mutex
);
404 if (tdev
->rx_channel
) {
405 tdev
->rx_buffer
= devm_kzalloc(&pdev
->dev
,
406 MBOX_MAX_MSG_LEN
, GFP_KERNEL
);
407 if (!tdev
->rx_buffer
)
411 ret
= mbox_test_add_debugfs(pdev
, tdev
);
415 init_waitqueue_head(&tdev
->waitq
);
416 dev_info(&pdev
->dev
, "Successfully registered\n");
421 static void mbox_test_remove(struct platform_device
*pdev
)
423 struct mbox_test_device
*tdev
= platform_get_drvdata(pdev
);
425 debugfs_remove_recursive(tdev
->root_debugfs_dir
);
427 if (tdev
->tx_channel
)
428 mbox_free_channel(tdev
->tx_channel
);
429 if (tdev
->rx_channel
)
430 mbox_free_channel(tdev
->rx_channel
);
433 static const struct of_device_id mbox_test_match
[] = {
434 { .compatible
= "mailbox-test" },
437 MODULE_DEVICE_TABLE(of
, mbox_test_match
);
439 static struct platform_driver mbox_test_driver
= {
441 .name
= "mailbox_test",
442 .of_match_table
= mbox_test_match
,
444 .probe
= mbox_test_probe
,
445 .remove
= mbox_test_remove
,
447 module_platform_driver(mbox_test_driver
);
449 MODULE_DESCRIPTION("Generic Mailbox Testing Facility");
450 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org");
451 MODULE_LICENSE("GPL v2");